summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile15
-rw-r--r--src/Makefile.global.in67
-rw-r--r--src/Makefile.shlib53
-rw-r--r--src/backend/Makefile27
-rw-r--r--src/backend/access/brin/brin.c292
-rw-r--r--src/backend/access/brin/brin_inclusion.c9
-rw-r--r--src/backend/access/brin/brin_minmax.c7
-rw-r--r--src/backend/access/brin/brin_pageops.c16
-rw-r--r--src/backend/access/brin/brin_revmap.c149
-rw-r--r--src/backend/access/brin/brin_tuple.c83
-rw-r--r--src/backend/access/brin/brin_validate.c3
-rw-r--r--src/backend/access/brin/brin_xlog.c78
-rw-r--r--src/backend/access/common/Makefile4
-rw-r--r--src/backend/access/common/bufmask.c128
-rw-r--r--src/backend/access/common/heaptuple.c68
-rw-r--r--src/backend/access/common/indextuple.c2
-rw-r--r--src/backend/access/common/printsimple.c131
-rw-r--r--src/backend/access/common/printtup.c10
-rw-r--r--src/backend/access/common/reloptions.c105
-rw-r--r--src/backend/access/common/scankey.c2
-rw-r--r--src/backend/access/common/tupconvert.c132
-rw-r--r--src/backend/access/common/tupdesc.c95
-rw-r--r--src/backend/access/gin/README15
-rw-r--r--src/backend/access/gin/ginarrayproc.c2
-rw-r--r--src/backend/access/gin/ginbtree.c9
-rw-r--r--src/backend/access/gin/ginbulk.c6
-rw-r--r--src/backend/access/gin/gindatapage.c5
-rw-r--r--src/backend/access/gin/ginentrypage.c3
-rw-r--r--src/backend/access/gin/ginfast.c8
-rw-r--r--src/backend/access/gin/ginget.c33
-rw-r--r--src/backend/access/gin/gininsert.c42
-rw-r--r--src/backend/access/gin/ginlogic.c2
-rw-r--r--src/backend/access/gin/ginpostinglist.c16
-rw-r--r--src/backend/access/gin/ginscan.c12
-rw-r--r--src/backend/access/gin/ginutil.c39
-rw-r--r--src/backend/access/gin/ginvacuum.c243
-rw-r--r--src/backend/access/gin/ginvalidate.c5
-rw-r--r--src/backend/access/gin/ginxlog.c40
-rw-r--r--src/backend/access/gist/README2
-rw-r--r--src/backend/access/gist/gist.c70
-rw-r--r--src/backend/access/gist/gistbuild.c3
-rw-r--r--src/backend/access/gist/gistbuildbuffers.c2
-rw-r--r--src/backend/access/gist/gistget.c22
-rw-r--r--src/backend/access/gist/gistproc.c3
-rw-r--r--src/backend/access/gist/gistscan.c22
-rw-r--r--src/backend/access/gist/gistsplit.c2
-rw-r--r--src/backend/access/gist/gistutil.c11
-rw-r--r--src/backend/access/gist/gistvacuum.c2
-rw-r--r--src/backend/access/gist/gistvalidate.c3
-rw-r--r--src/backend/access/gist/gistxlog.c75
-rw-r--r--src/backend/access/hash/Makefile4
-rw-r--r--src/backend/access/hash/README561
-rw-r--r--src/backend/access/hash/hash.c554
-rw-r--r--src/backend/access/hash/hash_xlog.c1270
-rw-r--r--src/backend/access/hash/hashfunc.c30
-rw-r--r--src/backend/access/hash/hashinsert.c338
-rw-r--r--src/backend/access/hash/hashovfl.c805
-rw-r--r--src/backend/access/hash/hashpage.c1198
-rw-r--r--src/backend/access/hash/hashscan.c153
-rw-r--r--src/backend/access/hash/hashsearch.c280
-rw-r--r--src/backend/access/hash/hashsort.c39
-rw-r--r--src/backend/access/hash/hashutil.c235
-rw-r--r--src/backend/access/hash/hashvalidate.c3
-rw-r--r--src/backend/access/heap/heapam.c348
-rw-r--r--src/backend/access/heap/hio.c2
-rw-r--r--src/backend/access/heap/pruneheap.c2
-rw-r--r--src/backend/access/heap/rewriteheap.c29
-rw-r--r--src/backend/access/heap/syncscan.c4
-rw-r--r--src/backend/access/heap/tuptoaster.c92
-rw-r--r--src/backend/access/heap/visibilitymap.c18
-rw-r--r--src/backend/access/index/amapi.c3
-rw-r--r--src/backend/access/index/amvalidate.c2
-rw-r--r--src/backend/access/index/genam.c8
-rw-r--r--src/backend/access/index/indexam.c146
-rw-r--r--src/backend/access/nbtree/README5
-rw-r--r--src/backend/access/nbtree/nbtcompare.c2
-rw-r--r--src/backend/access/nbtree/nbtinsert.c3
-rw-r--r--src/backend/access/nbtree/nbtpage.c3
-rw-r--r--src/backend/access/nbtree/nbtree.c280
-rw-r--r--src/backend/access/nbtree/nbtsearch.c290
-rw-r--r--src/backend/access/nbtree/nbtsort.c26
-rw-r--r--src/backend/access/nbtree/nbtutils.c12
-rw-r--r--src/backend/access/nbtree/nbtvalidate.c3
-rw-r--r--src/backend/access/nbtree/nbtxlog.c53
-rw-r--r--src/backend/access/rmgrdesc/brindesc.c12
-rw-r--r--src/backend/access/rmgrdesc/clogdesc.c14
-rw-r--r--src/backend/access/rmgrdesc/committsdesc.c8
-rw-r--r--src/backend/access/rmgrdesc/dbasedesc.c2
-rw-r--r--src/backend/access/rmgrdesc/genericdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/gindesc.c49
-rw-r--r--src/backend/access/rmgrdesc/gistdesc.c4
-rw-r--r--src/backend/access/rmgrdesc/hashdesc.c149
-rw-r--r--src/backend/access/rmgrdesc/heapdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/logicalmsgdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/mxactdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/nbtdesc.c4
-rw-r--r--src/backend/access/rmgrdesc/relmapdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/replorigindesc.c2
-rw-r--r--src/backend/access/rmgrdesc/seqdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/smgrdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/spgdesc.c4
-rw-r--r--src/backend/access/rmgrdesc/standbydesc.c6
-rw-r--r--src/backend/access/rmgrdesc/tblspcdesc.c2
-rw-r--r--src/backend/access/rmgrdesc/xactdesc.c4
-rw-r--r--src/backend/access/rmgrdesc/xlogdesc.c2
-rw-r--r--src/backend/access/spgist/spgdoinsert.c42
-rw-r--r--src/backend/access/spgist/spginsert.c37
-rw-r--r--src/backend/access/spgist/spgkdtreeproc.c2
-rw-r--r--src/backend/access/spgist/spgquadtreeproc.c2
-rw-r--r--src/backend/access/spgist/spgscan.c30
-rw-r--r--src/backend/access/spgist/spgtextproc.c18
-rw-r--r--src/backend/access/spgist/spgutils.c7
-rw-r--r--src/backend/access/spgist/spgvacuum.c3
-rw-r--r--src/backend/access/spgist/spgvalidate.c3
-rw-r--r--src/backend/access/spgist/spgxlog.c28
-rw-r--r--src/backend/access/tablesample/bernoulli.c2
-rw-r--r--src/backend/access/tablesample/system.c2
-rw-r--r--src/backend/access/tablesample/tablesample.c2
-rw-r--r--src/backend/access/transam/README10
-rw-r--r--src/backend/access/transam/README.parallel4
-rw-r--r--src/backend/access/transam/clog.c64
-rw-r--r--src/backend/access/transam/commit_ts.c53
-rw-r--r--src/backend/access/transam/generic_xlog.c14
-rw-r--r--src/backend/access/transam/multixact.c33
-rw-r--r--src/backend/access/transam/parallel.c293
-rw-r--r--src/backend/access/transam/recovery.conf.sample12
-rw-r--r--src/backend/access/transam/rmgr.c14
-rw-r--r--src/backend/access/transam/slru.c20
-rw-r--r--src/backend/access/transam/subtrans.c39
-rw-r--r--src/backend/access/transam/timeline.c24
-rw-r--r--src/backend/access/transam/transam.c10
-rw-r--r--src/backend/access/transam/twophase.c863
-rw-r--r--src/backend/access/transam/twophase_rmgr.c2
-rw-r--r--src/backend/access/transam/varsup.c27
-rw-r--r--src/backend/access/transam/xact.c121
-rw-r--r--src/backend/access/transam/xlog.c1043
-rw-r--r--src/backend/access/transam/xlogarchive.c5
-rw-r--r--src/backend/access/transam/xlogfuncs.c87
-rw-r--r--src/backend/access/transam/xloginsert.c75
-rw-r--r--src/backend/access/transam/xlogreader.c104
-rw-r--r--src/backend/access/transam/xlogutils.c240
-rw-r--r--src/backend/bootstrap/bootparse.y32
-rw-r--r--src/backend/bootstrap/bootscanner.l10
-rw-r--r--src/backend/bootstrap/bootstrap.c35
-rw-r--r--src/backend/catalog/Catalog.pm67
-rw-r--r--src/backend/catalog/Makefile12
-rw-r--r--src/backend/catalog/aclchk.c652
-rw-r--r--src/backend/catalog/catalog.c10
-rw-r--r--src/backend/catalog/dependency.c313
-rw-r--r--src/backend/catalog/genbki.pl132
-rw-r--r--src/backend/catalog/heap.c470
-rw-r--r--src/backend/catalog/index.c107
-rw-r--r--src/backend/catalog/indexing.c114
-rw-r--r--src/backend/catalog/information_schema.sql99
-rw-r--r--src/backend/catalog/namespace.c164
-rw-r--r--src/backend/catalog/objectaccess.c2
-rw-r--r--src/backend/catalog/objectaddress.c1091
-rw-r--r--src/backend/catalog/partition.c2314
-rw-r--r--src/backend/catalog/pg_aggregate.c8
-rw-r--r--src/backend/catalog/pg_collation.c94
-rw-r--r--src/backend/catalog/pg_constraint.c29
-rw-r--r--src/backend/catalog/pg_conversion.c9
-rw-r--r--src/backend/catalog/pg_db_role_setting.c23
-rw-r--r--src/backend/catalog/pg_depend.c73
-rw-r--r--src/backend/catalog/pg_enum.c140
-rw-r--r--src/backend/catalog/pg_inherits.c68
-rw-r--r--src/backend/catalog/pg_largeobject.c10
-rw-r--r--src/backend/catalog/pg_namespace.c27
-rw-r--r--src/backend/catalog/pg_operator.c19
-rw-r--r--src/backend/catalog/pg_proc.c23
-rw-r--r--src/backend/catalog/pg_publication.c465
-rw-r--r--src/backend/catalog/pg_range.c7
-rw-r--r--src/backend/catalog/pg_shdepend.c41
-rw-r--r--src/backend/catalog/pg_subscription.c504
-rw-r--r--src/backend/catalog/pg_type.c56
-rw-r--r--src/backend/catalog/pgxc_class.c7
-rw-r--r--src/backend/catalog/sql_features.txt12
-rw-r--r--src/backend/catalog/storage.c2
-rw-r--r--src/backend/catalog/system_views.sql182
-rw-r--r--src/backend/catalog/toasting.c11
-rw-r--r--src/backend/commands/Makefile8
-rw-r--r--src/backend/commands/aggregatecmds.c14
-rw-r--r--src/backend/commands/alter.c110
-rw-r--r--src/backend/commands/amcmds.c9
-rw-r--r--src/backend/commands/analyze.c90
-rw-r--r--src/backend/commands/async.c10
-rw-r--r--src/backend/commands/cluster.c40
-rw-r--r--src/backend/commands/collationcmds.c452
-rw-r--r--src/backend/commands/comment.c40
-rw-r--r--src/backend/commands/constraint.c7
-rw-r--r--src/backend/commands/conversioncmds.c3
-rw-r--r--src/backend/commands/copy.c577
-rw-r--r--src/backend/commands/createas.c22
-rw-r--r--src/backend/commands/dbcommands.c153
-rw-r--r--src/backend/commands/define.c31
-rw-r--r--src/backend/commands/discard.c2
-rw-r--r--src/backend/commands/dropcmds.c193
-rw-r--r--src/backend/commands/event_trigger.c115
-rw-r--r--src/backend/commands/explain.c242
-rw-r--r--src/backend/commands/extension.c714
-rw-r--r--src/backend/commands/foreigncmds.c114
-rw-r--r--src/backend/commands/functioncmds.c138
-rw-r--r--src/backend/commands/indexcmds.c57
-rw-r--r--src/backend/commands/lockcmds.c7
-rw-r--r--src/backend/commands/matview.c47
-rw-r--r--src/backend/commands/opclasscmds.c69
-rw-r--r--src/backend/commands/operatorcmds.c12
-rw-r--r--src/backend/commands/policy.c44
-rw-r--r--src/backend/commands/portalcmds.c54
-rw-r--r--src/backend/commands/prepare.c75
-rw-r--r--src/backend/commands/proclang.c18
-rw-r--r--src/backend/commands/publicationcmds.c740
-rw-r--r--src/backend/commands/schemacmds.c37
-rw-r--r--src/backend/commands/seclabel.c32
-rw-r--r--src/backend/commands/sequence.c956
-rw-r--r--src/backend/commands/statscmds.c408
-rw-r--r--src/backend/commands/subscriptioncmds.c1133
-rw-r--r--src/backend/commands/tablecmds.c2414
-rw-r--r--src/backend/commands/tablespace.c16
-rw-r--r--src/backend/commands/trigger.c446
-rw-r--r--src/backend/commands/tsearchcmds.c65
-rw-r--r--src/backend/commands/typecmds.c116
-rw-r--r--src/backend/commands/user.c148
-rw-r--r--src/backend/commands/vacuum.c88
-rw-r--r--src/backend/commands/vacuumlazy.c68
-rw-r--r--src/backend/commands/variable.c7
-rw-r--r--src/backend/commands/view.c107
-rw-r--r--src/backend/common.mk2
-rw-r--r--src/backend/executor/Makefile20
-rw-r--r--src/backend/executor/README185
-rw-r--r--src/backend/executor/execAmi.c73
-rw-r--r--src/backend/executor/execCurrent.c2
-rw-r--r--src/backend/executor/execExpr.c2677
-rw-r--r--src/backend/executor/execExprInterp.c3565
-rw-r--r--src/backend/executor/execGrouping.c174
-rw-r--r--src/backend/executor/execIndexing.c27
-rw-r--r--src/backend/executor/execJunk.c2
-rw-r--r--src/backend/executor/execMain.c622
-rw-r--r--src/backend/executor/execParallel.c186
-rw-r--r--src/backend/executor/execProcnode.c73
-rw-r--r--src/backend/executor/execQual.c5656
-rw-r--r--src/backend/executor/execReplication.c573
-rw-r--r--src/backend/executor/execSRF.c928
-rw-r--r--src/backend/executor/execScan.c45
-rw-r--r--src/backend/executor/execTuples.c7
-rw-r--r--src/backend/executor/execUtils.c450
-rw-r--r--src/backend/executor/functions.c121
-rw-r--r--src/backend/executor/instrument.c2
-rw-r--r--src/backend/executor/nodeAgg.c1322
-rw-r--r--src/backend/executor/nodeAppend.c8
-rw-r--r--src/backend/executor/nodeBitmapAnd.c2
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c538
-rw-r--r--src/backend/executor/nodeBitmapIndexscan.c6
-rw-r--r--src/backend/executor/nodeBitmapOr.c6
-rw-r--r--src/backend/executor/nodeCtescan.c19
-rw-r--r--src/backend/executor/nodeCustom.c25
-rw-r--r--src/backend/executor/nodeForeignscan.c35
-rw-r--r--src/backend/executor/nodeFunctionscan.c27
-rw-r--r--src/backend/executor/nodeGather.c86
-rw-r--r--src/backend/executor/nodeGatherMerge.c681
-rw-r--r--src/backend/executor/nodeGroup.c56
-rw-r--r--src/backend/executor/nodeHash.c55
-rw-r--r--src/backend/executor/nodeHashjoin.c132
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c204
-rw-r--r--src/backend/executor/nodeIndexscan.c230
-rw-r--r--src/backend/executor/nodeLimit.c21
-rw-r--r--src/backend/executor/nodeLockRows.c6
-rw-r--r--src/backend/executor/nodeMaterial.c2
-rw-r--r--src/backend/executor/nodeMergeAppend.c8
-rw-r--r--src/backend/executor/nodeMergejoin.c156
-rw-r--r--src/backend/executor/nodeModifyTable.c316
-rw-r--r--src/backend/executor/nodeNamedtuplestorescan.c199
-rw-r--r--src/backend/executor/nodeNestloop.c85
-rw-r--r--src/backend/executor/nodeProjectSet.c323
-rw-r--r--src/backend/executor/nodeRecursiveunion.c30
-rw-r--r--src/backend/executor/nodeResult.c54
-rw-r--r--src/backend/executor/nodeSamplescan.c28
-rw-r--r--src/backend/executor/nodeSeqscan.c12
-rw-r--r--src/backend/executor/nodeSetOp.c61
-rw-r--r--src/backend/executor/nodeSort.c7
-rw-r--r--src/backend/executor/nodeSubplan.c156
-rw-r--r--src/backend/executor/nodeSubqueryscan.c12
-rw-r--r--src/backend/executor/nodeTableFuncscan.c498
-rw-r--r--src/backend/executor/nodeTidscan.c151
-rw-r--r--src/backend/executor/nodeUnique.c6
-rw-r--r--src/backend/executor/nodeValuesscan.c17
-rw-r--r--src/backend/executor/nodeWindowAgg.c149
-rw-r--r--src/backend/executor/nodeWorktablescan.c16
-rw-r--r--src/backend/executor/spi.c471
-rw-r--r--src/backend/executor/tqueue.c6
-rw-r--r--src/backend/executor/tstoreReceiver.c2
-rw-r--r--src/backend/foreign/foreign.c14
-rw-r--r--src/backend/lib/Makefile4
-rw-r--r--src/backend/lib/binaryheap.c2
-rw-r--r--src/backend/lib/bipartite_match.c2
-rw-r--r--src/backend/lib/hyperloglog.c2
-rw-r--r--src/backend/lib/ilist.c2
-rw-r--r--src/backend/lib/knapsack.c114
-rw-r--r--src/backend/lib/pairingheap.c2
-rw-r--r--src/backend/lib/rbtree.c339
-rw-r--r--src/backend/lib/stringinfo.c2
-rw-r--r--src/backend/libpq/Makefile4
-rw-r--r--src/backend/libpq/auth-scram.c1134
-rw-r--r--src/backend/libpq/auth.c646
-rw-r--r--src/backend/libpq/be-fsstubs.c53
-rw-r--r--src/backend/libpq/be-secure-openssl.c465
-rw-r--r--src/backend/libpq/be-secure.c32
-rw-r--r--src/backend/libpq/crypt.c308
-rw-r--r--src/backend/libpq/hba.c1227
-rw-r--r--src/backend/libpq/ifaddr.c (renamed from src/backend/libpq/ip.c)237
-rw-r--r--src/backend/libpq/pg_hba.conf.sample24
-rw-r--r--src/backend/libpq/pqcomm.c75
-rw-r--r--src/backend/libpq/pqformat.c2
-rw-r--r--src/backend/libpq/pqmq.c32
-rw-r--r--src/backend/libpq/pqsignal.c2
-rw-r--r--src/backend/main/main.c4
-rw-r--r--src/backend/nls.mk2
-rw-r--r--src/backend/nodes/bitmapset.c32
-rw-r--r--src/backend/nodes/copyfuncs.c529
-rw-r--r--src/backend/nodes/equalfuncs.c358
-rw-r--r--src/backend/nodes/extensible.c2
-rw-r--r--src/backend/nodes/list.c2
-rw-r--r--src/backend/nodes/makefuncs.c19
-rw-r--r--src/backend/nodes/nodeFuncs.c145
-rw-r--r--src/backend/nodes/nodes.c2
-rw-r--r--src/backend/nodes/outfuncs.c630
-rw-r--r--src/backend/nodes/params.c2
-rw-r--r--src/backend/nodes/print.c10
-rw-r--r--src/backend/nodes/read.c2
-rw-r--r--src/backend/nodes/readfuncs.c190
-rw-r--r--src/backend/nodes/tidbitmap.c738
-rw-r--r--src/backend/nodes/value.c2
-rw-r--r--src/backend/optimizer/README108
-rw-r--r--src/backend/optimizer/geqo/geqo_copy.c2
-rw-r--r--src/backend/optimizer/geqo/geqo_erx.c6
-rw-r--r--src/backend/optimizer/geqo/geqo_eval.c6
-rw-r--r--src/backend/optimizer/geqo/geqo_main.c2
-rw-r--r--src/backend/optimizer/geqo/geqo_misc.c2
-rw-r--r--src/backend/optimizer/geqo/geqo_pool.c2
-rw-r--r--src/backend/optimizer/geqo/geqo_random.c2
-rw-r--r--src/backend/optimizer/geqo/geqo_selection.c2
-rw-r--r--src/backend/optimizer/path/allpaths.c638
-rw-r--r--src/backend/optimizer/path/clausesel.c137
-rw-r--r--src/backend/optimizer/path/costsize.c740
-rw-r--r--src/backend/optimizer/path/equivclass.c82
-rw-r--r--src/backend/optimizer/path/indxpath.c179
-rw-r--r--src/backend/optimizer/path/joinpath.c842
-rw-r--r--src/backend/optimizer/path/joinrels.c35
-rw-r--r--src/backend/optimizer/path/pathkeys.c66
-rw-r--r--src/backend/optimizer/path/tidpath.c27
-rw-r--r--src/backend/optimizer/plan/analyzejoins.c285
-rw-r--r--src/backend/optimizer/plan/createplan.c621
-rw-r--r--src/backend/optimizer/plan/initsplan.c104
-rw-r--r--src/backend/optimizer/plan/planagg.c15
-rw-r--r--src/backend/optimizer/plan/planmain.c22
-rw-r--r--src/backend/optimizer/plan/planner.c1670
-rw-r--r--src/backend/optimizer/plan/setrefs.c129
-rw-r--r--src/backend/optimizer/plan/subselect.c119
-rw-r--r--src/backend/optimizer/prep/Makefile2
-rw-r--r--src/backend/optimizer/prep/prepjointree.c49
-rw-r--r--src/backend/optimizer/prep/prepqual.c2
-rw-r--r--src/backend/optimizer/prep/prepsecurity.c486
-rw-r--r--src/backend/optimizer/prep/preptlist.c4
-rw-r--r--src/backend/optimizer/prep/prepunion.c200
-rw-r--r--src/backend/optimizer/util/clauses.c395
-rw-r--r--src/backend/optimizer/util/joininfo.c4
-rw-r--r--src/backend/optimizer/util/orclauses.c18
-rw-r--r--src/backend/optimizer/util/pathnode.c424
-rw-r--r--src/backend/optimizer/util/placeholder.c2
-rw-r--r--src/backend/optimizer/util/plancat.c132
-rw-r--r--src/backend/optimizer/util/predtest.c4
-rw-r--r--src/backend/optimizer/util/relnode.c227
-rw-r--r--src/backend/optimizer/util/restrictinfo.c139
-rw-r--r--src/backend/optimizer/util/tlist.c375
-rw-r--r--src/backend/optimizer/util/var.c2
-rw-r--r--src/backend/parser/Makefile12
-rw-r--r--src/backend/parser/analyze.c308
-rw-r--r--src/backend/parser/check_keywords.pl33
-rw-r--r--src/backend/parser/gram.y2702
-rw-r--r--src/backend/parser/parse_agg.c18
-rw-r--r--src/backend/parser/parse_clause.c384
-rw-r--r--src/backend/parser/parse_coerce.c70
-rw-r--r--src/backend/parser/parse_collate.c19
-rw-r--r--src/backend/parser/parse_cte.c13
-rw-r--r--src/backend/parser/parse_enr.c29
-rw-r--r--src/backend/parser/parse_expr.c304
-rw-r--r--src/backend/parser/parse_func.c228
-rw-r--r--src/backend/parser/parse_node.c8
-rw-r--r--src/backend/parser/parse_oper.c30
-rw-r--r--src/backend/parser/parse_param.c4
-rw-r--r--src/backend/parser/parse_relation.c321
-rw-r--r--src/backend/parser/parse_target.c170
-rw-r--r--src/backend/parser/parse_type.c7
-rw-r--r--src/backend/parser/parse_utilcmd.c845
-rw-r--r--src/backend/parser/parser.c5
-rw-r--r--src/backend/parser/scan.l9
-rw-r--r--src/backend/parser/scansup.c2
-rw-r--r--src/backend/pgxc/cluster/pause.c1
-rw-r--r--src/backend/pgxc/locator/locator.c2
-rw-r--r--src/backend/pgxc/nodemgr/groupmgr.c5
-rw-r--r--src/backend/pgxc/nodemgr/nodemgr.c12
-rw-r--r--src/backend/pgxc/pool/execRemote.c16
-rw-r--r--src/backend/pgxc/pool/pgxcnode.c3
-rw-r--r--src/backend/pgxc/pool/poolmgr.c3
-rw-r--r--src/backend/pgxc/squeue/squeue.c17
-rw-r--r--src/backend/po/de.po11544
-rw-r--r--src/backend/po/fr.po16979
-rw-r--r--src/backend/po/ko.po24982
-rw-r--r--src/backend/po/pl.po13646
-rw-r--r--src/backend/po/ru.po13506
-rw-r--r--src/backend/port/Makefile4
-rw-r--r--src/backend/port/atomics.c81
-rw-r--r--src/backend/port/darwin/README36
-rw-r--r--src/backend/port/darwin/system.c104
-rw-r--r--src/backend/port/dynloader/aix.h2
-rw-r--r--src/backend/port/dynloader/cygwin.h2
-rw-r--r--src/backend/port/dynloader/darwin.c5
-rw-r--r--src/backend/port/dynloader/freebsd.c2
-rw-r--r--src/backend/port/dynloader/freebsd.h3
-rw-r--r--src/backend/port/dynloader/hpux.c2
-rw-r--r--src/backend/port/dynloader/hpux.h2
-rw-r--r--src/backend/port/dynloader/linux.c4
-rw-r--r--src/backend/port/dynloader/linux.h2
-rw-r--r--src/backend/port/dynloader/netbsd.c2
-rw-r--r--src/backend/port/dynloader/netbsd.h3
-rw-r--r--src/backend/port/dynloader/openbsd.c2
-rw-r--r--src/backend/port/dynloader/openbsd.h3
-rw-r--r--src/backend/port/dynloader/sco.c7
-rw-r--r--src/backend/port/dynloader/sco.h46
-rw-r--r--src/backend/port/dynloader/solaris.h2
-rw-r--r--src/backend/port/dynloader/unixware.c7
-rw-r--r--src/backend/port/dynloader/unixware.h49
-rw-r--r--src/backend/port/posix_sema.c104
-rw-r--r--src/backend/port/sysv_sema.c53
-rw-r--r--src/backend/port/sysv_shmem.c251
-rw-r--r--src/backend/port/tas/sunstudio_sparc.s2
-rw-r--r--src/backend/port/tas/sunstudio_x86.s2
-rw-r--r--src/backend/port/win32/crashdump.c5
-rw-r--r--src/backend/port/win32/mingwcompat.c4
-rw-r--r--src/backend/port/win32/signal.c2
-rw-r--r--src/backend/port/win32/socket.c30
-rw-r--r--src/backend/port/win32/timer.c2
-rw-r--r--src/backend/port/win32_sema.c40
-rw-r--r--src/backend/port/win32_shmem.c2
-rw-r--r--src/backend/postmaster/autovacuum.c695
-rw-r--r--src/backend/postmaster/bgworker.c246
-rw-r--r--src/backend/postmaster/bgwriter.c28
-rw-r--r--src/backend/postmaster/checkpointer.c56
-rw-r--r--src/backend/postmaster/clustermon.c6
-rw-r--r--src/backend/postmaster/fork_process.c2
-rw-r--r--src/backend/postmaster/pgarch.c10
-rw-r--r--src/backend/postmaster/pgstat.c918
-rw-r--r--src/backend/postmaster/postmaster.c485
-rw-r--r--src/backend/postmaster/startup.c3
-rw-r--r--src/backend/postmaster/syslogger.c88
-rw-r--r--src/backend/postmaster/walwriter.c11
-rw-r--r--src/backend/regex/README96
-rw-r--r--src/backend/regex/regc_color.c891
-rw-r--r--src/backend/regex/regc_cvec.c10
-rw-r--r--src/backend/regex/regc_lex.c12
-rw-r--r--src/backend/regex/regc_locale.c126
-rw-r--r--src/backend/regex/regc_nfa.c8
-rw-r--r--src/backend/regex/regc_pg_locale.c150
-rw-r--r--src/backend/regex/regcomp.c88
-rw-r--r--src/backend/regex/rege_dfa.c6
-rw-r--r--src/backend/regex/regexec.c4
-rw-r--r--src/backend/regex/regexport.c178
-rw-r--r--src/backend/regex/regprefix.c7
-rw-r--r--src/backend/replication/Makefile5
-rw-r--r--src/backend/replication/README2
-rw-r--r--src/backend/replication/basebackup.c324
-rw-r--r--src/backend/replication/libpqwalreceiver/Makefile2
-rw-r--r--src/backend/replication/libpqwalreceiver/libpqwalreceiver.c790
-rw-r--r--src/backend/replication/logical/Makefile4
-rw-r--r--src/backend/replication/logical/decode.c5
-rw-r--r--src/backend/replication/logical/launcher.c1011
-rw-r--r--src/backend/replication/logical/logical.c74
-rw-r--r--src/backend/replication/logical/logicalfuncs.c32
-rw-r--r--src/backend/replication/logical/message.c6
-rw-r--r--src/backend/replication/logical/origin.c38
-rw-r--r--src/backend/replication/logical/proto.c637
-rw-r--r--src/backend/replication/logical/relation.c490
-rw-r--r--src/backend/replication/logical/reorderbuffer.c149
-rw-r--r--src/backend/replication/logical/snapbuild.c696
-rw-r--r--src/backend/replication/logical/tablesync.c905
-rw-r--r--src/backend/replication/logical/worker.c1617
-rw-r--r--src/backend/replication/pgoutput/Makefile30
-rw-r--r--src/backend/replication/pgoutput/pgoutput.c597
-rw-r--r--src/backend/replication/repl_gram.y124
-rw-r--r--src/backend/replication/repl_scanner.l11
-rw-r--r--src/backend/replication/slot.c223
-rw-r--r--src/backend/replication/slotfuncs.c35
-rw-r--r--src/backend/replication/syncrep.c302
-rw-r--r--src/backend/replication/syncrep_gram.y16
-rw-r--r--src/backend/replication/syncrep_scanner.l7
-rw-r--r--src/backend/replication/walreceiver.c188
-rw-r--r--src/backend/replication/walreceiverfuncs.c17
-rw-r--r--src/backend/replication/walsender.c1156
-rw-r--r--src/backend/rewrite/rewriteDefine.c47
-rw-r--r--src/backend/rewrite/rewriteHandler.c146
-rw-r--r--src/backend/rewrite/rewriteManip.c10
-rw-r--r--src/backend/rewrite/rewriteRemove.c4
-rw-r--r--src/backend/rewrite/rewriteSupport.c62
-rw-r--r--src/backend/rewrite/rowsecurity.c88
-rw-r--r--src/backend/snowball/Makefile3
-rw-r--r--src/backend/snowball/dict_snowball.c2
-rw-r--r--src/backend/snowball/snowball.sql.in2
-rw-r--r--src/backend/snowball/snowball_func.sql.in2
-rw-r--r--src/backend/statistics/Makefile (renamed from src/backend/port/darwin/Makefile)10
-rw-r--r--src/backend/statistics/README97
-rw-r--r--src/backend/statistics/README.dependencies119
-rw-r--r--src/backend/statistics/dependencies.c1075
-rw-r--r--src/backend/statistics/extended_stats.c514
-rw-r--r--src/backend/statistics/mvdistinct.c696
-rw-r--r--src/backend/storage/buffer/README2
-rw-r--r--src/backend/storage/buffer/buf_init.c18
-rw-r--r--src/backend/storage/buffer/buf_table.c2
-rw-r--r--src/backend/storage/buffer/bufmgr.c93
-rw-r--r--src/backend/storage/buffer/freelist.c6
-rw-r--r--src/backend/storage/buffer/localbuf.c22
-rw-r--r--src/backend/storage/file/buffile.c13
-rw-r--r--src/backend/storage/file/copydir.c19
-rw-r--r--src/backend/storage/file/fd.c290
-rw-r--r--src/backend/storage/file/reinit.c14
-rw-r--r--src/backend/storage/freespace/freespace.c22
-rw-r--r--src/backend/storage/freespace/fsmpage.c2
-rw-r--r--src/backend/storage/freespace/indexfsm.c2
-rw-r--r--src/backend/storage/ipc/dsm.c146
-rw-r--r--src/backend/storage/ipc/dsm_impl.c99
-rw-r--r--src/backend/storage/ipc/ipc.c2
-rw-r--r--src/backend/storage/ipc/ipci.c23
-rw-r--r--src/backend/storage/ipc/latch.c377
-rw-r--r--src/backend/storage/ipc/pmsignal.c2
-rw-r--r--src/backend/storage/ipc/procarray.c115
-rw-r--r--src/backend/storage/ipc/procsignal.c2
-rw-r--r--src/backend/storage/ipc/shm_mq.c11
-rw-r--r--src/backend/storage/ipc/shm_toc.c4
-rw-r--r--src/backend/storage/ipc/shmem.c108
-rw-r--r--src/backend/storage/ipc/shmqueue.c2
-rw-r--r--src/backend/storage/ipc/sinval.c2
-rw-r--r--src/backend/storage/ipc/sinvaladt.c2
-rw-r--r--src/backend/storage/ipc/standby.c29
-rw-r--r--src/backend/storage/large_object/inv_api.c20
-rw-r--r--src/backend/storage/lmgr/Makefile2
-rw-r--r--src/backend/storage/lmgr/condition_variable.c228
-rw-r--r--src/backend/storage/lmgr/deadlock.c2
-rw-r--r--src/backend/storage/lmgr/generate-lwlocknames.pl32
-rw-r--r--src/backend/storage/lmgr/lmgr.c8
-rw-r--r--src/backend/storage/lmgr/lock.c11
-rw-r--r--src/backend/storage/lmgr/lwlock.c315
-rw-r--r--src/backend/storage/lmgr/lwlocknames.txt3
-rw-r--r--src/backend/storage/lmgr/predicate.c117
-rw-r--r--src/backend/storage/lmgr/proc.c61
-rw-r--r--src/backend/storage/lmgr/s_lock.c4
-rw-r--r--src/backend/storage/lmgr/spin.c29
-rw-r--r--src/backend/storage/page/bufpage.c400
-rw-r--r--src/backend/storage/page/checksum.c2
-rw-r--r--src/backend/storage/page/itemptr.c17
-rw-r--r--src/backend/storage/smgr/md.c425
-rw-r--r--src/backend/storage/smgr/smgr.c6
-rw-r--r--src/backend/storage/smgr/smgrtype.c3
-rw-r--r--src/backend/tcop/dest.c20
-rw-r--r--src/backend/tcop/fastpath.c24
-rw-r--r--src/backend/tcop/postgres.c181
-rw-r--r--src/backend/tcop/pquery.c173
-rw-r--r--src/backend/tcop/utility.c434
-rw-r--r--src/backend/tsearch/Makefile2
-rw-r--r--src/backend/tsearch/dict.c12
-rw-r--r--src/backend/tsearch/dict_ispell.c3
-rw-r--r--src/backend/tsearch/dict_simple.c3
-rw-r--r--src/backend/tsearch/dict_synonym.c3
-rw-r--r--src/backend/tsearch/dict_thesaurus.c5
-rw-r--r--src/backend/tsearch/regis.c2
-rw-r--r--src/backend/tsearch/spell.c8
-rw-r--r--src/backend/tsearch/to_tsany.c166
-rw-r--r--src/backend/tsearch/ts_locale.c2
-rw-r--r--src/backend/tsearch/ts_parse.c8
-rw-r--r--src/backend/tsearch/ts_selfuncs.c21
-rw-r--r--src/backend/tsearch/ts_typanalyze.c2
-rw-r--r--src/backend/tsearch/ts_utils.c2
-rw-r--r--src/backend/tsearch/wparser.c217
-rw-r--r--src/backend/tsearch/wparser_def.c6
-rw-r--r--src/backend/utils/.gitignore1
-rw-r--r--src/backend/utils/Gen_dummy_probes.pl2
-rw-r--r--src/backend/utils/Gen_dummy_probes.sed2
-rw-r--r--src/backend/utils/Gen_fmgrtab.pl105
-rw-r--r--src/backend/utils/Makefile11
-rw-r--r--src/backend/utils/adt/Makefile4
-rw-r--r--src/backend/utils/adt/acl.c311
-rw-r--r--src/backend/utils/adt/amutils.c4
-rw-r--r--src/backend/utils/adt/array_expanded.c6
-rw-r--r--src/backend/utils/adt/array_selfuncs.c94
-rw-r--r--src/backend/utils/adt/array_typanalyze.c3
-rw-r--r--src/backend/utils/adt/array_userfuncs.c92
-rw-r--r--src/backend/utils/adt/arrayfuncs.c36
-rw-r--r--src/backend/utils/adt/arrayutils.c2
-rw-r--r--src/backend/utils/adt/ascii.c3
-rw-r--r--src/backend/utils/adt/bool.c5
-rw-r--r--src/backend/utils/adt/cash.c76
-rw-r--r--src/backend/utils/adt/char.c8
-rw-r--r--src/backend/utils/adt/date.c359
-rw-r--r--src/backend/utils/adt/datetime.c213
-rw-r--r--src/backend/utils/adt/datum.c6
-rw-r--r--src/backend/utils/adt/dbsize.c45
-rw-r--r--src/backend/utils/adt/domains.c50
-rw-r--r--src/backend/utils/adt/encode.c22
-rw-r--r--src/backend/utils/adt/enum.c122
-rw-r--r--src/backend/utils/adt/expandeddatum.c2
-rw-r--r--src/backend/utils/adt/float.c14
-rw-r--r--src/backend/utils/adt/format_type.c2
-rw-r--r--src/backend/utils/adt/formatting.c1219
-rw-r--r--src/backend/utils/adt/genfile.c104
-rw-r--r--src/backend/utils/adt/geo_ops.c2
-rw-r--r--src/backend/utils/adt/geo_selfuncs.c3
-rw-r--r--src/backend/utils/adt/geo_spgist.c26
-rw-r--r--src/backend/utils/adt/inet_cidr_ntop.c1
-rw-r--r--src/backend/utils/adt/inet_net_pton.c1
-rw-r--r--src/backend/utils/adt/int.c17
-rw-r--r--src/backend/utils/adt/int8.c14
-rw-r--r--src/backend/utils/adt/json.c63
-rw-r--r--src/backend/utils/adt/jsonb.c9
-rw-r--r--src/backend/utils/adt/jsonb_gin.c7
-rw-r--r--src/backend/utils/adt/jsonb_op.c3
-rw-r--r--src/backend/utils/adt/jsonb_util.c17
-rw-r--r--src/backend/utils/adt/jsonfuncs.c2140
-rw-r--r--src/backend/utils/adt/levenshtein.c2
-rw-r--r--src/backend/utils/adt/like.c79
-rw-r--r--src/backend/utils/adt/like_match.c2
-rw-r--r--src/backend/utils/adt/lockfuncs.c121
-rw-r--r--src/backend/utils/adt/mac.c229
-rw-r--r--src/backend/utils/adt/mac8.c568
-rw-r--r--src/backend/utils/adt/misc.c136
-rw-r--r--src/backend/utils/adt/nabstime.c19
-rw-r--r--src/backend/utils/adt/name.c2
-rw-r--r--src/backend/utils/adt/network.c123
-rw-r--r--src/backend/utils/adt/network_gist.c3
-rw-r--r--src/backend/utils/adt/network_selfuncs.c217
-rw-r--r--src/backend/utils/adt/network_spgist.c711
-rw-r--r--src/backend/utils/adt/numeric.c681
-rw-r--r--src/backend/utils/adt/numutils.c20
-rw-r--r--src/backend/utils/adt/oid.c39
-rw-r--r--src/backend/utils/adt/oracle_compat.c2
-rw-r--r--src/backend/utils/adt/orderedsetaggs.c8
-rw-r--r--src/backend/utils/adt/pg_locale.c489
-rw-r--r--src/backend/utils/adt/pg_lsn.c8
-rw-r--r--src/backend/utils/adt/pg_upgrade_support.c17
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c196
-rw-r--r--src/backend/utils/adt/pseudotypes.c348
-rw-r--r--src/backend/utils/adt/quote.c10
-rw-r--r--src/backend/utils/adt/rangetypes.c14
-rw-r--r--src/backend/utils/adt/rangetypes_gist.c2
-rw-r--r--src/backend/utils/adt/rangetypes_selfuncs.c72
-rw-r--r--src/backend/utils/adt/rangetypes_spgist.c9
-rw-r--r--src/backend/utils/adt/rangetypes_typanalyze.c2
-rw-r--r--src/backend/utils/adt/regexp.c140
-rw-r--r--src/backend/utils/adt/regproc.c241
-rw-r--r--src/backend/utils/adt/ri_triggers.c24
-rw-r--r--src/backend/utils/adt/rowtypes.c2
-rw-r--r--src/backend/utils/adt/ruleutils.c710
-rw-r--r--src/backend/utils/adt/selfuncs.c987
-rw-r--r--src/backend/utils/adt/tid.c34
-rw-r--r--src/backend/utils/adt/timestamp.c852
-rw-r--r--src/backend/utils/adt/trigfuncs.c2
-rw-r--r--src/backend/utils/adt/tsginidx.c42
-rw-r--r--src/backend/utils/adt/tsgistidx.c20
-rw-r--r--src/backend/utils/adt/tsquery.c27
-rw-r--r--src/backend/utils/adt/tsquery_cleanup.c427
-rw-r--r--src/backend/utils/adt/tsquery_gist.c3
-rw-r--r--src/backend/utils/adt/tsquery_op.c7
-rw-r--r--src/backend/utils/adt/tsquery_rewrite.c244
-rw-r--r--src/backend/utils/adt/tsquery_util.c84
-rw-r--r--src/backend/utils/adt/tsrank.c7
-rw-r--r--src/backend/utils/adt/tsvector.c3
-rw-r--r--src/backend/utils/adt/tsvector_op.c558
-rw-r--r--src/backend/utils/adt/tsvector_parser.c2
-rw-r--r--src/backend/utils/adt/txid.c159
-rw-r--r--src/backend/utils/adt/uuid.c15
-rw-r--r--src/backend/utils/adt/varbit.c26
-rw-r--r--src/backend/utils/adt/varchar.c6
-rw-r--r--src/backend/utils/adt/varlena.c260
-rw-r--r--src/backend/utils/adt/version.c2
-rw-r--r--src/backend/utils/adt/windowfuncs.c4
-rw-r--r--src/backend/utils/adt/xid.c20
-rw-r--r--src/backend/utils/adt/xml.c672
-rw-r--r--src/backend/utils/cache/attoptcache.c2
-rw-r--r--src/backend/utils/cache/catcache.c103
-rw-r--r--src/backend/utils/cache/evtcache.c6
-rw-r--r--src/backend/utils/cache/inval.c92
-rw-r--r--src/backend/utils/cache/lsyscache.c203
-rw-r--r--src/backend/utils/cache/plancache.c193
-rw-r--r--src/backend/utils/cache/relcache.c686
-rw-r--r--src/backend/utils/cache/relfilenodemap.c4
-rw-r--r--src/backend/utils/cache/relmapper.c9
-rw-r--r--src/backend/utils/cache/spccache.c13
-rw-r--r--src/backend/utils/cache/syscache.c162
-rw-r--r--src/backend/utils/cache/ts_cache.c7
-rw-r--r--src/backend/utils/cache/typcache.c66
-rw-r--r--src/backend/utils/errcodes.txt5
-rw-r--r--src/backend/utils/error/assert.c2
-rw-r--r--src/backend/utils/error/elog.c85
-rw-r--r--src/backend/utils/fmgr/README254
-rw-r--r--src/backend/utils/fmgr/dfmgr.c37
-rw-r--r--src/backend/utils/fmgr/fmgr.c553
-rw-r--r--src/backend/utils/fmgr/funcapi.c9
-rw-r--r--src/backend/utils/generate-errcodes.pl4
-rw-r--r--src/backend/utils/hash/dynahash.c12
-rw-r--r--src/backend/utils/hash/hashfn.c2
-rw-r--r--src/backend/utils/hash/pg_crc.c2
-rw-r--r--src/backend/utils/init/globals.c5
-rw-r--r--src/backend/utils/init/miscinit.c47
-rw-r--r--src/backend/utils/init/postinit.c18
-rw-r--r--src/backend/utils/mb/Unicode/Makefile67
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_BIG5.pl189
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_EUC_CN.pl169
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_EUC_JIS_2004.pl312
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_EUC_JP.pl671
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_EUC_KR.pl134
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_EUC_TW.pl148
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_GB18030.pl101
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_JOHAB.pl48
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_SHIFT_JIS_2004.pl263
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_SJIS.pl197
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_UHC.pl60
-rwxr-xr-xsrc/backend/utils/mb/Unicode/UCS_to_most.pl130
-rw-r--r--src/backend/utils/mb/Unicode/big5_to_utf8.map18321
-rw-r--r--src/backend/utils/mb/Unicode/convutils.pm818
-rw-r--r--src/backend/utils/mb/Unicode/euc_cn_to_utf8.map9723
-rw-r--r--src/backend/utils/mb/Unicode/euc_jis_2004_to_utf8.map14877
-rw-r--r--src/backend/utils/mb/Unicode/euc_jis_2004_to_utf8_combined.map30
-rw-r--r--src/backend/utils/mb/Unicode/euc_jp_to_utf8.map17337
-rw-r--r--src/backend/utils/mb/Unicode/euc_kr_to_utf8.map10725
-rw-r--r--src/backend/utils/mb/Unicode/euc_tw_to_utf8.map31407
-rw-r--r--src/backend/utils/mb/Unicode/gb18030_to_utf8.map41882
-rw-r--r--src/backend/utils/mb/Unicode/gbk_to_utf8.map28344
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_10_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_13_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_14_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_15_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_16_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_2_to_utf8.map205
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_3_to_utf8.map198
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_4_to_utf8.map205
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_5_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_6_to_utf8.map158
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_7_to_utf8.map234
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_8_to_utf8.map201
-rw-r--r--src/backend/utils/mb/Unicode/iso8859_9_to_utf8.map205
-rw-r--r--src/backend/utils/mb/Unicode/johab_to_utf8.map23329
-rw-r--r--src/backend/utils/mb/Unicode/koi8r_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/koi8u_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/shift_jis_2004_to_utf8.map14636
-rw-r--r--src/backend/utils/mb/Unicode/shift_jis_2004_to_utf8_combined.map30
-rw-r--r--src/backend/utils/mb/Unicode/sjis_to_utf8.map10202
-rw-r--r--src/backend/utils/mb/Unicode/ucs2utf.pl35
-rw-r--r--src/backend/utils/mb/Unicode/uhc_to_utf8.map23790
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_big5.map17809
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_euc_cn.map11489
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_euc_jis_2004.map24001
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_euc_jis_2004_combined.map30
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_euc_jp.map20316
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_euc_kr.map14619
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_euc_tw.map24574
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_gb18030.map40292
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_gbk.map26061
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_10.map240
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_13.map239
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_14.map272
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_15.map227
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_16.map257
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_2.map240
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_3.map232
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_4.map240
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_5.map229
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_6.map171
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_7.map248
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_8.map194
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_iso8859_9.map226
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_johab.map23382
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_koi8r.map301
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_koi8u.map312
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_shift_jis_2004.map19087
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_shift_jis_2004_combined.map30
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_sjis.map11651
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_uhc.map23614
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1250.map266
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1251.map259
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1252.map267
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1253.map244
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1254.map276
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1255.map260
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1256.map320
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1257.map259
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win1258.map284
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win866.map280
-rw-r--r--src/backend/utils/mb/Unicode/utf8_to_win874.map225
-rw-r--r--src/backend/utils/mb/Unicode/win1250_to_utf8.map232
-rw-r--r--src/backend/utils/mb/Unicode/win1251_to_utf8.map236
-rw-r--r--src/backend/utils/mb/Unicode/win1252_to_utf8.map232
-rw-r--r--src/backend/utils/mb/Unicode/win1253_to_utf8.map220
-rw-r--r--src/backend/utils/mb/Unicode/win1254_to_utf8.map230
-rw-r--r--src/backend/utils/mb/Unicode/win1255_to_utf8.map214
-rw-r--r--src/backend/utils/mb/Unicode/win1256_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/win1257_to_utf8.map225
-rw-r--r--src/backend/utils/mb/Unicode/win1258_to_utf8.map228
-rw-r--r--src/backend/utils/mb/Unicode/win866_to_utf8.map237
-rw-r--r--src/backend/utils/mb/Unicode/win874_to_utf8.map204
-rw-r--r--src/backend/utils/mb/conv.c254
-rw-r--r--src/backend/utils/mb/conversion_procs/ascii_and_mic/ascii_and_mic.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_ascii/utf8_and_ascii.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c10
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_euc2004/utf8_and_euc2004.c8
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c77
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c2
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_sjis2004/utf8_and_sjis2004.c8
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c6
-rw-r--r--src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c56
-rw-r--r--src/backend/utils/mb/encnames.c76
-rw-r--r--src/backend/utils/mb/mbutils.c2
-rw-r--r--src/backend/utils/misc/Makefile7
-rw-r--r--src/backend/utils/misc/README2
-rw-r--r--src/backend/utils/misc/backend_random.c158
-rw-r--r--src/backend/utils/misc/guc-file.l6
-rw-r--r--src/backend/utils/misc/guc.c431
-rw-r--r--src/backend/utils/misc/help_config.c2
-rw-r--r--src/backend/utils/misc/pg_config.c2
-rw-r--r--src/backend/utils/misc/pg_controldata.c61
-rw-r--r--src/backend/utils/misc/pg_rusage.c8
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample77
-rw-r--r--src/backend/utils/misc/ps_status.c33
-rw-r--r--src/backend/utils/misc/queryenvironment.c144
-rw-r--r--src/backend/utils/misc/rls.c5
-rw-r--r--src/backend/utils/misc/sampling.c2
-rw-r--r--src/backend/utils/misc/superuser.c2
-rw-r--r--src/backend/utils/misc/timeout.c2
-rw-r--r--src/backend/utils/misc/tzparser.c6
-rw-r--r--src/backend/utils/mmgr/Makefile2
-rw-r--r--src/backend/utils/mmgr/README329
-rw-r--r--src/backend/utils/mmgr/aset.c316
-rw-r--r--src/backend/utils/mmgr/dsa.c2241
-rw-r--r--src/backend/utils/mmgr/freepage.c1886
-rw-r--r--src/backend/utils/mmgr/mcxt.c143
-rw-r--r--src/backend/utils/mmgr/memdebug.c93
-rw-r--r--src/backend/utils/mmgr/portalmem.c49
-rw-r--r--src/backend/utils/mmgr/slab.c767
-rw-r--r--src/backend/utils/probes.d24
-rw-r--r--src/backend/utils/resowner/resowner.c4
-rw-r--r--src/backend/utils/sort/logtape.c830
-rw-r--r--src/backend/utils/sort/sortsupport.c2
-rw-r--r--src/backend/utils/sort/tuplesort.c1547
-rw-r--r--src/backend/utils/sort/tuplestore.c18
-rw-r--r--src/backend/utils/time/combocid.c2
-rw-r--r--src/backend/utils/time/snapmgr.c268
-rw-r--r--src/backend/utils/time/tqual.c14
-rw-r--r--src/bcc32.mak47
-rw-r--r--src/bin/Makefile6
-rw-r--r--src/bin/initdb/Makefile7
-rw-r--r--src/bin/initdb/findtimezone.c389
-rw-r--r--src/bin/initdb/initdb.c674
-rw-r--r--src/bin/initdb/nls.mk4
-rw-r--r--src/bin/initdb/po/de.po405
-rw-r--r--src/bin/initdb/po/fr.po380
-rw-r--r--src/bin/initdb/po/he.po1053
-rw-r--r--src/bin/initdb/po/ko.po380
-rw-r--r--src/bin/initdb/po/pl.po516
-rw-r--r--src/bin/initdb/po/pt_BR.po345
-rw-r--r--src/bin/initdb/po/ru.po441
-rw-r--r--src/bin/initdb/t/001_initdb.pl13
-rw-r--r--src/bin/pg_archivecleanup/nls.mk4
-rw-r--r--src/bin/pg_archivecleanup/pg_archivecleanup.c79
-rw-r--r--src/bin/pg_archivecleanup/po/pl.po178
-rw-r--r--src/bin/pg_archivecleanup/po/ru.po185
-rw-r--r--src/bin/pg_basebackup/.gitignore2
-rw-r--r--src/bin/pg_basebackup/Makefile27
-rw-r--r--src/bin/pg_basebackup/nls.mk3
-rw-r--r--src/bin/pg_basebackup/pg_basebackup.c488
-rw-r--r--src/bin/pg_basebackup/pg_receivewal.c (renamed from src/bin/pg_basebackup/pg_receivexlog.c)138
-rw-r--r--src/bin/pg_basebackup/pg_recvlogical.c169
-rw-r--r--src/bin/pg_basebackup/po/de.po743
-rw-r--r--src/bin/pg_basebackup/po/pl.po799
-rw-r--r--src/bin/pg_basebackup/po/ru.po745
-rw-r--r--src/bin/pg_basebackup/receivelog.c482
-rw-r--r--src/bin/pg_basebackup/receivelog.h14
-rw-r--r--src/bin/pg_basebackup/streamutil.c58
-rw-r--r--src/bin/pg_basebackup/streamutil.h10
-rw-r--r--src/bin/pg_basebackup/t/010_pg_basebackup.pl117
-rw-r--r--src/bin/pg_basebackup/t/020_pg_receivewal.pl8
-rw-r--r--src/bin/pg_basebackup/t/020_pg_receivexlog.pl8
-rw-r--r--src/bin/pg_basebackup/t/030_pg_recvlogical.pl56
-rw-r--r--src/bin/pg_basebackup/walmethods.c986
-rw-r--r--src/bin/pg_basebackup/walmethods.h94
-rw-r--r--src/bin/pg_config/Makefile2
-rw-r--r--src/bin/pg_config/pg_config.c2
-rw-r--r--src/bin/pg_config/po/fr.po78
-rw-r--r--src/bin/pg_config/po/ko.po263
-rw-r--r--src/bin/pg_config/po/pt_BR.po87
-rw-r--r--src/bin/pg_config/po/ru.po41
-rw-r--r--src/bin/pg_controldata/Makefile2
-rw-r--r--src/bin/pg_controldata/pg_controldata.c22
-rw-r--r--src/bin/pg_controldata/po/de.po178
-rw-r--r--src/bin/pg_controldata/po/fr.po136
-rw-r--r--src/bin/pg_controldata/po/ko.po256
-rw-r--r--src/bin/pg_controldata/po/pl.po189
-rw-r--r--src/bin/pg_controldata/po/pt_BR.po246
-rw-r--r--src/bin/pg_controldata/po/ru.po251
-rw-r--r--src/bin/pg_ctl/Makefile2
-rw-r--r--src/bin/pg_ctl/pg_ctl.c150
-rw-r--r--src/bin/pg_ctl/po/fr.po306
-rw-r--r--src/bin/pg_ctl/po/ko.po293
-rw-r--r--src/bin/pg_ctl/po/pl.po378
-rw-r--r--src/bin/pg_ctl/po/ru.po372
-rw-r--r--src/bin/pg_ctl/t/001_start_stop.pl31
-rw-r--r--src/bin/pg_ctl/t/002_status.pl2
-rw-r--r--src/bin/pg_ctl/t/003_promote.pl61
-rw-r--r--src/bin/pg_dump/Makefile2
-rw-r--r--src/bin/pg_dump/common.c18
-rw-r--r--src/bin/pg_dump/compress_io.c2
-rw-r--r--src/bin/pg_dump/compress_io.h2
-rw-r--r--src/bin/pg_dump/dumputils.c84
-rw-r--r--src/bin/pg_dump/dumputils.h6
-rw-r--r--src/bin/pg_dump/parallel.c506
-rw-r--r--src/bin/pg_dump/parallel.h71
-rw-r--r--src/bin/pg_dump/pg_backup.h16
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.c369
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.h199
-rw-r--r--src/bin/pg_dump/pg_backup_custom.c86
-rw-r--r--src/bin/pg_dump/pg_backup_db.c56
-rw-r--r--src/bin/pg_dump/pg_backup_directory.c129
-rw-r--r--src/bin/pg_dump/pg_backup_tar.c8
-rw-r--r--src/bin/pg_dump/pg_backup_utils.c2
-rw-r--r--src/bin/pg_dump/pg_backup_utils.h2
-rw-r--r--src/bin/pg_dump/pg_dump.c3585
-rw-r--r--src/bin/pg_dump/pg_dump.h74
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c182
-rw-r--r--src/bin/pg_dump/pg_dumpall.c384
-rw-r--r--src/bin/pg_dump/pg_restore.c57
-rw-r--r--src/bin/pg_dump/po/de.po1080
-rw-r--r--src/bin/pg_dump/po/fr.po2452
-rw-r--r--src/bin/pg_dump/po/ko.po1181
-rw-r--r--src/bin/pg_dump/po/pl.po1202
-rw-r--r--src/bin/pg_dump/po/pt_BR.po1043
-rw-r--r--src/bin/pg_dump/po/ru.po1248
-rw-r--r--src/bin/pg_dump/t/001_basic.pl126
-rw-r--r--src/bin/pg_dump/t/002_pg_dump.pl4730
-rw-r--r--src/bin/pg_dump/t/010_dump_connstr.pl175
-rw-r--r--src/bin/pg_resetwal/.gitignore1
-rw-r--r--src/bin/pg_resetwal/Makefile35
-rw-r--r--src/bin/pg_resetwal/nls.mk4
-rw-r--r--src/bin/pg_resetwal/pg_resetwal.c (renamed from src/bin/pg_resetxlog/pg_resetxlog.c)119
-rw-r--r--src/bin/pg_resetwal/po/cs.po (renamed from src/bin/pg_resetxlog/po/cs.po)0
-rw-r--r--src/bin/pg_resetwal/po/de.po (renamed from src/bin/pg_resetxlog/po/de.po)0
-rw-r--r--src/bin/pg_resetwal/po/es.po (renamed from src/bin/pg_resetxlog/po/es.po)0
-rw-r--r--src/bin/pg_resetwal/po/fr.po (renamed from src/bin/pg_resetxlog/po/fr.po)164
-rw-r--r--src/bin/pg_resetwal/po/it.po (renamed from src/bin/pg_resetxlog/po/it.po)0
-rw-r--r--src/bin/pg_resetwal/po/ja.po (renamed from src/bin/pg_resetxlog/po/ja.po)414
-rw-r--r--src/bin/pg_resetwal/po/ko.po (renamed from src/bin/pg_resetxlog/po/ko.po)15
-rw-r--r--src/bin/pg_resetwal/po/pl.po (renamed from src/bin/pg_resetxlog/po/pl.po)0
-rw-r--r--src/bin/pg_resetwal/po/pt_BR.po (renamed from src/bin/pg_resetxlog/po/pt_BR.po)8
-rw-r--r--src/bin/pg_resetwal/po/ru.po (renamed from src/bin/pg_resetxlog/po/ru.po)276
-rw-r--r--src/bin/pg_resetwal/po/sv.po (renamed from src/bin/pg_resetxlog/po/sv.po)0
-rw-r--r--src/bin/pg_resetwal/po/zh_CN.po (renamed from src/bin/pg_resetxlog/po/zh_CN.po)0
-rw-r--r--src/bin/pg_resetxlog/.gitignore1
-rw-r--r--src/bin/pg_resetxlog/Makefile35
-rw-r--r--src/bin/pg_resetxlog/nls.mk4
-rw-r--r--src/bin/pg_rewind/Makefile2
-rw-r--r--src/bin/pg_rewind/RewindTest.pm10
-rw-r--r--src/bin/pg_rewind/copy_fetch.c18
-rw-r--r--src/bin/pg_rewind/datapagemap.c2
-rw-r--r--src/bin/pg_rewind/datapagemap.h2
-rw-r--r--src/bin/pg_rewind/fetch.c3
-rw-r--r--src/bin/pg_rewind/fetch.h4
-rw-r--r--src/bin/pg_rewind/file_ops.c3
-rw-r--r--src/bin/pg_rewind/file_ops.h2
-rw-r--r--src/bin/pg_rewind/filemap.c11
-rw-r--r--src/bin/pg_rewind/filemap.h2
-rw-r--r--src/bin/pg_rewind/libpq_fetch.c23
-rw-r--r--src/bin/pg_rewind/logging.c12
-rw-r--r--src/bin/pg_rewind/logging.h2
-rw-r--r--src/bin/pg_rewind/nls.mk2
-rw-r--r--src/bin/pg_rewind/parsexlog.c8
-rw-r--r--src/bin/pg_rewind/pg_rewind.c15
-rw-r--r--src/bin/pg_rewind/pg_rewind.h4
-rw-r--r--src/bin/pg_rewind/po/de.po245
-rw-r--r--src/bin/pg_rewind/po/fr.po163
-rw-r--r--src/bin/pg_rewind/po/ja.po850
-rw-r--r--src/bin/pg_rewind/po/ko.po248
-rw-r--r--src/bin/pg_rewind/po/pl.po304
-rw-r--r--src/bin/pg_rewind/po/pt_BR.po859
-rw-r--r--src/bin/pg_rewind/po/ru.po252
-rw-r--r--src/bin/pg_rewind/t/004_pg_xlog_symlink.pl10
-rw-r--r--src/bin/pg_rewind/timeline.c4
-rw-r--r--src/bin/pg_test_fsync/nls.mk5
-rw-r--r--src/bin/pg_test_fsync/pg_test_fsync.c72
-rw-r--r--src/bin/pg_test_fsync/po/pl.po189
-rw-r--r--src/bin/pg_test_fsync/po/ru.po196
-rw-r--r--src/bin/pg_test_timing/nls.mk4
-rw-r--r--src/bin/pg_test_timing/pg_test_timing.c28
-rw-r--r--src/bin/pg_test_timing/po/de.po79
-rw-r--r--src/bin/pg_test_timing/po/pl.po76
-rw-r--r--src/bin/pg_test_timing/po/ru.po81
-rw-r--r--src/bin/pg_upgrade/IMPLEMENTATION4
-rw-r--r--src/bin/pg_upgrade/check.c82
-rw-r--r--src/bin/pg_upgrade/controldata.c28
-rw-r--r--src/bin/pg_upgrade/dump.c3
-rw-r--r--src/bin/pg_upgrade/exec.c148
-rw-r--r--src/bin/pg_upgrade/file.c271
-rw-r--r--src/bin/pg_upgrade/function.c105
-rw-r--r--src/bin/pg_upgrade/info.c14
-rw-r--r--src/bin/pg_upgrade/nls.mk12
-rw-r--r--src/bin/pg_upgrade/option.c118
-rw-r--r--src/bin/pg_upgrade/parallel.c11
-rw-r--r--src/bin/pg_upgrade/pg_upgrade.c60
-rw-r--r--src/bin/pg_upgrade/pg_upgrade.h18
-rw-r--r--src/bin/pg_upgrade/po/ru.po1729
-rw-r--r--src/bin/pg_upgrade/relfilenode.c50
-rw-r--r--src/bin/pg_upgrade/server.c10
-rw-r--r--src/bin/pg_upgrade/tablespace.c8
-rw-r--r--src/bin/pg_upgrade/test.sh8
-rw-r--r--src/bin/pg_upgrade/util.c31
-rw-r--r--src/bin/pg_upgrade/version.c222
-rw-r--r--src/bin/pg_waldump/.gitignore (renamed from src/bin/pg_xlogdump/.gitignore)2
-rw-r--r--src/bin/pg_waldump/Makefile (renamed from src/bin/pg_xlogdump/Makefile)18
-rw-r--r--src/bin/pg_waldump/compat.c (renamed from src/bin/pg_xlogdump/compat.c)13
-rw-r--r--src/bin/pg_waldump/nls.mk6
-rw-r--r--src/bin/pg_waldump/pg_waldump.c (renamed from src/bin/pg_xlogdump/pg_xlogdump.c)128
-rw-r--r--src/bin/pg_waldump/rmgrdesc.c (renamed from src/bin/pg_xlogdump/rmgrdesc.c)16
-rw-r--r--src/bin/pg_waldump/rmgrdesc.h (renamed from src/bin/pg_xlogdump/rmgrdesc.h)4
-rw-r--r--src/bin/pgbench/exprparse.y2
-rw-r--r--src/bin/pgbench/exprscan.l23
-rw-r--r--src/bin/pgbench/pgbench.c1279
-rw-r--r--src/bin/pgbench/pgbench.h2
-rw-r--r--src/bin/pgevent/Makefile2
-rw-r--r--src/bin/pgevent/pgevent.c6
-rw-r--r--src/bin/psql/Makefile16
-rw-r--r--src/bin/psql/command.c1792
-rw-r--r--src/bin/psql/command.h7
-rw-r--r--src/bin/psql/common.c183
-rw-r--r--src/bin/psql/common.h8
-rw-r--r--src/bin/psql/conditional.c153
-rw-r--r--src/bin/psql/conditional.h83
-rw-r--r--src/bin/psql/copy.c18
-rw-r--r--src/bin/psql/copy.h2
-rw-r--r--src/bin/psql/create_help.pl30
-rw-r--r--src/bin/psql/crosstabview.c52
-rw-r--r--src/bin/psql/crosstabview.h2
-rw-r--r--src/bin/psql/describe.c1161
-rw-r--r--src/bin/psql/describe.h11
-rw-r--r--src/bin/psql/help.c25
-rw-r--r--src/bin/psql/help.h2
-rw-r--r--src/bin/psql/input.c9
-rw-r--r--src/bin/psql/input.h2
-rw-r--r--src/bin/psql/large_obj.c2
-rw-r--r--src/bin/psql/large_obj.h2
-rw-r--r--src/bin/psql/mainloop.c123
-rw-r--r--src/bin/psql/mainloop.h2
-rw-r--r--src/bin/psql/nls.mk2
-rw-r--r--src/bin/psql/po/de.po2846
-rw-r--r--src/bin/psql/po/fr.po7055
-rw-r--r--src/bin/psql/po/he.po5800
-rw-r--r--src/bin/psql/po/ko.po5447
-rw-r--r--src/bin/psql/po/pl.po3228
-rw-r--r--src/bin/psql/po/pt_BR.po3461
-rw-r--r--src/bin/psql/po/ru.po3274
-rw-r--r--src/bin/psql/prompt.c8
-rw-r--r--src/bin/psql/prompt.h5
-rw-r--r--src/bin/psql/psqlscanslash.h9
-rw-r--r--src/bin/psql/psqlscanslash.l97
-rw-r--r--src/bin/psql/settings.h5
-rw-r--r--src/bin/psql/startup.c391
-rw-r--r--src/bin/psql/stringutils.c2
-rw-r--r--src/bin/psql/stringutils.h2
-rw-r--r--src/bin/psql/tab-complete.c844
-rw-r--r--src/bin/psql/tab-complete.h2
-rw-r--r--src/bin/psql/variables.c320
-rw-r--r--src/bin/psql/variables.h82
-rw-r--r--src/bin/scripts/.gitignore2
-rw-r--r--src/bin/scripts/Makefile10
-rw-r--r--src/bin/scripts/clusterdb.c2
-rw-r--r--src/bin/scripts/common.c36
-rw-r--r--src/bin/scripts/common.h2
-rw-r--r--src/bin/scripts/createdb.c2
-rw-r--r--src/bin/scripts/createlang.c251
-rw-r--r--src/bin/scripts/createuser.c66
-rw-r--r--src/bin/scripts/dropdb.c2
-rw-r--r--src/bin/scripts/droplang.c252
-rw-r--r--src/bin/scripts/dropuser.c9
-rw-r--r--src/bin/scripts/nls.mk6
-rw-r--r--src/bin/scripts/pg_isready.c2
-rw-r--r--src/bin/scripts/po/de.po384
-rw-r--r--src/bin/scripts/po/fr.po390
-rw-r--r--src/bin/scripts/po/he.po1079
-rw-r--r--src/bin/scripts/po/ja.po517
-rw-r--r--src/bin/scripts/po/ko.po361
-rw-r--r--src/bin/scripts/po/pt_BR.po181
-rw-r--r--src/bin/scripts/po/ru.po469
-rw-r--r--src/bin/scripts/reindexdb.c2
-rw-r--r--src/bin/scripts/t/010_clusterdb.pl5
-rw-r--r--src/bin/scripts/t/030_createlang.pl25
-rw-r--r--src/bin/scripts/t/060_droplang.pl23
-rw-r--r--src/bin/scripts/t/090_reindexdb.pl11
-rw-r--r--src/bin/scripts/t/100_vacuumdb.pl4
-rw-r--r--src/bin/scripts/t/200_connstr.pl41
-rw-r--r--src/bin/scripts/vacuumdb.c18
-rw-r--r--src/common/Makefile21
-rw-r--r--src/common/base64.c199
-rw-r--r--src/common/config_info.c2
-rw-r--r--src/common/controldata_utils.c24
-rw-r--r--src/common/exec.c13
-rw-r--r--src/common/fe_memutils.c2
-rw-r--r--src/common/file_utils.c403
-rw-r--r--src/common/ip.c259
-rw-r--r--src/common/keywords.c2
-rw-r--r--src/common/md5.c (renamed from src/backend/libpq/md5.c)13
-rw-r--r--src/common/pg_lzcompress.c2
-rw-r--r--src/common/pgfnames.c2
-rw-r--r--src/common/psprintf.c2
-rw-r--r--src/common/relpath.c2
-rw-r--r--src/common/restricted_token.c2
-rw-r--r--src/common/rmtree.c2
-rw-r--r--src/common/saslprep.c1279
-rw-r--r--src/common/scram-common.c247
-rw-r--r--src/common/sha2.c1006
-rw-r--r--src/common/sha2_openssl.c102
-rw-r--r--src/common/string.c2
-rw-r--r--src/common/unicode/.gitignore7
-rw-r--r--src/common/unicode/Makefile53
-rw-r--r--src/common/unicode/README35
-rw-r--r--src/common/unicode/generate-norm_test_table.pl102
-rw-r--r--src/common/unicode/generate-unicode_norm_table.pl231
-rw-r--r--src/common/unicode/norm_test.c80
-rw-r--r--src/common/unicode_norm.c437
-rw-r--r--src/common/username.c4
-rw-r--r--src/common/wait_error.c4
-rw-r--r--src/fe_utils/Makefile8
-rw-r--r--src/fe_utils/mbprint.c2
-rw-r--r--src/fe_utils/print.c11
-rw-r--r--src/fe_utils/psqlscan.l30
-rw-r--r--src/fe_utils/simple_list.c2
-rw-r--r--src/fe_utils/string_utils.c88
-rw-r--r--src/include/Makefile3
-rw-r--r--src/include/access/amapi.h29
-rw-r--r--src/include/access/amvalidate.h2
-rw-r--r--src/include/access/attnum.h2
-rw-r--r--src/include/access/brin.h27
-rw-r--r--src/include/access/brin_internal.h5
-rw-r--r--src/include/access/brin_page.h2
-rw-r--r--src/include/access/brin_pageops.h2
-rw-r--r--src/include/access/brin_revmap.h3
-rw-r--r--src/include/access/brin_tuple.h14
-rw-r--r--src/include/access/brin_xlog.h23
-rw-r--r--src/include/access/bufmask.h32
-rw-r--r--src/include/access/clog.h10
-rw-r--r--src/include/access/commit_ts.h10
-rw-r--r--src/include/access/genam.h17
-rw-r--r--src/include/access/generic_xlog.h3
-rw-r--r--src/include/access/gin.h9
-rw-r--r--src/include/access/gin_private.h527
-rw-r--r--src/include/access/ginblock.h336
-rw-r--r--src/include/access/ginxlog.h217
-rw-r--r--src/include/access/gist.h2
-rw-r--r--src/include/access/gist_private.h82
-rw-r--r--src/include/access/gistscan.h2
-rw-r--r--src/include/access/gistxlog.h69
-rw-r--r--src/include/access/hash.h217
-rw-r--r--src/include/access/hash_xlog.h282
-rw-r--r--src/include/access/heapam.h6
-rw-r--r--src/include/access/heapam_xlog.h3
-rw-r--r--src/include/access/hio.h2
-rw-r--r--src/include/access/htup.h2
-rw-r--r--src/include/access/htup_details.h22
-rw-r--r--src/include/access/itup.h4
-rw-r--r--src/include/access/multixact.h5
-rw-r--r--src/include/access/nbtree.h260
-rw-r--r--src/include/access/nbtxlog.h255
-rw-r--r--src/include/access/parallel.h8
-rw-r--r--src/include/access/printsimple.h23
-rw-r--r--src/include/access/printtup.h2
-rw-r--r--src/include/access/reloptions.h5
-rw-r--r--src/include/access/relscan.h25
-rw-r--r--src/include/access/rewriteheap.h2
-rw-r--r--src/include/access/rmgr.h2
-rw-r--r--src/include/access/rmgrlist.h48
-rw-r--r--src/include/access/sdir.h2
-rw-r--r--src/include/access/skey.h2
-rw-r--r--src/include/access/slru.h7
-rw-r--r--src/include/access/spgist.h25
-rw-r--r--src/include/access/spgist_private.h234
-rw-r--r--src/include/access/spgxlog.h257
-rw-r--r--src/include/access/stratnum.h2
-rw-r--r--src/include/access/subtrans.h4
-rw-r--r--src/include/access/sysattr.h2
-rw-r--r--src/include/access/timeline.h4
-rw-r--r--src/include/access/transam.h9
-rw-r--r--src/include/access/tsmapi.h2
-rw-r--r--src/include/access/tupconvert.h6
-rw-r--r--src/include/access/tupdesc.h9
-rw-r--r--src/include/access/tupmacs.h2
-rw-r--r--src/include/access/tuptoaster.h15
-rw-r--r--src/include/access/twophase.h11
-rw-r--r--src/include/access/twophase_rmgr.h2
-rw-r--r--src/include/access/valid.h2
-rw-r--r--src/include/access/visibilitymap.h4
-rw-r--r--src/include/access/xact.h32
-rw-r--r--src/include/access/xlog.h45
-rw-r--r--src/include/access/xlog_fn.h37
-rw-r--r--src/include/access/xlog_internal.h20
-rw-r--r--src/include/access/xlogdefs.h4
-rw-r--r--src/include/access/xloginsert.h4
-rw-r--r--src/include/access/xlogreader.h25
-rw-r--r--src/include/access/xlogrecord.h16
-rw-r--r--src/include/access/xlogutils.h5
-rw-r--r--src/include/bootstrap/bootstrap.h2
-rw-r--r--src/include/c.h50
-rw-r--r--src/include/catalog/binary_upgrade.h2
-rw-r--r--src/include/catalog/catalog.h2
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/dependency.h31
-rw-r--r--src/include/catalog/genbki.h2
-rw-r--r--src/include/catalog/heap.h13
-rw-r--r--src/include/catalog/index.h2
-rw-r--r--src/include/catalog/indexing.h48
-rw-r--r--src/include/catalog/namespace.h6
-rw-r--r--src/include/catalog/objectaccess.h2
-rw-r--r--src/include/catalog/objectaddress.h10
-rw-r--r--src/include/catalog/opfam_internal.h2
-rw-r--r--src/include/catalog/partition.h101
-rw-r--r--src/include/catalog/pg_aggregate.h2
-rw-r--r--src/include/catalog/pg_am.h2
-rw-r--r--src/include/catalog/pg_amop.h40
-rw-r--r--src/include/catalog/pg_amproc.h170
-rw-r--r--src/include/catalog/pg_attrdef.h2
-rw-r--r--src/include/catalog/pg_attribute.h26
-rw-r--r--src/include/catalog/pg_auth_members.h2
-rw-r--r--src/include/catalog/pg_authid.h18
-rw-r--r--src/include/catalog/pg_cast.h18
-rw-r--r--src/include/catalog/pg_class.h34
-rw-r--r--src/include/catalog/pg_collation.h28
-rw-r--r--src/include/catalog/pg_collation_fn.h7
-rw-r--r--src/include/catalog/pg_constraint.h2
-rw-r--r--src/include/catalog/pg_constraint_fn.h2
-rw-r--r--src/include/catalog/pg_control.h16
-rw-r--r--src/include/catalog/pg_conversion.h2
-rw-r--r--src/include/catalog/pg_conversion_fn.h2
-rw-r--r--src/include/catalog/pg_database.h2
-rw-r--r--src/include/catalog/pg_db_role_setting.h2
-rw-r--r--src/include/catalog/pg_default_acl.h3
-rw-r--r--src/include/catalog/pg_depend.h2
-rw-r--r--src/include/catalog/pg_description.h2
-rw-r--r--src/include/catalog/pg_enum.h4
-rw-r--r--src/include/catalog/pg_event_trigger.h2
-rw-r--r--src/include/catalog/pg_extension.h2
-rw-r--r--src/include/catalog/pg_foreign_data_wrapper.h2
-rw-r--r--src/include/catalog/pg_foreign_server.h2
-rw-r--r--src/include/catalog/pg_foreign_table.h4
-rw-r--r--src/include/catalog/pg_index.h2
-rw-r--r--src/include/catalog/pg_inherits.h2
-rw-r--r--src/include/catalog/pg_inherits_fn.h2
-rw-r--r--src/include/catalog/pg_init_privs.h2
-rw-r--r--src/include/catalog/pg_language.h2
-rw-r--r--src/include/catalog/pg_largeobject.h2
-rw-r--r--src/include/catalog/pg_largeobject_metadata.h2
-rw-r--r--src/include/catalog/pg_namespace.h2
-rw-r--r--src/include/catalog/pg_opclass.h38
-rw-r--r--src/include/catalog/pg_operator.h35
-rw-r--r--src/include/catalog/pg_operator_fn.h2
-rw-r--r--src/include/catalog/pg_opfamily.h7
-rw-r--r--src/include/catalog/pg_partitioned_table.h74
-rw-r--r--src/include/catalog/pg_pltemplate.h2
-rw-r--r--src/include/catalog/pg_policy.h18
-rw-r--r--src/include/catalog/pg_proc.h317
-rw-r--r--src/include/catalog/pg_proc_fn.h2
-rw-r--r--src/include/catalog/pg_publication.h104
-rw-r--r--src/include/catalog/pg_publication_rel.h52
-rw-r--r--src/include/catalog/pg_range.h2
-rw-r--r--src/include/catalog/pg_replication_origin.h2
-rw-r--r--src/include/catalog/pg_rewrite.h2
-rw-r--r--src/include/catalog/pg_seclabel.h2
-rw-r--r--src/include/catalog/pg_sequence.h32
-rw-r--r--src/include/catalog/pg_shdepend.h2
-rw-r--r--src/include/catalog/pg_shdescription.h2
-rw-r--r--src/include/catalog/pg_shseclabel.h2
-rw-r--r--src/include/catalog/pg_statistic.h4
-rw-r--r--src/include/catalog/pg_statistic_ext.h80
-rw-r--r--src/include/catalog/pg_subscription.h96
-rw-r--r--src/include/catalog/pg_subscription_rel.h82
-rw-r--r--src/include/catalog/pg_tablespace.h2
-rw-r--r--src/include/catalog/pg_transform.h2
-rw-r--r--src/include/catalog/pg_trigger.h15
-rw-r--r--src/include/catalog/pg_ts_config.h2
-rw-r--r--src/include/catalog/pg_ts_config_map.h2
-rw-r--r--src/include/catalog/pg_ts_dict.h2
-rw-r--r--src/include/catalog/pg_ts_parser.h2
-rw-r--r--src/include/catalog/pg_ts_template.h2
-rw-r--r--src/include/catalog/pg_type.h16
-rw-r--r--src/include/catalog/pg_type_fn.h2
-rw-r--r--src/include/catalog/pg_user_mapping.h2
-rw-r--r--src/include/catalog/storage.h2
-rw-r--r--src/include/catalog/storage_xlog.h2
-rw-r--r--src/include/catalog/toasting.h3
-rw-r--r--src/include/commands/alter.h2
-rw-r--r--src/include/commands/async.h7
-rw-r--r--src/include/commands/cluster.h2
-rw-r--r--src/include/commands/collationcmds.h5
-rw-r--r--src/include/commands/comment.h2
-rw-r--r--src/include/commands/conversioncmds.h2
-rw-r--r--src/include/commands/copy.h15
-rw-r--r--src/include/commands/createas.h5
-rw-r--r--src/include/commands/dbcommands.h6
-rw-r--r--src/include/commands/dbcommands_xlog.h2
-rw-r--r--src/include/commands/defrem.h25
-rw-r--r--src/include/commands/discard.h2
-rw-r--r--src/include/commands/event_trigger.h2
-rw-r--r--src/include/commands/explain.h15
-rw-r--r--src/include/commands/extension.h19
-rw-r--r--src/include/commands/lockcmds.h2
-rw-r--r--src/include/commands/matview.h2
-rw-r--r--src/include/commands/policy.h2
-rw-r--r--src/include/commands/portalcmds.h4
-rw-r--r--src/include/commands/prepare.h9
-rw-r--r--src/include/commands/progress.h2
-rw-r--r--src/include/commands/publicationcmds.h29
-rw-r--r--src/include/commands/schemacmds.h12
-rw-r--r--src/include/commands/seclabel.h2
-rw-r--r--src/include/commands/sequence.h46
-rw-r--r--src/include/commands/subscriptioncmds.h29
-rw-r--r--src/include/commands/tablecmds.h4
-rw-r--r--src/include/commands/tablespace.h2
-rw-r--r--src/include/commands/trigger.h6
-rw-r--r--src/include/commands/typecmds.h6
-rw-r--r--src/include/commands/user.h11
-rw-r--r--src/include/commands/vacuum.h2
-rw-r--r--src/include/commands/variable.h2
-rw-r--r--src/include/commands/view.h5
-rw-r--r--src/include/common/base64.h19
-rw-r--r--src/include/common/config_info.h2
-rw-r--r--src/include/common/controldata_utils.h4
-rw-r--r--src/include/common/fe_memutils.h2
-rw-r--r--src/include/common/file_utils.h27
-rw-r--r--src/include/common/int128.h276
-rw-r--r--src/include/common/ip.h (renamed from src/include/libpq/ip.h)20
-rw-r--r--src/include/common/keywords.h2
-rw-r--r--src/include/common/md5.h (renamed from src/include/libpq/md5.h)8
-rw-r--r--src/include/common/relpath.h2
-rw-r--r--src/include/common/restricted_token.h2
-rw-r--r--src/include/common/saslprep.h30
-rw-r--r--src/include/common/scram-common.h59
-rw-r--r--src/include/common/sha2.h115
-rw-r--r--src/include/common/string.h2
-rw-r--r--src/include/common/unicode_norm.h21
-rw-r--r--src/include/common/unicode_norm_table.h8859
-rw-r--r--src/include/common/username.h2
-rw-r--r--src/include/datatype/timestamp.h57
-rw-r--r--src/include/executor/execExpr.h650
-rw-r--r--src/include/executor/execParallel.h6
-rw-r--r--src/include/executor/execdebug.h25
-rw-r--r--src/include/executor/execdesc.h15
-rw-r--r--src/include/executor/executor.h229
-rw-r--r--src/include/executor/functions.h2
-rw-r--r--src/include/executor/hashjoin.h2
-rw-r--r--src/include/executor/instrument.h2
-rw-r--r--src/include/executor/nodeAgg.h2
-rw-r--r--src/include/executor/nodeAppend.h2
-rw-r--r--src/include/executor/nodeBitmapAnd.h2
-rw-r--r--src/include/executor/nodeBitmapHeapscan.h9
-rw-r--r--src/include/executor/nodeBitmapIndexscan.h2
-rw-r--r--src/include/executor/nodeBitmapOr.h2
-rw-r--r--src/include/executor/nodeCtescan.h2
-rw-r--r--src/include/executor/nodeCustom.h3
-rw-r--r--src/include/executor/nodeForeignscan.h3
-rw-r--r--src/include/executor/nodeFunctionscan.h2
-rw-r--r--src/include/executor/nodeGather.h2
-rw-r--r--src/include/executor/nodeGatherMerge.h27
-rw-r--r--src/include/executor/nodeGroup.h2
-rw-r--r--src/include/executor/nodeHash.h2
-rw-r--r--src/include/executor/nodeHashjoin.h2
-rw-r--r--src/include/executor/nodeIndexonlyscan.h11
-rw-r--r--src/include/executor/nodeIndexscan.h6
-rw-r--r--src/include/executor/nodeLimit.h2
-rw-r--r--src/include/executor/nodeLockRows.h2
-rw-r--r--src/include/executor/nodeMaterial.h2
-rw-r--r--src/include/executor/nodeMergeAppend.h2
-rw-r--r--src/include/executor/nodeMergejoin.h2
-rw-r--r--src/include/executor/nodeModifyTable.h2
-rw-r--r--src/include/executor/nodeNamedtuplestorescan.h24
-rw-r--r--src/include/executor/nodeNestloop.h2
-rw-r--r--src/include/executor/nodeProjectSet.h24
-rw-r--r--src/include/executor/nodeRecursiveunion.h2
-rw-r--r--src/include/executor/nodeResult.h2
-rw-r--r--src/include/executor/nodeSamplescan.h2
-rw-r--r--src/include/executor/nodeSeqscan.h2
-rw-r--r--src/include/executor/nodeSetOp.h2
-rw-r--r--src/include/executor/nodeSort.h2
-rw-r--r--src/include/executor/nodeSubplan.h6
-rw-r--r--src/include/executor/nodeSubqueryscan.h2
-rw-r--r--src/include/executor/nodeTableFuncscan.h24
-rw-r--r--src/include/executor/nodeTidscan.h2
-rw-r--r--src/include/executor/nodeUnique.h2
-rw-r--r--src/include/executor/nodeValuesscan.h2
-rw-r--r--src/include/executor/nodeWindowAgg.h2
-rw-r--r--src/include/executor/nodeWorktablescan.h2
-rw-r--r--src/include/executor/spi.h24
-rw-r--r--src/include/executor/spi_priv.h4
-rw-r--r--src/include/executor/tablefunc.h67
-rw-r--r--src/include/executor/tqueue.h2
-rw-r--r--src/include/executor/tstoreReceiver.h2
-rw-r--r--src/include/executor/tuptable.h2
-rw-r--r--src/include/fe_utils/mbprint.h2
-rw-r--r--src/include/fe_utils/print.h2
-rw-r--r--src/include/fe_utils/psqlscan.h18
-rw-r--r--src/include/fe_utils/psqlscan_int.h8
-rw-r--r--src/include/fe_utils/simple_list.h2
-rw-r--r--src/include/fe_utils/string_utils.h8
-rw-r--r--src/include/fmgr.h84
-rw-r--r--src/include/foreign/fdwapi.h4
-rw-r--r--src/include/foreign/foreign.h4
-rw-r--r--src/include/funcapi.h2
-rw-r--r--src/include/getaddrinfo.h6
-rw-r--r--src/include/getopt_long.h2
-rw-r--r--src/include/lib/binaryheap.h2
-rw-r--r--src/include/lib/bipartite_match.h2
-rw-r--r--src/include/lib/hyperloglog.h2
-rw-r--r--src/include/lib/ilist.h2
-rw-r--r--src/include/lib/knapsack.h17
-rw-r--r--src/include/lib/pairingheap.h2
-rw-r--r--src/include/lib/rbtree.h24
-rw-r--r--src/include/lib/simplehash.h956
-rw-r--r--src/include/lib/stringinfo.h2
-rw-r--r--src/include/libpq/auth.h2
-rw-r--r--src/include/libpq/be-fsstubs.h33
-rw-r--r--src/include/libpq/crypt.h33
-rw-r--r--src/include/libpq/hba.h22
-rw-r--r--src/include/libpq/ifaddr.h30
-rw-r--r--src/include/libpq/libpq-be.h15
-rw-r--r--src/include/libpq/libpq-fs.h2
-rw-r--r--src/include/libpq/libpq.h8
-rw-r--r--src/include/libpq/pqcomm.h7
-rw-r--r--src/include/libpq/pqformat.h2
-rw-r--r--src/include/libpq/pqmq.h2
-rw-r--r--src/include/libpq/pqsignal.h2
-rw-r--r--src/include/libpq/scram.h34
-rw-r--r--src/include/mb/pg_wchar.h92
-rw-r--r--src/include/miscadmin.h9
-rw-r--r--src/include/nodes/bitmapset.h8
-rw-r--r--src/include/nodes/execnodes.h776
-rw-r--r--src/include/nodes/extensible.h3
-rw-r--r--src/include/nodes/lockoptions.h2
-rw-r--r--src/include/nodes/makefuncs.h6
-rw-r--r--src/include/nodes/memnodes.h4
-rw-r--r--src/include/nodes/nodeFuncs.h2
-rw-r--r--src/include/nodes/nodes.h136
-rw-r--r--src/include/nodes/params.h2
-rw-r--r--src/include/nodes/parsenodes.h447
-rw-r--r--src/include/nodes/pg_list.h23
-rw-r--r--src/include/nodes/plannodes.h118
-rw-r--r--src/include/nodes/primnodes.h90
-rw-r--r--src/include/nodes/print.h2
-rw-r--r--src/include/nodes/readfuncs.h2
-rw-r--r--src/include/nodes/relation.h199
-rw-r--r--src/include/nodes/replnodes.h14
-rw-r--r--src/include/nodes/tidbitmap.h12
-rw-r--r--src/include/nodes/value.h2
-rw-r--r--src/include/optimizer/clauses.h6
-rw-r--r--src/include/optimizer/cost.h38
-rw-r--r--src/include/optimizer/geqo.h2
-rw-r--r--src/include/optimizer/geqo_copy.h2
-rw-r--r--src/include/optimizer/geqo_gene.h2
-rw-r--r--src/include/optimizer/geqo_misc.h2
-rw-r--r--src/include/optimizer/geqo_mutation.h2
-rw-r--r--src/include/optimizer/geqo_pool.h2
-rw-r--r--src/include/optimizer/geqo_random.h2
-rw-r--r--src/include/optimizer/geqo_recombination.h2
-rw-r--r--src/include/optimizer/geqo_selection.h2
-rw-r--r--src/include/optimizer/joininfo.h2
-rw-r--r--src/include/optimizer/orclauses.h2
-rw-r--r--src/include/optimizer/pathnode.h48
-rw-r--r--src/include/optimizer/paths.h15
-rw-r--r--src/include/optimizer/placeholder.h2
-rw-r--r--src/include/optimizer/plancat.h2
-rw-r--r--src/include/optimizer/planmain.h10
-rw-r--r--src/include/optimizer/planner.h4
-rw-r--r--src/include/optimizer/predtest.h2
-rw-r--r--src/include/optimizer/prep.h7
-rw-r--r--src/include/optimizer/restrictinfo.h10
-rw-r--r--src/include/optimizer/subselect.h2
-rw-r--r--src/include/optimizer/tlist.h9
-rw-r--r--src/include/optimizer/var.h2
-rw-r--r--src/include/parser/analyze.h15
-rw-r--r--src/include/parser/gramparse.h2
-rw-r--r--src/include/parser/kwlist.h15
-rw-r--r--src/include/parser/parse_agg.h2
-rw-r--r--src/include/parser/parse_clause.h8
-rw-r--r--src/include/parser/parse_coerce.h6
-rw-r--r--src/include/parser/parse_collate.h2
-rw-r--r--src/include/parser/parse_cte.h2
-rw-r--r--src/include/parser/parse_enr.h22
-rw-r--r--src/include/parser/parse_expr.h2
-rw-r--r--src/include/parser/parse_func.h12
-rw-r--r--src/include/parser/parse_node.h58
-rw-r--r--src/include/parser/parse_oper.h7
-rw-r--r--src/include/parser/parse_param.h2
-rw-r--r--src/include/parser/parse_relation.h15
-rw-r--r--src/include/parser/parse_target.h5
-rw-r--r--src/include/parser/parse_type.h2
-rw-r--r--src/include/parser/parse_utilcmd.h4
-rw-r--r--src/include/parser/parser.h2
-rw-r--r--src/include/parser/parsetree.h2
-rw-r--r--src/include/parser/scanner.h4
-rw-r--r--src/include/parser/scansup.h2
-rw-r--r--src/include/pg_config.h.in68
-rw-r--r--src/include/pg_config.h.win3249
-rw-r--r--src/include/pg_config_manual.h25
-rw-r--r--src/include/pg_getopt.h2
-rw-r--r--src/include/pg_trace.h2
-rw-r--r--src/include/pgstat.h223
-rw-r--r--src/include/pgtar.h3
-rw-r--r--src/include/pgtime.h4
-rw-r--r--src/include/port.h22
-rw-r--r--src/include/port/atomics.h71
-rw-r--r--src/include/port/atomics/arch-arm.h9
-rw-r--r--src/include/port/atomics/arch-hppa.h2
-rw-r--r--src/include/port/atomics/arch-ia64.h5
-rw-r--r--src/include/port/atomics/arch-ppc.h5
-rw-r--r--src/include/port/atomics/arch-x86.h16
-rw-r--r--src/include/port/atomics/fallback.h38
-rw-r--r--src/include/port/atomics/generic-acc.h2
-rw-r--r--src/include/port/atomics/generic-gcc.h15
-rw-r--r--src/include/port/atomics/generic-msvc.h4
-rw-r--r--src/include/port/atomics/generic-sunpro.h2
-rw-r--r--src/include/port/atomics/generic-xlc.h2
-rw-r--r--src/include/port/atomics/generic.h58
-rw-r--r--src/include/port/darwin.h2
-rw-r--r--src/include/port/pg_bswap.h27
-rw-r--r--src/include/port/pg_crc32c.h2
-rw-r--r--src/include/port/sco.h7
-rw-r--r--src/include/port/unixware.h11
-rw-r--r--src/include/port/win32.h43
-rw-r--r--src/include/portability/instr_time.h104
-rw-r--r--src/include/portability/mem.h2
-rw-r--r--src/include/postgres.h89
-rw-r--r--src/include/postgres_ext.h5
-rw-r--r--src/include/postgres_fe.h2
-rw-r--r--src/include/postmaster/autovacuum.h16
-rw-r--r--src/include/postmaster/bgworker.h16
-rw-r--r--src/include/postmaster/bgworker_internals.h10
-rw-r--r--src/include/postmaster/bgwriter.h2
-rw-r--r--src/include/postmaster/fork_process.h2
-rw-r--r--src/include/postmaster/pgarch.h4
-rw-r--r--src/include/postmaster/postmaster.h2
-rw-r--r--src/include/postmaster/startup.h2
-rw-r--r--src/include/postmaster/syslogger.h9
-rw-r--r--src/include/postmaster/walwriter.h2
-rw-r--r--src/include/regex/regcustom.h23
-rw-r--r--src/include/regex/regex.h1
-rw-r--r--src/include/regex/regexport.h2
-rw-r--r--src/include/regex/regguts.h142
-rw-r--r--src/include/replication/basebackup.h2
-rw-r--r--src/include/replication/decode.h2
-rw-r--r--src/include/replication/logical.h23
-rw-r--r--src/include/replication/logicalfuncs.h9
-rw-r--r--src/include/replication/logicallauncher.h27
-rw-r--r--src/include/replication/logicalproto.h106
-rw-r--r--src/include/replication/logicalrelation.h42
-rw-r--r--src/include/replication/logicalworker.h17
-rw-r--r--src/include/replication/message.h2
-rw-r--r--src/include/replication/origin.h16
-rw-r--r--src/include/replication/output_plugin.h36
-rw-r--r--src/include/replication/pgoutput.h30
-rw-r--r--src/include/replication/reorderbuffer.h16
-rw-r--r--src/include/replication/slot.h13
-rw-r--r--src/include/replication/snapbuild.h31
-rw-r--r--src/include/replication/syncrep.h9
-rw-r--r--src/include/replication/walreceiver.h164
-rw-r--r--src/include/replication/walsender.h17
-rw-r--r--src/include/replication/walsender_private.h10
-rw-r--r--src/include/replication/worker_internal.h97
-rw-r--r--src/include/rewrite/prs2lock.h2
-rw-r--r--src/include/rewrite/rewriteDefine.h2
-rw-r--r--src/include/rewrite/rewriteHandler.h2
-rw-r--r--src/include/rewrite/rewriteManip.h2
-rw-r--r--src/include/rewrite/rewriteRemove.h2
-rw-r--r--src/include/rewrite/rewriteSupport.h4
-rw-r--r--src/include/rewrite/rowsecurity.h3
-rw-r--r--src/include/rusagestub.h2
-rw-r--r--src/include/snowball/header.h7
-rw-r--r--src/include/statistics/extended_stats_internal.h69
-rw-r--r--src/include/statistics/statistics.h98
-rw-r--r--src/include/storage/backendid.h2
-rw-r--r--src/include/storage/barrier.h23
-rw-r--r--src/include/storage/block.h2
-rw-r--r--src/include/storage/buf.h2
-rw-r--r--src/include/storage/buf_internals.h9
-rw-r--r--src/include/storage/buffile.h2
-rw-r--r--src/include/storage/bufmgr.h17
-rw-r--r--src/include/storage/bufpage.h16
-rw-r--r--src/include/storage/checksum.h2
-rw-r--r--src/include/storage/checksum_impl.h2
-rw-r--r--src/include/storage/condition_variable.h59
-rw-r--r--src/include/storage/copydir.h2
-rw-r--r--src/include/storage/dsm.h6
-rw-r--r--src/include/storage/dsm_impl.h6
-rw-r--r--src/include/storage/fd.h15
-rw-r--r--src/include/storage/freespace.h2
-rw-r--r--src/include/storage/fsm_internals.h2
-rw-r--r--src/include/storage/indexfsm.h2
-rw-r--r--src/include/storage/ipc.h2
-rw-r--r--src/include/storage/item.h2
-rw-r--r--src/include/storage/itemid.h2
-rw-r--r--src/include/storage/itemptr.h36
-rw-r--r--src/include/storage/large_object.h2
-rw-r--r--src/include/storage/latch.h14
-rw-r--r--src/include/storage/lmgr.h2
-rw-r--r--src/include/storage/lock.h2
-rw-r--r--src/include/storage/lockdefs.h2
-rw-r--r--src/include/storage/lwlock.h73
-rw-r--r--src/include/storage/off.h2
-rw-r--r--src/include/storage/pg_sema.h54
-rw-r--r--src/include/storage/pg_shmem.h2
-rw-r--r--src/include/storage/pmsignal.h2
-rw-r--r--src/include/storage/pos.h64
-rw-r--r--src/include/storage/predicate.h4
-rw-r--r--src/include/storage/predicate_internals.h4
-rw-r--r--src/include/storage/proc.h32
-rw-r--r--src/include/storage/procarray.h45
-rw-r--r--src/include/storage/proclist.h208
-rw-r--r--src/include/storage/proclist_types.h45
-rw-r--r--src/include/storage/procsignal.h2
-rw-r--r--src/include/storage/reinit.h2
-rw-r--r--src/include/storage/relfilenode.h2
-rw-r--r--src/include/storage/s_lock.h29
-rw-r--r--src/include/storage/shm_mq.h2
-rw-r--r--src/include/storage/shm_toc.h2
-rw-r--r--src/include/storage/shmem.h4
-rw-r--r--src/include/storage/sinval.h5
-rw-r--r--src/include/storage/sinvaladt.h2
-rw-r--r--src/include/storage/smgr.h16
-rw-r--r--src/include/storage/spin.h6
-rw-r--r--src/include/storage/standby.h2
-rw-r--r--src/include/storage/standbydefs.h2
-rw-r--r--src/include/tcop/deparse_utility.h2
-rw-r--r--src/include/tcop/dest.h3
-rw-r--r--src/include/tcop/fastpath.h4
-rw-r--r--src/include/tcop/pquery.h4
-rw-r--r--src/include/tcop/tcopprot.h14
-rw-r--r--src/include/tcop/utility.h19
-rw-r--r--src/include/tsearch/dicts/regis.h2
-rw-r--r--src/include/tsearch/dicts/spell.h4
-rw-r--r--src/include/tsearch/ts_cache.h2
-rw-r--r--src/include/tsearch/ts_locale.h2
-rw-r--r--src/include/tsearch/ts_public.h2
-rw-r--r--src/include/tsearch/ts_type.h100
-rw-r--r--src/include/tsearch/ts_utils.h197
-rw-r--r--src/include/utils/.gitignore1
-rw-r--r--src/include/utils/acl.h37
-rw-r--r--src/include/utils/aclchk_internal.h2
-rw-r--r--src/include/utils/array.h63
-rw-r--r--src/include/utils/arrayaccess.h2
-rw-r--r--src/include/utils/ascii.h8
-rw-r--r--src/include/utils/attoptcache.h2
-rw-r--r--src/include/utils/backend_random.h19
-rw-r--r--src/include/utils/builtins.h1218
-rw-r--r--src/include/utils/bytea.h27
-rw-r--r--src/include/utils/cash.h48
-rw-r--r--src/include/utils/catcache.h11
-rw-r--r--src/include/utils/combocid.h2
-rw-r--r--src/include/utils/date.h145
-rw-r--r--src/include/utils/datetime.h15
-rw-r--r--src/include/utils/datum.h2
-rw-r--r--src/include/utils/dsa.h125
-rw-r--r--src/include/utils/dynahash.h2
-rw-r--r--src/include/utils/dynamic_loader.h2
-rw-r--r--src/include/utils/elog.h13
-rw-r--r--src/include/utils/evtcache.h2
-rw-r--r--src/include/utils/expandeddatum.h2
-rw-r--r--src/include/utils/fmgrtab.h2
-rw-r--r--src/include/utils/formatting.h14
-rw-r--r--src/include/utils/freepage.h99
-rw-r--r--src/include/utils/geo_decls.h264
-rw-r--r--src/include/utils/guc.h9
-rw-r--r--src/include/utils/guc_tables.h3
-rw-r--r--src/include/utils/help_config.h2
-rw-r--r--src/include/utils/hsearch.h2
-rw-r--r--src/include/utils/index_selfuncs.h20
-rw-r--r--src/include/utils/inet.h52
-rw-r--r--src/include/utils/int8.h106
-rw-r--r--src/include/utils/inval.h4
-rw-r--r--src/include/utils/json.h66
-rw-r--r--src/include/utils/jsonapi.h20
-rw-r--r--src/include/utils/jsonb.h111
-rw-r--r--src/include/utils/logtape.h10
-rw-r--r--src/include/utils/lsyscache.h38
-rw-r--r--src/include/utils/memdebug.h50
-rw-r--r--src/include/utils/memutils.h83
-rw-r--r--src/include/utils/nabstime.h65
-rw-r--r--src/include/utils/numeric.h2
-rw-r--r--src/include/utils/palloc.h4
-rw-r--r--src/include/utils/pg_crc.h2
-rw-r--r--src/include/utils/pg_locale.h37
-rw-r--r--src/include/utils/pg_lsn.h18
-rw-r--r--src/include/utils/pg_rusage.h2
-rw-r--r--src/include/utils/plancache.h21
-rw-r--r--src/include/utils/portal.h9
-rw-r--r--src/include/utils/queryenvironment.h74
-rw-r--r--src/include/utils/rangetypes.h82
-rw-r--r--src/include/utils/regproc.h28
-rw-r--r--src/include/utils/rel.h105
-rw-r--r--src/include/utils/relcache.h9
-rw-r--r--src/include/utils/relfilenodemap.h2
-rw-r--r--src/include/utils/relmapper.h2
-rw-r--r--src/include/utils/relptr.h77
-rw-r--r--src/include/utils/reltrigger.h9
-rw-r--r--src/include/utils/resowner.h2
-rw-r--r--src/include/utils/resowner_private.h2
-rw-r--r--src/include/utils/rls.h2
-rw-r--r--src/include/utils/ruleutils.h4
-rw-r--r--src/include/utils/sampling.h2
-rw-r--r--src/include/utils/selfuncs.h36
-rw-r--r--src/include/utils/snapmgr.h15
-rw-r--r--src/include/utils/snapshot.h5
-rw-r--r--src/include/utils/sortsupport.h2
-rw-r--r--src/include/utils/spccache.h2
-rw-r--r--src/include/utils/syscache.h17
-rw-r--r--src/include/utils/timeout.h2
-rw-r--r--src/include/utils/timestamp.h175
-rw-r--r--src/include/utils/tqual.h2
-rw-r--r--src/include/utils/tuplesort.h14
-rw-r--r--src/include/utils/tuplestore.h4
-rw-r--r--src/include/utils/typcache.h7
-rw-r--r--src/include/utils/tzparser.h2
-rw-r--r--src/include/utils/uuid.h10
-rw-r--r--src/include/utils/varbit.h48
-rw-r--r--src/include/utils/varlena.h37
-rw-r--r--src/include/utils/xml.h42
-rw-r--r--src/include/windowapi.h2
-rw-r--r--src/interfaces/ecpg/compatlib/Makefile4
-rw-r--r--src/interfaces/ecpg/ecpglib/Makefile4
-rw-r--r--src/interfaces/ecpg/ecpglib/data.c2
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c3
-rw-r--r--src/interfaces/ecpg/ecpglib/extern.h2
-rw-r--r--src/interfaces/ecpg/ecpglib/misc.c10
-rw-r--r--src/interfaces/ecpg/ecpglib/pg_type.h20
-rw-r--r--src/interfaces/ecpg/ecpglib/po/fr.po48
-rw-r--r--src/interfaces/ecpg/ecpglib/po/ko.po10
-rw-r--r--src/interfaces/ecpg/ecpglib/po/ru.po107
-rw-r--r--src/interfaces/ecpg/ecpglib/typename.c1
-rw-r--r--src/interfaces/ecpg/include/ecpg_config.h.in4
-rw-r--r--src/interfaces/ecpg/include/pgtypes_interval.h6
-rw-r--r--src/interfaces/ecpg/include/pgtypes_timestamp.h5
-rw-r--r--src/interfaces/ecpg/pgtypeslib/Makefile4
-rw-r--r--src/interfaces/ecpg/pgtypeslib/datetime.c7
-rw-r--r--src/interfaces/ecpg/pgtypeslib/dt.h40
-rw-r--r--src/interfaces/ecpg/pgtypeslib/dt_common.c80
-rw-r--r--src/interfaces/ecpg/pgtypeslib/interval.c54
-rw-r--r--src/interfaces/ecpg/pgtypeslib/numeric.c4
-rw-r--r--src/interfaces/ecpg/pgtypeslib/timestamp.c82
-rw-r--r--src/interfaces/ecpg/preproc/Makefile11
-rw-r--r--src/interfaces/ecpg/preproc/check_rules.pl14
-rw-r--r--src/interfaces/ecpg/preproc/descriptor.c28
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.addons30
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.c98
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.header14
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.trailer26
-rw-r--r--src/interfaces/ecpg/preproc/extern.h10
-rw-r--r--src/interfaces/ecpg/preproc/keywords.c2
-rw-r--r--src/interfaces/ecpg/preproc/output.c66
-rw-r--r--src/interfaces/ecpg/preproc/parse.pl4
-rw-r--r--src/interfaces/ecpg/preproc/parser.c12
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l70
-rw-r--r--src/interfaces/ecpg/preproc/po/de.po186
-rw-r--r--src/interfaces/ecpg/preproc/po/fr.po465
-rw-r--r--src/interfaces/ecpg/preproc/po/ko.po374
-rw-r--r--src/interfaces/ecpg/preproc/po/pl.po214
-rw-r--r--src/interfaces/ecpg/preproc/po/pt_BR.po146
-rw-r--r--src/interfaces/ecpg/preproc/po/ru.po197
-rw-r--r--src/interfaces/ecpg/preproc/type.c40
-rw-r--r--src/interfaces/ecpg/preproc/variable.c2
-rw-r--r--src/interfaces/ecpg/test/Makefile13
-rw-r--r--src/interfaces/ecpg/test/compat_informix/test_informix2.pgc4
-rw-r--r--src/interfaces/ecpg/test/expected/compat_informix-test_informix2.c4
-rw-r--r--src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.c6
-rw-r--r--src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.stdout2
-rw-r--r--src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c102
-rw-r--r--src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr354
-rw-r--r--src/interfaces/ecpg/test/expected/sql-twophase.c114
-rw-r--r--src/interfaces/ecpg/test/expected/sql-twophase.stderr34
-rw-r--r--src/interfaces/ecpg/test/expected/sql-twophase.stdout0
-rw-r--r--src/interfaces/ecpg/test/expected/thread-thread.c2
-rw-r--r--src/interfaces/ecpg/test/expected/thread-thread_implicit.c2
-rw-r--r--src/interfaces/ecpg/test/pg_regress_ecpg.c5
-rw-r--r--src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc6
-rw-r--r--src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc2
-rw-r--r--src/interfaces/ecpg/test/sql/.gitignore2
-rw-r--r--src/interfaces/ecpg/test/sql/Makefile1
-rw-r--r--src/interfaces/ecpg/test/sql/twophase.pgc44
-rw-r--r--src/interfaces/ecpg/test/thread/thread.pgc2
-rw-r--r--src/interfaces/ecpg/test/thread/thread_implicit.pgc2
-rw-r--r--src/interfaces/libpq/.gitignore17
-rw-r--r--src/interfaces/libpq/Makefile35
-rw-r--r--src/interfaces/libpq/bcc32.mak312
-rw-r--r--src/interfaces/libpq/exports.txt1
-rw-r--r--src/interfaces/libpq/fe-auth-scram.c707
-rw-r--r--src/interfaces/libpq/fe-auth.c537
-rw-r--r--src/interfaces/libpq/fe-auth.h13
-rw-r--r--src/interfaces/libpq/fe-connect.c1162
-rw-r--r--src/interfaces/libpq/fe-exec.c8
-rw-r--r--src/interfaces/libpq/fe-lobj.c2
-rw-r--r--src/interfaces/libpq/fe-misc.c15
-rw-r--r--src/interfaces/libpq/fe-print.c5
-rw-r--r--src/interfaces/libpq/fe-protocol2.c2
-rw-r--r--src/interfaces/libpq/fe-protocol3.c2
-rw-r--r--src/interfaces/libpq/fe-secure-openssl.c514
-rw-r--r--src/interfaces/libpq/fe-secure.c2
-rw-r--r--src/interfaces/libpq/libpq-events.c2
-rw-r--r--src/interfaces/libpq/libpq-events.h2
-rw-r--r--src/interfaces/libpq/libpq-fe.h9
-rw-r--r--src/interfaces/libpq/libpq-int.h70
-rw-r--r--src/interfaces/libpq/libpq.rc.in10
-rw-r--r--src/interfaces/libpq/po/de.po435
-rw-r--r--src/interfaces/libpq/po/fr.po402
-rw-r--r--src/interfaces/libpq/po/ko.po307
-rw-r--r--src/interfaces/libpq/po/pl.po443
-rw-r--r--src/interfaces/libpq/po/pt_BR.po372
-rw-r--r--src/interfaces/libpq/po/ru.po435
-rw-r--r--src/interfaces/libpq/po/zh_CN.po6
-rw-r--r--src/interfaces/libpq/pqexpbuffer.c2
-rw-r--r--src/interfaces/libpq/pqexpbuffer.h2
-rw-r--r--src/interfaces/libpq/pthread-win32.c3
-rw-r--r--src/interfaces/libpq/test/.gitignore3
-rw-r--r--src/interfaces/libpq/test/Makefile2
-rw-r--r--src/interfaces/libpq/test/regress.pl15
-rw-r--r--src/interfaces/libpq/test/uri-regress.c2
-rw-r--r--src/interfaces/libpq/win32.c4
-rw-r--r--src/interfaces/libpq/win32.h8
-rw-r--r--src/interfaces/libpq/win32.mak366
-rw-r--r--src/makefiles/Makefile.cygwin4
-rw-r--r--src/makefiles/Makefile.sco13
-rw-r--r--src/makefiles/Makefile.unixware35
-rw-r--r--src/makefiles/Makefile.win324
-rw-r--r--src/makefiles/pgxs.mk4
-rw-r--r--src/pl/plperl/Util.xs10
-rw-r--r--src/pl/plperl/expected/plperl_trigger.out29
-rw-r--r--src/pl/plperl/plc_perlboot.pl7
-rw-r--r--src/pl/plperl/plc_trusted.pl3
-rw-r--r--src/pl/plperl/plperl.c406
-rw-r--r--src/pl/plperl/plperl.h2
-rw-r--r--src/pl/plperl/po/de.po104
-rw-r--r--src/pl/plperl/po/fr.po82
-rw-r--r--src/pl/plperl/po/ko.po107
-rw-r--r--src/pl/plperl/po/pl.po106
-rw-r--r--src/pl/plperl/po/pt_BR.po95
-rw-r--r--src/pl/plperl/po/ru.po115
-rw-r--r--src/pl/plperl/ppport.h12
-rw-r--r--src/pl/plperl/sql/plperl_trigger.sql32
-rw-r--r--src/pl/plperl/text2macro.pl8
-rw-r--r--src/pl/plpgsql/src/Makefile2
-rw-r--r--src/pl/plpgsql/src/generate-plerrcodes.pl4
-rw-r--r--src/pl/plpgsql/src/pl_comp.c45
-rw-r--r--src/pl/plpgsql/src/pl_exec.c727
-rw-r--r--src/pl/plpgsql/src/pl_funcs.c18
-rw-r--r--src/pl/plpgsql/src/pl_gram.y45
-rw-r--r--src/pl/plpgsql/src/pl_handler.c11
-rw-r--r--src/pl/plpgsql/src/pl_scanner.c6
-rw-r--r--src/pl/plpgsql/src/plpgsql.h550
-rw-r--r--src/pl/plpgsql/src/po/fr.po316
-rw-r--r--src/pl/plpgsql/src/po/ko.po399
-rw-r--r--src/pl/plpgsql/src/po/pt_BR.po369
-rw-r--r--src/pl/plpgsql/src/po/ru.po363
-rw-r--r--src/pl/plpython/Makefile4
-rw-r--r--src/pl/plpython/expected/plpython_composite.out29
-rw-r--r--src/pl/plpython/expected/plpython_ereport.out28
-rw-r--r--src/pl/plpython/expected/plpython_setof.out7
-rw-r--r--src/pl/plpython/expected/plpython_spi.out23
-rw-r--r--src/pl/plpython/expected/plpython_test.out29
-rw-r--r--src/pl/plpython/expected/plpython_trigger.out21
-rw-r--r--src/pl/plpython/expected/plpython_types.out129
-rw-r--r--src/pl/plpython/expected/plpython_types_3.out129
-rw-r--r--src/pl/plpython/generate-spiexceptions.pl4
-rw-r--r--src/pl/plpython/plpy_cursorobject.c16
-rw-r--r--src/pl/plpython/plpy_cursorobject.h1
-rw-r--r--src/pl/plpython/plpy_elog.c2
-rw-r--r--src/pl/plpython/plpy_exec.c96
-rw-r--r--src/pl/plpython/plpy_main.c8
-rw-r--r--src/pl/plpython/plpy_planobject.c34
-rw-r--r--src/pl/plpython/plpy_plpymodule.c89
-rw-r--r--src/pl/plpython/plpy_procedure.c6
-rw-r--r--src/pl/plpython/plpy_spi.c29
-rw-r--r--src/pl/plpython/plpy_spi.h1
-rw-r--r--src/pl/plpython/plpy_subxactobject.c7
-rw-r--r--src/pl/plpython/plpy_typeio.c412
-rw-r--r--src/pl/plpython/plpy_typeio.h19
-rw-r--r--src/pl/plpython/plpython.h2
-rw-r--r--src/pl/plpython/po/de.po185
-rw-r--r--src/pl/plpython/po/fr.po271
-rw-r--r--src/pl/plpython/po/ko.po220
-rw-r--r--src/pl/plpython/po/pl.po246
-rw-r--r--src/pl/plpython/po/pt_BR.po185
-rw-r--r--src/pl/plpython/po/ru.po227
-rw-r--r--src/pl/plpython/sql/plpython_composite.sql21
-rw-r--r--src/pl/plpython/sql/plpython_ereport.sql8
-rw-r--r--src/pl/plpython/sql/plpython_spi.sql22
-rw-r--r--src/pl/plpython/sql/plpython_test.sql4
-rw-r--r--src/pl/plpython/sql/plpython_trigger.sql24
-rw-r--r--src/pl/plpython/sql/plpython_types.sql72
-rw-r--r--src/pl/tcl/Makefile9
-rw-r--r--src/pl/tcl/expected/pltcl_queries.out392
-rw-r--r--src/pl/tcl/expected/pltcl_setup.out159
-rw-r--r--src/pl/tcl/expected/pltcl_start_proc.out31
-rw-r--r--src/pl/tcl/expected/pltcl_subxact.out143
-rw-r--r--src/pl/tcl/generate-pltclerrcodes.pl4
-rw-r--r--src/pl/tcl/modules/.gitignore3
-rw-r--r--src/pl/tcl/modules/Makefile28
-rw-r--r--src/pl/tcl/modules/README18
-rw-r--r--src/pl/tcl/modules/pltcl_delmod.in117
-rw-r--r--src/pl/tcl/modules/pltcl_listmod.in123
-rw-r--r--src/pl/tcl/modules/pltcl_loadmod.in501
-rw-r--r--src/pl/tcl/modules/unknown.pltcl63
-rw-r--r--src/pl/tcl/pltcl.c1177
-rw-r--r--src/pl/tcl/po/de.po90
-rw-r--r--src/pl/tcl/po/pl.po120
-rw-r--r--src/pl/tcl/po/ru.po118
-rw-r--r--src/pl/tcl/sql/pltcl_queries.sql139
-rw-r--r--src/pl/tcl/sql/pltcl_setup.sql155
-rw-r--r--src/pl/tcl/sql/pltcl_start_proc.sql21
-rw-r--r--src/pl/tcl/sql/pltcl_subxact.sql95
-rw-r--r--src/port/Makefile4
-rw-r--r--src/port/README2
-rw-r--r--src/port/chklocale.c15
-rw-r--r--src/port/dirent.c2
-rw-r--r--src/port/dirmod.c21
-rw-r--r--src/port/erand48.c7
-rw-r--r--src/port/fls.c2
-rw-r--r--src/port/fseeko.c2
-rw-r--r--src/port/getaddrinfo.c2
-rw-r--r--src/port/getpeereid.c2
-rw-r--r--src/port/getrusage.c3
-rw-r--r--src/port/inet_net_ntop.c1
-rw-r--r--src/port/isinf.c2
-rw-r--r--src/port/kill.c2
-rw-r--r--src/port/mkdtemp.c2
-rw-r--r--src/port/noblock.c26
-rw-r--r--src/port/open.c3
-rw-r--r--src/port/path.c2
-rw-r--r--src/port/pg_crc32c_choose.c2
-rw-r--r--src/port/pg_crc32c_sb8.c2
-rw-r--r--src/port/pg_crc32c_sse42.c2
-rw-r--r--src/port/pg_strong_random.c149
-rw-r--r--src/port/pgcheckdir.c2
-rw-r--r--src/port/pgsleep.c5
-rw-r--r--src/port/pgstrcasecmp.c2
-rw-r--r--src/port/pqsignal.c33
-rw-r--r--src/port/quotes.c2
-rw-r--r--src/port/random.c2
-rw-r--r--src/port/sprompt.c46
-rw-r--r--src/port/srandom.c2
-rw-r--r--src/port/strlcpy.c2
-rw-r--r--src/port/system.c3
-rw-r--r--src/port/tar.c2
-rw-r--r--src/port/thread.c2
-rw-r--r--src/port/unsetenv.c2
-rw-r--r--src/port/win32env.c158
-rw-r--r--src/port/win32error.c5
-rw-r--r--src/port/win32security.c186
-rw-r--r--src/port/win32setlocale.c2
-rw-r--r--src/port/win32ver.rc6
-rw-r--r--src/template/darwin11
-rw-r--r--src/template/freebsd5
-rw-r--r--src/template/linux5
-rw-r--r--src/template/sco1
-rw-r--r--src/template/unixware41
-rw-r--r--src/test/Makefile2
-rw-r--r--src/test/README6
-rw-r--r--src/test/authentication/.gitignore2
-rw-r--r--src/test/authentication/Makefile20
-rw-r--r--src/test/authentication/README16
-rw-r--r--src/test/authentication/t/001_password.pl86
-rw-r--r--src/test/authentication/t/002_saslprep.pl105
-rw-r--r--src/test/examples/testlibpq2.c4
-rw-r--r--src/test/examples/testlo.c2
-rw-r--r--src/test/examples/testlo64.c2
-rw-r--r--src/test/isolation/.gitignore4
-rw-r--r--src/test/isolation/Makefile8
-rw-r--r--src/test/isolation/expected/eval-plan-qual.out21
-rw-r--r--src/test/isolation/expected/insert-conflict-do-nothing-2.out105
-rw-r--r--src/test/isolation/expected/insert-conflict-toast.out15
-rw-r--r--src/test/isolation/expected/insert-conflict-toast_1.out15
-rw-r--r--src/test/isolation/expected/read-only-anomaly-2.out44
-rw-r--r--src/test/isolation/expected/read-only-anomaly-3.out26
-rw-r--r--src/test/isolation/expected/read-only-anomaly.out25
-rw-r--r--src/test/isolation/expected/sequence-ddl.out85
-rw-r--r--src/test/isolation/expected/vacuum-reltuples.out59
-rw-r--r--src/test/isolation/isolation_main.c4
-rw-r--r--src/test/isolation/isolation_schedule7
-rw-r--r--src/test/isolation/isolationtester.c21
-rw-r--r--src/test/isolation/isolationtester.h2
-rw-r--r--src/test/isolation/specparse.y36
-rw-r--r--src/test/isolation/specs/eval-plan-qual.spec17
-rw-r--r--src/test/isolation/specs/insert-conflict-do-nothing-2.spec34
-rw-r--r--src/test/isolation/specs/insert-conflict-toast.spec51
-rw-r--r--src/test/isolation/specs/read-only-anomaly-2.spec42
-rw-r--r--src/test/isolation/specs/read-only-anomaly-3.spec39
-rw-r--r--src/test/isolation/specs/read-only-anomaly.spec38
-rw-r--r--src/test/isolation/specs/receipt-report.spec2
-rw-r--r--src/test/isolation/specs/sequence-ddl.spec39
-rw-r--r--src/test/isolation/specs/two-ids.spec2
-rw-r--r--src/test/isolation/specs/vacuum-reltuples.spec48
-rw-r--r--src/test/isolation/specscanner.l6
-rwxr-xr-xsrc/test/locale/sort-test.pl8
-rw-r--r--src/test/mb/expected/big5.out1
-rw-r--r--src/test/mb/expected/euc_jp.out1
-rw-r--r--src/test/mb/expected/euc_kr.out1
-rw-r--r--src/test/mb/expected/euc_tw.out1
-rw-r--r--src/test/mb/expected/gb18030.out1
-rw-r--r--src/test/mb/expected/mule_internal.out2
-rw-r--r--src/test/mb/expected/sjis.out1
-rw-r--r--src/test/mb/expected/utf8.out1
-rw-r--r--src/test/modules/commit_ts/Makefile10
-rw-r--r--src/test/modules/commit_ts/expected/commit_timestamp.out12
-rw-r--r--src/test/modules/commit_ts/expected/commit_timestamp_1.out12
-rw-r--r--src/test/modules/commit_ts/t/002_standby.pl10
-rw-r--r--src/test/modules/commit_ts/t/003_standby_2.pl7
-rw-r--r--src/test/modules/commit_ts/t/004_restart.pl122
-rw-r--r--src/test/modules/dummy_seclabel/dummy_seclabel.c2
-rw-r--r--src/test/modules/dummy_seclabel/expected/dummy_seclabel.out34
-rw-r--r--src/test/modules/dummy_seclabel/sql/dummy_seclabel.sql10
-rw-r--r--src/test/modules/snapshot_too_old/.gitignore2
-rw-r--r--src/test/modules/snapshot_too_old/Makefile8
-rw-r--r--src/test/modules/snapshot_too_old/expected/sto_using_hash_index.out15
-rw-r--r--src/test/modules/snapshot_too_old/specs/sto_using_hash_index.spec31
-rw-r--r--src/test/modules/test_ddl_deparse/Makefile1
-rw-r--r--src/test/modules/test_ddl_deparse/expected/alter_ts_config.out8
-rw-r--r--src/test/modules/test_ddl_deparse/expected/comment_on.out4
-rw-r--r--src/test/modules/test_ddl_deparse/sql/alter_ts_config.sql8
-rw-r--r--src/test/modules/test_ddl_deparse/sql/comment_on.sql5
-rw-r--r--src/test/modules/test_ddl_deparse/test_ddl_deparse.c6
-rw-r--r--src/test/modules/test_extensions/Makefile7
-rw-r--r--src/test/modules/test_extensions/expected/test_extensions.out83
-rw-r--r--src/test/modules/test_extensions/sql/test_extensions.sql47
-rw-r--r--src/test/modules/test_extensions/test_ext3--1.0.sql6
-rw-r--r--src/test/modules/test_extensions/test_ext7--1.0--2.0.sql8
-rw-r--r--src/test/modules/test_extensions/test_ext7--1.0.sql13
-rw-r--r--src/test/modules/test_extensions/test_ext7.control4
-rw-r--r--src/test/modules/test_extensions/test_ext8--1.0.sql21
-rw-r--r--src/test/modules/test_extensions/test_ext8.control4
-rw-r--r--src/test/modules/test_parser/test_parser.c3
-rw-r--r--src/test/modules/test_pg_dump/Makefile12
-rw-r--r--src/test/modules/test_pg_dump/expected/test_pg_dump.out100
-rw-r--r--src/test/modules/test_pg_dump/sql/test_pg_dump.sql108
-rw-r--r--src/test/modules/test_pg_dump/t/001_base.pl462
-rw-r--r--src/test/modules/test_pg_dump/test_pg_dump--1.0.sql27
-rw-r--r--src/test/modules/test_rls_hooks/expected/test_rls_hooks.out24
-rw-r--r--src/test/modules/test_rls_hooks/test_rls_hooks.c2
-rw-r--r--src/test/modules/test_rls_hooks/test_rls_hooks.h2
-rw-r--r--src/test/modules/test_shm_mq/setup.c7
-rw-r--r--src/test/modules/test_shm_mq/test.c5
-rw-r--r--src/test/modules/test_shm_mq/test_shm_mq.h2
-rw-r--r--src/test/modules/test_shm_mq/worker.c2
-rw-r--r--src/test/modules/worker_spi/worker_spi.c12
-rw-r--r--src/test/perl/Makefile33
-rw-r--r--src/test/perl/PostgresNode.pm461
-rw-r--r--src/test/perl/README33
-rw-r--r--src/test/perl/RecursiveCopy.pm4
-rw-r--r--src/test/perl/TestLib.pm51
-rw-r--r--src/test/recovery/Makefile6
-rw-r--r--src/test/recovery/t/001_stream_rep.pl229
-rw-r--r--src/test/recovery/t/002_archiving.pl12
-rw-r--r--src/test/recovery/t/003_recovery_targets.pl48
-rw-r--r--src/test/recovery/t/004_timeline_switch.pl23
-rw-r--r--src/test/recovery/t/005_replay_delay.pl5
-rw-r--r--src/test/recovery/t/006_logical_decoding.pl152
-rw-r--r--src/test/recovery/t/007_sync_rep.pl33
-rw-r--r--src/test/recovery/t/008_fsm_truncation.pl98
-rw-r--r--src/test/recovery/t/009_twophase.pl309
-rw-r--r--src/test/recovery/t/010_logical_decoding_timelines.pl197
-rw-r--r--src/test/recovery/t/011_crash_recovery.pl66
-rw-r--r--src/test/recovery/t/012_subtransactions.pl234
-rw-r--r--src/test/regress/GNUmakefile6
-rw-r--r--src/test/regress/expected/aggregates.out89
-rw-r--r--src/test/regress/expected/alter_generic.out83
-rw-r--r--src/test/regress/expected/alter_table.out1063
-rw-r--r--src/test/regress/expected/arrays.out122
-rw-r--r--src/test/regress/expected/boolean.out24
-rw-r--r--src/test/regress/expected/box.out104
-rw-r--r--src/test/regress/expected/brin.out139
-rw-r--r--src/test/regress/expected/case.out45
-rw-r--r--src/test/regress/expected/collate.icu.utf8.out1126
-rw-r--r--src/test/regress/expected/collate.linux.utf8.out112
-rw-r--r--src/test/regress/expected/collate.out20
-rw-r--r--src/test/regress/expected/combocid.out27
-rw-r--r--src/test/regress/expected/copy2.out112
-rw-r--r--src/test/regress/expected/create_function_3.out17
-rw-r--r--src/test/regress/expected/create_index.out103
-rw-r--r--src/test/regress/expected/create_table.out522
-rw-r--r--src/test/regress/expected/create_table_like.out100
-rw-r--r--src/test/regress/expected/create_view.out398
-rw-r--r--src/test/regress/expected/date.out8
-rw-r--r--src/test/regress/expected/enum.out88
-rw-r--r--src/test/regress/expected/equivclass.out70
-rw-r--r--src/test/regress/expected/errors.out2
-rw-r--r--src/test/regress/expected/event_trigger.out3
-rw-r--r--src/test/regress/expected/expressions.out77
-rw-r--r--src/test/regress/expected/foreign_data.out383
-rw-r--r--src/test/regress/expected/foreign_key.out34
-rw-r--r--src/test/regress/expected/gist.out34
-rw-r--r--src/test/regress/expected/groupingsets.out619
-rw-r--r--src/test/regress/expected/hash_index.out33
-rw-r--r--src/test/regress/expected/horology.out96
-rw-r--r--src/test/regress/expected/hs_standby_allowed.out8
-rw-r--r--src/test/regress/expected/hs_standby_functions.out2
-rw-r--r--src/test/regress/expected/identity.out322
-rw-r--r--src/test/regress/expected/indirect_toast.out8
-rw-r--r--src/test/regress/expected/inet.out148
-rw-r--r--src/test/regress/expected/inherit.out649
-rw-r--r--src/test/regress/expected/init_privs.out2
-rw-r--r--src/test/regress/expected/insert.out345
-rw-r--r--src/test/regress/expected/insert_conflict.out61
-rw-r--r--src/test/regress/expected/interval.out82
-rw-r--r--src/test/regress/expected/join.out436
-rw-r--r--src/test/regress/expected/json.out565
-rw-r--r--src/test/regress/expected/jsonb.out589
-rw-r--r--src/test/regress/expected/large_object.out15
-rw-r--r--src/test/regress/expected/limit.out10
-rw-r--r--src/test/regress/expected/macaddr.out1
-rw-r--r--src/test/regress/expected/macaddr8.out354
-rw-r--r--src/test/regress/expected/matview.out129
-rw-r--r--src/test/regress/expected/money.out259
-rw-r--r--src/test/regress/expected/numeric.out16
-rw-r--r--src/test/regress/expected/object_address.out51
-rw-r--r--src/test/regress/expected/oidjoins.out72
-rw-r--r--src/test/regress/expected/opr_sanity.out105
-rw-r--r--src/test/regress/expected/password.out91
-rw-r--r--src/test/regress/expected/plpgsql.out346
-rw-r--r--src/test/regress/expected/polymorphism.out69
-rw-r--r--src/test/regress/expected/portals.out16
-rw-r--r--src/test/regress/expected/prepared_xacts.out15
-rw-r--r--src/test/regress/expected/prepared_xacts_1.out14
-rw-r--r--src/test/regress/expected/privileges.out182
-rw-r--r--src/test/regress/expected/psql.out254
-rw-r--r--src/test/regress/expected/psql_crosstab.out13
-rw-r--r--src/test/regress/expected/publication.out242
-rw-r--r--src/test/regress/expected/rangefuncs.out12
-rw-r--r--src/test/regress/expected/regex.linux.utf8.out164
-rw-r--r--src/test/regress/expected/regex.out28
-rw-r--r--src/test/regress/expected/replica_identity.out45
-rw-r--r--src/test/regress/expected/rolenames.out2
-rw-r--r--src/test/regress/expected/rowsecurity.out126
-rw-r--r--src/test/regress/expected/rowtypes.out49
-rw-r--r--src/test/regress/expected/rules.out221
-rw-r--r--src/test/regress/expected/sanity_check.out22
-rw-r--r--src/test/regress/expected/select.out10
-rw-r--r--src/test/regress/expected/select_parallel.out210
-rw-r--r--src/test/regress/expected/select_views.out44
-rw-r--r--src/test/regress/expected/select_views_1.out1530
-rw-r--r--src/test/regress/expected/sequence.out336
-rw-r--r--src/test/regress/expected/sequence_1.out521
-rw-r--r--src/test/regress/expected/stats.out41
-rw-r--r--src/test/regress/expected/stats_ext.out507
-rw-r--r--src/test/regress/expected/strings.out4
-rw-r--r--src/test/regress/expected/subscription.out161
-rw-r--r--src/test/regress/expected/subselect.out157
-rw-r--r--src/test/regress/expected/sysviews.out121
-rw-r--r--src/test/regress/expected/tablesample.out32
-rw-r--r--src/test/regress/expected/tidscan.out179
-rw-r--r--src/test/regress/expected/timestamptz.out339
-rw-r--r--src/test/regress/expected/triggers.out130
-rw-r--r--src/test/regress/expected/tsdicts.out22
-rw-r--r--src/test/regress/expected/tsearch.out217
-rw-r--r--src/test/regress/expected/tsrf.out617
-rw-r--r--src/test/regress/expected/tstypes.out310
-rw-r--r--src/test/regress/expected/txid.out84
-rw-r--r--src/test/regress/expected/type_sanity.out17
-rw-r--r--src/test/regress/expected/typed_table.out67
-rw-r--r--src/test/regress/expected/union.out119
-rw-r--r--src/test/regress/expected/updatable_views.out164
-rw-r--r--src/test/regress/expected/update.out38
-rw-r--r--src/test/regress/expected/uuid.out13
-rw-r--r--src/test/regress/expected/vacuum.out9
-rw-r--r--src/test/regress/expected/with.out37
-rw-r--r--src/test/regress/expected/xml.out504
-rw-r--r--src/test/regress/expected/xml_1.out475
-rw-r--r--src/test/regress/expected/xml_2.out504
-rw-r--r--src/test/regress/expected/xmlmap.out64
-rw-r--r--src/test/regress/expected/xmlmap_1.out6
-rw-r--r--src/test/regress/input/create_function_2.source14
-rw-r--r--src/test/regress/input/tablespace.source50
-rw-r--r--src/test/regress/output/constraints.source2
-rw-r--r--src/test/regress/output/create_function_1.source2
-rw-r--r--src/test/regress/output/create_function_2.source12
-rw-r--r--src/test/regress/output/tablespace.source141
-rw-r--r--src/test/regress/parallel_schedule21
-rw-r--r--src/test/regress/pg_regress.c103
-rw-r--r--src/test/regress/pg_regress.h3
-rw-r--r--src/test/regress/pg_regress_main.c11
-rw-r--r--src/test/regress/regress.c74
-rw-r--r--src/test/regress/serial_schedule13
-rw-r--r--src/test/regress/sql/aggregates.sql25
-rw-r--r--src/test/regress/sql/alter_generic.sql35
-rw-r--r--src/test/regress/sql/alter_table.sql454
-rw-r--r--src/test/regress/sql/arrays.sql50
-rw-r--r--src/test/regress/sql/boolean.sql20
-rw-r--r--src/test/regress/sql/box.sql47
-rw-r--r--src/test/regress/sql/brin.sql89
-rw-r--r--src/test/regress/sql/case.sql46
-rw-r--r--src/test/regress/sql/collate.icu.utf8.sql433
-rw-r--r--src/test/regress/sql/collate.linux.utf8.sql34
-rw-r--r--src/test/regress/sql/combocid.sql18
-rw-r--r--src/test/regress/sql/copy2.sql92
-rw-r--r--src/test/regress/sql/create_function_3.sql10
-rw-r--r--src/test/regress/sql/create_index.sql17
-rw-r--r--src/test/regress/sql/create_table.sql378
-rw-r--r--src/test/regress/sql/create_table_like.sql19
-rw-r--r--src/test/regress/sql/create_view.sql46
-rw-r--r--src/test/regress/sql/date.sql2
-rw-r--r--src/test/regress/sql/enum.sql41
-rw-r--r--src/test/regress/sql/equivclass.sql41
-rw-r--r--src/test/regress/sql/errors.sql2
-rw-r--r--src/test/regress/sql/event_trigger.sql3
-rw-r--r--src/test/regress/sql/expressions.sql36
-rw-r--r--src/test/regress/sql/foreign_data.sql95
-rw-r--r--src/test/regress/sql/foreign_key.sql35
-rw-r--r--src/test/regress/sql/gist.sql16
-rw-r--r--src/test/regress/sql/groupingsets.sql158
-rw-r--r--src/test/regress/sql/hash_index.sql41
-rw-r--r--src/test/regress/sql/horology.sql30
-rw-r--r--src/test/regress/sql/hs_primary_extremes.sql2
-rw-r--r--src/test/regress/sql/hs_primary_setup.sql2
-rw-r--r--src/test/regress/sql/hs_standby_allowed.sql2
-rw-r--r--src/test/regress/sql/hs_standby_functions.sql2
-rw-r--r--src/test/regress/sql/identity.sql192
-rw-r--r--src/test/regress/sql/indirect_toast.sql8
-rw-r--r--src/test/regress/sql/inet.sql23
-rw-r--r--src/test/regress/sql/inherit.sql177
-rw-r--r--src/test/regress/sql/init_privs.sql2
-rw-r--r--src/test/regress/sql/insert.sql248
-rw-r--r--src/test/regress/sql/insert_conflict.sql52
-rw-r--r--src/test/regress/sql/interval.sql32
-rw-r--r--src/test/regress/sql/join.sql154
-rw-r--r--src/test/regress/sql/json.sql188
-rw-r--r--src/test/regress/sql/jsonb.sql193
-rw-r--r--src/test/regress/sql/large_object.sql8
-rw-r--r--src/test/regress/sql/macaddr8.sql89
-rw-r--r--src/test/regress/sql/matview.sql26
-rw-r--r--src/test/regress/sql/money.sql65
-rw-r--r--src/test/regress/sql/numeric.sql8
-rw-r--r--src/test/regress/sql/object_address.sql34
-rw-r--r--src/test/regress/sql/oidjoins.sql36
-rw-r--r--src/test/regress/sql/opr_sanity.sql81
-rw-r--r--src/test/regress/sql/password.sql72
-rw-r--r--src/test/regress/sql/plpgsql.sql348
-rw-r--r--src/test/regress/sql/polymorphism.sql22
-rw-r--r--src/test/regress/sql/prepared_xacts.sql6
-rw-r--r--src/test/regress/sql/privileges.sql110
-rw-r--r--src/test/regress/sql/psql.sql183
-rw-r--r--src/test/regress/sql/psql_crosstab.sql11
-rw-r--r--src/test/regress/sql/publication.sql144
-rw-r--r--src/test/regress/sql/rangefuncs.sql8
-rw-r--r--src/test/regress/sql/regex.linux.utf8.sql46
-rw-r--r--src/test/regress/sql/regex.sql7
-rw-r--r--src/test/regress/sql/replica_identity.sql2
-rw-r--r--src/test/regress/sql/rolenames.sql2
-rw-r--r--src/test/regress/sql/rowsecurity.sql49
-rw-r--r--src/test/regress/sql/rowtypes.sql28
-rw-r--r--src/test/regress/sql/rules.sql17
-rw-r--r--src/test/regress/sql/sanity_check.sql2
-rw-r--r--src/test/regress/sql/select.sql3
-rw-r--r--src/test/regress/sql/select_parallel.sql96
-rw-r--r--src/test/regress/sql/select_views.sql2
-rw-r--r--src/test/regress/sql/sequence.sql172
-rw-r--r--src/test/regress/sql/stats.sql32
-rw-r--r--src/test/regress/sql/stats_ext.sql283
-rw-r--r--src/test/regress/sql/subscription.sql123
-rw-r--r--src/test/regress/sql/subselect.sql58
-rw-r--r--src/test/regress/sql/sysviews.sql51
-rw-r--r--src/test/regress/sql/tablesample.sql8
-rw-r--r--src/test/regress/sql/tidscan.sql66
-rw-r--r--src/test/regress/sql/timestamptz.sql118
-rw-r--r--src/test/regress/sql/triggers.sql120
-rw-r--r--src/test/regress/sql/truncate.sql118
-rw-r--r--src/test/regress/sql/tsdicts.sql4
-rw-r--r--src/test/regress/sql/tsearch.sql44
-rw-r--r--src/test/regress/sql/tsrf.sql154
-rw-r--r--src/test/regress/sql/tstypes.sql58
-rw-r--r--src/test/regress/sql/txid.sql45
-rw-r--r--src/test/regress/sql/type_sanity.sql4
-rw-r--r--src/test/regress/sql/typed_table.sql21
-rw-r--r--src/test/regress/sql/union.sql41
-rw-r--r--src/test/regress/sql/updatable_views.sql39
-rw-r--r--src/test/regress/sql/update.sql31
-rw-r--r--src/test/regress/sql/vacuum.sql10
-rw-r--r--src/test/regress/sql/with.sql22
-rw-r--r--src/test/regress/sql/xml.sql288
-rw-r--r--src/test/regress/sql/xmlmap.sql3
-rw-r--r--src/test/ssl/Makefile13
-rw-r--r--src/test/ssl/README4
-rw-r--r--src/test/ssl/ServerSetup.pm91
-rw-r--r--src/test/ssl/cas.config7
-rw-r--r--src/test/ssl/root_ca.config4
-rw-r--r--src/test/ssl/server-cn-only.config1
-rw-r--r--src/test/ssl/server-no-names.config1
-rw-r--r--src/test/ssl/server-revoked.config1
-rw-r--r--src/test/ssl/ssl/.gitignore5
-rw-r--r--src/test/ssl/ssl/both-cas-1.crt67
-rw-r--r--src/test/ssl/ssl/both-cas-2.crt67
-rw-r--r--src/test/ssl/ssl/client+client_ca.crt25
-rw-r--r--src/test/ssl/ssl/client-revoked.crt16
-rw-r--r--src/test/ssl/ssl/client-revoked.key26
-rw-r--r--src/test/ssl/ssl/client.crl12
-rw-r--r--src/test/ssl/ssl/client.crt16
-rw-r--r--src/test/ssl/ssl/client.key26
-rw-r--r--src/test/ssl/ssl/client_ca.crt22
-rw-r--r--src/test/ssl/ssl/client_ca.key26
-rw-r--r--src/test/ssl/ssl/root+client.crl22
-rw-r--r--src/test/ssl/ssl/root+client_ca.crt45
-rw-r--r--src/test/ssl/ssl/root+server.crl22
-rw-r--r--src/test/ssl/ssl/root+server_ca.crt45
-rw-r--r--src/test/ssl/ssl/root.crl10
-rw-r--r--src/test/ssl/ssl/root_ca.crt23
-rw-r--r--src/test/ssl/ssl/root_ca.key26
-rw-r--r--src/test/ssl/ssl/server-cn-and-alt-names.crt18
-rw-r--r--src/test/ssl/ssl/server-cn-and-alt-names.key26
-rw-r--r--src/test/ssl/ssl/server-cn-only.crt16
-rw-r--r--src/test/ssl/ssl/server-cn-only.key26
-rw-r--r--src/test/ssl/ssl/server-multiple-alt-names.crt16
-rw-r--r--src/test/ssl/ssl/server-multiple-alt-names.key26
-rw-r--r--src/test/ssl/ssl/server-no-names.crt14
-rw-r--r--src/test/ssl/ssl/server-no-names.key26
-rw-r--r--src/test/ssl/ssl/server-revoked.crt16
-rw-r--r--src/test/ssl/ssl/server-revoked.key26
-rw-r--r--src/test/ssl/ssl/server-single-alt-name.crt14
-rw-r--r--src/test/ssl/ssl/server-single-alt-name.key26
-rw-r--r--src/test/ssl/ssl/server-ss.crt16
-rw-r--r--src/test/ssl/ssl/server-ss.key26
-rw-r--r--src/test/ssl/ssl/server.crl12
-rw-r--r--src/test/ssl/ssl/server_ca.crt22
-rw-r--r--src/test/ssl/ssl/server_ca.key26
-rw-r--r--src/test/ssl/t/001_ssltests.pl53
-rw-r--r--src/test/subscription/.gitignore2
-rw-r--r--src/test/subscription/Makefile22
-rw-r--r--src/test/subscription/README16
-rw-r--r--src/test/subscription/t/001_rep_changes.pl228
-rw-r--r--src/test/subscription/t/002_types.pl552
-rw-r--r--src/test/subscription/t/003_constraints.pl116
-rw-r--r--src/test/subscription/t/004_sync.pl164
-rw-r--r--src/test/subscription/t/005_encoding.pl56
-rw-r--r--src/test/thread/Makefile2
-rw-r--r--src/test/thread/thread_test.c2
-rw-r--r--src/timezone/README10
-rw-r--r--src/timezone/data/africa130
-rw-r--r--src/timezone/data/antarctica67
-rw-r--r--src/timezone/data/asia644
-rw-r--r--src/timezone/data/australasia209
-rw-r--r--src/timezone/data/backward2
-rw-r--r--src/timezone/data/backzone152
-rw-r--r--src/timezone/data/etcetera74
-rw-r--r--src/timezone/data/europe709
-rw-r--r--src/timezone/data/factory9
-rw-r--r--src/timezone/data/northamerica160
-rw-r--r--src/timezone/data/southamerica558
-rw-r--r--src/timezone/known_abbrevs.txt192
-rw-r--r--src/timezone/localtime.c103
-rw-r--r--src/timezone/pgtz.c58
-rw-r--r--src/timezone/pgtz.h2
-rw-r--r--src/timezone/private.h77
-rw-r--r--src/timezone/strftime.c15
-rw-r--r--src/timezone/tzfile.h52
-rw-r--r--src/timezone/tznames/Africa.txt2
-rw-r--r--src/timezone/tznames/America.txt112
-rw-r--r--src/timezone/tznames/Antarctica.txt29
-rw-r--r--src/timezone/tznames/Asia.txt151
-rw-r--r--src/timezone/tznames/Atlantic.txt15
-rw-r--r--src/timezone/tznames/Australia12
-rw-r--r--src/timezone/tznames/Australia.txt45
-rw-r--r--src/timezone/tznames/Default391
-rw-r--r--src/timezone/tznames/Etc.txt2
-rw-r--r--src/timezone/tznames/Europe.txt16
-rw-r--r--src/timezone/tznames/Indian.txt27
-rw-r--r--src/timezone/tznames/Pacific.txt114
-rw-r--r--src/timezone/tznames/README12
-rw-r--r--src/timezone/zic.c712
-rw-r--r--src/tools/RELEASE_CHANGES48
-rwxr-xr-xsrc/tools/check_bison_recursion.pl2
-rwxr-xr-xsrc/tools/copyright.pl2
-rwxr-xr-xsrc/tools/find_typedef2
-rw-r--r--src/tools/findoidjoins/Makefile2
-rw-r--r--src/tools/findoidjoins/README31
-rw-r--r--src/tools/findoidjoins/findoidjoins.c22
-rw-r--r--src/tools/fix-old-flex-code.pl66
-rwxr-xr-xsrc/tools/git_changelog6
-rw-r--r--src/tools/ifaddrs/.gitignore1
-rw-r--r--src/tools/ifaddrs/Makefile6
-rw-r--r--src/tools/ifaddrs/test_ifaddrs.c5
-rw-r--r--src/tools/msvc/Install.pm31
-rw-r--r--src/tools/msvc/Mkvcbuild.pm139
-rw-r--r--src/tools/msvc/Project.pm30
-rw-r--r--src/tools/msvc/Solution.pm208
-rw-r--r--src/tools/msvc/build.pl24
-rw-r--r--src/tools/msvc/builddoc.pl2
-rwxr-xr-xsrc/tools/msvc/clean.bat5
-rw-r--r--src/tools/msvc/config_default.pl3
-rw-r--r--src/tools/msvc/ecpg_regression.proj2
-rw-r--r--src/tools/msvc/gendef.pl31
-rwxr-xr-xsrc/tools/msvc/install.pl4
-rw-r--r--src/tools/msvc/mkvcbuild.pl4
-rw-r--r--src/tools/msvc/pgbison.pl4
-rw-r--r--src/tools/msvc/pgflex.pl37
-rw-r--r--src/tools/msvc/vcregress.pl84
-rwxr-xr-xsrc/tools/pginclude/pgcheckdefines91
-rw-r--r--src/tools/pgindent/README9
-rwxr-xr-xsrc/tools/pgindent/pgindent9
-rw-r--r--src/tools/pgindent/typedefs.list422
-rw-r--r--src/tools/testint128.c183
-rwxr-xr-xsrc/tools/version_stamp.pl36
-rwxr-xr-xsrc/tools/win32tzlist.pl8
-rw-r--r--src/tutorial/complex.source2
-rw-r--r--src/tutorial/funcs_new.c29
-rw-r--r--src/tutorial/syscat.source2
-rw-r--r--src/win32.mak32
2431 files changed, 417339 insertions, 477184 deletions
diff --git a/src/Makefile b/src/Makefile
index 5706bb1335..79cfeeb710 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -23,11 +23,13 @@ SUBDIRS = \
backend/snowball \
include \
backend/replication/libpqwalreceiver \
+ backend/replication/pgoutput \
fe_utils \
bin \
pl \
makefiles \
- test/regress
+ test/regress \
+ test/perl
# There are too many interdependencies between the subdirectories, so
# don't attempt parallel make here.
@@ -69,16 +71,5 @@ distclean maintainer-clean:
$(MAKE) -C test/thread $@
rm -f Makefile.port Makefile.global
-coverage:
- $(MAKE) -C timezone $@
- $(MAKE) -C gtm $@
- $(MAKE) -C backend $@
- $(MAKE) -C backend/utils/mb/conversion_procs $@
- $(MAKE) -C backend/snowball $@
- $(MAKE) -C interfaces $@
- $(MAKE) -C backend/replication/libpqwalreceiver $@
- $(MAKE) -C bin $@
- $(MAKE) -C pl $@
-
.PHONY: install-local installdirs-local uninstall-local
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 64b7b73d16..dc7b801dff 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -180,6 +180,7 @@ pgxsdir = $(pkglibdir)/pgxs
#
# Records the choice of the various --enable-xxx and --with-xxx options.
+with_icu = @with_icu@
with_perl = @with_perl@
with_python = @with_python@
with_tcl = @with_tcl@
@@ -198,6 +199,7 @@ enable_dtrace = @enable_dtrace@
enable_coverage = @enable_coverage@
enable_tap_tests = @enable_tap_tests@
enable_thread_safety = @enable_thread_safety@
+enable_strong_random = @enable_strong_random@
python_includespec = @python_includespec@
python_libdir = @python_libdir@
@@ -208,6 +210,9 @@ python_version = @python_version@
krb_srvtab = @krb_srvtab@
+ICU_CFLAGS = @ICU_CFLAGS@
+ICU_LIBS = @ICU_LIBS@
+
TCLSH = @TCLSH@
TCL_LIBS = @TCL_LIBS@
TCL_LIB_SPEC = @TCL_LIB_SPEC@
@@ -266,7 +271,6 @@ UUID_LIBS = @UUID_LIBS@
UUID_EXTRA_OBJS = @UUID_EXTRA_OBJS@
LD = @LD@
with_gnu_ld = @with_gnu_ld@
-ld_R_works = @ld_R_works@
# We want -L for libpgport.a and libpgcommon.a to be first in LDFLAGS. We
# also need LDFLAGS to be a "recursively expanded" variable, else adjustments
@@ -335,8 +339,11 @@ endif
endif
PROVE = @PROVE@
-PG_PROVE_FLAGS = -I $(top_srcdir)/src/test/perl/
-PROVE_FLAGS = --verbose
+# There are common routines in src/test/perl, and some test suites have
+# extra perl modules in their own directory.
+PG_PROVE_FLAGS = -I $(top_srcdir)/src/test/perl/ -I $(srcdir)
+# User-supplied prove flags such as --verbose can be provided in PROVE_FLAGS.
+
# prepend to path if already set, else just set it
define add_to_path
@@ -345,7 +352,7 @@ endef
# platform-specific environment variable to set shared library path
define ld_library_path_var
-$(if $(filter $(PORTNAME),darwin),DYLD_LIBRARY_PATH,$(if $(filter $(PORTNAME),aix),LIBPATH,LD_LIBRARY_PATH))
+$(if $(filter $(PORTNAME),darwin),DYLD_LIBRARY_PATH,$(if $(filter $(PORTNAME),aix),LIBPATH,$(if $(filter $(PORTNAME),hpux),SHLIB_PATH,LD_LIBRARY_PATH)))
endef
define with_temp_install
@@ -356,12 +363,12 @@ ifeq ($(enable_tap_tests),yes)
define prove_installcheck
rm -rf $(CURDIR)/tmp_check/log
-cd $(srcdir) && TESTDIR='$(CURDIR)' PATH="$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) t/*.pl
+cd $(srcdir) && TESTDIR='$(CURDIR)' PATH="$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl)
endef
define prove_check
rm -rf $(CURDIR)/tmp_check/log
-cd $(srcdir) && TESTDIR='$(CURDIR)' $(with_temp_install) PGPORT='6$(DEF_PGPORT)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) t/*.pl
+cd $(srcdir) && TESTDIR='$(CURDIR)' $(with_temp_install) PGPORT='6$(DEF_PGPORT)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl)
endef
else
@@ -395,11 +402,8 @@ STRIP_SHARED_LIB = @STRIP_SHARED_LIB@
# Documentation
-have_docbook = @have_docbook@
-COLLATEINDEX = @COLLATEINDEX@
DBTOEPUB = @DBTOEPUB@
-DOCBOOKSTYLE = @DOCBOOKSTYLE@
-JADE = @JADE@
+FOP = @FOP@
NSGMLS = @NSGMLS@
OSX = @OSX@
XMLLINT = @XMLLINT@
@@ -546,14 +550,35 @@ TEMP_CONF += --temp-config=$(TEMP_CONFIG)
endif
pg_regress_locale_flags = $(if $(ENCODING),--encoding=$(ENCODING)) $(NOLOCALE)
-
-pg_regress_check = $(with_temp_install) $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --temp-instance=./tmp_check $(TEMP_CONF) --bindir= $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
-pg_regress_installcheck = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --bindir='$(bindir)' $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
-
-pg_regress_clean_files = results/ regression.diffs regression.out tmp_check/ log/
-
-pg_isolation_regress_check = $(with_temp_install) $(top_builddir)/src/test/isolation/pg_isolation_regress --inputdir=$(srcdir) --temp-instance=./tmp_check $(TEMP_CONF) --bindir= $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
-pg_isolation_regress_installcheck = $(top_builddir)/src/test/isolation/pg_isolation_regress --inputdir=$(srcdir) $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
+pg_regress_clean_files = results/ regression.diffs regression.out tmp_check/ tmp_check_iso/ log/ output_iso/
+
+pg_regress_check = \
+ $(with_temp_install) \
+ $(top_builddir)/src/test/regress/pg_regress \
+ --temp-instance=./tmp_check \
+ --inputdir=$(srcdir) \
+ --bindir= \
+ $(TEMP_CONF) \
+ $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
+pg_regress_installcheck = \
+ $(top_builddir)/src/test/regress/pg_regress \
+ --inputdir=$(srcdir) \
+ --bindir='$(bindir)' \
+ $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
+
+pg_isolation_regress_check = \
+ $(with_temp_install) \
+ $(top_builddir)/src/test/isolation/pg_isolation_regress \
+ --temp-instance=./tmp_check_iso \
+ --inputdir=$(srcdir) --outputdir=output_iso \
+ --bindir= \
+ $(TEMP_CONF) \
+ $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
+pg_isolation_regress_installcheck = \
+ $(top_builddir)/src/test/isolation/pg_isolation_regress \
+ --inputdir=$(srcdir) --outputdir=output_iso \
+ --bindir='$(bindir)' \
+ $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS)
##########################################################################
#
@@ -583,6 +608,11 @@ ifneq ($(CUSTOM_COPT),)
COPT= $(CUSTOM_COPT)
endif
+#
+# These variables are meant to be set in the environment of "make"
+# to add flags to whatever configure picked. Unlike the ones above,
+# they are documented.
+#
ifdef COPT
CFLAGS += $(COPT)
LDFLAGS += $(COPT)
@@ -623,6 +653,7 @@ TAS = @TAS@
ifdef FLEX
$(FLEX) $(if $(FLEX_NO_BACKUP),-b) $(FLEXFLAGS) -o'$@' $<
@$(if $(FLEX_NO_BACKUP),if [ `wc -l <lex.backup` -eq 1 ]; then rm lex.backup; else echo "Scanner requires backup; see lex.backup." 1>&2; exit 1; fi)
+ $(if $(FLEX_FIX_WARNING),$(PERL) $(top_srcdir)/src/tools/fix-old-flex-code.pl '$@')
else
@$(missing) flex $< '$@'
endif
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 66452cc2bd..866a2572d4 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -47,9 +47,8 @@
# clean-lib delete the static and shared libraries from the build dir
# maintainer-clean-lib delete .def files built for win32
#
-# Since `all-lib' is the first rule in this file you probably want to
-# have the `all' target before including this file. In the most simple
-# case it would look like this:
+# Typically you would add `all-lib' to the `all' target so that `make all'
+# builds the libraries. In the most simple case it would look like this:
#
# all: all-lib
#
@@ -128,7 +127,7 @@ ifeq ($(PORTNAME), darwin)
else
# loadable module
DLSUFFIX = .so
- LINK.shared = $(COMPILER) -bundle -multiply_defined suppress -Wl,-undefined,dynamic_lookup
+ LINK.shared = $(COMPILER) -bundle -multiply_defined suppress
endif
BUILD.exports = $(AWK) '/^[^\#]/ {printf "_%s\n",$$1}' $< >$@
exports_file = $(SHLIB_EXPORTS:%.txt=%.list)
@@ -194,7 +193,7 @@ ifeq ($(PORTNAME), hpux)
# can't use the CC-syntax rpath pattern here, so instead:
rpath =
ifeq ($(enable_rpath), yes)
- LINK.shared += +b '$(rpathdir)'
+ LINK.shared += +s +b '$(rpathdir)'
endif
# On HPUX platforms, gcc is usually configured to search for libraries
# in /usr/local/lib, but ld won't do so. Add an explicit -L switch so
@@ -237,30 +236,6 @@ ifeq ($(PORTNAME), solaris)
endif
endif
-ifeq ($(PORTNAME), sco)
- ifeq ($(GCC), yes)
- LINK.shared = $(CC) -shared
- else
- LINK.shared = $(CC) -G
- endif
- LINK.shared += -Wl,-z,text
- ifdef soname
- LINK.shared += -Wl,-h,$(soname)
- endif
-endif
-
-ifeq ($(PORTNAME), unixware)
- ifeq ($(GCC), yes)
- LINK.shared = $(CC) -shared
- else
- LINK.shared = $(CC) -G
- endif
- LINK.shared += -Wl,-z,text
- ifdef soname
- LINK.shared += -Wl,-h,$(soname)
- endif
-endif
-
ifeq ($(PORTNAME), cygwin)
LINK.shared = $(CC) -shared
ifdef SO_MAJOR_VERSION
@@ -323,7 +298,7 @@ endif
endif # shlib_major
# Where possible, restrict the symbols exported by the library to just the
-# official list, so as to avoid unintentional ABI changes. On recent Darwin
+# official list, so as to avoid unintentional ABI changes. On recent macOS
# this also quiets multiply-defined-symbol warnings in programs that use
# libpgport along with libpq.
ifneq (,$(SHLIB_EXPORTS))
@@ -402,7 +377,7 @@ $(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
$(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
endif
-endif # PORTNAME == cgywin
+endif # PORTNAME == cygwin
endif # PORTNAME == cygwin || PORTNAME == win32
@@ -430,30 +405,22 @@ endif # PORTNAME == cygwin || PORTNAME == win32
# tarballs.
ifneq (,$(SHLIB_EXPORTS))
-distprep: lib$(NAME)dll.def lib$(NAME)ddll.def blib$(NAME)dll.def
+distprep: lib$(NAME)dll.def lib$(NAME)ddll.def
UC_NAME = $(shell echo $(NAME) | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
lib$(NAME)dll.def: $(SHLIB_EXPORTS)
- echo '; DEF file for win32.mak release build and for Makefile.shlib (MinGW)' >$@
+ echo '; DEF file for Makefile.shlib (MinGW)' >$@
echo 'LIBRARY LIB$(UC_NAME).dll' >>$@
echo 'EXPORTS' >>$@
sed -e '/^#/d' -e 's/^\(.*[ ]\)\([0-9][0-9]*\)/ \1@ \2/' $< >>$@
lib$(NAME)ddll.def: $(SHLIB_EXPORTS)
- echo '; DEF file for win32.mak debug build' >$@
+ echo '; DEF file for Makefile.shlib (MinGW)' >$@
echo 'LIBRARY LIB$(UC_NAME)D.dll' >>$@
echo 'EXPORTS' >>$@
sed -e '/^#/d' -e 's/^\(.*[ ]\)\([0-9][0-9]*\)/ \1@ \2/' $< >>$@
-blib$(NAME)dll.def: $(SHLIB_EXPORTS)
- echo '; DEF file for bcc32.mak (Borland C++ Builder)' >$@
- echo 'LIBRARY BLIB$(UC_NAME)' >>$@
- echo 'EXPORTS' >>$@
- sed -e '/^#/d' -e 's/^\(.*[ ]\)\([0-9][0-9]*\)/ _\1@ \2/' $< >>$@
- echo >>$@
- echo '; Aliases for MS compatible names' >> $@
- sed -e '/^#/d' -e 's/^\(.*[ ]\)\([0-9][0-9]*\)/ \1= _\1/' $< | sed 's/ *$$//' >>$@
endif # SHLIB_EXPORTS
@@ -542,5 +509,5 @@ clean-lib:
ifneq (,$(SHLIB_EXPORTS))
maintainer-clean-lib:
- rm -f lib$(NAME)dll.def lib$(NAME)ddll.def blib$(NAME)dll.def
+ rm -f lib$(NAME)dll.def lib$(NAME)ddll.def
endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index faec8d8523..d9aec0e0a4 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -2,7 +2,7 @@
#
# Makefile for the postgres backend
#
-# Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+# Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# src/backend/Makefile
@@ -23,15 +23,15 @@ endif
SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \
pgxc main nodes optimizer port postmaster regex replication rewrite \
- storage tcop tsearch utils $(top_builddir)/src/timezone $(top_builddir)/src/interfaces/libpq
+ statistics storage tcop tsearch utils $(top_builddir)/src/timezone $(top_builddir)/src/interfaces/libpq
include $(srcdir)/common.mk
# As of 1/2010:
# The probes.o file is necessary for dtrace support on Solaris, and on recent
# versions of systemtap. (Older systemtap releases just produce an empty
-# file, but that's okay.) However, OS X's dtrace doesn't use it and doesn't
-# even recognize the -G option. So, build probes.o except on Darwin.
+# file, but that's okay.) However, macOS's dtrace doesn't use it and doesn't
+# even recognize the -G option. So, build probes.o except on macOS.
# This might need adjustment as other platforms add dtrace support.
ifneq ($(PORTNAME), darwin)
ifeq ($(enable_dtrace), yes)
@@ -50,6 +50,7 @@ OBJS = $(SUBDIROBJS) $(LOCALOBJS) \
$(top_builddir)/src/interfaces/libpq/fe-exec.o \
$(top_builddir)/src/interfaces/libpq/fe-auth.o \
$(top_builddir)/src/interfaces/libpq/pqexpbuffer.o \
+ $(top_builddir)/src/interfaces/libpq/fe-auth-scram.o \
$(top_builddir)/src/gtm/client/libgtmclient.a \
$(top_builddir)/src/gtm/common/libgtm.a \
$(top_builddir)/src/gtm/libpq/libpqcomm.a
@@ -78,7 +79,7 @@ ifneq ($(PORTNAME), win32)
ifneq ($(PORTNAME), aix)
postgres: $(OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_EX) -L$(top_builddir)/src/gtm/libpg $(export_dynamic) $(call expand_subsys,$^) $(LIBS) -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_EX) -L$(top_builddir)/src/gtm/libpg $(export_dynamic) $(call expand_subsys,$^) $(LIBS) $(ICU_LIBS) -o $@
endif
endif
@@ -159,8 +160,11 @@ storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lw
utils/errcodes.h: utils/generate-errcodes.pl utils/errcodes.txt
$(MAKE) -C utils errcodes.h
+# see explanation in parser/Makefile
+utils/fmgrprotos.h: utils/fmgroids.h ;
+
utils/fmgroids.h: utils/Gen_fmgrtab.pl catalog/Catalog.pm $(top_srcdir)/src/include/catalog/pg_proc.h
- $(MAKE) -C utils fmgroids.h
+ $(MAKE) -C utils $(notdir $@)
utils/probes.h: utils/probes.d
$(MAKE) -C utils probes.h
@@ -186,7 +190,7 @@ submake-schemapg:
.PHONY: generated-headers
-generated-headers: $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/catalog/schemapg.h $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/errcodes.h $(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/probes.h
+generated-headers: $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/catalog/schemapg.h $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/errcodes.h $(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/fmgrprotos.h $(top_builddir)/src/include/utils/probes.h
$(top_builddir)/src/include/parser/gram.h: parser/gram.h
prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
@@ -213,6 +217,11 @@ $(top_builddir)/src/include/utils/fmgroids.h: utils/fmgroids.h
cd '$(dir $@)' && rm -f $(notdir $@) && \
$(LN_S) "$$prereqdir/$(notdir $<)" .
+$(top_builddir)/src/include/utils/fmgrprotos.h: utils/fmgrprotos.h
+ prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
+ cd '$(dir $@)' && rm -f $(notdir $@) && \
+ $(LN_S) "$$prereqdir/$(notdir $<)" .
+
$(top_builddir)/src/include/utils/probes.h: utils/probes.h
cd '$(dir $@)' && rm -f $(notdir $@) && \
$(LN_S) "../../../$(subdir)/utils/probes.h" .
@@ -231,7 +240,7 @@ distprep:
$(MAKE) -C catalog schemapg.h postgres.bki postgres.description postgres.shdescription
$(MAKE) -C replication repl_gram.c repl_scanner.c syncrep_gram.c syncrep_scanner.c
$(MAKE) -C storage/lmgr lwlocknames.h
- $(MAKE) -C utils fmgrtab.c fmgroids.h errcodes.h
+ $(MAKE) -C utils fmgrtab.c fmgroids.h fmgrprotos.h errcodes.h
$(MAKE) -C utils/misc guc-file.c
$(MAKE) -C utils/sort qsort_tuple.c
@@ -323,6 +332,7 @@ clean:
$(top_builddir)/src/include/catalog/schemapg.h \
$(top_builddir)/src/include/storage/lwlocknames.h \
$(top_builddir)/src/include/utils/fmgroids.h \
+ $(top_builddir)/src/include/utils/fmgrprotos.h \
$(top_builddir)/src/include/utils/probes.h
ifeq ($(PORTNAME), cygwin)
rm -f postgres.dll libpostgres.a
@@ -351,6 +361,7 @@ maintainer-clean: distclean
storage/lmgr/lwlocknames.c \
storage/lmgr/lwlocknames.h \
utils/fmgroids.h \
+ utils/fmgrprotos.h \
utils/fmgrtab.c \
utils/errcodes.h \
utils/misc/guc-file.c \
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index b194d33cc5..442a46140d 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -4,7 +4,7 @@
*
* See src/backend/access/brin/README for details.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -26,8 +26,10 @@
#include "catalog/pg_am.h"
#include "miscadmin.h"
#include "pgstat.h"
+#include "postmaster/autovacuum.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
+#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -59,10 +61,12 @@ typedef struct BrinOpaque
BrinDesc *bo_bdesc;
} BrinOpaque;
+#define BRIN_ALL_BLOCKRANGES InvalidBlockNumber
+
static BrinBuildState *initialize_brin_buildstate(Relation idxRel,
BrinRevmap *revmap, BlockNumber pagesPerRange);
static void terminate_brin_buildstate(BrinBuildState *state);
-static void brinsummarize(Relation index, Relation heapRel,
+static void brinsummarize(Relation index, Relation heapRel, BlockNumber pageRange,
double *numSummarized, double *numExisting);
static void form_and_insert_tuple(BrinBuildState *state);
static void union_tuples(BrinDesc *bdesc, BrinMemTuple *a,
@@ -92,6 +96,7 @@ brinhandler(PG_FUNCTION_ARGS)
amroutine->amstorage = true;
amroutine->amclusterable = false;
amroutine->ampredlocks = false;
+ amroutine->amcanparallel = false;
amroutine->amkeytype = InvalidOid;
amroutine->ambuild = brinbuild;
@@ -111,6 +116,9 @@ brinhandler(PG_FUNCTION_ARGS)
amroutine->amendscan = brinendscan;
amroutine->ammarkpos = NULL;
amroutine->amrestrpos = NULL;
+ amroutine->amestimateparallelscan = NULL;
+ amroutine->aminitparallelscan = NULL;
+ amroutine->amparallelrescan = NULL;
PG_RETURN_POINTER(amroutine);
}
@@ -121,57 +129,95 @@ brinhandler(PG_FUNCTION_ARGS)
* with those of the new tuple. If the tuple values are not consistent with
* the summary tuple, we need to update the index tuple.
*
+ * If autosummarization is enabled, check if we need to summarize the previous
+ * page range.
+ *
* If the range is not currently summarized (i.e. the revmap returns NULL for
- * it), there's nothing to do.
+ * it), there's nothing to do for this tuple.
*/
bool
brininsert(Relation idxRel, Datum *values, bool *nulls,
ItemPointer heaptid, Relation heapRel,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
BlockNumber pagesPerRange;
- BrinDesc *bdesc = NULL;
+ BlockNumber origHeapBlk;
+ BlockNumber heapBlk;
+ BrinDesc *bdesc = (BrinDesc *) indexInfo->ii_AmCache;
BrinRevmap *revmap;
Buffer buf = InvalidBuffer;
MemoryContext tupcxt = NULL;
- MemoryContext oldcxt = NULL;
+ MemoryContext oldcxt = CurrentMemoryContext;
+ bool autosummarize = BrinGetAutoSummarize(idxRel);
revmap = brinRevmapInitialize(idxRel, &pagesPerRange, NULL);
+ /*
+ * origHeapBlk is the block number where the insertion occurred. heapBlk
+ * is the first block in the corresponding page range.
+ */
+ origHeapBlk = ItemPointerGetBlockNumber(heaptid);
+ heapBlk = (origHeapBlk / pagesPerRange) * pagesPerRange;
+
for (;;)
{
bool need_insert = false;
OffsetNumber off;
BrinTuple *brtup;
BrinMemTuple *dtup;
- BlockNumber heapBlk;
int keyno;
CHECK_FOR_INTERRUPTS();
- heapBlk = ItemPointerGetBlockNumber(heaptid);
- /* normalize the block number to be the first block in the range */
- heapBlk = (heapBlk / pagesPerRange) * pagesPerRange;
- brtup = brinGetTupleForHeapBlock(revmap, heapBlk, &buf, &off, NULL,
- BUFFER_LOCK_SHARE, NULL);
+ /*
+ * If auto-summarization is enabled and we just inserted the first
+ * tuple into the first block of a new non-first page range, request a
+ * summarization run of the previous range.
+ */
+ if (autosummarize &&
+ heapBlk > 0 &&
+ heapBlk == origHeapBlk &&
+ ItemPointerGetOffsetNumber(heaptid) == FirstOffsetNumber)
+ {
+ BlockNumber lastPageRange = heapBlk - 1;
+ BrinTuple *lastPageTuple;
+
+ lastPageTuple =
+ brinGetTupleForHeapBlock(revmap, lastPageRange, &buf, &off,
+ NULL, BUFFER_LOCK_SHARE, NULL);
+ if (!lastPageTuple)
+ AutoVacuumRequestWork(AVW_BRINSummarizeRange,
+ RelationGetRelid(idxRel),
+ lastPageRange);
+ brin_free_tuple(lastPageTuple);
+ }
+
+ brtup = brinGetTupleForHeapBlock(revmap, heapBlk, &buf, &off,
+ NULL, BUFFER_LOCK_SHARE, NULL);
/* if range is unsummarized, there's nothing to do */
if (!brtup)
break;
- /* First time through? */
+ /* First time through in this statement? */
if (bdesc == NULL)
{
+ MemoryContextSwitchTo(indexInfo->ii_Context);
bdesc = brin_build_desc(idxRel);
+ indexInfo->ii_AmCache = (void *) bdesc;
+ MemoryContextSwitchTo(oldcxt);
+ }
+ /* First time through in this brininsert call? */
+ if (tupcxt == NULL)
+ {
tupcxt = AllocSetContextCreate(CurrentMemoryContext,
"brininsert cxt",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
- oldcxt = MemoryContextSwitchTo(tupcxt);
+ ALLOCSET_DEFAULT_SIZES);
+ MemoryContextSwitchTo(tupcxt);
}
- dtup = brin_deform_tuple(bdesc, brtup);
+ dtup = brin_deform_tuple(bdesc, brtup, NULL);
/*
* Compare the key values of the new tuple to the stored index values;
@@ -222,7 +268,7 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
* re-acquiring the lock.
*/
origsz = ItemIdGetLength(lp);
- origtup = brin_copy_tuple(brtup, origsz);
+ origtup = brin_copy_tuple(brtup, origsz, NULL, NULL);
/*
* Before releasing the lock, check if we can attempt a same-page
@@ -259,12 +305,9 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
brinRevmapTerminate(revmap);
if (BufferIsValid(buf))
ReleaseBuffer(buf);
- if (bdesc != NULL)
- {
- brin_free_desc(bdesc);
- MemoryContextSwitchTo(oldcxt);
+ MemoryContextSwitchTo(oldcxt);
+ if (tupcxt != NULL)
MemoryContextDelete(tupcxt);
- }
return false;
}
@@ -320,6 +363,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
FmgrInfo *consistentFn;
MemoryContext oldcxt;
MemoryContext perRangeCxt;
+ BrinMemTuple *dtup;
+ BrinTuple *btup = NULL;
+ Size btupsz = 0;
opaque = (BrinOpaque *) scan->opaque;
bdesc = opaque->bo_bdesc;
@@ -341,15 +387,16 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
*/
consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
+ /* allocate an initial in-memory tuple, out of the per-range memcxt */
+ dtup = brin_new_memtuple(bdesc);
+
/*
* Setup and use a per-range memory context, which is reset every time we
* loop below. This avoids having to free the tuples within the loop.
*/
perRangeCxt = AllocSetContextCreate(CurrentMemoryContext,
"bringetbitmap cxt",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(perRangeCxt);
/*
@@ -360,6 +407,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
for (heapBlk = 0; heapBlk < nblocks; heapBlk += opaque->bo_pagesPerRange)
{
bool addrange;
+ bool gottuple = false;
BrinTuple *tup;
OffsetNumber off;
Size size;
@@ -373,7 +421,8 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
scan->xs_snapshot);
if (tup)
{
- tup = brin_copy_tuple(tup, size);
+ gottuple = true;
+ btup = brin_copy_tuple(tup, size, btup, &btupsz);
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
}
@@ -381,15 +430,13 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
* For page ranges with no indexed tuple, we must return the whole
* range; otherwise, compare it to the scan keys.
*/
- if (tup == NULL)
+ if (!gottuple)
{
addrange = true;
}
else
{
- BrinMemTuple *dtup;
-
- dtup = brin_deform_tuple(bdesc, tup);
+ dtup = brin_deform_tuple(bdesc, btup, dtup);
if (dtup->bt_placeholder)
{
/*
@@ -741,7 +788,7 @@ brinvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
brin_vacuum_scan(info->index, info->strategy);
- brinsummarize(info->index, heapRel,
+ brinsummarize(info->index, heapRel, BRIN_ALL_BLOCKRANGES,
&stats->num_index_tuples, &stats->num_index_tuples);
heap_close(heapRel, AccessShareLock);
@@ -759,7 +806,8 @@ brinoptions(Datum reloptions, bool validate)
BrinOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = {
- {"pages_per_range", RELOPT_TYPE_INT, offsetof(BrinOptions, pagesPerRange)}
+ {"pages_per_range", RELOPT_TYPE_INT, offsetof(BrinOptions, pagesPerRange)},
+ {"autosummarize", RELOPT_TYPE_BOOL, offsetof(BrinOptions, autosummarize)}
};
options = parseRelOptions(reloptions, validate, RELOPT_KIND_BRIN,
@@ -786,12 +834,39 @@ brinoptions(Datum reloptions, bool validate)
Datum
brin_summarize_new_values(PG_FUNCTION_ARGS)
{
+ Datum relation = PG_GETARG_DATUM(0);
+
+ return DirectFunctionCall2(brin_summarize_range,
+ relation,
+ Int64GetDatum((int64) BRIN_ALL_BLOCKRANGES));
+}
+
+/*
+ * SQL-callable function to summarize the indicated page range, if not already
+ * summarized. If the second argument is BRIN_ALL_BLOCKRANGES, all
+ * unsummarized ranges are summarized.
+ */
+Datum
+brin_summarize_range(PG_FUNCTION_ARGS)
+{
Oid indexoid = PG_GETARG_OID(0);
+ int64 heapBlk64 = PG_GETARG_INT64(1);
+ BlockNumber heapBlk;
Oid heapoid;
Relation indexRel;
Relation heapRel;
double numSummarized = 0;
+ if (heapBlk64 > BRIN_ALL_BLOCKRANGES || heapBlk64 < 0)
+ {
+ char *blk = psprintf(INT64_FORMAT, heapBlk64);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("block number out of range: %s", blk)));
+ }
+ heapBlk = (BlockNumber) heapBlk64;
+
/*
* We must lock table before index to avoid deadlocks. However, if the
* passed indexoid isn't an index then IndexGetRelation() will fail.
@@ -831,7 +906,7 @@ brin_summarize_new_values(PG_FUNCTION_ARGS)
RelationGetRelationName(indexRel))));
/* OK, do it */
- brinsummarize(indexRel, heapRel, &numSummarized, NULL);
+ brinsummarize(indexRel, heapRel, heapBlk, &numSummarized, NULL);
relation_close(indexRel, ShareUpdateExclusiveLock);
relation_close(heapRel, ShareUpdateExclusiveLock);
@@ -840,6 +915,81 @@ brin_summarize_new_values(PG_FUNCTION_ARGS)
}
/*
+ * SQL-callable interface to mark a range as no longer summarized
+ */
+Datum
+brin_desummarize_range(PG_FUNCTION_ARGS)
+{
+ Oid indexoid = PG_GETARG_OID(0);
+ int64 heapBlk64 = PG_GETARG_INT64(1);
+ BlockNumber heapBlk;
+ Oid heapoid;
+ Relation heapRel;
+ Relation indexRel;
+ bool done;
+
+ if (heapBlk64 > MaxBlockNumber || heapBlk64 < 0)
+ {
+ char *blk = psprintf(INT64_FORMAT, heapBlk64);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("block number out of range: %s", blk)));
+ }
+ heapBlk = (BlockNumber) heapBlk64;
+
+ /*
+ * We must lock table before index to avoid deadlocks. However, if the
+ * passed indexoid isn't an index then IndexGetRelation() will fail.
+ * Rather than emitting a not-very-helpful error message, postpone
+ * complaining, expecting that the is-it-an-index test below will fail.
+ */
+ heapoid = IndexGetRelation(indexoid, true);
+ if (OidIsValid(heapoid))
+ heapRel = heap_open(heapoid, ShareUpdateExclusiveLock);
+ else
+ heapRel = NULL;
+
+ indexRel = index_open(indexoid, ShareUpdateExclusiveLock);
+
+ /* Must be a BRIN index */
+ if (indexRel->rd_rel->relkind != RELKIND_INDEX ||
+ indexRel->rd_rel->relam != BRIN_AM_OID)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a BRIN index",
+ RelationGetRelationName(indexRel))));
+
+ /* User must own the index (comparable to privileges needed for VACUUM) */
+ if (!pg_class_ownercheck(indexoid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+ RelationGetRelationName(indexRel));
+
+ /*
+ * Since we did the IndexGetRelation call above without any lock, it's
+ * barely possible that a race against an index drop/recreation could have
+ * netted us the wrong table. Recheck.
+ */
+ if (heapRel == NULL || heapoid != IndexGetRelation(indexoid, false))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("could not open parent table of index %s",
+ RelationGetRelationName(indexRel))));
+
+ /* the revmap does the hard work */
+ do
+ {
+ done = brinRevmapDesummarizeRange(indexRel, heapBlk);
+ }
+ while (!done);
+
+ relation_close(indexRel, ShareUpdateExclusiveLock);
+ relation_close(heapRel, ShareUpdateExclusiveLock);
+
+ PG_RETURN_VOID();
+}
+
+/*
* Build a BrinDesc used to create or scan a BRIN index
*/
BrinDesc *
@@ -856,9 +1006,7 @@ brin_build_desc(Relation rel)
cxt = AllocSetContextCreate(CurrentMemoryContext,
"brin desc cxt",
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(cxt);
tupdesc = RelationGetDescr(rel);
@@ -909,6 +1057,27 @@ brin_free_desc(BrinDesc *bdesc)
}
/*
+ * Fetch index's statistical data into *stats
+ */
+void
+brinGetStats(Relation index, BrinStatsData *stats)
+{
+ Buffer metabuffer;
+ Page metapage;
+ BrinMetaPageData *metadata;
+
+ metabuffer = ReadBuffer(index, BRIN_METAPAGE_BLKNO);
+ LockBuffer(metabuffer, BUFFER_LOCK_SHARE);
+ metapage = BufferGetPage(metabuffer);
+ metadata = (BrinMetaPageData *) PageGetContents(metapage);
+
+ stats->pagesPerRange = metadata->pagesPerRange;
+ stats->revmapNumPages = metadata->lastRevmapPage - 1;
+
+ UnlockReleaseBuffer(metabuffer);
+}
+
+/*
* Initialize a BrinBuildState appropriate to create tuples on the given index.
*/
static BrinBuildState *
@@ -1048,7 +1217,7 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel,
/* the placeholder tuple must exist */
if (phtup == NULL)
elog(ERROR, "missing placeholder tuple");
- phtup = brin_copy_tuple(phtup, phsz);
+ phtup = brin_copy_tuple(phtup, phsz, NULL, NULL);
LockBuffer(phbuf, BUFFER_LOCK_UNLOCK);
/* merge it into the tuple from the heap scan */
@@ -1059,17 +1228,17 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel,
}
/*
- * Scan a complete BRIN index, and summarize each page range that's not already
- * summarized. The index and heap must have been locked by caller in at
- * least ShareUpdateExclusiveLock mode.
+ * Summarize page ranges that are not already summarized. If pageRange is
+ * BRIN_ALL_BLOCKRANGES then the whole table is scanned; otherwise, only the
+ * page range containing the given heap page number is scanned.
*
* For each new index tuple inserted, *numSummarized (if not NULL) is
* incremented; for each existing tuple, *numExisting (if not NULL) is
* incremented.
*/
static void
-brinsummarize(Relation index, Relation heapRel, double *numSummarized,
- double *numExisting)
+brinsummarize(Relation index, Relation heapRel, BlockNumber pageRange,
+ double *numSummarized, double *numExisting)
{
BrinRevmap *revmap;
BrinBuildState *state = NULL;
@@ -1078,15 +1247,40 @@ brinsummarize(Relation index, Relation heapRel, double *numSummarized,
BlockNumber heapBlk;
BlockNumber pagesPerRange;
Buffer buf;
+ BlockNumber startBlk;
+ BlockNumber endBlk;
+
+ /* determine range of pages to process; nothing to do for an empty table */
+ heapNumBlocks = RelationGetNumberOfBlocks(heapRel);
+ if (heapNumBlocks == 0)
+ return;
revmap = brinRevmapInitialize(index, &pagesPerRange, NULL);
+ if (pageRange == BRIN_ALL_BLOCKRANGES)
+ {
+ startBlk = 0;
+ endBlk = heapNumBlocks;
+ }
+ else
+ {
+ startBlk = (pageRange / pagesPerRange) * pagesPerRange;
+ /* Nothing to do if start point is beyond end of table */
+ if (startBlk > heapNumBlocks)
+ {
+ brinRevmapTerminate(revmap);
+ return;
+ }
+ endBlk = startBlk + pagesPerRange;
+ if (endBlk > heapNumBlocks)
+ endBlk = heapNumBlocks;
+ }
+
/*
* Scan the revmap to find unsummarized items.
*/
buf = InvalidBuffer;
- heapNumBlocks = RelationGetNumberOfBlocks(heapRel);
- for (heapBlk = 0; heapBlk < heapNumBlocks; heapBlk += pagesPerRange)
+ for (heapBlk = startBlk; heapBlk < endBlk; heapBlk += pagesPerRange)
{
BrinTuple *tup;
OffsetNumber off;
@@ -1169,11 +1363,9 @@ union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b)
/* Use our own memory context to avoid retail pfree */
cxt = AllocSetContextCreate(CurrentMemoryContext,
"brin union",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(cxt);
- db = brin_deform_tuple(bdesc, b);
+ db = brin_deform_tuple(bdesc, b, NULL);
MemoryContextSwitchTo(oldcxt);
for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++)
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 0ae7a72996..bc16dd7981 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -16,7 +16,7 @@
* writing is the INET type, where IPv6 values cannot be merged with IPv4
* values.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -30,6 +30,7 @@
#include "access/skey.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_type.h"
+#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
@@ -76,10 +77,6 @@ typedef struct InclusionOpaque
FmgrInfo strategy_procinfos[RTMaxStrategyNumber];
} InclusionOpaque;
-Datum brin_inclusion_opcinfo(PG_FUNCTION_ARGS);
-Datum brin_inclusion_add_value(PG_FUNCTION_ARGS);
-Datum brin_inclusion_consistent(PG_FUNCTION_ARGS);
-Datum brin_inclusion_union(PG_FUNCTION_ARGS);
static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
uint16 procnum);
static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
@@ -431,7 +428,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
* It is straightforward to support the equality strategies with
* the contains operator. Generally, inequality strategies do not
* make much sense for the types which will be used with the
- * inclusion BRIN family of opclasses, but is is possible to
+ * inclusion BRIN family of opclasses, but is possible to
* implement them with logical negation of the left-of and
* right-of operators.
*
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index b7c76e6eda..8f7a0c75b8 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -2,7 +2,7 @@
* brin_minmax.c
* Implementation of Min/Max opclass for BRIN
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -16,6 +16,7 @@
#include "access/stratnum.h"
#include "catalog/pg_type.h"
#include "catalog/pg_amop.h"
+#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
@@ -28,10 +29,6 @@ typedef struct MinmaxOpaque
FmgrInfo strategy_procinfos[BTMaxStrategyNumber];
} MinmaxOpaque;
-Datum brin_minmax_opcinfo(PG_FUNCTION_ARGS);
-Datum brin_minmax_add_value(PG_FUNCTION_ARGS);
-Datum brin_minmax_consistent(PG_FUNCTION_ARGS);
-Datum brin_minmax_union(PG_FUNCTION_ARGS);
static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
Oid subtype, uint16 strategynum);
diff --git a/src/backend/access/brin/brin_pageops.c b/src/backend/access/brin/brin_pageops.c
index 6ebfedd6a9..1725591b05 100644
--- a/src/backend/access/brin/brin_pageops.c
+++ b/src/backend/access/brin/brin_pageops.c
@@ -2,7 +2,7 @@
* brin_pageops.c
* Page-handling routines for BRIN indexes
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -178,10 +178,8 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
}
START_CRIT_SECTION();
- PageIndexDeleteNoCompact(oldpage, &oldoff, 1);
- if (PageAddItemExtended(oldpage, (Item) newtup, newsz, oldoff,
- PAI_OVERWRITE | PAI_ALLOW_FAR_OFFSET) == InvalidOffsetNumber)
- elog(ERROR, "failed to add BRIN tuple");
+ if (!PageIndexTupleOverwrite(oldpage, oldoff, (Item) newtup, newsz))
+ elog(ERROR, "failed to replace BRIN tuple");
MarkBufferDirty(oldbuf);
/* XLOG stuff */
@@ -247,7 +245,7 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
if (extended)
brin_page_init(BufferGetPage(newbuf), BRIN_PAGETYPE_REGULAR);
- PageIndexDeleteNoCompact(oldpage, &oldoff, 1);
+ PageIndexTupleDeleteNoCompact(oldpage, oldoff);
newoff = PageAddItem(newpage, (Item) newtup, newsz,
InvalidOffsetNumber, false, false);
if (newoff == InvalidOffsetNumber)
@@ -289,7 +287,7 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
XLogRegisterBufData(0, (char *) newtup, newsz);
/* revmap page */
- XLogRegisterBuffer(1, revmapbuf, REGBUF_STANDARD);
+ XLogRegisterBuffer(1, revmapbuf, 0);
/* old page */
XLogRegisterBuffer(2, oldbuf, REGBUF_STANDARD);
@@ -550,6 +548,8 @@ brin_evacuate_page(Relation idxRel, BlockNumber pagesPerRange,
OffsetNumber off;
OffsetNumber maxoff;
Page page;
+ BrinTuple *btup = NULL;
+ Size btupsz = 0;
page = BufferGetPage(buf);
@@ -569,7 +569,7 @@ brin_evacuate_page(Relation idxRel, BlockNumber pagesPerRange,
{
sz = ItemIdGetLength(lp);
tup = (BrinTuple *) PageGetItem(page, lp);
- tup = brin_copy_tuple(tup, sz);
+ tup = brin_copy_tuple(tup, sz, btup, &btupsz);
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c
index 853181b3fa..fc8b10ab39 100644
--- a/src/backend/access/brin/brin_revmap.c
+++ b/src/backend/access/brin/brin_revmap.c
@@ -12,7 +12,7 @@
* the metapage. When the revmap needs to be expanded, all tuples on the
* regular BRIN page at that block (if any) are moved out of the way.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -168,9 +168,12 @@ brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange,
iptr = (ItemPointerData *) contents->rm_tids;
iptr += HEAPBLK_TO_REVMAP_INDEX(pagesPerRange, heapBlk);
- ItemPointerSet(iptr,
- ItemPointerGetBlockNumber(&tid),
- ItemPointerGetOffsetNumber(&tid));
+ if (ItemPointerIsValid(&tid))
+ ItemPointerSet(iptr,
+ ItemPointerGetBlockNumber(&tid),
+ ItemPointerGetOffsetNumber(&tid));
+ else
+ ItemPointerSetInvalid(iptr);
}
/*
@@ -205,7 +208,11 @@ brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk,
/* normalize the heap block number to be the first page in the range */
heapBlk = (heapBlk / revmap->rm_pagesPerRange) * revmap->rm_pagesPerRange;
- /* Compute the revmap page number we need */
+ /*
+ * Compute the revmap page number we need. If Invalid is returned (i.e.,
+ * the revmap page hasn't been created yet), the requested page range is
+ * not summarized.
+ */
mapBlk = revmap_get_blkno(revmap, heapBlk);
if (mapBlk == InvalidBlockNumber)
{
@@ -301,6 +308,138 @@ brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk,
}
/*
+ * Delete an index tuple, marking a page range as unsummarized.
+ *
+ * Index must be locked in ShareUpdateExclusiveLock mode.
+ *
+ * Return FALSE if caller should retry.
+ */
+bool
+brinRevmapDesummarizeRange(Relation idxrel, BlockNumber heapBlk)
+{
+ BrinRevmap *revmap;
+ BlockNumber pagesPerRange;
+ RevmapContents *contents;
+ ItemPointerData *iptr;
+ ItemPointerData invalidIptr;
+ BlockNumber revmapBlk;
+ Buffer revmapBuf;
+ Buffer regBuf;
+ Page revmapPg;
+ Page regPg;
+ OffsetNumber revmapOffset;
+ OffsetNumber regOffset;
+ ItemId lp;
+ BrinTuple *tup;
+
+ revmap = brinRevmapInitialize(idxrel, &pagesPerRange, NULL);
+
+ revmapBlk = revmap_get_blkno(revmap, heapBlk);
+ if (!BlockNumberIsValid(revmapBlk))
+ {
+ /* revmap page doesn't exist: range not summarized, we're done */
+ brinRevmapTerminate(revmap);
+ return true;
+ }
+
+ /* Lock the revmap page, obtain the index tuple pointer from it */
+ revmapBuf = brinLockRevmapPageForUpdate(revmap, heapBlk);
+ revmapPg = BufferGetPage(revmapBuf);
+ revmapOffset = HEAPBLK_TO_REVMAP_INDEX(revmap->rm_pagesPerRange, heapBlk);
+
+ contents = (RevmapContents *) PageGetContents(revmapPg);
+ iptr = contents->rm_tids;
+ iptr += revmapOffset;
+
+ if (!ItemPointerIsValid(iptr))
+ {
+ /* no index tuple: range not summarized, we're done */
+ LockBuffer(revmapBuf, BUFFER_LOCK_UNLOCK);
+ brinRevmapTerminate(revmap);
+ return true;
+ }
+
+ regBuf = ReadBuffer(idxrel, ItemPointerGetBlockNumber(iptr));
+ LockBuffer(regBuf, BUFFER_LOCK_EXCLUSIVE);
+ regPg = BufferGetPage(regBuf);
+
+ /* if this is no longer a regular page, tell caller to start over */
+ if (!BRIN_IS_REGULAR_PAGE(regPg))
+ {
+ LockBuffer(revmapBuf, BUFFER_LOCK_UNLOCK);
+ LockBuffer(regBuf, BUFFER_LOCK_UNLOCK);
+ brinRevmapTerminate(revmap);
+ return false;
+ }
+
+ regOffset = ItemPointerGetOffsetNumber(iptr);
+ if (regOffset > PageGetMaxOffsetNumber(regPg))
+ ereport(ERROR,
+ (errcode(ERRCODE_INDEX_CORRUPTED),
+ errmsg("corrupted BRIN index: inconsistent range map")));
+
+ lp = PageGetItemId(regPg, regOffset);
+ if (!ItemIdIsUsed(lp))
+ ereport(ERROR,
+ (errcode(ERRCODE_INDEX_CORRUPTED),
+ errmsg("corrupted BRIN index: inconsistent range map")));
+ tup = (BrinTuple *) PageGetItem(regPg, lp);
+ /* XXX apply sanity checks? Might as well delete a bogus tuple ... */
+
+ /*
+ * We're only removing data, not reading it, so there's no need to
+ * TestForOldSnapshot here.
+ */
+
+ /*
+ * Because of SUE lock, this function shouldn't run concurrently with
+ * summarization. Placeholder tuples can only exist as leftovers from
+ * crashed summarization, so if we detect any, we complain but proceed.
+ */
+ if (BrinTupleIsPlaceholder(tup))
+ ereport(WARNING,
+ (errmsg("leftover placeholder tuple detected in BRIN index \"%s\", deleting",
+ RelationGetRelationName(idxrel))));
+
+ START_CRIT_SECTION();
+
+ ItemPointerSetInvalid(&invalidIptr);
+ brinSetHeapBlockItemptr(revmapBuf, revmap->rm_pagesPerRange, heapBlk,
+ invalidIptr);
+ PageIndexTupleDeleteNoCompact(regPg, regOffset);
+ /* XXX record free space in FSM? */
+
+ MarkBufferDirty(regBuf);
+ MarkBufferDirty(revmapBuf);
+
+ if (RelationNeedsWAL(idxrel))
+ {
+ xl_brin_desummarize xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.pagesPerRange = revmap->rm_pagesPerRange;
+ xlrec.heapBlk = heapBlk;
+ xlrec.regOffset = regOffset;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfBrinDesummarize);
+ XLogRegisterBuffer(0, revmapBuf, 0);
+ XLogRegisterBuffer(1, regBuf, REGBUF_STANDARD);
+ recptr = XLogInsert(RM_BRIN_ID, XLOG_BRIN_DESUMMARIZE);
+ PageSetLSN(revmapPg, recptr);
+ PageSetLSN(regPg, recptr);
+ }
+
+ END_CRIT_SECTION();
+
+ UnlockReleaseBuffer(regBuf);
+ LockBuffer(revmapBuf, BUFFER_LOCK_UNLOCK);
+ brinRevmapTerminate(revmap);
+
+ return true;
+}
+
+/*
* Given a heap block number, find the corresponding physical revmap block
* number and return it. If the revmap page hasn't been allocated yet, return
* InvalidBlockNumber.
diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c
index 64b8264959..e2e1d23377 100644
--- a/src/backend/access/brin/brin_tuple.c
+++ b/src/backend/access/brin/brin_tuple.c
@@ -23,7 +23,7 @@
* Note the size of the null bitmask may not be the same as that of the
* datum array.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -311,17 +311,26 @@ brin_free_tuple(BrinTuple *tuple)
}
/*
- * Create a palloc'd copy of a BrinTuple.
+ * Given a brin tuple of size len, create a copy of it. If 'dest' is not
+ * NULL, its size is destsz, and can be used as output buffer; if the tuple
+ * to be copied does not fit, it is enlarged by repalloc, and the size is
+ * updated to match. This avoids palloc/free cycles when many brin tuples
+ * are being processed in loops.
*/
BrinTuple *
-brin_copy_tuple(BrinTuple *tuple, Size len)
+brin_copy_tuple(BrinTuple *tuple, Size len, BrinTuple *dest, Size *destsz)
{
- BrinTuple *newtup;
+ if (!destsz || *destsz == 0)
+ dest = palloc(len);
+ else if (len > *destsz)
+ {
+ dest = repalloc(dest, len);
+ *destsz = len;
+ }
- newtup = palloc(len);
- memcpy(newtup, tuple, len);
+ memcpy(dest, tuple, len);
- return newtup;
+ return dest;
}
/*
@@ -348,56 +357,69 @@ BrinMemTuple *
brin_new_memtuple(BrinDesc *brdesc)
{
BrinMemTuple *dtup;
- char *currdatum;
long basesize;
- int i;
basesize = MAXALIGN(sizeof(BrinMemTuple) +
sizeof(BrinValues) * brdesc->bd_tupdesc->natts);
dtup = palloc0(basesize + sizeof(Datum) * brdesc->bd_totalstored);
- currdatum = (char *) dtup + basesize;
- for (i = 0; i < brdesc->bd_tupdesc->natts; i++)
- {
- dtup->bt_columns[i].bv_attno = i + 1;
- dtup->bt_columns[i].bv_allnulls = true;
- dtup->bt_columns[i].bv_hasnulls = false;
- dtup->bt_columns[i].bv_values = (Datum *) currdatum;
- currdatum += sizeof(Datum) * brdesc->bd_info[i]->oi_nstored;
- }
+
+ dtup->bt_values = palloc(sizeof(Datum) * brdesc->bd_totalstored);
+ dtup->bt_allnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
+ dtup->bt_hasnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
dtup->bt_context = AllocSetContextCreate(CurrentMemoryContext,
"brin dtuple",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
+
+ brin_memtuple_initialize(dtup, brdesc);
+
return dtup;
}
/*
- * Reset a BrinMemTuple to initial state
+ * Reset a BrinMemTuple to initial state. We return the same tuple, for
+ * notational convenience.
*/
-void
+BrinMemTuple *
brin_memtuple_initialize(BrinMemTuple *dtuple, BrinDesc *brdesc)
{
int i;
+ char *currdatum;
MemoryContextReset(dtuple->bt_context);
+
+ currdatum = (char *) dtuple +
+ MAXALIGN(sizeof(BrinMemTuple) +
+ sizeof(BrinValues) * brdesc->bd_tupdesc->natts);
for (i = 0; i < brdesc->bd_tupdesc->natts; i++)
{
dtuple->bt_columns[i].bv_allnulls = true;
dtuple->bt_columns[i].bv_hasnulls = false;
+
+ dtuple->bt_columns[i].bv_attno = i + 1;
+ dtuple->bt_columns[i].bv_allnulls = true;
+ dtuple->bt_columns[i].bv_hasnulls = false;
+ dtuple->bt_columns[i].bv_values = (Datum *) currdatum;
+ currdatum += sizeof(Datum) * brdesc->bd_info[i]->oi_nstored;
}
+
+ return dtuple;
}
/*
* Convert a BrinTuple back to a BrinMemTuple. This is the reverse of
* brin_form_tuple.
*
+ * As an optimization, the caller can pass a previously allocated 'dMemtuple'.
+ * This avoids having to allocate it here, which can be useful when this
+ * function is called many times in a loop. It is caller's responsibility
+ * that the given BrinMemTuple matches what we need here.
+ *
* Note we don't need the "on disk tupdesc" here; we rely on our own routine to
* deconstruct the tuple from the on-disk format.
*/
BrinMemTuple *
-brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple)
+brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple, BrinMemTuple *dMemtuple)
{
BrinMemTuple *dtup;
Datum *values;
@@ -409,15 +431,16 @@ brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple)
int valueno;
MemoryContext oldcxt;
- dtup = brin_new_memtuple(brdesc);
+ dtup = dMemtuple ? brin_memtuple_initialize(dMemtuple, brdesc) :
+ brin_new_memtuple(brdesc);
if (BrinTupleIsPlaceholder(tuple))
dtup->bt_placeholder = true;
dtup->bt_blkno = tuple->bt_blkno;
- values = palloc(sizeof(Datum) * brdesc->bd_totalstored);
- allnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
- hasnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
+ values = dtup->bt_values;
+ allnulls = dtup->bt_allnulls;
+ hasnulls = dtup->bt_hasnulls;
tp = (char *) tuple + BrinTupleDataOffset(tuple);
@@ -460,10 +483,6 @@ brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple)
MemoryContextSwitchTo(oldcxt);
- pfree(values);
- pfree(allnulls);
- pfree(hasnulls);
-
return dtup;
}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 1f1011e0ac..dc23e00e89 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -3,7 +3,7 @@
* brin_validate.c
* Opclass validator for BRIN.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -23,6 +23,7 @@
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
+#include "utils/regproc.h"
/*
diff --git a/src/backend/access/brin/brin_xlog.c b/src/backend/access/brin/brin_xlog.c
index 27ba0a97f8..dff7198a39 100644
--- a/src/backend/access/brin/brin_xlog.c
+++ b/src/backend/access/brin/brin_xlog.c
@@ -2,7 +2,7 @@
* brin_xlog.c
* XLog replay routines for BRIN indexes
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -13,6 +13,7 @@
#include "access/brin_page.h"
#include "access/brin_pageops.h"
#include "access/brin_xlog.h"
+#include "access/bufmask.h"
#include "access/xlogutils.h"
@@ -148,10 +149,8 @@ brin_xlog_update(XLogReaderState *record)
page = (Page) BufferGetPage(buffer);
offnum = xlrec->oldOffnum;
- if (PageGetMaxOffsetNumber(page) + 1 < offnum)
- elog(PANIC, "brin_xlog_update: invalid max offset number");
- PageIndexDeleteNoCompact(page, &offnum, 1);
+ PageIndexTupleDeleteNoCompact(page, offnum);
PageSetLSN(page, lsn);
MarkBufferDirty(buffer);
@@ -189,14 +188,9 @@ brin_xlog_samepage_update(XLogReaderState *record)
page = (Page) BufferGetPage(buffer);
offnum = xlrec->offnum;
- if (PageGetMaxOffsetNumber(page) + 1 < offnum)
- elog(PANIC, "brin_xlog_samepage_update: invalid max offset number");
- PageIndexDeleteNoCompact(page, &offnum, 1);
- offnum = PageAddItemExtended(page, (Item) brintuple, tuplen, offnum,
- PAI_OVERWRITE | PAI_ALLOW_FAR_OFFSET);
- if (offnum == InvalidOffsetNumber)
- elog(PANIC, "brin_xlog_samepage_update: failed to add tuple");
+ if (!PageIndexTupleOverwrite(page, offnum, (Item) brintuple, tuplen))
+ elog(PANIC, "brin_xlog_samepage_update: failed to replace tuple");
PageSetLSN(page, lsn);
MarkBufferDirty(buffer);
@@ -260,6 +254,46 @@ brin_xlog_revmap_extend(XLogReaderState *record)
UnlockReleaseBuffer(metabuf);
}
+static void
+brin_xlog_desummarize_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_brin_desummarize *xlrec;
+ Buffer buffer;
+ XLogRedoAction action;
+
+ xlrec = (xl_brin_desummarize *) XLogRecGetData(record);
+
+ /* Update the revmap */
+ action = XLogReadBufferForRedo(record, 0, &buffer);
+ if (action == BLK_NEEDS_REDO)
+ {
+ ItemPointerData iptr;
+
+ ItemPointerSetInvalid(&iptr);
+ brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk, iptr);
+
+ PageSetLSN(BufferGetPage(buffer), lsn);
+ MarkBufferDirty(buffer);
+ }
+ if (BufferIsValid(buffer))
+ UnlockReleaseBuffer(buffer);
+
+ /* remove the leftover entry from the regular page */
+ action = XLogReadBufferForRedo(record, 1, &buffer);
+ if (action == BLK_NEEDS_REDO)
+ {
+ Page regPg = BufferGetPage(buffer);
+
+ PageIndexTupleDeleteNoCompact(regPg, xlrec->regOffset);
+
+ PageSetLSN(regPg, lsn);
+ MarkBufferDirty(buffer);
+ }
+ if (BufferIsValid(buffer))
+ UnlockReleaseBuffer(buffer);
+}
+
void
brin_redo(XLogReaderState *record)
{
@@ -282,7 +316,29 @@ brin_redo(XLogReaderState *record)
case XLOG_BRIN_REVMAP_EXTEND:
brin_xlog_revmap_extend(record);
break;
+ case XLOG_BRIN_DESUMMARIZE:
+ brin_xlog_desummarize_page(record);
+ break;
default:
elog(PANIC, "brin_redo: unknown op code %u", info);
}
}
+
+/*
+ * Mask a BRIN page before doing consistency checks.
+ */
+void
+brin_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+
+ mask_page_lsn(page);
+
+ mask_page_hint_bits(page);
+
+ if (BRIN_IS_REGULAR_PAGE(page))
+ {
+ /* Regular brin pages contain unused space which needs to be masked. */
+ mask_unused_space(page);
+ }
+}
diff --git a/src/backend/access/common/Makefile b/src/backend/access/common/Makefile
index 1fa6de0823..fb27944b89 100644
--- a/src/backend/access/common/Makefile
+++ b/src/backend/access/common/Makefile
@@ -12,7 +12,7 @@ subdir = src/backend/access/common
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = heaptuple.o indextuple.o printtup.o reloptions.o scankey.o \
- tupconvert.o tupdesc.o
+OBJS = bufmask.o heaptuple.o indextuple.o printsimple.o printtup.o \
+ reloptions.o scankey.o tupconvert.o tupdesc.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/common/bufmask.c b/src/backend/access/common/bufmask.c
new file mode 100644
index 0000000000..10253d3354
--- /dev/null
+++ b/src/backend/access/common/bufmask.c
@@ -0,0 +1,128 @@
+/*-------------------------------------------------------------------------
+ *
+ * bufmask.c
+ * Routines for buffer masking. Used to mask certain bits
+ * in a page which can be different when the WAL is generated
+ * and when the WAL is applied.
+ *
+ * Portions Copyright (c) 2016-2017, PostgreSQL Global Development Group
+ *
+ * Contains common routines required for masking a page.
+ *
+ * IDENTIFICATION
+ * src/backend/storage/buffer/bufmask.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/bufmask.h"
+
+/*
+ * mask_page_lsn
+ *
+ * In consistency checks, the LSN of the two pages compared will likely be
+ * different because of concurrent operations when the WAL is generated
+ * and the state of the page when WAL is applied.
+ */
+void
+mask_page_lsn(Page page)
+{
+ PageHeader phdr = (PageHeader) page;
+
+ PageXLogRecPtrSet(phdr->pd_lsn, (uint64) MASK_MARKER);
+}
+
+/*
+ * mask_page_hint_bits
+ *
+ * Mask hint bits in PageHeader. We want to ignore differences in hint bits,
+ * since they can be set without emitting any WAL.
+ */
+void
+mask_page_hint_bits(Page page)
+{
+ PageHeader phdr = (PageHeader) page;
+
+ /* Ignore prune_xid (it's like a hint-bit) */
+ phdr->pd_prune_xid = MASK_MARKER;
+
+ /* Ignore PD_PAGE_FULL and PD_HAS_FREE_LINES flags, they are just hints. */
+ PageClearFull(page);
+ PageClearHasFreeLinePointers(page);
+
+ /*
+ * During replay, if the page LSN has advanced past our XLOG record's LSN,
+ * we don't mark the page all-visible. See heap_xlog_visible() for
+ * details.
+ */
+ PageClearAllVisible(page);
+}
+
+/*
+ * mask_unused_space
+ *
+ * Mask the unused space of a page between pd_lower and pd_upper.
+ */
+void
+mask_unused_space(Page page)
+{
+ int pd_lower = ((PageHeader) page)->pd_lower;
+ int pd_upper = ((PageHeader) page)->pd_upper;
+ int pd_special = ((PageHeader) page)->pd_special;
+
+ /* Sanity check */
+ if (pd_lower > pd_upper || pd_special < pd_upper ||
+ pd_lower < SizeOfPageHeaderData || pd_special > BLCKSZ)
+ {
+ elog(ERROR, "invalid page pd_lower %u pd_upper %u pd_special %u\n",
+ pd_lower, pd_upper, pd_special);
+ }
+
+ memset(page + pd_lower, MASK_MARKER, pd_upper - pd_lower);
+}
+
+/*
+ * mask_lp_flags
+ *
+ * In some index AMs, line pointer flags can be modified in master without
+ * emitting any WAL record.
+ */
+void
+mask_lp_flags(Page page)
+{
+ OffsetNumber offnum,
+ maxoff;
+
+ maxoff = PageGetMaxOffsetNumber(page);
+ for (offnum = FirstOffsetNumber;
+ offnum <= maxoff;
+ offnum = OffsetNumberNext(offnum))
+ {
+ ItemId itemId = PageGetItemId(page, offnum);
+
+ if (ItemIdIsUsed(itemId))
+ itemId->lp_flags = LP_UNUSED;
+ }
+}
+
+/*
+ * mask_page_content
+ *
+ * In some index AMs, the contents of deleted pages need to be almost
+ * completely ignored.
+ */
+void
+mask_page_content(Page page)
+{
+ /* Mask Page Content */
+ memset(page + SizeOfPageHeaderData, MASK_MARKER,
+ BLCKSZ - SizeOfPageHeaderData);
+
+ /* Mask pd_lower and pd_upper */
+ memset(&((PageHeader) page)->pd_lower, MASK_MARKER,
+ sizeof(uint16));
+ memset(&((PageHeader) page)->pd_upper, MASK_MARKER,
+ sizeof(uint16));
+}
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 15a18a51cc..970e3aa6c9 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -46,7 +46,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -875,6 +875,72 @@ heap_modify_tuple(HeapTuple tuple,
}
/*
+ * heap_modify_tuple_by_cols
+ * form a new tuple from an old tuple and a set of replacement values.
+ *
+ * This is like heap_modify_tuple, except that instead of specifying which
+ * column(s) to replace by a boolean map, an array of target column numbers
+ * is used. This is often more convenient when a fixed number of columns
+ * are to be replaced. The replCols, replValues, and replIsnull arrays must
+ * be of length nCols. Target column numbers are indexed from 1.
+ *
+ * The result is allocated in the current memory context.
+ */
+HeapTuple
+heap_modify_tuple_by_cols(HeapTuple tuple,
+ TupleDesc tupleDesc,
+ int nCols,
+ int *replCols,
+ Datum *replValues,
+ bool *replIsnull)
+{
+ int numberOfAttributes = tupleDesc->natts;
+ Datum *values;
+ bool *isnull;
+ HeapTuple newTuple;
+ int i;
+
+ /*
+ * allocate and fill values and isnull arrays from the tuple, then replace
+ * selected columns from the input arrays.
+ */
+ values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
+ isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
+
+ heap_deform_tuple(tuple, tupleDesc, values, isnull);
+
+ for (i = 0; i < nCols; i++)
+ {
+ int attnum = replCols[i];
+
+ if (attnum <= 0 || attnum > numberOfAttributes)
+ elog(ERROR, "invalid column number %d", attnum);
+ values[attnum - 1] = replValues[i];
+ isnull[attnum - 1] = replIsnull[i];
+ }
+
+ /*
+ * create a new tuple from the values and isnull arrays
+ */
+ newTuple = heap_form_tuple(tupleDesc, values, isnull);
+
+ pfree(values);
+ pfree(isnull);
+
+ /*
+ * copy the identification info of the old tuple: t_ctid, t_self, and OID
+ * (if any)
+ */
+ newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
+ newTuple->t_self = tuple->t_self;
+ newTuple->t_tableOid = tuple->t_tableOid;
+ if (tupleDesc->tdhasoid)
+ HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
+
+ return newTuple;
+}
+
+/*
* heap_deform_tuple
* Given a tuple, extract data into values/isnull arrays; this is
* the inverse of heap_form_tuple.
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c
index 274a6c2e70..2846ec8b34 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -4,7 +4,7 @@
* This file contains index tuple accessor and mutator routines,
* as well as various tuple utilities.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/common/printsimple.c b/src/backend/access/common/printsimple.c
new file mode 100644
index 0000000000..851c3bf4de
--- /dev/null
+++ b/src/backend/access/common/printsimple.c
@@ -0,0 +1,131 @@
+/*-------------------------------------------------------------------------
+ *
+ * printsimple.c
+ * Routines to print out tuples containing only a limited range of
+ * builtin types without catalog access. This is intended for
+ * backends that don't have catalog access because they are not bound
+ * to a specific database, such as some walsender processes. It
+ * doesn't handle standalone backends or protocol versions other than
+ * 3.0, because we don't need such handling for current applications.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/access/common/printsimple.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/printsimple.h"
+#include "catalog/pg_type.h"
+#include "fmgr.h"
+#include "libpq/pqformat.h"
+#include "utils/builtins.h"
+
+/*
+ * At startup time, send a RowDescription message.
+ */
+void
+printsimple_startup(DestReceiver *self, int operation, TupleDesc tupdesc)
+{
+ StringInfoData buf;
+ int i;
+
+ pq_beginmessage(&buf, 'T'); /* RowDescription */
+ pq_sendint(&buf, tupdesc->natts, 2);
+
+ for (i = 0; i < tupdesc->natts; ++i)
+ {
+ Form_pg_attribute attr = tupdesc->attrs[i];
+
+ pq_sendstring(&buf, NameStr(attr->attname));
+ pq_sendint(&buf, 0, 4); /* table oid */
+ pq_sendint(&buf, 0, 2); /* attnum */
+ pq_sendint(&buf, (int) attr->atttypid, 4);
+ pq_sendint(&buf, attr->attlen, 2);
+ pq_sendint(&buf, attr->atttypmod, 4);
+ pq_sendint(&buf, 0, 2); /* format code */
+ }
+
+ pq_endmessage(&buf);
+}
+
+/*
+ * For each tuple, send a DataRow message.
+ */
+bool
+printsimple(TupleTableSlot *slot, DestReceiver *self)
+{
+ TupleDesc tupdesc = slot->tts_tupleDescriptor;
+ StringInfoData buf;
+ int i;
+
+ /* Make sure the tuple is fully deconstructed */
+ slot_getallattrs(slot);
+
+ /* Prepare and send message */
+ pq_beginmessage(&buf, 'D');
+ pq_sendint(&buf, tupdesc->natts, 2);
+
+ for (i = 0; i < tupdesc->natts; ++i)
+ {
+ Form_pg_attribute attr = tupdesc->attrs[i];
+ Datum value;
+
+ if (slot->tts_isnull[i])
+ {
+ pq_sendint(&buf, -1, 4);
+ continue;
+ }
+
+ value = slot->tts_values[i];
+
+ /*
+ * We can't call the regular type output functions here because we
+ * might not have catalog access. Instead, we must hard-wire
+ * knowledge of the required types.
+ */
+ switch (attr->atttypid)
+ {
+ case TEXTOID:
+ {
+ text *t = DatumGetTextPP(value);
+
+ pq_sendcountedtext(&buf,
+ VARDATA_ANY(t),
+ VARSIZE_ANY_EXHDR(t),
+ false);
+ }
+ break;
+
+ case INT4OID:
+ {
+ int32 num = DatumGetInt32(value);
+ char str[12]; /* sign, 10 digits and '\0' */
+
+ pg_ltoa(num, str);
+ pq_sendcountedtext(&buf, str, strlen(str), false);
+ }
+ break;
+
+ case INT8OID:
+ {
+ int64 num = DatumGetInt64(value);
+ char str[23]; /* sign, 21 digits and '\0' */
+
+ pg_lltoa(num, str);
+ pq_sendcountedtext(&buf, str, strlen(str), false);
+ }
+ break;
+
+ default:
+ elog(ERROR, "unsupported type OID: %u", attr->atttypid);
+ }
+ }
+
+ pq_endmessage(&buf);
+
+ return true;
+}
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index a44be6f96f..78704dafd9 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -6,7 +6,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -139,9 +139,7 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
*/
myState->tmpcontext = AllocSetContextCreate(CurrentMemoryContext,
"printtup",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
{
@@ -249,9 +247,7 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats)
atttypid = getBaseTypeAndTypmod(atttypid, &atttypmod);
pq_sendint(&buf, (int) atttypid, sizeof(atttypid));
pq_sendint(&buf, attrs[i]->attlen, sizeof(attrs[i]->attlen));
- /* typmod appears in protocol 2.0 and up */
- if (proto >= 2)
- pq_sendint(&buf, atttypmod, sizeof(atttypmod));
+ pq_sendint(&buf, atttypmod, sizeof(atttypmod));
/* format info appears in protocol 3.0 and up */
if (proto >= 3)
{
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index ba1f3aafed..6d1f22f049 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -3,7 +3,7 @@
* reloptions.c
* Core support for relation options (pg_class.reloptions)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -15,6 +15,8 @@
#include "postgres.h"
+#include <float.h>
+
#include "access/gist_private.h"
#include "access/hash.h"
#include "access/htup_details.h"
@@ -46,16 +48,61 @@
* (iii) add it to the appropriate options struct (perhaps StdRdOptions)
* (iv) add it to the appropriate handling routine (perhaps
* default_reloptions)
- * (v) don't forget to document the option
+ * (v) make sure the lock level is set correctly for that operation
+ * (vi) don't forget to document the option
*
* Note that we don't handle "oids" in relOpts because it is handled by
* interpretOidsOption().
+ *
+ * The default choice for any new option should be AccessExclusiveLock.
+ * In some cases the lock level can be reduced from there, but the lock
+ * level chosen should always conflict with itself to ensure that multiple
+ * changes aren't lost when we attempt concurrent changes.
+ * The choice of lock level depends completely upon how that parameter
+ * is used within the server, not upon how and when you'd like to change it.
+ * Safety first. Existing choices are documented here, and elsewhere in
+ * backend code where the parameters are used.
+ *
+ * In general, anything that affects the results obtained from a SELECT must be
+ * protected by AccessExclusiveLock.
+ *
+ * Autovacuum related parameters can be set at ShareUpdateExclusiveLock
+ * since they are only used by the AV procs and don't change anything
+ * currently executing.
+ *
+ * Fillfactor can be set because it applies only to subsequent changes made to
+ * data blocks, as documented in heapio.c
+ *
+ * n_distinct options can be set at ShareUpdateExclusiveLock because they
+ * are only used during ANALYZE, which uses a ShareUpdateExclusiveLock,
+ * so the ANALYZE will not be affected by in-flight changes. Changing those
+ * values has no affect until the next ANALYZE, so no need for stronger lock.
+ *
+ * Planner-related parameters can be set with ShareUpdateExclusiveLock because
+ * they only affect planning and not the correctness of the execution. Plans
+ * cannot be changed in mid-flight, so changes here could not easily result in
+ * new improved plans in any case. So we allow existing queries to continue
+ * and existing plans to survive, a small price to pay for allowing better
+ * plans to be introduced concurrently without interfering with users.
+ *
+ * Setting parallel_workers is safe, since it acts the same as
+ * max_parallel_workers_per_gather which is a USERSET parameter that doesn't
+ * affect existing plans or queries.
*/
static relopt_bool boolRelOpts[] =
{
{
{
+ "autosummarize",
+ "Enables automatic summarization on this BRIN index",
+ RELOPT_KIND_BRIN,
+ AccessExclusiveLock
+ },
+ false
+ },
+ {
+ {
"autovacuum_enabled",
"Enables autovacuum in this relation",
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
@@ -265,7 +312,7 @@ static relopt_int intRelOpts[] =
"effective_io_concurrency",
"Number of simultaneous requests that can be handled efficiently by the disk subsystem.",
RELOPT_KIND_TABLESPACE,
- AccessExclusiveLock
+ ShareUpdateExclusiveLock
},
#ifdef USE_PREFETCH
-1, 0, MAX_IO_CONCURRENCY
@@ -278,7 +325,7 @@ static relopt_int intRelOpts[] =
"parallel_workers",
"Number of parallel processes that can be used per executor node for this relation.",
RELOPT_KIND_HEAP,
- AccessExclusiveLock
+ ShareUpdateExclusiveLock
},
-1, 0, 1024
},
@@ -312,7 +359,7 @@ static relopt_real realRelOpts[] =
"seq_page_cost",
"Sets the planner's estimate of the cost of a sequentially fetched disk page.",
RELOPT_KIND_TABLESPACE,
- AccessExclusiveLock
+ ShareUpdateExclusiveLock
},
-1, 0.0, DBL_MAX
},
@@ -321,7 +368,7 @@ static relopt_real realRelOpts[] =
"random_page_cost",
"Sets the planner's estimate of the cost of a nonsequentially fetched disk page.",
RELOPT_KIND_TABLESPACE,
- AccessExclusiveLock
+ ShareUpdateExclusiveLock
},
-1, 0.0, DBL_MAX
},
@@ -330,7 +377,7 @@ static relopt_real realRelOpts[] =
"n_distinct",
"Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).",
RELOPT_KIND_ATTRIBUTE,
- AccessExclusiveLock
+ ShareUpdateExclusiveLock
},
0, -1.0, DBL_MAX
},
@@ -339,7 +386,7 @@ static relopt_real realRelOpts[] =
"n_distinct_inherited",
"Sets the planner's estimate of the number of distinct values appearing in a column (including child relations).",
RELOPT_KIND_ATTRIBUTE,
- AccessExclusiveLock
+ ShareUpdateExclusiveLock
},
0, -1.0, DBL_MAX
},
@@ -722,9 +769,8 @@ transformRelOptions(Datum oldOptions, List *defList, char *namspace,
for (i = 0; i < noldoptions; i++)
{
- text *oldoption = DatumGetTextP(oldoptions[i]);
- char *text_str = VARDATA(oldoption);
- int text_len = VARSIZE(oldoption) - VARHDRSZ;
+ char *text_str = VARDATA(oldoptions[i]);
+ int text_len = VARSIZE(oldoptions[i]) - VARHDRSZ;
/* Search for a match in defList */
foreach(cell, defList)
@@ -888,7 +934,7 @@ untransformRelOptions(Datum options)
*p++ = '\0';
val = (Node *) makeString(pstrdup(p));
}
- result = lappend(result, makeDefElem(pstrdup(s), val));
+ result = lappend(result, makeDefElem(pstrdup(s), val, -1));
}
return result;
@@ -930,6 +976,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
case RELKIND_RELATION:
case RELKIND_TOASTVALUE:
case RELKIND_MATVIEW:
+ case RELKIND_PARTITIONED_TABLE:
options = heap_reloptions(classForm->relkind, datum, false);
break;
case RELKIND_VIEW:
@@ -962,7 +1009,8 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
* array; this is so that the caller can easily locate the default values.
*
* If there are no options of the given kind, numrelopts is set to 0 and NULL
- * is returned.
+ * is returned (unless options are illegally supplied despite none being
+ * defined, in which case an error occurs).
*
* Note: values of type int, bool and real are allocated as part of the
* returned array. Values of type string are allocated separately and must
@@ -972,7 +1020,7 @@ relopt_value *
parseRelOptions(Datum options, bool validate, relopt_kind kind,
int *numrelopts)
{
- relopt_value *reloptions;
+ relopt_value *reloptions = NULL;
int numoptions = 0;
int i;
int j;
@@ -986,21 +1034,18 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
if (relOpts[i]->kinds & kind)
numoptions++;
- if (numoptions == 0)
+ if (numoptions > 0)
{
- *numrelopts = 0;
- return NULL;
- }
-
- reloptions = palloc(numoptions * sizeof(relopt_value));
+ reloptions = palloc(numoptions * sizeof(relopt_value));
- for (i = 0, j = 0; relOpts[i]; i++)
- {
- if (relOpts[i]->kinds & kind)
+ for (i = 0, j = 0; relOpts[i]; i++)
{
- reloptions[j].gen = relOpts[i];
- reloptions[j].isset = false;
- j++;
+ if (relOpts[i]->kinds & kind)
+ {
+ reloptions[j].gen = relOpts[i];
+ reloptions[j].isset = false;
+ j++;
+ }
}
}
@@ -1016,9 +1061,8 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
for (i = 0; i < noptions; i++)
{
- text *optiontext = DatumGetTextP(optiondatums[i]);
- char *text_str = VARDATA(optiontext);
- int text_len = VARSIZE(optiontext) - VARHDRSZ;
+ char *text_str = VARDATA(optiondatums[i]);
+ int text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
int j;
/* Search for a match in reloptions */
@@ -1382,6 +1426,9 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
case RELKIND_RELATION:
case RELKIND_MATVIEW:
return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
+ case RELKIND_PARTITIONED_TABLE:
+ return default_reloptions(reloptions, validate,
+ RELOPT_KIND_PARTITIONED);
default:
/* other relkinds are not supported */
return NULL;
diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c
index 35391c2c60..13edca1f94 100644
--- a/src/backend/access/common/scankey.c
+++ b/src/backend/access/common/scankey.c
@@ -3,7 +3,7 @@
* scankey.c
* scan key support code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 4787d4ca98..392a49b522 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -9,7 +9,7 @@
* executor's "junkfilter" routines, but these functions work on bare
* HeapTuples rather than TupleTableSlots.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -138,12 +138,14 @@ convert_tuples_by_position(TupleDesc indesc,
nincols, noutcols)));
/*
- * Check to see if the map is one-to-one and the tuple types are the same.
- * (We check the latter because if they're not, we want to do conversion
- * to inject the right OID into the tuple datum.)
+ * Check to see if the map is one-to-one, in which case we need not do a
+ * tuple conversion. We must also insist that both tupdescs either
+ * specify or don't specify an OID column, else we need a conversion to
+ * add/remove space for that. (For some callers, presence or absence of
+ * an OID column perhaps would not really matter, but let's be safe.)
*/
if (indesc->natts == outdesc->natts &&
- indesc->tdtypeid == outdesc->tdtypeid)
+ indesc->tdhasoid == outdesc->tdhasoid)
{
for (i = 0; i < n; i++)
{
@@ -206,63 +208,22 @@ convert_tuples_by_name(TupleDesc indesc,
{
TupleConversionMap *map;
AttrNumber *attrMap;
- int n;
+ int n = outdesc->natts;
int i;
bool same;
/* Verify compatibility and prepare attribute-number map */
- n = outdesc->natts;
- attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
- for (i = 0; i < n; i++)
- {
- Form_pg_attribute att = outdesc->attrs[i];
- char *attname;
- Oid atttypid;
- int32 atttypmod;
- int j;
-
- if (att->attisdropped)
- continue; /* attrMap[i] is already 0 */
- attname = NameStr(att->attname);
- atttypid = att->atttypid;
- atttypmod = att->atttypmod;
- for (j = 0; j < indesc->natts; j++)
- {
- att = indesc->attrs[j];
- if (att->attisdropped)
- continue;
- if (strcmp(attname, NameStr(att->attname)) == 0)
- {
- /* Found it, check type */
- if (atttypid != att->atttypid || atttypmod != att->atttypmod)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg_internal("%s", _(msg)),
- errdetail("Attribute \"%s\" of type %s does not match corresponding attribute of type %s.",
- attname,
- format_type_be(outdesc->tdtypeid),
- format_type_be(indesc->tdtypeid))));
- attrMap[i] = (AttrNumber) (j + 1);
- break;
- }
- }
- if (attrMap[i] == 0)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg_internal("%s", _(msg)),
- errdetail("Attribute \"%s\" of type %s does not exist in type %s.",
- attname,
- format_type_be(outdesc->tdtypeid),
- format_type_be(indesc->tdtypeid))));
- }
+ attrMap = convert_tuples_by_name_map(indesc, outdesc, msg);
/*
- * Check to see if the map is one-to-one and the tuple types are the same.
- * (We check the latter because if they're not, we want to do conversion
- * to inject the right OID into the tuple datum.)
+ * Check to see if the map is one-to-one, in which case we need not do a
+ * tuple conversion. We must also insist that both tupdescs either
+ * specify or don't specify an OID column, else we need a conversion to
+ * add/remove space for that. (For some callers, presence or absence of
+ * an OID column perhaps would not really matter, but let's be safe.)
*/
if (indesc->natts == outdesc->natts &&
- indesc->tdtypeid == outdesc->tdtypeid)
+ indesc->tdhasoid == outdesc->tdhasoid)
{
same = true;
for (i = 0; i < n; i++)
@@ -313,6 +274,69 @@ convert_tuples_by_name(TupleDesc indesc,
}
/*
+ * Return a palloc'd bare attribute map for tuple conversion, matching input
+ * and output columns by name. (Dropped columns are ignored in both input and
+ * output.) This is normally a subroutine for convert_tuples_by_name, but can
+ * be used standalone.
+ */
+AttrNumber *
+convert_tuples_by_name_map(TupleDesc indesc,
+ TupleDesc outdesc,
+ const char *msg)
+{
+ AttrNumber *attrMap;
+ int n;
+ int i;
+
+ n = outdesc->natts;
+ attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
+ for (i = 0; i < n; i++)
+ {
+ Form_pg_attribute att = outdesc->attrs[i];
+ char *attname;
+ Oid atttypid;
+ int32 atttypmod;
+ int j;
+
+ if (att->attisdropped)
+ continue; /* attrMap[i] is already 0 */
+ attname = NameStr(att->attname);
+ atttypid = att->atttypid;
+ atttypmod = att->atttypmod;
+ for (j = 0; j < indesc->natts; j++)
+ {
+ att = indesc->attrs[j];
+ if (att->attisdropped)
+ continue;
+ if (strcmp(attname, NameStr(att->attname)) == 0)
+ {
+ /* Found it, check type */
+ if (atttypid != att->atttypid || atttypmod != att->atttypmod)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg_internal("%s", _(msg)),
+ errdetail("Attribute \"%s\" of type %s does not match corresponding attribute of type %s.",
+ attname,
+ format_type_be(outdesc->tdtypeid),
+ format_type_be(indesc->tdtypeid))));
+ attrMap[i] = (AttrNumber) (j + 1);
+ break;
+ }
+ }
+ if (attrMap[i] == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg_internal("%s", _(msg)),
+ errdetail("Attribute \"%s\" of type %s does not exist in type %s.",
+ attname,
+ format_type_be(outdesc->tdtypeid),
+ format_type_be(indesc->tdtypeid))));
+ }
+
+ return attrMap;
+}
+
+/*
* Perform conversion of a tuple according to the map.
*/
HeapTuple
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index b56d0e336f..9fd7b4e019 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -3,7 +3,7 @@
* tupdesc.c
* POSTGRES tuple descriptor support code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -20,6 +20,7 @@
#include "postgres.h"
#include "access/htup_details.h"
+#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "parser/parse_type.h"
@@ -149,6 +150,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
desc->attrs[i]->attnotnull = false;
desc->attrs[i]->atthasdef = false;
+ desc->attrs[i]->attidentity = '\0';
}
desc->tdtypeid = tupdesc->tdtypeid;
@@ -256,6 +258,7 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
/* since we're not copying constraints or defaults, clear these */
dst->attrs[dstAttno - 1]->attnotnull = false;
dst->attrs[dstAttno - 1]->atthasdef = false;
+ dst->attrs[dstAttno - 1]->attidentity = '\0';
}
/*
@@ -400,6 +403,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
return false;
if (attr1->atthasdef != attr2->atthasdef)
return false;
+ if (attr1->attidentity != attr2->attidentity)
+ return false;
if (attr1->attisdropped != attr2->attisdropped)
return false;
if (attr1->attislocal != attr2->attislocal)
@@ -533,6 +538,7 @@ TupleDescInitEntry(TupleDesc desc,
att->attnotnull = false;
att->atthasdef = false;
+ att->attidentity = '\0';
att->attisdropped = false;
att->attislocal = true;
att->attinhcount = 0;
@@ -554,6 +560,93 @@ TupleDescInitEntry(TupleDesc desc,
}
/*
+ * TupleDescInitBuiltinEntry
+ * Initialize a tuple descriptor without catalog access. Only
+ * a limited range of builtin types are supported.
+ */
+void
+TupleDescInitBuiltinEntry(TupleDesc desc,
+ AttrNumber attributeNumber,
+ const char *attributeName,
+ Oid oidtypeid,
+ int32 typmod,
+ int attdim)
+{
+ Form_pg_attribute att;
+
+ /* sanity checks */
+ AssertArg(PointerIsValid(desc));
+ AssertArg(attributeNumber >= 1);
+ AssertArg(attributeNumber <= desc->natts);
+
+ /* initialize the attribute fields */
+ att = desc->attrs[attributeNumber - 1];
+ att->attrelid = 0; /* dummy value */
+
+ /* unlike TupleDescInitEntry, we require an attribute name */
+ Assert(attributeName != NULL);
+ namestrcpy(&(att->attname), attributeName);
+
+ att->attstattarget = -1;
+ att->attcacheoff = -1;
+ att->atttypmod = typmod;
+
+ att->attnum = attributeNumber;
+ att->attndims = attdim;
+
+ att->attnotnull = false;
+ att->atthasdef = false;
+ att->attidentity = '\0';
+ att->attisdropped = false;
+ att->attislocal = true;
+ att->attinhcount = 0;
+ /* attacl, attoptions and attfdwoptions are not present in tupledescs */
+
+ att->atttypid = oidtypeid;
+
+ /*
+ * Our goal here is to support just enough types to let basic builtin
+ * commands work without catalog access - e.g. so that we can do certain
+ * things even in processes that are not connected to a database.
+ */
+ switch (oidtypeid)
+ {
+ case TEXTOID:
+ case TEXTARRAYOID:
+ att->attlen = -1;
+ att->attbyval = false;
+ att->attalign = 'i';
+ att->attstorage = 'x';
+ att->attcollation = DEFAULT_COLLATION_OID;
+ break;
+
+ case BOOLOID:
+ att->attlen = 1;
+ att->attbyval = true;
+ att->attalign = 'c';
+ att->attstorage = 'p';
+ att->attcollation = InvalidOid;
+ break;
+
+ case INT4OID:
+ att->attlen = 4;
+ att->attbyval = true;
+ att->attalign = 'i';
+ att->attstorage = 'p';
+ att->attcollation = InvalidOid;
+ break;
+
+ case INT8OID:
+ att->attlen = 8;
+ att->attbyval = FLOAT8PASSBYVAL;
+ att->attalign = 'd';
+ att->attstorage = 'p';
+ att->attcollation = InvalidOid;
+ break;
+ }
+}
+
+/*
* TupleDescInitEntryCollation
*
* Assign a nondefault collation to a previously initialized tuple descriptor
diff --git a/src/backend/access/gin/README b/src/backend/access/gin/README
index fade0cbb61..990b5ffa58 100644
--- a/src/backend/access/gin/README
+++ b/src/backend/access/gin/README
@@ -314,10 +314,17 @@ deleted.
The previous paragraph's reasoning only applies to searches, and only to
posting trees. To protect from inserters following a downlink to a deleted
page, vacuum simply locks out all concurrent insertions to the posting tree,
-by holding a super-exclusive lock on the posting tree root. Inserters hold a
-pin on the root page, but searches do not, so while new searches cannot begin
-while root page is locked, any already-in-progress scans can continue
-concurrently with vacuum. In the entry tree, we never delete pages.
+by holding a super-exclusive lock on the parent page of subtree with deletable
+pages. Inserters hold a pin on the root page, but searches do not, so while
+new searches cannot begin while root page is locked, any already-in-progress
+scans can continue concurrently with vacuum in corresponding subtree of
+posting tree. To exclude interference with readers vacuum takes exclusive
+locks in a depth-first scan in left-to-right order of page tuples. Leftmost
+page is never deleted. Thus before deleting any page we obtain exclusive
+lock on any left page, effectively excluding deadlock with any reader, despite
+taking parent lock before current and left lock after current. We take left
+lock not for a concurrency reasons, but rather in need to mark page dirty.
+In the entry tree, we never delete pages.
(This is quite different from the mechanism the btree indexam uses to make
page-deletions safe; it stamps the deleted pages with an XID and keeps the
diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c
index aaf72a3f9e..cc7435e030 100644
--- a/src/backend/access/gin/ginarrayproc.c
+++ b/src/backend/access/gin/ginarrayproc.c
@@ -4,7 +4,7 @@
* support functions for GIN's indexing of any array
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c
index fa383719e6..b02cb8ae58 100644
--- a/src/backend/access/gin/ginbtree.c
+++ b/src/backend/access/gin/ginbtree.c
@@ -4,7 +4,7 @@
* page utilities routines for the postgres inverted index access method.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
#include "utils/memutils.h"
@@ -30,7 +31,7 @@ static void ginFinishSplit(GinBtree btree, GinBtreeStack *stack,
/*
* Lock buffer by needed method for search.
*/
-static int
+int
ginTraverseLock(Buffer buffer, bool searchMode)
{
Page page;
@@ -348,9 +349,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
*/
tmpCxt = AllocSetContextCreate(CurrentMemoryContext,
"ginPlaceToPage temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldCxt = MemoryContextSwitchTo(tmpCxt);
if (GinPageIsData(page))
diff --git a/src/backend/access/gin/ginbulk.c b/src/backend/access/gin/ginbulk.c
index d6422ea91e..f07c76b90b 100644
--- a/src/backend/access/gin/ginbulk.c
+++ b/src/backend/access/gin/ginbulk.c
@@ -4,7 +4,7 @@
* routines for fast build of inverted index
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -255,7 +255,7 @@ qsortCompareItemPointers(const void *a, const void *b)
void
ginBeginBAScan(BuildAccumulator *accum)
{
- rb_begin_iterate(accum->tree, LeftRightWalk);
+ rb_begin_iterate(accum->tree, LeftRightWalk, &accum->tree_walk);
}
/*
@@ -271,7 +271,7 @@ ginGetBAEntry(BuildAccumulator *accum,
GinEntryAccumulator *entry;
ItemPointerData *list;
- entry = (GinEntryAccumulator *) rb_iterate(accum->tree);
+ entry = (GinEntryAccumulator *) rb_iterate(&accum->tree_walk);
if (entry == NULL)
return NULL; /* no more entries */
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index 97c8bf78e7..ad62d4e0e9 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -4,7 +4,7 @@
* routines for handling GIN posting tree pages.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "lib/ilist.h"
#include "miscadmin.h"
@@ -86,7 +87,7 @@ typedef struct
char action;
ItemPointerData *modifieditems;
- int nmodifieditems;
+ uint16 nmodifieditems;
/*
* The following fields represent the items in this segment. If 'items' is
diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c
index 8c0bfe9fde..8c9859ce8e 100644
--- a/src/backend/access/gin/ginentrypage.c
+++ b/src/backend/access/gin/ginentrypage.c
@@ -4,7 +4,7 @@
* routines for handling GIN entry tree pages.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
#include "utils/rel.h"
diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index 59a63f28d0..0d5bb70cc9 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -7,7 +7,7 @@
* transfer pending entries into the regular index structure. This
* wins because bulk insertion is much more efficient than retail.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -19,6 +19,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "access/xlog.h"
#include "commands/vacuum.h"
@@ -30,6 +31,7 @@
#include "postmaster/autovacuum.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
+#include "utils/builtins.h"
/* GUC parameter */
int gin_pending_list_limit = 0;
@@ -808,9 +810,7 @@ ginInsertCleanup(GinState *ginstate, bool full_clean,
*/
opCtx = AllocSetContextCreate(CurrentMemoryContext,
"GIN insert cleanup temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldCtx = MemoryContextSwitchTo(opCtx);
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 9ed9fd2dc5..610d386ff8 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -4,7 +4,7 @@
* fetch tuples from a GIN scan.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -120,7 +120,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack,
Form_pg_attribute attr;
/* Initialize empty bitmap result */
- scanEntry->matchBitmap = tbm_create(work_mem * 1024L);
+ scanEntry->matchBitmap = tbm_create(work_mem * 1024L, NULL);
/* Null query cannot partial-match anything */
if (scanEntry->isPartialMatch &&
@@ -626,8 +626,9 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry,
}
else
{
- entry->btree.itemptr = advancePast;
- entry->btree.itemptr.ip_posid++;
+ ItemPointerSet(&entry->btree.itemptr,
+ GinItemPointerGetBlockNumber(&advancePast),
+ OffsetNumberNext(GinItemPointerGetOffsetNumber(&advancePast)));
}
entry->btree.fullScan = false;
stack = ginFindLeafPage(&entry->btree, true, snapshot);
@@ -979,15 +980,17 @@ keyGetItem(GinState *ginstate, MemoryContext tempCtx, GinScanKey key,
if (GinItemPointerGetBlockNumber(&advancePast) <
GinItemPointerGetBlockNumber(&minItem))
{
- advancePast.ip_blkid = minItem.ip_blkid;
- advancePast.ip_posid = 0;
+ ItemPointerSet(&advancePast,
+ GinItemPointerGetBlockNumber(&minItem),
+ InvalidOffsetNumber);
}
}
else
{
- Assert(minItem.ip_posid > 0);
- advancePast = minItem;
- advancePast.ip_posid--;
+ Assert(GinItemPointerGetOffsetNumber(&minItem) > 0);
+ ItemPointerSet(&advancePast,
+ GinItemPointerGetBlockNumber(&minItem),
+ OffsetNumberPrev(GinItemPointerGetOffsetNumber(&minItem)));
}
/*
@@ -1245,15 +1248,17 @@ scanGetItem(IndexScanDesc scan, ItemPointerData advancePast,
if (GinItemPointerGetBlockNumber(&advancePast) <
GinItemPointerGetBlockNumber(&key->curItem))
{
- advancePast.ip_blkid = key->curItem.ip_blkid;
- advancePast.ip_posid = 0;
+ ItemPointerSet(&advancePast,
+ GinItemPointerGetBlockNumber(&key->curItem),
+ InvalidOffsetNumber);
}
}
else
{
- Assert(key->curItem.ip_posid > 0);
- advancePast = key->curItem;
- advancePast.ip_posid--;
+ Assert(GinItemPointerGetOffsetNumber(&key->curItem) > 0);
+ ItemPointerSet(&advancePast,
+ GinItemPointerGetBlockNumber(&key->curItem),
+ OffsetNumberPrev(GinItemPointerGetOffsetNumber(&key->curItem)));
}
/*
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 9f784bf48d..d90faae65d 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -4,7 +4,7 @@
* insert routines for the postgres inverted index access method.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "catalog/index.h"
#include "miscadmin.h"
@@ -372,9 +373,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
*/
buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
"Gin build temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* create a temporary memory context that is used for calling
@@ -382,9 +381,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
*/
buildstate.funcCtx = AllocSetContextCreate(CurrentMemoryContext,
"Gin build temporary context for user-defined function",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
buildstate.accum.ginstate = &buildstate.ginstate;
ginInitBA(&buildstate.accum);
@@ -486,41 +483,48 @@ ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum,
bool
gininsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
- GinState ginstate;
+ GinState *ginstate = (GinState *) indexInfo->ii_AmCache;
MemoryContext oldCtx;
MemoryContext insertCtx;
int i;
+ /* Initialize GinState cache if first call in this statement */
+ if (ginstate == NULL)
+ {
+ oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
+ ginstate = (GinState *) palloc(sizeof(GinState));
+ initGinState(ginstate, index);
+ indexInfo->ii_AmCache = (void *) ginstate;
+ MemoryContextSwitchTo(oldCtx);
+ }
+
insertCtx = AllocSetContextCreate(CurrentMemoryContext,
"Gin insert temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldCtx = MemoryContextSwitchTo(insertCtx);
- initGinState(&ginstate, index);
-
if (GinGetUseFastUpdate(index))
{
GinTupleCollector collector;
memset(&collector, 0, sizeof(GinTupleCollector));
- for (i = 0; i < ginstate.origTupdesc->natts; i++)
- ginHeapTupleFastCollect(&ginstate, &collector,
+ for (i = 0; i < ginstate->origTupdesc->natts; i++)
+ ginHeapTupleFastCollect(ginstate, &collector,
(OffsetNumber) (i + 1),
values[i], isnull[i],
ht_ctid);
- ginHeapTupleFastInsert(&ginstate, &collector);
+ ginHeapTupleFastInsert(ginstate, &collector);
}
else
{
- for (i = 0; i < ginstate.origTupdesc->natts; i++)
- ginHeapTupleInsert(&ginstate, (OffsetNumber) (i + 1),
+ for (i = 0; i < ginstate->origTupdesc->natts; i++)
+ ginHeapTupleInsert(ginstate, (OffsetNumber) (i + 1),
values[i], isnull[i],
ht_ctid);
}
diff --git a/src/backend/access/gin/ginlogic.c b/src/backend/access/gin/ginlogic.c
index d3e84eee97..a940a9374a 100644
--- a/src/backend/access/gin/ginlogic.c
+++ b/src/backend/access/gin/ginlogic.c
@@ -24,7 +24,7 @@
* is used for.)
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c
index 54d5f6f630..8d2d31ac72 100644
--- a/src/backend/access/gin/ginpostinglist.c
+++ b/src/backend/access/gin/ginpostinglist.c
@@ -4,7 +4,7 @@
* routines for dealing with posting lists.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -79,13 +79,11 @@ itemptr_to_uint64(const ItemPointer iptr)
uint64 val;
Assert(ItemPointerIsValid(iptr));
- Assert(iptr->ip_posid < (1 << MaxHeapTuplesPerPageBits));
+ Assert(GinItemPointerGetOffsetNumber(iptr) < (1 << MaxHeapTuplesPerPageBits));
- val = iptr->ip_blkid.bi_hi;
- val <<= 16;
- val |= iptr->ip_blkid.bi_lo;
+ val = GinItemPointerGetBlockNumber(iptr);
val <<= MaxHeapTuplesPerPageBits;
- val |= iptr->ip_posid;
+ val |= GinItemPointerGetOffsetNumber(iptr);
return val;
}
@@ -93,11 +91,9 @@ itemptr_to_uint64(const ItemPointer iptr)
static inline void
uint64_to_itemptr(uint64 val, ItemPointer iptr)
{
- iptr->ip_posid = val & ((1 << MaxHeapTuplesPerPageBits) - 1);
+ GinItemPointerSetOffsetNumber(iptr, val & ((1 << MaxHeapTuplesPerPageBits) - 1));
val = val >> MaxHeapTuplesPerPageBits;
- iptr->ip_blkid.bi_lo = val & 0xFFFF;
- val = val >> 16;
- iptr->ip_blkid.bi_hi = val & 0xFFFF;
+ GinItemPointerSetBlockNumber(iptr, val);
Assert(ItemPointerIsValid(iptr));
}
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index c449c1cbc0..c83375d6b4 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -4,7 +4,7 @@
* routines to manage scans of inverted index relations
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -38,14 +38,10 @@ ginbeginscan(Relation rel, int nkeys, int norderbys)
so->nkeys = 0;
so->tempCtx = AllocSetContextCreate(CurrentMemoryContext,
"Gin scan temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
so->keyCtx = AllocSetContextCreate(CurrentMemoryContext,
"Gin scan key context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
initGinState(&so->ginstate, scan->indexRelation);
scan->opaque = so;
@@ -151,7 +147,7 @@ ginFillScanKey(GinScanOpaque so, OffsetNumber attnum,
key->nuserentries = nUserQueryValues;
key->scanEntry = (GinScanEntry *) palloc(sizeof(GinScanEntry) * nQueryValues);
- key->entryRes = (bool *) palloc0(sizeof(bool) * nQueryValues);
+ key->entryRes = (GinTernaryValue *) palloc0(sizeof(GinTernaryValue) * nQueryValues);
key->query = query;
key->queryValues = queryValues;
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index d9146488c4..d03d59da6a 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -4,7 +4,7 @@
* Utility routines for the Postgres inverted index access method.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/reloptions.h"
#include "access/xloginsert.h"
#include "catalog/pg_collation.h"
@@ -22,7 +23,9 @@
#include "miscadmin.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
+#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
+#include "utils/typcache.h"
/*
@@ -47,6 +50,7 @@ ginhandler(PG_FUNCTION_ARGS)
amroutine->amstorage = true;
amroutine->amclusterable = false;
amroutine->ampredlocks = false;
+ amroutine->amcanparallel = false;
amroutine->amkeytype = InvalidOid;
amroutine->ambuild = ginbuild;
@@ -66,6 +70,9 @@ ginhandler(PG_FUNCTION_ARGS)
amroutine->amendscan = ginendscan;
amroutine->ammarkpos = NULL;
amroutine->amrestrpos = NULL;
+ amroutine->amestimateparallelscan = NULL;
+ amroutine->aminitparallelscan = NULL;
+ amroutine->amparallelrescan = NULL;
PG_RETURN_POINTER(amroutine);
}
@@ -105,9 +112,33 @@ initGinState(GinState *state, Relation index)
origTupdesc->attrs[i]->attcollation);
}
- fmgr_info_copy(&(state->compareFn[i]),
- index_getprocinfo(index, i + 1, GIN_COMPARE_PROC),
- CurrentMemoryContext);
+ /*
+ * If the compare proc isn't specified in the opclass definition, look
+ * up the index key type's default btree comparator.
+ */
+ if (index_getprocid(index, i + 1, GIN_COMPARE_PROC) != InvalidOid)
+ {
+ fmgr_info_copy(&(state->compareFn[i]),
+ index_getprocinfo(index, i + 1, GIN_COMPARE_PROC),
+ CurrentMemoryContext);
+ }
+ else
+ {
+ TypeCacheEntry *typentry;
+
+ typentry = lookup_type_cache(origTupdesc->attrs[i]->atttypid,
+ TYPECACHE_CMP_PROC_FINFO);
+ if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify a comparison function for type %s",
+ format_type_be(origTupdesc->attrs[i]->atttypid))));
+ fmgr_info_copy(&(state->compareFn[i]),
+ &(typentry->cmp_proc_finfo),
+ CurrentMemoryContext);
+ }
+
+ /* Opclass must always provide extract procs */
fmgr_info_copy(&(state->extractValueFn[i]),
index_getprocinfo(index, i + 1, GIN_EXTRACTVALUE_PROC),
CurrentMemoryContext);
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index c258478f23..27e502a360 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -4,7 +4,7 @@
* delete & vacuum routines for the postgres GIN
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "commands/vacuum.h"
#include "miscadmin.h"
@@ -108,75 +109,17 @@ xlogVacuumPage(Relation index, Buffer buffer)
PageSetLSN(page, recptr);
}
-static bool
-ginVacuumPostingTreeLeaves(GinVacuumState *gvs, BlockNumber blkno, bool isRoot, Buffer *rootBuffer)
-{
- Buffer buffer;
- Page page;
- bool hasVoidPage = FALSE;
- MemoryContext oldCxt;
-
- buffer = ReadBufferExtended(gvs->index, MAIN_FORKNUM, blkno,
- RBM_NORMAL, gvs->strategy);
- page = BufferGetPage(buffer);
-
- /*
- * We should be sure that we don't concurrent with inserts, insert process
- * never release root page until end (but it can unlock it and lock
- * again). New scan can't start but previously started ones work
- * concurrently.
- */
- if (isRoot)
- LockBufferForCleanup(buffer);
- else
- LockBuffer(buffer, GIN_EXCLUSIVE);
-
- Assert(GinPageIsData(page));
- if (GinPageIsLeaf(page))
- {
- oldCxt = MemoryContextSwitchTo(gvs->tmpCxt);
- ginVacuumPostingTreeLeaf(gvs->index, buffer, gvs);
- MemoryContextSwitchTo(oldCxt);
- MemoryContextReset(gvs->tmpCxt);
-
- /* if root is a leaf page, we don't desire further processing */
- if (!isRoot && !hasVoidPage && GinDataLeafPageIsEmpty(page))
- hasVoidPage = TRUE;
- }
- else
- {
- OffsetNumber i;
- bool isChildHasVoid = FALSE;
-
- for (i = FirstOffsetNumber; i <= GinPageGetOpaque(page)->maxoff; i++)
- {
- PostingItem *pitem = GinDataPageGetPostingItem(page, i);
-
- if (ginVacuumPostingTreeLeaves(gvs, PostingItemGetBlockNumber(pitem), FALSE, NULL))
- isChildHasVoid = TRUE;
- }
-
- if (isChildHasVoid)
- hasVoidPage = TRUE;
- }
+typedef struct DataPageDeleteStack
+{
+ struct DataPageDeleteStack *child;
+ struct DataPageDeleteStack *parent;
- /*
- * if we have root and there are empty pages in tree, then we don't
- * release lock to go further processing and guarantee that tree is unused
- */
- if (!(isRoot && hasVoidPage))
- {
- UnlockReleaseBuffer(buffer);
- }
- else
- {
- Assert(rootBuffer);
- *rootBuffer = buffer;
- }
+ BlockNumber blkno; /* current block number */
+ BlockNumber leftBlkno; /* rightest non-deleted page on left */
+ bool isRoot;
+} DataPageDeleteStack;
- return hasVoidPage;
-}
/*
* Delete a posting tree page.
@@ -193,8 +136,13 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
BlockNumber rightlink;
/*
- * Lock the pages in the same order as an insertion would, to avoid
- * deadlocks: left, then right, then parent.
+ * This function MUST be called only if someone of parent pages hold
+ * exclusive cleanup lock. This guarantees that no insertions currently
+ * happen in this subtree. Caller also acquire Exclusive lock on deletable
+ * page and is acquiring and releasing exclusive lock on left page before.
+ * Left page was locked and released. Then parent and this page are
+ * locked. We acquire left page lock here only to mark page dirty after
+ * changing right pointer.
*/
lBuffer = ReadBufferExtended(gvs->index, MAIN_FORKNUM, leftBlkno,
RBM_NORMAL, gvs->strategy);
@@ -204,10 +152,6 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
RBM_NORMAL, gvs->strategy);
LockBuffer(lBuffer, GIN_EXCLUSIVE);
- LockBuffer(dBuffer, GIN_EXCLUSIVE);
- if (!isParentRoot) /* parent is already locked by
- * LockBufferForCleanup() */
- LockBuffer(pBuffer, GIN_EXCLUSIVE);
START_CRIT_SECTION();
@@ -271,26 +215,15 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
PageSetLSN(BufferGetPage(lBuffer), recptr);
}
- if (!isParentRoot)
- LockBuffer(pBuffer, GIN_UNLOCK);
ReleaseBuffer(pBuffer);
UnlockReleaseBuffer(lBuffer);
- UnlockReleaseBuffer(dBuffer);
+ ReleaseBuffer(dBuffer);
END_CRIT_SECTION();
gvs->result->pages_deleted++;
}
-typedef struct DataPageDeleteStack
-{
- struct DataPageDeleteStack *child;
- struct DataPageDeleteStack *parent;
-
- BlockNumber blkno; /* current block number */
- BlockNumber leftBlkno; /* rightest non-deleted page on left */
- bool isRoot;
-} DataPageDeleteStack;
/*
* scans posting tree and deletes empty pages
@@ -324,6 +257,10 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
buffer = ReadBufferExtended(gvs->index, MAIN_FORKNUM, blkno,
RBM_NORMAL, gvs->strategy);
+
+ if (!isRoot)
+ LockBuffer(buffer, GIN_EXCLUSIVE);
+
page = BufferGetPage(buffer);
Assert(GinPageIsData(page));
@@ -358,6 +295,9 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
}
}
+ if (!isRoot)
+ LockBuffer(buffer, GIN_UNLOCK);
+
ReleaseBuffer(buffer);
if (!meDelete)
@@ -366,37 +306,124 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
return meDelete;
}
-static void
-ginVacuumPostingTree(GinVacuumState *gvs, BlockNumber rootBlkno)
+
+/*
+ * Scan through posting tree, delete empty tuples from leaf pages.
+ * Also, this function collects empty subtrees (with all empty leafs).
+ * For parents of these subtrees CleanUp lock is taken, then we call
+ * ScanToDelete. This is done for every inner page, which points to
+ * empty subtree.
+ */
+static bool
+ginVacuumPostingTreeLeaves(GinVacuumState *gvs, BlockNumber blkno, bool isRoot)
{
- Buffer rootBuffer = InvalidBuffer;
- DataPageDeleteStack root,
- *ptr,
- *tmp;
+ Buffer buffer;
+ Page page;
+ bool hasVoidPage = FALSE;
+ MemoryContext oldCxt;
+
+ buffer = ReadBufferExtended(gvs->index, MAIN_FORKNUM, blkno,
+ RBM_NORMAL, gvs->strategy);
+ page = BufferGetPage(buffer);
+
+ ginTraverseLock(buffer, false);
+
+ Assert(GinPageIsData(page));
- if (ginVacuumPostingTreeLeaves(gvs, rootBlkno, TRUE, &rootBuffer) == FALSE)
+ if (GinPageIsLeaf(page))
{
- Assert(rootBuffer == InvalidBuffer);
- return;
+ oldCxt = MemoryContextSwitchTo(gvs->tmpCxt);
+ ginVacuumPostingTreeLeaf(gvs->index, buffer, gvs);
+ MemoryContextSwitchTo(oldCxt);
+ MemoryContextReset(gvs->tmpCxt);
+
+ /* if root is a leaf page, we don't desire further processing */
+ if (GinDataLeafPageIsEmpty(page))
+ hasVoidPage = TRUE;
+
+ UnlockReleaseBuffer(buffer);
+
+ return hasVoidPage;
}
+ else
+ {
+ OffsetNumber i;
+ bool hasEmptyChild = FALSE;
+ bool hasNonEmptyChild = FALSE;
+ OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff;
+ BlockNumber *children = palloc(sizeof(BlockNumber) * (maxoff + 1));
+
+ /*
+ * Read all children BlockNumbers. Not sure it is safe if there are
+ * many concurrent vacuums.
+ */
- memset(&root, 0, sizeof(DataPageDeleteStack));
- root.leftBlkno = InvalidBlockNumber;
- root.isRoot = TRUE;
+ for (i = FirstOffsetNumber; i <= maxoff; i++)
+ {
+ PostingItem *pitem = GinDataPageGetPostingItem(page, i);
- vacuum_delay_point();
+ children[i] = PostingItemGetBlockNumber(pitem);
+ }
- ginScanToDelete(gvs, rootBlkno, TRUE, &root, InvalidOffsetNumber);
+ UnlockReleaseBuffer(buffer);
- ptr = root.child;
- while (ptr)
- {
- tmp = ptr->child;
- pfree(ptr);
- ptr = tmp;
+ for (i = FirstOffsetNumber; i <= maxoff; i++)
+ {
+ if (ginVacuumPostingTreeLeaves(gvs, children[i], FALSE))
+ hasEmptyChild = TRUE;
+ else
+ hasNonEmptyChild = TRUE;
+ }
+
+ pfree(children);
+
+ vacuum_delay_point();
+
+ /*
+ * All subtree is empty - just return TRUE to indicate that parent
+ * must do a cleanup. Unless we are ROOT an there is way to go upper.
+ */
+
+ if (hasEmptyChild && !hasNonEmptyChild && !isRoot)
+ return TRUE;
+
+ if (hasEmptyChild)
+ {
+ DataPageDeleteStack root,
+ *ptr,
+ *tmp;
+
+ buffer = ReadBufferExtended(gvs->index, MAIN_FORKNUM, blkno,
+ RBM_NORMAL, gvs->strategy);
+ LockBufferForCleanup(buffer);
+
+ memset(&root, 0, sizeof(DataPageDeleteStack));
+ root.leftBlkno = InvalidBlockNumber;
+ root.isRoot = TRUE;
+
+ ginScanToDelete(gvs, blkno, TRUE, &root, InvalidOffsetNumber);
+
+ ptr = root.child;
+
+ while (ptr)
+ {
+ tmp = ptr->child;
+ pfree(ptr);
+ ptr = tmp;
+ }
+
+ UnlockReleaseBuffer(buffer);
+ }
+
+ /* Here we have deleted all empty subtrees */
+ return FALSE;
}
+}
- UnlockReleaseBuffer(rootBuffer);
+static void
+ginVacuumPostingTree(GinVacuumState *gvs, BlockNumber rootBlkno)
+{
+ ginVacuumPostingTreeLeaves(gvs, rootBlkno, TRUE);
}
/*
@@ -526,9 +553,7 @@ ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
gvs.tmpCxt = AllocSetContextCreate(CurrentMemoryContext,
"Gin vacuum temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
gvs.index = index;
gvs.callback = callback;
gvs.callback_state = callback_state;
diff --git a/src/backend/access/gin/ginvalidate.c b/src/backend/access/gin/ginvalidate.c
index 032508387d..0d2847456e 100644
--- a/src/backend/access/gin/ginvalidate.c
+++ b/src/backend/access/gin/ginvalidate.c
@@ -3,7 +3,7 @@
* ginvalidate.c
* Opclass validator for GIN.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -24,6 +24,7 @@
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+#include "utils/regproc.h"
/*
@@ -237,7 +238,7 @@ ginvalidate(Oid opclassoid)
if (opclassgroup &&
(opclassgroup->functionset & (((uint64) 1) << i)) != 0)
continue; /* got it */
- if (i == GIN_COMPARE_PARTIAL_PROC)
+ if (i == GIN_COMPARE_PROC || i == GIN_COMPARE_PARTIAL_PROC)
continue; /* optional method */
if (i == GIN_CONSISTENT_PROC || i == GIN_TRICONSISTENT_PROC)
continue; /* don't need both, see check below loop */
diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c
index b4d310f337..7ba04e324f 100644
--- a/src/backend/access/gin/ginxlog.c
+++ b/src/backend/access/gin/ginxlog.c
@@ -4,7 +4,7 @@
* WAL replay logic for inverted index.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -13,7 +13,9 @@
*/
#include "postgres.h"
+#include "access/bufmask.h"
#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xlogutils.h"
#include "utils/memutils.h"
@@ -749,13 +751,43 @@ gin_xlog_startup(void)
{
opCtx = AllocSetContextCreate(CurrentMemoryContext,
"GIN recovery temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
}
void
gin_xlog_cleanup(void)
{
MemoryContextDelete(opCtx);
+ opCtx = NULL;
+}
+
+/*
+ * Mask a GIN page before running consistency checks on it.
+ */
+void
+gin_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+ GinPageOpaque opaque;
+
+ mask_page_lsn(page);
+ opaque = GinPageGetOpaque(page);
+
+ mask_page_hint_bits(page);
+
+ /*
+ * GIN metapage doesn't use pd_lower/pd_upper. Other page types do. Hence,
+ * we need to apply masking for those pages.
+ */
+ if (opaque->flags != GIN_META)
+ {
+ /*
+ * For GIN_DELETED page, the page is initialized to empty. Hence, mask
+ * the page content.
+ */
+ if (opaque->flags & GIN_DELETED)
+ mask_page_content(page);
+ else
+ mask_unused_space(page);
+ }
}
diff --git a/src/backend/access/gist/README b/src/backend/access/gist/README
index dd4c9fa70a..02228662b8 100644
--- a/src/backend/access/gist/README
+++ b/src/backend/access/gist/README
@@ -28,7 +28,7 @@ The current implementation of GiST supports:
The support for concurrency implemented in PostgreSQL was developed based on
the paper "Access Methods for Next-Generation Database Systems" by
-Marcel Kornaker:
+Marcel Kornacker:
http://www.sai.msu.su/~megera/postgres/gist/papers/concurrency/access-methods-for-next-generation.pdf.gz
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 9a417ca2f4..6593771361 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -4,7 +4,7 @@
* interface routines for the postgres GiST index access method.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -18,6 +18,8 @@
#include "access/gistscan.h"
#include "catalog/pg_collation.h"
#include "miscadmin.h"
+#include "nodes/execnodes.h"
+#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -69,6 +71,7 @@ gisthandler(PG_FUNCTION_ARGS)
amroutine->amstorage = true;
amroutine->amclusterable = true;
amroutine->ampredlocks = false;
+ amroutine->amcanparallel = false;
amroutine->amkeytype = InvalidOid;
amroutine->ambuild = gistbuild;
@@ -88,6 +91,9 @@ gisthandler(PG_FUNCTION_ARGS)
amroutine->amendscan = gistendscan;
amroutine->ammarkpos = NULL;
amroutine->amrestrpos = NULL;
+ amroutine->amestimateparallelscan = NULL;
+ amroutine->aminitparallelscan = NULL;
+ amroutine->amparallelrescan = NULL;
PG_RETURN_POINTER(amroutine);
}
@@ -105,9 +111,7 @@ createTempGistContext(void)
{
return AllocSetContextCreate(CurrentMemoryContext,
"GiST temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
}
/*
@@ -142,21 +146,23 @@ gistbuildempty(Relation index)
bool
gistinsert(Relation r, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
+ GISTSTATE *giststate = (GISTSTATE *) indexInfo->ii_AmCache;
IndexTuple itup;
- GISTSTATE *giststate;
MemoryContext oldCxt;
- giststate = initGISTstate(r);
+ /* Initialize GISTSTATE cache if first call in this statement */
+ if (giststate == NULL)
+ {
+ oldCxt = MemoryContextSwitchTo(indexInfo->ii_Context);
+ giststate = initGISTstate(r);
+ giststate->tempCxt = createTempGistContext();
+ indexInfo->ii_AmCache = (void *) giststate;
+ MemoryContextSwitchTo(oldCxt);
+ }
- /*
- * We use the giststate's scan context as temp context too. This means
- * that any memory leaked by the support functions is not reclaimed until
- * end of insert. In most cases, we aren't going to call the support
- * functions very many times before finishing the insert, so this seems
- * cheaper than resetting a temp context for each function call.
- */
oldCxt = MemoryContextSwitchTo(giststate->tempCxt);
itup = gistFormTuple(giststate, r,
@@ -167,7 +173,7 @@ gistinsert(Relation r, Datum *values, bool *isnull,
/* cleanup */
MemoryContextSwitchTo(oldCxt);
- freeGISTstate(giststate);
+ MemoryContextReset(giststate->tempCxt);
return false;
}
@@ -495,18 +501,36 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
else
{
/*
- * Enough space. We also get here if ntuples==0.
+ * Enough space. We always get here if ntup==0.
*/
START_CRIT_SECTION();
/*
- * While we delete only one tuple at once we could mix calls
- * PageIndexTupleDelete() here and PageIndexMultiDelete() in
- * gistRedoPageUpdateRecord()
+ * Delete old tuple if any, then insert new tuple(s) if any. If
+ * possible, use the fast path of PageIndexTupleOverwrite.
*/
if (OffsetNumberIsValid(oldoffnum))
- PageIndexTupleDelete(page, oldoffnum);
- gistfillbuffer(page, itup, ntup, InvalidOffsetNumber);
+ {
+ if (ntup == 1)
+ {
+ /* One-for-one replacement, so use PageIndexTupleOverwrite */
+ if (!PageIndexTupleOverwrite(page, oldoffnum, (Item) *itup,
+ IndexTupleSize(*itup)))
+ elog(ERROR, "failed to add item to index page in \"%s\"",
+ RelationGetRelationName(rel));
+ }
+ else
+ {
+ /* Delete old, then append new tuple(s) to page */
+ PageIndexTupleDelete(page, oldoffnum);
+ gistfillbuffer(page, itup, ntup, InvalidOffsetNumber);
+ }
+ }
+ else
+ {
+ /* Just append new tuples at the end of the page */
+ gistfillbuffer(page, itup, ntup, InvalidOffsetNumber);
+ }
MarkBufferDirty(buffer);
@@ -1411,9 +1435,7 @@ initGISTstate(Relation index)
/* Create the memory context that will hold the GISTSTATE */
scanCxt = AllocSetContextCreate(CurrentMemoryContext,
"GiST scan context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldCxt = MemoryContextSwitchTo(scanCxt);
/* Create and fill in the GISTSTATE */
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 4e43a6932a..f1f08bb3d8 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -4,7 +4,7 @@
* build algorithm for GiST indexes implementation.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -18,6 +18,7 @@
#include "access/genam.h"
#include "access/gist_private.h"
+#include "access/gistxlog.h"
#include "access/xloginsert.h"
#include "catalog/index.h"
#include "miscadmin.h"
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 8e3fcfbdc1..ca4c32b3fe 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -4,7 +4,7 @@
* node buffer management functions for GiST buffering build algorithm.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 5ba7d0a793..5a4dea89ac 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -4,7 +4,7 @@
* fetch tuples from a GiST scan.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -375,6 +375,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
}
so->nPageData = so->curPageData = 0;
+ scan->xs_hitup = NULL; /* might point into pageDataCxt */
if (so->pageDataCxt)
MemoryContextReset(so->pageDataCxt);
@@ -441,12 +442,13 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
so->pageData[so->nPageData].offnum = i;
/*
- * In an index-only scan, also fetch the data from the tuple.
+ * In an index-only scan, also fetch the data from the tuple. The
+ * reconstructed tuples are stored in pageDataCxt.
*/
if (scan->xs_want_itup)
{
oldcxt = MemoryContextSwitchTo(so->pageDataCxt);
- so->pageData[so->nPageData].ftup =
+ so->pageData[so->nPageData].recontup =
gistFetchTuple(giststate, r, it);
MemoryContextSwitchTo(oldcxt);
}
@@ -478,7 +480,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
* In an index-only scan, also fetch the data from the tuple.
*/
if (scan->xs_want_itup)
- item->data.heap.ftup = gistFetchTuple(giststate, r, it);
+ item->data.heap.recontup = gistFetchTuple(giststate, r, it);
}
else
{
@@ -540,11 +542,11 @@ getNextNearest(IndexScanDesc scan)
bool res = false;
int i;
- if (scan->xs_itup)
+ if (scan->xs_hitup)
{
/* free previously returned tuple */
- pfree(scan->xs_itup);
- scan->xs_itup = NULL;
+ pfree(scan->xs_hitup);
+ scan->xs_hitup = NULL;
}
do
@@ -601,7 +603,7 @@ getNextNearest(IndexScanDesc scan)
/* in an index-only scan, also return the reconstructed tuple. */
if (scan->xs_want_itup)
- scan->xs_itup = item->data.heap.ftup;
+ scan->xs_hitup = item->data.heap.recontup;
res = true;
}
else
@@ -641,6 +643,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
so->firstCall = false;
so->curPageData = so->nPageData = 0;
+ scan->xs_hitup = NULL;
if (so->pageDataCxt)
MemoryContextReset(so->pageDataCxt);
@@ -685,7 +688,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
/* in an index-only scan, also return the reconstructed tuple */
if (scan->xs_want_itup)
- scan->xs_itup = so->pageData[so->curPageData].ftup;
+ scan->xs_hitup = so->pageData[so->curPageData].recontup;
so->curPageData++;
@@ -765,6 +768,7 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
/* Begin the scan by processing the root page */
so->curPageData = so->nPageData = 0;
+ scan->xs_hitup = NULL;
if (so->pageDataCxt)
MemoryContextReset(so->pageDataCxt);
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index d47211afc0..15b89fd8ad 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -7,7 +7,7 @@
* This gives R-tree behavior, with Guttman's poly-time split algorithm.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -17,6 +17,7 @@
*/
#include "postgres.h"
+#include <float.h>
#include <math.h>
#include "access/gist.h"
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 6f07cd8d46..058544e2ae 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -4,7 +4,7 @@
* routines to manage scans on GiST index relations
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -125,7 +125,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
* which is created on the second call and reset on later calls. Thus, in
* the common case where a scan is only rescan'd once, we just put the
* queue in scanCxt and don't pay the overhead of making a second memory
- * context. If we do rescan more than once, the first RBTree is just left
+ * context. If we do rescan more than once, the first queue is just left
* for dead until end of scan; this small wastage seems worth the savings
* in the common case.
*/
@@ -140,9 +140,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
/* second time through */
so->queueCxt = AllocSetContextCreate(so->giststate->scanCxt,
"GiST queue context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
first_time = false;
}
else
@@ -157,7 +155,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
* tuple descriptor to represent the returned index tuples and create a
* memory context to hold them during the scan.
*/
- if (scan->xs_want_itup && !scan->xs_itupdesc)
+ if (scan->xs_want_itup && !scan->xs_hitupdesc)
{
int natts;
int attno;
@@ -176,16 +174,15 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
scan->indexRelation->rd_opcintype[attno - 1],
-1, 0);
}
- scan->xs_itupdesc = so->giststate->fetchTupdesc;
+ scan->xs_hitupdesc = so->giststate->fetchTupdesc;
+ /* Also create a memory context that will hold the returned tuples */
so->pageDataCxt = AllocSetContextCreate(so->giststate->scanCxt,
"GiST page data context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
}
- /* create new, empty RBTree for search queue */
+ /* create new, empty pairing heap for search queue */
oldCxt = MemoryContextSwitchTo(so->queueCxt);
so->queue = pairingheap_allocate(pairingheap_GISTSearchItem_cmp, scan);
MemoryContextSwitchTo(oldCxt);
@@ -316,6 +313,9 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
if (!first_time)
pfree(fn_extras);
}
+
+ /* any previous xs_hitup will have been pfree'd in context resets above */
+ scan->xs_hitup = NULL;
}
void
diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index d394969a57..cffc5ddc75 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -15,7 +15,7 @@
* gistSplitByKey() is the entry point to this file.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 26d4a64694..cbdaec9d2b 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -4,7 +4,7 @@
* utilities routines for the postgres GiST index access method.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -13,6 +13,7 @@
*/
#include "postgres.h"
+#include <float.h>
#include <math.h>
#include "access/gist_private.h"
@@ -624,9 +625,9 @@ gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
/*
* Fetch all keys in tuple.
- * returns new IndexTuple that contains GISTENTRY with fetched data
+ * Returns a new HeapTuple containing the originally-indexed data.
*/
-IndexTuple
+HeapTuple
gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
{
MemoryContext oldcxt = MemoryContextSwitchTo(giststate->tempCxt);
@@ -660,7 +661,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
}
MemoryContextSwitchTo(oldcxt);
- return index_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
+ return heap_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
}
float
@@ -852,7 +853,7 @@ gistproperty(Oid index_oid, int attno,
bool *res, bool *isnull)
{
HeapTuple tuple;
- Form_pg_index rd_index;
+ Form_pg_index rd_index PG_USED_FOR_ASSERTS_ONLY;
Form_pg_opclass rd_opclass;
Datum datum;
bool disnull;
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 53e5cea580..77d9d12f0b 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -4,7 +4,7 @@
* vacuuming routines for the postgres GiST index access method.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c
index ffd7fd631b..585c92be26 100644
--- a/src/backend/access/gist/gistvalidate.c
+++ b/src/backend/access/gist/gistvalidate.c
@@ -3,7 +3,7 @@
* gistvalidate.c
* Opclass validator for GiST.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -23,6 +23,7 @@
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
+#include "utils/regproc.h"
#include "utils/syscache.h"
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c
index 01c7ef7ea6..4f4fe8fab5 100644
--- a/src/backend/access/gist/gistxlog.c
+++ b/src/backend/access/gist/gistxlog.c
@@ -4,7 +4,7 @@
* WAL replay logic for GiST.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -13,7 +13,9 @@
*/
#include "postgres.h"
+#include "access/bufmask.h"
#include "access/gist_private.h"
+#include "access/gistxlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "utils/memutils.h"
@@ -80,9 +82,31 @@ gistRedoPageUpdateRecord(XLogReaderState *record)
page = (Page) BufferGetPage(buffer);
- /* Delete old tuples */
- if (xldata->ntodelete > 0)
+ if (xldata->ntodelete == 1 && xldata->ntoinsert == 1)
{
+ /*
+ * When replacing one tuple with one other tuple, we must use
+ * PageIndexTupleOverwrite for consistency with gistplacetopage.
+ */
+ OffsetNumber offnum = *((OffsetNumber *) data);
+ IndexTuple itup;
+ Size itupsize;
+
+ data += sizeof(OffsetNumber);
+ itup = (IndexTuple) data;
+ itupsize = IndexTupleSize(itup);
+ if (!PageIndexTupleOverwrite(page, offnum, (Item) itup, itupsize))
+ elog(ERROR, "failed to add item to GiST index page, size %d bytes",
+ (int) itupsize);
+ data += itupsize;
+ /* should be nothing left after consuming 1 tuple */
+ Assert(data - begin == datalen);
+ /* update insertion count for assert check below */
+ ninserted++;
+ }
+ else if (xldata->ntodelete > 0)
+ {
+ /* Otherwise, delete old tuples if any */
OffsetNumber *todelete = (OffsetNumber *) data;
data += sizeof(OffsetNumber) * xldata->ntodelete;
@@ -92,7 +116,7 @@ gistRedoPageUpdateRecord(XLogReaderState *record)
GistMarkTuplesDeleted(page);
}
- /* add tuples */
+ /* Add new tuples if any */
if (data - begin < datalen)
{
OffsetNumber off = (PageIsEmpty(page)) ? FirstOffsetNumber :
@@ -115,6 +139,7 @@ gistRedoPageUpdateRecord(XLogReaderState *record)
}
}
+ /* Check that XLOG record contained expected number of tuples */
Assert(ninserted == xldata->ntoinsert);
PageSetLSN(page, lsn);
@@ -320,6 +345,48 @@ gist_xlog_cleanup(void)
}
/*
+ * Mask a Gist page before running consistency checks on it.
+ */
+void
+gist_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+
+ mask_page_lsn(page);
+
+ mask_page_hint_bits(page);
+ mask_unused_space(page);
+
+ /*
+ * NSN is nothing but a special purpose LSN. Hence, mask it for the same
+ * reason as mask_page_lsn.
+ */
+ GistPageSetNSN(page, (uint64) MASK_MARKER);
+
+ /*
+ * We update F_FOLLOW_RIGHT flag on the left child after writing WAL
+ * record. Hence, mask this flag. See gistplacetopage() for details.
+ */
+ GistMarkFollowRight(page);
+
+ if (GistPageIsLeaf(page))
+ {
+ /*
+ * In gist leaf pages, it is possible to modify the LP_FLAGS without
+ * emitting any WAL record. Hence, mask the line pointer flags. See
+ * gistkillitems() for details.
+ */
+ mask_lp_flags(page);
+ }
+
+ /*
+ * During gist redo, we never mark a page as garbage. Hence, mask it to
+ * ignore any differences.
+ */
+ GistClearPageHasGarbage(page);
+}
+
+/*
* Write WAL record of a page split.
*/
XLogRecPtr
diff --git a/src/backend/access/hash/Makefile b/src/backend/access/hash/Makefile
index 5d3bd94d3e..b154569b46 100644
--- a/src/backend/access/hash/Makefile
+++ b/src/backend/access/hash/Makefile
@@ -12,7 +12,7 @@ subdir = src/backend/access/hash
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = hash.o hashfunc.o hashinsert.o hashovfl.o hashpage.o hashscan.o \
- hashsearch.o hashsort.o hashutil.o hashvalidate.o
+OBJS = hash.o hashfunc.o hashinsert.o hashovfl.o hashpage.o hashsearch.o \
+ hashsort.o hashutil.o hashvalidate.o hash_xlog.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/hash/README b/src/backend/access/hash/README
index 0a7da89285..c8a0ec78a9 100644
--- a/src/backend/access/hash/README
+++ b/src/backend/access/hash/README
@@ -58,35 +58,51 @@ rules to support a variable number of overflow pages while not having to
move primary bucket pages around after they are created.
Primary bucket pages (henceforth just "bucket pages") are allocated in
-power-of-2 groups, called "split points" in the code. Buckets 0 and 1
-are created when the index is initialized. At the first split, buckets 2
-and 3 are allocated; when bucket 4 is needed, buckets 4-7 are allocated;
-when bucket 8 is needed, buckets 8-15 are allocated; etc. All the bucket
-pages of a power-of-2 group appear consecutively in the index. This
-addressing scheme allows the physical location of a bucket page to be
-computed from the bucket number relatively easily, using only a small
-amount of control information. We take the log2() of the bucket number
-to determine which split point S the bucket belongs to, and then simply
-add "hashm_spares[S] + 1" (where hashm_spares[] is an array stored in the
-metapage) to compute the physical address. hashm_spares[S] can be
-interpreted as the total number of overflow pages that have been allocated
-before the bucket pages of splitpoint S. hashm_spares[0] is always 0,
-so that buckets 0 and 1 (which belong to splitpoint 0) always appear at
-block numbers 1 and 2, just after the meta page. We always have
-hashm_spares[N] <= hashm_spares[N+1], since the latter count includes the
-former. The difference between the two represents the number of overflow
-pages appearing between the bucket page groups of splitpoints N and N+1.
-
+power-of-2 groups, called "split points" in the code. That means at every new
+splitpoint we double the existing number of buckets. Allocating huge chunks
+of bucket pages all at once isn't optimal and we will take ages to consume
+those. To avoid this exponential growth of index size, we did use a trick to
+break up allocation of buckets at the splitpoint into 4 equal phases. If
+(2 ^ x) are the total buckets need to be allocated at a splitpoint (from now on
+we shall call this as a splitpoint group), then we allocate 1/4th (2 ^ (x - 2))
+of total buckets at each phase of splitpoint group. Next quarter of allocation
+will only happen if buckets of the previous phase have been already consumed.
+For the initial splitpoint groups < 10 we will allocate all of their buckets in
+single phase only, as number of buckets allocated at initial groups are small
+in numbers. And for the groups >= 10 the allocation process is distributed
+among four equal phases. At group 10 we allocate (2 ^ 9) buckets in 4
+different phases {2 ^ 7, 2 ^ 7, 2 ^ 7, 2 ^ 7}, the numbers in curly braces
+indicate the number of buckets allocated within each phase of splitpoint group
+10. And, for splitpoint group 11 and 12 allocation phases will be
+{2 ^ 8, 2 ^ 8, 2 ^ 8, 2 ^ 8} and {2 ^ 9, 2 ^ 9, 2 ^ 9, 2 ^ 9} respectively. We
+can see that at each splitpoint group we double the total number of buckets
+from the previous group but in an incremental phase. The bucket pages
+allocated within one phase of a splitpoint group will appear consecutively in
+the index. This addressing scheme allows the physical location of a bucket
+page to be computed from the bucket number relatively easily, using only a
+small amount of control information. If we look at the function
+_hash_spareindex for a given bucket number we first compute the
+splitpoint group it belongs to and then the phase to which the bucket belongs
+to. Adding them we get the global splitpoint phase number S to which the
+bucket belongs and then simply add "hashm_spares[S] + 1" (where hashm_spares[]
+is an array stored in the metapage) with given bucket number to compute its
+physical address. The hashm_spares[S] can be interpreted as the total number
+of overflow pages that have been allocated before the bucket pages of
+splitpoint phase S. The hashm_spares[0] is always 0, so that buckets 0 and 1
+always appear at block numbers 1 and 2, just after the meta page. We always
+have hashm_spares[N] <= hashm_spares[N+1], since the latter count includes the
+former. The difference between the two represents the number of overflow pages
+appearing between the bucket page groups of splitpoints phase N and N+1.
(Note: the above describes what happens when filling an initially minimally
-sized hash index. In practice, we try to estimate the required index size
-and allocate a suitable number of splitpoints immediately, to avoid
+sized hash index. In practice, we try to estimate the required index size and
+allocate a suitable number of splitpoints phases immediately, to avoid
expensive re-splitting during initial index build.)
When S splitpoints exist altogether, the array entries hashm_spares[0]
through hashm_spares[S] are valid; hashm_spares[S] records the current
total number of overflow pages. New overflow pages are created as needed
at the end of the index, and recorded by incrementing hashm_spares[S].
-When it is time to create a new splitpoint's worth of bucket pages, we
+When it is time to create a new splitpoint phase's worth of bucket pages, we
copy hashm_spares[S] into hashm_spares[S+1] and increment S (which is
stored in the hashm_ovflpoint field of the meta page). This has the
effect of reserving the correct number of bucket pages at the end of the
@@ -101,7 +117,7 @@ We have to allow the case "greater than" because it's possible that during
an index extension we crash after allocating filesystem space and before
updating the metapage. Note that on filesystems that allow "holes" in
files, it's entirely likely that pages before the logical EOF are not yet
-allocated: when we allocate a new splitpoint's worth of bucket pages, we
+allocated: when we allocate a new splitpoint phase's worth of bucket pages, we
physically zero the last such page to force the EOF up, and the first such
page will be used immediately, but the intervening pages are not written
until needed.
@@ -126,53 +142,98 @@ the initially created buckets.
Lock Definitions
----------------
-We use both lmgr locks ("heavyweight" locks) and buffer context locks
-(LWLocks) to control access to a hash index. lmgr locks are needed for
-long-term locking since there is a (small) risk of deadlock, which we must
-be able to detect. Buffer context locks are used for short-term access
-control to individual pages of the index.
-
-LockPage(rel, page), where page is the page number of a hash bucket page,
-represents the right to split or compact an individual bucket. A process
-splitting a bucket must exclusive-lock both old and new halves of the
-bucket until it is done. A process doing VACUUM must exclusive-lock the
-bucket it is currently purging tuples from. Processes doing scans or
-insertions must share-lock the bucket they are scanning or inserting into.
-(It is okay to allow concurrent scans and insertions.)
-
-The lmgr lock IDs corresponding to overflow pages are currently unused.
-These are available for possible future refinements. LockPage(rel, 0)
-is also currently undefined (it was previously used to represent the right
-to modify the hash-code-to-bucket mapping, but it is no longer needed for
-that purpose).
-
-Note that these lock definitions are conceptually distinct from any sort
-of lock on the pages whose numbers they share. A process must also obtain
-read or write buffer lock on the metapage or bucket page before accessing
-said page.
-
-Processes performing hash index scans must hold share lock on the bucket
-they are scanning throughout the scan. This seems to be essential, since
-there is no reasonable way for a scan to cope with its bucket being split
-underneath it. This creates a possibility of deadlock external to the
-hash index code, since a process holding one of these locks could block
-waiting for an unrelated lock held by another process. If that process
-then does something that requires exclusive lock on the bucket, we have
-deadlock. Therefore the bucket locks must be lmgr locks so that deadlock
-can be detected and recovered from.
-
-Processes must obtain read (share) buffer context lock on any hash index
-page while reading it, and write (exclusive) lock while modifying it.
-To prevent deadlock we enforce these coding rules: no buffer lock may be
-held long term (across index AM calls), nor may any buffer lock be held
-while waiting for an lmgr lock, nor may more than one buffer lock
-be held at a time by any one process. (The third restriction is probably
-stronger than necessary, but it makes the proof of no deadlock obvious.)
+Concurrency control for hash indexes is provided using buffer content
+locks, buffer pins, and cleanup locks. Here as elsewhere in PostgreSQL,
+cleanup lock means that we hold an exclusive lock on the buffer and have
+observed at some point after acquiring the lock that we hold the only pin
+on that buffer. For hash indexes, a cleanup lock on a primary bucket page
+represents the right to perform an arbitrary reorganization of the entire
+bucket. Therefore, scans retain a pin on the primary bucket page for the
+bucket they are currently scanning. Splitting a bucket requires a cleanup
+lock on both the old and new primary bucket pages. VACUUM therefore takes
+a cleanup lock on every bucket page in order to remove tuples. It can also
+remove tuples copied to a new bucket by any previous split operation, because
+the cleanup lock taken on the primary bucket page guarantees that no scans
+which started prior to the most recent split can still be in progress. After
+cleaning each page individually, it attempts to take a cleanup lock on the
+primary bucket page in order to "squeeze" the bucket down to the minimum
+possible number of pages.
+
+To avoid deadlocks, we must be consistent about the lock order in which we
+lock the buckets for operations that requires locks on two different buckets.
+We choose to always lock the lower-numbered bucket first. The metapage is
+only ever locked after all bucket locks have been taken.
+
+
+Metapage Caching
+----------------
+Both scanning the index and inserting tuples require locating the bucket
+where a given tuple ought to be located. To do this, we need the bucket
+count, highmask, and lowmask from the metapage; however, it's undesirable
+for performance reasons to have to have to lock and pin the metapage for
+every such operation. Instead, we retain a cached copy of the metapage
+in each each backend's relcache entry. This will produce the correct
+bucket mapping as long as the target bucket hasn't been split since the
+last cache refresh.
+
+To guard against the possibility that such a split has occurred, the
+primary page of each bucket chain stores the number of buckets that
+existed as of the time the bucket was last split, or if never split as
+of the time it was created, in the space normally used for the
+previous block number (that is, hasho_prevblkno). This doesn't cost
+anything because the primary bucket page is always the first page in
+the chain, and the previous block number is therefore always, in
+reality, InvalidBlockNumber.
+
+After computing the ostensibly-correct bucket number based on our cached
+copy of the metapage, we lock the corresponding primary bucket page and
+check whether the bucket count stored in hasho_prevblkno is greater than
+our the number of buckets stored in our cached copy of the metapage. If
+so, the bucket has certainly been split, because the must originally
+have been less than the number of buckets that existed at that time and
+can't have increased except due to a split. If not, the bucket can't have
+been split, because a split would have created a new bucket with a higher
+bucket number than any we'd seen previously. In the latter case, we've
+locked the correct bucket and can proceed; in the former case, we must
+release the lock on this bucket, lock the metapage, update our cache,
+unlock the metapage, and retry.
+
+Needing to retry occasionally might seem expensive, but the number of times
+any given bucket can be split is limited to a few dozen no matter how
+many times the hash index is accessed, because the total number of
+buckets is limited to less than 2^32. On the other hand, the number of
+times we access a bucket is unbounded and will be several orders of
+magnitude larger even in unsympathetic cases.
+
+(The metapage cache is new in v10. Older hash indexes had the primary
+bucket page's hasho_prevblkno initialized to InvalidBuffer.)
Pseudocode Algorithms
---------------------
+Various flags that are used in hash index operations are described as below:
+
+The bucket-being-split and bucket-being-populated flags indicate that split
+the operation is in progress for a bucket. During split operation, a
+bucket-being-split flag is set on the old bucket and bucket-being-populated
+flag is set on new bucket. These flags are cleared once the split operation
+is finished.
+
+The split-cleanup flag indicates that a bucket which has been recently split
+still contains tuples that were also copied to the new bucket; it essentially
+marks the split as incomplete. Once we're certain that no scans which
+started before the new bucket was fully populated are still in progress, we
+can remove the copies from the old bucket and clear the flag. We insist that
+this flag must be clear before splitting a bucket; thus, a bucket can't be
+split again until the previous split is totally complete.
+
+The moved-by-split flag on a tuple indicates that tuple is moved from old to
+new bucket. Concurrent scans will skip such tuples until the split operation
+is finished. Once the tuple is marked as moved-by-split, it will remain so
+forever but that does no harm. We have intentionally not cleared it as that
+can generate an additional I/O which is not necessary.
+
The operations we need to support are: readers scanning the index for
entries of a particular hash code (which by definition are all in the same
bucket); insertion of a new tuple into the correct bucket; enlarging the
@@ -187,67 +248,75 @@ track of available overflow pages.
The reader algorithm is:
- pin meta page and take buffer content lock in shared mode
- loop:
- compute bucket number for target hash key
- release meta page buffer content lock
- if (correct bucket page is already locked)
- break
- release any existing bucket page lock (if a concurrent split happened)
- take heavyweight bucket lock
- retake meta page buffer content lock in shared mode
+ lock the primary bucket page of the target bucket
+ if the target bucket is still being populated by a split:
+ release the buffer content lock on current bucket page
+ pin and acquire the buffer content lock on old bucket in shared mode
+ release the buffer content lock on old bucket, but not pin
+ retake the buffer content lock on new bucket
+ arrange to scan the old bucket normally and the new bucket for
+ tuples which are not moved-by-split
-- then, per read request:
- release pin on metapage
- read current page of bucket and take shared buffer content lock
- step to next page if necessary (no chaining of locks)
+ reacquire content lock on current page
+ step to next page if necessary (no chaining of content locks, but keep
+ the pin on the primary bucket throughout the scan; we also maintain
+ a pin on the page currently being scanned)
get tuple
- release buffer content lock and pin on current page
+ release content lock
-- at scan shutdown:
- release bucket share-lock
-
-We can't hold the metapage lock while acquiring a lock on the target bucket,
-because that might result in an undetected deadlock (lwlocks do not participate
-in deadlock detection). Instead, we relock the metapage after acquiring the
-bucket page lock and check whether the bucket has been split. If not, we're
-done. If so, we release our previously-acquired lock and repeat the process
-using the new bucket number. Holding the bucket sharelock for
-the remainder of the scan prevents the reader's current-tuple pointer from
-being invalidated by splits or compactions. Notice that the reader's lock
-does not prevent other buckets from being split or compacted.
+ release all pins still held
+
+Holding the buffer pin on the primary bucket page for the whole scan prevents
+the reader's current-tuple pointer from being invalidated by splits or
+compactions. (Of course, other buckets can still be split or compacted.)
To keep concurrency reasonably good, we require readers to cope with
concurrent insertions, which means that they have to be able to re-find
-their current scan position after re-acquiring the page sharelock. Since
-deletion is not possible while a reader holds the bucket sharelock, and
-we assume that heap tuple TIDs are unique, this can be implemented by
+their current scan position after re-acquiring the buffer content lock on
+page. Since deletion is not possible while a reader holds the pin on bucket,
+and we assume that heap tuple TIDs are unique, this can be implemented by
searching for the same heap tuple TID previously returned. Insertion does
not move index entries across pages, so the previously-returned index entry
should always be on the same page, at the same or higher offset number,
as it was before.
+To allow for scans during a bucket split, if at the start of the scan, the
+bucket is marked as bucket-being-populated, it scan all the tuples in that
+bucket except for those that are marked as moved-by-split. Once it finishes
+the scan of all the tuples in the current bucket, it scans the old bucket from
+which this bucket is formed by split.
+
The insertion algorithm is rather similar:
- pin meta page and take buffer content lock in shared mode
- loop:
- compute bucket number for target hash key
- release meta page buffer content lock
- if (correct bucket page is already locked)
- break
- release any existing bucket page lock (if a concurrent split happened)
- take heavyweight bucket lock in shared mode
- retake meta page buffer content lock in shared mode
--- (so far same as reader)
- release pin on metapage
- pin current page of bucket and take exclusive buffer content lock
- if full, release, read/exclusive-lock next page; repeat as needed
+ lock the primary bucket page of the target bucket
+-- (so far same as reader, except for acquisition of buffer content lock in
+ exclusive mode on primary bucket page)
+ if the bucket-being-split flag is set for a bucket and pin count on it is
+ one, then finish the split
+ release the buffer content lock on current bucket
+ get the "new" bucket which was being populated by the split
+ scan the new bucket and form the hash table of TIDs
+ conditionally get the cleanup lock on old and new buckets
+ if we get the lock on both the buckets
+ finish the split using algorithm mentioned below for split
+ release the pin on old bucket and restart the insert from beginning.
+ if current page is full, first check if this page contains any dead tuples.
+ if yes, remove dead tuples from the current page and again check for the
+ availability of the space. If enough space found, insert the tuple else
+ release lock but not pin, read/exclusive-lock
+ next page; repeat as needed
>> see below if no space in any page of bucket
+ take buffer content lock in exclusive mode on metapage
insert tuple at appropriate place in page
- mark current page dirty and release buffer content lock and pin
- release heavyweight share-lock
- pin meta page and take buffer content lock in shared mode
+ mark current page dirty
increment tuple count, decide if split needed
- mark meta page dirty and release buffer content lock and pin
- done if no split needed, else enter Split algorithm below
+ mark meta page dirty
+ write WAL for insertion of tuple
+ release the buffer content lock on metapage
+ release buffer content lock on current page
+ if current page is not a bucket page, release the pin on bucket page
+ if split is needed, enter Split algorithm below
+ release the pin on metapage
To speed searches, the index entries within any individual index page are
kept sorted by hash code; the insertion code must take care to insert new
@@ -256,11 +325,13 @@ bucket that is being actively scanned, because readers can cope with this
as explained above. We only need the short-term buffer locks to ensure
that readers do not see a partially-updated page.
-It is clearly impossible for readers and inserters to deadlock, and in
-fact this algorithm allows them a very high degree of concurrency.
-(The exclusive metapage lock taken to update the tuple count is stronger
-than necessary, since readers do not care about the tuple count, but the
-lock is held for such a short time that this is probably not an issue.)
+To avoid deadlock between readers and inserters, whenever there is a need
+to lock multiple buckets, we always take in the order suggested in Lock
+Definitions above. This algorithm allows them a very high degree of
+concurrency. (The exclusive metapage lock taken to update the tuple count
+is stronger than necessary, since readers do not care about the tuple count,
+but the lock is held for such a short time that this is probably not an
+issue.)
When an inserter cannot find space in any existing page of a bucket, it
must obtain an overflow page and add that page to the bucket's chain.
@@ -271,46 +342,47 @@ index is overfull (has a higher-than-wanted ratio of tuples to buckets).
The algorithm attempts, but does not necessarily succeed, to split one
existing bucket in two, thereby lowering the fill ratio:
- pin meta page and take buffer content lock in exclusive mode
- check split still needed
- if split not needed anymore, drop buffer content lock and pin and exit
- decide which bucket to split
- Attempt to X-lock old bucket number (definitely could fail)
- Attempt to X-lock new bucket number (shouldn't fail, but...)
- if above fail, drop locks and pin and exit
- update meta page to reflect new number of buckets
- mark meta page dirty and release buffer content lock and pin
- -- now, accesses to all other buckets can proceed.
- Perform actual split of bucket, moving tuples as needed
- >> see below about acquiring needed extra space
- Release X-locks of old and new buckets
-
-Note the metapage lock is not held while the actual tuple rearrangement is
-performed, so accesses to other buckets can proceed in parallel; in fact,
-it's possible for multiple bucket splits to proceed in parallel.
-
-Split's attempt to X-lock the old bucket number could fail if another
-process holds S-lock on it. We do not want to wait if that happens, first
-because we don't want to wait while holding the metapage exclusive-lock,
-and second because it could very easily result in deadlock. (The other
-process might be out of the hash AM altogether, and could do something
-that blocks on another lock this process holds; so even if the hash
-algorithm itself is deadlock-free, a user-induced deadlock could occur.)
-So, this is a conditional LockAcquire operation, and if it fails we just
-abandon the attempt to split. This is all right since the index is
-overfull but perfectly functional. Every subsequent inserter will try to
-split, and eventually one will succeed. If multiple inserters failed to
-split, the index might still be overfull, but eventually, the index will
+ pin meta page and take buffer content lock in exclusive mode
+ check split still needed
+ if split not needed anymore, drop buffer content lock and pin and exit
+ decide which bucket to split
+ try to take a cleanup lock on that bucket; if fail, give up
+ if that bucket is still being split or has split-cleanup work:
+ try to finish the split and the cleanup work
+ if that succeeds, start over; if it fails, give up
+ mark the old and new buckets indicating split is in progress
+ mark both old and new buckets as dirty
+ write WAL for allocation of new page for split
+ copy the tuples that belongs to new bucket from old bucket, marking
+ them as moved-by-split
+ write WAL record for moving tuples to new page once the new page is full
+ or all the pages of old bucket are finished
+ release lock but not pin for primary bucket page of old bucket,
+ read/shared-lock next page; repeat as needed
+ clear the bucket-being-split and bucket-being-populated flags
+ mark the old bucket indicating split-cleanup
+ write WAL for changing the flags on both old and new buckets
+
+The split operation's attempt to acquire cleanup-lock on the old bucket number
+could fail if another process holds any lock or pin on it. We do not want to
+wait if that happens, because we don't want to wait while holding the metapage
+exclusive-lock. So, this is a conditional LWLockAcquire operation, and if
+it fails we just abandon the attempt to split. This is all right since the
+index is overfull but perfectly functional. Every subsequent inserter will
+try to split, and eventually one will succeed. If multiple inserters failed
+to split, the index might still be overfull, but eventually, the index will
not be overfull and split attempts will stop. (We could make a successful
splitter loop to see if the index is still overfull, but it seems better to
distribute the split overhead across successive insertions.)
-A problem is that if a split fails partway through (eg due to insufficient
-disk space) the index is left corrupt. The probability of that could be
-made quite low if we grab a free page or two before we update the meta
-page, but the only real solution is to treat a split as a WAL-loggable,
-must-complete action. I'm not planning to teach hash about WAL in this
-go-round.
+If a split fails partway through (e.g. due to insufficient disk space or an
+interrupt), the index will not be corrupted. Instead, we'll retry the split
+every time a tuple is inserted into the old bucket prior to inserting the new
+tuple; eventually, we should succeed. The fact that a split is left
+unfinished doesn't prevent subsequent buckets from being split, but we won't
+try to split the bucket again until the prior split is finished. In other
+words, a bucket can be in the middle of being split for some time, but it can't
+be in the middle of two splits at the same time.
The fourth operation is garbage collection (bulk deletion):
@@ -319,31 +391,46 @@ The fourth operation is garbage collection (bulk deletion):
fetch current max bucket number
release meta page buffer content lock and pin
while next bucket <= max bucket do
- Acquire X lock on target bucket
- Scan and remove tuples, compact free space as needed
- Release X lock
+ acquire cleanup lock on primary bucket page
+ loop:
+ scan and remove tuples
+ mark the target page dirty
+ write WAL for deleting tuples from target page
+ if this is the last bucket page, break out of loop
+ pin and x-lock next page
+ release prior lock and pin (except keep pin on primary bucket page)
+ if the page we have locked is not the primary bucket page:
+ release lock and take exclusive lock on primary bucket page
+ if there are no other pins on the primary bucket page:
+ squeeze the bucket to remove free space
+ release the pin on primary bucket page
next bucket ++
end loop
pin metapage and take buffer content lock in exclusive mode
check if number of buckets changed
if so, release content lock and pin and return to for-each-bucket loop
else update metapage tuple count
- mark meta page dirty and release buffer content lock and pin
-
-Note that this is designed to allow concurrent splits. If a split occurs,
-tuples relocated into the new bucket will be visited twice by the scan,
-but that does no harm. (We must however be careful about the statistics
+ mark meta page dirty and write WAL for update of metapage
+ release buffer content lock and pin
+
+Note that this is designed to allow concurrent splits and scans. If a split
+occurs, tuples relocated into the new bucket will be visited twice by the
+scan, but that does no harm. As we release the lock on bucket page during
+cleanup scan of a bucket, it will allow concurrent scan to start on a bucket
+and ensures that scan will always be behind cleanup. It is must to keep scans
+behind cleanup, else vacuum could decrease the TIDs that are required to
+complete the scan. Now, as the scan that returns multiple tuples from the
+same bucket page always expect next valid TID to be greater than or equal to
+the current TID, it might miss the tuples. This holds true for backward scans
+as well (backward scans first traverse each bucket starting from first bucket
+to last overflow page in the chain). We must be careful about the statistics
reported by the VACUUM operation. What we can do is count the number of
-tuples scanned, and believe this in preference to the stored tuple count
-if the stored tuple count and number of buckets did *not* change at any
-time during the scan. This provides a way of correcting the stored tuple
-count if it gets out of sync for some reason. But if a split or insertion
-does occur concurrently, the scan count is untrustworthy; instead,
-subtract the number of tuples deleted from the stored tuple count and
-use that.)
-
-The exclusive lock request could deadlock in some strange scenarios, but
-we can just error out without any great harm being done.
+tuples scanned, and believe this in preference to the stored tuple count if
+the stored tuple count and number of buckets did *not* change at any time
+during the scan. This provides a way of correcting the stored tuple count if
+it gets out of sync for some reason. But if a split or insertion does occur
+concurrently, the scan count is untrustworthy; instead, subtract the number of
+tuples deleted from the stored tuple count and use that.
Free Space Management
@@ -366,18 +453,16 @@ Obtaining an overflow page:
search for a free page (zero bit in bitmap)
if found:
set bit in bitmap
- mark bitmap page dirty and release content lock
+ mark bitmap page dirty
take metapage buffer content lock in exclusive mode
if first-free-bit value did not change,
update it and mark meta page dirty
- release meta page buffer content lock
- return page number
else (not found):
release bitmap page buffer content lock
loop back to try next bitmap page, if any
-- here when we have checked all bitmap pages; we hold meta excl. lock
extend index to add another overflow page; update meta information
- mark meta page dirty and release buffer content lock
+ mark meta page dirty
return page number
It is slightly annoying to release and reacquire the metapage lock
@@ -397,12 +482,17 @@ like this:
-- having determined that no space is free in the target bucket:
remember last page of bucket, drop write lock on it
- call free-page-acquire routine
re-write-lock last page of bucket
if it is not last anymore, step to the last page
- update (former) last page to point to new page
+ execute free-page-acquire (obtaining an overflow page) mechanism
+ described above
+ update (former) last page to point to the new page and mark buffer dirty
write-lock and initialize new page, with back link to former last page
- write and release former last page
+ write WAL for addition of overflow page
+ release the locks on meta page and bitmap page acquired in
+ free-page-acquire algorithm
+ release the lock on former last page
+ release the lock on new overflow page
insert tuple into new page
-- etc.
@@ -417,13 +507,11 @@ free page; there can be no other process holding lock on it.
Bucket splitting uses a similar algorithm if it has to extend the new
bucket, but it need not worry about concurrent extension since it has
-exclusive lock on the new bucket.
+buffer content lock in exclusive mode on the new bucket.
-Freeing an overflow page is done by garbage collection and by bucket
-splitting (the old bucket may contain no-longer-needed overflow pages).
-In both cases, the process holds exclusive lock on the containing bucket,
-so need not worry about other accessors of pages in the bucket. The
-algorithm is:
+Freeing an overflow page requires the process to hold buffer content lock in
+exclusive mode on the containing bucket, so need not worry about other
+accessors of pages in the bucket. The algorithm is:
delink overflow page from bucket chain
(this requires read/update/write/release of fore and aft siblings)
@@ -431,12 +519,14 @@ algorithm is:
determine which bitmap page contains the free space bit for page
release meta page buffer content lock
pin bitmap page and take buffer content lock in exclusive mode
- update bitmap bit
- mark bitmap page dirty and release buffer content lock and pin
- if page number is less than what we saw as first-free-bit in meta:
retake meta page buffer content lock in exclusive mode
+ move (insert) tuples that belong to the overflow page being freed
+ update bitmap bit
+ mark bitmap page dirty
if page number is still less than first-free-bit,
update first-free-bit field and mark meta page dirty
+ write WAL for delinking overflow page operation
+ release buffer content lock and pin
release meta page buffer content lock and pin
We have to do it this way because we must clear the bitmap bit before
@@ -447,21 +537,96 @@ page acquirer will scan more bitmap bits than he needs to. What must be
avoided is having first-free-bit greater than the actual first free bit,
because then that free page would never be found by searchers.
-All the freespace operations should be called while holding no buffer
-locks. Since they need no lmgr locks, deadlock is not possible.
+The reason of moving tuples from overflow page while delinking the later is
+to make that as an atomic operation. Not doing so could lead to spurious reads
+on standby. Basically, the user might see the same tuple twice.
+
+
+WAL Considerations
+------------------
+
+The hash index operations like create index, insert, delete, bucket split,
+allocate overflow page, and squeeze in themselves don't guarantee hash index
+consistency after a crash. To provide robustness, we write WAL for each of
+these operations.
+
+CREATE INDEX writes multiple WAL records. First, we write a record to cover
+the initializatoin of the metapage, followed by one for each new bucket
+created, followed by one for the initial bitmap page. It's not important for
+index creation to appear atomic, because the index isn't yet visible to any
+other transaction, and the creating transaction will roll back in the event of
+a crash. It would be difficult to cover the whole operation with a single
+write-ahead log record anyway, because we can log only a fixed number of
+pages, as given by XLR_MAX_BLOCK_ID (32), with current XLog machinery.
+
+Ordinary item insertions (that don't force a page split or need a new overflow
+page) are single WAL entries. They touch a single bucket page and the
+metapage. The metapage is updated during replay as it is updated during
+original operation.
+
+If an insertion causes the addition of an overflow page, there will be one
+WAL entry for the new overflow page and second entry for insert itself.
+
+If an insertion causes a bucket split, there will be one WAL entry for insert
+itself, followed by a WAL entry for allocating a new bucket, followed by a WAL
+entry for each overflow bucket page in the new bucket to which the tuples are
+moved from old bucket, followed by a WAL entry to indicate that split is
+complete for both old and new buckets. A split operation which requires
+overflow pages to complete the operation will need to write a WAL record for
+each new allocation of an overflow page.
+
+As splitting involves multiple atomic actions, it's possible that the system
+crashes between moving tuples from bucket pages of the old bucket to new
+bucket. In such a case, after recovery, the old and new buckets will be
+marked with bucket-being-split and bucket-being-populated flags respectively
+which indicates that split is in progress for those buckets. The reader
+algorithm works correctly, as it will scan both the old and new buckets when
+the split is in progress as explained in the reader algorithm section above.
+
+We finish the split at next insert or split operation on the old bucket as
+explained in insert and split algorithm above. It could be done during
+searches, too, but it seems best not to put any extra updates in what would
+otherwise be a read-only operation (updating is not possible in hot standby
+mode anyway). It would seem natural to complete the split in VACUUM, but since
+splitting a bucket might require allocating a new page, it might fail if you
+run out of disk space. That would be bad during VACUUM - the reason for
+running VACUUM in the first place might be that you run out of disk space,
+and now VACUUM won't finish because you're out of disk space. In contrast,
+an insertion can require enlarging the physical file anyway.
+
+Deletion of tuples from a bucket is performed for two reasons: to remove dead
+tuples, and to remove tuples that were moved by a bucket split. A WAL entry
+is made for each bucket page from which tuples are removed, and then another
+WAL entry is made when we clear the needs-split-cleanup flag. If dead tuples
+are removed, a separate WAL entry is made to update the metapage.
+
+As deletion involves multiple atomic operations, it is quite possible that
+system crashes after (a) removing tuples from some of the bucket pages, (b)
+before clearing the garbage flag, or (c) before updating the metapage. If the
+system crashes before completing (b), it will again try to clean the bucket
+during next vacuum or insert after recovery which can have some performance
+impact, but it will work fine. If the system crashes before completing (c),
+after recovery there could be some additional splits until the next vacuum
+updates the metapage, but the other operations like insert, delete and scan
+will work correctly. We can fix this problem by actually updating the
+metapage based on delete operation during replay, but it's not clear whether
+it's worth the complication.
+
+A squeeze operation moves tuples from one of the buckets later in the chain to
+one of the bucket earlier in chain and writes WAL record when either the
+bucket to which it is writing tuples is filled or bucket from which it
+is removing the tuples becomes empty.
+
+As a squeeze operation involves writing multiple atomic operations, it is
+quite possible that the system crashes before completing the operation on
+entire bucket. After recovery, the operations will work correctly, but
+the index will remain bloated and this can impact performance of read and
+insert operations until the next vacuum squeeze the bucket completely.
Other Notes
-----------
-All the shenanigans with locking prevent a split occurring while *another*
-process is stopped in a given bucket. They do not ensure that one of
-our *own* backend's scans is not stopped in the bucket, because lmgr
-doesn't consider a process's own locks to conflict. So the Split
-algorithm must check for that case separately before deciding it can go
-ahead with the split. VACUUM does not have this problem since nothing
-else can be happening within the vacuuming backend.
-
-Should we instead try to fix the state of any conflicting local scan?
-Seems mighty ugly --- got to move the held bucket S-lock as well as lots
-of other messiness. For now, just punt and don't split.
+Clean up locks prevent a split from occurring while *another* process is stopped
+in a given bucket. It also ensures that one of our *own* backend's scans is not
+stopped in the bucket.
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 07496f8156..8a3297924f 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -3,7 +3,7 @@
* hash.c
* Implementation of Margo Seltzer's Hashing package for postgres.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -19,13 +19,16 @@
#include "postgres.h"
#include "access/hash.h"
+#include "access/hash_xlog.h"
#include "access/relscan.h"
#include "catalog/index.h"
#include "commands/vacuum.h"
#include "miscadmin.h"
#include "optimizer/plancat.h"
+#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
#include "utils/rel.h"
+#include "miscadmin.h"
/* Working state for hashbuild and its callback */
@@ -33,6 +36,7 @@ typedef struct
{
HSpool *spool; /* NULL if not using spooling */
double indtuples; /* # tuples accepted into index */
+ Relation heapRel; /* heap relation descriptor */
} HashBuildState;
static void hashbuildCallback(Relation index,
@@ -65,6 +69,7 @@ hashhandler(PG_FUNCTION_ARGS)
amroutine->amstorage = false;
amroutine->amclusterable = false;
amroutine->ampredlocks = false;
+ amroutine->amcanparallel = false;
amroutine->amkeytype = INT4OID;
amroutine->ambuild = hashbuild;
@@ -84,6 +89,9 @@ hashhandler(PG_FUNCTION_ARGS)
amroutine->amendscan = hashendscan;
amroutine->ammarkpos = NULL;
amroutine->amrestrpos = NULL;
+ amroutine->amestimateparallelscan = NULL;
+ amroutine->aminitparallelscan = NULL;
+ amroutine->amparallelrescan = NULL;
PG_RETURN_POINTER(amroutine);
}
@@ -114,7 +122,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
estimate_rel_size(heap, NULL, &relpages, &reltuples, &allvisfrac);
/* Initialize the hash index metadata page and initial buckets */
- num_buckets = _hash_metapinit(index, reltuples, MAIN_FORKNUM);
+ num_buckets = _hash_init(index, reltuples, MAIN_FORKNUM);
/*
* If we just insert the tuples into the index in scan order, then
@@ -147,6 +155,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
/* prepare to build the index */
buildstate.indtuples = 0;
+ buildstate.heapRel = heap;
/* do the heap scan */
reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
@@ -155,7 +164,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
if (buildstate.spool)
{
/* sort the tuples and insert them into the index */
- _h_indexbuild(buildstate.spool);
+ _h_indexbuild(buildstate.spool, buildstate.heapRel);
_h_spooldestroy(buildstate.spool);
}
@@ -176,7 +185,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
void
hashbuildempty(Relation index)
{
- _hash_metapinit(index, 0, INIT_FORKNUM);
+ _hash_init(index, 0, INIT_FORKNUM);
}
/*
@@ -211,7 +220,7 @@ hashbuildCallback(Relation index,
itup = index_form_tuple(RelationGetDescr(index),
index_values, index_isnull);
itup->t_tid = htup->t_self;
- _hash_doinsert(index, itup);
+ _hash_doinsert(index, itup, buildstate->heapRel);
pfree(itup);
}
@@ -227,7 +236,8 @@ hashbuildCallback(Relation index,
bool
hashinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
Datum index_values[1];
bool index_isnull[1];
@@ -243,7 +253,7 @@ hashinsert(Relation rel, Datum *values, bool *isnull,
itup = index_form_tuple(RelationGetDescr(rel), index_values, index_isnull);
itup->t_tid = *ht_ctid;
- _hash_doinsert(rel, itup);
+ _hash_doinsert(rel, itup, heapRel);
pfree(itup);
@@ -273,7 +283,7 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir)
* Reacquire the read lock here.
*/
if (BufferIsValid(so->hashso_curbuf))
- _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ);
+ LockBuffer(so->hashso_curbuf, BUFFER_LOCK_SHARE);
/*
* If we've already initialized this scan, we can just advance it in the
@@ -286,16 +296,21 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir)
/*
* An insertion into the current index page could have happened while
* we didn't have read lock on it. Re-find our position by looking
- * for the TID we previously returned. (Because we hold share lock on
- * the bucket, no deletions or splits could have occurred; therefore
- * we can expect that the TID still exists in the current index page,
- * at an offset >= where we were.)
+ * for the TID we previously returned. (Because we hold a pin on the
+ * primary bucket page, no deletions or splits could have occurred;
+ * therefore we can expect that the TID still exists in the current
+ * index page, at an offset >= where we were.)
*/
OffsetNumber maxoffnum;
buf = so->hashso_curbuf;
Assert(BufferIsValid(buf));
page = BufferGetPage(buf);
+
+ /*
+ * We don't need test for old snapshot here as the current buffer is
+ * pinned, so vacuum can't clean the page.
+ */
maxoffnum = PageGetMaxOffsetNumber(page);
for (offnum = ItemPointerGetOffsetNumber(current);
offnum <= maxoffnum;
@@ -318,14 +333,24 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir)
if (scan->kill_prior_tuple)
{
/*
- * Yes, so mark it by setting the LP_DEAD state in the item flags.
+ * Yes, so remember it for later. (We'll deal with all such tuples
+ * at once right after leaving the index page or at end of scan.)
+ * In case if caller reverses the indexscan direction it is quite
+ * possible that the same item might get entered multiple times.
+ * But, we don't detect that; instead, we just forget any excess
+ * entries.
*/
- ItemIdMarkDead(PageGetItemId(page, offnum));
+ if (so->killedItems == NULL)
+ so->killedItems = palloc(MaxIndexTuplesPerPage *
+ sizeof(HashScanPosItem));
- /*
- * Since this can be redone later if needed, mark as a hint.
- */
- MarkBufferDirtyHint(buf, true);
+ if (so->numKilled < MaxIndexTuplesPerPage)
+ {
+ so->killedItems[so->numKilled].heapTid = so->hashso_heappos;
+ so->killedItems[so->numKilled].indexOffset =
+ ItemPointerGetOffsetNumber(&(so->hashso_curpos));
+ so->numKilled++;
+ }
}
/*
@@ -353,7 +378,7 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir)
/* Release read lock on current buffer, but keep it pinned */
if (BufferIsValid(so->hashso_curbuf))
- _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_READ, HASH_NOLOCK);
+ LockBuffer(so->hashso_curbuf, BUFFER_LOCK_UNLOCK);
/* Return current heap TID on success */
scan->xs_ctup.t_self = so->hashso_heappos;
@@ -423,17 +448,20 @@ hashbeginscan(Relation rel, int nkeys, int norderbys)
scan = RelationGetIndexScan(rel, nkeys, norderbys);
so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData));
- so->hashso_bucket_valid = false;
- so->hashso_bucket_blkno = 0;
so->hashso_curbuf = InvalidBuffer;
+ so->hashso_bucket_buf = InvalidBuffer;
+ so->hashso_split_bucket_buf = InvalidBuffer;
/* set position invalid (this will cause _hash_first call) */
ItemPointerSetInvalid(&(so->hashso_curpos));
ItemPointerSetInvalid(&(so->hashso_heappos));
- scan->opaque = so;
+ so->hashso_buc_populated = false;
+ so->hashso_buc_split = false;
- /* register scan in case we change pages it's using */
- _hash_regscan(scan);
+ so->killedItems = NULL;
+ so->numKilled = 0;
+
+ scan->opaque = so;
return scan;
}
@@ -448,15 +476,18 @@ hashrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
HashScanOpaque so = (HashScanOpaque) scan->opaque;
Relation rel = scan->indexRelation;
- /* release any pin we still hold */
- if (BufferIsValid(so->hashso_curbuf))
- _hash_dropbuf(rel, so->hashso_curbuf);
- so->hashso_curbuf = InvalidBuffer;
+ /*
+ * Before leaving current page, deal with any killed items. Also, ensure
+ * that we acquire lock on current page before calling _hash_kill_items.
+ */
+ if (so->numKilled > 0)
+ {
+ LockBuffer(so->hashso_curbuf, BUFFER_LOCK_SHARE);
+ _hash_kill_items(scan);
+ LockBuffer(so->hashso_curbuf, BUFFER_LOCK_UNLOCK);
+ }
- /* release lock on bucket, too */
- if (so->hashso_bucket_blkno)
- _hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE);
- so->hashso_bucket_blkno = 0;
+ _hash_dropscanbuf(rel, so);
/* set position invalid (this will cause _hash_first call) */
ItemPointerSetInvalid(&(so->hashso_curpos));
@@ -468,8 +499,10 @@ hashrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
memmove(scan->keyData,
scankey,
scan->numberOfKeys * sizeof(ScanKeyData));
- so->hashso_bucket_valid = false;
}
+
+ so->hashso_buc_populated = false;
+ so->hashso_buc_split = false;
}
/*
@@ -481,19 +514,21 @@ hashendscan(IndexScanDesc scan)
HashScanOpaque so = (HashScanOpaque) scan->opaque;
Relation rel = scan->indexRelation;
- /* don't need scan registered anymore */
- _hash_dropscan(scan);
-
- /* release any pin we still hold */
- if (BufferIsValid(so->hashso_curbuf))
- _hash_dropbuf(rel, so->hashso_curbuf);
- so->hashso_curbuf = InvalidBuffer;
+ /*
+ * Before leaving current page, deal with any killed items. Also, ensure
+ * that we acquire lock on current page before calling _hash_kill_items.
+ */
+ if (so->numKilled > 0)
+ {
+ LockBuffer(so->hashso_curbuf, BUFFER_LOCK_SHARE);
+ _hash_kill_items(scan);
+ LockBuffer(so->hashso_curbuf, BUFFER_LOCK_UNLOCK);
+ }
- /* release lock on bucket, too */
- if (so->hashso_bucket_blkno)
- _hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE);
- so->hashso_bucket_blkno = 0;
+ _hash_dropscanbuf(rel, so);
+ if (so->killedItems != NULL)
+ pfree(so->killedItems);
pfree(so);
scan->opaque = NULL;
}
@@ -503,6 +538,9 @@ hashendscan(IndexScanDesc scan)
* The set of target tuples is specified via a callback routine that tells
* whether any given heap tuple (identified by ItemPointer) is being deleted.
*
+ * This function also deletes the tuples that are moved by split to other
+ * bucket.
+ *
* Result: a palloc'd struct containing statistical info for VACUUM displays.
*/
IndexBulkDeleteResult *
@@ -516,27 +554,24 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
Bucket orig_maxbucket;
Bucket cur_maxbucket;
Bucket cur_bucket;
- Buffer metabuf;
+ Buffer metabuf = InvalidBuffer;
HashMetaPage metap;
- HashMetaPageData local_metapage;
+ HashMetaPage cachedmetap;
tuples_removed = 0;
num_index_tuples = 0;
/*
- * Read the metapage to fetch original bucket and tuple counts. Also, we
- * keep a copy of the last-seen metapage so that we can use its
- * hashm_spares[] values to compute bucket page addresses. This is a bit
- * hokey but perfectly safe, since the interesting entries in the spares
- * array cannot change under us; and it beats rereading the metapage for
- * each bucket.
+ * We need a copy of the metapage so that we can use its hashm_spares[]
+ * values to compute bucket page addresses, but a cached copy should be
+ * good enough. (If not, we'll detect that further down and refresh the
+ * cache as necessary.)
*/
- metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
- metap = HashPageGetMeta(BufferGetPage(metabuf));
- orig_maxbucket = metap->hashm_maxbucket;
- orig_ntuples = metap->hashm_ntuples;
- memcpy(&local_metapage, metap, sizeof(local_metapage));
- _hash_relbuf(rel, metabuf);
+ cachedmetap = _hash_getcachedmetap(rel, &metabuf, false);
+ Assert(cachedmetap != NULL);
+
+ orig_maxbucket = cachedmetap->hashm_maxbucket;
+ orig_ntuples = cachedmetap->hashm_ntuples;
/* Scan the buckets that we know exist */
cur_bucket = 0;
@@ -547,102 +582,89 @@ loop_top:
{
BlockNumber bucket_blkno;
BlockNumber blkno;
- bool bucket_dirty = false;
+ Buffer bucket_buf;
+ Buffer buf;
+ HashPageOpaque bucket_opaque;
+ Page page;
+ bool split_cleanup = false;
/* Get address of bucket's start page */
- bucket_blkno = BUCKET_TO_BLKNO(&local_metapage, cur_bucket);
+ bucket_blkno = BUCKET_TO_BLKNO(cachedmetap, cur_bucket);
- /* Exclusive-lock the bucket so we can shrink it */
- _hash_getlock(rel, bucket_blkno, HASH_EXCLUSIVE);
+ blkno = bucket_blkno;
- /* Shouldn't have any active scans locally, either */
- if (_hash_has_active_scan(rel, cur_bucket))
- elog(ERROR, "hash index has active scan during VACUUM");
+ /*
+ * We need to acquire a cleanup lock on the primary bucket page to out
+ * wait concurrent scans before deleting the dead tuples.
+ */
+ buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, info->strategy);
+ LockBufferForCleanup(buf);
+ _hash_checkpage(rel, buf, LH_BUCKET_PAGE);
- /* Scan each page in bucket */
- blkno = bucket_blkno;
- while (BlockNumberIsValid(blkno))
- {
- Buffer buf;
- Page page;
- HashPageOpaque opaque;
- OffsetNumber offno;
- OffsetNumber maxoffno;
- OffsetNumber deletable[MaxOffsetNumber];
- int ndeletable = 0;
-
- vacuum_delay_point();
-
- buf = _hash_getbuf_with_strategy(rel, blkno, HASH_WRITE,
- LH_BUCKET_PAGE | LH_OVERFLOW_PAGE,
- info->strategy);
- page = BufferGetPage(buf);
- opaque = (HashPageOpaque) PageGetSpecialPointer(page);
- Assert(opaque->hasho_bucket == cur_bucket);
-
- /* Scan each tuple in page */
- maxoffno = PageGetMaxOffsetNumber(page);
- for (offno = FirstOffsetNumber;
- offno <= maxoffno;
- offno = OffsetNumberNext(offno))
- {
- IndexTuple itup;
- ItemPointer htup;
+ page = BufferGetPage(buf);
+ bucket_opaque = (HashPageOpaque) PageGetSpecialPointer(page);
- itup = (IndexTuple) PageGetItem(page,
- PageGetItemId(page, offno));
- htup = &(itup->t_tid);
- if (callback(htup, callback_state))
- {
- /* mark the item for deletion */
- deletable[ndeletable++] = offno;
- tuples_removed += 1;
- }
- else
- num_index_tuples += 1;
- }
+ /*
+ * If the bucket contains tuples that are moved by split, then we need
+ * to delete such tuples. We can't delete such tuples if the split
+ * operation on bucket is not finished as those are needed by scans.
+ */
+ if (!H_BUCKET_BEING_SPLIT(bucket_opaque) &&
+ H_NEEDS_SPLIT_CLEANUP(bucket_opaque))
+ {
+ split_cleanup = true;
/*
- * Apply deletions and write page if needed, advance to next page.
+ * This bucket might have been split since we last held a lock on
+ * the metapage. If so, hashm_maxbucket, hashm_highmask and
+ * hashm_lowmask might be old enough to cause us to fail to remove
+ * tuples left behind by the most recent split. To prevent that,
+ * now that the primary page of the target bucket has been locked
+ * (and thus can't be further split), check whether we need to
+ * update our cached metapage data.
*/
- blkno = opaque->hasho_nextblkno;
-
- if (ndeletable > 0)
+ Assert(bucket_opaque->hasho_prevblkno != InvalidBlockNumber);
+ if (bucket_opaque->hasho_prevblkno > cachedmetap->hashm_maxbucket)
{
- PageIndexMultiDelete(page, deletable, ndeletable);
- _hash_wrtbuf(rel, buf);
- bucket_dirty = true;
+ cachedmetap = _hash_getcachedmetap(rel, &metabuf, true);
+ Assert(cachedmetap != NULL);
}
- else
- _hash_relbuf(rel, buf);
}
- /* If we deleted anything, try to compact free space */
- if (bucket_dirty)
- _hash_squeezebucket(rel, cur_bucket, bucket_blkno,
- info->strategy);
+ bucket_buf = buf;
+
+ hashbucketcleanup(rel, cur_bucket, bucket_buf, blkno, info->strategy,
+ cachedmetap->hashm_maxbucket,
+ cachedmetap->hashm_highmask,
+ cachedmetap->hashm_lowmask, &tuples_removed,
+ &num_index_tuples, split_cleanup,
+ callback, callback_state);
- /* Release bucket lock */
- _hash_droplock(rel, bucket_blkno, HASH_EXCLUSIVE);
+ _hash_dropbuf(rel, bucket_buf);
/* Advance to next bucket */
cur_bucket++;
}
+ if (BufferIsInvalid(metabuf))
+ metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_NOLOCK, LH_META_PAGE);
+
/* Write-lock metapage and check for split since we started */
- metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE, LH_META_PAGE);
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
metap = HashPageGetMeta(BufferGetPage(metabuf));
if (cur_maxbucket != metap->hashm_maxbucket)
{
/* There's been a split, so process the additional bucket(s) */
- cur_maxbucket = metap->hashm_maxbucket;
- memcpy(&local_metapage, metap, sizeof(local_metapage));
- _hash_relbuf(rel, metabuf);
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+ cachedmetap = _hash_getcachedmetap(rel, &metabuf, true);
+ Assert(cachedmetap != NULL);
+ cur_maxbucket = cachedmetap->hashm_maxbucket;
goto loop_top;
}
/* Okay, we're really done. Update tuple count in metapage. */
+ START_CRIT_SECTION();
if (orig_maxbucket == metap->hashm_maxbucket &&
orig_ntuples == metap->hashm_ntuples)
@@ -668,7 +690,28 @@ loop_top:
num_index_tuples = metap->hashm_ntuples;
}
- _hash_wrtbuf(rel, metabuf);
+ MarkBufferDirty(metabuf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_update_meta_page xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.ntuples = metap->hashm_ntuples;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashUpdateMetaPage);
+
+ XLogRegisterBuffer(0, metabuf, REGBUF_STANDARD);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_UPDATE_META_PAGE);
+ PageSetLSN(BufferGetPage(metabuf), recptr);
+ }
+
+ END_CRIT_SECTION();
+
+ _hash_relbuf(rel, metabuf);
/* return statistics */
if (stats == NULL)
@@ -704,9 +747,262 @@ hashvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
return stats;
}
-
+/*
+ * Helper function to perform deletion of index entries from a bucket.
+ *
+ * This function expects that the caller has acquired a cleanup lock on the
+ * primary bucket page, and will return with a write lock again held on the
+ * primary bucket page. The lock won't necessarily be held continuously,
+ * though, because we'll release it when visiting overflow pages.
+ *
+ * It would be very bad if this function cleaned a page while some other
+ * backend was in the midst of scanning it, because hashgettuple assumes
+ * that the next valid TID will be greater than or equal to the current
+ * valid TID. There can't be any concurrent scans in progress when we first
+ * enter this function because of the cleanup lock we hold on the primary
+ * bucket page, but as soon as we release that lock, there might be. We
+ * handle that by conspiring to prevent those scans from passing our cleanup
+ * scan. To do that, we lock the next page in the bucket chain before
+ * releasing the lock on the previous page. (This type of lock chaining is
+ * not ideal, so we might want to look for a better solution at some point.)
+ *
+ * We need to retain a pin on the primary bucket to ensure that no concurrent
+ * split can start.
+ */
void
-hash_redo(XLogReaderState *record)
+hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf,
+ BlockNumber bucket_blkno, BufferAccessStrategy bstrategy,
+ uint32 maxbucket, uint32 highmask, uint32 lowmask,
+ double *tuples_removed, double *num_index_tuples,
+ bool split_cleanup,
+ IndexBulkDeleteCallback callback, void *callback_state)
{
- elog(PANIC, "hash_redo: unimplemented");
+ BlockNumber blkno;
+ Buffer buf;
+ Bucket new_bucket PG_USED_FOR_ASSERTS_ONLY = InvalidBucket;
+ bool bucket_dirty = false;
+
+ blkno = bucket_blkno;
+ buf = bucket_buf;
+
+ if (split_cleanup)
+ new_bucket = _hash_get_newbucket_from_oldbucket(rel, cur_bucket,
+ lowmask, maxbucket);
+
+ /* Scan each page in bucket */
+ for (;;)
+ {
+ HashPageOpaque opaque;
+ OffsetNumber offno;
+ OffsetNumber maxoffno;
+ Buffer next_buf;
+ Page page;
+ OffsetNumber deletable[MaxOffsetNumber];
+ int ndeletable = 0;
+ bool retain_pin = false;
+ bool clear_dead_marking = false;
+
+ vacuum_delay_point();
+
+ page = BufferGetPage(buf);
+ opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+
+ /* Scan each tuple in page */
+ maxoffno = PageGetMaxOffsetNumber(page);
+ for (offno = FirstOffsetNumber;
+ offno <= maxoffno;
+ offno = OffsetNumberNext(offno))
+ {
+ ItemPointer htup;
+ IndexTuple itup;
+ Bucket bucket;
+ bool kill_tuple = false;
+
+ itup = (IndexTuple) PageGetItem(page,
+ PageGetItemId(page, offno));
+ htup = &(itup->t_tid);
+
+ /*
+ * To remove the dead tuples, we strictly want to rely on results
+ * of callback function. refer btvacuumpage for detailed reason.
+ */
+ if (callback && callback(htup, callback_state))
+ {
+ kill_tuple = true;
+ if (tuples_removed)
+ *tuples_removed += 1;
+ }
+ else if (split_cleanup)
+ {
+ /* delete the tuples that are moved by split. */
+ bucket = _hash_hashkey2bucket(_hash_get_indextuple_hashkey(itup),
+ maxbucket,
+ highmask,
+ lowmask);
+ /* mark the item for deletion */
+ if (bucket != cur_bucket)
+ {
+ /*
+ * We expect tuples to either belong to current bucket or
+ * new_bucket. This is ensured because we don't allow
+ * further splits from bucket that contains garbage. See
+ * comments in _hash_expandtable.
+ */
+ Assert(bucket == new_bucket);
+ kill_tuple = true;
+ }
+ }
+
+ if (kill_tuple)
+ {
+ /* mark the item for deletion */
+ deletable[ndeletable++] = offno;
+ }
+ else
+ {
+ /* we're keeping it, so count it */
+ if (num_index_tuples)
+ *num_index_tuples += 1;
+ }
+ }
+
+ /* retain the pin on primary bucket page till end of bucket scan */
+ if (blkno == bucket_blkno)
+ retain_pin = true;
+ else
+ retain_pin = false;
+
+ blkno = opaque->hasho_nextblkno;
+
+ /*
+ * Apply deletions, advance to next page and write page if needed.
+ */
+ if (ndeletable > 0)
+ {
+ /* No ereport(ERROR) until changes are logged */
+ START_CRIT_SECTION();
+
+ PageIndexMultiDelete(page, deletable, ndeletable);
+ bucket_dirty = true;
+
+ /*
+ * Let us mark the page as clean if vacuum removes the DEAD tuples
+ * from an index page. We do this by clearing
+ * LH_PAGE_HAS_DEAD_TUPLES flag.
+ */
+ if (tuples_removed && *tuples_removed > 0 &&
+ H_HAS_DEAD_TUPLES(opaque))
+ {
+ opaque->hasho_flag &= ~LH_PAGE_HAS_DEAD_TUPLES;
+ clear_dead_marking = true;
+ }
+
+ MarkBufferDirty(buf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_delete xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.clear_dead_marking = clear_dead_marking;
+ xlrec.is_primary_bucket_page = (buf == bucket_buf) ? true : false;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashDelete);
+
+ /*
+ * bucket buffer needs to be registered to ensure that we can
+ * acquire a cleanup lock on it during replay.
+ */
+ if (!xlrec.is_primary_bucket_page)
+ XLogRegisterBuffer(0, bucket_buf, REGBUF_STANDARD | REGBUF_NO_IMAGE);
+
+ XLogRegisterBuffer(1, buf, REGBUF_STANDARD);
+ XLogRegisterBufData(1, (char *) deletable,
+ ndeletable * sizeof(OffsetNumber));
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_DELETE);
+ PageSetLSN(BufferGetPage(buf), recptr);
+ }
+
+ END_CRIT_SECTION();
+ }
+
+ /* bail out if there are no more pages to scan. */
+ if (!BlockNumberIsValid(blkno))
+ break;
+
+ next_buf = _hash_getbuf_with_strategy(rel, blkno, HASH_WRITE,
+ LH_OVERFLOW_PAGE,
+ bstrategy);
+
+ /*
+ * release the lock on previous page after acquiring the lock on next
+ * page
+ */
+ if (retain_pin)
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+ else
+ _hash_relbuf(rel, buf);
+
+ buf = next_buf;
+ }
+
+ /*
+ * lock the bucket page to clear the garbage flag and squeeze the bucket.
+ * if the current buffer is same as bucket buffer, then we already have
+ * lock on bucket page.
+ */
+ if (buf != bucket_buf)
+ {
+ _hash_relbuf(rel, buf);
+ LockBuffer(bucket_buf, BUFFER_LOCK_EXCLUSIVE);
+ }
+
+ /*
+ * Clear the garbage flag from bucket after deleting the tuples that are
+ * moved by split. We purposefully clear the flag before squeeze bucket,
+ * so that after restart, vacuum shouldn't again try to delete the moved
+ * by split tuples.
+ */
+ if (split_cleanup)
+ {
+ HashPageOpaque bucket_opaque;
+ Page page;
+
+ page = BufferGetPage(bucket_buf);
+ bucket_opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+
+ /* No ereport(ERROR) until changes are logged */
+ START_CRIT_SECTION();
+
+ bucket_opaque->hasho_flag &= ~LH_BUCKET_NEEDS_SPLIT_CLEANUP;
+ MarkBufferDirty(bucket_buf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ XLogRecPtr recptr;
+
+ XLogBeginInsert();
+ XLogRegisterBuffer(0, bucket_buf, REGBUF_STANDARD);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SPLIT_CLEANUP);
+ PageSetLSN(page, recptr);
+ }
+
+ END_CRIT_SECTION();
+ }
+
+ /*
+ * If we have deleted anything, try to compact free space. For squeezing
+ * the bucket, we must have a cleanup lock, else it can impact the
+ * ordering of tuples for a scan that has started before it.
+ */
+ if (bucket_dirty && IsBufferCleanupOK(bucket_buf))
+ _hash_squeezebucket(rel, cur_bucket, bucket_blkno, bucket_buf,
+ bstrategy);
+ else
+ LockBuffer(bucket_buf, BUFFER_LOCK_UNLOCK);
}
diff --git a/src/backend/access/hash/hash_xlog.c b/src/backend/access/hash/hash_xlog.c
new file mode 100644
index 0000000000..0ea11b2e74
--- /dev/null
+++ b/src/backend/access/hash/hash_xlog.c
@@ -0,0 +1,1270 @@
+/*-------------------------------------------------------------------------
+ *
+ * hash_xlog.c
+ * WAL replay logic for hash index.
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/access/hash/hash_xlog.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam_xlog.h"
+#include "access/bufmask.h"
+#include "access/hash.h"
+#include "access/hash_xlog.h"
+#include "access/xlogutils.h"
+#include "access/xlog.h"
+#include "access/transam.h"
+#include "storage/procarray.h"
+#include "miscadmin.h"
+
+/*
+ * replay a hash index meta page
+ */
+static void
+hash_xlog_init_meta_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ Page page;
+ Buffer metabuf;
+
+ xl_hash_init_meta_page *xlrec = (xl_hash_init_meta_page *) XLogRecGetData(record);
+
+ /* create the index' metapage */
+ metabuf = XLogInitBufferForRedo(record, 0);
+ Assert(BufferIsValid(metabuf));
+ _hash_init_metabuffer(metabuf, xlrec->num_tuples, xlrec->procid,
+ xlrec->ffactor, true);
+ page = (Page) BufferGetPage(metabuf);
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(metabuf);
+ /* all done */
+ UnlockReleaseBuffer(metabuf);
+}
+
+/*
+ * replay a hash index bitmap page
+ */
+static void
+hash_xlog_init_bitmap_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ Buffer bitmapbuf;
+ Buffer metabuf;
+ Page page;
+ HashMetaPage metap;
+ uint32 num_buckets;
+
+ xl_hash_init_bitmap_page *xlrec = (xl_hash_init_bitmap_page *) XLogRecGetData(record);
+
+ /*
+ * Initialize bitmap page
+ */
+ bitmapbuf = XLogInitBufferForRedo(record, 0);
+ _hash_initbitmapbuffer(bitmapbuf, xlrec->bmsize, true);
+ PageSetLSN(BufferGetPage(bitmapbuf), lsn);
+ MarkBufferDirty(bitmapbuf);
+ UnlockReleaseBuffer(bitmapbuf);
+
+ /* add the new bitmap page to the metapage's list of bitmaps */
+ if (XLogReadBufferForRedo(record, 1, &metabuf) == BLK_NEEDS_REDO)
+ {
+ /*
+ * Note: in normal operation, we'd update the metapage while still
+ * holding lock on the bitmap page. But during replay it's not
+ * necessary to hold that lock, since nobody can see it yet; the
+ * creating transaction hasn't yet committed.
+ */
+ page = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(page);
+
+ num_buckets = metap->hashm_maxbucket + 1;
+ metap->hashm_mapp[metap->hashm_nmaps] = num_buckets + 1;
+ metap->hashm_nmaps++;
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(metabuf);
+ }
+ if (BufferIsValid(metabuf))
+ UnlockReleaseBuffer(metabuf);
+}
+
+/*
+ * replay a hash index insert without split
+ */
+static void
+hash_xlog_insert(XLogReaderState *record)
+{
+ HashMetaPage metap;
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_insert *xlrec = (xl_hash_insert *) XLogRecGetData(record);
+ Buffer buffer;
+ Page page;
+
+ if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
+ {
+ Size datalen;
+ char *datapos = XLogRecGetBlockData(record, 0, &datalen);
+
+ page = BufferGetPage(buffer);
+
+ if (PageAddItem(page, (Item) datapos, datalen, xlrec->offnum,
+ false, false) == InvalidOffsetNumber)
+ elog(PANIC, "hash_xlog_insert: failed to add item");
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(buffer);
+ }
+ if (BufferIsValid(buffer))
+ UnlockReleaseBuffer(buffer);
+
+ if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
+ {
+ /*
+ * Note: in normal operation, we'd update the metapage while still
+ * holding lock on the page we inserted into. But during replay it's
+ * not necessary to hold that lock, since no other index updates can
+ * be happening concurrently.
+ */
+ page = BufferGetPage(buffer);
+ metap = HashPageGetMeta(page);
+ metap->hashm_ntuples += 1;
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(buffer);
+ }
+ if (BufferIsValid(buffer))
+ UnlockReleaseBuffer(buffer);
+}
+
+/*
+ * replay addition of overflow page for hash index
+ */
+static void
+hash_xlog_add_ovfl_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_add_ovfl_page *xlrec = (xl_hash_add_ovfl_page *) XLogRecGetData(record);
+ Buffer leftbuf;
+ Buffer ovflbuf;
+ Buffer metabuf;
+ BlockNumber leftblk;
+ BlockNumber rightblk;
+ BlockNumber newmapblk = InvalidBlockNumber;
+ Page ovflpage;
+ HashPageOpaque ovflopaque;
+ uint32 *num_bucket;
+ char *data;
+ Size datalen PG_USED_FOR_ASSERTS_ONLY;
+ bool new_bmpage = false;
+
+ XLogRecGetBlockTag(record, 0, NULL, NULL, &rightblk);
+ XLogRecGetBlockTag(record, 1, NULL, NULL, &leftblk);
+
+ ovflbuf = XLogInitBufferForRedo(record, 0);
+ Assert(BufferIsValid(ovflbuf));
+
+ data = XLogRecGetBlockData(record, 0, &datalen);
+ num_bucket = (uint32 *) data;
+ Assert(datalen == sizeof(uint32));
+ _hash_initbuf(ovflbuf, InvalidBlockNumber, *num_bucket, LH_OVERFLOW_PAGE,
+ true);
+ /* update backlink */
+ ovflpage = BufferGetPage(ovflbuf);
+ ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
+ ovflopaque->hasho_prevblkno = leftblk;
+
+ PageSetLSN(ovflpage, lsn);
+ MarkBufferDirty(ovflbuf);
+
+ if (XLogReadBufferForRedo(record, 1, &leftbuf) == BLK_NEEDS_REDO)
+ {
+ Page leftpage;
+ HashPageOpaque leftopaque;
+
+ leftpage = BufferGetPage(leftbuf);
+ leftopaque = (HashPageOpaque) PageGetSpecialPointer(leftpage);
+ leftopaque->hasho_nextblkno = rightblk;
+
+ PageSetLSN(leftpage, lsn);
+ MarkBufferDirty(leftbuf);
+ }
+
+ if (BufferIsValid(leftbuf))
+ UnlockReleaseBuffer(leftbuf);
+ UnlockReleaseBuffer(ovflbuf);
+
+ /*
+ * Note: in normal operation, we'd update the bitmap and meta page while
+ * still holding lock on the overflow pages. But during replay it's not
+ * necessary to hold those locks, since no other index updates can be
+ * happening concurrently.
+ */
+ if (XLogRecHasBlockRef(record, 2))
+ {
+ Buffer mapbuffer;
+
+ if (XLogReadBufferForRedo(record, 2, &mapbuffer) == BLK_NEEDS_REDO)
+ {
+ Page mappage = (Page) BufferGetPage(mapbuffer);
+ uint32 *freep = NULL;
+ char *data;
+ uint32 *bitmap_page_bit;
+
+ freep = HashPageGetBitmap(mappage);
+
+ data = XLogRecGetBlockData(record, 2, &datalen);
+ bitmap_page_bit = (uint32 *) data;
+
+ SETBIT(freep, *bitmap_page_bit);
+
+ PageSetLSN(mappage, lsn);
+ MarkBufferDirty(mapbuffer);
+ }
+ if (BufferIsValid(mapbuffer))
+ UnlockReleaseBuffer(mapbuffer);
+ }
+
+ if (XLogRecHasBlockRef(record, 3))
+ {
+ Buffer newmapbuf;
+
+ newmapbuf = XLogInitBufferForRedo(record, 3);
+
+ _hash_initbitmapbuffer(newmapbuf, xlrec->bmsize, true);
+
+ new_bmpage = true;
+ newmapblk = BufferGetBlockNumber(newmapbuf);
+
+ MarkBufferDirty(newmapbuf);
+ PageSetLSN(BufferGetPage(newmapbuf), lsn);
+
+ UnlockReleaseBuffer(newmapbuf);
+ }
+
+ if (XLogReadBufferForRedo(record, 4, &metabuf) == BLK_NEEDS_REDO)
+ {
+ HashMetaPage metap;
+ Page page;
+ uint32 *firstfree_ovflpage;
+
+ data = XLogRecGetBlockData(record, 4, &datalen);
+ firstfree_ovflpage = (uint32 *) data;
+
+ page = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(page);
+ metap->hashm_firstfree = *firstfree_ovflpage;
+
+ if (!xlrec->bmpage_found)
+ {
+ metap->hashm_spares[metap->hashm_ovflpoint]++;
+
+ if (new_bmpage)
+ {
+ Assert(BlockNumberIsValid(newmapblk));
+
+ metap->hashm_mapp[metap->hashm_nmaps] = newmapblk;
+ metap->hashm_nmaps++;
+ metap->hashm_spares[metap->hashm_ovflpoint]++;
+ }
+ }
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(metabuf);
+ }
+ if (BufferIsValid(metabuf))
+ UnlockReleaseBuffer(metabuf);
+}
+
+/*
+ * replay allocation of page for split operation
+ */
+static void
+hash_xlog_split_allocate_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_split_allocate_page *xlrec = (xl_hash_split_allocate_page *) XLogRecGetData(record);
+ Buffer oldbuf;
+ Buffer newbuf;
+ Buffer metabuf;
+ Size datalen PG_USED_FOR_ASSERTS_ONLY;
+ char *data;
+ XLogRedoAction action;
+
+ /*
+ * To be consistent with normal operation, here we take cleanup locks on
+ * both the old and new buckets even though there can't be any concurrent
+ * inserts.
+ */
+
+ /* replay the record for old bucket */
+ action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &oldbuf);
+
+ /*
+ * Note that we still update the page even if it was restored from a full
+ * page image, because the special space is not included in the image.
+ */
+ if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
+ {
+ Page oldpage;
+ HashPageOpaque oldopaque;
+
+ oldpage = BufferGetPage(oldbuf);
+ oldopaque = (HashPageOpaque) PageGetSpecialPointer(oldpage);
+
+ oldopaque->hasho_flag = xlrec->old_bucket_flag;
+ oldopaque->hasho_prevblkno = xlrec->new_bucket;
+
+ PageSetLSN(oldpage, lsn);
+ MarkBufferDirty(oldbuf);
+ }
+
+ /* replay the record for new bucket */
+ newbuf = XLogInitBufferForRedo(record, 1);
+ _hash_initbuf(newbuf, xlrec->new_bucket, xlrec->new_bucket,
+ xlrec->new_bucket_flag, true);
+ if (!IsBufferCleanupOK(newbuf))
+ elog(PANIC, "hash_xlog_split_allocate_page: failed to acquire cleanup lock");
+ MarkBufferDirty(newbuf);
+ PageSetLSN(BufferGetPage(newbuf), lsn);
+
+ /*
+ * We can release the lock on old bucket early as well but doing here to
+ * consistent with normal operation.
+ */
+ if (BufferIsValid(oldbuf))
+ UnlockReleaseBuffer(oldbuf);
+ if (BufferIsValid(newbuf))
+ UnlockReleaseBuffer(newbuf);
+
+ /*
+ * Note: in normal operation, we'd update the meta page while still
+ * holding lock on the old and new bucket pages. But during replay it's
+ * not necessary to hold those locks, since no other bucket splits can be
+ * happening concurrently.
+ */
+
+ /* replay the record for metapage changes */
+ if (XLogReadBufferForRedo(record, 2, &metabuf) == BLK_NEEDS_REDO)
+ {
+ Page page;
+ HashMetaPage metap;
+
+ page = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(page);
+ metap->hashm_maxbucket = xlrec->new_bucket;
+
+ data = XLogRecGetBlockData(record, 2, &datalen);
+
+ if (xlrec->flags & XLH_SPLIT_META_UPDATE_MASKS)
+ {
+ uint32 lowmask;
+ uint32 *highmask;
+
+ /* extract low and high masks. */
+ memcpy(&lowmask, data, sizeof(uint32));
+ highmask = (uint32 *) ((char *) data + sizeof(uint32));
+
+ /* update metapage */
+ metap->hashm_lowmask = lowmask;
+ metap->hashm_highmask = *highmask;
+
+ data += sizeof(uint32) * 2;
+ }
+
+ if (xlrec->flags & XLH_SPLIT_META_UPDATE_SPLITPOINT)
+ {
+ uint32 ovflpoint;
+ uint32 *ovflpages;
+
+ /* extract information of overflow pages. */
+ memcpy(&ovflpoint, data, sizeof(uint32));
+ ovflpages = (uint32 *) ((char *) data + sizeof(uint32));
+
+ /* update metapage */
+ metap->hashm_spares[ovflpoint] = *ovflpages;
+ metap->hashm_ovflpoint = ovflpoint;
+ }
+
+ MarkBufferDirty(metabuf);
+ PageSetLSN(BufferGetPage(metabuf), lsn);
+ }
+
+ if (BufferIsValid(metabuf))
+ UnlockReleaseBuffer(metabuf);
+}
+
+/*
+ * replay of split operation
+ */
+static void
+hash_xlog_split_page(XLogReaderState *record)
+{
+ Buffer buf;
+
+ if (XLogReadBufferForRedo(record, 0, &buf) != BLK_RESTORED)
+ elog(ERROR, "Hash split record did not contain a full-page image");
+
+ UnlockReleaseBuffer(buf);
+}
+
+/*
+ * replay completion of split operation
+ */
+static void
+hash_xlog_split_complete(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_split_complete *xlrec = (xl_hash_split_complete *) XLogRecGetData(record);
+ Buffer oldbuf;
+ Buffer newbuf;
+ XLogRedoAction action;
+
+ /* replay the record for old bucket */
+ action = XLogReadBufferForRedo(record, 0, &oldbuf);
+
+ /*
+ * Note that we still update the page even if it was restored from a full
+ * page image, because the bucket flag is not included in the image.
+ */
+ if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
+ {
+ Page oldpage;
+ HashPageOpaque oldopaque;
+
+ oldpage = BufferGetPage(oldbuf);
+ oldopaque = (HashPageOpaque) PageGetSpecialPointer(oldpage);
+
+ oldopaque->hasho_flag = xlrec->old_bucket_flag;
+
+ PageSetLSN(oldpage, lsn);
+ MarkBufferDirty(oldbuf);
+ }
+ if (BufferIsValid(oldbuf))
+ UnlockReleaseBuffer(oldbuf);
+
+ /* replay the record for new bucket */
+ action = XLogReadBufferForRedo(record, 1, &newbuf);
+
+ /*
+ * Note that we still update the page even if it was restored from a full
+ * page image, because the bucket flag is not included in the image.
+ */
+ if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
+ {
+ Page newpage;
+ HashPageOpaque nopaque;
+
+ newpage = BufferGetPage(newbuf);
+ nopaque = (HashPageOpaque) PageGetSpecialPointer(newpage);
+
+ nopaque->hasho_flag = xlrec->new_bucket_flag;
+
+ PageSetLSN(newpage, lsn);
+ MarkBufferDirty(newbuf);
+ }
+ if (BufferIsValid(newbuf))
+ UnlockReleaseBuffer(newbuf);
+}
+
+/*
+ * replay move of page contents for squeeze operation of hash index
+ */
+static void
+hash_xlog_move_page_contents(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_move_page_contents *xldata = (xl_hash_move_page_contents *) XLogRecGetData(record);
+ Buffer bucketbuf = InvalidBuffer;
+ Buffer writebuf = InvalidBuffer;
+ Buffer deletebuf = InvalidBuffer;
+ XLogRedoAction action;
+
+ /*
+ * Ensure we have a cleanup lock on primary bucket page before we start
+ * with the actual replay operation. This is to ensure that neither a
+ * scan can start nor a scan can be already-in-progress during the replay
+ * of this operation. If we allow scans during this operation, then they
+ * can miss some records or show the same record multiple times.
+ */
+ if (xldata->is_prim_bucket_same_wrt)
+ action = XLogReadBufferForRedoExtended(record, 1, RBM_NORMAL, true, &writebuf);
+ else
+ {
+ /*
+ * we don't care for return value as the purpose of reading bucketbuf
+ * is to ensure a cleanup lock on primary bucket page.
+ */
+ (void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf);
+
+ action = XLogReadBufferForRedo(record, 1, &writebuf);
+ }
+
+ /* replay the record for adding entries in overflow buffer */
+ if (action == BLK_NEEDS_REDO)
+ {
+ Page writepage;
+ char *begin;
+ char *data;
+ Size datalen;
+ uint16 ninserted = 0;
+
+ data = begin = XLogRecGetBlockData(record, 1, &datalen);
+
+ writepage = (Page) BufferGetPage(writebuf);
+
+ if (xldata->ntups > 0)
+ {
+ OffsetNumber *towrite = (OffsetNumber *) data;
+
+ data += sizeof(OffsetNumber) * xldata->ntups;
+
+ while (data - begin < datalen)
+ {
+ IndexTuple itup = (IndexTuple) data;
+ Size itemsz;
+ OffsetNumber l;
+
+ itemsz = IndexTupleDSize(*itup);
+ itemsz = MAXALIGN(itemsz);
+
+ data += itemsz;
+
+ l = PageAddItem(writepage, (Item) itup, itemsz, towrite[ninserted], false, false);
+ if (l == InvalidOffsetNumber)
+ elog(ERROR, "hash_xlog_move_page_contents: failed to add item to hash index page, size %d bytes",
+ (int) itemsz);
+
+ ninserted++;
+ }
+ }
+
+ /*
+ * number of tuples inserted must be same as requested in REDO record.
+ */
+ Assert(ninserted == xldata->ntups);
+
+ PageSetLSN(writepage, lsn);
+ MarkBufferDirty(writebuf);
+ }
+
+ /* replay the record for deleting entries from overflow buffer */
+ if (XLogReadBufferForRedo(record, 2, &deletebuf) == BLK_NEEDS_REDO)
+ {
+ Page page;
+ char *ptr;
+ Size len;
+
+ ptr = XLogRecGetBlockData(record, 2, &len);
+
+ page = (Page) BufferGetPage(deletebuf);
+
+ if (len > 0)
+ {
+ OffsetNumber *unused;
+ OffsetNumber *unend;
+
+ unused = (OffsetNumber *) ptr;
+ unend = (OffsetNumber *) ((char *) ptr + len);
+
+ if ((unend - unused) > 0)
+ PageIndexMultiDelete(page, unused, unend - unused);
+ }
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(deletebuf);
+ }
+
+ /*
+ * Replay is complete, now we can release the buffers. We release locks at
+ * end of replay operation to ensure that we hold lock on primary bucket
+ * page till end of operation. We can optimize by releasing the lock on
+ * write buffer as soon as the operation for same is complete, if it is
+ * not same as primary bucket page, but that doesn't seem to be worth
+ * complicating the code.
+ */
+ if (BufferIsValid(deletebuf))
+ UnlockReleaseBuffer(deletebuf);
+
+ if (BufferIsValid(writebuf))
+ UnlockReleaseBuffer(writebuf);
+
+ if (BufferIsValid(bucketbuf))
+ UnlockReleaseBuffer(bucketbuf);
+}
+
+/*
+ * replay squeeze page operation of hash index
+ */
+static void
+hash_xlog_squeeze_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_squeeze_page *xldata = (xl_hash_squeeze_page *) XLogRecGetData(record);
+ Buffer bucketbuf = InvalidBuffer;
+ Buffer writebuf;
+ Buffer ovflbuf;
+ Buffer prevbuf = InvalidBuffer;
+ Buffer mapbuf;
+ XLogRedoAction action;
+
+ /*
+ * Ensure we have a cleanup lock on primary bucket page before we start
+ * with the actual replay operation. This is to ensure that neither a
+ * scan can start nor a scan can be already-in-progress during the replay
+ * of this operation. If we allow scans during this operation, then they
+ * can miss some records or show the same record multiple times.
+ */
+ if (xldata->is_prim_bucket_same_wrt)
+ action = XLogReadBufferForRedoExtended(record, 1, RBM_NORMAL, true, &writebuf);
+ else
+ {
+ /*
+ * we don't care for return value as the purpose of reading bucketbuf
+ * is to ensure a cleanup lock on primary bucket page.
+ */
+ (void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf);
+
+ action = XLogReadBufferForRedo(record, 1, &writebuf);
+ }
+
+ /* replay the record for adding entries in overflow buffer */
+ if (action == BLK_NEEDS_REDO)
+ {
+ Page writepage;
+ char *begin;
+ char *data;
+ Size datalen;
+ uint16 ninserted = 0;
+
+ data = begin = XLogRecGetBlockData(record, 1, &datalen);
+
+ writepage = (Page) BufferGetPage(writebuf);
+
+ if (xldata->ntups > 0)
+ {
+ OffsetNumber *towrite = (OffsetNumber *) data;
+
+ data += sizeof(OffsetNumber) * xldata->ntups;
+
+ while (data - begin < datalen)
+ {
+ IndexTuple itup = (IndexTuple) data;
+ Size itemsz;
+ OffsetNumber l;
+
+ itemsz = IndexTupleDSize(*itup);
+ itemsz = MAXALIGN(itemsz);
+
+ data += itemsz;
+
+ l = PageAddItem(writepage, (Item) itup, itemsz, towrite[ninserted], false, false);
+ if (l == InvalidOffsetNumber)
+ elog(ERROR, "hash_xlog_squeeze_page: failed to add item to hash index page, size %d bytes",
+ (int) itemsz);
+
+ ninserted++;
+ }
+ }
+
+ /*
+ * number of tuples inserted must be same as requested in REDO record.
+ */
+ Assert(ninserted == xldata->ntups);
+
+ /*
+ * if the page on which are adding tuples is a page previous to freed
+ * overflow page, then update its nextblno.
+ */
+ if (xldata->is_prev_bucket_same_wrt)
+ {
+ HashPageOpaque writeopaque = (HashPageOpaque) PageGetSpecialPointer(writepage);
+
+ writeopaque->hasho_nextblkno = xldata->nextblkno;
+ }
+
+ PageSetLSN(writepage, lsn);
+ MarkBufferDirty(writebuf);
+ }
+
+ /* replay the record for initializing overflow buffer */
+ if (XLogReadBufferForRedo(record, 2, &ovflbuf) == BLK_NEEDS_REDO)
+ {
+ Page ovflpage;
+ HashPageOpaque ovflopaque;
+
+ ovflpage = BufferGetPage(ovflbuf);
+
+ _hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
+
+ ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
+
+ ovflopaque->hasho_prevblkno = InvalidBlockNumber;
+ ovflopaque->hasho_nextblkno = InvalidBlockNumber;
+ ovflopaque->hasho_bucket = -1;
+ ovflopaque->hasho_flag = LH_UNUSED_PAGE;
+ ovflopaque->hasho_page_id = HASHO_PAGE_ID;
+
+ PageSetLSN(ovflpage, lsn);
+ MarkBufferDirty(ovflbuf);
+ }
+ if (BufferIsValid(ovflbuf))
+ UnlockReleaseBuffer(ovflbuf);
+
+ /* replay the record for page previous to the freed overflow page */
+ if (!xldata->is_prev_bucket_same_wrt &&
+ XLogReadBufferForRedo(record, 3, &prevbuf) == BLK_NEEDS_REDO)
+ {
+ Page prevpage = BufferGetPage(prevbuf);
+ HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);
+
+ prevopaque->hasho_nextblkno = xldata->nextblkno;
+
+ PageSetLSN(prevpage, lsn);
+ MarkBufferDirty(prevbuf);
+ }
+ if (BufferIsValid(prevbuf))
+ UnlockReleaseBuffer(prevbuf);
+
+ /* replay the record for page next to the freed overflow page */
+ if (XLogRecHasBlockRef(record, 4))
+ {
+ Buffer nextbuf;
+
+ if (XLogReadBufferForRedo(record, 4, &nextbuf) == BLK_NEEDS_REDO)
+ {
+ Page nextpage = BufferGetPage(nextbuf);
+ HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);
+
+ nextopaque->hasho_prevblkno = xldata->prevblkno;
+
+ PageSetLSN(nextpage, lsn);
+ MarkBufferDirty(nextbuf);
+ }
+ if (BufferIsValid(nextbuf))
+ UnlockReleaseBuffer(nextbuf);
+ }
+
+ if (BufferIsValid(writebuf))
+ UnlockReleaseBuffer(writebuf);
+
+ if (BufferIsValid(bucketbuf))
+ UnlockReleaseBuffer(bucketbuf);
+
+ /*
+ * Note: in normal operation, we'd update the bitmap and meta page while
+ * still holding lock on the primary bucket page and overflow pages. But
+ * during replay it's not necessary to hold those locks, since no other
+ * index updates can be happening concurrently.
+ */
+ /* replay the record for bitmap page */
+ if (XLogReadBufferForRedo(record, 5, &mapbuf) == BLK_NEEDS_REDO)
+ {
+ Page mappage = (Page) BufferGetPage(mapbuf);
+ uint32 *freep = NULL;
+ char *data;
+ uint32 *bitmap_page_bit;
+ Size datalen;
+
+ freep = HashPageGetBitmap(mappage);
+
+ data = XLogRecGetBlockData(record, 5, &datalen);
+ bitmap_page_bit = (uint32 *) data;
+
+ CLRBIT(freep, *bitmap_page_bit);
+
+ PageSetLSN(mappage, lsn);
+ MarkBufferDirty(mapbuf);
+ }
+ if (BufferIsValid(mapbuf))
+ UnlockReleaseBuffer(mapbuf);
+
+ /* replay the record for meta page */
+ if (XLogRecHasBlockRef(record, 6))
+ {
+ Buffer metabuf;
+
+ if (XLogReadBufferForRedo(record, 6, &metabuf) == BLK_NEEDS_REDO)
+ {
+ HashMetaPage metap;
+ Page page;
+ char *data;
+ uint32 *firstfree_ovflpage;
+ Size datalen;
+
+ data = XLogRecGetBlockData(record, 6, &datalen);
+ firstfree_ovflpage = (uint32 *) data;
+
+ page = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(page);
+ metap->hashm_firstfree = *firstfree_ovflpage;
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(metabuf);
+ }
+ if (BufferIsValid(metabuf))
+ UnlockReleaseBuffer(metabuf);
+ }
+}
+
+/*
+ * replay delete operation of hash index
+ */
+static void
+hash_xlog_delete(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_delete *xldata = (xl_hash_delete *) XLogRecGetData(record);
+ Buffer bucketbuf = InvalidBuffer;
+ Buffer deletebuf;
+ Page page;
+ XLogRedoAction action;
+
+ /*
+ * Ensure we have a cleanup lock on primary bucket page before we start
+ * with the actual replay operation. This is to ensure that neither a
+ * scan can start nor a scan can be already-in-progress during the replay
+ * of this operation. If we allow scans during this operation, then they
+ * can miss some records or show the same record multiple times.
+ */
+ if (xldata->is_primary_bucket_page)
+ action = XLogReadBufferForRedoExtended(record, 1, RBM_NORMAL, true, &deletebuf);
+ else
+ {
+ /*
+ * we don't care for return value as the purpose of reading bucketbuf
+ * is to ensure a cleanup lock on primary bucket page.
+ */
+ (void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf);
+
+ action = XLogReadBufferForRedo(record, 1, &deletebuf);
+ }
+
+ /* replay the record for deleting entries in bucket page */
+ if (action == BLK_NEEDS_REDO)
+ {
+ char *ptr;
+ Size len;
+
+ ptr = XLogRecGetBlockData(record, 1, &len);
+
+ page = (Page) BufferGetPage(deletebuf);
+
+ if (len > 0)
+ {
+ OffsetNumber *unused;
+ OffsetNumber *unend;
+
+ unused = (OffsetNumber *) ptr;
+ unend = (OffsetNumber *) ((char *) ptr + len);
+
+ if ((unend - unused) > 0)
+ PageIndexMultiDelete(page, unused, unend - unused);
+ }
+
+ /*
+ * Mark the page as not containing any LP_DEAD items only if
+ * clear_dead_marking flag is set to true. See comments in
+ * hashbucketcleanup() for details.
+ */
+ if (xldata->clear_dead_marking)
+ {
+ HashPageOpaque pageopaque;
+
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ pageopaque->hasho_flag &= ~LH_PAGE_HAS_DEAD_TUPLES;
+ }
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(deletebuf);
+ }
+ if (BufferIsValid(deletebuf))
+ UnlockReleaseBuffer(deletebuf);
+
+ if (BufferIsValid(bucketbuf))
+ UnlockReleaseBuffer(bucketbuf);
+}
+
+/*
+ * replay split cleanup flag operation for primary bucket page.
+ */
+static void
+hash_xlog_split_cleanup(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ Buffer buffer;
+ Page page;
+
+ if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
+ {
+ HashPageOpaque bucket_opaque;
+
+ page = (Page) BufferGetPage(buffer);
+
+ bucket_opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ bucket_opaque->hasho_flag &= ~LH_BUCKET_NEEDS_SPLIT_CLEANUP;
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(buffer);
+ }
+ if (BufferIsValid(buffer))
+ UnlockReleaseBuffer(buffer);
+}
+
+/*
+ * replay for update meta page
+ */
+static void
+hash_xlog_update_meta_page(XLogReaderState *record)
+{
+ HashMetaPage metap;
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_update_meta_page *xldata = (xl_hash_update_meta_page *) XLogRecGetData(record);
+ Buffer metabuf;
+ Page page;
+
+ if (XLogReadBufferForRedo(record, 0, &metabuf) == BLK_NEEDS_REDO)
+ {
+ page = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(page);
+
+ metap->hashm_ntuples = xldata->ntuples;
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(metabuf);
+ }
+ if (BufferIsValid(metabuf))
+ UnlockReleaseBuffer(metabuf);
+}
+
+/*
+ * Get the latestRemovedXid from the heap pages pointed at by the index
+ * tuples being deleted. See also btree_xlog_delete_get_latestRemovedXid,
+ * on which this function is based.
+ */
+static TransactionId
+hash_xlog_vacuum_get_latestRemovedXid(XLogReaderState *record)
+{
+ xl_hash_vacuum_one_page *xlrec;
+ OffsetNumber *unused;
+ Buffer ibuffer,
+ hbuffer;
+ Page ipage,
+ hpage;
+ RelFileNode rnode;
+ BlockNumber blkno;
+ ItemId iitemid,
+ hitemid;
+ IndexTuple itup;
+ HeapTupleHeader htuphdr;
+ BlockNumber hblkno;
+ OffsetNumber hoffnum;
+ TransactionId latestRemovedXid = InvalidTransactionId;
+ int i;
+
+ xlrec = (xl_hash_vacuum_one_page *) XLogRecGetData(record);
+
+ /*
+ * If there's nothing running on the standby we don't need to derive a
+ * full latestRemovedXid value, so use a fast path out of here. This
+ * returns InvalidTransactionId, and so will conflict with all HS
+ * transactions; but since we just worked out that that's zero people,
+ * it's OK.
+ *
+ * XXX There is a race condition here, which is that a new backend might
+ * start just after we look. If so, it cannot need to conflict, but this
+ * coding will result in throwing a conflict anyway.
+ */
+ if (CountDBBackends(InvalidOid) == 0)
+ return latestRemovedXid;
+
+ /*
+ * Check if WAL replay has reached a consistent database state. If not, we
+ * must PANIC. See the definition of
+ * btree_xlog_delete_get_latestRemovedXid for more details.
+ */
+ if (!reachedConsistency)
+ elog(PANIC, "hash_xlog_vacuum_get_latestRemovedXid: cannot operate with inconsistent data");
+
+ /*
+ * Get index page. If the DB is consistent, this should not fail, nor
+ * should any of the heap page fetches below. If one does, we return
+ * InvalidTransactionId to cancel all HS transactions. That's probably
+ * overkill, but it's safe, and certainly better than panicking here.
+ */
+ XLogRecGetBlockTag(record, 0, &rnode, NULL, &blkno);
+ ibuffer = XLogReadBufferExtended(rnode, MAIN_FORKNUM, blkno, RBM_NORMAL);
+
+ if (!BufferIsValid(ibuffer))
+ return InvalidTransactionId;
+ LockBuffer(ibuffer, HASH_READ);
+ ipage = (Page) BufferGetPage(ibuffer);
+
+ /*
+ * Loop through the deleted index items to obtain the TransactionId from
+ * the heap items they point to.
+ */
+ unused = (OffsetNumber *) ((char *) xlrec + SizeOfHashVacuumOnePage);
+
+ for (i = 0; i < xlrec->ntuples; i++)
+ {
+ /*
+ * Identify the index tuple about to be deleted.
+ */
+ iitemid = PageGetItemId(ipage, unused[i]);
+ itup = (IndexTuple) PageGetItem(ipage, iitemid);
+
+ /*
+ * Locate the heap page that the index tuple points at
+ */
+ hblkno = ItemPointerGetBlockNumber(&(itup->t_tid));
+ hbuffer = XLogReadBufferExtended(xlrec->hnode, MAIN_FORKNUM,
+ hblkno, RBM_NORMAL);
+
+ if (!BufferIsValid(hbuffer))
+ {
+ UnlockReleaseBuffer(ibuffer);
+ return InvalidTransactionId;
+ }
+ LockBuffer(hbuffer, HASH_READ);
+ hpage = (Page) BufferGetPage(hbuffer);
+
+ /*
+ * Look up the heap tuple header that the index tuple points at by
+ * using the heap node supplied with the xlrec. We can't use
+ * heap_fetch, since it uses ReadBuffer rather than XLogReadBuffer.
+ * Note that we are not looking at tuple data here, just headers.
+ */
+ hoffnum = ItemPointerGetOffsetNumber(&(itup->t_tid));
+ hitemid = PageGetItemId(hpage, hoffnum);
+
+ /*
+ * Follow any redirections until we find something useful.
+ */
+ while (ItemIdIsRedirected(hitemid))
+ {
+ hoffnum = ItemIdGetRedirect(hitemid);
+ hitemid = PageGetItemId(hpage, hoffnum);
+ CHECK_FOR_INTERRUPTS();
+ }
+
+ /*
+ * If the heap item has storage, then read the header and use that to
+ * set latestRemovedXid.
+ *
+ * Some LP_DEAD items may not be accessible, so we ignore them.
+ */
+ if (ItemIdHasStorage(hitemid))
+ {
+ htuphdr = (HeapTupleHeader) PageGetItem(hpage, hitemid);
+ HeapTupleHeaderAdvanceLatestRemovedXid(htuphdr, &latestRemovedXid);
+ }
+ else if (ItemIdIsDead(hitemid))
+ {
+ /*
+ * Conjecture: if hitemid is dead then it had xids before the xids
+ * marked on LP_NORMAL items. So we just ignore this item and move
+ * onto the next, for the purposes of calculating
+ * latestRemovedxids.
+ */
+ }
+ else
+ Assert(!ItemIdIsUsed(hitemid));
+
+ UnlockReleaseBuffer(hbuffer);
+ }
+
+ UnlockReleaseBuffer(ibuffer);
+
+ /*
+ * If all heap tuples were LP_DEAD then we will be returning
+ * InvalidTransactionId here, which avoids conflicts. This matches
+ * existing logic which assumes that LP_DEAD tuples must already be older
+ * than the latestRemovedXid on the cleanup record that set them as
+ * LP_DEAD, hence must already have generated a conflict.
+ */
+ return latestRemovedXid;
+}
+
+/*
+ * replay delete operation in hash index to remove
+ * tuples marked as DEAD during index tuple insertion.
+ */
+static void
+hash_xlog_vacuum_one_page(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ xl_hash_vacuum_one_page *xldata;
+ Buffer buffer;
+ Buffer metabuf;
+ Page page;
+ XLogRedoAction action;
+ HashPageOpaque pageopaque;
+
+ xldata = (xl_hash_vacuum_one_page *) XLogRecGetData(record);
+
+ /*
+ * If we have any conflict processing to do, it must happen before we
+ * update the page.
+ *
+ * Hash index records that are marked as LP_DEAD and being removed during
+ * hash index tuple insertion can conflict with standby queries. You might
+ * think that vacuum records would conflict as well, but we've handled
+ * that already. XLOG_HEAP2_CLEANUP_INFO records provide the highest xid
+ * cleaned by the vacuum of the heap and so we can resolve any conflicts
+ * just once when that arrives. After that we know that no conflicts
+ * exist from individual hash index vacuum records on that index.
+ */
+ if (InHotStandby)
+ {
+ TransactionId latestRemovedXid =
+ hash_xlog_vacuum_get_latestRemovedXid(record);
+ RelFileNode rnode;
+
+ XLogRecGetBlockTag(record, 0, &rnode, NULL, NULL);
+ ResolveRecoveryConflictWithSnapshot(latestRemovedXid, rnode);
+ }
+
+ action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &buffer);
+
+ if (action == BLK_NEEDS_REDO)
+ {
+ page = (Page) BufferGetPage(buffer);
+
+ if (XLogRecGetDataLen(record) > SizeOfHashVacuumOnePage)
+ {
+ OffsetNumber *unused;
+
+ unused = (OffsetNumber *) ((char *) xldata + SizeOfHashVacuumOnePage);
+
+ PageIndexMultiDelete(page, unused, xldata->ntuples);
+ }
+
+ /*
+ * Mark the page as not containing any LP_DEAD items. See comments in
+ * _hash_vacuum_one_page() for details.
+ */
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ pageopaque->hasho_flag &= ~LH_PAGE_HAS_DEAD_TUPLES;
+
+ PageSetLSN(page, lsn);
+ MarkBufferDirty(buffer);
+ }
+ if (BufferIsValid(buffer))
+ UnlockReleaseBuffer(buffer);
+
+ if (XLogReadBufferForRedo(record, 1, &metabuf) == BLK_NEEDS_REDO)
+ {
+ Page metapage;
+ HashMetaPage metap;
+
+ metapage = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(metapage);
+
+ metap->hashm_ntuples -= xldata->ntuples;
+
+ PageSetLSN(metapage, lsn);
+ MarkBufferDirty(metabuf);
+ }
+ if (BufferIsValid(metabuf))
+ UnlockReleaseBuffer(metabuf);
+}
+
+void
+hash_redo(XLogReaderState *record)
+{
+ uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
+
+ switch (info)
+ {
+ case XLOG_HASH_INIT_META_PAGE:
+ hash_xlog_init_meta_page(record);
+ break;
+ case XLOG_HASH_INIT_BITMAP_PAGE:
+ hash_xlog_init_bitmap_page(record);
+ break;
+ case XLOG_HASH_INSERT:
+ hash_xlog_insert(record);
+ break;
+ case XLOG_HASH_ADD_OVFL_PAGE:
+ hash_xlog_add_ovfl_page(record);
+ break;
+ case XLOG_HASH_SPLIT_ALLOCATE_PAGE:
+ hash_xlog_split_allocate_page(record);
+ break;
+ case XLOG_HASH_SPLIT_PAGE:
+ hash_xlog_split_page(record);
+ break;
+ case XLOG_HASH_SPLIT_COMPLETE:
+ hash_xlog_split_complete(record);
+ break;
+ case XLOG_HASH_MOVE_PAGE_CONTENTS:
+ hash_xlog_move_page_contents(record);
+ break;
+ case XLOG_HASH_SQUEEZE_PAGE:
+ hash_xlog_squeeze_page(record);
+ break;
+ case XLOG_HASH_DELETE:
+ hash_xlog_delete(record);
+ break;
+ case XLOG_HASH_SPLIT_CLEANUP:
+ hash_xlog_split_cleanup(record);
+ break;
+ case XLOG_HASH_UPDATE_META_PAGE:
+ hash_xlog_update_meta_page(record);
+ break;
+ case XLOG_HASH_VACUUM_ONE_PAGE:
+ hash_xlog_vacuum_one_page(record);
+ break;
+ default:
+ elog(PANIC, "hash_redo: unknown op code %u", info);
+ }
+}
+
+/*
+ * Mask a hash page before performing consistency checks on it.
+ */
+void
+hash_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+ HashPageOpaque opaque;
+ int pagetype;
+
+ mask_page_lsn(page);
+
+ mask_page_hint_bits(page);
+ mask_unused_space(page);
+
+ opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+
+ pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
+ if (pagetype == LH_UNUSED_PAGE)
+ {
+ /*
+ * Mask everything on a UNUSED page.
+ */
+ mask_page_content(page);
+ }
+ else if (pagetype == LH_BUCKET_PAGE ||
+ pagetype == LH_OVERFLOW_PAGE)
+ {
+ /*
+ * In hash bucket and overflow pages, it is possible to modify the
+ * LP_FLAGS without emitting any WAL record. Hence, mask the line
+ * pointer flags. See hashgettuple(), _hash_kill_items() for details.
+ */
+ mask_lp_flags(page);
+ }
+
+ /*
+ * It is possible that the hint bit LH_PAGE_HAS_DEAD_TUPLES may remain
+ * unlogged. So, mask it. See _hash_kill_items() for details.
+ */
+ opaque->hasho_flag &= ~LH_PAGE_HAS_DEAD_TUPLES;
+}
diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c
index bb9adad82e..4089fd6d8a 100644
--- a/src/backend/access/hash/hashfunc.c
+++ b/src/backend/access/hash/hashfunc.c
@@ -3,7 +3,7 @@
* hashfunc.c
* Support functions for hash access method.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -27,6 +27,7 @@
#include "postgres.h"
#include "access/hash.h"
+#include "utils/builtins.h"
#ifdef PGXC
#include "catalog/pg_type.h"
@@ -36,6 +37,16 @@
#include "utils/nabstime.h"
#endif
+/*
+ * Datatype-specific hash functions.
+ *
+ * These support both hash indexes and hash joins.
+ *
+ * NOTE: some of these are also used by catcache operations, without
+ * any direct connection to hash indexes. Also, the common hash_any
+ * routine is also used by dynahash tables.
+ */
+
/* Note: this is used for both "char" and boolean datatypes */
Datum
hashchar(PG_FUNCTION_ARGS)
@@ -138,22 +149,11 @@ hashoidvector(PG_FUNCTION_ARGS)
}
Datum
-hashint2vector(PG_FUNCTION_ARGS)
-{
- int2vector *key = (int2vector *) PG_GETARG_POINTER(0);
-
- return hash_any((unsigned char *) key->values, key->dim1 * sizeof(int16));
-}
-
-Datum
hashname(PG_FUNCTION_ARGS)
{
char *key = NameStr(*PG_GETARG_NAME(0));
- int keylen = strlen(key);
-
- Assert(keylen < NAMEDATALEN); /* else it's not truncated correctly */
- return hash_any((unsigned char *) key, keylen);
+ return hash_any((unsigned char *) key, strlen(key));
}
Datum
@@ -581,8 +581,6 @@ compute_hash(Oid type, Datum value, char locator)
return DirectFunctionCall1(hashchar, value);
case NAMEOID:
return DirectFunctionCall1(hashname, value);
- case INT2VECTOROID:
- return DirectFunctionCall1(hashint2vector, value);
case VARCHAROID:
case TEXTOID:
@@ -677,8 +675,6 @@ get_compute_hash_function(Oid type, char locator)
return "hashchar";
case NAMEOID:
return "hashname";
- case INT2VECTOROID:
- return "hashint2vector";
case VARCHAROID:
case TEXTOID:
return "hashtext";
diff --git a/src/backend/access/hash/hashinsert.c b/src/backend/access/hash/hashinsert.c
index acd2e64763..01c8d8006c 100644
--- a/src/backend/access/hash/hashinsert.c
+++ b/src/backend/access/hash/hashinsert.c
@@ -3,7 +3,7 @@
* hashinsert.c
* Item insertion in hash tables for Postgres.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -16,8 +16,15 @@
#include "postgres.h"
#include "access/hash.h"
+#include "access/hash_xlog.h"
+#include "access/heapam.h"
+#include "miscadmin.h"
#include "utils/rel.h"
+#include "storage/lwlock.h"
+#include "storage/buf_internals.h"
+static void _hash_vacuum_one_page(Relation rel, Buffer metabuf, Buffer buf,
+ RelFileNode hnode);
/*
* _hash_doinsert() -- Handle insertion of a single index tuple.
@@ -26,20 +33,21 @@
* and hashinsert. By here, itup is completely filled in.
*/
void
-_hash_doinsert(Relation rel, IndexTuple itup)
+_hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel)
{
- Buffer buf;
+ Buffer buf = InvalidBuffer;
+ Buffer bucket_buf;
Buffer metabuf;
HashMetaPage metap;
- BlockNumber blkno;
- BlockNumber oldblkno = InvalidBlockNumber;
- bool retry = false;
+ HashMetaPage usedmetap = NULL;
+ Page metapage;
Page page;
HashPageOpaque pageopaque;
Size itemsz;
bool do_expand;
uint32 hashkey;
Bucket bucket;
+ OffsetNumber itup_off;
/*
* Get the hash key for the item (it's stored in the index tuple itself).
@@ -51,9 +59,15 @@ _hash_doinsert(Relation rel, IndexTuple itup)
itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we
* need to be consistent */
- /* Read the metapage */
- metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
- metap = HashPageGetMeta(BufferGetPage(metabuf));
+restart_insert:
+
+ /*
+ * Read the metapage. We don't lock it yet; HashMaxItemSize() will
+ * examine pd_pagesize_version, but that can't change so we can examine it
+ * without a lock.
+ */
+ metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_NOLOCK, LH_META_PAGE);
+ metapage = BufferGetPage(metabuf);
/*
* Check whether the item can fit on a hash page at all. (Eventually, we
@@ -62,74 +76,90 @@ _hash_doinsert(Relation rel, IndexTuple itup)
*
* XXX this is useless code if we are only storing hash keys.
*/
- if (itemsz > HashMaxItemSize((Page) metap))
+ if (itemsz > HashMaxItemSize(metapage))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("index row size %zu exceeds hash maximum %zu",
- itemsz, HashMaxItemSize((Page) metap)),
+ itemsz, HashMaxItemSize(metapage)),
errhint("Values larger than a buffer page cannot be indexed.")));
+ /* Lock the primary bucket page for the target bucket. */
+ buf = _hash_getbucketbuf_from_hashkey(rel, hashkey, HASH_WRITE,
+ &usedmetap);
+ Assert(usedmetap != NULL);
+
+ /* remember the primary bucket buffer to release the pin on it at end. */
+ bucket_buf = buf;
+
+ page = BufferGetPage(buf);
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ bucket = pageopaque->hasho_bucket;
+
/*
- * Loop until we get a lock on the correct target bucket.
+ * If this bucket is in the process of being split, try to finish the
+ * split before inserting, because that might create room for the
+ * insertion to proceed without allocating an additional overflow page.
+ * It's only interesting to finish the split if we're trying to insert
+ * into the bucket from which we're removing tuples (the "old" bucket),
+ * not if we're trying to insert into the bucket into which tuples are
+ * being moved (the "new" bucket).
*/
- for (;;)
+ if (H_BUCKET_BEING_SPLIT(pageopaque) && IsBufferCleanupOK(buf))
{
- /*
- * Compute the target bucket number, and convert to block number.
- */
- bucket = _hash_hashkey2bucket(hashkey,
- metap->hashm_maxbucket,
- metap->hashm_highmask,
- metap->hashm_lowmask);
-
- blkno = BUCKET_TO_BLKNO(metap, bucket);
+ /* release the lock on bucket buffer, before completing the split. */
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+
+ _hash_finish_split(rel, metabuf, buf, bucket,
+ usedmetap->hashm_maxbucket,
+ usedmetap->hashm_highmask,
+ usedmetap->hashm_lowmask);
+
+ /* release the pin on old and meta buffer. retry for insert. */
+ _hash_dropbuf(rel, buf);
+ _hash_dropbuf(rel, metabuf);
+ goto restart_insert;
+ }
- /* Release metapage lock, but keep pin. */
- _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
+ /* Do the insertion */
+ while (PageGetFreeSpace(page) < itemsz)
+ {
+ BlockNumber nextblkno;
/*
- * If the previous iteration of this loop locked what is still the
- * correct target bucket, we are done. Otherwise, drop any old lock
- * and lock what now appears to be the correct bucket.
+ * Check if current page has any DEAD tuples. If yes, delete these
+ * tuples and see if we can get a space for the new item to be
+ * inserted before moving to the next page in the bucket chain.
*/
- if (retry)
+ if (H_HAS_DEAD_TUPLES(pageopaque))
{
- if (oldblkno == blkno)
- break;
- _hash_droplock(rel, oldblkno, HASH_SHARE);
- }
- _hash_getlock(rel, blkno, HASH_SHARE);
- /*
- * Reacquire metapage lock and check that no bucket split has taken
- * place while we were awaiting the bucket lock.
- */
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_READ);
- oldblkno = blkno;
- retry = true;
- }
+ if (IsBufferCleanupOK(buf))
+ {
+ _hash_vacuum_one_page(rel, metabuf, buf, heapRel->rd_node);
- /* Fetch the primary bucket page for the bucket */
- buf = _hash_getbuf(rel, blkno, HASH_WRITE, LH_BUCKET_PAGE);
- page = BufferGetPage(buf);
- pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
- Assert(pageopaque->hasho_bucket == bucket);
+ if (PageGetFreeSpace(page) >= itemsz)
+ break; /* OK, now we have enough space */
+ }
+ }
- /* Do the insertion */
- while (PageGetFreeSpace(page) < itemsz)
- {
/*
* no space on this page; check for an overflow page
*/
- BlockNumber nextblkno = pageopaque->hasho_nextblkno;
+ nextblkno = pageopaque->hasho_nextblkno;
if (BlockNumberIsValid(nextblkno))
{
/*
* ovfl page exists; go get it. if it doesn't have room, we'll
- * find out next pass through the loop test above.
+ * find out next pass through the loop test above. we always
+ * release both the lock and pin if this is an overflow page, but
+ * only the lock if this is the primary bucket page, since the pin
+ * on the primary bucket must be retained throughout the scan.
*/
- _hash_relbuf(rel, buf);
+ if (buf != bucket_buf)
+ _hash_relbuf(rel, buf);
+ else
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
buf = _hash_getbuf(rel, nextblkno, HASH_WRITE, LH_OVERFLOW_PAGE);
page = BufferGetPage(buf);
}
@@ -141,43 +171,77 @@ _hash_doinsert(Relation rel, IndexTuple itup)
*/
/* release our write lock without modifying buffer */
- _hash_chgbufaccess(rel, buf, HASH_READ, HASH_NOLOCK);
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
/* chain to a new overflow page */
- buf = _hash_addovflpage(rel, metabuf, buf);
+ buf = _hash_addovflpage(rel, metabuf, buf, (buf == bucket_buf) ? true : false);
page = BufferGetPage(buf);
/* should fit now, given test above */
Assert(PageGetFreeSpace(page) >= itemsz);
}
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
- Assert(pageopaque->hasho_flag == LH_OVERFLOW_PAGE);
+ Assert((pageopaque->hasho_flag & LH_PAGE_TYPE) == LH_OVERFLOW_PAGE);
Assert(pageopaque->hasho_bucket == bucket);
}
- /* found page with enough space, so add the item here */
- (void) _hash_pgaddtup(rel, buf, itemsz, itup);
-
- /* write and release the modified page */
- _hash_wrtbuf(rel, buf);
-
- /* We can drop the bucket lock now */
- _hash_droplock(rel, blkno, HASH_SHARE);
-
/*
* Write-lock the metapage so we can increment the tuple count. After
* incrementing it, check to see if it's time for a split.
*/
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
+ /* Do the update. No ereport(ERROR) until changes are logged */
+ START_CRIT_SECTION();
+
+ /* found page with enough space, so add the item here */
+ itup_off = _hash_pgaddtup(rel, buf, itemsz, itup);
+ MarkBufferDirty(buf);
+
+ /* metapage operations */
+ metap = HashPageGetMeta(metapage);
metap->hashm_ntuples += 1;
/* Make sure this stays in sync with _hash_expandtable() */
do_expand = metap->hashm_ntuples >
(double) metap->hashm_ffactor * (metap->hashm_maxbucket + 1);
- /* Write out the metapage and drop lock, but keep pin */
- _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK);
+ MarkBufferDirty(metabuf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_insert xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.offnum = itup_off;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashInsert);
+
+ XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD);
+
+ XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
+ XLogRegisterBufData(0, (char *) itup, IndexTupleDSize(*itup));
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INSERT);
+
+ PageSetLSN(BufferGetPage(buf), recptr);
+ PageSetLSN(BufferGetPage(metabuf), recptr);
+ }
+
+ END_CRIT_SECTION();
+
+ /* drop lock on metapage, but keep pin */
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+
+ /*
+ * Release the modified page and ensure to release the pin on primary
+ * page.
+ */
+ _hash_relbuf(rel, buf);
+ if (buf != bucket_buf)
+ _hash_dropbuf(rel, bucket_buf);
/* Attempt to split if a split is needed */
if (do_expand)
@@ -219,3 +283,143 @@ _hash_pgaddtup(Relation rel, Buffer buf, Size itemsize, IndexTuple itup)
return itup_off;
}
+
+/*
+ * _hash_pgaddmultitup() -- add a tuple vector to a particular page in the
+ * index.
+ *
+ * This routine has same requirements for locking and tuple ordering as
+ * _hash_pgaddtup().
+ *
+ * Returns the offset number array at which the tuples were inserted.
+ */
+void
+_hash_pgaddmultitup(Relation rel, Buffer buf, IndexTuple *itups,
+ OffsetNumber *itup_offsets, uint16 nitups)
+{
+ OffsetNumber itup_off;
+ Page page;
+ uint32 hashkey;
+ int i;
+
+ _hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
+ page = BufferGetPage(buf);
+
+ for (i = 0; i < nitups; i++)
+ {
+ Size itemsize;
+
+ itemsize = IndexTupleDSize(*itups[i]);
+ itemsize = MAXALIGN(itemsize);
+
+ /* Find where to insert the tuple (preserving page's hashkey ordering) */
+ hashkey = _hash_get_indextuple_hashkey(itups[i]);
+ itup_off = _hash_binsearch(page, hashkey);
+
+ itup_offsets[i] = itup_off;
+
+ if (PageAddItem(page, (Item) itups[i], itemsize, itup_off, false, false)
+ == InvalidOffsetNumber)
+ elog(ERROR, "failed to add index item to \"%s\"",
+ RelationGetRelationName(rel));
+ }
+}
+
+/*
+ * _hash_vacuum_one_page - vacuum just one index page.
+ *
+ * Try to remove LP_DEAD items from the given page. We must acquire cleanup
+ * lock on the page being modified before calling this function.
+ */
+
+static void
+_hash_vacuum_one_page(Relation rel, Buffer metabuf, Buffer buf,
+ RelFileNode hnode)
+{
+ OffsetNumber deletable[MaxOffsetNumber];
+ int ndeletable = 0;
+ OffsetNumber offnum,
+ maxoff;
+ Page page = BufferGetPage(buf);
+ HashPageOpaque pageopaque;
+ HashMetaPage metap;
+
+ /* Scan each tuple in page to see if it is marked as LP_DEAD */
+ maxoff = PageGetMaxOffsetNumber(page);
+ for (offnum = FirstOffsetNumber;
+ offnum <= maxoff;
+ offnum = OffsetNumberNext(offnum))
+ {
+ ItemId itemId = PageGetItemId(page, offnum);
+
+ if (ItemIdIsDead(itemId))
+ deletable[ndeletable++] = offnum;
+ }
+
+ if (ndeletable > 0)
+ {
+ /*
+ * Write-lock the meta page so that we can decrement tuple count.
+ */
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
+
+ /* No ereport(ERROR) until changes are logged */
+ START_CRIT_SECTION();
+
+ PageIndexMultiDelete(page, deletable, ndeletable);
+
+ /*
+ * Mark the page as not containing any LP_DEAD items. This is not
+ * certainly true (there might be some that have recently been marked,
+ * but weren't included in our target-item list), but it will almost
+ * always be true and it doesn't seem worth an additional page scan to
+ * check it. Remember that LH_PAGE_HAS_DEAD_TUPLES is only a hint
+ * anyway.
+ */
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ pageopaque->hasho_flag &= ~LH_PAGE_HAS_DEAD_TUPLES;
+
+ metap = HashPageGetMeta(BufferGetPage(metabuf));
+ metap->hashm_ntuples -= ndeletable;
+
+ MarkBufferDirty(buf);
+ MarkBufferDirty(metabuf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_vacuum_one_page xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.hnode = hnode;
+ xlrec.ntuples = ndeletable;
+
+ XLogBeginInsert();
+ XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
+ XLogRegisterData((char *) &xlrec, SizeOfHashVacuumOnePage);
+
+ /*
+ * We need the target-offsets array whether or not we store the
+ * whole buffer, to allow us to find the latestRemovedXid on a
+ * standby server.
+ */
+ XLogRegisterData((char *) deletable,
+ ndeletable * sizeof(OffsetNumber));
+
+ XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_VACUUM_ONE_PAGE);
+
+ PageSetLSN(BufferGetPage(buf), recptr);
+ PageSetLSN(BufferGetPage(metabuf), recptr);
+ }
+
+ END_CRIT_SECTION();
+
+ /*
+ * Releasing write lock on meta page as we have updated the tuple
+ * count.
+ */
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+ }
+}
diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c
index db3e268a76..b5133e3945 100644
--- a/src/backend/access/hash/hashovfl.c
+++ b/src/backend/access/hash/hashovfl.c
@@ -3,7 +3,7 @@
* hashovfl.c
* Overflow page management code for the Postgres hash access method
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -18,10 +18,11 @@
#include "postgres.h"
#include "access/hash.h"
+#include "access/hash_xlog.h"
+#include "miscadmin.h"
#include "utils/rel.h"
-static Buffer _hash_getovflpage(Relation rel, Buffer metabuf);
static uint32 _hash_firstfreebit(uint32 map);
@@ -48,14 +49,16 @@ bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum)
* Convert to absolute page number by adding the number of bucket pages
* that exist before this split point.
*/
- return (BlockNumber) ((1 << i) + ovflbitnum);
+ return (BlockNumber) (_hash_get_totalbuckets(i) + ovflbitnum);
}
/*
+ * _hash_ovflblkno_to_bitno
+ *
* Convert overflow page block number to bit number for free-page bitmap.
*/
-static uint32
-blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
+uint32
+_hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
{
uint32 splitnum = metap->hashm_ovflpoint;
uint32 i;
@@ -64,14 +67,24 @@ blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
/* Determine the split number containing this page */
for (i = 1; i <= splitnum; i++)
{
- if (ovflblkno <= (BlockNumber) (1 << i))
+ if (ovflblkno <= (BlockNumber) _hash_get_totalbuckets(i))
break; /* oops */
- bitnum = ovflblkno - (1 << i);
- if (bitnum <= metap->hashm_spares[i])
+ bitnum = ovflblkno - _hash_get_totalbuckets(i);
+
+ /*
+ * bitnum has to be greater than number of overflow page added in
+ * previous split point. The overflow page at this splitnum (i) if any
+ * should start from (_hash_get_totalbuckets(i) +
+ * metap->hashm_spares[i - 1] + 1).
+ */
+ if (bitnum > metap->hashm_spares[i - 1] &&
+ bitnum <= metap->hashm_spares[i])
return bitnum - 1; /* -1 to convert 1-based to 0-based */
}
- elog(ERROR, "invalid overflow block number %u", ovflblkno);
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid overflow block number %u", ovflblkno)));
return 0; /* keep compiler quiet */
}
@@ -82,38 +95,59 @@ blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
*
* On entry, the caller must hold a pin but no lock on 'buf'. The pin is
* dropped before exiting (we assume the caller is not interested in 'buf'
- * anymore). The returned overflow page will be pinned and write-locked;
- * it is guaranteed to be empty.
+ * anymore) if not asked to retain. The pin will be retained only for the
+ * primary bucket. The returned overflow page will be pinned and
+ * write-locked; it is guaranteed to be empty.
*
* The caller must hold a pin, but no lock, on the metapage buffer.
* That buffer is returned in the same state.
*
- * The caller must hold at least share lock on the bucket, to ensure that
- * no one else tries to compact the bucket meanwhile. This guarantees that
- * 'buf' won't stop being part of the bucket while it's unlocked.
- *
* NB: since this could be executed concurrently by multiple processes,
* one should not assume that the returned overflow page will be the
* immediate successor of the originally passed 'buf'. Additional overflow
* pages might have been added to the bucket chain in between.
*/
Buffer
-_hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf)
+_hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin)
{
Buffer ovflbuf;
Page page;
Page ovflpage;
HashPageOpaque pageopaque;
HashPageOpaque ovflopaque;
-
- /* allocate and lock an empty overflow page */
- ovflbuf = _hash_getovflpage(rel, metabuf);
+ HashMetaPage metap;
+ Buffer mapbuf = InvalidBuffer;
+ Buffer newmapbuf = InvalidBuffer;
+ BlockNumber blkno;
+ uint32 orig_firstfree;
+ uint32 splitnum;
+ uint32 *freep = NULL;
+ uint32 max_ovflpg;
+ uint32 bit;
+ uint32 bitmap_page_bit;
+ uint32 first_page;
+ uint32 last_bit;
+ uint32 last_page;
+ uint32 i,
+ j;
+ bool page_found = false;
/*
- * Write-lock the tail page. It is okay to hold two buffer locks here
- * since there cannot be anyone else contending for access to ovflbuf.
+ * Write-lock the tail page. Here, we need to maintain locking order such
+ * that, first acquire the lock on tail page of bucket, then on meta page
+ * to find and lock the bitmap page and if it is found, then lock on meta
+ * page is released, then finally acquire the lock on new overflow buffer.
+ * We need this locking order to avoid deadlock with backends that are
+ * doing inserts.
+ *
+ * Note: We could have avoided locking many buffers here if we made two
+ * WAL records for acquiring an overflow page (one to allocate an overflow
+ * page and another to add it to overflow bucket chain). However, doing
+ * so can leak an overflow page, if the system crashes after allocation.
+ * Needless to say, it is better to have a single record from a
+ * performance point of view as well.
*/
- _hash_chgbufaccess(rel, buf, HASH_NOLOCK, HASH_WRITE);
+ LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
/* probably redundant... */
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
@@ -131,59 +165,22 @@ _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf)
break;
/* we assume we do not need to write the unmodified page */
- _hash_relbuf(rel, buf);
+ if (retain_pin)
+ {
+ /* pin will be retained only for the primary bucket page */
+ Assert((pageopaque->hasho_flag & LH_PAGE_TYPE) == LH_BUCKET_PAGE);
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+ }
+ else
+ _hash_relbuf(rel, buf);
+
+ retain_pin = false;
buf = _hash_getbuf(rel, nextblkno, HASH_WRITE, LH_OVERFLOW_PAGE);
}
- /* now that we have correct backlink, initialize new overflow page */
- ovflpage = BufferGetPage(ovflbuf);
- ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
- ovflopaque->hasho_prevblkno = BufferGetBlockNumber(buf);
- ovflopaque->hasho_nextblkno = InvalidBlockNumber;
- ovflopaque->hasho_bucket = pageopaque->hasho_bucket;
- ovflopaque->hasho_flag = LH_OVERFLOW_PAGE;
- ovflopaque->hasho_page_id = HASHO_PAGE_ID;
-
- MarkBufferDirty(ovflbuf);
-
- /* logically chain overflow page to previous page */
- pageopaque->hasho_nextblkno = BufferGetBlockNumber(ovflbuf);
- _hash_wrtbuf(rel, buf);
-
- return ovflbuf;
-}
-
-/*
- * _hash_getovflpage()
- *
- * Find an available overflow page and return it. The returned buffer
- * is pinned and write-locked, and has had _hash_pageinit() applied,
- * but it is caller's responsibility to fill the special space.
- *
- * The caller must hold a pin, but no lock, on the metapage buffer.
- * That buffer is left in the same state at exit.
- */
-static Buffer
-_hash_getovflpage(Relation rel, Buffer metabuf)
-{
- HashMetaPage metap;
- Buffer mapbuf = 0;
- Buffer newbuf;
- BlockNumber blkno;
- uint32 orig_firstfree;
- uint32 splitnum;
- uint32 *freep = NULL;
- uint32 max_ovflpg;
- uint32 bit;
- uint32 first_page;
- uint32 last_bit;
- uint32 last_page;
- uint32 i,
- j;
-
/* Get exclusive lock on the meta page */
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
_hash_checkpage(rel, metabuf, LH_META_PAGE);
metap = HashPageGetMeta(BufferGetPage(metabuf));
@@ -221,7 +218,7 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
last_inpage = BMPGSZ_BIT(metap) - 1;
/* Release exclusive lock on metapage while reading bitmap page */
- _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
mapbuf = _hash_getbuf(rel, mapblkno, HASH_WRITE, LH_BITMAP_PAGE);
mappage = BufferGetPage(mapbuf);
@@ -230,17 +227,37 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
for (; bit <= last_inpage; j++, bit += BITS_PER_MAP)
{
if (freep[j] != ALL_SET)
+ {
+ page_found = true;
+
+ /* Reacquire exclusive lock on the meta page */
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
+
+ /* convert bit to bit number within page */
+ bit += _hash_firstfreebit(freep[j]);
+ bitmap_page_bit = bit;
+
+ /* convert bit to absolute bit number */
+ bit += (i << BMPG_SHIFT(metap));
+ /* Calculate address of the recycled overflow page */
+ blkno = bitno_to_blkno(metap, bit);
+
+ /* Fetch and init the recycled page */
+ ovflbuf = _hash_getinitbuf(rel, blkno);
+
goto found;
+ }
}
/* No free space here, try to advance to next map page */
_hash_relbuf(rel, mapbuf);
+ mapbuf = InvalidBuffer;
i++;
j = 0; /* scan from start of next map page */
bit = 0;
/* Reacquire exclusive lock on the meta page */
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
}
/*
@@ -258,8 +275,15 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
* convenient to pre-mark them as "in use" too.
*/
bit = metap->hashm_spares[splitnum];
- _hash_initbitmap(rel, metap, bitno_to_blkno(metap, bit), MAIN_FORKNUM);
- metap->hashm_spares[splitnum]++;
+
+ /* metapage already has a write lock */
+ if (metap->hashm_nmaps >= HASH_MAX_BITMAPS)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("out of overflow pages in hash index \"%s\"",
+ RelationGetRelationName(rel))));
+
+ newmapbuf = _hash_getnewbuf(rel, bitno_to_blkno(metap, bit), MAIN_FORKNUM);
}
else
{
@@ -270,7 +294,8 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
}
/* Calculate address of the new overflow page */
- bit = metap->hashm_spares[splitnum];
+ bit = BufferIsValid(newmapbuf) ?
+ metap->hashm_spares[splitnum] + 1 : metap->hashm_spares[splitnum];
blkno = bitno_to_blkno(metap, bit);
/*
@@ -278,39 +303,52 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
* relation length stays in sync with ours. XXX It's annoying to do this
* with metapage write lock held; would be better to use a lock that
* doesn't block incoming searches.
+ *
+ * It is okay to hold two buffer locks here (one on tail page of bucket
+ * and other on new overflow page) since there cannot be anyone else
+ * contending for access to ovflbuf.
*/
- newbuf = _hash_getnewbuf(rel, blkno, MAIN_FORKNUM);
+ ovflbuf = _hash_getnewbuf(rel, blkno, MAIN_FORKNUM);
- metap->hashm_spares[splitnum]++;
+found:
/*
- * Adjust hashm_firstfree to avoid redundant searches. But don't risk
- * changing it if someone moved it while we were searching bitmap pages.
+ * Do the update. No ereport(ERROR) until changes are logged. We want to
+ * log the changes for bitmap page and overflow page together to avoid
+ * loss of pages in case the new page is added.
*/
- if (metap->hashm_firstfree == orig_firstfree)
- metap->hashm_firstfree = bit + 1;
-
- /* Write updated metapage and release lock, but not pin */
- _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK);
+ START_CRIT_SECTION();
- return newbuf;
-
-found:
- /* convert bit to bit number within page */
- bit += _hash_firstfreebit(freep[j]);
-
- /* mark page "in use" in the bitmap */
- SETBIT(freep, bit);
- _hash_wrtbuf(rel, mapbuf);
+ if (page_found)
+ {
+ Assert(BufferIsValid(mapbuf));
- /* Reacquire exclusive lock on the meta page */
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
+ /* mark page "in use" in the bitmap */
+ SETBIT(freep, bitmap_page_bit);
+ MarkBufferDirty(mapbuf);
+ }
+ else
+ {
+ /* update the count to indicate new overflow page is added */
+ metap->hashm_spares[splitnum]++;
- /* convert bit to absolute bit number */
- bit += (i << BMPG_SHIFT(metap));
+ if (BufferIsValid(newmapbuf))
+ {
+ _hash_initbitmapbuffer(newmapbuf, metap->hashm_bmsize, false);
+ MarkBufferDirty(newmapbuf);
+
+ /* add the new bitmap page to the metapage's list of bitmaps */
+ metap->hashm_mapp[metap->hashm_nmaps] = BufferGetBlockNumber(newmapbuf);
+ metap->hashm_nmaps++;
+ metap->hashm_spares[splitnum]++;
+ MarkBufferDirty(metabuf);
+ }
- /* Calculate address of the recycled overflow page */
- blkno = bitno_to_blkno(metap, bit);
+ /*
+ * for new overflow page, we don't need to explicitly set the bit in
+ * bitmap page, as by default that will be set to "in use".
+ */
+ }
/*
* Adjust hashm_firstfree to avoid redundant searches. But don't risk
@@ -319,18 +357,84 @@ found:
if (metap->hashm_firstfree == orig_firstfree)
{
metap->hashm_firstfree = bit + 1;
-
- /* Write updated metapage and release lock, but not pin */
- _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK);
+ MarkBufferDirty(metabuf);
}
- else
+
+ /* initialize new overflow page */
+ ovflpage = BufferGetPage(ovflbuf);
+ ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
+ ovflopaque->hasho_prevblkno = BufferGetBlockNumber(buf);
+ ovflopaque->hasho_nextblkno = InvalidBlockNumber;
+ ovflopaque->hasho_bucket = pageopaque->hasho_bucket;
+ ovflopaque->hasho_flag = LH_OVERFLOW_PAGE;
+ ovflopaque->hasho_page_id = HASHO_PAGE_ID;
+
+ MarkBufferDirty(ovflbuf);
+
+ /* logically chain overflow page to previous page */
+ pageopaque->hasho_nextblkno = BufferGetBlockNumber(ovflbuf);
+
+ MarkBufferDirty(buf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
{
- /* We didn't change the metapage, so no need to write */
- _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
+ XLogRecPtr recptr;
+ xl_hash_add_ovfl_page xlrec;
+
+ xlrec.bmpage_found = page_found;
+ xlrec.bmsize = metap->hashm_bmsize;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashAddOvflPage);
+
+ XLogRegisterBuffer(0, ovflbuf, REGBUF_WILL_INIT);
+ XLogRegisterBufData(0, (char *) &pageopaque->hasho_bucket, sizeof(Bucket));
+
+ XLogRegisterBuffer(1, buf, REGBUF_STANDARD);
+
+ if (BufferIsValid(mapbuf))
+ {
+ XLogRegisterBuffer(2, mapbuf, REGBUF_STANDARD);
+ XLogRegisterBufData(2, (char *) &bitmap_page_bit, sizeof(uint32));
+ }
+
+ if (BufferIsValid(newmapbuf))
+ XLogRegisterBuffer(3, newmapbuf, REGBUF_WILL_INIT);
+
+ XLogRegisterBuffer(4, metabuf, REGBUF_STANDARD);
+ XLogRegisterBufData(4, (char *) &metap->hashm_firstfree, sizeof(uint32));
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_ADD_OVFL_PAGE);
+
+ PageSetLSN(BufferGetPage(ovflbuf), recptr);
+ PageSetLSN(BufferGetPage(buf), recptr);
+
+ if (BufferIsValid(mapbuf))
+ PageSetLSN(BufferGetPage(mapbuf), recptr);
+
+ if (BufferIsValid(newmapbuf))
+ PageSetLSN(BufferGetPage(newmapbuf), recptr);
+
+ PageSetLSN(BufferGetPage(metabuf), recptr);
}
- /* Fetch, init, and return the recycled page */
- return _hash_getinitbuf(rel, blkno);
+ END_CRIT_SECTION();
+
+ if (retain_pin)
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+ else
+ _hash_relbuf(rel, buf);
+
+ if (BufferIsValid(mapbuf))
+ _hash_relbuf(rel, mapbuf);
+
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+
+ if (BufferIsValid(newmapbuf))
+ _hash_relbuf(rel, newmapbuf);
+
+ return ovflbuf;
}
/*
@@ -363,18 +467,27 @@ _hash_firstfreebit(uint32 map)
* Remove this overflow page from its bucket's chain, and mark the page as
* free. On entry, ovflbuf is write-locked; it is released before exiting.
*
+ * Add the tuples (itups) to wbuf in this function. We could do that in the
+ * caller as well, but the advantage of doing it here is we can easily write
+ * the WAL for XLOG_HASH_SQUEEZE_PAGE operation. Addition of tuples and
+ * removal of overflow page has to done as an atomic operation, otherwise
+ * during replay on standby users might find duplicate records.
+ *
* Since this function is invoked in VACUUM, we provide an access strategy
* parameter that controls fetches of the bucket pages.
*
* Returns the block number of the page that followed the given page
* in the bucket, or InvalidBlockNumber if no following page.
*
- * NB: caller must not hold lock on metapage, nor on either page that's
- * adjacent in the bucket chain. The caller had better hold exclusive lock
- * on the bucket, too.
+ * NB: caller must not hold lock on metapage, nor on page, that's next to
+ * ovflbuf in the bucket chain. We don't acquire the lock on page that's
+ * prior to ovflbuf in chain if it is same as wbuf because the caller already
+ * has a lock on same.
*/
BlockNumber
-_hash_freeovflpage(Relation rel, Buffer ovflbuf,
+_hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf,
+ Buffer wbuf, IndexTuple *itups, OffsetNumber *itup_offsets,
+ Size *tups_size, uint16 nitups,
BufferAccessStrategy bstrategy)
{
HashMetaPage metap;
@@ -384,6 +497,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf,
BlockNumber prevblkno;
BlockNumber blkno;
BlockNumber nextblkno;
+ BlockNumber writeblkno;
HashPageOpaque ovflopaque;
Page ovflpage;
Page mappage;
@@ -392,6 +506,9 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf,
int32 bitmappage,
bitmapbit;
Bucket bucket PG_USED_FOR_ASSERTS_ONLY;
+ Buffer prevbuf = InvalidBuffer;
+ Buffer nextbuf = InvalidBuffer;
+ bool update_metap = false;
/* Get information from the doomed page */
_hash_checkpage(rel, ovflbuf, LH_OVERFLOW_PAGE);
@@ -400,50 +517,32 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf,
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
nextblkno = ovflopaque->hasho_nextblkno;
prevblkno = ovflopaque->hasho_prevblkno;
+ writeblkno = BufferGetBlockNumber(wbuf);
bucket = ovflopaque->hasho_bucket;
/*
- * Zero the page for debugging's sake; then write and release it. (Note:
- * if we failed to zero the page here, we'd have problems with the Assert
- * in _hash_pageinit() when the page is reused.)
- */
- MemSet(ovflpage, 0, BufferGetPageSize(ovflbuf));
- _hash_wrtbuf(rel, ovflbuf);
-
- /*
* Fix up the bucket chain. this is a doubly-linked list, so we must fix
* up the bucket chain members behind and ahead of the overflow page being
- * deleted. No concurrency issues since we hold exclusive lock on the
- * entire bucket.
+ * deleted. Concurrency issues are avoided by using lock chaining as
+ * described atop hashbucketcleanup.
*/
if (BlockNumberIsValid(prevblkno))
{
- Buffer prevbuf = _hash_getbuf_with_strategy(rel,
- prevblkno,
- HASH_WRITE,
+ if (prevblkno == writeblkno)
+ prevbuf = wbuf;
+ else
+ prevbuf = _hash_getbuf_with_strategy(rel,
+ prevblkno,
+ HASH_WRITE,
LH_BUCKET_PAGE | LH_OVERFLOW_PAGE,
- bstrategy);
- Page prevpage = BufferGetPage(prevbuf);
- HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);
-
- Assert(prevopaque->hasho_bucket == bucket);
- prevopaque->hasho_nextblkno = nextblkno;
- _hash_wrtbuf(rel, prevbuf);
+ bstrategy);
}
if (BlockNumberIsValid(nextblkno))
- {
- Buffer nextbuf = _hash_getbuf_with_strategy(rel,
- nextblkno,
- HASH_WRITE,
- LH_OVERFLOW_PAGE,
- bstrategy);
- Page nextpage = BufferGetPage(nextbuf);
- HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);
-
- Assert(nextopaque->hasho_bucket == bucket);
- nextopaque->hasho_prevblkno = prevblkno;
- _hash_wrtbuf(rel, nextbuf);
- }
+ nextbuf = _hash_getbuf_with_strategy(rel,
+ nextblkno,
+ HASH_WRITE,
+ LH_OVERFLOW_PAGE,
+ bstrategy);
/* Note: bstrategy is intentionally not used for metapage and bitmap */
@@ -452,7 +551,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf,
metap = HashPageGetMeta(BufferGetPage(metabuf));
/* Identify which bit to set */
- ovflbitno = blkno_to_bitno(metap, ovflblkno);
+ ovflbitno = _hash_ovflblkno_to_bitno(metap, ovflblkno);
bitmappage = ovflbitno >> BMPG_SHIFT(metap);
bitmapbit = ovflbitno & BMPG_MASK(metap);
@@ -462,67 +561,193 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf,
blkno = metap->hashm_mapp[bitmappage];
/* Release metapage lock while we access the bitmap page */
- _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
- /* Clear the bitmap bit to indicate that this overflow page is free */
+ /* read the bitmap page to clear the bitmap bit */
mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE, LH_BITMAP_PAGE);
mappage = BufferGetPage(mapbuf);
freep = HashPageGetBitmap(mappage);
Assert(ISSET(freep, bitmapbit));
- CLRBIT(freep, bitmapbit);
- _hash_wrtbuf(rel, mapbuf);
/* Get write-lock on metapage to update firstfree */
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
+
+ /* This operation needs to log multiple tuples, prepare WAL for that */
+ if (RelationNeedsWAL(rel))
+ XLogEnsureRecordSpace(HASH_XLOG_FREE_OVFL_BUFS, 4 + nitups);
+
+ START_CRIT_SECTION();
+
+ /*
+ * we have to insert tuples on the "write" page, being careful to preserve
+ * hashkey ordering. (If we insert many tuples into the same "write" page
+ * it would be worth qsort'ing them).
+ */
+ if (nitups > 0)
+ {
+ _hash_pgaddmultitup(rel, wbuf, itups, itup_offsets, nitups);
+ MarkBufferDirty(wbuf);
+ }
+
+ /*
+ * Reinitialize the freed overflow page. Just zeroing the page won't
+ * work, because WAL replay routines expect pages to be initialized. See
+ * explanation of RBM_NORMAL mode atop XLogReadBufferExtended. We are
+ * careful to make the special space valid here so that tools like
+ * pageinspect won't get confused.
+ */
+ _hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
+
+ ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
+
+ ovflopaque->hasho_prevblkno = InvalidBlockNumber;
+ ovflopaque->hasho_nextblkno = InvalidBlockNumber;
+ ovflopaque->hasho_bucket = -1;
+ ovflopaque->hasho_flag = LH_UNUSED_PAGE;
+ ovflopaque->hasho_page_id = HASHO_PAGE_ID;
+
+ MarkBufferDirty(ovflbuf);
+
+ if (BufferIsValid(prevbuf))
+ {
+ Page prevpage = BufferGetPage(prevbuf);
+ HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);
+
+ Assert(prevopaque->hasho_bucket == bucket);
+ prevopaque->hasho_nextblkno = nextblkno;
+ MarkBufferDirty(prevbuf);
+ }
+ if (BufferIsValid(nextbuf))
+ {
+ Page nextpage = BufferGetPage(nextbuf);
+ HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);
+
+ Assert(nextopaque->hasho_bucket == bucket);
+ nextopaque->hasho_prevblkno = prevblkno;
+ MarkBufferDirty(nextbuf);
+ }
+
+ /* Clear the bitmap bit to indicate that this overflow page is free */
+ CLRBIT(freep, bitmapbit);
+ MarkBufferDirty(mapbuf);
/* if this is now the first free page, update hashm_firstfree */
if (ovflbitno < metap->hashm_firstfree)
{
metap->hashm_firstfree = ovflbitno;
- _hash_wrtbuf(rel, metabuf);
+ update_metap = true;
+ MarkBufferDirty(metabuf);
}
- else
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
{
- /* no need to change metapage */
- _hash_relbuf(rel, metabuf);
+ xl_hash_squeeze_page xlrec;
+ XLogRecPtr recptr;
+ int i;
+
+ xlrec.prevblkno = prevblkno;
+ xlrec.nextblkno = nextblkno;
+ xlrec.ntups = nitups;
+ xlrec.is_prim_bucket_same_wrt = (wbuf == bucketbuf);
+ xlrec.is_prev_bucket_same_wrt = (wbuf == prevbuf);
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashSqueezePage);
+
+ /*
+ * bucket buffer needs to be registered to ensure that we can acquire
+ * a cleanup lock on it during replay.
+ */
+ if (!xlrec.is_prim_bucket_same_wrt)
+ XLogRegisterBuffer(0, bucketbuf, REGBUF_STANDARD | REGBUF_NO_IMAGE);
+
+ XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD);
+ if (xlrec.ntups > 0)
+ {
+ XLogRegisterBufData(1, (char *) itup_offsets,
+ nitups * sizeof(OffsetNumber));
+ for (i = 0; i < nitups; i++)
+ XLogRegisterBufData(1, (char *) itups[i], tups_size[i]);
+ }
+
+ XLogRegisterBuffer(2, ovflbuf, REGBUF_STANDARD);
+
+ /*
+ * If prevpage and the writepage (block in which we are moving tuples
+ * from overflow) are same, then no need to separately register
+ * prevpage. During replay, we can directly update the nextblock in
+ * writepage.
+ */
+ if (BufferIsValid(prevbuf) && !xlrec.is_prev_bucket_same_wrt)
+ XLogRegisterBuffer(3, prevbuf, REGBUF_STANDARD);
+
+ if (BufferIsValid(nextbuf))
+ XLogRegisterBuffer(4, nextbuf, REGBUF_STANDARD);
+
+ XLogRegisterBuffer(5, mapbuf, REGBUF_STANDARD);
+ XLogRegisterBufData(5, (char *) &bitmapbit, sizeof(uint32));
+
+ if (update_metap)
+ {
+ XLogRegisterBuffer(6, metabuf, REGBUF_STANDARD);
+ XLogRegisterBufData(6, (char *) &metap->hashm_firstfree, sizeof(uint32));
+ }
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SQUEEZE_PAGE);
+
+ PageSetLSN(BufferGetPage(wbuf), recptr);
+ PageSetLSN(BufferGetPage(ovflbuf), recptr);
+
+ if (BufferIsValid(prevbuf) && !xlrec.is_prev_bucket_same_wrt)
+ PageSetLSN(BufferGetPage(prevbuf), recptr);
+ if (BufferIsValid(nextbuf))
+ PageSetLSN(BufferGetPage(nextbuf), recptr);
+
+ PageSetLSN(BufferGetPage(mapbuf), recptr);
+
+ if (update_metap)
+ PageSetLSN(BufferGetPage(metabuf), recptr);
}
+ END_CRIT_SECTION();
+
+ /* release previous bucket if it is not same as write bucket */
+ if (BufferIsValid(prevbuf) && prevblkno != writeblkno)
+ _hash_relbuf(rel, prevbuf);
+
+ if (BufferIsValid(ovflbuf))
+ _hash_relbuf(rel, ovflbuf);
+
+ if (BufferIsValid(nextbuf))
+ _hash_relbuf(rel, nextbuf);
+
+ _hash_relbuf(rel, mapbuf);
+ _hash_relbuf(rel, metabuf);
+
return nextblkno;
}
/*
- * _hash_initbitmap()
- *
- * Initialize a new bitmap page. The metapage has a write-lock upon
- * entering the function, and must be written by caller after return.
+ * _hash_initbitmapbuffer()
*
- * 'blkno' is the block number of the new bitmap page.
- *
- * All bits in the new bitmap page are set to "1", indicating "in use".
+ * Initialize a new bitmap page. All bits in the new bitmap page are set to
+ * "1", indicating "in use".
*/
void
-_hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno,
- ForkNumber forkNum)
+_hash_initbitmapbuffer(Buffer buf, uint16 bmsize, bool initpage)
{
- Buffer buf;
Page pg;
HashPageOpaque op;
uint32 *freep;
- /*
- * It is okay to write-lock the new bitmap page while holding metapage
- * write lock, because no one else could be contending for the new page.
- * Also, the metapage lock makes it safe to extend the index using
- * _hash_getnewbuf.
- *
- * There is some loss of concurrency in possibly doing I/O for the new
- * page while holding the metapage lock, but this path is taken so seldom
- * that it's not worth worrying about.
- */
- buf = _hash_getnewbuf(rel, blkno, forkNum);
pg = BufferGetPage(buf);
+ /* initialize the page */
+ if (initpage)
+ _hash_pageinit(pg, BufferGetPageSize(buf));
+
/* initialize the page's special space */
op = (HashPageOpaque) PageGetSpecialPointer(pg);
op->hasho_prevblkno = InvalidBlockNumber;
@@ -533,22 +758,14 @@ _hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno,
/* set all of the bits to 1 */
freep = HashPageGetBitmap(pg);
- MemSet(freep, 0xFF, BMPGSZ_BYTE(metap));
-
- /* write out the new bitmap page (releasing write lock and pin) */
- _hash_wrtbuf(rel, buf);
+ MemSet(freep, 0xFF, bmsize);
- /* add the new bitmap page to the metapage's list of bitmaps */
- /* metapage already has a write lock */
- if (metap->hashm_nmaps >= HASH_MAX_BITMAPS)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("out of overflow pages in hash index \"%s\"",
- RelationGetRelationName(rel))));
-
- metap->hashm_mapp[metap->hashm_nmaps] = blkno;
-
- metap->hashm_nmaps++;
+ /*
+ * Set pd_lower just past the end of the bitmap page data. We could even
+ * set pd_lower equal to pd_upper, but this is more precise and makes the
+ * page look compressible to xlog.c.
+ */
+ ((PageHeader) pg)->pd_lower = ((char *) freep + bmsize) - (char *) pg;
}
@@ -570,8 +787,15 @@ _hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno,
* required that to be true on entry as well, but it's a lot easier for
* callers to leave empty overflow pages and let this guy clean it up.
*
- * Caller must hold exclusive lock on the target bucket. This allows
- * us to safely lock multiple pages in the bucket.
+ * Caller must acquire cleanup lock on the primary page of the target
+ * bucket to exclude any scans that are in progress, which could easily
+ * be confused into returning the same tuple more than once or some tuples
+ * not at all by the rearrangement we are performing here. To prevent
+ * any concurrent scan to cross the squeeze scan we use lock chaining
+ * similar to hasbucketcleanup. Refer comments atop hashbucketcleanup.
+ *
+ * We need to retain a pin on the primary bucket to ensure that no concurrent
+ * split can start.
*
* Since this function is invoked in VACUUM, we provide an access strategy
* parameter that controls fetches of the bucket pages.
@@ -580,6 +804,7 @@ void
_hash_squeezebucket(Relation rel,
Bucket bucket,
BlockNumber bucket_blkno,
+ Buffer bucket_buf,
BufferAccessStrategy bstrategy)
{
BlockNumber wblkno;
@@ -590,26 +815,22 @@ _hash_squeezebucket(Relation rel,
Page rpage;
HashPageOpaque wopaque;
HashPageOpaque ropaque;
- bool wbuf_dirty;
/*
- * start squeezing into the base bucket page.
+ * start squeezing into the primary bucket page.
*/
wblkno = bucket_blkno;
- wbuf = _hash_getbuf_with_strategy(rel,
- wblkno,
- HASH_WRITE,
- LH_BUCKET_PAGE,
- bstrategy);
+ wbuf = bucket_buf;
wpage = BufferGetPage(wbuf);
wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);
/*
- * if there aren't any overflow pages, there's nothing to squeeze.
+ * if there aren't any overflow pages, there's nothing to squeeze. caller
+ * is responsible for releasing the pin on primary bucket page.
*/
if (!BlockNumberIsValid(wopaque->hasho_nextblkno))
{
- _hash_relbuf(rel, wbuf);
+ LockBuffer(wbuf, BUFFER_LOCK_UNLOCK);
return;
}
@@ -639,14 +860,21 @@ _hash_squeezebucket(Relation rel,
/*
* squeeze the tuples.
*/
- wbuf_dirty = false;
for (;;)
{
OffsetNumber roffnum;
OffsetNumber maxroffnum;
OffsetNumber deletable[MaxOffsetNumber];
- int ndeletable = 0;
-
+ IndexTuple itups[MaxIndexTuplesPerPage];
+ Size tups_size[MaxIndexTuplesPerPage];
+ OffsetNumber itup_offsets[MaxIndexTuplesPerPage];
+ uint16 ndeletable = 0;
+ uint16 nitups = 0;
+ Size all_tups_size = 0;
+ int i;
+ bool retain_pin = false;
+
+readpage:
/* Scan each tuple in "read" page */
maxroffnum = PageGetMaxOffsetNumber(rpage);
for (roffnum = FirstOffsetNumber;
@@ -656,6 +884,10 @@ _hash_squeezebucket(Relation rel,
IndexTuple itup;
Size itemsz;
+ /* skip dead tuples */
+ if (ItemIdIsDead(PageGetItemId(rpage, roffnum)))
+ continue;
+
itup = (IndexTuple) PageGetItem(rpage,
PageGetItemId(rpage, roffnum));
itemsz = IndexTupleDSize(*itup);
@@ -663,56 +895,144 @@ _hash_squeezebucket(Relation rel,
/*
* Walk up the bucket chain, looking for a page big enough for
- * this item. Exit if we reach the read page.
+ * this item and all other accumulated items. Exit if we reach
+ * the read page.
*/
- while (PageGetFreeSpace(wpage) < itemsz)
+ while (PageGetFreeSpaceForMultipleTuples(wpage, nitups + 1) < (all_tups_size + itemsz))
{
+ Buffer next_wbuf = InvalidBuffer;
+ bool tups_moved = false;
+
Assert(!PageIsEmpty(wpage));
+ if (wblkno == bucket_blkno)
+ retain_pin = true;
+
wblkno = wopaque->hasho_nextblkno;
Assert(BlockNumberIsValid(wblkno));
- if (wbuf_dirty)
- _hash_wrtbuf(rel, wbuf);
+ /* don't need to move to next page if we reached the read page */
+ if (wblkno != rblkno)
+ next_wbuf = _hash_getbuf_with_strategy(rel,
+ wblkno,
+ HASH_WRITE,
+ LH_OVERFLOW_PAGE,
+ bstrategy);
+
+ if (nitups > 0)
+ {
+ Assert(nitups == ndeletable);
+
+ /*
+ * This operation needs to log multiple tuples, prepare
+ * WAL for that.
+ */
+ if (RelationNeedsWAL(rel))
+ XLogEnsureRecordSpace(0, 3 + nitups);
+
+ START_CRIT_SECTION();
+
+ /*
+ * we have to insert tuples on the "write" page, being
+ * careful to preserve hashkey ordering. (If we insert
+ * many tuples into the same "write" page it would be
+ * worth qsort'ing them).
+ */
+ _hash_pgaddmultitup(rel, wbuf, itups, itup_offsets, nitups);
+ MarkBufferDirty(wbuf);
+
+ /* Delete tuples we already moved off read page */
+ PageIndexMultiDelete(rpage, deletable, ndeletable);
+ MarkBufferDirty(rbuf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ XLogRecPtr recptr;
+ xl_hash_move_page_contents xlrec;
+
+ xlrec.ntups = nitups;
+ xlrec.is_prim_bucket_same_wrt = (wbuf == bucket_buf) ? true : false;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashMovePageContents);
+
+ /*
+ * bucket buffer needs to be registered to ensure that
+ * we can acquire a cleanup lock on it during replay.
+ */
+ if (!xlrec.is_prim_bucket_same_wrt)
+ XLogRegisterBuffer(0, bucket_buf, REGBUF_STANDARD | REGBUF_NO_IMAGE);
+
+ XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD);
+ XLogRegisterBufData(1, (char *) itup_offsets,
+ nitups * sizeof(OffsetNumber));
+ for (i = 0; i < nitups; i++)
+ XLogRegisterBufData(1, (char *) itups[i], tups_size[i]);
+
+ XLogRegisterBuffer(2, rbuf, REGBUF_STANDARD);
+ XLogRegisterBufData(2, (char *) deletable,
+ ndeletable * sizeof(OffsetNumber));
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_MOVE_PAGE_CONTENTS);
+
+ PageSetLSN(BufferGetPage(wbuf), recptr);
+ PageSetLSN(BufferGetPage(rbuf), recptr);
+ }
+
+ END_CRIT_SECTION();
+
+ tups_moved = true;
+ }
+
+ /*
+ * release the lock on previous page after acquiring the lock
+ * on next page
+ */
+ if (retain_pin)
+ LockBuffer(wbuf, BUFFER_LOCK_UNLOCK);
else
_hash_relbuf(rel, wbuf);
/* nothing more to do if we reached the read page */
if (rblkno == wblkno)
{
- if (ndeletable > 0)
- {
- /* Delete tuples we already moved off read page */
- PageIndexMultiDelete(rpage, deletable, ndeletable);
- _hash_wrtbuf(rel, rbuf);
- }
- else
- _hash_relbuf(rel, rbuf);
+ _hash_relbuf(rel, rbuf);
return;
}
- wbuf = _hash_getbuf_with_strategy(rel,
- wblkno,
- HASH_WRITE,
- LH_OVERFLOW_PAGE,
- bstrategy);
+ wbuf = next_wbuf;
wpage = BufferGetPage(wbuf);
wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);
Assert(wopaque->hasho_bucket == bucket);
- wbuf_dirty = false;
+ retain_pin = false;
+
+ /* be tidy */
+ for (i = 0; i < nitups; i++)
+ pfree(itups[i]);
+ nitups = 0;
+ all_tups_size = 0;
+ ndeletable = 0;
+
+ /*
+ * after moving the tuples, rpage would have been compacted,
+ * so we need to rescan it.
+ */
+ if (tups_moved)
+ goto readpage;
}
- /*
- * we have found room so insert on the "write" page, being careful
- * to preserve hashkey ordering. (If we insert many tuples into
- * the same "write" page it would be worth qsort'ing instead of
- * doing repeated _hash_pgaddtup.)
- */
- (void) _hash_pgaddtup(rel, wbuf, itemsz, itup);
- wbuf_dirty = true;
-
/* remember tuple for deletion from "read" page */
deletable[ndeletable++] = roffnum;
+
+ /*
+ * we need a copy of index tuples as they can be freed as part of
+ * overflow page, however we need them to write a WAL record in
+ * _hash_freeovflpage.
+ */
+ itups[nitups] = CopyIndexTuple(itup);
+ tups_size[nitups++] = itemsz;
+ all_tups_size += itemsz;
}
/*
@@ -724,29 +1044,30 @@ _hash_squeezebucket(Relation rel,
* Tricky point here: if our read and write pages are adjacent in the
* bucket chain, our write lock on wbuf will conflict with
* _hash_freeovflpage's attempt to update the sibling links of the
- * removed page. However, in that case we are done anyway, so we can
- * simply drop the write lock before calling _hash_freeovflpage.
+ * removed page. In that case, we don't need to lock it again.
*/
rblkno = ropaque->hasho_prevblkno;
Assert(BlockNumberIsValid(rblkno));
+ /* free this overflow page (releases rbuf) */
+ _hash_freeovflpage(rel, bucket_buf, rbuf, wbuf, itups, itup_offsets,
+ tups_size, nitups, bstrategy);
+
+ /* be tidy */
+ for (i = 0; i < nitups; i++)
+ pfree(itups[i]);
+
/* are we freeing the page adjacent to wbuf? */
if (rblkno == wblkno)
{
- /* yes, so release wbuf lock first */
- if (wbuf_dirty)
- _hash_wrtbuf(rel, wbuf);
+ /* retain the pin on primary bucket page till end of bucket scan */
+ if (wblkno == bucket_blkno)
+ LockBuffer(wbuf, BUFFER_LOCK_UNLOCK);
else
_hash_relbuf(rel, wbuf);
- /* free this overflow page (releases rbuf) */
- _hash_freeovflpage(rel, rbuf, bstrategy);
- /* done */
return;
}
- /* free this overflow page, then get the previous one */
- _hash_freeovflpage(rel, rbuf, bstrategy);
-
rbuf = _hash_getbuf_with_strategy(rel,
rblkno,
HASH_WRITE,
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 178463fcb6..4544889294 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -3,7 +3,7 @@
* hashpage.c
* Hash table page management code for the Postgres hash access method
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -29,6 +29,7 @@
#include "postgres.h"
#include "access/hash.h"
+#include "access/hash_xlog.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
@@ -38,10 +39,12 @@ static bool _hash_alloc_buckets(Relation rel, BlockNumber firstblock,
uint32 nblocks);
static void _hash_splitbucket(Relation rel, Buffer metabuf,
Bucket obucket, Bucket nbucket,
- BlockNumber start_oblkno,
+ Buffer obuf,
Buffer nbuf,
+ HTAB *htab,
uint32 maxbucket,
uint32 highmask, uint32 lowmask);
+static void log_split_page(Relation rel, Buffer buf);
/*
@@ -55,46 +58,6 @@ static void _hash_splitbucket(Relation rel, Buffer metabuf,
/*
- * _hash_getlock() -- Acquire an lmgr lock.
- *
- * 'whichlock' should the block number of a bucket's primary bucket page to
- * acquire the per-bucket lock. (See README for details of the use of these
- * locks.)
- *
- * 'access' must be HASH_SHARE or HASH_EXCLUSIVE.
- */
-void
-_hash_getlock(Relation rel, BlockNumber whichlock, int access)
-{
- if (USELOCKING(rel))
- LockPage(rel, whichlock, access);
-}
-
-/*
- * _hash_try_getlock() -- Acquire an lmgr lock, but only if it's free.
- *
- * Same as above except we return FALSE without blocking if lock isn't free.
- */
-bool
-_hash_try_getlock(Relation rel, BlockNumber whichlock, int access)
-{
- if (USELOCKING(rel))
- return ConditionalLockPage(rel, whichlock, access);
- else
- return true;
-}
-
-/*
- * _hash_droplock() -- Release an lmgr lock.
- */
-void
-_hash_droplock(Relation rel, BlockNumber whichlock, int access)
-{
- if (USELOCKING(rel))
- UnlockPage(rel, whichlock, access);
-}
-
-/*
* _hash_getbuf() -- Get a buffer by block number for read or write.
*
* 'access' must be HASH_READ, HASH_WRITE, or HASH_NOLOCK.
@@ -132,6 +95,35 @@ _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
}
/*
+ * _hash_getbuf_with_condlock_cleanup() -- Try to get a buffer for cleanup.
+ *
+ * We read the page and try to acquire a cleanup lock. If we get it,
+ * we return the buffer; otherwise, we return InvalidBuffer.
+ */
+Buffer
+_hash_getbuf_with_condlock_cleanup(Relation rel, BlockNumber blkno, int flags)
+{
+ Buffer buf;
+
+ if (blkno == P_NEW)
+ elog(ERROR, "hash AM does not use P_NEW");
+
+ buf = ReadBuffer(rel, blkno);
+
+ if (!ConditionalLockBufferForCleanup(buf))
+ {
+ ReleaseBuffer(buf);
+ return InvalidBuffer;
+ }
+
+ /* ref count and lock type are correct */
+
+ _hash_checkpage(rel, buf, flags);
+
+ return buf;
+}
+
+/*
* _hash_getinitbuf() -- Get and initialize a buffer by block number.
*
* This must be used only to fetch pages that are known to be before
@@ -167,6 +159,36 @@ _hash_getinitbuf(Relation rel, BlockNumber blkno)
}
/*
+ * _hash_initbuf() -- Get and initialize a buffer by bucket number.
+ */
+void
+_hash_initbuf(Buffer buf, uint32 max_bucket, uint32 num_bucket, uint32 flag,
+ bool initpage)
+{
+ HashPageOpaque pageopaque;
+ Page page;
+
+ page = BufferGetPage(buf);
+
+ /* initialize the page */
+ if (initpage)
+ _hash_pageinit(page, BufferGetPageSize(buf));
+
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+
+ /*
+ * Set hasho_prevblkno with current hashm_maxbucket. This value will be
+ * used to validate cached HashMetaPageData. See
+ * _hash_getbucketbuf_from_hashkey().
+ */
+ pageopaque->hasho_prevblkno = max_bucket;
+ pageopaque->hasho_nextblkno = InvalidBlockNumber;
+ pageopaque->hasho_bucket = num_bucket;
+ pageopaque->hasho_flag = flag;
+ pageopaque->hasho_page_id = HASHO_PAGE_ID;
+}
+
+/*
* _hash_getnewbuf() -- Get a new page at the end of the index.
*
* This has the same API as _hash_getinitbuf, except that we are adding
@@ -266,53 +288,39 @@ _hash_dropbuf(Relation rel, Buffer buf)
}
/*
- * _hash_wrtbuf() -- write a hash page to disk.
+ * _hash_dropscanbuf() -- release buffers used in scan.
*
- * This routine releases the lock held on the buffer and our refcount
- * for it. It is an error to call _hash_wrtbuf() without a write lock
- * and a pin on the buffer.
- *
- * NOTE: this routine should go away when/if hash indexes are WAL-ified.
- * The correct sequence of operations is to mark the buffer dirty, then
- * write the WAL record, then release the lock and pin; so marking dirty
- * can't be combined with releasing.
+ * This routine unpins the buffers used during scan on which we
+ * hold no lock.
*/
void
-_hash_wrtbuf(Relation rel, Buffer buf)
+_hash_dropscanbuf(Relation rel, HashScanOpaque so)
{
- MarkBufferDirty(buf);
- UnlockReleaseBuffer(buf);
-}
-
-/*
- * _hash_chgbufaccess() -- Change the lock type on a buffer, without
- * dropping our pin on it.
- *
- * from_access and to_access may be HASH_READ, HASH_WRITE, or HASH_NOLOCK,
- * the last indicating that no buffer-level lock is held or wanted.
- *
- * When from_access == HASH_WRITE, we assume the buffer is dirty and tell
- * bufmgr it must be written out. If the caller wants to release a write
- * lock on a page that's not been modified, it's okay to pass from_access
- * as HASH_READ (a bit ugly, but handy in some places).
- */
-void
-_hash_chgbufaccess(Relation rel,
- Buffer buf,
- int from_access,
- int to_access)
-{
- if (from_access == HASH_WRITE)
- MarkBufferDirty(buf);
- if (from_access != HASH_NOLOCK)
- LockBuffer(buf, BUFFER_LOCK_UNLOCK);
- if (to_access != HASH_NOLOCK)
- LockBuffer(buf, to_access);
+ /* release pin we hold on primary bucket page */
+ if (BufferIsValid(so->hashso_bucket_buf) &&
+ so->hashso_bucket_buf != so->hashso_curbuf)
+ _hash_dropbuf(rel, so->hashso_bucket_buf);
+ so->hashso_bucket_buf = InvalidBuffer;
+
+ /* release pin we hold on primary bucket page of bucket being split */
+ if (BufferIsValid(so->hashso_split_bucket_buf) &&
+ so->hashso_split_bucket_buf != so->hashso_curbuf)
+ _hash_dropbuf(rel, so->hashso_split_bucket_buf);
+ so->hashso_split_bucket_buf = InvalidBuffer;
+
+ /* release any pin we still hold */
+ if (BufferIsValid(so->hashso_curbuf))
+ _hash_dropbuf(rel, so->hashso_curbuf);
+ so->hashso_curbuf = InvalidBuffer;
+
+ /* reset split scan */
+ so->hashso_buc_populated = false;
+ so->hashso_buc_split = false;
}
/*
- * _hash_metapinit() -- Initialize the metadata page of a hash index,
+ * _hash_init() -- Initialize the metadata page of a hash index,
* the initial buckets, and the initial bitmap page.
*
* The initial number of buckets is dependent on num_tuples, an estimate
@@ -324,19 +332,18 @@ _hash_chgbufaccess(Relation rel,
* multiple buffer locks is ignored.
*/
uint32
-_hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
+_hash_init(Relation rel, double num_tuples, ForkNumber forkNum)
{
- HashMetaPage metap;
- HashPageOpaque pageopaque;
Buffer metabuf;
Buffer buf;
+ Buffer bitmapbuf;
Page pg;
+ HashMetaPage metap;
+ RegProcedure procid;
int32 data_width;
int32 item_width;
int32 ffactor;
- double dnumbuckets;
uint32 num_buckets;
- uint32 log2_num_buckets;
uint32 i;
/* safety check */
@@ -358,10 +365,151 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
if (ffactor < 10)
ffactor = 10;
+ procid = index_getprocid(rel, 1, HASHPROC);
+
+ /*
+ * We initialize the metapage, the first N bucket pages, and the first
+ * bitmap page in sequence, using _hash_getnewbuf to cause smgrextend()
+ * calls to occur. This ensures that the smgr level has the right idea of
+ * the physical index length.
+ *
+ * Critical section not required, because on error the creation of the
+ * whole relation will be rolled back.
+ */
+ metabuf = _hash_getnewbuf(rel, HASH_METAPAGE, forkNum);
+ _hash_init_metabuffer(metabuf, num_tuples, procid, ffactor, false);
+ MarkBufferDirty(metabuf);
+
+ pg = BufferGetPage(metabuf);
+ metap = HashPageGetMeta(pg);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_init_meta_page xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.num_tuples = num_tuples;
+ xlrec.procid = metap->hashm_procid;
+ xlrec.ffactor = metap->hashm_ffactor;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashInitMetaPage);
+ XLogRegisterBuffer(0, metabuf, REGBUF_WILL_INIT);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INIT_META_PAGE);
+
+ PageSetLSN(BufferGetPage(metabuf), recptr);
+ }
+
+ num_buckets = metap->hashm_maxbucket + 1;
+
+ /*
+ * Release buffer lock on the metapage while we initialize buckets.
+ * Otherwise, we'll be in interrupt holdoff and the CHECK_FOR_INTERRUPTS
+ * won't accomplish anything. It's a bad idea to hold buffer locks for
+ * long intervals in any case, since that can block the bgwriter.
+ */
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+
+ /*
+ * Initialize and WAL Log the first N buckets
+ */
+ for (i = 0; i < num_buckets; i++)
+ {
+ BlockNumber blkno;
+
+ /* Allow interrupts, in case N is huge */
+ CHECK_FOR_INTERRUPTS();
+
+ blkno = BUCKET_TO_BLKNO(metap, i);
+ buf = _hash_getnewbuf(rel, blkno, forkNum);
+ _hash_initbuf(buf, metap->hashm_maxbucket, i, LH_BUCKET_PAGE, false);
+ MarkBufferDirty(buf);
+
+ log_newpage(&rel->rd_node,
+ forkNum,
+ blkno,
+ BufferGetPage(buf),
+ true);
+ _hash_relbuf(rel, buf);
+ }
+
+ /* Now reacquire buffer lock on metapage */
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
+
+ /*
+ * Initialize bitmap page
+ */
+ bitmapbuf = _hash_getnewbuf(rel, num_buckets + 1, forkNum);
+ _hash_initbitmapbuffer(bitmapbuf, metap->hashm_bmsize, false);
+ MarkBufferDirty(bitmapbuf);
+
+ /* add the new bitmap page to the metapage's list of bitmaps */
+ /* metapage already has a write lock */
+ if (metap->hashm_nmaps >= HASH_MAX_BITMAPS)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("out of overflow pages in hash index \"%s\"",
+ RelationGetRelationName(rel))));
+
+ metap->hashm_mapp[metap->hashm_nmaps] = num_buckets + 1;
+
+ metap->hashm_nmaps++;
+ MarkBufferDirty(metabuf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_init_bitmap_page xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.bmsize = metap->hashm_bmsize;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, SizeOfHashInitBitmapPage);
+ XLogRegisterBuffer(0, bitmapbuf, REGBUF_WILL_INIT);
+
+ /*
+ * This is safe only because nobody else can be modifying the index at
+ * this stage; it's only visible to the transaction that is creating
+ * it.
+ */
+ XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INIT_BITMAP_PAGE);
+
+ PageSetLSN(BufferGetPage(bitmapbuf), recptr);
+ PageSetLSN(BufferGetPage(metabuf), recptr);
+ }
+
+ /* all done */
+ _hash_relbuf(rel, bitmapbuf);
+ _hash_relbuf(rel, metabuf);
+
+ return num_buckets;
+}
+
+/*
+ * _hash_init_metabuffer() -- Initialize the metadata page of a hash index.
+ */
+void
+_hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
+ uint16 ffactor, bool initpage)
+{
+ HashMetaPage metap;
+ HashPageOpaque pageopaque;
+ Page page;
+ double dnumbuckets;
+ uint32 num_buckets;
+ uint32 spare_index;
+ uint32 i;
+
/*
* Choose the number of initial bucket pages to match the fill factor
* given the estimated number of tuples. We round up the result to the
- * next power of 2, however, and always force at least 2 bucket pages. The
+ * total number of buckets which has to be allocated before using its
+ * _hashm_spare element. However always force at least 2 bucket pages. The
* upper limit is determined by considerations explained in
* _hash_expandtable().
*/
@@ -371,36 +519,30 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
else if (dnumbuckets >= (double) 0x40000000)
num_buckets = 0x40000000;
else
- num_buckets = ((uint32) 1) << _hash_log2((uint32) dnumbuckets);
+ num_buckets = _hash_get_totalbuckets(_hash_spareindex(dnumbuckets));
- log2_num_buckets = _hash_log2(num_buckets);
- Assert(num_buckets == (((uint32) 1) << log2_num_buckets));
- Assert(log2_num_buckets < HASH_MAX_SPLITPOINTS);
+ spare_index = _hash_spareindex(num_buckets);
+ Assert(spare_index < HASH_MAX_SPLITPOINTS);
- /*
- * We initialize the metapage, the first N bucket pages, and the first
- * bitmap page in sequence, using _hash_getnewbuf to cause smgrextend()
- * calls to occur. This ensures that the smgr level has the right idea of
- * the physical index length.
- */
- metabuf = _hash_getnewbuf(rel, HASH_METAPAGE, forkNum);
- pg = BufferGetPage(metabuf);
+ page = BufferGetPage(buf);
+ if (initpage)
+ _hash_pageinit(page, BufferGetPageSize(buf));
- pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg);
+ pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
pageopaque->hasho_prevblkno = InvalidBlockNumber;
pageopaque->hasho_nextblkno = InvalidBlockNumber;
pageopaque->hasho_bucket = -1;
pageopaque->hasho_flag = LH_META_PAGE;
pageopaque->hasho_page_id = HASHO_PAGE_ID;
- metap = HashPageGetMeta(pg);
+ metap = HashPageGetMeta(page);
metap->hashm_magic = HASH_MAGIC;
metap->hashm_version = HASH_VERSION;
metap->hashm_ntuples = 0;
metap->hashm_nmaps = 0;
metap->hashm_ffactor = ffactor;
- metap->hashm_bsize = HashGetMaxBitmapSize(pg);
+ metap->hashm_bsize = HashGetMaxBitmapSize(page);
/* find largest bitmap array size that will fit in page size */
for (i = _hash_log2(metap->hashm_bsize); i > 0; --i)
{
@@ -417,63 +559,35 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
* pretty useless for normal operation (in fact, hashm_procid is not used
* anywhere), but it might be handy for forensic purposes so we keep it.
*/
- metap->hashm_procid = index_getprocid(rel, 1, HASHPROC);
+ metap->hashm_procid = procid;
/*
* We initialize the index with N buckets, 0 .. N-1, occupying physical
- * blocks 1 to N. The first freespace bitmap page is in block N+1. Since
- * N is a power of 2, we can set the masks this way:
+ * blocks 1 to N. The first freespace bitmap page is in block N+1.
*/
- metap->hashm_maxbucket = metap->hashm_lowmask = num_buckets - 1;
- metap->hashm_highmask = (num_buckets << 1) - 1;
+ metap->hashm_maxbucket = num_buckets - 1;
+
+ /*
+ * Set highmask as next immediate ((2 ^ x) - 1), which should be
+ * sufficient to cover num_buckets.
+ */
+ metap->hashm_highmask = (1 << (_hash_log2(num_buckets + 1))) - 1;
+ metap->hashm_lowmask = (metap->hashm_highmask >> 1);
MemSet(metap->hashm_spares, 0, sizeof(metap->hashm_spares));
MemSet(metap->hashm_mapp, 0, sizeof(metap->hashm_mapp));
/* Set up mapping for one spare page after the initial splitpoints */
- metap->hashm_spares[log2_num_buckets] = 1;
- metap->hashm_ovflpoint = log2_num_buckets;
+ metap->hashm_spares[spare_index] = 1;
+ metap->hashm_ovflpoint = spare_index;
metap->hashm_firstfree = 0;
/*
- * Release buffer lock on the metapage while we initialize buckets.
- * Otherwise, we'll be in interrupt holdoff and the CHECK_FOR_INTERRUPTS
- * won't accomplish anything. It's a bad idea to hold buffer locks for
- * long intervals in any case, since that can block the bgwriter.
- */
- _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK);
-
- /*
- * Initialize the first N buckets
- */
- for (i = 0; i < num_buckets; i++)
- {
- /* Allow interrupts, in case N is huge */
- CHECK_FOR_INTERRUPTS();
-
- buf = _hash_getnewbuf(rel, BUCKET_TO_BLKNO(metap, i), forkNum);
- pg = BufferGetPage(buf);
- pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg);
- pageopaque->hasho_prevblkno = InvalidBlockNumber;
- pageopaque->hasho_nextblkno = InvalidBlockNumber;
- pageopaque->hasho_bucket = i;
- pageopaque->hasho_flag = LH_BUCKET_PAGE;
- pageopaque->hasho_page_id = HASHO_PAGE_ID;
- _hash_wrtbuf(rel, buf);
- }
-
- /* Now reacquire buffer lock on metapage */
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
-
- /*
- * Initialize first bitmap page
+ * Set pd_lower just past the end of the metadata. This is to log full
+ * page image of metapage in xloginsert.c.
*/
- _hash_initbitmap(rel, metap, num_buckets + 1, forkNum);
-
- /* all done */
- _hash_wrtbuf(rel, metabuf);
-
- return num_buckets;
+ ((PageHeader) page)->pd_lower =
+ ((char *) metap + sizeof(HashMetaPageData)) - (char *) page;
}
/*
@@ -482,16 +596,17 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
void
_hash_pageinit(Page page, Size size)
{
- Assert(PageIsNew(page));
PageInit(page, size, sizeof(HashPageOpaqueData));
}
/*
* Attempt to expand the hash table by creating one new bucket.
*
- * This will silently do nothing if it cannot get the needed locks.
+ * This will silently do nothing if we don't get cleanup lock on old or
+ * new bucket.
*
- * The caller should hold no locks on the hash index.
+ * Complete the pending splits and remove the tuples from old bucket,
+ * if there are any left over from the previous split.
*
* The caller must hold a pin, but no lock, on the metapage buffer.
* The buffer is returned in the same state.
@@ -506,15 +621,24 @@ _hash_expandtable(Relation rel, Buffer metabuf)
BlockNumber start_oblkno;
BlockNumber start_nblkno;
Buffer buf_nblkno;
+ Buffer buf_oblkno;
+ Page opage;
+ Page npage;
+ HashPageOpaque oopaque;
+ HashPageOpaque nopaque;
uint32 maxbucket;
uint32 highmask;
uint32 lowmask;
+ bool metap_update_masks = false;
+ bool metap_update_splitpoint = false;
+
+restart_expand:
/*
* Write-lock the meta page. It used to be necessary to acquire a
* heavyweight lock to begin a split, but that is no longer required.
*/
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
+ LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
_hash_checkpage(rel, metabuf, LH_META_PAGE);
metap = HashPageGetMeta(BufferGetPage(metabuf));
@@ -542,17 +666,22 @@ _hash_expandtable(Relation rel, Buffer metabuf)
* than a disk block then this would be an independent constraint.
*
* If you change this, see also the maximum initial number of buckets in
- * _hash_metapinit().
+ * _hash_init().
*/
if (metap->hashm_maxbucket >= (uint32) 0x7FFFFFFE)
goto fail;
/*
- * Determine which bucket is to be split, and attempt to lock the old
- * bucket. If we can't get the lock, give up.
+ * Determine which bucket is to be split, and attempt to take cleanup lock
+ * on the old bucket. If we can't get the lock, give up.
+ *
+ * The cleanup lock protects us not only against other backends, but
+ * against our own backend as well.
*
- * The lock protects us against other backends, but not against our own
- * backend. Must check for active scans separately.
+ * The cleanup lock is mainly to protect the split from concurrent
+ * inserts. See src/backend/access/hash/README, Lock Definitions for
+ * further details. Due to this locking restriction, if there is any
+ * pending scan, the split will give up which is not good, but harmless.
*/
new_bucket = metap->hashm_maxbucket + 1;
@@ -560,14 +689,86 @@ _hash_expandtable(Relation rel, Buffer metabuf)
start_oblkno = BUCKET_TO_BLKNO(metap, old_bucket);
- if (_hash_has_active_scan(rel, old_bucket))
+ buf_oblkno = _hash_getbuf_with_condlock_cleanup(rel, start_oblkno, LH_BUCKET_PAGE);
+ if (!buf_oblkno)
goto fail;
- if (!_hash_try_getlock(rel, start_oblkno, HASH_EXCLUSIVE))
- goto fail;
+ opage = BufferGetPage(buf_oblkno);
+ oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
+
+ /*
+ * We want to finish the split from a bucket as there is no apparent
+ * benefit by not doing so and it will make the code complicated to finish
+ * the split that involves multiple buckets considering the case where new
+ * split also fails. We don't need to consider the new bucket for
+ * completing the split here as it is not possible that a re-split of new
+ * bucket starts when there is still a pending split from old bucket.
+ */
+ if (H_BUCKET_BEING_SPLIT(oopaque))
+ {
+ /*
+ * Copy bucket mapping info now; refer the comment in code below where
+ * we copy this information before calling _hash_splitbucket to see
+ * why this is okay.
+ */
+ maxbucket = metap->hashm_maxbucket;
+ highmask = metap->hashm_highmask;
+ lowmask = metap->hashm_lowmask;
+
+ /*
+ * Release the lock on metapage and old_bucket, before completing the
+ * split.
+ */
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+ LockBuffer(buf_oblkno, BUFFER_LOCK_UNLOCK);
+
+ _hash_finish_split(rel, metabuf, buf_oblkno, old_bucket, maxbucket,
+ highmask, lowmask);
+
+ /* release the pin on old buffer and retry for expand. */
+ _hash_dropbuf(rel, buf_oblkno);
+
+ goto restart_expand;
+ }
/*
- * Likewise lock the new bucket (should never fail).
+ * Clean the tuples remained from the previous split. This operation
+ * requires cleanup lock and we already have one on the old bucket, so
+ * let's do it. We also don't want to allow further splits from the bucket
+ * till the garbage of previous split is cleaned. This has two
+ * advantages; first, it helps in avoiding the bloat due to garbage and
+ * second is, during cleanup of bucket, we are always sure that the
+ * garbage tuples belong to most recently split bucket. On the contrary,
+ * if we allow cleanup of bucket after meta page is updated to indicate
+ * the new split and before the actual split, the cleanup operation won't
+ * be able to decide whether the tuple has been moved to the newly created
+ * bucket and ended up deleting such tuples.
+ */
+ if (H_NEEDS_SPLIT_CLEANUP(oopaque))
+ {
+ /*
+ * Copy bucket mapping info now; refer to the comment in code below
+ * where we copy this information before calling _hash_splitbucket to
+ * see why this is okay.
+ */
+ maxbucket = metap->hashm_maxbucket;
+ highmask = metap->hashm_highmask;
+ lowmask = metap->hashm_lowmask;
+
+ /* Release the metapage lock. */
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
+
+ hashbucketcleanup(rel, old_bucket, buf_oblkno, start_oblkno, NULL,
+ maxbucket, highmask, lowmask, NULL, NULL, true,
+ NULL, NULL);
+
+ _hash_dropbuf(rel, buf_oblkno);
+
+ goto restart_expand;
+ }
+
+ /*
+ * There shouldn't be any active scan on new bucket.
*
* Note: it is safe to compute the new bucket's blkno here, even though we
* may still need to update the BUCKET_TO_BLKNO mapping. This is because
@@ -576,32 +777,28 @@ _hash_expandtable(Relation rel, Buffer metabuf)
*/
start_nblkno = BUCKET_TO_BLKNO(metap, new_bucket);
- if (_hash_has_active_scan(rel, new_bucket))
- elog(ERROR, "scan in progress on supposedly new bucket");
-
- if (!_hash_try_getlock(rel, start_nblkno, HASH_EXCLUSIVE))
- elog(ERROR, "could not get lock on supposedly new bucket");
-
/*
- * If the split point is increasing (hashm_maxbucket's log base 2
- * increases), we need to allocate a new batch of bucket pages.
+ * If the split point is increasing we need to allocate a new batch of
+ * bucket pages.
*/
- spare_ndx = _hash_log2(new_bucket + 1);
+ spare_ndx = _hash_spareindex(new_bucket + 1);
if (spare_ndx > metap->hashm_ovflpoint)
{
+ uint32 buckets_to_add;
+
Assert(spare_ndx == metap->hashm_ovflpoint + 1);
/*
- * The number of buckets in the new splitpoint is equal to the total
- * number already in existence, i.e. new_bucket. Currently this maps
- * one-to-one to blocks required, but someday we may need a more
- * complicated calculation here.
+ * We treat allocation of buckets as a separate WAL-logged action.
+ * Even if we fail after this operation, won't leak bucket pages;
+ * rather, the next split will consume this space. In any case, even
+ * without failure we don't use all the space in one split operation.
*/
- if (!_hash_alloc_buckets(rel, start_nblkno, new_bucket))
+ buckets_to_add = _hash_get_totalbuckets(spare_ndx) - new_bucket;
+ if (!_hash_alloc_buckets(rel, start_nblkno, buckets_to_add))
{
/* can't split due to BlockNumber overflow */
- _hash_droplock(rel, start_oblkno, HASH_EXCLUSIVE);
- _hash_droplock(rel, start_nblkno, HASH_EXCLUSIVE);
+ _hash_relbuf(rel, buf_oblkno);
goto fail;
}
}
@@ -609,21 +806,29 @@ _hash_expandtable(Relation rel, Buffer metabuf)
/*
* Physically allocate the new bucket's primary page. We want to do this
* before changing the metapage's mapping info, in case we can't get the
- * disk space.
+ * disk space. Ideally, we don't need to check for cleanup lock on new
+ * bucket as no other backend could find this bucket unless meta page is
+ * updated. However, it is good to be consistent with old bucket locking.
*/
buf_nblkno = _hash_getnewbuf(rel, start_nblkno, MAIN_FORKNUM);
+ if (!IsBufferCleanupOK(buf_nblkno))
+ {
+ _hash_relbuf(rel, buf_oblkno);
+ _hash_relbuf(rel, buf_nblkno);
+ goto fail;
+ }
/*
- * Okay to proceed with split. Update the metapage bucket mapping info.
- *
- * Since we are scribbling on the metapage data right in the shared
- * buffer, any failure in this next little bit leaves us with a big
+ * Since we are scribbling on the pages in the shared buffers, establish a
+ * critical section. Any failure in this next code leaves us with a big
* problem: the metapage is effectively corrupt but could get written back
- * to disk. We don't really expect any failure, but just to be sure,
- * establish a critical section.
+ * to disk.
*/
START_CRIT_SECTION();
+ /*
+ * Okay to proceed with split. Update the metapage bucket mapping info.
+ */
metap->hashm_maxbucket = new_bucket;
if (new_bucket > metap->hashm_highmask)
@@ -631,22 +836,22 @@ _hash_expandtable(Relation rel, Buffer metabuf)
/* Starting a new doubling */
metap->hashm_lowmask = metap->hashm_highmask;
metap->hashm_highmask = new_bucket | metap->hashm_lowmask;
+ metap_update_masks = true;
}
/*
- * If the split point is increasing (hashm_maxbucket's log base 2
- * increases), we need to adjust the hashm_spares[] array and
- * hashm_ovflpoint so that future overflow pages will be created beyond
- * this new batch of bucket pages.
+ * If the split point is increasing we need to adjust the hashm_spares[]
+ * array and hashm_ovflpoint so that future overflow pages will be created
+ * beyond this new batch of bucket pages.
*/
if (spare_ndx > metap->hashm_ovflpoint)
{
metap->hashm_spares[spare_ndx] = metap->hashm_spares[metap->hashm_ovflpoint];
metap->hashm_ovflpoint = spare_ndx;
+ metap_update_splitpoint = true;
}
- /* Done mucking with metapage */
- END_CRIT_SECTION();
+ MarkBufferDirty(metabuf);
/*
* Copy bucket mapping info now; this saves re-accessing the meta page
@@ -659,18 +864,92 @@ _hash_expandtable(Relation rel, Buffer metabuf)
highmask = metap->hashm_highmask;
lowmask = metap->hashm_lowmask;
- /* Write out the metapage and drop lock, but keep pin */
- _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK);
+ opage = BufferGetPage(buf_oblkno);
+ oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
+
+ /*
+ * Mark the old bucket to indicate that split is in progress. (At
+ * operation end, we will clear the split-in-progress flag.) Also, for a
+ * primary bucket page, hasho_prevblkno stores the number of buckets that
+ * existed as of the last split, so we must update that value here.
+ */
+ oopaque->hasho_flag |= LH_BUCKET_BEING_SPLIT;
+ oopaque->hasho_prevblkno = maxbucket;
+
+ MarkBufferDirty(buf_oblkno);
+
+ npage = BufferGetPage(buf_nblkno);
+
+ /*
+ * initialize the new bucket's primary page and mark it to indicate that
+ * split is in progress.
+ */
+ nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
+ nopaque->hasho_prevblkno = maxbucket;
+ nopaque->hasho_nextblkno = InvalidBlockNumber;
+ nopaque->hasho_bucket = new_bucket;
+ nopaque->hasho_flag = LH_BUCKET_PAGE | LH_BUCKET_BEING_POPULATED;
+ nopaque->hasho_page_id = HASHO_PAGE_ID;
+
+ MarkBufferDirty(buf_nblkno);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(rel))
+ {
+ xl_hash_split_allocate_page xlrec;
+ XLogRecPtr recptr;
+
+ xlrec.new_bucket = maxbucket;
+ xlrec.old_bucket_flag = oopaque->hasho_flag;
+ xlrec.new_bucket_flag = nopaque->hasho_flag;
+ xlrec.flags = 0;
+
+ XLogBeginInsert();
+
+ XLogRegisterBuffer(0, buf_oblkno, REGBUF_STANDARD);
+ XLogRegisterBuffer(1, buf_nblkno, REGBUF_WILL_INIT);
+ XLogRegisterBuffer(2, metabuf, REGBUF_STANDARD);
+
+ if (metap_update_masks)
+ {
+ xlrec.flags |= XLH_SPLIT_META_UPDATE_MASKS;
+ XLogRegisterBufData(2, (char *) &metap->hashm_lowmask, sizeof(uint32));
+ XLogRegisterBufData(2, (char *) &metap->hashm_highmask, sizeof(uint32));
+ }
+
+ if (metap_update_splitpoint)
+ {
+ xlrec.flags |= XLH_SPLIT_META_UPDATE_SPLITPOINT;
+ XLogRegisterBufData(2, (char *) &metap->hashm_ovflpoint,
+ sizeof(uint32));
+ XLogRegisterBufData(2,
+ (char *) &metap->hashm_spares[metap->hashm_ovflpoint],
+ sizeof(uint32));
+ }
+
+ XLogRegisterData((char *) &xlrec, SizeOfHashSplitAllocPage);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SPLIT_ALLOCATE_PAGE);
+
+ PageSetLSN(BufferGetPage(buf_oblkno), recptr);
+ PageSetLSN(BufferGetPage(buf_nblkno), recptr);
+ PageSetLSN(BufferGetPage(metabuf), recptr);
+ }
+
+ END_CRIT_SECTION();
+
+ /* drop lock, but keep pin */
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
/* Relocate records to the new bucket */
_hash_splitbucket(rel, metabuf,
old_bucket, new_bucket,
- start_oblkno, buf_nblkno,
+ buf_oblkno, buf_nblkno, NULL,
maxbucket, highmask, lowmask);
- /* Release bucket locks, allowing others to access them */
- _hash_droplock(rel, start_oblkno, HASH_EXCLUSIVE);
- _hash_droplock(rel, start_nblkno, HASH_EXCLUSIVE);
+ /* all done, now release the locks and pins on primary buckets. */
+ _hash_relbuf(rel, buf_oblkno);
+ _hash_relbuf(rel, buf_nblkno);
return;
@@ -678,7 +957,7 @@ _hash_expandtable(Relation rel, Buffer metabuf)
fail:
/* We didn't write the metapage, so just drop lock */
- _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
+ LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
}
@@ -698,7 +977,7 @@ fail:
* hash indexes sequentially anyway, that probably doesn't matter.
*
* XXX It's annoying that this code is executed with the metapage lock held.
- * We need to interlock against _hash_getovflpage() adding a new overflow page
+ * We need to interlock against _hash_addovflpage() adding a new overflow page
* concurrently, but it'd likely be better to use LockRelationForExtension
* for the purpose. OTOH, adding a splitpoint is a very infrequent operation,
* so it may not be worth worrying about.
@@ -711,6 +990,8 @@ _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
{
BlockNumber lastblock;
char zerobuf[BLCKSZ];
+ Page page;
+ HashPageOpaque ovflopaque;
lastblock = firstblock + nblocks - 1;
@@ -721,7 +1002,29 @@ _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
if (lastblock < firstblock || lastblock == InvalidBlockNumber)
return false;
- MemSet(zerobuf, 0, sizeof(zerobuf));
+ page = (Page) zerobuf;
+
+ /*
+ * Initialize the page. Just zeroing the page won't work; see
+ * _hash_freeovflpage for similar usage. We take care to make the special
+ * space valid for the benefit of tools such as pageinspect.
+ */
+ _hash_pageinit(page, BLCKSZ);
+
+ ovflopaque = (HashPageOpaque) PageGetSpecialPointer(page);
+
+ ovflopaque->hasho_prevblkno = InvalidBlockNumber;
+ ovflopaque->hasho_nextblkno = InvalidBlockNumber;
+ ovflopaque->hasho_bucket = -1;
+ ovflopaque->hasho_flag = LH_UNUSED_PAGE;
+ ovflopaque->hasho_page_id = HASHO_PAGE_ID;
+
+ if (RelationNeedsWAL(rel))
+ log_newpage(&rel->rd_node,
+ MAIN_FORKNUM,
+ lastblock,
+ zerobuf,
+ true);
RelationOpenSmgr(rel);
smgrextend(rel->rd_smgr, MAIN_FORKNUM, lastblock, zerobuf, false);
@@ -733,18 +1036,28 @@ _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
/*
* _hash_splitbucket -- split 'obucket' into 'obucket' and 'nbucket'
*
+ * This routine is used to partition the tuples between old and new bucket and
+ * is used to finish the incomplete split operations. To finish the previously
+ * interrupted split operation, the caller needs to fill htab. If htab is set,
+ * then we skip the movement of tuples that exists in htab, otherwise NULL
+ * value of htab indicates movement of all the tuples that belong to the new
+ * bucket.
+ *
* We are splitting a bucket that consists of a base bucket page and zero
* or more overflow (bucket chain) pages. We must relocate tuples that
- * belong in the new bucket, and compress out any free space in the old
- * bucket.
+ * belong in the new bucket.
*
- * The caller must hold exclusive locks on both buckets to ensure that
+ * The caller must hold cleanup locks on both buckets to ensure that
* no one else is trying to access them (see README).
*
* The caller must hold a pin, but no lock, on the metapage buffer.
* The buffer is returned in the same state. (The metapage is only
* touched if it becomes necessary to add or remove overflow pages.)
*
+ * Split needs to retain pin on primary bucket pages of both old and new
+ * buckets till end of operation. This is to prevent vacuum from starting
+ * while a split is in progress.
+ *
* In addition, the caller must have created the new bucket's base page,
* which is passed in buffer nbuf, pinned and write-locked. That lock and
* pin are released here. (The API is set up this way because we must do
@@ -756,36 +1069,32 @@ _hash_splitbucket(Relation rel,
Buffer metabuf,
Bucket obucket,
Bucket nbucket,
- BlockNumber start_oblkno,
+ Buffer obuf,
Buffer nbuf,
+ HTAB *htab,
uint32 maxbucket,
uint32 highmask,
uint32 lowmask)
{
- Buffer obuf;
+ Buffer bucket_obuf;
+ Buffer bucket_nbuf;
Page opage;
Page npage;
HashPageOpaque oopaque;
HashPageOpaque nopaque;
+ OffsetNumber itup_offsets[MaxIndexTuplesPerPage];
+ IndexTuple itups[MaxIndexTuplesPerPage];
+ Size all_tups_size = 0;
+ int i;
+ uint16 nitups = 0;
- /*
- * It should be okay to simultaneously write-lock pages from each bucket,
- * since no one else can be trying to acquire buffer lock on pages of
- * either bucket.
- */
- obuf = _hash_getbuf(rel, start_oblkno, HASH_WRITE, LH_BUCKET_PAGE);
+ bucket_obuf = obuf;
opage = BufferGetPage(obuf);
oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
+ bucket_nbuf = nbuf;
npage = BufferGetPage(nbuf);
-
- /* initialize the new bucket's primary page */
nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
- nopaque->hasho_prevblkno = InvalidBlockNumber;
- nopaque->hasho_nextblkno = InvalidBlockNumber;
- nopaque->hasho_bucket = nbucket;
- nopaque->hasho_flag = LH_BUCKET_PAGE;
- nopaque->hasho_page_id = HASHO_PAGE_ID;
/*
* Partition the tuples in the old bucket between the old bucket and the
@@ -798,8 +1107,6 @@ _hash_splitbucket(Relation rel,
BlockNumber oblkno;
OffsetNumber ooffnum;
OffsetNumber omaxoffnum;
- OffsetNumber deletable[MaxOffsetNumber];
- int ndeletable = 0;
/* Scan each tuple in old page */
omaxoffnum = PageGetMaxOffsetNumber(opage);
@@ -810,54 +1117,86 @@ _hash_splitbucket(Relation rel,
IndexTuple itup;
Size itemsz;
Bucket bucket;
+ bool found = false;
+
+ /* skip dead tuples */
+ if (ItemIdIsDead(PageGetItemId(opage, ooffnum)))
+ continue;
/*
- * Fetch the item's hash key (conveniently stored in the item) and
- * determine which bucket it now belongs in.
+ * Before inserting a tuple, probe the hash table containing TIDs
+ * of tuples belonging to new bucket, if we find a match, then
+ * skip that tuple, else fetch the item's hash key (conveniently
+ * stored in the item) and determine which bucket it now belongs
+ * in.
*/
itup = (IndexTuple) PageGetItem(opage,
PageGetItemId(opage, ooffnum));
+
+ if (htab)
+ (void) hash_search(htab, &itup->t_tid, HASH_FIND, &found);
+
+ if (found)
+ continue;
+
bucket = _hash_hashkey2bucket(_hash_get_indextuple_hashkey(itup),
maxbucket, highmask, lowmask);
if (bucket == nbucket)
{
+ IndexTuple new_itup;
+
+ /*
+ * make a copy of index tuple as we have to scribble on it.
+ */
+ new_itup = CopyIndexTuple(itup);
+
+ /*
+ * mark the index tuple as moved by split, such tuples are
+ * skipped by scan if there is split in progress for a bucket.
+ */
+ new_itup->t_info |= INDEX_MOVED_BY_SPLIT_MASK;
+
/*
* insert the tuple into the new bucket. if it doesn't fit on
* the current page in the new bucket, we must allocate a new
* overflow page and place the tuple on that page instead.
- *
- * XXX we have a problem here if we fail to get space for a
- * new overflow page: we'll error out leaving the bucket split
- * only partially complete, meaning the index is corrupt,
- * since searches may fail to find entries they should find.
*/
- itemsz = IndexTupleDSize(*itup);
+ itemsz = IndexTupleDSize(*new_itup);
itemsz = MAXALIGN(itemsz);
- if (PageGetFreeSpace(npage) < itemsz)
+ if (PageGetFreeSpaceForMultipleTuples(npage, nitups + 1) < (all_tups_size + itemsz))
{
- /* write out nbuf and drop lock, but keep pin */
- _hash_chgbufaccess(rel, nbuf, HASH_WRITE, HASH_NOLOCK);
+ /*
+ * Change the shared buffer state in critical section,
+ * otherwise any error could make it unrecoverable.
+ */
+ START_CRIT_SECTION();
+
+ _hash_pgaddmultitup(rel, nbuf, itups, itup_offsets, nitups);
+ MarkBufferDirty(nbuf);
+ /* log the split operation before releasing the lock */
+ log_split_page(rel, nbuf);
+
+ END_CRIT_SECTION();
+
+ /* drop lock, but keep pin */
+ LockBuffer(nbuf, BUFFER_LOCK_UNLOCK);
+
+ /* be tidy */
+ for (i = 0; i < nitups; i++)
+ pfree(itups[i]);
+ nitups = 0;
+ all_tups_size = 0;
+
/* chain to a new overflow page */
- nbuf = _hash_addovflpage(rel, metabuf, nbuf);
+ nbuf = _hash_addovflpage(rel, metabuf, nbuf, (nbuf == bucket_nbuf) ? true : false);
npage = BufferGetPage(nbuf);
- /* we don't need nopaque within the loop */
+ nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
}
- /*
- * Insert tuple on new page, using _hash_pgaddtup to ensure
- * correct ordering by hashkey. This is a tad inefficient
- * since we may have to shuffle itempointers repeatedly.
- * Possible future improvement: accumulate all the items for
- * the new page and qsort them before insertion.
- */
- (void) _hash_pgaddtup(rel, nbuf, itemsz, itup);
-
- /*
- * Mark tuple for deletion from old page.
- */
- deletable[ndeletable++] = ooffnum;
+ itups[nitups++] = new_itup;
+ all_tups_size += itemsz;
}
else
{
@@ -870,35 +1209,378 @@ _hash_splitbucket(Relation rel,
oblkno = oopaque->hasho_nextblkno;
- /*
- * Done scanning this old page. If we moved any tuples, delete them
- * from the old page.
- */
- if (ndeletable > 0)
- {
- PageIndexMultiDelete(opage, deletable, ndeletable);
- _hash_wrtbuf(rel, obuf);
- }
+ /* retain the pin on the old primary bucket */
+ if (obuf == bucket_obuf)
+ LockBuffer(obuf, BUFFER_LOCK_UNLOCK);
else
_hash_relbuf(rel, obuf);
/* Exit loop if no more overflow pages in old bucket */
if (!BlockNumberIsValid(oblkno))
+ {
+ /*
+ * Change the shared buffer state in critical section, otherwise
+ * any error could make it unrecoverable.
+ */
+ START_CRIT_SECTION();
+
+ _hash_pgaddmultitup(rel, nbuf, itups, itup_offsets, nitups);
+ MarkBufferDirty(nbuf);
+ /* log the split operation before releasing the lock */
+ log_split_page(rel, nbuf);
+
+ END_CRIT_SECTION();
+
+ if (nbuf == bucket_nbuf)
+ LockBuffer(nbuf, BUFFER_LOCK_UNLOCK);
+ else
+ _hash_relbuf(rel, nbuf);
+
+ /* be tidy */
+ for (i = 0; i < nitups; i++)
+ pfree(itups[i]);
break;
+ }
/* Else, advance to next old page */
- obuf = _hash_getbuf(rel, oblkno, HASH_WRITE, LH_OVERFLOW_PAGE);
+ obuf = _hash_getbuf(rel, oblkno, HASH_READ, LH_OVERFLOW_PAGE);
opage = BufferGetPage(obuf);
oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
}
/*
* We're at the end of the old bucket chain, so we're done partitioning
- * the tuples. Before quitting, call _hash_squeezebucket to ensure the
- * tuples remaining in the old bucket (including the overflow pages) are
- * packed as tightly as possible. The new bucket is already tight.
+ * the tuples. Mark the old and new buckets to indicate split is
+ * finished.
+ *
+ * To avoid deadlocks due to locking order of buckets, first lock the old
+ * bucket and then the new bucket.
+ */
+ LockBuffer(bucket_obuf, BUFFER_LOCK_EXCLUSIVE);
+ opage = BufferGetPage(bucket_obuf);
+ oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
+
+ LockBuffer(bucket_nbuf, BUFFER_LOCK_EXCLUSIVE);
+ npage = BufferGetPage(bucket_nbuf);
+ nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
+
+ START_CRIT_SECTION();
+
+ oopaque->hasho_flag &= ~LH_BUCKET_BEING_SPLIT;
+ nopaque->hasho_flag &= ~LH_BUCKET_BEING_POPULATED;
+
+ /*
+ * After the split is finished, mark the old bucket to indicate that it
+ * contains deletable tuples. Vacuum will clear split-cleanup flag after
+ * deleting such tuples.
+ */
+ oopaque->hasho_flag |= LH_BUCKET_NEEDS_SPLIT_CLEANUP;
+
+ /*
+ * now write the buffers, here we don't release the locks as caller is
+ * responsible to release locks.
+ */
+ MarkBufferDirty(bucket_obuf);
+ MarkBufferDirty(bucket_nbuf);
+
+ if (RelationNeedsWAL(rel))
+ {
+ XLogRecPtr recptr;
+ xl_hash_split_complete xlrec;
+
+ xlrec.old_bucket_flag = oopaque->hasho_flag;
+ xlrec.new_bucket_flag = nopaque->hasho_flag;
+
+ XLogBeginInsert();
+
+ XLogRegisterData((char *) &xlrec, SizeOfHashSplitComplete);
+
+ XLogRegisterBuffer(0, bucket_obuf, REGBUF_STANDARD);
+ XLogRegisterBuffer(1, bucket_nbuf, REGBUF_STANDARD);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SPLIT_COMPLETE);
+
+ PageSetLSN(BufferGetPage(bucket_obuf), recptr);
+ PageSetLSN(BufferGetPage(bucket_nbuf), recptr);
+ }
+
+ END_CRIT_SECTION();
+}
+
+/*
+ * _hash_finish_split() -- Finish the previously interrupted split operation
+ *
+ * To complete the split operation, we form the hash table of TIDs in new
+ * bucket which is then used by split operation to skip tuples that are
+ * already moved before the split operation was previously interrupted.
+ *
+ * The caller must hold a pin, but no lock, on the metapage and old bucket's
+ * primary page buffer. The buffers are returned in the same state. (The
+ * metapage is only touched if it becomes necessary to add or remove overflow
+ * pages.)
+ */
+void
+_hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket,
+ uint32 maxbucket, uint32 highmask, uint32 lowmask)
+{
+ HASHCTL hash_ctl;
+ HTAB *tidhtab;
+ Buffer bucket_nbuf = InvalidBuffer;
+ Buffer nbuf;
+ Page npage;
+ BlockNumber nblkno;
+ BlockNumber bucket_nblkno;
+ HashPageOpaque npageopaque;
+ Bucket nbucket;
+ bool found;
+
+ /* Initialize hash tables used to track TIDs */
+ memset(&hash_ctl, 0, sizeof(hash_ctl));
+ hash_ctl.keysize = sizeof(ItemPointerData);
+ hash_ctl.entrysize = sizeof(ItemPointerData);
+ hash_ctl.hcxt = CurrentMemoryContext;
+
+ tidhtab =
+ hash_create("bucket ctids",
+ 256, /* arbitrary initial size */
+ &hash_ctl,
+ HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+
+ bucket_nblkno = nblkno = _hash_get_newblock_from_oldbucket(rel, obucket);
+
+ /*
+ * Scan the new bucket and build hash table of TIDs
+ */
+ for (;;)
+ {
+ OffsetNumber noffnum;
+ OffsetNumber nmaxoffnum;
+
+ nbuf = _hash_getbuf(rel, nblkno, HASH_READ,
+ LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
+
+ /* remember the primary bucket buffer to acquire cleanup lock on it. */
+ if (nblkno == bucket_nblkno)
+ bucket_nbuf = nbuf;
+
+ npage = BufferGetPage(nbuf);
+ npageopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
+
+ /* Scan each tuple in new page */
+ nmaxoffnum = PageGetMaxOffsetNumber(npage);
+ for (noffnum = FirstOffsetNumber;
+ noffnum <= nmaxoffnum;
+ noffnum = OffsetNumberNext(noffnum))
+ {
+ IndexTuple itup;
+
+ /* Fetch the item's TID and insert it in hash table. */
+ itup = (IndexTuple) PageGetItem(npage,
+ PageGetItemId(npage, noffnum));
+
+ (void) hash_search(tidhtab, &itup->t_tid, HASH_ENTER, &found);
+
+ Assert(!found);
+ }
+
+ nblkno = npageopaque->hasho_nextblkno;
+
+ /*
+ * release our write lock without modifying buffer and ensure to
+ * retain the pin on primary bucket.
+ */
+ if (nbuf == bucket_nbuf)
+ LockBuffer(nbuf, BUFFER_LOCK_UNLOCK);
+ else
+ _hash_relbuf(rel, nbuf);
+
+ /* Exit loop if no more overflow pages in new bucket */
+ if (!BlockNumberIsValid(nblkno))
+ break;
+ }
+
+ /*
+ * Conditionally get the cleanup lock on old and new buckets to perform
+ * the split operation. If we don't get the cleanup locks, silently give
+ * up and next insertion on old bucket will try again to complete the
+ * split.
+ */
+ if (!ConditionalLockBufferForCleanup(obuf))
+ {
+ hash_destroy(tidhtab);
+ return;
+ }
+ if (!ConditionalLockBufferForCleanup(bucket_nbuf))
+ {
+ LockBuffer(obuf, BUFFER_LOCK_UNLOCK);
+ hash_destroy(tidhtab);
+ return;
+ }
+
+ npage = BufferGetPage(bucket_nbuf);
+ npageopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
+ nbucket = npageopaque->hasho_bucket;
+
+ _hash_splitbucket(rel, metabuf, obucket,
+ nbucket, obuf, bucket_nbuf, tidhtab,
+ maxbucket, highmask, lowmask);
+
+ _hash_relbuf(rel, bucket_nbuf);
+ LockBuffer(obuf, BUFFER_LOCK_UNLOCK);
+ hash_destroy(tidhtab);
+}
+
+/*
+ * log_split_page() -- Log the split operation
+ *
+ * We log the split operation when the new page in new bucket gets full,
+ * so we log the entire page.
+ *
+ * 'buf' must be locked by the caller which is also responsible for unlocking
+ * it.
+ */
+static void
+log_split_page(Relation rel, Buffer buf)
+{
+ if (RelationNeedsWAL(rel))
+ {
+ XLogRecPtr recptr;
+
+ XLogBeginInsert();
+
+ XLogRegisterBuffer(0, buf, REGBUF_FORCE_IMAGE | REGBUF_STANDARD);
+
+ recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SPLIT_PAGE);
+
+ PageSetLSN(BufferGetPage(buf), recptr);
+ }
+}
+
+/*
+ * _hash_getcachedmetap() -- Returns cached metapage data.
+ *
+ * If metabuf is not InvalidBuffer, caller must hold a pin, but no lock, on
+ * the metapage. If not set, we'll set it before returning if we have to
+ * refresh the cache, and return with a pin but no lock on it; caller is
+ * responsible for releasing the pin.
+ *
+ * We refresh the cache if it's not initialized yet or force_refresh is true.
+ */
+HashMetaPage
+_hash_getcachedmetap(Relation rel, Buffer *metabuf, bool force_refresh)
+{
+ Page page;
+
+ Assert(metabuf);
+ if (force_refresh || rel->rd_amcache == NULL)
+ {
+ char *cache = NULL;
+
+ /*
+ * It's important that we don't set rd_amcache to an invalid value.
+ * Either MemoryContextAlloc or _hash_getbuf could fail, so don't
+ * install a pointer to the newly-allocated storage in the actual
+ * relcache entry until both have succeeeded.
+ */
+ if (rel->rd_amcache == NULL)
+ cache = MemoryContextAlloc(rel->rd_indexcxt,
+ sizeof(HashMetaPageData));
+
+ /* Read the metapage. */
+ if (BufferIsValid(*metabuf))
+ LockBuffer(*metabuf, BUFFER_LOCK_SHARE);
+ else
+ *metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ,
+ LH_META_PAGE);
+ page = BufferGetPage(*metabuf);
+
+ /* Populate the cache. */
+ if (rel->rd_amcache == NULL)
+ rel->rd_amcache = cache;
+ memcpy(rel->rd_amcache, HashPageGetMeta(page),
+ sizeof(HashMetaPageData));
+
+ /* Release metapage lock, but keep the pin. */
+ LockBuffer(*metabuf, BUFFER_LOCK_UNLOCK);
+ }
+
+ return (HashMetaPage) rel->rd_amcache;
+}
+
+/*
+ * _hash_getbucketbuf_from_hashkey() -- Get the bucket's buffer for the given
+ * hashkey.
+ *
+ * Bucket pages do not move or get removed once they are allocated. This give
+ * us an opportunity to use the previously saved metapage contents to reach
+ * the target bucket buffer, instead of reading from the metapage every time.
+ * This saves one buffer access every time we want to reach the target bucket
+ * buffer, which is very helpful savings in bufmgr traffic and contention.
+ *
+ * The access type parameter (HASH_READ or HASH_WRITE) indicates whether the
+ * bucket buffer has to be locked for reading or writing.
+ *
+ * The out parameter cachedmetap is set with metapage contents used for
+ * hashkey to bucket buffer mapping. Some callers need this info to reach the
+ * old bucket in case of bucket split, see _hash_doinsert().
+ */
+Buffer
+_hash_getbucketbuf_from_hashkey(Relation rel, uint32 hashkey, int access,
+ HashMetaPage *cachedmetap)
+{
+ HashMetaPage metap;
+ Buffer buf;
+ Buffer metabuf = InvalidBuffer;
+ Page page;
+ Bucket bucket;
+ BlockNumber blkno;
+ HashPageOpaque opaque;
+
+ /* We read from target bucket buffer, hence locking is must. */
+ Assert(access == HASH_READ || access == HASH_WRITE);
+
+ metap = _hash_getcachedmetap(rel, &metabuf, false);
+ Assert(metap != NULL);
+
+ /*
+ * Loop until we get a lock on the correct target bucket.
*/
- _hash_wrtbuf(rel, nbuf);
+ for (;;)
+ {
+ /*
+ * Compute the target bucket number, and convert to block number.
+ */
+ bucket = _hash_hashkey2bucket(hashkey,
+ metap->hashm_maxbucket,
+ metap->hashm_highmask,
+ metap->hashm_lowmask);
+
+ blkno = BUCKET_TO_BLKNO(metap, bucket);
+
+ /* Fetch the primary bucket page for the bucket */
+ buf = _hash_getbuf(rel, blkno, access, LH_BUCKET_PAGE);
+ page = BufferGetPage(buf);
+ opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ Assert(opaque->hasho_bucket == bucket);
+ Assert(opaque->hasho_prevblkno != InvalidBlockNumber);
- _hash_squeezebucket(rel, obucket, start_oblkno, NULL);
+ /*
+ * If this bucket hasn't been split, we're done.
+ */
+ if (opaque->hasho_prevblkno <= metap->hashm_maxbucket)
+ break;
+
+ /* Drop lock on this buffer, update cached metapage, and retry. */
+ _hash_relbuf(rel, buf);
+ metap = _hash_getcachedmetap(rel, &metabuf, true);
+ Assert(metap != NULL);
+ }
+
+ if (BufferIsValid(metabuf))
+ _hash_dropbuf(rel, metabuf);
+
+ if (cachedmetap)
+ *cachedmetap = metap;
+
+ return buf;
}
diff --git a/src/backend/access/hash/hashscan.c b/src/backend/access/hash/hashscan.c
deleted file mode 100644
index fe97ef201a..0000000000
--- a/src/backend/access/hash/hashscan.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * hashscan.c
- * manage scans on hash tables
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/backend/access/hash/hashscan.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-#include "access/hash.h"
-#include "access/relscan.h"
-#include "utils/memutils.h"
-#include "utils/rel.h"
-#include "utils/resowner.h"
-
-
-/*
- * We track all of a backend's active scans on hash indexes using a list
- * of HashScanListData structs, which are allocated in TopMemoryContext.
- * It's okay to use a long-lived context because we rely on the ResourceOwner
- * mechanism to clean up unused entries after transaction or subtransaction
- * abort. We can't safely keep the entries in the executor's per-query
- * context, because that might be already freed before we get a chance to
- * clean up the list. (XXX seems like there should be a better way to
- * manage this...)
- */
-typedef struct HashScanListData
-{
- IndexScanDesc hashsl_scan;
- ResourceOwner hashsl_owner;
- struct HashScanListData *hashsl_next;
-} HashScanListData;
-
-typedef HashScanListData *HashScanList;
-
-static HashScanList HashScans = NULL;
-
-
-/*
- * ReleaseResources_hash() --- clean up hash subsystem resources.
- *
- * This is here because it needs to touch this module's static var HashScans.
- */
-void
-ReleaseResources_hash(void)
-{
- HashScanList l;
- HashScanList prev;
- HashScanList next;
-
- /*
- * Release all HashScanList items belonging to the current ResourceOwner.
- * Note that we do not release the underlying IndexScanDesc; that's in
- * executor memory and will go away on its own (in fact quite possibly has
- * gone away already, so we mustn't try to touch it here).
- *
- * Note: this should be a no-op during normal query shutdown. However, in
- * an abort situation ExecutorEnd is not called and so there may be open
- * index scans to clean up.
- */
- prev = NULL;
-
- for (l = HashScans; l != NULL; l = next)
- {
- next = l->hashsl_next;
- if (l->hashsl_owner == CurrentResourceOwner)
- {
- if (prev == NULL)
- HashScans = next;
- else
- prev->hashsl_next = next;
-
- pfree(l);
- /* prev does not change */
- }
- else
- prev = l;
- }
-}
-
-/*
- * _hash_regscan() -- register a new scan.
- */
-void
-_hash_regscan(IndexScanDesc scan)
-{
- HashScanList new_el;
-
- new_el = (HashScanList) MemoryContextAlloc(TopMemoryContext,
- sizeof(HashScanListData));
- new_el->hashsl_scan = scan;
- new_el->hashsl_owner = CurrentResourceOwner;
- new_el->hashsl_next = HashScans;
- HashScans = new_el;
-}
-
-/*
- * _hash_dropscan() -- drop a scan from the scan list
- */
-void
-_hash_dropscan(IndexScanDesc scan)
-{
- HashScanList chk,
- last;
-
- last = NULL;
- for (chk = HashScans;
- chk != NULL && chk->hashsl_scan != scan;
- chk = chk->hashsl_next)
- last = chk;
-
- if (chk == NULL)
- elog(ERROR, "hash scan list trashed; cannot find 0x%p", (void *) scan);
-
- if (last == NULL)
- HashScans = chk->hashsl_next;
- else
- last->hashsl_next = chk->hashsl_next;
-
- pfree(chk);
-}
-
-/*
- * Is there an active scan in this bucket?
- */
-bool
-_hash_has_active_scan(Relation rel, Bucket bucket)
-{
- Oid relid = RelationGetRelid(rel);
- HashScanList l;
-
- for (l = HashScans; l != NULL; l = l->hashsl_next)
- {
- if (relid == l->hashsl_scan->indexRelation->rd_id)
- {
- HashScanOpaque so = (HashScanOpaque) l->hashsl_scan->opaque;
-
- if (so->hashso_bucket_valid &&
- so->hashso_bucket == bucket)
- return true;
- }
- }
-
- return false;
-}
diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c
index 48255584e1..2d9204903f 100644
--- a/src/backend/access/hash/hashsearch.c
+++ b/src/backend/access/hash/hashsearch.c
@@ -3,7 +3,7 @@
* hashsearch.c
* search code for postgres hash tables
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -63,47 +63,149 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
}
/*
- * Advance to next page in a bucket, if any.
+ * Advance to next page in a bucket, if any. If we are scanning the bucket
+ * being populated during split operation then this function advances to the
+ * bucket being split after the last bucket page of bucket being populated.
*/
static void
-_hash_readnext(Relation rel,
+_hash_readnext(IndexScanDesc scan,
Buffer *bufp, Page *pagep, HashPageOpaque *opaquep)
{
BlockNumber blkno;
+ Relation rel = scan->indexRelation;
+ HashScanOpaque so = (HashScanOpaque) scan->opaque;
+ bool block_found = false;
blkno = (*opaquep)->hasho_nextblkno;
- _hash_relbuf(rel, *bufp);
+
+ /*
+ * Retain the pin on primary bucket page till the end of scan. Refer the
+ * comments in _hash_first to know the reason of retaining pin.
+ */
+ if (*bufp == so->hashso_bucket_buf || *bufp == so->hashso_split_bucket_buf)
+ LockBuffer(*bufp, BUFFER_LOCK_UNLOCK);
+ else
+ _hash_relbuf(rel, *bufp);
+
*bufp = InvalidBuffer;
/* check for interrupts while we're not holding any buffer lock */
CHECK_FOR_INTERRUPTS();
if (BlockNumberIsValid(blkno))
{
*bufp = _hash_getbuf(rel, blkno, HASH_READ, LH_OVERFLOW_PAGE);
+ block_found = true;
+ }
+ else if (so->hashso_buc_populated && !so->hashso_buc_split)
+ {
+ /*
+ * end of bucket, scan bucket being split if there was a split in
+ * progress at the start of scan.
+ */
+ *bufp = so->hashso_split_bucket_buf;
+
+ /*
+ * buffer for bucket being split must be valid as we acquire the pin
+ * on it before the start of scan and retain it till end of scan.
+ */
+ Assert(BufferIsValid(*bufp));
+
+ LockBuffer(*bufp, BUFFER_LOCK_SHARE);
+
+ /*
+ * setting hashso_buc_split to true indicates that we are scanning
+ * bucket being split.
+ */
+ so->hashso_buc_split = true;
+
+ block_found = true;
+ }
+
+ if (block_found)
+ {
*pagep = BufferGetPage(*bufp);
+ TestForOldSnapshot(scan->xs_snapshot, rel, *pagep);
*opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
}
}
/*
- * Advance to previous page in a bucket, if any.
+ * Advance to previous page in a bucket, if any. If the current scan has
+ * started during split operation then this function advances to bucket
+ * being populated after the first bucket page of bucket being split.
*/
static void
-_hash_readprev(Relation rel,
+_hash_readprev(IndexScanDesc scan,
Buffer *bufp, Page *pagep, HashPageOpaque *opaquep)
{
BlockNumber blkno;
+ Relation rel = scan->indexRelation;
+ HashScanOpaque so = (HashScanOpaque) scan->opaque;
+ bool haveprevblk;
blkno = (*opaquep)->hasho_prevblkno;
- _hash_relbuf(rel, *bufp);
+
+ /*
+ * Retain the pin on primary bucket page till the end of scan. Refer the
+ * comments in _hash_first to know the reason of retaining pin.
+ */
+ if (*bufp == so->hashso_bucket_buf || *bufp == so->hashso_split_bucket_buf)
+ {
+ LockBuffer(*bufp, BUFFER_LOCK_UNLOCK);
+ haveprevblk = false;
+ }
+ else
+ {
+ _hash_relbuf(rel, *bufp);
+ haveprevblk = true;
+ }
+
*bufp = InvalidBuffer;
/* check for interrupts while we're not holding any buffer lock */
CHECK_FOR_INTERRUPTS();
- if (BlockNumberIsValid(blkno))
+
+ if (haveprevblk)
{
+ Assert(BlockNumberIsValid(blkno));
*bufp = _hash_getbuf(rel, blkno, HASH_READ,
LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
*pagep = BufferGetPage(*bufp);
+ TestForOldSnapshot(scan->xs_snapshot, rel, *pagep);
*opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
+
+ /*
+ * We always maintain the pin on bucket page for whole scan operation,
+ * so releasing the additional pin we have acquired here.
+ */
+ if (*bufp == so->hashso_bucket_buf || *bufp == so->hashso_split_bucket_buf)
+ _hash_dropbuf(rel, *bufp);
+ }
+ else if (so->hashso_buc_populated && so->hashso_buc_split)
+ {
+ /*
+ * end of bucket, scan bucket being populated if there was a split in
+ * progress at the start of scan.
+ */
+ *bufp = so->hashso_bucket_buf;
+
+ /*
+ * buffer for bucket being populated must be valid as we acquire the
+ * pin on it before the start of scan and retain it till end of scan.
+ */
+ Assert(BufferIsValid(*bufp));
+
+ LockBuffer(*bufp, BUFFER_LOCK_SHARE);
+ *pagep = BufferGetPage(*bufp);
+ *opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
+
+ /* move to the end of bucket chain */
+ while (BlockNumberIsValid((*opaquep)->hasho_nextblkno))
+ _hash_readnext(scan, bufp, pagep, opaquep);
+
+ /*
+ * setting hashso_buc_split to false indicates that we are scanning
+ * bucket being populated.
+ */
+ so->hashso_buc_split = false;
}
}
@@ -124,14 +226,9 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
ScanKey cur;
uint32 hashkey;
Bucket bucket;
- BlockNumber blkno;
- BlockNumber oldblkno = InvalidBuffer;
- bool retry = false;
Buffer buf;
- Buffer metabuf;
Page page;
HashPageOpaque opaque;
- HashMetaPage metap;
IndexTuple itup;
ItemPointer current;
OffsetNumber offnum;
@@ -186,70 +283,77 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
so->hashso_sk_hash = hashkey;
- /* Read the metapage */
- metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
- page = BufferGetPage(metabuf);
- metap = HashPageGetMeta(page);
+ buf = _hash_getbucketbuf_from_hashkey(rel, hashkey, HASH_READ, NULL);
+ page = BufferGetPage(buf);
+ TestForOldSnapshot(scan->xs_snapshot, rel, page);
+ opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ bucket = opaque->hasho_bucket;
+
+ so->hashso_bucket_buf = buf;
/*
- * Loop until we get a lock on the correct target bucket.
+ * If a bucket split is in progress, then while scanning the bucket being
+ * populated, we need to skip tuples that were copied from bucket being
+ * split. We also need to maintain a pin on the bucket being split to
+ * ensure that split-cleanup work done by vacuum doesn't remove tuples
+ * from it till this scan is done. We need to maintain a pin on the
+ * bucket being populated to ensure that vacuum doesn't squeeze that
+ * bucket till this scan is complete; otherwise, the ordering of tuples
+ * can't be maintained during forward and backward scans. Here, we have
+ * to be cautious about locking order: first, acquire the lock on bucket
+ * being split; then, release the lock on it but not the pin; then,
+ * acquire a lock on bucket being populated and again re-verify whether
+ * the bucket split is still in progress. Acquiring the lock on bucket
+ * being split first ensures that the vacuum waits for this scan to
+ * finish.
*/
- for (;;)
+ if (H_BUCKET_BEING_POPULATED(opaque))
{
- /*
- * Compute the target bucket number, and convert to block number.
- */
- bucket = _hash_hashkey2bucket(hashkey,
- metap->hashm_maxbucket,
- metap->hashm_highmask,
- metap->hashm_lowmask);
+ BlockNumber old_blkno;
+ Buffer old_buf;
- blkno = BUCKET_TO_BLKNO(metap, bucket);
-
- /* Release metapage lock, but keep pin. */
- _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
+ old_blkno = _hash_get_oldblock_from_newbucket(rel, bucket);
/*
- * If the previous iteration of this loop locked what is still the
- * correct target bucket, we are done. Otherwise, drop any old lock
- * and lock what now appears to be the correct bucket.
+ * release the lock on new bucket and re-acquire it after acquiring
+ * the lock on old bucket.
*/
- if (retry)
- {
- if (oldblkno == blkno)
- break;
- _hash_droplock(rel, oldblkno, HASH_SHARE);
- }
- _hash_getlock(rel, blkno, HASH_SHARE);
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+
+ old_buf = _hash_getbuf(rel, old_blkno, HASH_READ, LH_BUCKET_PAGE);
+ TestForOldSnapshot(scan->xs_snapshot, rel, BufferGetPage(old_buf));
/*
- * Reacquire metapage lock and check that no bucket split has taken
- * place while we were awaiting the bucket lock.
+ * remember the split bucket buffer so as to use it later for
+ * scanning.
*/
- _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_READ);
- oldblkno = blkno;
- retry = true;
- }
-
- /* done with the metapage */
- _hash_dropbuf(rel, metabuf);
+ so->hashso_split_bucket_buf = old_buf;
+ LockBuffer(old_buf, BUFFER_LOCK_UNLOCK);
- /* Update scan opaque state to show we have lock on the bucket */
- so->hashso_bucket = bucket;
- so->hashso_bucket_valid = true;
- so->hashso_bucket_blkno = blkno;
+ LockBuffer(buf, BUFFER_LOCK_SHARE);
+ page = BufferGetPage(buf);
+ opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ Assert(opaque->hasho_bucket == bucket);
- /* Fetch the primary bucket page for the bucket */
- buf = _hash_getbuf(rel, blkno, HASH_READ, LH_BUCKET_PAGE);
- page = BufferGetPage(buf);
- opaque = (HashPageOpaque) PageGetSpecialPointer(page);
- Assert(opaque->hasho_bucket == bucket);
+ if (H_BUCKET_BEING_POPULATED(opaque))
+ so->hashso_buc_populated = true;
+ else
+ {
+ _hash_dropbuf(rel, so->hashso_split_bucket_buf);
+ so->hashso_split_bucket_buf = InvalidBuffer;
+ }
+ }
/* If a backwards scan is requested, move to the end of the chain */
if (ScanDirectionIsBackward(dir))
{
- while (BlockNumberIsValid(opaque->hasho_nextblkno))
- _hash_readnext(rel, &buf, &page, &opaque);
+ /*
+ * Backward scans that start during split needs to start from end of
+ * bucket being split.
+ */
+ while (BlockNumberIsValid(opaque->hasho_nextblkno) ||
+ (so->hashso_buc_populated && !so->hashso_buc_split))
+ _hash_readnext(scan, &buf, &page, &opaque);
}
/* Now find the first tuple satisfying the qualification */
@@ -273,6 +377,12 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
* false. Else, return true and set the hashso_curpos for the
* scan to the right thing.
*
+ * Here we need to ensure that if the scan has started during split, then
+ * skip the tuples that are moved by split while scanning bucket being
+ * populated and then scan the bucket being split to cover all such
+ * tuples. This is done to ensure that we don't miss tuples in the scans
+ * that are started during split.
+ *
* 'bufP' points to the current buffer, which is pinned and read-locked.
* On success exit, we have pin and read-lock on whichever page
* contains the right item; on failure, we have released all buffers.
@@ -338,14 +448,31 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
{
Assert(offnum >= FirstOffsetNumber);
itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
+
+ /*
+ * skip the tuples that are moved by split operation
+ * for the scan that has started when split was in
+ * progress
+ */
+ if (so->hashso_buc_populated && !so->hashso_buc_split &&
+ (itup->t_info & INDEX_MOVED_BY_SPLIT_MASK))
+ {
+ offnum = OffsetNumberNext(offnum); /* move forward */
+ continue;
+ }
+
if (so->hashso_sk_hash == _hash_get_indextuple_hashkey(itup))
break; /* yes, so exit for-loop */
}
+ /* Before leaving current page, deal with any killed items */
+ if (so->numKilled > 0)
+ _hash_kill_items(scan);
+
/*
* ran off the end of this page, try the next
*/
- _hash_readnext(rel, &buf, &page, &opaque);
+ _hash_readnext(scan, &buf, &page, &opaque);
if (BufferIsValid(buf))
{
maxoff = PageGetMaxOffsetNumber(page);
@@ -353,7 +480,6 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
}
else
{
- /* end of bucket */
itup = NULL;
break; /* exit for-loop */
}
@@ -379,22 +505,39 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
{
Assert(offnum <= maxoff);
itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
+
+ /*
+ * skip the tuples that are moved by split operation
+ * for the scan that has started when split was in
+ * progress
+ */
+ if (so->hashso_buc_populated && !so->hashso_buc_split &&
+ (itup->t_info & INDEX_MOVED_BY_SPLIT_MASK))
+ {
+ offnum = OffsetNumberPrev(offnum); /* move back */
+ continue;
+ }
+
if (so->hashso_sk_hash == _hash_get_indextuple_hashkey(itup))
break; /* yes, so exit for-loop */
}
+ /* Before leaving current page, deal with any killed items */
+ if (so->numKilled > 0)
+ _hash_kill_items(scan);
+
/*
* ran off the end of this page, try the next
*/
- _hash_readprev(rel, &buf, &page, &opaque);
+ _hash_readprev(scan, &buf, &page, &opaque);
if (BufferIsValid(buf))
{
+ TestForOldSnapshot(scan->xs_snapshot, rel, page);
maxoff = PageGetMaxOffsetNumber(page);
offnum = _hash_binsearch_last(page, so->hashso_sk_hash);
}
else
{
- /* end of bucket */
itup = NULL;
break; /* exit for-loop */
}
@@ -410,9 +553,16 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
if (itup == NULL)
{
- /* we ran off the end of the bucket without finding a match */
+ /*
+ * We ran off the end of the bucket without finding a match.
+ * Release the pin on bucket buffers. Normally, such pins are
+ * released at end of scan, however scrolling cursors can
+ * reacquire the bucket lock and pin in the same scan multiple
+ * times.
+ */
*bufP = so->hashso_curbuf = InvalidBuffer;
ItemPointerSetInvalid(current);
+ _hash_dropscanbuf(rel, so);
return false;
}
diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c
index 8938ab5b24..41d615df8b 100644
--- a/src/backend/access/hash/hashsort.c
+++ b/src/backend/access/hash/hashsort.c
@@ -14,7 +14,7 @@
* plenty of locality of access.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -37,7 +37,15 @@ struct HSpool
{
Tuplesortstate *sortstate; /* state data for tuplesort.c */
Relation index;
- uint32 hash_mask; /* bitmask for hash codes */
+
+ /*
+ * We sort the hash keys based on the buckets they belong to. Below masks
+ * are used in _hash_hashkey2bucket to determine the bucket of given hash
+ * key.
+ */
+ uint32 high_mask;
+ uint32 low_mask;
+ uint32 max_buckets;
};
@@ -56,11 +64,12 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
* num_buckets buckets in the index, the appropriate mask can be computed
* as follows.
*
- * Note: at present, the passed-in num_buckets is always a power of 2, so
- * we could just compute num_buckets - 1. We prefer not to assume that
- * here, though.
+ * NOTE : This hash mask calculation should be in sync with similar
+ * calculation in _hash_init_metabuffer.
*/
- hspool->hash_mask = (((uint32) 1) << _hash_log2(num_buckets)) - 1;
+ hspool->high_mask = (((uint32) 1) << _hash_log2(num_buckets + 1)) - 1;
+ hspool->low_mask = (hspool->high_mask >> 1);
+ hspool->max_buckets = num_buckets - 1;
/*
* We size the sort area as maintenance_work_mem rather than work_mem to
@@ -69,7 +78,9 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
*/
hspool->sortstate = tuplesort_begin_index_hash(heap,
index,
- hspool->hash_mask,
+ hspool->high_mask,
+ hspool->low_mask,
+ hspool->max_buckets,
maintenance_work_mem,
false);
@@ -101,18 +112,16 @@ _h_spool(HSpool *hspool, ItemPointer self, Datum *values, bool *isnull)
* create an entire index.
*/
void
-_h_indexbuild(HSpool *hspool)
+_h_indexbuild(HSpool *hspool, Relation heapRel)
{
IndexTuple itup;
- bool should_free;
#ifdef USE_ASSERT_CHECKING
uint32 hashkey = 0;
#endif
tuplesort_performsort(hspool->sortstate);
- while ((itup = tuplesort_getindextuple(hspool->sortstate,
- true, &should_free)) != NULL)
+ while ((itup = tuplesort_getindextuple(hspool->sortstate, true)) != NULL)
{
/*
* Technically, it isn't critical that hash keys be found in sorted
@@ -124,12 +133,12 @@ _h_indexbuild(HSpool *hspool)
#ifdef USE_ASSERT_CHECKING
uint32 lasthashkey = hashkey;
- hashkey = _hash_get_indextuple_hashkey(itup) & hspool->hash_mask;
+ hashkey = _hash_hashkey2bucket(_hash_get_indextuple_hashkey(itup),
+ hspool->max_buckets, hspool->high_mask,
+ hspool->low_mask);
Assert(hashkey >= lasthashkey);
#endif
- _hash_doinsert(hspool->index, itup);
- if (should_free)
- pfree(itup);
+ _hash_doinsert(hspool->index, itup, heapRel);
}
}
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 822862db7a..c513c3b842 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -3,7 +3,7 @@
* hashutil.c
* Utility code for Postgres hash implementation.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -19,7 +19,10 @@
#include "access/relscan.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
+#include "storage/buf_internals.h"
+#define CALC_NEW_BUCKET(old_bucket, lowmask) \
+ old_bucket | (lowmask + 1)
/*
* _hash_checkqual -- does the index tuple satisfy the scan conditions?
@@ -147,10 +150,76 @@ _hash_log2(uint32 num)
}
/*
+ * _hash_spareindex -- returns spare index / global splitpoint phase of the
+ * bucket
+ */
+uint32
+_hash_spareindex(uint32 num_bucket)
+{
+ uint32 splitpoint_group;
+ uint32 splitpoint_phases;
+
+ splitpoint_group = _hash_log2(num_bucket);
+
+ if (splitpoint_group < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
+ return splitpoint_group;
+
+ /* account for single-phase groups */
+ splitpoint_phases = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
+
+ /* account for multi-phase groups before splitpoint_group */
+ splitpoint_phases +=
+ ((splitpoint_group - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) <<
+ HASH_SPLITPOINT_PHASE_BITS);
+
+ /* account for phases within current group */
+ splitpoint_phases +=
+ (((num_bucket - 1) >>
+ (splitpoint_group - (HASH_SPLITPOINT_PHASE_BITS + 1))) &
+ HASH_SPLITPOINT_PHASE_MASK); /* to 0-based value. */
+
+ return splitpoint_phases;
+}
+
+/*
+ * _hash_get_totalbuckets -- returns total number of buckets allocated till
+ * the given splitpoint phase.
+ */
+uint32
+_hash_get_totalbuckets(uint32 splitpoint_phase)
+{
+ uint32 splitpoint_group;
+ uint32 total_buckets;
+ uint32 phases_within_splitpoint_group;
+
+ if (splitpoint_phase < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
+ return (1 << splitpoint_phase);
+
+ /* get splitpoint's group */
+ splitpoint_group = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
+ splitpoint_group +=
+ ((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) >>
+ HASH_SPLITPOINT_PHASE_BITS);
+
+ /* account for buckets before splitpoint_group */
+ total_buckets = (1 << (splitpoint_group - 1));
+
+ /* account for buckets within splitpoint_group */
+ phases_within_splitpoint_group =
+ (((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) &
+ HASH_SPLITPOINT_PHASE_MASK) + 1); /* from 0-based to 1-based */
+ total_buckets +=
+ (((1 << (splitpoint_group - 1)) >> HASH_SPLITPOINT_PHASE_BITS) *
+ phases_within_splitpoint_group);
+
+ return total_buckets;
+}
+
+/*
* _hash_checkpage -- sanity checks on the format of all hash pages
*
- * If flags is not zero, it is a bitwise OR of the acceptable values of
- * hasho_flag.
+ * If flags is not zero, it is a bitwise OR of the acceptable page types
+ * (values of hasho_flag & LH_PAGE_TYPE).
*/
void
_hash_checkpage(Relation rel, Buffer buf, int flags)
@@ -352,3 +421,163 @@ _hash_binsearch_last(Page page, uint32 hash_value)
return lower;
}
+
+/*
+ * _hash_get_oldblock_from_newbucket() -- get the block number of a bucket
+ * from which current (new) bucket is being split.
+ */
+BlockNumber
+_hash_get_oldblock_from_newbucket(Relation rel, Bucket new_bucket)
+{
+ Bucket old_bucket;
+ uint32 mask;
+ Buffer metabuf;
+ HashMetaPage metap;
+ BlockNumber blkno;
+
+ /*
+ * To get the old bucket from the current bucket, we need a mask to modulo
+ * into lower half of table. This mask is stored in meta page as
+ * hashm_lowmask, but here we can't rely on the same, because we need a
+ * value of lowmask that was prevalent at the time when bucket split was
+ * started. Masking the most significant bit of new bucket would give us
+ * old bucket.
+ */
+ mask = (((uint32) 1) << (fls(new_bucket) - 1)) - 1;
+ old_bucket = new_bucket & mask;
+
+ metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
+ metap = HashPageGetMeta(BufferGetPage(metabuf));
+
+ blkno = BUCKET_TO_BLKNO(metap, old_bucket);
+
+ _hash_relbuf(rel, metabuf);
+
+ return blkno;
+}
+
+/*
+ * _hash_get_newblock_from_oldbucket() -- get the block number of a bucket
+ * that will be generated after split from old bucket.
+ *
+ * This is used to find the new bucket from old bucket based on current table
+ * half. It is mainly required to finish the incomplete splits where we are
+ * sure that not more than one bucket could have split in progress from old
+ * bucket.
+ */
+BlockNumber
+_hash_get_newblock_from_oldbucket(Relation rel, Bucket old_bucket)
+{
+ Bucket new_bucket;
+ Buffer metabuf;
+ HashMetaPage metap;
+ BlockNumber blkno;
+
+ metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
+ metap = HashPageGetMeta(BufferGetPage(metabuf));
+
+ new_bucket = _hash_get_newbucket_from_oldbucket(rel, old_bucket,
+ metap->hashm_lowmask,
+ metap->hashm_maxbucket);
+ blkno = BUCKET_TO_BLKNO(metap, new_bucket);
+
+ _hash_relbuf(rel, metabuf);
+
+ return blkno;
+}
+
+/*
+ * _hash_get_newbucket_from_oldbucket() -- get the new bucket that will be
+ * generated after split from current (old) bucket.
+ *
+ * This is used to find the new bucket from old bucket. New bucket can be
+ * obtained by OR'ing old bucket with most significant bit of current table
+ * half (lowmask passed in this function can be used to identify msb of
+ * current table half). There could be multiple buckets that could have
+ * been split from current bucket. We need the first such bucket that exists.
+ * Caller must ensure that no more than one split has happened from old
+ * bucket.
+ */
+Bucket
+_hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket,
+ uint32 lowmask, uint32 maxbucket)
+{
+ Bucket new_bucket;
+
+ new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
+ if (new_bucket > maxbucket)
+ {
+ lowmask = lowmask >> 1;
+ new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
+ }
+
+ return new_bucket;
+}
+
+/*
+ * _hash_kill_items - set LP_DEAD state for items an indexscan caller has
+ * told us were killed.
+ *
+ * scan->opaque, referenced locally through so, contains information about the
+ * current page and killed tuples thereon (generally, this should only be
+ * called if so->numKilled > 0).
+ *
+ * We match items by heap TID before assuming they are the right ones to
+ * delete.
+ */
+void
+_hash_kill_items(IndexScanDesc scan)
+{
+ HashScanOpaque so = (HashScanOpaque) scan->opaque;
+ Page page;
+ HashPageOpaque opaque;
+ OffsetNumber offnum,
+ maxoff;
+ int numKilled = so->numKilled;
+ int i;
+ bool killedsomething = false;
+
+ Assert(so->numKilled > 0);
+ Assert(so->killedItems != NULL);
+
+ /*
+ * Always reset the scan state, so we don't look for same items on other
+ * pages.
+ */
+ so->numKilled = 0;
+
+ page = BufferGetPage(so->hashso_curbuf);
+ opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ maxoff = PageGetMaxOffsetNumber(page);
+
+ for (i = 0; i < numKilled; i++)
+ {
+ offnum = so->killedItems[i].indexOffset;
+
+ while (offnum <= maxoff)
+ {
+ ItemId iid = PageGetItemId(page, offnum);
+ IndexTuple ituple = (IndexTuple) PageGetItem(page, iid);
+
+ if (ItemPointerEquals(&ituple->t_tid, &so->killedItems[i].heapTid))
+ {
+ /* found the item */
+ ItemIdMarkDead(iid);
+ killedsomething = true;
+ break; /* out of inner search loop */
+ }
+ offnum = OffsetNumberNext(offnum);
+ }
+ }
+
+ /*
+ * Since this can be redone later if needed, mark as dirty hint. Whenever
+ * we mark anything LP_DEAD, we also set the page's
+ * LH_PAGE_HAS_DEAD_TUPLES flag, which is likewise just a hint.
+ */
+ if (killedsomething)
+ {
+ opaque->hasho_flag |= LH_PAGE_HAS_DEAD_TUPLES;
+ MarkBufferDirtyHint(so->hashso_curbuf, true);
+ }
+}
diff --git a/src/backend/access/hash/hashvalidate.c b/src/backend/access/hash/hashvalidate.c
index d8c5ed4d98..f914c015bd 100644
--- a/src/backend/access/hash/hashvalidate.c
+++ b/src/backend/access/hash/hashvalidate.c
@@ -3,7 +3,7 @@
* hashvalidate.c
* Opclass validator for hash.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -25,6 +25,7 @@
#include "parser/parse_coerce.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/regproc.h"
#include "utils/syscache.h"
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 2368340b08..05fd372664 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -3,7 +3,7 @@
* heapam.c
* heap access method code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -38,6 +38,7 @@
*/
#include "postgres.h"
+#include "access/bufmask.h"
#include "access/heapam.h"
#include "access/heapam_xlog.h"
#include "access/hio.h"
@@ -98,11 +99,8 @@ static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
Buffer newbuf, HeapTuple oldtup,
HeapTuple newtup, HeapTuple old_key_tup,
bool all_visible_cleared, bool new_all_visible_cleared);
-static void HeapSatisfiesHOTandKeyUpdate(Relation relation,
- Bitmapset *hot_attrs,
- Bitmapset *key_attrs, Bitmapset *id_attrs,
- bool *satisfies_hot, bool *satisfies_key,
- bool *satisfies_id,
+static Bitmapset *HeapDetermineModifiedColumns(Relation relation,
+ Bitmapset *interesting_cols,
HeapTuple oldtup, HeapTuple newtup);
static bool heap_acquire_tuplock(Relation relation, ItemPointer tid,
LockTupleMode mode, LockWaitPolicy wait_policy,
@@ -1134,7 +1132,7 @@ relation_open(Oid relationId, LOCKMODE lockmode)
/* Make note that we've accessed a temporary relation */
if (RelationUsesLocalBuffers(r))
- MyXactAccessedTempRel = true;
+ MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
pgstat_initstats(r);
@@ -1180,7 +1178,7 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
/* Make note that we've accessed a temporary relation */
if (RelationUsesLocalBuffers(r))
- MyXactAccessedTempRel = true;
+ MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
pgstat_initstats(r);
@@ -1760,6 +1758,22 @@ retry:
}
/* ----------------
+ * heap_update_snapshot
+ *
+ * Update snapshot info in heap scan descriptor.
+ * ----------------
+ */
+void
+heap_update_snapshot(HeapScanDesc scan, Snapshot snapshot)
+{
+ Assert(IsMVCCSnapshot(snapshot));
+
+ RegisterSnapshot(snapshot);
+ scan->rs_snapshot = snapshot;
+ scan->rs_temp_snap = true;
+}
+
+/* ----------------
* heap_getnext - retrieve next tuple in scan
*
* Fix to work with index relations.
@@ -2337,6 +2351,17 @@ FreeBulkInsertState(BulkInsertState bistate)
pfree(bistate);
}
+/*
+ * ReleaseBulkInsertStatePin - release a buffer currently held in bistate
+ */
+void
+ReleaseBulkInsertStatePin(BulkInsertState bistate)
+{
+ if (bistate->current_buf != InvalidBuffer)
+ ReleaseBuffer(bistate->current_buf);
+ bistate->current_buf = InvalidBuffer;
+}
+
/*
* heap_insert - insert tuple into a heap
@@ -2520,7 +2545,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
heaptup->t_len - SizeofHeapTupleHeader);
/* filtering by origin on a row level is much more efficient */
- XLogIncludeOrigin();
+ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
recptr = XLogInsert(RM_HEAP_ID, info);
@@ -2862,7 +2887,7 @@ heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples,
XLogRegisterBufData(0, tupledata, totaldatalen);
/* filtering by origin on a row level is much more efficient */
- XLogIncludeOrigin();
+ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
recptr = XLogInsert(RM_HEAP2_ID, info);
@@ -3324,7 +3349,7 @@ l1:
}
/* filtering by origin on a row level is much more efficient */
- XLogIncludeOrigin();
+ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
@@ -3351,7 +3376,7 @@ l1:
Assert(!HeapTupleHasExternal(&tp));
}
else if (HeapTupleHasExternal(&tp))
- toast_delete(relation, &tp);
+ toast_delete(relation, &tp, false);
/*
* Mark tuple for invalidation from system caches at next command
@@ -3459,6 +3484,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
Bitmapset *hot_attrs;
Bitmapset *key_attrs;
Bitmapset *id_attrs;
+ Bitmapset *interesting_attrs;
+ Bitmapset *modified_attrs;
ItemId lp;
HeapTupleData oldtup;
HeapTuple heaptup;
@@ -3476,10 +3503,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
pagefree;
bool have_tuple_lock = false;
bool iscombo;
- bool satisfies_hot;
- bool satisfies_key;
- bool satisfies_id;
bool use_hot_update = false;
+ bool hot_attrs_checked = false;
bool key_intact;
bool all_visible_cleared = false;
bool all_visible_cleared_new = false;
@@ -3505,26 +3530,51 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
errmsg("cannot update tuples during a parallel operation")));
/*
- * Fetch the list of attributes to be checked for HOT update. This is
- * wasted effort if we fail to update or have to put the new tuple on a
- * different page. But we must compute the list before obtaining buffer
- * lock --- in the worst case, if we are doing an update on one of the
- * relevant system catalogs, we could deadlock if we try to fetch the list
- * later. In any case, the relcache caches the data so this is usually
- * pretty cheap.
+ * Fetch the list of attributes to be checked for various operations.
+ *
+ * For HOT considerations, this is wasted effort if we fail to update or
+ * have to put the new tuple on a different page. But we must compute the
+ * list before obtaining buffer lock --- in the worst case, if we are
+ * doing an update on one of the relevant system catalogs, we could
+ * deadlock if we try to fetch the list later. In any case, the relcache
+ * caches the data so this is usually pretty cheap.
*
- * Note that we get a copy here, so we need not worry about relcache flush
- * happening midway through.
+ * We also need columns used by the replica identity and columns that are
+ * considered the "key" of rows in the table.
+ *
+ * Note that we get copies of each bitmap, so we need not worry about
+ * relcache flush happening midway through.
*/
hot_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_ALL);
key_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_KEY);
id_attrs = RelationGetIndexAttrBitmap(relation,
INDEX_ATTR_BITMAP_IDENTITY_KEY);
+
block = ItemPointerGetBlockNumber(otid);
buffer = ReadBuffer(relation, block);
page = BufferGetPage(buffer);
+ interesting_attrs = NULL;
+
+ /*
+ * If the page is already full, there is hardly any chance of doing a HOT
+ * update on this page. It might be wasteful effort to look for index
+ * column updates only to later reject HOT updates for lack of space in
+ * the same page. So we be conservative and only fetch hot_attrs if the
+ * page is not already full. Since we are already holding a pin on the
+ * buffer, there is no chance that the buffer can get cleaned up
+ * concurrently and even if that was possible, in the worst case we lose a
+ * chance to do a HOT update.
+ */
+ if (!PageIsFull(page))
+ {
+ interesting_attrs = bms_add_members(interesting_attrs, hot_attrs);
+ hot_attrs_checked = true;
+ }
+ interesting_attrs = bms_add_members(interesting_attrs, key_attrs);
+ interesting_attrs = bms_add_members(interesting_attrs, id_attrs);
+
/*
* Before locking the buffer, pin the visibility map page if it appears to
* be necessary. Since we haven't got the lock yet, someone else might be
@@ -3540,7 +3590,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
Assert(ItemIdIsNormal(lp));
/*
- * Fill in enough data in oldtup for HeapSatisfiesHOTandKeyUpdate to work
+ * Fill in enough data in oldtup for HeapDetermineModifiedColumns to work
* properly.
*/
oldtup.t_tableOid = RelationGetRelid(relation);
@@ -3566,6 +3616,10 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
Assert(!(newtup->t_data->t_infomask & HEAP_HASOID));
}
+ /* Determine columns modified by the update. */
+ modified_attrs = HeapDetermineModifiedColumns(relation, interesting_attrs,
+ &oldtup, newtup);
+
/*
* If we're not updating any "key" column, we can grab a weaker lock type.
* This allows for more concurrency when we are running simultaneously
@@ -3577,10 +3631,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
* is updates that don't manipulate key columns, not those that
* serendipitiously arrive at the same key values.
*/
- HeapSatisfiesHOTandKeyUpdate(relation, hot_attrs, key_attrs, id_attrs,
- &satisfies_hot, &satisfies_key,
- &satisfies_id, &oldtup, newtup);
- if (satisfies_key)
+ if (!bms_overlap(modified_attrs, key_attrs))
{
*lockmode = LockTupleNoKeyExclusive;
mxact_status = MultiXactStatusNoKeyUpdate;
@@ -3818,6 +3869,9 @@ l2:
ReleaseBuffer(vmbuffer);
bms_free(hot_attrs);
bms_free(key_attrs);
+ bms_free(id_attrs);
+ bms_free(modified_attrs);
+ bms_free(interesting_attrs);
return result;
}
@@ -4123,9 +4177,10 @@ l2:
/*
* Since the new tuple is going into the same page, we might be able
* to do a HOT update. Check if any of the index columns have been
- * changed. If not, then HOT update is possible.
+ * changed. If the page was already full, we may have skipped checking
+ * for index columns. If so, HOT update is possible.
*/
- if (satisfies_hot)
+ if (hot_attrs_checked && !bms_overlap(modified_attrs, hot_attrs))
use_hot_update = true;
}
else
@@ -4140,7 +4195,9 @@ l2:
* ExtractReplicaIdentity() will return NULL if nothing needs to be
* logged.
*/
- old_key_tuple = ExtractReplicaIdentity(relation, &oldtup, !satisfies_id, &old_key_copied);
+ old_key_tuple = ExtractReplicaIdentity(relation, &oldtup,
+ bms_overlap(modified_attrs, id_attrs),
+ &old_key_copied);
/* NO EREPORT(ERROR) from here till changes are logged */
START_CRIT_SECTION();
@@ -4287,13 +4344,16 @@ l2:
bms_free(hot_attrs);
bms_free(key_attrs);
+ bms_free(id_attrs);
+ bms_free(modified_attrs);
+ bms_free(interesting_attrs);
return HeapTupleMayBeUpdated;
}
/*
* Check if the specified attribute's value is same in both given tuples.
- * Subroutine for HeapSatisfiesHOTandKeyUpdate.
+ * Subroutine for HeapDetermineModifiedColumns.
*/
static bool
heap_tuple_attr_equals(TupleDesc tupdesc, int attrnum,
@@ -4330,7 +4390,7 @@ heap_tuple_attr_equals(TupleDesc tupdesc, int attrnum,
/*
* Extract the corresponding values. XXX this is pretty inefficient if
- * there are many indexed columns. Should HeapSatisfiesHOTandKeyUpdate do
+ * there are many indexed columns. Should HeapDetermineModifiedColumns do
* a single heap_deform_tuple call on each tuple, instead? But that
* doesn't work for system columns ...
*/
@@ -4375,114 +4435,30 @@ heap_tuple_attr_equals(TupleDesc tupdesc, int attrnum,
/*
* Check which columns are being updated.
*
- * This simultaneously checks conditions for HOT updates, for FOR KEY
- * SHARE updates, and REPLICA IDENTITY concerns. Since much of the time they
- * will be checking very similar sets of columns, and doing the same tests on
- * them, it makes sense to optimize and do them together.
- *
- * We receive three bitmapsets comprising the three sets of columns we're
- * interested in. Note these are destructively modified; that is OK since
- * this is invoked at most once in heap_update.
+ * Given an updated tuple, determine (and return into the output bitmapset),
+ * from those listed as interesting, the set of columns that changed.
*
- * hot_result is set to TRUE if it's okay to do a HOT update (i.e. it does not
- * modified indexed columns); key_result is set to TRUE if the update does not
- * modify columns used in the key; id_result is set to TRUE if the update does
- * not modify columns in any index marked as the REPLICA IDENTITY.
+ * The input bitmapset is destructively modified; that is OK since this is
+ * invoked at most once in heap_update.
*/
-static void
-HeapSatisfiesHOTandKeyUpdate(Relation relation, Bitmapset *hot_attrs,
- Bitmapset *key_attrs, Bitmapset *id_attrs,
- bool *satisfies_hot, bool *satisfies_key,
- bool *satisfies_id,
+static Bitmapset *
+HeapDetermineModifiedColumns(Relation relation, Bitmapset *interesting_cols,
HeapTuple oldtup, HeapTuple newtup)
{
- int next_hot_attnum;
- int next_key_attnum;
- int next_id_attnum;
- bool hot_result = true;
- bool key_result = true;
- bool id_result = true;
-
- /* If REPLICA IDENTITY is set to FULL, id_attrs will be empty. */
- Assert(bms_is_subset(id_attrs, key_attrs));
- Assert(bms_is_subset(key_attrs, hot_attrs));
-
- /*
- * If one of these sets contains no remaining bits, bms_first_member will
- * return -1, and after adding FirstLowInvalidHeapAttributeNumber (which
- * is negative!) we'll get an attribute number that can't possibly be
- * real, and thus won't match any actual attribute number.
- */
- next_hot_attnum = bms_first_member(hot_attrs);
- next_hot_attnum += FirstLowInvalidHeapAttributeNumber;
- next_key_attnum = bms_first_member(key_attrs);
- next_key_attnum += FirstLowInvalidHeapAttributeNumber;
- next_id_attnum = bms_first_member(id_attrs);
- next_id_attnum += FirstLowInvalidHeapAttributeNumber;
+ int attnum;
+ Bitmapset *modified = NULL;
- for (;;)
+ while ((attnum = bms_first_member(interesting_cols)) >= 0)
{
- bool changed;
- int check_now;
+ attnum += FirstLowInvalidHeapAttributeNumber;
- /*
- * Since the HOT attributes are a superset of the key attributes and
- * the key attributes are a superset of the id attributes, this logic
- * is guaranteed to identify the next column that needs to be checked.
- */
- if (hot_result && next_hot_attnum > FirstLowInvalidHeapAttributeNumber)
- check_now = next_hot_attnum;
- else if (key_result && next_key_attnum > FirstLowInvalidHeapAttributeNumber)
- check_now = next_key_attnum;
- else if (id_result && next_id_attnum > FirstLowInvalidHeapAttributeNumber)
- check_now = next_id_attnum;
- else
- break;
-
- /* See whether it changed. */
- changed = !heap_tuple_attr_equals(RelationGetDescr(relation),
- check_now, oldtup, newtup);
- if (changed)
- {
- if (check_now == next_hot_attnum)
- hot_result = false;
- if (check_now == next_key_attnum)
- key_result = false;
- if (check_now == next_id_attnum)
- id_result = false;
-
- /* if all are false now, we can stop checking */
- if (!hot_result && !key_result && !id_result)
- break;
- }
-
- /*
- * Advance the next attribute numbers for the sets that contain the
- * attribute we just checked. As we work our way through the columns,
- * the next_attnum values will rise; but when each set becomes empty,
- * bms_first_member() will return -1 and the attribute number will end
- * up with a value less than FirstLowInvalidHeapAttributeNumber.
- */
- if (hot_result && check_now == next_hot_attnum)
- {
- next_hot_attnum = bms_first_member(hot_attrs);
- next_hot_attnum += FirstLowInvalidHeapAttributeNumber;
- }
- if (key_result && check_now == next_key_attnum)
- {
- next_key_attnum = bms_first_member(key_attrs);
- next_key_attnum += FirstLowInvalidHeapAttributeNumber;
- }
- if (id_result && check_now == next_id_attnum)
- {
- next_id_attnum = bms_first_member(id_attrs);
- next_id_attnum += FirstLowInvalidHeapAttributeNumber;
- }
+ if (!heap_tuple_attr_equals(RelationGetDescr(relation),
+ attnum, oldtup, newtup))
+ modified = bms_add_member(modified,
+ attnum - FirstLowInvalidHeapAttributeNumber);
}
- *satisfies_hot = hot_result;
- *satisfies_key = key_result;
- *satisfies_id = id_result;
+ return modified;
}
/*
@@ -5745,6 +5721,17 @@ l4:
goto out_locked;
}
+ /*
+ * Also check Xmin: if this tuple was created by an aborted
+ * (sub)transaction, then we already locked the last live one in the
+ * chain, thus we're done, so return success.
+ */
+ if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(mytup.t_data)))
+ {
+ UnlockReleaseBuffer(buf);
+ return HeapTupleMayBeUpdated;
+ }
+
old_infomask = mytup.t_data->t_infomask;
old_infomask2 = mytup.t_data->t_infomask2;
xmax = HeapTupleHeaderGetRawXmax(mytup.t_data);
@@ -6047,7 +6034,7 @@ heap_finish_speculative(Relation relation, HeapTuple tuple)
XLogBeginInsert();
/* We want the same filtering on this as on a plain insert */
- XLogIncludeOrigin();
+ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
XLogRegisterData((char *) &xlrec, SizeOfHeapConfirm);
XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
@@ -6082,7 +6069,8 @@ heap_finish_speculative(Relation relation, HeapTuple tuple)
* could deadlock with each other, which would not be acceptable.
*
* This is somewhat redundant with heap_delete, but we prefer to have a
- * dedicated routine with stripped down requirements.
+ * dedicated routine with stripped down requirements. Note that this is also
+ * used to delete the TOAST tuples created during speculative insertion.
*
* This routine does not affect logical decoding as it only looks at
* confirmation records.
@@ -6126,7 +6114,7 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
*/
if (tp.t_data->t_choice.t_heap.t_xmin != xid)
elog(ERROR, "attempted to kill a tuple inserted by another transaction");
- if (!HeapTupleHeaderIsSpeculative(tp.t_data))
+ if (!(IsToastRelation(relation) || HeapTupleHeaderIsSpeculative(tp.t_data)))
elog(ERROR, "attempted to kill a non-speculative tuple");
Assert(!HeapTupleHeaderIsHeapOnly(tp.t_data));
@@ -6196,7 +6184,10 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
if (HeapTupleHasExternal(&tp))
- toast_delete(relation, &tp);
+ {
+ Assert(!IsToastRelation(relation));
+ toast_delete(relation, &tp, true);
+ }
/*
* Never need to mark tuple for invalidation, since catalogs don't support
@@ -6770,8 +6761,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
* Note: it might seem we could make the changes without exclusive lock, since
* TransactionId read/write is assumed atomic anyway. However there is a race
* condition: someone who just fetched an old XID that we overwrite here could
- * conceivably not finish checking the XID against pg_clog before we finish
- * the VACUUM and perhaps truncate off the part of pg_clog he needs. Getting
+ * conceivably not finish checking the XID against pg_xact before we finish
+ * the VACUUM and perhaps truncate off the part of pg_xact he needs. Getting
* exclusive lock ensures no other backend is in process of checking the
* tuple status. Also, getting exclusive lock makes it safe to adjust the
* infomask bits.
@@ -7711,7 +7702,7 @@ log_heap_update(Relation reln, Buffer oldbuf,
}
/* filtering by origin on a row level is much more efficient */
- XLogIncludeOrigin();
+ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
recptr = XLogInsert(RM_HEAP_ID, info);
@@ -9139,3 +9130,80 @@ heap_sync(Relation rel)
heap_close(toastrel, AccessShareLock);
}
}
+
+/*
+ * Mask a heap page before performing consistency checks on it.
+ */
+void
+heap_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+ OffsetNumber off;
+
+ mask_page_lsn(page);
+
+ mask_page_hint_bits(page);
+ mask_unused_space(page);
+
+ for (off = 1; off <= PageGetMaxOffsetNumber(page); off++)
+ {
+ ItemId iid = PageGetItemId(page, off);
+ char *page_item;
+
+ page_item = (char *) (page + ItemIdGetOffset(iid));
+
+ if (ItemIdIsNormal(iid))
+ {
+ HeapTupleHeader page_htup = (HeapTupleHeader) page_item;
+
+ /*
+ * If xmin of a tuple is not yet frozen, we should ignore
+ * differences in hint bits, since they can be set without
+ * emitting WAL.
+ */
+ if (!HeapTupleHeaderXminFrozen(page_htup))
+ page_htup->t_infomask &= ~HEAP_XACT_MASK;
+ else
+ {
+ /* Still we need to mask xmax hint bits. */
+ page_htup->t_infomask &= ~HEAP_XMAX_INVALID;
+ page_htup->t_infomask &= ~HEAP_XMAX_COMMITTED;
+ }
+
+ /*
+ * During replay, we set Command Id to FirstCommandId. Hence, mask
+ * it. See heap_xlog_insert() for details.
+ */
+ page_htup->t_choice.t_heap.t_field3.t_cid = MASK_MARKER;
+
+ /*
+ * For a speculative tuple, heap_insert() does not set ctid in the
+ * caller-passed heap tuple itself, leaving the ctid field to
+ * contain a speculative token value - a per-backend monotonically
+ * increasing identifier. Besides, it does not WAL-log ctid under
+ * any circumstances.
+ *
+ * During redo, heap_xlog_insert() sets t_ctid to current block
+ * number and self offset number. It doesn't care about any
+ * speculative insertions in master. Hence, we set t_ctid to
+ * current block number and self offset number to ignore any
+ * inconsistency.
+ */
+ if (HeapTupleHeaderIsSpeculative(page_htup))
+ ItemPointerSet(&page_htup->t_ctid, blkno, off);
+ }
+
+ /*
+ * Ignore any padding bytes after the tuple, when the length of the
+ * item is not MAXALIGNed.
+ */
+ if (ItemIdHasStorage(iid))
+ {
+ int len = ItemIdGetLength(iid);
+ int padlen = MAXALIGN(len) - len;
+
+ if (padlen > 0)
+ memset(page_item + len, MASK_MARKER, padlen);
+ }
+ }
+}
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index c90fb71965..6529fe3d6b 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -3,7 +3,7 @@
* hio.c
* POSTGRES heap access method input/output code.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 200861eef1..4f41511764 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -3,7 +3,7 @@
* pruneheap.c
* heap page pruning and HOT-chain management code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index f9ce9861e2..60dcb67a20 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -92,7 +92,7 @@
* heap's TOAST table will go through the normal bufmgr.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
@@ -119,6 +119,8 @@
#include "lib/ilist.h"
+#include "pgstat.h"
+
#include "replication/logical.h"
#include "replication/slot.h"
@@ -209,7 +211,7 @@ typedef struct RewriteMappingFile
} RewriteMappingFile;
/*
- * A single In-Memeory logical rewrite mapping, hanging of
+ * A single In-Memory logical rewrite mapping, hanging off
* RewriteMappingFile->mappings.
*/
typedef struct RewriteMappingDataEntry
@@ -258,9 +260,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
*/
rw_cxt = AllocSetContextCreate(CurrentMemoryContext,
"Table rewrite",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
old_cxt = MemoryContextSwitchTo(rw_cxt);
/* Create and fill in the state struct */
@@ -918,7 +918,8 @@ logical_heap_rewrite_flush_mappings(RewriteState state)
* Note that we deviate from the usual WAL coding practices here,
* check the above "Logical rewrite support" comment for reasoning.
*/
- written = FileWrite(src->vfd, waldata_start, len);
+ written = FileWrite(src->vfd, waldata_start, len,
+ WAIT_EVENT_LOGICAL_REWRITE_WRITE);
if (written != len)
ereport(ERROR,
(errcode_for_file_access(),
@@ -959,7 +960,7 @@ logical_end_heap_rewrite(RewriteState state)
hash_seq_init(&seq_status, state->rs_logical_mappings);
while ((src = (RewriteMappingFile *) hash_seq_search(&seq_status)) != NULL)
{
- if (FileSync(src->vfd) != 0)
+ if (FileSync(src->vfd, WAIT_EVENT_LOGICAL_REWRITE_SYNC) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", src->path)));
@@ -1143,11 +1144,13 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
* Truncate all data that's not guaranteed to have been safely fsynced (by
* previous record or by the last checkpoint).
*/
+ pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE);
if (ftruncate(fd, xlrec->offset) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not truncate file \"%s\" to %u: %m",
path, (uint32) xlrec->offset)));
+ pgstat_report_wait_end();
/* now seek to the position we want to write our data to */
if (lseek(fd, xlrec->offset, SEEK_SET) != xlrec->offset)
@@ -1161,20 +1164,24 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
len = xlrec->num_mappings * sizeof(LogicalRewriteMappingData);
/* write out tail end of mapping file (again) */
+ pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE);
if (write(fd, data, len) != len)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m", path)));
+ pgstat_report_wait_end();
/*
* Now fsync all previously written data. We could improve things and only
* do this for the last write to a file, but the required bookkeeping
* doesn't seem worth the trouble.
*/
+ pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC);
if (pg_fsync(fd) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", path)));
+ pgstat_report_wait_end();
CloseTransientFile(fd);
}
@@ -1196,7 +1203,7 @@ CheckPointLogicalRewriteHeap(void)
XLogRecPtr redo;
DIR *mappings_dir;
struct dirent *mapping_de;
- char path[MAXPGPATH];
+ char path[MAXPGPATH + 20];
/*
* We start of with a minimum of the last redo pointer. No new decoding
@@ -1227,7 +1234,7 @@ CheckPointLogicalRewriteHeap(void)
strcmp(mapping_de->d_name, "..") == 0)
continue;
- snprintf(path, MAXPGPATH, "pg_logical/mappings/%s", mapping_de->d_name);
+ snprintf(path, sizeof(path), "pg_logical/mappings/%s", mapping_de->d_name);
if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
continue;
@@ -1268,10 +1275,12 @@ CheckPointLogicalRewriteHeap(void)
* changed or have only been created since the checkpoint's start,
* but it's currently not deemed worth the effort.
*/
- else if (pg_fsync(fd) != 0)
+ pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC);
+ if (pg_fsync(fd) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", path)));
+ pgstat_report_wait_end();
CloseTransientFile(fd);
}
}
diff --git a/src/backend/access/heap/syncscan.c b/src/backend/access/heap/syncscan.c
index a0f500edc8..20640cbbaf 100644
--- a/src/backend/access/heap/syncscan.c
+++ b/src/backend/access/heap/syncscan.c
@@ -36,7 +36,7 @@
* ss_report_location - update current scan location
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -48,6 +48,8 @@
#include "access/heapam.h"
#include "miscadmin.h"
+#include "storage/lwlock.h"
+#include "storage/shmem.h"
#include "utils/rel.h"
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 452a9ecb68..b9963ab5ef 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -4,7 +4,7 @@
* Support routines for external and compressed storage of
* variable size attributes.
*
- * Copyright (c) 2000-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
@@ -67,7 +67,7 @@ typedef struct toast_compress_header
#define TOAST_COMPRESS_SET_RAWSIZE(ptr, len) \
(((toast_compress_header *) (ptr))->rawsize = (len))
-static void toast_delete_datum(Relation rel, Datum value);
+static void toast_delete_datum(Relation rel, Datum value, bool is_speculative);
static Datum toast_save_datum(Relation rel, Datum value,
struct varlena * oldexternal, int options);
static bool toastrel_valueid_exists(Relation toastrel, Oid valueid);
@@ -461,7 +461,7 @@ toast_datum_size(Datum value)
* ----------
*/
void
-toast_delete(Relation rel, HeapTuple oldtup)
+toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)
{
TupleDesc tupleDesc;
Form_pg_attribute *att;
@@ -508,7 +508,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
if (toast_isnull[i])
continue;
else if (VARATT_IS_EXTERNAL_ONDISK(PointerGetDatum(value)))
- toast_delete_datum(rel, value);
+ toast_delete_datum(rel, value, is_speculative);
}
}
}
@@ -1068,7 +1068,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
if (need_delold)
for (i = 0; i < numAttrs; i++)
if (toast_delold[i])
- toast_delete_datum(rel, toast_oldvalues[i]);
+ toast_delete_datum(rel, toast_oldvalues[i], false);
return result_tuple;
}
@@ -1296,6 +1296,74 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
/* ----------
+ * toast_build_flattened_tuple -
+ *
+ * Build a tuple containing no out-of-line toasted fields.
+ * (This does not eliminate compressed or short-header datums.)
+ *
+ * This is essentially just like heap_form_tuple, except that it will
+ * expand any external-data pointers beforehand.
+ *
+ * It's not very clear whether it would be preferable to decompress
+ * in-line compressed datums while at it. For now, we don't.
+ * ----------
+ */
+HeapTuple
+toast_build_flattened_tuple(TupleDesc tupleDesc,
+ Datum *values,
+ bool *isnull)
+{
+ HeapTuple new_tuple;
+ Form_pg_attribute *att = tupleDesc->attrs;
+ int numAttrs = tupleDesc->natts;
+ int num_to_free;
+ int i;
+ Datum new_values[MaxTupleAttributeNumber];
+ Pointer freeable_values[MaxTupleAttributeNumber];
+
+ /*
+ * We can pass the caller's isnull array directly to heap_form_tuple, but
+ * we potentially need to modify the values array.
+ */
+ Assert(numAttrs <= MaxTupleAttributeNumber);
+ memcpy(new_values, values, numAttrs * sizeof(Datum));
+
+ num_to_free = 0;
+ for (i = 0; i < numAttrs; i++)
+ {
+ /*
+ * Look at non-null varlena attributes
+ */
+ if (!isnull[i] && att[i]->attlen == -1)
+ {
+ struct varlena *new_value;
+
+ new_value = (struct varlena *) DatumGetPointer(new_values[i]);
+ if (VARATT_IS_EXTERNAL(new_value))
+ {
+ new_value = heap_tuple_fetch_attr(new_value);
+ new_values[i] = PointerGetDatum(new_value);
+ freeable_values[num_to_free++] = (Pointer) new_value;
+ }
+ }
+ }
+
+ /*
+ * Form the reconfigured tuple.
+ */
+ new_tuple = heap_form_tuple(tupleDesc, new_values, isnull);
+
+ /*
+ * Free allocated temp values
+ */
+ for (i = 0; i < num_to_free; i++)
+ pfree(freeable_values[i]);
+
+ return new_tuple;
+}
+
+
+/* ----------
* toast_compress_datum -
*
* Create a compressed version of a varlena datum
@@ -1611,7 +1679,9 @@ toast_save_datum(Relation rel, Datum value,
* Create the index entry. We cheat a little here by not using
* FormIndexDatum: this relies on the knowledge that the index columns
* are the same as the initial columns of the table for all the
- * indexes.
+ * indexes. We also cheat by not providing an IndexInfo: this is okay
+ * for now because btree doesn't need one, but we might have to be
+ * more honest someday.
*
* Note also that there had better not be any user-created index on
* the TOAST table, since we don't bother to update anything else.
@@ -1624,7 +1694,8 @@ toast_save_datum(Relation rel, Datum value,
&(toasttup->t_self),
toastrel,
toastidxs[i]->rd_index->indisunique ?
- UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+ UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+ NULL);
}
/*
@@ -1663,7 +1734,7 @@ toast_save_datum(Relation rel, Datum value,
* ----------
*/
static void
-toast_delete_datum(Relation rel, Datum value)
+toast_delete_datum(Relation rel, Datum value, bool is_speculative)
{
struct varlena *attr = (struct varlena *) DatumGetPointer(value);
struct varatt_external toast_pointer;
@@ -1714,7 +1785,10 @@ toast_delete_datum(Relation rel, Datum value)
/*
* Have a chunk, delete it
*/
- simple_heap_delete(toastrel, &toasttup->t_self);
+ if (is_speculative)
+ heap_abort_speculative(toastrel, toasttup);
+ else
+ simple_heap_delete(toastrel, &toasttup->t_self);
}
/*
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index 3ad4a9f587..e5616ce051 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -3,7 +3,7 @@
* visibilitymap.c
* bitmap for tracking visibility of heap tuples
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -508,6 +508,9 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
LockBuffer(mapBuffer, BUFFER_LOCK_EXCLUSIVE);
+ /* NO EREPORT(ERROR) from here till changes are logged */
+ START_CRIT_SECTION();
+
/* Clear out the unwanted bytes. */
MemSet(&map[truncByte + 1], 0, MAPSIZE - (truncByte + 1));
@@ -523,7 +526,20 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
*/
map[truncByte] &= (1 << truncOffset) - 1;
+ /*
+ * Truncation of a relation is WAL-logged at a higher-level, and we
+ * will be called at WAL replay. But if checksums are enabled, we need
+ * to still write a WAL record to protect against a torn page, if the
+ * page is flushed to disk before the truncation WAL record. We cannot
+ * use MarkBufferDirtyHint here, because that will not dirty the page
+ * during recovery.
+ */
MarkBufferDirty(mapBuffer);
+ if (!InRecovery && RelationNeedsWAL(rel) && XLogHintBitIsNeeded())
+ log_newpage_buffer(mapBuffer, false);
+
+ END_CRIT_SECTION();
+
UnlockReleaseBuffer(mapBuffer);
}
else
diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c
index 28f6cde896..7b597a072f 100644
--- a/src/backend/access/index/amapi.c
+++ b/src/backend/access/index/amapi.c
@@ -3,7 +3,7 @@
* amapi.c
* Support routines for API for Postgres index access methods.
*
- * Copyright (c) 2015-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2015-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
@@ -17,6 +17,7 @@
#include "access/htup_details.h"
#include "catalog/pg_am.h"
#include "catalog/pg_opclass.h"
+#include "utils/builtins.h"
#include "utils/syscache.h"
diff --git a/src/backend/access/index/amvalidate.c b/src/backend/access/index/amvalidate.c
index 1a3c5f16b9..80865e9ff9 100644
--- a/src/backend/access/index/amvalidate.c
+++ b/src/backend/access/index/amvalidate.c
@@ -3,7 +3,7 @@
* amvalidate.c
* Support routines for index access methods' amvalidate functions.
*
- * Copyright (c) 2016, PostgreSQL Global Development Group
+ * Copyright (c) 2016-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 65c941d812..a91fda7bcd 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -3,7 +3,7 @@
* genam.c
* general index access method routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -119,6 +119,8 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
scan->xs_itup = NULL;
scan->xs_itupdesc = NULL;
+ scan->xs_hitup = NULL;
+ scan->xs_hitupdesc = NULL;
ItemPointerSetInvalid(&scan->xs_ctup.t_self);
scan->xs_ctup.t_data = NULL;
@@ -166,6 +168,10 @@ IndexScanEnd(IndexScanDesc scan)
* The passed-in values/nulls arrays are the "raw" input to the index AM,
* e.g. results of FormIndexDatum --- this is not necessarily what is stored
* in the index, but it's what the user perceives to be stored.
+ *
+ * Note: if you change anything here, check whether
+ * ExecBuildSlotPartitionKeyDescription() in execMain.c needs a similar
+ * change.
*/
char *
BuildIndexValueDescription(Relation indexRelation,
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 54b71cb2f7..cc5ac8b857 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -3,7 +3,7 @@
* indexam.c
* general index access method routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -20,6 +20,10 @@
* index_insert - insert an index tuple into a relation
* index_markpos - mark a scan position
* index_restrpos - restore a scan position
+ * index_parallelscan_estimate - estimate shared memory for parallel scan
+ * index_parallelscan_initialize - initialize parallel scan
+ * index_parallelrescan - (re)start a parallel scan of an index
+ * index_beginscan_parallel - join parallel index scan
* index_getnext_tid - get the next TID from a scan
* index_fetch_heap - get the scan's next heap tuple
* index_getnext - get the next heap tuple from a scan
@@ -120,7 +124,8 @@ do { \
} while(0)
static IndexScanDesc index_beginscan_internal(Relation indexRelation,
- int nkeys, int norderbys, Snapshot snapshot);
+ int nkeys, int norderbys, Snapshot snapshot,
+ ParallelIndexScanDesc pscan, bool temp_snap);
/* ----------------------------------------------------------------
@@ -191,7 +196,8 @@ index_insert(Relation indexRelation,
bool *isnull,
ItemPointer heap_t_ctid,
Relation heapRelation,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
RELATION_CHECKS;
CHECK_REL_PROCEDURE(aminsert);
@@ -203,7 +209,7 @@ index_insert(Relation indexRelation,
return indexRelation->rd_amroutine->aminsert(indexRelation, values, isnull,
heap_t_ctid, heapRelation,
- checkUnique);
+ checkUnique, indexInfo);
}
/*
@@ -219,7 +225,7 @@ index_beginscan(Relation heapRelation,
{
IndexScanDesc scan;
- scan = index_beginscan_internal(indexRelation, nkeys, norderbys, snapshot);
+ scan = index_beginscan_internal(indexRelation, nkeys, norderbys, snapshot, NULL, false);
/*
* Save additional parameters into the scandesc. Everything else was set
@@ -244,7 +250,7 @@ index_beginscan_bitmap(Relation indexRelation,
{
IndexScanDesc scan;
- scan = index_beginscan_internal(indexRelation, nkeys, 0, snapshot);
+ scan = index_beginscan_internal(indexRelation, nkeys, 0, snapshot, NULL, false);
/*
* Save additional parameters into the scandesc. Everything else was set
@@ -260,8 +266,11 @@ index_beginscan_bitmap(Relation indexRelation,
*/
static IndexScanDesc
index_beginscan_internal(Relation indexRelation,
- int nkeys, int norderbys, Snapshot snapshot)
+ int nkeys, int norderbys, Snapshot snapshot,
+ ParallelIndexScanDesc pscan, bool temp_snap)
{
+ IndexScanDesc scan;
+
RELATION_CHECKS;
CHECK_REL_PROCEDURE(ambeginscan);
@@ -276,8 +285,13 @@ index_beginscan_internal(Relation indexRelation,
/*
* Tell the AM to open a scan.
*/
- return indexRelation->rd_amroutine->ambeginscan(indexRelation, nkeys,
+ scan = indexRelation->rd_amroutine->ambeginscan(indexRelation, nkeys,
norderbys);
+ /* Initialize information for parallel scan. */
+ scan->parallel_scan = pscan;
+ scan->xs_temp_snap = temp_snap;
+
+ return scan;
}
/* ----------------
@@ -341,6 +355,9 @@ index_endscan(IndexScanDesc scan)
/* Release index refcount acquired by index_beginscan */
RelationDecrementReferenceCount(scan->indexRelation);
+ if (scan->xs_temp_snap)
+ UnregisterSnapshot(scan->xs_snapshot);
+
/* Release the scan data structure itself */
IndexScanEnd(scan);
}
@@ -389,6 +406,115 @@ index_restrpos(IndexScanDesc scan)
scan->indexRelation->rd_amroutine->amrestrpos(scan);
}
+/*
+ * index_parallelscan_estimate - estimate shared memory for parallel scan
+ *
+ * Currently, we don't pass any information to the AM-specific estimator,
+ * so it can probably only return a constant. In the future, we might need
+ * to pass more information.
+ */
+Size
+index_parallelscan_estimate(Relation indexRelation, Snapshot snapshot)
+{
+ Size nbytes;
+
+ RELATION_CHECKS;
+
+ nbytes = offsetof(ParallelIndexScanDescData, ps_snapshot_data);
+ nbytes = add_size(nbytes, EstimateSnapshotSpace(snapshot));
+ nbytes = MAXALIGN(nbytes);
+
+ /*
+ * If amestimateparallelscan is not provided, assume there is no
+ * AM-specific data needed. (It's hard to believe that could work, but
+ * it's easy enough to cater to it here.)
+ */
+ if (indexRelation->rd_amroutine->amestimateparallelscan != NULL)
+ nbytes = add_size(nbytes,
+ indexRelation->rd_amroutine->amestimateparallelscan());
+
+ return nbytes;
+}
+
+/*
+ * index_parallelscan_initialize - initialize parallel scan
+ *
+ * We initialize both the ParallelIndexScanDesc proper and the AM-specific
+ * information which follows it.
+ *
+ * This function calls access method specific initialization routine to
+ * initialize am specific information. Call this just once in the leader
+ * process; then, individual workers attach via index_beginscan_parallel.
+ */
+void
+index_parallelscan_initialize(Relation heapRelation, Relation indexRelation,
+ Snapshot snapshot, ParallelIndexScanDesc target)
+{
+ Size offset;
+
+ RELATION_CHECKS;
+
+ offset = add_size(offsetof(ParallelIndexScanDescData, ps_snapshot_data),
+ EstimateSnapshotSpace(snapshot));
+ offset = MAXALIGN(offset);
+
+ target->ps_relid = RelationGetRelid(heapRelation);
+ target->ps_indexid = RelationGetRelid(indexRelation);
+ target->ps_offset = offset;
+ SerializeSnapshot(snapshot, target->ps_snapshot_data);
+
+ /* aminitparallelscan is optional; assume no-op if not provided by AM */
+ if (indexRelation->rd_amroutine->aminitparallelscan != NULL)
+ {
+ void *amtarget;
+
+ amtarget = OffsetToPointer(target, offset);
+ indexRelation->rd_amroutine->aminitparallelscan(amtarget);
+ }
+}
+
+/* ----------------
+ * index_parallelrescan - (re)start a parallel scan of an index
+ * ----------------
+ */
+void
+index_parallelrescan(IndexScanDesc scan)
+{
+ SCAN_CHECKS;
+
+ /* amparallelrescan is optional; assume no-op if not provided by AM */
+ if (scan->indexRelation->rd_amroutine->amparallelrescan != NULL)
+ scan->indexRelation->rd_amroutine->amparallelrescan(scan);
+}
+
+/*
+ * index_beginscan_parallel - join parallel index scan
+ *
+ * Caller must be holding suitable locks on the heap and the index.
+ */
+IndexScanDesc
+index_beginscan_parallel(Relation heaprel, Relation indexrel, int nkeys,
+ int norderbys, ParallelIndexScanDesc pscan)
+{
+ Snapshot snapshot;
+ IndexScanDesc scan;
+
+ Assert(RelationGetRelid(heaprel) == pscan->ps_relid);
+ snapshot = RestoreSnapshot(pscan->ps_snapshot_data);
+ RegisterSnapshot(snapshot);
+ scan = index_beginscan_internal(indexrel, nkeys, norderbys, snapshot,
+ pscan, true);
+
+ /*
+ * Save additional parameters into the scandesc. Everything else was set
+ * up by index_beginscan_internal.
+ */
+ scan->heapRelation = heaprel;
+ scan->xs_snapshot = snapshot;
+
+ return scan;
+}
+
/* ----------------
* index_getnext_tid - get the next TID from a scan
*
@@ -409,8 +535,8 @@ index_getnext_tid(IndexScanDesc scan, ScanDirection direction)
/*
* The AM's amgettuple proc finds the next index entry matching the scan
* keys, and puts the TID into scan->xs_ctup.t_self. It should also set
- * scan->xs_recheck and possibly scan->xs_itup, though we pay no attention
- * to those fields here.
+ * scan->xs_recheck and possibly scan->xs_itup/scan->xs_hitup, though we
+ * pay no attention to those fields here.
*/
found = scan->indexRelation->rd_amroutine->amgettuple(scan, direction);
diff --git a/src/backend/access/nbtree/README b/src/backend/access/nbtree/README
index 067d15c803..a3f11da8d5 100644
--- a/src/backend/access/nbtree/README
+++ b/src/backend/access/nbtree/README
@@ -521,11 +521,12 @@ because it allows running applications to continue while the standby
changes state into a normally running server.
The interlocking required to avoid returning incorrect results from
-MVCC scans is not required on standby nodes. That is because
+non-MVCC scans is not required on standby nodes. That is because
HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesSelf(),
HeapTupleSatisfiesDirty() and HeapTupleSatisfiesVacuum() are only
ever used during write transactions, which cannot exist on the standby.
-This leaves HeapTupleSatisfiesMVCC() and HeapTupleSatisfiesToast().
+MVCC scans are already protected by definition, so HeapTupleSatisfiesMVCC()
+is not a problem. That leaves concern only for HeapTupleSatisfiesToast().
HeapTupleSatisfiesToast() doesn't use MVCC semantics, though that's
because it doesn't need to - if the main heap row is visible then the
toast rows will also be visible. So as long as we follow a toast
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c
index 0d60da61cc..4b131efb87 100644
--- a/src/backend/access/nbtree/nbtcompare.c
+++ b/src/backend/access/nbtree/nbtcompare.c
@@ -3,7 +3,7 @@
* nbtcompare.c
* Comparison functions for btree access method.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index ef69290b6c..6dca8109fd 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -3,7 +3,7 @@
* nbtinsert.c
* Item insertion in Lehman and Yao btrees for Postgres.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -17,6 +17,7 @@
#include "access/heapam.h"
#include "access/nbtree.h"
+#include "access/nbtxlog.h"
#include "access/transam.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 2001dc14fb..f815fd40b2 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -4,7 +4,7 @@
* BTree-specific page management code for the Postgres btree access
* method.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -23,6 +23,7 @@
#include "postgres.h"
#include "access/nbtree.h"
+#include "access/nbtxlog.h"
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 4668c5ee59..116f5f32f6 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -8,7 +8,7 @@
* This file contains only the public interface routines.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -23,11 +23,14 @@
#include "access/xlog.h"
#include "catalog/index.h"
#include "commands/vacuum.h"
+#include "pgstat.h"
+#include "storage/condition_variable.h"
#include "storage/indexfsm.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
#include "tcop/tcopprot.h" /* pgrminclude ignore */
+#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
#include "utils/memutils.h"
@@ -62,6 +65,45 @@ typedef struct
MemoryContext pagedelcontext;
} BTVacState;
+/*
+ * BTPARALLEL_NOT_INITIALIZED indicates that the scan has not started.
+ *
+ * BTPARALLEL_ADVANCING indicates that some process is advancing the scan to
+ * a new page; others must wait.
+ *
+ * BTPARALLEL_IDLE indicates that no backend is currently advancing the scan
+ * to a new page; some process can start doing that.
+ *
+ * BTPARALLEL_DONE indicates that the scan is complete (including error exit).
+ * We reach this state once for every distinct combination of array keys.
+ */
+typedef enum
+{
+ BTPARALLEL_NOT_INITIALIZED,
+ BTPARALLEL_ADVANCING,
+ BTPARALLEL_IDLE,
+ BTPARALLEL_DONE
+} BTPS_State;
+
+/*
+ * BTParallelScanDescData contains btree specific shared information required
+ * for parallel scan.
+ */
+typedef struct BTParallelScanDescData
+{
+ BlockNumber btps_scanPage; /* latest or next page to be scanned */
+ BTPS_State btps_pageStatus;/* indicates whether next page is available
+ * for scan. see above for possible states of
+ * parallel scan. */
+ int btps_arrayKeyCount; /* count indicating number of array
+ * scan keys processed by parallel
+ * scan */
+ slock_t btps_mutex; /* protects above variables */
+ ConditionVariable btps_cv; /* used to synchronize parallel scan */
+} BTParallelScanDescData;
+
+typedef struct BTParallelScanDescData *BTParallelScanDesc;
+
static void btbuildCallback(Relation index,
HeapTuple htup,
@@ -98,6 +140,7 @@ bthandler(PG_FUNCTION_ARGS)
amroutine->amstorage = false;
amroutine->amclusterable = true;
amroutine->ampredlocks = true;
+ amroutine->amcanparallel = true;
amroutine->amkeytype = InvalidOid;
amroutine->ambuild = btbuild;
@@ -117,6 +160,9 @@ bthandler(PG_FUNCTION_ARGS)
amroutine->amendscan = btendscan;
amroutine->ammarkpos = btmarkpos;
amroutine->amrestrpos = btrestrpos;
+ amroutine->amestimateparallelscan = btestimateparallelscan;
+ amroutine->aminitparallelscan = btinitparallelscan;
+ amroutine->amparallelrescan = btparallelrescan;
PG_RETURN_POINTER(amroutine);
}
@@ -242,13 +288,18 @@ btbuildempty(Relation index)
metapage = (Page) palloc(BLCKSZ);
_bt_initmetapage(metapage, P_NONE, 0);
- /* Write the page. If archiving/streaming, XLOG it. */
+ /*
+ * Write the page and log it. It might seem that an immediate sync would
+ * be sufficient to guarantee that the file exists on disk, but recovery
+ * itself might remove it while replaying, for example, an
+ * XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE record. Therefore, we need
+ * this even when wal_level=minimal.
+ */
PageSetChecksumInplace(metapage, BTREE_METAPAGE);
smgrwrite(index->rd_smgr, INIT_FORKNUM, BTREE_METAPAGE,
(char *) metapage, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
- BTREE_METAPAGE, metapage, false);
+ log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ BTREE_METAPAGE, metapage, false);
/*
* An immediate sync is required even if we xlog'd the page, because the
@@ -267,7 +318,8 @@ btbuildempty(Relation index)
bool
btinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
bool result;
IndexTuple itup;
@@ -481,6 +533,7 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
}
so->markItemIndex = -1;
+ so->arrayKeyCount = 0;
BTScanPosUnpinIfPinned(so->markPos);
BTScanPosInvalidate(so->markPos);
@@ -643,6 +696,217 @@ btrestrpos(IndexScanDesc scan)
}
/*
+ * btestimateparallelscan -- estimate storage for BTParallelScanDescData
+ */
+Size
+btestimateparallelscan(void)
+{
+ return sizeof(BTParallelScanDescData);
+}
+
+/*
+ * btinitparallelscan -- initialize BTParallelScanDesc for parallel btree scan
+ */
+void
+btinitparallelscan(void *target)
+{
+ BTParallelScanDesc bt_target = (BTParallelScanDesc) target;
+
+ SpinLockInit(&bt_target->btps_mutex);
+ bt_target->btps_scanPage = InvalidBlockNumber;
+ bt_target->btps_pageStatus = BTPARALLEL_NOT_INITIALIZED;
+ bt_target->btps_arrayKeyCount = 0;
+ ConditionVariableInit(&bt_target->btps_cv);
+}
+
+/*
+ * btparallelrescan() -- reset parallel scan
+ */
+void
+btparallelrescan(IndexScanDesc scan)
+{
+ BTParallelScanDesc btscan;
+ ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
+
+ Assert(parallel_scan);
+
+ btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan,
+ parallel_scan->ps_offset);
+
+ /*
+ * In theory, we don't need to acquire the spinlock here, because there
+ * shouldn't be any other workers running at this point, but we do so for
+ * consistency.
+ */
+ SpinLockAcquire(&btscan->btps_mutex);
+ btscan->btps_scanPage = InvalidBlockNumber;
+ btscan->btps_pageStatus = BTPARALLEL_NOT_INITIALIZED;
+ btscan->btps_arrayKeyCount = 0;
+ SpinLockRelease(&btscan->btps_mutex);
+}
+
+/*
+ * _bt_parallel_seize() -- Begin the process of advancing the scan to a new
+ * page. Other scans must wait until we call bt_parallel_release() or
+ * bt_parallel_done().
+ *
+ * The return value is true if we successfully seized the scan and false
+ * if we did not. The latter case occurs if no pages remain for the current
+ * set of scankeys.
+ *
+ * If the return value is true, *pageno returns the next or current page
+ * of the scan (depending on the scan direction). An invalid block number
+ * means the scan hasn't yet started, and P_NONE means we've reached the end.
+ * The first time a participating process reaches the last page, it will return
+ * true and set *pageno to P_NONE; after that, further attempts to seize the
+ * scan will return false.
+ *
+ * Callers should ignore the value of pageno if the return value is false.
+ */
+bool
+_bt_parallel_seize(IndexScanDesc scan, BlockNumber *pageno)
+{
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ BTPS_State pageStatus;
+ bool exit_loop = false;
+ bool status = true;
+ ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
+ BTParallelScanDesc btscan;
+
+ *pageno = P_NONE;
+
+ btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan,
+ parallel_scan->ps_offset);
+
+ while (1)
+ {
+ SpinLockAcquire(&btscan->btps_mutex);
+ pageStatus = btscan->btps_pageStatus;
+
+ if (so->arrayKeyCount < btscan->btps_arrayKeyCount)
+ {
+ /* Parallel scan has already advanced to a new set of scankeys. */
+ status = false;
+ }
+ else if (pageStatus == BTPARALLEL_DONE)
+ {
+ /*
+ * We're done with this set of scankeys. This may be the end, or
+ * there could be more sets to try.
+ */
+ status = false;
+ }
+ else if (pageStatus != BTPARALLEL_ADVANCING)
+ {
+ /*
+ * We have successfully seized control of the scan for the purpose
+ * of advancing it to a new page!
+ */
+ btscan->btps_pageStatus = BTPARALLEL_ADVANCING;
+ *pageno = btscan->btps_scanPage;
+ exit_loop = true;
+ }
+ SpinLockRelease(&btscan->btps_mutex);
+ if (exit_loop || !status)
+ break;
+ ConditionVariableSleep(&btscan->btps_cv, WAIT_EVENT_BTREE_PAGE);
+ }
+ ConditionVariableCancelSleep();
+
+ return status;
+}
+
+/*
+ * _bt_parallel_release() -- Complete the process of advancing the scan to a
+ * new page. We now have the new value btps_scanPage; some other backend
+ * can now begin advancing the scan.
+ */
+void
+_bt_parallel_release(IndexScanDesc scan, BlockNumber scan_page)
+{
+ ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
+ BTParallelScanDesc btscan;
+
+ btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan,
+ parallel_scan->ps_offset);
+
+ SpinLockAcquire(&btscan->btps_mutex);
+ btscan->btps_scanPage = scan_page;
+ btscan->btps_pageStatus = BTPARALLEL_IDLE;
+ SpinLockRelease(&btscan->btps_mutex);
+ ConditionVariableSignal(&btscan->btps_cv);
+}
+
+/*
+ * _bt_parallel_done() -- Mark the parallel scan as complete.
+ *
+ * When there are no pages left to scan, this function should be called to
+ * notify other workers. Otherwise, they might wait forever for the scan to
+ * advance to the next page.
+ */
+void
+_bt_parallel_done(IndexScanDesc scan)
+{
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
+ BTParallelScanDesc btscan;
+ bool status_changed = false;
+
+ /* Do nothing, for non-parallel scans */
+ if (parallel_scan == NULL)
+ return;
+
+ btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan,
+ parallel_scan->ps_offset);
+
+ /*
+ * Mark the parallel scan as done for this combination of scan keys,
+ * unless some other process already did so. See also
+ * _bt_advance_array_keys.
+ */
+ SpinLockAcquire(&btscan->btps_mutex);
+ if (so->arrayKeyCount >= btscan->btps_arrayKeyCount &&
+ btscan->btps_pageStatus != BTPARALLEL_DONE)
+ {
+ btscan->btps_pageStatus = BTPARALLEL_DONE;
+ status_changed = true;
+ }
+ SpinLockRelease(&btscan->btps_mutex);
+
+ /* wake up all the workers associated with this parallel scan */
+ if (status_changed)
+ ConditionVariableBroadcast(&btscan->btps_cv);
+}
+
+/*
+ * _bt_parallel_advance_array_keys() -- Advances the parallel scan for array
+ * keys.
+ *
+ * Updates the count of array keys processed for both local and parallel
+ * scans.
+ */
+void
+_bt_parallel_advance_array_keys(IndexScanDesc scan)
+{
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
+ BTParallelScanDesc btscan;
+
+ btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan,
+ parallel_scan->ps_offset);
+
+ so->arrayKeyCount++;
+ SpinLockAcquire(&btscan->btps_mutex);
+ if (btscan->btps_pageStatus == BTPARALLEL_DONE)
+ {
+ btscan->btps_scanPage = InvalidBlockNumber;
+ btscan->btps_pageStatus = BTPARALLEL_NOT_INITIALIZED;
+ btscan->btps_arrayKeyCount++;
+ }
+ SpinLockRelease(&btscan->btps_mutex);
+}
+
+/*
* Bulk deletion of all index entries pointing to a set of heap tuples.
* The set of target tuples is specified via a callback routine that tells
* whether any given heap tuple (identified by ItemPointer) is being deleted.
@@ -763,9 +1027,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
/* Create a temporary memory context to run _bt_pagedel in */
vstate.pagedelcontext = AllocSetContextCreate(CurrentMemoryContext,
"_bt_pagedel",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* The outer loop iterates over all index pages except the metapage, in
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index ee46023c5a..2f32b2e78d 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -4,7 +4,7 @@
* Search code for postgres btrees.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -30,9 +30,13 @@ static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir,
static void _bt_saveitem(BTScanOpaque so, int itemIndex,
OffsetNumber offnum, IndexTuple itup);
static bool _bt_steppage(IndexScanDesc scan, ScanDirection dir);
+static bool _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir);
+static bool _bt_parallel_readpage(IndexScanDesc scan, BlockNumber blkno,
+ ScanDirection dir);
static Buffer _bt_walk_left(Relation rel, Buffer buf, Snapshot snapshot);
static bool _bt_endpoint(IndexScanDesc scan, ScanDirection dir);
static void _bt_drop_lock_and_maybe_pin(IndexScanDesc scan, BTScanPos sp);
+static inline void _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir);
/*
@@ -544,8 +548,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ScanKeyData notnullkeys[INDEX_MAX_KEYS];
int keysCount = 0;
int i;
+ bool status = true;
StrategyNumber strat_total;
BTScanPosItem *currItem;
+ BlockNumber blkno;
Assert(!BTScanPosIsValid(so->currPos));
@@ -564,6 +570,30 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
if (!so->qual_ok)
return false;
+ /*
+ * For parallel scans, get the starting page from shared state. If the
+ * scan has not started, proceed to find out first leaf page in the usual
+ * way while keeping other participating processes waiting. If the scan
+ * has already begun, use the page number from the shared structure.
+ */
+ if (scan->parallel_scan != NULL)
+ {
+ status = _bt_parallel_seize(scan, &blkno);
+ if (!status)
+ return false;
+ else if (blkno == P_NONE)
+ {
+ _bt_parallel_done(scan);
+ return false;
+ }
+ else if (blkno != InvalidBlockNumber)
+ {
+ if (!_bt_parallel_readpage(scan, blkno, dir))
+ return false;
+ goto readcomplete;
+ }
+ }
+
/*----------
* Examine the scan keys to discover where we need to start the scan.
*
@@ -743,7 +773,19 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* there.
*/
if (keysCount == 0)
- return _bt_endpoint(scan, dir);
+ {
+ bool match;
+
+ match = _bt_endpoint(scan, dir);
+
+ if (!match)
+ {
+ /* No match, so mark (parallel) scan finished */
+ _bt_parallel_done(scan);
+ }
+
+ return match;
+ }
/*
* We want to start the scan somewhere within the index. Set up an
@@ -773,7 +815,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
Assert(subkey->sk_flags & SK_ROW_MEMBER);
if (subkey->sk_flags & SK_ISNULL)
+ {
+ _bt_parallel_done(scan);
return false;
+ }
memcpy(scankeys + i, subkey, sizeof(ScanKeyData));
/*
@@ -993,25 +1038,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* because nothing finer to lock exists.
*/
PredicateLockRelation(rel, scan->xs_snapshot);
+
+ /*
+ * mark parallel scan as done, so that all the workers can finish
+ * their scan
+ */
+ _bt_parallel_done(scan);
+ BTScanPosInvalidate(so->currPos);
+
return false;
}
else
PredicateLockPage(rel, BufferGetBlockNumber(buf),
scan->xs_snapshot);
- /* initialize moreLeft/moreRight appropriately for scan direction */
- if (ScanDirectionIsForward(dir))
- {
- so->currPos.moreLeft = false;
- so->currPos.moreRight = true;
- }
- else
- {
- so->currPos.moreLeft = true;
- so->currPos.moreRight = false;
- }
- so->numKilled = 0; /* just paranoia */
- Assert(so->markItemIndex == -1);
+ _bt_initialize_more_data(so, dir);
/* position to the precise item on the page */
offnum = _bt_binsrch(rel, buf, keysCount, scankeys, nextkey);
@@ -1060,6 +1101,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
_bt_drop_lock_and_maybe_pin(scan, &so->currPos);
}
+readcomplete:
/* OK, itemIndex says what to return */
currItem = &so->currPos.items[so->currPos.itemIndex];
scan->xs_ctup.t_self = currItem->heapTid;
@@ -1132,6 +1174,10 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
* moreLeft or moreRight (as appropriate) is cleared if _bt_checkkeys reports
* that there can be no more matching tuples in the current scan direction.
*
+ * In the case of a parallel scan, caller must have called _bt_parallel_seize
+ * prior to calling this function; this function will invoke
+ * _bt_parallel_release before returning.
+ *
* Returns true if any matching items found on the page, false if none.
*/
static bool
@@ -1154,6 +1200,16 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
page = BufferGetPage(so->currPos.buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+
+ /* allow next page be processed by parallel worker */
+ if (scan->parallel_scan)
+ {
+ if (ScanDirectionIsForward(dir))
+ _bt_parallel_release(scan, opaque->btpo_next);
+ else
+ _bt_parallel_release(scan, BufferGetBlockNumber(so->currPos.buf));
+ }
+
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
@@ -1278,21 +1334,16 @@ _bt_saveitem(BTScanOpaque so, int itemIndex,
* if pinned, we'll drop the pin before moving to next page. The buffer is
* not locked on entry.
*
- * On success exit, so->currPos is updated to contain data from the next
- * interesting page. For success on a scan using a non-MVCC snapshot we hold
- * a pin, but not a read lock, on that page. If we do not hold the pin, we
- * set so->currPos.buf to InvalidBuffer. We return TRUE to indicate success.
- *
- * If there are no more matching records in the given direction, we drop all
- * locks and pins, set so->currPos.buf to InvalidBuffer, and return FALSE.
+ * For success on a scan using a non-MVCC snapshot we hold a pin, but not a
+ * read lock, on that page. If we do not hold the pin, we set so->currPos.buf
+ * to InvalidBuffer. We return TRUE to indicate success.
*/
static bool
_bt_steppage(IndexScanDesc scan, ScanDirection dir)
{
BTScanOpaque so = (BTScanOpaque) scan->opaque;
- Relation rel;
- Page page;
- BTPageOpaque opaque;
+ BlockNumber blkno = InvalidBlockNumber;
+ bool status = true;
Assert(BTScanPosIsValid(so->currPos));
@@ -1319,25 +1370,103 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
so->markItemIndex = -1;
}
- rel = scan->indexRelation;
-
if (ScanDirectionIsForward(dir))
{
/* Walk right to the next page with data */
- /* We must rely on the previously saved nextPage link! */
- BlockNumber blkno = so->currPos.nextPage;
+ if (scan->parallel_scan != NULL)
+ {
+ /*
+ * Seize the scan to get the next block number; if the scan has
+ * ended already, bail out.
+ */
+ status = _bt_parallel_seize(scan, &blkno);
+ if (!status)
+ {
+ /* release the previous buffer, if pinned */
+ BTScanPosUnpinIfPinned(so->currPos);
+ BTScanPosInvalidate(so->currPos);
+ return false;
+ }
+ }
+ else
+ {
+ /* Not parallel, so use the previously-saved nextPage link. */
+ blkno = so->currPos.nextPage;
+ }
/* Remember we left a page with data */
so->currPos.moreLeft = true;
/* release the previous buffer, if pinned */
BTScanPosUnpinIfPinned(so->currPos);
+ }
+ else
+ {
+ /* Remember we left a page with data */
+ so->currPos.moreRight = true;
+
+ if (scan->parallel_scan != NULL)
+ {
+ /*
+ * Seize the scan to get the current block number; if the scan has
+ * ended already, bail out.
+ */
+ status = _bt_parallel_seize(scan, &blkno);
+ BTScanPosUnpinIfPinned(so->currPos);
+ if (!status)
+ {
+ BTScanPosInvalidate(so->currPos);
+ return false;
+ }
+ }
+ else
+ {
+ /* Not parallel, so just use our own notion of the current page */
+ blkno = so->currPos.currPage;
+ }
+ }
+
+ if (!_bt_readnextpage(scan, blkno, dir))
+ return false;
+
+ /* Drop the lock, and maybe the pin, on the current page */
+ _bt_drop_lock_and_maybe_pin(scan, &so->currPos);
+
+ return true;
+}
+/*
+ * _bt_readnextpage() -- Read next page containing valid data for scan
+ *
+ * On success exit, so->currPos is updated to contain data from the next
+ * interesting page. Caller is responsible to release lock and pin on
+ * buffer on success. We return TRUE to indicate success.
+ *
+ * If there are no more matching records in the given direction, we drop all
+ * locks and pins, set so->currPos.buf to InvalidBuffer, and return FALSE.
+ */
+static bool
+_bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir)
+{
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ Relation rel;
+ Page page;
+ BTPageOpaque opaque;
+ bool status = true;
+
+ rel = scan->indexRelation;
+
+ if (ScanDirectionIsForward(dir))
+ {
for (;;)
{
- /* if we're at end of scan, give up */
+ /*
+ * if we're at end of scan, give up and mark parallel scan as
+ * done, so that all the workers can finish their scan
+ */
if (blkno == P_NONE || !so->currPos.moreRight)
{
+ _bt_parallel_done(scan);
BTScanPosInvalidate(so->currPos);
return false;
}
@@ -1345,10 +1474,10 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
CHECK_FOR_INTERRUPTS();
/* step right one page */
so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ);
- /* check for deleted page */
page = BufferGetPage(so->currPos.buf);
TestForOldSnapshot(scan->xs_snapshot, rel, page);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+ /* check for deleted page */
if (!P_IGNORE(opaque))
{
PredicateLockPage(rel, blkno, scan->xs_snapshot);
@@ -1359,14 +1488,32 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
}
/* nope, keep going */
- blkno = opaque->btpo_next;
+ if (scan->parallel_scan != NULL)
+ {
+ status = _bt_parallel_seize(scan, &blkno);
+ if (!status)
+ {
+ _bt_relbuf(rel, so->currPos.buf);
+ BTScanPosInvalidate(so->currPos);
+ return false;
+ }
+ }
+ else
+ blkno = opaque->btpo_next;
_bt_relbuf(rel, so->currPos.buf);
}
}
else
{
- /* Remember we left a page with data */
- so->currPos.moreRight = true;
+ /*
+ * Should only happen in parallel cases, when some other backend
+ * advanced the scan.
+ */
+ if (so->currPos.currPage != blkno)
+ {
+ BTScanPosUnpinIfPinned(so->currPos);
+ so->currPos.currPage = blkno;
+ }
/*
* Walk left to the next page with data. This is much more complex
@@ -1401,6 +1548,7 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
if (!so->currPos.moreLeft)
{
_bt_relbuf(rel, so->currPos.buf);
+ _bt_parallel_done(scan);
BTScanPosInvalidate(so->currPos);
return false;
}
@@ -1412,6 +1560,7 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
/* if we're physically at end of index, return failure */
if (so->currPos.buf == InvalidBuffer)
{
+ _bt_parallel_done(scan);
BTScanPosInvalidate(so->currPos);
return false;
}
@@ -1432,9 +1581,46 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page)))
break;
}
+
+ /*
+ * For parallel scans, get the last page scanned as it is quite
+ * possible that by the time we try to seize the scan, some other
+ * worker has already advanced the scan to a different page. We
+ * must continue based on the latest page scanned by any worker.
+ */
+ if (scan->parallel_scan != NULL)
+ {
+ _bt_relbuf(rel, so->currPos.buf);
+ status = _bt_parallel_seize(scan, &blkno);
+ if (!status)
+ {
+ BTScanPosInvalidate(so->currPos);
+ return false;
+ }
+ so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ);
+ }
}
}
+ return true;
+}
+
+/*
+ * _bt_parallel_readpage() -- Read current page containing valid data for scan
+ *
+ * On success, release lock and maybe pin on buffer. We return TRUE to
+ * indicate success.
+ */
+static bool
+_bt_parallel_readpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir)
+{
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+
+ _bt_initialize_more_data(so, dir);
+
+ if (!_bt_readnextpage(scan, blkno, dir))
+ return false;
+
/* Drop the lock, and maybe the pin, on the current page */
_bt_drop_lock_and_maybe_pin(scan, &so->currPos);
@@ -1712,19 +1898,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
/* remember which buffer we have pinned */
so->currPos.buf = buf;
- /* initialize moreLeft/moreRight appropriately for scan direction */
- if (ScanDirectionIsForward(dir))
- {
- so->currPos.moreLeft = false;
- so->currPos.moreRight = true;
- }
- else
- {
- so->currPos.moreLeft = true;
- so->currPos.moreRight = false;
- }
- so->numKilled = 0; /* just paranoia */
- so->markItemIndex = -1; /* ditto */
+ _bt_initialize_more_data(so, dir);
/*
* Now load data from the first page of the scan.
@@ -1753,3 +1927,25 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
return true;
}
+
+/*
+ * _bt_initialize_more_data() -- initialize moreLeft/moreRight appropriately
+ * for scan direction
+ */
+static inline void
+_bt_initialize_more_data(BTScanOpaque so, ScanDirection dir)
+{
+ /* initialize moreLeft/moreRight appropriately for scan direction */
+ if (ScanDirectionIsForward(dir))
+ {
+ so->currPos.moreLeft = false;
+ so->currPos.moreRight = true;
+ }
+ else
+ {
+ so->currPos.moreLeft = true;
+ so->currPos.moreRight = false;
+ }
+ so->numKilled = 0; /* just paranoia */
+ so->markItemIndex = -1; /* ditto */
+}
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 99a014e8f4..3d041c47c0 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -55,7 +55,7 @@
* This code isn't concerned about the FSM at all. The caller is responsible
* for initializing that.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -680,9 +680,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
bool merge = (btspool2 != NULL);
IndexTuple itup,
itup2 = NULL;
- bool should_free,
- should_free2,
- load1;
+ bool load1;
TupleDesc tupdes = RelationGetDescr(wstate->index);
int i,
keysz = RelationGetNumberOfAttributes(wstate->index);
@@ -697,10 +695,8 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
*/
/* the preparation of merge */
- itup = tuplesort_getindextuple(btspool->sortstate,
- true, &should_free);
- itup2 = tuplesort_getindextuple(btspool2->sortstate,
- true, &should_free2);
+ itup = tuplesort_getindextuple(btspool->sortstate, true);
+ itup2 = tuplesort_getindextuple(btspool2->sortstate, true);
indexScanKey = _bt_mkscankey_nodata(wstate->index);
/* Prepare SortSupport data for each column */
@@ -775,18 +771,12 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
if (load1)
{
_bt_buildadd(wstate, state, itup);
- if (should_free)
- pfree(itup);
- itup = tuplesort_getindextuple(btspool->sortstate,
- true, &should_free);
+ itup = tuplesort_getindextuple(btspool->sortstate, true);
}
else
{
_bt_buildadd(wstate, state, itup2);
- if (should_free2)
- pfree(itup2);
- itup2 = tuplesort_getindextuple(btspool2->sortstate,
- true, &should_free2);
+ itup2 = tuplesort_getindextuple(btspool2->sortstate, true);
}
}
pfree(sortKeys);
@@ -795,15 +785,13 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
{
/* merge is unnecessary */
while ((itup = tuplesort_getindextuple(btspool->sortstate,
- true, &should_free)) != NULL)
+ true)) != NULL)
{
/* When we see first tuple, create first index page */
if (state == NULL)
state = _bt_pagestate(wstate, 0);
_bt_buildadd(wstate, state, itup);
- if (should_free)
- pfree(itup);
}
}
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 5d335c7f97..5b259a31d9 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -3,7 +3,7 @@
* nbtutils.c
* Utility code for Postgres btree implementation.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -232,10 +232,8 @@ _bt_preprocess_array_keys(IndexScanDesc scan)
*/
if (so->arrayContext == NULL)
so->arrayContext = AllocSetContextCreate(CurrentMemoryContext,
- "BTree Array Context",
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ "BTree array context",
+ ALLOCSET_SMALL_SIZES);
else
MemoryContextReset(so->arrayContext);
@@ -592,6 +590,10 @@ _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir)
break;
}
+ /* advance parallel scan */
+ if (scan->parallel_scan != NULL)
+ _bt_parallel_advance_array_keys(scan);
+
return found;
}
diff --git a/src/backend/access/nbtree/nbtvalidate.c b/src/backend/access/nbtree/nbtvalidate.c
index 7d0bdabc1d..88e33f54cd 100644
--- a/src/backend/access/nbtree/nbtvalidate.c
+++ b/src/backend/access/nbtree/nbtvalidate.c
@@ -3,7 +3,7 @@
* nbtvalidate.c
* Opclass validator for btree.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -22,6 +22,7 @@
#include "catalog/pg_opfamily.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
+#include "utils/regproc.h"
#include "utils/syscache.h"
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index c536e22432..ac60db0d49 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -4,7 +4,7 @@
* WAL replay logic for btrees.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -14,8 +14,10 @@
*/
#include "postgres.h"
+#include "access/bufmask.h"
#include "access/heapam_xlog.h"
#include "access/nbtree.h"
+#include "access/nbtxlog.h"
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xlogutils.h"
@@ -1028,3 +1030,52 @@ btree_redo(XLogReaderState *record)
elog(PANIC, "btree_redo: unknown op code %u", info);
}
}
+
+/*
+ * Mask a btree page before performing consistency checks on it.
+ */
+void
+btree_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+ BTPageOpaque maskopaq;
+
+ mask_page_lsn(page);
+
+ mask_page_hint_bits(page);
+ mask_unused_space(page);
+
+ maskopaq = (BTPageOpaque) PageGetSpecialPointer(page);
+
+ if (P_ISDELETED(maskopaq))
+ {
+ /*
+ * Mask page content on a DELETED page since it will be re-initialized
+ * during replay. See btree_xlog_unlink_page() for details.
+ */
+ mask_page_content(page);
+ }
+ else if (P_ISLEAF(maskopaq))
+ {
+ /*
+ * In btree leaf pages, it is possible to modify the LP_FLAGS without
+ * emitting any WAL record. Hence, mask the line pointer flags. See
+ * _bt_killitems(), _bt_check_unique() for details.
+ */
+ mask_lp_flags(page);
+ }
+
+ /*
+ * BTP_HAS_GARBAGE is just an un-logged hint bit. So, mask it. See
+ * _bt_killitems(), _bt_check_unique() for details.
+ */
+ maskopaq->btpo_flags &= ~BTP_HAS_GARBAGE;
+
+ /*
+ * During replay of a btree page split, we don't set the BTP_SPLIT_END
+ * flag of the right sibling and initialize the cycle_id to 0 for the same
+ * page. See btree_xlog_split() for details.
+ */
+ maskopaq->btpo_flags &= ~BTP_SPLIT_END;
+ maskopaq->btpo_cycleid = 0;
+}
diff --git a/src/backend/access/rmgrdesc/brindesc.c b/src/backend/access/rmgrdesc/brindesc.c
index 433526f5ec..637ebf30f8 100644
--- a/src/backend/access/rmgrdesc/brindesc.c
+++ b/src/backend/access/rmgrdesc/brindesc.c
@@ -3,7 +3,7 @@
* brindesc.c
* rmgr descriptor routines for BRIN indexes
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -61,6 +61,13 @@ brin_desc(StringInfo buf, XLogReaderState *record)
appendStringInfo(buf, "targetBlk %u", xlrec->targetBlk);
}
+ else if (info == XLOG_BRIN_DESUMMARIZE)
+ {
+ xl_brin_desummarize *xlrec = (xl_brin_desummarize *) rec;
+
+ appendStringInfo(buf, "pagesPerRange %u, heapBlk %u, page offset %u",
+ xlrec->pagesPerRange, xlrec->heapBlk, xlrec->regOffset);
+ }
}
const char *
@@ -91,6 +98,9 @@ brin_identify(uint8 info)
case XLOG_BRIN_REVMAP_EXTEND:
id = "REVMAP_EXTEND";
break;
+ case XLOG_BRIN_DESUMMARIZE:
+ id = "DESUMMARIZE";
+ break;
}
return id;
diff --git a/src/backend/access/rmgrdesc/clogdesc.c b/src/backend/access/rmgrdesc/clogdesc.c
index 41ea254710..9181154ffd 100644
--- a/src/backend/access/rmgrdesc/clogdesc.c
+++ b/src/backend/access/rmgrdesc/clogdesc.c
@@ -3,7 +3,7 @@
* clogdesc.c
* rmgr descriptor routines for access/transam/clog.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -23,12 +23,20 @@ clog_desc(StringInfo buf, XLogReaderState *record)
char *rec = XLogRecGetData(record);
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
- if (info == CLOG_ZEROPAGE || info == CLOG_TRUNCATE)
+ if (info == CLOG_ZEROPAGE)
{
int pageno;
memcpy(&pageno, rec, sizeof(int));
- appendStringInfo(buf, "%d", pageno);
+ appendStringInfo(buf, "page %d", pageno);
+ }
+ else if (info == CLOG_TRUNCATE)
+ {
+ xl_clog_truncate xlrec;
+
+ memcpy(&xlrec, rec, sizeof(xl_clog_truncate));
+ appendStringInfo(buf, "page %d; oldestXact %u",
+ xlrec.pageno, xlrec.oldestXact);
}
}
diff --git a/src/backend/access/rmgrdesc/committsdesc.c b/src/backend/access/rmgrdesc/committsdesc.c
index 527e5dc724..3e670bd543 100644
--- a/src/backend/access/rmgrdesc/committsdesc.c
+++ b/src/backend/access/rmgrdesc/committsdesc.c
@@ -3,7 +3,7 @@
* committsdesc.c
* rmgr descriptor routines for access/transam/commit_ts.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -33,10 +33,10 @@ commit_ts_desc(StringInfo buf, XLogReaderState *record)
}
else if (info == COMMIT_TS_TRUNCATE)
{
- int pageno;
+ xl_commit_ts_truncate *trunc = (xl_commit_ts_truncate *) rec;
- memcpy(&pageno, rec, sizeof(int));
- appendStringInfo(buf, "%d", pageno);
+ appendStringInfo(buf, "pageno %d, oldestXid %u",
+ trunc->pageno, trunc->oldestXid);
}
else if (info == COMMIT_TS_SETTS)
{
diff --git a/src/backend/access/rmgrdesc/dbasedesc.c b/src/backend/access/rmgrdesc/dbasedesc.c
index 83720ce765..768242cfd5 100644
--- a/src/backend/access/rmgrdesc/dbasedesc.c
+++ b/src/backend/access/rmgrdesc/dbasedesc.c
@@ -3,7 +3,7 @@
* dbasedesc.c
* rmgr descriptor routines for commands/dbcommands.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/genericdesc.c b/src/backend/access/rmgrdesc/genericdesc.c
index 22f81570a5..c4705428f1 100644
--- a/src/backend/access/rmgrdesc/genericdesc.c
+++ b/src/backend/access/rmgrdesc/genericdesc.c
@@ -4,7 +4,7 @@
* rmgr descriptor routines for access/transam/generic_xlog.c
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/rmgrdesc/genericdesc.c
diff --git a/src/backend/access/rmgrdesc/gindesc.c b/src/backend/access/rmgrdesc/gindesc.c
index db832a5f78..df51f3ce1f 100644
--- a/src/backend/access/rmgrdesc/gindesc.c
+++ b/src/backend/access/rmgrdesc/gindesc.c
@@ -3,7 +3,7 @@
* gindesc.c
* rmgr descriptor routines for access/transam/gin/ginxlog.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,7 +14,7 @@
*/
#include "postgres.h"
-#include "access/gin_private.h"
+#include "access/ginxlog.h"
#include "access/xlogutils.h"
#include "lib/stringinfo.h"
#include "storage/relfilenode.h"
@@ -87,13 +87,13 @@ gin_desc(StringInfo buf, XLogReaderState *record)
case XLOG_GIN_INSERT:
{
ginxlogInsert *xlrec = (ginxlogInsert *) rec;
- char *payload = rec + sizeof(ginxlogInsert);
appendStringInfo(buf, "isdata: %c isleaf: %c",
(xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
(xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
if (!(xlrec->flags & GIN_INSERT_ISLEAF))
{
+ char *payload = rec + sizeof(ginxlogInsert);
BlockNumber leftChildBlkno;
BlockNumber rightChildBlkno;
@@ -104,27 +104,32 @@ gin_desc(StringInfo buf, XLogReaderState *record)
appendStringInfo(buf, " children: %u/%u",
leftChildBlkno, rightChildBlkno);
}
- if (!(xlrec->flags & GIN_INSERT_ISDATA))
- appendStringInfo(buf, " isdelete: %c",
- (((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
- else if (xlrec->flags & GIN_INSERT_ISLEAF)
+ if (XLogRecHasBlockImage(record, 0))
{
- ginxlogRecompressDataLeaf *insertData =
- (ginxlogRecompressDataLeaf *) payload;
-
- if (XLogRecHasBlockImage(record, 0))
+ if (XLogRecBlockImageApply(record, 0))
appendStringInfoString(buf, " (full page image)");
else
- desc_recompress_leaf(buf, insertData);
+ appendStringInfoString(buf, " (full page image, for WAL verification)");
}
else
{
- ginxlogInsertDataInternal *insertData = (ginxlogInsertDataInternal *) payload;
+ char *payload = XLogRecGetBlockData(record, 0, NULL);
+
+ if (!(xlrec->flags & GIN_INSERT_ISDATA))
+ appendStringInfo(buf, " isdelete: %c",
+ (((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
+ else if (xlrec->flags & GIN_INSERT_ISLEAF)
+ desc_recompress_leaf(buf, (ginxlogRecompressDataLeaf *) payload);
+ else
+ {
+ ginxlogInsertDataInternal *insertData =
+ (ginxlogInsertDataInternal *) payload;
- appendStringInfo(buf, " pitem: %u-%u/%u",
+ appendStringInfo(buf, " pitem: %u-%u/%u",
PostingItemGetBlockNumber(&insertData->newitem),
ItemPointerGetBlockNumber(&insertData->newitem.key),
- ItemPointerGetOffsetNumber(&insertData->newitem.key));
+ ItemPointerGetOffsetNumber(&insertData->newitem.key));
+ }
}
}
break;
@@ -144,12 +149,20 @@ gin_desc(StringInfo buf, XLogReaderState *record)
break;
case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
{
- ginxlogVacuumDataLeafPage *xlrec = (ginxlogVacuumDataLeafPage *) rec;
-
if (XLogRecHasBlockImage(record, 0))
- appendStringInfoString(buf, " (full page image)");
+ {
+ if (XLogRecBlockImageApply(record, 0))
+ appendStringInfoString(buf, " (full page image)");
+ else
+ appendStringInfoString(buf, " (full page image, for WAL verification)");
+ }
else
+ {
+ ginxlogVacuumDataLeafPage *xlrec =
+ (ginxlogVacuumDataLeafPage *) XLogRecGetBlockData(record, 0, NULL);
+
desc_recompress_leaf(buf, &xlrec->data);
+ }
}
break;
case XLOG_GIN_DELETE_PAGE:
diff --git a/src/backend/access/rmgrdesc/gistdesc.c b/src/backend/access/rmgrdesc/gistdesc.c
index 90bb88109f..dc0506913c 100644
--- a/src/backend/access/rmgrdesc/gistdesc.c
+++ b/src/backend/access/rmgrdesc/gistdesc.c
@@ -3,7 +3,7 @@
* gistdesc.c
* rmgr descriptor routines for access/gist/gistxlog.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,7 +14,7 @@
*/
#include "postgres.h"
-#include "access/gist_private.h"
+#include "access/gistxlog.h"
#include "lib/stringinfo.h"
#include "storage/relfilenode.h"
diff --git a/src/backend/access/rmgrdesc/hashdesc.c b/src/backend/access/rmgrdesc/hashdesc.c
index d37c9b1aae..35d86dc893 100644
--- a/src/backend/access/rmgrdesc/hashdesc.c
+++ b/src/backend/access/rmgrdesc/hashdesc.c
@@ -3,7 +3,7 @@
* hashdesc.c
* rmgr descriptor routines for access/hash/hash.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,15 +14,158 @@
*/
#include "postgres.h"
-#include "access/hash.h"
+#include "access/hash_xlog.h"
void
hash_desc(StringInfo buf, XLogReaderState *record)
{
+ char *rec = XLogRecGetData(record);
+ uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
+
+ switch (info)
+ {
+ case XLOG_HASH_INIT_META_PAGE:
+ {
+ xl_hash_init_meta_page *xlrec = (xl_hash_init_meta_page *) rec;
+
+ appendStringInfo(buf, "num_tuples %g, fillfactor %d",
+ xlrec->num_tuples, xlrec->ffactor);
+ break;
+ }
+ case XLOG_HASH_INIT_BITMAP_PAGE:
+ {
+ xl_hash_init_bitmap_page *xlrec = (xl_hash_init_bitmap_page *) rec;
+
+ appendStringInfo(buf, "bmsize %d", xlrec->bmsize);
+ break;
+ }
+ case XLOG_HASH_INSERT:
+ {
+ xl_hash_insert *xlrec = (xl_hash_insert *) rec;
+
+ appendStringInfo(buf, "off %u", xlrec->offnum);
+ break;
+ }
+ case XLOG_HASH_ADD_OVFL_PAGE:
+ {
+ xl_hash_add_ovfl_page *xlrec = (xl_hash_add_ovfl_page *) rec;
+
+ appendStringInfo(buf, "bmsize %d, bmpage_found %c",
+ xlrec->bmsize, (xlrec->bmpage_found) ? 'T' : 'F');
+ break;
+ }
+ case XLOG_HASH_SPLIT_ALLOCATE_PAGE:
+ {
+ xl_hash_split_allocate_page *xlrec = (xl_hash_split_allocate_page *) rec;
+
+ appendStringInfo(buf, "new_bucket %u, meta_page_masks_updated %c, issplitpoint_changed %c",
+ xlrec->new_bucket,
+ (xlrec->flags & XLH_SPLIT_META_UPDATE_MASKS) ? 'T' : 'F',
+ (xlrec->flags & XLH_SPLIT_META_UPDATE_SPLITPOINT) ? 'T' : 'F');
+ break;
+ }
+ case XLOG_HASH_SPLIT_COMPLETE:
+ {
+ xl_hash_split_complete *xlrec = (xl_hash_split_complete *) rec;
+
+ appendStringInfo(buf, "old_bucket_flag %u, new_bucket_flag %u",
+ xlrec->old_bucket_flag, xlrec->new_bucket_flag);
+ break;
+ }
+ case XLOG_HASH_MOVE_PAGE_CONTENTS:
+ {
+ xl_hash_move_page_contents *xlrec = (xl_hash_move_page_contents *) rec;
+
+ appendStringInfo(buf, "ntups %d, is_primary %c",
+ xlrec->ntups,
+ xlrec->is_prim_bucket_same_wrt ? 'T' : 'F');
+ break;
+ }
+ case XLOG_HASH_SQUEEZE_PAGE:
+ {
+ xl_hash_squeeze_page *xlrec = (xl_hash_squeeze_page *) rec;
+
+ appendStringInfo(buf, "prevblkno %u, nextblkno %u, ntups %d, is_primary %c",
+ xlrec->prevblkno,
+ xlrec->nextblkno,
+ xlrec->ntups,
+ xlrec->is_prim_bucket_same_wrt ? 'T' : 'F');
+ break;
+ }
+ case XLOG_HASH_DELETE:
+ {
+ xl_hash_delete *xlrec = (xl_hash_delete *) rec;
+
+ appendStringInfo(buf, "clear_dead_marking %c, is_primary %c",
+ xlrec->clear_dead_marking ? 'T' : 'F',
+ xlrec->is_primary_bucket_page ? 'T' : 'F');
+ break;
+ }
+ case XLOG_HASH_UPDATE_META_PAGE:
+ {
+ xl_hash_update_meta_page *xlrec = (xl_hash_update_meta_page *) rec;
+
+ appendStringInfo(buf, "ntuples %g",
+ xlrec->ntuples);
+ break;
+ }
+ case XLOG_HASH_VACUUM_ONE_PAGE:
+ {
+ xl_hash_vacuum_one_page *xlrec = (xl_hash_vacuum_one_page *) rec;
+
+ appendStringInfo(buf, "ntuples %d",
+ xlrec->ntuples);
+ break;
+ }
+ }
}
const char *
hash_identify(uint8 info)
{
- return NULL;
+ const char *id = NULL;
+
+ switch (info & ~XLR_INFO_MASK)
+ {
+ case XLOG_HASH_INIT_META_PAGE:
+ id = "INIT_META_PAGE";
+ break;
+ case XLOG_HASH_INIT_BITMAP_PAGE:
+ id = "INIT_BITMAP_PAGE";
+ break;
+ case XLOG_HASH_INSERT:
+ id = "INSERT";
+ break;
+ case XLOG_HASH_ADD_OVFL_PAGE:
+ id = "ADD_OVFL_PAGE";
+ break;
+ case XLOG_HASH_SPLIT_ALLOCATE_PAGE:
+ id = "SPLIT_ALLOCATE_PAGE";
+ break;
+ case XLOG_HASH_SPLIT_PAGE:
+ id = "SPLIT_PAGE";
+ break;
+ case XLOG_HASH_SPLIT_COMPLETE:
+ id = "SPLIT_COMPLETE";
+ break;
+ case XLOG_HASH_MOVE_PAGE_CONTENTS:
+ id = "MOVE_PAGE_CONTENTS";
+ break;
+ case XLOG_HASH_SQUEEZE_PAGE:
+ id = "SQUEEZE_PAGE";
+ break;
+ case XLOG_HASH_DELETE:
+ id = "DELETE";
+ break;
+ case XLOG_HASH_SPLIT_CLEANUP:
+ id = "SPLIT_CLEANUP";
+ break;
+ case XLOG_HASH_UPDATE_META_PAGE:
+ id = "UPDATE_META_PAGE";
+ break;
+ case XLOG_HASH_VACUUM_ONE_PAGE:
+ id = "VACUUM_ONE_PAGE";
+ }
+
+ return id;
}
diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c
index 7c763b6b0e..44d2d6333f 100644
--- a/src/backend/access/rmgrdesc/heapdesc.c
+++ b/src/backend/access/rmgrdesc/heapdesc.c
@@ -3,7 +3,7 @@
* heapdesc.c
* rmgr descriptor routines for access/heap/heapam.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/logicalmsgdesc.c b/src/backend/access/rmgrdesc/logicalmsgdesc.c
index 525826efd3..8287751e48 100644
--- a/src/backend/access/rmgrdesc/logicalmsgdesc.c
+++ b/src/backend/access/rmgrdesc/logicalmsgdesc.c
@@ -3,7 +3,7 @@
* logicalmsgdesc.c
* rmgr descriptor routines for replication/logical/message.c
*
- * Portions Copyright (c) 2015-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2015-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
diff --git a/src/backend/access/rmgrdesc/mxactdesc.c b/src/backend/access/rmgrdesc/mxactdesc.c
index 27c1fb0fc0..9c17447744 100644
--- a/src/backend/access/rmgrdesc/mxactdesc.c
+++ b/src/backend/access/rmgrdesc/mxactdesc.c
@@ -3,7 +3,7 @@
* mxactdesc.c
* rmgr descriptor routines for access/transam/multixact.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rmgrdesc/nbtdesc.c
index 7631cb5c73..fbde9d6555 100644
--- a/src/backend/access/rmgrdesc/nbtdesc.c
+++ b/src/backend/access/rmgrdesc/nbtdesc.c
@@ -3,7 +3,7 @@
* nbtdesc.c
* rmgr descriptor routines for access/nbtree/nbtxlog.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,7 +14,7 @@
*/
#include "postgres.h"
-#include "access/nbtree.h"
+#include "access/nbtxlog.h"
void
btree_desc(StringInfo buf, XLogReaderState *record)
diff --git a/src/backend/access/rmgrdesc/relmapdesc.c b/src/backend/access/rmgrdesc/relmapdesc.c
index 097a709fb2..4cbdf37c70 100644
--- a/src/backend/access/rmgrdesc/relmapdesc.c
+++ b/src/backend/access/rmgrdesc/relmapdesc.c
@@ -3,7 +3,7 @@
* relmapdesc.c
* rmgr descriptor routines for utils/cache/relmapper.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/replorigindesc.c b/src/backend/access/rmgrdesc/replorigindesc.c
index ce8ba10c14..c43f850f8e 100644
--- a/src/backend/access/rmgrdesc/replorigindesc.c
+++ b/src/backend/access/rmgrdesc/replorigindesc.c
@@ -3,7 +3,7 @@
* replorigindesc.c
* rmgr descriptor routines for replication/logical/origin.c
*
- * Portions Copyright (c) 2015-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2015-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
diff --git a/src/backend/access/rmgrdesc/seqdesc.c b/src/backend/access/rmgrdesc/seqdesc.c
index 5855715735..2209f7284e 100644
--- a/src/backend/access/rmgrdesc/seqdesc.c
+++ b/src/backend/access/rmgrdesc/seqdesc.c
@@ -3,7 +3,7 @@
* seqdesc.c
* rmgr descriptor routines for commands/sequence.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/smgrdesc.c b/src/backend/access/rmgrdesc/smgrdesc.c
index f36b1099a9..7ad46bcf7a 100644
--- a/src/backend/access/rmgrdesc/smgrdesc.c
+++ b/src/backend/access/rmgrdesc/smgrdesc.c
@@ -3,7 +3,7 @@
* smgrdesc.c
* rmgr descriptor routines for catalog/storage.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/spgdesc.c b/src/backend/access/rmgrdesc/spgdesc.c
index 8be47f9526..24d6cb58fd 100644
--- a/src/backend/access/rmgrdesc/spgdesc.c
+++ b/src/backend/access/rmgrdesc/spgdesc.c
@@ -3,7 +3,7 @@
* spgdesc.c
* rmgr descriptor routines for access/spgist/spgxlog.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,7 +14,7 @@
*/
#include "postgres.h"
-#include "access/spgist_private.h"
+#include "access/spgxlog.h"
void
spg_desc(StringInfo buf, XLogReaderState *record)
diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c
index 13797a3d2f..278546a728 100644
--- a/src/backend/access/rmgrdesc/standbydesc.c
+++ b/src/backend/access/rmgrdesc/standbydesc.c
@@ -3,7 +3,7 @@
* standbydesc.c
* rmgr descriptor routines for storage/ipc/standby.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -122,12 +122,10 @@ standby_desc_invalidations(StringInfo buf,
appendStringInfoString(buf, " smgr");
/* not expected, but print something anyway */
else if (msg->id == SHAREDINVALRELMAP_ID)
- appendStringInfoString(buf, " relmap");
- else if (msg->id == SHAREDINVALRELMAP_ID)
appendStringInfo(buf, " relmap db %u", msg->rm.dbId);
else if (msg->id == SHAREDINVALSNAPSHOT_ID)
appendStringInfo(buf, " snapshot %u", msg->sn.relId);
else
- appendStringInfo(buf, " unknown id %d", msg->id);
+ appendStringInfo(buf, " unrecognized id %d", msg->id);
}
}
diff --git a/src/backend/access/rmgrdesc/tblspcdesc.c b/src/backend/access/rmgrdesc/tblspcdesc.c
index 15440271a3..47c42328f3 100644
--- a/src/backend/access/rmgrdesc/tblspcdesc.c
+++ b/src/backend/access/rmgrdesc/tblspcdesc.c
@@ -3,7 +3,7 @@
* tblspcdesc.c
* rmgr descriptor routines for commands/tablespace.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c
index d2965b70b7..063e66834d 100644
--- a/src/backend/access/rmgrdesc/xactdesc.c
+++ b/src/backend/access/rmgrdesc/xactdesc.c
@@ -3,7 +3,7 @@
* xactdesc.c
* rmgr descriptor routines for access/transam/xact.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -26,7 +26,7 @@
* understand format.
*
* This routines are in xactdesc.c because they're accessed in backend (when
- * replaying WAL) and frontend (pg_xlogdump) code. This file is the only xact
+ * replaying WAL) and frontend (pg_waldump) code. This file is the only xact
* specific one shared between both. They're complicated enough that
* duplication would be bothersome.
*/
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 62ed1dc04b..5f07eb1499 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -3,7 +3,7 @@
* xlogdesc.c
* rmgr descriptor routines for access/transam/xlog.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index f090ca528b..90c6534139 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -4,7 +4,7 @@
* implementation of insert algorithm
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -17,6 +17,7 @@
#include "access/genam.h"
#include "access/spgist_private.h"
+#include "access/spgxlog.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
@@ -1705,17 +1706,40 @@ spgSplitNodeAction(Relation index, SpGistState *state,
/* Should not be applied to nulls */
Assert(!SpGistPageStoresNulls(current->page));
+ /* Check opclass gave us sane values */
+ if (out->result.splitTuple.prefixNNodes <= 0 ||
+ out->result.splitTuple.prefixNNodes > SGITMAXNNODES)
+ elog(ERROR, "invalid number of prefix nodes: %d",
+ out->result.splitTuple.prefixNNodes);
+ if (out->result.splitTuple.childNodeN < 0 ||
+ out->result.splitTuple.childNodeN >=
+ out->result.splitTuple.prefixNNodes)
+ elog(ERROR, "invalid child node number: %d",
+ out->result.splitTuple.childNodeN);
+
/*
- * Construct new prefix tuple, containing a single node with the specified
- * label. (We'll update the node's downlink to point to the new postfix
- * tuple, below.)
+ * Construct new prefix tuple with requested number of nodes. We'll fill
+ * in the childNodeN'th node's downlink below.
*/
- node = spgFormNodeTuple(state, out->result.splitTuple.nodeLabel, false);
+ nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) *
+ out->result.splitTuple.prefixNNodes);
+
+ for (i = 0; i < out->result.splitTuple.prefixNNodes; i++)
+ {
+ Datum label = (Datum) 0;
+ bool labelisnull;
+
+ labelisnull = (out->result.splitTuple.prefixNodeLabels == NULL);
+ if (!labelisnull)
+ label = out->result.splitTuple.prefixNodeLabels[i];
+ nodes[i] = spgFormNodeTuple(state, label, labelisnull);
+ }
prefixTuple = spgFormInnerTuple(state,
out->result.splitTuple.prefixHasPrefix,
out->result.splitTuple.prefixPrefixDatum,
- 1, &node);
+ out->result.splitTuple.prefixNNodes,
+ nodes);
/* it must fit in the space that innerTuple now occupies */
if (prefixTuple->size > innerTuple->size)
@@ -1807,10 +1831,12 @@ spgSplitNodeAction(Relation index, SpGistState *state,
* the postfix tuple first.) We have to update the local copy of the
* prefixTuple too, because that's what will be written to WAL.
*/
- spgUpdateNodeLink(prefixTuple, 0, postfixBlkno, postfixOffset);
+ spgUpdateNodeLink(prefixTuple, out->result.splitTuple.childNodeN,
+ postfixBlkno, postfixOffset);
prefixTuple = (SpGistInnerTuple) PageGetItem(current->page,
PageGetItemId(current->page, current->offnum));
- spgUpdateNodeLink(prefixTuple, 0, postfixBlkno, postfixOffset);
+ spgUpdateNodeLink(prefixTuple, out->result.splitTuple.childNodeN,
+ postfixBlkno, postfixOffset);
MarkBufferDirty(current->buffer);
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 44fd644e42..9a37259916 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -5,7 +5,7 @@
*
* All the actual insertion logic is in spgdoinsert.c.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -18,6 +18,7 @@
#include "access/genam.h"
#include "access/spgist_private.h"
+#include "access/spgxlog.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "catalog/index.h"
@@ -134,9 +135,7 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
"SP-GiST build temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
spgistBuildCallback, (void *) &buildstate);
@@ -163,13 +162,18 @@ spgbuildempty(Relation index)
page = (Page) palloc(BLCKSZ);
SpGistInitMetapage(page);
- /* Write the page. If archiving/streaming, XLOG it. */
+ /*
+ * Write the page and log it unconditionally. This is important
+ * particularly for indexes created on tablespaces and databases whose
+ * creation happened after the last redo pointer as recovery removes any
+ * of their existing content when the corresponding create records are
+ * replayed.
+ */
PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO);
smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO,
(char *) page, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
- SPGIST_METAPAGE_BLKNO, page, false);
+ log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ SPGIST_METAPAGE_BLKNO, page, false);
/* Likewise for the root page. */
SpGistInitPage(page, SPGIST_LEAF);
@@ -177,9 +181,8 @@ spgbuildempty(Relation index)
PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO);
smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_ROOT_BLKNO,
(char *) page, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
- SPGIST_ROOT_BLKNO, page, true);
+ log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ SPGIST_ROOT_BLKNO, page, true);
/* Likewise for the null-tuples root page. */
SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS);
@@ -187,9 +190,8 @@ spgbuildempty(Relation index)
PageSetChecksumInplace(page, SPGIST_NULL_BLKNO);
smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_NULL_BLKNO,
(char *) page, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
- SPGIST_NULL_BLKNO, page, true);
+ log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ SPGIST_NULL_BLKNO, page, true);
/*
* An immediate sync is required even if we xlog'd the pages, because the
@@ -205,7 +207,8 @@ spgbuildempty(Relation index)
bool
spginsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
- IndexUniqueCheck checkUnique)
+ IndexUniqueCheck checkUnique,
+ IndexInfo *indexInfo)
{
SpGistState spgstate;
MemoryContext oldCtx;
@@ -213,9 +216,7 @@ spginsert(Relation index, Datum *values, bool *isnull,
insertCtx = AllocSetContextCreate(CurrentMemoryContext,
"SP-GiST insert temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldCtx = MemoryContextSwitchTo(insertCtx);
initSpGistState(&spgstate, index);
diff --git a/src/backend/access/spgist/spgkdtreeproc.c b/src/backend/access/spgist/spgkdtreeproc.c
index 1ab93350e1..9a2649bf2a 100644
--- a/src/backend/access/spgist/spgkdtreeproc.c
+++ b/src/backend/access/spgist/spgkdtreeproc.c
@@ -4,7 +4,7 @@
* implementation of k-d tree over points for SP-GiST
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c
index 40ab760b0f..6ad73f448d 100644
--- a/src/backend/access/spgist/spgquadtreeproc.c
+++ b/src/backend/access/spgist/spgquadtreeproc.c
@@ -4,7 +4,7 @@
* implementation of quad tree over points for SP-GiST
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 6f9e223f43..2d96c0094e 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -4,7 +4,7 @@
* routines for scanning SP-GiST indexes
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -92,11 +92,11 @@ resetSpGistScanOpaque(SpGistScanOpaque so)
if (so->want_itup)
{
- /* Must pfree IndexTuples to avoid memory leak */
+ /* Must pfree reconstructed tuples to avoid memory leak */
int i;
for (i = 0; i < so->nPtrs; i++)
- pfree(so->indexTups[i]);
+ pfree(so->reconTups[i]);
}
so->iPtr = so->nPtrs = 0;
}
@@ -193,12 +193,10 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
initSpGistState(&so->state, scan->indexRelation);
so->tempCxt = AllocSetContextCreate(CurrentMemoryContext,
"SP-GiST search temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
- /* Set up indexTupDesc and xs_itupdesc in case it's an index-only scan */
- so->indexTupDesc = scan->xs_itupdesc = RelationGetDescr(rel);
+ /* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
+ so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
scan->opaque = so;
@@ -593,12 +591,12 @@ storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr,
if (so->want_itup)
{
/*
- * Reconstruct desired IndexTuple. We have to copy the datum out of
- * the temp context anyway, so we may as well create the tuple here.
+ * Reconstruct index data. We have to copy the datum out of the temp
+ * context anyway, so we may as well create the tuple here.
*/
- so->indexTups[so->nPtrs] = index_form_tuple(so->indexTupDesc,
- &leafValue,
- &isnull);
+ so->reconTups[so->nPtrs] = heap_form_tuple(so->indexTupDesc,
+ &leafValue,
+ &isnull);
}
so->nPtrs++;
}
@@ -621,18 +619,18 @@ spggettuple(IndexScanDesc scan, ScanDirection dir)
/* continuing to return tuples from a leaf page */
scan->xs_ctup.t_self = so->heapPtrs[so->iPtr];
scan->xs_recheck = so->recheck[so->iPtr];
- scan->xs_itup = so->indexTups[so->iPtr];
+ scan->xs_hitup = so->reconTups[so->iPtr];
so->iPtr++;
return true;
}
if (so->want_itup)
{
- /* Must pfree IndexTuples to avoid memory leak */
+ /* Must pfree reconstructed tuples to avoid memory leak */
int i;
for (i = 0; i < so->nPtrs; i++)
- pfree(so->indexTups[i]);
+ pfree(so->reconTups[i]);
}
so->iPtr = so->nPtrs = 0;
diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c
index e0d8f30ef1..53f298b6c2 100644
--- a/src/backend/access/spgist/spgtextproc.c
+++ b/src/backend/access/spgist/spgtextproc.c
@@ -29,7 +29,7 @@
* No new entries ever get pushed into a -2-labeled child, either.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -45,6 +45,7 @@
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/pg_locale.h"
+#include "utils/varlena.h"
/*
@@ -212,9 +213,14 @@ spg_text_choose(PG_FUNCTION_ARGS)
out->result.splitTuple.prefixPrefixDatum =
formTextDatum(prefixStr, commonLen);
}
- out->result.splitTuple.nodeLabel =
+ out->result.splitTuple.prefixNNodes = 1;
+ out->result.splitTuple.prefixNodeLabels =
+ (Datum *) palloc(sizeof(Datum));
+ out->result.splitTuple.prefixNodeLabels[0] =
Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
+ out->result.splitTuple.childNodeN = 0;
+
if (prefixSize - commonLen == 1)
{
out->result.splitTuple.postfixHasPrefix = false;
@@ -280,7 +286,10 @@ spg_text_choose(PG_FUNCTION_ARGS)
out->resultType = spgSplitTuple;
out->result.splitTuple.prefixHasPrefix = in->hasPrefix;
out->result.splitTuple.prefixPrefixDatum = in->prefixDatum;
- out->result.splitTuple.nodeLabel = Int16GetDatum(-2);
+ out->result.splitTuple.prefixNNodes = 1;
+ out->result.splitTuple.prefixNodeLabels = (Datum *) palloc(sizeof(Datum));
+ out->result.splitTuple.prefixNodeLabels[0] = Int16GetDatum(-2);
+ out->result.splitTuple.childNodeN = 0;
out->result.splitTuple.postfixHasPrefix = false;
}
else
@@ -559,8 +568,9 @@ spg_text_leaf_consistent(PG_FUNCTION_ARGS)
leafValue = DatumGetTextPP(in->leafDatum);
+ /* As above, in->reconstructedValue isn't toasted or short. */
if (DatumGetPointer(in->reconstructedValue))
- reconstrValue = DatumGetTextP(in->reconstructedValue);
+ reconstrValue = (text *) DatumGetPointer(in->reconstructedValue);
Assert(reconstrValue == NULL ? level == 0 :
VARSIZE_ANY_EXHDR(reconstrValue) == level);
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index d570ae5992..e57ac49c6b 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -4,7 +4,7 @@
* various support functions for SP-GiST
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -22,6 +22,7 @@
#include "storage/bufmgr.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
+#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
#include "utils/lsyscache.h"
@@ -48,6 +49,7 @@ spghandler(PG_FUNCTION_ARGS)
amroutine->amstorage = false;
amroutine->amclusterable = false;
amroutine->ampredlocks = false;
+ amroutine->amcanparallel = false;
amroutine->amkeytype = InvalidOid;
amroutine->ambuild = spgbuild;
@@ -67,6 +69,9 @@ spghandler(PG_FUNCTION_ARGS)
amroutine->amendscan = spgendscan;
amroutine->ammarkpos = NULL;
amroutine->amrestrpos = NULL;
+ amroutine->amestimateparallelscan = NULL;
+ amroutine->aminitparallelscan = NULL;
+ amroutine->amparallelrescan = NULL;
PG_RETURN_POINTER(amroutine);
}
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 15b867f24c..cce9b3f618 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -4,7 +4,7 @@
* vacuum for SP-GiST
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -17,6 +17,7 @@
#include "access/genam.h"
#include "access/spgist_private.h"
+#include "access/spgxlog.h"
#include "access/transam.h"
#include "access/xloginsert.h"
#include "catalog/storage_xlog.h"
diff --git a/src/backend/access/spgist/spgvalidate.c b/src/backend/access/spgist/spgvalidate.c
index 6297111a7c..1bc5bce72e 100644
--- a/src/backend/access/spgist/spgvalidate.c
+++ b/src/backend/access/spgist/spgvalidate.c
@@ -3,7 +3,7 @@
* spgvalidate.c
* Opclass validator for SP-GiST.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -22,6 +22,7 @@
#include "catalog/pg_opfamily.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
+#include "utils/regproc.h"
#include "utils/syscache.h"
diff --git a/src/backend/access/spgist/spgxlog.c b/src/backend/access/spgist/spgxlog.c
index 01a4e0f252..c007601efd 100644
--- a/src/backend/access/spgist/spgxlog.c
+++ b/src/backend/access/spgist/spgxlog.c
@@ -4,7 +4,7 @@
* WAL replay logic for SP-GiST
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -14,7 +14,9 @@
*/
#include "postgres.h"
+#include "access/bufmask.h"
#include "access/spgist_private.h"
+#include "access/spgxlog.h"
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xlogutils.h"
@@ -1014,9 +1016,7 @@ spg_xlog_startup(void)
{
opCtx = AllocSetContextCreate(CurrentMemoryContext,
"SP-GiST temporary context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
}
void
@@ -1025,3 +1025,23 @@ spg_xlog_cleanup(void)
MemoryContextDelete(opCtx);
opCtx = NULL;
}
+
+/*
+ * Mask a SpGist page before performing consistency checks on it.
+ */
+void
+spg_mask(char *pagedata, BlockNumber blkno)
+{
+ Page page = (Page) pagedata;
+
+ mask_page_lsn(page);
+
+ mask_page_hint_bits(page);
+
+ /*
+ * Any SpGist page other than meta contains unused space which needs to be
+ * masked.
+ */
+ if (!SpGistPageIsMeta(page))
+ mask_unused_space(page);
+}
diff --git a/src/backend/access/tablesample/bernoulli.c b/src/backend/access/tablesample/bernoulli.c
index bc45fd1bed..5f6d478159 100644
--- a/src/backend/access/tablesample/bernoulli.c
+++ b/src/backend/access/tablesample/bernoulli.c
@@ -13,7 +13,7 @@
* cutoff value computed from the selection probability by BeginSampleScan.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/tablesample/system.c b/src/backend/access/tablesample/system.c
index 65f8c58d67..e270cbc4a0 100644
--- a/src/backend/access/tablesample/system.c
+++ b/src/backend/access/tablesample/system.c
@@ -13,7 +13,7 @@
* cutoff value computed from the selection probability by BeginSampleScan.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/access/tablesample/tablesample.c b/src/backend/access/tablesample/tablesample.c
index d96aa5b2a3..10d2bc91b3 100644
--- a/src/backend/access/tablesample/tablesample.c
+++ b/src/backend/access/tablesample/tablesample.c
@@ -3,7 +3,7 @@
* tablesample.c
* Support functions for TABLESAMPLE feature
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/transam/README b/src/backend/access/transam/README
index 4ae4715339..e7dd19fd7b 100644
--- a/src/backend/access/transam/README
+++ b/src/backend/access/transam/README
@@ -331,17 +331,17 @@ of the xid fields is atomic, so assuming it for xmin as well is no extra
risk.
-pg_clog and pg_subtrans
+pg_xact and pg_subtrans
-----------------------
-pg_clog and pg_subtrans are permanent (on-disk) storage of transaction related
+pg_xact and pg_subtrans are permanent (on-disk) storage of transaction related
information. There is a limited number of pages of each kept in memory, so
in many cases there is no need to actually read from disk. However, if
there's a long running transaction or a backend sitting idle with an open
transaction, it may be necessary to be able to read and write this information
from disk. They also allow information to be permanent across server restarts.
-pg_clog records the commit status for each transaction that has been assigned
+pg_xact records the commit status for each transaction that has been assigned
an XID. A transaction can be in progress, committed, aborted, or
"sub-committed". This last state means that it's a subtransaction that's no
longer running, but its parent has not updated its state yet. It is not
@@ -381,9 +381,9 @@ each transaction we keep a "cache" of Xids that are known to be part of the
transaction tree, so we can skip looking at pg_subtrans unless we know the
cache has been overflowed. See storage/ipc/procarray.c for the gory details.
-slru.c is the supporting mechanism for both pg_clog and pg_subtrans. It
+slru.c is the supporting mechanism for both pg_xact and pg_subtrans. It
implements the LRU policy for in-memory buffer pages. The high-level routines
-for pg_clog are implemented in transam.c, while the low-level functions are in
+for pg_xact are implemented in transam.c, while the low-level functions are in
clog.c. pg_subtrans is contained completely in subtrans.c.
diff --git a/src/backend/access/transam/README.parallel b/src/backend/access/transam/README.parallel
index db9ac3d504..5c33c40ae9 100644
--- a/src/backend/access/transam/README.parallel
+++ b/src/backend/access/transam/README.parallel
@@ -154,7 +154,7 @@ parallelism was started before all parallel workers have exited; and it's even
more clearly crazy for a parallel worker to try to subcommit or subabort the
current subtransaction and execute in some other transaction context than was
present in the initiating backend. It might be practical to allow internal
-sub-transactions (e.g. to implement a PL/pgsql EXCEPTION block) to be used in
+sub-transactions (e.g. to implement a PL/pgSQL EXCEPTION block) to be used in
parallel mode, provided that they are XID-less, because other backends
wouldn't really need to know about those transactions or do anything
differently because of them. Right now, we don't even allow that.
@@ -198,7 +198,7 @@ pattern looks like this:
EnterParallelMode(); /* prohibit unsafe state changes */
- pcxt = CreateParallelContext(entrypoint, nworkers);
+ pcxt = CreateParallelContext("library_name", "function_name", nworkers);
/* Allow space for application-specific data here. */
shm_toc_estimate_chunk(&pcxt->estimator, size);
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 0fcccfc3a7..9c6964d79c 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -24,7 +24,7 @@
* be that such transactions failed anyway.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -84,7 +84,8 @@ static SlruCtlData ClogCtlData;
static int ZeroCLOGPage(int pageno, bool writeXlog);
static bool CLOGPagePrecedes(int page1, int page2);
static void WriteZeroPageXlogRec(int pageno);
-static void WriteTruncateXlogRec(int pageno);
+static void WriteTruncateXlogRec(int pageno, TransactionId oldestXact,
+ Oid oldestXidDb);
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
TransactionId *subxids, XidStatus status,
XLogRecPtr lsn, int pageno);
@@ -460,7 +461,7 @@ CLOGShmemInit(void)
{
ClogCtl->PagePrecedes = CLOGPagePrecedes;
SimpleLruInit(ClogCtl, "clog", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE,
- CLogControlLock, "pg_clog", LWTRANCHE_CLOG_BUFFERS);
+ CLogControlLock, "pg_xact", LWTRANCHE_CLOG_BUFFERS);
}
/*
@@ -586,6 +587,13 @@ ShutdownCLOG(void)
/* Flush dirty CLOG pages to disk */
TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(false);
SimpleLruFlush(ClogCtl, false);
+
+ /*
+ * fsync pg_xact to ensure that any files flushed previously are durably
+ * on disk.
+ */
+ fsync_fname("pg_xact", true);
+
TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(false);
}
@@ -598,6 +606,13 @@ CheckPointCLOG(void)
/* Flush dirty CLOG pages to disk */
TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
SimpleLruFlush(ClogCtl, true);
+
+ /*
+ * fsync pg_xact to ensure that any files flushed previously are durably
+ * on disk.
+ */
+ fsync_fname("pg_xact", true);
+
TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
}
@@ -703,7 +718,7 @@ ExtendCLOG(TransactionId newestXact)
* the XLOG flush unless we have confirmed that there is a removable segment.
*/
void
-TruncateCLOG(TransactionId oldestXact)
+TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid)
{
int cutoffPage;
@@ -717,8 +732,26 @@ TruncateCLOG(TransactionId oldestXact)
if (!SlruScanDirectory(ClogCtl, SlruScanDirCbReportPresence, &cutoffPage))
return; /* nothing to remove */
- /* Write XLOG record and flush XLOG to disk */
- WriteTruncateXlogRec(cutoffPage);
+ /*
+ * Advance oldestClogXid before truncating clog, so concurrent xact status
+ * lookups can ensure they don't attempt to access truncated-away clog.
+ *
+ * It's only necessary to do this if we will actually truncate away clog
+ * pages.
+ */
+ AdvanceOldestClogXid(oldestXact);
+
+ /* vac_truncate_clog already advanced oldestXid */
+ Assert(TransactionIdPrecedesOrEquals(oldestXact,
+ ShmemVariableCache->oldestXid));
+
+ /*
+ * Write XLOG record and flush XLOG to disk. We record the oldest xid
+ * we're keeping information about here so we can ensure that it's always
+ * ahead of clog truncation in case we crash, and so a standby finds out
+ * the new valid xid before the next checkpoint.
+ */
+ WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid);
/* Now we can remove the old CLOG segment(s) */
SimpleLruTruncate(ClogCtl, cutoffPage);
@@ -767,12 +800,17 @@ WriteZeroPageXlogRec(int pageno)
* in TruncateCLOG().
*/
static void
-WriteTruncateXlogRec(int pageno)
+WriteTruncateXlogRec(int pageno, TransactionId oldestXact, Oid oldestXactDb)
{
XLogRecPtr recptr;
+ xl_clog_truncate xlrec;
+
+ xlrec.pageno = pageno;
+ xlrec.oldestXact = oldestXact;
+ xlrec.oldestXactDb = oldestXactDb;
XLogBeginInsert();
- XLogRegisterData((char *) (&pageno), sizeof(int));
+ XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
XLogFlush(recptr);
}
@@ -805,17 +843,19 @@ clog_redo(XLogReaderState *record)
}
else if (info == CLOG_TRUNCATE)
{
- int pageno;
+ xl_clog_truncate xlrec;
- memcpy(&pageno, XLogRecGetData(record), sizeof(int));
+ memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
/*
* During XLOG replay, latest_page_number isn't set up yet; insert a
* suitable value to bypass the sanity test in SimpleLruTruncate.
*/
- ClogCtl->shared->latest_page_number = pageno;
+ ClogCtl->shared->latest_page_number = xlrec.pageno;
+
+ AdvanceOldestClogXid(xlrec.oldestXact);
- SimpleLruTruncate(ClogCtl, pageno);
+ SimpleLruTruncate(ClogCtl, xlrec.pageno);
}
else
elog(PANIC, "clog_redo: unknown op code %u", info);
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 35b7451e6f..cb75430bc9 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -3,7 +3,7 @@
* commit_ts.c
* PostgreSQL commit timestamp manager
*
- * This module is a pg_clog-like system that stores the commit timestamp
+ * This module is a pg_xact-like system that stores the commit timestamp
* for each transaction.
*
* XLOG interactions: this module generates an XLOG record whenever a new
@@ -15,7 +15,7 @@
* re-perform the status update on redo; so we need make no additional XLOG
* entry here.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/commit_ts.c
@@ -32,6 +32,7 @@
#include "funcapi.h"
#include "miscadmin.h"
#include "pg_trace.h"
+#include "storage/shmem.h"
#include "utils/builtins.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
@@ -112,7 +113,7 @@ static bool CommitTsPagePrecedes(int page1, int page2);
static void ActivateCommitTs(void);
static void DeactivateCommitTs(void);
static void WriteZeroPageXlogRec(int pageno);
-static void WriteTruncateXlogRec(int pageno);
+static void WriteTruncateXlogRec(int pageno, TransactionId oldestXid);
static void WriteSetTimestampXlogRec(TransactionId mainxid, int nsubxids,
TransactionId *subxids, TimestampTz timestamp,
RepOriginId nodeid);
@@ -288,11 +289,18 @@ TransactionIdGetCommitTsData(TransactionId xid, TimestampTz *ts,
TransactionId oldestCommitTsXid;
TransactionId newestCommitTsXid;
- /* error if the given Xid doesn't normally commit */
- if (!TransactionIdIsNormal(xid))
+ if (!TransactionIdIsValid(xid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot retrieve commit timestamp for transaction %u", xid)));
+ else if (!TransactionIdIsNormal(xid))
+ {
+ /* frozen and bootstrap xids are always committed far in the past */
+ *ts = 0;
+ if (nodeid)
+ *nodeid = 0;
+ return false;
+ }
LWLockAcquire(CommitTsLock, LW_SHARED);
@@ -607,7 +615,7 @@ CommitTsParameterChange(bool newvalue, bool oldvalue)
/*
* Activate this module whenever necessary.
- * This must happen during postmaster or standalong-backend startup,
+ * This must happen during postmaster or standalone-backend startup,
* or during WAL replay anytime the track_commit_timestamp setting is
* changed in the master.
*
@@ -738,6 +746,12 @@ ShutdownCommitTs(void)
{
/* Flush dirty CommitTs pages to disk */
SimpleLruFlush(CommitTsCtl, false);
+
+ /*
+ * fsync pg_commit_ts to ensure that any files flushed previously are
+ * durably on disk.
+ */
+ fsync_fname("pg_commit_ts", true);
}
/*
@@ -748,6 +762,12 @@ CheckPointCommitTs(void)
{
/* Flush dirty CommitTs pages to disk */
SimpleLruFlush(CommitTsCtl, true);
+
+ /*
+ * fsync pg_commit_ts to ensure that any files flushed previously are
+ * durably on disk.
+ */
+ fsync_fname("pg_commit_ts", true);
}
/*
@@ -843,7 +863,7 @@ TruncateCommitTs(TransactionId oldestXact)
return; /* nothing to remove */
/* Write XLOG record */
- WriteTruncateXlogRec(cutoffPage);
+ WriteTruncateXlogRec(cutoffPage, oldestXact);
/* Now we can remove the old CommitTs segment(s) */
SimpleLruTruncate(CommitTsCtl, cutoffPage);
@@ -870,6 +890,8 @@ SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
else
{
Assert(ShmemVariableCache->newestCommitTsXid == InvalidTransactionId);
+ ShmemVariableCache->oldestCommitTsXid = oldestXact;
+ ShmemVariableCache->newestCommitTsXid = newestXact;
}
LWLockRelease(CommitTsLock);
}
@@ -927,10 +949,15 @@ WriteZeroPageXlogRec(int pageno)
* Write a TRUNCATE xlog record
*/
static void
-WriteTruncateXlogRec(int pageno)
+WriteTruncateXlogRec(int pageno, TransactionId oldestXid)
{
+ xl_commit_ts_truncate xlrec;
+
+ xlrec.pageno = pageno;
+ xlrec.oldestXid = oldestXid;
+
XLogBeginInsert();
- XLogRegisterData((char *) (&pageno), sizeof(int));
+ XLogRegisterData((char *) (&xlrec), SizeOfCommitTsTruncate);
(void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_TRUNCATE);
}
@@ -984,17 +1011,17 @@ commit_ts_redo(XLogReaderState *record)
}
else if (info == COMMIT_TS_TRUNCATE)
{
- int pageno;
+ xl_commit_ts_truncate *trunc = (xl_commit_ts_truncate *) XLogRecGetData(record);
- memcpy(&pageno, XLogRecGetData(record), sizeof(int));
+ AdvanceOldestCommitTsXid(trunc->oldestXid);
/*
* During XLOG replay, latest_page_number isn't set up yet; insert a
* suitable value to bypass the sanity test in SimpleLruTruncate.
*/
- CommitTsCtl->shared->latest_page_number = pageno;
+ CommitTsCtl->shared->latest_page_number = trunc->pageno;
- SimpleLruTruncate(CommitTsCtl, pageno);
+ SimpleLruTruncate(CommitTsCtl, trunc->pageno);
}
else if (info == COMMIT_TS_SETTS)
{
diff --git a/src/backend/access/transam/generic_xlog.c b/src/backend/access/transam/generic_xlog.c
index 1926d98de0..fbc6810c2f 100644
--- a/src/backend/access/transam/generic_xlog.c
+++ b/src/backend/access/transam/generic_xlog.c
@@ -4,7 +4,7 @@
* Implementation of generic xlog records.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/generic_xlog.c
@@ -13,6 +13,7 @@
*/
#include "postgres.h"
+#include "access/bufmask.h"
#include "access/generic_xlog.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
@@ -533,3 +534,14 @@ generic_redo(XLogReaderState *record)
UnlockReleaseBuffer(buffers[block_id]);
}
}
+
+/*
+ * Mask a generic page before performing consistency checks on it.
+ */
+void
+generic_mask(char *page, BlockNumber blkno)
+{
+ mask_page_lsn(page);
+
+ mask_unused_space(page);
+}
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c2e4fa377d..1a7824b5d4 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -3,7 +3,7 @@
* multixact.c
* PostgreSQL multi-transaction-log manager
*
- * The pg_multixact manager is a pg_clog-like manager that stores an array of
+ * The pg_multixact manager is a pg_xact-like manager that stores an array of
* MultiXactMember for each MultiXactId. It is a fundamental part of the
* shared-row-lock implementation. Each MultiXactMember is comprised of a
* TransactionId and a set of flag bits. The name is a bit historical:
@@ -59,7 +59,7 @@
* counter does not fall within the wraparound horizon considering the global
* minimum value.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/multixact.c
@@ -363,7 +363,7 @@ static void ExtendMultiXactOffset(MultiXactId multi);
static void ExtendMultiXactMember(MultiXactOffset offset, int nmembers);
static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary,
MultiXactOffset start, uint32 distance);
-static bool SetOffsetVacuumLimit(void);
+static bool SetOffsetVacuumLimit(bool is_startup);
static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result);
static void WriteMZeroPageXlogRec(int pageno, uint8 info);
static void WriteMTruncateXlogRec(Oid oldestMultiDB,
@@ -1570,10 +1570,8 @@ mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
/* The cache only lives as long as the current transaction */
debug_elog2(DEBUG2, "CachePut: initializing memory context");
MXactContext = AllocSetContextCreate(TopTransactionContext,
- "MultiXact Cache Context",
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ "MultiXact cache context",
+ ALLOCSET_SMALL_SIZES);
}
entry = (mXactCacheEnt *)
@@ -2097,7 +2095,7 @@ TrimMultiXact(void)
LWLockRelease(MultiXactGenLock);
/* Now compute how far away the next members wraparound is. */
- SetMultiXactIdLimit(oldestMXact, oldestMXactDB);
+ SetMultiXactIdLimit(oldestMXact, oldestMXactDB, true);
}
/*
@@ -2188,9 +2186,13 @@ MultiXactSetNextMXact(MultiXactId nextMulti,
* Determine the last safe MultiXactId to allocate given the currently oldest
* datminmxid (ie, the oldest MultiXactId that might exist in any database
* of our cluster), and the OID of the (or a) database with that value.
+ *
+ * is_startup is true when we are just starting the cluster, false when we
+ * are updating state in a running cluster. This only affects log messages.
*/
void
-SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
+SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid,
+ bool is_startup)
{
MultiXactId multiVacLimit;
MultiXactId multiWarnLimit;
@@ -2279,7 +2281,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
Assert(!InRecovery);
/* Set limits for offset vacuum. */
- needs_offset_vacuum = SetOffsetVacuumLimit();
+ needs_offset_vacuum = SetOffsetVacuumLimit(is_startup);
/*
* If past the autovacuum force point, immediately signal an autovac
@@ -2372,7 +2374,7 @@ MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB)
Assert(InRecovery);
if (MultiXactIdPrecedes(MultiXactState->oldestMultiXactId, oldestMulti))
- SetMultiXactIdLimit(oldestMulti, oldestMultiDB);
+ SetMultiXactIdLimit(oldestMulti, oldestMultiDB, false);
}
/*
@@ -2539,7 +2541,7 @@ GetOldestMultiXactId(void)
* otherwise.
*/
static bool
-SetOffsetVacuumLimit(void)
+SetOffsetVacuumLimit(bool is_startup)
{
MultiXactId oldestMultiXactId;
MultiXactId nextMXact;
@@ -2621,9 +2623,10 @@ SetOffsetVacuumLimit(void)
/* always leave one segment before the wraparound point */
offsetStopLimit -= (MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT);
- if (!prevOldestOffsetKnown && IsUnderPostmaster)
+ if (!prevOldestOffsetKnown && !is_startup)
ereport(LOG,
(errmsg("MultiXact member wraparound protections are now enabled")));
+
ereport(DEBUG1,
(errmsg("MultiXact member stop limit is now %u based on MultiXact %u",
offsetStopLimit, oldestMultiXactId)));
@@ -2802,7 +2805,7 @@ ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
* more aggressive in clamping this value. That not only causes autovacuum
* to ramp up, but also makes any manual vacuums the user issues more
* aggressive. This happens because vacuum_set_xid_limits() clamps the
- * freeze table and and the minimum freeze age based on the effective
+ * freeze table and the minimum freeze age based on the effective
* autovacuum_multixact_freeze_max_age this function returns. In the worst
* case, we'll claim the freeze_max_age to zero, and every vacuum of any
* table will try to freeze every multixact.
@@ -3314,7 +3317,7 @@ multixact_redo(XLogReaderState *record)
* Advance the horizon values, so they're current at the end of
* recovery.
*/
- SetMultiXactIdLimit(xlrec.endTruncOff, xlrec.oldestMultiDB);
+ SetMultiXactIdLimit(xlrec.endTruncOff, xlrec.oldestMultiDB, false);
PerformMembersTruncation(xlrec.startTruncMemb, xlrec.endTruncMemb);
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index c36a92cdb9..d3585c8449 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -3,7 +3,7 @@
* parallel.c
* Infrastructure for launching parallel workers
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -19,11 +19,13 @@
#include "access/xlog.h"
#include "catalog/namespace.h"
#include "commands/async.h"
+#include "executor/execParallel.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/pqmq.h"
#include "miscadmin.h"
#include "optimizer/planmain.h"
+#include "pgstat.h"
#include "pgxc/pgxcnode.h"
#include "storage/ipc.h"
#include "storage/sinval.h"
@@ -61,7 +63,7 @@
#define PARALLEL_KEY_TRANSACTION_SNAPSHOT UINT64CONST(0xFFFFFFFFFFFF0006)
#define PARALLEL_KEY_ACTIVE_SNAPSHOT UINT64CONST(0xFFFFFFFFFFFF0007)
#define PARALLEL_KEY_TRANSACTION_STATE UINT64CONST(0xFFFFFFFFFFFF0008)
-#define PARALLEL_KEY_EXTENSION_TRAMPOLINE UINT64CONST(0xFFFFFFFFFFFF0009)
+#define PARALLEL_KEY_ENTRYPOINT UINT64CONST(0xFFFFFFFFFFFF0009)
/* Fixed-size parallel state. */
typedef struct FixedParallelState
@@ -77,9 +79,6 @@ typedef struct FixedParallelState
pid_t parallel_master_pid;
BackendId parallel_master_backend_id;
- /* Entrypoint for parallel workers. */
- parallel_worker_main_type entrypoint;
-
/* Mutex protects remaining fields. */
slock_t mutex;
@@ -107,12 +106,26 @@ static FixedParallelState *MyFixedParallelState;
/* List of active parallel contexts. */
static dlist_head pcxt_list = DLIST_STATIC_INIT(pcxt_list);
+/*
+ * List of internal parallel worker entry points. We need this for
+ * reasons explained in LookupParallelWorkerFunction(), below.
+ */
+static const struct
+{
+ const char *fn_name;
+ parallel_worker_main_type fn_addr;
+} InternalParallelWorkers[] =
+
+{
+ {
+ "ParallelQueryMain", ParallelQueryMain
+ }
+};
+
/* Private functions. */
static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg);
-static void ParallelErrorContext(void *arg);
-static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc);
-static void ParallelWorkerMain(Datum main_arg);
static void WaitForParallelWorkersToExit(ParallelContext *pcxt);
+static parallel_worker_main_type LookupParallelWorkerFunction(const char *libraryname, const char *funcname);
/*
@@ -121,7 +134,8 @@ static void WaitForParallelWorkersToExit(ParallelContext *pcxt);
* destroyed before exiting the current subtransaction.
*/
ParallelContext *
-CreateParallelContext(parallel_worker_main_type entrypoint, int nworkers)
+CreateParallelContext(const char *library_name, const char *function_name,
+ int nworkers)
{
MemoryContext oldcontext;
ParallelContext *pcxt;
@@ -154,7 +168,8 @@ CreateParallelContext(parallel_worker_main_type entrypoint, int nworkers)
pcxt = palloc0(sizeof(ParallelContext));
pcxt->subid = GetCurrentSubTransactionId();
pcxt->nworkers = nworkers;
- pcxt->entrypoint = entrypoint;
+ pcxt->library_name = pstrdup(library_name);
+ pcxt->function_name = pstrdup(function_name);
pcxt->error_context_stack = error_context_stack;
shm_toc_initialize_estimator(&pcxt->estimator);
dlist_push_head(&pcxt_list, &pcxt->node);
@@ -166,33 +181,6 @@ CreateParallelContext(parallel_worker_main_type entrypoint, int nworkers)
}
/*
- * Establish a new parallel context that calls a function provided by an
- * extension. This works around the fact that the library might get mapped
- * at a different address in each backend.
- */
-ParallelContext *
-CreateParallelContextForExternalFunction(char *library_name,
- char *function_name,
- int nworkers)
-{
- MemoryContext oldcontext;
- ParallelContext *pcxt;
-
- /* We might be running in a very short-lived memory context. */
- oldcontext = MemoryContextSwitchTo(TopTransactionContext);
-
- /* Create the context. */
- pcxt = CreateParallelContext(ParallelExtensionTrampoline, nworkers);
- pcxt->library_name = pstrdup(library_name);
- pcxt->function_name = pstrdup(function_name);
-
- /* Restore previous memory context. */
- MemoryContextSwitchTo(oldcontext);
-
- return pcxt;
-}
-
-/*
* Establish the dynamic shared memory segment for a parallel context and
* copy state and other bookkeeping information that will be needed by
* parallel workers into it.
@@ -251,15 +239,10 @@ InitializeParallelDSM(ParallelContext *pcxt)
pcxt->nworkers));
shm_toc_estimate_keys(&pcxt->estimator, 1);
- /* Estimate how much we'll need for extension entrypoint info. */
- if (pcxt->library_name != NULL)
- {
- Assert(pcxt->entrypoint == ParallelExtensionTrampoline);
- Assert(pcxt->function_name != NULL);
- shm_toc_estimate_chunk(&pcxt->estimator, strlen(pcxt->library_name)
- + strlen(pcxt->function_name) + 2);
- shm_toc_estimate_keys(&pcxt->estimator, 1);
- }
+ /* Estimate how much we'll need for the entrypoint info. */
+ shm_toc_estimate_chunk(&pcxt->estimator, strlen(pcxt->library_name) +
+ strlen(pcxt->function_name) + 2);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
}
/*
@@ -299,7 +282,6 @@ InitializeParallelDSM(ParallelContext *pcxt)
fps->parallel_master_pgproc = MyProc;
fps->parallel_master_pid = MyProcPid;
fps->parallel_master_backend_id = MyBackendId;
- fps->entrypoint = pcxt->entrypoint;
SpinLockInit(&fps->mutex);
fps->last_xlog_end = 0;
shm_toc_insert(pcxt->toc, PARALLEL_KEY_FIXED, fps);
@@ -314,6 +296,8 @@ InitializeParallelDSM(ParallelContext *pcxt)
char *asnapspace;
char *tstatespace;
char *error_queue_space;
+ char *entrypointstate;
+ Size lnamelen;
/* Serialize shared libraries we have loaded. */
libraryspace = shm_toc_allocate(pcxt->toc, library_len);
@@ -370,19 +354,19 @@ InitializeParallelDSM(ParallelContext *pcxt)
}
shm_toc_insert(pcxt->toc, PARALLEL_KEY_ERROR_QUEUE, error_queue_space);
- /* Serialize extension entrypoint information. */
- if (pcxt->library_name != NULL)
- {
- Size lnamelen = strlen(pcxt->library_name);
- char *extensionstate;
-
- extensionstate = shm_toc_allocate(pcxt->toc, lnamelen
- + strlen(pcxt->function_name) + 2);
- strcpy(extensionstate, pcxt->library_name);
- strcpy(extensionstate + lnamelen + 1, pcxt->function_name);
- shm_toc_insert(pcxt->toc, PARALLEL_KEY_EXTENSION_TRAMPOLINE,
- extensionstate);
- }
+ /*
+ * Serialize entrypoint information. It's unsafe to pass function
+ * pointers across processes, as the function pointer may be different
+ * in each process in EXEC_BACKEND builds, so we always pass library
+ * and function name. (We use library name "postgres" for functions
+ * in the core backend.)
+ */
+ lnamelen = strlen(pcxt->library_name);
+ entrypointstate = shm_toc_allocate(pcxt->toc, lnamelen +
+ strlen(pcxt->function_name) + 2);
+ strcpy(entrypointstate, pcxt->library_name);
+ strcpy(entrypointstate + lnamelen + 1, pcxt->function_name);
+ shm_toc_insert(pcxt->toc, PARALLEL_KEY_ENTRYPOINT, entrypointstate);
}
/* Restore previous memory context. */
@@ -452,16 +436,18 @@ LaunchParallelWorkers(ParallelContext *pcxt)
oldcontext = MemoryContextSwitchTo(TopTransactionContext);
/* Configure a worker. */
+ memset(&worker, 0, sizeof(worker));
snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
MyProcPid);
worker.bgw_flags =
- BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
+ BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
+ | BGWORKER_CLASS_PARALLEL;
worker.bgw_start_time = BgWorkerStart_ConsistentState;
worker.bgw_restart_time = BGW_NEVER_RESTART;
- worker.bgw_main = ParallelWorkerMain;
+ sprintf(worker.bgw_library_name, "postgres");
+ sprintf(worker.bgw_function_name, "ParallelWorkerMain");
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));
worker.bgw_notify_pid = MyProcPid;
- memset(&worker.bgw_extra, 0, BGW_EXTRALEN);
/*
* Start workers.
@@ -542,7 +528,8 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt)
if (!anyone_alive)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1,
+ WAIT_EVENT_PARALLEL_FINISH);
ResetLatch(&MyProc->procLatch);
}
@@ -670,6 +657,8 @@ DestroyParallelContext(ParallelContext *pcxt)
}
/* Free memory. */
+ pfree(pcxt->library_name);
+ pfree(pcxt->function_name);
pfree(pcxt);
}
@@ -704,6 +693,9 @@ void
HandleParallelMessages(void)
{
dlist_iter iter;
+ MemoryContext oldcontext;
+
+ static MemoryContext hpm_context = NULL;
/*
* This is invoked from ProcessInterrupts(), and since some of the
@@ -714,6 +706,21 @@ HandleParallelMessages(void)
*/
HOLD_INTERRUPTS();
+ /*
+ * Moreover, CurrentMemoryContext might be pointing almost anywhere. We
+ * don't want to risk leaking data into long-lived contexts, so let's do
+ * our work here in a private context that we can reset on each use.
+ */
+ if (hpm_context == NULL) /* first time through? */
+ hpm_context = AllocSetContextCreate(TopMemoryContext,
+ "HandleParallelMessages",
+ ALLOCSET_DEFAULT_SIZES);
+ else
+ MemoryContextReset(hpm_context);
+
+ oldcontext = MemoryContextSwitchTo(hpm_context);
+
+ /* OK to process messages. Reset the flag saying there are more to do. */
ParallelMessagePending = false;
dlist_foreach(iter, &pcxt_list)
@@ -760,6 +767,11 @@ HandleParallelMessages(void)
}
}
+ MemoryContextSwitchTo(oldcontext);
+
+ /* Might as well clear the context on our way out */
+ MemoryContextReset(hpm_context);
+
RESUME_INTERRUPTS();
}
@@ -789,30 +801,43 @@ HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg)
case 'N': /* NoticeResponse */
{
ErrorData edata;
- ErrorContextCallback errctx;
ErrorContextCallback *save_error_context_stack;
- /*
- * Rethrow the error using the error context callbacks that
- * were in effect when the context was created, not the
- * current ones.
- */
- save_error_context_stack = error_context_stack;
- errctx.callback = ParallelErrorContext;
- errctx.arg = NULL;
- errctx.previous = pcxt->error_context_stack;
- error_context_stack = &errctx;
-
/* Parse ErrorResponse or NoticeResponse. */
pq_parse_errornotice(msg, &edata);
/* Death of a worker isn't enough justification for suicide. */
edata.elevel = Min(edata.elevel, ERROR);
- /* Rethrow error or notice. */
+ /*
+ * If desired, add a context line to show that this is a
+ * message propagated from a parallel worker. Otherwise, it
+ * can sometimes be confusing to understand what actually
+ * happened. (We don't do this in FORCE_PARALLEL_REGRESS mode
+ * because it causes test-result instability depending on
+ * whether a parallel worker is actually used or not.)
+ */
+ if (force_parallel_mode != FORCE_PARALLEL_REGRESS)
+ {
+ if (edata.context)
+ edata.context = psprintf("%s\n%s", edata.context,
+ _("parallel worker"));
+ else
+ edata.context = pstrdup(_("parallel worker"));
+ }
+
+ /*
+ * Context beyond that should use the error context callbacks
+ * that were in effect when the ParallelContext was created,
+ * not the current ones.
+ */
+ save_error_context_stack = error_context_stack;
+ error_context_stack = pcxt->error_context_stack;
+
+ /* Rethrow error or print notice. */
ThrowErrorData(&edata);
- /* Restore previous context. */
+ /* Not an error, so restore previous context stack. */
error_context_stack = save_error_context_stack;
break;
@@ -894,7 +919,7 @@ AtEOXact_Parallel(bool isCommit)
/*
* Main entrypoint for parallel workers.
*/
-static void
+void
ParallelWorkerMain(Datum main_arg)
{
dsm_segment *seg;
@@ -904,6 +929,10 @@ ParallelWorkerMain(Datum main_arg)
shm_mq *mq;
shm_mq_handle *mqh;
char *libraryspace;
+ char *entrypointstate;
+ char *library_name;
+ char *function_name;
+ parallel_worker_main_type entrypt;
char *gucspace;
char *combocidspace;
char *tsnapspace;
@@ -926,10 +955,8 @@ ParallelWorkerMain(Datum main_arg)
Assert(CurrentResourceOwner == NULL);
CurrentResourceOwner = ResourceOwnerCreate(NULL, "parallel toplevel");
CurrentMemoryContext = AllocSetContextCreate(TopMemoryContext,
- "parallel worker",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ "Parallel worker",
+ ALLOCSET_DEFAULT_SIZES);
/*
* Now that we have a resource owner, we can attach to the dynamic shared
@@ -1005,6 +1032,18 @@ ParallelWorkerMain(Datum main_arg)
Assert(libraryspace != NULL);
RestoreLibraryState(libraryspace);
+ /*
+ * Identify the entry point to be called. In theory this could result in
+ * loading an additional library, though most likely the entry point is in
+ * the core backend or in a library we just loaded.
+ */
+ entrypointstate = shm_toc_lookup(toc, PARALLEL_KEY_ENTRYPOINT);
+ Assert(entrypointstate != NULL);
+ library_name = entrypointstate;
+ function_name = entrypointstate + strlen(library_name) + 1;
+
+ entrypt = LookupParallelWorkerFunction(library_name, function_name);
+
/* Restore database connection. */
BackgroundWorkerInitializeConnectionByOid(fps->database_id,
fps->authenticated_user_id);
@@ -1072,11 +1111,8 @@ ParallelWorkerMain(Datum main_arg)
/*
* Time to do the real work: invoke the caller-supplied code.
- *
- * If you get a crash at this line, see the comments for
- * ParallelExtensionTrampoline.
*/
- fps->entrypoint(seg, toc);
+ entrypt(seg, toc);
/* Must exit parallel mode to pop active snapshot. */
ExitParallelMode();
@@ -1092,45 +1128,6 @@ ParallelWorkerMain(Datum main_arg)
}
/*
- * It's unsafe for the entrypoint invoked by ParallelWorkerMain to be a
- * function living in a dynamically loaded module, because the module might
- * not be loaded in every process, or might be loaded but not at the same
- * address. To work around that problem, CreateParallelContextForExtension()
- * arranges to call this function rather than calling the extension-provided
- * function directly; and this function then looks up the real entrypoint and
- * calls it.
- */
-static void
-ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc)
-{
- char *extensionstate;
- char *library_name;
- char *function_name;
- parallel_worker_main_type entrypt;
-
- extensionstate = shm_toc_lookup(toc, PARALLEL_KEY_EXTENSION_TRAMPOLINE);
- Assert(extensionstate != NULL);
- library_name = extensionstate;
- function_name = extensionstate + strlen(library_name) + 1;
-
- entrypt = (parallel_worker_main_type)
- load_external_function(library_name, function_name, true, NULL);
- entrypt(seg, toc);
-}
-
-/*
- * Give the user a hint that this is a message propagated from a parallel
- * worker. Otherwise, it can sometimes be confusing to understand what
- * actually happened.
- */
-static void
-ParallelErrorContext(void *arg)
-{
- if (force_parallel_mode != FORCE_PARALLEL_REGRESS)
- errcontext("parallel worker");
-}
-
-/*
* Update shared memory with the ending location of the last WAL record we
* wrote, if it's greater than the value already stored there.
*/
@@ -1145,3 +1142,47 @@ ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end)
fps->last_xlog_end = last_xlog_end;
SpinLockRelease(&fps->mutex);
}
+
+/*
+ * Look up (and possibly load) a parallel worker entry point function.
+ *
+ * For functions contained in the core code, we use library name "postgres"
+ * and consult the InternalParallelWorkers array. External functions are
+ * looked up, and loaded if necessary, using load_external_function().
+ *
+ * The point of this is to pass function names as strings across process
+ * boundaries. We can't pass actual function addresses because of the
+ * possibility that the function has been loaded at a different address
+ * in a different process. This is obviously a hazard for functions in
+ * loadable libraries, but it can happen even for functions in the core code
+ * on platforms using EXEC_BACKEND (e.g., Windows).
+ *
+ * At some point it might be worthwhile to get rid of InternalParallelWorkers[]
+ * in favor of applying load_external_function() for core functions too;
+ * but that raises portability issues that are not worth addressing now.
+ */
+static parallel_worker_main_type
+LookupParallelWorkerFunction(const char *libraryname, const char *funcname)
+{
+ /*
+ * If the function is to be loaded from postgres itself, search the
+ * InternalParallelWorkers array.
+ */
+ if (strcmp(libraryname, "postgres") == 0)
+ {
+ int i;
+
+ for (i = 0; i < lengthof(InternalParallelWorkers); i++)
+ {
+ if (strcmp(InternalParallelWorkers[i].fn_name, funcname) == 0)
+ return InternalParallelWorkers[i].fn_addr;
+ }
+
+ /* We can only reach this by programming error. */
+ elog(ERROR, "internal function \"%s\" not found", funcname);
+ }
+
+ /* Otherwise load from external library. */
+ return (parallel_worker_main_type)
+ load_external_function(libraryname, funcname, true, NULL);
+}
diff --git a/src/backend/access/transam/recovery.conf.sample b/src/backend/access/transam/recovery.conf.sample
index 5624eeca84..acb81afd66 100644
--- a/src/backend/access/transam/recovery.conf.sample
+++ b/src/backend/access/transam/recovery.conf.sample
@@ -67,10 +67,10 @@
# must set a recovery target.
#
# You may set a recovery target either by transactionId, by name,
-# or by timestamp or by barrier. Recovery may either include or exclude the
-# transaction(s) with the recovery target value (ie, stop either
-# just after or just before the given target, respectively). In case of
-# barrier, the recovery stops exactly at that point.
+# or by timestamp or by WAL location (LSN) or by barrier. Recovery may either
+# include or exclude the transaction(s) with the recovery target value (ie,
+# stop either just after or just before the given target, respectively). In
+# case of barrier, the recovery stops exactly at that point.
#
#
#recovery_target_name = '' # e.g. 'daily backup 2011-01-26'
@@ -81,6 +81,8 @@
#
#recovery_target_barrier = ''
#
+#recovery_target_lsn = '' # e.g. '0/70006B8'
+#
#recovery_target_inclusive = true
#
#
@@ -99,7 +101,7 @@
#
# If recovery_target_action = 'pause', recovery will pause when the
# recovery target is reached. The pause state will continue until
-# pg_xlog_replay_resume() is called. This setting has no effect if
+# pg_wal_replay_resume() is called. This setting has no effect if
# no recovery target is set. If hot_standby is not enabled then the
# server will shutdown instead, though you may request this in
# any case by specifying 'shutdown'.
diff --git a/src/backend/access/transam/rmgr.c b/src/backend/access/transam/rmgr.c
index bc875677b0..db9899bb6f 100644
--- a/src/backend/access/transam/rmgr.c
+++ b/src/backend/access/transam/rmgr.c
@@ -9,15 +9,15 @@
#include "access/clog.h"
#include "access/commit_ts.h"
-#include "access/gin.h"
-#include "access/gist_private.h"
+#include "access/ginxlog.h"
+#include "access/gistxlog.h"
#include "access/generic_xlog.h"
-#include "access/hash.h"
+#include "access/hash_xlog.h"
#include "access/heapam_xlog.h"
#include "access/brin_xlog.h"
#include "access/multixact.h"
-#include "access/nbtree.h"
-#include "access/spgist.h"
+#include "access/nbtxlog.h"
+#include "access/spgxlog.h"
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "catalog/storage_xlog.h"
@@ -33,8 +33,8 @@
#include "utils/relmapper.h"
/* must be kept in sync with RmgrData definition in xlog_internal.h */
-#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup) \
- { name, redo, desc, identify, startup, cleanup },
+#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask) \
+ { name, redo, desc, identify, startup, cleanup, mask },
const RmgrData RmgrTable[RM_MAX_ID + 1] = {
#include "access/rmgrlist.h"
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 37fdd5a5e1..ed90fb9232 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -38,7 +38,7 @@
* by re-setting the page's page_dirty flag.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/slru.c
@@ -54,6 +54,7 @@
#include "access/slru.h"
#include "access/transam.h"
#include "access/xlog.h"
+#include "pgstat.h"
#include "storage/fd.h"
#include "storage/shmem.h"
#include "miscadmin.h"
@@ -216,9 +217,6 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
Assert(strlen(name) + 1 < SLRU_MAX_NAME_LENGTH);
strlcpy(shared->lwlock_tranche_name, name, SLRU_MAX_NAME_LENGTH);
shared->lwlock_tranche_id = tranche_id;
- shared->lwlock_tranche.name = shared->lwlock_tranche_name;
- shared->lwlock_tranche.array_base = shared->buffer_locks;
- shared->lwlock_tranche.array_stride = sizeof(LWLockPadded);
ptr += BUFFERALIGN(offset);
for (slotno = 0; slotno < nslots; slotno++)
@@ -237,7 +235,8 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
Assert(found);
/* Register SLRU tranche in the main tranches array */
- LWLockRegisterTranche(shared->lwlock_tranche_id, &shared->lwlock_tranche);
+ LWLockRegisterTranche(shared->lwlock_tranche_id,
+ shared->lwlock_tranche_name);
/*
* Initialize the unshared control struct, including directory path. We
@@ -691,13 +690,16 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
}
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_SLRU_READ);
if (read(fd, shared->page_buffer[slotno], BLCKSZ) != BLCKSZ)
{
+ pgstat_report_wait_end();
slru_errcause = SLRU_READ_FAILED;
slru_errno = errno;
CloseTransientFile(fd);
return false;
}
+ pgstat_report_wait_end();
if (CloseTransientFile(fd))
{
@@ -850,8 +852,10 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
}
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_SLRU_WRITE);
if (write(fd, shared->page_buffer[slotno], BLCKSZ) != BLCKSZ)
{
+ pgstat_report_wait_end();
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
@@ -861,6 +865,7 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
CloseTransientFile(fd);
return false;
}
+ pgstat_report_wait_end();
/*
* If not part of Flush, need to fsync now. We assume this happens
@@ -868,13 +873,16 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
*/
if (!fdata)
{
+ pgstat_report_wait_start(WAIT_EVENT_SLRU_SYNC);
if (ctl->do_fsync && pg_fsync(fd))
{
+ pgstat_report_wait_end();
slru_errcause = SLRU_FSYNC_FAILED;
slru_errno = errno;
CloseTransientFile(fd);
return false;
}
+ pgstat_report_wait_end();
if (CloseTransientFile(fd))
{
@@ -1142,6 +1150,7 @@ SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
ok = true;
for (i = 0; i < fdata.num_files; i++)
{
+ pgstat_report_wait_start(WAIT_EVENT_SLRU_FLUSH_SYNC);
if (ctl->do_fsync && pg_fsync(fdata.fd[i]))
{
slru_errcause = SLRU_FSYNC_FAILED;
@@ -1149,6 +1158,7 @@ SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
pageno = fdata.segno[i] * SLRU_PAGES_PER_SEGMENT;
ok = false;
}
+ pgstat_report_wait_end();
if (CloseTransientFile(fdata.fd[i]))
{
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 76069546cb..a0390bf25b 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -3,15 +3,14 @@
* subtrans.c
* PostgreSQL subtransaction-log manager
*
- * The pg_subtrans manager is a pg_clog-like manager that stores the parent
+ * The pg_subtrans manager is a pg_xact-like manager that stores the parent
* transaction Id for each transaction. It is a fundamental part of the
* nested transactions implementation. A main transaction has a parent
* of InvalidTransactionId, and each subtransaction has its immediate parent.
* The tree can easily be walked from child to parent, but not in the
* opposite direction.
*
- * This code is based on clog.c, but the robustness requirements
- * are completely different from pg_clog, because we only need to remember
+ * are completely different from pg_xact, because we only need to remember
* pg_subtrans information for currently-open transactions. Thus, there is
* no need to preserve data over a crash and restart.
*
@@ -19,7 +18,7 @@
* data across crashes. During database startup, we simply force the
* currently-active page of SUBTRANS to zeroes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -69,11 +68,9 @@ static bool SubTransPagePrecedes(int page1, int page2);
/*
* Record the parent of a subtransaction in the subtrans log.
- *
- * In some cases we may need to overwrite an existing value.
*/
void
-SubTransSetParent(TransactionId xid, TransactionId parent, bool overwriteOK)
+SubTransSetParent(TransactionId xid, TransactionId parent)
{
int pageno = TransactionIdToPage(xid);
int entryno = TransactionIdToEntry(xid);
@@ -81,6 +78,7 @@ SubTransSetParent(TransactionId xid, TransactionId parent, bool overwriteOK)
TransactionId *ptr;
Assert(TransactionIdIsValid(parent));
+ Assert(TransactionIdFollows(xid, parent));
LWLockAcquire(SubtransControlLock, LW_EXCLUSIVE);
@@ -88,13 +86,17 @@ SubTransSetParent(TransactionId xid, TransactionId parent, bool overwriteOK)
ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno];
ptr += entryno;
- /* Current state should be 0 */
- Assert(*ptr == InvalidTransactionId ||
- (*ptr == parent && overwriteOK));
-
- *ptr = parent;
-
- SubTransCtl->shared->page_dirty[slotno] = true;
+ /*
+ * It's possible we'll try to set the parent xid multiple times but we
+ * shouldn't ever be changing the xid from one valid xid to another valid
+ * xid, which would corrupt the data structure.
+ */
+ if (*ptr != parent)
+ {
+ Assert(*ptr == InvalidTransactionId);
+ *ptr = parent;
+ SubTransCtl->shared->page_dirty[slotno] = true;
+ }
LWLockRelease(SubtransControlLock);
}
@@ -158,6 +160,15 @@ SubTransGetTopmostTransaction(TransactionId xid)
if (TransactionIdPrecedes(parentXid, TransactionXmin))
break;
parentXid = SubTransGetParent(parentXid);
+
+ /*
+ * By convention the parent xid gets allocated first, so should always
+ * precede the child xid. Anything else points to a corrupted data
+ * structure that could lead to an infinite loop, so exit.
+ */
+ if (!TransactionIdPrecedes(parentXid, previousXid))
+ elog(ERROR, "pg_subtrans contains invalid entry: xid %u points to parent xid %u",
+ previousXid, parentXid);
}
Assert(TransactionIdIsValid(previousXid));
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index bd91573708..8cab8b9aa9 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -15,13 +15,13 @@
* <parentTLI> <switchpoint> <reason>
*
* parentTLI ID of the parent timeline
- * switchpoint XLogRecPtr of the WAL position where the switch happened
+ * switchpoint XLogRecPtr of the WAL location where the switch happened
* reason human-readable explanation of why the timeline was changed
*
* The fields are separated by tabs. Lines beginning with # are comments, and
* are ignored. Empty lines are also ignored.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/timeline.c
@@ -32,18 +32,18 @@
#include "postgres.h"
#include <sys/stat.h>
-#include <stdio.h>
#include <unistd.h>
#include "access/timeline.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogdefs.h"
+#include "pgstat.h"
#include "storage/fd.h"
/*
* Copies all timeline history files with id's between 'begin' and 'end'
- * from archive to pg_xlog.
+ * from archive to pg_wal.
*/
void
restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
@@ -151,7 +151,7 @@ readTimeLineHistory(TimeLineID targetTLI)
if (nfields != 3)
ereport(FATAL,
(errmsg("syntax error in history file: %s", fline),
- errhint("Expected a transaction log switchpoint location.")));
+ errhint("Expected a write-ahead log switchpoint location.")));
if (result && tli <= lasttli)
ereport(FATAL,
@@ -191,7 +191,7 @@ readTimeLineHistory(TimeLineID targetTLI)
result = lcons(entry, result);
/*
- * If the history file was fetched from archive, save it in pg_xlog for
+ * If the history file was fetched from archive, save it in pg_wal for
* future reference.
*/
if (fromArchive)
@@ -278,7 +278,7 @@ findNewestTimeLine(TimeLineID startTLI)
*
* newTLI: ID of the new timeline
* parentTLI: ID of its immediate parent
- * switchpoint: XLOG position where the system switched to the new timeline
+ * switchpoint: WAL location where the system switched to the new timeline
* reason: human-readable explanation of why the timeline was switched
*
* Currently this is only used at the end recovery, and so there are no locking
@@ -339,7 +339,9 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
for (;;)
{
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_READ);
nbytes = (int) read(srcfd, buffer, sizeof(buffer));
+ pgstat_report_wait_end();
if (nbytes < 0 || errno != 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -347,6 +349,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
if (nbytes == 0)
break;
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_WRITE);
if ((int) write(fd, buffer, nbytes) != nbytes)
{
int save_errno = errno;
@@ -366,6 +369,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m", tmppath)));
}
+ pgstat_report_wait_end();
}
CloseTransientFile(srcfd);
}
@@ -401,10 +405,12 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
errmsg("could not write to file \"%s\": %m", tmppath)));
}
+ pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_SYNC);
if (pg_fsync(fd) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", tmppath)));
+ pgstat_report_wait_end();
if (CloseTransientFile(fd))
ereport(ERROR,
@@ -461,6 +467,7 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size)
errmsg("could not create file \"%s\": %m", tmppath)));
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE);
if ((int) write(fd, content, size) != size)
{
int save_errno = errno;
@@ -476,11 +483,14 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size)
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m", tmppath)));
}
+ pgstat_report_wait_end();
+ pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC);
if (pg_fsync(fd) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", tmppath)));
+ pgstat_report_wait_end();
if (CloseTransientFile(fd))
ereport(ERROR,
diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c
index d1a549b2b2..b160973270 100644
--- a/src/backend/access/transam/transam.c
+++ b/src/backend/access/transam/transam.c
@@ -1,9 +1,9 @@
/*-------------------------------------------------------------------------
*
* transam.c
- * postgres transaction log interface routines
+ * postgres transaction (commit) log interface routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -169,7 +169,7 @@ pgxc_is_inprogress(PG_FUNCTION_ARGS)
* True iff transaction associated with the identifier did commit.
*
* Note:
- * Assumes transaction identifier is valid.
+ * Assumes transaction identifier is valid and exists in clog.
*/
bool /* true if given transaction committed */
TransactionIdDidCommit(TransactionId transactionId)
@@ -225,7 +225,7 @@ TransactionIdDidCommit(TransactionId transactionId)
* True iff transaction associated with the identifier did abort.
*
* Note:
- * Assumes transaction identifier is valid.
+ * Assumes transaction identifier is valid and exists in clog.
*/
bool /* true if given transaction aborted */
TransactionIdDidAbort(TransactionId transactionId)
@@ -274,7 +274,7 @@ TransactionIdDidAbort(TransactionId transactionId)
* True iff transaction associated with the identifier is currently
* known to have either committed or aborted.
*
- * This does NOT look into pg_clog but merely probes our local cache
+ * This does NOT look into pg_xact but merely probes our local cache
* (and so it's not named TransactionIdDidComplete, which would be the
* appropriate name for a function that worked that way). The intended
* use is just to short-circuit TransactionIdIsInProgress calls when doing
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index b65227922b..f6986d37db 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -3,7 +3,7 @@
* twophase.c
* Two-phase commit support functions.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -46,8 +46,27 @@
* fsynced
* * If COMMIT happens after checkpoint then backend reads state data from
* files
- * * In case of crash replay will move data from xlog to files, if that
- * hasn't happened before. XXX TODO - move to shmem in replay also
+ *
+ * During replay and replication, TwoPhaseState also holds information
+ * about active prepared transactions that haven't been moved to disk yet.
+ *
+ * Replay of twophase records happens by the following rules:
+ *
+ * * At the beginning of recovery, pg_twophase is scanned once, filling
+ * TwoPhaseState with entries marked with gxact->inredo and
+ * gxact->ondisk. Two-phase file data older than the XID horizon of
+ * the redo position are discarded.
+ * * On PREPARE redo, the transaction is added to TwoPhaseState->prepXacts.
+ * gxact->inredo is set to true for such entries.
+ * * On Checkpoint we iterate through TwoPhaseState->prepXacts entries
+ * that have gxact->inredo set and are behind the redo_horizon. We
+ * save them to disk and then switch gxact->ondisk to true.
+ * * On COMMIT/ABORT we delete the entry from TwoPhaseState->prepXacts.
+ * If gxact->ondisk is true, the corresponding entry from the disk
+ * is additionally deleted.
+ * * RecoverPreparedTransactions(), StandbyRecoverPreparedTransactions()
+ * and PrescanPreparedTransactions() have been modified to go through
+ * gxact->inredo entries that have not made it to disk.
*
*-------------------------------------------------------------------------
*/
@@ -55,7 +74,6 @@
#include <fcntl.h>
#include <sys/stat.h>
-#include <sys/types.h>
#include <time.h>
#include <unistd.h>
@@ -157,11 +175,13 @@ typedef struct GlobalTransactionData
*/
XLogRecPtr prepare_start_lsn; /* XLOG offset of prepare record start */
XLogRecPtr prepare_end_lsn; /* XLOG offset of prepare record end */
+ TransactionId xid; /* The GXACT id */
Oid owner; /* ID of user that executed the xact */
BackendId locking_backend; /* backend currently working on the xact */
bool valid; /* TRUE if PGPROC entry is in proc array */
bool ondisk; /* TRUE if prepare state file is on disk */
+ bool inredo; /* TRUE if entry was added via xlog_redo */
char gid[GIDSIZE]; /* The GID assigned to the prepared xact */
} GlobalTransactionData;
@@ -208,6 +228,14 @@ static void ProcessRecords(char *bufptr, TransactionId xid,
static void RemoveGXact(GlobalTransaction gxact);
static void XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len);
+static char *ProcessTwoPhaseBuffer(TransactionId xid,
+ XLogRecPtr prepare_start_lsn,
+ bool fromdisk, bool setParent, bool setNextXid);
+static void MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid,
+ const char *gid, TimestampTz prepared_at, Oid owner,
+ Oid databaseid);
+static void RemoveTwoPhaseFile(TransactionId xid, bool giveWarning);
+static void RecreateTwoPhaseFile(TransactionId xid, void *content, int len);
/*
* Initialization of shared memory
@@ -352,18 +380,12 @@ PostPrepare_Twophase(void)
/*
* MarkAsPreparing
* Reserve the GID for the given transaction.
- *
- * Internally, this creates a gxact struct and puts it into the active array.
- * NOTE: this is also used when reloading a gxact after a crash; so avoid
- * assuming that we can use very much backend context.
*/
GlobalTransaction
MarkAsPreparing(TransactionId xid, const char *gid,
TimestampTz prepared_at, Oid owner, Oid databaseid)
{
GlobalTransaction gxact;
- PGPROC *proc;
- PGXACT *pgxact;
int i;
if (strlen(gid) >= GIDSIZE)
@@ -411,6 +433,37 @@ MarkAsPreparing(TransactionId xid, const char *gid,
gxact = TwoPhaseState->freeGXacts;
TwoPhaseState->freeGXacts = gxact->next;
+ MarkAsPreparingGuts(gxact, xid, gid, prepared_at, owner, databaseid);
+
+ gxact->ondisk = false;
+
+ /* And insert it into the active array */
+ Assert(TwoPhaseState->numPrepXacts < max_prepared_xacts);
+ TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts++] = gxact;
+
+ LWLockRelease(TwoPhaseStateLock);
+
+ return gxact;
+}
+
+/*
+ * MarkAsPreparingGuts
+ *
+ * This uses a gxact struct and puts it into the active array.
+ * NOTE: this is also used when reloading a gxact after a crash; so avoid
+ * assuming that we can use very much backend context.
+ *
+ * Note: This function should be called with appropriate locks held.
+ */
+static void
+MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
+ TimestampTz prepared_at, Oid owner, Oid databaseid)
+{
+ PGPROC *proc;
+ PGXACT *pgxact;
+ int i;
+
+ Assert(gxact != NULL);
proc = &ProcGlobal->allProcs[gxact->pgprocno];
pgxact = &ProcGlobal->allPgXact[gxact->pgprocno];
@@ -429,6 +482,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
proc->backendId = InvalidBackendId;
proc->databaseId = databaseid;
proc->roleId = owner;
+ proc->isBackgroundWorker = false;
proc->lwWaiting = false;
proc->lwWaitMode = 0;
proc->waitLock = NULL;
@@ -440,28 +494,18 @@ MarkAsPreparing(TransactionId xid, const char *gid,
pgxact->nxids = 0;
gxact->prepared_at = prepared_at;
- /* initialize LSN to InvalidXLogRecPtr */
- gxact->prepare_start_lsn = InvalidXLogRecPtr;
- gxact->prepare_end_lsn = InvalidXLogRecPtr;
+ gxact->xid = xid;
gxact->owner = owner;
gxact->locking_backend = MyBackendId;
gxact->valid = false;
- gxact->ondisk = false;
+ gxact->inredo = false;
strcpy(gxact->gid, gid);
- /* And insert it into the active array */
- Assert(TwoPhaseState->numPrepXacts < max_prepared_xacts);
- TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts++] = gxact;
-
/*
* Remember that we have this GlobalTransaction entry locked for us. If we
* abort after this, we must release it.
*/
MyLockedGxact = gxact;
-
- LWLockRelease(TwoPhaseStateLock);
-
- return gxact;
}
/*
@@ -1220,8 +1264,10 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
*/
buf = (char *) palloc(stat.st_size);
+ pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_READ);
if (read(fd, buf, stat.st_size) != stat.st_size)
{
+ pgstat_report_wait_end();
CloseTransientFile(fd);
if (give_warnings)
ereport(WARNING,
@@ -1232,6 +1278,7 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
return NULL;
}
+ pgstat_report_wait_end();
CloseTransientFile(fd);
hdr = (TwoPhaseFileHeader *) buf;
@@ -1261,9 +1308,9 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
* Reads 2PC data from xlog. During checkpoint this data will be moved to
* twophase files and ReadTwoPhaseFile should be used instead.
*
- * Note clearly that this function accesses WAL during normal operation, similarly
- * to the way WALSender or Logical Decoding would do. It does not run during
- * crash recovery or standby processing.
+ * Note clearly that this function can access WAL during normal operation,
+ * similarly to the way WALSender or Logical Decoding would do.
+ *
*/
static void
XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
@@ -1272,20 +1319,18 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
XLogReaderState *xlogreader;
char *errormsg;
- Assert(!RecoveryInProgress());
-
xlogreader = XLogReaderAllocate(&read_local_xlog_page, NULL);
if (!xlogreader)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory"),
- errdetail("Failed while allocating an XLog reading processor.")));
+ errdetail("Failed while allocating a WAL reading processor.")));
record = XLogReadRecord(xlogreader, lsn, &errormsg);
if (record == NULL)
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not read two-phase state from xlog at %X/%X",
+ errmsg("could not read two-phase state from WAL at %X/%X",
(uint32) (lsn >> 32),
(uint32) lsn)));
@@ -1293,9 +1338,9 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
(XLogRecGetInfo(xlogreader) & XLOG_XACT_OPMASK) != XLOG_XACT_PREPARE)
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("expected two-phase state data is not present in xlog at %X/%X",
- (uint32) (lsn >> 32),
- (uint32) lsn)));
+ errmsg("expected two-phase state data is not present in WAL at %X/%X",
+ (uint32) (lsn >> 32),
+ (uint32) lsn)));
if (len != NULL)
*len = XLogRecGetDataLen(xlogreader);
@@ -1413,7 +1458,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
/*
* The order of operations here is critical: make the XLOG entry for
* commit or abort, then mark the transaction committed or aborted in
- * pg_clog, then remove its PGPROC from the global ProcArray (which means
+ * pg_xact, then remove its PGPROC from the global ProcArray (which means
* TransactionIdIsInProgress will stop saying the prepared xact is in
* progress), then run the post-commit or post-abort callbacks. The
* callbacks will release the locks the transaction held.
@@ -1532,7 +1577,7 @@ ProcessRecords(char *bufptr, TransactionId xid,
* If giveWarning is false, do not complain about file-not-present;
* this is an expected case during WAL replay.
*/
-void
+static void
RemoveTwoPhaseFile(TransactionId xid, bool giveWarning)
{
char path[MAXPGPATH];
@@ -1552,7 +1597,7 @@ RemoveTwoPhaseFile(TransactionId xid, bool giveWarning)
*
* Note: content and len don't include CRC.
*/
-void
+static void
RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
{
char path[MAXPGPATH];
@@ -1576,8 +1621,10 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
path)));
/* Write content and CRC */
+ pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_WRITE);
if (write(fd, content, len) != len)
{
+ pgstat_report_wait_end();
CloseTransientFile(fd);
ereport(ERROR,
(errcode_for_file_access(),
@@ -1585,16 +1632,19 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
}
if (write(fd, &statefile_crc, sizeof(pg_crc32c)) != sizeof(pg_crc32c))
{
+ pgstat_report_wait_end();
CloseTransientFile(fd);
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not write two-phase state file: %m")));
}
+ pgstat_report_wait_end();
/*
* We must fsync the file because the end-of-replay checkpoint will not do
* so, there being no GXACT in shared memory yet to tell it to.
*/
+ pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_SYNC);
if (pg_fsync(fd) != 0)
{
CloseTransientFile(fd);
@@ -1602,6 +1652,7 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
(errcode_for_file_access(),
errmsg("could not fsync two-phase state file: %m")));
}
+ pgstat_report_wait_end();
if (CloseTransientFile(fd) != 0)
ereport(ERROR,
@@ -1612,9 +1663,11 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
/*
* CheckPointTwoPhase -- handle 2PC component of checkpointing.
*
- * We must fsync the state file of any GXACT that is valid and has a PREPARE
- * LSN <= the checkpoint's redo horizon. (If the gxact isn't valid yet or
- * has a later LSN, this checkpoint is not responsible for fsyncing it.)
+ * We must fsync the state file of any GXACT that is valid or has been
+ * generated during redo and has a PREPARE LSN <= the checkpoint's redo
+ * horizon. (If the gxact isn't valid yet, has not been generated in
+ * redo, or has a later LSN, this checkpoint is not responsible for
+ * fsyncing it.)
*
* This is deliberately run as late as possible in the checkpoint sequence,
* because GXACTs ordinarily have short lifespans, and so it is quite
@@ -1646,7 +1699,7 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
*
* It's also possible to move I/O out of the lock, but on every error we
* should check whether somebody committed our transaction in different
- * backend. Let's leave this optimisation for future, if somebody will
+ * backend. Let's leave this optimization for future, if somebody will
* spot that this place cause bottleneck.
*
* Note that it isn't possible for there to be a GXACT with a
@@ -1656,10 +1709,13 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
{
+ /*
+ * Note that we are using gxact not pgxact so this works in recovery
+ * also
+ */
GlobalTransaction gxact = TwoPhaseState->prepXacts[i];
- PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno];
- if (gxact->valid &&
+ if ((gxact->valid || gxact->inredo) &&
!gxact->ondisk &&
gxact->prepare_end_lsn <= redo_horizon)
{
@@ -1667,20 +1723,30 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
int len;
XlogReadTwoPhaseData(gxact->prepare_start_lsn, &buf, &len);
- RecreateTwoPhaseFile(pgxact->xid, buf, len);
+ RecreateTwoPhaseFile(gxact->xid, buf, len);
gxact->ondisk = true;
+ gxact->prepare_start_lsn = InvalidXLogRecPtr;
+ gxact->prepare_end_lsn = InvalidXLogRecPtr;
pfree(buf);
serialized_xacts++;
}
}
LWLockRelease(TwoPhaseStateLock);
+ /*
+ * Flush unconditionally the parent directory to make any information
+ * durable on disk. Two-phase files could have been removed and those
+ * removals need to be made persistent as well as any files newly created
+ * previously since the last checkpoint.
+ */
+ fsync_fname(TWOPHASE_DIR, true);
+
TRACE_POSTGRESQL_TWOPHASE_CHECKPOINT_DONE();
if (log_checkpoints && serialized_xacts > 0)
ereport(LOG,
(errmsg_plural("%u two-phase state file was written "
- "for long-running prepared transactions",
+ "for a long-running prepared transaction",
"%u two-phase state files were written "
"for long-running prepared transactions",
serialized_xacts,
@@ -1688,12 +1754,48 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
}
/*
+ * restoreTwoPhaseData
+ *
+ * Scan pg_twophase and fill TwoPhaseState depending on the on-disk data.
+ * This is called once at the beginning of recovery, saving any extra
+ * lookups in the future. Two-phase files that are newer than the
+ * minimum XID horizon are discarded on the way.
+ */
+void
+restoreTwoPhaseData(void)
+{
+ DIR *cldir;
+ struct dirent *clde;
+
+ cldir = AllocateDir(TWOPHASE_DIR);
+ while ((clde = ReadDir(cldir, TWOPHASE_DIR)) != NULL)
+ {
+ if (strlen(clde->d_name) == 8 &&
+ strspn(clde->d_name, "0123456789ABCDEF") == 8)
+ {
+ TransactionId xid;
+ char *buf;
+
+ xid = (TransactionId) strtoul(clde->d_name, NULL, 16);
+
+ buf = ProcessTwoPhaseBuffer(xid, InvalidXLogRecPtr,
+ true, false, false);
+ if (buf == NULL)
+ continue;
+
+ PrepareRedoAdd(buf, InvalidXLogRecPtr, InvalidXLogRecPtr);
+ }
+ }
+ FreeDir(cldir);
+}
+
+/*
* PrescanPreparedTransactions
*
- * Scan the pg_twophase directory and determine the range of valid XIDs
- * present. This is run during database startup, after we have completed
- * reading WAL. ShmemVariableCache->nextXid has been set to one more than
- * the highest XID for which evidence exists in WAL.
+ * Scan the shared memory entries of TwoPhaseState and determine the range
+ * of valid XIDs present. This is run during database startup, after we
+ * have completed reading WAL. ShmemVariableCache->nextXid has been set to
+ * one more than the highest XID for which evidence exists in WAL.
*
* We throw away any prepared xacts with main XID beyond nextXid --- if any
* are present, it suggests that the DBA has done a PITR recovery to an
@@ -1719,119 +1821,57 @@ PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
{
TransactionId origNextXid = ShmemVariableCache->nextXid;
TransactionId result = origNextXid;
- DIR *cldir;
- struct dirent *clde;
TransactionId *xids = NULL;
int nxids = 0;
int allocsize = 0;
+ int i;
- cldir = AllocateDir(TWOPHASE_DIR);
- while ((clde = ReadDir(cldir, TWOPHASE_DIR)) != NULL)
+ LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
+ for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
{
- if (strlen(clde->d_name) == 8 &&
- strspn(clde->d_name, "0123456789ABCDEF") == 8)
- {
- TransactionId xid;
- char *buf;
- TwoPhaseFileHeader *hdr;
- TransactionId *subxids;
- int i;
+ TransactionId xid;
+ char *buf;
+ GlobalTransaction gxact = TwoPhaseState->prepXacts[i];
- xid = (TransactionId) strtoul(clde->d_name, NULL, 16);
+ Assert(gxact->inredo);
- /* Reject XID if too new */
- if (TransactionIdFollowsOrEquals(xid, origNextXid))
- {
- ereport(WARNING,
- (errmsg("removing future two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- continue;
- }
+ xid = gxact->xid;
- /*
- * Note: we can't check if already processed because clog
- * subsystem isn't up yet.
- */
+ buf = ProcessTwoPhaseBuffer(xid,
+ gxact->prepare_start_lsn,
+ gxact->ondisk, false, true);
- /* Read and validate file */
- buf = ReadTwoPhaseFile(xid, true);
- if (buf == NULL)
- {
- ereport(WARNING,
- (errmsg("removing corrupt two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- continue;
- }
-
- /* Deconstruct header */
- hdr = (TwoPhaseFileHeader *) buf;
- if (!TransactionIdEquals(hdr->xid, xid))
- {
- ereport(WARNING,
- (errmsg("removing corrupt two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- pfree(buf);
- continue;
- }
+ if (buf == NULL)
+ continue;
- /*
- * OK, we think this file is valid. Incorporate xid into the
- * running-minimum result.
- */
- if (TransactionIdPrecedes(xid, result))
- result = xid;
+ /*
+ * OK, we think this file is valid. Incorporate xid into the
+ * running-minimum result.
+ */
+ if (TransactionIdPrecedes(xid, result))
+ result = xid;
- /*
- * Examine subtransaction XIDs ... they should all follow main
- * XID, and they may force us to advance nextXid.
- *
- * We don't expect anyone else to modify nextXid, hence we don't
- * need to hold a lock while examining it. We still acquire the
- * lock to modify it, though.
- */
- subxids = (TransactionId *)
- (buf + MAXALIGN(sizeof(TwoPhaseFileHeader)));
- for (i = 0; i < hdr->nsubxacts; i++)
+ if (xids_p)
+ {
+ if (nxids == allocsize)
{
- TransactionId subxid = subxids[i];
-
- Assert(TransactionIdFollows(subxid, xid));
- if (TransactionIdFollowsOrEquals(subxid,
- ShmemVariableCache->nextXid))
+ if (nxids == 0)
{
- LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
- ShmemVariableCache->nextXid = subxid;
- TransactionIdAdvance(ShmemVariableCache->nextXid);
- LWLockRelease(XidGenLock);
+ allocsize = 10;
+ xids = palloc(allocsize * sizeof(TransactionId));
}
- }
-
-
- if (xids_p)
- {
- if (nxids == allocsize)
+ else
{
- if (nxids == 0)
- {
- allocsize = 10;
- xids = palloc(allocsize * sizeof(TransactionId));
- }
- else
- {
- allocsize = allocsize * 2;
- xids = repalloc(xids, allocsize * sizeof(TransactionId));
- }
+ allocsize = allocsize * 2;
+ xids = repalloc(xids, allocsize * sizeof(TransactionId));
}
- xids[nxids++] = xid;
}
-
- pfree(buf);
+ xids[nxids++] = xid;
}
+
+ pfree(buf);
}
- FreeDir(cldir);
+ LWLockRelease(TwoPhaseStateLock);
if (xids_p)
{
@@ -1845,211 +1885,294 @@ PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
/*
* StandbyRecoverPreparedTransactions
*
- * Scan the pg_twophase directory and setup all the required information to
- * allow standby queries to treat prepared transactions as still active.
+ * Scan the shared memory entries of TwoPhaseState and setup all the required
+ * information to allow standby queries to treat prepared transactions as still
+ * active.
+ *
* This is never called at the end of recovery - we use
* RecoverPreparedTransactions() at that point.
*
- * Currently we simply call SubTransSetParent() for any subxids of prepared
- * transactions. If overwriteOK is true, it's OK if some XIDs have already
- * been marked in pg_subtrans.
+ * The lack of calls to SubTransSetParent() calls here is by design;
+ * those calls are made by RecoverPreparedTransactions() at the end of recovery
+ * for those xacts that need this.
*/
void
-StandbyRecoverPreparedTransactions(bool overwriteOK)
+StandbyRecoverPreparedTransactions(void)
{
- DIR *cldir;
- struct dirent *clde;
+ int i;
- cldir = AllocateDir(TWOPHASE_DIR);
- while ((clde = ReadDir(cldir, TWOPHASE_DIR)) != NULL)
+ LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
+ for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
{
- if (strlen(clde->d_name) == 8 &&
- strspn(clde->d_name, "0123456789ABCDEF") == 8)
- {
- TransactionId xid;
- char *buf;
- TwoPhaseFileHeader *hdr;
- TransactionId *subxids;
- int i;
-
- xid = (TransactionId) strtoul(clde->d_name, NULL, 16);
-
- /* Already processed? */
- if (TransactionIdDidCommit(xid) || TransactionIdDidAbort(xid))
- {
- ereport(WARNING,
- (errmsg("removing stale two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- continue;
- }
+ TransactionId xid;
+ char *buf;
+ GlobalTransaction gxact = TwoPhaseState->prepXacts[i];
- /* Read and validate file */
- buf = ReadTwoPhaseFile(xid, true);
- if (buf == NULL)
- {
- ereport(WARNING,
- (errmsg("removing corrupt two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- continue;
- }
+ Assert(gxact->inredo);
- /* Deconstruct header */
- hdr = (TwoPhaseFileHeader *) buf;
- if (!TransactionIdEquals(hdr->xid, xid))
- {
- ereport(WARNING,
- (errmsg("removing corrupt two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- pfree(buf);
- continue;
- }
+ xid = gxact->xid;
- /*
- * Examine subtransaction XIDs ... they should all follow main
- * XID.
- */
- subxids = (TransactionId *)
- (buf + MAXALIGN(sizeof(TwoPhaseFileHeader)));
- for (i = 0; i < hdr->nsubxacts; i++)
- {
- TransactionId subxid = subxids[i];
-
- Assert(TransactionIdFollows(subxid, xid));
- SubTransSetParent(xid, subxid, overwriteOK);
- }
- }
+ buf = ProcessTwoPhaseBuffer(xid,
+ gxact->prepare_start_lsn,
+ gxact->ondisk, false, false);
+ if (buf != NULL)
+ pfree(buf);
}
- FreeDir(cldir);
+ LWLockRelease(TwoPhaseStateLock);
}
/*
* RecoverPreparedTransactions
*
- * Scan the pg_twophase directory and reload shared-memory state for each
- * prepared transaction (reacquire locks, etc). This is run during database
- * startup.
+ * Scan the shared memory entries of TwoPhaseState and reload the state for
+ * each prepared transaction (reacquire locks, etc).
+ *
+ * This is run during database startup.
+ *
+ * At the end of recovery the way we take snapshots will change. We now need
+ * to mark all running transactions with their full SubTransSetParent() info
+ * to allow normal snapshots to work correctly if snapshots overflow.
+ * We do this here because by definition prepared transactions are the only
+ * type of write transaction still running, so this is necessary and
+ * complete.
*/
void
RecoverPreparedTransactions(void)
{
- char dir[MAXPGPATH];
- DIR *cldir;
- struct dirent *clde;
- bool overwriteOK = false;
-
- snprintf(dir, MAXPGPATH, "%s", TWOPHASE_DIR);
+ int i;
- cldir = AllocateDir(dir);
- while ((clde = ReadDir(cldir, dir)) != NULL)
+ /*
+ * Don't need a lock in the recovery phase.
+ */
+ for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
{
- if (strlen(clde->d_name) == 8 &&
- strspn(clde->d_name, "0123456789ABCDEF") == 8)
- {
- TransactionId xid;
- char *buf;
- char *bufptr;
- TwoPhaseFileHeader *hdr;
- TransactionId *subxids;
- GlobalTransaction gxact;
- const char *gid;
- int i;
+ TransactionId xid;
+ char *buf;
+ GlobalTransaction gxact = TwoPhaseState->prepXacts[i];
+ char *bufptr;
+ TwoPhaseFileHeader *hdr;
+ TransactionId *subxids;
+ const char *gid;
- xid = (TransactionId) strtoul(clde->d_name, NULL, 16);
+ xid = gxact->xid;
- /* Already processed? */
- if (TransactionIdDidCommit(xid) || TransactionIdDidAbort(xid))
- {
- ereport(WARNING,
- (errmsg("removing stale two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- continue;
- }
+ /*
+ * Reconstruct subtrans state for the transaction --- needed because
+ * pg_subtrans is not preserved over a restart. Note that we are
+ * linking all the subtransactions directly to the top-level XID;
+ * there may originally have been a more complex hierarchy, but
+ * there's no need to restore that exactly. It's possible that
+ * SubTransSetParent has been set before, if the prepared transaction
+ * generated xid assignment records.
+ */
+ buf = ProcessTwoPhaseBuffer(xid,
+ gxact->prepare_start_lsn,
+ gxact->ondisk, true, false);
+ if (buf == NULL)
+ continue;
- /* Read and validate file */
- buf = ReadTwoPhaseFile(xid, true);
- if (buf == NULL)
- {
- ereport(WARNING,
- (errmsg("removing corrupt two-phase state file \"%s\"",
- clde->d_name)));
- RemoveTwoPhaseFile(xid, true);
- continue;
- }
+ ereport(LOG,
+ (errmsg("recovering prepared transaction %u from shared memory", xid)));
+
+ hdr = (TwoPhaseFileHeader *) buf;
+ Assert(TransactionIdEquals(hdr->xid, xid));
+ bufptr = buf + MAXALIGN(sizeof(TwoPhaseFileHeader));
+ gid = (const char *) bufptr;
+ bufptr += MAXALIGN(hdr->gidlen);
+ subxids = (TransactionId *) bufptr;
+ bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId));
+ bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode));
+ bufptr += MAXALIGN(hdr->nabortrels * sizeof(RelFileNode));
+ bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
- ereport(LOG,
- (errmsg("recovering prepared transaction %u", xid)));
-
- /* Deconstruct header */
- hdr = (TwoPhaseFileHeader *) buf;
- Assert(TransactionIdEquals(hdr->xid, xid));
- bufptr = buf + MAXALIGN(sizeof(TwoPhaseFileHeader));
- gid = (const char *) bufptr;
- bufptr += MAXALIGN(hdr->gidlen);
- subxids = (TransactionId *) bufptr;
- bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId));
- bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode));
- bufptr += MAXALIGN(hdr->nabortrels * sizeof(RelFileNode));
- bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
+ /*
+ * Recreate its GXACT and dummy PGPROC. But, check whether it was
+ * added in redo and already has a shmem entry for it.
+ */
+ LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
+ MarkAsPreparingGuts(gxact, xid, gid,
+ hdr->prepared_at,
+ hdr->owner, hdr->database);
- /*
- * It's possible that SubTransSetParent has been set before, if
- * the prepared transaction generated xid assignment records. Test
- * here must match one used in AssignTransactionId().
- */
- if (InHotStandby && (hdr->nsubxacts >= PGPROC_MAX_CACHED_SUBXIDS ||
- XLogLogicalInfoActive()))
- overwriteOK = true;
+ /* recovered, so reset the flag for entries generated by redo */
+ gxact->inredo = false;
- /*
- * Reconstruct subtrans state for the transaction --- needed
- * because pg_subtrans is not preserved over a restart. Note that
- * we are linking all the subtransactions directly to the
- * top-level XID; there may originally have been a more complex
- * hierarchy, but there's no need to restore that exactly.
- */
- for (i = 0; i < hdr->nsubxacts; i++)
- SubTransSetParent(subxids[i], xid, overwriteOK);
+ LWLockRelease(TwoPhaseStateLock);
- /*
- * Recreate its GXACT and dummy PGPROC
- */
- gxact = MarkAsPreparing(xid, gid,
- hdr->prepared_at,
- hdr->owner, hdr->database);
- gxact->ondisk = true;
- GXactLoadSubxactData(gxact, hdr->nsubxacts, subxids);
- MarkAsPrepared(gxact);
+ GXactLoadSubxactData(gxact, hdr->nsubxacts, subxids);
+ MarkAsPrepared(gxact);
- /*
- * Recover other state (notably locks) using resource managers
- */
- ProcessRecords(bufptr, xid, twophase_recover_callbacks);
+ /*
+ * Recover other state (notably locks) using resource managers
+ */
+ ProcessRecords(bufptr, xid, twophase_recover_callbacks);
- /*
- * Release locks held by the standby process after we process each
- * prepared transaction. As a result, we don't need too many
- * additional locks at any one time.
- */
- if (InHotStandby)
- StandbyReleaseLockTree(xid, hdr->nsubxacts, subxids);
+ /*
+ * Release locks held by the standby process after we process each
+ * prepared transaction. As a result, we don't need too many
+ * additional locks at any one time.
+ */
+ if (InHotStandby)
+ StandbyReleaseLockTree(xid, hdr->nsubxacts, subxids);
+
+ /*
+ * We're done with recovering this transaction. Clear MyLockedGxact,
+ * like we do in PrepareTransaction() during normal operation.
+ */
+ PostPrepare_Twophase();
+
+ pfree(buf);
+ }
+}
+
+/*
+ * ProcessTwoPhaseBuffer
+ *
+ * Given a transaction id, read it either from disk or read it directly
+ * via shmem xlog record pointer using the provided "prepare_start_lsn".
+ *
+ * If setParent is true, set up subtransaction parent linkages.
+ *
+ * If setNextXid is true, set ShmemVariableCache->nextXid to the newest
+ * value scanned.
+ */
+static char *
+ProcessTwoPhaseBuffer(TransactionId xid,
+ XLogRecPtr prepare_start_lsn,
+ bool fromdisk,
+ bool setParent, bool setNextXid)
+{
+ TransactionId origNextXid = ShmemVariableCache->nextXid;
+ TransactionId *subxids;
+ char *buf;
+ TwoPhaseFileHeader *hdr;
+ int i;
+
+ if (!fromdisk)
+ Assert(prepare_start_lsn != InvalidXLogRecPtr);
+
+ /* Already processed? */
+ if (TransactionIdDidCommit(xid) || TransactionIdDidAbort(xid))
+ {
+ if (fromdisk)
+ {
+ ereport(WARNING,
+ (errmsg("removing stale two-phase state file for \"%u\"",
+ xid)));
+ RemoveTwoPhaseFile(xid, true);
+ }
+ else
+ {
+ ereport(WARNING,
+ (errmsg("removing stale two-phase state from"
+ " shared memory for \"%u\"", xid)));
+ PrepareRedoRemove(xid, true);
+ }
+ return NULL;
+ }
+
+ /* Reject XID if too new */
+ if (TransactionIdFollowsOrEquals(xid, origNextXid))
+ {
+ if (fromdisk)
+ {
+ ereport(WARNING,
+ (errmsg("removing future two-phase state file for \"%u\"",
+ xid)));
+ RemoveTwoPhaseFile(xid, true);
+ }
+ else
+ {
+ ereport(WARNING,
+ (errmsg("removing future two-phase state from memory for \"%u\"",
+ xid)));
+ PrepareRedoRemove(xid, true);
+ }
+ return NULL;
+ }
+
+ if (fromdisk)
+ {
+ /* Read and validate file */
+ buf = ReadTwoPhaseFile(xid, true);
+ if (buf == NULL)
+ {
+ ereport(WARNING,
+ (errmsg("removing corrupt two-phase state file for \"%u\"",
+ xid)));
+ RemoveTwoPhaseFile(xid, true);
+ return NULL;
+ }
+ }
+ else
+ {
+ /* Read xlog data */
+ XlogReadTwoPhaseData(prepare_start_lsn, &buf, NULL);
+ }
+
+ /* Deconstruct header */
+ hdr = (TwoPhaseFileHeader *) buf;
+ if (!TransactionIdEquals(hdr->xid, xid))
+ {
+ if (fromdisk)
+ {
+ ereport(WARNING,
+ (errmsg("removing corrupt two-phase state file for \"%u\"",
+ xid)));
+ RemoveTwoPhaseFile(xid, true);
+ }
+ else
+ {
+ ereport(WARNING,
+ (errmsg("removing corrupt two-phase state from memory for \"%u\"",
+ xid)));
+ PrepareRedoRemove(xid, true);
+ }
+ pfree(buf);
+ return NULL;
+ }
+
+ /*
+ * Examine subtransaction XIDs ... they should all follow main XID, and
+ * they may force us to advance nextXid.
+ */
+ subxids = (TransactionId *) (buf +
+ MAXALIGN(sizeof(TwoPhaseFileHeader)) +
+ MAXALIGN(hdr->gidlen));
+ for (i = 0; i < hdr->nsubxacts; i++)
+ {
+ TransactionId subxid = subxids[i];
+
+ Assert(TransactionIdFollows(subxid, xid));
+ /* update nextXid if needed */
+ if (setNextXid &&
+ TransactionIdFollowsOrEquals(subxid,
+ ShmemVariableCache->nextXid))
+ {
/*
- * We're done with recovering this transaction. Clear
- * MyLockedGxact, like we do in PrepareTransaction() during normal
- * operation.
+ * We don't expect anyone else to modify nextXid, hence we don't
+ * need to hold a lock while examining it. We still acquire the
+ * lock to modify it, though, so we recheck.
*/
- PostPrepare_Twophase();
-
- pfree(buf);
+ LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
+ if (TransactionIdFollowsOrEquals(subxid,
+ ShmemVariableCache->nextXid))
+ {
+ ShmemVariableCache->nextXid = subxid;
+ TransactionIdAdvance(ShmemVariableCache->nextXid);
+ }
+ LWLockRelease(XidGenLock);
}
+
+ if (setParent)
+ SubTransSetParent(subxid, xid);
}
- FreeDir(cldir);
+
+ return buf;
}
+
/*
* RecordTransactionCommitPrepared
*
@@ -2086,11 +2209,16 @@ RecordTransactionCommitPrepared(TransactionId xid,
/* See notes in RecordTransactionCommit */
MyPgXact->delayChkpt = true;
- /* Emit the XLOG commit record */
+ /*
+ * Emit the XLOG commit record. Note that we mark 2PC commits as
+ * potentially having AccessExclusiveLocks since we don't know whether or
+ * not they do.
+ */
recptr = XactLogCommitRecord(committs,
nchildren, children, nrels, rels,
ninvalmsgs, invalmsgs,
initfileinval, false,
+ MyXactFlags | XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK,
xid);
@@ -2123,7 +2251,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
/* Flush XLOG to disk */
XLogFlush(recptr);
- /* Mark the transaction committed in pg_clog */
+ /* Mark the transaction committed in pg_xact */
TransactionIdCommitTree(xid, nchildren, children);
/* Checkpoint can proceed now */
@@ -2167,10 +2295,15 @@ RecordTransactionAbortPrepared(TransactionId xid,
START_CRIT_SECTION();
- /* Emit the XLOG abort record */
+ /*
+ * Emit the XLOG commit record. Note that we mark 2PC aborts as
+ * potentially having AccessExclusiveLocks since we don't know whether or
+ * not they do.
+ */
recptr = XactLogAbortRecord(GetCurrentTimestamp(),
nchildren, children,
nrels, rels,
+ MyXactFlags | XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK,
xid);
/* Always flush, since we're about to remove the 2PC state file */
@@ -2192,3 +2325,113 @@ RecordTransactionAbortPrepared(TransactionId xid,
*/
SyncRepWaitForLSN(recptr, false);
}
+
+/*
+ * PrepareRedoAdd
+ *
+ * Store pointers to the start/end of the WAL record along with the xid in
+ * a gxact entry in shared memory TwoPhaseState structure. If caller
+ * specifies InvalidXLogRecPtr as WAL location to fetch the two-phase
+ * data, the entry is marked as located on disk.
+ */
+void
+PrepareRedoAdd(char *buf, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
+{
+ TwoPhaseFileHeader *hdr = (TwoPhaseFileHeader *) buf;
+ char *bufptr;
+ const char *gid;
+ GlobalTransaction gxact;
+
+ Assert(RecoveryInProgress());
+
+ bufptr = buf + MAXALIGN(sizeof(TwoPhaseFileHeader));
+ gid = (const char *) bufptr;
+
+ /*
+ * Reserve the GID for the given transaction in the redo code path.
+ *
+ * This creates a gxact struct and puts it into the active array.
+ *
+ * In redo, this struct is mainly used to track PREPARE/COMMIT entries in
+ * shared memory. Hence, we only fill up the bare minimum contents here.
+ * The gxact also gets marked with gxact->inredo set to true to indicate
+ * that it got added in the redo phase
+ */
+
+ LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
+ /* Get a free gxact from the freelist */
+ if (TwoPhaseState->freeGXacts == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("maximum number of prepared transactions reached"),
+ errhint("Increase max_prepared_transactions (currently %d).",
+ max_prepared_xacts)));
+ gxact = TwoPhaseState->freeGXacts;
+ TwoPhaseState->freeGXacts = gxact->next;
+
+ gxact->prepared_at = hdr->prepared_at;
+ gxact->prepare_start_lsn = start_lsn;
+ gxact->prepare_end_lsn = end_lsn;
+ gxact->xid = hdr->xid;
+ gxact->owner = hdr->owner;
+ gxact->locking_backend = InvalidBackendId;
+ gxact->valid = false;
+ gxact->ondisk = XLogRecPtrIsInvalid(start_lsn);
+ gxact->inredo = true; /* yes, added in redo */
+ strcpy(gxact->gid, gid);
+
+ /* And insert it into the active array */
+ Assert(TwoPhaseState->numPrepXacts < max_prepared_xacts);
+ TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts++] = gxact;
+
+ LWLockRelease(TwoPhaseStateLock);
+
+ elog(DEBUG2, "Adding 2PC data to shared memory %u", gxact->xid);
+}
+
+/*
+ * PrepareRedoRemove
+ *
+ * Remove the corresponding gxact entry from TwoPhaseState. Also
+ * remove the 2PC file if a prepared transaction was saved via
+ * an earlier checkpoint.
+ */
+void
+PrepareRedoRemove(TransactionId xid, bool giveWarning)
+{
+ GlobalTransaction gxact = NULL;
+ int i;
+ bool found = false;
+
+ Assert(RecoveryInProgress());
+
+ LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
+ for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
+ {
+ gxact = TwoPhaseState->prepXacts[i];
+
+ if (gxact->xid == xid)
+ {
+ Assert(gxact->inredo);
+ found = true;
+ break;
+ }
+ }
+ LWLockRelease(TwoPhaseStateLock);
+
+ /*
+ * Just leave if there is nothing, this is expected during WAL replay.
+ */
+ if (!found)
+ return;
+
+ /*
+ * And now we can clean up any files we may have left.
+ */
+ elog(DEBUG2, "Removing 2PC data from shared memory %u", xid);
+ if (gxact->ondisk)
+ RemoveTwoPhaseFile(xid, giveWarning);
+ RemoveGXact(gxact);
+
+ return;
+}
diff --git a/src/backend/access/transam/twophase_rmgr.c b/src/backend/access/transam/twophase_rmgr.c
index 9f56e61e54..cdcc382f34 100644
--- a/src/backend/access/transam/twophase_rmgr.c
+++ b/src/backend/access/transam/twophase_rmgr.c
@@ -3,7 +3,7 @@
* twophase_rmgr.c
* Two-phase-commit resource managers tables
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index a4e67d9fc3..d94a1deeb1 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -5,7 +5,7 @@
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
- * Copyright (c) 2000-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/access/transam/varsup.c
@@ -536,7 +536,28 @@ ReadNewTransactionId(void)
}
/*
- * Determine the last safe XID to allocate given the currently oldest
+ * Advance the cluster-wide value for the oldest valid clog entry.
+ *
+ * We must acquire CLogTruncationLock to advance the oldestClogXid. It's not
+ * necessary to hold the lock during the actual clog truncation, only when we
+ * advance the limit, as code looking up arbitrary xids is required to hold
+ * CLogTruncationLock from when it tests oldestClogXid through to when it
+ * completes the clog lookup.
+ */
+void
+AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
+{
+ LWLockAcquire(CLogTruncationLock, LW_EXCLUSIVE);
+ if (TransactionIdPrecedes(ShmemVariableCache->oldestClogXid,
+ oldest_datfrozenxid))
+ {
+ ShmemVariableCache->oldestClogXid = oldest_datfrozenxid;
+ }
+ LWLockRelease(CLogTruncationLock);
+}
+
+/*
+ * Determine the last safe XID to allocate using the currently oldest
* datfrozenxid (ie, the oldest XID that might exist in any database
* of our cluster), and the OID of the (or a) database with that value.
*/
@@ -676,7 +697,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
*
* We primarily check whether oldestXidDB is valid. The cases we have in
* mind are that that database was dropped, or the field was reset to zero
- * by pg_resetxlog. In either case we should force recalculation of the
+ * by pg_resetwal. In either case we should force recalculation of the
* wrap limit. Also do it if oldestXid is old enough to be forcing
* autovacuums or other actions; this ensures we update our state as soon
* as possible once extra overhead is being incurred.
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 049aabc209..77666c4b80 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -6,7 +6,7 @@
* See src/backend/access/transam/README for more information.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -58,9 +58,11 @@
#include "miscadmin.h"
#include "pgstat.h"
#include "replication/logical.h"
+#include "replication/logicallauncher.h"
#include "replication/origin.h"
#include "replication/syncrep.h"
#include "replication/walsender.h"
+#include "storage/condition_variable.h"
#include "storage/fd.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
@@ -131,12 +133,13 @@ int nParallelCurrentXids = 0;
TransactionId *ParallelCurrentXids;
/*
- * MyXactAccessedTempRel is set when a temporary relation is accessed.
- * We don't allow PREPARE TRANSACTION in that case. (This is global
- * so that it can be set from heapam.c.)
+ * Miscellaneous flag bits to record events which occur on the top level
+ * transaction. These flags are only persisted in MyXactFlags and are intended
+ * so we remember to do certain things later on in the transaction. This is
+ * globally accessible, so can be set from anywhere in the code that requires
+ * recording flags.
*/
-bool MyXactAccessedTempRel = false;
-
+int MyXactFlags;
/*
* transaction states - transaction state from server perspective
@@ -430,7 +433,7 @@ static void TransactionRecordXidWait_Internal(TransactionState s,
#endif
static void ShowTransactionState(const char *str);
-static void ShowTransactionStateRec(TransactionState state);
+static void ShowTransactionStateRec(const char *str, TransactionState state);
static const char *BlockStateAsString(TBlockState blockState);
static const char *TransStateAsString(TransState state);
static void PrepareTransaction(void);
@@ -693,7 +696,7 @@ AssignTransactionId(TransactionState s)
XactTopTransactionId = s->transactionId;
if (isSubXact)
- SubTransSetParent(s->transactionId, s->parent->transactionId, false);
+ SubTransSetParent(s->transactionId, s->parent->transactionId);
/*
* If it's a top-level transaction, the predicate locking system needs to
@@ -1303,9 +1306,7 @@ AtStart_Memory(void)
TopTransactionContext =
AllocSetContextCreate(TopMemoryContext,
"TopTransactionContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* In a top-level transaction, CurTransactionContext is the same as
@@ -1363,9 +1364,7 @@ AtSubStart_Memory(void)
*/
CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
"CurTransactionContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
s->curTransactionContext = CurTransactionContext;
/* Make the CurTransactionContext active. */
@@ -1495,8 +1494,8 @@ RecordTransactionCommit(void)
/*
* Mark ourselves as within our "commit critical section". This
* forces any concurrent checkpoint to wait until we've updated
- * pg_clog. Without this, it is possible for the checkpoint to set
- * REDO after the XLOG record but fail to flush the pg_clog update to
+ * pg_xact. Without this, it is possible for the checkpoint to set
+ * REDO after the XLOG record but fail to flush the pg_xact update to
* disk, leading to loss of the transaction commit if the system
* crashes a little later.
*
@@ -1518,6 +1517,7 @@ RecordTransactionCommit(void)
nchildren, children, nrels, rels,
nmsgs, invalMessages,
RelcacheInitFileInval, forceSyncCommit,
+ MyXactFlags,
InvalidTransactionId /* plain commit */ );
if (replorigin)
@@ -1885,7 +1885,7 @@ RecordTransactionAbort(bool isSubXact)
XactLogAbortRecord(xact_time,
nchildren, children,
nrels, rels,
- InvalidTransactionId);
+ MyXactFlags, InvalidTransactionId);
/*
* Report the latest async abort LSN, so that the WAL writer knows to
@@ -2158,8 +2158,8 @@ StartTransaction(void)
#endif
XactIsoLevel = DefaultXactIsoLevel;
forceSyncCommit = false;
- MyXactAccessedTempRel = false;
XactLocalNodePrepared = false;
+ MyXactFlags = 0;
/*
* reinitialize within-transaction counters
@@ -2498,7 +2498,7 @@ CommitTransaction(void)
if (!is_parallel_worker)
{
/*
- * We need to mark our XIDs as committed in pg_clog. This is where we
+ * We need to mark our XIDs as committed in pg_xact. This is where we
* durably commit.
*/
#ifdef XCP
@@ -2636,7 +2636,8 @@ CommitTransaction(void)
AtEOXact_ComboCid();
AtEOXact_HashTables(true);
AtEOXact_PgStat(true);
- AtEOXact_Snapshot(true);
+ AtEOXact_Snapshot(true, false);
+ AtEOXact_ApplyLauncher(true);
pgstat_report_xact_timestamp(0);
CurrentResourceOwner = NULL;
@@ -2896,7 +2897,7 @@ PrepareTransaction(void)
* cases, such as a temp table created and dropped all within the
* transaction. That seems to require much more bookkeeping though.
*/
- if (MyXactAccessedTempRel)
+ if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPREL))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
@@ -3048,7 +3049,7 @@ PrepareTransaction(void)
AtEOXact_ComboCid();
AtEOXact_HashTables(true);
/* don't call AtEOXact_PgStat here; we fixed pgstat state above */
- AtEOXact_Snapshot(true);
+ AtEOXact_Snapshot(true, true);
pgstat_report_xact_timestamp(0);
CurrentResourceOwner = NULL;
@@ -3209,6 +3210,9 @@ AbortTransaction(void)
/* Reset WAL record construction state */
XLogResetInsertion();
+ /* Cancel condition variable sleep */
+ ConditionVariableCancelSleep();
+
/*
* Also clean up any open wait for lock, since the lock manager will choke
* if we try to wait for another lock before doing this.
@@ -3276,7 +3280,7 @@ AbortTransaction(void)
AtAbort_Twophase();
/*
- * Advertise the fact that we aborted in pg_clog (assuming that we got as
+ * Advertise the fact that we aborted in pg_xact (assuming that we got as
* far as assigning an XID to advertise). But if we're inside a parallel
* worker, skip this; the user backend must be the one to write the abort
* record.
@@ -3354,6 +3358,7 @@ AbortTransaction(void)
AtEOXact_ComboCid();
AtEOXact_HashTables(false);
AtEOXact_PgStat(false);
+ AtEOXact_ApplyLauncher(false);
pgstat_report_xact_timestamp(0);
}
@@ -3391,7 +3396,8 @@ CleanupTransaction(void)
* do abort cleanup processing
*/
AtCleanup_Portals(); /* now safe to release portal memory */
- AtEOXact_Snapshot(false); /* and release the transaction's snapshots */
+ AtEOXact_Snapshot(false, true); /* and release the transaction's
+ * snapshots */
CurrentResourceOwner = NULL; /* and resource owner */
if (TopTransactionResourceOwner)
@@ -3527,7 +3533,7 @@ CommitTransactionCommand(void)
* These shouldn't happen. TBLOCK_DEFAULT means the previous
* StartTransactionCommand didn't set the STARTED state
* appropriately, while TBLOCK_PARALLEL_INPROGRESS should be ended
- * by EndParallelWorkerTranaction(), not this function.
+ * by EndParallelWorkerTransaction(), not this function.
*/
case TBLOCK_DEFAULT:
case TBLOCK_PARALLEL_INPROGRESS:
@@ -5490,7 +5496,7 @@ AbortSubTransaction(void)
s->parent->subTransactionId);
AtSubAbort_Notify();
- /* Advertise the fact that we aborted in pg_clog. */
+ /* Advertise the fact that we aborted in pg_xact. */
(void) RecordTransactionAbort(true);
/* Post-abort cleanup */
@@ -5812,11 +5818,8 @@ static void
ShowTransactionState(const char *str)
{
/* skip work if message will definitely not be printed */
- if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
- {
- elog(DEBUG3, "%s", str);
- ShowTransactionStateRec(CurrentTransactionState);
- }
+ if (log_min_messages <= DEBUG5 || client_min_messages <= DEBUG5)
+ ShowTransactionStateRec(str, CurrentTransactionState);
}
/*
@@ -5824,7 +5827,7 @@ ShowTransactionState(const char *str)
* Recursive subroutine for ShowTransactionState
*/
static void
-ShowTransactionStateRec(TransactionState s)
+ShowTransactionStateRec(const char *str, TransactionState s)
{
StringInfoData buf;
@@ -5834,17 +5837,18 @@ ShowTransactionStateRec(TransactionState s)
{
int i;
- appendStringInfo(&buf, "%u", s->childXids[0]);
+ appendStringInfo(&buf, ", children: %u", s->childXids[0]);
for (i = 1; i < s->nChildXids; i++)
appendStringInfo(&buf, " %u", s->childXids[i]);
}
if (s->parent)
- ShowTransactionStateRec(s->parent);
+ ShowTransactionStateRec(str, s->parent);
/* use ereport to suppress computation if msg will not be printed */
- ereport(DEBUG3,
- (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
+ ereport(DEBUG5,
+ (errmsg_internal("%s(%d) name: %s; blockState: %s; state: %s, xid/subid/cid: %u/%u/%u%s%s",
+ str, s->nestingLevel,
PointerIsValid(s->name) ? s->name : "unnamed",
BlockStateAsString(s->blockState),
TransStateAsString(s->state),
@@ -5852,7 +5856,7 @@ ShowTransactionStateRec(TransactionState s)
(unsigned int) s->subTransactionId,
(unsigned int) currentCommandId,
currentCommandIdUsed ? " (used)" : "",
- s->nestingLevel, buf.data)));
+ buf.data)));
pfree(buf.data);
}
@@ -5972,7 +5976,7 @@ XactLogCommitRecord(TimestampTz commit_time,
int nrels, RelFileNode *rels,
int nmsgs, SharedInvalidationMessage *msgs,
bool relcacheInval, bool forceSync,
- TransactionId twophase_xid)
+ int xactflags, TransactionId twophase_xid)
{
xl_xact_commit xlrec;
xl_xact_xinfo xl_xinfo;
@@ -6003,6 +6007,8 @@ XactLogCommitRecord(TimestampTz commit_time,
xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
if (forceSyncCommit)
xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
+ if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
+ xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
/*
* Check if the caller would like to ask standbys for immediate feedback
@@ -6100,7 +6106,7 @@ XactLogCommitRecord(TimestampTz commit_time,
XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
/* we allow filtering by xacts */
- XLogIncludeOrigin();
+ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
return XLogInsert(RM_XACT_ID, info);
}
@@ -6115,7 +6121,7 @@ XLogRecPtr
XactLogAbortRecord(TimestampTz abort_time,
int nsubxacts, TransactionId *subxacts,
int nrels, RelFileNode *rels,
- TransactionId twophase_xid)
+ int xactflags, TransactionId twophase_xid)
{
xl_xact_abort xlrec;
xl_xact_xinfo xl_xinfo;
@@ -6140,6 +6146,9 @@ XactLogAbortRecord(TimestampTz abort_time,
xlrec.xact_time = abort_time;
+ if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
+ xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
+
if (nsubxacts > 0)
{
xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
@@ -6239,7 +6248,7 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
if (standbyState == STANDBY_DISABLED)
{
/*
- * Mark the transaction committed in pg_clog.
+ * Mark the transaction committed in pg_xact.
*/
TransactionIdCommitTree(xid, parsed->nsubxacts, parsed->subxacts);
}
@@ -6257,7 +6266,7 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
RecordKnownAssignedTransactionIds(max_xid);
/*
- * Mark the transaction committed in pg_clog. We use async commit
+ * Mark the transaction committed in pg_xact. We use async commit
* protocol during recovery to provide information on database
* consistency for when users try to set hint bits. It is important
* that we do not set hint bits until the minRecoveryPoint is past
@@ -6291,7 +6300,8 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
* via their top-level xid only, so no need to provide subxact list,
* which will save time when replaying commits.
*/
- StandbyReleaseLockTree(xid, 0, NULL);
+ if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
+ StandbyReleaseLockTree(xid, 0, NULL);
}
if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
@@ -6394,7 +6404,7 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
if (standbyState == STANDBY_DISABLED)
{
- /* Mark the transaction aborted in pg_clog, no need for async stuff */
+ /* Mark the transaction aborted in pg_xact, no need for async stuff */
TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
}
else
@@ -6410,7 +6420,7 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
*/
RecordKnownAssignedTransactionIds(max_xid);
- /* Mark the transaction aborted in pg_clog, no need for async stuff */
+ /* Mark the transaction aborted in pg_xact, no need for async stuff */
TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
/*
@@ -6427,7 +6437,8 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
/*
* Release locks, if any. There are no invalidations to send.
*/
- StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
+ if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
+ StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
}
/* Make sure files supposed to be dropped are dropped */
@@ -6470,7 +6481,9 @@ xact_redo(XLogReaderState *record)
Assert(TransactionIdIsValid(parsed.twophase_xid));
xact_redo_commit(&parsed, parsed.twophase_xid,
record->EndRecPtr, XLogRecGetOrigin(record));
- RemoveTwoPhaseFile(parsed.twophase_xid, false);
+
+ /* Delete TwoPhaseState gxact entry and/or 2PC file. */
+ PrepareRedoRemove(parsed.twophase_xid, false);
}
}
else if (info == XLOG_XACT_ABORT || info == XLOG_XACT_ABORT_PREPARED)
@@ -6490,14 +6503,20 @@ xact_redo(XLogReaderState *record)
{
Assert(TransactionIdIsValid(parsed.twophase_xid));
xact_redo_abort(&parsed, parsed.twophase_xid);
- RemoveTwoPhaseFile(parsed.twophase_xid, false);
+
+ /* Delete TwoPhaseState gxact entry and/or 2PC file. */
+ PrepareRedoRemove(parsed.twophase_xid, false);
}
}
else if (info == XLOG_XACT_PREPARE)
{
- /* the record contents are exactly the 2PC file */
- RecreateTwoPhaseFile(XLogRecGetXid(record),
- XLogRecGetData(record), XLogRecGetDataLen(record));
+ /*
+ * Store xid and start/end pointers of the WAL record in TwoPhaseState
+ * gxact entry.
+ */
+ PrepareRedoAdd(XLogRecGetData(record),
+ record->ReadRecPtr,
+ record->EndRecPtr);
}
else if (info == XLOG_XACT_ASSIGNMENT)
{
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 19b4921075..b29f283e6a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -1,10 +1,10 @@
/*-------------------------------------------------------------------------
*
* xlog.c
- * PostgreSQL transaction log manager
+ * PostgreSQL write-ahead log manager
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/xlog.c
@@ -15,6 +15,7 @@
#include "postgres.h"
#include <ctype.h>
+#include <math.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -44,6 +45,7 @@
#include "pgxc/barrier.h"
#endif
#include "pgstat.h"
+#include "port/atomics.h"
#include "postmaster/bgwriter.h"
#include "postmaster/walwriter.h"
#include "postmaster/startup.h"
@@ -54,7 +56,6 @@
#include "replication/snapbuild.h"
#include "replication/walreceiver.h"
#include "replication/walsender.h"
-#include "storage/barrier.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
@@ -67,9 +68,11 @@
#include "storage/reinit.h"
#include "storage/smgr.h"
#include "storage/spin.h"
+#include "utils/backend_random.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
+#include "utils/pg_lsn.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
#include "utils/snapmgr.h"
@@ -86,8 +89,8 @@ extern uint32 bootstrap_data_checksum_version;
/* User-settable parameters */
-int max_wal_size = 64; /* 1 GB */
-int min_wal_size = 5; /* 80 MB */
+int max_wal_size_mb = 1024; /* 1 GB */
+int min_wal_size_mb = 80; /* 80 MB */
int wal_keep_segments = 0;
int XLOGbuffers = -1;
int XLogArchiveTimeout = 0;
@@ -97,6 +100,8 @@ bool EnableHotStandby = false;
bool fullPageWrites = true;
bool wal_log_hints = false;
bool wal_compression = false;
+char *wal_consistency_checking_string = NULL;
+bool *wal_consistency_checking = NULL;
bool log_checkpoints = false;
int sync_method = DEFAULT_SYNC_METHOD;
int wal_level = WAL_LEVEL_MINIMAL;
@@ -237,9 +242,9 @@ static int LocalXLogInsertAllowed = -1;
* valid in the startup process.
*
* When ArchiveRecoveryRequested is true, but InArchiveRecovery is false, we're
- * currently performing crash recovery using only XLOG files in pg_xlog, but
+ * currently performing crash recovery using only XLOG files in pg_wal, but
* will switch to using offline XLOG archives as soon as we reach the end of
- * WAL in pg_xlog.
+ * WAL in pg_wal.
*/
bool ArchiveRecoveryRequested = false;
bool InArchiveRecovery = false;
@@ -247,6 +252,10 @@ bool InArchiveRecovery = false;
/* Was the last xlog file restored from archive, or local? */
static bool restoredFromArchive = false;
+/* Buffers dedicated to consistency checks of size BLCKSZ */
+static char *replay_image_masked = NULL;
+static char *master_image_masked = NULL;
+
/* options taken from recovery.conf for archive recovery */
char *recoveryRestoreCommand = NULL;
static char *recoveryEndCommand = NULL;
@@ -258,6 +267,7 @@ static TransactionId recoveryTargetXid;
static TimestampTz recoveryTargetTime;
static char *recoveryTargetBarrierId;
static char *recoveryTargetName;
+static XLogRecPtr recoveryTargetLSN;
static int recovery_min_apply_delay = 0;
static TimestampTz recoveryDelayUntilTime;
@@ -279,6 +289,7 @@ static bool fast_promote = false;
*/
static TransactionId recoveryStopXid;
static TimestampTz recoveryStopTime;
+static XLogRecPtr recoveryStopLSN;
static char recoveryStopName[MAXFNAMELEN];
static bool recoveryStopAfter;
@@ -443,11 +454,21 @@ typedef struct XLogwrtResult
* the WAL record is just copied to the page and the lock is released. But
* to avoid the deadlock-scenario explained above, the indicator is always
* updated before sleeping while holding an insertion lock.
+ *
+ * lastImportantAt contains the LSN of the last important WAL record inserted
+ * using a given lock. This value is used to detect if there has been
+ * important WAL activity since the last time some action, like a checkpoint,
+ * was performed - allowing to not repeat the action if not. The LSN is
+ * updated for all insertions, unless the XLOG_MARK_UNIMPORTANT flag was
+ * set. lastImportantAt is never cleared, only overwritten by the LSN of newer
+ * records. Tracking the WAL activity directly in WALInsertLock has the
+ * advantage of not needing any additional locks to update the value.
*/
typedef struct
{
LWLock lock;
XLogRecPtr insertingAt;
+ XLogRecPtr lastImportantAt;
} WALInsertLock;
/*
@@ -464,6 +485,35 @@ typedef union WALInsertLockPadded
} WALInsertLockPadded;
/*
+ * State of an exclusive backup, necessary to control concurrent activities
+ * across sessions when working on exclusive backups.
+ *
+ * EXCLUSIVE_BACKUP_NONE means that there is no exclusive backup actually
+ * running, to be more precise pg_start_backup() is not being executed for
+ * an exclusive backup and there is no exclusive backup in progress.
+ * EXCLUSIVE_BACKUP_STARTING means that pg_start_backup() is starting an
+ * exclusive backup.
+ * EXCLUSIVE_BACKUP_IN_PROGRESS means that pg_start_backup() has finished
+ * running and an exclusive backup is in progress. pg_stop_backup() is
+ * needed to finish it.
+ * EXCLUSIVE_BACKUP_STOPPING means that pg_stop_backup() is stopping an
+ * exclusive backup.
+ */
+typedef enum ExclusiveBackupState
+{
+ EXCLUSIVE_BACKUP_NONE = 0,
+ EXCLUSIVE_BACKUP_STARTING,
+ EXCLUSIVE_BACKUP_IN_PROGRESS,
+ EXCLUSIVE_BACKUP_STOPPING
+} ExclusiveBackupState;
+
+/*
+ * Session status of running backup, used for sanity checks in SQL-callable
+ * functions to start and stop backups.
+ */
+static SessionBackupState sessionBackupState = SESSION_BACKUP_NONE;
+
+/*
* Shared state data for WAL insertion.
*/
typedef struct XLogCtlInsert
@@ -504,13 +554,14 @@ typedef struct XLogCtlInsert
bool fullPageWrites;
/*
- * exclusiveBackup is true if a backup started with pg_start_backup() is
- * in progress, and nonExclusiveBackups is a counter indicating the number
- * of streaming base backups currently in progress. forcePageWrites is set
- * to true when either of these is non-zero. lastBackupStart is the latest
- * checkpoint redo location used as a starting point for an online backup.
+ * exclusiveBackupState indicates the state of an exclusive backup (see
+ * comments of ExclusiveBackupState for more details). nonExclusiveBackups
+ * is a counter indicating the number of streaming base backups currently
+ * in progress. forcePageWrites is set to true when either of these is
+ * non-zero. lastBackupStart is the latest checkpoint redo location used
+ * as a starting point for an online backup.
*/
- bool exclusiveBackup;
+ ExclusiveBackupState exclusiveBackupState;
int nonExclusiveBackups;
XLogRecPtr lastBackupStart;
@@ -518,7 +569,6 @@ typedef struct XLogCtlInsert
* WAL insertion locks.
*/
WALInsertLockPadded *WALInsertLocks;
- LWLockTranche WALInsertLockTranche;
} XLogCtlInsert;
/*
@@ -543,8 +593,9 @@ typedef struct XLogCtlData
XLogRecPtr unloggedLSN;
slock_t ulsn_lck;
- /* Time of last xlog segment switch. Protected by WALWriteLock. */
+ /* Time and LSN of last xlog segment switch. Protected by WALWriteLock. */
pg_time_t lastSegSwitchTime;
+ XLogRecPtr lastSegSwitchLSN;
/*
* Protected by info_lck and WALWriteLock (you must hold either lock to
@@ -616,11 +667,14 @@ typedef struct XLogCtlData
/*
* During recovery, we keep a copy of the latest checkpoint record here.
- * Used by the background writer when it wants to create a restartpoint.
+ * lastCheckPointRecPtr points to start of checkpoint record and
+ * lastCheckPointEndPtr points to end+1 of checkpoint record. Used by the
+ * checkpointer when it wants to create a restartpoint.
*
* Protected by info_lck.
*/
XLogRecPtr lastCheckPointRecPtr;
+ XLogRecPtr lastCheckPointEndPtr;
CheckPoint lastCheckPoint;
/*
@@ -687,6 +741,10 @@ static ControlFileData *ControlFile = NULL;
#define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)
#define UsableBytesInSegment ((XLOG_SEG_SIZE / XLOG_BLCKSZ) * UsableBytesInPage - (SizeOfXLogLongPHD - SizeOfXLogShortPHD))
+/* Convert min_wal_size_mb and max wal_size_mb to equivalent segment count */
+#define ConvertToXSegs(x) \
+ (x / (XLOG_SEG_SIZE / (1024 * 1024)))
+
/*
* Private, possibly out-of-date copy of shared LogwrtResult.
* See discussion above.
@@ -701,12 +759,12 @@ typedef enum
{
XLOG_FROM_ANY = 0, /* request to read WAL from any source */
XLOG_FROM_ARCHIVE, /* restored using restore_command */
- XLOG_FROM_PG_XLOG, /* existing file in pg_xlog */
+ XLOG_FROM_PG_WAL, /* existing file in pg_wal */
XLOG_FROM_STREAM /* streamed from master */
} XLogSource;
/* human-readable names for XLogSources, for debugging output */
-static const char *xlogSourceNames[] = {"any", "archive", "pg_xlog", "stream"};
+static const char *xlogSourceNames[] = {"any", "archive", "pg_wal", "stream"};
/*
* openLogFile is -1 or a kernel FD for an open log file segment.
@@ -814,7 +872,7 @@ static bool InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
bool find_free, XLogSegNo max_segno,
bool use_lock);
static int XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
- int source, bool notexistOk);
+ int source, bool notfoundOk);
static int XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source);
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
int reqLen, XLogRecPtr targetRecPtr, char *readBuf,
@@ -846,6 +904,7 @@ static void xlog_outrec(StringInfo buf, XLogReaderState *record);
#endif
static void xlog_outdesc(StringInfo buf, XLogReaderState *record);
static void pg_start_backup_callback(int code, Datum arg);
+static void pg_stop_backup_callback(int code, Datum arg);
static bool read_backup_label(XLogRecPtr *checkPointLoc,
bool *backupEndRequired, bool *backupFromStandby);
static bool read_tablespace_map(List **tablespaces);
@@ -865,6 +924,7 @@ static char *GetXLogBuffer(XLogRecPtr ptr);
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos);
static XLogRecPtr XLogBytePosToEndRecPtr(uint64 bytepos);
static uint64 XLogRecPtrToBytePos(XLogRecPtr ptr);
+static void checkXLogConsistency(XLogReaderState *record);
static void WALInsertLockAcquire(void);
static void WALInsertLockAcquireExclusive(void);
@@ -883,6 +943,9 @@ static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
* which pages need a full-page image, and retry. If fpw_lsn is invalid, the
* record is always inserted.
*
+ * 'flags' gives more in-depth control on the record being inserted. See
+ * XLogSetRecordFlags() for details.
+ *
* The first XLogRecData in the chain must be for the record header, and its
* data must be MAXALIGNed. XLogInsertRecord fills in the xl_prev and
* xl_crc fields in the header, the rest of the header must already be filled
@@ -895,14 +958,17 @@ static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
* WAL rule "write the log before the data".)
*/
XLogRecPtr
-XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn)
+XLogInsertRecord(XLogRecData *rdata,
+ XLogRecPtr fpw_lsn,
+ uint8 flags)
{
XLogCtlInsert *Insert = &XLogCtl->Insert;
pg_crc32c rdata_crc;
bool inserted;
XLogRecord *rechdr = (XLogRecord *) rdata->data;
+ uint8 info = rechdr->xl_info & ~XLR_INFO_MASK;
bool isLogSwitch = (rechdr->xl_rmid == RM_XLOG_ID &&
- rechdr->xl_info == XLOG_SWITCH);
+ info == XLOG_SWITCH);
XLogRecPtr StartPos;
XLogRecPtr EndPos;
@@ -1011,6 +1077,18 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn)
*/
CopyXLogRecordToWAL(rechdr->xl_tot_len, isLogSwitch, rdata,
StartPos, EndPos);
+
+ /*
+ * Unless record is flagged as not important, update LSN of last
+ * important record in the current slot. When holding all locks, just
+ * update the first one.
+ */
+ if ((flags & XLOG_MARK_UNIMPORTANT) == 0)
+ {
+ int lockno = holdingAllLocks ? 0 : MyLockNo;
+
+ WALInsertLocks[lockno].l.lastImportantAt = StartPos;
+ }
}
else
{
@@ -1051,7 +1129,7 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn)
*/
if (isLogSwitch)
{
- TRACE_POSTGRESQL_XLOG_SWITCH();
+ TRACE_POSTGRESQL_WAL_SWITCH();
XLogFlush(EndPos);
/*
@@ -1259,6 +1337,114 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
}
/*
+ * Checks whether the current buffer page and backup page stored in the
+ * WAL record are consistent or not. Before comparing the two pages, a
+ * masking can be applied to the pages to ignore certain areas like hint bits,
+ * unused space between pd_lower and pd_upper among other things. This
+ * function should be called once WAL replay has been completed for a
+ * given record.
+ */
+static void
+checkXLogConsistency(XLogReaderState *record)
+{
+ RmgrId rmid = XLogRecGetRmid(record);
+ RelFileNode rnode;
+ ForkNumber forknum;
+ BlockNumber blkno;
+ int block_id;
+
+ /* Records with no backup blocks have no need for consistency checks. */
+ if (!XLogRecHasAnyBlockRefs(record))
+ return;
+
+ Assert((XLogRecGetInfo(record) & XLR_CHECK_CONSISTENCY) != 0);
+
+ for (block_id = 0; block_id <= record->max_block_id; block_id++)
+ {
+ Buffer buf;
+ Page page;
+
+ if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
+ {
+ /*
+ * WAL record doesn't contain a block reference with the given id.
+ * Do nothing.
+ */
+ continue;
+ }
+
+ Assert(XLogRecHasBlockImage(record, block_id));
+
+ if (XLogRecBlockImageApply(record, block_id))
+ {
+ /*
+ * WAL record has already applied the page, so bypass the
+ * consistency check as that would result in comparing the full
+ * page stored in the record with itself.
+ */
+ continue;
+ }
+
+ /*
+ * Read the contents from the current buffer and store it in a
+ * temporary page.
+ */
+ buf = XLogReadBufferExtended(rnode, forknum, blkno,
+ RBM_NORMAL_NO_LOG);
+ if (!BufferIsValid(buf))
+ continue;
+
+ LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
+ page = BufferGetPage(buf);
+
+ /*
+ * Take a copy of the local page where WAL has been applied to have a
+ * comparison base before masking it...
+ */
+ memcpy(replay_image_masked, page, BLCKSZ);
+
+ /* No need for this page anymore now that a copy is in. */
+ UnlockReleaseBuffer(buf);
+
+ /*
+ * If the block LSN is already ahead of this WAL record, we can't
+ * expect contents to match. This can happen if recovery is
+ * restarted.
+ */
+ if (PageGetLSN(replay_image_masked) > record->EndRecPtr)
+ continue;
+
+ /*
+ * Read the contents from the backup copy, stored in WAL record and
+ * store it in a temporary page. There is no need to allocate a new
+ * page here, a local buffer is fine to hold its contents and a mask
+ * can be directly applied on it.
+ */
+ if (!RestoreBlockImage(record, block_id, master_image_masked))
+ elog(ERROR, "failed to restore block image");
+
+ /*
+ * If masking function is defined, mask both the master and replay
+ * images
+ */
+ if (RmgrTable[rmid].rm_mask != NULL)
+ {
+ RmgrTable[rmid].rm_mask(replay_image_masked, blkno);
+ RmgrTable[rmid].rm_mask(master_image_masked, blkno);
+ }
+
+ /* Time to compare the master and replay images. */
+ if (memcmp(replay_image_masked, master_image_masked, BLCKSZ) != 0)
+ {
+ elog(FATAL,
+ "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
+ rnode.spcNode, rnode.dbNode, rnode.relNode,
+ forknum, blkno);
+ }
+ }
+}
+
+/*
* Subroutine of XLogInsertRecord. Copies a WAL record to an already-reserved
* area in the WAL.
*/
@@ -2022,7 +2208,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
}
/*
- * Calculate CheckPointSegments based on max_wal_size and
+ * Calculate CheckPointSegments based on max_wal_size_mb and
* checkpoint_completion_target.
*/
static void
@@ -2032,14 +2218,14 @@ CalculateCheckpointSegments(void)
/*-------
* Calculate the distance at which to trigger a checkpoint, to avoid
- * exceeding max_wal_size. This is based on two assumptions:
+ * exceeding max_wal_size_mb. This is based on two assumptions:
*
* a) we keep WAL for two checkpoint cycles, back to the "prev" checkpoint.
* b) during checkpoint, we consume checkpoint_completion_target *
* number of segments consumed between checkpoints.
*-------
*/
- target = (double) max_wal_size / (2.0 + CheckPointCompletionTarget);
+ target = (double) ConvertToXSegs(max_wal_size_mb) / (2.0 + CheckPointCompletionTarget);
/* round down */
CheckPointSegments = (int) target;
@@ -2051,7 +2237,7 @@ CalculateCheckpointSegments(void)
void
assign_max_wal_size(int newval, void *extra)
{
- max_wal_size = newval;
+ max_wal_size_mb = newval;
CalculateCheckpointSegments();
}
@@ -2075,12 +2261,12 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
XLogSegNo recycleSegNo;
/*
- * Calculate the segment numbers that min_wal_size and max_wal_size
+ * Calculate the segment numbers that min_wal_size_mb and max_wal_size_mb
* correspond to. Always recycle enough segments to meet the minimum, and
* remove enough segments to stay below the maximum.
*/
- minSegNo = PriorRedoPtr / XLOG_SEG_SIZE + min_wal_size - 1;
- maxSegNo = PriorRedoPtr / XLOG_SEG_SIZE + max_wal_size - 1;
+ minSegNo = PriorRedoPtr / XLOG_SEG_SIZE + ConvertToXSegs(min_wal_size_mb) - 1;
+ maxSegNo = PriorRedoPtr / XLOG_SEG_SIZE + ConvertToXSegs(max_wal_size_mb) - 1;
/*
* Between those limits, recycle enough segments to get us through to the
@@ -2284,7 +2470,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
do
{
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE);
written = write(openLogFile, from, nleft);
+ pgstat_report_wait_end();
if (written <= 0)
{
if (errno == EINTR)
@@ -2330,6 +2518,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
XLogArchiveNotifySeg(openLogSegNo);
XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
+ XLogCtl->lastSegSwitchLSN = LogwrtResult.Flush;
/*
* Request a checkpoint if we've consumed too much xlog since
@@ -2756,7 +2945,7 @@ XLogFlush(XLogRecPtr record)
* This routine is invoked periodically by the background walwriter process.
*
* Returns TRUE if there was any work to do, even if we skipped flushing due
- * to wal_writer_delay/wal_flush_after.
+ * to wal_writer_delay/wal_writer_flush_after.
*/
bool
XLogBackgroundFlush(void)
@@ -3034,6 +3223,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
{
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE);
if ((int) write(fd, zbuffer, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ)
{
int save_errno = errno;
@@ -3052,8 +3242,10 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m", tmppath)));
}
+ pgstat_report_wait_end();
}
+ pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC);
if (pg_fsync(fd) != 0)
{
close(fd);
@@ -3061,6 +3253,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", tmppath)));
}
+ pgstat_report_wait_end();
if (close(fd))
ereport(ERROR,
@@ -3187,6 +3380,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
if (nread > sizeof(buffer))
nread = sizeof(buffer);
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_READ);
if (read(srcfd, buffer, nread) != nread)
{
if (errno != 0)
@@ -3199,8 +3393,10 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
(errmsg("not enough data in file \"%s\"",
path)));
}
+ pgstat_report_wait_end();
}
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_WRITE);
if ((int) write(fd, buffer, sizeof(buffer)) != (int) sizeof(buffer))
{
int save_errno = errno;
@@ -3216,12 +3412,15 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m", tmppath)));
}
+ pgstat_report_wait_end();
}
+ pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_SYNC);
if (pg_fsync(fd) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", tmppath)));
+ pgstat_report_wait_end();
if (CloseTransientFile(fd))
ereport(ERROR,
@@ -3284,7 +3483,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
if (!find_free)
{
/* Force installation: get rid of any pre-existing segment file */
- unlink(path);
+ durable_unlink(path, DEBUG1);
}
else
{
@@ -3337,7 +3536,7 @@ XLogFileOpen(XLogSegNo segno)
if (fd < 0)
ereport(PANIC,
(errcode_for_file_access(),
- errmsg("could not open transaction log file \"%s\": %m", path)));
+ errmsg("could not open write-ahead log file \"%s\": %m", path)));
return fd;
}
@@ -3346,7 +3545,7 @@ XLogFileOpen(XLogSegNo segno)
* Open a logfile segment for reading (during recovery).
*
* If source == XLOG_FROM_ARCHIVE, the segment is retrieved from archive.
- * Otherwise, it's assumed to be already available in pg_xlog.
+ * Otherwise, it's assumed to be already available in pg_wal.
*/
static int
XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
@@ -3375,7 +3574,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
return -1;
break;
- case XLOG_FROM_PG_XLOG:
+ case XLOG_FROM_PG_WAL:
case XLOG_FROM_STREAM:
XLogFilePath(path, tli, segno);
restoredFromArchive = false;
@@ -3394,7 +3593,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
KeepFileRestoredFromArchive(path, xlogfname);
/*
- * Set path to point at the new file in pg_xlog.
+ * Set path to point at the new file in pg_wal.
*/
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
}
@@ -3482,10 +3681,10 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source)
}
}
- if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_XLOG)
+ if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_WAL)
{
fd = XLogFileRead(segno, emode, tli,
- XLOG_FROM_PG_XLOG, true);
+ XLOG_FROM_PG_WAL, true);
if (fd != -1)
{
if (!expectedTLEs)
@@ -3643,7 +3842,7 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
if (xldir == NULL)
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not open transaction log directory \"%s\": %m",
+ errmsg("could not open write-ahead log directory \"%s\": %m",
XLOGDIR)));
/*
@@ -3694,10 +3893,10 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
*
* This is called during recovery, whenever we switch to follow a new
* timeline, and at the end of recovery when we create a new timeline. We
- * wouldn't otherwise care about extra WAL files lying in pg_xlog, but they
+ * wouldn't otherwise care about extra WAL files lying in pg_wal, but they
* might be leftover pre-allocated or recycled WAL segments on the old timeline
* that we haven't used yet, and contain garbage. If we just leave them in
- * pg_xlog, they will eventually be archived, and we can't let that happen.
+ * pg_wal, they will eventually be archived, and we can't let that happen.
* Files that belong to our timeline history are valid, because we have
* successfully replayed them, but from others we can't be sure.
*
@@ -3718,7 +3917,7 @@ RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
if (xldir == NULL)
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not open transaction log directory \"%s\": %m",
+ errmsg("could not open write-ahead log directory \"%s\": %m",
XLOGDIR)));
/*
@@ -3799,7 +3998,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
true, recycleSegNo, true))
{
ereport(DEBUG2,
- (errmsg("recycled transaction log file \"%s\"",
+ (errmsg("recycled write-ahead log file \"%s\"",
segname)));
CheckpointStats.ckpt_segs_recycled++;
/* Needn't recheck that slot on future iterations */
@@ -3811,7 +4010,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
int rc;
ereport(DEBUG2,
- (errmsg("removing transaction log file \"%s\"",
+ (errmsg("removing write-ahead log file \"%s\"",
segname)));
#ifdef WIN32
@@ -3831,20 +4030,17 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
{
ereport(LOG,
(errcode_for_file_access(),
- errmsg("could not rename old transaction log file \"%s\": %m",
+ errmsg("could not rename old write-ahead log file \"%s\": %m",
path)));
return;
}
- rc = unlink(newpath);
+ rc = durable_unlink(newpath, LOG);
#else
- rc = unlink(path);
+ rc = durable_unlink(path, LOG);
#endif
if (rc != 0)
{
- ereport(LOG,
- (errcode_for_file_access(),
- errmsg("could not remove old transaction log file \"%s\": %m",
- path)));
+ /* Message already logged by durable_unlink() */
return;
}
CheckpointStats.ckpt_segs_removed++;
@@ -3854,15 +4050,15 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
}
/*
- * Verify whether pg_xlog and pg_xlog/archive_status exist.
+ * Verify whether pg_wal and pg_wal/archive_status exist.
* If the latter does not exist, recreate it.
*
* It is not the goal of this function to verify the contents of these
* directories, but to help in cases where someone has performed a cluster
- * copy for PITR purposes but omitted pg_xlog from the copy.
+ * copy for PITR purposes but omitted pg_wal from the copy.
*
- * We could also recreate pg_xlog if it doesn't exist, but a deliberate
- * policy decision was made not to. It is fairly common for pg_xlog to be
+ * We could also recreate pg_wal if it doesn't exist, but a deliberate
+ * policy decision was made not to. It is fairly common for pg_wal to be
* a symlink, and if that was the DBA's intent then automatically making a
* plain directory would result in degraded performance with no notice.
*/
@@ -3872,7 +4068,7 @@ ValidateXLOGDirectoryStructure(void)
char path[MAXPGPATH];
struct stat stat_buf;
- /* Check for pg_xlog; if it doesn't exist, error out */
+ /* Check for pg_wal; if it doesn't exist, error out */
if (stat(XLOGDIR, &stat_buf) != 0 ||
!S_ISDIR(stat_buf.st_mode))
ereport(FATAL,
@@ -3910,13 +4106,13 @@ CleanupBackupHistory(void)
{
DIR *xldir;
struct dirent *xlde;
- char path[MAXPGPATH];
+ char path[MAXPGPATH + sizeof(XLOGDIR)];
xldir = AllocateDir(XLOGDIR);
if (xldir == NULL)
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not open transaction log directory \"%s\": %m",
+ errmsg("could not open write-ahead log directory \"%s\": %m",
XLOGDIR)));
while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
@@ -3925,10 +4121,9 @@ CleanupBackupHistory(void)
{
if (XLogArchiveCheckDone(xlde->d_name))
{
- ereport(DEBUG2,
- (errmsg("removing transaction log backup history file \"%s\"",
- xlde->d_name)));
- snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name);
+ elog(DEBUG2, "removing WAL backup history file \"%s\"",
+ xlde->d_name);
+ snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
unlink(path);
XLogArchiveCleanup(xlde->d_name);
}
@@ -4028,11 +4223,11 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
* If archive recovery was requested, but we were still doing
* crash recovery, switch to archive recovery and retry using the
* offline archive. We have now replayed all the valid WAL in
- * pg_xlog, so we are presumably now consistent.
+ * pg_wal, so we are presumably now consistent.
*
* We require that there's at least some valid WAL present in
- * pg_xlog, however (!fetch_ckpt). We could recover using the WAL
- * from the archive, even if pg_xlog is completely empty, but we'd
+ * pg_wal, however (!fetch_ckpt). We could recover using the WAL
+ * from the archive, even if pg_wal is completely empty, but we'd
* have no idea how far we'd have to replay to reach consistency.
* So err on the safe side and give up.
*/
@@ -4040,7 +4235,7 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
!fetching_ckpt)
{
ereport(DEBUG1,
- (errmsg_internal("reached end of WAL in pg_xlog, entering archive recovery")));
+ (errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
InArchiveRecovery = true;
if (StandbyModeRequested)
StandbyMode = true;
@@ -4157,7 +4352,7 @@ rescanLatestTimeLine(void)
/*
* As in StartupXLOG(), try to ensure we have all the history files
- * between the old target and new target in pg_xlog.
+ * between the old target and new target in pg_wal.
*/
restoreTimeLineHistoryFiles(oldtarget + 1, newtarget);
@@ -4208,11 +4403,6 @@ WriteControlFile(void)
ControlFile->toast_max_chunk_size = TOAST_MAX_CHUNK_SIZE;
ControlFile->loblksize = LOBLKSIZE;
-#ifdef HAVE_INT64_TIMESTAMP
- ControlFile->enableIntTimes = true;
-#else
- ControlFile->enableIntTimes = false;
-#endif
ControlFile->float4ByVal = FLOAT4PASSBYVAL;
ControlFile->float8ByVal = FLOAT8PASSBYVAL;
@@ -4246,6 +4436,7 @@ WriteControlFile(void)
XLOG_CONTROL_FILE)));
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE);
if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
{
/* if write didn't set errno, assume problem is no disk space */
@@ -4255,11 +4446,14 @@ WriteControlFile(void)
(errcode_for_file_access(),
errmsg("could not write to control file: %m")));
}
+ pgstat_report_wait_end();
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC);
if (pg_fsync(fd) != 0)
ereport(PANIC,
(errcode_for_file_access(),
errmsg("could not fsync control file: %m")));
+ pgstat_report_wait_end();
if (close(fd))
ereport(PANIC,
@@ -4285,10 +4479,12 @@ ReadControlFile(void)
errmsg("could not open control file \"%s\": %m",
XLOG_CONTROL_FILE)));
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_READ);
if (read(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
ereport(PANIC,
(errcode_for_file_access(),
errmsg("could not read from control file: %m")));
+ pgstat_report_wait_end();
close(fd);
@@ -4408,22 +4604,6 @@ ReadControlFile(void)
ControlFile->loblksize, (int) LOBLKSIZE),
errhint("It looks like you need to recompile or initdb.")));
-#ifdef HAVE_INT64_TIMESTAMP
- if (ControlFile->enableIntTimes != true)
- ereport(FATAL,
- (errmsg("database files are incompatible with server"),
- errdetail("The database cluster was initialized without HAVE_INT64_TIMESTAMP"
- " but the server was compiled with HAVE_INT64_TIMESTAMP."),
- errhint("It looks like you need to recompile or initdb.")));
-#else
- if (ControlFile->enableIntTimes != false)
- ereport(FATAL,
- (errmsg("database files are incompatible with server"),
- errdetail("The database cluster was initialized with HAVE_INT64_TIMESTAMP"
- " but the server was compiled without HAVE_INT64_TIMESTAMP."),
- errhint("It looks like you need to recompile or initdb.")));
-#endif
-
#ifdef USE_FLOAT4_BYVAL
if (ControlFile->float4ByVal != true)
ereport(FATAL,
@@ -4482,6 +4662,7 @@ UpdateControlFile(void)
XLOG_CONTROL_FILE)));
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE);
if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
{
/* if write didn't set errno, assume problem is no disk space */
@@ -4491,11 +4672,14 @@ UpdateControlFile(void)
(errcode_for_file_access(),
errmsg("could not write to control file: %m")));
}
+ pgstat_report_wait_end();
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE);
if (pg_fsync(fd) != 0)
ereport(PANIC,
(errcode_for_file_access(),
errmsg("could not fsync control file: %m")));
+ pgstat_report_wait_end();
if (close(fd))
ereport(PANIC,
@@ -4514,6 +4698,16 @@ GetSystemIdentifier(void)
}
/*
+ * Returns the random nonce from control file.
+ */
+char *
+GetMockAuthenticationNonce(void)
+{
+ Assert(ControlFile != NULL);
+ return ControlFile->mock_authentication_nonce;
+}
+
+/*
* Are checksums enabled for data pages?
*/
bool
@@ -4667,9 +4861,7 @@ XLOGShmemInit(void)
{
walDebugCxt = AllocSetContextCreate(TopMemoryContext,
"WAL Debug",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
MemoryContextAllowInCriticalSection(walDebugCxt, true);
}
#endif
@@ -4687,7 +4879,7 @@ XLOGShmemInit(void)
/* Initialize local copy of WALInsertLocks and register the tranche */
WALInsertLocks = XLogCtl->Insert.WALInsertLocks;
LWLockRegisterTranche(LWTRANCHE_WAL_INSERT,
- &XLogCtl->Insert.WALInsertLockTranche);
+ "wal_insert");
return;
}
memset(XLogCtl, 0, sizeof(XLogCtlData));
@@ -4710,15 +4902,12 @@ XLOGShmemInit(void)
(WALInsertLockPadded *) allocptr;
allocptr += sizeof(WALInsertLockPadded) * NUM_XLOGINSERT_LOCKS;
- XLogCtl->Insert.WALInsertLockTranche.name = "wal_insert";
- XLogCtl->Insert.WALInsertLockTranche.array_base = WALInsertLocks;
- XLogCtl->Insert.WALInsertLockTranche.array_stride = sizeof(WALInsertLockPadded);
-
- LWLockRegisterTranche(LWTRANCHE_WAL_INSERT, &XLogCtl->Insert.WALInsertLockTranche);
+ LWLockRegisterTranche(LWTRANCHE_WAL_INSERT, "wal_insert");
for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
{
LWLockInitialize(&WALInsertLocks[i].l.lock, LWTRANCHE_WAL_INSERT);
WALInsertLocks[i].l.insertingAt = InvalidXLogRecPtr;
+ WALInsertLocks[i].l.lastImportantAt = InvalidXLogRecPtr;
}
/*
@@ -4768,6 +4957,7 @@ BootStrapXLOG(void)
char *recptr;
bool use_existent;
uint64 sysidentifier;
+ char mock_auth_nonce[MOCK_AUTH_NONCE_LEN];
struct timeval tv;
pg_crc32c crc;
@@ -4788,6 +4978,17 @@ BootStrapXLOG(void)
sysidentifier |= ((uint64) tv.tv_usec) << 12;
sysidentifier |= getpid() & 0xFFF;
+ /*
+ * Generate a random nonce. This is used for authentication requests that
+ * will fail because the user does not exist. The nonce is used to create
+ * a genuine-looking password challenge for the non-existent user, in lieu
+ * of an actual stored password.
+ */
+ if (!pg_backend_random(mock_auth_nonce, MOCK_AUTH_NONCE_LEN))
+ ereport(PANIC,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("could not generate secret authorization token")));
+
/* First timeline ID is always 1 */
ThisTimeLineID = 1;
@@ -4825,8 +5026,9 @@ BootStrapXLOG(void)
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
+ AdvanceOldestClogXid(checkPoint.oldestXid);
SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
- SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB);
+ SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
SetCommitTsLimit(InvalidTransactionId, InvalidTransactionId);
/* Set up the XLOG page header */
@@ -4849,7 +5051,7 @@ BootStrapXLOG(void)
record->xl_rmid = RM_XLOG_ID;
recptr += SizeOfXLogRecord;
/* fill the XLogRecordDataHeaderShort struct */
- *(recptr++) = XLR_BLOCK_ID_DATA_SHORT;
+ *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
*(recptr++) = sizeof(checkPoint);
memcpy(recptr, &checkPoint, sizeof(checkPoint));
recptr += sizeof(checkPoint);
@@ -4867,6 +5069,7 @@ BootStrapXLOG(void)
/* Write the first page with the initial record */
errno = 0;
+ pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
{
/* if write didn't set errno, assume problem is no disk space */
@@ -4874,18 +5077,21 @@ BootStrapXLOG(void)
errno = ENOSPC;
ereport(PANIC,
(errcode_for_file_access(),
- errmsg("could not write bootstrap transaction log file: %m")));
+ errmsg("could not write bootstrap write-ahead log file: %m")));
}
+ pgstat_report_wait_end();
+ pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC);
if (pg_fsync(openLogFile) != 0)
ereport(PANIC,
(errcode_for_file_access(),
- errmsg("could not fsync bootstrap transaction log file: %m")));
+ errmsg("could not fsync bootstrap write-ahead log file: %m")));
+ pgstat_report_wait_end();
if (close(openLogFile))
ereport(PANIC,
(errcode_for_file_access(),
- errmsg("could not close bootstrap transaction log file: %m")));
+ errmsg("could not close bootstrap write-ahead log file: %m")));
openLogFile = -1;
@@ -4894,6 +5100,7 @@ BootStrapXLOG(void)
memset(ControlFile, 0, sizeof(ControlFileData));
/* Initialize pg_control status fields */
ControlFile->system_identifier = sysidentifier;
+ memcpy(ControlFile->mock_authentication_nonce, mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
ControlFile->state = DB_SHUTDOWNED;
ControlFile->time = checkPoint.time;
ControlFile->checkPoint = checkPoint.redo;
@@ -5028,7 +5235,8 @@ readRecoveryCommandFile(void)
rtli = (TimeLineID) strtoul(item->value, NULL, 0);
if (errno == EINVAL || errno == ERANGE)
ereport(FATAL,
- (errmsg("recovery_target_timeline is not a valid number: \"%s\"",
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("recovery_target_timeline is not a valid number: \"%s\"",
item->value)));
}
if (rtli)
@@ -5044,7 +5252,8 @@ readRecoveryCommandFile(void)
recoveryTargetXid = (TransactionId) strtoul(item->value, NULL, 0);
if (errno == EINVAL || errno == ERANGE)
ereport(FATAL,
- (errmsg("recovery_target_xid is not a valid number: \"%s\"",
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("recovery_target_xid is not a valid number: \"%s\"",
item->value)));
ereport(DEBUG2,
(errmsg_internal("recovery_target_xid = %u",
@@ -5089,6 +5298,23 @@ readRecoveryCommandFile(void)
(errmsg_internal("recovery_target_name = '%s'",
recoveryTargetName)));
}
+ else if (strcmp(item->name, "recovery_target_lsn") == 0)
+ {
+ recoveryTarget = RECOVERY_TARGET_LSN;
+
+ /*
+ * Convert the LSN string given by the user to XLogRecPtr form.
+ */
+ recoveryTargetLSN =
+ DatumGetLSN(DirectFunctionCall3(pg_lsn_in,
+ CStringGetDatum(item->value),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1)));
+ ereport(DEBUG2,
+ (errmsg_internal("recovery_target_lsn = '%X/%X'",
+ (uint32) (recoveryTargetLSN >> 32),
+ (uint32) recoveryTargetLSN)));
+ }
else if (strcmp(item->name, "recovery_target") == 0)
{
if (strcmp(item->value, "immediate") == 0)
@@ -5166,7 +5392,8 @@ readRecoveryCommandFile(void)
}
else
ereport(FATAL,
- (errmsg("unrecognized recovery parameter \"%s\"",
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized recovery parameter \"%s\"",
item->name)));
}
@@ -5179,13 +5406,14 @@ readRecoveryCommandFile(void)
ereport(WARNING,
(errmsg("recovery command file \"%s\" specified neither primary_conninfo nor restore_command",
RECOVERY_COMMAND_FILE),
- errhint("The database server will regularly poll the pg_xlog subdirectory to check for files placed there.")));
+ errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
}
else
{
if (recoveryRestoreCommand == NULL)
ereport(FATAL,
- (errmsg("recovery command file \"%s\" must specify restore_command when standby mode is not enabled",
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("recovery command file \"%s\" must specify restore_command when standby mode is not enabled",
RECOVERY_COMMAND_FILE)));
}
@@ -5199,6 +5427,15 @@ readRecoveryCommandFile(void)
!EnableHotStandby)
recoveryTargetAction = RECOVERY_TARGET_ACTION_SHUTDOWN;
+ /*
+ * We don't support standby_mode in standalone backends; that requires
+ * other processes such as the WAL receiver to be alive.
+ */
+ if (StandbyModeRequested && !IsUnderPostmaster)
+ ereport(FATAL,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("standby mode is not supported by single-user servers")));
+
/* Enable fetching from archive recovery area */
ArchiveRecoveryRequested = true;
@@ -5215,7 +5452,8 @@ readRecoveryCommandFile(void)
/* Timeline 1 does not have a history file, all else should */
if (rtli != 1 && !existsTimeLineHistory(rtli))
ereport(FATAL,
- (errmsg("recovery target timeline %u does not exist",
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("recovery target timeline %u does not exist",
rtli)));
recoveryTargetTLI = rtli;
recoveryTargetIsLatest = false;
@@ -5404,8 +5642,26 @@ recoveryStopsBefore(XLogReaderState *record)
recoveryStopAfter = false;
recoveryStopXid = InvalidTransactionId;
+ recoveryStopLSN = InvalidXLogRecPtr;
+ recoveryStopTime = 0;
+ recoveryStopName[0] = '\0';
+ return true;
+ }
+
+ /* Check if target LSN has been reached */
+ if (recoveryTarget == RECOVERY_TARGET_LSN &&
+ !recoveryTargetInclusive &&
+ record->ReadRecPtr >= recoveryTargetLSN)
+ {
+ recoveryStopAfter = false;
+ recoveryStopXid = InvalidTransactionId;
+ recoveryStopLSN = record->ReadRecPtr;
recoveryStopTime = 0;
recoveryStopName[0] = '\0';
+ ereport(LOG,
+ (errmsg("recovery stopping before WAL location (LSN) \"%X/%X\"",
+ (uint32) (recoveryStopLSN >> 32),
+ (uint32) recoveryStopLSN)));
return true;
}
#ifdef PGXC
@@ -5520,6 +5776,7 @@ recoveryStopsBefore(XLogReaderState *record)
recoveryStopAfter = false;
recoveryStopXid = recordXid;
recoveryStopTime = recordXtime;
+ recoveryStopLSN = InvalidXLogRecPtr;
recoveryStopName[0] = '\0';
if (isCommit)
@@ -5584,6 +5841,7 @@ recoveryStopsAfter(XLogReaderState *record)
{
recoveryStopAfter = true;
recoveryStopXid = InvalidTransactionId;
+ recoveryStopLSN = InvalidXLogRecPtr;
(void) getRecordTimestamp(record, &recoveryStopTime);
strlcpy(recoveryStopName, recordRestorePointData->rp_name, MAXFNAMELEN);
@@ -5595,6 +5853,23 @@ recoveryStopsAfter(XLogReaderState *record)
}
}
+ /* Check if the target LSN has been reached */
+ if (recoveryTarget == RECOVERY_TARGET_LSN &&
+ recoveryTargetInclusive &&
+ record->ReadRecPtr >= recoveryTargetLSN)
+ {
+ recoveryStopAfter = true;
+ recoveryStopXid = InvalidTransactionId;
+ recoveryStopLSN = record->ReadRecPtr;
+ recoveryStopTime = 0;
+ recoveryStopName[0] = '\0';
+ ereport(LOG,
+ (errmsg("recovery stopping after WAL location (LSN) \"%X/%X\"",
+ (uint32) (recoveryStopLSN >> 32),
+ (uint32) recoveryStopLSN)));
+ return true;
+ }
+
if (rmid != RM_XACT_ID)
return false;
@@ -5650,6 +5925,7 @@ recoveryStopsAfter(XLogReaderState *record)
recoveryStopAfter = true;
recoveryStopXid = recordXid;
recoveryStopTime = recordXtime;
+ recoveryStopLSN = InvalidXLogRecPtr;
recoveryStopName[0] = '\0';
if (xact_info == XLOG_XACT_COMMIT ||
@@ -5681,6 +5957,7 @@ recoveryStopsAfter(XLogReaderState *record)
recoveryStopAfter = true;
recoveryStopXid = InvalidTransactionId;
recoveryStopTime = 0;
+ recoveryStopLSN = InvalidXLogRecPtr;
recoveryStopName[0] = '\0';
return true;
}
@@ -5704,7 +5981,7 @@ recoveryPausesHere(void)
ereport(LOG,
(errmsg("recovery has paused"),
- errhint("Execute pg_xlog_replay_resume() to continue.")));
+ errhint("Execute pg_wal_replay_resume() to continue.")));
while (RecoveryIsPaused())
{
@@ -5820,7 +6097,8 @@ recoveryApplyDelay(XLogReaderState *record)
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- secs * 1000L + microsecs / 1000);
+ secs * 1000L + microsecs / 1000,
+ WAIT_EVENT_RECOVERY_APPLY_DELAY);
}
return true;
}
@@ -6048,7 +6326,7 @@ StartupXLOG(void)
#endif
/*
- * Verify that pg_xlog and pg_xlog/archive_status exist. In cases where
+ * Verify that pg_wal and pg_wal/archive_status exist. In cases where
* someone has performed a copy for PITR, these directories may have been
* excluded and need to be re-created.
*/
@@ -6113,6 +6391,11 @@ StartupXLOG(void)
ereport(LOG,
(errmsg("starting point-in-time recovery to \"%s\"",
recoveryTargetName)));
+ else if (recoveryTarget == RECOVERY_TARGET_LSN)
+ ereport(LOG,
+ (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
+ (uint32) (recoveryTargetLSN >> 32),
+ (uint32) recoveryTargetLSN)));
else if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE)
ereport(LOG,
(errmsg("starting point-in-time recovery to earliest consistent point")));
@@ -6135,9 +6418,16 @@ StartupXLOG(void)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory"),
- errdetail("Failed while allocating an XLog reading processor.")));
+ errdetail("Failed while allocating a WAL reading processor.")));
xlogreader->system_identifier = ControlFile->system_identifier;
+ /*
+ * Allocate pages dedicated to WAL consistency checks, those had better be
+ * aligned.
+ */
+ replay_image_masked = (char *) palloc(BLCKSZ);
+ master_image_masked = (char *) palloc(BLCKSZ);
+
if (read_backup_label(&checkPointLoc, &backupEndRequired,
&backupFromStandby))
{
@@ -6160,7 +6450,7 @@ StartupXLOG(void)
if (record != NULL)
{
memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
- wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN);
+ wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
ereport(DEBUG1,
(errmsg("checkpoint record is at %X/%X",
(uint32) (checkPointLoc >> 32), (uint32) checkPointLoc)));
@@ -6262,7 +6552,7 @@ StartupXLOG(void)
* and put it into archive recovery by creating a recovery.conf file.
*
* Our strategy in that case is to perform crash recovery first,
- * replaying all the WAL present in pg_xlog, and only enter archive
+ * replaying all the WAL present in pg_wal, and only enter archive
* recovery after that.
*
* But usually we already know how far we need to replay the WAL (up
@@ -6318,7 +6608,7 @@ StartupXLOG(void)
(errmsg("could not locate a valid checkpoint record")));
}
memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
- wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN);
+ wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
}
/*
@@ -6409,8 +6699,9 @@ StartupXLOG(void)
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
+ AdvanceOldestClogXid(checkPoint.oldestXid);
SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
- SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB);
+ SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
SetCommitTsLimit(checkPoint.oldestCommitTsXid,
checkPoint.newestCommitTsXid);
XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
@@ -6466,18 +6757,28 @@ StartupXLOG(void)
/*
* Copy any missing timeline history files between 'now' and the recovery
- * target timeline from archive to pg_xlog. While we don't need those
- * files ourselves - the history file of the recovery target timeline
- * covers all the previous timelines in the history too - a cascading
- * standby server might be interested in them. Or, if you archive the WAL
- * from this server to a different archive than the master, it'd be good
- * for all the history files to get archived there after failover, so that
- * you can use one of the old timelines as a PITR target. Timeline history
- * files are small, so it's better to copy them unnecessarily than not
- * copy them and regret later.
+ * target timeline from archive to pg_wal. While we don't need those files
+ * ourselves - the history file of the recovery target timeline covers all
+ * the previous timelines in the history too - a cascading standby server
+ * might be interested in them. Or, if you archive the WAL from this
+ * server to a different archive than the master, it'd be good for all the
+ * history files to get archived there after failover, so that you can use
+ * one of the old timelines as a PITR target. Timeline history files are
+ * small, so it's better to copy them unnecessarily than not copy them and
+ * regret later.
*/
restoreTimeLineHistoryFiles(ThisTimeLineID, recoveryTargetTLI);
+ /*
+ * Before running in recovery, scan pg_twophase and fill in its status to
+ * be able to work on entries generated by redo. Doing a scan before
+ * taking any recovery action has the merit to discard any 2PC files that
+ * are newer than the first record to replay, saving from any conflicts at
+ * replay. This avoids as well any subsequent scans when doing recovery
+ * of the on-disk two-phase data.
+ */
+ restoreTwoPhaseData();
+
lastFullPageWrites = checkPoint.fullPageWrites;
RedoRecPtr = XLogCtl->RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
@@ -6698,7 +6999,7 @@ StartupXLOG(void)
ProcArrayApplyRecoveryInfo(&running);
- StandbyRecoverPreparedTransactions(false);
+ StandbyRecoverPreparedTransactions();
}
}
@@ -6938,6 +7239,15 @@ StartupXLOG(void)
/* Now apply the WAL record itself */
RmgrTable[record->xl_rmid].rm_redo(xlogreader);
+ /*
+ * After redo, check whether the backup pages associated with
+ * the WAL record are consistent with the existing pages. This
+ * check is done only if consistency check is enabled for this
+ * record.
+ */
+ if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
+ checkXLogConsistency(xlogreader);
+
/* Pop the error context stack */
error_context_stack = errcallback.previous;
@@ -7087,7 +7397,7 @@ StartupXLOG(void)
/*
* We are now done reading the xlog from stream. Turn off streaming
* recovery to force fetching the files (which would be required at end of
- * recovery, e.g., timeline history file) from archive or pg_xlog.
+ * recovery, e.g., timeline history file) from archive or pg_wal.
*/
StandbyMode = false;
@@ -7182,6 +7492,12 @@ StartupXLOG(void)
"%s %s\n",
recoveryStopAfter ? "after" : "before",
timestamptz_to_str(recoveryStopTime));
+ else if (recoveryTarget == RECOVERY_TARGET_LSN)
+ snprintf(reason, sizeof(reason),
+ "%s LSN %X/%X\n",
+ recoveryStopAfter ? "after" : "before",
+ (uint32) (recoveryStopLSN >> 32),
+ (uint32) recoveryStopLSN);
else if (recoveryTarget == RECOVERY_TARGET_NAME)
snprintf(reason, sizeof(reason),
"at restore point \"%s\"",
@@ -7216,7 +7532,7 @@ StartupXLOG(void)
exitArchiveRecovery(EndOfLogTLI, EndOfLog);
/*
- * Prepare to write WAL starting at EndOfLog position, and init xlog
+ * Prepare to write WAL starting at EndOfLog location, and init xlog
* buffer cache using the block containing the last record from the
* previous incarnation.
*/
@@ -7376,7 +7692,7 @@ StartupXLOG(void)
* As a compromise, we rename the last segment with the .partial
* suffix, and archive it. Archive recovery will never try to read
* .partial segments, so they will normally go unused. But in the odd
- * PITR case, the administrator can copy them manually to the pg_xlog
+ * PITR case, the administrator can copy them manually to the pg_wal
* directory (removing the suffix). They can be useful in debugging,
* too.
*
@@ -7426,14 +7742,9 @@ StartupXLOG(void)
*/
InRecovery = false;
- LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
- ControlFile->state = DB_IN_PRODUCTION;
- ControlFile->time = (pg_time_t) time(NULL);
- UpdateControlFile();
- LWLockRelease(ControlFileLock);
-
- /* start the archive_timeout timer running */
+ /* start the archive_timeout timer and LSN running */
XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
+ XLogCtl->lastSegSwitchLSN = EndOfLog;
/* also initialize latestCompletedXid, to nextXid - 1 */
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
@@ -7489,15 +7800,32 @@ StartupXLOG(void)
CompleteCommitTsInitialization();
/*
- * All done. Allow backends to write WAL. (Although the bool flag is
- * probably atomic in itself, we use the info_lck here to ensure that
- * there are no race conditions concerning visibility of other recent
- * updates to shared memory.)
+ * All done with end-of-recovery actions.
+ *
+ * Now allow backends to write WAL and update the control file status in
+ * consequence. The boolean flag allowing backends to write WAL is
+ * updated while holding ControlFileLock to prevent other backends to look
+ * at an inconsistent state of the control file in shared memory. There
+ * is still a small window during which backends can write WAL and the
+ * control file is still referring to a system not in DB_IN_PRODUCTION
+ * state while looking at the on-disk control file.
+ *
+ * Also, although the boolean flag to allow WAL is probably atomic in
+ * itself, we use the info_lck here to ensure that there are no race
+ * conditions concerning visibility of other recent updates to shared
+ * memory.
*/
+ LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
+ ControlFile->state = DB_IN_PRODUCTION;
+ ControlFile->time = (pg_time_t) time(NULL);
+
SpinLockAcquire(&XLogCtl->info_lck);
XLogCtl->SharedRecoveryInProgress = false;
SpinLockRelease(&XLogCtl->info_lck);
+ UpdateControlFile();
+ LWLockRelease(ControlFileLock);
+
/*
* If there were cascading standby servers connected to us, nudge any wal
* sender processes to notice that we've been promoted.
@@ -7765,6 +8093,7 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
int whichChkpt, bool report)
{
XLogRecord *record;
+ uint8 info;
if (!XRecOffIsValid(RecPtr))
{
@@ -7832,8 +8161,9 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
}
return NULL;
}
- if (record->xl_info != XLOG_CHECKPOINT_SHUTDOWN &&
- record->xl_info != XLOG_CHECKPOINT_ONLINE)
+ info = record->xl_info & ~XLR_INFO_MASK;
+ if (info != XLOG_CHECKPOINT_SHUTDOWN &&
+ info != XLOG_CHECKPOINT_ONLINE)
{
switch (whichChkpt)
{
@@ -7976,16 +8306,51 @@ GetFlushRecPtr(void)
}
/*
- * Get the time of the last xlog segment switch
+ * GetLastImportantRecPtr -- Returns the LSN of the last important record
+ * inserted. All records not explicitly marked as unimportant are considered
+ * important.
+ *
+ * The LSN is determined by computing the maximum of
+ * WALInsertLocks[i].lastImportantAt.
+ */
+XLogRecPtr
+GetLastImportantRecPtr(void)
+{
+ XLogRecPtr res = InvalidXLogRecPtr;
+ int i;
+
+ for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
+ {
+ XLogRecPtr last_important;
+
+ /*
+ * Need to take a lock to prevent torn reads of the LSN, which are
+ * possible on some of the supported platforms. WAL insert locks only
+ * support exclusive mode, so we have to use that.
+ */
+ LWLockAcquire(&WALInsertLocks[i].l.lock, LW_EXCLUSIVE);
+ last_important = WALInsertLocks[i].l.lastImportantAt;
+ LWLockRelease(&WALInsertLocks[i].l.lock);
+
+ if (res < last_important)
+ res = last_important;
+ }
+
+ return res;
+}
+
+/*
+ * Get the time and LSN of the last xlog segment switch
*/
pg_time_t
-GetLastSegSwitchTime(void)
+GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN)
{
pg_time_t result;
/* Need WALWriteLock, but shared lock is sufficient */
LWLockAcquire(WALWriteLock, LW_SHARED);
result = XLogCtl->lastSegSwitchTime;
+ *lastSwitchLSN = XLogCtl->lastSegSwitchLSN;
LWLockRelease(WALWriteLock);
return result;
@@ -8036,6 +8401,12 @@ ShutdownXLOG(int code, Datum arg)
ereport(IsPostmasterEnvironment ? LOG : NOTICE,
(errmsg("shutting down")));
+ /*
+ * Wait for WAL senders to be in stopping state. This prevents commands
+ * from writing new WAL.
+ */
+ WalSndWaitStopping();
+
if (RecoveryInProgress())
CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
else
@@ -8047,7 +8418,7 @@ ShutdownXLOG(int code, Datum arg)
* record will go to the next XLOG file and won't be archived (yet).
*/
if (XLogArchivingActive() && XLogArchiveCommandSet())
- RequestXLogSwitch();
+ RequestXLogSwitch(false);
CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
}
@@ -8137,7 +8508,7 @@ LogCheckpointEnd(bool restartpoint)
average_usecs = average_sync_time - (uint64) average_secs *1000000;
elog(LOG, "%s complete: wrote %d buffers (%.1f%%); "
- "%d transaction log file(s) added, %d removed, %d recycled; "
+ "%d WAL file(s) added, %d removed, %d recycled; "
"write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
"sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; "
"distance=%d kB, estimate=%d kB",
@@ -8235,7 +8606,7 @@ CreateCheckPoint(int flags)
uint32 freespace;
XLogRecPtr PriorRedoPtr;
XLogRecPtr curInsert;
- XLogRecPtr prevPtr;
+ XLogRecPtr last_important_lsn;
VirtualTransactionId *vxids;
int nvxids;
@@ -8316,38 +8687,33 @@ CreateCheckPoint(int flags)
checkPoint.oldestActiveXid = InvalidTransactionId;
/*
+ * Get location of last important record before acquiring insert locks (as
+ * GetLastImportantRecPtr() also locks WAL locks).
+ */
+ last_important_lsn = GetLastImportantRecPtr();
+
+ /*
* We must block concurrent insertions while examining insert state to
* determine the checkpoint REDO pointer.
*/
WALInsertLockAcquireExclusive();
curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
- prevPtr = XLogBytePosToRecPtr(Insert->PrevBytePos);
/*
- * If this isn't a shutdown or forced checkpoint, and we have not inserted
- * any XLOG records since the start of the last checkpoint, skip the
- * checkpoint. The idea here is to avoid inserting duplicate checkpoints
- * when the system is idle. That wastes log space, and more importantly it
- * exposes us to possible loss of both current and previous checkpoint
- * records if the machine crashes just as we're writing the update.
- * (Perhaps it'd make even more sense to checkpoint only when the previous
- * checkpoint record is in a different xlog page?)
- *
- * If the previous checkpoint crossed a WAL segment, however, we create
- * the checkpoint anyway, to have the latest checkpoint fully contained in
- * the new segment. This is for a little bit of extra robustness: it's
- * better if you don't need to keep two WAL segments around to recover the
- * checkpoint.
+ * If this isn't a shutdown or forced checkpoint, and if there has been no
+ * WAL activity requiring a checkpoint, skip it. The idea here is to
+ * avoid inserting duplicate checkpoints when the system is idle.
*/
if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
CHECKPOINT_FORCE)) == 0)
{
- if (prevPtr == ControlFile->checkPointCopy.redo &&
- prevPtr / XLOG_SEG_SIZE == curInsert / XLOG_SEG_SIZE)
+ if (last_important_lsn == ControlFile->checkPoint)
{
WALInsertLockRelease();
LWLockRelease(CheckpointLock);
END_CRIT_SECTION();
+ ereport(DEBUG1,
+ (errmsg("checkpoint skipped due to an idle system")));
return;
}
}
@@ -8422,6 +8788,11 @@ CreateCheckPoint(int flags)
/*
* Get the other info we need for the checkpoint record.
+ *
+ * We don't need to save oldestClogXid in the checkpoint, it only matters
+ * for the short period in which clog is being truncated, and if we crash
+ * during that we'll redo the clog truncation and fix up oldestClogXid
+ * there.
*/
LWLockAcquire(XidGenLock, LW_SHARED);
checkPoint.nextXid = ShmemVariableCache->nextXid;
@@ -8471,7 +8842,7 @@ CreateCheckPoint(int flags)
* that are currently in commit critical sections. If an xact inserted
* its commit record into XLOG just before the REDO point, then a crash
* restart from the REDO point would not replay that record, which means
- * that our flushing had better include the xact's update of pg_clog. So
+ * that our flushing had better include the xact's update of pg_xact. So
* we wait till he's out of his commit critical section before proceeding.
* See notes in RecordTransactionCommit().
*
@@ -8547,7 +8918,7 @@ CreateCheckPoint(int flags)
*/
if (shutdown && checkPoint.redo != ProcLastRecPtr)
ereport(PANIC,
- (errmsg("concurrent transaction log activity while database system is shutting down")));
+ (errmsg("concurrent write-ahead log activity while database system is shutting down")));
/*
* Remember the prior checkpoint's redo pointer, used later to determine
@@ -8630,7 +9001,7 @@ CreateCheckPoint(int flags)
* StartupSUBTRANS hasn't been called yet.
*/
if (!RecoveryInProgress())
- TruncateSUBTRANS(GetOldestXmin(NULL, false));
+ TruncateSUBTRANS(GetOldestXmin(NULL, PROCARRAY_FLAGS_DEFAULT));
/* Real work is done, but log and update stats before releasing lock. */
LogCheckpointEnd(false);
@@ -8756,6 +9127,7 @@ RecoveryRestartPoint(const CheckPoint *checkPoint)
*/
SpinLockAcquire(&XLogCtl->info_lck);
XLogCtl->lastCheckPointRecPtr = ReadRecPtr;
+ XLogCtl->lastCheckPointEndPtr = EndRecPtr;
XLogCtl->lastCheckPoint = *checkPoint;
SpinLockRelease(&XLogCtl->info_lck);
}
@@ -8775,6 +9147,7 @@ bool
CreateRestartPoint(int flags)
{
XLogRecPtr lastCheckPointRecPtr;
+ XLogRecPtr lastCheckPointEndPtr;
CheckPoint lastCheckPoint;
XLogRecPtr PriorRedoPtr;
TimestampTz xtime;
@@ -8788,6 +9161,7 @@ CreateRestartPoint(int flags)
/* Get a local copy of the last safe checkpoint record. */
SpinLockAcquire(&XLogCtl->info_lck);
lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
+ lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
lastCheckPoint = XLogCtl->lastCheckPoint;
SpinLockRelease(&XLogCtl->info_lck);
@@ -8891,6 +9265,27 @@ CreateRestartPoint(int flags)
ControlFile->checkPoint = lastCheckPointRecPtr;
ControlFile->checkPointCopy = lastCheckPoint;
ControlFile->time = (pg_time_t) time(NULL);
+
+ /*
+ * Ensure minRecoveryPoint is past the checkpoint record. Normally,
+ * this will have happened already while writing out dirty buffers,
+ * but not necessarily - e.g. because no buffers were dirtied. We do
+ * this because a non-exclusive base backup uses minRecoveryPoint to
+ * determine which WAL files must be included in the backup, and the
+ * file (or files) containing the checkpoint record must be included,
+ * at a minimum. Note that for an ordinary restart of recovery there's
+ * no value in having the minimum recovery point any earlier than this
+ * anyway, because redo will begin just after the checkpoint record.
+ */
+ if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
+ {
+ ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
+ ControlFile->minRecoveryPointTLI = lastCheckPoint.ThisTimeLineID;
+
+ /* update local copy */
+ minRecoveryPoint = ControlFile->minRecoveryPoint;
+ minRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
+ }
if (flags & CHECKPOINT_IS_SHUTDOWN)
ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY;
UpdateControlFile();
@@ -8969,7 +9364,7 @@ CreateRestartPoint(int flags)
* this because StartupSUBTRANS hasn't been called yet.
*/
if (EnableHotStandby)
- TruncateSUBTRANS(GetOldestXmin(NULL, false));
+ TruncateSUBTRANS(GetOldestXmin(NULL, PROCARRAY_FLAGS_DEFAULT));
/* Real work is done, but log and update before releasing lock. */
LogCheckpointEnd(true);
@@ -9024,7 +9419,7 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
/* then check whether slots limit removal further */
if (max_replication_slots > 0 && keep != InvalidXLogRecPtr)
{
- XLogRecPtr slotSegNo;
+ XLogSegNo slotSegNo;
XLByteToSeg(keep, slotSegNo);
@@ -9080,12 +9475,15 @@ XLogPutNextOid(Oid nextOid)
* write a switch record because we are already at segment start.
*/
XLogRecPtr
-RequestXLogSwitch(void)
+RequestXLogSwitch(bool mark_unimportant)
{
XLogRecPtr RecPtr;
/* XLOG SWITCH has no data */
XLogBeginInsert();
+
+ if (mark_unimportant)
+ XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT);
RecPtr = XLogInsert(RM_XLOG_ID, XLOG_SWITCH);
return RecPtr;
@@ -9324,6 +9722,11 @@ xlog_redo(XLogReaderState *record)
MultiXactAdvanceOldest(checkPoint.oldestMulti,
checkPoint.oldestMultiDB);
+
+ /*
+ * No need to set oldestClogXid here as well; it'll be set when we
+ * redo an xl_clog_truncate if it changed since initialization.
+ */
SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
/*
@@ -9372,7 +9775,7 @@ xlog_redo(XLogReaderState *record)
ProcArrayApplyRecoveryInfo(&running);
- StandbyRecoverPreparedTransactions(true);
+ StandbyRecoverPreparedTransactions();
}
/* ControlFile->checkPointCopy always tracks the latest ckpt XID */
@@ -9733,11 +10136,13 @@ assign_xlog_sync_method(int new_sync_method, void *extra)
*/
if (openLogFile >= 0)
{
+ pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN);
if (pg_fsync(openLogFile) != 0)
ereport(PANIC,
(errcode_for_file_access(),
errmsg("could not fsync log segment %s: %m",
XLogFileNameP(ThisTimeLineID, openLogSegNo))));
+ pgstat_report_wait_end();
if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
XLogFileClose();
}
@@ -9832,7 +10237,7 @@ XLogFileNameP(TimeLineID tli, XLogSegNo segno)
* when backup needs to generate tablespace_map file, it is used to
* embed escape character before newline character in tablespace path.
*
- * Returns the minimum WAL position that must be present to restore from this
+ * Returns the minimum WAL location that must be present to restore from this
* backup, and the corresponding timeline ID in *starttli_p.
*
* Every successfully started non-exclusive backup must be stopped by calling
@@ -9910,7 +10315,12 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
WALInsertLockAcquireExclusive();
if (exclusive)
{
- if (XLogCtl->Insert.exclusiveBackup)
+ /*
+ * At first, mark that we're now starting an exclusive backup, to
+ * ensure that there are no other sessions currently running
+ * pg_start_backup() or pg_stop_backup().
+ */
+ if (XLogCtl->Insert.exclusiveBackupState != EXCLUSIVE_BACKUP_NONE)
{
WALInsertLockRelease();
ereport(ERROR,
@@ -9918,7 +10328,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
errmsg("a backup is already in progress"),
errhint("Run pg_stop_backup() and try again.")));
}
- XLogCtl->Insert.exclusiveBackup = true;
+ XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_STARTING;
}
else
XLogCtl->Insert.nonExclusiveBackups++;
@@ -9941,7 +10351,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
* first WAL segment containing the startup checkpoint has pages in
* the beginning with the old timeline ID. That can cause trouble at
* recovery: we won't have a history file covering the old timeline if
- * pg_xlog directory was not included in the base backup and the WAL
+ * pg_wal directory was not included in the base backup and the WAL
* archive was cleared too before starting the backup.
*
* This also ensures that we have emitted a WAL page header that has
@@ -9955,7 +10365,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
* recovery case described above.
*/
if (!backup_started_in_recovery)
- RequestXLogSwitch();
+ RequestXLogSwitch(false);
do
{
@@ -10062,7 +10472,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
/* Collect information about all tablespaces */
while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
{
- char fullpath[MAXPGPATH];
+ char fullpath[MAXPGPATH + 10];
char linkpath[MAXPGPATH];
char *relpath = NULL;
int rllen;
@@ -10173,8 +10583,9 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
{
/*
* Check for existing backup label --- implies a backup is already
- * running. (XXX given that we checked exclusiveBackup above,
- * maybe it would be OK to just unlink any such label file?)
+ * running. (XXX given that we checked exclusiveBackupState
+ * above, maybe it would be OK to just unlink any such label
+ * file?)
*/
if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
{
@@ -10255,6 +10666,20 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
PG_END_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) BoolGetDatum(exclusive));
/*
+ * Mark that start phase has correctly finished for an exclusive backup.
+ * Session-level locks are updated as well to reflect that state.
+ */
+ if (exclusive)
+ {
+ WALInsertLockAcquireExclusive();
+ XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
+ WALInsertLockRelease();
+ sessionBackupState = SESSION_BACKUP_EXCLUSIVE;
+ }
+ else
+ sessionBackupState = SESSION_BACKUP_NON_EXCLUSIVE;
+
+ /*
* We're done. As a convenience, return the starting WAL location.
*/
if (starttli_p)
@@ -10272,8 +10697,8 @@ pg_start_backup_callback(int code, Datum arg)
WALInsertLockAcquireExclusive();
if (exclusive)
{
- Assert(XLogCtl->Insert.exclusiveBackup);
- XLogCtl->Insert.exclusiveBackup = false;
+ Assert(XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_STARTING);
+ XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_NONE;
}
else
{
@@ -10281,7 +10706,7 @@ pg_start_backup_callback(int code, Datum arg)
XLogCtl->Insert.nonExclusiveBackups--;
}
- if (!XLogCtl->Insert.exclusiveBackup &&
+ if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
XLogCtl->Insert.nonExclusiveBackups == 0)
{
XLogCtl->Insert.forcePageWrites = false;
@@ -10290,13 +10715,40 @@ pg_start_backup_callback(int code, Datum arg)
}
/*
+ * Error cleanup callback for pg_stop_backup
+ */
+static void
+pg_stop_backup_callback(int code, Datum arg)
+{
+ bool exclusive = DatumGetBool(arg);
+
+ /* Update backup status on failure */
+ WALInsertLockAcquireExclusive();
+ if (exclusive)
+ {
+ Assert(XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_STOPPING);
+ XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
+ }
+ WALInsertLockRelease();
+}
+
+/*
+ * Utility routine to fetch the session-level status of a backup running.
+ */
+SessionBackupState
+get_backup_status(void)
+{
+ return sessionBackupState;
+}
+
+/*
* do_pg_stop_backup is the workhorse of the user-visible pg_stop_backup()
* function.
-
+ *
* If labelfile is NULL, this stops an exclusive backup. Otherwise this stops
* the non-exclusive backup specified by 'labelfile'.
*
- * Returns the last WAL position that must be present to restore from this
+ * Returns the last WAL location that must be present to restore from this
* backup, and the corresponding timeline ID in *stoptli_p.
*
* It is the responsibility of the caller of this function to verify the
@@ -10351,20 +10803,87 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
errmsg("WAL level not sufficient for making an online backup"),
errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
- /*
- * OK to update backup counters and forcePageWrites
- */
- WALInsertLockAcquireExclusive();
if (exclusive)
{
- if (!XLogCtl->Insert.exclusiveBackup)
+ /*
+ * At first, mark that we're now stopping an exclusive backup, to
+ * ensure that there are no other sessions currently running
+ * pg_start_backup() or pg_stop_backup().
+ */
+ WALInsertLockAcquireExclusive();
+ if (XLogCtl->Insert.exclusiveBackupState != EXCLUSIVE_BACKUP_IN_PROGRESS)
{
WALInsertLockRelease();
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("exclusive backup not in progress")));
}
- XLogCtl->Insert.exclusiveBackup = false;
+ XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_STOPPING;
+ WALInsertLockRelease();
+
+ /*
+ * Remove backup_label. In case of failure, the state for an exclusive
+ * backup is switched back to in-progress.
+ */
+ PG_ENSURE_ERROR_CLEANUP(pg_stop_backup_callback, (Datum) BoolGetDatum(exclusive));
+ {
+ /*
+ * Read the existing label file into memory.
+ */
+ struct stat statbuf;
+ int r;
+
+ if (stat(BACKUP_LABEL_FILE, &statbuf))
+ {
+ /* should not happen per the upper checks */
+ if (errno != ENOENT)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not stat file \"%s\": %m",
+ BACKUP_LABEL_FILE)));
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("a backup is not in progress")));
+ }
+
+ lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
+ if (!lfp)
+ {
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not read file \"%s\": %m",
+ BACKUP_LABEL_FILE)));
+ }
+ labelfile = palloc(statbuf.st_size + 1);
+ r = fread(labelfile, statbuf.st_size, 1, lfp);
+ labelfile[statbuf.st_size] = '\0';
+
+ /*
+ * Close and remove the backup label file
+ */
+ if (r != 1 || ferror(lfp) || FreeFile(lfp))
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not read file \"%s\": %m",
+ BACKUP_LABEL_FILE)));
+ durable_unlink(BACKUP_LABEL_FILE, ERROR);
+
+ /*
+ * Remove tablespace_map file if present, it is created only if
+ * there are tablespaces.
+ */
+ durable_unlink(TABLESPACE_MAP, DEBUG1);
+ }
+ PG_END_ENSURE_ERROR_CLEANUP(pg_stop_backup_callback, (Datum) BoolGetDatum(exclusive));
+ }
+
+ /*
+ * OK to update backup counters and forcePageWrites
+ */
+ WALInsertLockAcquireExclusive();
+ if (exclusive)
+ {
+ XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_NONE;
}
else
{
@@ -10378,65 +10897,15 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
XLogCtl->Insert.nonExclusiveBackups--;
}
- if (!XLogCtl->Insert.exclusiveBackup &&
+ if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
XLogCtl->Insert.nonExclusiveBackups == 0)
{
XLogCtl->Insert.forcePageWrites = false;
}
WALInsertLockRelease();
- if (exclusive)
- {
- /*
- * Read the existing label file into memory.
- */
- struct stat statbuf;
- int r;
-
- if (stat(BACKUP_LABEL_FILE, &statbuf))
- {
- if (errno != ENOENT)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("a backup is not in progress")));
- }
-
- lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
- if (!lfp)
- {
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not read file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- }
- labelfile = palloc(statbuf.st_size + 1);
- r = fread(labelfile, statbuf.st_size, 1, lfp);
- labelfile[statbuf.st_size] = '\0';
-
- /*
- * Close and remove the backup label file
- */
- if (r != 1 || ferror(lfp) || FreeFile(lfp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not read file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- if (unlink(BACKUP_LABEL_FILE) != 0)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not remove file \"%s\": %m",
- BACKUP_LABEL_FILE)));
-
- /*
- * Remove tablespace_map file if present, it is created only if there
- * are tablespaces.
- */
- unlink(TABLESPACE_MAP);
- }
+ /* Clean up session-level lock */
+ sessionBackupState = SESSION_BACKUP_NONE;
/*
* Read and parse the START WAL LOCATION line (this code is pretty crude,
@@ -10540,7 +11009,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
* Force a switch to a new xlog segment file, so that the backup is valid
* as soon as archiver moves out the current segment file.
*/
- RequestXLogSwitch();
+ RequestXLogSwitch(false);
XLByteToPrevSeg(stoppoint, _logSegNo);
XLogFileName(stopxlogfilename, ThisTimeLineID, _logSegNo);
@@ -10588,9 +11057,9 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
* archived before returning. If archiving isn't enabled, the required WAL
* needs to be transported via streaming replication (hopefully with
* wal_keep_segments set high enough), or some more exotic mechanism like
- * polling and copying files from pg_xlog with script. We have no
- * knowledge of those mechanisms, so it's up to the user to ensure that he
- * gets all the required WAL.
+ * polling and copying files from pg_wal with script. We have no knowledge
+ * of those mechanisms, so it's up to the user to ensure that he gets all
+ * the required WAL.
*
* We wait until both the last WAL file filled during backup and the
* history file have been archived, and assume that the alphabetic sorting
@@ -10599,8 +11068,9 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
*
* We wait forever, since archive_command is supposed to work and we
* assume the admin wanted his backup to work completely. If you don't
- * wish to wait, you can set statement_timeout. Also, some notices are
- * issued to clue in anyone who might be doing this interactively.
+ * wish to wait, then either waitforarchive should be passed in as false,
+ * or you can set statement_timeout. Also, some notices are issued to
+ * clue in anyone who might be doing this interactively.
*/
if (waitforarchive && XLogArchivingActive())
{
@@ -10674,7 +11144,7 @@ do_pg_abort_backup(void)
Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
XLogCtl->Insert.nonExclusiveBackups--;
- if (!XLogCtl->Insert.exclusiveBackup &&
+ if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
XLogCtl->Insert.nonExclusiveBackups == 0)
{
XLogCtl->Insert.forcePageWrites = false;
@@ -10929,8 +11399,8 @@ rm_redo_error_callback(void *arg)
initStringInfo(&buf);
xlog_outdesc(&buf, record);
- /* translator: %s is an XLog record description */
- errcontext("xlog redo at %X/%X for %s",
+ /* translator: %s is a WAL record description */
+ errcontext("WAL redo at %X/%X for %s",
(uint32) (record->ReadRecPtr >> 32),
(uint32) record->ReadRecPtr,
buf.data);
@@ -11139,10 +11609,12 @@ retry:
goto next_record_is_invalid;
}
+ pgstat_report_wait_start(WAIT_EVENT_WAL_READ);
if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
{
char fname[MAXFNAMELEN];
+ pgstat_report_wait_end();
XLogFileName(fname, curFileTLI, readSegNo);
ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
(errcode_for_file_access(),
@@ -11150,6 +11622,7 @@ retry:
fname, readOff)));
goto next_record_is_invalid;
}
+ pgstat_report_wait_end();
Assert(targetSegNo == readSegNo);
Assert(targetPageOff == readOff);
@@ -11175,12 +11648,12 @@ next_record_is_invalid:
}
/*
- * Open the WAL segment containing WAL position 'RecPtr'.
+ * Open the WAL segment containing WAL location 'RecPtr'.
*
* The segment can be fetched via restore_command, or via walreceiver having
- * streamed the record, or it can already be present in pg_xlog. Checking
- * pg_xlog is mainly for crash recovery, but it will be polled in standby mode
- * too, in case someone copies a new segment directly to pg_xlog. That is not
+ * streamed the record, or it can already be present in pg_wal. Checking
+ * pg_wal is mainly for crash recovery, but it will be polled in standby mode
+ * too, in case someone copies a new segment directly to pg_wal. That is not
* documented or recommended, though.
*
* If 'fetching_ckpt' is true, we're fetching a checkpoint record, and should
@@ -11206,12 +11679,13 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
{
static TimestampTz last_fail_time = 0;
TimestampTz now;
+ bool streaming_reply_sent = false;
/*-------
* Standby mode is implemented by a state machine:
*
- * 1. Read from either archive or pg_xlog (XLOG_FROM_ARCHIVE), or just
- * pg_xlog (XLOG_FROM_XLOG)
+ * 1. Read from either archive or pg_wal (XLOG_FROM_ARCHIVE), or just
+ * pg_wal (XLOG_FROM_PG_WAL)
* 2. Check trigger file
* 3. Read from primary server via walreceiver (XLOG_FROM_STREAM)
* 4. Rescan timelines
@@ -11227,7 +11701,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
*-------
*/
if (!InArchiveRecovery)
- currentSource = XLOG_FROM_PG_XLOG;
+ currentSource = XLOG_FROM_PG_WAL;
else if (currentSource == 0)
currentSource = XLOG_FROM_ARCHIVE;
@@ -11246,13 +11720,13 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
switch (currentSource)
{
case XLOG_FROM_ARCHIVE:
- case XLOG_FROM_PG_XLOG:
+ case XLOG_FROM_PG_WAL:
/*
* Check to see if the trigger file exists. Note that we
* do this only after failure, so when you create the
* trigger file, we still finish replaying as much as we
- * can from archive and pg_xlog before failover.
+ * can from archive and pg_wal before failover.
*/
if (StandbyMode && CheckForStandbyTrigger())
{
@@ -11262,7 +11736,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
/*
* Not in standby mode, and we've now tried the archive
- * and pg_xlog.
+ * and pg_wal.
*/
if (!StandbyMode)
return false;
@@ -11322,8 +11796,8 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* little chance that the problem will just go away, but
* PANIC is not good for availability either, especially
* in hot standby mode. So, we treat that the same as
- * disconnection, and retry from archive/pg_xlog again.
- * The WAL in the archive should be identical to what was
+ * disconnection, and retry from archive/pg_wal again. The
+ * WAL in the archive should be identical to what was
* streamed, so it's unlikely that it helps, but one can
* hope...
*/
@@ -11371,7 +11845,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- wait_time);
+ wait_time, WAIT_EVENT_RECOVERY_WAL_STREAM);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
now = GetCurrentTimestamp();
}
@@ -11383,11 +11857,11 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
elog(ERROR, "unexpected WAL source %d", currentSource);
}
}
- else if (currentSource == XLOG_FROM_PG_XLOG)
+ else if (currentSource == XLOG_FROM_PG_WAL)
{
/*
- * We just successfully read a file in pg_xlog. We prefer files in
- * the archive over ones in pg_xlog, so try the next file again
+ * We just successfully read a file in pg_wal. We prefer files in
+ * the archive over ones in pg_wal, so try the next file again
* from the archive first.
*/
if (InArchiveRecovery)
@@ -11408,7 +11882,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
switch (currentSource)
{
case XLOG_FROM_ARCHIVE:
- case XLOG_FROM_PG_XLOG:
+ case XLOG_FROM_PG_WAL:
/* Close any old file we might have open. */
if (readFile >= 0)
{
@@ -11421,7 +11895,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
/*
* Try to restore the file from archive, or read an existing
- * file from pg_xlog.
+ * file from pg_wal.
*/
readFile = XLogFileReadAnyTLI(readSegNo, DEBUG2,
currentSource == XLOG_FROM_ARCHIVE ? XLOG_FROM_ANY :
@@ -11430,7 +11904,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
return true; /* success! */
/*
- * Nope, not found in archive or pg_xlog.
+ * Nope, not found in archive or pg_wal.
*/
lastSourceFailed = true;
break;
@@ -11486,9 +11960,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* not open already. Also read the timeline history
* file if we haven't initialized timeline history
* yet; it should be streamed over and present in
- * pg_xlog by now. Use XLOG_FROM_STREAM so that
- * source info is set correctly and XLogReceiptTime
- * isn't changed.
+ * pg_wal by now. Use XLOG_FROM_STREAM so that source
+ * info is set correctly and XLogReceiptTime isn't
+ * changed.
*/
if (readFile < 0)
{
@@ -11518,10 +11992,10 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
/*
* Note that we don't "return false" immediately here.
* After being triggered, we still want to replay all
- * the WAL that was already streamed. It's in pg_xlog
+ * the WAL that was already streamed. It's in pg_wal
* now, so we just treat this as a failure, and the
* state machine will move on to replay the streamed
- * WAL from pg_xlog, and then recheck the trigger and
+ * WAL from pg_wal, and then recheck the trigger and
* exit replay.
*/
lastSourceFailed = true;
@@ -11529,12 +12003,25 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
}
/*
+ * Since we have replayed everything we have received so
+ * far and are about to start waiting for more WAL, let's
+ * tell the upstream server our replay location now so
+ * that pg_stat_replication doesn't show stale
+ * information.
+ */
+ if (!streaming_reply_sent)
+ {
+ WalRcvForceReply();
+ streaming_reply_sent = true;
+ }
+
+ /*
* Wait for more WAL to arrive. Time out after 5 seconds
* to react to a trigger file promptly.
*/
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- 5000L);
+ 5000L, WAIT_EVENT_RECOVERY_WAL_ALL);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
break;
}
@@ -11561,7 +12048,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* or legitimate end-of-WAL situation. Generally, we use it as-is, but if
* we're retrying the exact same record that we've tried previously, only
* complain the first time to keep the noise down. However, we only do when
- * reading from pg_xlog, because we don't expect any invalid records in archive
+ * reading from pg_wal, because we don't expect any invalid records in archive
* or in records streamed from master. Files in the archive should be complete,
* and we should never hit the end of WAL because we stop and wait for more WAL
* to arrive before replaying it.
@@ -11576,7 +12063,7 @@ emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
{
static XLogRecPtr lastComplaint = 0;
- if (readSource == XLOG_FROM_PG_XLOG && emode == LOG)
+ if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
{
if (RecPtr == lastComplaint)
emode = DEBUG1;
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index d153a44ea9..7afb73579b 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -4,7 +4,7 @@
* Functions for archiving WAL files and restoring from the archive.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/xlogarchive.c
@@ -14,7 +14,6 @@
#include "postgres.h"
-#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
@@ -421,7 +420,7 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
/*
* A file was restored from the archive under a temporary filename (path),
* and now we want to keep it. Rename it under the permanent filename in
- * in pg_xlog (xlogfname), replacing any existing file with the same name.
+ * in pg_wal (xlogfname), replacing any existing file with the same name.
*/
void
KeepFileRestoredFromArchive(char *path, char *xlogfname)
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 33383b4dcc..b3223d691d 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -2,12 +2,12 @@
*
* xlogfuncs.c
*
- * PostgreSQL transaction log manager user interface functions
+ * PostgreSQL write-ahead log manager user interface functions
*
* This file contains WAL control and information functions.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/xlogfuncs.c
@@ -18,7 +18,6 @@
#include "access/htup_details.h"
#include "access/xlog.h"
-#include "access/xlog_fn.h"
#include "access/xlog_internal.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
@@ -43,8 +42,6 @@
*/
static StringInfo label_file;
static StringInfo tblspc_map_file;
-static bool exclusive_backup_running = false;
-static bool nonexclusive_backup_running = false;
/*
* Called when the backend exits with a running non-exclusive base backup,
@@ -73,16 +70,17 @@ nonexclusive_base_backup_cleanup(int code, Datum arg)
Datum
pg_start_backup(PG_FUNCTION_ARGS)
{
- text *backupid = PG_GETARG_TEXT_P(0);
+ text *backupid = PG_GETARG_TEXT_PP(0);
bool fast = PG_GETARG_BOOL(1);
bool exclusive = PG_GETARG_BOOL(2);
char *backupidstr;
XLogRecPtr startpoint;
DIR *dir;
+ SessionBackupState status = get_backup_status();
backupidstr = text_to_cstring(backupid);
- if (exclusive_backup_running || nonexclusive_backup_running)
+ if (status == SESSION_BACKUP_NON_EXCLUSIVE)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("a backup is already in progress in this session")));
@@ -97,7 +95,6 @@ pg_start_backup(PG_FUNCTION_ARGS)
{
startpoint = do_pg_start_backup(backupidstr, fast, NULL, NULL,
dir, NULL, NULL, false, true);
- exclusive_backup_running = true;
}
else
{
@@ -114,7 +111,6 @@ pg_start_backup(PG_FUNCTION_ARGS)
startpoint = do_pg_start_backup(backupidstr, fast, NULL, label_file,
dir, NULL, tblspc_map_file, false, true);
- nonexclusive_backup_running = true;
before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
}
@@ -128,7 +124,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
* pg_stop_backup: finish taking an on-line backup dump
*
* We write an end-of-backup WAL record, and remove the backup label file
- * created by pg_start_backup, creating a backup history file in pg_xlog
+ * created by pg_start_backup, creating a backup history file in pg_wal
* instead (whence it will immediately be archived). The backup history file
* contains the same info found in the label file, plus the backup-end time
* and WAL location. Before 9.0, the backup-end time was read from the backup
@@ -148,8 +144,9 @@ Datum
pg_stop_backup(PG_FUNCTION_ARGS)
{
XLogRecPtr stoppoint;
+ SessionBackupState status = get_backup_status();
- if (nonexclusive_backup_running)
+ if (status == SESSION_BACKUP_NON_EXCLUSIVE)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("non-exclusive backup in progress"),
@@ -157,14 +154,13 @@ pg_stop_backup(PG_FUNCTION_ARGS)
/*
* Exclusive backups were typically started in a different connection, so
- * don't try to verify that exclusive_backup_running is set in this one.
- * Actual verification that an exclusive backup is in fact running is
- * handled inside do_pg_stop_backup.
+ * don't try to verify that status of backup is set to
+ * SESSION_BACKUP_EXCLUSIVE in this function. Actual verification that an
+ * exclusive backup is in fact running is handled inside
+ * do_pg_stop_backup.
*/
stoppoint = do_pg_stop_backup(NULL, true, NULL);
- exclusive_backup_running = false;
-
PG_RETURN_LSN(stoppoint);
}
@@ -176,6 +172,13 @@ pg_stop_backup(PG_FUNCTION_ARGS)
* the backup label and tablespace map files as text fields in as part of the
* resultset.
*
+ * The first parameter (variable 'exclusive') allows the user to tell us if
+ * this is an exclusive or a non-exclusive backup.
+ *
+ * The second paramter (variable 'waitforarchive'), which is optional,
+ * allows the user to choose if they want to wait for the WAL to be archived
+ * or if we should just return as soon as the WAL record is written.
+ *
* Permission checking for this function is managed through the normal
* GRANT system.
*/
@@ -191,7 +194,9 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
bool nulls[3];
bool exclusive = PG_GETARG_BOOL(0);
+ bool waitforarchive = PG_GETARG_BOOL(1);
XLogRecPtr stoppoint;
+ SessionBackupState status = get_backup_status();
/* check to see if caller supports us returning a tuplestore */
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
@@ -223,7 +228,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
if (exclusive)
{
- if (nonexclusive_backup_running)
+ if (status == SESSION_BACKUP_NON_EXCLUSIVE)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("non-exclusive backup in progress"),
@@ -233,15 +238,14 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
* Stop the exclusive backup, and since we're in an exclusive backup
* return NULL for both backup_label and tablespace_map.
*/
- stoppoint = do_pg_stop_backup(NULL, true, NULL);
- exclusive_backup_running = false;
+ stoppoint = do_pg_stop_backup(NULL, waitforarchive, NULL);
nulls[1] = true;
nulls[2] = true;
}
else
{
- if (!nonexclusive_backup_running)
+ if (status != SESSION_BACKUP_NON_EXCLUSIVE)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("non-exclusive backup is not in progress"),
@@ -251,8 +255,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
* Stop the non-exclusive backup. Return a copy of the backup label
* and tablespace map so they can be written to disk by the caller.
*/
- stoppoint = do_pg_stop_backup(label_file->data, true, NULL);
- nonexclusive_backup_running = false;
+ stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
values[1] = CStringGetTextDatum(label_file->data);
@@ -277,13 +280,13 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
}
/*
- * pg_switch_xlog: switch to next xlog file
+ * pg_switch_wal: switch to next xlog file
*
* Permission checking for this function is managed through the normal
* GRANT system.
*/
Datum
-pg_switch_xlog(PG_FUNCTION_ARGS)
+pg_switch_wal(PG_FUNCTION_ARGS)
{
XLogRecPtr switchpoint;
@@ -293,7 +296,7 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
errmsg("recovery is in progress"),
errhint("WAL control functions cannot be executed during recovery.")));
- switchpoint = RequestXLogSwitch();
+ switchpoint = RequestXLogSwitch(false);
/*
* As a convenience, return the WAL location of the switch record
@@ -310,7 +313,7 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
Datum
pg_create_restore_point(PG_FUNCTION_ARGS)
{
- text *restore_name = PG_GETARG_TEXT_P(0);
+ text *restore_name = PG_GETARG_TEXT_PP(0);
char *restore_name_str;
XLogRecPtr restorepoint;
@@ -349,7 +352,7 @@ pg_create_restore_point(PG_FUNCTION_ARGS)
* to the kernel, but is not necessarily synced to disk.
*/
Datum
-pg_current_xlog_location(PG_FUNCTION_ARGS)
+pg_current_wal_lsn(PG_FUNCTION_ARGS)
{
XLogRecPtr current_recptr;
@@ -370,7 +373,7 @@ pg_current_xlog_location(PG_FUNCTION_ARGS)
* This function is mostly for debugging purposes.
*/
Datum
-pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
+pg_current_wal_insert_lsn(PG_FUNCTION_ARGS)
{
XLogRecPtr current_recptr;
@@ -391,7 +394,7 @@ pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
* This function is mostly for debugging purposes.
*/
Datum
-pg_current_xlog_flush_location(PG_FUNCTION_ARGS)
+pg_current_wal_flush_lsn(PG_FUNCTION_ARGS)
{
XLogRecPtr current_recptr;
@@ -413,7 +416,7 @@ pg_current_xlog_flush_location(PG_FUNCTION_ARGS)
* and synced to disk by walreceiver.
*/
Datum
-pg_last_xlog_receive_location(PG_FUNCTION_ARGS)
+pg_last_wal_receive_lsn(PG_FUNCTION_ARGS)
{
XLogRecPtr recptr;
@@ -432,7 +435,7 @@ pg_last_xlog_receive_location(PG_FUNCTION_ARGS)
* connections during recovery.
*/
Datum
-pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
+pg_last_wal_replay_lsn(PG_FUNCTION_ARGS)
{
XLogRecPtr recptr;
@@ -453,7 +456,7 @@ pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
* expected usage is to determine which xlog file(s) are ready to archive.
*/
Datum
-pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
+pg_walfile_name_offset(PG_FUNCTION_ARGS)
{
XLogSegNo xlogsegno;
uint32 xrecoff;
@@ -469,7 +472,7 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
- errhint("pg_xlogfile_name_offset() cannot be executed during recovery.")));
+ errhint("pg_walfile_name_offset() cannot be executed during recovery.")));
/*
* Construct a tuple descriptor for the result row. This must match this
@@ -515,7 +518,7 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
* such as is returned by pg_stop_backup() or pg_xlog_switch().
*/
Datum
-pg_xlogfile_name(PG_FUNCTION_ARGS)
+pg_walfile_name(PG_FUNCTION_ARGS)
{
XLogSegNo xlogsegno;
XLogRecPtr locationpoint = PG_GETARG_LSN(0);
@@ -525,7 +528,7 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
- errhint("pg_xlogfile_name() cannot be executed during recovery.")));
+ errhint("pg_walfile_name() cannot be executed during recovery.")));
XLByteToPrevSeg(locationpoint, xlogsegno);
XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno);
@@ -534,13 +537,13 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
}
/*
- * pg_xlog_replay_pause - pause recovery now
+ * pg_wal_replay_pause - pause recovery now
*
* Permission checking for this function is managed through the normal
* GRANT system.
*/
Datum
-pg_xlog_replay_pause(PG_FUNCTION_ARGS)
+pg_wal_replay_pause(PG_FUNCTION_ARGS)
{
if (!RecoveryInProgress())
ereport(ERROR,
@@ -554,13 +557,13 @@ pg_xlog_replay_pause(PG_FUNCTION_ARGS)
}
/*
- * pg_xlog_replay_resume - resume recovery now
+ * pg_wal_replay_resume - resume recovery now
*
* Permission checking for this function is managed through the normal
* GRANT system.
*/
Datum
-pg_xlog_replay_resume(PG_FUNCTION_ARGS)
+pg_wal_replay_resume(PG_FUNCTION_ARGS)
{
if (!RecoveryInProgress())
ereport(ERROR,
@@ -574,10 +577,10 @@ pg_xlog_replay_resume(PG_FUNCTION_ARGS)
}
/*
- * pg_is_xlog_replay_paused
+ * pg_is_wal_replay_paused
*/
Datum
-pg_is_xlog_replay_paused(PG_FUNCTION_ARGS)
+pg_is_wal_replay_paused(PG_FUNCTION_ARGS)
{
if (!RecoveryInProgress())
ereport(ERROR,
@@ -619,7 +622,7 @@ pg_is_in_recovery(PG_FUNCTION_ARGS)
* Compute the difference in bytes between two WAL locations.
*/
Datum
-pg_xlog_location_diff(PG_FUNCTION_ARGS)
+pg_wal_lsn_diff(PG_FUNCTION_ARGS)
{
Datum result;
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index c37003a24c..6a02738479 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -9,7 +9,7 @@
* of XLogRecData structs by a call to XLogRecordAssemble(). See
* access/transam/README for details.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/xloginsert.c
@@ -73,8 +73,8 @@ static XLogRecData *mainrdata_head;
static XLogRecData *mainrdata_last = (XLogRecData *) &mainrdata_head;
static uint32 mainrdata_len; /* total # of bytes in chain */
-/* Should the in-progress insertion log the origin? */
-static bool include_origin = false;
+/* flags for the in-progress insertion */
+static uint8 curinsert_flags = 0;
/*
* These are used to hold the record header while constructing a record.
@@ -201,7 +201,7 @@ XLogResetInsertion(void)
max_registered_block_id = 0;
mainrdata_len = 0;
mainrdata_last = (XLogRecData *) &mainrdata_head;
- include_origin = false;
+ curinsert_flags = 0;
begininsert_called = false;
}
@@ -384,13 +384,20 @@ XLogRegisterBufData(uint8 block_id, char *data, int len)
}
/*
- * Should this record include the replication origin if one is set up?
+ * Set insert status flags for the upcoming WAL record.
+ *
+ * The flags that can be used here are:
+ * - XLOG_INCLUDE_ORIGIN, to determine if the replication origin should be
+ * included in the record.
+ * - XLOG_MARK_UNIMPORTANT, to signal that the record is not important for
+ * durability, which allows to avoid triggering WAL archiving and other
+ * background activity.
*/
void
-XLogIncludeOrigin(void)
+XLogSetRecordFlags(uint8 flags)
{
Assert(begininsert_called);
- include_origin = true;
+ curinsert_flags = flags;
}
/*
@@ -414,13 +421,15 @@ XLogInsert(RmgrId rmid, uint8 info)
elog(ERROR, "XLogBeginInsert was not called");
/*
- * The caller can set rmgr bits and XLR_SPECIAL_REL_UPDATE; the rest are
- * reserved for use by me.
+ * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and
+ * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me.
*/
- if ((info & ~(XLR_RMGR_INFO_MASK | XLR_SPECIAL_REL_UPDATE)) != 0)
+ if ((info & ~(XLR_RMGR_INFO_MASK |
+ XLR_SPECIAL_REL_UPDATE |
+ XLR_CHECK_CONSISTENCY)) != 0)
elog(PANIC, "invalid xlog info mask %02X", info);
- TRACE_POSTGRESQL_XLOG_INSERT(rmid, info);
+ TRACE_POSTGRESQL_WAL_INSERT(rmid, info);
/*
* In bootstrap mode, we don't actually log anything but XLOG resources;
@@ -450,7 +459,7 @@ XLogInsert(RmgrId rmid, uint8 info)
rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
&fpw_lsn);
- EndPos = XLogInsertRecord(rdt, fpw_lsn);
+ EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags);
} while (EndPos == InvalidXLogRecPtr);
XLogResetInsertion();
@@ -498,6 +507,15 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
hdr_rdt.data = hdr_scratch;
/*
+ * Enforce consistency checks for this record if user is looking for it.
+ * Do this before at the beginning of this routine to give the possibility
+ * for callers of XLogInsert() to pass XLR_CHECK_CONSISTENCY directly for
+ * a record.
+ */
+ if (wal_consistency_checking[rmid])
+ info |= XLR_CHECK_CONSISTENCY;
+
+ /*
* Make an rdata chain containing all the data portions of all block
* references. This includes the data for full-page images. Also append
* the headers for the block references in the scratch buffer.
@@ -513,6 +531,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
XLogRecordBlockCompressHeader cbimg = {0};
bool samerel;
bool is_compressed = false;
+ bool include_image;
if (!regbuf->in_use)
continue;
@@ -556,7 +575,13 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
if ((regbuf->flags & REGBUF_WILL_INIT) == REGBUF_WILL_INIT)
bkpb.fork_flags |= BKPBLOCK_WILL_INIT;
- if (needs_backup)
+ /*
+ * If needs_backup is true or WAL checking is enabled for current
+ * resource manager, log a full-page write for the current block.
+ */
+ include_image = needs_backup || (info & XLR_CHECK_CONSISTENCY) != 0;
+
+ if (include_image)
{
Page page = regbuf->page;
uint16 compressed_len;
@@ -618,6 +643,15 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
bimg.bimg_info = (cbimg.hole_length == 0) ? 0 : BKPIMAGE_HAS_HOLE;
+ /*
+ * If WAL consistency checking is enabled for the resource manager
+ * of this WAL record, a full-page image is included in the record
+ * for the block modified. During redo, the full-page is replayed
+ * only if BKPIMAGE_APPLY is set.
+ */
+ if (needs_backup)
+ bimg.bimg_info |= BKPIMAGE_APPLY;
+
if (is_compressed)
{
bimg.length = compressed_len;
@@ -680,7 +714,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
/* Ok, copy the header to the scratch buffer */
memcpy(scratch, &bkpb, SizeOfXLogRecordBlockHeader);
scratch += SizeOfXLogRecordBlockHeader;
- if (needs_backup)
+ if (include_image)
{
memcpy(scratch, &bimg, SizeOfXLogRecordBlockImageHeader);
scratch += SizeOfXLogRecordBlockImageHeader;
@@ -701,9 +735,10 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
}
/* followed by the record's origin, if any */
- if (include_origin && replorigin_session_origin != InvalidRepOriginId)
+ if ((curinsert_flags & XLOG_INCLUDE_ORIGIN) &&
+ replorigin_session_origin != InvalidRepOriginId)
{
- *(scratch++) = XLR_BLOCK_ID_ORIGIN;
+ *(scratch++) = (char) XLR_BLOCK_ID_ORIGIN;
memcpy(scratch, &replorigin_session_origin, sizeof(replorigin_session_origin));
scratch += sizeof(replorigin_session_origin);
}
@@ -713,13 +748,13 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
{
if (mainrdata_len > 255)
{
- *(scratch++) = XLR_BLOCK_ID_DATA_LONG;
+ *(scratch++) = (char) XLR_BLOCK_ID_DATA_LONG;
memcpy(scratch, &mainrdata_len, sizeof(uint32));
scratch += sizeof(uint32);
}
else
{
- *(scratch++) = XLR_BLOCK_ID_DATA_SHORT;
+ *(scratch++) = (char) XLR_BLOCK_ID_DATA_SHORT;
*(scratch++) = (uint8) mainrdata_len;
}
rdt_datas_last->next = mainrdata_head;
@@ -997,9 +1032,7 @@ InitXLogInsert(void)
{
xloginsert_cxt = AllocSetContextCreate(TopMemoryContext,
"WAL record construction",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
}
if (registered_buffers == NULL)
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index dcf747c633..c3b1371764 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -3,7 +3,7 @@
* xlogreader.c
* Generic XLog reading facility
*
- * Portions Copyright (c) 2013-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2013-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/access/transam/xlogreader.c
@@ -462,7 +462,8 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
/*
* Special processing if it's an XLOG SWITCH record
*/
- if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_SWITCH)
+ if (record->xl_rmid == RM_XLOG_ID &&
+ (record->xl_info & ~XLR_INFO_MASK) == XLOG_SWITCH)
{
/* Pretend it extends to end of segment */
state->EndRecPtr += XLogSegSize - 1;
@@ -866,46 +867,83 @@ XLogRecPtr
XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
{
XLogReaderState saved_state = *state;
- XLogRecPtr targetPagePtr;
XLogRecPtr tmpRecPtr;
- int targetRecOff;
XLogRecPtr found = InvalidXLogRecPtr;
- uint32 pageHeaderSize;
XLogPageHeader header;
- int readLen;
char *errormsg;
Assert(!XLogRecPtrIsInvalid(RecPtr));
- targetRecOff = RecPtr % XLOG_BLCKSZ;
+ /*
+ * skip over potential continuation data, keeping in mind that it may span
+ * multiple pages
+ */
+ tmpRecPtr = RecPtr;
+ while (true)
+ {
+ XLogRecPtr targetPagePtr;
+ int targetRecOff;
+ uint32 pageHeaderSize;
+ int readLen;
- /* scroll back to page boundary */
- targetPagePtr = RecPtr - targetRecOff;
+ /*
+ * Compute targetRecOff. It should typically be equal or greater than
+ * short page-header since a valid record can't start anywhere before
+ * that, except when caller has explicitly specified the offset that
+ * falls somewhere there or when we are skipping multi-page
+ * continuation record. It doesn't matter though because
+ * ReadPageInternal() is prepared to handle that and will read at
+ * least short page-header worth of data
+ */
+ targetRecOff = tmpRecPtr % XLOG_BLCKSZ;
- /* Read the page containing the record */
- readLen = ReadPageInternal(state, targetPagePtr, targetRecOff);
- if (readLen < 0)
- goto err;
+ /* scroll back to page boundary */
+ targetPagePtr = tmpRecPtr - targetRecOff;
- header = (XLogPageHeader) state->readBuf;
+ /* Read the page containing the record */
+ readLen = ReadPageInternal(state, targetPagePtr, targetRecOff);
+ if (readLen < 0)
+ goto err;
- pageHeaderSize = XLogPageHeaderSize(header);
+ header = (XLogPageHeader) state->readBuf;
- /* make sure we have enough data for the page header */
- readLen = ReadPageInternal(state, targetPagePtr, pageHeaderSize);
- if (readLen < 0)
- goto err;
+ pageHeaderSize = XLogPageHeaderSize(header);
- /* skip over potential continuation data */
- if (header->xlp_info & XLP_FIRST_IS_CONTRECORD)
- {
- /* record headers are MAXALIGN'ed */
- tmpRecPtr = targetPagePtr + pageHeaderSize
- + MAXALIGN(header->xlp_rem_len);
- }
- else
- {
- tmpRecPtr = targetPagePtr + pageHeaderSize;
+ /* make sure we have enough data for the page header */
+ readLen = ReadPageInternal(state, targetPagePtr, pageHeaderSize);
+ if (readLen < 0)
+ goto err;
+
+ /* skip over potential continuation data */
+ if (header->xlp_info & XLP_FIRST_IS_CONTRECORD)
+ {
+ /*
+ * If the length of the remaining continuation data is more than
+ * what can fit in this page, the continuation record crosses over
+ * this page. Read the next page and try again. xlp_rem_len in the
+ * next page header will contain the remaining length of the
+ * continuation data
+ *
+ * Note that record headers are MAXALIGN'ed
+ */
+ if (MAXALIGN(header->xlp_rem_len) > (XLOG_BLCKSZ - pageHeaderSize))
+ tmpRecPtr = targetPagePtr + XLOG_BLCKSZ;
+ else
+ {
+ /*
+ * The previous continuation record ends in this page. Set
+ * tmpRecPtr to point to the first valid record
+ */
+ tmpRecPtr = targetPagePtr + pageHeaderSize
+ + MAXALIGN(header->xlp_rem_len);
+ break;
+ }
+ }
+ else
+ {
+ tmpRecPtr = targetPagePtr + pageHeaderSize;
+ break;
+ }
}
/*
@@ -959,6 +997,7 @@ ResetDecoder(XLogReaderState *state)
state->blocks[block_id].in_use = false;
state->blocks[block_id].has_image = false;
state->blocks[block_id].has_data = false;
+ state->blocks[block_id].apply_image = false;
}
state->max_block_id = -1;
}
@@ -1051,6 +1090,7 @@ DecodeXLogRecord(XLogReaderState *state, XLogRecord *record, char **errormsg)
blk = &state->blocks[block_id];
blk->in_use = true;
+ blk->apply_image = false;
COPY_HEADER_FIELD(&fork_flags, sizeof(uint8));
blk->forknum = fork_flags & BKPBLOCK_FORK_MASK;
@@ -1082,6 +1122,9 @@ DecodeXLogRecord(XLogReaderState *state, XLogRecord *record, char **errormsg)
COPY_HEADER_FIELD(&blk->bimg_len, sizeof(uint16));
COPY_HEADER_FIELD(&blk->hole_offset, sizeof(uint16));
COPY_HEADER_FIELD(&blk->bimg_info, sizeof(uint8));
+
+ blk->apply_image = ((blk->bimg_info & BKPIMAGE_APPLY) != 0);
+
if (blk->bimg_info & BKPIMAGE_IS_COMPRESSED)
{
if (blk->bimg_info & BKPIMAGE_HAS_HOLE)
@@ -1205,6 +1248,9 @@ DecodeXLogRecord(XLogReaderState *state, XLogRecord *record, char **errormsg)
if (!blk->in_use)
continue;
+
+ Assert(blk->has_image || !blk->apply_image);
+
if (blk->has_image)
{
blk->bkp_image = ptr;
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 1bdbea655b..4f67dc62fb 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -2,13 +2,13 @@
*
* xlogutils.c
*
- * PostgreSQL transaction log manager utility routines
+ * PostgreSQL write-ahead log manager utility routines
*
* This file contains support routines that are used by XLOG replay functions.
* None of this code is used during normal system operation.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/xlogutils.c
@@ -20,11 +20,13 @@
#include <unistd.h>
#include "miscadmin.h"
+#include "access/timeline.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/smgr.h"
#include "utils/guc.h"
#include "utils/hsearch.h"
@@ -276,9 +278,9 @@ XLogCheckInvalidPages(void)
* will complain if we don't have the lock. In hot standby mode it's
* definitely necessary.)
*
- * Note: when a backup block is available in XLOG, we restore it
- * unconditionally, even if the page in the database appears newer. This is
- * to protect ourselves against database pages that were partially or
+ * Note: when a backup block is available in XLOG with the BKPIMAGE_APPLY flag
+ * set, we restore it, even if the page in the database appears newer. This
+ * is to protect ourselves against database pages that were partially or
* incorrectly written during a crash. We assume that the XLOG data must be
* good because it has passed a CRC check, while the database page might not
* be. This will force us to replay all subsequent modifications of the page
@@ -353,9 +355,10 @@ XLogReadBufferForRedoExtended(XLogReaderState *record,
if (!willinit && zeromode)
elog(PANIC, "block to be initialized in redo routine must be marked with WILL_INIT flag in the WAL record");
- /* If it's a full-page image, restore it. */
- if (XLogRecHasBlockImage(record, block_id))
+ /* If it has a full-page image and it should be restored, do it. */
+ if (XLogRecBlockImageApply(record, block_id))
{
+ Assert(XLogRecHasBlockImage(record, block_id));
*buf = XLogReadBufferExtended(rnode, forknum, blkno,
get_cleanup_lock ? RBM_ZERO_AND_CLEANUP_LOCK : RBM_ZERO_AND_LOCK);
page = BufferGetPage(*buf);
@@ -647,7 +650,7 @@ XLogTruncateRelation(RelFileNode rnode, ForkNumber forkNum,
* always be one descriptor left open until the process ends, but never
* more than one.
*
- * XXX This is very similar to pg_xlogdump's XLogDumpXLogRead and to XLogRead
+ * XXX This is very similar to pg_waldump's XLogDumpXLogRead and to XLogRead
* in walsender.c but for small differences (such as lack of elog() in
* frontend). Probably these should be merged at some point.
*/
@@ -661,6 +664,7 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
/* state maintained across calls */
static int sendFile = -1;
static XLogSegNo sendSegNo = 0;
+ static TimeLineID sendTLI = 0;
static uint32 sendOff = 0;
p = buf;
@@ -676,7 +680,8 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
startoff = recptr % XLogSegSize;
/* Do we need to switch to a different xlog segment? */
- if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo))
+ if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo) ||
+ sendTLI != tli)
{
char path[MAXPGPATH];
@@ -703,6 +708,7 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
path)));
}
sendOff = 0;
+ sendTLI = tli;
}
/* Need to seek in the file? */
@@ -728,7 +734,9 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
else
segbytes = nbytes;
+ pgstat_report_wait_start(WAIT_EVENT_WAL_READ);
readbytes = read(sendFile, p, segbytes);
+ pgstat_report_wait_end();
if (readbytes <= 0)
{
char path[MAXPGPATH];
@@ -751,6 +759,137 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
}
/*
+ * Determine which timeline to read an xlog page from and set the
+ * XLogReaderState's currTLI to that timeline ID.
+ *
+ * We care about timelines in xlogreader when we might be reading xlog
+ * generated prior to a promotion, either if we're currently a standby in
+ * recovery or if we're a promoted master reading xlogs generated by the old
+ * master before our promotion.
+ *
+ * wantPage must be set to the start address of the page to read and
+ * wantLength to the amount of the page that will be read, up to
+ * XLOG_BLCKSZ. If the amount to be read isn't known, pass XLOG_BLCKSZ.
+ *
+ * We switch to an xlog segment from the new timeline eagerly when on a
+ * historical timeline, as soon as we reach the start of the xlog segment
+ * containing the timeline switch. The server copied the segment to the new
+ * timeline so all the data up to the switch point is the same, but there's no
+ * guarantee the old segment will still exist. It may have been deleted or
+ * renamed with a .partial suffix so we can't necessarily keep reading from
+ * the old TLI even though tliSwitchPoint says it's OK.
+ *
+ * We can't just check the timeline when we read a page on a different segment
+ * to the last page. We could've received a timeline switch from a cascading
+ * upstream, so the current segment ends abruptly (possibly getting renamed to
+ * .partial) and we have to switch to a new one. Even in the middle of reading
+ * a page we could have to dump the cached page and switch to a new TLI.
+ *
+ * Because of this, callers MAY NOT assume that currTLI is the timeline that
+ * will be in a page's xlp_tli; the page may begin on an older timeline or we
+ * might be reading from historical timeline data on a segment that's been
+ * copied to a new timeline.
+ *
+ * The caller must also make sure it doesn't read past the current replay
+ * position (using GetWalRcvWriteRecPtr) if executing in recovery, so it
+ * doesn't fail to notice that the current timeline became historical. The
+ * caller must also update ThisTimeLineID with the result of
+ * GetWalRcvWriteRecPtr and must check RecoveryInProgress().
+ */
+void
+XLogReadDetermineTimeline(XLogReaderState *state, XLogRecPtr wantPage, uint32 wantLength)
+{
+ const XLogRecPtr lastReadPage = state->readSegNo * XLogSegSize + state->readOff;
+
+ Assert(wantPage != InvalidXLogRecPtr && wantPage % XLOG_BLCKSZ == 0);
+ Assert(wantLength <= XLOG_BLCKSZ);
+ Assert(state->readLen == 0 || state->readLen <= XLOG_BLCKSZ);
+
+ /*
+ * If the desired page is currently read in and valid, we have nothing to
+ * do.
+ *
+ * The caller should've ensured that it didn't previously advance readOff
+ * past the valid limit of this timeline, so it doesn't matter if the
+ * current TLI has since become historical.
+ */
+ if (lastReadPage == wantPage &&
+ state->readLen != 0 &&
+ lastReadPage + state->readLen >= wantPage + Min(wantLength, XLOG_BLCKSZ - 1))
+ return;
+
+ /*
+ * If we're reading from the current timeline, it hasn't become historical
+ * and the page we're reading is after the last page read, we can again
+ * just carry on. (Seeking backwards requires a check to make sure the
+ * older page isn't on a prior timeline).
+ *
+ * ThisTimeLineID might've become historical since we last looked, but the
+ * caller is required not to read past the flush limit it saw at the time
+ * it looked up the timeline. There's nothing we can do about it if
+ * StartupXLOG() renames it to .partial concurrently.
+ */
+ if (state->currTLI == ThisTimeLineID && wantPage >= lastReadPage)
+ {
+ Assert(state->currTLIValidUntil == InvalidXLogRecPtr);
+ return;
+ }
+
+ /*
+ * If we're just reading pages from a previously validated historical
+ * timeline and the timeline we're reading from is valid until the end of
+ * the current segment we can just keep reading.
+ */
+ if (state->currTLIValidUntil != InvalidXLogRecPtr &&
+ state->currTLI != ThisTimeLineID &&
+ state->currTLI != 0 &&
+ (wantPage + wantLength) / XLogSegSize < state->currTLIValidUntil / XLogSegSize)
+ return;
+
+ /*
+ * If we reach this point we're either looking up a page for random
+ * access, the current timeline just became historical, or we're reading
+ * from a new segment containing a timeline switch. In all cases we need
+ * to determine the newest timeline on the segment.
+ *
+ * If it's the current timeline we can just keep reading from here unless
+ * we detect a timeline switch that makes the current timeline historical.
+ * If it's a historical timeline we can read all the segment on the newest
+ * timeline because it contains all the old timelines' data too. So only
+ * one switch check is required.
+ */
+ {
+ /*
+ * We need to re-read the timeline history in case it's been changed
+ * by a promotion or replay from a cascaded replica.
+ */
+ List *timelineHistory = readTimeLineHistory(ThisTimeLineID);
+
+ XLogRecPtr endOfSegment = (((wantPage / XLogSegSize) + 1) * XLogSegSize) - 1;
+
+ Assert(wantPage / XLogSegSize == endOfSegment / XLogSegSize);
+
+ /*
+ * Find the timeline of the last LSN on the segment containing
+ * wantPage.
+ */
+ state->currTLI = tliOfPointInHistory(endOfSegment, timelineHistory);
+ state->currTLIValidUntil = tliSwitchPoint(state->currTLI, timelineHistory,
+ &state->nextTLI);
+
+ Assert(state->currTLIValidUntil == InvalidXLogRecPtr ||
+ wantPage + wantLength < state->currTLIValidUntil);
+
+ list_free_deep(timelineHistory);
+
+ elog(DEBUG3, "switched to timeline %u valid until %X/%X",
+ state->currTLI,
+ (uint32) (state->currTLIValidUntil >> 32),
+ (uint32) (state->currTLIValidUntil));
+ }
+}
+
+/*
* read_page callback for reading local xlog files
*
* Public because it would likely be very helpful for someone writing another
@@ -771,28 +910,85 @@ read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr,
int count;
loc = targetPagePtr + reqLen;
+
+ /* Loop waiting for xlog to be available if necessary */
while (1)
{
/*
- * TODO: we're going to have to do something more intelligent about
- * timelines on standbys. Use readTimeLineHistory() and
- * tliOfPointInHistory() to get the proper LSN? For now we'll catch
- * that case earlier, but the code and TODO is left in here for when
- * that changes.
+ * Determine the limit of xlog we can currently read to, and what the
+ * most recent timeline is.
+ *
+ * RecoveryInProgress() will update ThisTimeLineID when it first
+ * notices recovery finishes, so we only have to maintain it for the
+ * local process until recovery ends.
*/
if (!RecoveryInProgress())
- {
- *pageTLI = ThisTimeLineID;
read_upto = GetFlushRecPtr();
- }
else
- read_upto = GetXLogReplayRecPtr(pageTLI);
+ read_upto = GetXLogReplayRecPtr(&ThisTimeLineID);
- if (loc <= read_upto)
- break;
+ *pageTLI = ThisTimeLineID;
+
+ /*
+ * Check which timeline to get the record from.
+ *
+ * We have to do it each time through the loop because if we're in
+ * recovery as a cascading standby, the current timeline might've
+ * become historical. We can't rely on RecoveryInProgress() because in
+ * a standby configuration like
+ *
+ * A => B => C
+ *
+ * if we're a logical decoding session on C, and B gets promoted, our
+ * timeline will change while we remain in recovery.
+ *
+ * We can't just keep reading from the old timeline as the last WAL
+ * archive in the timeline will get renamed to .partial by
+ * StartupXLOG().
+ *
+ * If that happens after our caller updated ThisTimeLineID but before
+ * we actually read the xlog page, we might still try to read from the
+ * old (now renamed) segment and fail. There's not much we can do
+ * about this, but it can only happen when we're a leaf of a cascading
+ * standby whose master gets promoted while we're decoding, so a
+ * one-off ERROR isn't too bad.
+ */
+ XLogReadDetermineTimeline(state, targetPagePtr, reqLen);
+
+ if (state->currTLI == ThisTimeLineID)
+ {
- CHECK_FOR_INTERRUPTS();
- pg_usleep(1000L);
+ if (loc <= read_upto)
+ break;
+
+ CHECK_FOR_INTERRUPTS();
+ pg_usleep(1000L);
+ }
+ else
+ {
+ /*
+ * We're on a historical timeline, so limit reading to the switch
+ * point where we moved to the next timeline.
+ *
+ * We don't need to GetFlushRecPtr or GetXLogReplayRecPtr. We know
+ * about the new timeline, so we must've received past the end of
+ * it.
+ */
+ read_upto = state->currTLIValidUntil;
+
+ /*
+ * Setting pageTLI to our wanted record's TLI is slightly wrong;
+ * the page might begin on an older timeline if it contains a
+ * timeline switch, since its xlog segment will have been copied
+ * from the prior timeline. This is pretty harmless though, as
+ * nothing cares so long as the timeline doesn't go backwards. We
+ * should read the page header instead; FIXME someday.
+ */
+ *pageTLI = state->currTLI;
+
+ /* No need to wait on a historical timeline */
+ break;
+ }
}
if (targetPagePtr + XLOG_BLCKSZ <= read_upto)
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 41d2fd4a5f..de3695c7e0 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -4,7 +4,7 @@
* bootparse.y
* yacc grammar for the "bootstrap" mode (BKI file format)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,7 +22,6 @@
#include "access/htup.h"
#include "access/itup.h"
#include "access/tupdesc.h"
-#include "access/xact.h"
#include "bootstrap/bootstrap.h"
#include "catalog/catalog.h"
#include "catalog/heap.h"
@@ -49,10 +48,9 @@
#include "storage/off.h"
#include "storage/smgr.h"
#include "tcop/dest.h"
+#include "utils/memutils.h"
#include "utils/rel.h"
-#define atooid(x) ((Oid) strtoul((x), NULL, 10))
-
/*
* Bison doesn't allocate anything that needs to live across parser calls,
@@ -65,19 +63,27 @@
#define YYMALLOC palloc
#define YYFREE pfree
+static MemoryContext per_line_ctx = NULL;
+
static void
do_start(void)
{
- StartTransactionCommand();
- elog(DEBUG4, "start transaction");
+ Assert(CurrentMemoryContext == CurTransactionContext);
+ /* First time through, create the per-line working context */
+ if (per_line_ctx == NULL)
+ per_line_ctx = AllocSetContextCreate(CurTransactionContext,
+ "bootstrap per-line processing",
+ ALLOCSET_DEFAULT_SIZES);
+ MemoryContextSwitchTo(per_line_ctx);
}
static void
do_end(void)
{
- CommitTransactionCommand();
- elog(DEBUG4, "commit transaction");
+ /* Reclaim memory allocated while processing this line */
+ MemoryContextSwitchTo(CurTransactionContext);
+ MemoryContextReset(per_line_ctx);
CHECK_FOR_INTERRUPTS(); /* allow SIGINT to kill bootstrap run */
if (isatty(0))
{
@@ -105,11 +111,11 @@ static int num_columns_read = 0;
%type <list> boot_index_params
%type <ielem> boot_index_param
-%type <str> boot_const boot_ident
+%type <str> boot_ident
%type <ival> optbootstrap optsharedrelation optwithoutoids boot_column_nullness
%type <oidval> oidspec optoideq optrowtypeoid
-%token <str> CONST_P ID
+%token <str> ID
%token OPEN XCLOSE XCREATE INSERT_TUPLE
%token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST
%token COMMA EQUALS LPAREN RPAREN
@@ -464,16 +470,10 @@ boot_column_val_list:
boot_column_val:
boot_ident
{ InsertOneValue($1, num_columns_read++); }
- | boot_const
- { InsertOneValue($1, num_columns_read++); }
| NULLVAL
{ InsertOneNull(num_columns_read++); }
;
-boot_const :
- CONST_P { $$ = yylval.str; }
- ;
-
boot_ident :
ID { $$ = yylval.str; }
;
diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l
index 0e1413bff9..6467882fa3 100644
--- a/src/backend/bootstrap/bootscanner.l
+++ b/src/backend/bootstrap/bootscanner.l
@@ -4,7 +4,7 @@
* bootscanner.l
* a lexical scanner for the bootstrap parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -66,7 +66,6 @@ static int yyline = 1; /* line number for error reporting */
D [0-9]
oct \\{D}{D}{D}
-Exp [Ee][-+]?{D}+
id ([A-Za-z0-9_]|{oct}|\-)+
sid \"([^\"])*\"
arrayid [A-Za-z0-9_]+\[{D}*\]
@@ -127,13 +126,6 @@ insert { return(INSERT_TUPLE); }
return(ID);
}
-(-)?{D}+"."{D}*({Exp})? |
-(-)?{D}*"."{D}+({Exp})? |
-(-)?{D}+{Exp} {
- yylval.str = pstrdup(yytext);
- return(CONST_P);
- }
-
. {
elog(ERROR, "syntax error at line %d: unexpected character \"%s\"", yyline, yytext);
}
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 86732f73d8..c2274ae2ff 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -5,7 +5,7 @@
* bootstrap mode is used to create the initial template database
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -20,6 +20,7 @@
#include <signal.h>
#include "access/htup_details.h"
+#include "access/xact.h"
#include "bootstrap/bootstrap.h"
#include "catalog/index.h"
#include "catalog/pg_collation.h"
@@ -36,6 +37,7 @@
#include "replication/walreceiver.h"
#include "storage/bufmgr.h"
#include "storage/bufpage.h"
+#include "storage/condition_variable.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "tcop/tcopprot.h"
@@ -56,7 +58,8 @@
uint32 bootstrap_data_checksum_version = 0; /* No checksum */
-#define ALLOC(t, c) ((t *) calloc((unsigned)(c), sizeof(t)))
+#define ALLOC(t, c) \
+ ((t *) MemoryContextAllocZero(TopMemoryContext, (unsigned)(c) * sizeof(t)))
static void CheckerModeMain(void);
static void BootstrapModeMain(void);
@@ -236,7 +239,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
break;
case 'D':
- userDoption = strdup(optarg);
+ userDoption = pstrdup(optarg);
break;
case 'd':
{
@@ -408,6 +411,10 @@ AuxiliaryProcessMain(int argc, char *argv[])
/* finish setting up bufmgr.c */
InitBufferPoolBackend();
+ /* Initialize backend status information */
+ pgstat_initialize();
+ pgstat_bestart();
+
/* register a before-shutdown callback for LWLock cleanup */
before_shmem_exit(ShutdownAuxiliaryProcess, 0);
}
@@ -525,7 +532,9 @@ BootstrapModeMain(void)
/*
* Process bootstrap input.
*/
+ StartTransactionCommand();
boot_yyparse();
+ CommitTransactionCommand();
/*
* We should now know about all mapped relations, so it's okay to write
@@ -570,6 +579,7 @@ static void
ShutdownAuxiliaryProcess(int code, Datum arg)
{
LWLockReleaseAll();
+ ConditionVariableCancelSleep();
pgstat_report_wait_end();
}
@@ -1037,13 +1047,8 @@ boot_get_type_io_data(Oid typid,
static Form_pg_attribute
AllocateAttribute(void)
{
- Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_FIXED_PART_SIZE);
-
- if (!PointerIsValid(attribute))
- elog(FATAL, "out of memory");
- MemSet(attribute, 0, ATTRIBUTE_FIXED_PART_SIZE);
-
- return attribute;
+ return (Form_pg_attribute)
+ MemoryContextAllocZero(TopMemoryContext, ATTRIBUTE_FIXED_PART_SIZE);
}
/*
@@ -1104,9 +1109,7 @@ index_register(Oid heap,
if (nogc == NULL)
nogc = AllocSetContextCreate(NULL,
"BootstrapNoGC",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(nogc);
@@ -1117,13 +1120,13 @@ index_register(Oid heap,
memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
/* expressions will likely be null, but may as well copy it */
- newind->il_info->ii_Expressions = (List *)
+ newind->il_info->ii_Expressions =
copyObject(indexInfo->ii_Expressions);
newind->il_info->ii_ExpressionsState = NIL;
/* predicate will likely be null, but may as well copy it */
- newind->il_info->ii_Predicate = (List *)
+ newind->il_info->ii_Predicate =
copyObject(indexInfo->ii_Predicate);
- newind->il_info->ii_PredicateState = NIL;
+ newind->il_info->ii_PredicateState = NULL;
/* no exclusion constraints at bootstrap time, so no need to copy */
Assert(indexInfo->ii_ExclusionOps == NULL);
Assert(indexInfo->ii_ExclusionProcs == NULL);
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index f411b970e5..7abfda3d3a 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -4,7 +4,7 @@
# Perl module that extracts info from catalog headers into Perl
# data structures
#
-# Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+# Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# src/backend/catalog/Catalog.pm
@@ -19,7 +19,7 @@ use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = ();
-our @EXPORT_OK = qw(Catalogs RenameTempFile);
+our @EXPORT_OK = qw(Catalogs SplitDataLine RenameTempFile);
# Call this function with an array of names of header files to parse.
# Returns a nested data structure describing the data in the headers.
@@ -44,10 +44,13 @@ sub Catalogs
$catalog{columns} = [];
$catalog{data} = [];
- open(INPUT_FILE, '<', $input_file) || die "$input_file: $!";
+ open(my $ifh, '<', $input_file) || die "$input_file: $!";
+
+ my ($filename) = ($input_file =~ m/(\w+)\.h$/);
+ my $natts_pat = "Natts_$filename";
# Scan the input file.
- while (<INPUT_FILE>)
+ while (<$ifh>)
{
# Strip C-style comments.
@@ -56,13 +59,16 @@ sub Catalogs
{
# handle multi-line comments properly.
- my $next_line = <INPUT_FILE>;
+ my $next_line = <$ifh>;
die "$input_file: ends within C-style comment\n"
if !defined $next_line;
$_ .= $next_line;
redo;
}
+ # Remember input line number for later.
+ my $input_line_number = $.;
+
# Strip useless whitespace and trailing semicolons.
chomp;
s/^\s+//;
@@ -70,8 +76,16 @@ sub Catalogs
s/\s+/ /g;
# Push the data into the appropriate data structure.
- if (/^DATA\(insert(\s+OID\s+=\s+(\d+))?\s+\(\s*(.*)\s*\)\s*\)$/)
+ if (/$natts_pat\s+(\d+)/)
+ {
+ $catalog{natts} = $1;
+ }
+ elsif (
+ /^DATA\(insert(\s+OID\s+=\s+(\d+))?\s+\(\s*(.*)\s*\)\s*\)$/)
{
+ check_natts($filename, $catalog{natts}, $3, $input_file,
+ $input_line_number);
+
push @{ $catalog{data} }, { oid => $2, bki_values => $3 };
}
elsif (/^DESCR\(\"(.*)\"\)$/)
@@ -198,11 +212,33 @@ sub Catalogs
}
}
$catalogs{$catname} = \%catalog;
- close INPUT_FILE;
+ close $ifh;
}
return \%catalogs;
}
+# Split a DATA line into fields.
+# Call this on the bki_values element of a DATA item returned by Catalogs();
+# it returns a list of field values. We don't strip quoting from the fields.
+# Note: it should be safe to assign the result to a list of length equal to
+# the nominal number of catalog fields, because check_natts already checked
+# the number of fields.
+sub SplitDataLine
+{
+ my $bki_values = shift;
+
+ # This handling of quoted strings might look too simplistic, but it
+ # matches what bootscanner.l does: that has no provision for quote marks
+ # inside quoted strings, either. If we don't have a quoted string, just
+ # snarf everything till next whitespace. That will accept some things
+ # that bootscanner.l will see as erroneous tokens; but it seems wiser
+ # to do that and let bootscanner.l complain than to silently drop
+ # non-whitespace characters.
+ my @result = $bki_values =~ /"[^"]*"|\S+/g;
+
+ return @result;
+}
+
# Rename temporary files to final names.
# Call this function with the final file name and the .tmp extension
# Note: recommended extension is ".tmp$$", so that parallel make steps
@@ -216,4 +252,21 @@ sub RenameTempFile
rename($temp_name, $final_name) || die "rename: $temp_name: $!";
}
+# verify the number of fields in the passed-in DATA line
+sub check_natts
+{
+ my ($catname, $natts, $bki_val, $file, $line) = @_;
+
+ die
+"Could not find definition for Natts_${catname} before start of DATA() in $file\n"
+ unless defined $natts;
+
+ my $nfields = scalar(SplitDataLine($bki_val));
+
+ die sprintf
+"Wrong number of attributes in DATA() entry at %s:%d (expected %d but got %d)\n",
+ $file, $line, $natts, $nfields
+ unless $natts == $nfields;
+}
+
1;
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 240c44d0f0..52bc63c788 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -11,11 +11,12 @@ top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \
- objectaccess.o objectaddress.o pg_aggregate.o pg_collation.o \
+ objectaccess.o objectaddress.o partition.o pg_aggregate.o pg_collation.o \
pg_constraint.o pg_conversion.o \
pg_depend.o pg_enum.o pg_inherits.o pg_largeobject.o pg_namespace.o \
- pg_operator.o pg_proc.o pg_range.o pg_db_role_setting.o pg_shdepend.o \
- pg_type.o pgxc_class.o storage.o toasting.o
+ pg_operator.o pg_proc.o pg_publication.o pg_range.o \
+ pg_db_role_setting.o pg_shdepend.o pg_subscription.o pg_type.o \
+ pgxc_class.o storage.o toasting.o
BKIFILES = postgres.bki postgres.description postgres.shdescription
@@ -32,6 +33,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h pg_operator.h \
pg_opfamily.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
pg_language.h pg_largeobject_metadata.h pg_largeobject.h pg_aggregate.h \
+ pg_statistic_ext.h \
pg_statistic.h pg_rewrite.h pg_trigger.h pg_event_trigger.h pg_description.h \
pg_cast.h pg_enum.h pg_namespace.h pg_conversion.h pg_depend.h \
pg_database.h pg_db_role_setting.h pg_tablespace.h pg_pltemplate.h \
@@ -42,7 +44,9 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pgxc_class.h pgxc_node.h pgxc_group.h \
pg_foreign_table.h pg_policy.h pg_replication_origin.h \
pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
- pg_collation.h pg_range.h pg_transform.h \
+ pg_collation.h pg_partitioned_table.h pg_range.h pg_transform.h \
+ pg_sequence.h pg_publication.h pg_publication_rel.h pg_subscription.h \
+ pg_subscription_rel.h toasting.h indexing.h \
toasting.h indexing.h \
)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index a585c3ad19..387a3be701 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -3,7 +3,7 @@
* aclchk.c
* Routines to check access control permissions.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -27,7 +27,10 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
@@ -45,10 +48,15 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_transform.h"
#include "commands/dbcommands.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
@@ -130,6 +138,8 @@ static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnu
Oid roleid, AclMode mask, AclMaskHow how);
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
Acl *new_acl);
+static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
+ Acl *new_acl);
#ifdef ACLDEBUG
@@ -423,7 +433,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
grantee_uid = ACL_ID_PUBLIC;
break;
default:
- grantee_uid = get_rolespec_oid((Node *) grantee, false);
+ grantee_uid = get_rolespec_oid(grantee, false);
break;
}
istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
@@ -658,11 +668,10 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
case ACL_OBJECT_FUNCTION:
foreach(cell, objnames)
{
- FuncWithArgs *func = (FuncWithArgs *) lfirst(cell);
+ ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
Oid funcid;
- funcid = LookupFuncNameTypeNames(func->funcname,
- func->funcargs, false);
+ funcid = LookupFuncWithArgs(func, false);
objects = lappend_oid(objects, funcid);
}
break;
@@ -768,6 +777,8 @@ objectsInSchemaToOids(GrantObjectType objtype, List *nspnames)
objects = list_concat(objects, objs);
objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
objects = list_concat(objects, objs);
+ objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
+ objects = list_concat(objects, objs);
break;
case ACL_OBJECT_SEQUENCE:
objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
@@ -849,7 +860,7 @@ getRelationsInNamespace(Oid namespaceId, char relkind)
* ALTER DEFAULT PRIVILEGES statement
*/
void
-ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
+ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
{
GrantStmt *action = stmt->action;
InternalDefaultACL iacls;
@@ -871,7 +882,8 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
if (dnspnames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
@@ -879,7 +891,8 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
if (drolespecs)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
drolespecs = defel;
}
else
@@ -918,7 +931,7 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
grantee_uid = ACL_ID_PUBLIC;
break;
default:
- grantee_uid = get_rolespec_oid((Node *) grantee, false);
+ grantee_uid = get_rolespec_oid(grantee, false);
break;
}
iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
@@ -946,6 +959,10 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
all_privileges = ACL_ALL_RIGHTS_TYPE;
errormsg = gettext_noop("invalid privilege type %s for type");
break;
+ case ACL_OBJECT_NAMESPACE:
+ all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
+ errormsg = gettext_noop("invalid privilege type %s for schema");
+ break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) action->objtype);
@@ -1008,7 +1025,7 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
{
RoleSpec *rolespec = lfirst(rolecell);
- iacls.roleid = get_rolespec_oid((Node *) rolespec, false);
+ iacls.roleid = get_rolespec_oid(rolespec, false);
/*
* We insist that calling user be a member of each target role. If
@@ -1133,6 +1150,16 @@ SetDefaultACL(InternalDefaultACL *iacls)
this_privileges = ACL_ALL_RIGHTS_TYPE;
break;
+ case ACL_OBJECT_NAMESPACE:
+ if (OidIsValid(iacls->nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
+ objtype = DEFACLOBJ_NAMESPACE;
+ if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ this_privileges = ACL_ALL_RIGHTS_NAMESPACE;
+ break;
+
default:
elog(ERROR, "unrecognized objtype: %d",
(int) iacls->objtype);
@@ -1239,7 +1266,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
- simple_heap_insert(rel, newtuple);
+ CatalogTupleInsert(rel, newtuple);
}
else
{
@@ -1249,12 +1276,9 @@ SetDefaultACL(InternalDefaultACL *iacls)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
values, nulls, replaces);
- simple_heap_update(rel, &newtuple->t_self, newtuple);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
}
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(rel, newtuple);
-
/* these dependencies don't change in an update */
if (isNew)
{
@@ -1359,6 +1383,9 @@ RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
case DEFACLOBJ_TYPE:
iacls.objtype = ACL_OBJECT_TYPE;
break;
+ case DEFACLOBJ_NAMESPACE:
+ iacls.objtype = ACL_OBJECT_NAMESPACE;
+ break;
default:
/* Shouldn't get here */
elog(ERROR, "unexpected default ACL type: %d",
@@ -1460,7 +1487,7 @@ RemoveDefaultACLById(Oid defaclOid)
if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for default ACL %u", defaclOid);
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
@@ -1684,10 +1711,7 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
values, nulls, replaces);
- simple_heap_update(attRelation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(attRelation, newtuple);
+ CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(relOid, RelationRelationId, attnum,
@@ -1815,7 +1839,8 @@ ExecGrant_Relation(InternalGrant *istmt)
*/
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
- errmsg("invalid privilege type USAGE for table")));
+ errmsg("invalid privilege type %s for table",
+ "USAGE")));
}
}
}
@@ -1949,10 +1974,7 @@ ExecGrant_Relation(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
values, nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
@@ -2142,10 +2164,7 @@ ExecGrant_Database(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple), 0,
@@ -2267,10 +2286,7 @@ ExecGrant_Fdw(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
@@ -2396,10 +2412,7 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
@@ -2523,10 +2536,7 @@ ExecGrant_Function(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
@@ -2657,10 +2667,7 @@ ExecGrant_Language(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
@@ -2799,10 +2806,7 @@ ExecGrant_Largeobject(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
values, nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
@@ -2927,10 +2931,7 @@ ExecGrant_Namespace(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
@@ -3054,10 +3055,7 @@ ExecGrant_Tablespace(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(TableSpaceRelationId, tblId, 0,
@@ -3191,10 +3189,7 @@ ExecGrant_Type(InternalGrant *istmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
/* Update initial privileges for extensions */
recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
@@ -3325,6 +3320,8 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
gettext_noop("permission denied for collation %s"),
/* ACL_KIND_CONVERSION */
gettext_noop("permission denied for conversion %s"),
+ /* ACL_KIND_STATISTICS */
+ gettext_noop("permission denied for statistics object %s"),
/* ACL_KIND_TABLESPACE */
gettext_noop("permission denied for tablespace %s"),
/* ACL_KIND_TSDICTIONARY */
@@ -3339,6 +3336,10 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
gettext_noop("permission denied for event trigger %s"),
/* ACL_KIND_EXTENSION */
gettext_noop("permission denied for extension %s"),
+ /* ACL_KIND_PUBLICATION */
+ gettext_noop("permission denied for publication %s"),
+ /* ACL_KIND_SUBSCRIPTION */
+ gettext_noop("permission denied for subscription %s"),
};
static const char *const not_owner_msg[MAX_ACL_KIND] =
@@ -3371,6 +3372,8 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
gettext_noop("must be owner of collation %s"),
/* ACL_KIND_CONVERSION */
gettext_noop("must be owner of conversion %s"),
+ /* ACL_KIND_STATISTICS */
+ gettext_noop("must be owner of statistics object %s"),
/* ACL_KIND_TABLESPACE */
gettext_noop("must be owner of tablespace %s"),
/* ACL_KIND_TSDICTIONARY */
@@ -3385,6 +3388,10 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
gettext_noop("must be owner of event trigger %s"),
/* ACL_KIND_EXTENSION */
gettext_noop("must be owner of extension %s"),
+ /* ACL_KIND_PUBLICATION */
+ gettext_noop("must be owner of publication %s"),
+ /* ACL_KIND_SUBSCRIPTION */
+ gettext_noop("must be owner of subscription %s"),
};
@@ -3482,6 +3489,10 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
mask, how, NULL);
case ACL_KIND_NAMESPACE:
return pg_namespace_aclmask(table_oid, roleid, mask, how);
+ case ACL_KIND_STATISTICS:
+ elog(ERROR, "grantable rights not supported for statistics objects");
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
case ACL_KIND_TABLESPACE:
return pg_tablespace_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_FDW:
@@ -5067,6 +5078,85 @@ pg_extension_ownercheck(Oid ext_oid, Oid roleid)
}
/*
+ * Ownership check for an publication (specified by OID).
+ */
+bool
+pg_publication_ownercheck(Oid pub_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pub_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication with OID %u does not exist", pub_oid)));
+
+ ownerId = ((Form_pg_publication) GETSTRUCT(tuple))->pubowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a subscription (specified by OID).
+ */
+bool
+pg_subscription_ownercheck(Oid sub_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(sub_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription with OID %u does not exist", sub_oid)));
+
+ ownerId = ((Form_pg_subscription) GETSTRUCT(tuple))->subowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a statistics object (specified by OID).
+ */
+bool
+pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stat_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("statistics object with OID %u does not exist",
+ stat_oid)));
+
+ ownerId = ((Form_pg_statistic_ext) GETSTRUCT(tuple))->stxowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
* Check whether specified role has CREATEROLE privilege (or is a superuser)
*
* Note: roles do not have owners per se; instead we use this test in
@@ -5187,6 +5277,10 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
defaclobjtype = DEFACLOBJ_TYPE;
break;
+ case ACL_OBJECT_NAMESPACE:
+ defaclobjtype = DEFACLOBJ_NAMESPACE;
+ break;
+
default:
return NULL;
}
@@ -5222,10 +5316,367 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
}
/*
- * Record initial ACL for an extension object
+ * Record initial privileges for the top-level object passed in.
*
- * This will perform a wholesale replacement of the entire ACL for the object
- * passed in, therefore be sure to pass in the complete new ACL to use.
+ * For the object passed in, this will record its ACL (if any) and the ACLs of
+ * any sub-objects (eg: columns) into pg_init_privs.
+ *
+ * Any new kinds of objects which have ACLs associated with them and can be
+ * added to an extension should be added to the if-else tree below.
+ */
+void
+recordExtObjInitPriv(Oid objoid, Oid classoid)
+{
+ /*
+ * pg_class / pg_attribute
+ *
+ * If this is a relation then we need to see if there are any sub-objects
+ * (eg: columns) for it and, if so, be sure to call
+ * recordExtensionInitPrivWorker() for each one.
+ */
+ if (classoid == RelationRelationId)
+ {
+ Form_pg_class pg_class_tuple;
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", objoid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ /* Indexes don't have permissions */
+ if (pg_class_tuple->relkind == RELKIND_INDEX)
+ return;
+
+ /* Composite types don't have permissions either */
+ if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+ return;
+
+ /*
+ * If this isn't a sequence, index, or composite type then it's
+ * possibly going to have columns associated with it that might have
+ * ACLs.
+ */
+ if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+ {
+ AttrNumber curr_att;
+ AttrNumber nattrs = pg_class_tuple->relnatts;
+
+ for (curr_att = 1; curr_att <= nattrs; curr_att++)
+ {
+ HeapTuple attTuple;
+ Datum attaclDatum;
+
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(objoid),
+ Int16GetDatum(curr_att));
+
+ if (!HeapTupleIsValid(attTuple))
+ continue;
+
+ /* ignore dropped columns */
+ if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
+ {
+ ReleaseSysCache(attTuple);
+ continue;
+ }
+
+ attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
+ Anum_pg_attribute_attacl,
+ &isNull);
+
+ /* no need to do anything for a NULL ACL */
+ if (isNull)
+ {
+ ReleaseSysCache(attTuple);
+ continue;
+ }
+
+ recordExtensionInitPrivWorker(objoid, classoid, curr_att,
+ DatumGetAclP(attaclDatum));
+
+ ReleaseSysCache(attTuple);
+ }
+ }
+
+ aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_foreign_data_wrapper */
+ else if (classoid == ForeignDataWrapperRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
+ ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign data wrapper %u",
+ objoid);
+
+ aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
+ Anum_pg_foreign_data_wrapper_fdwacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_foreign_server */
+ else if (classoid == ForeignServerRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign data wrapper %u",
+ objoid);
+
+ aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
+ Anum_pg_foreign_server_srvacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_language */
+ else if (classoid == LanguageRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for language %u", objoid);
+
+ aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_largeobject_metadata */
+ else if (classoid == LargeObjectMetadataRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+ ScanKeyData entry[1];
+ SysScanDesc scan;
+ Relation relation;
+
+ relation = heap_open(LargeObjectMetadataRelationId, RowExclusiveLock);
+
+ /* There's no syscache for pg_largeobject_metadata */
+ ScanKeyInit(&entry[0],
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objoid));
+
+ scan = systable_beginscan(relation,
+ LargeObjectMetadataOidIndexId, true,
+ NULL, 1, entry);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for large object %u", objoid);
+
+ aclDatum = heap_getattr(tuple,
+ Anum_pg_largeobject_metadata_lomacl,
+ RelationGetDescr(relation), &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ systable_endscan(scan);
+ }
+ /* pg_namespace */
+ else if (classoid == NamespaceRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", objoid);
+
+ aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple,
+ Anum_pg_namespace_nspacl, &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_proc */
+ else if (classoid == ProcedureRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", objoid);
+
+ aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_type */
+ else if (classoid == TypeRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", objoid);
+
+ aclDatum = SysCacheGetAttr(TYPEOID, tuple, Anum_pg_type_typacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ else if (classoid == AccessMethodRelationId ||
+ classoid == AggregateRelationId ||
+ classoid == CastRelationId ||
+ classoid == CollationRelationId ||
+ classoid == ConversionRelationId ||
+ classoid == EventTriggerRelationId ||
+ classoid == OperatorRelationId ||
+ classoid == OperatorClassRelationId ||
+ classoid == OperatorFamilyRelationId ||
+ classoid == NamespaceRelationId ||
+ classoid == TSConfigRelationId ||
+ classoid == TSDictionaryRelationId ||
+ classoid == TSParserRelationId ||
+ classoid == TSTemplateRelationId ||
+ classoid == TransformRelationId
+ )
+ {
+ /* no ACL for these object types, so do nothing. */
+ }
+
+ /*
+ * complain if we are given a class OID for a class that extensions don't
+ * support or that we don't recognize.
+ */
+ else
+ {
+ elog(ERROR, "unrecognized or unsupported class OID: %u", classoid);
+ }
+}
+
+/*
+ * For the object passed in, remove its ACL and the ACLs of any object subIds
+ * from pg_init_privs (via recordExtensionInitPrivWorker()).
+ */
+void
+removeExtObjInitPriv(Oid objoid, Oid classoid)
+{
+ /*
+ * If this is a relation then we need to see if there are any sub-objects
+ * (eg: columns) for it and, if so, be sure to call
+ * recordExtensionInitPrivWorker() for each one.
+ */
+ if (classoid == RelationRelationId)
+ {
+ Form_pg_class pg_class_tuple;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", objoid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ /* Indexes don't have permissions */
+ if (pg_class_tuple->relkind == RELKIND_INDEX)
+ return;
+
+ /* Composite types don't have permissions either */
+ if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+ return;
+
+ /*
+ * If this isn't a sequence, index, or composite type then it's
+ * possibly going to have columns associated with it that might have
+ * ACLs.
+ */
+ if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+ {
+ AttrNumber curr_att;
+ AttrNumber nattrs = pg_class_tuple->relnatts;
+
+ for (curr_att = 1; curr_att <= nattrs; curr_att++)
+ {
+ HeapTuple attTuple;
+
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(objoid),
+ Int16GetDatum(curr_att));
+
+ if (!HeapTupleIsValid(attTuple))
+ continue;
+
+ /* when removing, remove all entires, even dropped columns */
+
+ recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
+
+ ReleaseSysCache(attTuple);
+ }
+ }
+
+ ReleaseSysCache(tuple);
+ }
+
+ /* Remove the record, if any, for the top-level object */
+ recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
+}
+
+/*
+ * Record initial ACL for an extension object
*
* Can be called at any time, we check if 'creating_extension' is set and, if
* not, exit immediately.
@@ -5244,12 +5695,6 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
static void
recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
{
- Relation relation;
- ScanKeyData key[3];
- SysScanDesc scan;
- HeapTuple tuple;
- HeapTuple oldtuple;
-
/*
* Generally, we only record the initial privileges when an extension is
* being created, but because we don't actually use CREATE EXTENSION
@@ -5261,6 +5706,30 @@ recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
if (!creating_extension && !binary_upgrade_record_init_privs)
return;
+ recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
+}
+
+/*
+ * Record initial ACL for an extension object, worker.
+ *
+ * This will perform a wholesale replacement of the entire ACL for the object
+ * passed in, therefore be sure to pass in the complete new ACL to use.
+ *
+ * Generally speaking, do *not* use this function directly but instead use
+ * recordExtensionInitPriv(), which checks if 'creating_extension' is set.
+ * This function does *not* check if 'creating_extension' is set as it is also
+ * used when an object is added to or removed from an extension via ALTER
+ * EXTENSION ... ADD/DROP.
+ */
+static void
+recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
+{
+ Relation relation;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ HeapTuple oldtuple;
+
relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
ScanKeyInit(&key[0],
@@ -5302,39 +5771,44 @@ recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
values, nulls, replace);
- simple_heap_update(relation, &oldtuple->t_self, oldtuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, oldtuple);
+ CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
}
else
+ {
/* new_acl is NULL, so delete the entry we found. */
- simple_heap_delete(relation, &oldtuple->t_self);
+ CatalogTupleDelete(relation, &oldtuple->t_self);
+ }
}
else
{
- /* No entry found, so add it. */
Datum values[Natts_pg_init_privs];
bool nulls[Natts_pg_init_privs];
- MemSet(nulls, false, sizeof(nulls));
-
- values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
- values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
- values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
+ /*
+ * Only add a new entry if the new ACL is non-NULL.
+ *
+ * If we are passed in a NULL ACL and no entry exists, we can just
+ * fall through and do nothing.
+ */
+ if (new_acl)
+ {
+ /* No entry found, so add it. */
+ MemSet(nulls, false, sizeof(nulls));
- /* This function only handles initial privileges of extensions */
- values[Anum_pg_init_privs_privtype - 1] =
- CharGetDatum(INITPRIVS_EXTENSION);
+ values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
+ values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
+ values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
- values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
+ /* This function only handles initial privileges of extensions */
+ values[Anum_pg_init_privs_privtype - 1] =
+ CharGetDatum(INITPRIVS_EXTENSION);
- tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+ values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
- simple_heap_insert(relation, tuple);
+ tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relation, tuple);
+ CatalogTupleInsert(relation, tuple);
+ }
}
systable_endscan(scan);
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index 9bb937aa4c..2e8cd10ebb 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -6,7 +6,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -37,6 +37,7 @@
#include "catalog/pg_shdepend.h"
#include "catalog/pg_shdescription.h"
#include "catalog/pg_shseclabel.h"
+#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/toasting.h"
#include "catalog/pgxc_node.h"
@@ -237,7 +238,8 @@ IsSharedRelation(Oid relationId)
relationId == PgxcNodeRelationId ||
#endif
relationId == DbRoleSettingRelationId ||
- relationId == ReplicationOriginRelationId)
+ relationId == ReplicationOriginRelationId ||
+ relationId == SubscriptionRelationId)
return true;
/* These are their indexes (see indexing.h) */
if (relationId == AuthIdRolnameIndexId ||
@@ -262,7 +264,9 @@ IsSharedRelation(Oid relationId)
#endif
relationId == DbRoleSettingDatidRolidIndexId ||
relationId == ReplicationOriginIdentIndex ||
- relationId == ReplicationOriginNameIndex)
+ relationId == ReplicationOriginNameIndex ||
+ relationId == SubscriptionObjectIndexId ||
+ relationId == SubscriptionNameIndexId)
return true;
/* These are their toast tables and toast indexes (see toasting.h) */
if (relationId == PgShdescriptionToastTable ||
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 467d9ead0e..f8e560a8d4 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -5,7 +5,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -50,7 +50,11 @@
#include "catalog/pg_opfamily.h"
#include "catalog/pg_policy.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_publication.h"
+#include "catalog/pg_publication_rel.h"
#include "catalog/pg_rewrite.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_transform.h"
#include "catalog/pg_trigger.h"
@@ -77,8 +81,10 @@
#include "commands/extension.h"
#include "commands/policy.h"
#include "commands/proclang.h"
+#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
#include "commands/seclabel.h"
+#include "commands/sequence.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "nodes/nodeFuncs.h"
@@ -162,6 +168,7 @@ static const Oid object_classes[] = {
RewriteRelationId, /* OCLASS_REWRITE */
TriggerRelationId, /* OCLASS_TRIGGER */
NamespaceRelationId, /* OCLASS_SCHEMA */
+ StatisticExtRelationId, /* OCLASS_STATISTIC_EXT */
TSParserRelationId, /* OCLASS_TSPARSER */
TSDictionaryRelationId, /* OCLASS_TSDICT */
TSTemplateRelationId, /* OCLASS_TSTEMPLATE */
@@ -181,10 +188,14 @@ static const Oid object_classes[] = {
#endif
EventTriggerRelationId, /* OCLASS_EVENT_TRIGGER */
PolicyRelationId, /* OCLASS_POLICY */
+ PublicationRelationId, /* OCLASS_PUBLICATION */
+ PublicationRelRelationId, /* OCLASS_PUBLICATION_REL */
+ SubscriptionRelationId, /* OCLASS_SUBSCRIPTION */
TransformRelationId /* OCLASS_TRANSFORM */
};
static void findDependentObjects(const ObjectAddress *object,
+ int objflags,
int flags,
ObjectAddressStack *stack,
ObjectAddresses *targetObjects,
@@ -192,7 +203,7 @@ static void findDependentObjects(const ObjectAddress *object,
Relation *depRel);
static void reportDependentObjects(const ObjectAddresses *targetObjects,
DropBehavior behavior,
- int msglevel,
+ int flags,
const ObjectAddress *origObject);
static void deleteOneObject(const ObjectAddress *object,
Relation *depRel, int32 flags);
@@ -254,11 +265,17 @@ deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
}
/*
- * Delete all the objects in the proper order.
+ * Delete all the objects in the proper order, except that if told to, we
+ * should skip the original object(s).
*/
for (i = 0; i < targetObjects->numrefs; i++)
{
ObjectAddress *thisobj = targetObjects->refs + i;
+ ObjectAddressExtra *thisextra = targetObjects->extras + i;
+
+ if ((flags & PERFORM_DELETION_SKIP_ORIGINAL) &&
+ (thisextra->flags & DEPFLAG_ORIGINAL))
+ continue;
deleteOneObject(thisobj, depRel, flags);
}
@@ -272,16 +289,32 @@ deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
* according to the dependency type.
*
* This is the outer control routine for all forms of DROP that drop objects
- * that can participate in dependencies. Note that the next two routines
- * are variants on the same theme; if you change anything here you'll likely
- * need to fix them too.
+ * that can participate in dependencies. Note that performMultipleDeletions
+ * is a variant on the same theme; if you change anything here you'll likely
+ * need to fix that too.
+ *
+ * Bits in the flags argument can include:
+ *
+ * PERFORM_DELETION_INTERNAL: indicates that the drop operation is not the
+ * direct result of a user-initiated action. For example, when a temporary
+ * schema is cleaned out so that a new backend can use it, or when a column
+ * default is dropped as an intermediate step while adding a new one, that's
+ * an internal operation. On the other hand, when we drop something because
+ * the user issued a DROP statement against it, that's not internal. Currently
+ * this suppresses calling event triggers and making some permissions checks.
+ *
+ * PERFORM_DELETION_CONCURRENTLY: perform the drop concurrently. This does
+ * not currently work for anything except dropping indexes; don't set it for
+ * other object types or you may get strange results.
+ *
+ * PERFORM_DELETION_QUIETLY: reduce message level from NOTICE to DEBUG2.
*
- * flags should include PERFORM_DELETION_INTERNAL when the drop operation is
- * not the direct result of a user-initiated action. For example, when a
- * temporary schema is cleaned out so that a new backend can use it, or when
- * a column default is dropped as an intermediate step while adding a new one,
- * that's an internal operation. On the other hand, when we drop something
- * because the user issued a DROP statement against it, that's not internal.
+ * PERFORM_DELETION_SKIP_ORIGINAL: do not delete the specified object(s),
+ * but only what depends on it/them.
+ *
+ * PERFORM_DELETION_SKIP_EXTENSIONS: do not delete extensions, even when
+ * deleting objects that are part of an extension. This should generally
+ * be used only when dropping temporary objects.
*/
void
performDeletion(const ObjectAddress *object,
@@ -310,6 +343,7 @@ performDeletion(const ObjectAddress *object,
findDependentObjects(object,
DEPFLAG_ORIGINAL,
+ flags,
NULL, /* empty stack */
targetObjects,
NULL, /* no pendingObjects */
@@ -320,7 +354,7 @@ performDeletion(const ObjectAddress *object,
*/
reportDependentObjects(targetObjects,
behavior,
- NOTICE,
+ flags,
object);
/* do the deed */
@@ -381,6 +415,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
findDependentObjects(thisobj,
DEPFLAG_ORIGINAL,
+ flags,
NULL, /* empty stack */
targetObjects,
objects,
@@ -395,7 +430,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
*/
reportDependentObjects(targetObjects,
behavior,
- NOTICE,
+ flags,
(objects->numrefs == 1 ? objects->refs : NULL));
/* do the deed */
@@ -474,6 +509,8 @@ performRename(const ObjectAddress *object, const char *oldname, const char *newn
findDependentObjects(object,
DEPFLAG_ORIGINAL,
+ 0, /* XXX seems like flags are only used while
+ dropping objects */
NULL, /* empty stack */
targetObjects,
NULL,
@@ -494,88 +531,6 @@ performRename(const ObjectAddress *object, const char *oldname, const char *newn
#endif
/*
- * deleteWhatDependsOn: attempt to drop everything that depends on the
- * specified object, though not the object itself. Behavior is always
- * CASCADE.
- *
- * This is currently used only to clean out the contents of a schema
- * (namespace): the passed object is a namespace. We normally want this
- * to be done silently, so there's an option to suppress NOTICE messages.
- *
- * Note we don't fire object drop event triggers here; it would be wrong to do
- * so for the current only use of this function, but if more callers are added
- * this might need to be reconsidered.
- */
-void
-deleteWhatDependsOn(const ObjectAddress *object,
- bool showNotices)
-{
- Relation depRel;
- ObjectAddresses *targetObjects;
- int i;
-
- /*
- * We save some cycles by opening pg_depend just once and passing the
- * Relation pointer down to all the recursive deletion steps.
- */
- depRel = heap_open(DependRelationId, RowExclusiveLock);
-
- /*
- * Acquire deletion lock on the target object. (Ideally the caller has
- * done this already, but many places are sloppy about it.)
- */
- AcquireDeletionLock(object, 0);
-
- /*
- * Construct a list of objects to delete (ie, the given object plus
- * everything directly or indirectly dependent on it).
- */
- targetObjects = new_object_addresses();
-
- findDependentObjects(object,
- DEPFLAG_ORIGINAL,
- NULL, /* empty stack */
- targetObjects,
- NULL, /* no pendingObjects */
- &depRel);
-
- /*
- * Check if deletion is allowed, and report about cascaded deletes.
- */
- reportDependentObjects(targetObjects,
- DROP_CASCADE,
- showNotices ? NOTICE : DEBUG2,
- object);
-
- /*
- * Delete all the objects in the proper order, except we skip the original
- * object.
- */
- for (i = 0; i < targetObjects->numrefs; i++)
- {
- ObjectAddress *thisobj = targetObjects->refs + i;
- ObjectAddressExtra *thisextra = targetObjects->extras + i;
-
- if (thisextra->flags & DEPFLAG_ORIGINAL)
- continue;
-
- /*
- * Since this function is currently only used to clean out temporary
- * schemas, we pass PERFORM_DELETION_INTERNAL here, indicating that
- * the operation is an automatic system operation rather than a user
- * action. If, in the future, this function is used for other
- * purposes, we might need to revisit this.
- */
- deleteOneObject(thisobj, &depRel, PERFORM_DELETION_INTERNAL);
- }
-
- /* And clean up */
- free_object_addresses(targetObjects);
-
- heap_close(depRel, RowExclusiveLock);
-}
-
-/*
* findDependentObjects - find all objects that depend on 'object'
*
* For every object that depends on the starting object, acquire a deletion
@@ -595,16 +550,22 @@ deleteWhatDependsOn(const ObjectAddress *object,
* its sub-objects too.
*
* object: the object to add to targetObjects and find dependencies on
- * flags: flags to be ORed into the object's targetObjects entry
+ * objflags: flags to be ORed into the object's targetObjects entry
+ * flags: PERFORM_DELETION_xxx flags for the deletion operation as a whole
* stack: list of objects being visited in current recursion; topmost item
* is the object that we recursed from (NULL for external callers)
* targetObjects: list of objects that are scheduled to be deleted
* pendingObjects: list of other objects slated for destruction, but
* not necessarily in targetObjects yet (can be NULL if none)
* *depRel: already opened pg_depend relation
+ *
+ * Note: objflags describes the reason for visiting this particular object
+ * at this time, and is not passed down when recursing. The flags argument
+ * is passed down, since it describes what we're doing overall.
*/
static void
findDependentObjects(const ObjectAddress *object,
+ int objflags,
int flags,
ObjectAddressStack *stack,
ObjectAddresses *targetObjects,
@@ -621,8 +582,8 @@ findDependentObjects(const ObjectAddress *object,
/*
* If the target object is already being visited in an outer recursion
- * level, just report the current flags back to that level and exit. This
- * is needed to avoid infinite recursion in the face of circular
+ * level, just report the current objflags back to that level and exit.
+ * This is needed to avoid infinite recursion in the face of circular
* dependencies.
*
* The stack check alone would result in dependency loops being broken at
@@ -635,19 +596,19 @@ findDependentObjects(const ObjectAddress *object,
* auto dependency, too, if we had to. However there are no known cases
* where that would be necessary.
*/
- if (stack_address_present_add_flags(object, flags, stack))
+ if (stack_address_present_add_flags(object, objflags, stack))
return;
/*
* It's also possible that the target object has already been completely
* processed and put into targetObjects. If so, again we just add the
- * specified flags to its entry and return.
+ * specified objflags to its entry and return.
*
* (Note: in these early-exit cases we could release the caller-taken
* lock, since the object is presumably now locked multiple times; but it
* seems not worth the cycles.)
*/
- if (object_address_present_add_flags(object, flags, targetObjects))
+ if (object_address_present_add_flags(object, objflags, targetObjects))
return;
/*
@@ -697,29 +658,52 @@ findDependentObjects(const ObjectAddress *object,
case DEPENDENCY_AUTO_EXTENSION:
/* no problem */
break;
- case DEPENDENCY_INTERNAL:
+
case DEPENDENCY_EXTENSION:
/*
+ * If told to, ignore EXTENSION dependencies altogether. This
+ * flag is normally used to prevent dropping extensions during
+ * temporary-object cleanup, even if a temp object was created
+ * during an extension script.
+ */
+ if (flags & PERFORM_DELETION_SKIP_EXTENSIONS)
+ break;
+
+ /*
+ * If the other object is the extension currently being
+ * created/altered, ignore this dependency and continue with
+ * the deletion. This allows dropping of an extension's
+ * objects within the extension's scripts, as well as corner
+ * cases such as dropping a transient object created within
+ * such a script.
+ */
+ if (creating_extension &&
+ otherObject.classId == ExtensionRelationId &&
+ otherObject.objectId == CurrentExtensionObject)
+ break;
+
+ /* Otherwise, treat this like an internal dependency */
+ /* FALL THRU */
+
+ case DEPENDENCY_INTERNAL:
+
+ /*
* This object is part of the internal implementation of
* another object, or is part of the extension that is the
* other object. We have three cases:
*
- * 1. At the outermost recursion level, we normally disallow
- * the DROP. (We just ereport here, rather than proceeding,
- * since no other dependencies are likely to be interesting.)
- * However, there are exceptions.
+ * 1. At the outermost recursion level, disallow the DROP. (We
+ * just ereport here, rather than proceeding, since no other
+ * dependencies are likely to be interesting.) However, if
+ * the owning object is listed in pendingObjects, just release
+ * the caller's lock and return; we'll eventually complete the
+ * DROP when we reach that entry in the pending list.
*/
if (stack == NULL)
{
char *otherObjDesc;
- /*
- * Exception 1a: if the owning object is listed in
- * pendingObjects, just release the caller's lock and
- * return. We'll eventually complete the DROP when we
- * reach that entry in the pending list.
- */
if (pendingObjects &&
object_address_present(&otherObject, pendingObjects))
{
@@ -728,21 +712,6 @@ findDependentObjects(const ObjectAddress *object,
ReleaseDeletionLock(object);
return;
}
-
- /*
- * Exception 1b: if the owning object is the extension
- * currently being created/altered, it's okay to continue
- * with the deletion. This allows dropping of an
- * extension's objects within the extension's scripts, as
- * well as corner cases such as dropping a transient
- * object created within such a script.
- */
- if (creating_extension &&
- otherObject.classId == ExtensionRelationId &&
- otherObject.objectId == CurrentExtensionObject)
- break;
-
- /* No exception applies, so throw the error */
otherObjDesc = getObjectDescription(&otherObject);
ereport(ERROR,
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
@@ -803,6 +772,7 @@ findDependentObjects(const ObjectAddress *object,
*/
findDependentObjects(&otherObject,
DEPFLAG_REVERSE,
+ flags,
stack,
targetObjects,
pendingObjects,
@@ -833,7 +803,7 @@ findDependentObjects(const ObjectAddress *object,
* they have to be deleted before the current object.
*/
mystack.object = object; /* set up a new stack level */
- mystack.flags = flags;
+ mystack.flags = objflags;
mystack.next = stack;
ScanKeyInit(&key[0],
@@ -887,7 +857,7 @@ findDependentObjects(const ObjectAddress *object,
continue;
}
- /* Recurse, passing flags indicating the dependency type */
+ /* Recurse, passing objflags indicating the dependency type */
switch (foundDep->deptype)
{
case DEPENDENCY_NORMAL:
@@ -924,6 +894,7 @@ findDependentObjects(const ObjectAddress *object,
findDependentObjects(&otherObject,
subflags,
+ flags,
&mystack,
targetObjects,
pendingObjects,
@@ -954,16 +925,17 @@ findDependentObjects(const ObjectAddress *object,
*
* targetObjects: list of objects that are scheduled to be deleted
* behavior: RESTRICT or CASCADE
- * msglevel: elog level for non-error report messages
+ * flags: other flags for the deletion operation
* origObject: base object of deletion, or NULL if not available
* (the latter case occurs in DROP OWNED)
*/
static void
reportDependentObjects(const ObjectAddresses *targetObjects,
DropBehavior behavior,
- int msglevel,
+ int flags,
const ObjectAddress *origObject)
{
+ int msglevel = (flags & PERFORM_DELETION_QUIETLY) ? DEBUG2 : NOTICE;
bool ok = true;
StringInfoData clientdetail;
StringInfoData logdetail;
@@ -1197,7 +1169,7 @@ deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
- simple_heap_delete(*depRel, &tup->t_self);
+ CatalogTupleDelete(*depRel, &tup->t_self);
}
systable_endscan(scan);
@@ -1244,8 +1216,7 @@ doDeletion(const ObjectAddress *object, int flags)
if (relKind == RELKIND_INDEX)
{
- bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY)
- == PERFORM_DELETION_CONCURRENTLY);
+ bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
Assert(object->objectSubId == 0);
index_drop(object->objectId, concurrent);
@@ -1259,6 +1230,12 @@ doDeletion(const ObjectAddress *object, int flags)
heap_drop_with_catalog(object->objectId);
}
+ /*
+ * for a sequence, in addition to dropping the heap, also
+ * delete pg_sequence tuple
+ */
+ if (relKind == RELKIND_SEQUENCE)
+ DeleteSequenceTuple(object->objectId);
#ifdef PGXC
/*
* Do not do extra process if this session is connected to a remote
@@ -1382,6 +1359,10 @@ doDeletion(const ObjectAddress *object, int flags)
RemoveSchemaById(object->objectId);
break;
+ case OCLASS_STATISTIC_EXT:
+ RemoveStatisticsById(object->objectId);
+ break;
+
case OCLASS_TSPARSER:
RemoveTSParserById(object->objectId);
break;
@@ -1436,13 +1417,35 @@ doDeletion(const ObjectAddress *object, int flags)
RemovePolicyById(object->objectId);
break;
+ case OCLASS_PUBLICATION:
+ RemovePublicationById(object->objectId);
+ break;
+
+ case OCLASS_PUBLICATION_REL:
+ RemovePublicationRelById(object->objectId);
+ break;
+
case OCLASS_TRANSFORM:
DropTransformById(object->objectId);
break;
- default:
- elog(ERROR, "unrecognized object class: %u",
- object->classId);
+ /*
+ * These global object types are not supported here.
+ */
+ case OCLASS_ROLE:
+ case OCLASS_DATABASE:
+ case OCLASS_TBLSPACE:
+ case OCLASS_SUBSCRIPTION:
+ case OCLASS_PGXC_NODE:
+ case OCLASS_PGXC_GROUP:
+ elog(ERROR, "global objects cannot be deleted by doDeletion");
+ break;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
+
}
}
@@ -1550,7 +1553,8 @@ void
recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
Node *expr, Oid relId,
DependencyType behavior,
- DependencyType self_behavior)
+ DependencyType self_behavior,
+ bool ignore_self)
{
find_expr_references_context context;
RangeTblEntry rte;
@@ -1605,9 +1609,10 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
context.addrs->numrefs = outrefs;
/* Record the self-dependencies */
- recordMultipleDependencies(depender,
- self_addrs->refs, self_addrs->numrefs,
- self_behavior);
+ if (!ignore_self)
+ recordMultipleDependencies(depender,
+ self_addrs->refs, self_addrs->numrefs,
+ self_behavior);
free_object_addresses(self_addrs);
}
@@ -1788,7 +1793,8 @@ find_expr_references_walker(Node *node,
case REGROLEOID:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("constant of the type \"regrole\" cannot be used here")));
+ errmsg("constant of the type %s cannot be used here",
+ "regrole")));
break;
}
}
@@ -2097,6 +2103,13 @@ find_expr_references_walker(Node *node,
context->addrs);
/* fall through to examine arguments */
}
+ else if (IsA(node, NextValueExpr))
+ {
+ NextValueExpr *nve = (NextValueExpr *) node;
+
+ add_object_address(OCLASS_CLASS, nve->seqid, 0,
+ context->addrs);
+ }
return expression_tree_walker(node, find_expr_references_walker,
(void *) context);
@@ -2551,6 +2564,9 @@ getObjectClass(const ObjectAddress *object)
case NamespaceRelationId:
return OCLASS_SCHEMA;
+ case StatisticExtRelationId:
+ return OCLASS_STATISTIC_EXT;
+
case TSParserRelationId:
return OCLASS_TSPARSER;
@@ -2598,6 +2614,15 @@ getObjectClass(const ObjectAddress *object)
case PolicyRelationId:
return OCLASS_POLICY;
+ case PublicationRelationId:
+ return OCLASS_PUBLICATION;
+
+ case PublicationRelRelationId:
+ return OCLASS_PUBLICATION_REL;
+
+ case SubscriptionRelationId:
+ return OCLASS_SUBSCRIPTION;
+
case TransformRelationId:
return OCLASS_TRANSFORM;
}
@@ -2637,7 +2662,7 @@ DeleteInitPrivs(const ObjectAddress *object)
NULL, 3, key);
while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
- simple_heap_delete(relation, &oldtuple->t_self);
+ CatalogTupleDelete(relation, &oldtuple->t_self);
systable_endscan(scan);
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index e15c2e95d6..12acedd2e0 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -7,7 +7,7 @@
# header files. The .bki files are used to initialize the postgres
# template database.
#
-# Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+# Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# src/backend/catalog/genbki.pl
@@ -43,8 +43,8 @@ while (@ARGV)
elsif ($arg =~ /^--set-version=(.*)$/)
{
$major_version = $1;
- die "Version must be in format nn.nn.\n"
- if !($major_version =~ /^\d+\.\d+$/);
+ die "Invalid version string.\n"
+ if !($major_version =~ /^\d+$/);
}
else
{
@@ -66,16 +66,16 @@ if ($output_path ne '' && substr($output_path, -1) ne '/')
# Open temp files
my $tmpext = ".tmp$$";
my $bkifile = $output_path . 'postgres.bki';
-open BKI, '>', $bkifile . $tmpext
+open my $bki, '>', $bkifile . $tmpext
or die "can't open $bkifile$tmpext: $!";
my $schemafile = $output_path . 'schemapg.h';
-open SCHEMAPG, '>', $schemafile . $tmpext
+open my $schemapg, '>', $schemafile . $tmpext
or die "can't open $schemafile$tmpext: $!";
my $descrfile = $output_path . 'postgres.description';
-open DESCR, '>', $descrfile . $tmpext
+open my $descr, '>', $descrfile . $tmpext
or die "can't open $descrfile$tmpext: $!";
my $shdescrfile = $output_path . 'postgres.shdescription';
-open SHDESCR, '>', $shdescrfile . $tmpext
+open my $shdescr, '>', $shdescrfile . $tmpext
or die "can't open $shdescrfile$tmpext: $!";
# Fetch some special data that we will substitute into the output file.
@@ -97,11 +97,12 @@ my $catalogs = Catalog::Catalogs(@input_files);
# Generate postgres.bki, postgres.description, and postgres.shdescription
# version marker for .bki file
-print BKI "# PostgreSQL $major_version\n";
+print $bki "# PostgreSQL $major_version\n";
# vars to hold data needed for schemapg.h
my %schemapg_entries;
my @tables_needing_macros;
+my %regprocoids;
our @types;
# produce output, one catalog at a time
@@ -110,7 +111,7 @@ foreach my $catname (@{ $catalogs->{names} })
# .bki CREATE command for this catalog
my $catalog = $catalogs->{$catname};
- print BKI "create $catname $catalog->{relation_oid}"
+ print $bki "create $catname $catalog->{relation_oid}"
. $catalog->{shared_relation}
. $catalog->{bootstrap}
. $catalog->{without_oids}
@@ -120,7 +121,7 @@ foreach my $catname (@{ $catalogs->{names} })
my @attnames;
my $first = 1;
- print BKI " (\n";
+ print $bki " (\n";
foreach my $column (@{ $catalog->{columns} })
{
my $attname = $column->{name};
@@ -130,27 +131,27 @@ foreach my $catname (@{ $catalogs->{names} })
if (!$first)
{
- print BKI " ,\n";
+ print $bki " ,\n";
}
$first = 0;
- print BKI " $attname = $atttype";
+ print $bki " $attname = $atttype";
if (defined $column->{forcenotnull})
{
- print BKI " FORCE NOT NULL";
+ print $bki " FORCE NOT NULL";
}
elsif (defined $column->{forcenull})
{
- print BKI " FORCE NULL";
+ print $bki " FORCE NULL";
}
}
- print BKI "\n )\n";
+ print $bki "\n )\n";
# open it, unless bootstrap case (create bootstrap does this automatically)
if ($catalog->{bootstrap} eq '')
{
- print BKI "open $catname\n";
+ print $bki "open $catname\n";
}
if (defined $catalog->{data})
@@ -160,32 +161,67 @@ foreach my $catname (@{ $catalogs->{names} })
foreach my $row (@{ $catalog->{data} })
{
- # substitute constant values we acquired above
- $row->{bki_values} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
- $row->{bki_values} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g;
+ # Split line into tokens without interpreting their meaning.
+ my %bki_values;
+ @bki_values{@attnames} =
+ Catalog::SplitDataLine($row->{bki_values});
+
+ # Perform required substitutions on fields
+ foreach my $att (keys %bki_values)
+ {
+
+ # Substitute constant values we acquired above.
+ # (It's intentional that this can apply to parts of a field).
+ $bki_values{$att} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
+ $bki_values{$att} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g;
+
+ # Replace regproc columns' values with OIDs.
+ # If we don't have a unique value to substitute,
+ # just do nothing (regprocin will complain).
+ if ($bki_attr{$att}->{type} eq 'regproc')
+ {
+ my $procoid = $regprocoids{ $bki_values{$att} };
+ $bki_values{$att} = $procoid
+ if defined($procoid) && $procoid ne 'MULTIPLE';
+ }
+ }
+
+ # Save pg_proc oids for use in later regproc substitutions.
+ # This relies on the order we process the files in!
+ if ($catname eq 'pg_proc')
+ {
+ if (defined($regprocoids{ $bki_values{proname} }))
+ {
+ $regprocoids{ $bki_values{proname} } = 'MULTIPLE';
+ }
+ else
+ {
+ $regprocoids{ $bki_values{proname} } = $row->{oid};
+ }
+ }
# Save pg_type info for pg_attribute processing below
if ($catname eq 'pg_type')
{
- my %type;
+ my %type = %bki_values;
$type{oid} = $row->{oid};
- @type{@attnames} = split /\s+/, $row->{bki_values};
push @types, \%type;
}
# Write to postgres.bki
my $oid = $row->{oid} ? "OID = $row->{oid} " : '';
- printf BKI "insert %s( %s)\n", $oid, $row->{bki_values};
+ printf $bki "insert %s( %s )\n", $oid,
+ join(' ', @bki_values{@attnames});
# Write comments to postgres.description and postgres.shdescription
if (defined $row->{descr})
{
- printf DESCR "%s\t%s\t0\t%s\n", $row->{oid}, $catname,
+ printf $descr "%s\t%s\t0\t%s\n", $row->{oid}, $catname,
$row->{descr};
}
if (defined $row->{shdescr})
{
- printf SHDESCR "%s\t%s\t%s\n", $row->{oid}, $catname,
+ printf $shdescr "%s\t%s\t%s\n", $row->{oid}, $catname,
$row->{shdescr};
}
}
@@ -271,7 +307,7 @@ foreach my $catname (@{ $catalogs->{names} })
}
}
- print BKI "close $catname\n";
+ print $bki "close $catname\n";
}
# Any information needed for the BKI that is not contained in a pg_*.h header
@@ -280,25 +316,25 @@ foreach my $catname (@{ $catalogs->{names} })
# Write out declare toast/index statements
foreach my $declaration (@{ $catalogs->{toasting}->{data} })
{
- print BKI $declaration;
+ print $bki $declaration;
}
foreach my $declaration (@{ $catalogs->{indexing}->{data} })
{
- print BKI $declaration;
+ print $bki $declaration;
}
# Now generate schemapg.h
# Opening boilerplate for schemapg.h
-print SCHEMAPG <<EOM;
+print $schemapg <<EOM;
/*-------------------------------------------------------------------------
*
* schemapg.h
* Schema_pg_xxx macros for use by relcache.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* NOTES
@@ -317,19 +353,19 @@ EOM
# Emit schemapg declarations
foreach my $table_name (@tables_needing_macros)
{
- print SCHEMAPG "\n#define Schema_$table_name \\\n";
- print SCHEMAPG join ", \\\n", @{ $schemapg_entries{$table_name} };
- print SCHEMAPG "\n";
+ print $schemapg "\n#define Schema_$table_name \\\n";
+ print $schemapg join ", \\\n", @{ $schemapg_entries{$table_name} };
+ print $schemapg "\n";
}
# Closing boilerplate for schemapg.h
-print SCHEMAPG "\n#endif /* SCHEMAPG_H */\n";
+print $schemapg "\n#endif /* SCHEMAPG_H */\n";
# We're done emitting data
-close BKI;
-close SCHEMAPG;
-close DESCR;
-close SHDESCR;
+close $bki;
+close $schemapg;
+close $descr;
+close $shdescr;
# Finally, rename the completed files into place.
Catalog::RenameTempFile($bkifile, $tmpext);
@@ -413,6 +449,7 @@ sub emit_pgattr_row
attcacheoff => '-1',
atttypmod => '-1',
atthasdef => 'f',
+ attidentity => '',
attisdropped => 'f',
attislocal => 't',
attinhcount => '0',
@@ -428,8 +465,9 @@ sub bki_insert
my $row = shift;
my @attnames = @_;
my $oid = $row->{oid} ? "OID = $row->{oid} " : '';
- my $bki_values = join ' ', map $row->{$_}, @attnames;
- printf BKI "insert %s( %s)\n", $oid, $bki_values;
+ my $bki_values = join ' ', map { $_ eq '' ? '""' : $_ } map $row->{$_},
+ @attnames;
+ printf $bki "insert %s( %s )\n", $oid, $bki_values;
}
# The field values of a Schema_pg_xxx declaration are similar, but not
@@ -439,10 +477,14 @@ sub emit_schemapg_row
my $row = shift;
my @bool_attrs = @_;
+ # Replace empty string by zero char constant
+ $row->{attidentity} ||= '\0';
+
# Supply appropriate quoting for these fields.
- $row->{attname} = q|{"| . $row->{attname} . q|"}|;
- $row->{attstorage} = q|'| . $row->{attstorage} . q|'|;
- $row->{attalign} = q|'| . $row->{attalign} . q|'|;
+ $row->{attname} = q|{"| . $row->{attname} . q|"}|;
+ $row->{attstorage} = q|'| . $row->{attstorage} . q|'|;
+ $row->{attalign} = q|'| . $row->{attalign} . q|'|;
+ $row->{attidentity} = q|'| . $row->{attidentity} . q|'|;
# We don't emit initializers for the variable length fields at all.
# Only the fixed-size portions of the descriptors are ever used.
@@ -476,15 +518,15 @@ sub find_defined_symbol
}
my $file = $path . $catalog_header;
next if !-f $file;
- open(FIND_DEFINED_SYMBOL, '<', $file) || die "$file: $!";
- while (<FIND_DEFINED_SYMBOL>)
+ open(my $find_defined_symbol, '<', $file) || die "$file: $!";
+ while (<$find_defined_symbol>)
{
if (/^#define\s+\Q$symbol\E\s+(\S+)/)
{
return $1;
}
}
- close FIND_DEFINED_SYMBOL;
+ close $find_defined_symbol;
die "$file: no definition found for $symbol\n";
}
die "$catalog_header: not found in any include directory\n";
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index a1df27d43f..ea3d2ade21 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3,7 +3,7 @@
* heap.c
* code to create and destroy POSTGRES heap relations
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -42,6 +42,7 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/objectaccess.h"
+#include "catalog/partition.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
@@ -49,7 +50,10 @@
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_statistic.h"
+#include "catalog/pg_subscription_rel.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/pg_type_fn.h"
@@ -64,6 +68,7 @@
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
+#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/smgr.h"
#include "utils/acl.h"
@@ -115,6 +120,7 @@ static void StoreConstraints(Relation rel, List *cooked_constraints,
bool is_internal);
static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local,
+ bool is_initially_valid,
bool is_no_inherit);
static void SetRelationNumChecks(Relation rel, int numchecks);
static Node *cookConstraint(ParseState *pstate,
@@ -148,37 +154,37 @@ static List *insert_ordered_unique_oid(List *list, Oid datum);
static FormData_pg_attribute a1 = {
0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
- false, 'p', 's', true, false, false, true, 0
+ false, 'p', 's', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a2 = {
0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a3 = {
0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a4 = {
0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a5 = {
0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a6 = {
0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
/*
@@ -190,7 +196,7 @@ static FormData_pg_attribute a6 = {
static FormData_pg_attribute a7 = {
0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
#ifdef PGXC
@@ -314,6 +320,7 @@ heap_create(const char *relname,
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
create_storage = false;
/*
@@ -513,18 +520,7 @@ CheckAttributeType(const char *attname,
char att_typtype = get_typtype(atttypid);
Oid att_typelem;
- if (atttypid == UNKNOWNOID)
- {
- /*
- * Warn user, but don't fail, if column to be created has UNKNOWN type
- * (usually as a result of a 'retrieve into' - jolly)
- */
- ereport(WARNING,
- (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
- errmsg("column \"%s\" has type \"unknown\"", attname),
- errdetail("Proceeding with relation creation anyway.")));
- }
- else if (att_typtype == TYPTYPE_PSEUDO)
+ if (att_typtype == TYPTYPE_PSEUDO)
{
/*
* Refuse any attempt to create a pseudo-type column, except for a
@@ -620,9 +616,10 @@ CheckAttributeType(const char *attname,
* attribute to insert (but we ignore attacl and attoptions, which are always
* initialized to NULL).
*
- * indstate is the index state for CatalogIndexInsert. It can be passed as
- * NULL, in which case we'll fetch the necessary info. (Don't do this when
- * inserting multiple attributes, because it's a tad more expensive.)
+ * indstate is the index state for CatalogTupleInsertWithInfo. It can be
+ * passed as NULL, in which case we'll fetch the necessary info. (Don't do
+ * this when inserting multiple attributes, because it's a tad more
+ * expensive.)
*/
void
InsertPgAttributeTuple(Relation pg_attribute_rel,
@@ -651,6 +648,7 @@ InsertPgAttributeTuple(Relation pg_attribute_rel,
values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
+ values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
@@ -664,12 +662,10 @@ InsertPgAttributeTuple(Relation pg_attribute_rel,
tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
/* finally insert the new tuple, update the indexes, and clean up */
- simple_heap_insert(pg_attribute_rel, tup);
-
if (indstate != NULL)
- CatalogIndexInsert(indstate, tup);
+ CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
else
- CatalogUpdateIndexes(pg_attribute_rel, tup);
+ CatalogTupleInsert(pg_attribute_rel, tup);
heap_freetuple(tup);
}
@@ -834,6 +830,7 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
+ values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
if (relacl != (Datum) 0)
@@ -845,6 +842,9 @@ InsertPgClassTuple(Relation pg_class_desc,
else
nulls[Anum_pg_class_reloptions - 1] = true;
+ /* relpartbound is set by updating this tuple, if necessary */
+ nulls[Anum_pg_class_relpartbound - 1] = true;
+
tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
/*
@@ -854,9 +854,7 @@ InsertPgClassTuple(Relation pg_class_desc,
HeapTupleSetOid(tup, new_rel_oid);
/* finally insert the new tuple, update the indexes, and clean up */
- simple_heap_insert(pg_class_desc, tup);
-
- CatalogUpdateIndexes(pg_class_desc, tup);
+ CatalogTupleInsert(pg_class_desc, tup);
heap_freetuple(tup);
}
@@ -950,6 +948,9 @@ AddNewRelationTuple(Relation pg_class_desc,
new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->reloftype = reloftype;
+ /* relispartition is always set by updating this tuple later */
+ new_rel_reltup->relispartition = false;
+
new_rel_desc->rd_att->tdtypeid = new_type_oid;
/* Now build and insert the tuple */
@@ -1484,7 +1485,8 @@ heap_create_with_catalog(const char *relname,
if (IsBinaryUpgrade &&
(relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
- relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE))
+ relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
+ relkind == RELKIND_PARTITIONED_TABLE))
{
if (!OidIsValid(binary_upgrade_next_heap_pg_class_oid))
ereport(ERROR,
@@ -1518,6 +1520,7 @@ heap_create_with_catalog(const char *relname,
case RELKIND_VIEW:
case RELKIND_MATVIEW:
case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
relacl = get_user_default_acl(ACL_OBJECT_RELATION, ownerid,
relnamespace);
break;
@@ -1562,7 +1565,8 @@ heap_create_with_catalog(const char *relname,
relkind == RELKIND_VIEW ||
relkind == RELKIND_MATVIEW ||
relkind == RELKIND_FOREIGN_TABLE ||
- relkind == RELKIND_COMPOSITE_TYPE))
+ relkind == RELKIND_COMPOSITE_TYPE ||
+ relkind == RELKIND_PARTITIONED_TABLE))
new_array_oid = AssignTypeArrayOid();
/*
@@ -1665,10 +1669,6 @@ heap_create_with_catalog(const char *relname,
* should they have any ACL entries. The same applies for extension
* dependencies.
*
- * If it's a temp table, we do not make it an extension member; this
- * prevents the unintuitive result that deletion of the temp table at
- * session end would make the whole extension go away.
- *
* Also, skip this in bootstrap mode, since we don't make dependencies
* while bootstrapping.
*/
@@ -1689,8 +1689,7 @@ heap_create_with_catalog(const char *relname,
recordDependencyOnOwner(RelationRelationId, relid, ownerid);
- if (relpersistence != RELPERSISTENCE_TEMP)
- recordDependencyOnCurrentExtension(&myself, false);
+ recordDependencyOnCurrentExtension(&myself, false);
if (reloftypeid)
{
@@ -1731,12 +1730,13 @@ heap_create_with_catalog(const char *relname,
if (oncommit != ONCOMMIT_NOOP)
register_on_commit_action(relid, oncommit);
- if (relpersistence == RELPERSISTENCE_UNLOGGED)
- {
- Assert(relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW ||
- relkind == RELKIND_TOASTVALUE);
+ /*
+ * Unlogged objects need an init fork, except for partitioned tables which
+ * have no storage at all.
+ */
+ if (relpersistence == RELPERSISTENCE_UNLOGGED &&
+ relkind != RELKIND_PARTITIONED_TABLE)
heap_create_init_fork(new_rel_desc);
- }
/*
* ok, the relation has been cataloged, so close our relations and return
@@ -1750,18 +1750,22 @@ heap_create_with_catalog(const char *relname,
/*
* Set up an init fork for an unlogged table so that it can be correctly
- * reinitialized on restart. Since we're going to do an immediate sync, we
- * only need to xlog this if archiving or streaming is enabled. And the
- * immediate sync is required, because otherwise there's no guarantee that
- * this will hit the disk before the next checkpoint moves the redo pointer.
+ * reinitialized on restart. An immediate sync is required even if the
+ * page has been logged, because the write did not go through
+ * shared_buffers and therefore a concurrent checkpoint may have moved
+ * the redo pointer past our xlog record. Recovery may as well remove it
+ * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE
+ * record. Therefore, logging is necessary even if wal_level=minimal.
*/
void
heap_create_init_fork(Relation rel)
{
+ Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
+ rel->rd_rel->relkind == RELKIND_MATVIEW ||
+ rel->rd_rel->relkind == RELKIND_TOASTVALUE);
RelationOpenSmgr(rel);
smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
- if (XLogIsNeeded())
- log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
+ log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
}
@@ -1793,7 +1797,7 @@ RelationRemoveInheritance(Oid relid)
NULL, 1, &key);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
- simple_heap_delete(catalogRelation, &tuple->t_self);
+ CatalogTupleDelete(catalogRelation, &tuple->t_self);
systable_endscan(scan);
heap_close(catalogRelation, RowExclusiveLock);
@@ -1821,7 +1825,7 @@ DeleteRelationTuple(Oid relid)
elog(ERROR, "cache lookup failed for relation %u", relid);
/* delete the relation tuple from pg_class, and finish up */
- simple_heap_delete(pg_class_desc, &tup->t_self);
+ CatalogTupleDelete(pg_class_desc, &tup->t_self);
ReleaseSysCache(tup);
@@ -1858,7 +1862,7 @@ DeleteAttributeTuples(Oid relid)
/* Delete all the matching tuples */
while ((atttup = systable_getnext(scan)) != NULL)
- simple_heap_delete(attrel, &atttup->t_self);
+ CatalogTupleDelete(attrel, &atttup->t_self);
/* Clean up after the scan */
systable_endscan(scan);
@@ -1899,7 +1903,7 @@ DeleteSystemAttributeTuples(Oid relid)
/* Delete all the matching tuples */
while ((atttup = systable_getnext(scan)) != NULL)
- simple_heap_delete(attrel, &atttup->t_self);
+ CatalogTupleDelete(attrel, &atttup->t_self);
/* Clean up after the scan */
systable_endscan(scan);
@@ -1946,7 +1950,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
{
/* System attribute (probably OID) ... just delete the row */
- simple_heap_delete(attr_rel, &tuple->t_self);
+ CatalogTupleDelete(attr_rel, &tuple->t_self);
}
else
{
@@ -1979,10 +1983,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
"........pg.dropped.%d........", attnum);
namestrcpy(&(attStruct->attname), newattname);
- simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(attr_rel, tuple);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
}
/*
@@ -2094,7 +2095,7 @@ RemoveAttrDefaultById(Oid attrdefId)
myrel = relation_open(myrelid, AccessExclusiveLock);
/* Now we can delete the pg_attrdef row */
- simple_heap_delete(attrdef_rel, &tuple->t_self);
+ CatalogTupleDelete(attrdef_rel, &tuple->t_self);
systable_endscan(scan);
heap_close(attrdef_rel, RowExclusiveLock);
@@ -2111,10 +2112,7 @@ RemoveAttrDefaultById(Oid attrdefId)
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
- simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(attr_rel, tuple);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
/*
* Our update of the pg_attribute row will force a relcache rebuild, so
@@ -2139,6 +2137,26 @@ void
heap_drop_with_catalog(Oid relid)
{
Relation rel;
+ HeapTuple tuple;
+ Oid parentOid = InvalidOid;
+
+ /*
+ * To drop a partition safely, we must grab exclusive lock on its parent,
+ * because another backend might be about to execute a query on the parent
+ * table. If it relies on previously cached partition descriptor, then it
+ * could attempt to access the just-dropped relation as its partition. We
+ * must therefore take a table lock strong enough to prevent all queries
+ * on the table from proceeding until we commit and send out a
+ * shared-cache-inval notice that will make them update their index lists.
+ */
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
+ {
+ parentOid = get_partition_parent(relid);
+ LockRelationOid(parentOid, AccessExclusiveLock);
+ }
+
+ ReleaseSysCache(tuple);
/*
* Open and lock the relation.
@@ -2174,18 +2192,25 @@ heap_drop_with_catalog(Oid relid)
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for foreign table %u", relid);
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
ReleaseSysCache(tuple);
heap_close(rel, RowExclusiveLock);
}
/*
+ * If a partitioned table, delete the pg_partitioned_table tuple.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ RemovePartitionKeyByRelId(relid);
+
+ /*
* Schedule unlinking of the relation's physical files at commit.
*/
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
- rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
{
RelationDropStorage(rel);
}
@@ -2198,6 +2223,11 @@ heap_drop_with_catalog(Oid relid)
relation_close(rel, NoLock);
/*
+ * Remove any associated relation synchronization states.
+ */
+ RemoveSubscriptionRel(InvalidOid, relid);
+
+ /*
* Forget any ON COMMIT action for the rel
*/
remove_on_commit_action(relid);
@@ -2230,6 +2260,16 @@ heap_drop_with_catalog(Oid relid)
* delete relation tuple
*/
DeleteRelationTuple(relid);
+
+ if (OidIsValid(parentOid))
+ {
+ /*
+ * Invalidate the parent's relcache so that the partition is no longer
+ * included in its partition descriptor.
+ */
+ CacheInvalidateRelcacheByRelid(parentOid);
+ /* keep the lock */
+ }
}
@@ -2279,9 +2319,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
tuple = heap_form_tuple(adrel->rd_att, values, nulls);
- attrdefOid = simple_heap_insert(adrel, tuple);
-
- CatalogUpdateIndexes(adrel, tuple);
+ attrdefOid = CatalogTupleInsert(adrel, tuple);
defobject.classId = AttrDefaultRelationId;
defobject.objectId = attrdefOid;
@@ -2311,9 +2349,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
if (!attStruct->atthasdef)
{
attStruct->atthasdef = true;
- simple_heap_update(attrrel, &atttup->t_self, atttup);
- /* keep catalog indexes current */
- CatalogUpdateIndexes(attrrel, atttup);
+ CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
}
heap_close(attrrel, RowExclusiveLock);
heap_freetuple(atttup);
@@ -2413,6 +2449,17 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
attNos = NULL;
/*
+ * Partitioned tables do not contain any rows themselves, so a NO INHERIT
+ * constraint makes no sense.
+ */
+ if (is_no_inherit &&
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
+ RelationGetRelationName(rel))));
+
+ /*
* Create the Check Constraint
*/
constrOid =
@@ -2682,6 +2729,7 @@ AddRelationNewConstraints(Relation rel,
*/
if (MergeWithExistingConstraint(rel, ccname, expr,
allow_merge, is_local,
+ cdef->initially_valid,
cdef->is_no_inherit))
continue;
}
@@ -2770,6 +2818,7 @@ AddRelationNewConstraints(Relation rel,
static bool
MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local,
+ bool is_initially_valid,
bool is_no_inherit)
{
bool found;
@@ -2817,37 +2866,85 @@ MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
if (equal(expr, stringToNode(TextDatumGetCString(val))))
found = true;
}
+
+ /*
+ * If the existing constraint is purely inherited (no local
+ * definition) then interpret addition of a local constraint as a
+ * legal merge. This allows ALTER ADD CONSTRAINT on parent and
+ * child tables to be given in either order with same end state.
+ * However if the relation is a partition, all inherited
+ * constraints are always non-local, including those that were
+ * merged.
+ */
+ if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
+ allow_merge = true;
+
if (!found || !allow_merge)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("constraint \"%s\" for relation \"%s\" already exists",
ccname, RelationGetRelationName(rel))));
- tup = heap_copytuple(tup);
- con = (Form_pg_constraint) GETSTRUCT(tup);
-
- /* If the constraint is "no inherit" then cannot merge */
+ /* If the child constraint is "no inherit" then cannot merge */
if (con->connoinherit)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
ccname, RelationGetRelationName(rel))));
- if (is_local)
- con->conislocal = true;
+ /*
+ * Must not change an existing inherited constraint to "no
+ * inherit" status. That's because inherited constraints should
+ * be able to propagate to lower-level children.
+ */
+ if (con->coninhcount > 0 && is_no_inherit)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
+ ccname, RelationGetRelationName(rel))));
+
+ /*
+ * If the child constraint is "not valid" then cannot merge with a
+ * valid parent constraint
+ */
+ if (is_initially_valid && !con->convalidated)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
+ ccname, RelationGetRelationName(rel))));
+
+ /* OK to update the tuple */
+ ereport(NOTICE,
+ (errmsg("merging constraint \"%s\" with inherited definition",
+ ccname)));
+
+ tup = heap_copytuple(tup);
+ con = (Form_pg_constraint) GETSTRUCT(tup);
+
+ /*
+ * In case of partitions, an inherited constraint must be
+ * inherited only once since it cannot have multiple parents and
+ * it is never considered local.
+ */
+ if (rel->rd_rel->relispartition)
+ {
+ con->coninhcount = 1;
+ con->conislocal = false;
+ }
else
- con->coninhcount++;
+ {
+ if (is_local)
+ con->conislocal = true;
+ else
+ con->coninhcount++;
+ }
+
if (is_no_inherit)
{
Assert(is_local);
con->connoinherit = true;
}
- /* OK to update the tuple */
- ereport(NOTICE,
- (errmsg("merging constraint \"%s\" with inherited definition",
- ccname)));
- simple_heap_update(conDesc, &tup->t_self, tup);
- CatalogUpdateIndexes(conDesc, tup);
+ CatalogTupleUpdate(conDesc, &tup->t_self, tup);
break;
}
}
@@ -2887,10 +2984,7 @@ SetRelationNumChecks(Relation rel, int numchecks)
{
relStruct->relchecks = numchecks;
- simple_heap_update(relrel, &reltup->t_self, reltup);
-
- /* keep catalog indexes current */
- CatalogUpdateIndexes(relrel, reltup);
+ CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
}
else
{
@@ -2941,14 +3035,9 @@ cookDefault(ParseState *pstate,
/*
* transformExpr() should have already rejected subqueries, aggregates,
- * and window functions, based on the EXPR_KIND_ for a default expression.
- *
- * It can't return a set either.
+ * window functions, and SRFs, based on the EXPR_KIND_ for a default
+ * expression.
*/
- if (expression_returns_set(expr))
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("default expression must not return a set")));
/*
* Coerce the expression to the correct type and typmod, if given. This
@@ -3064,7 +3153,7 @@ RemoveStatistics(Oid relid, AttrNumber attnum)
/* we must loop even when attnum != 0, in case of inherited stats */
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
- simple_heap_delete(pgstatistic, &tuple->t_self);
+ CatalogTupleDelete(pgstatistic, &tuple->t_self);
systable_endscan(scan);
@@ -3369,3 +3458,192 @@ insert_ordered_unique_oid(List *list, Oid datum)
lappend_cell_oid(list, prev, datum);
return list;
}
+
+/*
+ * StorePartitionKey
+ * Store information about the partition key rel into the catalog
+ */
+void
+StorePartitionKey(Relation rel,
+ char strategy,
+ int16 partnatts,
+ AttrNumber *partattrs,
+ List *partexprs,
+ Oid *partopclass,
+ Oid *partcollation)
+{
+ int i;
+ int2vector *partattrs_vec;
+ oidvector *partopclass_vec;
+ oidvector *partcollation_vec;
+ Datum partexprDatum;
+ Relation pg_partitioned_table;
+ HeapTuple tuple;
+ Datum values[Natts_pg_partitioned_table];
+ bool nulls[Natts_pg_partitioned_table];
+ ObjectAddress myself;
+ ObjectAddress referenced;
+
+ Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+
+ tuple = SearchSysCache1(PARTRELID,
+ ObjectIdGetDatum(RelationGetRelid(rel)));
+
+ /* Copy the partition attribute numbers, opclass OIDs into arrays */
+ partattrs_vec = buildint2vector(partattrs, partnatts);
+ partopclass_vec = buildoidvector(partopclass, partnatts);
+ partcollation_vec = buildoidvector(partcollation, partnatts);
+
+ /* Convert the expressions (if any) to a text datum */
+ if (partexprs)
+ {
+ char *exprString;
+
+ exprString = nodeToString(partexprs);
+ partexprDatum = CStringGetTextDatum(exprString);
+ pfree(exprString);
+ }
+ else
+ partexprDatum = (Datum) 0;
+
+ pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
+
+ MemSet(nulls, false, sizeof(nulls));
+
+ /* Only this can ever be NULL */
+ if (!partexprDatum)
+ nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
+
+ values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
+ values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
+ values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
+ values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
+ values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
+ values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
+ values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
+
+ tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
+
+ CatalogTupleInsert(pg_partitioned_table, tuple);
+ heap_close(pg_partitioned_table, RowExclusiveLock);
+
+ /* Mark this relation as dependent on a few things as follows */
+ myself.classId = RelationRelationId;
+ myself.objectId = RelationGetRelid(rel);;
+ myself.objectSubId = 0;
+
+ /* Operator class and collation per key column */
+ for (i = 0; i < partnatts; i++)
+ {
+ referenced.classId = OperatorClassRelationId;
+ referenced.objectId = partopclass[i];
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ referenced.classId = CollationRelationId;
+ referenced.objectId = partcollation[i];
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /*
+ * Anything mentioned in the expressions. We must ignore the column
+ * references, which will depend on the table itself; there is no separate
+ * partition key object.
+ */
+ if (partexprs)
+ recordDependencyOnSingleRelExpr(&myself,
+ (Node *) partexprs,
+ RelationGetRelid(rel),
+ DEPENDENCY_NORMAL,
+ DEPENDENCY_AUTO, true);
+
+ /*
+ * We must invalidate the relcache so that the next
+ * CommandCounterIncrement() will cause the same to be rebuilt using the
+ * information in just created catalog entry.
+ */
+ CacheInvalidateRelcache(rel);
+}
+
+/*
+ * RemovePartitionKeyByRelId
+ * Remove pg_partitioned_table entry for a relation
+ */
+void
+RemovePartitionKeyByRelId(Oid relid)
+{
+ Relation rel;
+ HeapTuple tuple;
+
+ rel = heap_open(PartitionedRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for partition key of relation %u",
+ relid);
+
+ CatalogTupleDelete(rel, &tuple->t_self);
+
+ ReleaseSysCache(tuple);
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * StorePartitionBound
+ * Update pg_class tuple of rel to store the partition bound and set
+ * relispartition to true
+ *
+ * Also, invalidate the parent's relcache, so that the next rebuild will load
+ * the new partition's info into its partition descriptor.
+ */
+void
+StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
+{
+ Relation classRel;
+ HeapTuple tuple,
+ newtuple;
+ Datum new_val[Natts_pg_class];
+ bool new_null[Natts_pg_class],
+ new_repl[Natts_pg_class];
+
+ /* Update pg_class tuple */
+ classRel = heap_open(RelationRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(RelationGetRelid(rel)));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u",
+ RelationGetRelid(rel));
+
+#ifdef USE_ASSERT_CHECKING
+ {
+ Form_pg_class classForm;
+ bool isnull;
+
+ classForm = (Form_pg_class) GETSTRUCT(tuple);
+ Assert(!classForm->relispartition);
+ (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
+ &isnull);
+ Assert(isnull);
+ }
+#endif
+
+ /* Fill in relpartbound value */
+ memset(new_val, 0, sizeof(new_val));
+ memset(new_null, false, sizeof(new_null));
+ memset(new_repl, false, sizeof(new_repl));
+ new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
+ new_null[Anum_pg_class_relpartbound - 1] = false;
+ new_repl[Anum_pg_class_relpartbound - 1] = true;
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
+ new_val, new_null, new_repl);
+ /* Also set the flag */
+ ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
+ CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
+ heap_freetuple(newtuple);
+ heap_close(classRel, RowExclusiveLock);
+
+ CacheInvalidateRelcache(parent);
+}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5d895de9af..9104855ce2 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -3,7 +3,7 @@
* index.c
* code to create and destroy POSTGRES index relations
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -354,6 +354,7 @@ ConstructTupleDescriptor(Relation heapRelation,
to->attcacheoff = -1;
to->attnotnull = false;
to->atthasdef = false;
+ to->attidentity = '\0';
to->attislocal = true;
to->attinhcount = 0;
to->attcollation = collationObjectId[i];
@@ -438,11 +439,28 @@ ConstructTupleDescriptor(Relation heapRelation,
keyType = opclassTup->opckeytype;
else
keyType = amroutine->amkeytype;
+
+ /*
+ * If keytype is specified as ANYELEMENT, and opcintype is ANYARRAY,
+ * then the attribute type must be an array (else it'd not have
+ * matched this opclass); use its element type.
+ */
+ if (keyType == ANYELEMENTOID && opclassTup->opcintype == ANYARRAYOID)
+ {
+ keyType = get_base_element_type(to->atttypid);
+ if (!OidIsValid(keyType))
+ elog(ERROR, "could not get element type of array type %u",
+ to->atttypid);
+ }
+
ReleaseSysCache(tuple);
+ /*
+ * If a key type different from the heap value is specified, update
+ * the type-related fields in the index tupdesc.
+ */
if (OidIsValid(keyType) && keyType != to->atttypid)
{
- /* index value and heap value have different types */
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for type %u", keyType);
@@ -633,10 +651,7 @@ UpdateIndexRelation(Oid indexoid,
/*
* insert the tuple into the pg_index catalog
*/
- simple_heap_insert(pg_index, tuple);
-
- /* update the indexes on pg_index */
- CatalogUpdateIndexes(pg_index, tuple);
+ CatalogTupleInsert(pg_index, tuple);
/*
* close the relation and free the tuple
@@ -1027,7 +1042,7 @@ index_create(Relation heapRelation,
(Node *) indexInfo->ii_Expressions,
heapRelationId,
DEPENDENCY_NORMAL,
- DEPENDENCY_AUTO);
+ DEPENDENCY_AUTO, false);
}
/* Store dependencies on anything mentioned in predicate */
@@ -1037,7 +1052,7 @@ index_create(Relation heapRelation,
(Node *) indexInfo->ii_Predicate,
heapRelationId,
DEPENDENCY_NORMAL,
- DEPENDENCY_AUTO);
+ DEPENDENCY_AUTO, false);
}
}
else
@@ -1308,8 +1323,7 @@ index_constraint_create(Relation heapRelation,
if (dirty)
{
- simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
- CatalogUpdateIndexes(pg_index, indexTuple);
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
InvalidOid, is_internal);
@@ -1561,7 +1575,7 @@ index_drop(Oid indexId, bool concurrent)
hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs);
- simple_heap_delete(indexRelation, &tuple->t_self);
+ CatalogTupleDelete(indexRelation, &tuple->t_self);
ReleaseSysCache(tuple);
heap_close(indexRelation, RowExclusiveLock);
@@ -1646,7 +1660,7 @@ BuildIndexInfo(Relation index)
/* fetch index predicate if any */
ii->ii_Predicate = RelationGetIndexPredicate(index);
- ii->ii_PredicateState = NIL;
+ ii->ii_PredicateState = NULL;
/* fetch exclusion constraint info if any */
if (indexStruct->indisexclusion)
@@ -1675,6 +1689,10 @@ BuildIndexInfo(Relation index)
ii->ii_Concurrent = false;
ii->ii_BrokenHotChain = false;
+ /* set up for possible use by index AM */
+ ii->ii_AmCache = NULL;
+ ii->ii_Context = CurrentMemoryContext;
+
return ii;
}
@@ -1758,9 +1776,8 @@ FormIndexDatum(IndexInfo *indexInfo,
indexInfo->ii_ExpressionsState == NIL)
{
/* First time through, set up expression evaluation state */
- indexInfo->ii_ExpressionsState = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Expressions,
- estate);
+ indexInfo->ii_ExpressionsState =
+ ExecPrepareExprList(indexInfo->ii_Expressions, estate);
/* Check caller has set up context correctly */
Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
}
@@ -1789,8 +1806,7 @@ FormIndexDatum(IndexInfo *indexInfo,
elog(ERROR, "wrong number of index expressions");
iDatum = ExecEvalExprSwitchContext((ExprState *) lfirst(indexpr_item),
GetPerTupleExprContext(estate),
- &isNull,
- NULL);
+ &isNull);
indexpr_item = lnext(indexpr_item);
}
values[i] = iDatum;
@@ -1843,8 +1859,8 @@ index_update_stats(Relation rel,
* 1. In bootstrap mode, we have no choice --- UPDATE wouldn't work.
*
* 2. We could be reindexing pg_class itself, in which case we can't move
- * its pg_class row because CatalogUpdateIndexes might not know about all
- * the indexes yet (see reindex_relation).
+ * its pg_class row because CatalogTupleInsert/CatalogTupleUpdate might
+ * not know about all the indexes yet (see reindex_relation).
*
* 3. Because we execute CREATE INDEX with just share lock on the parent
* rel (to allow concurrent index creations), an ordinary update could
@@ -2102,8 +2118,7 @@ index_build(Relation heapRelation,
Assert(!indexForm->indcheckxmin);
indexForm->indcheckxmin = true;
- simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
- CatalogUpdateIndexes(pg_index, indexTuple);
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
heap_freetuple(indexTuple);
heap_close(pg_index, RowExclusiveLock);
@@ -2208,7 +2223,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
Datum values[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
double reltuples;
- List *predicate;
+ ExprState *predicate;
TupleTableSlot *slot;
EState *estate;
ExprContext *econtext;
@@ -2247,9 +2262,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
econtext->ecxt_scantuple = slot;
/* Set up execution state for predicate, if any. */
- predicate = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
- estate);
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
/*
* Prepare for scan of the base relation. In a normal index build, we use
@@ -2270,7 +2283,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
{
snapshot = SnapshotAny;
/* okay to ignore lazy VACUUMs here */
- OldestXmin = GetOldestXmin(heapRelation, true);
+ OldestXmin = GetOldestXmin(heapRelation, PROCARRAY_FLAGS_VACUUM);
}
scan = heap_beginscan_strat(heapRelation, /* relation */
@@ -2552,9 +2565,9 @@ IndexBuildHeapRangeScan(Relation heapRelation,
* In a partial index, discard tuples that don't satisfy the
* predicate.
*/
- if (predicate != NIL)
+ if (predicate != NULL)
{
- if (!ExecQual(predicate, econtext, false))
+ if (!ExecQual(predicate, econtext))
continue;
}
@@ -2619,7 +2632,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
/* These may have been pointing to the now-gone estate */
indexInfo->ii_ExpressionsState = NIL;
- indexInfo->ii_PredicateState = NIL;
+ indexInfo->ii_PredicateState = NULL;
return reltuples;
}
@@ -2646,7 +2659,7 @@ IndexCheckExclusion(Relation heapRelation,
HeapTuple heapTuple;
Datum values[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
- List *predicate;
+ ExprState *predicate;
TupleTableSlot *slot;
EState *estate;
ExprContext *econtext;
@@ -2672,9 +2685,7 @@ IndexCheckExclusion(Relation heapRelation,
econtext->ecxt_scantuple = slot;
/* Set up execution state for predicate, if any. */
- predicate = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
- estate);
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
/*
* Scan all live tuples in the base relation.
@@ -2699,9 +2710,9 @@ IndexCheckExclusion(Relation heapRelation,
/*
* In a partial index, ignore tuples that don't satisfy the predicate.
*/
- if (predicate != NIL)
+ if (predicate != NULL)
{
- if (!ExecQual(predicate, econtext, false))
+ if (!ExecQual(predicate, econtext))
continue;
}
@@ -2732,7 +2743,7 @@ IndexCheckExclusion(Relation heapRelation,
/* These may have been pointing to the now-gone estate */
indexInfo->ii_ExpressionsState = NIL;
- indexInfo->ii_PredicateState = NIL;
+ indexInfo->ii_PredicateState = NULL;
}
@@ -2962,7 +2973,7 @@ validate_index_heapscan(Relation heapRelation,
HeapTuple heapTuple;
Datum values[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
- List *predicate;
+ ExprState *predicate;
TupleTableSlot *slot;
EState *estate;
ExprContext *econtext;
@@ -2992,9 +3003,7 @@ validate_index_heapscan(Relation heapRelation,
econtext->ecxt_scantuple = slot;
/* Set up execution state for predicate, if any. */
- predicate = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
- estate);
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
/*
* Prepare for scan of the base relation. We need just those tuples
@@ -3121,9 +3130,9 @@ validate_index_heapscan(Relation heapRelation,
* In a partial index, discard tuples that don't satisfy the
* predicate.
*/
- if (predicate != NIL)
+ if (predicate != NULL)
{
- if (!ExecQual(predicate, econtext, false))
+ if (!ExecQual(predicate, econtext))
continue;
}
@@ -3162,7 +3171,8 @@ validate_index_heapscan(Relation heapRelation,
&rootTuple,
heapRelation,
indexInfo->ii_Unique ?
- UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+ UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+ indexInfo);
state->tups_inserted += 1;
}
@@ -3176,7 +3186,7 @@ validate_index_heapscan(Relation heapRelation,
/* These may have been pointing to the now-gone estate */
indexInfo->ii_ExpressionsState = NIL;
- indexInfo->ii_PredicateState = NIL;
+ indexInfo->ii_PredicateState = NULL;
}
@@ -3447,8 +3457,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
indexForm->indisvalid = true;
indexForm->indisready = true;
indexForm->indislive = true;
- simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
- CatalogUpdateIndexes(pg_index, indexTuple);
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
/*
* Invalidate the relcache for the table, so that after we commit
@@ -3542,9 +3551,9 @@ reindex_relation(Oid relid, int flags, int options)
* that the updates do not try to insert index entries into indexes we
* have not processed yet. (When we are trying to recover from corrupted
* indexes, that could easily cause a crash.) We can accomplish this
- * because CatalogUpdateIndexes will use the relcache's index list to know
- * which indexes to update. We just force the index list to be only the
- * stuff we've processed.
+ * because CatalogTupleInsert/CatalogTupleUpdate will use the relcache's
+ * index list to know which indexes to update. We just force the index
+ * list to be only the stuff we've processed.
*
* It is okay to not insert entries into the indexes we have not processed
* yet because all of this is transaction-safe. If we fail partway
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index b9fe10237b..abc344ad69 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -4,7 +4,7 @@
* This file contains routines to support indexes defined on system
* catalogs.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -68,7 +68,7 @@ CatalogCloseIndexes(CatalogIndexState indstate)
*
* This is effectively a cut-down version of ExecInsertIndexTuples.
*/
-void
+static void
CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
{
int i;
@@ -139,26 +139,120 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
&(heapTuple->t_self), /* tid of heap tuple */
heapRelation,
relationDescs[i]->rd_index->indisunique ?
- UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+ UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+ indexInfo);
}
ExecDropSingleTupleTableSlot(slot);
}
/*
- * CatalogUpdateIndexes - do all the indexing work for a new catalog tuple
+ * CatalogTupleInsert - do heap and indexing work for a new catalog tuple
+ *
+ * Insert the tuple data in "tup" into the specified catalog relation.
+ * The Oid of the inserted tuple is returned.
+ *
+ * This is a convenience routine for the common case of inserting a single
+ * tuple in a system catalog; it inserts a new heap tuple, keeping indexes
+ * current. Avoid using it for multiple tuples, since opening the indexes
+ * and building the index info structures is moderately expensive.
+ * (Use CatalogTupleInsertWithInfo in such cases.)
+ */
+Oid
+CatalogTupleInsert(Relation heapRel, HeapTuple tup)
+{
+ CatalogIndexState indstate;
+ Oid oid;
+
+ indstate = CatalogOpenIndexes(heapRel);
+
+ oid = simple_heap_insert(heapRel, tup);
+
+ CatalogIndexInsert(indstate, tup);
+ CatalogCloseIndexes(indstate);
+
+ return oid;
+}
+
+/*
+ * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
+ *
+ * This should be used when it's important to amortize CatalogOpenIndexes/
+ * CatalogCloseIndexes work across multiple insertions. At some point we
+ * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
+ * so that callers needn't trouble over this ... but we don't do so today.
+ */
+Oid
+CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate)
+{
+ Oid oid;
+
+ oid = simple_heap_insert(heapRel, tup);
+
+ CatalogIndexInsert(indstate, tup);
+
+ return oid;
+}
+
+/*
+ * CatalogTupleUpdate - do heap and indexing work for updating a catalog tuple
+ *
+ * Update the tuple identified by "otid", replacing it with the data in "tup".
*
- * This is a convenience routine for the common case where we only need
- * to insert or update a single tuple in a system catalog. Avoid using it for
- * multiple tuples, since opening the indexes and building the index info
- * structures is moderately expensive.
+ * This is a convenience routine for the common case of updating a single
+ * tuple in a system catalog; it updates one heap tuple, keeping indexes
+ * current. Avoid using it for multiple tuples, since opening the indexes
+ * and building the index info structures is moderately expensive.
+ * (Use CatalogTupleUpdateWithInfo in such cases.)
*/
void
-CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
+CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
{
CatalogIndexState indstate;
indstate = CatalogOpenIndexes(heapRel);
- CatalogIndexInsert(indstate, heapTuple);
+
+ simple_heap_update(heapRel, otid, tup);
+
+ CatalogIndexInsert(indstate, tup);
CatalogCloseIndexes(indstate);
}
+
+/*
+ * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
+ *
+ * This should be used when it's important to amortize CatalogOpenIndexes/
+ * CatalogCloseIndexes work across multiple updates. At some point we
+ * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
+ * so that callers needn't trouble over this ... but we don't do so today.
+ */
+void
+CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup,
+ CatalogIndexState indstate)
+{
+ simple_heap_update(heapRel, otid, tup);
+
+ CatalogIndexInsert(indstate, tup);
+}
+
+/*
+ * CatalogTupleDelete - do heap and indexing work for deleting a catalog tuple
+ *
+ * Delete the tuple identified by "tid" in the specified catalog.
+ *
+ * With Postgres heaps, there is no index work to do at deletion time;
+ * cleanup will be done later by VACUUM. However, callers of this function
+ * shouldn't have to know that; we'd like a uniform abstraction for all
+ * catalog tuple changes. Hence, provide this currently-trivial wrapper.
+ *
+ * The abstraction is a bit leaky in that we don't provide an optimized
+ * CatalogTupleDeleteWithInfo version, because there is currently nothing to
+ * optimize. If we ever need that, rather than touching a lot of call sites,
+ * it might be better to do something about caching CatalogIndexState.
+ */
+void
+CatalogTupleDelete(Relation heapRel, ItemPointer tid)
+{
+ simple_heap_delete(heapRel, tid);
+}
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
index 18be08fead..cbcd6cfbc1 100644
--- a/src/backend/catalog/information_schema.sql
+++ b/src/backend/catalog/information_schema.sql
@@ -2,7 +2,7 @@
* SQL Information Schema
* as defined in ISO/IEC 9075-11:2011
*
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2003-2017, PostgreSQL Global Development Group
*
* src/backend/catalog/information_schema.sql
*
@@ -42,14 +42,14 @@ SET search_path TO information_schema;
/* Expand any 1-D array into a set with integers 1..N */
CREATE FUNCTION _pg_expandarray(IN anyarray, OUT x anyelement, OUT n int)
RETURNS SETOF RECORD
- LANGUAGE sql STRICT IMMUTABLE
+ LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE
AS 'select $1[s], s - pg_catalog.array_lower($1,1) + 1
from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
pg_catalog.array_upper($1,1),
1) as g(s)';
CREATE FUNCTION _pg_keysequal(smallint[], smallint[]) RETURNS boolean
- LANGUAGE sql IMMUTABLE -- intentionally not STRICT, to allow inlining
+ LANGUAGE sql IMMUTABLE PARALLEL SAFE -- intentionally not STRICT, to allow inlining
AS 'select $1 operator(pg_catalog.<@) $2 and $2 operator(pg_catalog.<@) $1';
/* Given an index's OID and an underlying-table column number, return the
@@ -66,6 +66,7 @@ $$;
CREATE FUNCTION _pg_truetypid(pg_attribute, pg_type) RETURNS oid
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT CASE WHEN $2.typtype = 'd' THEN $2.typbasetype ELSE $1.atttypid END$$;
@@ -73,6 +74,7 @@ $$SELECT CASE WHEN $2.typtype = 'd' THEN $2.typbasetype ELSE $1.atttypid END$$;
CREATE FUNCTION _pg_truetypmod(pg_attribute, pg_type) RETURNS int4
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT CASE WHEN $2.typtype = 'd' THEN $2.typtypmod ELSE $1.atttypmod END$$;
@@ -82,6 +84,7 @@ $$SELECT CASE WHEN $2.typtype = 'd' THEN $2.typtypmod ELSE $1.atttypmod END$$;
CREATE FUNCTION _pg_char_max_length(typid oid, typmod int4) RETURNS integer
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -97,6 +100,7 @@ $$SELECT
CREATE FUNCTION _pg_char_octet_length(typid oid, typmod int4) RETURNS integer
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -112,6 +116,7 @@ $$SELECT
CREATE FUNCTION _pg_numeric_precision(typid oid, typmod int4) RETURNS integer
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -132,6 +137,7 @@ $$SELECT
CREATE FUNCTION _pg_numeric_precision_radix(typid oid, typmod int4) RETURNS integer
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -143,6 +149,7 @@ $$SELECT
CREATE FUNCTION _pg_numeric_scale(typid oid, typmod int4) RETURNS integer
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -158,6 +165,7 @@ $$SELECT
CREATE FUNCTION _pg_datetime_precision(typid oid, typmod int4) RETURNS integer
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -173,6 +181,7 @@ $$SELECT
CREATE FUNCTION _pg_interval_type(typid oid, mod int4) RETURNS text
LANGUAGE sql
IMMUTABLE
+ PARALLEL SAFE
RETURNS NULL ON NULL INPUT
AS
$$SELECT
@@ -365,7 +374,7 @@ CREATE VIEW attributes AS
ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default')
WHERE a.attnum > 0 AND NOT a.attisdropped
- AND c.relkind in ('c')
+ AND c.relkind IN ('c')
AND (pg_has_role(c.relowner, 'USAGE')
OR has_type_privilege(c.reltype, 'USAGE'));
@@ -453,7 +462,7 @@ CREATE VIEW check_constraints AS
AND a.attnum > 0
AND NOT a.attisdropped
AND a.attnotnull
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
AND pg_has_role(r.relowner, 'USAGE');
GRANT SELECT ON check_constraints TO PUBLIC;
@@ -525,7 +534,7 @@ CREATE VIEW column_domain_usage AS
AND a.attrelid = c.oid
AND a.atttypid = t.oid
AND t.typtype = 'd'
- AND c.relkind IN ('r', 'v', 'f')
+ AND c.relkind IN ('r', 'v', 'f', 'p')
AND a.attnum > 0
AND NOT a.attisdropped
AND pg_has_role(t.typowner, 'USAGE');
@@ -564,7 +573,7 @@ CREATE VIEW column_privileges AS
pr_c.relowner
FROM (SELECT oid, relname, relnamespace, relowner, (aclexplode(coalesce(relacl, acldefault('r', relowner)))).*
FROM pg_class
- WHERE relkind IN ('r', 'v', 'f')
+ WHERE relkind IN ('r', 'v', 'f', 'p')
) pr_c (oid, relname, relnamespace, relowner, grantor, grantee, prtype, grantable),
pg_attribute a
WHERE a.attrelid = pr_c.oid
@@ -586,7 +595,7 @@ CREATE VIEW column_privileges AS
) pr_a (attrelid, attname, grantor, grantee, prtype, grantable),
pg_class c
WHERE pr_a.attrelid = c.oid
- AND relkind IN ('r', 'v', 'f')
+ AND relkind IN ('r', 'v', 'f', 'p')
) x,
pg_namespace nc,
pg_authid u_grantor,
@@ -629,7 +638,8 @@ CREATE VIEW column_udt_usage AS
WHERE a.attrelid = c.oid
AND a.atttypid = t.oid
AND nc.oid = c.relnamespace
- AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'v', 'f')
+ AND a.attnum > 0 AND NOT a.attisdropped
+ AND c.relkind in ('r', 'v', 'f', 'p')
AND pg_has_role(coalesce(bt.typowner, t.typowner), 'USAGE');
GRANT SELECT ON column_udt_usage TO PUBLIC;
@@ -727,18 +737,18 @@ CREATE VIEW columns AS
CAST(a.attnum AS sql_identifier) AS dtd_identifier,
CAST('NO' AS yes_or_no) AS is_self_referencing,
- CAST('NO' AS yes_or_no) AS is_identity,
- CAST(null AS character_data) AS identity_generation,
- CAST(null AS character_data) AS identity_start,
- CAST(null AS character_data) AS identity_increment,
- CAST(null AS character_data) AS identity_maximum,
- CAST(null AS character_data) AS identity_minimum,
- CAST(null AS yes_or_no) AS identity_cycle,
+ CAST(CASE WHEN a.attidentity IN ('a', 'd') THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_identity,
+ CAST(CASE a.attidentity WHEN 'a' THEN 'ALWAYS' WHEN 'd' THEN 'BY DEFAULT' END AS character_data) AS identity_generation,
+ CAST(seq.seqstart AS character_data) AS identity_start,
+ CAST(seq.seqincrement AS character_data) AS identity_increment,
+ CAST(seq.seqmax AS character_data) AS identity_maximum,
+ CAST(seq.seqmin AS character_data) AS identity_minimum,
+ CAST(CASE WHEN seq.seqcycle THEN 'YES' ELSE 'NO' END AS yes_or_no) AS identity_cycle,
CAST('NEVER' AS character_data) AS is_generated,
CAST(null AS character_data) AS generation_expression,
- CAST(CASE WHEN c.relkind = 'r' OR
+ CAST(CASE WHEN c.relkind IN ('r', 'p') OR
(c.relkind IN ('v', 'f') AND
pg_column_is_updatable(c.oid, a.attnum, false))
THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable
@@ -750,10 +760,13 @@ CREATE VIEW columns AS
ON (t.typtype = 'd' AND t.typbasetype = bt.oid)
LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid))
ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default')
+ LEFT JOIN (pg_depend dep JOIN pg_sequence seq ON (dep.classid = 'pg_class'::regclass AND dep.objid = seq.seqrelid AND dep.deptype = 'i'))
+ ON (dep.refclassid = 'pg_class'::regclass AND dep.refobjid = c.oid AND dep.refobjsubid = a.attnum)
WHERE (NOT pg_is_other_temp_schema(nc.oid))
- AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'v', 'f')
+ AND a.attnum > 0 AND NOT a.attisdropped
+ AND c.relkind IN ('r', 'v', 'f', 'p')
AND (pg_has_role(c.relowner, 'USAGE')
OR has_column_privilege(c.oid, a.attnum,
@@ -789,7 +802,7 @@ CREATE VIEW constraint_column_usage AS
AND d.objid = c.oid
AND c.connamespace = nc.oid
AND c.contype = 'c'
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
AND NOT a.attisdropped
UNION ALL
@@ -801,11 +814,11 @@ CREATE VIEW constraint_column_usage AS
WHERE nr.oid = r.relnamespace
AND r.oid = a.attrelid
AND nc.oid = c.connamespace
- AND (CASE WHEN c.contype = 'f' THEN r.oid = c.confrelid AND a.attnum = ANY (c.confkey)
- ELSE r.oid = c.conrelid AND a.attnum = ANY (c.conkey) END)
+ AND r.oid = CASE c.contype WHEN 'f' THEN c.confrelid ELSE c.conrelid END
+ AND a.attnum = ANY (CASE c.contype WHEN 'f' THEN c.confkey ELSE c.conkey END)
AND NOT a.attisdropped
AND c.contype IN ('p', 'u', 'f')
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
) AS x (tblschema, tblname, tblowner, colname, cstrschema, cstrname)
@@ -841,7 +854,7 @@ CREATE VIEW constraint_table_usage AS
WHERE c.connamespace = nc.oid AND r.relnamespace = nr.oid
AND ( (c.contype = 'f' AND c.confrelid = r.oid)
OR (c.contype IN ('p', 'u') AND c.conrelid = r.oid) )
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
AND pg_has_role(r.relowner, 'USAGE');
GRANT SELECT ON constraint_table_usage TO PUBLIC;
@@ -1058,7 +1071,7 @@ CREATE VIEW key_column_usage AS
AND r.oid = c.conrelid
AND nc.oid = c.connamespace
AND c.contype IN ('p', 'u', 'f')
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
AND (NOT pg_is_other_temp_schema(nr.oid)) ) AS ss
WHERE ss.roid = a.attrelid
AND a.attnum = (ss.x).x
@@ -1531,19 +1544,21 @@ CREATE VIEW sequences AS
SELECT CAST(current_database() AS sql_identifier) AS sequence_catalog,
CAST(nc.nspname AS sql_identifier) AS sequence_schema,
CAST(c.relname AS sql_identifier) AS sequence_name,
- CAST('bigint' AS character_data) AS data_type,
- CAST(64 AS cardinal_number) AS numeric_precision,
+ CAST(format_type(s.seqtypid, null) AS character_data) AS data_type,
+ CAST(_pg_numeric_precision(s.seqtypid, -1) AS cardinal_number) AS numeric_precision,
CAST(2 AS cardinal_number) AS numeric_precision_radix,
CAST(0 AS cardinal_number) AS numeric_scale,
- CAST(p.start_value AS character_data) AS start_value,
- CAST(p.minimum_value AS character_data) AS minimum_value,
- CAST(p.maximum_value AS character_data) AS maximum_value,
- CAST(p.increment AS character_data) AS increment,
- CAST(CASE WHEN p.cycle_option THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
- FROM pg_namespace nc, pg_class c, LATERAL pg_sequence_parameters(c.oid) p
+ CAST(s.seqstart AS character_data) AS start_value,
+ CAST(s.seqmin AS character_data) AS minimum_value,
+ CAST(s.seqmax AS character_data) AS maximum_value,
+ CAST(s.seqincrement AS character_data) AS increment,
+ CAST(CASE WHEN s.seqcycle THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
+ FROM pg_namespace nc, pg_class c, pg_sequence s
WHERE c.relnamespace = nc.oid
AND c.relkind = 'S'
+ AND NOT EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_class'::regclass AND objid = c.oid AND deptype = 'i')
AND (NOT pg_is_other_temp_schema(nc.oid))
+ AND c.oid = s.seqrelid
AND (pg_has_role(c.relowner, 'USAGE')
OR has_sequence_privilege(c.oid, 'SELECT, UPDATE, USAGE') );
@@ -1773,7 +1788,7 @@ CREATE VIEW table_constraints AS
WHERE nc.oid = c.connamespace AND nr.oid = r.relnamespace
AND c.conrelid = r.oid
AND c.contype NOT IN ('t', 'x') -- ignore nonstandard constraints
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
AND (NOT pg_is_other_temp_schema(nr.oid))
AND (pg_has_role(r.relowner, 'USAGE')
-- SELECT privilege omitted, per SQL standard
@@ -1803,7 +1818,7 @@ CREATE VIEW table_constraints AS
AND a.attnotnull
AND a.attnum > 0
AND NOT a.attisdropped
- AND r.relkind = 'r'
+ AND r.relkind IN ('r', 'p')
AND (NOT pg_is_other_temp_schema(nr.oid))
AND (pg_has_role(r.relowner, 'USAGE')
-- SELECT privilege omitted, per SQL standard
@@ -1853,7 +1868,7 @@ CREATE VIEW table_privileges AS
) AS grantee (oid, rolname)
WHERE c.relnamespace = nc.oid
- AND c.relkind IN ('r', 'v')
+ AND c.relkind IN ('r', 'v', 'p')
AND c.grantee = grantee.oid
AND c.grantor = u_grantor.oid
AND c.prtype IN ('INSERT', 'SELECT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER')
@@ -1897,7 +1912,7 @@ CREATE VIEW tables AS
CAST(
CASE WHEN nc.oid = pg_my_temp_schema() THEN 'LOCAL TEMPORARY'
- WHEN c.relkind = 'r' THEN 'BASE TABLE'
+ WHEN c.relkind IN ('r', 'p') THEN 'BASE TABLE'
WHEN c.relkind = 'v' THEN 'VIEW'
WHEN c.relkind = 'f' THEN 'FOREIGN TABLE'
ELSE null END
@@ -1910,7 +1925,7 @@ CREATE VIEW tables AS
CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema,
CAST(t.typname AS sql_identifier) AS user_defined_type_name,
- CAST(CASE WHEN c.relkind = 'r' OR
+ CAST(CASE WHEN c.relkind IN ('r', 'p') OR
(c.relkind IN ('v', 'f') AND
-- 1 << CMD_INSERT
pg_relation_is_updatable(c.oid, false) & 8 = 8)
@@ -1922,7 +1937,7 @@ CREATE VIEW tables AS
FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace)
LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid)
- WHERE c.relkind IN ('r', 'v', 'f')
+ WHERE c.relkind IN ('r', 'v', 'f', 'p')
AND (NOT pg_is_other_temp_schema(nc.oid))
AND (pg_has_role(c.relowner, 'USAGE')
OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
@@ -2068,7 +2083,7 @@ CREATE VIEW triggers AS
-- XXX strange hacks follow
CAST(
CASE WHEN pg_has_role(c.relowner, 'USAGE')
- THEN (SELECT m[1] FROM regexp_matches(pg_get_triggerdef(t.oid), E'.{35,} WHEN \\((.+)\\) EXECUTE PROCEDURE') AS rm(m) LIMIT 1)
+ THEN (regexp_match(pg_get_triggerdef(t.oid), E'.{35,} WHEN \\((.+)\\) EXECUTE PROCEDURE'))[1]
ELSE null END
AS character_data) AS action_condition,
CAST(
@@ -2441,7 +2456,7 @@ CREATE VIEW view_column_usage AS
AND dt.refclassid = 'pg_catalog.pg_class'::regclass
AND dt.refobjid = t.oid
AND t.relnamespace = nt.oid
- AND t.relkind IN ('r', 'v', 'f')
+ AND t.relkind IN ('r', 'v', 'f', 'p')
AND t.oid = a.attrelid
AND dt.refobjsubid = a.attnum
AND pg_has_role(t.relowner, 'USAGE');
@@ -2519,7 +2534,7 @@ CREATE VIEW view_table_usage AS
AND dt.refclassid = 'pg_catalog.pg_class'::regclass
AND dt.refobjid = t.oid
AND t.relnamespace = nt.oid
- AND t.relkind IN ('r', 'v', 'f')
+ AND t.relkind IN ('r', 'v', 'f', 'p')
AND pg_has_role(t.relowner, 'USAGE');
GRANT SELECT ON view_table_usage TO PUBLIC;
@@ -2672,7 +2687,7 @@ CREATE VIEW element_types AS
a.attnum, a.atttypid, a.attcollation
FROM pg_class c, pg_attribute a
WHERE c.oid = a.attrelid
- AND c.relkind IN ('r', 'v', 'f', 'c')
+ AND c.relkind IN ('r', 'v', 'f', 'c', 'p')
AND attnum > 0 AND NOT attisdropped
UNION ALL
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 5caaef144f..d7f6075b13 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -10,7 +10,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -39,6 +39,7 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
@@ -64,6 +65,7 @@
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
+#include "utils/varlena.h"
/*
@@ -209,22 +211,6 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
static void FindTemporaryNamespace(void);
#endif
-/* These don't really need to appear in any header file */
-Datum pg_table_is_visible(PG_FUNCTION_ARGS);
-Datum pg_type_is_visible(PG_FUNCTION_ARGS);
-Datum pg_function_is_visible(PG_FUNCTION_ARGS);
-Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
-Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
-Datum pg_opfamily_is_visible(PG_FUNCTION_ARGS);
-Datum pg_collation_is_visible(PG_FUNCTION_ARGS);
-Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
-Datum pg_ts_parser_is_visible(PG_FUNCTION_ARGS);
-Datum pg_ts_dict_is_visible(PG_FUNCTION_ARGS);
-Datum pg_ts_template_is_visible(PG_FUNCTION_ARGS);
-Datum pg_ts_config_is_visible(PG_FUNCTION_ARGS);
-Datum pg_my_temp_schema(PG_FUNCTION_ARGS);
-Datum pg_is_other_temp_schema(PG_FUNCTION_ARGS);
-
/*
* RangeVarGetRelid
@@ -2144,6 +2130,128 @@ ConversionIsVisible(Oid conid)
}
/*
+ * get_statistics_object_oid - find a statistics object by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_statistics_object_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *stats_name;
+ Oid namespaceId;
+ Oid stats_oid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &stats_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ stats_oid = InvalidOid;
+ else
+ stats_oid = GetSysCacheOid2(STATEXTNAMENSP,
+ PointerGetDatum(stats_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+ stats_oid = GetSysCacheOid2(STATEXTNAMENSP,
+ PointerGetDatum(stats_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(stats_oid))
+ break;
+ }
+ }
+
+ if (!OidIsValid(stats_oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("statistics object \"%s\" does not exist",
+ NameListToString(names))));
+
+ return stats_oid;
+}
+
+/*
+ * StatisticsObjIsVisible
+ * Determine whether a statistics object (identified by OID) is visible in
+ * the current search path. Visible means "would be found by searching
+ * for the unqualified statistics object name".
+ */
+bool
+StatisticsObjIsVisible(Oid relid)
+{
+ HeapTuple stxtup;
+ Form_pg_statistic_ext stxform;
+ Oid stxnamespace;
+ bool visible;
+
+ stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(stxtup))
+ elog(ERROR, "cache lookup failed for statistics object %u", relid);
+ stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ stxnamespace = stxform->stxnamespace;
+ if (stxnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, stxnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another statistics object of the same name earlier in the
+ * path. So we must do a slow check for conflicting objects.
+ */
+ char *stxname = NameStr(stxform->stxname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == stxnamespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(STATEXTNAMENSP,
+ PointerGetDatum(stxname),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(stxtup);
+
+ return visible;
+}
+
+/*
* get_ts_parser_oid - find a TS parser by possibly qualified name
*
* If not found, returns InvalidOid if missing_ok, else throws error
@@ -4013,14 +4121,19 @@ RemoveTempRelations(Oid tempNamespaceId)
/*
* We want to get rid of everything in the target namespace, but not the
* namespace itself (deleting it only to recreate it later would be a
- * waste of cycles). We do this by finding everything that has a
- * dependency on the namespace.
+ * waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
+ * deletion, and we want to not drop any extensions that might happen to
+ * own temp objects.
*/
object.classId = NamespaceRelationId;
object.objectId = tempNamespaceId;
object.objectSubId = 0;
- deleteWhatDependsOn(&object, false);
+ performDeletion(&object, DROP_CASCADE,
+ PERFORM_DELETION_INTERNAL |
+ PERFORM_DELETION_QUIETLY |
+ PERFORM_DELETION_SKIP_ORIGINAL |
+ PERFORM_DELETION_SKIP_EXTENSIONS);
}
/*
@@ -4380,6 +4493,17 @@ pg_conversion_is_visible(PG_FUNCTION_ARGS)
}
Datum
+pg_statistics_obj_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(STATEXTOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(StatisticsObjIsVisible(oid));
+}
+
+Datum
pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
{
Oid oid = PG_GETARG_OID(0);
diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c
index 23103d0cb6..9d5eb7b9da 100644
--- a/src/backend/catalog/objectaccess.c
+++ b/src/backend/catalog/objectaccess.c
@@ -3,7 +3,7 @@
* objectaccess.c
* functions for object_access_hook on various events
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* -------------------------------------------------------------------------
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 8068b82eab..6a365dceec 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -3,7 +3,7 @@
* objectaddress.c
* functions for working with ObjectAddresses
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -45,7 +45,11 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_policy.h"
+#include "catalog/pg_publication.h"
+#include "catalog/pg_publication_rel.h"
#include "catalog/pg_rewrite.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_transform.h"
#include "catalog/pg_trigger.h"
@@ -78,6 +82,7 @@
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+#include "utils/regproc.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
@@ -450,6 +455,42 @@ static const ObjectPropertyType ObjectProperty[] =
Anum_pg_type_typacl,
ACL_KIND_TYPE,
true
+ },
+ {
+ PublicationRelationId,
+ PublicationObjectIndexId,
+ PUBLICATIONOID,
+ PUBLICATIONNAME,
+ Anum_pg_publication_pubname,
+ InvalidAttrNumber,
+ Anum_pg_publication_pubowner,
+ InvalidAttrNumber,
+ ACL_KIND_PUBLICATION,
+ true
+ },
+ {
+ SubscriptionRelationId,
+ SubscriptionObjectIndexId,
+ SUBSCRIPTIONOID,
+ SUBSCRIPTIONNAME,
+ Anum_pg_subscription_subname,
+ InvalidAttrNumber,
+ Anum_pg_subscription_subowner,
+ InvalidAttrNumber,
+ ACL_KIND_SUBSCRIPTION,
+ true
+ },
+ {
+ StatisticExtRelationId,
+ StatisticExtOidIndexId,
+ STATEXTOID,
+ STATEXTNAMENSP,
+ Anum_pg_statistic_ext_stxname,
+ Anum_pg_statistic_ext_stxnamespace,
+ Anum_pg_statistic_ext_stxowner,
+ InvalidAttrNumber, /* no ACL (same as relation) */
+ ACL_KIND_STATISTICS,
+ true
}
};
@@ -653,9 +694,25 @@ static const struct object_type_map
{
"policy", OBJECT_POLICY
},
+ /* OCLASS_PUBLICATION */
+ {
+ "publication", OBJECT_PUBLICATION
+ },
+ /* OCLASS_PUBLICATION_REL */
+ {
+ "publication relation", OBJECT_PUBLICATION_REL
+ },
+ /* OCLASS_SUBSCRIPTION */
+ {
+ "subscription", OBJECT_SUBSCRIPTION
+ },
/* OCLASS_TRANSFORM */
{
"transform", OBJECT_TRANSFORM
+ },
+ /* OBJECT_STATISTIC_EXT */
+ {
+ "statistics object", OBJECT_STATISTIC_EXT
}
};
@@ -667,28 +724,31 @@ const ObjectAddress InvalidObjectAddress =
};
static ObjectAddress get_object_address_unqualified(ObjectType objtype,
- List *qualname, bool missing_ok);
+ Value *strval, bool missing_ok);
static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
- List *objname, Relation *relp,
+ List *object, Relation *relp,
LOCKMODE lockmode, bool missing_ok);
static ObjectAddress get_object_address_relobject(ObjectType objtype,
- List *objname, Relation *relp, bool missing_ok);
+ List *object, Relation *relp, bool missing_ok);
static ObjectAddress get_object_address_attribute(ObjectType objtype,
- List *objname, Relation *relp,
+ List *object, Relation *relp,
LOCKMODE lockmode, bool missing_ok);
static ObjectAddress get_object_address_attrdef(ObjectType objtype,
- List *objname, Relation *relp, LOCKMODE lockmode,
+ List *object, Relation *relp, LOCKMODE lockmode,
bool missing_ok);
static ObjectAddress get_object_address_type(ObjectType objtype,
- ListCell *typecell, bool missing_ok);
-static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
+ TypeName *typename, bool missing_ok);
+static ObjectAddress get_object_address_opcf(ObjectType objtype, List *object,
bool missing_ok);
static ObjectAddress get_object_address_opf_member(ObjectType objtype,
- List *objname, List *objargs, bool missing_ok);
-
-static ObjectAddress get_object_address_usermapping(List *objname,
- List *objargs, bool missing_ok);
-static ObjectAddress get_object_address_defacl(List *objname, List *objargs,
+ List *object, bool missing_ok);
+
+static ObjectAddress get_object_address_usermapping(List *object,
+ bool missing_ok);
+static ObjectAddress get_object_address_publication_rel(List *object,
+ Relation *relp,
+ bool missing_ok);
+static ObjectAddress get_object_address_defacl(List *object,
bool missing_ok);
static const ObjectPropertyType *get_object_property_data(Oid class_id);
@@ -698,8 +758,8 @@ static void getRelationTypeDescription(StringInfo buffer, Oid relid,
int32 objectSubId);
static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
-static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname);
-static void getRelationIdentity(StringInfo buffer, Oid relid, List **objname);
+static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object);
+static void getRelationIdentity(StringInfo buffer, Oid relid, List **object);
/*
* Translate an object name and arguments (as passed by the parser) to an
@@ -727,13 +787,13 @@ static void getRelationIdentity(StringInfo buffer, Oid relid, List **objname);
*
* Note: If the object is not found, we don't give any indication of the
* reason. (It might have been a missing schema if the name was qualified, or
- * an inexistant type name in case of a cast, function or operator; etc).
+ * a nonexistent type name in case of a cast, function or operator; etc).
* Currently there is only one caller that might be interested in such info, so
* we don't spend much effort here. If more callers start to care, it might be
* better to add some support for that in this function.
*/
ObjectAddress
-get_object_address(ObjectType objtype, List *objname, List *objargs,
+get_object_address(ObjectType objtype, Node *object,
Relation *relp, LOCKMODE lockmode, bool missing_ok)
{
ObjectAddress address;
@@ -763,19 +823,19 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
case OBJECT_MATVIEW:
case OBJECT_FOREIGN_TABLE:
address =
- get_relation_by_qualified_name(objtype, objname,
+ get_relation_by_qualified_name(objtype, castNode(List, object),
&relation, lockmode,
missing_ok);
break;
case OBJECT_COLUMN:
address =
- get_object_address_attribute(objtype, objname,
+ get_object_address_attribute(objtype, castNode(List, object),
&relation, lockmode,
missing_ok);
break;
case OBJECT_DEFAULT:
address =
- get_object_address_attrdef(objtype, objname,
+ get_object_address_attrdef(objtype, castNode(List, object),
&relation, lockmode,
missing_ok);
break;
@@ -783,17 +843,20 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
case OBJECT_TRIGGER:
case OBJECT_TABCONSTRAINT:
case OBJECT_POLICY:
- address = get_object_address_relobject(objtype, objname,
+ address = get_object_address_relobject(objtype, castNode(List, object),
&relation, missing_ok);
break;
case OBJECT_DOMCONSTRAINT:
{
+ List *objlist;
ObjectAddress domaddr;
char *constrname;
+ objlist = castNode(List, object);
domaddr = get_object_address_type(OBJECT_DOMAIN,
- list_head(objname), missing_ok);
- constrname = strVal(linitial(objargs));
+ linitial_node(TypeName, objlist),
+ missing_ok);
+ constrname = strVal(lsecond(objlist));
address.classId = ConstraintRelationId;
address.objectId = get_domain_constraint_oid(domaddr.objectId,
@@ -812,58 +875,51 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
case OBJECT_FOREIGN_SERVER:
case OBJECT_EVENT_TRIGGER:
case OBJECT_ACCESS_METHOD:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SUBSCRIPTION:
address = get_object_address_unqualified(objtype,
- objname, missing_ok);
+ (Value *) object, missing_ok);
break;
case OBJECT_TYPE:
case OBJECT_DOMAIN:
- address = get_object_address_type(objtype, list_head(objname), missing_ok);
+ address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
break;
case OBJECT_AGGREGATE:
address.classId = ProcedureRelationId;
- address.objectId =
- LookupAggNameTypeNames(objname, objargs, missing_ok);
+ address.objectId = LookupAggWithArgs(castNode(ObjectWithArgs, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_FUNCTION:
address.classId = ProcedureRelationId;
- address.objectId =
- LookupFuncNameTypeNames(objname, objargs, missing_ok);
+ address.objectId = LookupFuncWithArgs(castNode(ObjectWithArgs, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_OPERATOR:
- Assert(list_length(objargs) == 2);
address.classId = OperatorRelationId;
- address.objectId =
- LookupOperNameTypeNames(NULL, objname,
- (TypeName *) linitial(objargs),
- (TypeName *) lsecond(objargs),
- missing_ok, -1);
+ address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_COLLATION:
address.classId = CollationRelationId;
- address.objectId = get_collation_oid(objname, missing_ok);
+ address.objectId = get_collation_oid(castNode(List, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_CONVERSION:
address.classId = ConversionRelationId;
- address.objectId = get_conversion_oid(objname, missing_ok);
+ address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
- address = get_object_address_opcf(objtype, objname, missing_ok);
+ address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
break;
case OBJECT_AMOP:
case OBJECT_AMPROC:
- address = get_object_address_opf_member(objtype, objname,
- objargs, missing_ok);
+ address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
break;
case OBJECT_LARGEOBJECT:
- Assert(list_length(objname) == 1);
address.classId = LargeObjectRelationId;
- address.objectId = oidparse(linitial(objname));
+ address.objectId = oidparse(object);
address.objectSubId = 0;
if (!LargeObjectExists(address.objectId))
{
@@ -876,8 +932,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
break;
case OBJECT_CAST:
{
- TypeName *sourcetype = (TypeName *) linitial(objname);
- TypeName *targettype = (TypeName *) linitial(objargs);
+ TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
+ TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
Oid sourcetypeid;
Oid targettypeid;
@@ -891,8 +947,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
break;
case OBJECT_TRANSFORM:
{
- TypeName *typename = (TypeName *) linitial(objname);
- char *langname = strVal(linitial(objargs));
+ TypeName *typename = linitial_node(TypeName, castNode(List, object));
+ char *langname = strVal(lsecond(castNode(List, object)));
Oid type_id = LookupTypeNameOid(NULL, typename, missing_ok);
Oid lang_id = get_language_oid(langname, missing_ok);
@@ -904,32 +960,43 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
break;
case OBJECT_TSPARSER:
address.classId = TSParserRelationId;
- address.objectId = get_ts_parser_oid(objname, missing_ok);
+ address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_TSDICTIONARY:
address.classId = TSDictionaryRelationId;
- address.objectId = get_ts_dict_oid(objname, missing_ok);
+ address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_TSTEMPLATE:
address.classId = TSTemplateRelationId;
- address.objectId = get_ts_template_oid(objname, missing_ok);
+ address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_TSCONFIGURATION:
address.classId = TSConfigRelationId;
- address.objectId = get_ts_config_oid(objname, missing_ok);
+ address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
address.objectSubId = 0;
break;
case OBJECT_USER_MAPPING:
- address = get_object_address_usermapping(objname, objargs,
+ address = get_object_address_usermapping(castNode(List, object),
missing_ok);
break;
+ case OBJECT_PUBLICATION_REL:
+ address = get_object_address_publication_rel(castNode(List, object),
+ &relation,
+ missing_ok);
+ break;
case OBJECT_DEFACL:
- address = get_object_address_defacl(objname, objargs,
+ address = get_object_address_defacl(castNode(List, object),
missing_ok);
break;
+ case OBJECT_STATISTIC_EXT:
+ address.classId = StatisticExtRelationId;
+ address.objectId = get_statistics_object_oid(castNode(List, object),
+ missing_ok);
+ address.objectSubId = 0;
+ break;
default:
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
/* placate compiler, in case it thinks elog might return */
@@ -1018,25 +1085,25 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
/*
* Return an ObjectAddress based on a RangeVar and an object name. The
* name of the relation identified by the RangeVar is prepended to the
- * (possibly empty) list passed in as objname. This is useful to find
+ * (possibly empty) list passed in as object. This is useful to find
* the ObjectAddress of objects that depend on a relation. All other
* considerations are exactly as for get_object_address above.
*/
ObjectAddress
-get_object_address_rv(ObjectType objtype, RangeVar *rel, List *objname,
- List *objargs, Relation *relp, LOCKMODE lockmode,
+get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object,
+ Relation *relp, LOCKMODE lockmode,
bool missing_ok)
{
if (rel)
{
- objname = lcons(makeString(rel->relname), objname);
+ object = lcons(makeString(rel->relname), object);
if (rel->schemaname)
- objname = lcons(makeString(rel->schemaname), objname);
+ object = lcons(makeString(rel->schemaname), object);
if (rel->catalogname)
- objname = lcons(makeString(rel->catalogname), objname);
+ object = lcons(makeString(rel->catalogname), object);
}
- return get_object_address(objtype, objname, objargs,
+ return get_object_address(objtype, (Node *) object,
relp, lockmode, missing_ok);
}
@@ -1046,62 +1113,12 @@ get_object_address_rv(ObjectType objtype, RangeVar *rel, List *objname,
*/
static ObjectAddress
get_object_address_unqualified(ObjectType objtype,
- List *qualname, bool missing_ok)
+ Value *strval, bool missing_ok)
{
const char *name;
ObjectAddress address;
- /*
- * The types of names handled by this function are not permitted to be
- * schema-qualified or catalog-qualified.
- */
- if (list_length(qualname) != 1)
- {
- const char *msg;
-
- switch (objtype)
- {
- case OBJECT_ACCESS_METHOD:
- msg = gettext_noop("access method name cannot be qualified");
- break;
- case OBJECT_DATABASE:
- msg = gettext_noop("database name cannot be qualified");
- break;
- case OBJECT_EXTENSION:
- msg = gettext_noop("extension name cannot be qualified");
- break;
- case OBJECT_TABLESPACE:
- msg = gettext_noop("tablespace name cannot be qualified");
- break;
- case OBJECT_ROLE:
- msg = gettext_noop("role name cannot be qualified");
- break;
- case OBJECT_SCHEMA:
- msg = gettext_noop("schema name cannot be qualified");
- break;
- case OBJECT_LANGUAGE:
- msg = gettext_noop("language name cannot be qualified");
- break;
- case OBJECT_FDW:
- msg = gettext_noop("foreign-data wrapper name cannot be qualified");
- break;
- case OBJECT_FOREIGN_SERVER:
- msg = gettext_noop("server name cannot be qualified");
- break;
- case OBJECT_EVENT_TRIGGER:
- msg = gettext_noop("event trigger name cannot be qualified");
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- msg = NULL; /* placate compiler */
- }
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("%s", _(msg))));
- }
-
- /* Format is valid, extract the actual name. */
- name = strVal(linitial(qualname));
+ name = strVal(strval);
/* Translate name to OID. */
switch (objtype)
@@ -1156,6 +1173,16 @@ get_object_address_unqualified(ObjectType objtype,
address.objectId = get_event_trigger_oid(name, missing_ok);
address.objectSubId = 0;
break;
+ case OBJECT_PUBLICATION:
+ address.classId = PublicationRelationId;
+ address.objectId = get_publication_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_SUBSCRIPTION:
+ address.classId = SubscriptionRelationId;
+ address.objectId = get_subscription_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
default:
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
/* placate compiler, which doesn't know elog won't return */
@@ -1171,7 +1198,7 @@ get_object_address_unqualified(ObjectType objtype,
* Locate a relation by qualified name.
*/
static ObjectAddress
-get_relation_by_qualified_name(ObjectType objtype, List *objname,
+get_relation_by_qualified_name(ObjectType objtype, List *object,
Relation *relp, LOCKMODE lockmode,
bool missing_ok)
{
@@ -1182,7 +1209,7 @@ get_relation_by_qualified_name(ObjectType objtype, List *objname,
address.objectId = InvalidOid;
address.objectSubId = 0;
- relation = relation_openrv_extended(makeRangeVarFromNameList(objname),
+ relation = relation_openrv_extended(makeRangeVarFromNameList(object),
lockmode, missing_ok);
if (!relation)
return address;
@@ -1204,7 +1231,8 @@ get_relation_by_qualified_name(ObjectType objtype, List *objname,
RelationGetRelationName(relation))));
break;
case OBJECT_TABLE:
- if (relation->rd_rel->relkind != RELKIND_RELATION)
+ if (relation->rd_rel->relkind != RELKIND_RELATION &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
@@ -1251,102 +1279,74 @@ get_relation_by_qualified_name(ObjectType objtype, List *objname,
* mode for the object itself, not the relation to which it is attached.
*/
static ObjectAddress
-get_object_address_relobject(ObjectType objtype, List *objname,
+get_object_address_relobject(ObjectType objtype, List *object,
Relation *relp, bool missing_ok)
{
ObjectAddress address;
Relation relation = NULL;
int nnames;
const char *depname;
+ List *relname;
+ Oid reloid;
/* Extract name of dependent object. */
- depname = strVal(llast(objname));
+ depname = strVal(llast(object));
/* Separate relation name from dependent object name. */
- nnames = list_length(objname);
+ nnames = list_length(object);
if (nnames < 2)
- {
- Oid reloid;
-
- /*
- * For compatibility with very old releases, we sometimes allow users
- * to attempt to specify a rule without mentioning the relation name.
- * If there's only rule by that name in the entire database, this will
- * work. But objects other than rules don't get this special
- * treatment.
- */
- if (objtype != OBJECT_RULE)
- elog(ERROR, "must specify relation and object name");
- address.classId = RewriteRelationId;
- address.objectId =
- get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
- address.objectSubId = 0;
-
- /*
- * Caller is expecting to get back the relation, even though we didn't
- * end up using it to find the rule.
- */
- if (OidIsValid(address.objectId))
- relation = heap_open(reloid, AccessShareLock);
- }
- else
- {
- List *relname;
- Oid reloid;
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("must specify relation and object name")));
- /* Extract relation name and open relation. */
- relname = list_truncate(list_copy(objname), nnames - 1);
- relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
- AccessShareLock,
- missing_ok);
+ /* Extract relation name and open relation. */
+ relname = list_truncate(list_copy(object), nnames - 1);
+ relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
+ AccessShareLock,
+ missing_ok);
- reloid = relation ? RelationGetRelid(relation) : InvalidOid;
+ reloid = relation ? RelationGetRelid(relation) : InvalidOid;
- switch (objtype)
- {
- case OBJECT_RULE:
- address.classId = RewriteRelationId;
- address.objectId = relation ?
- get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
- address.objectSubId = 0;
- break;
- case OBJECT_TRIGGER:
- address.classId = TriggerRelationId;
- address.objectId = relation ?
- get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
- address.objectSubId = 0;
- break;
- case OBJECT_TABCONSTRAINT:
- address.classId = ConstraintRelationId;
- address.objectId = relation ?
- get_relation_constraint_oid(reloid, depname, missing_ok) :
- InvalidOid;
- address.objectSubId = 0;
- break;
- case OBJECT_POLICY:
- address.classId = PolicyRelationId;
- address.objectId = relation ?
- get_relation_policy_oid(reloid, depname, missing_ok) :
- InvalidOid;
- address.objectSubId = 0;
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- /* placate compiler, which doesn't know elog won't return */
- address.classId = InvalidOid;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- }
+ switch (objtype)
+ {
+ case OBJECT_RULE:
+ address.classId = RewriteRelationId;
+ address.objectId = relation ?
+ get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TRIGGER:
+ address.classId = TriggerRelationId;
+ address.objectId = relation ?
+ get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TABCONSTRAINT:
+ address.classId = ConstraintRelationId;
+ address.objectId = relation ?
+ get_relation_constraint_oid(reloid, depname, missing_ok) :
+ InvalidOid;
+ address.objectSubId = 0;
+ break;
+ case OBJECT_POLICY:
+ address.classId = PolicyRelationId;
+ address.objectId = relation ?
+ get_relation_policy_oid(reloid, depname, missing_ok) :
+ InvalidOid;
+ address.objectSubId = 0;
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ }
- /* Avoid relcache leak when object not found. */
- if (!OidIsValid(address.objectId))
- {
- if (relation != NULL)
- heap_close(relation, AccessShareLock);
+ /* Avoid relcache leak when object not found. */
+ if (!OidIsValid(address.objectId))
+ {
+ if (relation != NULL)
+ heap_close(relation, AccessShareLock);
- relation = NULL; /* department of accident prevention */
- return address;
- }
+ relation = NULL; /* department of accident prevention */
+ return address;
}
/* Done. */
@@ -1358,7 +1358,7 @@ get_object_address_relobject(ObjectType objtype, List *objname,
* Find the ObjectAddress for an attribute.
*/
static ObjectAddress
-get_object_address_attribute(ObjectType objtype, List *objname,
+get_object_address_attribute(ObjectType objtype, List *object,
Relation *relp, LOCKMODE lockmode,
bool missing_ok)
{
@@ -1370,12 +1370,12 @@ get_object_address_attribute(ObjectType objtype, List *objname,
AttrNumber attnum;
/* Extract relation name and open relation. */
- if (list_length(objname) < 2)
+ if (list_length(object) < 2)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("column name must be qualified")));
- attname = strVal(lfirst(list_tail(objname)));
- relname = list_truncate(list_copy(objname), list_length(objname) - 1);
+ attname = strVal(lfirst(list_tail(object)));
+ relname = list_truncate(list_copy(object), list_length(object) - 1);
/* XXX no missing_ok support here */
relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
reloid = RelationGetRelid(relation);
@@ -1409,7 +1409,7 @@ get_object_address_attribute(ObjectType objtype, List *objname,
* Find the ObjectAddress for an attribute's default value.
*/
static ObjectAddress
-get_object_address_attrdef(ObjectType objtype, List *objname,
+get_object_address_attrdef(ObjectType objtype, List *object,
Relation *relp, LOCKMODE lockmode,
bool missing_ok)
{
@@ -1423,12 +1423,12 @@ get_object_address_attrdef(ObjectType objtype, List *objname,
Oid defoid;
/* Extract relation name and open relation. */
- if (list_length(objname) < 2)
+ if (list_length(object) < 2)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("column name must be qualified")));
- attname = strVal(llast(objname));
- relname = list_truncate(list_copy(objname), list_length(objname) - 1);
+ attname = strVal(llast(object));
+ relname = list_truncate(list_copy(object), list_length(object) - 1);
/* XXX no missing_ok support here */
relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
reloid = RelationGetRelid(relation);
@@ -1491,14 +1491,11 @@ get_object_address_attrdef(ObjectType objtype, List *objname,
* Find the ObjectAddress for a type or domain
*/
static ObjectAddress
-get_object_address_type(ObjectType objtype, ListCell *typecell, bool missing_ok)
+get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
{
ObjectAddress address;
- TypeName *typename;
Type tup;
- typename = (TypeName *) lfirst(typecell);
-
address.classId = TypeRelationId;
address.objectId = InvalidOid;
address.objectSubId = 0;
@@ -1533,25 +1530,25 @@ get_object_address_type(ObjectType objtype, ListCell *typecell, bool missing_ok)
* Find the ObjectAddress for an opclass or opfamily.
*/
static ObjectAddress
-get_object_address_opcf(ObjectType objtype, List *objname, bool missing_ok)
+get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
{
Oid amoid;
ObjectAddress address;
/* XXX no missing_ok support here */
- amoid = get_index_am_oid(strVal(linitial(objname)), false);
- objname = list_copy_tail(objname, 1);
+ amoid = get_index_am_oid(strVal(linitial(object)), false);
+ object = list_copy_tail(object, 1);
switch (objtype)
{
case OBJECT_OPCLASS:
address.classId = OperatorClassRelationId;
- address.objectId = get_opclass_oid(amoid, objname, missing_ok);
+ address.objectId = get_opclass_oid(amoid, object, missing_ok);
address.objectSubId = 0;
break;
case OBJECT_OPFAMILY:
address.classId = OperatorFamilyRelationId;
- address.objectId = get_opfamily_oid(amoid, objname, missing_ok);
+ address.objectId = get_opfamily_oid(amoid, object, missing_ok);
address.objectSubId = 0;
break;
default:
@@ -1572,36 +1569,36 @@ get_object_address_opcf(ObjectType objtype, List *objname, bool missing_ok)
*/
static ObjectAddress
get_object_address_opf_member(ObjectType objtype,
- List *objname, List *objargs, bool missing_ok)
+ List *object, bool missing_ok)
{
ObjectAddress famaddr;
ObjectAddress address;
ListCell *cell;
List *copy;
- char *typenames[2];
+ TypeName *typenames[2];
Oid typeoids[2];
int membernum;
int i;
/*
- * The last element of the objname list contains the strategy or procedure
+ * The last element of the object list contains the strategy or procedure
* number. We need to strip that out before getting the opclass/family
* address. The rest can be used directly by get_object_address_opcf().
*/
- membernum = atoi(strVal(llast(objname)));
- copy = list_truncate(list_copy(objname), list_length(objname) - 1);
+ membernum = atoi(strVal(llast(linitial(object))));
+ copy = list_truncate(list_copy(linitial(object)), list_length(linitial(object)) - 1);
/* no missing_ok support here */
famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
/* find out left/right type names and OIDs */
i = 0;
- foreach(cell, objargs)
+ foreach(cell, lsecond(object))
{
ObjectAddress typaddr;
- typenames[i] = strVal(lfirst(cell));
- typaddr = get_object_address_type(OBJECT_TYPE, cell, missing_ok);
+ typenames[i] = lfirst_node(TypeName, cell);
+ typaddr = get_object_address_type(OBJECT_TYPE, typenames[i], missing_ok);
typeoids[i] = typaddr.objectId;
if (++i >= 2)
break;
@@ -1627,7 +1624,9 @@ get_object_address_opf_member(ObjectType objtype,
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("operator %d (%s, %s) of %s does not exist",
- membernum, typenames[0], typenames[1],
+ membernum,
+ TypeNameToString(typenames[0]),
+ TypeNameToString(typenames[1]),
getObjectDescription(&famaddr))));
}
else
@@ -1656,7 +1655,9 @@ get_object_address_opf_member(ObjectType objtype,
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("function %d (%s, %s) of %s does not exist",
- membernum, typenames[0], typenames[1],
+ membernum,
+ TypeNameToString(typenames[0]),
+ TypeNameToString(typenames[1]),
getObjectDescription(&famaddr))));
}
else
@@ -1677,7 +1678,7 @@ get_object_address_opf_member(ObjectType objtype,
* Find the ObjectAddress for a user mapping.
*/
static ObjectAddress
-get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
+get_object_address_usermapping(List *object, bool missing_ok)
{
ObjectAddress address;
Oid userid;
@@ -1689,8 +1690,8 @@ get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
ObjectAddressSet(address, UserMappingRelationId, InvalidOid);
/* fetch string names from input lists, for error messages */
- username = strVal(linitial(objname));
- servername = strVal(linitial(objargs));
+ username = strVal(linitial(object));
+ servername = strVal(lsecond(object));
/* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
if (strcmp(username, "public") == 0)
@@ -1743,10 +1744,64 @@ get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
}
/*
+ * Find the ObjectAddress for a publication relation. The first element of
+ * the object parameter is the relation name, the second is the
+ * publication name.
+ */
+static ObjectAddress
+get_object_address_publication_rel(List *object,
+ Relation *relp, bool missing_ok)
+{
+ ObjectAddress address;
+ Relation relation;
+ List *relname;
+ char *pubname;
+ Publication *pub;
+
+ ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
+
+ relname = linitial(object);
+ relation = relation_openrv_extended(makeRangeVarFromNameList(relname),
+ AccessShareLock, missing_ok);
+ if (!relation)
+ return address;
+
+ /* fetch publication name from input list */
+ pubname = strVal(lsecond(object));
+
+ /* Now look up the pg_publication tuple */
+ pub = GetPublicationByName(pubname, missing_ok);
+ if (!pub)
+ {
+ relation_close(relation, AccessShareLock);
+ return address;
+ }
+
+ /* Find the publication relation mapping in syscache. */
+ address.objectId =
+ GetSysCacheOid2(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(RelationGetRelid(relation)),
+ ObjectIdGetDatum(pub->oid));
+ if (!OidIsValid(address.objectId))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
+ RelationGetRelationName(relation), pubname)));
+ relation_close(relation, AccessShareLock);
+ return address;
+ }
+
+ *relp = relation;
+ return address;
+}
+
+/*
* Find the ObjectAddress for a default ACL.
*/
static ObjectAddress
-get_object_address_defacl(List *objname, List *objargs, bool missing_ok)
+get_object_address_defacl(List *object, bool missing_ok)
{
HeapTuple tp;
Oid userid;
@@ -1763,9 +1818,9 @@ get_object_address_defacl(List *objname, List *objargs, bool missing_ok)
* First figure out the textual attributes so that they can be used for
* error reporting.
*/
- username = strVal(linitial(objname));
- if (list_length(objname) >= 2)
- schema = (char *) strVal(lsecond(objname));
+ username = strVal(lsecond(object));
+ if (list_length(object) >= 3)
+ schema = (char *) strVal(lthird(object));
else
schema = NULL;
@@ -1773,7 +1828,7 @@ get_object_address_defacl(List *objname, List *objargs, bool missing_ok)
* Decode defaclobjtype. Only first char is considered; the rest of the
* string, if any, is blissfully ignored.
*/
- objtype = ((char *) strVal(linitial(objargs)))[0];
+ objtype = ((char *) strVal(linitial(object)))[0];
switch (objtype)
{
case DEFACLOBJ_RELATION:
@@ -1788,11 +1843,14 @@ get_object_address_defacl(List *objname, List *objargs, bool missing_ok)
case DEFACLOBJ_TYPE:
objtype_str = "types";
break;
+ case DEFACLOBJ_NAMESPACE:
+ objtype_str = "schemas";
+ break;
default:
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized default ACL object type %c", objtype),
- errhint("Valid object types are \"r\", \"S\", \"f\", and \"T\".")));
+ errhint("Valid object types are \"r\", \"S\", \"f\", \"T\" and \"s\".")));
}
/*
@@ -1888,8 +1946,10 @@ pg_get_object_address(PG_FUNCTION_ARGS)
ArrayType *argsarr = PG_GETARG_ARRAYTYPE_P(2);
int itype;
ObjectType type;
- List *name;
- List *args;
+ List *name = NIL;
+ TypeName *typename = NULL;
+ List *args = NIL;
+ Node *objnode = NULL;
ObjectAddress addr;
TupleDesc tupdesc;
Datum values[3];
@@ -1927,7 +1987,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("name or argument lists may not contain nulls")));
- name = list_make1(typeStringToTypeName(TextDatumGetCString(elems[0])));
+ typename = typeStringToTypeName(TextDatumGetCString(elems[0]));
}
else if (type == OBJECT_LARGEOBJECT)
{
@@ -1945,7 +2005,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("large object OID may not be null")));
- name = list_make1(makeFloat(TextDatumGetCString(elems[0])));
+ objnode = (Node *) makeFloat(TextDatumGetCString(elems[0]));
}
else
{
@@ -1993,7 +2053,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
}
/*
- * get_object_name is pretty sensitive to the length its input lists;
+ * get_object_address is pretty sensitive to the length its input lists;
* check that they're what it wants.
*/
switch (type)
@@ -2001,6 +2061,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
case OBJECT_DOMCONSTRAINT:
case OBJECT_CAST:
case OBJECT_USER_MAPPING:
+ case OBJECT_PUBLICATION_REL:
case OBJECT_DEFACL:
case OBJECT_TRANSFORM:
if (list_length(args) != 1)
@@ -2032,7 +2093,97 @@ pg_get_object_address(PG_FUNCTION_ARGS)
break;
}
- addr = get_object_address(type, name, args,
+ /*
+ * Now build the Node type that get_object_address() expects for the given
+ * type.
+ */
+ switch (type)
+ {
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLUMN:
+ case OBJECT_ATTRIBUTE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_DEFAULT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ objnode = (Node *) name;
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ if (list_length(name) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be exactly %d", 1)));
+ objnode = linitial(name);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ objnode = (Node *) typename;
+ break;
+ case OBJECT_CAST:
+ case OBJECT_DOMCONSTRAINT:
+ case OBJECT_TRANSFORM:
+ objnode = (Node *) list_make2(typename, linitial(args));
+ break;
+ case OBJECT_PUBLICATION_REL:
+ objnode = (Node *) list_make2(name, linitial(args));
+ break;
+ case OBJECT_USER_MAPPING:
+ objnode = (Node *) list_make2(linitial(name), linitial(args));
+ break;
+ case OBJECT_DEFACL:
+ objnode = (Node *) lcons(linitial(args), name);
+ break;
+ case OBJECT_AMOP:
+ case OBJECT_AMPROC:
+ objnode = (Node *) list_make2(name, args);
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_AGGREGATE:
+ case OBJECT_OPERATOR:
+ {
+ ObjectWithArgs *owa = makeNode(ObjectWithArgs);
+
+ owa->objname = name;
+ owa->objargs = args;
+ objnode = (Node *) owa;
+ break;
+ }
+ case OBJECT_LARGEOBJECT:
+ /* already handled above */
+ break;
+ /* no default, to let compiler warn about missing case */
+ }
+
+ if (objnode == NULL)
+ elog(ERROR, "unrecognized object type: %d", type);
+
+ addr = get_object_address(type, objnode,
&relation, AccessShareLock, false);
/* We don't need the relcache entry, thank you very much */
@@ -2065,7 +2216,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
*/
void
check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
- List *objname, List *objargs, Relation relation)
+ Node *object, Relation relation)
{
switch (objtype)
{
@@ -2087,7 +2238,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
case OBJECT_DATABASE:
if (!pg_database_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_TYPE:
case OBJECT_DOMAIN:
@@ -2100,62 +2251,62 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
case OBJECT_FUNCTION:
if (!pg_proc_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
- NameListToString(objname));
+ NameListToString((castNode(ObjectWithArgs, object))->objname));
break;
case OBJECT_OPERATOR:
if (!pg_oper_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
- NameListToString(objname));
+ NameListToString((castNode(ObjectWithArgs, object))->objname));
break;
case OBJECT_SCHEMA:
if (!pg_namespace_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_COLLATION:
if (!pg_collation_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
- NameListToString(objname));
+ NameListToString(castNode(List, object)));
break;
case OBJECT_CONVERSION:
if (!pg_conversion_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
- NameListToString(objname));
+ NameListToString(castNode(List, object)));
break;
case OBJECT_EXTENSION:
if (!pg_extension_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_FDW:
if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_FOREIGN_SERVER:
if (!pg_foreign_server_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_EVENT_TRIGGER:
if (!pg_event_trigger_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_LANGUAGE:
if (!pg_language_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_OPCLASS:
if (!pg_opclass_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
- NameListToString(objname));
+ NameListToString(castNode(List, object)));
break;
case OBJECT_OPFAMILY:
if (!pg_opfamily_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
- NameListToString(objname));
+ NameListToString(castNode(List, object)));
break;
case OBJECT_LARGEOBJECT:
if (!lo_compat_privileges &&
@@ -2168,8 +2319,8 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
case OBJECT_CAST:
{
/* We can only check permissions on the source/target types */
- TypeName *sourcetype = (TypeName *) linitial(objname);
- TypeName *targettype = (TypeName *) linitial(objargs);
+ TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
+ TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
Oid targettypeid = typenameTypeId(NULL, targettype);
@@ -2182,9 +2333,19 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
format_type_be(targettypeid))));
}
break;
+ case OBJECT_PUBLICATION:
+ if (!pg_publication_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PUBLICATION,
+ strVal((Value *) object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ if (!pg_subscription_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_SUBSCRIPTION,
+ strVal((Value *) object));
+ break;
case OBJECT_TRANSFORM:
{
- TypeName *typename = (TypeName *) linitial(objname);
+ TypeName *typename = linitial_node(TypeName, castNode(List, object));
Oid typeid = typenameTypeId(NULL, typename);
if (!pg_type_ownercheck(typeid, roleid))
@@ -2194,17 +2355,17 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
case OBJECT_TABLESPACE:
if (!pg_tablespace_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
- NameListToString(objname));
+ strVal((Value *) object));
break;
case OBJECT_TSDICTIONARY:
if (!pg_ts_dict_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
- NameListToString(objname));
+ NameListToString(castNode(List, object)));
break;
case OBJECT_TSCONFIGURATION:
if (!pg_ts_config_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
- NameListToString(objname));
+ NameListToString(castNode(List, object)));
break;
case OBJECT_ROLE:
@@ -2236,6 +2397,10 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser")));
break;
+ case OBJECT_STATISTIC_EXT:
+ if (!pg_statistics_object_ownercheck(address.objectId, roleid))
+ aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
+ break;
default:
elog(ERROR, "unrecognized object type: %d",
(int) objtype);
@@ -2290,23 +2455,18 @@ get_object_namespace(const ObjectAddress *address)
int
read_objtype_from_string(const char *objtype)
{
- ObjectType type;
int i;
for (i = 0; i < lengthof(ObjectTypeMap); i++)
{
if (strcmp(ObjectTypeMap[i].tm_name, objtype) == 0)
- {
- type = ObjectTypeMap[i].tm_type;
- break;
- }
+ return ObjectTypeMap[i].tm_type;
}
- if (i >= lengthof(ObjectTypeMap))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized object type \"%s\"", objtype)));
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized object type \"%s\"", objtype)));
- return type;
+ return -1; /* keep compiler quiet */
}
/*
@@ -2709,6 +2869,21 @@ getObjectDescription(const ObjectAddress *object)
getOpFamilyDescription(&buffer, object->objectId);
break;
+ case OCLASS_AM:
+ {
+ HeapTuple tup;
+
+ tup = SearchSysCache1(AMOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for access method %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("access method %s"),
+ NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
+ ReleaseSysCache(tup);
+ break;
+ }
+
case OCLASS_AMOP:
{
Relation amopDesc;
@@ -2844,27 +3019,6 @@ getObjectDescription(const ObjectAddress *object)
break;
}
- case OCLASS_TRANSFORM:
- {
- HeapTuple trfTup;
- Form_pg_transform trfForm;
-
- trfTup = SearchSysCache1(TRFOID,
- ObjectIdGetDatum(object->objectId));
- if (!HeapTupleIsValid(trfTup))
- elog(ERROR, "could not find tuple for transform %u",
- object->objectId);
-
- trfForm = (Form_pg_transform) GETSTRUCT(trfTup);
-
- appendStringInfo(&buffer, _("transform for %s language %s"),
- format_type_be(trfForm->trftype),
- get_language_name(trfForm->trflang, false));
-
- ReleaseSysCache(trfTup);
- break;
- }
-
case OCLASS_TRIGGER:
{
Relation trigDesc;
@@ -2912,6 +3066,26 @@ getObjectDescription(const ObjectAddress *object)
break;
}
+ case OCLASS_STATISTIC_EXT:
+ {
+ HeapTuple stxTup;
+ Form_pg_statistic_ext stxForm;
+
+ stxTup = SearchSysCache1(STATEXTOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(stxTup))
+ elog(ERROR, "could not find tuple for statistics object %u",
+ object->objectId);
+
+ stxForm = (Form_pg_statistic_ext) GETSTRUCT(stxTup);
+
+ appendStringInfo(&buffer, _("statistics object %s"),
+ NameStr(stxForm->stxname));
+
+ ReleaseSysCache(stxTup);
+ break;
+ }
+
case OCLASS_TSPARSER:
{
HeapTuple tup;
@@ -3098,6 +3272,11 @@ getObjectDescription(const ObjectAddress *object)
_("default privileges on new types belonging to role %s"),
GetUserNameFromId(defacl->defaclrole, false));
break;
+ case DEFACLOBJ_NAMESPACE:
+ appendStringInfo(&buffer,
+ _("default privileges on new schemas belonging to role %s"),
+ GetUserNameFromId(defacl->defaclrole, false));
+ break;
default:
/* shouldn't get here */
appendStringInfo(&buffer,
@@ -3180,27 +3359,80 @@ getObjectDescription(const ObjectAddress *object)
break;
}
- case OCLASS_AM:
+ case OCLASS_PUBLICATION:
+ {
+ appendStringInfo(&buffer, _("publication %s"),
+ get_publication_name(object->objectId));
+ break;
+ }
+
+ case OCLASS_PUBLICATION_REL:
{
HeapTuple tup;
+ char *pubname;
+ Form_pg_publication_rel prform;
- tup = SearchSysCache1(AMOID,
+ tup = SearchSysCache1(PUBLICATIONREL,
ObjectIdGetDatum(object->objectId));
if (!HeapTupleIsValid(tup))
- elog(ERROR, "cache lookup failed for access method %u",
+ elog(ERROR, "cache lookup failed for publication table %u",
object->objectId);
- appendStringInfo(&buffer, _("access method %s"),
- NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
+
+ prform = (Form_pg_publication_rel) GETSTRUCT(tup);
+ pubname = get_publication_name(prform->prpubid);
+
+ appendStringInfo(&buffer, _("publication table %s in publication %s"),
+ get_rel_name(prform->prrelid), pubname);
ReleaseSysCache(tup);
break;
}
- default:
- appendStringInfo(&buffer, "unrecognized object %u %u %d",
- object->classId,
- object->objectId,
- object->objectSubId);
- break;
+ case OCLASS_SUBSCRIPTION:
+ {
+ appendStringInfo(&buffer, _("subscription %s"),
+ get_subscription_name(object->objectId));
+ break;
+ }
+
+ case OCLASS_TRANSFORM:
+ {
+ HeapTuple trfTup;
+ Form_pg_transform trfForm;
+
+ trfTup = SearchSysCache1(TRFOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(trfTup))
+ elog(ERROR, "could not find tuple for transform %u",
+ object->objectId);
+
+ trfForm = (Form_pg_transform) GETSTRUCT(trfTup);
+
+ appendStringInfo(&buffer, _("transform for %s language %s"),
+ format_type_be(trfForm->trftype),
+ get_language_name(trfForm->trflang, false));
+
+ ReleaseSysCache(trfTup);
+ break;
+ }
+
+ case OCLASS_PGXC_NODE:
+ {
+ appendStringInfo(&buffer, _("node %s"),
+ get_pgxc_nodename(object->objectId));
+ break;
+ }
+
+ case OCLASS_PGXC_GROUP:
+ {
+ appendStringInfo(&buffer, _("node group %s"),
+ get_pgxc_groupname(object->objectId));
+ break;
+ }
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
}
return buffer.data;
@@ -3249,6 +3481,7 @@ getRelationDescription(StringInfo buffer, Oid relid)
switch (relForm->relkind)
{
case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
appendStringInfo(buffer, _("table %s"),
relname);
break;
@@ -3336,7 +3569,7 @@ pg_describe_object(PG_FUNCTION_ARGS)
{
Oid classid = PG_GETARG_OID(0);
Oid objid = PG_GETARG_OID(1);
- int32 subobjid = PG_GETARG_INT32(2);
+ int32 objsubid = PG_GETARG_INT32(2);
char *description;
ObjectAddress address;
@@ -3346,7 +3579,7 @@ pg_describe_object(PG_FUNCTION_ARGS)
address.classId = classid;
address.objectId = objid;
- address.objectSubId = subobjid;
+ address.objectSubId = objsubid;
description = getObjectDescription(&address);
PG_RETURN_TEXT_P(cstring_to_text(description));
@@ -3360,7 +3593,7 @@ pg_identify_object(PG_FUNCTION_ARGS)
{
Oid classid = PG_GETARG_OID(0);
Oid objid = PG_GETARG_OID(1);
- int32 subobjid = PG_GETARG_INT32(2);
+ int32 objsubid = PG_GETARG_INT32(2);
Oid schema_oid = InvalidOid;
const char *objname = NULL;
ObjectAddress address;
@@ -3371,7 +3604,7 @@ pg_identify_object(PG_FUNCTION_ARGS)
address.classId = classid;
address.objectId = objid;
- address.objectSubId = subobjid;
+ address.objectSubId = objsubid;
/*
* Construct a tuple descriptor for the result row. This must match this
@@ -3476,7 +3709,7 @@ pg_identify_object_as_address(PG_FUNCTION_ARGS)
{
Oid classid = PG_GETARG_OID(0);
Oid objid = PG_GETARG_OID(1);
- int32 subobjid = PG_GETARG_INT32(2);
+ int32 objsubid = PG_GETARG_INT32(2);
ObjectAddress address;
char *identity;
List *names;
@@ -3488,7 +3721,7 @@ pg_identify_object_as_address(PG_FUNCTION_ARGS)
address.classId = classid;
address.objectId = objid;
- address.objectSubId = subobjid;
+ address.objectSubId = objsubid;
/*
* Construct a tuple descriptor for the result row. This must match this
@@ -3596,6 +3829,10 @@ getObjectTypeDescription(const ObjectAddress *object)
appendStringInfoString(&buffer, "operator family");
break;
+ case OCLASS_AM:
+ appendStringInfoString(&buffer, "access method");
+ break;
+
case OCLASS_AMOP:
appendStringInfoString(&buffer, "operator of access method");
break;
@@ -3616,6 +3853,10 @@ getObjectTypeDescription(const ObjectAddress *object)
appendStringInfoString(&buffer, "schema");
break;
+ case OCLASS_STATISTIC_EXT:
+ appendStringInfoString(&buffer, "statistics object");
+ break;
+
case OCLASS_TSPARSER:
appendStringInfoString(&buffer, "text search parser");
break;
@@ -3672,17 +3913,38 @@ getObjectTypeDescription(const ObjectAddress *object)
appendStringInfoString(&buffer, "policy");
break;
+ case OCLASS_PUBLICATION:
+ appendStringInfoString(&buffer, "publication");
+ break;
+
+ case OCLASS_PUBLICATION_REL:
+ appendStringInfoString(&buffer, "publication relation");
+ break;
+
+ case OCLASS_SUBSCRIPTION:
+ appendStringInfoString(&buffer, "subscription");
+ break;
+
case OCLASS_TRANSFORM:
appendStringInfoString(&buffer, "transform");
break;
- case OCLASS_AM:
- appendStringInfoString(&buffer, "access method");
+ case OCLASS_PGXC_CLASS:
+ appendStringInfoString(&buffer, "pgxc_class");
break;
- default:
- appendStringInfo(&buffer, "unrecognized %u", object->classId);
+ case OCLASS_PGXC_NODE:
+ appendStringInfoString(&buffer, "node");
+ break;
+
+ case OCLASS_PGXC_GROUP:
+ appendStringInfoString(&buffer, "node group");
break;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
}
return buffer.data;
@@ -3706,6 +3968,7 @@ getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId)
switch (relForm->relkind)
{
case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
appendStringInfoString(buffer, "table");
break;
case RELKIND_INDEX:
@@ -4097,6 +4360,20 @@ getObjectIdentityParts(const ObjectAddress *object,
getOpFamilyIdentity(&buffer, object->objectId, objname);
break;
+ case OCLASS_AM:
+ {
+ char *amname;
+
+ amname = get_am_name(object->objectId);
+ if (!amname)
+ elog(ERROR, "cache lookup failed for access method %u",
+ object->objectId);
+ appendStringInfoString(&buffer, quote_identifier(amname));
+ if (objname)
+ *objname = list_make1(amname);
+ }
+ break;
+
case OCLASS_AMOP:
{
Relation amopDesc;
@@ -4257,32 +4534,6 @@ getObjectIdentityParts(const ObjectAddress *object,
break;
}
- case OCLASS_POLICY:
- {
- Relation polDesc;
- HeapTuple tup;
- Form_pg_policy policy;
-
- polDesc = heap_open(PolicyRelationId, AccessShareLock);
-
- tup = get_catalog_object_by_oid(polDesc, object->objectId);
-
- if (!HeapTupleIsValid(tup))
- elog(ERROR, "could not find tuple for policy %u",
- object->objectId);
-
- policy = (Form_pg_policy) GETSTRUCT(tup);
-
- appendStringInfo(&buffer, "%s on ",
- quote_identifier(NameStr(policy->polname)));
- getRelationIdentity(&buffer, policy->polrelid, objname);
- if (objname)
- *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
-
- heap_close(polDesc, AccessShareLock);
- break;
- }
-
case OCLASS_SCHEMA:
{
char *nspname;
@@ -4298,6 +4549,29 @@ getObjectIdentityParts(const ObjectAddress *object,
break;
}
+ case OCLASS_STATISTIC_EXT:
+ {
+ HeapTuple tup;
+ Form_pg_statistic_ext formStatistic;
+ char *schema;
+
+ tup = SearchSysCache1(STATEXTOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for statistics object %u",
+ object->objectId);
+ formStatistic = (Form_pg_statistic_ext) GETSTRUCT(tup);
+ schema = get_namespace_name_or_temp(formStatistic->stxnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(formStatistic->stxname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(formStatistic->stxname)));
+ ReleaseSysCache(tup);
+ }
+ break;
+
case OCLASS_TSPARSER:
{
HeapTuple tup;
@@ -4552,6 +4826,10 @@ getObjectIdentityParts(const ObjectAddress *object,
appendStringInfoString(&buffer,
" on types");
break;
+ case DEFACLOBJ_NAMESPACE:
+ appendStringInfoString(&buffer,
+ " on schemas");
+ break;
}
if (objname)
@@ -4602,6 +4880,84 @@ getObjectIdentityParts(const ObjectAddress *object,
break;
}
+ case OCLASS_POLICY:
+ {
+ Relation polDesc;
+ HeapTuple tup;
+ Form_pg_policy policy;
+
+ polDesc = heap_open(PolicyRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(polDesc, object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for policy %u",
+ object->objectId);
+
+ policy = (Form_pg_policy) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, "%s on ",
+ quote_identifier(NameStr(policy->polname)));
+ getRelationIdentity(&buffer, policy->polrelid, objname);
+ if (objname)
+ *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
+
+ heap_close(polDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_PUBLICATION:
+ {
+ char *pubname;
+
+ pubname = get_publication_name(object->objectId);
+ appendStringInfoString(&buffer,
+ quote_identifier(pubname));
+ if (objname)
+ *objname = list_make1(pubname);
+ break;
+ }
+
+ case OCLASS_PUBLICATION_REL:
+ {
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication_rel prform;
+
+ tup = SearchSysCache1(PUBLICATIONREL,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication table %u",
+ object->objectId);
+
+ prform = (Form_pg_publication_rel) GETSTRUCT(tup);
+ pubname = get_publication_name(prform->prpubid);
+
+ appendStringInfo(&buffer, _("%s in publication %s"),
+ get_rel_name(prform->prrelid), pubname);
+
+ if (objname)
+ {
+ getRelationIdentity(&buffer, prform->prrelid, objname);
+ *objargs = list_make1(pubname);
+ }
+
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_SUBSCRIPTION:
+ {
+ char *subname;
+
+ subname = get_subscription_name(object->objectId);
+ appendStringInfoString(&buffer,
+ quote_identifier(subname));
+ if (objname)
+ *objname = list_make1(subname);
+ break;
+ }
+
case OCLASS_TRANSFORM:
{
Relation transformDesc;
@@ -4635,27 +4991,44 @@ getObjectIdentityParts(const ObjectAddress *object,
heap_close(transformDesc, AccessShareLock);
}
break;
+
+ case OCLASS_PGXC_CLASS:
+ /*
+ * XXX PG10MERGE: ISTM that we don't record dependencies on
+ * pgxc_class, pgxc_node and pgxc_group. So it's not clear if we
+ * really need corresponding OCLASS_* either. We should check this
+ * in more detail.
+ */
+ break;
- case OCLASS_AM:
+ case OCLASS_PGXC_NODE:
{
- char *amname;
+ char *nodename;
- amname = get_am_name(object->objectId);
- if (!amname)
- elog(ERROR, "cache lookup failed for access method %u",
- object->objectId);
- appendStringInfoString(&buffer, quote_identifier(amname));
+ nodename = get_pgxc_nodename(object->objectId);
if (objname)
- *objname = list_make1(amname);
+ *objname = list_make1(nodename);
+ appendStringInfoString(&buffer,
+ quote_identifier(nodename));
+ break;
}
- break;
- default:
- appendStringInfo(&buffer, "unrecognized object %u %u %d",
- object->classId,
- object->objectId,
- object->objectSubId);
- break;
+ case OCLASS_PGXC_GROUP:
+ {
+ char *groupname;
+
+ groupname = get_pgxc_groupname(object->objectId);
+ if (objname)
+ *objname = list_make1(groupname);
+ appendStringInfoString(&buffer,
+ quote_identifier(groupname));
+ break;
+ }
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
}
/*
@@ -4671,7 +5044,7 @@ getObjectIdentityParts(const ObjectAddress *object,
}
static void
-getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname)
+getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object)
{
HeapTuple opfTup;
Form_pg_opfamily opfForm;
@@ -4696,10 +5069,10 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname)
NameStr(opfForm->opfname)),
NameStr(amForm->amname));
- if (objname)
- *objname = list_make3(pstrdup(NameStr(amForm->amname)),
- pstrdup(schema),
- pstrdup(NameStr(opfForm->opfname)));
+ if (object)
+ *object = list_make3(pstrdup(NameStr(amForm->amname)),
+ pstrdup(schema),
+ pstrdup(NameStr(opfForm->opfname)));
ReleaseSysCache(amTup);
ReleaseSysCache(opfTup);
@@ -4710,7 +5083,7 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname)
* StringInfo.
*/
static void
-getRelationIdentity(StringInfo buffer, Oid relid, List **objname)
+getRelationIdentity(StringInfo buffer, Oid relid, List **object)
{
HeapTuple relTup;
Form_pg_class relForm;
@@ -4726,8 +5099,8 @@ getRelationIdentity(StringInfo buffer, Oid relid, List **objname)
appendStringInfoString(buffer,
quote_qualified_identifier(schema,
NameStr(relForm->relname)));
- if (objname)
- *objname = list_make2(schema, pstrdup(NameStr(relForm->relname)));
+ if (object)
+ *object = list_make2(schema, pstrdup(NameStr(relForm->relname)));
ReleaseSysCache(relTup);
}
@@ -4747,9 +5120,7 @@ strlist_to_textarray(List *list)
memcxt = AllocSetContextCreate(CurrentMemoryContext,
"strlist to array",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(memcxt);
datums = palloc(sizeof(text *) * list_length(list));
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
new file mode 100644
index 0000000000..37fa1458be
--- /dev/null
+++ b/src/backend/catalog/partition.c
@@ -0,0 +1,2314 @@
+/*-------------------------------------------------------------------------
+ *
+ * partition.c
+ * Partitioning related data structures and functions.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/partition.c
+ *
+ *-------------------------------------------------------------------------
+*/
+
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/nbtree.h"
+#include "access/sysattr.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaddress.h"
+#include "catalog/partition.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_inherits_fn.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_type.h"
+#include "executor/executor.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
+#include "nodes/parsenodes.h"
+#include "optimizer/clauses.h"
+#include "optimizer/planmain.h"
+#include "optimizer/var.h"
+#include "rewrite/rewriteManip.h"
+#include "storage/lmgr.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/datum.h"
+#include "utils/memutils.h"
+#include "utils/fmgroids.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/ruleutils.h"
+#include "utils/syscache.h"
+
+/*
+ * Information about bounds of a partitioned relation
+ *
+ * A list partition datum that is known to be NULL is never put into the
+ * datums array. Instead, it is tracked using the null_index field.
+ *
+ * In the case of range partitioning, ndatums will typically be far less than
+ * 2 * nparts, because a partition's upper bound and the next partition's lower
+ * bound are the same in most common cases, and we only store one of them.
+ *
+ * In the case of list partitioning, the indexes array stores one entry for
+ * every datum, which is the index of the partition that accepts a given datum.
+ * In case of range partitioning, it stores one entry per distinct range
+ * datum, which is the index of the partition for which a given datum
+ * is an upper bound.
+ */
+
+/* Ternary value to represent what's contained in a range bound datum */
+typedef enum RangeDatumContent
+{
+ RANGE_DATUM_FINITE = 0, /* actual datum stored elsewhere */
+ RANGE_DATUM_NEG_INF, /* negative infinity */
+ RANGE_DATUM_POS_INF /* positive infinity */
+} RangeDatumContent;
+
+typedef struct PartitionBoundInfoData
+{
+ char strategy; /* list or range bounds? */
+ int ndatums; /* Length of the datums following array */
+ Datum **datums; /* Array of datum-tuples with key->partnatts
+ * datums each */
+ RangeDatumContent **content;/* what's contained in each range bound datum?
+ * (see the above enum); NULL for list
+ * partitioned tables */
+ int *indexes; /* Partition indexes; one entry per member of
+ * the datums array (plus one if range
+ * partitioned table) */
+ int null_index; /* Index of the null-accepting partition; -1
+ * if there isn't one */
+} PartitionBoundInfoData;
+
+#define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
+
+/*
+ * When qsort'ing partition bounds after reading from the catalog, each bound
+ * is represented with one of the following structs.
+ */
+
+/* One value coming from some (index'th) list partition */
+typedef struct PartitionListValue
+{
+ int index;
+ Datum value;
+} PartitionListValue;
+
+/* One bound of a range partition */
+typedef struct PartitionRangeBound
+{
+ int index;
+ Datum *datums; /* range bound datums */
+ RangeDatumContent *content; /* what's contained in each datum? */
+ bool lower; /* this is the lower (vs upper) bound */
+} PartitionRangeBound;
+
+static int32 qsort_partition_list_value_cmp(const void *a, const void *b,
+ void *arg);
+static int32 qsort_partition_rbound_cmp(const void *a, const void *b,
+ void *arg);
+
+static Oid get_partition_operator(PartitionKey key, int col,
+ StrategyNumber strategy, bool *need_relabel);
+static Expr *make_partition_op_expr(PartitionKey key, int keynum,
+ uint16 strategy, Expr *arg1, Expr *arg2);
+static void get_range_key_properties(PartitionKey key, int keynum,
+ PartitionRangeDatum *ldatum,
+ PartitionRangeDatum *udatum,
+ ListCell **partexprs_item,
+ Expr **keyCol,
+ Const **lower_val, Const **upper_val);
+static List *get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec);
+static List *get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec);
+static List *generate_partition_qual(Relation rel);
+
+static PartitionRangeBound *make_one_range_bound(PartitionKey key, int index,
+ List *datums, bool lower);
+static int32 partition_rbound_cmp(PartitionKey key,
+ Datum *datums1, RangeDatumContent *content1, bool lower1,
+ PartitionRangeBound *b2);
+static int32 partition_rbound_datum_cmp(PartitionKey key,
+ Datum *rb_datums, RangeDatumContent *rb_content,
+ Datum *tuple_datums);
+
+static int32 partition_bound_cmp(PartitionKey key,
+ PartitionBoundInfo boundinfo,
+ int offset, void *probe, bool probe_is_bound);
+static int partition_bound_bsearch(PartitionKey key,
+ PartitionBoundInfo boundinfo,
+ void *probe, bool probe_is_bound, bool *is_equal);
+
+/*
+ * RelationBuildPartitionDesc
+ * Form rel's partition descriptor
+ *
+ * Not flushed from the cache by RelationClearRelation() unless changed because
+ * of addition or removal of partition.
+ */
+void
+RelationBuildPartitionDesc(Relation rel)
+{
+ List *inhoids,
+ *partoids;
+ Oid *oids = NULL;
+ List *boundspecs = NIL;
+ ListCell *cell;
+ int i,
+ nparts;
+ PartitionKey key = RelationGetPartitionKey(rel);
+ PartitionDesc result;
+ MemoryContext oldcxt;
+
+ int ndatums = 0;
+
+ /* List partitioning specific */
+ PartitionListValue **all_values = NULL;
+ int null_index = -1;
+
+ /* Range partitioning specific */
+ PartitionRangeBound **rbounds = NULL;
+
+ /*
+ * The following could happen in situations where rel has a pg_class entry
+ * but not the pg_partitioned_table entry yet.
+ */
+ if (key == NULL)
+ return;
+
+ /* Get partition oids from pg_inherits */
+ inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
+
+ /* Collect bound spec nodes in a list */
+ i = 0;
+ partoids = NIL;
+ foreach(cell, inhoids)
+ {
+ Oid inhrelid = lfirst_oid(cell);
+ HeapTuple tuple;
+ Datum datum;
+ bool isnull;
+ Node *boundspec;
+
+ tuple = SearchSysCache1(RELOID, inhrelid);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", inhrelid);
+
+ /*
+ * It is possible that the pg_class tuple of a partition has not been
+ * updated yet to set its relpartbound field. The only case where
+ * this happens is when we open the parent relation to check using its
+ * partition descriptor that a new partition's bound does not overlap
+ * some existing partition.
+ */
+ if (!((Form_pg_class) GETSTRUCT(tuple))->relispartition)
+ {
+ ReleaseSysCache(tuple);
+ continue;
+ }
+
+ datum = SysCacheGetAttr(RELOID, tuple,
+ Anum_pg_class_relpartbound,
+ &isnull);
+ Assert(!isnull);
+ boundspec = (Node *) stringToNode(TextDatumGetCString(datum));
+ boundspecs = lappend(boundspecs, boundspec);
+ partoids = lappend_oid(partoids, inhrelid);
+ ReleaseSysCache(tuple);
+ }
+
+ nparts = list_length(partoids);
+
+ if (nparts > 0)
+ {
+ oids = (Oid *) palloc(nparts * sizeof(Oid));
+ i = 0;
+ foreach(cell, partoids)
+ oids[i++] = lfirst_oid(cell);
+
+ /* Convert from node to the internal representation */
+ if (key->strategy == PARTITION_STRATEGY_LIST)
+ {
+ List *non_null_values = NIL;
+
+ /*
+ * Create a unified list of non-null values across all partitions.
+ */
+ i = 0;
+ null_index = -1;
+ foreach(cell, boundspecs)
+ {
+ PartitionBoundSpec *spec = castNode(PartitionBoundSpec,
+ lfirst(cell));
+ ListCell *c;
+
+ if (spec->strategy != PARTITION_STRATEGY_LIST)
+ elog(ERROR, "invalid strategy in partition bound spec");
+
+ foreach(c, spec->listdatums)
+ {
+ Const *val = castNode(Const, lfirst(c));
+ PartitionListValue *list_value = NULL;
+
+ if (!val->constisnull)
+ {
+ list_value = (PartitionListValue *)
+ palloc0(sizeof(PartitionListValue));
+ list_value->index = i;
+ list_value->value = val->constvalue;
+ }
+ else
+ {
+ /*
+ * Never put a null into the values array, flag
+ * instead for the code further down below where we
+ * construct the actual relcache struct.
+ */
+ if (null_index != -1)
+ elog(ERROR, "found null more than once");
+ null_index = i;
+ }
+
+ if (list_value)
+ non_null_values = lappend(non_null_values,
+ list_value);
+ }
+
+ i++;
+ }
+
+ ndatums = list_length(non_null_values);
+
+ /*
+ * Collect all list values in one array. Alongside the value, we
+ * also save the index of partition the value comes from.
+ */
+ all_values = (PartitionListValue **) palloc(ndatums *
+ sizeof(PartitionListValue *));
+ i = 0;
+ foreach(cell, non_null_values)
+ {
+ PartitionListValue *src = lfirst(cell);
+
+ all_values[i] = (PartitionListValue *)
+ palloc(sizeof(PartitionListValue));
+ all_values[i]->value = src->value;
+ all_values[i]->index = src->index;
+ i++;
+ }
+
+ qsort_arg(all_values, ndatums, sizeof(PartitionListValue *),
+ qsort_partition_list_value_cmp, (void *) key);
+ }
+ else if (key->strategy == PARTITION_STRATEGY_RANGE)
+ {
+ int j,
+ k;
+ PartitionRangeBound **all_bounds,
+ *prev;
+ bool *distinct_indexes;
+
+ all_bounds = (PartitionRangeBound **) palloc0(2 * nparts *
+ sizeof(PartitionRangeBound *));
+ distinct_indexes = (bool *) palloc(2 * nparts * sizeof(bool));
+
+ /*
+ * Create a unified list of range bounds across all the
+ * partitions.
+ */
+ i = j = 0;
+ foreach(cell, boundspecs)
+ {
+ PartitionBoundSpec *spec = castNode(PartitionBoundSpec,
+ lfirst(cell));
+ PartitionRangeBound *lower,
+ *upper;
+
+ if (spec->strategy != PARTITION_STRATEGY_RANGE)
+ elog(ERROR, "invalid strategy in partition bound spec");
+
+ lower = make_one_range_bound(key, i, spec->lowerdatums,
+ true);
+ upper = make_one_range_bound(key, i, spec->upperdatums,
+ false);
+ all_bounds[j] = lower;
+ all_bounds[j + 1] = upper;
+ j += 2;
+ i++;
+ }
+ Assert(j == 2 * nparts);
+
+ /* Sort all the bounds in ascending order */
+ qsort_arg(all_bounds, 2 * nparts,
+ sizeof(PartitionRangeBound *),
+ qsort_partition_rbound_cmp,
+ (void *) key);
+
+ /*
+ * Count the number of distinct bounds to allocate an array of
+ * that size.
+ */
+ ndatums = 0;
+ prev = NULL;
+ for (i = 0; i < 2 * nparts; i++)
+ {
+ PartitionRangeBound *cur = all_bounds[i];
+ bool is_distinct = false;
+ int j;
+
+ /* Is current bound is distinct from the previous? */
+ for (j = 0; j < key->partnatts; j++)
+ {
+ Datum cmpval;
+
+ if (prev == NULL)
+ {
+ is_distinct = true;
+ break;
+ }
+
+ /*
+ * If either of them has infinite element, we can't equate
+ * them. Even when both are infinite, they'd have
+ * opposite signs, because only one of cur and prev is a
+ * lower bound).
+ */
+ if (cur->content[j] != RANGE_DATUM_FINITE ||
+ prev->content[j] != RANGE_DATUM_FINITE)
+ {
+ is_distinct = true;
+ break;
+ }
+ cmpval = FunctionCall2Coll(&key->partsupfunc[j],
+ key->partcollation[j],
+ cur->datums[j],
+ prev->datums[j]);
+ if (DatumGetInt32(cmpval) != 0)
+ {
+ is_distinct = true;
+ break;
+ }
+ }
+
+ /*
+ * Count the current bound if it is distinct from the previous
+ * one. Also, store if the index i contains a distinct bound
+ * that we'd like put in the relcache array.
+ */
+ if (is_distinct)
+ {
+ distinct_indexes[i] = true;
+ ndatums++;
+ }
+ else
+ distinct_indexes[i] = false;
+
+ prev = cur;
+ }
+
+ /*
+ * Finally save them in an array from where they will be copied
+ * into the relcache.
+ */
+ rbounds = (PartitionRangeBound **) palloc(ndatums *
+ sizeof(PartitionRangeBound *));
+ k = 0;
+ for (i = 0; i < 2 * nparts; i++)
+ {
+ if (distinct_indexes[i])
+ rbounds[k++] = all_bounds[i];
+ }
+ Assert(k == ndatums);
+ }
+ else
+ elog(ERROR, "unexpected partition strategy: %d",
+ (int) key->strategy);
+ }
+
+ /* Now build the actual relcache partition descriptor */
+ rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
+ RelationGetRelationName(rel),
+ ALLOCSET_DEFAULT_SIZES);
+ oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
+
+ result = (PartitionDescData *) palloc0(sizeof(PartitionDescData));
+ result->nparts = nparts;
+ if (nparts > 0)
+ {
+ PartitionBoundInfo boundinfo;
+ int *mapping;
+ int next_index = 0;
+
+ result->oids = (Oid *) palloc0(nparts * sizeof(Oid));
+
+ boundinfo = (PartitionBoundInfoData *)
+ palloc0(sizeof(PartitionBoundInfoData));
+ boundinfo->strategy = key->strategy;
+ boundinfo->ndatums = ndatums;
+ boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+
+ /* Initialize mapping array with invalid values */
+ mapping = (int *) palloc(sizeof(int) * nparts);
+ for (i = 0; i < nparts; i++)
+ mapping[i] = -1;
+
+ switch (key->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ {
+ boundinfo->indexes = (int *) palloc(ndatums * sizeof(int));
+
+ /*
+ * Copy values. Indexes of individual values are mapped
+ * to canonical values so that they match for any two list
+ * partitioned tables with same number of partitions and
+ * same lists per partition. One way to canonicalize is
+ * to assign the index in all_values[] of the smallest
+ * value of each partition, as the index of all of the
+ * partition's values.
+ */
+ for (i = 0; i < ndatums; i++)
+ {
+ boundinfo->datums[i] = (Datum *) palloc(sizeof(Datum));
+ boundinfo->datums[i][0] = datumCopy(all_values[i]->value,
+ key->parttypbyval[0],
+ key->parttyplen[0]);
+
+ /* If the old index has no mapping, assign one */
+ if (mapping[all_values[i]->index] == -1)
+ mapping[all_values[i]->index] = next_index++;
+
+ boundinfo->indexes[i] = mapping[all_values[i]->index];
+ }
+
+ /*
+ * If null-accepting partition has no mapped index yet,
+ * assign one. This could happen if such partition
+ * accepts only null and hence not covered in the above
+ * loop which only handled non-null values.
+ */
+ if (null_index != -1)
+ {
+ Assert(null_index >= 0);
+ if (mapping[null_index] == -1)
+ mapping[null_index] = next_index++;
+ boundinfo->null_index = mapping[null_index];
+ }
+ else
+ boundinfo->null_index = -1;
+
+ /* All partition must now have a valid mapping */
+ Assert(next_index == nparts);
+ break;
+ }
+
+ case PARTITION_STRATEGY_RANGE:
+ {
+ boundinfo->content = (RangeDatumContent **) palloc(ndatums *
+ sizeof(RangeDatumContent *));
+ boundinfo->indexes = (int *) palloc((ndatums + 1) *
+ sizeof(int));
+
+ for (i = 0; i < ndatums; i++)
+ {
+ int j;
+
+ boundinfo->datums[i] = (Datum *) palloc(key->partnatts *
+ sizeof(Datum));
+ boundinfo->content[i] = (RangeDatumContent *)
+ palloc(key->partnatts *
+ sizeof(RangeDatumContent));
+ for (j = 0; j < key->partnatts; j++)
+ {
+ if (rbounds[i]->content[j] == RANGE_DATUM_FINITE)
+ boundinfo->datums[i][j] =
+ datumCopy(rbounds[i]->datums[j],
+ key->parttypbyval[j],
+ key->parttyplen[j]);
+ /* Remember, we are storing the tri-state value. */
+ boundinfo->content[i][j] = rbounds[i]->content[j];
+ }
+
+ /*
+ * There is no mapping for invalid indexes.
+ *
+ * Any lower bounds in the rbounds array have invalid
+ * indexes assigned, because the values between the
+ * previous bound (if there is one) and this (lower)
+ * bound are not part of the range of any existing
+ * partition.
+ */
+ if (rbounds[i]->lower)
+ boundinfo->indexes[i] = -1;
+ else
+ {
+ int orig_index = rbounds[i]->index;
+
+ /* If the old index has no mapping, assign one */
+ if (mapping[orig_index] == -1)
+ mapping[orig_index] = next_index++;
+
+ boundinfo->indexes[i] = mapping[orig_index];
+ }
+ }
+ boundinfo->indexes[i] = -1;
+ break;
+ }
+
+ default:
+ elog(ERROR, "unexpected partition strategy: %d",
+ (int) key->strategy);
+ }
+
+ result->boundinfo = boundinfo;
+
+ /*
+ * Now assign OIDs from the original array into mapped indexes of the
+ * result array. Order of OIDs in the former is defined by the
+ * catalog scan that retrived them, whereas that in the latter is
+ * defined by canonicalized representation of the list values or the
+ * range bounds.
+ */
+ for (i = 0; i < nparts; i++)
+ result->oids[mapping[i]] = oids[i];
+ pfree(mapping);
+ }
+
+ MemoryContextSwitchTo(oldcxt);
+ rel->rd_partdesc = result;
+}
+
+/*
+ * Are two partition bound collections logically equal?
+ *
+ * Used in the keep logic of relcache.c (ie, in RelationClearRelation()).
+ * This is also useful when b1 and b2 are bound collections of two separate
+ * relations, respectively, because PartitionBoundInfo is a canonical
+ * representation of partition bounds.
+ */
+bool
+partition_bounds_equal(PartitionKey key,
+ PartitionBoundInfo b1, PartitionBoundInfo b2)
+{
+ int i;
+
+ if (b1->strategy != b2->strategy)
+ return false;
+
+ if (b1->ndatums != b2->ndatums)
+ return false;
+
+ if (b1->null_index != b2->null_index)
+ return false;
+
+ for (i = 0; i < b1->ndatums; i++)
+ {
+ int j;
+
+ for (j = 0; j < key->partnatts; j++)
+ {
+ /* For range partitions, the bounds might not be finite. */
+ if (b1->content != NULL)
+ {
+ /*
+ * A finite bound always differs from an infinite bound, and
+ * different kinds of infinities differ from each other.
+ */
+ if (b1->content[i][j] != b2->content[i][j])
+ return false;
+
+ /* Non-finite bounds are equal without further examination. */
+ if (b1->content[i][j] != RANGE_DATUM_FINITE)
+ continue;
+ }
+
+ /*
+ * Compare the actual values. Note that it would be both incorrect
+ * and unsafe to invoke the comparison operator derived from the
+ * partitioning specification here. It would be incorrect because
+ * we want the relcache entry to be updated for ANY change to the
+ * partition bounds, not just those that the partitioning operator
+ * thinks are significant. It would be unsafe because we might
+ * reach this code in the context of an aborted transaction, and
+ * an arbitrary partitioning operator might not be safe in that
+ * context. datumIsEqual() should be simple enough to be safe.
+ */
+ if (!datumIsEqual(b1->datums[i][j], b2->datums[i][j],
+ key->parttypbyval[j],
+ key->parttyplen[j]))
+ return false;
+ }
+
+ if (b1->indexes[i] != b2->indexes[i])
+ return false;
+ }
+
+ /* There are ndatums+1 indexes in case of range partitions */
+ if (key->strategy == PARTITION_STRATEGY_RANGE &&
+ b1->indexes[i] != b2->indexes[i])
+ return false;
+
+ return true;
+}
+
+/*
+ * check_new_partition_bound
+ *
+ * Checks if the new partition's bound overlaps any of the existing partitions
+ * of parent. Also performs additional checks as necessary per strategy.
+ */
+void
+check_new_partition_bound(char *relname, Relation parent,
+ PartitionBoundSpec *spec)
+{
+ PartitionKey key = RelationGetPartitionKey(parent);
+ PartitionDesc partdesc = RelationGetPartitionDesc(parent);
+ ParseState *pstate = make_parsestate(NULL);
+ int with = -1;
+ bool overlap = false;
+
+ switch (key->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ {
+ Assert(spec->strategy == PARTITION_STRATEGY_LIST);
+
+ if (partdesc->nparts > 0)
+ {
+ PartitionBoundInfo boundinfo = partdesc->boundinfo;
+ ListCell *cell;
+
+ Assert(boundinfo &&
+ boundinfo->strategy == PARTITION_STRATEGY_LIST &&
+ (boundinfo->ndatums > 0 ||
+ partition_bound_accepts_nulls(boundinfo)));
+
+ foreach(cell, spec->listdatums)
+ {
+ Const *val = castNode(Const, lfirst(cell));
+
+ if (!val->constisnull)
+ {
+ int offset;
+ bool equal;
+
+ offset = partition_bound_bsearch(key, boundinfo,
+ &val->constvalue,
+ true, &equal);
+ if (offset >= 0 && equal)
+ {
+ overlap = true;
+ with = boundinfo->indexes[offset];
+ break;
+ }
+ }
+ else if (partition_bound_accepts_nulls(boundinfo))
+ {
+ overlap = true;
+ with = boundinfo->null_index;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case PARTITION_STRATEGY_RANGE:
+ {
+ PartitionRangeBound *lower,
+ *upper;
+
+ Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
+ lower = make_one_range_bound(key, -1, spec->lowerdatums, true);
+ upper = make_one_range_bound(key, -1, spec->upperdatums, false);
+
+ /*
+ * First check if the resulting range would be empty with
+ * specified lower and upper bounds
+ */
+ if (partition_rbound_cmp(key, lower->datums, lower->content, true,
+ upper) >= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot create range partition with empty range"),
+ parser_errposition(pstate, spec->location)));
+
+ if (partdesc->nparts > 0)
+ {
+ PartitionBoundInfo boundinfo = partdesc->boundinfo;
+ int off1,
+ off2;
+ bool equal = false;
+
+ Assert(boundinfo && boundinfo->ndatums > 0 &&
+ boundinfo->strategy == PARTITION_STRATEGY_RANGE);
+
+ /*
+ * Firstly, find the greatest range bound that is less
+ * than or equal to the new lower bound.
+ */
+ off1 = partition_bound_bsearch(key, boundinfo, lower, true,
+ &equal);
+
+ /*
+ * off1 == -1 means that all existing bounds are greater
+ * than the new lower bound. In that case and the case
+ * where no partition is defined between the bounds at
+ * off1 and off1 + 1, we have a "gap" in the range that
+ * could be occupied by the new partition. We confirm if
+ * so by checking whether the new upper bound is confined
+ * within the gap.
+ */
+ if (!equal && boundinfo->indexes[off1 + 1] < 0)
+ {
+ off2 = partition_bound_bsearch(key, boundinfo, upper,
+ true, &equal);
+
+ /*
+ * If the new upper bound is returned to be equal to
+ * the bound at off2, the latter must be the upper
+ * bound of some partition with which the new
+ * partition clearly overlaps.
+ *
+ * Also, if bound at off2 is not same as the one
+ * returned for the new lower bound (IOW, off1 !=
+ * off2), then the new partition overlaps at least one
+ * partition.
+ */
+ if (equal || off1 != off2)
+ {
+ overlap = true;
+
+ /*
+ * The bound at off2 could be the lower bound of
+ * the partition with which the new partition
+ * overlaps. In that case, use the upper bound
+ * (that is, the bound at off2 + 1) to get the
+ * index of that partition.
+ */
+ if (boundinfo->indexes[off2] < 0)
+ with = boundinfo->indexes[off2 + 1];
+ else
+ with = boundinfo->indexes[off2];
+ }
+ }
+ else
+ {
+ /*
+ * Equal has been set to true and there is no "gap"
+ * between the bound at off1 and that at off1 + 1, so
+ * the new partition will overlap some partition. In
+ * the former case, the new lower bound is found to be
+ * equal to the bound at off1, which could only ever
+ * be true if the latter is the lower bound of some
+ * partition. It's clear in such a case that the new
+ * partition overlaps that partition, whose index we
+ * get using its upper bound (that is, using the bound
+ * at off1 + 1).
+ */
+ overlap = true;
+ with = boundinfo->indexes[off1 + 1];
+ }
+ }
+
+ break;
+ }
+
+ default:
+ elog(ERROR, "unexpected partition strategy: %d",
+ (int) key->strategy);
+ }
+
+ if (overlap)
+ {
+ Assert(with >= 0);
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("partition \"%s\" would overlap partition \"%s\"",
+ relname, get_rel_name(partdesc->oids[with])),
+ parser_errposition(pstate, spec->location)));
+ }
+}
+
+/*
+ * get_partition_parent
+ *
+ * Returns inheritance parent of a partition by scanning pg_inherits
+ *
+ * Note: Because this function assumes that the relation whose OID is passed
+ * as an argument will have precisely one parent, it should only be called
+ * when it is known that the relation is a partition.
+ */
+Oid
+get_partition_parent(Oid relid)
+{
+ Form_pg_inherits form;
+ Relation catalogRelation;
+ SysScanDesc scan;
+ ScanKeyData key[2];
+ HeapTuple tuple;
+ Oid result;
+
+ catalogRelation = heap_open(InheritsRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&key[1],
+ Anum_pg_inherits_inhseqno,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(1));
+
+ scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
+ NULL, 2, key);
+
+ tuple = systable_getnext(scan);
+ Assert(HeapTupleIsValid(tuple));
+
+ form = (Form_pg_inherits) GETSTRUCT(tuple);
+ result = form->inhparent;
+
+ systable_endscan(scan);
+ heap_close(catalogRelation, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * get_qual_from_partbound
+ * Given a parser node for partition bound, return the list of executable
+ * expressions as partition constraint
+ */
+List *
+get_qual_from_partbound(Relation rel, Relation parent,
+ PartitionBoundSpec *spec)
+{
+ PartitionKey key = RelationGetPartitionKey(parent);
+ List *my_qual = NIL;
+
+ Assert(key != NULL);
+
+ switch (key->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ Assert(spec->strategy == PARTITION_STRATEGY_LIST);
+ my_qual = get_qual_for_list(key, spec);
+ break;
+
+ case PARTITION_STRATEGY_RANGE:
+ Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
+ my_qual = get_qual_for_range(key, spec);
+ break;
+
+ default:
+ elog(ERROR, "unexpected partition strategy: %d",
+ (int) key->strategy);
+ }
+
+ return my_qual;
+}
+
+/*
+ * map_partition_varattnos - maps varattno of any Vars in expr from the
+ * parent attno to partition attno.
+ *
+ * We must allow for cases where physical attnos of a partition can be
+ * different from the parent's.
+ *
+ * Note: this will work on any node tree, so really the argument and result
+ * should be declared "Node *". But a substantial majority of the callers
+ * are working on Lists, so it's less messy to do the casts internally.
+ */
+List *
+map_partition_varattnos(List *expr, int target_varno,
+ Relation partrel, Relation parent)
+{
+ AttrNumber *part_attnos;
+ bool found_whole_row;
+
+ if (expr == NIL)
+ return NIL;
+
+ part_attnos = convert_tuples_by_name_map(RelationGetDescr(partrel),
+ RelationGetDescr(parent),
+ gettext_noop("could not convert row type"));
+ expr = (List *) map_variable_attnos((Node *) expr,
+ target_varno, 0,
+ part_attnos,
+ RelationGetDescr(parent)->natts,
+ &found_whole_row);
+ /* There can never be a whole-row reference here */
+ if (found_whole_row)
+ elog(ERROR, "unexpected whole-row reference found in partition key");
+
+ return expr;
+}
+
+/*
+ * RelationGetPartitionQual
+ *
+ * Returns a list of partition quals
+ */
+List *
+RelationGetPartitionQual(Relation rel)
+{
+ /* Quick exit */
+ if (!rel->rd_rel->relispartition)
+ return NIL;
+
+ return generate_partition_qual(rel);
+}
+
+/*
+ * get_partition_qual_relid
+ *
+ * Returns an expression tree describing the passed-in relation's partition
+ * constraint.
+ */
+Expr *
+get_partition_qual_relid(Oid relid)
+{
+ Relation rel = heap_open(relid, AccessShareLock);
+ Expr *result = NULL;
+ List *and_args;
+
+ /* Do the work only if this relation is a partition. */
+ if (rel->rd_rel->relispartition)
+ {
+ and_args = generate_partition_qual(rel);
+ if (list_length(and_args) > 1)
+ result = makeBoolExpr(AND_EXPR, and_args, -1);
+ else
+ result = linitial(and_args);
+ }
+
+ /* Keep the lock. */
+ heap_close(rel, NoLock);
+
+ return result;
+}
+
+/*
+ * Append OIDs of rel's partitions to the list 'partoids' and for each OID,
+ * append pointer rel to the list 'parents'.
+ */
+#define APPEND_REL_PARTITION_OIDS(rel, partoids, parents) \
+ do\
+ {\
+ int i;\
+ for (i = 0; i < (rel)->rd_partdesc->nparts; i++)\
+ {\
+ (partoids) = lappend_oid((partoids), (rel)->rd_partdesc->oids[i]);\
+ (parents) = lappend((parents), (rel));\
+ }\
+ } while(0)
+
+/*
+ * RelationGetPartitionDispatchInfo
+ * Returns information necessary to route tuples down a partition tree
+ *
+ * All the partitions will be locked with lockmode, unless it is NoLock.
+ * A list of the OIDs of all the leaf partitions of rel is returned in
+ * *leaf_part_oids.
+ */
+PartitionDispatch *
+RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
+ int *num_parted, List **leaf_part_oids)
+{
+ PartitionDispatchData **pd;
+ List *all_parts = NIL,
+ *all_parents = NIL,
+ *parted_rels,
+ *parted_rel_parents;
+ ListCell *lc1,
+ *lc2;
+ int i,
+ k,
+ offset;
+
+ /*
+ * Lock partitions and make a list of the partitioned ones to prepare
+ * their PartitionDispatch objects below.
+ *
+ * Cannot use find_all_inheritors() here, because then the order of OIDs
+ * in parted_rels list would be unknown, which does not help, because we
+ * assign indexes within individual PartitionDispatch in an order that is
+ * predetermined (determined by the order of OIDs in individual partition
+ * descriptors).
+ */
+ *num_parted = 1;
+ parted_rels = list_make1(rel);
+ /* Root partitioned table has no parent, so NULL for parent */
+ parted_rel_parents = list_make1(NULL);
+ APPEND_REL_PARTITION_OIDS(rel, all_parts, all_parents);
+ forboth(lc1, all_parts, lc2, all_parents)
+ {
+ Relation partrel = heap_open(lfirst_oid(lc1), lockmode);
+ Relation parent = lfirst(lc2);
+ PartitionDesc partdesc = RelationGetPartitionDesc(partrel);
+
+ /*
+ * If this partition is a partitioned table, add its children to the
+ * end of the list, so that they are processed as well.
+ */
+ if (partdesc)
+ {
+ (*num_parted)++;
+ parted_rels = lappend(parted_rels, partrel);
+ parted_rel_parents = lappend(parted_rel_parents, parent);
+ APPEND_REL_PARTITION_OIDS(partrel, all_parts, all_parents);
+ }
+ else
+ heap_close(partrel, NoLock);
+
+ /*
+ * We keep the partitioned ones open until we're done using the
+ * information being collected here (for example, see
+ * ExecEndModifyTable).
+ */
+ }
+
+ /*
+ * We want to create two arrays - one for leaf partitions and another for
+ * partitioned tables (including the root table and internal partitions).
+ * While we only create the latter here, leaf partition array of suitable
+ * objects (such as, ResultRelInfo) is created by the caller using the
+ * list of OIDs we return. Indexes into these arrays get assigned in a
+ * breadth-first manner, whereby partitions of any given level are placed
+ * consecutively in the respective arrays.
+ */
+ pd = (PartitionDispatchData **) palloc(*num_parted *
+ sizeof(PartitionDispatchData *));
+ *leaf_part_oids = NIL;
+ i = k = offset = 0;
+ forboth(lc1, parted_rels, lc2, parted_rel_parents)
+ {
+ Relation partrel = lfirst(lc1);
+ Relation parent = lfirst(lc2);
+ PartitionKey partkey = RelationGetPartitionKey(partrel);
+ TupleDesc tupdesc = RelationGetDescr(partrel);
+ PartitionDesc partdesc = RelationGetPartitionDesc(partrel);
+ int j,
+ m;
+
+ pd[i] = (PartitionDispatch) palloc(sizeof(PartitionDispatchData));
+ pd[i]->reldesc = partrel;
+ pd[i]->key = partkey;
+ pd[i]->keystate = NIL;
+ pd[i]->partdesc = partdesc;
+ if (parent != NULL)
+ {
+ /*
+ * For every partitioned table other than root, we must store a
+ * tuple table slot initialized with its tuple descriptor and a
+ * tuple conversion map to convert a tuple from its parent's
+ * rowtype to its own. That is to make sure that we are looking at
+ * the correct row using the correct tuple descriptor when
+ * computing its partition key for tuple routing.
+ */
+ pd[i]->tupslot = MakeSingleTupleTableSlot(tupdesc);
+ pd[i]->tupmap = convert_tuples_by_name(RelationGetDescr(parent),
+ tupdesc,
+ gettext_noop("could not convert row type"));
+ }
+ else
+ {
+ /* Not required for the root partitioned table */
+ pd[i]->tupslot = NULL;
+ pd[i]->tupmap = NULL;
+ }
+ pd[i]->indexes = (int *) palloc(partdesc->nparts * sizeof(int));
+
+ /*
+ * Indexes corresponding to the internal partitions are multiplied by
+ * -1 to distinguish them from those of leaf partitions. Encountering
+ * an index >= 0 means we found a leaf partition, which is immediately
+ * returned as the partition we are looking for. A negative index
+ * means we found a partitioned table, whose PartitionDispatch object
+ * is located at the above index multiplied back by -1. Using the
+ * PartitionDispatch object, search is continued further down the
+ * partition tree.
+ */
+ m = 0;
+ for (j = 0; j < partdesc->nparts; j++)
+ {
+ Oid partrelid = partdesc->oids[j];
+
+ if (get_rel_relkind(partrelid) != RELKIND_PARTITIONED_TABLE)
+ {
+ *leaf_part_oids = lappend_oid(*leaf_part_oids, partrelid);
+ pd[i]->indexes[j] = k++;
+ }
+ else
+ {
+ /*
+ * offset denotes the number of partitioned tables of upper
+ * levels including those of the current level. Any partition
+ * of this table must belong to the next level and hence will
+ * be placed after the last partitioned table of this level.
+ */
+ pd[i]->indexes[j] = -(1 + offset + m);
+ m++;
+ }
+ }
+ i++;
+
+ /*
+ * This counts the number of partitioned tables at upper levels
+ * including those of the current level.
+ */
+ offset += m;
+ }
+
+ return pd;
+}
+
+/* Module-local functions */
+
+/*
+ * get_partition_operator
+ *
+ * Return oid of the operator of given strategy for a given partition key
+ * column.
+ */
+static Oid
+get_partition_operator(PartitionKey key, int col, StrategyNumber strategy,
+ bool *need_relabel)
+{
+ Oid operoid;
+
+ /*
+ * First check if there exists an operator of the given strategy, with
+ * this column's type as both its lefttype and righttype, in the
+ * partitioning operator family specified for the column.
+ */
+ operoid = get_opfamily_member(key->partopfamily[col],
+ key->parttypid[col],
+ key->parttypid[col],
+ strategy);
+
+ /*
+ * If one doesn't exist, we must resort to using an operator in the same
+ * opreator family but with the operator class declared input type. It is
+ * OK to do so, because the column's type is known to be binary-coercible
+ * with the operator class input type (otherwise, the operator class in
+ * question would not have been accepted as the partitioning operator
+ * class). We must however inform the caller to wrap the non-Const
+ * expression with a RelabelType node to denote the implicit coercion. It
+ * ensures that the resulting expression structurally matches similarly
+ * processed expressions within the optimizer.
+ */
+ if (!OidIsValid(operoid))
+ {
+ operoid = get_opfamily_member(key->partopfamily[col],
+ key->partopcintype[col],
+ key->partopcintype[col],
+ strategy);
+ *need_relabel = true;
+ }
+ else
+ *need_relabel = false;
+
+ if (!OidIsValid(operoid))
+ elog(ERROR, "could not find operator for partitioning");
+
+ return operoid;
+}
+
+/*
+ * make_partition_op_expr
+ * Returns an Expr for the given partition key column with arg1 and
+ * arg2 as its leftop and rightop, respectively
+ */
+static Expr *
+make_partition_op_expr(PartitionKey key, int keynum,
+ uint16 strategy, Expr *arg1, Expr *arg2)
+{
+ Oid operoid;
+ bool need_relabel = false;
+ Expr *result = NULL;
+
+ /* Get the correct btree operator for this partitioning column */
+ operoid = get_partition_operator(key, keynum, strategy, &need_relabel);
+
+ /*
+ * Chosen operator may be such that the non-Const operand needs to be
+ * coerced, so apply the same; see the comment in
+ * get_partition_operator().
+ */
+ if (!IsA(arg1, Const) &&
+ (need_relabel ||
+ key->partcollation[keynum] != key->parttypcoll[keynum]))
+ arg1 = (Expr *) makeRelabelType(arg1,
+ key->partopcintype[keynum],
+ -1,
+ key->partcollation[keynum],
+ COERCE_EXPLICIT_CAST);
+
+ /* Generate the actual expression */
+ switch (key->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ {
+ ScalarArrayOpExpr *saopexpr;
+
+ /* Build leftop = ANY (rightop) */
+ saopexpr = makeNode(ScalarArrayOpExpr);
+ saopexpr->opno = operoid;
+ saopexpr->opfuncid = get_opcode(operoid);
+ saopexpr->useOr = true;
+ saopexpr->inputcollid = key->partcollation[keynum];
+ saopexpr->args = list_make2(arg1, arg2);
+ saopexpr->location = -1;
+
+ result = (Expr *) saopexpr;
+ break;
+ }
+
+ case PARTITION_STRATEGY_RANGE:
+ result = make_opclause(operoid,
+ BOOLOID,
+ false,
+ arg1, arg2,
+ InvalidOid,
+ key->partcollation[keynum]);
+ break;
+
+ default:
+ elog(ERROR, "invalid partitioning strategy");
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * get_qual_for_list
+ *
+ * Returns an implicit-AND list of expressions to use as a list partition's
+ * constraint, given the partition key and bound structures.
+ */
+static List *
+get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec)
+{
+ List *result;
+ Expr *keyCol;
+ ArrayExpr *arr;
+ Expr *opexpr;
+ NullTest *nulltest;
+ ListCell *cell;
+ List *arrelems = NIL;
+ bool list_has_null = false;
+
+ /* Construct Var or expression representing the partition column */
+ if (key->partattrs[0] != 0)
+ keyCol = (Expr *) makeVar(1,
+ key->partattrs[0],
+ key->parttypid[0],
+ key->parttypmod[0],
+ key->parttypcoll[0],
+ 0);
+ else
+ keyCol = (Expr *) copyObject(linitial(key->partexprs));
+
+ /* Create list of Consts for the allowed values, excluding any nulls */
+ foreach(cell, spec->listdatums)
+ {
+ Const *val = castNode(Const, lfirst(cell));
+
+ if (val->constisnull)
+ list_has_null = true;
+ else
+ arrelems = lappend(arrelems, copyObject(val));
+ }
+
+ /* Construct an ArrayExpr for the non-null partition values */
+ arr = makeNode(ArrayExpr);
+ arr->array_typeid = !type_is_array(key->parttypid[0])
+ ? get_array_type(key->parttypid[0])
+ : key->parttypid[0];
+ arr->array_collid = key->parttypcoll[0];
+ arr->element_typeid = key->parttypid[0];
+ arr->elements = arrelems;
+ arr->multidims = false;
+ arr->location = -1;
+
+ /* Generate the main expression, i.e., keyCol = ANY (arr) */
+ opexpr = make_partition_op_expr(key, 0, BTEqualStrategyNumber,
+ keyCol, (Expr *) arr);
+
+ if (!list_has_null)
+ {
+ /*
+ * Gin up a "col IS NOT NULL" test that will be AND'd with the main
+ * expression. This might seem redundant, but the partition routing
+ * machinery needs it.
+ */
+ nulltest = makeNode(NullTest);
+ nulltest->arg = keyCol;
+ nulltest->nulltesttype = IS_NOT_NULL;
+ nulltest->argisrow = false;
+ nulltest->location = -1;
+
+ result = list_make2(nulltest, opexpr);
+ }
+ else
+ {
+ /*
+ * Gin up a "col IS NULL" test that will be OR'd with the main
+ * expression.
+ */
+ Expr *or;
+
+ nulltest = makeNode(NullTest);
+ nulltest->arg = keyCol;
+ nulltest->nulltesttype = IS_NULL;
+ nulltest->argisrow = false;
+ nulltest->location = -1;
+
+ or = makeBoolExpr(OR_EXPR, list_make2(nulltest, opexpr), -1);
+ result = list_make1(or);
+ }
+
+ return result;
+}
+
+/*
+ * get_range_key_properties
+ * Returns range partition key information for a given column
+ *
+ * This is a subroutine for get_qual_for_range, and its API is pretty
+ * specialized to that caller.
+ *
+ * Constructs an Expr for the key column (returned in *keyCol) and Consts
+ * for the lower and upper range limits (returned in *lower_val and
+ * *upper_val). For UNBOUNDED limits, NULL is returned instead of a Const.
+ * All of these structures are freshly palloc'd.
+ *
+ * *partexprs_item points to the cell containing the next expression in
+ * the key->partexprs list, or NULL. It may be advanced upon return.
+ */
+static void
+get_range_key_properties(PartitionKey key, int keynum,
+ PartitionRangeDatum *ldatum,
+ PartitionRangeDatum *udatum,
+ ListCell **partexprs_item,
+ Expr **keyCol,
+ Const **lower_val, Const **upper_val)
+{
+ /* Get partition key expression for this column */
+ if (key->partattrs[keynum] != 0)
+ {
+ *keyCol = (Expr *) makeVar(1,
+ key->partattrs[keynum],
+ key->parttypid[keynum],
+ key->parttypmod[keynum],
+ key->parttypcoll[keynum],
+ 0);
+ }
+ else
+ {
+ if (*partexprs_item == NULL)
+ elog(ERROR, "wrong number of partition key expressions");
+ *keyCol = copyObject(lfirst(*partexprs_item));
+ *partexprs_item = lnext(*partexprs_item);
+ }
+
+ /* Get appropriate Const nodes for the bounds */
+ if (!ldatum->infinite)
+ *lower_val = castNode(Const, copyObject(ldatum->value));
+ else
+ *lower_val = NULL;
+
+ if (!udatum->infinite)
+ *upper_val = castNode(Const, copyObject(udatum->value));
+ else
+ *upper_val = NULL;
+}
+
+/*
+ * get_qual_for_range
+ *
+ * Returns an implicit-AND list of expressions to use as a range partition's
+ * constraint, given the partition key and bound structures.
+ *
+ * For a multi-column range partition key, say (a, b, c), with (al, bl, cl)
+ * as the lower bound tuple and (au, bu, cu) as the upper bound tuple, we
+ * generate an expression tree of the following form:
+ *
+ * (a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
+ * AND
+ * (a > al OR (a = al AND b > bl) OR (a = al AND b = bl AND c >= cl))
+ * AND
+ * (a < au OR (a = au AND b < bu) OR (a = au AND b = bu AND c < cu))
+ *
+ * It is often the case that a prefix of lower and upper bound tuples contains
+ * the same values, for example, (al = au), in which case, we will emit an
+ * expression tree of the following form:
+ *
+ * (a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
+ * AND
+ * (a = al)
+ * AND
+ * (b > bl OR (b = bl AND c >= cl))
+ * AND
+ * (b < bu) OR (b = bu AND c < cu))
+ *
+ * If cu happens to be UNBOUNDED, we need not emit any expression for it, so
+ * the last line would be:
+ *
+ * (b < bu) OR (b = bu), which is simplified to (b <= bu)
+ *
+ * In most common cases with only one partition column, say a, the following
+ * expression tree will be generated: a IS NOT NULL AND a >= al AND a < au
+ *
+ * If all values of both lower and upper bounds are UNBOUNDED, the partition
+ * does not really have a constraint, except the IS NOT NULL constraint for
+ * partition keys.
+ *
+ * If we end up with an empty result list, we return a single-member list
+ * containing a constant TRUE, because callers expect a non-empty list.
+ */
+static List *
+get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
+{
+ List *result = NIL;
+ ListCell *cell1,
+ *cell2,
+ *partexprs_item,
+ *partexprs_item_saved;
+ int i,
+ j;
+ PartitionRangeDatum *ldatum,
+ *udatum;
+ Expr *keyCol;
+ Const *lower_val,
+ *upper_val;
+ NullTest *nulltest;
+ List *lower_or_arms,
+ *upper_or_arms;
+ int num_or_arms,
+ current_or_arm;
+ ListCell *lower_or_start_datum,
+ *upper_or_start_datum;
+ bool need_next_lower_arm,
+ need_next_upper_arm;
+
+ lower_or_start_datum = list_head(spec->lowerdatums);
+ upper_or_start_datum = list_head(spec->upperdatums);
+ num_or_arms = key->partnatts;
+
+ /*
+ * A range-partitioned table does not currently allow partition keys to be
+ * null, so emit an IS NOT NULL expression for each key column.
+ */
+ partexprs_item = list_head(key->partexprs);
+ for (i = 0; i < key->partnatts; i++)
+ {
+ Expr *keyCol;
+
+ if (key->partattrs[i] != 0)
+ {
+ keyCol = (Expr *) makeVar(1,
+ key->partattrs[i],
+ key->parttypid[i],
+ key->parttypmod[i],
+ key->parttypcoll[i],
+ 0);
+ }
+ else
+ {
+ if (partexprs_item == NULL)
+ elog(ERROR, "wrong number of partition key expressions");
+ keyCol = copyObject(lfirst(partexprs_item));
+ partexprs_item = lnext(partexprs_item);
+ }
+
+ nulltest = makeNode(NullTest);
+ nulltest->arg = keyCol;
+ nulltest->nulltesttype = IS_NOT_NULL;
+ nulltest->argisrow = false;
+ nulltest->location = -1;
+ result = lappend(result, nulltest);
+ }
+
+ /*
+ * Iterate over the key columns and check if the corresponding lower and
+ * upper datums are equal using the btree equality operator for the
+ * column's type. If equal, we emit single keyCol = common_value
+ * expression. Starting from the first column for which the corresponding
+ * lower and upper bound datums are not equal, we generate OR expressions
+ * as shown in the function's header comment.
+ */
+ i = 0;
+ partexprs_item = list_head(key->partexprs);
+ partexprs_item_saved = partexprs_item; /* placate compiler */
+ forboth(cell1, spec->lowerdatums, cell2, spec->upperdatums)
+ {
+ EState *estate;
+ MemoryContext oldcxt;
+ Expr *test_expr;
+ ExprState *test_exprstate;
+ Datum test_result;
+ bool isNull;
+
+ ldatum = castNode(PartitionRangeDatum, lfirst(cell1));
+ udatum = castNode(PartitionRangeDatum, lfirst(cell2));
+
+ /*
+ * Since get_range_key_properties() modifies partexprs_item, and we
+ * might need to start over from the previous expression in the later
+ * part of this function, save away the current value.
+ */
+ partexprs_item_saved = partexprs_item;
+
+ get_range_key_properties(key, i, ldatum, udatum,
+ &partexprs_item,
+ &keyCol,
+ &lower_val, &upper_val);
+
+ /*
+ * If either or both of lower_val and upper_val is NULL, they are
+ * unequal, because being NULL means the column is unbounded in the
+ * respective direction.
+ */
+ if (!lower_val || !upper_val)
+ break;
+
+ /* Create the test expression */
+ estate = CreateExecutorState();
+ oldcxt = MemoryContextSwitchTo(estate->es_query_cxt);
+ test_expr = make_partition_op_expr(key, i, BTEqualStrategyNumber,
+ (Expr *) lower_val,
+ (Expr *) upper_val);
+ fix_opfuncids((Node *) test_expr);
+ test_exprstate = ExecInitExpr(test_expr, NULL);
+ test_result = ExecEvalExprSwitchContext(test_exprstate,
+ GetPerTupleExprContext(estate),
+ &isNull);
+ MemoryContextSwitchTo(oldcxt);
+ FreeExecutorState(estate);
+
+ /* If not equal, go generate the OR expressions */
+ if (!DatumGetBool(test_result))
+ break;
+
+ /*
+ * The bounds for the last key column can't be equal, because such a
+ * range partition would never be allowed to be defined (it would have
+ * an empty range otherwise).
+ */
+ if (i == key->partnatts - 1)
+ elog(ERROR, "invalid range bound specification");
+
+ /* Equal, so generate keyCol = lower_val expression */
+ result = lappend(result,
+ make_partition_op_expr(key, i, BTEqualStrategyNumber,
+ keyCol, (Expr *) lower_val));
+
+ i++;
+ }
+
+ /* First pair of lower_val and upper_val that are not equal. */
+ lower_or_start_datum = cell1;
+ upper_or_start_datum = cell2;
+
+ /* OR will have as many arms as there are key columns left. */
+ num_or_arms = key->partnatts - i;
+ current_or_arm = 0;
+ lower_or_arms = upper_or_arms = NIL;
+ need_next_lower_arm = need_next_upper_arm = true;
+ while (current_or_arm < num_or_arms)
+ {
+ List *lower_or_arm_args = NIL,
+ *upper_or_arm_args = NIL;
+
+ /* Restart scan of columns from the i'th one */
+ j = i;
+ partexprs_item = partexprs_item_saved;
+
+ for_both_cell(cell1, lower_or_start_datum, cell2, upper_or_start_datum)
+ {
+ PartitionRangeDatum *ldatum_next = NULL,
+ *udatum_next = NULL;
+
+ ldatum = castNode(PartitionRangeDatum, lfirst(cell1));
+ if (lnext(cell1))
+ ldatum_next = castNode(PartitionRangeDatum,
+ lfirst(lnext(cell1)));
+ udatum = castNode(PartitionRangeDatum, lfirst(cell2));
+ if (lnext(cell2))
+ udatum_next = castNode(PartitionRangeDatum,
+ lfirst(lnext(cell2)));
+ get_range_key_properties(key, j, ldatum, udatum,
+ &partexprs_item,
+ &keyCol,
+ &lower_val, &upper_val);
+
+ if (need_next_lower_arm && lower_val)
+ {
+ uint16 strategy;
+
+ /*
+ * For the non-last columns of this arm, use the EQ operator.
+ * For the last or the last finite-valued column, use GE.
+ */
+ if (j - i < current_or_arm)
+ strategy = BTEqualStrategyNumber;
+ else if ((ldatum_next && ldatum_next->infinite) ||
+ j == key->partnatts - 1)
+ strategy = BTGreaterEqualStrategyNumber;
+ else
+ strategy = BTGreaterStrategyNumber;
+
+ lower_or_arm_args = lappend(lower_or_arm_args,
+ make_partition_op_expr(key, j,
+ strategy,
+ keyCol,
+ (Expr *) lower_val));
+ }
+
+ if (need_next_upper_arm && upper_val)
+ {
+ uint16 strategy;
+
+ /*
+ * For the non-last columns of this arm, use the EQ operator.
+ * For the last finite-valued column, use LE.
+ */
+ if (j - i < current_or_arm)
+ strategy = BTEqualStrategyNumber;
+ else if (udatum_next && udatum_next->infinite)
+ strategy = BTLessEqualStrategyNumber;
+ else
+ strategy = BTLessStrategyNumber;
+
+ upper_or_arm_args = lappend(upper_or_arm_args,
+ make_partition_op_expr(key, j,
+ strategy,
+ keyCol,
+ (Expr *) upper_val));
+ }
+
+ /*
+ * Did we generate enough of OR's arguments? First arm considers
+ * the first of the remaining columns, second arm considers first
+ * two of the remaining columns, and so on.
+ */
+ ++j;
+ if (j - i > current_or_arm)
+ {
+ /*
+ * We need not emit the next arm if the new column that will
+ * be considered is unbounded.
+ */
+ need_next_lower_arm = ldatum_next && !ldatum_next->infinite;
+ need_next_upper_arm = udatum_next && !udatum_next->infinite;
+ break;
+ }
+ }
+
+ if (lower_or_arm_args != NIL)
+ lower_or_arms = lappend(lower_or_arms,
+ list_length(lower_or_arm_args) > 1
+ ? makeBoolExpr(AND_EXPR, lower_or_arm_args, -1)
+ : linitial(lower_or_arm_args));
+
+ if (upper_or_arm_args != NIL)
+ upper_or_arms = lappend(upper_or_arms,
+ list_length(upper_or_arm_args) > 1
+ ? makeBoolExpr(AND_EXPR, upper_or_arm_args, -1)
+ : linitial(upper_or_arm_args));
+
+ /* If no work to do in the next iteration, break away. */
+ if (!need_next_lower_arm && !need_next_upper_arm)
+ break;
+
+ ++current_or_arm;
+ }
+
+ /*
+ * Generate the OR expressions for each of lower and upper bounds (if
+ * required), and append to the list of implicitly ANDed list of
+ * expressions.
+ */
+ if (lower_or_arms != NIL)
+ result = lappend(result,
+ list_length(lower_or_arms) > 1
+ ? makeBoolExpr(OR_EXPR, lower_or_arms, -1)
+ : linitial(lower_or_arms));
+ if (upper_or_arms != NIL)
+ result = lappend(result,
+ list_length(upper_or_arms) > 1
+ ? makeBoolExpr(OR_EXPR, upper_or_arms, -1)
+ : linitial(upper_or_arms));
+
+ /* As noted above, caller expects the list to be non-empty. */
+ if (result == NIL)
+ result = list_make1(makeBoolConst(true, false));
+
+ return result;
+}
+
+/*
+ * generate_partition_qual
+ *
+ * Generate partition predicate from rel's partition bound expression
+ *
+ * Result expression tree is stored CacheMemoryContext to ensure it survives
+ * as long as the relcache entry. But we should be running in a less long-lived
+ * working context. To avoid leaking cache memory if this routine fails partway
+ * through, we build in working memory and then copy the completed structure
+ * into cache memory.
+ */
+static List *
+generate_partition_qual(Relation rel)
+{
+ HeapTuple tuple;
+ MemoryContext oldcxt;
+ Datum boundDatum;
+ bool isnull;
+ PartitionBoundSpec *bound;
+ List *my_qual = NIL,
+ *result = NIL;
+ Relation parent;
+
+ /* Guard against stack overflow due to overly deep partition tree */
+ check_stack_depth();
+
+ /* Quick copy */
+ if (rel->rd_partcheck != NIL)
+ return copyObject(rel->rd_partcheck);
+
+ /* Grab at least an AccessShareLock on the parent table */
+ parent = heap_open(get_partition_parent(RelationGetRelid(rel)),
+ AccessShareLock);
+
+ /* Get pg_class.relpartbound */
+ tuple = SearchSysCache1(RELOID, RelationGetRelid(rel));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u",
+ RelationGetRelid(rel));
+
+ boundDatum = SysCacheGetAttr(RELOID, tuple,
+ Anum_pg_class_relpartbound,
+ &isnull);
+ if (isnull) /* should not happen */
+ elog(ERROR, "relation \"%s\" has relpartbound = null",
+ RelationGetRelationName(rel));
+ bound = castNode(PartitionBoundSpec,
+ stringToNode(TextDatumGetCString(boundDatum)));
+ ReleaseSysCache(tuple);
+
+ my_qual = get_qual_from_partbound(rel, parent, bound);
+
+ /* Add the parent's quals to the list (if any) */
+ if (parent->rd_rel->relispartition)
+ result = list_concat(generate_partition_qual(parent), my_qual);
+ else
+ result = my_qual;
+
+ /*
+ * Change Vars to have partition's attnos instead of the parent's. We do
+ * this after we concatenate the parent's quals, because we want every Var
+ * in it to bear this relation's attnos. It's safe to assume varno = 1
+ * here.
+ */
+ result = map_partition_varattnos(result, 1, rel, parent);
+
+ /* Save a copy in the relcache */
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+ rel->rd_partcheck = copyObject(result);
+ MemoryContextSwitchTo(oldcxt);
+
+ /* Keep the parent locked until commit */
+ heap_close(parent, NoLock);
+
+ return result;
+}
+
+/* ----------------
+ * FormPartitionKeyDatum
+ * Construct values[] and isnull[] arrays for the partition key
+ * of a tuple.
+ *
+ * pd Partition dispatch object of the partitioned table
+ * slot Heap tuple from which to extract partition key
+ * estate executor state for evaluating any partition key
+ * expressions (must be non-NULL)
+ * values Array of partition key Datums (output area)
+ * isnull Array of is-null indicators (output area)
+ *
+ * the ecxt_scantuple slot of estate's per-tuple expr context must point to
+ * the heap tuple passed in.
+ * ----------------
+ */
+void
+FormPartitionKeyDatum(PartitionDispatch pd,
+ TupleTableSlot *slot,
+ EState *estate,
+ Datum *values,
+ bool *isnull)
+{
+ ListCell *partexpr_item;
+ int i;
+
+ if (pd->key->partexprs != NIL && pd->keystate == NIL)
+ {
+ /* Check caller has set up context correctly */
+ Assert(estate != NULL &&
+ GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
+
+ /* First time through, set up expression evaluation state */
+ pd->keystate = ExecPrepareExprList(pd->key->partexprs, estate);
+ }
+
+ partexpr_item = list_head(pd->keystate);
+ for (i = 0; i < pd->key->partnatts; i++)
+ {
+ AttrNumber keycol = pd->key->partattrs[i];
+ Datum datum;
+ bool isNull;
+
+ if (keycol != 0)
+ {
+ /* Plain column; get the value directly from the heap tuple */
+ datum = slot_getattr(slot, keycol, &isNull);
+ }
+ else
+ {
+ /* Expression; need to evaluate it */
+ if (partexpr_item == NULL)
+ elog(ERROR, "wrong number of partition key expressions");
+ datum = ExecEvalExprSwitchContext((ExprState *) lfirst(partexpr_item),
+ GetPerTupleExprContext(estate),
+ &isNull);
+ partexpr_item = lnext(partexpr_item);
+ }
+ values[i] = datum;
+ isnull[i] = isNull;
+ }
+
+ if (partexpr_item != NULL)
+ elog(ERROR, "wrong number of partition key expressions");
+}
+
+/*
+ * get_partition_for_tuple
+ * Finds a leaf partition for tuple contained in *slot
+ *
+ * Returned value is the sequence number of the leaf partition thus found,
+ * or -1 if no leaf partition is found for the tuple. *failed_at is set
+ * to the OID of the partitioned table whose partition was not found in
+ * the latter case.
+ */
+int
+get_partition_for_tuple(PartitionDispatch *pd,
+ TupleTableSlot *slot,
+ EState *estate,
+ PartitionDispatchData **failed_at,
+ TupleTableSlot **failed_slot)
+{
+ PartitionDispatch parent;
+ Datum values[PARTITION_MAX_KEYS];
+ bool isnull[PARTITION_MAX_KEYS];
+ int cur_offset,
+ cur_index;
+ int i,
+ result;
+ ExprContext *ecxt = GetPerTupleExprContext(estate);
+ TupleTableSlot *ecxt_scantuple_old = ecxt->ecxt_scantuple;
+
+ /* start with the root partitioned table */
+ parent = pd[0];
+ while (true)
+ {
+ PartitionKey key = parent->key;
+ PartitionDesc partdesc = parent->partdesc;
+ TupleTableSlot *myslot = parent->tupslot;
+ TupleConversionMap *map = parent->tupmap;
+
+ if (myslot != NULL && map != NULL)
+ {
+ HeapTuple tuple = ExecFetchSlotTuple(slot);
+
+ ExecClearTuple(myslot);
+ tuple = do_convert_tuple(tuple, map);
+ ExecStoreTuple(tuple, myslot, InvalidBuffer, true);
+ slot = myslot;
+ }
+
+ /* Quick exit */
+ if (partdesc->nparts == 0)
+ {
+ *failed_at = parent;
+ *failed_slot = slot;
+ result = -1;
+ goto error_exit;
+ }
+
+ /*
+ * Extract partition key from tuple. Expression evaluation machinery
+ * that FormPartitionKeyDatum() invokes expects ecxt_scantuple to
+ * point to the correct tuple slot. The slot might have changed from
+ * what was used for the parent table if the table of the current
+ * partitioning level has different tuple descriptor from the parent.
+ * So update ecxt_scantuple accordingly.
+ */
+ ecxt->ecxt_scantuple = slot;
+ FormPartitionKeyDatum(parent, slot, estate, values, isnull);
+
+ if (key->strategy == PARTITION_STRATEGY_RANGE)
+ {
+ /*
+ * Since we cannot route tuples with NULL partition keys through a
+ * range-partitioned table, simply return that no partition exists
+ */
+ for (i = 0; i < key->partnatts; i++)
+ {
+ if (isnull[i])
+ {
+ *failed_at = parent;
+ *failed_slot = slot;
+ result = -1;
+ goto error_exit;
+ }
+ }
+ }
+
+ /*
+ * A null partition key is only acceptable if null-accepting list
+ * partition exists.
+ */
+ cur_index = -1;
+ if (isnull[0] && partition_bound_accepts_nulls(partdesc->boundinfo))
+ cur_index = partdesc->boundinfo->null_index;
+ else if (!isnull[0])
+ {
+ /* Else bsearch in partdesc->boundinfo */
+ bool equal = false;
+
+ cur_offset = partition_bound_bsearch(key, partdesc->boundinfo,
+ values, false, &equal);
+ switch (key->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ if (cur_offset >= 0 && equal)
+ cur_index = partdesc->boundinfo->indexes[cur_offset];
+ else
+ cur_index = -1;
+ break;
+
+ case PARTITION_STRATEGY_RANGE:
+
+ /*
+ * Offset returned is such that the bound at offset is
+ * found to be less or equal with the tuple. So, the bound
+ * at offset+1 would be the upper bound.
+ */
+ cur_index = partdesc->boundinfo->indexes[cur_offset + 1];
+ break;
+
+ default:
+ elog(ERROR, "unexpected partition strategy: %d",
+ (int) key->strategy);
+ }
+ }
+
+ /*
+ * cur_index < 0 means we failed to find a partition of this parent.
+ * cur_index >= 0 means we either found the leaf partition, or the
+ * next parent to find a partition of.
+ */
+ if (cur_index < 0)
+ {
+ result = -1;
+ *failed_at = parent;
+ *failed_slot = slot;
+ break;
+ }
+ else if (parent->indexes[cur_index] >= 0)
+ {
+ result = parent->indexes[cur_index];
+ break;
+ }
+ else
+ parent = pd[-parent->indexes[cur_index]];
+ }
+
+error_exit:
+ ecxt->ecxt_scantuple = ecxt_scantuple_old;
+ return result;
+}
+
+/*
+ * qsort_partition_list_value_cmp
+ *
+ * Compare two list partition bound datums
+ */
+static int32
+qsort_partition_list_value_cmp(const void *a, const void *b, void *arg)
+{
+ Datum val1 = (*(const PartitionListValue **) a)->value,
+ val2 = (*(const PartitionListValue **) b)->value;
+ PartitionKey key = (PartitionKey) arg;
+
+ return DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0],
+ key->partcollation[0],
+ val1, val2));
+}
+
+/*
+ * make_one_range_bound
+ *
+ * Return a PartitionRangeBound given a list of PartitionRangeDatum elements
+ * and a flag telling whether the bound is lower or not. Made into a function
+ * because there are multiple sites that want to use this facility.
+ */
+static PartitionRangeBound *
+make_one_range_bound(PartitionKey key, int index, List *datums, bool lower)
+{
+ PartitionRangeBound *bound;
+ ListCell *lc;
+ int i;
+
+ bound = (PartitionRangeBound *) palloc0(sizeof(PartitionRangeBound));
+ bound->index = index;
+ bound->datums = (Datum *) palloc0(key->partnatts * sizeof(Datum));
+ bound->content = (RangeDatumContent *) palloc0(key->partnatts *
+ sizeof(RangeDatumContent));
+ bound->lower = lower;
+
+ i = 0;
+ foreach(lc, datums)
+ {
+ PartitionRangeDatum *datum = castNode(PartitionRangeDatum, lfirst(lc));
+
+ /* What's contained in this range datum? */
+ bound->content[i] = !datum->infinite
+ ? RANGE_DATUM_FINITE
+ : (lower ? RANGE_DATUM_NEG_INF
+ : RANGE_DATUM_POS_INF);
+
+ if (bound->content[i] == RANGE_DATUM_FINITE)
+ {
+ Const *val = castNode(Const, datum->value);
+
+ if (val->constisnull)
+ elog(ERROR, "invalid range bound datum");
+ bound->datums[i] = val->constvalue;
+ }
+
+ i++;
+ }
+
+ return bound;
+}
+
+/* Used when sorting range bounds across all range partitions */
+static int32
+qsort_partition_rbound_cmp(const void *a, const void *b, void *arg)
+{
+ PartitionRangeBound *b1 = (*(PartitionRangeBound *const *) a);
+ PartitionRangeBound *b2 = (*(PartitionRangeBound *const *) b);
+ PartitionKey key = (PartitionKey) arg;
+
+ return partition_rbound_cmp(key, b1->datums, b1->content, b1->lower, b2);
+}
+
+/*
+ * partition_rbound_cmp
+ *
+ * Return for two range bounds whether the 1st one (specified in datum1,
+ * content1, and lower1) is <=, =, >= the bound specified in *b2
+ */
+static int32
+partition_rbound_cmp(PartitionKey key,
+ Datum *datums1, RangeDatumContent *content1, bool lower1,
+ PartitionRangeBound *b2)
+{
+ int32 cmpval = 0; /* placate compiler */
+ int i;
+ Datum *datums2 = b2->datums;
+ RangeDatumContent *content2 = b2->content;
+ bool lower2 = b2->lower;
+
+ for (i = 0; i < key->partnatts; i++)
+ {
+ /*
+ * First, handle cases involving infinity, which don't require
+ * invoking the comparison proc.
+ */
+ if (content1[i] != RANGE_DATUM_FINITE &&
+ content2[i] != RANGE_DATUM_FINITE)
+
+ /*
+ * Both are infinity, so they are equal unless one is negative
+ * infinity and other positive (or vice versa)
+ */
+ return content1[i] == content2[i] ? 0
+ : (content1[i] < content2[i] ? -1 : 1);
+ else if (content1[i] != RANGE_DATUM_FINITE)
+ return content1[i] == RANGE_DATUM_NEG_INF ? -1 : 1;
+ else if (content2[i] != RANGE_DATUM_FINITE)
+ return content2[i] == RANGE_DATUM_NEG_INF ? 1 : -1;
+
+ cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[i],
+ key->partcollation[i],
+ datums1[i],
+ datums2[i]));
+ if (cmpval != 0)
+ break;
+ }
+
+ /*
+ * If the comparison is anything other than equal, we're done. If they
+ * compare equal though, we still have to consider whether the boundaries
+ * are inclusive or exclusive. Exclusive one is considered smaller of the
+ * two.
+ */
+ if (cmpval == 0 && lower1 != lower2)
+ cmpval = lower1 ? 1 : -1;
+
+ return cmpval;
+}
+
+/*
+ * partition_rbound_datum_cmp
+ *
+ * Return whether range bound (specified in rb_datums, rb_content, and
+ * rb_lower) <=, =, >= partition key of tuple (tuple_datums)
+ */
+static int32
+partition_rbound_datum_cmp(PartitionKey key,
+ Datum *rb_datums, RangeDatumContent *rb_content,
+ Datum *tuple_datums)
+{
+ int i;
+ int32 cmpval = -1;
+
+ for (i = 0; i < key->partnatts; i++)
+ {
+ if (rb_content[i] != RANGE_DATUM_FINITE)
+ return rb_content[i] == RANGE_DATUM_NEG_INF ? -1 : 1;
+
+ cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[i],
+ key->partcollation[i],
+ rb_datums[i],
+ tuple_datums[i]));
+ if (cmpval != 0)
+ break;
+ }
+
+ return cmpval;
+}
+
+/*
+ * partition_bound_cmp
+ *
+ * Return whether the bound at offset in boundinfo is <=, =, >= the argument
+ * specified in *probe.
+ */
+static int32
+partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo,
+ int offset, void *probe, bool probe_is_bound)
+{
+ Datum *bound_datums = boundinfo->datums[offset];
+ int32 cmpval = -1;
+
+ switch (key->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0],
+ key->partcollation[0],
+ bound_datums[0],
+ *(Datum *) probe));
+ break;
+
+ case PARTITION_STRATEGY_RANGE:
+ {
+ RangeDatumContent *content = boundinfo->content[offset];
+
+ if (probe_is_bound)
+ {
+ /*
+ * We need to pass whether the existing bound is a lower
+ * bound, so that two equal-valued lower and upper bounds
+ * are not regarded equal.
+ */
+ bool lower = boundinfo->indexes[offset] < 0;
+
+ cmpval = partition_rbound_cmp(key,
+ bound_datums, content, lower,
+ (PartitionRangeBound *) probe);
+ }
+ else
+ cmpval = partition_rbound_datum_cmp(key,
+ bound_datums, content,
+ (Datum *) probe);
+ break;
+ }
+
+ default:
+ elog(ERROR, "unexpected partition strategy: %d",
+ (int) key->strategy);
+ }
+
+ return cmpval;
+}
+
+/*
+ * Binary search on a collection of partition bounds. Returns greatest
+ * bound in array boundinfo->datums which is less than or equal to *probe
+ * If all bounds in the array are greater than *probe, -1 is returned.
+ *
+ * *probe could either be a partition bound or a Datum array representing
+ * the partition key of a tuple being routed; probe_is_bound tells which.
+ * We pass that down to the comparison function so that it can interpret the
+ * contents of *probe accordingly.
+ *
+ * *is_equal is set to whether the bound at the returned index is equal with
+ * *probe.
+ */
+static int
+partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
+ void *probe, bool probe_is_bound, bool *is_equal)
+{
+ int lo,
+ hi,
+ mid;
+
+ lo = -1;
+ hi = boundinfo->ndatums - 1;
+ while (lo < hi)
+ {
+ int32 cmpval;
+
+ mid = (lo + hi + 1) / 2;
+ cmpval = partition_bound_cmp(key, boundinfo, mid, probe,
+ probe_is_bound);
+ if (cmpval <= 0)
+ {
+ lo = mid;
+ *is_equal = (cmpval == 0);
+
+ if (*is_equal)
+ break;
+ }
+ else
+ hi = mid - 1;
+ }
+
+ return lo;
+}
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 959d3845df..65c2e88e93 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -3,7 +3,7 @@
* pg_aggregate.c
* routines to support manipulation of the pg_aggregate relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -433,7 +433,7 @@ AggregateCreate(const char *aggName,
if (aggTransType == INTERNALOID && func_strict(combinefn))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("combine function with \"%s\" transition type must not be declared STRICT",
+ errmsg("combine function with transition type %s must not be declared STRICT",
format_type_be(aggTransType))));
}
@@ -674,9 +674,7 @@ AggregateCreate(const char *aggName,
tupDesc = aggdesc->rd_att;
tup = heap_form_tuple(tupDesc, values, nulls);
- simple_heap_insert(aggdesc, tup);
-
- CatalogUpdateIndexes(aggdesc, tup);
+ CatalogTupleInsert(aggdesc, tup);
heap_close(aggdesc, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
index f37cf37c4a..30cd0cba19 100644
--- a/src/backend/catalog/pg_collation.c
+++ b/src/backend/catalog/pg_collation.c
@@ -3,7 +3,7 @@
* pg_collation.c
* routines to support manipulation of the pg_collation relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -27,6 +27,7 @@
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/pg_locale.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
@@ -40,8 +41,11 @@
Oid
CollationCreate(const char *collname, Oid collnamespace,
Oid collowner,
+ char collprovider,
int32 collencoding,
- const char *collcollate, const char *collctype)
+ const char *collcollate, const char *collctype,
+ const char *collversion,
+ bool if_not_exists)
{
Relation rel;
TupleDesc tupDesc;
@@ -72,27 +76,65 @@ CollationCreate(const char *collname, Oid collnamespace,
PointerGetDatum(collname),
Int32GetDatum(collencoding),
ObjectIdGetDatum(collnamespace)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("collation \"%s\" for encoding \"%s\" already exists",
- collname, pg_encoding_to_char(collencoding))));
+ {
+ if (if_not_exists)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ collencoding == -1
+ ? errmsg("collation \"%s\" already exists, skipping",
+ collname)
+ : errmsg("collation \"%s\" for encoding \"%s\" already exists, skipping",
+ collname, pg_encoding_to_char(collencoding))));
+ return InvalidOid;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ collencoding == -1
+ ? errmsg("collation \"%s\" already exists",
+ collname)
+ : errmsg("collation \"%s\" for encoding \"%s\" already exists",
+ collname, pg_encoding_to_char(collencoding))));
+ }
+
+ /* open pg_collation; see below about the lock level */
+ rel = heap_open(CollationRelationId, ShareRowExclusiveLock);
/*
- * Also forbid matching an any-encoding entry. This test of course is not
- * backed up by the unique index, but it's not a problem since we don't
- * support adding any-encoding entries after initdb.
+ * Also forbid a specific-encoding collation shadowing an any-encoding
+ * collation, or an any-encoding collation being shadowed (see
+ * get_collation_name()). This test is not backed up by the unique index,
+ * so we take a ShareRowExclusiveLock earlier, to protect against
+ * concurrent changes fooling this check.
*/
- if (SearchSysCacheExists3(COLLNAMEENCNSP,
- PointerGetDatum(collname),
- Int32GetDatum(-1),
- ObjectIdGetDatum(collnamespace)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("collation \"%s\" already exists",
- collname)));
+ if ((collencoding == -1 &&
+ SearchSysCacheExists3(COLLNAMEENCNSP,
+ PointerGetDatum(collname),
+ Int32GetDatum(GetDatabaseEncoding()),
+ ObjectIdGetDatum(collnamespace))) ||
+ (collencoding != -1 &&
+ SearchSysCacheExists3(COLLNAMEENCNSP,
+ PointerGetDatum(collname),
+ Int32GetDatum(-1),
+ ObjectIdGetDatum(collnamespace))))
+ {
+ if (if_not_exists)
+ {
+ heap_close(rel, NoLock);
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("collation \"%s\" already exists, skipping",
+ collname)));
+ return InvalidOid;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("collation \"%s\" already exists",
+ collname)));
+ }
- /* open pg_collation */
- rel = heap_open(CollationRelationId, RowExclusiveLock);
tupDesc = RelationGetDescr(rel);
/* form a tuple */
@@ -102,21 +144,23 @@ CollationCreate(const char *collname, Oid collnamespace,
values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name);
values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace);
values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner);
+ values[Anum_pg_collation_collprovider - 1] = CharGetDatum(collprovider);
values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding);
namestrcpy(&name_collate, collcollate);
values[Anum_pg_collation_collcollate - 1] = NameGetDatum(&name_collate);
namestrcpy(&name_ctype, collctype);
values[Anum_pg_collation_collctype - 1] = NameGetDatum(&name_ctype);
+ if (collversion)
+ values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(collversion);
+ else
+ nulls[Anum_pg_collation_collversion - 1] = true;
tup = heap_form_tuple(tupDesc, values, nulls);
/* insert a new tuple */
- oid = simple_heap_insert(rel, tup);
+ oid = CatalogTupleInsert(rel, tup);
Assert(OidIsValid(oid));
- /* update the index if any */
- CatalogUpdateIndexes(rel, tup);
-
/* set up dependencies for the new collation */
myself.classId = CollationRelationId;
myself.objectId = oid;
@@ -139,7 +183,7 @@ CollationCreate(const char *collname, Oid collnamespace,
InvokeObjectPostCreateHook(CollationRelationId, oid, 0);
heap_freetuple(tup);
- heap_close(rel, RowExclusiveLock);
+ heap_close(rel, NoLock);
return oid;
}
@@ -171,7 +215,7 @@ RemoveCollationById(Oid collationOid)
tuple = systable_getnext(scandesc);
if (HeapTupleIsValid(tuple))
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
else
elog(ERROR, "could not find tuple for collation %u", collationOid);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 8fabe6899f..e5ae3d9292 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -3,7 +3,7 @@
* pg_constraint.c
* routines to support manipulation of the pg_constraint relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -226,10 +226,7 @@ CreateConstraintEntry(const char *constraintName,
tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
- conOid = simple_heap_insert(conDesc, tup);
-
- /* update catalog indexes */
- CatalogUpdateIndexes(conDesc, tup);
+ conOid = CatalogTupleInsert(conDesc, tup);
conobject.classId = ConstraintRelationId;
conobject.objectId = conOid;
@@ -368,7 +365,7 @@ CreateConstraintEntry(const char *constraintName,
*/
recordDependencyOnSingleRelExpr(&conobject, conExpr, relId,
DEPENDENCY_NORMAL,
- DEPENDENCY_NORMAL);
+ DEPENDENCY_NORMAL, false);
}
/* Post creation hook for new constraint */
@@ -584,9 +581,7 @@ RemoveConstraintById(Oid conId)
RelationGetRelationName(rel));
classForm->relchecks--;
- simple_heap_update(pgrel, &relTup->t_self, relTup);
-
- CatalogUpdateIndexes(pgrel, relTup);
+ CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
heap_freetuple(relTup);
@@ -609,7 +604,7 @@ RemoveConstraintById(Oid conId)
elog(ERROR, "constraint %u is not of a known type", conId);
/* Fry the constraint itself */
- simple_heap_delete(conDesc, &tup->t_self);
+ CatalogTupleDelete(conDesc, &tup->t_self);
/* Clean up */
ReleaseSysCache(tup);
@@ -666,10 +661,7 @@ RenameConstraintById(Oid conId, const char *newname)
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
namestrcpy(&(con->conname), newname);
- simple_heap_update(conDesc, &tuple->t_self, tuple);
-
- /* update the system catalog indexes */
- CatalogUpdateIndexes(conDesc, tuple);
+ CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
@@ -736,8 +728,7 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
conform->connamespace = newNspId;
- simple_heap_update(conRel, &tup->t_self, tup);
- CatalogUpdateIndexes(conRel, tup);
+ CatalogTupleUpdate(conRel, &tup->t_self, tup);
/*
* Note: currently, the constraint will not have its own
@@ -852,8 +843,8 @@ get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
if (OidIsValid(conOid))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("domain \"%s\" has multiple constraints named \"%s\"",
- format_type_be(typid), conname)));
+ errmsg("domain %s has multiple constraints named \"%s\"",
+ format_type_be(typid), conname)));
conOid = HeapTupleGetOid(tuple);
}
}
@@ -864,7 +855,7 @@ get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
if (!OidIsValid(conOid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("constraint \"%s\" for domain \"%s\" does not exist",
+ errmsg("constraint \"%s\" for domain %s does not exist",
conname, format_type_be(typid))));
heap_close(pg_constraint, AccessShareLock);
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index e2feb1709c..5746dc349a 100644
--- a/src/backend/catalog/pg_conversion.c
+++ b/src/backend/catalog/pg_conversion.c
@@ -3,7 +3,7 @@
* pg_conversion.c
* routines to support manipulation of the pg_conversion relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -105,10 +105,7 @@ ConversionCreate(const char *conname, Oid connamespace,
tup = heap_form_tuple(tupDesc, values, nulls);
/* insert a new tuple */
- simple_heap_insert(rel, tup);
-
- /* update the index if any */
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleInsert(rel, tup);
myself.classId = ConversionRelationId;
myself.objectId = HeapTupleGetOid(tup);
@@ -168,7 +165,7 @@ RemoveConversionById(Oid conversionOid)
/* search for the target tuple */
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
else
elog(ERROR, "could not find tuple for conversion %u", conversionOid);
heap_endscan(scan);
diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c
index 9414ede961..323471bc83 100644
--- a/src/backend/catalog/pg_db_role_setting.c
+++ b/src/backend/catalog/pg_db_role_setting.c
@@ -2,7 +2,7 @@
* pg_db_role_setting.c
* Routines to support manipulation of the pg_db_role_setting relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -88,13 +88,10 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &tuple->t_self, newtuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
}
else
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
}
}
else if (HeapTupleIsValid(tuple))
@@ -129,13 +126,10 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &tuple->t_self, newtuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
}
else
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
}
else if (valuestr)
{
@@ -155,10 +149,7 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
- simple_heap_insert(rel, newtuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleInsert(rel, newtuple);
}
InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
@@ -208,7 +199,7 @@ DropSetting(Oid databaseid, Oid roleid)
scan = heap_beginscan_catalog(relsetting, numkeys, keys);
while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
{
- simple_heap_delete(relsetting, &tup->t_self);
+ CatalogTupleDelete(relsetting, &tup->t_self);
}
heap_endscan(scan);
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 7a0713e6cc..d616df62c1 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -3,7 +3,7 @@
* pg_depend.c
* routines to support manipulation of the pg_depend relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -107,13 +107,11 @@ recordMultipleDependencies(const ObjectAddress *depender,
tup = heap_form_tuple(dependDesc->rd_att, values, nulls);
- simple_heap_insert(dependDesc, tup);
-
- /* keep indexes current */
+ /* fetch index info only when we know we need it */
if (indstate == NULL)
indstate = CatalogOpenIndexes(dependDesc);
- CatalogIndexInsert(indstate, tup);
+ CatalogTupleInsertWithInfo(dependDesc, tup, indstate);
heap_freetuple(tup);
}
@@ -219,7 +217,7 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId,
((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
continue;
- simple_heap_delete(depRel, &tup->t_self);
+ CatalogTupleDelete(depRel, &tup->t_self);
count++;
}
@@ -269,7 +267,7 @@ deleteDependencyRecordsForClass(Oid classId, Oid objectId,
if (depform->refclassid == refclassId && depform->deptype == deptype)
{
- simple_heap_delete(depRel, &tup->t_self);
+ CatalogTupleDelete(depRel, &tup->t_self);
count++;
}
}
@@ -353,7 +351,7 @@ changeDependencyFor(Oid classId, Oid objectId,
depform->refobjid == oldRefObjectId)
{
if (newIsPinned)
- simple_heap_delete(depRel, &tup->t_self);
+ CatalogTupleDelete(depRel, &tup->t_self);
else
{
/* make a modifiable copy */
@@ -362,8 +360,7 @@ changeDependencyFor(Oid classId, Oid objectId,
depform->refobjid = newRefObjectId;
- simple_heap_update(depRel, &tup->t_self, tup);
- CatalogUpdateIndexes(depRel, tup);
+ CatalogTupleUpdate(depRel, &tup->t_self, tup);
heap_freetuple(tup);
}
@@ -491,7 +488,7 @@ getExtensionOfObject(Oid classId, Oid objectId)
/*
* Detect whether a sequence is marked as "owned" by a column
*
- * An ownership marker is an AUTO dependency from the sequence to the
+ * An ownership marker is an AUTO or INTERNAL dependency from the sequence to the
* column. If we find one, store the identity of the owning column
* into *tableId and *colId and return TRUE; else return FALSE.
*
@@ -500,7 +497,7 @@ getExtensionOfObject(Oid classId, Oid objectId)
* not happen, though.
*/
bool
-sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
+sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
{
bool ret = false;
Relation depRel;
@@ -527,7 +524,7 @@ sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
if (depform->refclassid == RelationRelationId &&
- depform->deptype == DEPENDENCY_AUTO)
+ depform->deptype == deptype)
{
*tableId = depform->refobjid;
*colId = depform->refobjsubid;
@@ -544,27 +541,15 @@ sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
}
/*
- * Remove any existing "owned" markers for the specified sequence.
- *
- * Note: we don't provide a special function to install an "owned"
- * marker; just use recordDependencyOn().
- */
-void
-markSequenceUnowned(Oid seqId)
-{
- deleteDependencyRecordsForClass(RelationRelationId, seqId,
- RelationRelationId, DEPENDENCY_AUTO);
-}
-
-/*
- * Collect a list of OIDs of all sequences owned by the specified relation.
+ * Collect a list of OIDs of all sequences owned by the specified relation,
+ * and column if specified.
*/
List *
-getOwnedSequences(Oid relid)
+getOwnedSequences(Oid relid, AttrNumber attnum)
{
List *result = NIL;
Relation depRel;
- ScanKeyData key[2];
+ ScanKeyData key[3];
SysScanDesc scan;
HeapTuple tup;
@@ -578,23 +563,28 @@ getOwnedSequences(Oid relid)
Anum_pg_depend_refobjid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
+ if (attnum)
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_refobjsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(attnum));
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
- NULL, 2, key);
+ NULL, attnum ? 3 : 2, key);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
/*
- * We assume any auto dependency of a sequence on a column must be
- * what we are looking for. (We need the relkind test because indexes
- * can also have auto dependencies on columns.)
+ * We assume any auto or internal dependency of a sequence on a column
+ * must be what we are looking for. (We need the relkind test because
+ * indexes can also have auto dependencies on columns.)
*/
if (deprec->classid == RelationRelationId &&
deprec->objsubid == 0 &&
deprec->refobjsubid != 0 &&
- deprec->deptype == DEPENDENCY_AUTO &&
+ (deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
{
result = lappend_oid(result, deprec->objid);
@@ -608,6 +598,21 @@ getOwnedSequences(Oid relid)
return result;
}
+/*
+ * Get owned sequence, error if not exactly one.
+ */
+Oid
+getOwnedSequence(Oid relid, AttrNumber attnum)
+{
+ List *seqlist = getOwnedSequences(relid, attnum);
+
+ if (list_length(seqlist) > 1)
+ elog(ERROR, "more than one owned sequence found");
+ else if (list_length(seqlist) < 1)
+ elog(ERROR, "no owned sequence found");
+
+ return linitial_oid(seqlist);
+}
/*
* get_constraint_index
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index af89daa712..300f24d231 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -3,7 +3,7 @@
* pg_enum.c
* routines to support manipulation of the pg_enum relation
*
- * Copyright (c) 2006-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2006-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
@@ -24,6 +24,7 @@
#include "catalog/pg_type.h"
#include "storage/lmgr.h"
#include "miscadmin.h"
+#include "nodes/value.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
@@ -35,7 +36,6 @@
Oid binary_upgrade_next_pg_enum_oid = InvalidOid;
static void RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems);
-static int oid_cmp(const void *p1, const void *p2);
static int sort_order_cmp(const void *p1, const void *p2);
@@ -124,8 +124,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
HeapTupleSetOid(tup, oids[elemno]);
- simple_heap_insert(pg_enum, tup);
- CatalogUpdateIndexes(pg_enum, tup);
+ CatalogTupleInsert(pg_enum, tup);
heap_freetuple(tup);
elemno++;
@@ -161,7 +160,7 @@ EnumValuesDelete(Oid enumTypeOid)
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
- simple_heap_delete(pg_enum, &tup->t_self);
+ CatalogTupleDelete(pg_enum, &tup->t_self);
}
systable_endscan(scan);
@@ -315,21 +314,21 @@ restart:
newelemorder = nbr_en->enumsortorder + 1;
else
{
- other_nbr_en = (Form_pg_enum) GETSTRUCT(existing[other_nbr_index]);
- newelemorder = (nbr_en->enumsortorder +
- other_nbr_en->enumsortorder) / 2;
-
/*
- * On some machines, newelemorder may be in a register that's
- * wider than float4. We need to force it to be rounded to float4
- * precision before making the following comparisons, or we'll get
- * wrong results. (Such behavior violates the C standard, but
- * fixing the compilers is out of our reach.)
+ * The midpoint value computed here has to be rounded to float4
+ * precision, else our equality comparisons against the adjacent
+ * values are meaningless. The most portable way of forcing that
+ * to happen with non-C-standard-compliant compilers is to store
+ * it into a volatile variable.
*/
- newelemorder = DatumGetFloat4(Float4GetDatum(newelemorder));
+ volatile float4 midpoint;
+
+ other_nbr_en = (Form_pg_enum) GETSTRUCT(existing[other_nbr_index]);
+ midpoint = (nbr_en->enumsortorder +
+ other_nbr_en->enumsortorder) / 2;
- if (newelemorder == nbr_en->enumsortorder ||
- newelemorder == other_nbr_en->enumsortorder)
+ if (midpoint == nbr_en->enumsortorder ||
+ midpoint == other_nbr_en->enumsortorder)
{
RenumberEnumType(pg_enum, existing, nelems);
/* Clean up and start over */
@@ -337,6 +336,8 @@ restart:
ReleaseCatCacheList(list);
goto restart;
}
+
+ newelemorder = midpoint;
}
}
@@ -455,8 +456,91 @@ restart:
values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
enum_tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
HeapTupleSetOid(enum_tup, newOid);
- simple_heap_insert(pg_enum, enum_tup);
- CatalogUpdateIndexes(pg_enum, enum_tup);
+ CatalogTupleInsert(pg_enum, enum_tup);
+ heap_freetuple(enum_tup);
+
+ heap_close(pg_enum, RowExclusiveLock);
+}
+
+
+/*
+ * RenameEnumLabel
+ * Rename a label in an enum set.
+ */
+void
+RenameEnumLabel(Oid enumTypeOid,
+ const char *oldVal,
+ const char *newVal)
+{
+ Relation pg_enum;
+ HeapTuple enum_tup;
+ Form_pg_enum en;
+ CatCList *list;
+ int nelems;
+ HeapTuple old_tup;
+ bool found_new;
+ int i;
+
+ /* check length of new label is ok */
+ if (strlen(newVal) > (NAMEDATALEN - 1))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid enum label \"%s\"", newVal),
+ errdetail("Labels must be %d characters or less.",
+ NAMEDATALEN - 1)));
+
+ /*
+ * Acquire a lock on the enum type, which we won't release until commit.
+ * This ensures that two backends aren't concurrently modifying the same
+ * enum type. Since we are not changing the type's sort order, this is
+ * probably not really necessary, but there seems no reason not to take
+ * the lock to be sure.
+ */
+ LockDatabaseObject(TypeRelationId, enumTypeOid, 0, ExclusiveLock);
+
+ pg_enum = heap_open(EnumRelationId, RowExclusiveLock);
+
+ /* Get the list of existing members of the enum */
+ list = SearchSysCacheList1(ENUMTYPOIDNAME,
+ ObjectIdGetDatum(enumTypeOid));
+ nelems = list->n_members;
+
+ /*
+ * Locate the element to rename and check if the new label is already in
+ * use. (The unique index on pg_enum would catch that anyway, but we
+ * prefer a friendlier error message.)
+ */
+ old_tup = NULL;
+ found_new = false;
+ for (i = 0; i < nelems; i++)
+ {
+ enum_tup = &(list->members[i]->tuple);
+ en = (Form_pg_enum) GETSTRUCT(enum_tup);
+ if (strcmp(NameStr(en->enumlabel), oldVal) == 0)
+ old_tup = enum_tup;
+ if (strcmp(NameStr(en->enumlabel), newVal) == 0)
+ found_new = true;
+ }
+ if (!old_tup)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is not an existing enum label",
+ oldVal)));
+ if (found_new)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("enum label \"%s\" already exists",
+ newVal)));
+
+ /* OK, make a writable copy of old tuple */
+ enum_tup = heap_copytuple(old_tup);
+ en = (Form_pg_enum) GETSTRUCT(enum_tup);
+
+ ReleaseCatCacheList(list);
+
+ /* Update the pg_enum entry */
+ namestrcpy(&en->enumlabel, newVal);
+ CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup);
heap_freetuple(enum_tup);
heap_close(pg_enum, RowExclusiveLock);
@@ -509,9 +593,7 @@ RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems)
{
en->enumsortorder = newsortorder;
- simple_heap_update(pg_enum, &newtup->t_self, newtup);
-
- CatalogUpdateIndexes(pg_enum, newtup);
+ CatalogTupleUpdate(pg_enum, &newtup->t_self, newtup);
}
heap_freetuple(newtup);
@@ -522,20 +604,6 @@ RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems)
}
-/* qsort comparison function for oids */
-static int
-oid_cmp(const void *p1, const void *p2)
-{
- Oid v1 = *((const Oid *) p1);
- Oid v2 = *((const Oid *) p2);
-
- if (v1 < v2)
- return -1;
- if (v1 > v2)
- return 1;
- return 0;
-}
-
/* qsort comparison function for tuples by sort order */
static int
sort_order_cmp(const void *p1, const void *p2)
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
index 00f2ae0bbb..e5fb52cfbf 100644
--- a/src/backend/catalog/pg_inherits.c
+++ b/src/backend/catalog/pg_inherits.c
@@ -8,7 +8,7 @@
* Perhaps someday that code should be moved here, but it'd have to be
* disentangled from other stuff such as pg_depend updates.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -27,12 +27,20 @@
#include "catalog/pg_inherits_fn.h"
#include "parser/parse_type.h"
#include "storage/lmgr.h"
+#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
-static int oid_cmp(const void *p1, const void *p2);
-
+/*
+ * Entry of a hash table used in find_all_inheritors. See below.
+ */
+typedef struct SeenRelsEntry
+{
+ Oid rel_id; /* relation oid */
+ ListCell *numparents_cell; /* corresponding list cell */
+} SeenRelsEntry;
/*
* find_inheritance_children
@@ -158,10 +166,23 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
List *
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
{
+ /* hash table for O(1) rel_oid -> rel_numparents cell lookup */
+ HTAB *seen_rels;
+ HASHCTL ctl;
List *rels_list,
*rel_numparents;
ListCell *l;
+ memset(&ctl, 0, sizeof(ctl));
+ ctl.keysize = sizeof(Oid);
+ ctl.entrysize = sizeof(SeenRelsEntry);
+ ctl.hcxt = CurrentMemoryContext;
+
+ seen_rels = hash_create("find_all_inheritors temporary table",
+ 32, /* start small and extend */
+ &ctl,
+ HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+
/*
* We build a list starting with the given rel and adding all direct and
* indirect children. We can use a single list as both the record of
@@ -191,26 +212,21 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
foreach(lc, currentchildren)
{
Oid child_oid = lfirst_oid(lc);
- bool found = false;
- ListCell *lo;
- ListCell *li;
+ bool found;
+ SeenRelsEntry *hash_entry;
- /* if the rel is already there, bump number-of-parents counter */
- forboth(lo, rels_list, li, rel_numparents)
+ hash_entry = hash_search(seen_rels, &child_oid, HASH_ENTER, &found);
+ if (found)
{
- if (lfirst_oid(lo) == child_oid)
- {
- lfirst_int(li)++;
- found = true;
- break;
- }
+ /* if the rel is already there, bump number-of-parents counter */
+ lfirst_int(hash_entry->numparents_cell)++;
}
-
- /* if it's not there, add it. expect 1 parent, initially. */
- if (!found)
+ else
{
+ /* if it's not there, add it. expect 1 parent, initially. */
rels_list = lappend_oid(rels_list, child_oid);
rel_numparents = lappend_int(rel_numparents, 1);
+ hash_entry->numparents_cell = rel_numparents->tail;
}
}
}
@@ -219,6 +235,9 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
*numparents = rel_numparents;
else
list_free(rel_numparents);
+
+ hash_destroy(seen_rels);
+
return rels_list;
}
@@ -357,18 +376,3 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
return result;
}
-
-
-/* qsort comparison function */
-static int
-oid_cmp(const void *p1, const void *p2)
-{
- Oid v1 = *((const Oid *) p1);
- Oid v2 = *((const Oid *) p2);
-
- if (v1 < v2)
- return -1;
- if (v1 > v2)
- return 1;
- return 0;
-}
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
index d08b94e28f..fc4f4f8c9b 100644
--- a/src/backend/catalog/pg_largeobject.c
+++ b/src/backend/catalog/pg_largeobject.c
@@ -3,7 +3,7 @@
* pg_largeobject.c
* routines to support manipulation of the pg_largeobject relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -63,11 +63,9 @@ LargeObjectCreate(Oid loid)
if (OidIsValid(loid))
HeapTupleSetOid(ntup, loid);
- loid_new = simple_heap_insert(pg_lo_meta, ntup);
+ loid_new = CatalogTupleInsert(pg_lo_meta, ntup);
Assert(!OidIsValid(loid) || loid == loid_new);
- CatalogUpdateIndexes(pg_lo_meta, ntup);
-
heap_freetuple(ntup);
heap_close(pg_lo_meta, RowExclusiveLock);
@@ -112,7 +110,7 @@ LargeObjectDrop(Oid loid)
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("large object %u does not exist", loid)));
- simple_heap_delete(pg_lo_meta, &tuple->t_self);
+ CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
systable_endscan(scan);
@@ -129,7 +127,7 @@ LargeObjectDrop(Oid loid)
NULL, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
- simple_heap_delete(pg_largeobject, &tuple->t_self);
+ CatalogTupleDelete(pg_largeobject, &tuple->t_self);
}
systable_endscan(scan);
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index e5eed79237..3e20d051c2 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -3,7 +3,7 @@
* pg_namespace.c
* routines to support manipulation of the pg_namespace relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -31,10 +31,11 @@
* Create a namespace (schema) with the given name and owner OID.
*
* If isTemp is true, this schema is a per-backend schema for holding
- * temporary tables. Currently, the only effect of that is to prevent it
- * from being linked as a member of any active extension. (If someone
- * does CREATE TEMP TABLE in an extension script, we don't want the temp
- * schema to become part of the extension.)
+ * temporary tables. Currently, it is used to prevent it from being
+ * linked as a member of any active extension. (If someone does CREATE
+ * TEMP TABLE in an extension script, we don't want the temp schema to
+ * become part of the extension). And to avoid checking for default ACL
+ * for temp namespace (as it is not necessary).
* ---------------
*/
Oid
@@ -49,6 +50,7 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
TupleDesc tupDesc;
ObjectAddress myself;
int i;
+ Acl *nspacl;
/* sanity checks */
if (!nspName)
@@ -60,6 +62,12 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
(errcode(ERRCODE_DUPLICATE_SCHEMA),
errmsg("schema \"%s\" already exists", nspName)));
+ if (!isTemp)
+ nspacl = get_user_default_acl(ACL_OBJECT_NAMESPACE, ownerId,
+ InvalidOid);
+ else
+ nspacl = NULL;
+
/* initialize nulls and values */
for (i = 0; i < Natts_pg_namespace; i++)
{
@@ -69,18 +77,19 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
namestrcpy(&nname, nspName);
values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
- nulls[Anum_pg_namespace_nspacl - 1] = true;
+ if (nspacl != NULL)
+ values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl);
+ else
+ nulls[Anum_pg_namespace_nspacl - 1] = true;
nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
tupDesc = nspdesc->rd_att;
tup = heap_form_tuple(tupDesc, values, nulls);
- nspoid = simple_heap_insert(nspdesc, tup);
+ nspoid = CatalogTupleInsert(nspdesc, tup);
Assert(OidIsValid(nspoid));
- CatalogUpdateIndexes(nspdesc, tup);
-
heap_close(nspdesc, RowExclusiveLock);
/* Record dependencies */
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 5b5cd3fc01..b5cbc04889 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -3,7 +3,7 @@
* pg_operator.c
* routines to support manipulation of the pg_operator relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -262,9 +262,7 @@ OperatorShellMake(const char *operatorName,
/*
* insert our "shell" operator tuple
*/
- operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
-
- CatalogUpdateIndexes(pg_operator_desc, tup);
+ operatorObjectId = CatalogTupleInsert(pg_operator_desc, tup);
/* Add dependencies for the entry */
makeOperatorDependencies(tup, false);
@@ -526,7 +524,7 @@ OperatorCreate(const char *operatorName,
nulls,
replaces);
- simple_heap_update(pg_operator_desc, &tup->t_self, tup);
+ CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
}
else
{
@@ -535,12 +533,9 @@ OperatorCreate(const char *operatorName,
tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
values, nulls);
- operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
+ operatorObjectId = CatalogTupleInsert(pg_operator_desc, tup);
}
- /* Must update the indexes in either case */
- CatalogUpdateIndexes(pg_operator_desc, tup);
-
/* Add dependencies for the entry */
address = makeOperatorDependencies(tup, isUpdate);
@@ -695,8 +690,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
/* If any columns were found to need modification, update tuple. */
if (update_commutator)
{
- simple_heap_update(pg_operator_desc, &tup->t_self, tup);
- CatalogUpdateIndexes(pg_operator_desc, tup);
+ CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
/*
* Do CCI to make the updated tuple visible. We must do this in
@@ -741,8 +735,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
/* If any columns were found to need modification, update tuple. */
if (update_negator)
{
- simple_heap_update(pg_operator_desc, &tup->t_self, tup);
- CatalogUpdateIndexes(pg_operator_desc, tup);
+ CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
/*
* In the deletion case, do CCI to make the updated tuple visible.
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 75621bd6e3..0f7ab80f65 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -4,7 +4,7 @@
* routines to support manipulation of the pg_proc relation
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -38,6 +38,7 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
+#include "utils/regproc.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#ifdef PGXC
@@ -47,10 +48,6 @@
#endif
-Datum fmgr_internal_validator(PG_FUNCTION_ARGS);
-Datum fmgr_c_validator(PG_FUNCTION_ARGS);
-Datum fmgr_sql_validator(PG_FUNCTION_ARGS);
-
typedef struct
{
char *proname;
@@ -519,8 +516,7 @@ ProcedureCreate(const char *procedureName,
Anum_pg_proc_proargdefaults,
&isnull);
Assert(!isnull);
- oldDefaults = (List *) stringToNode(TextDatumGetCString(proargdefaults));
- Assert(IsA(oldDefaults, List));
+ oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults)));
Assert(list_length(oldDefaults) == oldproc->pronargdefaults);
/* new list can have more defaults than old, advance over 'em */
@@ -582,7 +578,7 @@ ProcedureCreate(const char *procedureName,
/* Okay, do it... */
tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
- simple_heap_update(rel, &tup->t_self, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
ReleaseSysCache(oldtup);
is_update = true;
@@ -600,12 +596,10 @@ ProcedureCreate(const char *procedureName,
nulls[Anum_pg_proc_proacl - 1] = true;
tup = heap_form_tuple(tupDesc, values, nulls);
- simple_heap_insert(rel, tup);
+ CatalogTupleInsert(rel, tup);
is_update = false;
}
- /* Need to update indexes for either the insert or update case */
- CatalogUpdateIndexes(rel, tup);
retval = HeapTupleGetOid(tup);
@@ -940,7 +934,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
querytree_list = NIL;
foreach(lc, raw_parsetree_list)
{
- Node *parsetree = (Node *) lfirst(lc);
+ RawStmt *parsetree = lfirst_node(RawStmt, lc);
List *querytree_sublist;
#ifdef PGXC
@@ -954,9 +948,8 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
querytree_sublist = pg_analyze_and_rewrite_params(parsetree,
prosrc,
(ParserSetupHook) sql_fn_parser_setup,
- pinfo);
-
-
+ pinfo,
+ NULL);
querytree_list = list_concat(querytree_list,
querytree_sublist);
}
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
new file mode 100644
index 0000000000..17105f4f2c
--- /dev/null
+++ b/src/backend/catalog/pg_publication.c
@@ -0,0 +1,465 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication.c
+ * publication C API manipulation
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * pg_publication.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "miscadmin.h"
+
+#include "access/genam.h"
+#include "access/hash.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/xact.h"
+
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/index.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_publication.h"
+#include "catalog/pg_publication_rel.h"
+
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/fmgroids.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/*
+ * Check if relation can be in given publication and throws appropriate
+ * error if not.
+ */
+static void
+check_publication_add_relation(Relation targetrel)
+{
+ /* Give more specific error for partitioned tables */
+ if (RelationGetForm(targetrel)->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("\"%s\" is a partitioned table",
+ RelationGetRelationName(targetrel)),
+ errdetail("Adding partitioned tables to publications is not supported."),
+ errhint("You can add the table partitions individually.")));
+
+ /* Must be table */
+ if (RelationGetForm(targetrel)->relkind != RELKIND_RELATION)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is not a table",
+ RelationGetRelationName(targetrel)),
+ errdetail("Only tables can be added to publications.")));
+
+ /* Can't be system table */
+ if (IsCatalogRelation(targetrel))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is a system table",
+ RelationGetRelationName(targetrel)),
+ errdetail("System tables cannot be added to publications.")));
+
+ /* UNLOGGED and TEMP relations cannot be part of publication. */
+ if (!RelationNeedsWAL(targetrel))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("table \"%s\" cannot be replicated",
+ RelationGetRelationName(targetrel)),
+ errdetail("Temporary and unlogged relations cannot be replicated.")));
+}
+
+/*
+ * Returns if relation represented by oid and Form_pg_class entry
+ * is publishable.
+ *
+ * Does same checks as the above, but does not need relation to be opened
+ * and also does not throw errors.
+ *
+ * Note this also excludes all tables with relid < FirstNormalObjectId,
+ * ie all tables created during initdb. This mainly affects the preinstalled
+ * information_schema. (IsCatalogClass() only checks for these inside
+ * pg_catalog and toast schemas.)
+ */
+static bool
+is_publishable_class(Oid relid, Form_pg_class reltuple)
+{
+ return reltuple->relkind == RELKIND_RELATION &&
+ !IsCatalogClass(relid, reltuple) &&
+ reltuple->relpersistence == RELPERSISTENCE_PERMANENT &&
+ relid >= FirstNormalObjectId;
+}
+
+/*
+ * Insert new publication / relation mapping.
+ */
+ObjectAddress
+publication_add_relation(Oid pubid, Relation targetrel,
+ bool if_not_exists)
+{
+ Relation rel;
+ HeapTuple tup;
+ Datum values[Natts_pg_publication_rel];
+ bool nulls[Natts_pg_publication_rel];
+ Oid relid = RelationGetRelid(targetrel);
+ Oid prrelid;
+ Publication *pub = GetPublication(pubid);
+ ObjectAddress myself,
+ referenced;
+
+ rel = heap_open(PublicationRelRelationId, RowExclusiveLock);
+
+ /*
+ * Check for duplicates. Note that this does not really prevent
+ * duplicates, it's here just to provide nicer error message in common
+ * case. The real protection is the unique key on the catalog.
+ */
+ if (SearchSysCacheExists2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(pubid)))
+ {
+ heap_close(rel, RowExclusiveLock);
+
+ if (if_not_exists)
+ return InvalidObjectAddress;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("relation \"%s\" is already member of publication \"%s\"",
+ RelationGetRelationName(targetrel), pub->name)));
+ }
+
+ check_publication_add_relation(targetrel);
+
+ /* Form a tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_publication_rel_prpubid - 1] =
+ ObjectIdGetDatum(pubid);
+ values[Anum_pg_publication_rel_prrelid - 1] =
+ ObjectIdGetDatum(relid);
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ prrelid = CatalogTupleInsert(rel, tup);
+ heap_freetuple(tup);
+
+ ObjectAddressSet(myself, PublicationRelRelationId, prrelid);
+
+ /* Add dependency on the publication */
+ ObjectAddressSet(referenced, PublicationRelationId, pubid);
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+ /* Add dependency on the relation */
+ ObjectAddressSet(referenced, RelationRelationId, relid);
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+ /* Close the table. */
+ heap_close(rel, RowExclusiveLock);
+
+ /* Invalidate relcache so that publication info is rebuilt. */
+ CacheInvalidateRelcache(targetrel);
+
+ return myself;
+}
+
+
+/*
+ * Gets list of publication oids for a relation oid.
+ */
+List *
+GetRelationPublications(Oid relid)
+{
+ List *result = NIL;
+ CatCList *pubrellist;
+ int i;
+
+ /* Find all publications associated with the relation. */
+ pubrellist = SearchSysCacheList1(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(relid));
+ for (i = 0; i < pubrellist->n_members; i++)
+ {
+ HeapTuple tup = &pubrellist->members[i]->tuple;
+ Oid pubid = ((Form_pg_publication_rel) GETSTRUCT(tup))->prpubid;
+
+ result = lappend_oid(result, pubid);
+ }
+
+ ReleaseSysCacheList(pubrellist);
+
+ return result;
+}
+
+/*
+ * Gets list of relation oids for a publication.
+ *
+ * This should only be used for normal publications, the FOR ALL TABLES
+ * should use GetAllTablesPublicationRelations().
+ */
+List *
+GetPublicationRelations(Oid pubid)
+{
+ List *result;
+ Relation pubrelsrel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Find all publications associated with the relation. */
+ pubrelsrel = heap_open(PublicationRelRelationId, AccessShareLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_publication_rel_prpubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(pubid));
+
+ scan = systable_beginscan(pubrelsrel, PublicationRelPrrelidPrpubidIndexId,
+ true, NULL, 1, &scankey);
+
+ result = NIL;
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_publication_rel pubrel;
+
+ pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+
+ result = lappend_oid(result, pubrel->prrelid);
+ }
+
+ systable_endscan(scan);
+ heap_close(pubrelsrel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Gets list of publication oids for publications marked as FOR ALL TABLES.
+ */
+List *
+GetAllTablesPublications(void)
+{
+ List *result;
+ Relation rel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Find all publications that are marked as for all tables. */
+ rel = heap_open(PublicationRelationId, AccessShareLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_publication_puballtables,
+ BTEqualStrategyNumber, F_BOOLEQ,
+ BoolGetDatum(true));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, 1, &scankey);
+
+ result = NIL;
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ result = lappend_oid(result, HeapTupleGetOid(tup));
+
+ systable_endscan(scan);
+ heap_close(rel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Gets list of all relation published by FOR ALL TABLES publication(s).
+ */
+List *
+GetAllTablesPublicationRelations(void)
+{
+ Relation classRel;
+ ScanKeyData key[1];
+ HeapScanDesc scan;
+ HeapTuple tuple;
+ List *result = NIL;
+
+ classRel = heap_open(RelationRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ CharGetDatum(RELKIND_RELATION));
+
+ scan = heap_beginscan_catalog(classRel, 1, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Oid relid = HeapTupleGetOid(tuple);
+ Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple);
+
+ if (is_publishable_class(relid, relForm))
+ result = lappend_oid(result, relid);
+ }
+
+ heap_endscan(scan);
+ heap_close(classRel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Get publication using oid
+ *
+ * The Publication struct and its data are palloc'ed here.
+ */
+Publication *
+GetPublication(Oid pubid)
+{
+ HeapTuple tup;
+ Publication *pub;
+ Form_pg_publication pubform;
+
+ tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication %u", pubid);
+
+ pubform = (Form_pg_publication) GETSTRUCT(tup);
+
+ pub = (Publication *) palloc(sizeof(Publication));
+ pub->oid = pubid;
+ pub->name = pstrdup(NameStr(pubform->pubname));
+ pub->alltables = pubform->puballtables;
+ pub->pubactions.pubinsert = pubform->pubinsert;
+ pub->pubactions.pubupdate = pubform->pubupdate;
+ pub->pubactions.pubdelete = pubform->pubdelete;
+
+ ReleaseSysCache(tup);
+
+ return pub;
+}
+
+
+/*
+ * Get Publication using name.
+ */
+Publication *
+GetPublicationByName(const char *pubname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = GetSysCacheOid1(PUBLICATIONNAME, CStringGetDatum(pubname));
+ if (!OidIsValid(oid))
+ {
+ if (missing_ok)
+ return NULL;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication \"%s\" does not exist", pubname)));
+ }
+
+ return GetPublication(oid);
+}
+
+/*
+ * get_publication_oid - given a publication name, look up the OID
+ *
+ * If missing_ok is false, throw an error if name not found. If true, just
+ * return InvalidOid.
+ */
+Oid
+get_publication_oid(const char *pubname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = GetSysCacheOid1(PUBLICATIONNAME, CStringGetDatum(pubname));
+ if (!OidIsValid(oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication \"%s\" does not exist", pubname)));
+ return oid;
+}
+
+/*
+ * get_publication_name - given a publication Oid, look up the name
+ */
+char *
+get_publication_name(Oid pubid)
+{
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication pubform;
+
+ tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication %u", pubid);
+
+ pubform = (Form_pg_publication) GETSTRUCT(tup);
+ pubname = pstrdup(NameStr(pubform->pubname));
+
+ ReleaseSysCache(tup);
+
+ return pubname;
+}
+
+/*
+ * Returns Oids of tables in a publication.
+ */
+Datum
+pg_get_publication_tables(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ char *pubname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+ Publication *publication;
+ List *tables;
+ ListCell **lcp;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL())
+ {
+ MemoryContext oldcontext;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ publication = GetPublicationByName(pubname, false);
+ if (publication->alltables)
+ tables = GetAllTablesPublicationRelations();
+ else
+ tables = GetPublicationRelations(publication->oid);
+ lcp = (ListCell **) palloc(sizeof(ListCell *));
+ *lcp = list_head(tables);
+ funcctx->user_fctx = (void *) lcp;
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+ lcp = (ListCell **) funcctx->user_fctx;
+
+ while (*lcp != NULL)
+ {
+ Oid relid = lfirst_oid(*lcp);
+
+ *lcp = lnext(*lcp);
+ SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid));
+ }
+
+ SRF_RETURN_DONE(funcctx);
+}
diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c
index 84e7733e74..a3b0fb8838 100644
--- a/src/backend/catalog/pg_range.c
+++ b/src/backend/catalog/pg_range.c
@@ -3,7 +3,7 @@
* pg_range.c
* routines to support manipulation of the pg_range relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -58,8 +58,7 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
tup = heap_form_tuple(RelationGetDescr(pg_range), values, nulls);
- simple_heap_insert(pg_range, tup);
- CatalogUpdateIndexes(pg_range, tup);
+ CatalogTupleInsert(pg_range, tup);
heap_freetuple(tup);
/* record type's dependencies on range-related items */
@@ -130,7 +129,7 @@ RangeDelete(Oid rangeTypeOid)
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
- simple_heap_delete(pg_range, &tup->t_self);
+ CatalogTupleDelete(pg_range, &tup->t_self);
}
systable_endscan(scan);
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 65ecc45d49..d28a8afb47 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -3,7 +3,7 @@
* pg_shdepend.c
* routines to support manipulation of the pg_shdepend relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -39,6 +39,8 @@
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shdepend.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
@@ -53,7 +55,9 @@
#include "commands/extension.h"
#include "commands/policy.h"
#include "commands/proclang.h"
+#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
+#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "storage/lmgr.h"
@@ -246,7 +250,7 @@ shdepChangeDep(Relation sdepRel,
{
/* No new entry needed, so just delete existing entry if any */
if (oldtup)
- simple_heap_delete(sdepRel, &oldtup->t_self);
+ CatalogTupleDelete(sdepRel, &oldtup->t_self);
}
else if (oldtup)
{
@@ -257,10 +261,7 @@ shdepChangeDep(Relation sdepRel,
shForm->refclassid = refclassid;
shForm->refobjid = refobjid;
- simple_heap_update(sdepRel, &oldtup->t_self, oldtup);
-
- /* keep indexes current */
- CatalogUpdateIndexes(sdepRel, oldtup);
+ CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup);
}
else
{
@@ -284,10 +285,7 @@ shdepChangeDep(Relation sdepRel,
* it's certainly a new tuple
*/
oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls);
- simple_heap_insert(sdepRel, oldtup);
-
- /* keep indexes current */
- CatalogUpdateIndexes(sdepRel, oldtup);
+ CatalogTupleInsert(sdepRel, oldtup);
}
if (oldtup)
@@ -756,10 +754,7 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
HeapTuple newtup;
newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace);
- simple_heap_insert(sdepRel, newtup);
-
- /* Keep indexes current */
- CatalogIndexInsert(indstate, newtup);
+ CatalogTupleInsertWithInfo(sdepRel, newtup, indstate);
heap_freetuple(newtup);
}
@@ -801,7 +796,7 @@ dropDatabaseDependencies(Oid databaseId)
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
- simple_heap_delete(sdepRel, &tup->t_self);
+ CatalogTupleDelete(sdepRel, &tup->t_self);
}
systable_endscan(scan);
@@ -879,10 +874,7 @@ shdepAddDependency(Relation sdepRel,
tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
- simple_heap_insert(sdepRel, tup);
-
- /* keep indexes current */
- CatalogUpdateIndexes(sdepRel, tup);
+ CatalogTupleInsert(sdepRel, tup);
/* clean up */
heap_freetuple(tup);
@@ -957,7 +949,7 @@ shdepDropDependency(Relation sdepRel,
continue;
/* OK, delete it */
- simple_heap_delete(sdepRel, &tup->t_self);
+ CatalogTupleDelete(sdepRel, &tup->t_self);
}
systable_endscan(scan);
@@ -1406,6 +1398,14 @@ shdepReassignOwned(List *roleids, Oid newrole)
AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
break;
+ case PublicationRelationId:
+ AlterPublicationOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case SubscriptionRelationId:
+ AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
+ break;
+
/* Generic alter owner cases */
case CollationRelationId:
case ConversionRelationId:
@@ -1416,6 +1416,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
case OperatorFamilyRelationId:
case OperatorClassRelationId:
case ExtensionRelationId:
+ case StatisticExtRelationId:
case TableSpaceRelationId:
case DatabaseRelationId:
case TSConfigRelationId:
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
new file mode 100644
index 0000000000..ab5f3719fc
--- /dev/null
+++ b/src/backend/catalog/pg_subscription.c
@@ -0,0 +1,504 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_subscription.c
+ * replication subscriptions
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_subscription.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "miscadmin.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/xact.h"
+
+#include "catalog/indexing.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_subscription.h"
+#include "catalog/pg_subscription_rel.h"
+
+#include "nodes/makefuncs.h"
+
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/pg_lsn.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+static List *textarray_to_stringlist(ArrayType *textarray);
+
+/*
+ * Fetch the subscription from the syscache.
+ */
+Subscription *
+GetSubscription(Oid subid, bool missing_ok)
+{
+ HeapTuple tup;
+ Subscription *sub;
+ Form_pg_subscription subform;
+ Datum datum;
+ bool isnull;
+
+ tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ if (missing_ok)
+ return NULL;
+
+ elog(ERROR, "cache lookup failed for subscription %u", subid);
+ }
+
+ subform = (Form_pg_subscription) GETSTRUCT(tup);
+
+ sub = (Subscription *) palloc(sizeof(Subscription));
+ sub->oid = subid;
+ sub->dbid = subform->subdbid;
+ sub->name = pstrdup(NameStr(subform->subname));
+ sub->owner = subform->subowner;
+ sub->enabled = subform->subenabled;
+
+ /* Get conninfo */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subconninfo,
+ &isnull);
+ Assert(!isnull);
+ sub->conninfo = TextDatumGetCString(datum);
+
+ /* Get slotname */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subslotname,
+ &isnull);
+ if (!isnull)
+ sub->slotname = pstrdup(NameStr(*DatumGetName(datum)));
+ else
+ sub->slotname = NULL;
+
+ /* Get synccommit */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subsynccommit,
+ &isnull);
+ Assert(!isnull);
+ sub->synccommit = TextDatumGetCString(datum);
+
+ /* Get publications */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subpublications,
+ &isnull);
+ Assert(!isnull);
+ sub->publications = textarray_to_stringlist(DatumGetArrayTypeP(datum));
+
+ ReleaseSysCache(tup);
+
+ return sub;
+}
+
+/*
+ * Return number of subscriptions defined in given database.
+ * Used by dropdb() to check if database can indeed be dropped.
+ */
+int
+CountDBSubscriptions(Oid dbid)
+{
+ int nsubs = 0;
+ Relation rel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_subscription_subdbid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(dbid));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, 1, &scankey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ nsubs++;
+
+ systable_endscan(scan);
+
+ heap_close(rel, NoLock);
+
+ return nsubs;
+}
+
+/*
+ * Free memory allocated by subscription struct.
+ */
+void
+FreeSubscription(Subscription *sub)
+{
+ pfree(sub->name);
+ pfree(sub->conninfo);
+ if (sub->slotname)
+ pfree(sub->slotname);
+ list_free_deep(sub->publications);
+ pfree(sub);
+}
+
+/*
+ * get_subscription_oid - given a subscription name, look up the OID
+ *
+ * If missing_ok is false, throw an error if name not found. If true, just
+ * return InvalidOid.
+ */
+Oid
+get_subscription_oid(const char *subname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = GetSysCacheOid2(SUBSCRIPTIONNAME, MyDatabaseId,
+ CStringGetDatum(subname));
+ if (!OidIsValid(oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription \"%s\" does not exist", subname)));
+ return oid;
+}
+
+/*
+ * get_subscription_name - given a subscription OID, look up the name
+ */
+char *
+get_subscription_name(Oid subid)
+{
+ HeapTuple tup;
+ char *subname;
+ Form_pg_subscription subform;
+
+ tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for subscription %u", subid);
+
+ subform = (Form_pg_subscription) GETSTRUCT(tup);
+ subname = pstrdup(NameStr(subform->subname));
+
+ ReleaseSysCache(tup);
+
+ return subname;
+}
+
+/*
+ * Convert text array to list of strings.
+ *
+ * Note: the resulting list of strings is pallocated here.
+ */
+static List *
+textarray_to_stringlist(ArrayType *textarray)
+{
+ Datum *elems;
+ int nelems,
+ i;
+ List *res = NIL;
+
+ deconstruct_array(textarray,
+ TEXTOID, -1, false, 'i',
+ &elems, NULL, &nelems);
+
+ if (nelems == 0)
+ return NIL;
+
+ for (i = 0; i < nelems; i++)
+ res = lappend(res, makeString(TextDatumGetCString(elems[i])));
+
+ return res;
+}
+
+/*
+ * Set the state of a subscription table.
+ *
+ * The insert-or-update logic in this function is not concurrency safe so it
+ * might raise an error in rare circumstances. But if we took a stronger lock
+ * such as ShareRowExclusiveLock, we would risk more deadlocks.
+ */
+Oid
+SetSubscriptionRelState(Oid subid, Oid relid, char state,
+ XLogRecPtr sublsn)
+{
+ Relation rel;
+ HeapTuple tup;
+ Oid subrelid;
+ bool nulls[Natts_pg_subscription_rel];
+ Datum values[Natts_pg_subscription_rel];
+
+ rel = heap_open(SubscriptionRelRelationId, RowExclusiveLock);
+
+ /* Try finding existing mapping. */
+ tup = SearchSysCacheCopy2(SUBSCRIPTIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(subid));
+
+ /*
+ * If the record for given table does not exist yet create new record,
+ * otherwise update the existing one.
+ */
+ if (!HeapTupleIsValid(tup))
+ {
+ /* Form the tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ values[Anum_pg_subscription_rel_srsubid - 1] = ObjectIdGetDatum(subid);
+ values[Anum_pg_subscription_rel_srrelid - 1] = ObjectIdGetDatum(relid);
+ values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state);
+ if (sublsn != InvalidXLogRecPtr)
+ values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn);
+ else
+ nulls[Anum_pg_subscription_rel_srsublsn - 1] = true;
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ subrelid = CatalogTupleInsert(rel, tup);
+
+ heap_freetuple(tup);
+ }
+ else
+ {
+ bool replaces[Natts_pg_subscription_rel];
+
+ /* Update the tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_subscription_rel_srsubstate - 1] = true;
+ values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state);
+
+ replaces[Anum_pg_subscription_rel_srsublsn - 1] = true;
+ if (sublsn != InvalidXLogRecPtr)
+ values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn);
+ else
+ nulls[Anum_pg_subscription_rel_srsublsn - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ subrelid = HeapTupleGetOid(tup);
+ }
+
+ /* Cleanup. */
+ heap_close(rel, NoLock);
+
+ return subrelid;
+}
+
+/*
+ * Get state of subscription table.
+ *
+ * Returns SUBREL_STATE_UNKNOWN when not found and missing_ok is true.
+ */
+char
+GetSubscriptionRelState(Oid subid, Oid relid, XLogRecPtr *sublsn,
+ bool missing_ok)
+{
+ Relation rel;
+ HeapTuple tup;
+ char substate;
+ bool isnull;
+ Datum d;
+
+ rel = heap_open(SubscriptionRelRelationId, AccessShareLock);
+
+ /* Try finding the mapping. */
+ tup = SearchSysCache2(SUBSCRIPTIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ if (missing_ok)
+ {
+ heap_close(rel, AccessShareLock);
+ *sublsn = InvalidXLogRecPtr;
+ return SUBREL_STATE_UNKNOWN;
+ }
+
+ elog(ERROR, "subscription table %u in subscription %u does not exist",
+ relid, subid);
+ }
+
+ /* Get the state. */
+ d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
+ Anum_pg_subscription_rel_srsubstate, &isnull);
+ Assert(!isnull);
+ substate = DatumGetChar(d);
+ d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
+ Anum_pg_subscription_rel_srsublsn, &isnull);
+ if (isnull)
+ *sublsn = InvalidXLogRecPtr;
+ else
+ *sublsn = DatumGetLSN(d);
+
+ /* Cleanup */
+ ReleaseSysCache(tup);
+ heap_close(rel, AccessShareLock);
+
+ return substate;
+}
+
+/*
+ * Drop subscription relation mapping. These can be for a particular
+ * subscription, or for a particular relation, or both.
+ */
+void
+RemoveSubscriptionRel(Oid subid, Oid relid)
+{
+ Relation rel;
+ HeapScanDesc scan;
+ ScanKeyData skey[2];
+ HeapTuple tup;
+ int nkeys = 0;
+
+ rel = heap_open(SubscriptionRelRelationId, RowExclusiveLock);
+
+ if (OidIsValid(subid))
+ {
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubid,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(subid));
+ }
+
+ if (OidIsValid(relid))
+ {
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srrelid,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ }
+
+ /* Do the search and delete what we found. */
+ scan = heap_beginscan_catalog(rel, nkeys, skey);
+ while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
+ {
+ simple_heap_delete(rel, &tup->t_self);
+ }
+ heap_endscan(scan);
+
+ heap_close(rel, RowExclusiveLock);
+}
+
+
+/*
+ * Get all relations for subscription.
+ *
+ * Returned list is palloc'ed in current memory context.
+ */
+List *
+GetSubscriptionRelations(Oid subid)
+{
+ List *res = NIL;
+ Relation rel;
+ HeapTuple tup;
+ int nkeys = 0;
+ ScanKeyData skey[2];
+ SysScanDesc scan;
+
+ rel = heap_open(SubscriptionRelRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(subid));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, nkeys, skey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_subscription_rel subrel;
+ SubscriptionRelState *relstate;
+
+ subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
+
+ relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
+ relstate->relid = subrel->srrelid;
+ relstate->state = subrel->srsubstate;
+ relstate->lsn = subrel->srsublsn;
+
+ res = lappend(res, relstate);
+ }
+
+ /* Cleanup */
+ systable_endscan(scan);
+ heap_close(rel, AccessShareLock);
+
+ return res;
+}
+
+/*
+ * Get all relations for subscription that are not in a ready state.
+ *
+ * Returned list is palloc'ed in current memory context.
+ */
+List *
+GetSubscriptionNotReadyRelations(Oid subid)
+{
+ List *res = NIL;
+ Relation rel;
+ HeapTuple tup;
+ int nkeys = 0;
+ ScanKeyData skey[2];
+ SysScanDesc scan;
+
+ rel = heap_open(SubscriptionRelRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(subid));
+
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubstate,
+ BTEqualStrategyNumber, F_CHARNE,
+ CharGetDatum(SUBREL_STATE_READY));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, nkeys, skey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_subscription_rel subrel;
+ SubscriptionRelState *relstate;
+
+ subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
+
+ relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
+ relstate->relid = subrel->srrelid;
+ relstate->state = subrel->srsubstate;
+ relstate->lsn = subrel->srsublsn;
+
+ res = lappend(res, relstate);
+ }
+
+ /* Cleanup */
+ systable_endscan(scan);
+ heap_close(rel, AccessShareLock);
+
+ return res;
+}
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 4b2d281f2c..6b0e4f4729 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -3,7 +3,7 @@
* pg_type.c
* routines to support manipulation of the pg_type relation
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -142,9 +142,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
/*
* insert the tuple in the relation and get the tuple's oid.
*/
- typoid = simple_heap_insert(pg_type_desc, tup);
-
- CatalogUpdateIndexes(pg_type_desc, tup);
+ typoid = CatalogTupleInsert(pg_type_desc, tup);
/*
* Create dependencies. We can/must skip this in bootstrap mode.
@@ -430,7 +428,7 @@ TypeCreate(Oid newTypeOid,
nulls,
replaces);
- simple_heap_update(pg_type_desc, &tup->t_self, tup);
+ CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
typeObjectId = HeapTupleGetOid(tup);
@@ -458,12 +456,9 @@ TypeCreate(Oid newTypeOid,
}
/* else allow system to assign oid */
- typeObjectId = simple_heap_insert(pg_type_desc, tup);
+ typeObjectId = CatalogTupleInsert(pg_type_desc, tup);
}
- /* Update indexes */
- CatalogUpdateIndexes(pg_type_desc, tup);
-
/*
* Create dependencies. We can/must skip this in bootstrap mode.
*/
@@ -700,6 +695,7 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
HeapTuple tuple;
Form_pg_type typ;
Oid arrayOid;
+ Oid oldTypeOid;
pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
@@ -713,29 +709,45 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
arrayOid = typ->typarray;
- /* Just to give a more friendly error than unique-index violation */
- if (SearchSysCacheExists2(TYPENAMENSP,
- CStringGetDatum(newTypeName),
- ObjectIdGetDatum(typeNamespace)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("type \"%s\" already exists", newTypeName)));
+ /* Check for a conflicting type name. */
+ oldTypeOid = GetSysCacheOid2(TYPENAMENSP,
+ CStringGetDatum(newTypeName),
+ ObjectIdGetDatum(typeNamespace));
+
+ /*
+ * If there is one, see if it's an autogenerated array type, and if so
+ * rename it out of the way. (But we must skip that for a shell type
+ * because moveArrayTypeName will do the wrong thing in that case.)
+ * Otherwise, we can at least give a more friendly error than unique-index
+ * violation.
+ */
+ if (OidIsValid(oldTypeOid))
+ {
+ if (get_typisdefined(oldTypeOid) &&
+ moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
+ /* successfully dodged the problem */ ;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" already exists", newTypeName)));
+ }
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
namestrcpy(&(typ->typname), newTypeName);
- simple_heap_update(pg_type_desc, &tuple->t_self, tuple);
-
- /* update the system catalog indexes */
- CatalogUpdateIndexes(pg_type_desc, tuple);
+ CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
heap_freetuple(tuple);
heap_close(pg_type_desc, RowExclusiveLock);
- /* If the type has an array type, recurse to handle that */
- if (OidIsValid(arrayOid))
+ /*
+ * If the type has an array type, recurse to handle that. But we don't
+ * need to do anything more if we already renamed that array type above
+ * (which would happen when, eg, renaming "foo" to "_foo").
+ */
+ if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
{
char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
diff --git a/src/backend/catalog/pgxc_class.c b/src/backend/catalog/pgxc_class.c
index 297010be9f..a35cf7866d 100644
--- a/src/backend/catalog/pgxc_class.c
+++ b/src/backend/catalog/pgxc_class.c
@@ -79,9 +79,7 @@ PgxcClassCreate(Oid pcrelid,
htup = heap_form_tuple(pgxcclassrel->rd_att, values, nulls);
- (void) simple_heap_insert(pgxcclassrel, htup);
-
- CatalogUpdateIndexes(pgxcclassrel, htup);
+ CatalogTupleInsert(pgxcclassrel, htup);
heap_close(pgxcclassrel, RowExclusiveLock);
}
@@ -176,8 +174,7 @@ PgxcClassAlter(Oid pcrelid,
newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(rel, &oldtup->t_self, newtup);
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &oldtup->t_self, newtup);
heap_close(rel, RowExclusiveLock);
}
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
index 8956ba9304..2821b9b702 100644
--- a/src/backend/catalog/sql_features.txt
+++ b/src/backend/catalog/sql_features.txt
@@ -200,7 +200,7 @@ F181 Multiple module support NO
F191 Referential delete actions YES
F200 TRUNCATE TABLE statement YES
F201 CAST function YES
-F202 TRUNCATE TABLE: identity column restart option NO
+F202 TRUNCATE TABLE: identity column restart option YES
F221 Explicit defaults YES
F222 INSERT statement: DEFAULT VALUES clause YES
F231 Privilege tables YES
@@ -241,9 +241,9 @@ F381 Extended schema manipulation 02 ALTER TABLE statement: ADD CONSTRAINT claus
F381 Extended schema manipulation 03 ALTER TABLE statement: DROP CONSTRAINT clause YES
F382 Alter column data type YES
F383 Set column not null clause YES
-F384 Drop identity property clause NO
+F384 Drop identity property clause YES
F385 Drop column generation expression clause NO
-F386 Set identity column generation clause NO
+F386 Set identity column generation clause YES
F391 Long identifiers YES
F392 Unicode escapes in identifiers YES
F393 Unicode escapes in literals YES
@@ -420,11 +420,11 @@ T152 DISTINCT predicate with negation YES
T171 LIKE clause in table definition YES
T172 AS subquery clause in table definition YES
T173 Extended LIKE clause in table definition YES
-T174 Identity columns NO
+T174 Identity columns YES
T175 Generated columns NO
T176 Sequence generator support NO
-T177 Sequence generator support: simple restart option NO
-T178 Identity columns: simple restart option NO
+T177 Sequence generator support: simple restart option YES
+T178 Identity columns: simple restart option YES
T180 System-versioned tables NO
T181 Application-time period tables NO
T191 Referential action RESTRICT YES
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index a759e16c72..d5c4754d01 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -4,7 +4,7 @@
* code to create and destroy physical storage for relations
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 4fc5d5a065..0fdad0c119 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1,7 +1,7 @@
/*
* PostgreSQL System Views
*
- * Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Copyright (c) 1996-2017, PostgreSQL Global Development Group
*
* src/backend/catalog/system_views.sql
*
@@ -76,6 +76,12 @@ CREATE VIEW pg_policies AS
C.relname AS tablename,
pol.polname AS policyname,
CASE
+ WHEN pol.polpermissive THEN
+ 'PERMISSIVE'
+ ELSE
+ 'RESTRICTIVE'
+ END AS permissive,
+ CASE
WHEN pol.polroles = '{0}' THEN
string_to_array('public', '')
ELSE
@@ -130,7 +136,7 @@ CREATE VIEW pg_tables AS
C.relrowsecurity AS rowsecurity
FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
LEFT JOIN pg_tablespace T ON (T.oid = C.reltablespace)
- WHERE C.relkind = 'r';
+ WHERE C.relkind IN ('r', 'p');
CREATE VIEW pg_matviews AS
SELECT
@@ -158,6 +164,28 @@ CREATE VIEW pg_indexes AS
LEFT JOIN pg_tablespace T ON (T.oid = I.reltablespace)
WHERE C.relkind IN ('r', 'm') AND I.relkind = 'i';
+CREATE OR REPLACE VIEW pg_sequences AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS sequencename,
+ pg_get_userbyid(C.relowner) AS sequenceowner,
+ S.seqtypid::regtype AS data_type,
+ S.seqstart AS start_value,
+ S.seqmin AS min_value,
+ S.seqmax AS max_value,
+ S.seqincrement AS increment_by,
+ S.seqcycle AS cycle,
+ S.seqcache AS cache_size,
+ CASE
+ WHEN has_sequence_privilege(C.oid, 'SELECT,USAGE'::text)
+ THEN pg_sequence_last_value(C.oid)
+ ELSE NULL
+ END AS last_value
+ FROM pg_sequence S JOIN pg_class C ON (C.oid = S.seqrelid)
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE NOT pg_is_other_temp_schema(N.oid)
+ AND relkind = 'S';
+
CREATE VIEW pg_stats WITH (security_barrier) AS
SELECT
nspname AS schemaname,
@@ -225,6 +253,15 @@ CREATE VIEW pg_stats WITH (security_barrier) AS
REVOKE ALL on pg_statistic FROM public;
+CREATE VIEW pg_publication_tables AS
+ SELECT
+ P.pubname AS pubname,
+ N.nspname AS schemaname,
+ C.relname AS tablename
+ FROM pg_publication P, pg_class C
+ JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.oid IN (SELECT relid FROM pg_get_publication_tables(P.pubname));
+
CREATE VIEW pg_locks AS
SELECT * FROM pg_lock_status() AS L;
@@ -257,7 +294,7 @@ CREATE VIEW pg_prepared_statements AS
CREATE VIEW pg_seclabels AS
SELECT
l.objoid, l.classoid, l.objsubid,
- CASE WHEN rel.relkind = 'r' THEN 'table'::text
+ CASE WHEN rel.relkind IN ('r', 'p') THEN 'table'::text
WHEN rel.relkind = 'v' THEN 'view'::text
WHEN rel.relkind = 'm' THEN 'materialized view'::text
WHEN rel.relkind = 'S' THEN 'sequence'::text
@@ -378,6 +415,28 @@ WHERE
l.objsubid = 0
UNION ALL
SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'publication'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(p.pubname) AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_publication p ON l.classoid = p.tableoid AND l.objoid = p.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, 0::int4 AS objsubid,
+ 'subscription'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(s.subname) AS objname,
+ l.provider, l.label
+FROM
+ pg_shseclabel l
+ JOIN pg_subscription s ON l.classoid = s.tableoid AND l.objoid = s.oid
+UNION ALL
+SELECT
l.objoid, l.classoid, 0::int4 AS objsubid,
'database'::text AS objtype,
NULL::oid AS objnamespace,
@@ -427,6 +486,12 @@ CREATE VIEW pg_file_settings AS
REVOKE ALL on pg_file_settings FROM PUBLIC;
REVOKE EXECUTE ON FUNCTION pg_show_all_file_settings() FROM PUBLIC;
+CREATE VIEW pg_hba_file_rules AS
+ SELECT * FROM pg_hba_file_rules() AS A;
+
+REVOKE ALL on pg_hba_file_rules FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_hba_file_rules() FROM PUBLIC;
+
CREATE VIEW pg_timezone_abbrevs AS
SELECT * FROM pg_timezone_abbrevs();
@@ -641,10 +706,11 @@ CREATE VIEW pg_stat_activity AS
S.state,
S.backend_xid,
s.backend_xmin,
- S.query
- FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U
- WHERE S.datid = D.oid AND
- S.usesysid = U.oid;
+ S.query,
+ S.backend_type
+ FROM pg_stat_get_activity(NULL) AS S
+ LEFT JOIN pg_database AS D ON (S.datid = D.oid)
+ LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
CREATE VIEW pg_stat_replication AS
SELECT
@@ -658,16 +724,18 @@ CREATE VIEW pg_stat_replication AS
S.backend_start,
S.backend_xmin,
W.state,
- W.sent_location,
- W.write_location,
- W.flush_location,
- W.replay_location,
+ W.sent_lsn,
+ W.write_lsn,
+ W.flush_lsn,
+ W.replay_lsn,
+ W.write_lag,
+ W.flush_lag,
+ W.replay_lag,
W.sync_priority,
W.sync_state
- FROM pg_stat_get_activity(NULL) AS S, pg_authid U,
- pg_stat_get_wal_senders() AS W
- WHERE S.usesysid = U.oid AND
- S.pid = W.pid;
+ FROM pg_stat_get_activity(NULL) AS S
+ JOIN pg_stat_get_wal_senders() AS W ON (S.pid = W.pid)
+ LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
CREATE VIEW pg_stat_wal_receiver AS
SELECT
@@ -686,6 +754,21 @@ CREATE VIEW pg_stat_wal_receiver AS
FROM pg_stat_get_wal_receiver() s
WHERE s.pid IS NOT NULL;
+CREATE VIEW pg_stat_subscription AS
+ SELECT
+ su.oid AS subid,
+ su.subname,
+ st.pid,
+ st.relid,
+ st.received_lsn,
+ st.last_msg_send_time,
+ st.last_msg_receipt_time,
+ st.latest_end_lsn,
+ st.latest_end_time
+ FROM pg_subscription su
+ LEFT JOIN pg_stat_get_subscription(NULL) st
+ ON (st.subid = su.oid);
+
CREATE VIEW pg_stat_ssl AS
SELECT
S.pid,
@@ -704,6 +787,7 @@ CREATE VIEW pg_replication_slots AS
L.slot_type,
L.datoid,
D.datname AS database,
+ L.temporary,
L.active,
L.active_pid,
L.xmin,
@@ -813,7 +897,7 @@ CREATE VIEW pg_stat_progress_vacuum AS
S.param4 AS heap_blks_vacuumed, S.param5 AS index_vacuum_count,
S.param6 AS max_dead_tuples, S.param7 AS num_dead_tuples
FROM pg_stat_get_progress_info('VACUUM') AS S
- JOIN pg_database D ON S.datid = D.oid;
+ LEFT JOIN pg_database D ON S.datid = D.oid;
CREATE VIEW pg_user_mappings AS
SELECT
@@ -826,24 +910,29 @@ CREATE VIEW pg_user_mappings AS
ELSE
A.rolname
END AS usename,
- CASE WHEN pg_has_role(S.srvowner, 'USAGE') OR has_server_privilege(S.oid, 'USAGE') THEN
- U.umoptions
- ELSE
- NULL
- END AS umoptions
+ CASE WHEN (U.umuser <> 0 AND A.rolname = current_user)
+ OR (U.umuser = 0 AND pg_has_role(S.srvowner, 'USAGE'))
+ OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
+ THEN U.umoptions
+ ELSE NULL END AS umoptions
FROM pg_user_mapping U
- LEFT JOIN pg_authid A ON (A.oid = U.umuser) JOIN
- pg_foreign_server S ON (U.umserver = S.oid);
+ JOIN pg_foreign_server S ON (U.umserver = S.oid)
+ LEFT JOIN pg_authid A ON (A.oid = U.umuser);
REVOKE ALL on pg_user_mapping FROM public;
-
CREATE VIEW pg_replication_origin_status AS
SELECT *
FROM pg_show_replication_origin_status();
REVOKE ALL ON pg_replication_origin_status FROM public;
+-- All columns of pg_subscription except subconninfo are readable.
+REVOKE ALL ON pg_subscription FROM public;
+GRANT SELECT (subdbid, subname, subowner, subenabled, subslotname, subpublications)
+ ON pg_subscription TO public;
+
+
--
-- We have a few function definitions in here, too.
-- At some point there might be enough to justify breaking them out into
@@ -926,6 +1015,12 @@ CREATE OR REPLACE FUNCTION
RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup'
PARALLEL RESTRICTED;
+CREATE OR REPLACE FUNCTION pg_stop_backup (
+ exclusive boolean, wait_for_archive boolean DEFAULT true,
+ OUT lsn pg_lsn, OUT labelfile text, OUT spcmapfile text)
+ RETURNS SETOF record STRICT VOLATILE LANGUAGE internal as 'pg_stop_backup_v2'
+ PARALLEL RESTRICTED;
+
-- legacy definition for compatibility with 9.3
CREATE OR REPLACE FUNCTION
json_populate_record(base anyelement, from_json json, use_json_as_text boolean DEFAULT false)
@@ -938,7 +1033,7 @@ CREATE OR REPLACE FUNCTION
CREATE OR REPLACE FUNCTION pg_logical_slot_get_changes(
IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
- OUT location pg_lsn, OUT xid xid, OUT data text)
+ OUT lsn pg_lsn, OUT xid xid, OUT data text)
RETURNS SETOF RECORD
LANGUAGE INTERNAL
VOLATILE ROWS 1000 COST 1000
@@ -946,7 +1041,7 @@ AS 'pg_logical_slot_get_changes';
CREATE OR REPLACE FUNCTION pg_logical_slot_peek_changes(
IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
- OUT location pg_lsn, OUT xid xid, OUT data text)
+ OUT lsn pg_lsn, OUT xid xid, OUT data text)
RETURNS SETOF RECORD
LANGUAGE INTERNAL
VOLATILE ROWS 1000 COST 1000
@@ -954,7 +1049,7 @@ AS 'pg_logical_slot_peek_changes';
CREATE OR REPLACE FUNCTION pg_logical_slot_get_binary_changes(
IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
- OUT location pg_lsn, OUT xid xid, OUT data bytea)
+ OUT lsn pg_lsn, OUT xid xid, OUT data bytea)
RETURNS SETOF RECORD
LANGUAGE INTERNAL
VOLATILE ROWS 1000 COST 1000
@@ -962,7 +1057,7 @@ AS 'pg_logical_slot_get_binary_changes';
CREATE OR REPLACE FUNCTION pg_logical_slot_peek_binary_changes(
IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
- OUT location pg_lsn, OUT xid xid, OUT data bytea)
+ OUT lsn pg_lsn, OUT xid xid, OUT data bytea)
RETURNS SETOF RECORD
LANGUAGE INTERNAL
VOLATILE ROWS 1000 COST 1000
@@ -970,12 +1065,22 @@ AS 'pg_logical_slot_peek_binary_changes';
CREATE OR REPLACE FUNCTION pg_create_physical_replication_slot(
IN slot_name name, IN immediately_reserve boolean DEFAULT false,
- OUT slot_name name, OUT xlog_position pg_lsn)
+ IN temporary boolean DEFAULT false,
+ OUT slot_name name, OUT lsn pg_lsn)
RETURNS RECORD
LANGUAGE INTERNAL
STRICT VOLATILE
AS 'pg_create_physical_replication_slot';
+CREATE OR REPLACE FUNCTION pg_create_logical_replication_slot(
+ IN slot_name name, IN plugin name,
+ IN temporary boolean DEFAULT false,
+ OUT slot_name text, OUT lsn pg_lsn)
+RETURNS RECORD
+LANGUAGE INTERNAL
+STRICT VOLATILE
+AS 'pg_create_logical_replication_slot';
+
CREATE OR REPLACE FUNCTION
make_interval(years int4 DEFAULT 0, months int4 DEFAULT 0, weeks int4 DEFAULT 0,
days int4 DEFAULT 0, hours int4 DEFAULT 0, mins int4 DEFAULT 0,
@@ -1016,15 +1121,26 @@ AS 'jsonb_insert';
-- available to superuser / cluster owner, if they choose.
REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stop_backup() FROM public;
-REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean, boolean) FROM public;
REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public;
-REVOKE EXECUTE ON FUNCTION pg_switch_xlog() FROM public;
-REVOKE EXECUTE ON FUNCTION pg_xlog_replay_pause() FROM public;
-REVOKE EXECUTE ON FUNCTION pg_xlog_replay_resume() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_switch_wal() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_wal_replay_resume() FROM public;
REVOKE EXECUTE ON FUNCTION pg_rotate_logfile() FROM public;
REVOKE EXECUTE ON FUNCTION pg_reload_conf() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_current_logfile() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_current_logfile(text) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset() FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_shared(text) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_table_counters(oid) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_ls_logdir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public;
+GRANT EXECUTE ON FUNCTION pg_ls_logdir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor;
+
+GRANT pg_read_all_settings TO pg_monitor;
+GRANT pg_read_all_stats TO pg_monitor;
+GRANT pg_stat_scan_tables TO pg_monitor;
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 564e10e3a2..29756eb14e 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -4,7 +4,7 @@
* This file contains routines to support creation of toast tables
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -307,7 +307,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
indexInfo->ii_Expressions = NIL;
indexInfo->ii_ExpressionsState = NIL;
indexInfo->ii_Predicate = NIL;
- indexInfo->ii_PredicateState = NIL;
+ indexInfo->ii_PredicateState = NULL;
indexInfo->ii_ExclusionOps = NULL;
indexInfo->ii_ExclusionProcs = NULL;
indexInfo->ii_ExclusionStrats = NULL;
@@ -315,6 +315,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
indexInfo->ii_ReadyForInserts = true;
indexInfo->ii_Concurrent = false;
indexInfo->ii_BrokenHotChain = false;
+ indexInfo->ii_AmCache = NULL;
+ indexInfo->ii_Context = CurrentMemoryContext;
collationObjectId[0] = InvalidOid;
collationObjectId[1] = InvalidOid;
@@ -350,10 +352,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
if (!IsBootstrapProcessingMode())
{
/* normal case, use a transactional update */
- simple_heap_update(class_rel, &reltup->t_self, reltup);
-
- /* Keep catalog indexes current */
- CatalogUpdateIndexes(class_rel, reltup);
+ CatalogTupleUpdate(class_rel, &reltup->t_self, reltup);
}
else
{
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index 6b3742c0a0..4a6c99e090 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -17,9 +17,9 @@ OBJS = amcmds.o aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \
dbcommands.o define.o discard.o dropcmds.o \
event_trigger.o explain.o extension.o foreigncmds.o functioncmds.o \
indexcmds.o lockcmds.o matview.o operatorcmds.o opclasscmds.o \
- policy.o portalcmds.o prepare.o proclang.o \
- schemacmds.o seclabel.o sequence.o tablecmds.o tablespace.o trigger.o \
- tsearchcmds.o typecmds.o user.o vacuum.o vacuumlazy.o \
- variable.o view.o
+ policy.o portalcmds.o prepare.o proclang.o publicationcmds.o \
+ schemacmds.o seclabel.o sequence.o statscmds.o subscriptioncmds.o \
+ tablecmds.o tablespace.o trigger.o tsearchcmds.o typecmds.o user.o \
+ vacuum.o vacuumlazy.o variable.o view.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index d34c82c5ba..a84c61493f 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -4,7 +4,7 @@
*
* Routines for aggregate-manipulation commands
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,7 +22,6 @@
*/
#include "postgres.h"
-#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
@@ -52,8 +51,7 @@
* "parameters" is a list of DefElem representing the agg's definition clauses.
*/
ObjectAddress
-DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
- const char *queryString)
+DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle, List *parameters)
{
char *aggName;
Oid aggNamespace;
@@ -111,13 +109,13 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
aggKind = AGGKIND_ORDERED_SET;
else
numDirectArgs = 0;
- args = (List *) linitial(args);
+ args = linitial_node(List, args);
}
/* Examine aggregate's definition clauses */
foreach(pl, parameters)
{
- DefElem *defel = (DefElem *) lfirst(pl);
+ DefElem *defel = lfirst_node(DefElem, pl);
/*
* sfunc1, stype1, and initcond1 are accepted as obsolete spellings
@@ -287,10 +285,10 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
errmsg("basetype is redundant with aggregate input type specification")));
numArgs = list_length(args);
- interpret_function_parameter_list(args,
+ interpret_function_parameter_list(pstate,
+ args,
InvalidOid,
true, /* is an aggregate */
- queryString,
&parameterTypes,
&allParameterTypes,
&parameterModes,
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 1301bcb5e8..4d3fe8c745 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -3,7 +3,7 @@
* alter.c
* Drivers for generic alter commands
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -32,6 +32,8 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_subscription.h"
+#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
@@ -45,7 +47,9 @@
#include "commands/extension.h"
#include "commands/policy.h"
#include "commands/proclang.h"
+#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
+#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
@@ -88,6 +92,12 @@ report_name_conflict(Oid classId, const char *name)
case LanguageRelationId:
msgfmt = gettext_noop("language \"%s\" already exists");
break;
+ case PublicationRelationId:
+ msgfmt = gettext_noop("publication \"%s\" already exists");
+ break;
+ case SubscriptionRelationId:
+ msgfmt = gettext_noop("subscription \"%s\" already exists");
+ break;
default:
elog(ERROR, "unsupported object class %u", classId);
break;
@@ -111,6 +121,10 @@ report_namespace_conflict(Oid classId, const char *name, Oid nspOid)
Assert(OidIsValid(nspOid));
msgfmt = gettext_noop("conversion \"%s\" already exists in schema \"%s\"");
break;
+ case StatisticExtRelationId:
+ Assert(OidIsValid(nspOid));
+ msgfmt = gettext_noop("statistics object \"%s\" already exists in schema \"%s\"");
+ break;
case TSParserRelationId:
Assert(OidIsValid(nspOid));
msgfmt = gettext_noop("text search parser \"%s\" already exists in schema \"%s\"");
@@ -254,6 +268,12 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
IsThereOpFamilyInNamespace(new_name, opf->opfmethod,
opf->opfnamespace);
}
+ else if (classId == SubscriptionRelationId)
+ {
+ if (SearchSysCacheExists2(SUBSCRIPTIONNAME, MyDatabaseId,
+ CStringGetDatum(new_name)))
+ report_name_conflict(classId, new_name);
+ }
else if (nameCacheId >= 0)
{
if (OidIsValid(namespaceId))
@@ -282,8 +302,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
values, nulls, replaces);
/* Perform actual update */
- simple_heap_update(rel, &oldtup->t_self, newtup);
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &oldtup->t_self, newtup);
InvokeObjectPostAlterHook(classId, objectId, 0);
@@ -359,17 +378,20 @@ ExecRenameStmt(RenameStmt *stmt)
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
case OBJECT_LANGUAGE:
+ case OBJECT_STATISTIC_EXT:
case OBJECT_TSCONFIGURATION:
case OBJECT_TSDICTIONARY:
case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SUBSCRIPTION:
{
ObjectAddress address;
Relation catalog;
Relation relation;
address = get_object_address(stmt->renameType,
- stmt->object, stmt->objarg,
+ stmt->object,
&relation,
AccessExclusiveLock, false);
Assert(relation == NULL);
@@ -405,8 +427,8 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre
Relation rel;
address =
- get_object_address_rv(stmt->objectType, stmt->relation, stmt->objname,
- stmt->objargs, &rel, AccessExclusiveLock, false);
+ get_object_address_rv(stmt->objectType, stmt->relation, (List *) stmt->object,
+ &rel, AccessExclusiveLock, false);
/*
* If a relation was involved, it would have been opened and locked. We
@@ -415,8 +437,8 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre
if (rel)
heap_close(rel, NoLock);
- refAddr = get_object_address(OBJECT_EXTENSION, list_make1(stmt->extname),
- NULL, &rel, AccessExclusiveLock, false);
+ refAddr = get_object_address(OBJECT_EXTENSION, (Node *) stmt->extname,
+ &rel, AccessExclusiveLock, false);
Assert(rel == NULL);
if (refAddress)
*refAddress = refAddr;
@@ -445,7 +467,7 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
switch (stmt->objectType)
{
case OBJECT_EXTENSION:
- address = AlterExtensionNamespace(stmt->object, stmt->newschema,
+ address = AlterExtensionNamespace(strVal((Value *) stmt->object), stmt->newschema,
oldSchemaAddr ? &oldNspOid : NULL);
break;
@@ -460,7 +482,7 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
case OBJECT_DOMAIN:
case OBJECT_TYPE:
- address = AlterTypeNamespace(stmt->object, stmt->newschema,
+ address = AlterTypeNamespace(castNode(List, stmt->object), stmt->newschema,
stmt->objectType,
oldSchemaAddr ? &oldNspOid : NULL);
break;
@@ -473,6 +495,7 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
case OBJECT_OPERATOR:
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
+ case OBJECT_STATISTIC_EXT:
case OBJECT_TSCONFIGURATION:
case OBJECT_TSDICTIONARY:
case OBJECT_TSPARSER:
@@ -485,7 +508,6 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
address = get_object_address(stmt->objectType,
stmt->object,
- stmt->objarg,
&relation,
AccessExclusiveLock,
false);
@@ -521,7 +543,8 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
* so it only needs to cover object types that can be members of an
* extension, and it doesn't have to deal with certain special cases
* such as not wanting to process array types --- those should never
- * be direct members of an extension anyway.
+ * be direct members of an extension anyway. Nonetheless, we insist
+ * on listing all OCLASS types in the switch.
*
* Returns the OID of the object's previous namespace, or InvalidOid if
* object doesn't have a schema.
@@ -556,12 +579,13 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
oldNspOid = AlterTypeNamespace_oid(objid, nspOid, objsMoved);
break;
+ case OCLASS_PROC:
case OCLASS_COLLATION:
case OCLASS_CONVERSION:
case OCLASS_OPERATOR:
case OCLASS_OPCLASS:
case OCLASS_OPFAMILY:
- case OCLASS_PROC:
+ case OCLASS_STATISTIC_EXT:
case OCLASS_TSPARSER:
case OCLASS_TSDICT:
case OCLASS_TSTEMPLATE:
@@ -578,8 +602,38 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
}
break;
- default:
+ case OCLASS_CAST:
+ case OCLASS_CONSTRAINT:
+ case OCLASS_DEFAULT:
+ case OCLASS_LANGUAGE:
+ case OCLASS_LARGEOBJECT:
+ case OCLASS_AM:
+ case OCLASS_AMOP:
+ case OCLASS_AMPROC:
+ case OCLASS_REWRITE:
+ case OCLASS_TRIGGER:
+ case OCLASS_SCHEMA:
+ case OCLASS_ROLE:
+ case OCLASS_DATABASE:
+ case OCLASS_TBLSPACE:
+ case OCLASS_FDW:
+ case OCLASS_FOREIGN_SERVER:
+ case OCLASS_USER_MAPPING:
+ case OCLASS_DEFACL:
+ case OCLASS_EXTENSION:
+ case OCLASS_EVENT_TRIGGER:
+ case OCLASS_POLICY:
+ case OCLASS_PUBLICATION:
+ case OCLASS_PUBLICATION_REL:
+ case OCLASS_SUBSCRIPTION:
+ case OCLASS_TRANSFORM:
+ /* ignore object types that don't have schema-qualified names */
break;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
}
return oldNspOid;
@@ -720,8 +774,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
values, nulls, replaces);
/* Perform actual update */
- simple_heap_update(rel, &tup->t_self, newtup);
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &tup->t_self, newtup);
/* Release memory */
pfree(values);
@@ -749,26 +802,34 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
switch (stmt->objectType)
{
case OBJECT_DATABASE:
- return AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
+ return AlterDatabaseOwner(strVal((Value *) stmt->object), newowner);
case OBJECT_SCHEMA:
- return AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
+ return AlterSchemaOwner(strVal((Value *) stmt->object), newowner);
case OBJECT_TYPE:
case OBJECT_DOMAIN: /* same as TYPE */
- return AlterTypeOwner(stmt->object, newowner, stmt->objectType);
+ return AlterTypeOwner(castNode(List, stmt->object), newowner, stmt->objectType);
break;
case OBJECT_FDW:
- return AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
+ return AlterForeignDataWrapperOwner(strVal((Value *) stmt->object),
newowner);
case OBJECT_FOREIGN_SERVER:
- return AlterForeignServerOwner(strVal(linitial(stmt->object)),
+ return AlterForeignServerOwner(strVal((Value *) stmt->object),
newowner);
case OBJECT_EVENT_TRIGGER:
- return AlterEventTriggerOwner(strVal(linitial(stmt->object)),
+ return AlterEventTriggerOwner(strVal((Value *) stmt->object),
+ newowner);
+
+ case OBJECT_PUBLICATION:
+ return AlterPublicationOwner(strVal((Value *) stmt->object),
+ newowner);
+
+ case OBJECT_SUBSCRIPTION:
+ return AlterSubscriptionOwner(strVal((Value *) stmt->object),
newowner);
/* Generic cases */
@@ -781,6 +842,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
case OBJECT_OPERATOR:
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
+ case OBJECT_STATISTIC_EXT:
case OBJECT_TABLESPACE:
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION:
@@ -792,7 +854,6 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
address = get_object_address(stmt->objectType,
stmt->object,
- stmt->objarg,
&relation,
AccessExclusiveLock,
false);
@@ -945,8 +1006,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
values, nulls, replaces);
/* Perform actual update */
- simple_heap_update(rel, &newtup->t_self, newtup);
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &newtup->t_self, newtup);
/* Update owner dependency reference */
if (classId == LargeObjectMetadataRelationId)
diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c
index 9ac930ea8b..7e0a9aa0fd 100644
--- a/src/backend/commands/amcmds.c
+++ b/src/backend/commands/amcmds.c
@@ -3,7 +3,7 @@
* amcmds.c
* Routines for SQL commands that manipulate access methods.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -34,7 +34,7 @@ static const char *get_am_type_string(char amtype);
/*
- * CreateAcessMethod
+ * CreateAccessMethod
* Registers a new access method.
*/
ObjectAddress
@@ -87,8 +87,7 @@ CreateAccessMethod(CreateAmStmt *stmt)
tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
- amoid = simple_heap_insert(rel, tup);
- CatalogUpdateIndexes(rel, tup);
+ amoid = CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
myself.classId = AccessMethodRelationId;
@@ -129,7 +128,7 @@ RemoveAccessMethodById(Oid amOid)
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for access method %u", amOid);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 14aad4fd7c..67e4146c6c 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -4,7 +4,7 @@
* the Postgres statistics generator
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -18,6 +18,7 @@
#include <math.h>
#include "access/multixact.h"
+#include "access/sysattr.h"
#include "access/transam.h"
#include "access/tupconvert.h"
#include "access/tuptoaster.h"
@@ -29,6 +30,7 @@
#include "catalog/pg_collation.h"
#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_namespace.h"
+#include "catalog/pg_statistic_ext.h"
#include "commands/dbcommands.h"
#include "commands/tablecmds.h"
#include "commands/vacuum.h"
@@ -40,13 +42,17 @@
#include "parser/parse_relation.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
+#include "statistics/extended_stats_internal.h"
+#include "statistics/statistics.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
#include "utils/attoptcache.h"
+#include "utils/builtins.h"
#include "utils/datum.h"
+#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
@@ -246,6 +252,12 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
return;
}
}
+ else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ /*
+ * For partitioned tables, we want to do the recursive ANALYZE below.
+ */
+ }
else
{
/* No need for a WARNING if we already complained during VACUUM */
@@ -265,10 +277,12 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
LWLockRelease(ProcArrayLock);
/*
- * Do the normal non-recursive ANALYZE.
+ * Do the normal non-recursive ANALYZE. We can skip this for partitioned
+ * tables, which don't contain any rows.
*/
- do_analyze_rel(onerel, options, params, va_cols, acquirefunc, relpages,
- false, in_outer_xact, elevel);
+ if (onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ do_analyze_rel(onerel, options, params, va_cols, acquirefunc,
+ relpages, false, in_outer_xact, elevel);
/*
* If there are child tables, do recursive ANALYZE.
@@ -345,9 +359,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
*/
anl_context = AllocSetContextCreate(CurrentMemoryContext,
"Analyze",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
caller_context = MemoryContextSwitchTo(anl_context);
/*
@@ -541,9 +553,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
col_context = AllocSetContextCreate(anl_context,
"Analyze Column",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
old_context = MemoryContextSwitchTo(col_context);
for (i = 0; i < attr_cnt; i++)
@@ -599,6 +609,10 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
update_attstats(RelationGetRelid(Irel[ind]), false,
thisdata->attr_cnt, thisdata->vacattrstats);
}
+
+ /* Build extended statistics (if there are any). */
+ BuildRelationExtStatistics(onerel, totalrows, numrows, rows, attr_cnt,
+ vacattrstats);
}
/*
@@ -731,9 +745,7 @@ compute_index_stats(Relation onerel, double totalrows,
ind_context = AllocSetContextCreate(anl_context,
"Analyze Index",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
old_context = MemoryContextSwitchTo(ind_context);
for (ind = 0; ind < nindexes; ind++)
@@ -744,7 +756,7 @@ compute_index_stats(Relation onerel, double totalrows,
TupleTableSlot *slot;
EState *estate;
ExprContext *econtext;
- List *predicate;
+ ExprState *predicate;
Datum *exprvals;
bool *exprnulls;
int numindexrows,
@@ -770,9 +782,7 @@ compute_index_stats(Relation onerel, double totalrows,
econtext->ecxt_scantuple = slot;
/* Set up execution state for predicate. */
- predicate = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
- estate);
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
/* Compute and save index expression values */
exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
@@ -795,9 +805,9 @@ compute_index_stats(Relation onerel, double totalrows,
ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
/* If index is partial, check predicate */
- if (predicate != NIL)
+ if (predicate != NULL)
{
- if (!ExecQual(predicate, econtext, false))
+ if (!ExecQual(predicate, econtext))
continue;
}
numindexrows++;
@@ -1041,7 +1051,7 @@ acquire_sample_rows(Relation onerel, int elevel,
totalblocks = RelationGetNumberOfBlocks(onerel);
/* Need a cutoff xmin for HeapTupleSatisfiesVacuum */
- OldestXmin = GetOldestXmin(onerel, true);
+ OldestXmin = GetOldestXmin(onerel, PROCARRAY_FLAGS_VACUUM);
/* Prepare for sampling block numbers */
BlockSampler_Init(&bs, totalblocks, targrows, random());
@@ -1308,6 +1318,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
nrels,
i;
ListCell *lc;
+ bool has_child;
/*
* Find all members of inheritance set. We only need AccessShareLock on
@@ -1345,6 +1356,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
relblocks = (double *) palloc(list_length(tableOIDs) * sizeof(double));
totalblocks = 0;
nrels = 0;
+ has_child = false;
foreach(lc, tableOIDs)
{
Oid childOID = lfirst_oid(lc);
@@ -1398,13 +1410,20 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
}
else
{
- /* ignore, but release the lock on it */
- Assert(childrel != onerel);
- heap_close(childrel, AccessShareLock);
+ /*
+ * ignore, but release the lock on it. don't try to unlock the
+ * passed-in relation
+ */
+ Assert(childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+ if (childrel != onerel)
+ heap_close(childrel, AccessShareLock);
+ else
+ heap_close(childrel, NoLock);
continue;
}
/* OK, we'll process this child */
+ has_child = true;
rels[nrels] = childrel;
acquirefuncs[nrels] = acquirefunc;
relblocks[nrels] = (double) relpages;
@@ -1413,9 +1432,10 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
}
/*
- * If we don't have at least two tables to consider, fail.
+ * If we don't have at least one child table to consider, fail. If the
+ * relation is a partitioned table, it's not counted as a child table.
*/
- if (nrels < 2)
+ if (!has_child)
{
ereport(elevel,
(errmsg("skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables",
@@ -1636,18 +1656,15 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
nulls,
replaces);
ReleaseSysCache(oldtup);
- simple_heap_update(sd, &stup->t_self, stup);
+ CatalogTupleUpdate(sd, &stup->t_self, stup);
}
else
{
/* No, insert new tuple */
stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
- simple_heap_insert(sd, stup);
+ CatalogTupleInsert(sd, stup);
}
- /* update indexes too */
- CatalogUpdateIndexes(sd, stup);
-
heap_freetuple(stup);
}
@@ -1717,19 +1734,6 @@ ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull)
*/
typedef struct
{
- Oid eqopr; /* '=' operator for datatype, if any */
- Oid eqfunc; /* and associated function */
- Oid ltopr; /* '<' operator for datatype, if any */
-} StdAnalyzeData;
-
-typedef struct
-{
- Datum value; /* a data value */
- int tupno; /* position index for tuple it came from */
-} ScalarItem;
-
-typedef struct
-{
int count; /* # of duplicates */
int first; /* values[] index of first occurrence */
} ScalarMCVItem;
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 716f1c3318..87b215d8d3 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -3,7 +3,7 @@
* async.c
* Asynchronous notification: NOTIFY, LISTEN, UNLISTEN
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -1636,7 +1636,7 @@ AtSubCommit_Notify(void)
List *parentPendingActions;
List *parentPendingNotifies;
- parentPendingActions = (List *) linitial(upperPendingActions);
+ parentPendingActions = linitial_node(List, upperPendingActions);
upperPendingActions = list_delete_first(upperPendingActions);
Assert(list_length(upperPendingActions) ==
@@ -1647,7 +1647,7 @@ AtSubCommit_Notify(void)
*/
pendingActions = list_concat(parentPendingActions, pendingActions);
- parentPendingNotifies = (List *) linitial(upperPendingNotifies);
+ parentPendingNotifies = linitial_node(List, upperPendingNotifies);
upperPendingNotifies = list_delete_first(upperPendingNotifies);
Assert(list_length(upperPendingNotifies) ==
@@ -1679,13 +1679,13 @@ AtSubAbort_Notify(void)
*/
while (list_length(upperPendingActions) > my_level - 2)
{
- pendingActions = (List *) linitial(upperPendingActions);
+ pendingActions = linitial_node(List, upperPendingActions);
upperPendingActions = list_delete_first(upperPendingActions);
}
while (list_length(upperPendingNotifies) > my_level - 2)
{
- pendingNotifies = (List *) linitial(upperPendingNotifies);
+ pendingNotifies = linitial_node(List, upperPendingNotifies);
upperPendingNotifies = list_delete_first(upperPendingNotifies);
}
}
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index ca59799248..9a08a07319 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -6,7 +6,7 @@
* There is hardly anything left of Paul Brown's original implementation...
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
*
@@ -205,9 +205,7 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
*/
cluster_context = AllocSetContextCreate(PortalContext,
"Cluster",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* Build the list of relations to cluster. Note that this lives in
@@ -526,8 +524,7 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
if (indexForm->indisclustered)
{
indexForm->indisclustered = false;
- simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
- CatalogUpdateIndexes(pg_index, indexTuple);
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
}
else if (thisIndexOid == indexOid)
{
@@ -535,8 +532,7 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
if (!IndexIsValid(indexForm))
elog(ERROR, "cannot cluster on invalid index %u", indexOid);
indexForm->indisclustered = true;
- simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
- CatalogUpdateIndexes(pg_index, indexTuple);
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
}
InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
@@ -562,6 +558,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose)
Oid tableOid = RelationGetRelid(OldHeap);
Oid tableSpace = OldHeap->rd_rel->reltablespace;
Oid OIDNewHeap;
+ char relpersistence;
bool is_system_catalog;
bool swap_toast_by_content;
TransactionId frozenXid;
@@ -571,7 +568,8 @@ rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose)
if (OidIsValid(indexOid))
mark_index_clustered(OldHeap, indexOid, true);
- /* Remember if it's a system catalog */
+ /* Remember info about rel before closing OldHeap */
+ relpersistence = OldHeap->rd_rel->relpersistence;
is_system_catalog = IsSystemRelation(OldHeap);
/* Close relcache entry, but keep lock until transaction commit */
@@ -579,7 +577,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose)
/* Create the transient table that will receive the re-ordered data */
OIDNewHeap = make_new_heap(tableOid, tableSpace,
- OldHeap->rd_rel->relpersistence,
+ relpersistence,
AccessExclusiveLock);
/* Copy the heap data into the new table in the desired order */
@@ -593,7 +591,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose)
finish_heap_swap(tableOid, OIDNewHeap, is_system_catalog,
swap_toast_by_content, false, true,
frozenXid, cutoffMulti,
- OldHeap->rd_rel->relpersistence);
+ relpersistence);
}
@@ -1060,11 +1058,10 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
for (;;)
{
HeapTuple tuple;
- bool shouldfree;
CHECK_FOR_INTERRUPTS();
- tuple = tuplesort_getheaptuple(tuplesort, true, &shouldfree);
+ tuple = tuplesort_getheaptuple(tuplesort, true);
if (tuple == NULL)
break;
@@ -1072,9 +1069,6 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
oldTupDesc, newTupDesc,
values, isnull,
NewHeap->rd_rel->relhasoids, rwstate);
-
- if (shouldfree)
- heap_freetuple(tuple);
}
tuplesort_end(tuplesort);
@@ -1150,7 +1144,6 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
relfilenode2;
Oid swaptemp;
char swptmpchr;
- CatalogIndexState indstate;
/* We need writable copies of both pg_class tuples. */
relRelation = heap_open(RelationRelationId, RowExclusiveLock);
@@ -1301,13 +1294,13 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
*/
if (!target_is_pg_class)
{
- simple_heap_update(relRelation, &reltup1->t_self, reltup1);
- simple_heap_update(relRelation, &reltup2->t_self, reltup2);
+ CatalogIndexState indstate;
- /* Keep system catalogs current */
indstate = CatalogOpenIndexes(relRelation);
- CatalogIndexInsert(indstate, reltup1);
- CatalogIndexInsert(indstate, reltup2);
+ CatalogTupleUpdateWithInfo(relRelation, &reltup1->t_self, reltup1,
+ indstate);
+ CatalogTupleUpdateWithInfo(relRelation, &reltup2->t_self, reltup2,
+ indstate);
CatalogCloseIndexes(indstate);
}
else
@@ -1572,8 +1565,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
relform->relfrozenxid = frozenXid;
relform->relminmxid = cutoffMulti;
- simple_heap_update(relRelation, &reltup->t_self, reltup);
- CatalogUpdateIndexes(relRelation, reltup);
+ CatalogTupleUpdate(relRelation, &reltup->t_self, reltup);
heap_close(relRelation, RowExclusiveLock);
}
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index e4ebb654a6..110fb7ef65 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -3,7 +3,7 @@
* collationcmds.c
* collation-related commands support code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -20,10 +20,12 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_collation_fn.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
+#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "mb/pg_wchar.h"
@@ -34,11 +36,12 @@
#include "utils/rel.h"
#include "utils/syscache.h"
+
/*
* CREATE COLLATION
*/
ObjectAddress
-DefineCollation(List *names, List *parameters)
+DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
{
char *collName;
Oid collNamespace;
@@ -48,8 +51,14 @@ DefineCollation(List *names, List *parameters)
DefElem *localeEl = NULL;
DefElem *lccollateEl = NULL;
DefElem *lcctypeEl = NULL;
+ DefElem *providerEl = NULL;
+ DefElem *versionEl = NULL;
char *collcollate = NULL;
char *collctype = NULL;
+ char *collproviderstr = NULL;
+ int collencoding;
+ char collprovider = 0;
+ char *collversion = NULL;
Oid newoid;
ObjectAddress address;
@@ -62,7 +71,7 @@ DefineCollation(List *names, List *parameters)
foreach(pl, parameters)
{
- DefElem *defel = (DefElem *) lfirst(pl);
+ DefElem *defel = lfirst_node(DefElem, pl);
DefElem **defelp;
if (pg_strcasecmp(defel->defname, "from") == 0)
@@ -73,12 +82,17 @@ DefineCollation(List *names, List *parameters)
defelp = &lccollateEl;
else if (pg_strcasecmp(defel->defname, "lc_ctype") == 0)
defelp = &lcctypeEl;
+ else if (pg_strcasecmp(defel->defname, "provider") == 0)
+ defelp = &providerEl;
+ else if (pg_strcasecmp(defel->defname, "version") == 0)
+ defelp = &versionEl;
else
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("collation attribute \"%s\" not recognized",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
break;
}
@@ -103,6 +117,7 @@ DefineCollation(List *names, List *parameters)
collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
+ collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
ReleaseSysCache(tp);
}
@@ -119,6 +134,27 @@ DefineCollation(List *names, List *parameters)
if (lcctypeEl)
collctype = defGetString(lcctypeEl);
+ if (providerEl)
+ collproviderstr = defGetString(providerEl);
+
+ if (versionEl)
+ collversion = defGetString(versionEl);
+
+ if (collproviderstr)
+ {
+ if (pg_strcasecmp(collproviderstr, "icu") == 0)
+ collprovider = COLLPROVIDER_ICU;
+ else if (pg_strcasecmp(collproviderstr, "libc") == 0)
+ collprovider = COLLPROVIDER_LIBC;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("unrecognized collation provider: %s",
+ collproviderstr)));
+ }
+ else if (!fromEl)
+ collprovider = COLLPROVIDER_LIBC;
+
if (!collcollate)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -129,14 +165,29 @@ DefineCollation(List *names, List *parameters)
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("parameter \"lc_ctype\" must be specified")));
- check_encoding_locale_matches(GetDatabaseEncoding(), collcollate, collctype);
+ if (collprovider == COLLPROVIDER_ICU)
+ collencoding = -1;
+ else
+ {
+ collencoding = GetDatabaseEncoding();
+ check_encoding_locale_matches(collencoding, collcollate, collctype);
+ }
+
+ if (!collversion)
+ collversion = get_collation_actual_version(collprovider, collcollate);
newoid = CollationCreate(collName,
collNamespace,
GetUserId(),
- GetDatabaseEncoding(),
+ collprovider,
+ collencoding,
collcollate,
- collctype);
+ collctype,
+ collversion,
+ if_not_exists);
+
+ if (!OidIsValid(newoid))
+ return InvalidObjectAddress;
ObjectAddressSet(address, CollationRelationId, newoid);
@@ -177,3 +228,390 @@ IsThereCollationInNamespace(const char *collname, Oid nspOid)
errmsg("collation \"%s\" already exists in schema \"%s\"",
collname, get_namespace_name(nspOid))));
}
+
+/*
+ * ALTER COLLATION
+ */
+ObjectAddress
+AlterCollation(AlterCollationStmt *stmt)
+{
+ Relation rel;
+ Oid collOid;
+ HeapTuple tup;
+ Form_pg_collation collForm;
+ Datum collversion;
+ bool isnull;
+ char *oldversion;
+ char *newversion;
+ ObjectAddress address;
+
+ rel = heap_open(CollationRelationId, RowExclusiveLock);
+ collOid = get_collation_oid(stmt->collname, false);
+
+ if (!pg_collation_ownercheck(collOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
+ NameListToString(stmt->collname));
+
+ tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for collation %u", collOid);
+
+ collForm = (Form_pg_collation) GETSTRUCT(tup);
+ collversion = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion,
+ &isnull);
+ oldversion = isnull ? NULL : TextDatumGetCString(collversion);
+
+ newversion = get_collation_actual_version(collForm->collprovider, NameStr(collForm->collcollate));
+
+ /* cannot change from NULL to non-NULL or vice versa */
+ if ((!oldversion && newversion) || (oldversion && !newversion))
+ elog(ERROR, "invalid collation version change");
+ else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
+ {
+ bool nulls[Natts_pg_collation];
+ bool replaces[Natts_pg_collation];
+ Datum values[Natts_pg_collation];
+
+ ereport(NOTICE,
+ (errmsg("changing version from %s to %s",
+ oldversion, newversion)));
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
+ replaces[Anum_pg_collation_collversion - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel),
+ values, nulls, replaces);
+ }
+ else
+ ereport(NOTICE,
+ (errmsg("version has not changed")));
+
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ InvokeObjectPostAlterHook(CollationRelationId, collOid, 0);
+
+ ObjectAddressSet(address, CollationRelationId, collOid);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+
+ return address;
+}
+
+
+Datum
+pg_collation_actual_version(PG_FUNCTION_ARGS)
+{
+ Oid collid = PG_GETARG_OID(0);
+ HeapTuple tp;
+ char *collcollate;
+ char collprovider;
+ char *version;
+
+ tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
+ if (!HeapTupleIsValid(tp))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("collation with OID %u does not exist", collid)));
+
+ collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
+ collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
+
+ ReleaseSysCache(tp);
+
+ version = get_collation_actual_version(collprovider, collcollate);
+
+ if (version)
+ PG_RETURN_TEXT_P(cstring_to_text(version));
+ else
+ PG_RETURN_NULL();
+}
+
+
+/*
+ * "Normalize" a libc locale name, stripping off encoding tags such as
+ * ".utf8" (e.g., "en_US.utf8" -> "en_US", but "br_FR.iso885915@euro"
+ * -> "br_FR@euro"). Return true if a new, different name was
+ * generated.
+ */
+pg_attribute_unused()
+static bool
+normalize_libc_locale_name(char *new, const char *old)
+{
+ char *n = new;
+ const char *o = old;
+ bool changed = false;
+
+ while (*o)
+ {
+ if (*o == '.')
+ {
+ /* skip over encoding tag such as ".utf8" or ".UTF-8" */
+ o++;
+ while ((*o >= 'A' && *o <= 'Z')
+ || (*o >= 'a' && *o <= 'z')
+ || (*o >= '0' && *o <= '9')
+ || (*o == '-'))
+ o++;
+ changed = true;
+ }
+ else
+ *n++ = *o++;
+ }
+ *n = '\0';
+
+ return changed;
+}
+
+
+#ifdef USE_ICU
+static char *
+get_icu_language_tag(const char *localename)
+{
+ char buf[ULOC_FULLNAME_CAPACITY];
+ UErrorCode status;
+
+ status = U_ZERO_ERROR;
+ uloc_toLanguageTag(localename, buf, sizeof(buf), TRUE, &status);
+ if (U_FAILURE(status))
+ ereport(ERROR,
+ (errmsg("could not convert locale name \"%s\" to language tag: %s",
+ localename, u_errorName(status))));
+
+ return pstrdup(buf);
+}
+
+
+static char *
+get_icu_locale_comment(const char *localename)
+{
+ UErrorCode status;
+ UChar displayname[128];
+ int32 len_uchar;
+ char *result;
+
+ status = U_ZERO_ERROR;
+ len_uchar = uloc_getDisplayName(localename, "en", &displayname[0], sizeof(displayname), &status);
+ if (U_FAILURE(status))
+ ereport(ERROR,
+ (errmsg("could get display name for locale \"%s\": %s",
+ localename, u_errorName(status))));
+
+ icu_from_uchar(&result, displayname, len_uchar);
+
+ return result;
+}
+#endif /* USE_ICU */
+
+
+Datum
+pg_import_system_collations(PG_FUNCTION_ARGS)
+{
+#if defined(HAVE_LOCALE_T) && !defined(WIN32)
+ bool if_not_exists = PG_GETARG_BOOL(0);
+ Oid nspid = PG_GETARG_OID(1);
+
+ FILE *locale_a_handle;
+ char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
+ int count = 0;
+ List *aliaslist = NIL;
+ List *localelist = NIL;
+ List *enclist = NIL;
+ ListCell *lca,
+ *lcl,
+ *lce;
+#endif
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to import system collations"))));
+
+#if defined(HAVE_LOCALE_T) && !defined(WIN32)
+ locale_a_handle = OpenPipeStream("locale -a", "r");
+ if (locale_a_handle == NULL)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not execute command \"%s\": %m",
+ "locale -a")));
+
+ while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
+ {
+ int i;
+ size_t len;
+ int enc;
+ bool skip;
+ char alias[NAMEDATALEN];
+
+ len = strlen(localebuf);
+
+ if (len == 0 || localebuf[len - 1] != '\n')
+ {
+ elog(DEBUG1, "locale name too long, skipped: \"%s\"", localebuf);
+ continue;
+ }
+ localebuf[len - 1] = '\0';
+
+ /*
+ * Some systems have locale names that don't consist entirely of ASCII
+ * letters (such as "bokm&aring;l" or "fran&ccedil;ais"). This is
+ * pretty silly, since we need the locale itself to interpret the
+ * non-ASCII characters. We can't do much with those, so we filter
+ * them out.
+ */
+ skip = false;
+ for (i = 0; i < len; i++)
+ {
+ if (IS_HIGHBIT_SET(localebuf[i]))
+ {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ {
+ elog(DEBUG1, "locale name has non-ASCII characters, skipped: \"%s\"", localebuf);
+ continue;
+ }
+
+ enc = pg_get_encoding_from_locale(localebuf, false);
+ if (enc < 0)
+ {
+ /* error message printed by pg_get_encoding_from_locale() */
+ continue;
+ }
+ if (!PG_VALID_BE_ENCODING(enc))
+ continue; /* ignore locales for client-only encodings */
+ if (enc == PG_SQL_ASCII)
+ continue; /* C/POSIX are already in the catalog */
+
+ count++;
+
+ CollationCreate(localebuf, nspid, GetUserId(), COLLPROVIDER_LIBC, enc,
+ localebuf, localebuf,
+ get_collation_actual_version(COLLPROVIDER_LIBC, localebuf),
+ if_not_exists);
+
+ CommandCounterIncrement();
+
+ /*
+ * Generate aliases such as "en_US" in addition to "en_US.utf8" for
+ * ease of use. Note that collation names are unique per encoding
+ * only, so this doesn't clash with "en_US" for LATIN1, say.
+ *
+ * However, it might conflict with a name we'll see later in the
+ * "locale -a" output. So save up the aliases and try to add them
+ * after we've read all the output.
+ */
+ if (normalize_libc_locale_name(alias, localebuf))
+ {
+ aliaslist = lappend(aliaslist, pstrdup(alias));
+ localelist = lappend(localelist, pstrdup(localebuf));
+ enclist = lappend_int(enclist, enc);
+ }
+ }
+
+ ClosePipeStream(locale_a_handle);
+
+ /* Now try to add any aliases we created */
+ forthree(lca, aliaslist, lcl, localelist, lce, enclist)
+ {
+ char *alias = (char *) lfirst(lca);
+ char *locale = (char *) lfirst(lcl);
+ int enc = lfirst_int(lce);
+
+ CollationCreate(alias, nspid, GetUserId(), COLLPROVIDER_LIBC, enc,
+ locale, locale,
+ get_collation_actual_version(COLLPROVIDER_LIBC, locale),
+ true);
+ CommandCounterIncrement();
+ }
+
+ if (count == 0)
+ ereport(WARNING,
+ (errmsg("no usable system locales were found")));
+#endif /* not HAVE_LOCALE_T && not WIN32 */
+
+#ifdef USE_ICU
+ if (!is_encoding_supported_by_icu(GetDatabaseEncoding()))
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("encoding \"%s\" not supported by ICU",
+ pg_encoding_to_char(GetDatabaseEncoding()))));
+ }
+ else
+ {
+ int i;
+
+ /*
+ * Start the loop at -1 to sneak in the root locale without too much
+ * code duplication.
+ */
+ for (i = -1; i < ucol_countAvailable(); i++)
+ {
+ const char *name;
+ char *langtag;
+ const char *collcollate;
+ UEnumeration *en;
+ UErrorCode status;
+ const char *val;
+ Oid collid;
+
+ if (i == -1)
+ name = ""; /* ICU root locale */
+ else
+ name = ucol_getAvailable(i);
+
+ langtag = get_icu_language_tag(name);
+ collcollate = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag : name;
+ collid = CollationCreate(psprintf("%s-x-icu", langtag),
+ nspid, GetUserId(), COLLPROVIDER_ICU, -1,
+ collcollate, collcollate,
+ get_collation_actual_version(COLLPROVIDER_ICU, collcollate),
+ if_not_exists);
+
+ CreateComments(collid, CollationRelationId, 0,
+ get_icu_locale_comment(name));
+
+ /*
+ * Add keyword variants
+ */
+ status = U_ZERO_ERROR;
+ en = ucol_getKeywordValuesForLocale("collation", name, TRUE, &status);
+ if (U_FAILURE(status))
+ ereport(ERROR,
+ (errmsg("could not get keyword values for locale \"%s\": %s",
+ name, u_errorName(status))));
+
+ status = U_ZERO_ERROR;
+ uenum_reset(en, &status);
+ while ((val = uenum_next(en, NULL, &status)))
+ {
+ char *localeid = psprintf("%s@collation=%s", name, val);
+
+ langtag = get_icu_language_tag(localeid);
+ collcollate = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag : localeid;
+ collid = CollationCreate(psprintf("%s-x-icu", langtag),
+ nspid, GetUserId(), COLLPROVIDER_ICU, -1,
+ collcollate, collcollate,
+ get_collation_actual_version(COLLPROVIDER_ICU, collcollate),
+ if_not_exists);
+ CreateComments(collid, CollationRelationId, 0,
+ get_icu_locale_comment(localeid));
+ }
+ if (U_FAILURE(status))
+ ereport(ERROR,
+ (errmsg("could not get keyword values for locale \"%s\": %s",
+ name, u_errorName(status))));
+ uenum_close(en);
+ }
+ }
+#endif
+
+ PG_RETURN_VOID();
+}
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index f45da2d914..236b582f7c 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -5,7 +5,7 @@
* PostgreSQL object comments utility code.
*
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
- * Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Copyright (c) 1996-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/commands/comment.c
@@ -49,12 +49,11 @@ CommentObject(CommentStmt *stmt)
* (which is really pg_restore's fault, but for now we will work around
* the problem here). Consensus is that the best fix is to treat wrong
* database name as a WARNING not an ERROR; hence, the following special
- * case. (If the length of stmt->objname is not 1, get_object_address
- * will throw an error below; that's OK.)
+ * case.
*/
- if (stmt->objtype == OBJECT_DATABASE && list_length(stmt->objname) == 1)
+ if (stmt->objtype == OBJECT_DATABASE)
{
- char *database = strVal(linitial(stmt->objname));
+ char *database = strVal((Value *) stmt->object);
if (!OidIsValid(get_database_oid(database, true)))
{
@@ -71,12 +70,12 @@ CommentObject(CommentStmt *stmt)
* does not exist, and will also acquire a lock on the target to guard
* against concurrent DROP operations.
*/
- address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
+ address = get_object_address(stmt->objtype, stmt->object,
&relation, ShareUpdateExclusiveLock, false);
/* Require ownership of the target object. */
check_object_ownership(GetUserId(), stmt->objtype, address,
- stmt->objname, stmt->objargs, relation);
+ stmt->object, relation);
/* Perform other integrity checks as needed. */
switch (stmt->objtype)
@@ -96,7 +95,8 @@ CommentObject(CommentStmt *stmt)
relation->rd_rel->relkind != RELKIND_VIEW &&
relation->rd_rel->relkind != RELKIND_MATVIEW &&
relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
- relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
@@ -195,12 +195,12 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
/* Found the old tuple, so delete or update it */
if (comment == NULL)
- simple_heap_delete(description, &oldtuple->t_self);
+ CatalogTupleDelete(description, &oldtuple->t_self);
else
{
newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(description), values,
nulls, replaces);
- simple_heap_update(description, &oldtuple->t_self, newtuple);
+ CatalogTupleUpdate(description, &oldtuple->t_self, newtuple);
}
break; /* Assume there can be only one match */
@@ -214,15 +214,11 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
{
newtuple = heap_form_tuple(RelationGetDescr(description),
values, nulls);
- simple_heap_insert(description, newtuple);
+ CatalogTupleInsert(description, newtuple);
}
- /* Update indexes, if necessary */
if (newtuple != NULL)
- {
- CatalogUpdateIndexes(description, newtuple);
heap_freetuple(newtuple);
- }
/* Done */
@@ -289,12 +285,12 @@ CreateSharedComments(Oid oid, Oid classoid, char *comment)
/* Found the old tuple, so delete or update it */
if (comment == NULL)
- simple_heap_delete(shdescription, &oldtuple->t_self);
+ CatalogTupleDelete(shdescription, &oldtuple->t_self);
else
{
newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(shdescription),
values, nulls, replaces);
- simple_heap_update(shdescription, &oldtuple->t_self, newtuple);
+ CatalogTupleUpdate(shdescription, &oldtuple->t_self, newtuple);
}
break; /* Assume there can be only one match */
@@ -308,15 +304,11 @@ CreateSharedComments(Oid oid, Oid classoid, char *comment)
{
newtuple = heap_form_tuple(RelationGetDescr(shdescription),
values, nulls);
- simple_heap_insert(shdescription, newtuple);
+ CatalogTupleInsert(shdescription, newtuple);
}
- /* Update indexes, if necessary */
if (newtuple != NULL)
- {
- CatalogUpdateIndexes(shdescription, newtuple);
heap_freetuple(newtuple);
- }
/* Done */
@@ -367,7 +359,7 @@ DeleteComments(Oid oid, Oid classoid, int32 subid)
NULL, nkeys, skey);
while ((oldtuple = systable_getnext(sd)) != NULL)
- simple_heap_delete(description, &oldtuple->t_self);
+ CatalogTupleDelete(description, &oldtuple->t_self);
/* Done */
@@ -403,7 +395,7 @@ DeleteSharedComments(Oid oid, Oid classoid)
NULL, 2, skey);
while ((oldtuple = systable_getnext(sd)) != NULL)
- simple_heap_delete(shdescription, &oldtuple->t_self);
+ CatalogTupleDelete(shdescription, &oldtuple->t_self);
/* Done */
diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c
index 26f9114f55..e2544e51ed 100644
--- a/src/backend/commands/constraint.c
+++ b/src/backend/commands/constraint.c
@@ -3,7 +3,7 @@
* constraint.c
* PostgreSQL CONSTRAINT support code.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -37,7 +37,7 @@
Datum
unique_key_recheck(PG_FUNCTION_ARGS)
{
- TriggerData *trigdata = (TriggerData *) fcinfo->context;
+ TriggerData *trigdata = castNode(TriggerData, fcinfo->context);
const char *funcname = "unique_key_recheck";
HeapTuple new_row;
ItemPointerData tmptid;
@@ -165,7 +165,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
* index will know about.
*/
index_insert(indexRel, values, isnull, &(new_row->t_self),
- trigdata->tg_relation, UNIQUE_CHECK_EXISTING);
+ trigdata->tg_relation, UNIQUE_CHECK_EXISTING,
+ indexInfo);
}
else
{
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 175d4ab685..9861d3df22 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -3,7 +3,7 @@
* conversioncmds.c
* conversion creation command support code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,7 +14,6 @@
*/
#include "postgres.h"
-#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 461e94ed0b..5d5e409c7d 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -4,7 +4,7 @@
* Implements the COPY utility command
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -56,6 +56,7 @@
#endif
#include "nodes/makefuncs.h"
#include "optimizer/pgxcship.h"
+#include "parser/parse_relation.h"
#include "rewrite/rewriteHandler.h"
#include "storage/fd.h"
#include "tcop/tcopprot.h"
@@ -79,10 +80,11 @@ typedef enum CopyDest
{
COPY_FILE, /* to/from file (or a piped program) */
COPY_OLD_FE, /* to/from frontend (2.0 protocol) */
- COPY_NEW_FE /* to/from frontend (3.0 protocol) */
+ COPY_NEW_FE, /* to/from frontend (3.0 protocol) */
#ifdef PGXC
- ,COPY_BUFFER /* Do not send, just prepare */
+ COPY_BUFFER, /* Do not send, just prepare */
#endif
+ COPY_CALLBACK /* to/from callback function */
} CopyDest;
/*
@@ -131,6 +133,7 @@ typedef struct CopyStateData
List *attnumlist; /* integer list of attnums to copy */
char *filename; /* filename, or NULL for STDIN/STDOUT */
bool is_program; /* is 'filename' a program to popen? */
+ copy_data_source_cb data_source_cb; /* function for reading data */
bool binary; /* binary format? */
bool oids; /* include OIDs? */
bool freeze; /* freeze rows on loading? */
@@ -184,6 +187,13 @@ typedef struct CopyStateData
bool volatile_defexprs; /* is any of defexprs volatile? */
List *range_table;
+ PartitionDispatch *partition_dispatch_info;
+ int num_dispatch; /* Number of entries in the above array */
+ int num_partitions; /* Number of members in the following arrays */
+ ResultRelInfo *partitions; /* Per partition result relation */
+ TupleConversionMap **partition_tupconv_maps;
+ TupleTableSlot *partition_tuple_slot;
+
/*
* These variables are used to reduce overhead in textual COPY FROM.
*
@@ -305,20 +315,19 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
/* non-export function prototypes */
-static CopyState BeginCopy(bool is_from, Relation rel, Node *raw_query,
- const char *queryString, const Oid queryRelId, List *attnamelist,
+static CopyState BeginCopy(ParseState *pstate, bool is_from, Relation rel,
+ RawStmt *raw_query, Oid queryRelId, List *attnamelist,
List *options);
static void EndCopy(CopyState cstate);
static void ClosePipeToProgram(CopyState cstate);
-static CopyState BeginCopyTo(Relation rel, Node *query, const char *queryString,
- const Oid queryRelId, const char *filename, bool is_program,
+static CopyState BeginCopyTo(ParseState *pstate, Relation rel, RawStmt *query,
+ Oid queryRelId, const char *filename, bool is_program,
List *attnamelist, List *options);
static void EndCopyTo(CopyState cstate);
static uint64 DoCopyTo(CopyState cstate);
static uint64 CopyTo(CopyState cstate);
static void CopyOneRowTo(CopyState cstate, Oid tupleOid,
Datum *values, bool *nulls);
-static uint64 CopyFrom(CopyState cstate);
static void CopyFromInsertBatch(CopyState cstate, EState *estate,
CommandId mycid, int hi_options,
ResultRelInfo *resultRelInfo, TupleTableSlot *myslot,
@@ -384,7 +393,7 @@ SendCopyBegin(CopyState cstate)
pq_endmessage(&buf);
cstate->copy_dest = COPY_NEW_FE;
}
- else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
+ else
{
/* old way */
if (cstate->binary)
@@ -396,18 +405,6 @@ SendCopyBegin(CopyState cstate)
pq_startcopyout();
cstate->copy_dest = COPY_OLD_FE;
}
- else
- {
- /* very old way */
- if (cstate->binary)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("COPY BINARY is not supported to stdout or from stdin")));
- pq_putemptymessage('B');
- /* grottiness needed for old COPY OUT protocol */
- pq_startcopyout();
- cstate->copy_dest = COPY_OLD_FE;
- }
}
static void
@@ -430,7 +427,7 @@ ReceiveCopyBegin(CopyState cstate)
cstate->copy_dest = COPY_NEW_FE;
cstate->fe_msgbuf = makeStringInfo();
}
- else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
+ else
{
/* old way */
if (cstate->binary)
@@ -442,18 +439,6 @@ ReceiveCopyBegin(CopyState cstate)
pq_startmsgread();
cstate->copy_dest = COPY_OLD_FE;
}
- else
- {
- /* very old way */
- if (cstate->binary)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("COPY BINARY is not supported to stdout or from stdin")));
- pq_putemptymessage('D');
- /* any error in old protocol will make us lose sync */
- pq_startmsgread();
- cstate->copy_dest = COPY_OLD_FE;
- }
/* We *must* flush here to ensure FE knows it can send. */
pq_flush();
}
@@ -582,6 +567,9 @@ CopySendEndOfRow(CopyState cstate)
/* Do not send yet anywhere, just return */
return;
#endif
+ case COPY_CALLBACK:
+ Assert(false); /* Not yet supported. */
+ break;
}
resetStringInfo(fe_msgbuf);
@@ -701,6 +689,9 @@ CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
elog(ERROR, "COPY_BUFFER not allowed in this context");
break;
#endif
+ case COPY_CALLBACK:
+ bytesread = cstate->data_source_cb(databuf, minread, maxread);
+ break;
}
return bytesread;
@@ -826,16 +817,17 @@ CopyLoadRawBuf(CopyState cstate)
* Do not allow the copy if user doesn't have proper permission to access
* the table or the specifically requested columns.
*/
-Oid
-DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
+void
+DoCopy(ParseState *pstate, const CopyStmt *stmt,
+ int stmt_location, int stmt_len,
+ uint64 *processed)
{
CopyState cstate;
bool is_from = stmt->is_from;
bool pipe = (stmt->filename == NULL);
Relation rel;
Oid relid;
- Node *query = NULL;
- List *range_table = NIL;
+ RawStmt *query = NULL;
/* Disallow COPY to/from file or program except to superusers. */
if (!pipe && !superuser())
@@ -857,7 +849,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
if (stmt->relation)
{
TupleDesc tupDesc;
- AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
List *attnums;
ListCell *cur;
RangeTblEntry *rte;
@@ -870,12 +861,8 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
relid = RelationGetRelid(rel);
- rte = makeNode(RangeTblEntry);
- rte->rtekind = RTE_RELATION;
- rte->relid = RelationGetRelid(rel);
- rte->relkind = rel->rd_rel->relkind;
- rte->requiredPerms = required_access;
- range_table = list_make1(rte);
+ rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, false);
+ rte->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
tupDesc = RelationGetDescr(rel);
attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
@@ -889,7 +876,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
else
rte->selectedCols = bms_add_member(rte->selectedCols, attno);
}
- ExecCheckRTPerms(range_table, true);
+ ExecCheckRTPerms(pstate->p_rtable, true);
/*
* Permission check for row security policies.
@@ -911,6 +898,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
ColumnRef *cr;
ResTarget *target;
RangeVar *from;
+ List *targetList = NIL;
if (is_from)
ereport(ERROR,
@@ -918,35 +906,77 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
errmsg("COPY FROM not supported with row-level security"),
errhint("Use INSERT statements instead.")));
- /* Build target list */
- cr = makeNode(ColumnRef);
-
+ /*
+ * Build target list
+ *
+ * If no columns are specified in the attribute list of the COPY
+ * command, then the target list is 'all' columns. Therefore, '*'
+ * should be used as the target list for the resulting SELECT
+ * statement.
+ *
+ * In the case that columns are specified in the attribute list,
+ * create a ColumnRef and ResTarget for each column and add them
+ * to the target list for the resulting SELECT statement.
+ */
if (!stmt->attlist)
+ {
+ cr = makeNode(ColumnRef);
cr->fields = list_make1(makeNode(A_Star));
- else
- cr->fields = stmt->attlist;
+ cr->location = -1;
+
+ target = makeNode(ResTarget);
+ target->name = NULL;
+ target->indirection = NIL;
+ target->val = (Node *) cr;
+ target->location = -1;
- cr->location = 1;
+ targetList = list_make1(target);
+ }
+ else
+ {
+ ListCell *lc;
- target = makeNode(ResTarget);
- target->name = NULL;
- target->indirection = NIL;
- target->val = (Node *) cr;
- target->location = 1;
+ foreach(lc, stmt->attlist)
+ {
+ /*
+ * Build the ColumnRef for each column. The ColumnRef
+ * 'fields' property is a String 'Value' node (see
+ * nodes/value.h) that corresponds to the column name
+ * respectively.
+ */
+ cr = makeNode(ColumnRef);
+ cr->fields = list_make1(lfirst(lc));
+ cr->location = -1;
+
+ /* Build the ResTarget and add the ColumnRef to it. */
+ target = makeNode(ResTarget);
+ target->name = NULL;
+ target->indirection = NIL;
+ target->val = (Node *) cr;
+ target->location = -1;
+
+ /* Add each column to the SELECT statement's target list */
+ targetList = lappend(targetList, target);
+ }
+ }
/*
* Build RangeVar for from clause, fully qualified based on the
* relation which we have opened and locked.
*/
from = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
- RelationGetRelationName(rel), -1);
+ pstrdup(RelationGetRelationName(rel)),
+ -1);
/* Build query */
select = makeNode(SelectStmt);
- select->targetList = list_make1(target);
+ select->targetList = targetList;
select->fromClause = list_make1(from);
- query = (Node *) select;
+ query = makeNode(RawStmt);
+ query->stmt = (Node *) select;
+ query->stmt_location = stmt_location;
+ query->stmt_len = stmt_len;
/*
* Close the relation for now, but keep the lock on it to prevent
@@ -962,7 +992,11 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
{
Assert(stmt->query);
- query = stmt->query;
+ query = makeNode(RawStmt);
+ query->stmt = stmt->query;
+ query->stmt_location = stmt_location;
+ query->stmt_len = stmt_len;
+
relid = InvalidOid;
rel = NULL;
}
@@ -976,9 +1010,8 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
PreventCommandIfReadOnly("COPY FROM");
PreventCommandIfParallelMode("COPY FROM");
- cstate = BeginCopyFrom(rel, stmt->filename, stmt->is_program,
- stmt->attlist, stmt->options);
- cstate->range_table = range_table;
+ cstate = BeginCopyFrom(pstate, rel, stmt->filename, stmt->is_program,
+ NULL, stmt->attlist, stmt->options);
*processed = CopyFrom(cstate); /* copy from file to database */
#ifdef XCP
/*
@@ -993,7 +1026,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
}
else
{
- cstate = BeginCopyTo(rel, query, queryString, relid,
+ cstate = BeginCopyTo(pstate, rel, query, relid,
stmt->filename, stmt->is_program,
stmt->attlist, stmt->options);
*processed = DoCopyTo(cstate); /* copy from database to file */
@@ -1007,8 +1040,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
*/
if (rel != NULL)
heap_close(rel, (is_from ? NoLock : AccessShareLock));
-
- return relid;
}
/*
@@ -1029,7 +1060,8 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
* self-consistency of the options list.
*/
void
-ProcessCopyOptions(CopyState cstate,
+ProcessCopyOptions(ParseState *pstate,
+ CopyState cstate,
bool is_from,
List *options)
{
@@ -1045,7 +1077,7 @@ ProcessCopyOptions(CopyState cstate,
/* Extract options from the statement node tree */
foreach(option, options)
{
- DefElem *defel = (DefElem *) lfirst(option);
+ DefElem *defel = lfirst_node(DefElem, option);
if (strcmp(defel->defname, "format") == 0)
{
@@ -1054,7 +1086,8 @@ ProcessCopyOptions(CopyState cstate,
if (format_specified)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
format_specified = true;
if (strcmp(fmt, "text") == 0)
/* default format */ ;
@@ -1065,14 +1098,16 @@ ProcessCopyOptions(CopyState cstate,
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("COPY format \"%s\" not recognized", fmt)));
+ errmsg("COPY format \"%s\" not recognized", fmt),
+ parser_errposition(pstate, defel->location)));
}
else if (strcmp(defel->defname, "oids") == 0)
{
if (cstate->oids)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->oids = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "freeze") == 0)
@@ -1080,7 +1115,8 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->freeze)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->freeze = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "delimiter") == 0)
@@ -1088,7 +1124,8 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->delim)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->delim = defGetString(defel);
}
else if (strcmp(defel->defname, "null") == 0)
@@ -1096,7 +1133,8 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->null_print)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->null_print = defGetString(defel);
}
else if (strcmp(defel->defname, "header") == 0)
@@ -1104,7 +1142,8 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->header_line)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->header_line = defGetBoolean(defel);
}
else if (strcmp(defel->defname, "quote") == 0)
@@ -1112,7 +1151,8 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->quote)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->quote = defGetString(defel);
}
else if (strcmp(defel->defname, "escape") == 0)
@@ -1120,7 +1160,8 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->escape)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->escape = defGetString(defel);
}
else if (strcmp(defel->defname, "force_quote") == 0)
@@ -1128,30 +1169,34 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->force_quote || cstate->force_quote_all)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, A_Star))
cstate->force_quote_all = true;
else if (defel->arg && IsA(defel->arg, List))
- cstate->force_quote = (List *) defel->arg;
+ cstate->force_quote = castNode(List, defel->arg);
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument to option \"%s\" must be a list of column names",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
}
else if (strcmp(defel->defname, "force_not_null") == 0)
{
if (cstate->force_notnull)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
if (defel->arg && IsA(defel->arg, List))
- cstate->force_notnull = (List *) defel->arg;
+ cstate->force_notnull = castNode(List, defel->arg);
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument to option \"%s\" must be a list of column names",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
}
else if (strcmp(defel->defname, "force_null") == 0)
{
@@ -1160,12 +1205,13 @@ ProcessCopyOptions(CopyState cstate,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
if (defel->arg && IsA(defel->arg, List))
- cstate->force_null = (List *) defel->arg;
+ cstate->force_null = castNode(List, defel->arg);
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument to option \"%s\" must be a list of column names",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
}
else if (strcmp(defel->defname, "convert_selectively") == 0)
{
@@ -1177,34 +1223,39 @@ ProcessCopyOptions(CopyState cstate,
if (cstate->convert_selectively)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->convert_selectively = true;
if (defel->arg == NULL || IsA(defel->arg, List))
- cstate->convert_select = (List *) defel->arg;
+ cstate->convert_select = castNode(List, defel->arg);
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument to option \"%s\" must be a list of column names",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
}
else if (strcmp(defel->defname, "encoding") == 0)
{
if (cstate->file_encoding >= 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cstate->file_encoding = pg_char_to_encoding(defGetString(defel));
if (cstate->file_encoding < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument to option \"%s\" must be a valid encoding name",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("option \"%s\" not recognized",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
}
/*
@@ -1367,11 +1418,11 @@ ProcessCopyOptions(CopyState cstate,
* NULL values as <null_print>.
*/
static CopyState
-BeginCopy(bool is_from,
+BeginCopy(ParseState *pstate,
+ bool is_from,
Relation rel,
- Node *raw_query,
- const char *queryString,
- const Oid queryRelId,
+ RawStmt *raw_query,
+ Oid queryRelId,
List *attnamelist,
List *options)
{
@@ -1389,14 +1440,12 @@ BeginCopy(bool is_from,
*/
cstate->copycontext = AllocSetContextCreate(CurrentMemoryContext,
"COPY",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcontext = MemoryContextSwitchTo(cstate->copycontext);
/* Extract options from the statement node tree */
- ProcessCopyOptions(cstate, is_from, options);
+ ProcessCopyOptions(pstate, cstate, is_from, options);
/* Process the source/target relation or query */
if (rel)
@@ -1413,6 +1462,30 @@ BeginCopy(bool is_from,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("table \"%s\" does not have OIDs",
RelationGetRelationName(cstate->rel))));
+
+ /* Initialize state for CopyFrom tuple routing. */
+ if (is_from && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ PartitionDispatch *partition_dispatch_info;
+ ResultRelInfo *partitions;
+ TupleConversionMap **partition_tupconv_maps;
+ TupleTableSlot *partition_tuple_slot;
+ int num_parted,
+ num_partitions;
+
+ ExecSetupPartitionTupleRouting(rel,
+ &partition_dispatch_info,
+ &partitions,
+ &partition_tupconv_maps,
+ &partition_tuple_slot,
+ &num_parted, &num_partitions);
+ cstate->partition_dispatch_info = partition_dispatch_info;
+ cstate->num_dispatch = num_parted;
+ cstate->partitions = partitions;
+ cstate->num_partitions = num_partitions;
+ cstate->partition_tupconv_maps = partition_tupconv_maps;
+ cstate->partition_tuple_slot = partition_tuple_slot;
+ }
#ifdef PGXC
/* Get copy statement and execution node information */
if (IS_PGXC_COORDINATOR)
@@ -1493,8 +1566,9 @@ BeginCopy(bool is_from,
* function and is executed repeatedly. (See also the same hack in
* DECLARE CURSOR and PREPARE.) XXX FIXME someday.
*/
- rewritten = pg_analyze_and_rewrite((Node *) copyObject(raw_query),
- queryString, NULL, 0);
+ rewritten = pg_analyze_and_rewrite(copyObject(raw_query),
+ pstate->p_sourcetext, NULL, 0,
+ NULL);
/* check that we got back something we can work with */
if (rewritten == NIL)
@@ -1510,7 +1584,7 @@ BeginCopy(bool is_from,
/* examine queries to determine which error message to issue */
foreach(lc, rewritten)
{
- Query *q = (Query *) lfirst(lc);
+ Query *q = lfirst_node(Query, lc);
if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
ereport(ERROR,
@@ -1527,7 +1601,7 @@ BeginCopy(bool is_from,
errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
}
- query = (Query *) linitial(rewritten);
+ query = linitial_node(Query, rewritten);
Assert(query->utilityStmt == NULL);
@@ -1587,10 +1661,10 @@ BeginCopy(bool is_from,
((DR_copy *) dest)->cstate = cstate;
/* Create a QueryDesc requesting no output */
- cstate->queryDesc = CreateQueryDesc(plan, queryString,
+ cstate->queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
GetActiveSnapshot(),
InvalidSnapshot,
- dest, NULL, 0);
+ dest, NULL, NULL, 0);
/*
* Call ExecutorStart to prepare the plan for execution.
@@ -1799,10 +1873,10 @@ EndCopy(CopyState cstate)
* Setup CopyState to read tuples from a table or a query for COPY TO.
*/
static CopyState
-BeginCopyTo(Relation rel,
- Node *query,
- const char *queryString,
- const Oid queryRelId,
+BeginCopyTo(ParseState *pstate,
+ Relation rel,
+ RawStmt *query,
+ Oid queryRelId,
const char *filename,
bool is_program,
List *attnamelist,
@@ -1837,6 +1911,12 @@ BeginCopyTo(Relation rel,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot copy from sequence \"%s\"",
RelationGetRelationName(rel))));
+ else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot copy from partitioned table \"%s\"",
+ RelationGetRelationName(rel)),
+ errhint("Try the COPY (SELECT ...) TO variant.")));
else
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -1844,7 +1924,7 @@ BeginCopyTo(Relation rel,
RelationGetRelationName(rel))));
}
- cstate = BeginCopy(false, rel, query, queryString, queryRelId, attnamelist,
+ cstate = BeginCopy(pstate, false, rel, query, queryRelId, attnamelist,
options);
oldcontext = MemoryContextSwitchTo(cstate->copycontext);
@@ -1886,10 +1966,18 @@ BeginCopyTo(Relation rel,
cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
umask(oumask);
if (cstate->copy_file == NULL)
+ {
+ /* copy errno because ereport subfunctions might change it */
+ int save_errno = errno;
+
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\" for writing: %m",
- cstate->filename)));
+ cstate->filename),
+ (save_errno == ENOENT || save_errno == EACCES) ?
+ errhint("COPY TO instructs the PostgreSQL server process to write a file. "
+ "You may want a client-side facility such as psql's \\copy.") : 0));
+ }
if (fstat(fileno(cstate->copy_file), &st))
ereport(ERROR,
@@ -2014,9 +2102,7 @@ CopyTo(CopyState cstate)
*/
cstate->rowcontext = AllocSetContextCreate(CurrentMemoryContext,
"COPY TO",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
if (cstate->binary)
{
@@ -2127,7 +2213,7 @@ CopyTo(CopyState cstate)
else
{
/* run the plan --- the dest receiver will send tuples */
- ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0L);
+ ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0L, true);
processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
}
@@ -2358,7 +2444,7 @@ limit_printout_length(const char *str)
/*
* Copy FROM file to relation.
*/
-static uint64
+uint64
CopyFrom(CopyState cstate)
{
HeapTuple tuple;
@@ -2366,6 +2452,7 @@ CopyFrom(CopyState cstate)
Datum *values;
bool *nulls;
ResultRelInfo *resultRelInfo;
+ ResultRelInfo *saved_resultRelInfo = NULL;
EState *estate = CreateExecutorState(); /* for ExecConstraints() */
ExprContext *econtext;
TupleTableSlot *myslot;
@@ -2378,6 +2465,7 @@ CopyFrom(CopyState cstate)
uint64 processed = 0;
bool useHeapMultiInsert;
int nBufferedTuples = 0;
+ int prev_leaf_part_index = -1;
#define MAX_BUFFERED_TUPLES 1000
HeapTuple *bufferedTuples = NULL; /* initialize to silence warning */
@@ -2386,13 +2474,22 @@ CopyFrom(CopyState cstate)
Assert(cstate->rel);
- if (cstate->rel->rd_rel->relkind != RELKIND_RELATION)
+ /*
+ * The target must be a plain relation or have an INSTEAD OF INSERT row
+ * trigger. (Currently, such triggers are only allowed on views, so we
+ * only hint about them in the view case.)
+ */
+ if (cstate->rel->rd_rel->relkind != RELKIND_RELATION &&
+ cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
+ !(cstate->rel->trigdesc &&
+ cstate->rel->trigdesc->trig_insert_instead_row))
{
if (cstate->rel->rd_rel->relkind == RELKIND_VIEW)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot copy to view \"%s\"",
- RelationGetRelationName(cstate->rel))));
+ RelationGetRelationName(cstate->rel)),
+ errhint("To enable copying to a view, provide an INSTEAD OF INSERT trigger.")));
else if (cstate->rel->rd_rel->relkind == RELKIND_MATVIEW)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -2467,7 +2564,7 @@ CopyFrom(CopyState cstate)
* earlier scan or command. This ensures that if this subtransaction
* aborts then the frozen rows won't be visible after xact cleanup. Note
* that the stronger test of exactly which subtransaction created it is
- * crucial for correctness of this optimisation.
+ * crucial for correctness of this optimization.
*/
if (cstate->freeze)
{
@@ -2494,6 +2591,7 @@ CopyFrom(CopyState cstate)
InitResultRelInfo(resultRelInfo,
cstate->rel,
1, /* dummy rangetable index */
+ NULL,
0);
ExecOpenIndices(resultRelInfo, false);
@@ -2516,11 +2614,13 @@ CopyFrom(CopyState cstate)
* BEFORE/INSTEAD OF triggers, or we need to evaluate volatile default
* expressions. Such triggers or expressions might query the table we're
* inserting to, and act differently if the tuples that have already been
- * processed and prepared for insertion are not there.
+ * processed and prepared for insertion are not there. We also can't do
+ * it if the table is partitioned.
*/
if ((resultRelInfo->ri_TrigDesc != NULL &&
(resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
resultRelInfo->ri_TrigDesc->trig_insert_instead_row)) ||
+ cstate->partition_dispatch_info != NULL ||
cstate->volatile_defexprs)
{
useHeapMultiInsert = false;
@@ -2628,6 +2728,81 @@ CopyFrom(CopyState cstate)
slot = myslot;
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ /* Determine the partition to heap_insert the tuple into */
+ if (cstate->partition_dispatch_info)
+ {
+ int leaf_part_index;
+ TupleConversionMap *map;
+
+ /*
+ * Away we go ... If we end up not finding a partition after all,
+ * ExecFindPartition() does not return and errors out instead.
+ * Otherwise, the returned value is to be used as an index into
+ * arrays mt_partitions[] and mt_partition_tupconv_maps[] that
+ * will get us the ResultRelInfo and TupleConversionMap for the
+ * partition, respectively.
+ */
+ leaf_part_index = ExecFindPartition(resultRelInfo,
+ cstate->partition_dispatch_info,
+ slot,
+ estate);
+ Assert(leaf_part_index >= 0 &&
+ leaf_part_index < cstate->num_partitions);
+
+ /*
+ * If this tuple is mapped to a partition that is not same as the
+ * previous one, we'd better make the bulk insert mechanism gets a
+ * new buffer.
+ */
+ if (prev_leaf_part_index != leaf_part_index)
+ {
+ ReleaseBulkInsertStatePin(bistate);
+ prev_leaf_part_index = leaf_part_index;
+ }
+
+ /*
+ * Save the old ResultRelInfo and switch to the one corresponding
+ * to the selected partition.
+ */
+ saved_resultRelInfo = resultRelInfo;
+ resultRelInfo = cstate->partitions + leaf_part_index;
+
+ /* We do not yet have a way to insert into a foreign partition */
+ if (resultRelInfo->ri_FdwRoutine)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot route inserted tuples to a foreign table")));
+
+ /*
+ * For ExecInsertIndexTuples() to work on the partition's indexes
+ */
+ estate->es_result_relation_info = resultRelInfo;
+
+ /*
+ * We might need to convert from the parent rowtype to the
+ * partition rowtype.
+ */
+ map = cstate->partition_tupconv_maps[leaf_part_index];
+ if (map)
+ {
+ Relation partrel = resultRelInfo->ri_RelationDesc;
+
+ tuple = do_convert_tuple(tuple, map);
+
+ /*
+ * We must use the partition's tuple descriptor from this
+ * point on. Use a dedicated slot from this point on until
+ * we're finished dealing with the partition.
+ */
+ slot = cstate->partition_tuple_slot;
+ Assert(slot != NULL);
+ ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
+ ExecStoreTuple(tuple, slot, InvalidBuffer, true);
+ }
+
+ tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
+ }
+
skip_tuple = false;
/* BEFORE ROW INSERT Triggers */
@@ -2644,52 +2819,66 @@ CopyFrom(CopyState cstate)
if (!skip_tuple)
{
- /* Check the constraints of the tuple */
- if (cstate->rel->rd_att->constr)
- ExecConstraints(resultRelInfo, slot, estate);
-
- if (useHeapMultiInsert)
+ if (resultRelInfo->ri_TrigDesc &&
+ resultRelInfo->ri_TrigDesc->trig_insert_instead_row)
{
- /* Add this tuple to the tuple buffer */
- if (nBufferedTuples == 0)
- firstBufferedLineNo = cstate->cur_lineno;
- bufferedTuples[nBufferedTuples++] = tuple;
- bufferedTuplesSize += tuple->t_len;
-
- /*
- * If the buffer filled up, flush it. Also flush if the total
- * size of all the tuples in the buffer becomes large, to
- * avoid using large amounts of memory for the buffers when
- * the tuples are exceptionally wide.
- */
- if (nBufferedTuples == MAX_BUFFERED_TUPLES ||
- bufferedTuplesSize > 65535)
- {
- CopyFromInsertBatch(cstate, estate, mycid, hi_options,
- resultRelInfo, myslot, bistate,
- nBufferedTuples, bufferedTuples,
- firstBufferedLineNo);
- nBufferedTuples = 0;
- bufferedTuplesSize = 0;
- }
+ /* Pass the data to the INSTEAD ROW INSERT trigger */
+ ExecIRInsertTriggers(estate, resultRelInfo, slot);
}
else
{
- List *recheckIndexes = NIL;
+ /* Check the constraints of the tuple */
+ if (cstate->rel->rd_att->constr ||
+ resultRelInfo->ri_PartitionCheck)
+ ExecConstraints(resultRelInfo, slot, estate);
+
+ if (useHeapMultiInsert)
+ {
+ /* Add this tuple to the tuple buffer */
+ if (nBufferedTuples == 0)
+ firstBufferedLineNo = cstate->cur_lineno;
+ bufferedTuples[nBufferedTuples++] = tuple;
+ bufferedTuplesSize += tuple->t_len;
+
+ /*
+ * If the buffer filled up, flush it. Also flush if the
+ * total size of all the tuples in the buffer becomes
+ * large, to avoid using large amounts of memory for the
+ * buffer when the tuples are exceptionally wide.
+ */
+ if (nBufferedTuples == MAX_BUFFERED_TUPLES ||
+ bufferedTuplesSize > 65535)
+ {
+ CopyFromInsertBatch(cstate, estate, mycid, hi_options,
+ resultRelInfo, myslot, bistate,
+ nBufferedTuples, bufferedTuples,
+ firstBufferedLineNo);
+ nBufferedTuples = 0;
+ bufferedTuplesSize = 0;
+ }
+ }
+ else
+ {
+ List *recheckIndexes = NIL;
- /* OK, store the tuple and create index entries for it */
- heap_insert(cstate->rel, tuple, mycid, hi_options, bistate);
+ /* OK, store the tuple and create index entries for it */
+ heap_insert(resultRelInfo->ri_RelationDesc, tuple, mycid,
+ hi_options, bistate);
- if (resultRelInfo->ri_NumIndices > 0)
- recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
- estate, false, NULL,
- NIL);
+ if (resultRelInfo->ri_NumIndices > 0)
+ recheckIndexes = ExecInsertIndexTuples(slot,
+ &(tuple->t_self),
+ estate,
+ false,
+ NULL,
+ NIL);
- /* AFTER ROW INSERT Triggers */
- ExecARInsertTriggers(estate, resultRelInfo, tuple,
- recheckIndexes);
+ /* AFTER ROW INSERT Triggers */
+ ExecARInsertTriggers(estate, resultRelInfo, tuple,
+ recheckIndexes);
- list_free(recheckIndexes);
+ list_free(recheckIndexes);
+ }
}
/*
@@ -2698,6 +2887,12 @@ CopyFrom(CopyState cstate)
* tuples inserted by an INSERT command.
*/
processed++;
+
+ if (saved_resultRelInfo)
+ {
+ resultRelInfo = saved_resultRelInfo;
+ estate->es_result_relation_info = resultRelInfo;
+ }
}
#ifdef PGXC
}
@@ -2758,6 +2953,39 @@ CopyFrom(CopyState cstate)
ExecCloseIndices(resultRelInfo);
+ /* Close all the partitioned tables, leaf partitions, and their indices */
+ if (cstate->partition_dispatch_info)
+ {
+ int i;
+
+ /*
+ * Remember cstate->partition_dispatch_info[0] corresponds to the root
+ * partitioned table, which we must not try to close, because it is
+ * the main target table of COPY that will be closed eventually by
+ * DoCopy(). Also, tupslot is NULL for the root partitioned table.
+ */
+ for (i = 1; i < cstate->num_dispatch; i++)
+ {
+ PartitionDispatch pd = cstate->partition_dispatch_info[i];
+
+ heap_close(pd->reldesc, NoLock);
+ ExecDropSingleTupleTableSlot(pd->tupslot);
+ }
+ for (i = 0; i < cstate->num_partitions; i++)
+ {
+ ResultRelInfo *resultRelInfo = cstate->partitions + i;
+
+ ExecCloseIndices(resultRelInfo);
+ heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+ }
+
+ /* Release the standalone partition tuple descriptor */
+ ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot);
+ }
+
+ /* Close any trigger target relations */
+ ExecCleanUpTriggerState(estate);
+
FreeExecutorState(estate);
/*
@@ -2859,9 +3087,11 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
* Returns a CopyState, to be passed to NextCopyFrom and related functions.
*/
CopyState
-BeginCopyFrom(Relation rel,
+BeginCopyFrom(ParseState *pstate,
+ Relation rel,
const char *filename,
bool is_program,
+ copy_data_source_cb data_source_cb,
List *attnamelist,
List *options)
{
@@ -2880,7 +3110,7 @@ BeginCopyFrom(Relation rel,
MemoryContext oldcontext;
bool volatile_defexprs;
- cstate = BeginCopy(true, rel, NULL, NULL, InvalidOid, attnamelist, options);
+ cstate = BeginCopy(pstate, true, rel, NULL, InvalidOid, attnamelist, options);
oldcontext = MemoryContextSwitchTo(cstate->copycontext);
/* Initialize state variables */
@@ -2898,6 +3128,10 @@ BeginCopyFrom(Relation rel,
cstate->raw_buf = (char *) palloc(RAW_BUF_SIZE + 1);
cstate->raw_buf_index = cstate->raw_buf_len = 0;
+ /* Assign range table, we'll need it in CopyFrom. */
+ if (pstate)
+ cstate->range_table = pstate->p_rtable;
+
tupDesc = RelationGetDescr(cstate->rel);
attr = tupDesc->attrs;
num_phys_attrs = tupDesc->natts;
@@ -2998,7 +3232,7 @@ BeginCopyFrom(Relation rel,
* the special case of when the default expression is the
* nextval() of a sequence which in this specific case is
* known to be safe for use with the multi-insert
- * optimisation. Hence we use this special case function
+ * optimization. Hence we use this special case function
* checker rather than the standard check for
* contain_volatile_functions().
*/
@@ -3020,7 +3254,12 @@ BeginCopyFrom(Relation rel,
cstate->num_defaults = num_defaults;
cstate->is_program = is_program;
- if (pipe)
+ if (data_source_cb)
+ {
+ cstate->copy_dest = COPY_CALLBACK;
+ cstate->data_source_cb = data_source_cb;
+ }
+ else if (pipe)
{
Assert(!is_program); /* the grammar does not allow this */
if (whereToSendOutput == DestRemote)
@@ -3047,10 +3286,18 @@ BeginCopyFrom(Relation rel,
cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
if (cstate->copy_file == NULL)
+ {
+ /* copy errno because ereport subfunctions might change it */
+ int save_errno = errno;
+
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\" for reading: %m",
- cstate->filename)));
+ cstate->filename),
+ (save_errno == ENOENT || save_errno == EACCES) ?
+ errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
+ "You may want a client-side facility such as psql's \\copy.") : 0));
+ }
if (fstat(fileno(cstate->copy_file), &st))
ereport(ERROR,
@@ -3499,7 +3746,7 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext,
Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory);
values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
- &nulls[defmap[i]], NULL);
+ &nulls[defmap[i]]);
}
#ifdef PGXC
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 5b4f6affcc..06425cc0eb 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -13,7 +13,7 @@
* we must return a tuples-processed count in the completionTag. (We no
* longer do that for CTAS ... WITH NO DATA, however.)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -112,7 +112,7 @@ create_ctas_internal(List *attrList, IntoClause *into)
* Create the relation. (This will error out if there's an existing view,
* so we don't need more code to complain if "replace" is false.)
*/
- intoRelationAddr = DefineRelation(create, relkind, InvalidOid, NULL);
+ intoRelationAddr = DefineRelation(create, relkind, InvalidOid, NULL, NULL);
/*
* If necessary, create a TOAST table for the target table. Note that
@@ -222,9 +222,10 @@ create_ctas_nodata(List *tlist, IntoClause *into)
*/
ObjectAddress
ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
- ParamListInfo params, char *completionTag)
+ ParamListInfo params, QueryEnvironment *queryEnv,
+ char *completionTag)
{
- Query *query = (Query *) stmt->query;
+ Query *query = castNode(Query, stmt->query);
IntoClause *into = stmt->into;
bool is_matview = (into->viewQuery != NULL);
DestReceiver *dest;
@@ -261,11 +262,10 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
* The contained Query could be a SELECT, or an EXECUTE utility command.
* If the latter, we just pass it off to ExecuteQuery.
*/
- Assert(IsA(query, Query));
if (query->commandType == CMD_UTILITY &&
IsA(query->utilityStmt, ExecuteStmt))
{
- ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt;
+ ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
Assert(!is_matview); /* excluded by syntax */
ExecuteQuery(estmt, into, queryString, params, dest, completionTag);
@@ -316,17 +316,17 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
* and is executed repeatedly. (See also the same hack in EXPLAIN and
* PREPARE.)
*/
- rewritten = QueryRewrite((Query *) copyObject(query));
+ rewritten = QueryRewrite(copyObject(query));
/* SELECT should never rewrite to more or less than one SELECT query */
if (list_length(rewritten) != 1)
elog(ERROR, "unexpected rewrite result for %s",
is_matview ? "CREATE MATERIALIZED VIEW" :
"CREATE TABLE AS SELECT");
- query = (Query *) linitial(rewritten);
+ query = linitial_node(Query, rewritten);
Assert(query->commandType == CMD_SELECT);
- /* plan the query */
+ /* plan the query --- note we disallow parallelism */
plan = pg_plan_query(query, 0, params);
/*
@@ -342,13 +342,13 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
/* Create a QueryDesc, redirecting output to our tuple receiver */
queryDesc = CreateQueryDesc(plan, queryString,
GetActiveSnapshot(), InvalidSnapshot,
- dest, params, 0);
+ dest, params, queryEnv, 0);
/* call ExecutorStart to prepare the plan for execution */
ExecutorStart(queryDesc, GetIntoRelEFlags(into));
/* run the plan to completion */
- ExecutorRun(queryDesc, ForwardScanDirection, 0L);
+ ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
/* save the rowcount if we're given a completionTag to fill */
if (completionTag)
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index d87945e4d3..baeb8b591e 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -8,7 +8,7 @@
* stepping on each others' toes. Formerly we used table-level locks
* on pg_database, but that's too coarse-grained.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -20,7 +20,6 @@
#include "postgres.h"
#include <fcntl.h>
-#include <locale.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -37,6 +36,7 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
+#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
@@ -108,7 +108,7 @@ static void movedb_success_callback(Oid db_id, Oid tblspcoid);
* CREATE DATABASE
*/
Oid
-createdb(const CreatedbStmt *stmt)
+createdb(ParseState *pstate, const CreatedbStmt *stmt)
{
HeapScanDesc scan;
Relation rel;
@@ -164,7 +164,8 @@ createdb(const CreatedbStmt *stmt)
if (dtablespacename)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dtablespacename = defel;
}
else if (strcmp(defel->defname, "owner") == 0)
@@ -172,7 +173,8 @@ createdb(const CreatedbStmt *stmt)
if (downer)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
downer = defel;
}
else if (strcmp(defel->defname, "template") == 0)
@@ -180,7 +182,8 @@ createdb(const CreatedbStmt *stmt)
if (dtemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dtemplate = defel;
}
else if (strcmp(defel->defname, "encoding") == 0)
@@ -188,7 +191,8 @@ createdb(const CreatedbStmt *stmt)
if (dencoding)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dencoding = defel;
}
else if (strcmp(defel->defname, "lc_collate") == 0)
@@ -196,7 +200,8 @@ createdb(const CreatedbStmt *stmt)
if (dcollate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dcollate = defel;
}
else if (strcmp(defel->defname, "lc_ctype") == 0)
@@ -204,7 +209,8 @@ createdb(const CreatedbStmt *stmt)
if (dctype)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dctype = defel;
}
else if (strcmp(defel->defname, "is_template") == 0)
@@ -212,7 +218,8 @@ createdb(const CreatedbStmt *stmt)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
@@ -220,7 +227,8 @@ createdb(const CreatedbStmt *stmt)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
@@ -228,7 +236,8 @@ createdb(const CreatedbStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "location") == 0)
@@ -236,12 +245,14 @@ createdb(const CreatedbStmt *stmt)
ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("LOCATION is not supported anymore"),
- errhint("Consider using tablespaces instead.")));
+ errhint("Consider using tablespaces instead."),
+ parser_errposition(pstate, defel->location)));
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("option \"%s\" not recognized", defel->defname)));
+ errmsg("option \"%s\" not recognized", defel->defname),
+ parser_errposition(pstate, defel->location)));
}
if (downer && downer->arg)
@@ -261,7 +272,8 @@ createdb(const CreatedbStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("%d is not a valid encoding code",
- encoding)));
+ encoding),
+ parser_errposition(pstate, dencoding->location)));
}
else
{
@@ -271,7 +283,8 @@ createdb(const CreatedbStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("%s is not a valid encoding name",
- encoding_name)));
+ encoding_name),
+ parser_errposition(pstate, dencoding->location)));
}
}
if (dcollate && dcollate->arg)
@@ -544,10 +557,7 @@ createdb(const CreatedbStmt *stmt)
HeapTupleSetOid(tuple, dboid);
- simple_heap_insert(pg_database_rel, tuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(pg_database_rel, tuple);
+ CatalogTupleInsert(pg_database_rel, tuple);
/*
* Now generate additional catalog entries associated with the new DB
@@ -686,7 +696,7 @@ createdb(const CreatedbStmt *stmt)
/*
* Force synchronous commit, thus minimizing the window between
- * creation of the database files and commital of the transaction. If
+ * creation of the database files and committal of the transaction. If
* we crash before committing, we'll have a DB that's taking up disk
* space but is not in pg_database, which is not good.
*/
@@ -817,6 +827,7 @@ dropdb(const char *dbname, bool missing_ok)
int npreparedxacts;
int nslots,
nslots_active;
+ int nsubscriptions;
/*
* Look up the target database's OID, and get exclusive lock on it. We
@@ -874,19 +885,22 @@ dropdb(const char *dbname, bool missing_ok)
errmsg("cannot drop the currently open database")));
/*
- * Check whether there are, possibly unconnected, logical slots that refer
- * to the to-be-dropped database. The database lock we are holding
- * prevents the creation of new slots using the database.
+ * Check whether there are active logical slots that refer to the
+ * to-be-dropped database. The database lock we are holding prevents the
+ * creation of new slots using the database or existing slots becoming
+ * active.
*/
- if (ReplicationSlotsCountDBSlots(db_id, &nslots, &nslots_active))
+ (void) ReplicationSlotsCountDBSlots(db_id, &nslots, &nslots_active);
+ if (nslots_active)
+ {
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
- errmsg("database \"%s\" is used by a logical replication slot",
- dbname),
- errdetail_plural("There is %d slot, %d of them active.",
- "There are %d slots, %d of them active.",
- nslots,
- nslots, nslots_active)));
+ errmsg("database \"%s\" is used by an active logical replication slot",
+ dbname),
+ errdetail_plural("There is %d active slot",
+ "There are %d active slots",
+ nslots_active, nslots_active)));
+ }
/*
* Check for other backends in the target database. (Because we hold the
@@ -902,13 +916,28 @@ dropdb(const char *dbname, bool missing_ok)
errdetail_busy_db(notherbackends, npreparedxacts)));
/*
+ * Check if there are subscriptions defined in the target database.
+ *
+ * We can't drop them automatically because they might be holding
+ * resources in other databases/instances.
+ */
+ if ((nsubscriptions = CountDBSubscriptions(db_id)) > 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_IN_USE),
+ errmsg("database \"%s\" is being used by logical replication subscription",
+ dbname),
+ errdetail_plural("There is %d subscription.",
+ "There are %d subscriptions.",
+ nsubscriptions, nsubscriptions)));
+
+ /*
* Remove the database's tuple from pg_database.
*/
tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_id));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for database %u", db_id);
- simple_heap_delete(pgdbrel, &tup->t_self);
+ CatalogTupleDelete(pgdbrel, &tup->t_self);
ReleaseSysCache(tup);
@@ -929,6 +958,11 @@ dropdb(const char *dbname, bool missing_ok)
dropDatabaseDependencies(db_id);
/*
+ * Drop db-specific replication slots.
+ */
+ ReplicationSlotsDropDBSlots(db_id);
+
+ /*
* Drop pages for this database that are in the shared buffer cache. This
* is important to ensure that no remaining backend tries to write out a
* dirty buffer to the dead database later...
@@ -968,7 +1002,7 @@ dropdb(const char *dbname, bool missing_ok)
/*
* Force synchronous commit, thus minimizing the window between removal of
- * the database files and commital of the transaction. If we crash before
+ * the database files and committal of the transaction. If we crash before
* committing, we'll have a DB that's gone on disk but still there
* according to pg_database, which is not good.
*/
@@ -1057,8 +1091,7 @@ RenameDatabase(const char *oldname, const char *newname)
if (!HeapTupleIsValid(newtup))
elog(ERROR, "cache lookup failed for database %u", db_id);
namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname);
- simple_heap_update(rel, &newtup->t_self, newtup);
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &newtup->t_self, newtup);
InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
@@ -1325,7 +1358,7 @@ movedb(const char *dbname, const char *tblspcname)
ScanKeyInit(&scankey,
Anum_pg_database_datname,
BTEqualStrategyNumber, F_NAMEEQ,
- NameGetDatum(dbname));
+ CStringGetDatum(dbname));
sysscan = systable_beginscan(pgdbrel, DatabaseNameIndexId, true,
NULL, 1, &scankey);
oldtuple = systable_getnext(sysscan);
@@ -1344,10 +1377,7 @@ movedb(const char *dbname, const char *tblspcname)
newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(pgdbrel),
new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(pgdbrel, &oldtuple->t_self, newtuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(pgdbrel, newtuple);
+ CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple);
InvokeObjectPostAlterHook(DatabaseRelationId,
HeapTupleGetOid(newtuple), 0);
@@ -1364,7 +1394,7 @@ movedb(const char *dbname, const char *tblspcname)
/*
* Force synchronous commit, thus minimizing the window between
- * copying the database files and commital of the transaction. If we
+ * copying the database files and committal of the transaction. If we
* crash before committing, we'll leave an orphaned set of files on
* disk, which is not fatal but not good either.
*/
@@ -1497,7 +1527,7 @@ movedb_failure_callback(int code, Datum arg)
* ALTER DATABASE name ...
*/
Oid
-AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
+AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
{
Relation rel;
Oid dboid;
@@ -1527,7 +1557,8 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
if (distemplate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
distemplate = defel;
}
else if (strcmp(defel->defname, "allow_connections") == 0)
@@ -1535,7 +1566,8 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
if (dallowconnections)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dallowconnections = defel;
}
else if (strcmp(defel->defname, "connection_limit") == 0)
@@ -1543,7 +1575,8 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "tablespace") == 0)
@@ -1551,13 +1584,15 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
if (dtablespace)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dtablespace = defel;
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("option \"%s\" not recognized", defel->defname)));
+ errmsg("option \"%s\" not recognized", defel->defname),
+ parser_errposition(pstate, defel->location)));
}
if (dtablespace)
@@ -1571,7 +1606,8 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("option \"%s\" cannot be specified with other options",
- dtablespace->defname)));
+ dtablespace->defname),
+ parser_errposition(pstate, dtablespace->location)));
/* this case isn't allowed within a transaction block */
#ifdef PGXC
/* ... but we allow it on remote nodes */
@@ -1605,7 +1641,7 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
ScanKeyInit(&scankey,
Anum_pg_database_datname,
BTEqualStrategyNumber, F_NAMEEQ,
- NameGetDatum(stmt->dbname));
+ CStringGetDatum(stmt->dbname));
scan = systable_beginscan(rel, DatabaseNameIndexId, true,
NULL, 1, &scankey);
tuple = systable_getnext(scan);
@@ -1656,10 +1692,7 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(rel, &tuple->t_self, newtuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
InvokeObjectPostAlterHook(DatabaseRelationId,
HeapTupleGetOid(newtuple), 0);
@@ -1722,7 +1755,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
ScanKeyInit(&scankey,
Anum_pg_database_datname,
BTEqualStrategyNumber, F_NAMEEQ,
- NameGetDatum(dbname));
+ CStringGetDatum(dbname));
scan = systable_beginscan(rel, DatabaseNameIndexId, true,
NULL, 1, &scankey);
tuple = systable_getnext(scan);
@@ -1794,8 +1827,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
}
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
heap_freetuple(newtuple);
@@ -1862,7 +1894,7 @@ get_db_info(const char *name, LOCKMODE lockmode,
ScanKeyInit(&scanKey,
Anum_pg_database_datname,
BTEqualStrategyNumber, F_NAMEEQ,
- NameGetDatum(name));
+ CStringGetDatum(name));
scan = systable_beginscan(relation, DatabaseNameIndexId, true,
NULL, 1, &scanKey);
@@ -2238,11 +2270,18 @@ dbase_redo(XLogReaderState *record)
* InitPostgres() cannot fully re-execute concurrently. This
* avoids backends re-connecting automatically to same database,
* which can happen in some cases.
+ *
+ * This will lock out walsenders trying to connect to db-specific
+ * slots for logical decoding too, so it's safe for us to drop
+ * slots.
*/
LockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
ResolveRecoveryConflictWithDatabase(xlrec->db_id);
}
+ /* Drop any database-specific replication slots */
+ ReplicationSlotsDropDBSlots(xlrec->db_id);
+
/* Drop pages for this database that are in the shared buffer cache */
DropDatabaseBuffers(xlrec->db_id);
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index ece803ec4b..3ad4eea59e 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -4,7 +4,7 @@
* Support routines for various kinds of object creation.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -40,7 +40,7 @@
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "parser/scansup.h"
-#include "utils/int8.h"
+#include "utils/builtins.h"
/*
* Extract a string value (otherwise uninterpreted) from a DefElem.
@@ -321,10 +321,29 @@ defGetTypeLength(DefElem *def)
}
/*
- * Create a DefElem setting "oids" to the specified value.
+ * Extract a list of string values (otherwise uninterpreted) from a DefElem.
*/
-DefElem *
-defWithOids(bool value)
+List *
+defGetStringList(DefElem *def)
{
- return makeDefElem("oids", (Node *) makeInteger(value));
+ ListCell *cell;
+
+ if (def->arg == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("%s requires a parameter",
+ def->defname)));
+ if (nodeTag(def->arg) != T_List)
+ elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
+
+ foreach(cell, (List *) def->arg)
+ {
+ Node *str = (Node *) lfirst(cell);
+
+ if (!IsA(str, String))
+ elog(ERROR, "unexpected node type in name list: %d",
+ (int) nodeTag(str));
+ }
+
+ return (List *) def->arg;
}
diff --git a/src/backend/commands/discard.c b/src/backend/commands/discard.c
index 5b8bd67579..f0dcd87fb8 100644
--- a/src/backend/commands/discard.c
+++ b/src/backend/commands/discard.c
@@ -3,7 +3,7 @@
* discard.c
* The implementation of the DISCARD command
*
- * Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Copyright (c) 1996-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index 61ff8f2190..9e307eb8af 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -3,7 +3,7 @@
* dropcmds.c
* handle various "DROP" operations
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -30,10 +30,10 @@
static void does_not_exist_skipping(ObjectType objtype,
- List *objname, List *objargs);
-static bool owningrel_does_not_exist_skipping(List *objname,
+ Node *object);
+static bool owningrel_does_not_exist_skipping(List *object,
const char **msg, char **name);
-static bool schema_does_not_exist_skipping(List *objname,
+static bool schema_does_not_exist_skipping(List *object,
const char **msg, char **name);
static bool type_in_list_does_not_exist_skipping(List *typenames,
const char **msg, char **name);
@@ -55,27 +55,19 @@ RemoveObjects(DropStmt *stmt)
{
ObjectAddresses *objects;
ListCell *cell1;
- ListCell *cell2 = NULL;
objects = new_object_addresses();
foreach(cell1, stmt->objects)
{
ObjectAddress address;
- List *objname = lfirst(cell1);
- List *objargs = NIL;
+ Node *object = lfirst(cell1);
Relation relation = NULL;
Oid namespaceId;
- if (stmt->arguments)
- {
- cell2 = (!cell2 ? list_head(stmt->arguments) : lnext(cell2));
- objargs = lfirst(cell2);
- }
-
/* Get an ObjectAddress for the object. */
address = get_object_address(stmt->removeType,
- objname, objargs,
+ object,
&relation,
AccessExclusiveLock,
stmt->missing_ok);
@@ -88,7 +80,7 @@ RemoveObjects(DropStmt *stmt)
if (!OidIsValid(address.objectId))
{
Assert(stmt->missing_ok);
- does_not_exist_skipping(stmt->removeType, objname, objargs);
+ does_not_exist_skipping(stmt->removeType, object);
continue;
}
@@ -110,7 +102,7 @@ RemoveObjects(DropStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is an aggregate function",
- NameListToString(objname)),
+ NameListToString(castNode(ObjectWithArgs, object)->objname)),
errhint("Use DROP AGGREGATE to drop aggregate functions.")));
ReleaseSysCache(tup);
@@ -121,7 +113,7 @@ RemoveObjects(DropStmt *stmt)
if (!OidIsValid(namespaceId) ||
!pg_namespace_ownercheck(namespaceId, GetUserId()))
check_object_ownership(GetUserId(), stmt->removeType, address,
- objname, objargs, relation);
+ object, relation);
/* Release any relcache reference count, but keep lock until commit. */
if (relation)
@@ -147,23 +139,23 @@ RemoveObjects(DropStmt *stmt)
* exist, fill the error message format string and name, and return true.
*/
static bool
-owningrel_does_not_exist_skipping(List *objname, const char **msg, char **name)
+owningrel_does_not_exist_skipping(List *object, const char **msg, char **name)
{
- List *parent_objname;
+ List *parent_object;
RangeVar *parent_rel;
- parent_objname = list_truncate(list_copy(objname),
- list_length(objname) - 1);
+ parent_object = list_truncate(list_copy(object),
+ list_length(object) - 1);
- if (schema_does_not_exist_skipping(parent_objname, msg, name))
+ if (schema_does_not_exist_skipping(parent_object, msg, name))
return true;
- parent_rel = makeRangeVarFromNameList(parent_objname);
+ parent_rel = makeRangeVarFromNameList(parent_object);
if (!OidIsValid(RangeVarGetRelid(parent_rel, NoLock, true)))
{
*msg = gettext_noop("relation \"%s\" does not exist, skipping");
- *name = NameListToString(parent_objname);
+ *name = NameListToString(parent_object);
return true;
}
@@ -183,11 +175,11 @@ owningrel_does_not_exist_skipping(List *objname, const char **msg, char **name)
* specified schema name, and return true.
*/
static bool
-schema_does_not_exist_skipping(List *objname, const char **msg, char **name)
+schema_does_not_exist_skipping(List *object, const char **msg, char **name)
{
RangeVar *rel;
- rel = makeRangeVarFromNameList(objname);
+ rel = makeRangeVarFromNameList(object);
if (rel->schemaname != NULL &&
!OidIsValid(LookupNamespaceNoError(rel->schemaname)))
@@ -222,12 +214,10 @@ type_in_list_does_not_exist_skipping(List *typenames, const char **msg,
foreach(l, typenames)
{
- TypeName *typeName = (TypeName *) lfirst(l);
+ TypeName *typeName = lfirst_node(TypeName, l);
if (typeName != NULL)
{
- Assert(IsA(typeName, TypeName));
-
if (!OidIsValid(LookupTypeNameOid(NULL, typeName, true)))
{
/* type doesn't exist, try to find why */
@@ -254,7 +244,7 @@ type_in_list_does_not_exist_skipping(List *typenames, const char **msg,
* get_object_address() in RemoveObjects would have thrown an ERROR.
*/
static void
-does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
+does_not_exist_skipping(ObjectType objtype, Node *object)
{
const char *msg = NULL;
char *name = NULL;
@@ -264,12 +254,12 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
{
case OBJECT_ACCESS_METHOD:
msg = gettext_noop("access method \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
break;
case OBJECT_TYPE:
case OBJECT_DOMAIN:
{
- TypeName *typ = linitial(objname);
+ TypeName *typ = castNode(TypeName, object);
if (!schema_does_not_exist_skipping(typ->names, &msg, &name))
{
@@ -279,168 +269,191 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
}
break;
case OBJECT_COLLATION:
- if (!schema_does_not_exist_skipping(objname, &msg, &name))
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("collation \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = NameListToString(castNode(List, object));
}
break;
case OBJECT_CONVERSION:
- if (!schema_does_not_exist_skipping(objname, &msg, &name))
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("conversion \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = NameListToString(castNode(List, object));
}
break;
case OBJECT_SCHEMA:
msg = gettext_noop("schema \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
+ {
+ msg = gettext_noop("statistics object \"%s\" does not exist, skipping");
+ name = NameListToString(castNode(List, object));
+ }
break;
case OBJECT_TSPARSER:
- if (!schema_does_not_exist_skipping(objname, &msg, &name))
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = NameListToString(castNode(List, object));
}
break;
case OBJECT_TSDICTIONARY:
- if (!schema_does_not_exist_skipping(objname, &msg, &name))
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = NameListToString(castNode(List, object));
}
break;
case OBJECT_TSTEMPLATE:
- if (!schema_does_not_exist_skipping(objname, &msg, &name))
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("text search template \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = NameListToString(castNode(List, object));
}
break;
case OBJECT_TSCONFIGURATION:
- if (!schema_does_not_exist_skipping(objname, &msg, &name))
+ if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = NameListToString(castNode(List, object));
}
break;
case OBJECT_EXTENSION:
msg = gettext_noop("extension \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
break;
case OBJECT_FUNCTION:
- if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
- !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
{
- msg = gettext_noop("function %s(%s) does not exist, skipping");
- name = NameListToString(objname);
- args = TypeNameListToString(objargs);
+ ObjectWithArgs *owa = castNode(ObjectWithArgs, object);
+
+ if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) &&
+ !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name))
+ {
+ msg = gettext_noop("function %s(%s) does not exist, skipping");
+ name = NameListToString(owa->objname);
+ args = TypeNameListToString(owa->objargs);
+ }
+ break;
}
- break;
case OBJECT_AGGREGATE:
- if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
- !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
{
- msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
- name = NameListToString(objname);
- args = TypeNameListToString(objargs);
+ ObjectWithArgs *owa = castNode(ObjectWithArgs, object);
+
+ if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) &&
+ !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name))
+ {
+ msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
+ name = NameListToString(owa->objname);
+ args = TypeNameListToString(owa->objargs);
+ }
+ break;
}
- break;
case OBJECT_OPERATOR:
- if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
- !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
{
- msg = gettext_noop("operator %s does not exist, skipping");
- name = NameListToString(objname);
+ ObjectWithArgs *owa = castNode(ObjectWithArgs, object);
+
+ if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) &&
+ !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name))
+ {
+ msg = gettext_noop("operator %s does not exist, skipping");
+ name = NameListToString(owa->objname);
+ }
+ break;
}
- break;
case OBJECT_LANGUAGE:
msg = gettext_noop("language \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
break;
case OBJECT_CAST:
{
- if (!type_in_list_does_not_exist_skipping(objname, &msg, &name) &&
- !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
+ if (!type_in_list_does_not_exist_skipping(list_make1(linitial(castNode(List, object))), &msg, &name) &&
+ !type_in_list_does_not_exist_skipping(list_make1(lsecond(castNode(List, object))), &msg, &name))
{
/* XXX quote or no quote? */
msg = gettext_noop("cast from type %s to type %s does not exist, skipping");
- name = TypeNameToString((TypeName *) linitial(objname));
- args = TypeNameToString((TypeName *) linitial(objargs));
+ name = TypeNameToString(linitial_node(TypeName, castNode(List, object)));
+ args = TypeNameToString(lsecond_node(TypeName, castNode(List, object)));
}
}
break;
case OBJECT_TRANSFORM:
- if (!type_in_list_does_not_exist_skipping(objname, &msg, &name))
+ if (!type_in_list_does_not_exist_skipping(list_make1(linitial(castNode(List, object))), &msg, &name))
{
msg = gettext_noop("transform for type %s language \"%s\" does not exist, skipping");
- name = TypeNameToString((TypeName *) linitial(objname));
- args = strVal(linitial(objargs));
+ name = TypeNameToString(linitial_node(TypeName, castNode(List, object)));
+ args = strVal(lsecond(castNode(List, object)));
}
break;
case OBJECT_TRIGGER:
- if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
+ if (!owningrel_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("trigger \"%s\" for relation \"%s\" does not exist, skipping");
- name = strVal(llast(objname));
- args = NameListToString(list_truncate(list_copy(objname),
- list_length(objname) - 1));
+ name = strVal(llast(castNode(List, object)));
+ args = NameListToString(list_truncate(list_copy(castNode(List, object)),
+ list_length(castNode(List, object)) - 1));
}
break;
case OBJECT_POLICY:
- if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
+ if (!owningrel_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("policy \"%s\" for relation \"%s\" does not exist, skipping");
- name = strVal(llast(objname));
- args = NameListToString(list_truncate(list_copy(objname),
- list_length(objname) - 1));
+ name = strVal(llast(castNode(List, object)));
+ args = NameListToString(list_truncate(list_copy(castNode(List, object)),
+ list_length(castNode(List, object)) - 1));
}
break;
case OBJECT_EVENT_TRIGGER:
msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
break;
case OBJECT_RULE:
- if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
+ if (!owningrel_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
- name = strVal(llast(objname));
- args = NameListToString(list_truncate(list_copy(objname),
- list_length(objname) - 1));
+ name = strVal(llast(castNode(List, object)));
+ args = NameListToString(list_truncate(list_copy(castNode(List, object)),
+ list_length(castNode(List, object)) - 1));
}
break;
case OBJECT_FDW:
msg = gettext_noop("foreign-data wrapper \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
break;
case OBJECT_FOREIGN_SERVER:
msg = gettext_noop("server \"%s\" does not exist, skipping");
- name = NameListToString(objname);
+ name = strVal((Value *) object);
break;
case OBJECT_OPCLASS:
{
- List *opcname = list_copy_tail(objname, 1);
+ List *opcname = list_copy_tail(castNode(List, object), 1);
if (!schema_does_not_exist_skipping(opcname, &msg, &name))
{
msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
name = NameListToString(opcname);
- args = strVal(linitial(objname));
+ args = strVal(linitial(castNode(List, object)));
}
}
break;
case OBJECT_OPFAMILY:
{
- List *opfname = list_copy_tail(objname, 1);
+ List *opfname = list_copy_tail(castNode(List, object), 1);
if (!schema_does_not_exist_skipping(opfname, &msg, &name))
{
msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
name = NameListToString(opfname);
- args = strVal(linitial(objname));
+ args = strVal(linitial(castNode(List, object)));
}
}
break;
+ case OBJECT_PUBLICATION:
+ msg = gettext_noop("publication \"%s\" does not exist, skipping");
+ name = strVal((Value *) object);
+ break;
default:
elog(ERROR, "unrecognized object type: %d", (int) objtype);
break;
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 0b58639229..51d8783fb6 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -3,7 +3,7 @@
* event_trigger.c
* PostgreSQL EVENT TRIGGER support code.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -106,11 +106,14 @@ static event_trigger_support_data event_trigger_support[] = {
{"OPERATOR CLASS", true},
{"OPERATOR FAMILY", true},
{"POLICY", true},
+ {"PUBLICATION", true},
{"ROLE", false},
{"RULE", true},
{"SCHEMA", true},
{"SEQUENCE", true},
{"SERVER", true},
+ {"STATISTICS", true},
+ {"SUBSCRIPTION", true},
{"TABLE", true},
{"TABLESPACE", false},
{"TRANSFORM", true},
@@ -403,8 +406,7 @@ insert_event_trigger_tuple(char *trigname, char *eventname, Oid evtOwner,
/* Insert heap tuple. */
tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
- trigoid = simple_heap_insert(tgrel, tuple);
- CatalogUpdateIndexes(tgrel, tuple);
+ trigoid = CatalogTupleInsert(tgrel, tuple);
heap_freetuple(tuple);
/* Depend on owner. */
@@ -483,7 +485,7 @@ RemoveEventTriggerById(Oid trigOid)
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for event trigger %u", trigOid);
- simple_heap_delete(tgrel, &tup->t_self);
+ CatalogTupleDelete(tgrel, &tup->t_self);
ReleaseSysCache(tup);
@@ -522,8 +524,7 @@ AlterEventTrigger(AlterEventTrigStmt *stmt)
evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
evtForm->evtenabled = tgenabled;
- simple_heap_update(tgrel, &tup->t_self, tup);
- CatalogUpdateIndexes(tgrel, tup);
+ CatalogTupleUpdate(tgrel, &tup->t_self, tup);
InvokeObjectPostAlterHook(EventTriggerRelationId,
trigoid, 0);
@@ -619,8 +620,7 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
errhint("The owner of an event trigger must be a superuser.")));
form->evtowner = newOwnerId;
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
/* Update owner dependency reference */
changeDependencyOnOwner(EventTriggerRelationId,
@@ -742,7 +742,7 @@ EventTriggerCommonSetup(Node *parsetree,
/*
* Filter list of event triggers by command tag, and copy them into our
- * memory context. Once we start running the command trigers, or indeed
+ * memory context. Once we start running the command triggers, or indeed
* once we do anything at all that touches the catalogs, an invalidation
* might leave cachelist pointing at garbage, so we must do this before we
* can do much else.
@@ -1018,9 +1018,7 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata)
*/
context = AllocSetContextCreate(CurrentMemoryContext,
"event trigger context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcontext = MemoryContextSwitchTo(context);
/* Call each event trigger. */
@@ -1105,9 +1103,13 @@ EventTriggerSupportsObjectType(ObjectType obtype)
case OBJECT_OPERATOR:
case OBJECT_OPFAMILY:
case OBJECT_POLICY:
+ case OBJECT_PUBLICATION:
+ case OBJECT_PUBLICATION_REL:
case OBJECT_RULE:
case OBJECT_SCHEMA:
case OBJECT_SEQUENCE:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_STATISTIC_EXT:
case OBJECT_TABCONSTRAINT:
case OBJECT_TABLE:
case OBJECT_TRANSFORM:
@@ -1120,8 +1122,15 @@ EventTriggerSupportsObjectType(ObjectType obtype)
case OBJECT_USER_MAPPING:
case OBJECT_VIEW:
return true;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new ObjectType hasn't been handled above.
+ */
}
- return true;
+
+ /* Shouldn't get here, but if we do, say "no support" */
+ return false;
}
/*
@@ -1153,12 +1162,13 @@ EventTriggerSupportsObjectClass(ObjectClass objclass)
case OCLASS_OPERATOR:
case OCLASS_OPCLASS:
case OCLASS_OPFAMILY:
+ case OCLASS_AM:
case OCLASS_AMOP:
case OCLASS_AMPROC:
case OCLASS_REWRITE:
case OCLASS_TRIGGER:
case OCLASS_SCHEMA:
- case OCLASS_TRANSFORM:
+ case OCLASS_STATISTIC_EXT:
case OCLASS_TSPARSER:
case OCLASS_TSDICT:
case OCLASS_TSTEMPLATE:
@@ -1174,11 +1184,20 @@ EventTriggerSupportsObjectClass(ObjectClass objclass)
case OCLASS_PGXC_GROUP:
#endif
case OCLASS_POLICY:
- case OCLASS_AM:
+ case OCLASS_PUBLICATION:
+ case OCLASS_PUBLICATION_REL:
+ case OCLASS_SUBSCRIPTION:
+ case OCLASS_TRANSFORM:
return true;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
}
- return true;
+ /* Shouldn't get here, but if we do, say "no support" */
+ return false;
}
bool
@@ -1203,10 +1222,15 @@ EventTriggerSupportsGrantObjectType(GrantObjectType objtype)
case ACL_OBJECT_NAMESPACE:
case ACL_OBJECT_TYPE:
return true;
- default:
- Assert(false);
- return true;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new ACL class hasn't been handled above.
+ */
}
+
+ /* Shouldn't get here, but if we do, say "no support" */
+ return false;
}
/*
@@ -1231,9 +1255,7 @@ EventTriggerBeginCompleteQuery(void)
cxt = AllocSetContextCreate(TopMemoryContext,
"event trigger state",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
state = MemoryContextAlloc(cxt, sizeof(EventTriggerQueryState));
state->cxt = cxt;
slist_init(&(state->SQLDropList));
@@ -1870,7 +1892,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
OperatorFamilyRelationId, opfamoid);
command->d.opfam.operators = operators;
command->d.opfam.procedures = procedures;
- command->parsetree = copyObject(stmt);
+ command->parsetree = (Node *) copyObject(stmt);
currentEventTriggerState->commandList =
lappend(currentEventTriggerState->commandList, command);
@@ -1903,7 +1925,7 @@ EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
OperatorClassRelationId, opcoid);
command->d.createopc.operators = operators;
command->d.createopc.procedures = procedures;
- command->parsetree = copyObject(stmt);
+ command->parsetree = (Node *) copyObject(stmt);
currentEventTriggerState->commandList =
lappend(currentEventTriggerState->commandList, command);
@@ -1938,7 +1960,7 @@ EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
command->d.atscfg.ndicts = ndicts;
- command->parsetree = copyObject(stmt);
+ command->parsetree = (Node *) copyObject(stmt);
currentEventTriggerState->commandList =
lappend(currentEventTriggerState->commandList, command);
@@ -1968,7 +1990,7 @@ EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
command->type = SCT_AlterDefaultPrivileges;
command->d.defprivs.objtype = stmt->action->objtype;
command->in_extension = creating_extension;
- command->parsetree = copyObject(stmt);
+ command->parsetree = (Node *) copyObject(stmt);
currentEventTriggerState->commandList =
lappend(currentEventTriggerState->commandList, command);
@@ -2230,35 +2252,50 @@ stringify_grantobjtype(GrantObjectType objtype)
return "TABLESPACE";
case ACL_OBJECT_TYPE:
return "TYPE";
- default:
- elog(ERROR, "unrecognized type %d", objtype);
- return "???"; /* keep compiler quiet */
}
+
+ elog(ERROR, "unrecognized grant object type: %d", (int) objtype);
+ return "???"; /* keep compiler quiet */
}
/*
* Return the GrantObjectType as a string; as above, but use the spelling
- * in ALTER DEFAULT PRIVILEGES commands instead.
+ * in ALTER DEFAULT PRIVILEGES commands instead. Generally this is just
+ * the plural.
*/
static const char *
stringify_adefprivs_objtype(GrantObjectType objtype)
{
switch (objtype)
{
+ case ACL_OBJECT_COLUMN:
+ return "COLUMNS";
case ACL_OBJECT_RELATION:
return "TABLES";
- break;
- case ACL_OBJECT_FUNCTION:
- return "FUNCTIONS";
- break;
case ACL_OBJECT_SEQUENCE:
return "SEQUENCES";
- break;
+ case ACL_OBJECT_DATABASE:
+ return "DATABASES";
+ case ACL_OBJECT_DOMAIN:
+ return "DOMAINS";
+ case ACL_OBJECT_FDW:
+ return "FOREIGN DATA WRAPPERS";
+ case ACL_OBJECT_FOREIGN_SERVER:
+ return "FOREIGN SERVERS";
+ case ACL_OBJECT_FUNCTION:
+ return "FUNCTIONS";
+ case ACL_OBJECT_LANGUAGE:
+ return "LANGUAGES";
+ case ACL_OBJECT_LARGEOBJECT:
+ return "LARGE OBJECTS";
+ case ACL_OBJECT_NAMESPACE:
+ return "SCHEMAS";
+ case ACL_OBJECT_TABLESPACE:
+ return "TABLESPACES";
case ACL_OBJECT_TYPE:
return "TYPES";
- break;
- default:
- elog(ERROR, "unrecognized type %d", objtype);
- return "???"; /* keep compiler quiet */
}
+
+ elog(ERROR, "unrecognized grant object type: %d", (int) objtype);
+ return "???"; /* keep compiler quiet */
}
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index cdc0fe8f0c..1bb5d7582f 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4,7 +4,7 @@
* Explain query execution plans
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
@@ -60,8 +60,10 @@ explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
#define X_CLOSE_IMMEDIATE 2
#define X_NOWHITESPACE 4
-static void ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
- const char *queryString, ParamListInfo params);
+static void ExplainOneQuery(Query *query, int cursorOptions,
+ IntoClause *into, ExplainState *es,
+ const char *queryString, ParamListInfo params,
+ QueryEnvironment *queryEnv);
static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
ExplainState *es);
static double elapsed_time(instr_time *starttime);
@@ -154,14 +156,16 @@ static void escape_yaml(StringInfo buf, const char *str);
* execute an EXPLAIN command
*/
void
-ExplainQuery(ExplainStmt *stmt, const char *queryString,
- ParamListInfo params, DestReceiver *dest)
+ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
+ ParamListInfo params, QueryEnvironment *queryEnv,
+ DestReceiver *dest)
{
ExplainState *es = NewExplainState();
TupOutputState *tstate;
List *rewritten;
ListCell *lc;
bool timing_set = false;
+ bool summary_set = false;
/* Parse options list. */
foreach(lc, stmt->options)
@@ -187,6 +191,11 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
timing_set = true;
es->timing = defGetBoolean(opt);
}
+ else if (strcmp(opt->defname, "summary") == 0)
+ {
+ summary_set = true;
+ es->summary = defGetBoolean(opt);
+ }
else if (strcmp(opt->defname, "format") == 0)
{
char *p = defGetString(opt);
@@ -203,13 +212,15 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
- opt->defname, p)));
+ opt->defname, p),
+ parser_errposition(pstate, opt->location)));
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized EXPLAIN option \"%s\"",
- opt->defname)));
+ opt->defname),
+ parser_errposition(pstate, opt->location)));
}
if (es->buffers && !es->analyze)
@@ -226,8 +237,8 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("EXPLAIN option TIMING requires ANALYZE")));
- /* currently, summary option is not exposed to users; just set it */
- es->summary = es->analyze;
+ /* if the summary was not set explicitly, set default value */
+ es->summary = (summary_set) ? es->summary : es->analyze;
/*
* Parse analysis was done already, but we still have to run the rule
@@ -241,8 +252,7 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
* executed repeatedly. (See also the same hack in DECLARE CURSOR and
* PREPARE.) XXX FIXME someday.
*/
- Assert(IsA(stmt->query, Query));
- rewritten = QueryRewrite((Query *) copyObject(stmt->query));
+ rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
/* emit opening boilerplate */
ExplainBeginOutput(es);
@@ -263,8 +273,9 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
/* Explain every plan */
foreach(l, rewritten)
{
- ExplainOneQuery((Query *) lfirst(l), NULL, es,
- queryString, params);
+ ExplainOneQuery(lfirst_node(Query, l),
+ CURSOR_OPT_PARALLEL_OK, NULL, es,
+ queryString, params, queryEnv);
/* Separate plans with an appropriate separator */
if (lnext(l) != NULL)
@@ -350,8 +361,10 @@ ExplainResultDesc(ExplainStmt *stmt)
* "into" is NULL unless we are explaining the contents of a CreateTableAsStmt.
*/
static void
-ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
- const char *queryString, ParamListInfo params)
+ExplainOneQuery(Query *query, int cursorOptions,
+ IntoClause *into, ExplainState *es,
+ const char *queryString, ParamListInfo params,
+ QueryEnvironment *queryEnv)
{
/* planner will not cope with utility statements */
if (query->commandType == CMD_UTILITY)
@@ -366,18 +379,19 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
{
List *rewritten = QueryRewriteCTAS(query);
Assert(list_length(rewritten) == 1);
- ExplainOneQuery((Query *) linitial(rewritten), into, es,
- queryString, params);
+ ExplainOneQuery((Query *) linitial(rewritten), cursorOptions,
+ into, es, queryString, params, queryEnv);
}
else
ExplainOneUtility(query->utilityStmt, into, es,
- queryString, params);
+ queryString, params, queryEnv);
return;
}
/* if an advisor plugin is present, let it manage things */
if (ExplainOneQuery_hook)
- (*ExplainOneQuery_hook) (query, into, es, queryString, params);
+ (*ExplainOneQuery_hook) (query, cursorOptions, into, es,
+ queryString, params);
else
{
PlannedStmt *plan;
@@ -387,13 +401,14 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
INSTR_TIME_SET_CURRENT(planstart);
/* plan the query */
- plan = pg_plan_query(query, into ? 0 : CURSOR_OPT_PARALLEL_OK, params);
+ plan = pg_plan_query(query, cursorOptions, params);
INSTR_TIME_SET_CURRENT(planduration);
INSTR_TIME_SUBTRACT(planduration, planstart);
/* run it (if needed) and produce output */
- ExplainOnePlan(plan, into, es, queryString, params, &planduration);
+ ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
+ &planduration);
}
}
@@ -410,7 +425,8 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
*/
void
ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
- const char *queryString, ParamListInfo params)
+ const char *queryString, ParamListInfo params,
+ QueryEnvironment *queryEnv)
{
if (utilityStmt == NULL)
return;
@@ -421,19 +437,40 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
* We have to rewrite the contained SELECT and then pass it back to
* ExplainOneQuery. It's probably not really necessary to copy the
* contained parsetree another time, but let's be safe.
+ *
+ * Like ExecCreateTableAs, disallow parallelism in the plan.
*/
CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
List *rewritten;
- Assert(IsA(ctas->query, Query));
- rewritten = QueryRewrite((Query *) copyObject(ctas->query));
+ rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
+ Assert(list_length(rewritten) == 1);
+ ExplainOneQuery(linitial_node(Query, rewritten),
+ 0, ctas->into, es,
+ queryString, params, queryEnv);
+ }
+ else if (IsA(utilityStmt, DeclareCursorStmt))
+ {
+ /*
+ * Likewise for DECLARE CURSOR.
+ *
+ * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
+ * actually run the query. This is different from pre-8.3 behavior
+ * but seems more useful than not running the query. No cursor will
+ * be created, however.
+ */
+ DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
+ List *rewritten;
+
+ rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
Assert(list_length(rewritten) == 1);
- ExplainOneQuery((Query *) linitial(rewritten), ctas->into, es,
- queryString, params);
+ ExplainOneQuery(linitial_node(Query, rewritten),
+ dcs->options, NULL, es,
+ queryString, params, queryEnv);
}
else if (IsA(utilityStmt, ExecuteStmt))
ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
- queryString, params);
+ queryString, params, queryEnv);
else if (IsA(utilityStmt, NotifyStmt))
{
if (es->format == EXPLAIN_FORMAT_TEXT)
@@ -459,11 +496,6 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
* "into" is NULL unless we are explaining the contents of a CreateTableAsStmt,
* in which case executing the query should result in creating that table.
*
- * Since we ignore any DeclareCursorStmt that might be attached to the query,
- * if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll actually run the
- * query. This is different from pre-8.3 behavior but seems more useful than
- * not running the query. No cursor will be created, however.
- *
* This is exported because it's called back from prepare.c in the
* EXPLAIN EXECUTE case, and because an index advisor plugin would need
* to call it.
@@ -471,7 +503,7 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
void
ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
const char *queryString, ParamListInfo params,
- const instr_time *planduration)
+ QueryEnvironment *queryEnv, const instr_time *planduration)
{
DestReceiver *dest;
QueryDesc *queryDesc;
@@ -480,6 +512,8 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
int eflags;
int instrument_option = 0;
+ Assert(plannedstmt->commandType != CMD_UTILITY);
+
if (es->analyze && es->timing)
instrument_option |= INSTRUMENT_TIMER;
else if (es->analyze)
@@ -514,7 +548,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
/* Create a QueryDesc for the query */
queryDesc = CreateQueryDesc(plannedstmt, queryString,
GetActiveSnapshot(), InvalidSnapshot,
- dest, params, instrument_option);
+ dest, params, queryEnv, instrument_option);
/* Select execution options */
if (es->analyze)
@@ -539,7 +573,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
dir = ForwardScanDirection;
/* run the plan */
- ExecutorRun(queryDesc, dir, 0L);
+ ExecutorRun(queryDesc, dir, 0L, true);
/* run cleanup too */
ExecutorFinish(queryDesc);
@@ -586,7 +620,13 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
totaltime += elapsed_time(&starttime);
- if (es->summary)
+ /*
+ * We only report execution time if we actually ran the query (that is,
+ * the user specified ANALYZE), and if summary reporting is enabled (the
+ * user can set SUMMARY OFF to not have the timing information included in
+ * the output). By default, ANALYZE sets SUMMARY to true.
+ */
+ if (es->summary && es->analyze)
{
if (es->format == EXPLAIN_FORMAT_TEXT)
appendStringInfo(es->str, "Execution time: %.3f ms\n",
@@ -796,8 +836,10 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
case T_TidScan:
case T_SubqueryScan:
case T_FunctionScan:
+ case T_TableFuncScan:
case T_ValuesScan:
case T_CteScan:
+ case T_NamedTuplestoreScan:
case T_WorkTableScan:
*rels_used = bms_add_member(*rels_used,
((Scan *) plan)->scanrelid);
@@ -864,6 +906,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
case T_Result:
pname = sname = "Result";
break;
+ case T_ProjectSet:
+ pname = sname = "ProjectSet";
+ break;
case T_ModifyTable:
sname = "ModifyTable";
switch (((ModifyTable *) plan)->operation)
@@ -917,6 +962,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
case T_Gather:
pname = sname = "Gather";
break;
+ case T_GatherMerge:
+ pname = sname = "Gather Merge";
+ break;
case T_IndexScan:
pname = sname = "Index Scan";
break;
@@ -938,12 +986,18 @@ ExplainNode(PlanState *planstate, List *ancestors,
case T_FunctionScan:
pname = sname = "Function Scan";
break;
+ case T_TableFuncScan:
+ pname = sname = "Table Function Scan";
+ break;
case T_ValuesScan:
pname = sname = "Values Scan";
break;
case T_CteScan:
pname = sname = "CTE Scan";
break;
+ case T_NamedTuplestoreScan:
+ pname = sname = "Named Tuplestore Scan";
+ break;
case T_WorkTableScan:
pname = sname = "WorkTable Scan";
break;
@@ -1018,6 +1072,10 @@ ExplainNode(PlanState *planstate, List *ancestors,
pname = "HashAggregate";
strategy = "Hashed";
break;
+ case AGG_MIXED:
+ pname = "MixedAggregate";
+ strategy = "Mixed";
+ break;
default:
pname = "Aggregate ???";
strategy = "???";
@@ -1125,6 +1183,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
case T_TidScan:
case T_SubqueryScan:
case T_FunctionScan:
+ case T_TableFuncScan:
case T_ValuesScan:
case T_CteScan:
case T_WorkTableScan:
@@ -1398,6 +1457,23 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (es->verbose)
show_plan_tlist(planstate, ancestors, es);
+ /* unique join */
+ switch (nodeTag(plan))
+ {
+ case T_NestLoop:
+ case T_MergeJoin:
+ case T_HashJoin:
+ /* try not to be too chatty about this in text mode */
+ if (es->format != EXPLAIN_FORMAT_TEXT ||
+ (es->verbose && ((Join *) plan)->inner_unique))
+ ExplainPropertyBool("Inner Unique",
+ ((Join *) plan)->inner_unique,
+ es);
+ break;
+ default:
+ break;
+ }
+
/* quals, sort keys, etc */
switch (nodeTag(plan))
{
@@ -1501,6 +1577,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
case T_SeqScan:
case T_ValuesScan:
case T_CteScan:
+ case T_NamedTuplestoreScan:
case T_WorkTableScan:
case T_SubqueryScan:
show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
@@ -1530,6 +1607,26 @@ ExplainNode(PlanState *planstate, List *ancestors,
ExplainPropertyBool("Single Copy", gather->single_copy, es);
}
break;
+ case T_GatherMerge:
+ {
+ GatherMerge *gm = (GatherMerge *) plan;
+
+ show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
+ if (plan->qual)
+ show_instrumentation_count("Rows Removed by Filter", 1,
+ planstate, es);
+ ExplainPropertyInteger("Workers Planned",
+ gm->num_workers, es);
+ if (es->analyze)
+ {
+ int nworkers;
+
+ nworkers = ((GatherMergeState *) planstate)->nworkers_launched;
+ ExplainPropertyInteger("Workers Launched",
+ nworkers, es);
+ }
+ }
+ break;
case T_FunctionScan:
if (es->verbose)
{
@@ -1552,6 +1649,20 @@ ExplainNode(PlanState *planstate, List *ancestors,
show_instrumentation_count("Rows Removed by Filter", 1,
planstate, es);
break;
+ case T_TableFuncScan:
+ if (es->verbose)
+ {
+ TableFunc *tablefunc = ((TableFuncScan *) plan)->tablefunc;
+
+ show_expression((Node *) tablefunc,
+ "Table Function Call", planstate, ancestors,
+ es->verbose, es);
+ }
+ show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
+ if (plan->qual)
+ show_instrumentation_count("Rows Removed by Filter", 1,
+ planstate, es);
+ break;
case T_TidScan:
{
/*
@@ -1626,25 +1737,25 @@ ExplainNode(PlanState *planstate, List *ancestors,
planstate, es);
break;
case T_Agg:
- show_agg_keys((AggState *) planstate, ancestors, es);
+ show_agg_keys(castNode(AggState, planstate), ancestors, es);
show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
if (plan->qual)
show_instrumentation_count("Rows Removed by Filter", 1,
planstate, es);
break;
case T_Group:
- show_group_keys((GroupState *) planstate, ancestors, es);
+ show_group_keys(castNode(GroupState, planstate), ancestors, es);
show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
if (plan->qual)
show_instrumentation_count("Rows Removed by Filter", 1,
planstate, es);
break;
case T_Sort:
- show_sort_keys((SortState *) planstate, ancestors, es);
- show_sort_info((SortState *) planstate, es);
+ show_sort_keys(castNode(SortState, planstate), ancestors, es);
+ show_sort_info(castNode(SortState, planstate), es);
break;
case T_MergeAppend:
- show_merge_append_keys((MergeAppendState *) planstate,
+ show_merge_append_keys(castNode(MergeAppendState, planstate),
ancestors, es);
break;
case T_Result:
@@ -1656,11 +1767,11 @@ ExplainNode(PlanState *planstate, List *ancestors,
planstate, es);
break;
case T_ModifyTable:
- show_modifytable_info((ModifyTableState *) planstate, ancestors,
+ show_modifytable_info(castNode(ModifyTableState, planstate), ancestors,
es);
break;
case T_Hash:
- show_hash_info((HashState *) planstate, es);
+ show_hash_info(castNode(HashState, planstate), es);
break;
default:
break;
@@ -2082,6 +2193,19 @@ show_grouping_set_keys(PlanState *planstate,
ListCell *lc;
List *gsets = aggnode->groupingSets;
AttrNumber *keycols = aggnode->grpColIdx;
+ const char *keyname;
+ const char *keysetname;
+
+ if (aggnode->aggstrategy == AGG_HASHED || aggnode->aggstrategy == AGG_MIXED)
+ {
+ keyname = "Hash Key";
+ keysetname = "Hash Keys";
+ }
+ else
+ {
+ keyname = "Group Key";
+ keysetname = "Group Keys";
+ }
ExplainOpenGroup("Grouping Set", NULL, true, es);
@@ -2096,7 +2220,7 @@ show_grouping_set_keys(PlanState *planstate,
es->indent++;
}
- ExplainOpenGroup("Group Keys", "Group Keys", false, es);
+ ExplainOpenGroup(keysetname, keysetname, false, es);
foreach(lc, gsets)
{
@@ -2120,12 +2244,12 @@ show_grouping_set_keys(PlanState *planstate,
}
if (!result && es->format == EXPLAIN_FORMAT_TEXT)
- ExplainPropertyText("Group Key", "()", es);
+ ExplainPropertyText(keyname, "()", es);
else
- ExplainPropertyListNested("Group Key", result, es);
+ ExplainPropertyListNested(keyname, result, es);
}
- ExplainCloseGroup("Group Keys", "Group Keys", false, es);
+ ExplainCloseGroup(keysetname, keysetname, false, es);
if (sortnode && es->format == EXPLAIN_FORMAT_TEXT)
es->indent--;
@@ -2338,7 +2462,6 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate,
static void
show_sort_info(SortState *sortstate, ExplainState *es)
{
- Assert(IsA(sortstate, SortState));
if (es->analyze && sortstate->sort_Done &&
sortstate->tuplesortstate != NULL)
{
@@ -2372,7 +2495,6 @@ show_hash_info(HashState *hashstate, ExplainState *es)
{
HashJoinTable hashtable;
- Assert(IsA(hashstate, HashState));
hashtable = hashstate->hashtable;
if (hashtable)
@@ -2753,6 +2875,11 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
objecttag = "Function Name";
}
break;
+ case T_TableFuncScan:
+ Assert(rte->rtekind == RTE_TABLEFUNC);
+ objectname = "xmltable";
+ objecttag = "Table Function Name";
+ break;
case T_ValuesScan:
Assert(rte->rtekind == RTE_VALUES);
break;
@@ -2763,6 +2890,11 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
objectname = rte->ctename;
objecttag = "CTE Name";
break;
+ case T_NamedTuplestoreScan:
+ Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
+ objectname = rte->enrname;
+ objecttag = "Tuplestore Name";
+ break;
case T_WorkTableScan:
/* Assert it's on a self-reference CTE */
Assert(rte->rtekind == RTE_CTE);
@@ -2997,7 +3129,7 @@ ExplainSubPlans(List *plans, List *ancestors,
foreach(lst, plans)
{
SubPlanState *sps = (SubPlanState *) lfirst(lst);
- SubPlan *sp = (SubPlan *) sps->xprstate.expr;
+ SubPlan *sp = sps->subplan;
/*
* There can be multiple SubPlan nodes referencing the same physical
@@ -3669,13 +3801,15 @@ ExplainRemoteQuery(RemoteQuery *plan, PlanState *planstate, List *ancestors, Exp
* Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally
* add.
*
- * XML tag names can't contain white space, so we replace any spaces in
- * "tagname" with dashes.
+ * XML restricts tag names more than our other output formats, eg they can't
+ * contain white space or slashes. Replace invalid characters with dashes,
+ * so that for example "I/O Read Time" becomes "I-O-Read-Time".
*/
static void
ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
{
const char *s;
+ const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
if ((flags & X_NOWHITESPACE) == 0)
appendStringInfoSpaces(es->str, 2 * es->indent);
@@ -3683,7 +3817,7 @@ ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
if ((flags & X_CLOSING) != 0)
appendStringInfoCharMacro(es->str, '/');
for (s = tagname; *s; s++)
- appendStringInfoCharMacro(es->str, (*s == ' ') ? '-' : *s);
+ appendStringInfoChar(es->str, strchr(valid, *s) ? *s : '-');
if ((flags & X_CLOSE_IMMEDIATE) != 0)
appendStringInfoString(es->str, " /");
appendStringInfoCharMacro(es->str, '>');
@@ -3734,7 +3868,7 @@ ExplainYAMLLineStarting(ExplainState *es)
}
/*
- * YAML is a superset of JSON; unfortuantely, the YAML quoting rules are
+ * YAML is a superset of JSON; unfortunately, the YAML quoting rules are
* ridiculously complicated -- as documented in sections 5.3 and 7.3.3 of
* http://yaml.org/spec/1.2/spec.html -- so we chose to just quote everything.
* Empty strings, strings with leading or trailing whitespace, and strings
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index be8641b573..fa79e71955 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -12,7 +12,7 @@
* postgresql.conf and recovery.conf. An extension also has an installation
* script file, containing SQL commands to create the extension's objects.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -52,6 +52,7 @@
#include "nodes/makefuncs.h"
#include "storage/fd.h"
#include "tcop/utility.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
@@ -59,6 +60,7 @@
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
+#include "utils/varlena.h"
/* Globally visible state variables */
@@ -100,14 +102,25 @@ typedef struct ExtensionVersionInfo
static List *find_update_path(List *evi_list,
ExtensionVersionInfo *evi_start,
ExtensionVersionInfo *evi_target,
+ bool reject_indirect,
bool reinitialize);
+static Oid get_required_extension(char *reqExtensionName,
+ char *extensionName,
+ char *origSchemaName,
+ bool cascade,
+ List *parents,
+ bool is_create);
static void get_available_versions_for_extension(ExtensionControlFile *pcontrol,
Tuplestorestate *tupstore,
TupleDesc tupdesc);
+static Datum convert_requires_to_datum(List *requires);
static void ApplyExtensionUpdates(Oid extensionOid,
ExtensionControlFile *pcontrol,
const char *initialVersion,
- List *updateVersions);
+ List *updateVersions,
+ char *origSchemaName,
+ bool cascade,
+ bool is_create);
static char *read_whole_file(const char *filename, int *length);
@@ -702,42 +715,40 @@ execute_sql_string(const char *sql, const char *filename)
*/
forboth(lc1, raw_parsetree_list, lc3, querysource_list)
{
- Node *parsetree = (Node *) lfirst(lc1);
+ RawStmt *parsetree = lfirst_node(RawStmt, lc1);
char *querysource = (char *) lfirst(lc3);
List *stmt_list;
ListCell *lc2;
+ /* Be sure parser can see any DDL done so far */
+ CommandCounterIncrement();
+
stmt_list = pg_analyze_and_rewrite(parsetree,
querysource,
NULL,
- 0);
+ 0,
+ NULL);
stmt_list = pg_plan_queries(stmt_list, CURSOR_OPT_PARALLEL_OK, NULL);
foreach(lc2, stmt_list)
{
- Node *stmt = (Node *) lfirst(lc2);
-
- if (IsA(stmt, TransactionStmt))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("transaction control statements are not allowed within an extension script")));
+ PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
CommandCounterIncrement();
PushActiveSnapshot(GetTransactionSnapshot());
- if (IsA(stmt, PlannedStmt) &&
- ((PlannedStmt *) stmt)->utilityStmt == NULL)
+ if (stmt->utilityStmt == NULL)
{
QueryDesc *qdesc;
- qdesc = CreateQueryDesc((PlannedStmt *) stmt,
+ qdesc = CreateQueryDesc(stmt,
querysource,
GetActiveSnapshot(), NULL,
- dest, NULL, 0);
+ dest, NULL, NULL, 0);
ExecutorStart(qdesc, 0);
- ExecutorRun(qdesc, ForwardScanDirection, 0);
+ ExecutorRun(qdesc, ForwardScanDirection, 0, true);
ExecutorFinish(qdesc);
ExecutorEnd(qdesc);
@@ -745,10 +756,16 @@ execute_sql_string(const char *sql, const char *filename)
}
else
{
+ if (IsA(stmt->utilityStmt, TransactionStmt))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("transaction control statements are not allowed within an extension script")));
+
ProcessUtility(stmt,
querysource,
PROCESS_UTILITY_QUERY,
NULL,
+ NULL,
dest,
#ifdef PGXC
true, /* this is created at remote node level */
@@ -1076,7 +1093,7 @@ identify_update_path(ExtensionControlFile *control,
evi_target = get_ext_ver_info(newVersion, &evi_list);
/* Find shortest path */
- result = find_update_path(evi_list, evi_start, evi_target, false);
+ result = find_update_path(evi_list, evi_start, evi_target, false, false);
if (result == NIL)
ereport(ERROR,
@@ -1091,9 +1108,13 @@ identify_update_path(ExtensionControlFile *control,
* Apply Dijkstra's algorithm to find the shortest path from evi_start to
* evi_target.
*
+ * If reject_indirect is true, ignore paths that go through installable
+ * versions. This saves work when the caller will consider starting from
+ * all installable versions anyway.
+ *
* If reinitialize is false, assume the ExtensionVersionInfo list has not
* been used for this before, and the initialization done by get_ext_ver_info
- * is still good.
+ * is still good. Otherwise, reinitialize all transient fields used here.
*
* Result is a List of names of versions to transition through (the initial
* version is *not* included). Returns NIL if no such path.
@@ -1102,6 +1123,7 @@ static List *
find_update_path(List *evi_list,
ExtensionVersionInfo *evi_start,
ExtensionVersionInfo *evi_target,
+ bool reject_indirect,
bool reinitialize)
{
List *result;
@@ -1110,6 +1132,8 @@ find_update_path(List *evi_list,
/* Caller error if start == target */
Assert(evi_start != evi_target);
+ /* Caller error if reject_indirect and target is installable */
+ Assert(!(reject_indirect && evi_target->installable));
if (reinitialize)
{
@@ -1136,6 +1160,9 @@ find_update_path(List *evi_list,
ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
int newdist;
+ /* if reject_indirect, treat installable versions as unreachable */
+ if (reject_indirect && evi2->installable)
+ continue;
newdist = evi->distance + 1;
if (newdist < evi2->distance)
{
@@ -1172,25 +1199,85 @@ find_update_path(List *evi_list,
}
/*
+ * Given a target version that is not directly installable, find the
+ * best installation sequence starting from a directly-installable version.
+ *
+ * evi_list: previously-collected version update graph
+ * evi_target: member of that list that we want to reach
+ *
+ * Returns the best starting-point version, or NULL if there is none.
+ * On success, *best_path is set to the path from the start point.
+ *
+ * If there's more than one possible start point, prefer shorter update paths,
+ * and break any ties arbitrarily on the basis of strcmp'ing the starting
+ * versions' names.
+ */
+static ExtensionVersionInfo *
+find_install_path(List *evi_list, ExtensionVersionInfo *evi_target,
+ List **best_path)
+{
+ ExtensionVersionInfo *evi_start = NULL;
+ ListCell *lc;
+
+ *best_path = NIL;
+
+ /*
+ * We don't expect to be called for an installable target, but if we are,
+ * the answer is easy: just start from there, with an empty update path.
+ */
+ if (evi_target->installable)
+ return evi_target;
+
+ /* Consider all installable versions as start points */
+ foreach(lc, evi_list)
+ {
+ ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc);
+ List *path;
+
+ if (!evi1->installable)
+ continue;
+
+ /*
+ * Find shortest path from evi1 to evi_target; but no need to consider
+ * paths going through other installable versions.
+ */
+ path = find_update_path(evi_list, evi1, evi_target, true, true);
+ if (path == NIL)
+ continue;
+
+ /* Remember best path */
+ if (evi_start == NULL ||
+ list_length(path) < list_length(*best_path) ||
+ (list_length(path) == list_length(*best_path) &&
+ strcmp(evi_start->name, evi1->name) < 0))
+ {
+ evi_start = evi1;
+ *best_path = path;
+ }
+ }
+
+ return evi_start;
+}
+
+/*
* CREATE EXTENSION worker
*
- * When CASCADE is specified CreateExtensionInternal() recurses if required
- * extensions need to be installed. To sanely handle cyclic dependencies
- * cascade_parent contains the dependency chain leading to the current
- * invocation; thus allowing to error out if there's a cyclic dependency.
+ * When CASCADE is specified, CreateExtensionInternal() recurses if required
+ * extensions need to be installed. To sanely handle cyclic dependencies,
+ * the "parents" list contains a list of names of extensions already being
+ * installed, allowing us to error out if we recurse to one of those.
*/
static ObjectAddress
-CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
+CreateExtensionInternal(char *extensionName,
+ char *schemaName,
+ char *versionName,
+ char *oldVersionName,
+ bool cascade,
+ List *parents,
+ bool is_create)
{
- DefElem *d_schema = NULL;
- DefElem *d_new_version = NULL;
- DefElem *d_old_version = NULL;
- DefElem *d_cascade = NULL;
- char *schemaName = NULL;
+ char *origSchemaName = schemaName;
Oid schemaOid = InvalidOid;
- char *versionName;
- char *oldVersionName;
- bool cascade = false;
Oid extowner = GetUserId();
ExtensionControlFile *pcontrol;
ExtensionControlFile *control;
@@ -1198,83 +1285,43 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
List *requiredExtensions;
List *requiredSchemas;
Oid extensionOid;
- ListCell *lc;
ObjectAddress address;
+ ListCell *lc;
/*
* Read the primary control file. Note we assume that it does not contain
* any non-ASCII data, so there is no need to worry about encoding at this
* point.
*/
- pcontrol = read_extension_control_file(stmt->extname);
-
- /*
- * Read the statement option list
- */
- foreach(lc, stmt->options)
- {
- DefElem *defel = (DefElem *) lfirst(lc);
-
- if (strcmp(defel->defname, "schema") == 0)
- {
- if (d_schema)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
- d_schema = defel;
- }
- else if (strcmp(defel->defname, "new_version") == 0)
- {
- if (d_new_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
- d_new_version = defel;
- }
- else if (strcmp(defel->defname, "old_version") == 0)
- {
- if (d_old_version)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
- d_old_version = defel;
- }
- else if (strcmp(defel->defname, "cascade") == 0)
- {
- if (d_cascade)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
- d_cascade = defel;
- cascade = defGetBoolean(d_cascade);
- }
- else
- elog(ERROR, "unrecognized option: %s", defel->defname);
- }
+ pcontrol = read_extension_control_file(extensionName);
/*
* Determine the version to install
*/
- if (d_new_version && d_new_version->arg)
- versionName = strVal(d_new_version->arg);
- else if (pcontrol->default_version)
- versionName = pcontrol->default_version;
- else
+ if (versionName == NULL)
{
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("version to install must be specified")));
- versionName = NULL; /* keep compiler quiet */
+ if (pcontrol->default_version)
+ versionName = pcontrol->default_version;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("version to install must be specified")));
}
check_valid_version_name(versionName);
/*
- * Determine the (unpackaged) version to update from, if any, and then
- * figure out what sequence of update scripts we need to apply.
+ * Figure out which script(s) we need to run to install the desired
+ * version of the extension. If we do not have a script that directly
+ * does what is needed, we try to find a sequence of update scripts that
+ * will get us there.
*/
- if (d_old_version && d_old_version->arg)
+ if (oldVersionName)
{
- oldVersionName = strVal(d_old_version->arg);
+ /*
+ * "FROM old_version" was specified, indicating that we're trying to
+ * update from some unpackaged version of the extension. Locate a
+ * series of update scripts that will do it.
+ */
check_valid_version_name(oldVersionName);
if (strcmp(oldVersionName, versionName) == 0)
@@ -1309,8 +1356,48 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
}
else
{
+ /*
+ * No FROM, so we're installing from scratch. If there is an install
+ * script for the desired version, we only need to run that one.
+ */
+ char *filename;
+ struct stat fst;
+
oldVersionName = NULL;
- updateVersions = NIL;
+
+ filename = get_extension_script_filename(pcontrol, NULL, versionName);
+ if (stat(filename, &fst) == 0)
+ {
+ /* Easy, no extra scripts */
+ updateVersions = NIL;
+ }
+ else
+ {
+ /* Look for best way to install this version */
+ List *evi_list;
+ ExtensionVersionInfo *evi_start;
+ ExtensionVersionInfo *evi_target;
+
+ /* Extract the version update graph from the script directory */
+ evi_list = get_ext_ver_list(pcontrol);
+
+ /* Identify the target version */
+ evi_target = get_ext_ver_info(versionName, &evi_list);
+
+ /* Identify best path to reach target */
+ evi_start = find_install_path(evi_list, evi_target,
+ &updateVersions);
+
+ /* Fail if no path ... */
+ if (evi_start == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("extension \"%s\" has no installation script nor update path for version \"%s\"",
+ pcontrol->name, versionName)));
+
+ /* Otherwise, install best starting point and then upgrade */
+ versionName = evi_start->name;
+ }
}
/*
@@ -1321,13 +1408,8 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
/*
* Determine the target schema to install the extension into
*/
- if (d_schema && d_schema->arg)
+ if (schemaName)
{
- /*
- * User given schema, CREATE EXTENSION ... WITH SCHEMA ...
- */
- schemaName = strVal(d_schema->arg);
-
/* If the user is giving us the schema name, it must exist already. */
schemaOid = get_namespace_oid(schemaName, false);
}
@@ -1363,11 +1445,8 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
csstmt->authrole = NULL; /* will be created by current user */
csstmt->schemaElts = NIL;
csstmt->if_not_exists = false;
-#ifdef PGXC
- CreateSchemaCommand(csstmt, NULL, true);
-#else
- CreateSchemaCommand(csstmt, NULL);
-#endif
+ CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
+ true, -1, -1);
/*
* CreateSchemaCommand includes CommandCounterIncrement, so new
@@ -1379,7 +1458,7 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
else if (!OidIsValid(schemaOid))
{
/*
- * Neither user nor author of the extension specified schema, use the
+ * Neither user nor author of the extension specified schema; use the
* current default creation namespace, which is the first explicit
* entry in the search_path.
*/
@@ -1409,8 +1488,8 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
*/
/*
- * Look up the prerequisite extensions, and build lists of their OIDs and
- * the OIDs of their target schemas.
+ * Look up the prerequisite extensions, install them if necessary, and
+ * build lists of their OIDs and the OIDs of their target schemas.
*/
requiredExtensions = NIL;
requiredSchemas = NIL;
@@ -1420,65 +1499,12 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
Oid reqext;
Oid reqschema;
- reqext = get_extension_oid(curreq, true);
- if (!OidIsValid(reqext))
- {
- if (cascade)
- {
- CreateExtensionStmt *ces;
- ListCell *lc;
- ObjectAddress addr;
- List *cascade_parents;
-
- /* Check extension name validity before trying to cascade */
- check_valid_extension_name(curreq);
-
- /* Check for cyclic dependency between extensions. */
- foreach(lc, parents)
- {
- char *pname = (char *) lfirst(lc);
-
- if (strcmp(pname, curreq) == 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_RECURSION),
- errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
- curreq, stmt->extname)));
- }
-
- ereport(NOTICE,
- (errmsg("installing required extension \"%s\"",
- curreq)));
-
- /* Create and execute new CREATE EXTENSION statement. */
- ces = makeNode(CreateExtensionStmt);
- ces->extname = curreq;
-
- /* Propagate the CASCADE option */
- ces->options = list_make1(d_cascade);
-
- /* Propagate the SCHEMA option if given. */
- if (d_schema && d_schema->arg)
- ces->options = lappend(ces->options, d_schema);
-
- /*
- * Pass the current list of parents + the current extension to
- * the "child" CreateExtensionInternal().
- */
- cascade_parents =
- lappend(list_copy(parents), stmt->extname);
-
- /* Create the required extension. */
- addr = CreateExtensionInternal(ces, cascade_parents);
- reqext = addr.objectId;
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("required extension \"%s\" is not installed",
- curreq),
- errhint("Use CREATE EXTENSION ... CASCADE to install required extensions too.")));
- }
-
+ reqext = get_required_extension(curreq,
+ extensionName,
+ origSchemaName,
+ cascade,
+ parents,
+ is_create);
reqschema = get_extension_schema(reqext);
requiredExtensions = lappend_oid(requiredExtensions, reqext);
requiredSchemas = lappend_oid(requiredSchemas, reqschema);
@@ -1514,17 +1540,100 @@ CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
* though a series of ALTER EXTENSION UPDATE commands were given
*/
ApplyExtensionUpdates(extensionOid, pcontrol,
- versionName, updateVersions);
+ versionName, updateVersions,
+ origSchemaName, cascade, is_create);
return address;
}
/*
+ * Get the OID of an extension listed in "requires", possibly creating it.
+ */
+static Oid
+get_required_extension(char *reqExtensionName,
+ char *extensionName,
+ char *origSchemaName,
+ bool cascade,
+ List *parents,
+ bool is_create)
+{
+ Oid reqExtensionOid;
+
+ reqExtensionOid = get_extension_oid(reqExtensionName, true);
+ if (!OidIsValid(reqExtensionOid))
+ {
+ if (cascade)
+ {
+ /* Must install it. */
+ ObjectAddress addr;
+ List *cascade_parents;
+ ListCell *lc;
+
+ /* Check extension name validity before trying to cascade. */
+ check_valid_extension_name(reqExtensionName);
+
+ /* Check for cyclic dependency between extensions. */
+ foreach(lc, parents)
+ {
+ char *pname = (char *) lfirst(lc);
+
+ if (strcmp(pname, reqExtensionName) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_RECURSION),
+ errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
+ reqExtensionName, extensionName)));
+ }
+
+ ereport(NOTICE,
+ (errmsg("installing required extension \"%s\"",
+ reqExtensionName)));
+
+ /* Add current extension to list of parents to pass down. */
+ cascade_parents = lappend(list_copy(parents), extensionName);
+
+ /*
+ * Create the required extension. We propagate the SCHEMA option
+ * if any, and CASCADE, but no other options.
+ */
+ addr = CreateExtensionInternal(reqExtensionName,
+ origSchemaName,
+ NULL,
+ NULL,
+ cascade,
+ cascade_parents,
+ is_create);
+
+ /* Get its newly-assigned OID. */
+ reqExtensionOid = addr.objectId;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("required extension \"%s\" is not installed",
+ reqExtensionName),
+ is_create ?
+ errhint("Use CREATE EXTENSION ... CASCADE to install required extensions too.") : 0));
+ }
+
+ return reqExtensionOid;
+}
+
+/*
* CREATE EXTENSION
*/
ObjectAddress
-CreateExtension(CreateExtensionStmt *stmt)
+CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
{
+ DefElem *d_schema = NULL;
+ DefElem *d_new_version = NULL;
+ DefElem *d_old_version = NULL;
+ DefElem *d_cascade = NULL;
+ char *schemaName = NULL;
+ char *versionName = NULL;
+ char *oldVersionName = NULL;
+ bool cascade = false;
+ ListCell *lc;
+
/* Check extension name validity before any filesystem access */
check_valid_extension_name(stmt->extname);
@@ -1560,9 +1669,63 @@ CreateExtension(CreateExtensionStmt *stmt)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("nested CREATE EXTENSION is not supported")));
+ /* Deconstruct the statement option list */
+ foreach(lc, stmt->options)
+ {
+ DefElem *defel = (DefElem *) lfirst(lc);
+
+ if (strcmp(defel->defname, "schema") == 0)
+ {
+ if (d_schema)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ d_schema = defel;
+ schemaName = defGetString(d_schema);
+ }
+ else if (strcmp(defel->defname, "new_version") == 0)
+ {
+ if (d_new_version)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ d_new_version = defel;
+ versionName = defGetString(d_new_version);
+ }
+ else if (strcmp(defel->defname, "old_version") == 0)
+ {
+ if (d_old_version)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ d_old_version = defel;
+ oldVersionName = defGetString(d_old_version);
+ }
+ else if (strcmp(defel->defname, "cascade") == 0)
+ {
+ if (d_cascade)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ d_cascade = defel;
+ cascade = defGetBoolean(d_cascade);
+ }
+ else
+ elog(ERROR, "unrecognized option: %s", defel->defname);
+ }
- /* Finally create the extension. */
- return CreateExtensionInternal(stmt, NIL);
+ /* Call CreateExtensionInternal to do the real work. */
+ return CreateExtensionInternal(stmt->extname,
+ schemaName,
+ versionName,
+ oldVersionName,
+ cascade,
+ NIL,
+ true);
}
/*
@@ -1620,8 +1783,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
tuple = heap_form_tuple(rel->rd_att, values, nulls);
- extensionOid = simple_heap_insert(rel, tuple);
- CatalogUpdateIndexes(rel, tuple);
+ extensionOid = CatalogTupleInsert(rel, tuple);
heap_freetuple(tuple);
heap_close(rel, RowExclusiveLock);
@@ -1702,7 +1864,7 @@ RemoveExtensionById(Oid extId)
/* We assume that there can be at most one matching tuple */
if (HeapTupleIsValid(tuple))
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
systable_endscan(scandesc);
@@ -1919,43 +2081,28 @@ get_available_versions_for_extension(ExtensionControlFile *pcontrol,
Tuplestorestate *tupstore,
TupleDesc tupdesc)
{
- int extnamelen = strlen(pcontrol->name);
- char *location;
- DIR *dir;
- struct dirent *de;
+ List *evi_list;
+ ListCell *lc;
- location = get_extension_script_directory(pcontrol);
- dir = AllocateDir(location);
- /* Note this will fail if script directory doesn't exist */
- while ((de = ReadDir(dir, location)) != NULL)
+ /* Extract the version update graph from the script directory */
+ evi_list = get_ext_ver_list(pcontrol);
+
+ /* For each installable version ... */
+ foreach(lc, evi_list)
{
+ ExtensionVersionInfo *evi = (ExtensionVersionInfo *) lfirst(lc);
ExtensionControlFile *control;
- char *vername;
Datum values[7];
bool nulls[7];
+ ListCell *lc2;
- /* must be a .sql file ... */
- if (!is_extension_script_filename(de->d_name))
- continue;
-
- /* ... matching extension name followed by separator */
- if (strncmp(de->d_name, pcontrol->name, extnamelen) != 0 ||
- de->d_name[extnamelen] != '-' ||
- de->d_name[extnamelen + 1] != '-')
- continue;
-
- /* extract version name from 'extname--something.sql' filename */
- vername = pstrdup(de->d_name + extnamelen + 2);
- *strrchr(vername, '.') = '\0';
-
- /* ignore it if it's an update script */
- if (strstr(vername, "--"))
+ if (!evi->installable)
continue;
/*
* Fetch parameters for specific version (pcontrol is not changed)
*/
- control = read_extension_aux_control_file(pcontrol, vername);
+ control = read_extension_aux_control_file(pcontrol, evi->name);
memset(values, 0, sizeof(values));
memset(nulls, 0, sizeof(nulls));
@@ -1964,7 +2111,7 @@ get_available_versions_for_extension(ExtensionControlFile *pcontrol,
values[0] = DirectFunctionCall1(namein,
CStringGetDatum(control->name));
/* version */
- values[1] = CStringGetTextDatum(vername);
+ values[1] = CStringGetTextDatum(evi->name);
/* superuser */
values[2] = BoolGetDatum(control->superuser);
/* relocatable */
@@ -1979,27 +2126,7 @@ get_available_versions_for_extension(ExtensionControlFile *pcontrol,
if (control->requires == NIL)
nulls[5] = true;
else
- {
- Datum *datums;
- int ndatums;
- ArrayType *a;
- ListCell *lc;
-
- ndatums = list_length(control->requires);
- datums = (Datum *) palloc(ndatums * sizeof(Datum));
- ndatums = 0;
- foreach(lc, control->requires)
- {
- char *curreq = (char *) lfirst(lc);
-
- datums[ndatums++] =
- DirectFunctionCall1(namein, CStringGetDatum(curreq));
- }
- a = construct_array(datums, ndatums,
- NAMEOID,
- NAMEDATALEN, false, 'c');
- values[5] = PointerGetDatum(a);
- }
+ values[5] = convert_requires_to_datum(control->requires);
/* comment */
if (control->comment == NULL)
nulls[6] = true;
@@ -2007,9 +2134,75 @@ get_available_versions_for_extension(ExtensionControlFile *pcontrol,
values[6] = CStringGetTextDatum(control->comment);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+
+ /*
+ * Find all non-directly-installable versions that would be installed
+ * starting from this version, and report them, inheriting the
+ * parameters that aren't changed in updates from this version.
+ */
+ foreach(lc2, evi_list)
+ {
+ ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
+ List *best_path;
+
+ if (evi2->installable)
+ continue;
+ if (find_install_path(evi_list, evi2, &best_path) == evi)
+ {
+ /*
+ * Fetch parameters for this version (pcontrol is not changed)
+ */
+ control = read_extension_aux_control_file(pcontrol, evi2->name);
+
+ /* name stays the same */
+ /* version */
+ values[1] = CStringGetTextDatum(evi2->name);
+ /* superuser */
+ values[2] = BoolGetDatum(control->superuser);
+ /* relocatable */
+ values[3] = BoolGetDatum(control->relocatable);
+ /* schema stays the same */
+ /* requires */
+ if (control->requires == NIL)
+ nulls[5] = true;
+ else
+ {
+ values[5] = convert_requires_to_datum(control->requires);
+ nulls[5] = false;
+ }
+ /* comment stays the same */
+
+ tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ }
+ }
}
+}
- FreeDir(dir);
+/*
+ * Convert a list of extension names to a name[] Datum
+ */
+static Datum
+convert_requires_to_datum(List *requires)
+{
+ Datum *datums;
+ int ndatums;
+ ArrayType *a;
+ ListCell *lc;
+
+ ndatums = list_length(requires);
+ datums = (Datum *) palloc(ndatums * sizeof(Datum));
+ ndatums = 0;
+ foreach(lc, requires)
+ {
+ char *curreq = (char *) lfirst(lc);
+
+ datums[ndatums++] =
+ DirectFunctionCall1(namein, CStringGetDatum(curreq));
+ }
+ a = construct_array(datums, ndatums,
+ NAMEOID,
+ NAMEDATALEN, false, 'c');
+ return PointerGetDatum(a);
}
/*
@@ -2081,7 +2274,7 @@ pg_extension_update_paths(PG_FUNCTION_ARGS)
continue;
/* Find shortest path from evi1 to evi2 */
- path = find_update_path(evi_list, evi1, evi2, true);
+ path = find_update_path(evi_list, evi1, evi2, false, true);
/* Emit result row */
memset(values, 0, sizeof(values));
@@ -2134,7 +2327,7 @@ Datum
pg_extension_config_dump(PG_FUNCTION_ARGS)
{
Oid tableoid = PG_GETARG_OID(0);
- text *wherecond = PG_GETARG_TEXT_P(1);
+ text *wherecond = PG_GETARG_TEXT_PP(1);
char *tablename;
Relation extRel;
ScanKeyData key[1];
@@ -2301,8 +2494,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
repl_val, repl_null, repl_repl);
- simple_heap_update(extRel, &extTup->t_self, extTup);
- CatalogUpdateIndexes(extRel, extTup);
+ CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
systable_endscan(extScan);
@@ -2479,8 +2671,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid)
extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
repl_val, repl_null, repl_repl);
- simple_heap_update(extRel, &extTup->t_self, extTup);
- CatalogUpdateIndexes(extRel, extTup);
+ CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
systable_endscan(extScan);
@@ -2491,9 +2682,8 @@ extension_config_remove(Oid extensionoid, Oid tableoid)
* Execute ALTER EXTENSION SET SCHEMA
*/
ObjectAddress
-AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema)
+AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
{
- char *extensionName;
Oid extensionOid;
Oid nspOid;
Oid oldNspOid = InvalidOid;
@@ -2509,12 +2699,6 @@ AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema)
ObjectAddresses *objsMoved;
ObjectAddress extAddr;
- if (list_length(names) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("extension name cannot be qualified")));
- extensionName = strVal(linitial(names));
-
extensionOid = get_extension_oid(extensionName, false);
nspOid = LookupCreationNamespace(newschema);
@@ -2660,8 +2844,7 @@ AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema)
/* Now adjust pg_extension.extnamespace */
extForm->extnamespace = nspOid;
- simple_heap_update(extRel, &extTup->t_self, extTup);
- CatalogUpdateIndexes(extRel, extTup);
+ CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
heap_close(extRel, RowExclusiveLock);
@@ -2680,7 +2863,7 @@ AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema)
* Execute ALTER EXTENSION UPDATE
*/
ObjectAddress
-ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
+ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
{
DefElem *d_new_version = NULL;
char *versionName;
@@ -2766,7 +2949,8 @@ ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
if (d_new_version)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
d_new_version = defel;
}
else
@@ -2812,7 +2996,8 @@ ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
* time
*/
ApplyExtensionUpdates(extensionOid, control,
- oldVersionName, updateVersions);
+ oldVersionName, updateVersions,
+ NULL, false, false);
ObjectAddressSet(address, ExtensionRelationId, extensionOid);
@@ -2831,7 +3016,10 @@ static void
ApplyExtensionUpdates(Oid extensionOid,
ExtensionControlFile *pcontrol,
const char *initialVersion,
- List *updateVersions)
+ List *updateVersions,
+ char *origSchemaName,
+ bool cascade,
+ bool is_create)
{
const char *oldVersionName = initialVersion;
ListCell *lcv;
@@ -2902,16 +3090,16 @@ ApplyExtensionUpdates(Oid extensionOid,
extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
values, nulls, repl);
- simple_heap_update(extRel, &extTup->t_self, extTup);
- CatalogUpdateIndexes(extRel, extTup);
+ CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
systable_endscan(extScan);
heap_close(extRel, RowExclusiveLock);
/*
- * Look up the prerequisite extensions for this version, and build
- * lists of their OIDs and the OIDs of their target schemas.
+ * Look up the prerequisite extensions for this version, install them
+ * if necessary, and build lists of their OIDs and the OIDs of their
+ * target schemas.
*/
requiredExtensions = NIL;
requiredSchemas = NIL;
@@ -2921,16 +3109,12 @@ ApplyExtensionUpdates(Oid extensionOid,
Oid reqext;
Oid reqschema;
- /*
- * We intentionally don't use get_extension_oid's default error
- * message here, because it would be confusing in this context.
- */
- reqext = get_extension_oid(curreq, true);
- if (!OidIsValid(reqext))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("required extension \"%s\" is not installed",
- curreq)));
+ reqext = get_required_extension(curreq,
+ control->name,
+ origSchemaName,
+ cascade,
+ NIL,
+ is_create);
reqschema = get_extension_schema(reqext);
requiredExtensions = lappend_oid(requiredExtensions, reqext);
requiredSchemas = lappend_oid(requiredSchemas, reqschema);
@@ -3010,7 +3194,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
* does not exist, and will also acquire a lock on the object to guard
* against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
*/
- object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
+ object = get_object_address(stmt->objtype, stmt->object,
&relation, ShareUpdateExclusiveLock, false);
Assert(object.objectSubId == 0);
@@ -3019,7 +3203,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
/* Permission check: must own target object, too */
check_object_ownership(GetUserId(), stmt->objtype, object,
- stmt->objname, stmt->objargs, relation);
+ stmt->object, relation);
/*
* Check existing extension membership.
@@ -3055,6 +3239,16 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
* OK, add the dependency.
*/
recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
+
+ /*
+ * Also record the initial ACL on the object, if any.
+ *
+ * Note that this will handle the object's ACLs, as well as any ACLs
+ * on object subIds. (In other words, when the object is a table,
+ * this will record the table's ACL and the ACLs for the columns on
+ * the table, if any).
+ */
+ recordExtObjInitPriv(object.objectId, object.classId);
}
else
{
@@ -3082,6 +3276,16 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
*/
if (object.classId == RelationRelationId)
extension_config_remove(extension.objectId, object.objectId);
+
+ /*
+ * Remove all the initial ACLs, if any.
+ *
+ * Note that this will remove the object's ACLs, as well as any ACLs
+ * on object subIds. (In other words, when the object is a table,
+ * this will remove the table's ACL and the ACLs for the columns on
+ * the table, if any).
+ */
+ removeExtObjInitPriv(object.objectId, object.classId);
}
InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index 6963855373..554656b6ec 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -3,7 +3,7 @@
* foreigncmds.c
* foreign-data wrapper/server creation/manipulation commands
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
@@ -256,8 +256,7 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI
tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
repl_repl);
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
/* Update owner dependency reference */
changeDependencyOnOwner(ForeignDataWrapperRelationId,
@@ -397,8 +396,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
repl_repl);
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
/* Update owner dependency reference */
changeDependencyOnOwner(ForeignServerRelationId, HeapTupleGetOid(tup),
@@ -629,8 +627,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
tuple = heap_form_tuple(rel->rd_att, values, nulls);
- fdwId = simple_heap_insert(rel, tuple);
- CatalogUpdateIndexes(rel, tuple);
+ fdwId = CatalogTupleInsert(rel, tuple);
heap_freetuple(tuple);
@@ -786,8 +783,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
tp = heap_modify_tuple(tp, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &tp->t_self, tp);
- CatalogUpdateIndexes(rel, tp);
+ CatalogTupleUpdate(rel, &tp->t_self, tp);
heap_freetuple(tp);
@@ -850,7 +846,7 @@ RemoveForeignDataWrapperById(Oid fdwId)
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwId);
- simple_heap_delete(rel, &tp->t_self);
+ CatalogTupleDelete(rel, &tp->t_self);
ReleaseSysCache(tp);
@@ -882,13 +878,26 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
ownerId = GetUserId();
/*
- * Check that there is no other foreign server by this name.
+ * Check that there is no other foreign server by this name. Do nothing if
+ * IF NOT EXISTS was enforced.
*/
if (GetForeignServerByName(stmt->servername, true) != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("server \"%s\" already exists",
- stmt->servername)));
+ {
+ if (stmt->if_not_exists)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("server \"%s\" already exists, skipping",
+ stmt->servername)));
+ heap_close(rel, RowExclusiveLock);
+ return InvalidObjectAddress;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("server \"%s\" already exists",
+ stmt->servername)));
+ }
/*
* Check that the FDW exists and that we have USAGE on it. Also get the
@@ -941,9 +950,7 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
tuple = heap_form_tuple(rel->rd_att, values, nulls);
- srvId = simple_heap_insert(rel, tuple);
-
- CatalogUpdateIndexes(rel, tuple);
+ srvId = CatalogTupleInsert(rel, tuple);
heap_freetuple(tuple);
@@ -1056,8 +1063,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
tp = heap_modify_tuple(tp, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &tp->t_self, tp);
- CatalogUpdateIndexes(rel, tp);
+ CatalogTupleUpdate(rel, &tp->t_self, tp);
InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
@@ -1087,7 +1093,7 @@ RemoveForeignServerById(Oid srvId)
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for foreign server %u", srvId);
- simple_heap_delete(rel, &tp->t_self);
+ CatalogTupleDelete(rel, &tp->t_self);
ReleaseSysCache(tp);
@@ -1159,12 +1165,27 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
ObjectIdGetDatum(useId),
ObjectIdGetDatum(srv->serverid));
+
if (OidIsValid(umId))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("user mapping \"%s\" already exists for server %s",
- MappingUserName(useId),
- stmt->servername)));
+ {
+ if (stmt->if_not_exists)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("user mapping for \"%s\" already exists for server %s, skipping",
+ MappingUserName(useId),
+ stmt->servername)));
+
+ heap_close(rel, RowExclusiveLock);
+ return InvalidObjectAddress;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("user mapping for \"%s\" already exists for server %s",
+ MappingUserName(useId),
+ stmt->servername)));
+ }
fdw = GetForeignDataWrapper(srv->fdwid);
@@ -1190,9 +1211,7 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
tuple = heap_form_tuple(rel->rd_att, values, nulls);
- umId = simple_heap_insert(rel, tuple);
-
- CatalogUpdateIndexes(rel, tuple);
+ umId = CatalogTupleInsert(rel, tuple);
heap_freetuple(tuple);
@@ -1256,8 +1275,8 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
if (!OidIsValid(umId))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user mapping \"%s\" does not exist for the server",
- MappingUserName(useId))));
+ errmsg("user mapping for \"%s\" does not exist for the server",
+ MappingUserName(useId))));
user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
@@ -1307,8 +1326,7 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
tp = heap_modify_tuple(tp, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &tp->t_self, tp);
- CatalogUpdateIndexes(rel, tp);
+ CatalogTupleUpdate(rel, &tp->t_self, tp);
ObjectAddressSet(address, UserMappingRelationId, umId);
@@ -1372,13 +1390,13 @@ RemoveUserMapping(DropUserMappingStmt *stmt)
if (!stmt->missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user mapping \"%s\" does not exist for the server",
- MappingUserName(useId))));
+ errmsg("user mapping for \"%s\" does not exist for the server",
+ MappingUserName(useId))));
/* IF EXISTS specified, just note it */
ereport(NOTICE,
- (errmsg("user mapping \"%s\" does not exist for the server, skipping",
- MappingUserName(useId))));
+ (errmsg("user mapping for \"%s\" does not exist for the server, skipping",
+ MappingUserName(useId))));
return InvalidOid;
}
@@ -1413,7 +1431,7 @@ RemoveUserMappingById(Oid umId)
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for user mapping %u", umId);
- simple_heap_delete(rel, &tp->t_self);
+ CatalogTupleDelete(rel, &tp->t_self);
ReleaseSysCache(tp);
@@ -1484,8 +1502,7 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid)
tuple = heap_form_tuple(ftrel->rd_att, values, nulls);
- simple_heap_insert(ftrel, tuple);
- CatalogUpdateIndexes(ftrel, tuple);
+ CatalogTupleInsert(ftrel, tuple);
heap_freetuple(tuple);
@@ -1572,7 +1589,9 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
*/
foreach(lc2, raw_parsetree_list)
{
- CreateForeignTableStmt *cstmt = lfirst(lc2);
+ RawStmt *rs = lfirst_node(RawStmt, lc2);
+ CreateForeignTableStmt *cstmt = (CreateForeignTableStmt *) rs->stmt;
+ PlannedStmt *pstmt;
/*
* Because we only allow CreateForeignTableStmt, we can skip parse
@@ -1593,14 +1612,21 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
/* Ensure creation schema is the one given in IMPORT statement */
cstmt->base.relation->schemaname = pstrdup(stmt->local_schema);
+ /* No planning needed, just make a wrapper PlannedStmt */
+ pstmt = makeNode(PlannedStmt);
+ pstmt->commandType = CMD_UTILITY;
+ pstmt->canSetTag = false;
+ pstmt->utilityStmt = (Node *) cstmt;
+ pstmt->stmt_location = rs->stmt_location;
+ pstmt->stmt_len = rs->stmt_len;
+
/* Execute statement */
- ProcessUtility((Node *) cstmt,
+ ProcessUtility(pstmt,
cmd,
PROCESS_UTILITY_SUBCOMMAND, NULL,
+ NULL,
None_Receiver,
-#ifdef XCP
false,
-#endif
NULL);
/* Be sure to advance the command counter between subcommands */
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 748c8f75d4..ffcae34189 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -5,7 +5,7 @@
* Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
* CAST commands.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -167,7 +167,6 @@ compute_return_type(TypeName *returnType, Oid languageOid,
* parameters: list of FunctionParameter structs
* languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE)
* is_aggregate: needed only to determine error handling
- * queryString: likewise, needed only for error handling
*
* Results are stored into output parameters. parameterTypes must always
* be created, but the other arrays are set to NULL if not needed.
@@ -177,10 +176,10 @@ compute_return_type(TypeName *returnType, Oid languageOid,
* else it is set to the OID of the implied result type.
*/
void
-interpret_function_parameter_list(List *parameters,
+interpret_function_parameter_list(ParseState *pstate,
+ List *parameters,
Oid languageOid,
bool is_aggregate,
- const char *queryString,
oidvector **parameterTypes,
ArrayType **allParameterTypes,
ArrayType **parameterModes,
@@ -201,7 +200,6 @@ interpret_function_parameter_list(List *parameters,
bool have_defaults = false;
ListCell *x;
int i;
- ParseState *pstate;
*variadicArgType = InvalidOid; /* default result */
*requiredResultType = InvalidOid; /* default result */
@@ -212,10 +210,6 @@ interpret_function_parameter_list(List *parameters,
paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
*parameterDefaults = NIL;
- /* may need a pstate for parse analysis of default exprs */
- pstate = make_parsestate(NULL);
- pstate->p_sourcetext = queryString;
-
/* Scan the list and extract data into work arrays */
i = 0;
foreach(x, parameters)
@@ -413,8 +407,6 @@ interpret_function_parameter_list(List *parameters,
i++;
}
- free_parsestate(pstate);
-
/* Now construct the proper outputs as needed */
*parameterTypes = buildoidvector(inTypes, inCount);
@@ -458,7 +450,8 @@ interpret_function_parameter_list(List *parameters,
* SET parameters though --- if you're redundant, the last one wins.)
*/
static bool
-compute_common_attribute(DefElem *defel,
+compute_common_attribute(ParseState *pstate,
+ DefElem *defel,
DefElem **volatility_item,
DefElem **strict_item,
DefElem **security_item,
@@ -530,7 +523,8 @@ compute_common_attribute(DefElem *defel,
duplicate_error:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
return false; /* keep compiler quiet */
}
@@ -584,9 +578,8 @@ update_proconfig_value(ArrayType *a, List *set_items)
foreach(l, set_items)
{
- VariableSetStmt *sstmt = (VariableSetStmt *) lfirst(l);
+ VariableSetStmt *sstmt = lfirst_node(VariableSetStmt, l);
- Assert(IsA(sstmt, VariableSetStmt));
if (sstmt->kind == VAR_RESET_ALL)
a = NULL;
else
@@ -609,7 +602,8 @@ update_proconfig_value(ArrayType *a, List *set_items)
* attributes.
*/
static void
-compute_attributes_sql_style(List *options,
+compute_attributes_sql_style(ParseState *pstate,
+ List *options,
List **as,
char **language,
Node **transform,
@@ -646,7 +640,8 @@ compute_attributes_sql_style(List *options,
if (as_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
as_item = defel;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -654,7 +649,8 @@ compute_attributes_sql_style(List *options,
if (language_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
language_item = defel;
}
else if (strcmp(defel->defname, "transform") == 0)
@@ -662,7 +658,8 @@ compute_attributes_sql_style(List *options,
if (transform_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
transform_item = defel;
}
else if (strcmp(defel->defname, "window") == 0)
@@ -670,10 +667,12 @@ compute_attributes_sql_style(List *options,
if (windowfunc_item)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
windowfunc_item = defel;
}
- else if (compute_common_attribute(defel,
+ else if (compute_common_attribute(pstate,
+ defel,
&volatility_item,
&strict_item,
&security_item,
@@ -763,7 +762,7 @@ compute_attributes_sql_style(List *options,
*------------
*/
static void
-compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatility_p)
+compute_attributes_with_style(ParseState *pstate, List *parameters, bool *isStrict_p, char *volatility_p)
{
ListCell *pl;
@@ -783,7 +782,8 @@ compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatili
ereport(WARNING,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized function attribute \"%s\" ignored",
- param->defname)));
+ param->defname),
+ parser_errposition(pstate, param->location)));
}
}
@@ -858,7 +858,7 @@ interpret_AS_clause(Oid languageOid, const char *languageName,
* Execute a CREATE FUNCTION utility statement.
*/
ObjectAddress
-CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
+CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
{
char *probin_str;
char *prosrc_str;
@@ -915,7 +915,8 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
parallel = PROPARALLEL_UNSAFE;
/* override attributes from explicit list */
- compute_attributes_sql_style(stmt->options,
+ compute_attributes_sql_style(pstate,
+ stmt->options,
&as_clause, &language, &transformDefElem,
&isWindowFunc, &volatility,
&isStrict, &security, &isLeakProof,
@@ -969,11 +970,10 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
{
ListCell *lc;
- Assert(IsA(transformDefElem, List));
-
- foreach(lc, (List *) transformDefElem)
+ foreach(lc, castNode(List, transformDefElem))
{
- Oid typeid = typenameTypeId(NULL, lfirst(lc));
+ Oid typeid = typenameTypeId(NULL,
+ lfirst_node(TypeName, lc));
Oid elt = get_base_element_type(typeid);
typeid = elt ? elt : typeid;
@@ -987,10 +987,10 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
* Convert remaining parameters of CREATE to form wanted by
* ProcedureCreate.
*/
- interpret_function_parameter_list(stmt->parameters,
+ interpret_function_parameter_list(pstate,
+ stmt->parameters,
languageOid,
false, /* not an aggregate */
- queryString,
&parameterTypes,
&allParameterTypes,
&parameterModes,
@@ -1041,11 +1041,11 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
}
else
{
- /* store SQL NULL instead of emtpy array */
+ /* store SQL NULL instead of empty array */
trftypes = NULL;
}
- compute_attributes_with_style(stmt->withClause, &isStrict, &volatility);
+ compute_attributes_with_style(pstate, stmt->withClause, &isStrict, &volatility);
interpret_AS_clause(languageOid, language, funcname, as_clause,
&prosrc_str, &probin_str);
@@ -1132,7 +1132,7 @@ RemoveFunctionById(Oid funcOid)
isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -1149,7 +1149,7 @@ RemoveFunctionById(Oid funcOid)
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -1163,7 +1163,7 @@ RemoveFunctionById(Oid funcOid)
* ALTER framework).
*/
ObjectAddress
-AlterFunction(AlterFunctionStmt *stmt)
+AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
{
HeapTuple tup;
Oid funcOid;
@@ -1182,9 +1182,7 @@ AlterFunction(AlterFunctionStmt *stmt)
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
- funcOid = LookupFuncNameTypeNames(stmt->func->funcname,
- stmt->func->funcargs,
- false);
+ funcOid = LookupFuncWithArgs(stmt->func, false);
tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
if (!HeapTupleIsValid(tup)) /* should not happen */
@@ -1195,20 +1193,21 @@ AlterFunction(AlterFunctionStmt *stmt)
/* Permission check: must own function */
if (!pg_proc_ownercheck(funcOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
- NameListToString(stmt->func->funcname));
+ NameListToString(stmt->func->objname));
if (procForm->proisagg)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is an aggregate function",
- NameListToString(stmt->func->funcname))));
+ NameListToString(stmt->func->objname))));
/* Examine requested actions. */
foreach(l, stmt->actions)
{
DefElem *defel = (DefElem *) lfirst(l);
- if (compute_common_attribute(defel,
+ if (compute_common_attribute(pstate,
+ defel,
&volatility_item,
&strict_item,
&security_def_item,
@@ -1292,8 +1291,7 @@ AlterFunction(AlterFunctionStmt *stmt)
procForm->proparallel = interpret_func_parallel(parallel_item);
/* Do the update */
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
@@ -1333,9 +1331,7 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
procForm->prorettype = newRetType;
/* update the catalog and its indexes */
- simple_heap_update(pg_proc_rel, &tup->t_self, tup);
-
- CatalogUpdateIndexes(pg_proc_rel, tup);
+ CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
heap_close(pg_proc_rel, RowExclusiveLock);
}
@@ -1368,9 +1364,7 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
procForm->proargtypes.values[argIndex] = newArgType;
/* update the catalog and its indexes */
- simple_heap_update(pg_proc_rel, &tup->t_self, tup);
-
- CatalogUpdateIndexes(pg_proc_rel, tup);
+ CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
heap_close(pg_proc_rel, RowExclusiveLock);
}
@@ -1446,7 +1440,7 @@ CreateCast(CreateCastStmt *stmt)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cast will be ignored because the target data type is a domain")));
- /* Detemine the cast method */
+ /* Determine the cast method */
if (stmt->func != NULL)
castmethod = COERCION_METHOD_FUNCTION;
else if (stmt->inout)
@@ -1458,9 +1452,7 @@ CreateCast(CreateCastStmt *stmt)
{
Form_pg_proc procstruct;
- funcid = LookupFuncNameTypeNames(stmt->func->funcname,
- stmt->func->funcargs,
- false);
+ funcid = LookupFuncWithArgs(stmt->func, false);
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
if (!HeapTupleIsValid(tuple))
@@ -1479,11 +1471,13 @@ CreateCast(CreateCastStmt *stmt)
if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("second argument of cast function must be type integer")));
+ errmsg("second argument of cast function must be type %s",
+ "integer")));
if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("third argument of cast function must be type boolean")));
+ errmsg("third argument of cast function must be type %s",
+ "boolean")));
if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -1654,9 +1648,7 @@ CreateCast(CreateCastStmt *stmt)
tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
- castid = simple_heap_insert(relation, tuple);
-
- CatalogUpdateIndexes(relation, tuple);
+ castid = CatalogTupleInsert(relation, tuple);
/* make dependency entries */
myself.classId = CastRelationId;
@@ -1740,7 +1732,7 @@ DropCastById(Oid castOid)
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for cast %u", castOid);
- simple_heap_delete(relation, &tuple->t_self);
+ CatalogTupleDelete(relation, &tuple->t_self);
systable_endscan(scan);
heap_close(relation, RowExclusiveLock);
@@ -1773,7 +1765,8 @@ check_transform_function(Form_pg_proc procstruct)
if (procstruct->proargtypes.values[0] != INTERNALOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("first argument of transform function must be type \"internal\"")));
+ errmsg("first argument of transform function must be type %s",
+ "internal")));
}
@@ -1840,14 +1833,14 @@ CreateTransform(CreateTransformStmt *stmt)
*/
if (stmt->fromsql)
{
- fromsqlfuncid = LookupFuncNameTypeNames(stmt->fromsql->funcname, stmt->fromsql->funcargs, false);
+ fromsqlfuncid = LookupFuncWithArgs(stmt->fromsql, false);
if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(stmt->fromsql->funcname));
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(stmt->fromsql->objname));
aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_PROC, NameListToString(stmt->fromsql->funcname));
+ aclcheck_error(aclresult, ACL_KIND_PROC, NameListToString(stmt->fromsql->objname));
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
if (!HeapTupleIsValid(tuple))
@@ -1856,7 +1849,8 @@ CreateTransform(CreateTransformStmt *stmt)
if (procstruct->prorettype != INTERNALOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("return data type of FROM SQL function must be \"internal\"")));
+ errmsg("return data type of FROM SQL function must be %s",
+ "internal")));
check_transform_function(procstruct);
ReleaseSysCache(tuple);
}
@@ -1865,14 +1859,14 @@ CreateTransform(CreateTransformStmt *stmt)
if (stmt->tosql)
{
- tosqlfuncid = LookupFuncNameTypeNames(stmt->tosql->funcname, stmt->tosql->funcargs, false);
+ tosqlfuncid = LookupFuncWithArgs(stmt->tosql, false);
if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(stmt->tosql->funcname));
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(stmt->tosql->objname));
aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_PROC, NameListToString(stmt->tosql->funcname));
+ aclcheck_error(aclresult, ACL_KIND_PROC, NameListToString(stmt->tosql->objname));
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
if (!HeapTupleIsValid(tuple))
@@ -1917,7 +1911,7 @@ CreateTransform(CreateTransformStmt *stmt)
replaces[Anum_pg_transform_trftosql - 1] = true;
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
- simple_heap_update(relation, &newtuple->t_self, newtuple);
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
transformid = HeapTupleGetOid(tuple);
ReleaseSysCache(tuple);
@@ -1926,12 +1920,10 @@ CreateTransform(CreateTransformStmt *stmt)
else
{
newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
- transformid = simple_heap_insert(relation, newtuple);
+ transformid = CatalogTupleInsert(relation, newtuple);
is_replace = false;
}
- CatalogUpdateIndexes(relation, newtuple);
-
if (is_replace)
deleteDependencyRecordsFor(TransformRelationId, transformid, true);
@@ -2026,7 +2018,7 @@ DropTransformById(Oid transformOid)
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for transform %u", transformOid);
- simple_heap_delete(relation, &tuple->t_self);
+ CatalogTupleDelete(relation, &tuple->t_self);
systable_endscan(scan);
heap_close(relation, RowExclusiveLock);
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 1587fb6e80..87ff7faf48 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -4,7 +4,7 @@
* POSTGRES define and remove index code.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -57,6 +57,7 @@
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+#include "utils/regproc.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
@@ -75,8 +76,6 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo,
char *accessMethodName, Oid accessMethodId,
bool amcanorder,
bool isconstraint);
-static Oid GetIndexOpClass(List *opclass, Oid attrType,
- char *accessMethodName, Oid accessMethodId);
static char *ChooseIndexName(const char *tabname, Oid namespaceId,
List *colnames, List *exclusionOpNames,
bool primary, bool isconstraint);
@@ -106,7 +105,7 @@ static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
* Errors arising from the attribute list still apply.
*
* Most column type changes that can skip a table rewrite do not invalidate
- * indexes. We ackowledge this when all operator classes, collations and
+ * indexes. We acknowledge this when all operator classes, collations and
* exclusion operators match. Though we could further permit intra-opfamily
* changes for btree and hash indexes, that adds subtle complexity with no
* concrete benefit for core types.
@@ -186,10 +185,12 @@ CheckIndexCompatible(Oid oldId,
indexInfo = makeNode(IndexInfo);
indexInfo->ii_Expressions = NIL;
indexInfo->ii_ExpressionsState = NIL;
- indexInfo->ii_PredicateState = NIL;
+ indexInfo->ii_PredicateState = NULL;
indexInfo->ii_ExclusionOps = NULL;
indexInfo->ii_ExclusionProcs = NULL;
indexInfo->ii_ExclusionStrats = NULL;
+ indexInfo->ii_AmCache = NULL;
+ indexInfo->ii_Context = CurrentMemoryContext;
typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
@@ -298,8 +299,8 @@ CheckIndexCompatible(Oid oldId,
* 'indexRelationId': normally InvalidOid, but during bootstrap can be
* nonzero to specify a preselected OID for the index.
* 'is_alter_table': this is due to an ALTER rather than a CREATE operation.
- * 'check_rights': check for CREATE rights in the namespace. (This should
- * be true except when ALTER is deleting/recreating an index.)
+ * 'check_rights': check for CREATE rights in namespace and tablespace. (This
+ * should be true except when ALTER is deleting/recreating an index.)
* 'skip_build': make the catalog entries but leave the index file empty;
* it will be filled later.
* 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
@@ -389,6 +390,11 @@ DefineIndex(Oid relationId,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot create index on foreign table \"%s\"",
RelationGetRelationName(rel))));
+ else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot create index on partitioned table \"%s\"",
+ RelationGetRelationName(rel))));
else
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -435,8 +441,9 @@ DefineIndex(Oid relationId,
/* note InvalidOid is OK in this case */
}
- /* Check permissions except when using database's default */
- if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
+ /* Check tablespace permissions */
+ if (check_rights &&
+ OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
{
AclResult aclresult;
@@ -505,11 +512,6 @@ DefineIndex(Oid relationId,
accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
- if (strcmp(accessMethodName, "hash") == 0 &&
- RelationNeedsWAL(rel))
- ereport(WARNING,
- (errmsg("hash indexes are not WAL-logged and their use is discouraged")));
-
if (stmt->unique && !amRoutine->amcanunique)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -597,7 +599,7 @@ DefineIndex(Oid relationId,
indexInfo->ii_Expressions = NIL; /* for now */
indexInfo->ii_ExpressionsState = NIL;
indexInfo->ii_Predicate = make_ands_implicit((Expr *) stmt->whereClause);
- indexInfo->ii_PredicateState = NIL;
+ indexInfo->ii_PredicateState = NULL;
indexInfo->ii_ExclusionOps = NULL;
indexInfo->ii_ExclusionProcs = NULL;
indexInfo->ii_ExclusionStrats = NULL;
@@ -606,6 +608,8 @@ DefineIndex(Oid relationId,
indexInfo->ii_ReadyForInserts = !stmt->concurrent;
indexInfo->ii_Concurrent = stmt->concurrent;
indexInfo->ii_BrokenHotChain = false;
+ indexInfo->ii_AmCache = NULL;
+ indexInfo->ii_Context = CurrentMemoryContext;
typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
@@ -1009,7 +1013,7 @@ CheckMutability(Expr *expr)
* indxpath.c could do something with. However, that seems overly
* restrictive. One useful application of partial indexes is to apply
* a UNIQUE constraint across a subset of a table, and in that scenario
- * any evaluatable predicate will work. So accept any predicate here
+ * any evaluable predicate will work. So accept any predicate here
* (except ones requiring a plan), and let indxpath.c fend for itself.
*/
static void
@@ -1193,10 +1197,10 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
/*
* Identify the opclass to use.
*/
- classOidP[attn] = GetIndexOpClass(attribute->opclass,
- atttype,
- accessMethodName,
- accessMethodId);
+ classOidP[attn] = ResolveOpClass(attribute->opclass,
+ atttype,
+ accessMethodName,
+ accessMethodId);
/*
* Identify the exclusion operator, if any.
@@ -1303,10 +1307,13 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
/*
* Resolve possibly-defaulted operator class specification
+ *
+ * Note: This is used to resolve operator class specification in index and
+ * partition key definitions.
*/
-static Oid
-GetIndexOpClass(List *opclass, Oid attrType,
- char *accessMethodName, Oid accessMethodId)
+Oid
+ResolveOpClass(List *opclass, Oid attrType,
+ char *accessMethodName, Oid accessMethodId)
{
char *schemaname;
char *opcname;
@@ -1951,9 +1958,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
*/
private_context = AllocSetContextCreate(PortalContext,
"ReindexMultipleTables",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
/*
* Define the search keys to find the objects to reindex. For a schema, we
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index 175d1f3f2e..9fe9e022b0 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -3,7 +3,7 @@
* lockcmds.c
* LOCK command support code
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,7 +14,6 @@
*/
#include "postgres.h"
-#include "access/heapam.h"
#include "catalog/namespace.h"
#include "catalog/pg_inherits_fn.h"
#include "commands/lockcmds.h"
@@ -55,7 +54,7 @@ LockTableCommand(LockStmt *lockstmt)
foreach(p, lockstmt->relations)
{
RangeVar *rv = (RangeVar *) lfirst(p);
- bool recurse = interpretInhOption(rv->inhOpt);
+ bool recurse = rv->inh;
Oid reloid;
reloid = RangeVarGetRelidExtended(rv, lockstmt->mode, false,
@@ -88,7 +87,7 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
* check */
/* Currently, we only allow plain tables to be locked */
- if (relkind != RELKIND_RELATION)
+ if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 442ee236a1..2061568d7f 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -3,7 +3,7 @@
* matview.c
* materialized view support
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -36,6 +36,7 @@
#include "nodes/makefuncs.h"
#endif
#include "parser/parse_relation.h"
+#include "pgstat.h"
#include "rewrite/rewriteHandler.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
@@ -65,7 +66,7 @@ static void transientrel_startup(DestReceiver *self, int operation, TupleDesc ty
static bool transientrel_receive(TupleTableSlot *slot, DestReceiver *self);
static void transientrel_shutdown(DestReceiver *self);
static void transientrel_destroy(DestReceiver *self);
-static void refresh_matview_datafill(DestReceiver *dest, Query *query,
+static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query,
const char *queryString);
static char *make_temptable_name_n(char *tempname, int n);
@@ -106,9 +107,7 @@ SetMatViewPopulatedState(Relation relation, bool newstate)
((Form_pg_class) GETSTRUCT(tuple))->relispopulated = newstate;
- simple_heap_update(pgrel, &tuple->t_self, tuple);
-
- CatalogUpdateIndexes(pgrel, tuple);
+ CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
heap_freetuple(tuple);
heap_close(pgrel, RowExclusiveLock);
@@ -153,6 +152,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
Oid relowner;
Oid OIDNewHeap;
DestReceiver *dest;
+ uint64 processed = 0;
bool concurrent;
LOCKMODE lockmode;
char relpersistence;
@@ -270,8 +270,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
* The stored query was rewritten at the time of the MV definition, but
* has not been scribbled on by the planner.
*/
- dataQuery = (Query *) linitial(actions);
- Assert(IsA(dataQuery, Query));
+ dataQuery = linitial_node(Query, actions);
/*
* Check for active uses of the relation in the current transaction, such
@@ -331,9 +330,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
/* Generate the data, if wanted. */
if (!stmt->skipData)
- refresh_matview_datafill(dest, dataQuery, queryString);
-
- heap_close(matviewRel, NoLock);
+ processed = refresh_matview_datafill(dest, dataQuery, queryString);
/* Make the matview match the newly generated data. */
if (concurrent)
@@ -354,8 +351,22 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
Assert(matview_maintenance_depth == old_depth);
}
else
+ {
refresh_by_heap_swap(matviewOid, OIDNewHeap, relpersistence);
+ /*
+ * Inform stats collector about our activity: basically, we truncated
+ * the matview and inserted some new data. (The concurrent code path
+ * above doesn't need to worry about this because the inserts and
+ * deletes it issues get counted by lower-level code.)
+ */
+ pgstat_count_truncate(matviewRel);
+ if (!stmt->skipData)
+ pgstat_count_heap_insert(matviewRel, processed);
+ }
+
+ heap_close(matviewRel, NoLock);
+
/* Roll back any GUC changes */
AtEOXact_GUC(false, save_nestlevel);
@@ -369,8 +380,13 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
/*
* refresh_matview_datafill
+ *
+ * Execute the given query, sending result rows to "dest" (which will
+ * insert them into the target matview).
+ *
+ * Returns number of rows inserted.
*/
-static void
+static uint64
refresh_matview_datafill(DestReceiver *dest, Query *query,
const char *queryString)
{
@@ -378,6 +394,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
PlannedStmt *plan;
QueryDesc *queryDesc;
Query *copied_query;
+ uint64 processed;
/* Lock and rewrite, using a copy to preserve the original query. */
copied_query = copyObject(query);
@@ -407,13 +424,15 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
/* Create a QueryDesc, redirecting output to our tuple receiver */
queryDesc = CreateQueryDesc(plan, queryString,
GetActiveSnapshot(), InvalidSnapshot,
- dest, NULL, 0);
+ dest, NULL, NULL, 0);
/* call ExecutorStart to prepare the plan for execution */
ExecutorStart(queryDesc, EXEC_FLAG_WITHOUT_OIDS);
/* run the plan */
- ExecutorRun(queryDesc, ForwardScanDirection, 0L);
+ ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
+
+ processed = queryDesc->estate->es_processed;
/* and clean up */
ExecutorFinish(queryDesc);
@@ -422,6 +441,8 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
FreeQueryDesc(queryDesc);
PopActiveSnapshot();
+
+ return processed;
}
DestReceiver *
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index f4dfdb9642..ab51d1a417 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -4,7 +4,7 @@
*
* Routines for opclass (and opfamily) manipulation commands
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -278,9 +278,7 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
tup = heap_form_tuple(rel->rd_att, values, nulls);
- opfamilyoid = simple_heap_insert(rel, tup);
-
- CatalogUpdateIndexes(rel, tup);
+ opfamilyoid = CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
@@ -462,13 +460,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
*/
foreach(l, stmt->items)
{
- CreateOpClassItem *item = lfirst(l);
+ CreateOpClassItem *item = lfirst_node(CreateOpClassItem, l);
Oid operOid;
Oid funcOid;
Oid sortfamilyOid;
OpFamilyMember *member;
- Assert(IsA(item, CreateOpClassItem));
switch (item->itemtype)
{
case OPCLASS_ITEM_OPERATOR:
@@ -478,19 +475,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
errmsg("invalid operator number %d,"
" must be between 1 and %d",
item->number, maxOpNumber)));
- if (item->args != NIL)
- {
- TypeName *typeName1 = (TypeName *) linitial(item->args);
- TypeName *typeName2 = (TypeName *) lsecond(item->args);
-
- operOid = LookupOperNameTypeNames(NULL, item->name,
- typeName1, typeName2,
- false, -1);
- }
+ if (item->name->objargs != NIL)
+ operOid = LookupOperWithArgs(item->name, false);
else
{
/* Default to binary op on input datatype */
- operOid = LookupOperName(NULL, item->name,
+ operOid = LookupOperName(NULL, item->name->objname,
typeoid, typeoid,
false, -1);
}
@@ -529,8 +519,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
errmsg("invalid procedure number %d,"
" must be between 1 and %d",
item->number, maxProcNumber)));
- funcOid = LookupFuncNameTypeNames(item->name, item->args,
- false);
+ funcOid = LookupFuncWithArgs(item->name, false);
#ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */
/* Caller must own function */
@@ -655,9 +644,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
tup = heap_form_tuple(rel->rd_att, values, nulls);
- opclassoid = simple_heap_insert(rel, tup);
-
- CatalogUpdateIndexes(rel, tup);
+ opclassoid = CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
@@ -847,13 +834,12 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
*/
foreach(l, items)
{
- CreateOpClassItem *item = lfirst(l);
+ CreateOpClassItem *item = lfirst_node(CreateOpClassItem, l);
Oid operOid;
Oid funcOid;
Oid sortfamilyOid;
OpFamilyMember *member;
- Assert(IsA(item, CreateOpClassItem));
switch (item->itemtype)
{
case OPCLASS_ITEM_OPERATOR:
@@ -863,15 +849,8 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
errmsg("invalid operator number %d,"
" must be between 1 and %d",
item->number, maxOpNumber)));
- if (item->args != NIL)
- {
- TypeName *typeName1 = (TypeName *) linitial(item->args);
- TypeName *typeName2 = (TypeName *) lsecond(item->args);
-
- operOid = LookupOperNameTypeNames(NULL, item->name,
- typeName1, typeName2,
- false, -1);
- }
+ if (item->name->objargs != NIL)
+ operOid = LookupOperWithArgs(item->name, false);
else
{
ereport(ERROR,
@@ -914,8 +893,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
errmsg("invalid procedure number %d,"
" must be between 1 and %d",
item->number, maxProcNumber)));
- funcOid = LookupFuncNameTypeNames(item->name, item->args,
- false);
+ funcOid = LookupFuncWithArgs(item->name, false);
#ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */
/* Caller must own function */
@@ -981,12 +959,11 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
*/
foreach(l, items)
{
- CreateOpClassItem *item = lfirst(l);
+ CreateOpClassItem *item = lfirst_node(CreateOpClassItem, l);
Oid lefttype,
righttype;
OpFamilyMember *member;
- Assert(IsA(item, CreateOpClassItem));
switch (item->itemtype)
{
case OPCLASS_ITEM_OPERATOR:
@@ -996,7 +973,7 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
errmsg("invalid operator number %d,"
" must be between 1 and %d",
item->number, maxOpNumber)));
- processTypesSpec(item->args, &lefttype, &righttype);
+ processTypesSpec(item->class_args, &lefttype, &righttype);
/* Save the info */
member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
member->number = item->number;
@@ -1011,7 +988,7 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
errmsg("invalid procedure number %d,"
" must be between 1 and %d",
item->number, maxProcNumber)));
- processTypesSpec(item->args, &lefttype, &righttype);
+ processTypesSpec(item->class_args, &lefttype, &righttype);
/* Save the info */
member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
member->number = item->number;
@@ -1330,9 +1307,7 @@ storeOperators(List *opfamilyname, Oid amoid,
tup = heap_form_tuple(rel->rd_att, values, nulls);
- entryoid = simple_heap_insert(rel, tup);
-
- CatalogUpdateIndexes(rel, tup);
+ entryoid = CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
@@ -1441,9 +1416,7 @@ storeProcedures(List *opfamilyname, Oid amoid,
tup = heap_form_tuple(rel->rd_att, values, nulls);
- entryoid = simple_heap_insert(rel, tup);
-
- CatalogUpdateIndexes(rel, tup);
+ entryoid = CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
@@ -1582,7 +1555,7 @@ RemoveOpFamilyById(Oid opfamilyOid)
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
- simple_heap_delete(rel, &tup->t_self);
+ CatalogTupleDelete(rel, &tup->t_self);
ReleaseSysCache(tup);
@@ -1601,7 +1574,7 @@ RemoveOpClassById(Oid opclassOid)
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
- simple_heap_delete(rel, &tup->t_self);
+ CatalogTupleDelete(rel, &tup->t_self);
ReleaseSysCache(tup);
@@ -1631,7 +1604,7 @@ RemoveAmOpEntryById(Oid entryOid)
if (!HeapTupleIsValid(tup))
elog(ERROR, "could not find tuple for amop entry %u", entryOid);
- simple_heap_delete(rel, &tup->t_self);
+ CatalogTupleDelete(rel, &tup->t_self);
systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
@@ -1660,7 +1633,7 @@ RemoveAmProcEntryById(Oid entryOid)
if (!HeapTupleIsValid(tup))
elog(ERROR, "could not find tuple for amproc entry %u", entryOid);
- simple_heap_delete(rel, &tup->t_self);
+ CatalogTupleDelete(rel, &tup->t_self);
systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 67d08d862b..739d5875eb 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -4,7 +4,7 @@
*
* Routines for operator manipulation commands
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -368,7 +368,7 @@ RemoveOperatorById(Oid operOid)
}
}
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -402,10 +402,7 @@ AlterOperator(AlterOperatorStmt *stmt)
Oid joinOid;
/* Look up the operator */
- oprId = LookupOperNameTypeNames(NULL, stmt->opername,
- (TypeName *) linitial(stmt->operargs),
- (TypeName *) lsecond(stmt->operargs),
- false, -1);
+ oprId = LookupOperWithArgs(stmt->opername, false);
catalog = heap_open(OperatorRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(oprId));
if (tup == NULL)
@@ -518,8 +515,7 @@ AlterOperator(AlterOperatorStmt *stmt)
tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
values, nulls, replaces);
- simple_heap_update(catalog, &tup->t_self, tup);
- CatalogUpdateIndexes(catalog, tup);
+ CatalogTupleUpdate(catalog, &tup->t_self, tup);
address = makeOperatorDependencies(tup, true);
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index bc2e4af82a..4a758426c3 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -3,7 +3,7 @@
* policy.c
* Commands for manipulating policies.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/commands/policy.c
@@ -88,7 +88,7 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
rv->relname)));
/* Relation type MUST be a table. */
- if (relkind != RELKIND_RELATION)
+ if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table", rv->relname)));
@@ -177,7 +177,7 @@ policy_role_list_to_array(List *roles, int *num_roles)
}
else
role_oids[i++] =
- ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false));
+ ObjectIdGetDatum(get_rolespec_oid(spec, false));
}
return role_oids;
@@ -201,9 +201,7 @@ RelationBuildRowSecurity(Relation relation)
*/
rscxt = AllocSetContextCreate(CacheMemoryContext,
"row security descriptor",
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
/*
* Since rscxt lives under CacheMemoryContext, it is long-lived. Use a
@@ -237,6 +235,7 @@ RelationBuildRowSecurity(Relation relation)
{
Datum value_datum;
char cmd_value;
+ bool permissive_value;
Datum roles_datum;
char *qual_value;
Expr *qual_expr;
@@ -259,6 +258,12 @@ RelationBuildRowSecurity(Relation relation)
Assert(!isnull);
cmd_value = DatumGetChar(value_datum);
+ /* Get policy permissive or restrictive */
+ value_datum = heap_getattr(tuple, Anum_pg_policy_polpermissive,
+ RelationGetDescr(catalog), &isnull);
+ Assert(!isnull);
+ permissive_value = DatumGetBool(value_datum);
+
/* Get policy name */
value_datum = heap_getattr(tuple, Anum_pg_policy_polname,
RelationGetDescr(catalog), &isnull);
@@ -300,6 +305,7 @@ RelationBuildRowSecurity(Relation relation)
policy = palloc0(sizeof(RowSecurityPolicy));
policy->policy_name = pstrdup(policy_name_value);
policy->polcmd = cmd_value;
+ policy->permissive = permissive_value;
policy->roles = DatumGetArrayTypePCopy(roles_datum);
policy->qual = copyObject(qual_expr);
policy->with_check_qual = copyObject(with_check_qual);
@@ -378,7 +384,8 @@ RemovePolicyById(Oid policy_id)
relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
rel = heap_open(relid, AccessExclusiveLock);
- if (rel->rd_rel->relkind != RELKIND_RELATION)
+ if (rel->rd_rel->relkind != RELKIND_RELATION &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
@@ -390,7 +397,7 @@ RemovePolicyById(Oid policy_id)
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(rel))));
- simple_heap_delete(pg_policy_rel, &tuple->t_self);
+ CatalogTupleDelete(pg_policy_rel, &tuple->t_self);
systable_endscan(sscan);
@@ -607,10 +614,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
new_tuple = heap_modify_tuple(tuple,
RelationGetDescr(pg_policy_rel),
values, isnull, replaces);
- simple_heap_update(pg_policy_rel, &new_tuple->t_self, new_tuple);
-
- /* Update Catalog Indexes */
- CatalogUpdateIndexes(pg_policy_rel, new_tuple);
+ CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
/* Remove all old dependencies. */
deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
@@ -798,6 +802,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
CStringGetDatum(stmt->policy_name));
values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
+ values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive);
values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
/* Add qual if present. */
@@ -815,10 +820,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
isnull);
- policy_id = simple_heap_insert(pg_policy_rel, policy_tuple);
-
- /* Update Indexes */
- CatalogUpdateIndexes(pg_policy_rel, policy_tuple);
+ policy_id = CatalogTupleInsert(pg_policy_rel, policy_tuple);
/* Record Dependencies */
target.classId = RelationRelationId;
@@ -1142,10 +1144,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
new_tuple = heap_modify_tuple(policy_tuple,
RelationGetDescr(pg_policy_rel),
values, isnull, replaces);
- simple_heap_update(pg_policy_rel, &new_tuple->t_self, new_tuple);
-
- /* Update Catalog Indexes */
- CatalogUpdateIndexes(pg_policy_rel, new_tuple);
+ CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
/* Update Dependencies. */
deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
@@ -1279,10 +1278,7 @@ rename_policy(RenameStmt *stmt)
namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
stmt->newname);
- simple_heap_update(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
-
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(pg_policy_rel, policy_tuple);
+ CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
InvokeObjectPostAlterHook(PolicyRelationId,
HeapTupleGetOid(policy_tuple), 0);
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index bbd5ca54dc..6191459982 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -10,7 +10,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -28,7 +28,9 @@
#include "commands/portalcmds.h"
#include "executor/executor.h"
#include "executor/tstoreReceiver.h"
+#include "rewrite/rewriteHandler.h"
#include "tcop/pquery.h"
+#include "tcop/tcopprot.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
@@ -39,22 +41,17 @@
/*
* PerformCursorOpen
* Execute SQL DECLARE CURSOR command.
- *
- * The query has already been through parse analysis, rewriting, and planning.
- * When it gets here, it looks like a SELECT PlannedStmt, except that the
- * utilityStmt field is set.
*/
void
-PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
+PerformCursorOpen(DeclareCursorStmt *cstmt, ParamListInfo params,
const char *queryString, bool isTopLevel)
{
- DeclareCursorStmt *cstmt = (DeclareCursorStmt *) stmt->utilityStmt;
+ Query *query = castNode(Query, cstmt->query);
+ List *rewritten;
+ PlannedStmt *plan;
Portal portal;
MemoryContext oldContext;
- if (cstmt == NULL || !IsA(cstmt, DeclareCursorStmt))
- elog(ERROR, "PerformCursorOpen called for non-cursor query");
-
/*
* Disallow empty-string cursor name (conflicts with protocol-level
* unnamed portal).
@@ -73,6 +70,32 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
RequireTransactionChain(isTopLevel, "DECLARE CURSOR");
/*
+ * Parse analysis was done already, but we still have to run the rule
+ * rewriter. We do not do AcquireRewriteLocks: we assume the query either
+ * came straight from the parser, or suitable locks were acquired by
+ * plancache.c.
+ *
+ * Because the rewriter and planner tend to scribble on the input, we make
+ * a preliminary copy of the source querytree. This prevents problems in
+ * the case that the DECLARE CURSOR is in a portal or plpgsql function and
+ * is executed repeatedly. (See also the same hack in EXPLAIN and
+ * PREPARE.) XXX FIXME someday.
+ */
+ rewritten = QueryRewrite((Query *) copyObject(query));
+
+ /* SELECT should never rewrite to more or less than one query */
+ if (list_length(rewritten) != 1)
+ elog(ERROR, "non-SELECT statement in DECLARE CURSOR");
+
+ query = linitial_node(Query, rewritten);
+
+ if (query->commandType != CMD_SELECT)
+ elog(ERROR, "non-SELECT statement in DECLARE CURSOR");
+
+ /* Plan the query, applying the specified options */
+ plan = pg_plan_query(query, cstmt->options, params);
+
+ /*
* Create a portal and copy the plan and queryString into its memory.
*/
portal = CreatePortal(cstmt->portalname, false, false);
@@ -87,8 +110,7 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
- stmt = copyObject(stmt);
- stmt->utilityStmt = NULL; /* make it look like plain SELECT */
+ plan = copyObject(plan);
queryString = pstrdup(queryString);
@@ -96,7 +118,7 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
NULL,
queryString,
"SELECT", /* cursor's query is always a SELECT */
- list_make1(stmt),
+ list_make1(plan),
NULL);
/*----------
@@ -123,8 +145,8 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
portal->cursorOptions = cstmt->options;
if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
{
- if (stmt->rowMarks == NIL &&
- ExecSupportsBackwardScan(stmt->planTree))
+ if (plan->rowMarks == NIL &&
+ ExecSupportsBackwardScan(plan->planTree))
portal->cursorOptions |= CURSOR_OPT_SCROLL;
else
portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
@@ -483,7 +505,7 @@ PersistHoldablePortal(Portal portal)
true);
/* Fetch the result set into the tuplestore */
- ExecutorRun(queryDesc, ForwardScanDirection, 0L);
+ ExecutorRun(queryDesc, ForwardScanDirection, 0L, false);
(*queryDesc->dest->rDestroy) (queryDesc->dest);
queryDesc->dest = NULL;
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 316fc49109..287affa515 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -7,7 +7,7 @@
* accessed via the extended FE/BE query protocol.
*
*
- * Copyright (c) 2002-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2002-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/commands/prepare.c
@@ -16,6 +16,8 @@
*/
#include "postgres.h"
+#include <limits.h>
+
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/createas.h"
@@ -67,8 +69,10 @@ static Datum build_regtype_array(Oid *param_types, int num_params);
* Implements the 'PREPARE' utility statement.
*/
void
-PrepareQuery(PrepareStmt *stmt, const char *queryString)
+PrepareQuery(PrepareStmt *stmt, const char *queryString,
+ int stmt_location, int stmt_len)
{
+ RawStmt *rawstmt;
CachedPlanSource *plansource;
Oid *argtypes = NULL;
int nargs;
@@ -86,10 +90,22 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
errmsg("invalid statement name: must not be empty")));
/*
+ * Need to wrap the contained statement in a RawStmt node to pass it to
+ * parse analysis.
+ *
+ * Because parse analysis scribbles on the raw querytree, we must make a
+ * copy to ensure we don't modify the passed-in tree. FIXME someday.
+ */
+ rawstmt = makeNode(RawStmt);
+ rawstmt->stmt = (Node *) copyObject(stmt->query);
+ rawstmt->stmt_location = stmt_location;
+ rawstmt->stmt_len = stmt_len;
+
+ /*
* Create the CachedPlanSource before we do parse analysis, since it needs
* to see the unmodified raw parse tree.
*/
- plansource = CreateCachedPlan(stmt->query, queryString,
+ plansource = CreateCachedPlan(rawstmt, queryString,
#ifdef PGXC
stmt->name,
#endif
@@ -126,12 +142,8 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
* Analyze the statement using these parameter types (any parameters
* passed in from above us will not be visible to it), allowing
* information about unknown parameters to be deduced from context.
- *
- * Because parse analysis scribbles on the raw querytree, we must make a
- * copy to ensure we don't modify the passed-in tree. FIXME someday.
*/
- query = parse_analyze_varparams((Node *) copyObject(stmt->query),
- queryString,
+ query = parse_analyze_varparams(rawstmt, queryString,
&argtypes, &nargs);
/*
@@ -177,7 +189,7 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
nargs,
NULL,
NULL,
- 0, /* default cursor options */
+ CURSOR_OPT_PARALLEL_OK, /* allow parallel mode */
true); /* fixed result */
/*
@@ -250,7 +262,7 @@ ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause,
entry->plansource->query_string);
/* Replan if needed, and increment plan refcount for portal */
- cplan = GetCachedPlan(entry->plansource, paramLI, false);
+ cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL);
plan_list = cplan->stmt_list;
/*
@@ -274,10 +286,8 @@ ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause,
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("prepared statement is not a SELECT")));
- pstmt = (PlannedStmt *) linitial(plan_list);
- if (!IsA(pstmt, PlannedStmt) ||
- pstmt->commandType != CMD_SELECT ||
- pstmt->utilityStmt != NULL)
+ pstmt = linitial_node(PlannedStmt, plan_list);
+ if (pstmt->commandType != CMD_SELECT)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("prepared statement is not a SELECT")));
@@ -310,7 +320,7 @@ ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause,
*/
PortalStart(portal, paramLI, eflags, GetActiveSnapshot());
- (void) PortalRun(portal, count, false, dest, dest, completionTag);
+ (void) PortalRun(portal, count, false, true, dest, dest, completionTag);
PortalDrop(portal, false);
@@ -361,7 +371,7 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
* We have to run parse analysis for the expressions. Since the parser is
* not cool about scribbling on its input, copy first.
*/
- params = (List *) copyObject(params);
+ params = copyObject(params);
pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString;
@@ -400,7 +410,7 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
}
/* Prepare the expressions for execution */
- exprstates = (List *) ExecPrepareExpr((Expr *) params, estate);
+ exprstates = ExecPrepareExprList(params, estate);
paramLI = (ParamListInfo)
palloc(offsetof(ParamListInfoData, params) +
@@ -416,15 +426,14 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
i = 0;
foreach(l, exprstates)
{
- ExprState *n = lfirst(l);
+ ExprState *n = (ExprState *) lfirst(l);
ParamExternData *prm = &paramLI->params[i];
prm->ptype = param_types[i];
prm->pflags = PARAM_FLAG_CONST;
prm->value = ExecEvalExprSwitchContext(n,
GetPerTupleExprContext(estate),
- &prm->isnull,
- NULL);
+ &prm->isnull);
i++;
}
@@ -682,10 +691,10 @@ FetchPreparedStatementTargetList(PreparedStatement *stmt)
List *tlist;
/* Get the plan's primary targetlist */
- tlist = CachedPlanGetTargetList(stmt->plansource);
+ tlist = CachedPlanGetTargetList(stmt->plansource, NULL);
/* Copy into caller's context in case plan gets invalidated */
- return (List *) copyObject(tlist);
+ return copyObject(tlist);
}
/*
@@ -772,7 +781,8 @@ DropAllPreparedStatements(void)
*/
void
ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
- const char *queryString, ParamListInfo params)
+ const char *queryString, ParamListInfo params,
+ QueryEnvironment *queryEnv)
{
PreparedStatement *entry;
const char *query_string;
@@ -781,6 +791,10 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
ListCell *p;
ParamListInfo paramLI = NULL;
EState *estate = NULL;
+ instr_time planstart;
+ instr_time planduration;
+
+ INSTR_TIME_SET_CURRENT(planstart);
/* Look it up in the hash table */
entry = FetchPreparedStatement(execstmt->name, true);
@@ -807,19 +821,24 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
}
/* Replan if needed, and acquire a transient refcount */
- cplan = GetCachedPlan(entry->plansource, paramLI, true);
+ cplan = GetCachedPlan(entry->plansource, paramLI, true, queryEnv);
+
+ INSTR_TIME_SET_CURRENT(planduration);
+ INSTR_TIME_SUBTRACT(planduration, planstart);
plan_list = cplan->stmt_list;
/* Explain each query */
foreach(p, plan_list)
{
- PlannedStmt *pstmt = (PlannedStmt *) lfirst(p);
+ PlannedStmt *pstmt = lfirst_node(PlannedStmt, p);
- if (IsA(pstmt, PlannedStmt))
- ExplainOnePlan(pstmt, into, es, query_string, paramLI, NULL);
+ if (pstmt->commandType != CMD_UTILITY)
+ ExplainOnePlan(pstmt, into, es, query_string, paramLI, queryEnv,
+ &planduration);
else
- ExplainOneUtility((Node *) pstmt, into, es, query_string, paramLI);
+ ExplainOneUtility(pstmt->utilityStmt, into, es, query_string,
+ paramLI, queryEnv);
/* No need for CommandCounterIncrement, as ExplainOnePlan did it */
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 761d08f604..a4fbc05a12 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -3,7 +3,7 @@
* proclang.c
* PostgreSQL PROCEDURAL LANGUAGE support code.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -278,8 +278,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
{
ereport(WARNING,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"",
- NameListToString(stmt->plhandler))));
+ errmsg("changing return type of function %s from %s to %s",
+ NameListToString(stmt->plhandler),
+ "opaque", "language_handler")));
SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
}
else
@@ -377,7 +378,7 @@ create_proc_lang(const char *languageName, bool replace,
/* Okay, do it... */
tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
- simple_heap_update(rel, &tup->t_self, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
ReleaseSysCache(oldtup);
is_update = true;
@@ -386,13 +387,10 @@ create_proc_lang(const char *languageName, bool replace,
{
/* Creating a new language */
tup = heap_form_tuple(tupDesc, values, nulls);
- simple_heap_insert(rel, tup);
+ CatalogTupleInsert(rel, tup);
is_update = false;
}
- /* Need to update indexes for either the insert or update case */
- CatalogUpdateIndexes(rel, tup);
-
/*
* Create dependencies for the new language. If we are updating an
* existing language, first delete any existing pg_depend entries.
@@ -463,7 +461,7 @@ find_language_template(const char *languageName)
ScanKeyInit(&key,
Anum_pg_pltemplate_tmplname,
BTEqualStrategyNumber, F_NAMEEQ,
- NameGetDatum(languageName));
+ CStringGetDatum(languageName));
scan = systable_beginscan(rel, PLTemplateNameIndexId, true,
NULL, 1, &key);
@@ -538,7 +536,7 @@ DropProceduralLanguageById(Oid langOid)
if (!HeapTupleIsValid(langTup)) /* should not happen */
elog(ERROR, "cache lookup failed for language %u", langOid);
- simple_heap_delete(rel, &langTup->t_self);
+ CatalogTupleDelete(rel, &langTup->t_self);
ReleaseSysCache(langTup);
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
new file mode 100644
index 0000000000..8f06c23df9
--- /dev/null
+++ b/src/backend/commands/publicationcmds.c
@@ -0,0 +1,740 @@
+/*-------------------------------------------------------------------------
+ *
+ * publicationcmds.c
+ * publication manipulation
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * publicationcmds.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "miscadmin.h"
+
+#include "access/genam.h"
+#include "access/hash.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/xact.h"
+
+#include "catalog/catalog.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_inherits_fn.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_publication.h"
+#include "catalog/pg_publication_rel.h"
+
+#include "commands/dbcommands.h"
+#include "commands/defrem.h"
+#include "commands/event_trigger.h"
+#include "commands/publicationcmds.h"
+
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/fmgroids.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+#include "utils/varlena.h"
+
+/* Same as MAXNUMMESSAGES in sinvaladt.c */
+#define MAX_RELCACHE_INVAL_MSGS 4096
+
+static List *OpenTableList(List *tables);
+static void CloseTableList(List *rels);
+static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
+ AlterPublicationStmt *stmt);
+static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
+
+static void
+parse_publication_options(List *options,
+ bool *publish_given,
+ bool *publish_insert,
+ bool *publish_update,
+ bool *publish_delete)
+{
+ ListCell *lc;
+
+ *publish_given = false;
+
+ /* Defaults are true */
+ *publish_insert = true;
+ *publish_update = true;
+ *publish_delete = true;
+
+ /* Parse options */
+ foreach(lc, options)
+ {
+ DefElem *defel = (DefElem *) lfirst(lc);
+
+ if (strcmp(defel->defname, "publish") == 0)
+ {
+ char *publish;
+ List *publish_list;
+ ListCell *lc;
+
+ if (*publish_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ /*
+ * If publish option was given only the explicitly listed actions
+ * should be published.
+ */
+ *publish_insert = false;
+ *publish_update = false;
+ *publish_delete = false;
+
+ *publish_given = true;
+ publish = defGetString(defel);
+
+ if (!SplitIdentifierString(publish, ',', &publish_list))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid publish list")));
+
+ /* Process the option list. */
+ foreach(lc, publish_list)
+ {
+ char *publish_opt = (char *) lfirst(lc);
+
+ if (strcmp(publish_opt, "insert") == 0)
+ *publish_insert = true;
+ else if (strcmp(publish_opt, "update") == 0)
+ *publish_update = true;
+ else if (strcmp(publish_opt, "delete") == 0)
+ *publish_delete = true;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized \"publish\" value: \"%s\"", publish_opt)));
+ }
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized publication parameter: %s", defel->defname)));
+ }
+}
+
+/*
+ * Create new publication.
+ */
+ObjectAddress
+CreatePublication(CreatePublicationStmt *stmt)
+{
+ Relation rel;
+ ObjectAddress myself;
+ Oid puboid;
+ bool nulls[Natts_pg_publication];
+ Datum values[Natts_pg_publication];
+ HeapTuple tup;
+ bool publish_given;
+ bool publish_insert;
+ bool publish_update;
+ bool publish_delete;
+ AclResult aclresult;
+
+ /* must have CREATE privilege on database */
+ aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_DATABASE,
+ get_database_name(MyDatabaseId));
+
+ /* FOR ALL TABLES requires superuser */
+ if (stmt->for_all_tables && !superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to create FOR ALL TABLES publication"))));
+
+ rel = heap_open(PublicationRelationId, RowExclusiveLock);
+
+ /* Check if name is used */
+ puboid = GetSysCacheOid1(PUBLICATIONNAME, CStringGetDatum(stmt->pubname));
+ if (OidIsValid(puboid))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("publication \"%s\" already exists",
+ stmt->pubname)));
+ }
+
+ /* Form a tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_publication_pubname - 1] =
+ DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname));
+ values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
+
+ parse_publication_options(stmt->options,
+ &publish_given, &publish_insert,
+ &publish_update, &publish_delete);
+
+ values[Anum_pg_publication_puballtables - 1] =
+ BoolGetDatum(stmt->for_all_tables);
+ values[Anum_pg_publication_pubinsert - 1] =
+ BoolGetDatum(publish_insert);
+ values[Anum_pg_publication_pubupdate - 1] =
+ BoolGetDatum(publish_update);
+ values[Anum_pg_publication_pubdelete - 1] =
+ BoolGetDatum(publish_delete);
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ puboid = CatalogTupleInsert(rel, tup);
+ heap_freetuple(tup);
+
+ recordDependencyOnOwner(PublicationRelationId, puboid, GetUserId());
+
+ ObjectAddressSet(myself, PublicationRelationId, puboid);
+
+ /* Make the changes visible. */
+ CommandCounterIncrement();
+
+ if (stmt->tables)
+ {
+ List *rels;
+
+ Assert(list_length(stmt->tables) > 0);
+
+ rels = OpenTableList(stmt->tables);
+ PublicationAddTables(puboid, rels, true, NULL);
+ CloseTableList(rels);
+ }
+
+ heap_close(rel, RowExclusiveLock);
+
+ InvokeObjectPostCreateHook(PublicationRelationId, puboid, 0);
+
+ return myself;
+}
+
+/*
+ * Change options of a publication.
+ */
+static void
+AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
+ HeapTuple tup)
+{
+ bool nulls[Natts_pg_publication];
+ bool replaces[Natts_pg_publication];
+ Datum values[Natts_pg_publication];
+ bool publish_given;
+ bool publish_insert;
+ bool publish_update;
+ bool publish_delete;
+ ObjectAddress obj;
+
+ parse_publication_options(stmt->options,
+ &publish_given, &publish_insert,
+ &publish_update, &publish_delete);
+
+ /* Everything ok, form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ if (publish_given)
+ {
+ values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(publish_insert);
+ replaces[Anum_pg_publication_pubinsert - 1] = true;
+
+ values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(publish_update);
+ replaces[Anum_pg_publication_pubupdate - 1] = true;
+
+ values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(publish_delete);
+ replaces[Anum_pg_publication_pubdelete - 1] = true;
+ }
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ CommandCounterIncrement();
+
+ /* Invalidate the relcache. */
+ if (((Form_pg_publication) GETSTRUCT(tup))->puballtables)
+ {
+ CacheInvalidateRelcacheAll();
+ }
+ else
+ {
+ List *relids = GetPublicationRelations(HeapTupleGetOid(tup));
+
+ /*
+ * We don't want to send too many individual messages, at some point
+ * it's cheaper to just reset whole relcache.
+ */
+ if (list_length(relids) < MAX_RELCACHE_INVAL_MSGS)
+ {
+ ListCell *lc;
+
+ foreach(lc, relids)
+ {
+ Oid relid = lfirst_oid(lc);
+
+ CacheInvalidateRelcacheByRelid(relid);
+ }
+ }
+ else
+ CacheInvalidateRelcacheAll();
+ }
+
+ ObjectAddressSet(obj, PublicationRelationId, HeapTupleGetOid(tup));
+ EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
+ (Node *) stmt);
+
+ InvokeObjectPostAlterHook(PublicationRelationId, HeapTupleGetOid(tup), 0);
+}
+
+/*
+ * Add or remove table to/from publication.
+ */
+static void
+AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
+ HeapTuple tup)
+{
+ Oid pubid = HeapTupleGetOid(tup);
+ List *rels = NIL;
+ Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
+
+ /* Check that user is allowed to manipulate the publication tables. */
+ if (pubform->puballtables)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
+
+ Assert(list_length(stmt->tables) > 0);
+
+ rels = OpenTableList(stmt->tables);
+
+ if (stmt->tableAction == DEFELEM_ADD)
+ PublicationAddTables(pubid, rels, false, stmt);
+ else if (stmt->tableAction == DEFELEM_DROP)
+ PublicationDropTables(pubid, rels, false);
+ else /* DEFELEM_SET */
+ {
+ List *oldrelids = GetPublicationRelations(pubid);
+ List *delrels = NIL;
+ ListCell *oldlc;
+
+ /* Calculate which relations to drop. */
+ foreach(oldlc, oldrelids)
+ {
+ Oid oldrelid = lfirst_oid(oldlc);
+ ListCell *newlc;
+ bool found = false;
+
+ foreach(newlc, rels)
+ {
+ Relation newrel = (Relation) lfirst(newlc);
+
+ if (RelationGetRelid(newrel) == oldrelid)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ Relation oldrel = heap_open(oldrelid,
+ ShareUpdateExclusiveLock);
+
+ delrels = lappend(delrels, oldrel);
+ }
+ }
+
+ /* And drop them. */
+ PublicationDropTables(pubid, delrels, true);
+
+ /*
+ * Don't bother calculating the difference for adding, we'll catch and
+ * skip existing ones when doing catalog update.
+ */
+ PublicationAddTables(pubid, rels, true, stmt);
+
+ CloseTableList(delrels);
+ }
+
+ CloseTableList(rels);
+}
+
+/*
+ * Alter the existing publication.
+ *
+ * This is dispatcher function for AlterPublicationOptions and
+ * AlterPublicationTables.
+ */
+void
+AlterPublication(AlterPublicationStmt *stmt)
+{
+ Relation rel;
+ HeapTuple tup;
+
+ rel = heap_open(PublicationRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(PUBLICATIONNAME,
+ CStringGetDatum(stmt->pubname));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication \"%s\" does not exist",
+ stmt->pubname)));
+
+ /* must be owner */
+ if (!pg_publication_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PUBLICATION,
+ stmt->pubname);
+
+ if (stmt->options)
+ AlterPublicationOptions(stmt, rel, tup);
+ else
+ AlterPublicationTables(stmt, rel, tup);
+
+ /* Cleanup. */
+ heap_freetuple(tup);
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * Drop publication by OID
+ */
+void
+RemovePublicationById(Oid pubid)
+{
+ Relation rel;
+ HeapTuple tup;
+
+ rel = heap_open(PublicationRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication %u", pubid);
+
+ CatalogTupleDelete(rel, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * Remove relation from publication by mapping OID.
+ */
+void
+RemovePublicationRelById(Oid proid)
+{
+ Relation rel;
+ HeapTuple tup;
+ Form_pg_publication_rel pubrel;
+
+ rel = heap_open(PublicationRelRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache1(PUBLICATIONREL, ObjectIdGetDatum(proid));
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication table %u",
+ proid);
+
+ pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+
+ /* Invalidate relcache so that publication info is rebuilt. */
+ CacheInvalidateRelcacheByRelid(pubrel->prrelid);
+
+ CatalogTupleDelete(rel, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * Open relations based on provided by RangeVar list.
+ * The returned tables are locked in ShareUpdateExclusiveLock mode.
+ */
+static List *
+OpenTableList(List *tables)
+{
+ List *relids = NIL;
+ List *rels = NIL;
+ ListCell *lc;
+
+ /*
+ * Open, share-lock, and check all the explicitly-specified relations
+ */
+ foreach(lc, tables)
+ {
+ RangeVar *rv = lfirst(lc);
+ Relation rel;
+ bool recurse = rv->inh;
+ Oid myrelid;
+
+ CHECK_FOR_INTERRUPTS();
+
+ rel = heap_openrv(rv, ShareUpdateExclusiveLock);
+ myrelid = RelationGetRelid(rel);
+
+ /*
+ * Filter out duplicates if user specifies "foo, foo".
+ *
+ * Note that this algorithm is known to not be very efficient (O(N^2))
+ * but given that it only works on list of tables given to us by user
+ * it's deemed acceptable.
+ */
+ if (list_member_oid(relids, myrelid))
+ {
+ heap_close(rel, ShareUpdateExclusiveLock);
+ continue;
+ }
+ rels = lappend(rels, rel);
+ relids = lappend_oid(relids, myrelid);
+
+ if (recurse)
+ {
+ ListCell *child;
+ List *children;
+
+ children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
+ NULL);
+
+ foreach(child, children)
+ {
+ Oid childrelid = lfirst_oid(child);
+
+ if (list_member_oid(relids, childrelid))
+ continue;
+
+ /*
+ * Skip duplicates if user specified both parent and child
+ * tables.
+ */
+ if (list_member_oid(relids, childrelid))
+ {
+ heap_close(rel, ShareUpdateExclusiveLock);
+ continue;
+ }
+
+ /* find_all_inheritors already got lock */
+ rel = heap_open(childrelid, NoLock);
+ rels = lappend(rels, rel);
+ relids = lappend_oid(relids, childrelid);
+ }
+ }
+ }
+
+ list_free(relids);
+
+ return rels;
+}
+
+/*
+ * Close all relations in the list.
+ */
+static void
+CloseTableList(List *rels)
+{
+ ListCell *lc;
+
+ foreach(lc, rels)
+ {
+ Relation rel = (Relation) lfirst(lc);
+
+ heap_close(rel, NoLock);
+ }
+}
+
+/*
+ * Add listed tables to the publication.
+ */
+static void
+PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
+ AlterPublicationStmt *stmt)
+{
+ ListCell *lc;
+
+ Assert(!stmt || !stmt->for_all_tables);
+
+ foreach(lc, rels)
+ {
+ Relation rel = (Relation) lfirst(lc);
+ ObjectAddress obj;
+
+ /* Must be owner of the table or superuser. */
+ if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+ RelationGetRelationName(rel));
+
+ obj = publication_add_relation(pubid, rel, if_not_exists);
+ if (stmt)
+ {
+ EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
+ (Node *) stmt);
+
+ InvokeObjectPostCreateHook(PublicationRelRelationId,
+ obj.objectId, 0);
+ }
+ }
+}
+
+/*
+ * Remove listed tables from the publication.
+ */
+static void
+PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
+{
+ ObjectAddress obj;
+ ListCell *lc;
+ Oid prid;
+
+ foreach(lc, rels)
+ {
+ Relation rel = (Relation) lfirst(lc);
+ Oid relid = RelationGetRelid(rel);
+
+ prid = GetSysCacheOid2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(pubid));
+ if (!OidIsValid(prid))
+ {
+ if (missing_ok)
+ continue;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("relation \"%s\" is not part of the publication",
+ RelationGetRelationName(rel))));
+ }
+
+ ObjectAddressSet(obj, PublicationRelRelationId, prid);
+ performDeletion(&obj, DROP_CASCADE, 0);
+ }
+}
+
+/*
+ * Internal workhorse for changing a publication owner
+ */
+static void
+AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
+{
+ Form_pg_publication form;
+
+ form = (Form_pg_publication) GETSTRUCT(tup);
+
+ if (form->pubowner == newOwnerId)
+ return;
+
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Must be owner */
+ if (!pg_publication_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PUBLICATION,
+ NameStr(form->pubname));
+
+ /* Must be able to become new owner */
+ check_is_member_of_role(GetUserId(), newOwnerId);
+
+ /* New owner must have CREATE privilege on database */
+ aclresult = pg_database_aclcheck(MyDatabaseId, newOwnerId, ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_DATABASE,
+ get_database_name(MyDatabaseId));
+
+ if (form->puballtables && !superuser_arg(newOwnerId))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to change owner of publication \"%s\"",
+ NameStr(form->pubname)),
+ errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
+ }
+
+ form->pubowner = newOwnerId;
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Update owner dependency reference */
+ changeDependencyOnOwner(PublicationRelationId,
+ HeapTupleGetOid(tup),
+ newOwnerId);
+
+ InvokeObjectPostAlterHook(PublicationRelationId,
+ HeapTupleGetOid(tup), 0);
+}
+
+/*
+ * Change publication owner -- by name
+ */
+ObjectAddress
+AlterPublicationOwner(const char *name, Oid newOwnerId)
+{
+ Oid subid;
+ HeapTuple tup;
+ Relation rel;
+ ObjectAddress address;
+
+ rel = heap_open(PublicationRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(PUBLICATIONNAME, CStringGetDatum(name));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication \"%s\" does not exist", name)));
+
+ subid = HeapTupleGetOid(tup);
+
+ AlterPublicationOwner_internal(rel, tup, newOwnerId);
+
+ ObjectAddressSet(address, PublicationRelationId, subid);
+
+ heap_freetuple(tup);
+
+ heap_close(rel, RowExclusiveLock);
+
+ return address;
+}
+
+/*
+ * Change publication owner -- by OID
+ */
+void
+AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
+{
+ HeapTuple tup;
+ Relation rel;
+
+ rel = heap_open(PublicationRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(PUBLICATIONOID, ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication with OID %u does not exist", subid)));
+
+ AlterPublicationOwner_internal(rel, tup, newOwnerId);
+
+ heap_freetuple(tup);
+
+ heap_close(rel, RowExclusiveLock);
+}
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 255ca89199..546b54bd9f 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -4,7 +4,7 @@
* schema creation/manipulation commands
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -45,13 +45,17 @@ static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerI
/*
* CREATE SCHEMA
+ *
+ * Note: caller should pass in location information for the whole
+ * CREATE SCHEMA statement, which in turn we pass down as the location
+ * of the component commands. This comports with our general plan of
+ * reporting location/len for the whole command even when executing
+ * a subquery.
*/
Oid
-#ifdef PGXC
-CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, bool sentToRemote)
-#else
-CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
-#endif
+CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
+ bool sentToRemote,
+ int stmt_location, int stmt_len)
{
const char *schemaName = stmt->schemaname;
Oid namespaceId;
@@ -191,17 +195,28 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
foreach(parsetree_item, parsetree_list)
{
Node *stmt = (Node *) lfirst(parsetree_item);
+ PlannedStmt *wrapper;
+
+ /* need to make a wrapper PlannedStmt */
+ wrapper = makeNode(PlannedStmt);
+ wrapper->commandType = CMD_UTILITY;
+ wrapper->canSetTag = false;
+ wrapper->utilityStmt = stmt;
+ wrapper->stmt_location = stmt_location;
+ wrapper->stmt_len = stmt_len;
/* do this step */
- ProcessUtility(stmt,
+ ProcessUtility(wrapper,
queryString,
PROCESS_UTILITY_SUBCOMMAND,
NULL,
+ NULL,
None_Receiver,
#ifdef PGXC
true,
#endif /* PGXC */
NULL);
+
/* make sure later steps can see the object created here */
CommandCounterIncrement();
}
@@ -231,7 +246,7 @@ RemoveSchemaById(Oid schemaOid)
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for namespace %u", schemaOid);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -286,8 +301,7 @@ RenameSchema(const char *oldname, const char *newname)
/* rename */
namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname);
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
InvokeObjectPostAlterHook(NamespaceRelationId, HeapTupleGetOid(tup), 0);
@@ -442,8 +456,7 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
heap_freetuple(newtuple);
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index 5bd7e124c1..5f16d6cf1c 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -3,7 +3,7 @@
* seclabel.c
* routines to support security label feature.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* -------------------------------------------------------------------------
@@ -89,12 +89,12 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
* object does not exist, and will also acquire a lock on the target to
* guard against concurrent modifications.
*/
- address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
+ address = get_object_address(stmt->objtype, stmt->object,
&relation, ShareUpdateExclusiveLock, false);
/* Require ownership of the target object. */
check_object_ownership(GetUserId(), stmt->objtype, address,
- stmt->objname, stmt->objargs, relation);
+ stmt->object, relation);
/* Perform other integrity checks as needed. */
switch (stmt->objtype)
@@ -110,7 +110,8 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
relation->rd_rel->relkind != RELKIND_VIEW &&
relation->rd_rel->relkind != RELKIND_MATVIEW &&
relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
- relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
@@ -292,13 +293,13 @@ SetSharedSecurityLabel(const ObjectAddress *object,
if (HeapTupleIsValid(oldtup))
{
if (label == NULL)
- simple_heap_delete(pg_shseclabel, &oldtup->t_self);
+ CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
else
{
replaces[Anum_pg_shseclabel_label - 1] = true;
newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
values, nulls, replaces);
- simple_heap_update(pg_shseclabel, &oldtup->t_self, newtup);
+ CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
}
}
systable_endscan(scan);
@@ -308,15 +309,11 @@ SetSharedSecurityLabel(const ObjectAddress *object,
{
newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
values, nulls);
- simple_heap_insert(pg_shseclabel, newtup);
+ CatalogTupleInsert(pg_shseclabel, newtup);
}
- /* Update indexes, if necessary */
if (newtup != NULL)
- {
- CatalogUpdateIndexes(pg_shseclabel, newtup);
heap_freetuple(newtup);
- }
heap_close(pg_shseclabel, RowExclusiveLock);
}
@@ -383,13 +380,13 @@ SetSecurityLabel(const ObjectAddress *object,
if (HeapTupleIsValid(oldtup))
{
if (label == NULL)
- simple_heap_delete(pg_seclabel, &oldtup->t_self);
+ CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
else
{
replaces[Anum_pg_seclabel_label - 1] = true;
newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
values, nulls, replaces);
- simple_heap_update(pg_seclabel, &oldtup->t_self, newtup);
+ CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
}
}
systable_endscan(scan);
@@ -399,15 +396,12 @@ SetSecurityLabel(const ObjectAddress *object,
{
newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
values, nulls);
- simple_heap_insert(pg_seclabel, newtup);
+ CatalogTupleInsert(pg_seclabel, newtup);
}
/* Update indexes, if necessary */
if (newtup != NULL)
- {
- CatalogUpdateIndexes(pg_seclabel, newtup);
heap_freetuple(newtup);
- }
heap_close(pg_seclabel, RowExclusiveLock);
}
@@ -438,7 +432,7 @@ DeleteSharedSecurityLabel(Oid objectId, Oid classId)
scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
NULL, 2, skey);
while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
- simple_heap_delete(pg_shseclabel, &oldtup->t_self);
+ CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
systable_endscan(scan);
heap_close(pg_shseclabel, RowExclusiveLock);
@@ -489,7 +483,7 @@ DeleteSecurityLabel(const ObjectAddress *object)
scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
NULL, nkeys, skey);
while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
- simple_heap_delete(pg_seclabel, &oldtup->t_self);
+ CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
systable_endscan(scan);
heap_close(pg_seclabel, RowExclusiveLock);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index e4a2029477..0ccbe37a1b 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -4,7 +4,7 @@
* PostgreSQL sequences support code.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -15,7 +15,9 @@
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include <math.h>
+#include "access/bufmask.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/transam.h"
@@ -24,8 +26,10 @@
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/dependency.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
+#include "catalog/pg_sequence.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/sequence.h"
@@ -33,6 +37,7 @@
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
+#include "parser/parse_type.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/smgr.h"
@@ -52,6 +57,7 @@
#include "utils/timestamp.h"
#endif
#endif
+#include "utils/varlena.h"
/*
* We don't want to log each fetching of a value from a sequence,
@@ -92,7 +98,7 @@ typedef struct SeqTableData
int64 cached; /* last value already cached for nextval */
/* if last != cached, we have not used up all the cached values */
int64 increment; /* copy of sequence's increment field */
- /* note that increment is zero until we first do read_seq_tuple() */
+ /* note that increment is zero until we first do nextval_internal() */
#ifdef XCP
TimestampTz last_call_time; /* the time when the last call as made */
int64 range_multiplier; /* multiply this value with 2 next time */
@@ -131,21 +137,20 @@ typedef struct rename_sequence_callback_arg
static SeqTableData *last_used_seq = NULL;
static void fill_seq_with_data(Relation rel, HeapTuple tuple);
-static int64 nextval_internal(Oid relid);
-static Relation open_share_lock(SeqTable seq);
+static Relation lock_and_open_sequence(SeqTable seq);
static void create_seq_hashtable(void);
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
-static Form_pg_sequence read_seq_tuple(SeqTable elm, Relation rel,
- Buffer *buf, HeapTuple seqtuple);
-#ifdef PGXC
-static void init_params(List *options, bool isInit,
- Form_pg_sequence new, List **owned_by, bool *is_restart);
-#else
-static void init_params(List *options, bool isInit,
- Form_pg_sequence new, List **owned_by);
-#endif
+static Form_pg_sequence_data read_seq_tuple(Relation rel,
+ Buffer *buf, HeapTuple seqdatatuple);
+static LOCKMODE alter_sequence_get_lock_level(List *options);
+static void init_params(ParseState *pstate, List *options, bool for_identity,
+ bool isInit,
+ Form_pg_sequence seqform,
+ bool *changed_seqform,
+ Form_pg_sequence_data seqdataform, List **owned_by,
+ bool *is_restart);
static void do_setval(Oid relid, int64 next, bool iscalled);
-static void process_owned_by(Relation seqrel, List *owned_by);
+static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity);
/*
@@ -153,9 +158,11 @@ static void process_owned_by(Relation seqrel, List *owned_by);
* Creates a new sequence relation
*/
ObjectAddress
-DefineSequence(CreateSeqStmt *seq)
+DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
{
- FormData_pg_sequence new;
+ FormData_pg_sequence seqform;
+ FormData_pg_sequence_data seqdataform;
+ bool changed_seqform = false; /* not used here */
List *owned_by;
CreateStmt *stmt = makeNode(CreateStmt);
Oid seqoid;
@@ -165,8 +172,9 @@ DefineSequence(CreateSeqStmt *seq)
TupleDesc tupDesc;
Datum value[SEQ_COL_LASTCOL];
bool null[SEQ_COL_LASTCOL];
+ Datum pgs_values[Natts_pg_sequence];
+ bool pgs_nulls[Natts_pg_sequence];
int i;
- NameData name;
#ifdef PGXC /* PGXC_COORD */
GTM_Sequence start_value = 1;
GTM_Sequence min_value = 1;
@@ -201,11 +209,8 @@ DefineSequence(CreateSeqStmt *seq)
}
/* Check and set all option values */
-#ifdef PGXC
- init_params(seq->options, true, &new, &owned_by, &is_restart);
-#else
- init_params(seq->options, true, &new, &owned_by);
-#endif
+ init_params(pstate, seq->options, seq->for_identity, true, &seqform,
+ &changed_seqform, &seqdataform, &owned_by, &is_restart);
/*
* Create relation (and fill value[] and null[] for the tuple)
@@ -219,6 +224,7 @@ DefineSequence(CreateSeqStmt *seq)
coldef->is_local = true;
coldef->is_not_null = true;
coldef->is_from_type = false;
+ coldef->is_from_parent = false;
coldef->storage = 0;
coldef->raw_default = NULL;
coldef->cooked_default = NULL;
@@ -231,67 +237,16 @@ DefineSequence(CreateSeqStmt *seq)
switch (i)
{
- case SEQ_COL_NAME:
- coldef->typeName = makeTypeNameFromOid(NAMEOID, -1);
- coldef->colname = "sequence_name";
- namestrcpy(&name, seq->sequence->relname);
- value[i - 1] = NameGetDatum(&name);
- break;
case SEQ_COL_LASTVAL:
coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "last_value";
- value[i - 1] = Int64GetDatumFast(new.last_value);
- break;
- case SEQ_COL_STARTVAL:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "start_value";
- value[i - 1] = Int64GetDatumFast(new.start_value);
-#ifdef PGXC /* PGXC_COORD */
- start_value = new.start_value;
-#endif
- break;
- case SEQ_COL_INCBY:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "increment_by";
- value[i - 1] = Int64GetDatumFast(new.increment_by);
-#ifdef PGXC /* PGXC_COORD */
- increment = new.increment_by;
-#endif
- break;
- case SEQ_COL_MAXVALUE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "max_value";
- value[i - 1] = Int64GetDatumFast(new.max_value);
-#ifdef PGXC /* PGXC_COORD */
- max_value = new.max_value;
-#endif
- break;
- case SEQ_COL_MINVALUE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "min_value";
- value[i - 1] = Int64GetDatumFast(new.min_value);
-#ifdef PGXC /* PGXC_COORD */
- min_value = new.min_value;
-#endif
- break;
- case SEQ_COL_CACHE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "cache_value";
- value[i - 1] = Int64GetDatumFast(new.cache_value);
+ value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
break;
case SEQ_COL_LOG:
coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "log_cnt";
value[i - 1] = Int64GetDatum((int64) 0);
break;
- case SEQ_COL_CYCLE:
- coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
- coldef->colname = "is_cycled";
- value[i - 1] = BoolGetDatum(new.is_cycled);
-#ifdef PGXC /* PGXC_COORD */
- cycle = new.is_cycled;
-#endif
- break;
case SEQ_COL_CALLED:
coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
coldef->colname = "is_called";
@@ -309,7 +264,7 @@ DefineSequence(CreateSeqStmt *seq)
stmt->tablespacename = NULL;
stmt->if_not_exists = seq->if_not_exists;
- address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL);
+ address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
seqoid = address.objectId;
Assert(seqoid != InvalidOid);
@@ -322,10 +277,31 @@ DefineSequence(CreateSeqStmt *seq)
/* process OWNED BY if given */
if (owned_by)
- process_owned_by(rel, owned_by);
+ process_owned_by(rel, owned_by, seq->for_identity);
heap_close(rel, NoLock);
+ /* fill in pg_sequence */
+ rel = heap_open(SequenceRelationId, RowExclusiveLock);
+ tupDesc = RelationGetDescr(rel);
+
+ memset(pgs_nulls, 0, sizeof(pgs_nulls));
+
+ pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
+ pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
+ pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
+ pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
+ pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
+ pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
+ pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
+ pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
+
+ tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
+ CatalogTupleInsert(rel, tuple);
+
+ heap_freetuple(tuple);
+ heap_close(rel, RowExclusiveLock);
+
#ifdef PGXC /* PGXC_COORD */
/*
* Remote Coordinator is in charge of creating sequence in GTM.
@@ -371,10 +347,13 @@ ResetSequence(Oid seq_relid)
{
Relation seq_rel;
SeqTable elm;
- Form_pg_sequence seq;
+ Form_pg_sequence_data seq;
Buffer buf;
- HeapTupleData seqtuple;
+ HeapTupleData seqdatatuple;
HeapTuple tuple;
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ int64 startv;
/*
* Read the old sequence. This does a bit more work than really
@@ -382,12 +361,19 @@ ResetSequence(Oid seq_relid)
* indeed a sequence.
*/
init_sequence(seq_relid, &elm, &seq_rel);
- (void) read_seq_tuple(elm, seq_rel, &buf, &seqtuple);
+ (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
+
+ pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+ startv = pgsform->seqstart;
+ ReleaseSysCache(pgstuple);
/*
* Copy the existing sequence tuple.
*/
- tuple = heap_copytuple(&seqtuple);
+ tuple = heap_copytuple(&seqdatatuple);
/* Now we're done with the old page */
UnlockReleaseBuffer(buf);
@@ -396,8 +382,8 @@ ResetSequence(Oid seq_relid)
* Modify the copied tuple to execute the restart (compare the RESTART
* action in AlterSequence)
*/
- seq = (Form_pg_sequence) GETSTRUCT(tuple);
- seq->last_value = seq->start_value;
+ seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
+ seq->last_value = startv;
seq->is_called = false;
seq->log_cnt = 0;
@@ -504,15 +490,17 @@ fill_seq_with_data(Relation rel, HeapTuple tuple)
* Modify the definition of a sequence relation
*/
ObjectAddress
-AlterSequence(AlterSeqStmt *stmt)
+AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
{
Oid relid;
SeqTable elm;
Relation seqrel;
Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
- FormData_pg_sequence new;
+ HeapTupleData seqdatatuple;
+ Form_pg_sequence seqform;
+ Form_pg_sequence_data seqdata;
+ FormData_pg_sequence_data newseqdata;
+ bool changed_seqform = false;
List *owned_by;
#ifdef PGXC
GTM_Sequence start_value;
@@ -524,9 +512,13 @@ AlterSequence(AlterSeqStmt *stmt)
bool is_restart;
#endif
ObjectAddress address;
+ Relation rel;
+ HeapTuple tuple;
/* Open and lock sequence. */
- relid = RangeVarGetRelid(stmt->sequence, AccessShareLock, stmt->missing_ok);
+ relid = RangeVarGetRelid(stmt->sequence,
+ alter_sequence_get_lock_level(stmt->options),
+ stmt->missing_ok);
if (relid == InvalidOid)
{
ereport(NOTICE,
@@ -542,18 +534,24 @@ AlterSequence(AlterSeqStmt *stmt)
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
stmt->sequence->relname);
- /* lock page' buffer and read tuple into new sequence structure */
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ rel = heap_open(SequenceRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopy1(SEQRELID,
+ ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for sequence %u",
+ relid);
+
+ seqform = (Form_pg_sequence) GETSTRUCT(tuple);
- /* Copy old values of options into workspace */
- memcpy(&new, seq, sizeof(FormData_pg_sequence));
+ /* lock page's buffer and read tuple into new sequence structure */
+ seqdata = read_seq_tuple(seqrel, &buf, &seqdatatuple);
+
+ /* Copy old sequence data into workspace */
+ memcpy(&newseqdata, seqdata, sizeof(FormData_pg_sequence_data));
/* Check and set new values */
-#ifdef PGXC
- init_params(stmt->options, false, &new, &owned_by, &is_restart);
-#else
- init_params(stmt->options, false, &new, &owned_by);
-#endif
+ init_params(pstate, stmt->options, stmt->for_identity, false, seqform,
+ &changed_seqform, &newseqdata, &owned_by, &is_restart);
/* Clear local cache so that we don't think we have cached numbers */
/* Note that we do not change the currval() state */
@@ -565,17 +563,17 @@ AlterSequence(AlterSeqStmt *stmt)
/* Now okay to update the on-disk tuple */
#ifdef PGXC
- increment = new.increment_by;
- min_value = new.min_value;
- max_value = new.max_value;
- start_value = new.start_value;
- last_value = new.last_value;
- cycle = new.is_cycled;
+ increment = seqform->seqincrement;
+ min_value = seqform->seqmin;
+ max_value = seqform->seqmax;
+ start_value = seqform->seqstart;
+ last_value = elm->last;
+ cycle = seqform->seqcycle;
#endif
START_CRIT_SECTION();
- memcpy(seq, &new, sizeof(FormData_pg_sequence));
+ memcpy(seqdata, &newseqdata, sizeof(FormData_pg_sequence_data));
MarkBufferDirty(buf);
@@ -592,7 +590,7 @@ AlterSequence(AlterSeqStmt *stmt)
xlrec.node = seqrel->rd_node;
XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
- XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+ XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
@@ -605,12 +603,16 @@ AlterSequence(AlterSeqStmt *stmt)
/* process OWNED BY if given */
if (owned_by)
- process_owned_by(seqrel, owned_by);
+ process_owned_by(seqrel, owned_by, stmt->for_identity);
InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
ObjectAddressSet(address, RelationRelationId, relid);
+ if (changed_seqform)
+ CatalogTupleUpdate(rel, &tuple->t_self, tuple);
+ heap_close(rel, RowExclusiveLock);
+
relation_close(seqrel, NoLock);
#ifdef PGXC
@@ -640,6 +642,23 @@ AlterSequence(AlterSeqStmt *stmt)
return address;
}
+void
+DeleteSequenceTuple(Oid relid)
+{
+ Relation rel;
+ HeapTuple tuple;
+
+ rel = heap_open(SequenceRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+
+ CatalogTupleDelete(rel, &tuple->t_self);
+
+ ReleaseSysCache(tuple);
+ heap_close(rel, RowExclusiveLock);
+}
/*
* Note: nextval with a text argument is no longer exported as a pg_proc
@@ -649,7 +668,7 @@ AlterSequence(AlterSeqStmt *stmt)
Datum
nextval(PG_FUNCTION_ARGS)
{
- text *seqin = PG_GETARG_TEXT_P(0);
+ text *seqin = PG_GETARG_TEXT_PP(0);
RangeVar *sequence;
Oid relid;
@@ -665,7 +684,7 @@ nextval(PG_FUNCTION_ARGS)
*/
relid = RangeVarGetRelid(sequence, NoLock, false);
- PG_RETURN_INT64(nextval_internal(relid));
+ PG_RETURN_INT64(nextval_internal(relid, true));
}
Datum
@@ -673,18 +692,20 @@ nextval_oid(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);
- PG_RETURN_INT64(nextval_internal(relid));
+ PG_RETURN_INT64(nextval_internal(relid, true));
}
-static int64
-nextval_internal(Oid relid)
+int64
+nextval_internal(Oid relid, bool check_permissions)
{
SeqTable elm;
Relation seqrel;
Buffer buf;
Page page;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ HeapTupleData seqdatatuple;
+ Form_pg_sequence_data seq;
int64 incby,
maxv,
minv,
@@ -695,12 +716,14 @@ nextval_internal(Oid relid)
int64 result,
next,
rescnt = 0;
+ bool cycle;
bool logit = false;
- /* open and AccessShareLock sequence */
+ /* open and lock sequence */
init_sequence(relid, &elm, &seqrel);
- if (pg_class_aclcheck(elm->relid, GetUserId(),
+ if (check_permissions &&
+ pg_class_aclcheck(elm->relid, GetUserId(),
ACL_USAGE | ACL_UPDATE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -728,12 +751,23 @@ nextval_internal(Oid relid)
return elm->last;
}
+ pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+ incby = pgsform->seqincrement;
+ maxv = pgsform->seqmax;
+ minv = pgsform->seqmin;
+ cache = pgsform->seqcache;
+ cycle = pgsform->seqcycle;
+ ReleaseSysCache(pgstuple);
+
/* lock page' buffer and read tuple */
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
page = BufferGetPage(buf);
{
- int64 range = seq->cache_value; /* how many values to ask from GTM? */
+ int64 range = cache; /* how many values to ask from GTM? */
int64 rangemax; /* the max value returned from the GTM for our request */
char *seqname = GetGlobalSeqName(seqrel, NULL, NULL);
@@ -812,7 +846,9 @@ nextval_internal(Oid relid)
last_used_seq = elm;
}
- fetch = cache = seq->cache_value;
+ elm->increment = incby;
+ last = next = result = seq->last_value;
+ fetch = cache;
log = seq->log_cnt;
if (!seq->is_called)
@@ -855,6 +891,52 @@ nextval_internal(Oid relid)
* Check MAXVALUE for ascending sequences and MINVALUE for descending
* sequences
*/
+ if (incby > 0)
+ {
+ /* ascending sequence */
+ if ((maxv >= 0 && next > maxv - incby) ||
+ (maxv < 0 && next + incby > maxv))
+ {
+ if (rescnt > 0)
+ break; /* stop fetching */
+ if (!cycle)
+ {
+ char buf[100];
+
+ snprintf(buf, sizeof(buf), INT64_FORMAT, maxv);
+ ereport(ERROR,
+ (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
+ errmsg("nextval: reached maximum value of sequence \"%s\" (%s)",
+ RelationGetRelationName(seqrel), buf)));
+ }
+ next = minv;
+ }
+ else
+ next += incby;
+ }
+ else
+ {
+ /* descending sequence */
+ if ((minv < 0 && next < minv - incby) ||
+ (minv >= 0 && next + incby < minv))
+ {
+ if (rescnt > 0)
+ break; /* stop fetching */
+ if (!cycle)
+ {
+ char buf[100];
+
+ snprintf(buf, sizeof(buf), INT64_FORMAT, minv);
+ ereport(ERROR,
+ (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
+ errmsg("nextval: reached minimum value of sequence \"%s\" (%s)",
+ RelationGetRelationName(seqrel), buf)));
+ }
+ next = maxv;
+ }
+ else
+ next += incby;
+ }
fetch--;
if (rescnt < cache)
{
@@ -865,7 +947,75 @@ nextval_internal(Oid relid)
log -= fetch; /* adjust for any unfetched numbers */
Assert(log >= 0);
- seq->log_cnt = log;
+
+ /* save info in local cache */
+ elm->last = result; /* last returned number */
+ elm->cached = last; /* last fetched number */
+ elm->last_valid = true;
+
+ last_used_seq = elm;
+
+ /*
+ * If something needs to be WAL logged, acquire an xid, so this
+ * transaction's commit will trigger a WAL flush and wait for syncrep.
+ * It's sufficient to ensure the toplevel transaction has an xid, no need
+ * to assign xids subxacts, that'll already trigger an appropriate wait.
+ * (Have to do that here, so we're outside the critical section)
+ */
+ if (logit && RelationNeedsWAL(seqrel))
+ GetTopTransactionId();
+
+ /* ready to change the on-disk (or really, in-buffer) tuple */
+ START_CRIT_SECTION();
+
+ /*
+ * We must mark the buffer dirty before doing XLogInsert(); see notes in
+ * SyncOneBuffer(). However, we don't apply the desired changes just yet.
+ * This looks like a violation of the buffer update protocol, but it is in
+ * fact safe because we hold exclusive lock on the buffer. Any other
+ * process, including a checkpoint, that tries to examine the buffer
+ * contents will block until we release the lock, and then will see the
+ * final state that we install below.
+ */
+ MarkBufferDirty(buf);
+
+ /* XLOG stuff */
+ if (logit && RelationNeedsWAL(seqrel))
+ {
+ xl_seq_rec xlrec;
+ XLogRecPtr recptr;
+
+ /*
+ * We don't log the current state of the tuple, but rather the state
+ * as it would appear after "log" more fetches. This lets us skip
+ * that many future WAL records, at the cost that we lose those
+ * sequence values if we crash.
+ */
+ XLogBeginInsert();
+ XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
+
+ /* set values that will be saved in xlog */
+ seq->last_value = next;
+ seq->is_called = true;
+ seq->log_cnt = 0;
+
+ xlrec.node = seqrel->rd_node;
+
+ XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
+ XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
+
+ recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
+
+ PageSetLSN(page, recptr);
+ }
+
+ /* Now update sequence tuple to the intended final state */
+ seq->last_value = last; /* last fetched number */
+ seq->is_called = true;
+ seq->log_cnt = log; /* how much is logged */
+
+ END_CRIT_SECTION();
+
UnlockReleaseBuffer(buf);
relation_close(seqrel, NoLock);
@@ -881,7 +1031,7 @@ currval_oid(PG_FUNCTION_ARGS)
SeqTable elm;
Relation seqrel;
- /* open and AccessShareLock sequence */
+ /* open and lock sequence */
init_sequence(relid, &elm, &seqrel);
if (pg_class_aclcheck(elm->relid, GetUserId(),
@@ -931,7 +1081,7 @@ lastval(PG_FUNCTION_ARGS)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("lastval is not yet defined in this session")));
- seqrel = open_share_lock(last_used_seq);
+ seqrel = lock_and_open_sequence(last_used_seq);
/* nextval() must have already been called for this sequence */
Assert(last_used_seq->last_valid);
@@ -968,10 +1118,14 @@ do_setval(Oid relid, int64 next, bool iscalled)
SeqTable elm;
Relation seqrel;
Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
-
- /* open and AccessShareLock sequence */
+ HeapTupleData seqdatatuple;
+ Form_pg_sequence_data seq;
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ int64 maxv,
+ minv;
+
+ /* open and lock sequence */
init_sequence(relid, &elm, &seqrel);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
@@ -980,6 +1134,14 @@ do_setval(Oid relid, int64 next, bool iscalled)
errmsg("permission denied for sequence %s",
RelationGetRelationName(seqrel))));
+ pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+ maxv = pgsform->seqmax;
+ minv = pgsform->seqmin;
+ ReleaseSysCache(pgstuple);
+
/* read-only transactions may only modify temp sequences */
if (!seqrel->rd_islocaltemp)
PreventCommandIfReadOnly("setval()");
@@ -992,17 +1154,17 @@ do_setval(Oid relid, int64 next, bool iscalled)
PreventCommandIfParallelMode("setval()");
/* lock page' buffer and read tuple */
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
- if ((next < seq->min_value) || (next > seq->max_value))
+ if ((next < minv) || (next > maxv))
{
char bufv[100],
bufm[100],
bufx[100];
snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, seq->min_value);
- snprintf(bufx, sizeof(bufx), INT64_FORMAT, seq->max_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
+ snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
@@ -1028,6 +1190,37 @@ do_setval(Oid relid, int64 next, bool iscalled)
elm->last = next; /* last returned number */
elm->last_valid = true;
}
+ }
+ /* In any case, forget any future cached numbers */
+ elm->cached = elm->last;
+
+ /* check the comment above nextval_internal()'s equivalent call. */
+ if (RelationNeedsWAL(seqrel))
+ GetTopTransactionId();
+
+ /* ready to change the on-disk (or really, in-buffer) tuple */
+ START_CRIT_SECTION();
+
+ seq->last_value = next; /* last fetched number */
+ seq->is_called = iscalled;
+ seq->log_cnt = 0;
+
+ MarkBufferDirty(buf);
+
+ /* XLOG stuff */
+ if (RelationNeedsWAL(seqrel))
+ {
+ xl_seq_rec xlrec;
+ XLogRecPtr recptr;
+
+ XLogBeginInsert();
+ XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
+
+ xlrec.node = seqrel->rd_node;
+ XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
+ XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
+
+ recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
elm->cached = elm->last;
}
@@ -1070,15 +1263,15 @@ setval3_oid(PG_FUNCTION_ARGS)
/*
- * Open the sequence and acquire AccessShareLock if needed
+ * Open the sequence and acquire lock if needed
*
* If we haven't touched the sequence already in this transaction,
- * we need to acquire AccessShareLock. We arrange for the lock to
+ * we need to acquire a lock. We arrange for the lock to
* be owned by the top transaction, so that we don't need to do it
* more than once per xact.
*/
static Relation
-open_share_lock(SeqTable seq)
+lock_and_open_sequence(SeqTable seq)
{
LocalTransactionId thislxid = MyProc->lxid;
@@ -1091,7 +1284,7 @@ open_share_lock(SeqTable seq)
PG_TRY();
{
CurrentResourceOwner = TopTransactionResourceOwner;
- LockRelationOid(seq->relid, AccessShareLock);
+ LockRelationOid(seq->relid, RowExclusiveLock);
}
PG_CATCH();
{
@@ -1106,7 +1299,7 @@ open_share_lock(SeqTable seq)
seq->lxid = thislxid;
}
- /* We now know we have AccessShareLock, and can safely open the rel */
+ /* We now know we have the lock, and can safely open the rel */
return relation_open(seq->relid, NoLock);
}
@@ -1157,17 +1350,17 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
elm->filenode = InvalidOid;
elm->lxid = InvalidLocalTransactionId;
elm->last_valid = false;
- elm->last = elm->cached = elm->increment = 0;
#ifdef XCP
elm->last_call_time = 0;
elm->range_multiplier = DEFAULT_CACHEVAL;
#endif
+ elm->last = elm->cached = 0;
}
/*
* Open the sequence relation.
*/
- seqrel = open_share_lock(elm);
+ seqrel = lock_and_open_sequence(elm);
if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
ereport(ERROR,
@@ -1196,18 +1389,18 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
* Given an opened sequence relation, lock the page buffer and find the tuple
*
* *buf receives the reference to the pinned-and-ex-locked buffer
- * *seqtuple receives the reference to the sequence tuple proper
+ * *seqdatatuple receives the reference to the sequence tuple proper
* (this arg should point to a local variable of type HeapTupleData)
*
* Function's return value points to the data payload of the tuple
*/
-static Form_pg_sequence
-read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
+static Form_pg_sequence_data
+read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
{
Page page;
ItemId lp;
sequence_magic *sm;
- Form_pg_sequence seq;
+ Form_pg_sequence_data seq;
*buf = ReadBuffer(rel, 0);
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
@@ -1222,9 +1415,9 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
lp = PageGetItemId(page, FirstOffsetNumber);
Assert(ItemIdIsNormal(lp));
- /* Note we currently only bother to set these two fields of *seqtuple */
- seqtuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
- seqtuple->t_len = ItemIdGetLength(lp);
+ /* Note we currently only bother to set these two fields of *seqdatatuple */
+ seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
+ seqdatatuple->t_len = ItemIdGetLength(lp);
/*
* Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
@@ -1234,40 +1427,65 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
* bit update, ie, don't bother to WAL-log it, since we can certainly do
* this again if the update gets lost.
*/
- Assert(!(seqtuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
- if (HeapTupleHeaderGetRawXmax(seqtuple->t_data) != InvalidTransactionId)
+ Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
+ if (HeapTupleHeaderGetRawXmax(seqdatatuple->t_data) != InvalidTransactionId)
{
- HeapTupleHeaderSetXmax(seqtuple->t_data, InvalidTransactionId);
- seqtuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
- seqtuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
+ HeapTupleHeaderSetXmax(seqdatatuple->t_data, InvalidTransactionId);
+ seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
+ seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
MarkBufferDirtyHint(*buf, true);
}
- seq = (Form_pg_sequence) GETSTRUCT(seqtuple);
-
- /* this is a handy place to update our copy of the increment */
- elm->increment = seq->increment_by;
+ seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
return seq;
}
/*
- * init_params: process the options list of CREATE or ALTER SEQUENCE,
- * and store the values into appropriate fields of *new. Also set
- * *owned_by to any OWNED BY option, or to NIL if there is none.
+ * Check the sequence options list and return the appropriate lock level for
+ * ALTER SEQUENCE.
+ *
+ * Most sequence option changes require a self-exclusive lock and should block
+ * concurrent nextval() et al. But RESTART does not, because it's not
+ * transactional. Also take a lower lock if no option at all is present.
+ */
+static LOCKMODE
+alter_sequence_get_lock_level(List *options)
+{
+ ListCell *option;
+
+ foreach(option, options)
+ {
+ DefElem *defel = (DefElem *) lfirst(option);
+
+ if (strcmp(defel->defname, "restart") != 0)
+ return ShareRowExclusiveLock;
+ }
+
+ return RowExclusiveLock;
+}
+
+/*
+ * init_params: process the options list of CREATE or ALTER SEQUENCE, and
+ * store the values into appropriate fields of seqform, for changes that go
+ * into the pg_sequence catalog, and seqdataform for changes to the sequence
+ * relation itself. Set *changed_seqform to true if seqform was changed
+ * (interesting for ALTER SEQUENCE). Also set *owned_by to any OWNED BY
+ * option, or to NIL if there is none.
*
* If isInit is true, fill any unspecified options with default values;
* otherwise, do not change existing options that aren't explicitly overridden.
*/
static void
-#ifdef PGXC
-init_params(List *options, bool isInit,
- Form_pg_sequence new, List **owned_by, bool *is_restart)
-#else
-init_params(List *options, bool isInit,
- Form_pg_sequence new, List **owned_by)
-#endif
+init_params(ParseState *pstate, List *options, bool for_identity,
+ bool isInit,
+ Form_pg_sequence seqform,
+ bool *changed_seqform,
+ Form_pg_sequence_data seqdataform,
+ List **owned_by,
+ bool *is_restart)
{
+ DefElem *as_type = NULL;
DefElem *start_value = NULL;
DefElem *restart_value = NULL;
DefElem *increment_by = NULL;
@@ -1276,6 +1494,8 @@ init_params(List *options, bool isInit,
DefElem *cache_value = NULL;
DefElem *is_cycled = NULL;
ListCell *option;
+ bool reset_max_value = false;
+ bool reset_min_value = false;
#ifdef PGXC
*is_restart = false;
@@ -1287,12 +1507,22 @@ init_params(List *options, bool isInit,
{
DefElem *defel = (DefElem *) lfirst(option);
- if (strcmp(defel->defname, "increment") == 0)
+ if (strcmp(defel->defname, "as") == 0)
+ {
+ if (as_type)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ as_type = defel;
+ }
+ else if (strcmp(defel->defname, "increment") == 0)
{
if (increment_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
increment_by = defel;
}
else if (strcmp(defel->defname, "start") == 0)
@@ -1300,7 +1530,8 @@ init_params(List *options, bool isInit,
if (start_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
start_value = defel;
}
else if (strcmp(defel->defname, "restart") == 0)
@@ -1308,7 +1539,8 @@ init_params(List *options, bool isInit,
if (restart_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
restart_value = defel;
}
else if (strcmp(defel->defname, "maxvalue") == 0)
@@ -1316,7 +1548,8 @@ init_params(List *options, bool isInit,
if (max_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
max_value = defel;
}
else if (strcmp(defel->defname, "minvalue") == 0)
@@ -1324,7 +1557,8 @@ init_params(List *options, bool isInit,
if (min_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
min_value = defel;
}
else if (strcmp(defel->defname, "cache") == 0)
@@ -1332,7 +1566,8 @@ init_params(List *options, bool isInit,
if (cache_value)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
cache_value = defel;
}
else if (strcmp(defel->defname, "cycle") == 0)
@@ -1340,7 +1575,8 @@ init_params(List *options, bool isInit,
if (is_cycled)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
is_cycled = defel;
}
else if (strcmp(defel->defname, "owned_by") == 0)
@@ -1348,82 +1584,194 @@ init_params(List *options, bool isInit,
if (*owned_by)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
*owned_by = defGetQualifiedName(defel);
}
+ else if (strcmp(defel->defname, "sequence_name") == 0)
+ {
+ /*
+ * The parser allows this, but it is only for identity columns, in
+ * which case it is filtered out in parse_utilcmd.c. We only get
+ * here if someone puts it into a CREATE SEQUENCE.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid sequence option SEQUENCE NAME"),
+ parser_errposition(pstate, defel->location)));
+ }
else
elog(ERROR, "option \"%s\" not recognized",
defel->defname);
}
+ *changed_seqform = false;
+
/*
* We must reset log_cnt when isInit or when changing any parameters that
* would affect future nextval allocations.
*/
if (isInit)
- new->log_cnt = 0;
+ seqdataform->log_cnt = 0;
+
+ /* AS type */
+ if (as_type != NULL)
+ {
+ Oid newtypid = typenameTypeId(pstate, defGetTypeName(as_type));
+
+ if (newtypid != INT2OID &&
+ newtypid != INT4OID &&
+ newtypid != INT8OID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ for_identity
+ ? errmsg("identity column type must be smallint, integer, or bigint")
+ : errmsg("sequence type must be smallint, integer, or bigint")));
+
+ if (!isInit)
+ {
+ /*
+ * When changing type and the old sequence min/max values were the
+ * min/max of the old type, adjust sequence min/max values to
+ * min/max of new type. (Otherwise, the user chose explicit
+ * min/max values, which we'll leave alone.)
+ */
+ if ((seqform->seqtypid == INT2OID && seqform->seqmax == PG_INT16_MAX) ||
+ (seqform->seqtypid == INT4OID && seqform->seqmax == PG_INT32_MAX) ||
+ (seqform->seqtypid == INT8OID && seqform->seqmax == PG_INT64_MAX))
+ reset_max_value = true;
+ if ((seqform->seqtypid == INT2OID && seqform->seqmin == PG_INT16_MIN) ||
+ (seqform->seqtypid == INT4OID && seqform->seqmin == PG_INT32_MIN) ||
+ (seqform->seqtypid == INT8OID && seqform->seqmin == PG_INT64_MIN))
+ reset_min_value = true;
+ }
+
+ seqform->seqtypid = newtypid;
+ *changed_seqform = true;
+ }
+ else if (isInit)
+ {
+ seqform->seqtypid = INT8OID;
+ *changed_seqform = true;
+ }
/* INCREMENT BY */
if (increment_by != NULL)
{
- new->increment_by = defGetInt64(increment_by);
- if (new->increment_by == 0)
+ seqform->seqincrement = defGetInt64(increment_by);
+ *changed_seqform = true;
+ if (seqform->seqincrement == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("INCREMENT must not be zero")));
- new->log_cnt = 0;
+ seqdataform->log_cnt = 0;
}
else if (isInit)
- new->increment_by = 1;
+ {
+ seqform->seqincrement = 1;
+ *changed_seqform = true;
+ }
/* CYCLE */
if (is_cycled != NULL)
{
- new->is_cycled = intVal(is_cycled->arg);
- Assert(BoolIsValid(new->is_cycled));
- new->log_cnt = 0;
+ seqform->seqcycle = intVal(is_cycled->arg);
+ *changed_seqform = true;
+ Assert(BoolIsValid(seqform->seqcycle));
+ seqdataform->log_cnt = 0;
}
else if (isInit)
- new->is_cycled = false;
+ {
+ seqform->seqcycle = false;
+ *changed_seqform = true;
+ }
/* MAXVALUE (null arg means NO MAXVALUE) */
if (max_value != NULL && max_value->arg)
{
- new->max_value = defGetInt64(max_value);
- new->log_cnt = 0;
+ seqform->seqmax = defGetInt64(max_value);
+ *changed_seqform = true;
+ seqdataform->log_cnt = 0;
}
- else if (isInit || max_value != NULL)
+ else if (isInit || max_value != NULL || reset_max_value)
{
- if (new->increment_by > 0)
- new->max_value = SEQ_MAXVALUE; /* ascending seq */
+ if (seqform->seqincrement > 0 || reset_max_value)
+ {
+ /* ascending seq */
+ if (seqform->seqtypid == INT2OID)
+ seqform->seqmax = PG_INT16_MAX;
+ else if (seqform->seqtypid == INT4OID)
+ seqform->seqmax = PG_INT32_MAX;
+ else
+ seqform->seqmax = PG_INT64_MAX;
+ }
else
- new->max_value = -1; /* descending seq */
- new->log_cnt = 0;
+ seqform->seqmax = -1; /* descending seq */
+ *changed_seqform = true;
+ seqdataform->log_cnt = 0;
+ }
+
+ if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX))
+ || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX))
+ || (seqform->seqtypid == INT8OID && (seqform->seqmax < PG_INT64_MIN || seqform->seqmax > PG_INT64_MAX)))
+ {
+ char bufx[100];
+
+ snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("MAXVALUE (%s) is out of range for sequence data type %s",
+ bufx, format_type_be(seqform->seqtypid))));
}
/* MINVALUE (null arg means NO MINVALUE) */
if (min_value != NULL && min_value->arg)
{
- new->min_value = defGetInt64(min_value);
- new->log_cnt = 0;
+ seqform->seqmin = defGetInt64(min_value);
+ *changed_seqform = true;
+ seqdataform->log_cnt = 0;
}
- else if (isInit || min_value != NULL)
+ else if (isInit || min_value != NULL || reset_min_value)
{
- if (new->increment_by > 0)
- new->min_value = 1; /* ascending seq */
+ if (seqform->seqincrement < 0 || reset_min_value)
+ {
+ /* descending seq */
+ if (seqform->seqtypid == INT2OID)
+ seqform->seqmin = PG_INT16_MIN;
+ else if (seqform->seqtypid == INT4OID)
+ seqform->seqmin = PG_INT32_MIN;
+ else
+ seqform->seqmin = PG_INT64_MIN;
+ }
else
- new->min_value = SEQ_MINVALUE; /* descending seq */
- new->log_cnt = 0;
+ seqform->seqmin = 1; /* ascending seq */
+ *changed_seqform = true;
+ seqdataform->log_cnt = 0;
+ }
+
+ if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX))
+ || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX))
+ || (seqform->seqtypid == INT8OID && (seqform->seqmin < PG_INT64_MIN || seqform->seqmin > PG_INT64_MAX)))
+ {
+ char bufm[100];
+
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("MINVALUE (%s) is out of range for sequence data type %s",
+ bufm, format_type_be(seqform->seqtypid))));
}
/* crosscheck min/max */
- if (new->min_value >= new->max_value)
+ if (seqform->seqmin >= seqform->seqmax)
{
char bufm[100],
bufx[100];
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
- snprintf(bufx, sizeof(bufx), INT64_FORMAT, new->max_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
+ snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",
@@ -1432,35 +1780,39 @@ init_params(List *options, bool isInit,
/* START WITH */
if (start_value != NULL)
- new->start_value = defGetInt64(start_value);
+ {
+ seqform->seqstart = defGetInt64(start_value);
+ *changed_seqform = true;
+ }
else if (isInit)
{
- if (new->increment_by > 0)
- new->start_value = new->min_value; /* ascending seq */
+ if (seqform->seqincrement > 0)
+ seqform->seqstart = seqform->seqmin; /* ascending seq */
else
- new->start_value = new->max_value; /* descending seq */
+ seqform->seqstart = seqform->seqmax; /* descending seq */
+ *changed_seqform = true;
}
/* crosscheck START */
- if (new->start_value < new->min_value)
+ if (seqform->seqstart < seqform->seqmin)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->start_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("START value (%s) cannot be less than MINVALUE (%s)",
bufs, bufm)));
}
- if (new->start_value > new->max_value)
+ if (seqform->seqstart > seqform->seqmax)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->start_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("START value (%s) cannot be greater than MAXVALUE (%s)",
@@ -1471,41 +1823,42 @@ init_params(List *options, bool isInit,
if (restart_value != NULL)
{
if (restart_value->arg != NULL)
- new->last_value = defGetInt64(restart_value);
+ seqdataform->last_value = defGetInt64(restart_value);
else
- new->last_value = new->start_value;
+ seqdataform->last_value = seqform->seqstart;
#ifdef PGXC
*is_restart = true;
#endif
- new->is_called = false;
- new->log_cnt = 0;
+ seqdataform->last_value = seqform->seqstart;
+ seqdataform->is_called = false;
+ seqdataform->log_cnt = 0;
}
else if (isInit)
{
- new->last_value = new->start_value;
- new->is_called = false;
+ seqdataform->last_value = seqform->seqstart;
+ seqdataform->is_called = false;
}
/* crosscheck RESTART (or current value, if changing MIN/MAX) */
- if (new->last_value < new->min_value)
+ if (seqdataform->last_value < seqform->seqmin)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)",
bufs, bufm)));
}
- if (new->last_value > new->max_value)
+ if (seqdataform->last_value > seqform->seqmax)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)",
@@ -1515,21 +1868,25 @@ init_params(List *options, bool isInit,
/* CACHE */
if (cache_value != NULL)
{
- new->cache_value = defGetInt64(cache_value);
- if (new->cache_value <= 0)
+ seqform->seqcache = defGetInt64(cache_value);
+ *changed_seqform = true;
+ if (seqform->seqcache <= 0)
{
char buf[100];
- snprintf(buf, sizeof(buf), INT64_FORMAT, new->cache_value);
+ snprintf(buf, sizeof(buf), INT64_FORMAT, seqform->seqcache);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("CACHE (%s) must be greater than zero",
buf)));
}
- new->log_cnt = 0;
+ seqdataform->log_cnt = 0;
}
else if (isInit)
- new->cache_value = 1;
+ {
+ seqform->seqcache = 1;
+ *changed_seqform = true;
+ }
}
#ifdef PGXC
@@ -1629,12 +1986,15 @@ IsTempSequence(Oid relid)
* as the sequence.
*/
static void
-process_owned_by(Relation seqrel, List *owned_by)
+process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
{
+ DependencyType deptype;
int nnames;
Relation tablerel;
AttrNumber attnum;
+ deptype = for_identity ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO;
+
nnames = list_length(owned_by);
Assert(nnames > 0);
if (nnames == 1)
@@ -1664,7 +2024,9 @@ process_owned_by(Relation seqrel, List *owned_by)
/* Must be a regular or foreign table */
if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
- tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE))
+ tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
+ tablerel->rd_rel->relkind == RELKIND_VIEW ||
+ tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("referenced relation \"%s\" is not a table or foreign table",
@@ -1690,10 +2052,28 @@ process_owned_by(Relation seqrel, List *owned_by)
}
/*
- * OK, we are ready to update pg_depend. First remove any existing AUTO
+ * Catch user explicitly running OWNED BY on identity sequence.
+ */
+ if (deptype == DEPENDENCY_AUTO)
+ {
+ Oid tableId;
+ int32 colId;
+
+ if (sequenceIsOwned(RelationGetRelid(seqrel), DEPENDENCY_INTERNAL, &tableId, &colId))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot change ownership of identity sequence"),
+ errdetail("Sequence \"%s\" is linked to table \"%s\".",
+ RelationGetRelationName(seqrel),
+ get_rel_name(tableId))));
+ }
+
+ /*
+ * OK, we are ready to update pg_depend. First remove any existing
* dependencies for the sequence, then optionally add a new one.
*/
- markSequenceUnowned(RelationGetRelid(seqrel));
+ deleteDependencyRecordsForClass(RelationRelationId, RelationGetRelid(seqrel),
+ RelationRelationId, deptype);
if (tablerel)
{
@@ -1706,7 +2086,7 @@ process_owned_by(Relation seqrel, List *owned_by)
depobject.classId = RelationRelationId;
depobject.objectId = RelationGetRelid(seqrel);
depobject.objectSubId = 0;
- recordDependencyOn(&depobject, &refobject, DEPENDENCY_AUTO);
+ recordDependencyOn(&depobject, &refobject, deptype);
}
/* Done, but hold lock until commit */
@@ -1716,31 +2096,52 @@ process_owned_by(Relation seqrel, List *owned_by)
/*
- * Return sequence parameters, for use by information schema
+ * Return sequence parameters in a list of the form created by the parser.
+ */
+List *
+sequence_options(Oid relid)
+{
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ List *options = NIL;
+
+ pgstuple = SearchSysCache1(SEQRELID, relid);
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+
+ options = lappend(options, makeDefElem("cache", (Node *) makeInteger(pgsform->seqcache), -1));
+ options = lappend(options, makeDefElem("cycle", (Node *) makeInteger(pgsform->seqcycle), -1));
+ options = lappend(options, makeDefElem("increment", (Node *) makeInteger(pgsform->seqincrement), -1));
+ options = lappend(options, makeDefElem("maxvalue", (Node *) makeInteger(pgsform->seqmax), -1));
+ options = lappend(options, makeDefElem("minvalue", (Node *) makeInteger(pgsform->seqmin), -1));
+ options = lappend(options, makeDefElem("start", (Node *) makeInteger(pgsform->seqstart), -1));
+
+ ReleaseSysCache(pgstuple);
+
+ return options;
+}
+
+/*
+ * Return sequence parameters (formerly for use by information schema)
*/
Datum
pg_sequence_parameters(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);
TupleDesc tupdesc;
- Datum values[5];
- bool isnull[5];
- SeqTable elm;
- Relation seqrel;
- Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
-
- /* open and AccessShareLock sequence */
- init_sequence(relid, &elm, &seqrel);
+ Datum values[7];
+ bool isnull[7];
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_UPDATE | ACL_USAGE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
- RelationGetRelationName(seqrel))));
+ get_rel_name(relid))));
- tupdesc = CreateTemplateTupleDesc(5, false);
+ tupdesc = CreateTemplateTupleDesc(7, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
INT8OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
@@ -1751,23 +2152,71 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
INT8OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 6, "cache_size",
+ INT8OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 7, "data_type",
+ OIDOID, -1, 0);
BlessTupleDesc(tupdesc);
memset(isnull, 0, sizeof(isnull));
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ pgstuple = SearchSysCache1(SEQRELID, relid);
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+
+ values[0] = Int64GetDatum(pgsform->seqstart);
+ values[1] = Int64GetDatum(pgsform->seqmin);
+ values[2] = Int64GetDatum(pgsform->seqmax);
+ values[3] = Int64GetDatum(pgsform->seqincrement);
+ values[4] = BoolGetDatum(pgsform->seqcycle);
+ values[5] = Int64GetDatum(pgsform->seqcache);
+ values[6] = ObjectIdGetDatum(pgsform->seqtypid);
- values[0] = Int64GetDatum(seq->start_value);
- values[1] = Int64GetDatum(seq->min_value);
- values[2] = Int64GetDatum(seq->max_value);
- values[3] = Int64GetDatum(seq->increment_by);
- values[4] = BoolGetDatum(seq->is_cycled);
+ ReleaseSysCache(pgstuple);
+
+ return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
+}
+
+/*
+ * Return the last value from the sequence
+ *
+ * Note: This has a completely different meaning than lastval().
+ */
+Datum
+pg_sequence_last_value(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ SeqTable elm;
+ Relation seqrel;
+ Buffer buf;
+ HeapTupleData seqtuple;
+ Form_pg_sequence_data seq;
+ bool is_called;
+ int64 result;
+
+ /* open and lock sequence */
+ init_sequence(relid, &elm, &seqrel);
+
+ if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_USAGE) != ACLCHECK_OK)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied for sequence %s",
+ RelationGetRelationName(seqrel))));
+
+ seq = read_seq_tuple(seqrel, &buf, &seqtuple);
+
+ is_called = seq->is_called;
+ result = seq->last_value;
UnlockReleaseBuffer(buf);
relation_close(seqrel, NoLock);
- return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
+ if (is_called)
+ PG_RETURN_INT64(result);
+ else
+ PG_RETURN_NULL();
}
@@ -1835,3 +2284,14 @@ ResetSequenceCaches(void)
last_used_seq = NULL;
}
+
+/*
+ * Mask a Sequence page before performing consistency checks on it.
+ */
+void
+seq_mask(char *page, BlockNumber blkno)
+{
+ mask_page_lsn(page);
+
+ mask_unused_space(page);
+}
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
new file mode 100644
index 0000000000..2b3785f394
--- /dev/null
+++ b/src/backend/commands/statscmds.c
@@ -0,0 +1,408 @@
+/*-------------------------------------------------------------------------
+ *
+ * statscmds.c
+ * Commands for creating and altering extended statistics objects
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/commands/statscmds.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/relscan.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_statistic_ext.h"
+#include "commands/defrem.h"
+#include "miscadmin.h"
+#include "statistics/statistics.h"
+#include "utils/builtins.h"
+#include "utils/inval.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+#include "utils/typcache.h"
+
+
+/* qsort comparator for the attnums in CreateStatistics */
+static int
+compare_int16(const void *a, const void *b)
+{
+ int av = *(const int16 *) a;
+ int bv = *(const int16 *) b;
+
+ /* this can't overflow if int is wider than int16 */
+ return (av - bv);
+}
+
+/*
+ * CREATE STATISTICS
+ */
+ObjectAddress
+CreateStatistics(CreateStatsStmt *stmt)
+{
+ int16 attnums[STATS_MAX_DIMENSIONS];
+ int numcols = 0;
+ char *namestr;
+ NameData stxname;
+ Oid statoid;
+ Oid namespaceId;
+ Oid stxowner = GetUserId();
+ HeapTuple htup;
+ Datum values[Natts_pg_statistic_ext];
+ bool nulls[Natts_pg_statistic_ext];
+ int2vector *stxkeys;
+ Relation statrel;
+ Relation rel = NULL;
+ Oid relid;
+ ObjectAddress parentobject,
+ myself;
+ Datum types[2]; /* one for each possible type of statistic */
+ int ntypes;
+ ArrayType *stxkind;
+ bool build_ndistinct;
+ bool build_dependencies;
+ bool requested_type = false;
+ int i;
+ ListCell *cell;
+
+ Assert(IsA(stmt, CreateStatsStmt));
+
+ /* resolve the pieces of the name (namespace etc.) */
+ namespaceId = QualifiedNameGetCreationNamespace(stmt->defnames, &namestr);
+ namestrcpy(&stxname, namestr);
+
+ /*
+ * Deal with the possibility that the statistics object already exists.
+ */
+ if (SearchSysCacheExists2(STATEXTNAMENSP,
+ NameGetDatum(&stxname),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ if (stmt->if_not_exists)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("statistics object \"%s\" already exists, skipping",
+ namestr)));
+ return InvalidObjectAddress;
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("statistics object \"%s\" already exists", namestr)));
+ }
+
+ /*
+ * Examine the FROM clause. Currently, we only allow it to be a single
+ * simple table, but later we'll probably allow multiple tables and JOIN
+ * syntax. The grammar is already prepared for that, so we have to check
+ * here that what we got is what we can support.
+ */
+ if (list_length(stmt->relations) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("only a single relation is allowed in CREATE STATISTICS")));
+
+ foreach(cell, stmt->relations)
+ {
+ Node *rln = (Node *) lfirst(cell);
+
+ if (!IsA(rln, RangeVar))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("only a single relation is allowed in CREATE STATISTICS")));
+
+ /*
+ * CREATE STATISTICS will influence future execution plans but does
+ * not interfere with currently executing plans. So it should be
+ * enough to take only ShareUpdateExclusiveLock on relation,
+ * conflicting with ANALYZE and other DDL that sets statistical
+ * information, but not with normal queries.
+ */
+ rel = relation_openrv((RangeVar *) rln, ShareUpdateExclusiveLock);
+
+ /* Restrict to allowed relation types */
+ if (rel->rd_rel->relkind != RELKIND_RELATION &&
+ rel->rd_rel->relkind != RELKIND_MATVIEW &&
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("relation \"%s\" is not a table, foreign table, or materialized view",
+ RelationGetRelationName(rel))));
+
+ /* You must own the relation to create stats on it */
+ if (!pg_class_ownercheck(RelationGetRelid(rel), stxowner))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+ RelationGetRelationName(rel));
+ }
+
+ Assert(rel);
+ relid = RelationGetRelid(rel);
+
+ /*
+ * Currently, we only allow simple column references in the expression
+ * list. That will change someday, and again the grammar already supports
+ * it so we have to enforce restrictions here. For now, we can convert
+ * the expression list to a simple array of attnums. While at it, enforce
+ * some constraints.
+ */
+ foreach(cell, stmt->exprs)
+ {
+ Node *expr = (Node *) lfirst(cell);
+ ColumnRef *cref;
+ char *attname;
+ HeapTuple atttuple;
+ Form_pg_attribute attForm;
+ TypeCacheEntry *type;
+
+ if (!IsA(expr, ColumnRef))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("only simple column references are allowed in CREATE STATISTICS")));
+ cref = (ColumnRef *) expr;
+
+ if (list_length(cref->fields) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("only simple column references are allowed in CREATE STATISTICS")));
+ attname = strVal((Value *) linitial(cref->fields));
+
+ atttuple = SearchSysCacheAttName(relid, attname);
+ if (!HeapTupleIsValid(atttuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" referenced in statistics does not exist",
+ attname)));
+ attForm = (Form_pg_attribute) GETSTRUCT(atttuple);
+
+ /* Disallow use of system attributes in extended stats */
+ if (attForm->attnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("statistics creation on system columns is not supported")));
+
+ /* Disallow data types without a less-than operator */
+ type = lookup_type_cache(attForm->atttypid, TYPECACHE_LT_OPR);
+ if (type->lt_opr == InvalidOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("column \"%s\" cannot be used in statistics because its type has no default btree operator class",
+ attname)));
+
+ /* Make sure no more than STATS_MAX_DIMENSIONS columns are used */
+ if (numcols >= STATS_MAX_DIMENSIONS)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_COLUMNS),
+ errmsg("cannot have more than %d columns in statistics",
+ STATS_MAX_DIMENSIONS)));
+
+ attnums[numcols] = attForm->attnum;
+ numcols++;
+ ReleaseSysCache(atttuple);
+ }
+
+ /*
+ * Check that at least two columns were specified in the statement. The
+ * upper bound was already checked in the loop above.
+ */
+ if (numcols < 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("extended statistics require at least 2 columns")));
+
+ /*
+ * Sort the attnums, which makes detecting duplicates somewhat easier, and
+ * it does not hurt (it does not affect the efficiency, unlike for
+ * indexes, for example).
+ */
+ qsort(attnums, numcols, sizeof(int16), compare_int16);
+
+ /*
+ * Check for duplicates in the list of columns. The attnums are sorted so
+ * just check consecutive elements.
+ */
+ for (i = 1; i < numcols; i++)
+ {
+ if (attnums[i] == attnums[i - 1])
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_COLUMN),
+ errmsg("duplicate column name in statistics definition")));
+ }
+
+ /* Form an int2vector representation of the sorted column list */
+ stxkeys = buildint2vector(attnums, numcols);
+
+ /*
+ * Parse the statistics types.
+ */
+ build_ndistinct = false;
+ build_dependencies = false;
+ foreach(cell, stmt->stat_types)
+ {
+ char *type = strVal((Value *) lfirst(cell));
+
+ if (strcmp(type, "ndistinct") == 0)
+ {
+ build_ndistinct = true;
+ requested_type = true;
+ }
+ else if (strcmp(type, "dependencies") == 0)
+ {
+ build_dependencies = true;
+ requested_type = true;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized statistic type \"%s\"",
+ type)));
+ }
+ /* If no statistic type was specified, build them all. */
+ if (!requested_type)
+ {
+ build_ndistinct = true;
+ build_dependencies = true;
+ }
+
+ /* construct the char array of enabled statistic types */
+ ntypes = 0;
+ if (build_ndistinct)
+ types[ntypes++] = CharGetDatum(STATS_EXT_NDISTINCT);
+ if (build_dependencies)
+ types[ntypes++] = CharGetDatum(STATS_EXT_DEPENDENCIES);
+ Assert(ntypes > 0 && ntypes <= lengthof(types));
+ stxkind = construct_array(types, ntypes, CHAROID, 1, true, 'c');
+
+ /*
+ * Everything seems fine, so let's build the pg_statistic_ext tuple.
+ */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid);
+ values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname);
+ values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId);
+ values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner);
+ values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys);
+ values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind);
+
+ /* no statistics built yet */
+ nulls[Anum_pg_statistic_ext_stxndistinct - 1] = true;
+ nulls[Anum_pg_statistic_ext_stxdependencies - 1] = true;
+
+ /* insert it into pg_statistic_ext */
+ statrel = heap_open(StatisticExtRelationId, RowExclusiveLock);
+ htup = heap_form_tuple(statrel->rd_att, values, nulls);
+ CatalogTupleInsert(statrel, htup);
+ statoid = HeapTupleGetOid(htup);
+ heap_freetuple(htup);
+ relation_close(statrel, RowExclusiveLock);
+
+ /*
+ * Invalidate relcache so that others see the new statistics object.
+ */
+ CacheInvalidateRelcache(rel);
+
+ relation_close(rel, NoLock);
+
+ /*
+ * Add an AUTO dependency on each column used in the stats, so that the
+ * stats object goes away if any or all of them get dropped.
+ */
+ ObjectAddressSet(myself, StatisticExtRelationId, statoid);
+
+ for (i = 0; i < numcols; i++)
+ {
+ ObjectAddressSubSet(parentobject, RelationRelationId, relid, attnums[i]);
+ recordDependencyOn(&myself, &parentobject, DEPENDENCY_AUTO);
+ }
+
+ /*
+ * Also add dependencies on namespace and owner. These are required
+ * because the stats object might have a different namespace and/or owner
+ * than the underlying table(s).
+ */
+ ObjectAddressSet(parentobject, NamespaceRelationId, namespaceId);
+ recordDependencyOn(&myself, &parentobject, DEPENDENCY_NORMAL);
+
+ recordDependencyOnOwner(StatisticExtRelationId, statoid, stxowner);
+
+ /*
+ * XXX probably there should be a recordDependencyOnCurrentExtension call
+ * here too, but we'd have to add support for ALTER EXTENSION ADD/DROP
+ * STATISTICS, which is more work than it seems worth.
+ */
+
+ /* Return stats object's address */
+ return myself;
+}
+
+/*
+ * Guts of statistics object deletion.
+ */
+void
+RemoveStatisticsById(Oid statsOid)
+{
+ Relation relation;
+ HeapTuple tup;
+ Form_pg_statistic_ext statext;
+ Oid relid;
+
+ /*
+ * Delete the pg_statistic_ext tuple. Also send out a cache inval on the
+ * associated table, so that dependent plans will be rebuilt.
+ */
+ relation = heap_open(StatisticExtRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid));
+
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for statistics object %u", statsOid);
+
+ statext = (Form_pg_statistic_ext) GETSTRUCT(tup);
+ relid = statext->stxrelid;
+
+ CacheInvalidateRelcacheByRelid(relid);
+
+ simple_heap_delete(relation, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ heap_close(relation, RowExclusiveLock);
+}
+
+/*
+ * Update a statistics object for ALTER COLUMN TYPE on a source column.
+ *
+ * This could throw an error if the type change can't be supported.
+ * If it can be supported, but the stats must be recomputed, a likely choice
+ * would be to set the relevant column(s) of the pg_statistic_ext tuple to
+ * null until the next ANALYZE. (Note that the type change hasn't actually
+ * happened yet, so one option that's *not* on the table is to recompute
+ * immediately.)
+ */
+void
+UpdateStatisticsForTypeChange(Oid statsOid, Oid relationOid, int attnum,
+ Oid oldColumnType, Oid newColumnType)
+{
+ /*
+ * Currently, we don't actually need to do anything here. For both
+ * ndistinct and functional-dependencies stats, the on-disk representation
+ * is independent of the source column data types, and it is plausible to
+ * assume that the old statistic values will still be good for the new
+ * column contents. (Obviously, if the ALTER COLUMN TYPE has a USING
+ * expression that substantially alters the semantic meaning of the column
+ * values, this assumption could fail. But that seems like a corner case
+ * that doesn't justify zapping the stats in common cases.)
+ *
+ * Future types of extended stats will likely require us to work harder.
+ */
+}
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
new file mode 100644
index 0000000000..86eb31df93
--- /dev/null
+++ b/src/backend/commands/subscriptioncmds.c
@@ -0,0 +1,1133 @@
+/*-------------------------------------------------------------------------
+ *
+ * subscriptioncmds.c
+ * subscription catalog manipulation functions
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * subscriptioncmds.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "miscadmin.h"
+
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/xact.h"
+
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_subscription.h"
+#include "catalog/pg_subscription_rel.h"
+
+#include "commands/defrem.h"
+#include "commands/event_trigger.h"
+#include "commands/subscriptioncmds.h"
+
+#include "executor/executor.h"
+
+#include "nodes/makefuncs.h"
+
+#include "replication/logicallauncher.h"
+#include "replication/origin.h"
+#include "replication/walreceiver.h"
+#include "replication/walsender.h"
+#include "replication/worker_internal.h"
+
+#include "storage/lmgr.h"
+
+#include "utils/builtins.h"
+#include "utils/guc.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
+
+static List *fetch_table_list(WalReceiverConn *wrconn, List *publications);
+
+/*
+ * Common option parsing function for CREATE and ALTER SUBSCRIPTION commands.
+ *
+ * Since not all options can be specified in both commands, this function
+ * will report an error on options if the target output pointer is NULL to
+ * accommodate that.
+ */
+static void
+parse_subscription_options(List *options, bool *connect, bool *enabled_given,
+ bool *enabled, bool *create_slot,
+ bool *slot_name_given, char **slot_name,
+ bool *copy_data, char **synchronous_commit)
+{
+ ListCell *lc;
+ bool connect_given = false;
+ bool create_slot_given = false;
+ bool copy_data_given = false;
+
+ /* If connect is specified, the others also need to be. */
+ Assert(!connect || (enabled && create_slot && copy_data));
+
+ if (connect)
+ *connect = true;
+ if (enabled)
+ {
+ *enabled_given = false;
+ *enabled = true;
+ }
+ if (create_slot)
+ *create_slot = true;
+ if (slot_name)
+ {
+ *slot_name_given = false;
+ *slot_name = NULL;
+ }
+ if (copy_data)
+ *copy_data = true;
+ if (synchronous_commit)
+ *synchronous_commit = NULL;
+
+ /* Parse options */
+ foreach(lc, options)
+ {
+ DefElem *defel = (DefElem *) lfirst(lc);
+
+ if (strcmp(defel->defname, "connect") == 0 && connect)
+ {
+ if (connect_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ connect_given = true;
+ *connect = defGetBoolean(defel);
+ }
+ else if (strcmp(defel->defname, "enabled") == 0 && enabled)
+ {
+ if (*enabled_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ *enabled_given = true;
+ *enabled = defGetBoolean(defel);
+ }
+ else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
+ {
+ if (create_slot_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ create_slot_given = true;
+ *create_slot = defGetBoolean(defel);
+ }
+ else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
+ {
+ if (*slot_name_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ *slot_name_given = true;
+ *slot_name = defGetString(defel);
+
+ /* Setting slot_name = NONE is treated as no slot name. */
+ if (strcmp(*slot_name, "none") == 0)
+ *slot_name = NULL;
+ }
+ else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
+ {
+ if (copy_data_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ copy_data_given = true;
+ *copy_data = defGetBoolean(defel);
+ }
+ else if (strcmp(defel->defname, "synchronous_commit") == 0 &&
+ synchronous_commit)
+ {
+ if (*synchronous_commit)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
+ *synchronous_commit = defGetString(defel);
+
+ /* Test if the given value is valid for synchronous_commit GUC. */
+ (void) set_config_option("synchronous_commit", *synchronous_commit,
+ PGC_BACKEND, PGC_S_TEST, GUC_ACTION_SET,
+ false, 0, false);
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized subscription parameter: %s", defel->defname)));
+ }
+
+ /*
+ * We've been explicitly asked to not connect, that requires some
+ * additional processing.
+ */
+ if (connect && !*connect)
+ {
+ /* Check for incompatible options from the user. */
+ if (enabled && *enabled_given && *enabled)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("connect = false and enabled = true are mutually exclusive options")));
+
+ if (create_slot && create_slot_given && *create_slot)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("connect = false and create_slot = true are mutually exclusive options")));
+
+ if (copy_data && copy_data_given && *copy_data)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("connect = false and copy_data = true are mutually exclusive options")));
+
+ /* Change the defaults of other options. */
+ *enabled = false;
+ *create_slot = false;
+ *copy_data = false;
+ }
+
+ /*
+ * Do additional checking for disallowed combination when slot_name = NONE
+ * was used.
+ */
+ if (slot_name && *slot_name_given && !*slot_name)
+ {
+ if (enabled && *enabled_given && *enabled)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("slot_name = NONE and enabled = true are mutually exclusive options")));
+
+ if (create_slot && create_slot_given && *create_slot)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("slot_name = NONE and create_slot = true are mutually exclusive options")));
+
+ if (enabled && !*enabled_given && *enabled)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("subscription with slot_name = NONE must also set enabled = false")));
+
+ if (create_slot && !create_slot_given && *create_slot)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("subscription with slot_name = NONE must also set create_slot = false")));
+ }
+}
+
+/*
+ * Auxiliary function to return a text array out of a list of String nodes.
+ */
+static Datum
+publicationListToArray(List *publist)
+{
+ ArrayType *arr;
+ Datum *datums;
+ int j = 0;
+ ListCell *cell;
+ MemoryContext memcxt;
+ MemoryContext oldcxt;
+
+ /* Create memory context for temporary allocations. */
+ memcxt = AllocSetContextCreate(CurrentMemoryContext,
+ "publicationListToArray to array",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+ oldcxt = MemoryContextSwitchTo(memcxt);
+
+ datums = palloc(sizeof(text *) * list_length(publist));
+ foreach(cell, publist)
+ {
+ char *name = strVal(lfirst(cell));
+ ListCell *pcell;
+
+ /* Check for duplicates. */
+ foreach(pcell, publist)
+ {
+ char *pname = strVal(lfirst(pcell));
+
+ if (name == pname)
+ break;
+
+ if (strcmp(name, pname) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("publication name \"%s\" used more than once",
+ pname)));
+ }
+
+ datums[j++] = CStringGetTextDatum(name);
+ }
+
+ MemoryContextSwitchTo(oldcxt);
+
+ arr = construct_array(datums, list_length(publist),
+ TEXTOID, -1, false, 'i');
+ MemoryContextDelete(memcxt);
+
+ return PointerGetDatum(arr);
+}
+
+/*
+ * Create new subscription.
+ */
+ObjectAddress
+CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
+{
+ Relation rel;
+ ObjectAddress myself;
+ Oid subid;
+ bool nulls[Natts_pg_subscription];
+ Datum values[Natts_pg_subscription];
+ Oid owner = GetUserId();
+ HeapTuple tup;
+ bool connect;
+ bool enabled_given;
+ bool enabled;
+ bool copy_data;
+ char *synchronous_commit;
+ char *conninfo;
+ char *slotname;
+ bool slotname_given;
+ char originname[NAMEDATALEN];
+ bool create_slot;
+ List *publications;
+
+ /*
+ * Parse and check options.
+ *
+ * Connection and publication should not be specified here.
+ */
+ parse_subscription_options(stmt->options, &connect, &enabled_given,
+ &enabled, &create_slot, &slotname_given,
+ &slotname, &copy_data, &synchronous_commit);
+
+ /*
+ * Since creating a replication slot is not transactional, rolling back
+ * the transaction leaves the created replication slot. So we cannot run
+ * CREATE SUBSCRIPTION inside a transaction block if creating a
+ * replication slot.
+ */
+ if (create_slot)
+ PreventTransactionChain(isTopLevel, "CREATE SUBSCRIPTION ... WITH (create_slot = true)");
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to create subscriptions"))));
+
+ rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
+
+ /* Check if name is used */
+ subid = GetSysCacheOid2(SUBSCRIPTIONNAME, MyDatabaseId,
+ CStringGetDatum(stmt->subname));
+ if (OidIsValid(subid))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("subscription \"%s\" already exists",
+ stmt->subname)));
+ }
+
+ if (!slotname_given && slotname == NULL)
+ slotname = stmt->subname;
+
+ /* The default for synchronous_commit of subscriptions is off. */
+ if (synchronous_commit == NULL)
+ synchronous_commit = "off";
+
+ conninfo = stmt->conninfo;
+ publications = stmt->publication;
+
+ /* Load the library providing us libpq calls. */
+ load_file("libpqwalreceiver", false);
+
+ /* Check the connection info string. */
+ walrcv_check_conninfo(conninfo);
+
+ /* Everything ok, form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_subscription_subdbid - 1] = ObjectIdGetDatum(MyDatabaseId);
+ values[Anum_pg_subscription_subname - 1] =
+ DirectFunctionCall1(namein, CStringGetDatum(stmt->subname));
+ values[Anum_pg_subscription_subowner - 1] = ObjectIdGetDatum(owner);
+ values[Anum_pg_subscription_subenabled - 1] = BoolGetDatum(enabled);
+ values[Anum_pg_subscription_subconninfo - 1] =
+ CStringGetTextDatum(conninfo);
+ if (slotname)
+ values[Anum_pg_subscription_subslotname - 1] =
+ DirectFunctionCall1(namein, CStringGetDatum(slotname));
+ else
+ nulls[Anum_pg_subscription_subslotname - 1] = true;
+ values[Anum_pg_subscription_subsynccommit - 1] =
+ CStringGetTextDatum(synchronous_commit);
+ values[Anum_pg_subscription_subpublications - 1] =
+ publicationListToArray(publications);
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ subid = CatalogTupleInsert(rel, tup);
+ heap_freetuple(tup);
+
+ recordDependencyOnOwner(SubscriptionRelationId, subid, owner);
+
+ snprintf(originname, sizeof(originname), "pg_%u", subid);
+ replorigin_create(originname);
+
+ /*
+ * Connect to remote side to execute requested commands and fetch table
+ * info.
+ */
+ if (connect)
+ {
+ XLogRecPtr lsn;
+ char *err;
+ WalReceiverConn *wrconn;
+ List *tables;
+ ListCell *lc;
+ char table_state;
+
+ /* Try to connect to the publisher. */
+ wrconn = walrcv_connect(conninfo, true, stmt->subname, &err);
+ if (!wrconn)
+ ereport(ERROR,
+ (errmsg("could not connect to the publisher: %s", err)));
+
+ PG_TRY();
+ {
+ /*
+ * Set sync state based on if we were asked to do data copy or
+ * not.
+ */
+ table_state = copy_data ? SUBREL_STATE_INIT : SUBREL_STATE_READY;
+
+ /*
+ * Get the table list from publisher and build local table status
+ * info.
+ */
+ tables = fetch_table_list(wrconn, publications);
+ foreach(lc, tables)
+ {
+ RangeVar *rv = (RangeVar *) lfirst(lc);
+ Oid relid;
+
+ relid = RangeVarGetRelid(rv, AccessShareLock, false);
+
+ /* Check for supported relkind. */
+ CheckSubscriptionRelkind(get_rel_relkind(relid),
+ rv->schemaname, rv->relname);
+
+ SetSubscriptionRelState(subid, relid, table_state,
+ InvalidXLogRecPtr);
+ }
+
+ ereport(NOTICE,
+ (errmsg("synchronized table states")));
+
+ /*
+ * If requested, create permanent slot for the subscription. We
+ * won't use the initial snapshot for anything, so no need to
+ * export it.
+ */
+ if (create_slot)
+ {
+ Assert(slotname);
+
+ walrcv_create_slot(wrconn, slotname, false,
+ CRS_NOEXPORT_SNAPSHOT, &lsn);
+ ereport(NOTICE,
+ (errmsg("created replication slot \"%s\" on publisher",
+ slotname)));
+ }
+ }
+ PG_CATCH();
+ {
+ /* Close the connection in case of failure. */
+ walrcv_disconnect(wrconn);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+
+ /* And we are done with the remote side. */
+ walrcv_disconnect(wrconn);
+ }
+ else
+ ereport(WARNING,
+ (errmsg("tables were not subscribed, you will have to run "
+ "ALTER SUBSCRIPTION ... REFRESH PUBLICATION to "
+ "subscribe the tables")));
+
+ heap_close(rel, RowExclusiveLock);
+
+ if (enabled)
+ ApplyLauncherWakeupAtCommit();
+
+ ObjectAddressSet(myself, SubscriptionRelationId, subid);
+
+ InvokeObjectPostCreateHook(SubscriptionRelationId, subid, 0);
+
+ return myself;
+}
+
+static void
+AlterSubscription_refresh(Subscription *sub, bool copy_data)
+{
+ char *err;
+ List *pubrel_names;
+ List *subrel_states;
+ Oid *subrel_local_oids;
+ Oid *pubrel_local_oids;
+ ListCell *lc;
+ int off;
+
+ /* Load the library providing us libpq calls. */
+ load_file("libpqwalreceiver", false);
+
+ /* Try to connect to the publisher. */
+ wrconn = walrcv_connect(sub->conninfo, true, sub->name, &err);
+ if (!wrconn)
+ ereport(ERROR,
+ (errmsg("could not connect to the publisher: %s", err)));
+
+ /* Get the table list from publisher. */
+ pubrel_names = fetch_table_list(wrconn, sub->publications);
+
+ /* We are done with the remote side, close connection. */
+ walrcv_disconnect(wrconn);
+
+ /* Get local table list. */
+ subrel_states = GetSubscriptionRelations(sub->oid);
+
+ /*
+ * Build qsorted array of local table oids for faster lookup. This can
+ * potentially contain all tables in the database so speed of lookup is
+ * important.
+ */
+ subrel_local_oids = palloc(list_length(subrel_states) * sizeof(Oid));
+ off = 0;
+ foreach(lc, subrel_states)
+ {
+ SubscriptionRelState *relstate = (SubscriptionRelState *) lfirst(lc);
+
+ subrel_local_oids[off++] = relstate->relid;
+ }
+ qsort(subrel_local_oids, list_length(subrel_states),
+ sizeof(Oid), oid_cmp);
+
+ /*
+ * Walk over the remote tables and try to match them to locally known
+ * tables. If the table is not known locally create a new state for it.
+ *
+ * Also builds array of local oids of remote tables for the next step.
+ */
+ off = 0;
+ pubrel_local_oids = palloc(list_length(pubrel_names) * sizeof(Oid));
+
+ foreach(lc, pubrel_names)
+ {
+ RangeVar *rv = (RangeVar *) lfirst(lc);
+ Oid relid;
+
+ relid = RangeVarGetRelid(rv, AccessShareLock, false);
+
+ /* Check for supported relkind. */
+ CheckSubscriptionRelkind(get_rel_relkind(relid),
+ rv->schemaname, rv->relname);
+
+ pubrel_local_oids[off++] = relid;
+
+ if (!bsearch(&relid, subrel_local_oids,
+ list_length(subrel_states), sizeof(Oid), oid_cmp))
+ {
+ SetSubscriptionRelState(sub->oid, relid,
+ copy_data ? SUBREL_STATE_INIT : SUBREL_STATE_READY,
+ InvalidXLogRecPtr);
+ ereport(NOTICE,
+ (errmsg("added subscription for table %s.%s",
+ quote_identifier(rv->schemaname),
+ quote_identifier(rv->relname))));
+ }
+ }
+
+ /*
+ * Next remove state for tables we should not care about anymore using the
+ * data we collected above
+ */
+ qsort(pubrel_local_oids, list_length(pubrel_names),
+ sizeof(Oid), oid_cmp);
+
+ for (off = 0; off < list_length(subrel_states); off++)
+ {
+ Oid relid = subrel_local_oids[off];
+
+ if (!bsearch(&relid, pubrel_local_oids,
+ list_length(pubrel_names), sizeof(Oid), oid_cmp))
+ {
+ char *namespace;
+
+ RemoveSubscriptionRel(sub->oid, relid);
+
+ namespace = get_namespace_name(get_rel_namespace(relid));
+ ereport(NOTICE,
+ (errmsg("removed subscription for table %s.%s",
+ quote_identifier(namespace),
+ quote_identifier(get_rel_name(relid)))));
+ }
+ }
+}
+
+/*
+ * Alter the existing subscription.
+ */
+ObjectAddress
+AlterSubscription(AlterSubscriptionStmt *stmt)
+{
+ Relation rel;
+ ObjectAddress myself;
+ bool nulls[Natts_pg_subscription];
+ bool replaces[Natts_pg_subscription];
+ Datum values[Natts_pg_subscription];
+ HeapTuple tup;
+ Oid subid;
+ bool update_tuple = false;
+ Subscription *sub;
+
+ rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
+
+ /* Fetch the existing tuple. */
+ tup = SearchSysCacheCopy2(SUBSCRIPTIONNAME, MyDatabaseId,
+ CStringGetDatum(stmt->subname));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription \"%s\" does not exist",
+ stmt->subname)));
+
+ /* must be owner */
+ if (!pg_subscription_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_SUBSCRIPTION,
+ stmt->subname);
+
+ subid = HeapTupleGetOid(tup);
+ sub = GetSubscription(subid, false);
+
+ /* Form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ switch (stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ {
+ char *slotname;
+ bool slotname_given;
+ char *synchronous_commit;
+
+ parse_subscription_options(stmt->options, NULL, NULL, NULL,
+ NULL, &slotname_given, &slotname,
+ NULL, &synchronous_commit);
+
+ if (slotname_given)
+ {
+ if (sub->enabled && !slotname)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("cannot set slot_name = NONE for enabled subscription")));
+
+ if (slotname)
+ values[Anum_pg_subscription_subslotname - 1] =
+ DirectFunctionCall1(namein, CStringGetDatum(slotname));
+ else
+ nulls[Anum_pg_subscription_subslotname - 1] = true;
+ replaces[Anum_pg_subscription_subslotname - 1] = true;
+ }
+
+ if (synchronous_commit)
+ {
+ values[Anum_pg_subscription_subsynccommit - 1] =
+ CStringGetTextDatum(synchronous_commit);
+ replaces[Anum_pg_subscription_subsynccommit - 1] = true;
+ }
+
+ update_tuple = true;
+ break;
+ }
+
+ case ALTER_SUBSCRIPTION_ENABLED:
+ {
+ bool enabled,
+ enabled_given;
+
+ parse_subscription_options(stmt->options, NULL,
+ &enabled_given, &enabled, NULL,
+ NULL, NULL, NULL, NULL);
+ Assert(enabled_given);
+
+ if (!sub->slotname && enabled)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("cannot enable subscription that does not have a slot name")));
+
+ values[Anum_pg_subscription_subenabled - 1] =
+ BoolGetDatum(enabled);
+ replaces[Anum_pg_subscription_subenabled - 1] = true;
+
+ if (enabled)
+ ApplyLauncherWakeupAtCommit();
+
+ update_tuple = true;
+ break;
+ }
+
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ /* Load the library providing us libpq calls. */
+ load_file("libpqwalreceiver", false);
+ /* Check the connection info string. */
+ walrcv_check_conninfo(stmt->conninfo);
+
+ values[Anum_pg_subscription_subconninfo - 1] =
+ CStringGetTextDatum(stmt->conninfo);
+ replaces[Anum_pg_subscription_subconninfo - 1] = true;
+ update_tuple = true;
+ break;
+
+ case ALTER_SUBSCRIPTION_PUBLICATION:
+ case ALTER_SUBSCRIPTION_PUBLICATION_REFRESH:
+ {
+ bool copy_data;
+
+ parse_subscription_options(stmt->options, NULL, NULL, NULL,
+ NULL, NULL, NULL, &copy_data,
+ NULL);
+
+ values[Anum_pg_subscription_subpublications - 1] =
+ publicationListToArray(stmt->publication);
+ replaces[Anum_pg_subscription_subpublications - 1] = true;
+
+ update_tuple = true;
+
+ /* Refresh if user asked us to. */
+ if (stmt->kind == ALTER_SUBSCRIPTION_PUBLICATION_REFRESH)
+ {
+ if (!sub->enabled)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
+
+ /* Make sure refresh sees the new list of publications. */
+ sub->publications = stmt->publication;
+
+ AlterSubscription_refresh(sub, copy_data);
+ }
+
+ break;
+ }
+
+ case ALTER_SUBSCRIPTION_REFRESH:
+ {
+ bool copy_data;
+
+ if (!sub->enabled)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
+
+ parse_subscription_options(stmt->options, NULL, NULL, NULL,
+ NULL, NULL, NULL, &copy_data,
+ NULL);
+
+ AlterSubscription_refresh(sub, copy_data);
+
+ break;
+ }
+
+ default:
+ elog(ERROR, "unrecognized ALTER SUBSCRIPTION kind %d",
+ stmt->kind);
+ }
+
+ /* Update the catalog if needed. */
+ if (update_tuple)
+ {
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ heap_freetuple(tup);
+ }
+
+ heap_close(rel, RowExclusiveLock);
+
+ ObjectAddressSet(myself, SubscriptionRelationId, subid);
+
+ InvokeObjectPostAlterHook(SubscriptionRelationId, subid, 0);
+
+ return myself;
+}
+
+/*
+ * Drop a subscription
+ */
+void
+DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
+{
+ Relation rel;
+ ObjectAddress myself;
+ HeapTuple tup;
+ Oid subid;
+ Datum datum;
+ bool isnull;
+ char *subname;
+ char *conninfo;
+ char *slotname;
+ char originname[NAMEDATALEN];
+ char *err = NULL;
+ RepOriginId originid;
+ WalReceiverConn *wrconn = NULL;
+ StringInfoData cmd;
+
+ /*
+ * Lock pg_subscription with AccessExclusiveLock to ensure that the
+ * launcher doesn't restart new worker during dropping the subscription
+ */
+ rel = heap_open(SubscriptionRelationId, AccessExclusiveLock);
+
+ tup = SearchSysCache2(SUBSCRIPTIONNAME, MyDatabaseId,
+ CStringGetDatum(stmt->subname));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ heap_close(rel, NoLock);
+
+ if (!stmt->missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription \"%s\" does not exist",
+ stmt->subname)));
+ else
+ ereport(NOTICE,
+ (errmsg("subscription \"%s\" does not exist, skipping",
+ stmt->subname)));
+
+ return;
+ }
+
+ subid = HeapTupleGetOid(tup);
+
+ /* must be owner */
+ if (!pg_subscription_ownercheck(subid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_SUBSCRIPTION,
+ stmt->subname);
+
+ /* DROP hook for the subscription being removed */
+ InvokeObjectDropHook(SubscriptionRelationId, subid, 0);
+
+ /*
+ * Lock the subscription so nobody else can do anything with it (including
+ * the replication workers).
+ */
+ LockSharedObject(SubscriptionRelationId, subid, 0, AccessExclusiveLock);
+
+ /* Get subname */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup,
+ Anum_pg_subscription_subname, &isnull);
+ Assert(!isnull);
+ subname = pstrdup(NameStr(*DatumGetName(datum)));
+
+ /* Get conninfo */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup,
+ Anum_pg_subscription_subconninfo, &isnull);
+ Assert(!isnull);
+ conninfo = TextDatumGetCString(datum);
+
+ /* Get slotname */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup,
+ Anum_pg_subscription_subslotname, &isnull);
+ if (!isnull)
+ slotname = pstrdup(NameStr(*DatumGetName(datum)));
+ else
+ slotname = NULL;
+
+ /*
+ * Since dropping a replication slot is not transactional, the replication
+ * slot stays dropped even if the transaction rolls back. So we cannot
+ * run DROP SUBSCRIPTION inside a transaction block if dropping the
+ * replication slot.
+ *
+ * XXX The command name should really be something like "DROP SUBSCRIPTION
+ * of a subscription that is associated with a replication slot", but we
+ * don't have the proper facilities for that.
+ */
+ if (slotname)
+ PreventTransactionChain(isTopLevel, "DROP SUBSCRIPTION");
+
+
+ ObjectAddressSet(myself, SubscriptionRelationId, subid);
+ EventTriggerSQLDropAddObject(&myself, true, true);
+
+ /* Remove the tuple from catalog. */
+ CatalogTupleDelete(rel, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ /* Clean up dependencies */
+ deleteSharedDependencyRecordsFor(SubscriptionRelationId, subid, 0);
+
+ /* Remove any associated relation synchronization states. */
+ RemoveSubscriptionRel(subid, InvalidOid);
+
+ /* Kill the apply worker so that the slot becomes accessible. */
+ logicalrep_worker_stop(subid, InvalidOid);
+
+ /* Remove the origin tracking if exists. */
+ snprintf(originname, sizeof(originname), "pg_%u", subid);
+ originid = replorigin_by_name(originname, true);
+ if (originid != InvalidRepOriginId)
+ replorigin_drop(originid);
+
+ /*
+ * If there is no slot associated with the subscription, we can finish
+ * here.
+ */
+ if (!slotname)
+ {
+ heap_close(rel, NoLock);
+ return;
+ }
+
+ /*
+ * Otherwise drop the replication slot at the publisher node using the
+ * replication connection.
+ */
+ load_file("libpqwalreceiver", false);
+
+ initStringInfo(&cmd);
+ appendStringInfo(&cmd, "DROP_REPLICATION_SLOT %s", quote_identifier(slotname));
+
+ wrconn = walrcv_connect(conninfo, true, subname, &err);
+ if (wrconn == NULL)
+ ereport(ERROR,
+ (errmsg("could not connect to publisher when attempting to "
+ "drop the replication slot \"%s\"", slotname),
+ errdetail("The error was: %s", err),
+ errhint("Use ALTER SUBSCRIPTION ... SET (slot_name = NONE) "
+ "to disassociate the subscription from the slot.")));
+
+ PG_TRY();
+ {
+ WalRcvExecResult *res;
+
+ res = walrcv_exec(wrconn, cmd.data, 0, NULL);
+
+ if (res->status != WALRCV_OK_COMMAND)
+ ereport(ERROR,
+ (errmsg("could not drop the replication slot \"%s\" on publisher",
+ slotname),
+ errdetail("The error was: %s", res->err)));
+ else
+ ereport(NOTICE,
+ (errmsg("dropped replication slot \"%s\" on publisher",
+ slotname)));
+
+ walrcv_clear_result(res);
+ }
+ PG_CATCH();
+ {
+ /* Close the connection in case of failure */
+ walrcv_disconnect(wrconn);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+
+ walrcv_disconnect(wrconn);
+
+ pfree(cmd.data);
+
+ heap_close(rel, NoLock);
+}
+
+/*
+ * Internal workhorse for changing a subscription owner
+ */
+static void
+AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
+{
+ Form_pg_subscription form;
+
+ form = (Form_pg_subscription) GETSTRUCT(tup);
+
+ if (form->subowner == newOwnerId)
+ return;
+
+ if (!pg_subscription_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_SUBSCRIPTION,
+ NameStr(form->subname));
+
+ /* New owner must be a superuser */
+ if (!superuser_arg(newOwnerId))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to change owner of subscription \"%s\"",
+ NameStr(form->subname)),
+ errhint("The owner of a subscription must be a superuser.")));
+
+ form->subowner = newOwnerId;
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Update owner dependency reference */
+ changeDependencyOnOwner(SubscriptionRelationId,
+ HeapTupleGetOid(tup),
+ newOwnerId);
+
+ InvokeObjectPostAlterHook(SubscriptionRelationId,
+ HeapTupleGetOid(tup), 0);
+}
+
+/*
+ * Change subscription owner -- by name
+ */
+ObjectAddress
+AlterSubscriptionOwner(const char *name, Oid newOwnerId)
+{
+ Oid subid;
+ HeapTuple tup;
+ Relation rel;
+ ObjectAddress address;
+
+ rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy2(SUBSCRIPTIONNAME, MyDatabaseId,
+ CStringGetDatum(name));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription \"%s\" does not exist", name)));
+
+ subid = HeapTupleGetOid(tup);
+
+ AlterSubscriptionOwner_internal(rel, tup, newOwnerId);
+
+ ObjectAddressSet(address, SubscriptionRelationId, subid);
+
+ heap_freetuple(tup);
+
+ heap_close(rel, RowExclusiveLock);
+
+ return address;
+}
+
+/*
+ * Change subscription owner -- by OID
+ */
+void
+AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
+{
+ HeapTuple tup;
+ Relation rel;
+
+ rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription with OID %u does not exist", subid)));
+
+ AlterSubscriptionOwner_internal(rel, tup, newOwnerId);
+
+ heap_freetuple(tup);
+
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * Get the list of tables which belong to specified publications on the
+ * publisher connection.
+ */
+static List *
+fetch_table_list(WalReceiverConn *wrconn, List *publications)
+{
+ WalRcvExecResult *res;
+ StringInfoData cmd;
+ TupleTableSlot *slot;
+ Oid tableRow[2] = {TEXTOID, TEXTOID};
+ ListCell *lc;
+ bool first;
+ List *tablelist = NIL;
+
+ Assert(list_length(publications) > 0);
+
+ initStringInfo(&cmd);
+ appendStringInfo(&cmd, "SELECT DISTINCT t.schemaname, t.tablename\n"
+ " FROM pg_catalog.pg_publication_tables t\n"
+ " WHERE t.pubname IN (");
+ first = true;
+ foreach(lc, publications)
+ {
+ char *pubname = strVal(lfirst(lc));
+
+ if (first)
+ first = false;
+ else
+ appendStringInfoString(&cmd, ", ");
+
+ appendStringInfo(&cmd, "%s", quote_literal_cstr(pubname));
+ }
+ appendStringInfoString(&cmd, ")");
+
+ res = walrcv_exec(wrconn, cmd.data, 2, tableRow);
+ pfree(cmd.data);
+
+ if (res->status != WALRCV_OK_TUPLES)
+ ereport(ERROR,
+ (errmsg("could not receive list of replicated tables from the publisher: %s",
+ res->err)));
+
+ /* Process tables. */
+ slot = MakeSingleTupleTableSlot(res->tupledesc);
+ while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
+ {
+ char *nspname;
+ char *relname;
+ bool isnull;
+ RangeVar *rv;
+
+ nspname = TextDatumGetCString(slot_getattr(slot, 1, &isnull));
+ Assert(!isnull);
+ relname = TextDatumGetCString(slot_getattr(slot, 2, &isnull));
+ Assert(!isnull);
+
+ rv = makeRangeVar(pstrdup(nspname), pstrdup(relname), -1);
+ tablelist = lappend(tablelist, rv);
+
+ ExecClearTuple(slot);
+ }
+ ExecDropSingleTupleTableSlot(slot);
+
+ walrcv_clear_result(res);
+
+ return tablelist;
+}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b48f6e529d..5be449648c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4,7 +4,7 @@
* Commands for creating and altering table structures and settings
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -22,6 +22,7 @@
#include "access/reloptions.h"
#include "access/relscan.h"
#include "access/sysattr.h"
+#include "access/tupconvert.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
@@ -31,6 +32,7 @@
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
+#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
@@ -67,6 +69,9 @@
#include "nodes/parsenodes.h"
#include "optimizer/clauses.h"
#include "optimizer/planner.h"
+#include "optimizer/predtest.h"
+#include "optimizer/prep.h"
+#include "optimizer/var.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
@@ -178,6 +183,7 @@ typedef struct AlteredTableInfo
Oid newTableSpace; /* new tablespace; 0 means no change */
bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */
char newrelpersistence; /* if above is true */
+ Expr *partition_constraint; /* for attach partition validation */
/* Objects to rebuild after completing ALTER TYPE operations */
List *changedConstraintOids; /* OIDs of constraints to rebuild */
List *changedConstraintDefs; /* string definitions of same */
@@ -195,7 +201,7 @@ typedef struct NewConstraint
Oid refindid; /* OID of PK's index, if FOREIGN */
Oid conid; /* OID of pg_constraint entry, if FOREIGN */
Node *qual; /* Check expr or CONSTR_FOREIGN Constraint */
- List *qualstate; /* Execution state for CHECK */
+ ExprState *qualstate; /* Execution state for CHECK expr */
} NewConstraint;
/*
@@ -268,6 +274,12 @@ static const struct dropmsgstrings dropmsgstringarray[] = {
gettext_noop("foreign table \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a foreign table"),
gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")},
+ {RELKIND_PARTITIONED_TABLE,
+ ERRCODE_UNDEFINED_TABLE,
+ gettext_noop("table \"%s\" does not exist"),
+ gettext_noop("table \"%s\" does not exist, skipping"),
+ gettext_noop("\"%s\" is not a table"),
+ gettext_noop("Use DROP TABLE to remove a table.")},
{'\0', 0, NULL, NULL, NULL, NULL}
};
@@ -275,6 +287,7 @@ struct DropRelationCallbackState
{
char relkind;
Oid heapOid;
+ Oid partParentOid;
bool concurrent;
};
@@ -288,13 +301,16 @@ struct DropRelationCallbackState
static void truncate_check_rel(Relation rel);
static List *MergeAttributes(List *schema, List *supers, char relpersistence,
- List **supOids, List **supconstr, int *supOidCount);
+ bool is_partition, List **supOids, List **supconstr,
+ int *supOidCount);
static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel);
static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
-static void StoreCatalogInheritance(Oid relationId, List *supers);
+static void StoreCatalogInheritance(Oid relationId, List *supers,
+ bool child_is_partition);
static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
- int16 seqNumber, Relation inhRelation);
+ int16 seqNumber, Relation inhRelation,
+ bool child_is_partition);
static int findAttrByName(const char *attributeName, List *schema);
static void AlterIndexNamespaces(Relation classRel, Relation rel,
Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved);
@@ -355,11 +371,18 @@ static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
AlterTableCmd *cmd, LOCKMODE lockmode);
+static void ATPrepDropNotNull(Relation rel, bool recurse, bool recursing);
static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
+static void ATPrepSetNotNull(Relation rel, bool recurse, bool recursing);
static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
const char *colName, LOCKMODE lockmode);
static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
Node *newDefault, LOCKMODE lockmode);
+static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
+ Node *def, LOCKMODE lockmode);
+static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
+ Node *def, LOCKMODE lockmode);
+static ObjectAddress ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode);
static void ATPrepSetStatistics(Relation rel, const char *colName,
Node *newValue, LOCKMODE lockmode);
static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName,
@@ -459,6 +482,15 @@ static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
Oid oldRelOid, void *arg);
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
Oid oldrelid, void *arg);
+static bool is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr);
+static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy);
+static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
+ List **partexprs, Oid *partopclass, Oid *partcollation);
+static void CreateInheritance(Relation child_rel, Relation parent_rel);
+static void RemoveInheritance(Relation child_rel, Relation parent_rel);
+static ObjectAddress ATExecAttachPartition(List **wqueue, Relation rel,
+ PartitionCmd *cmd);
+static ObjectAddress ATExecDetachPartition(Relation rel, RangeVar *name);
/* ----------------------------------------------------------------
@@ -481,11 +513,10 @@ static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
*/
ObjectAddress
DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
- ObjectAddress *typaddress)
+ ObjectAddress *typaddress, const char *queryString)
{
char relname[NAMEDATALEN];
Oid namespaceId;
- List *schema = stmt->tableElts;
Oid relationId;
Oid tablespaceId;
Relation rel;
@@ -518,6 +549,14 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("ON COMMIT can only be used on temporary tables")));
+ if (stmt->partspec != NULL)
+ {
+ if (relkind != RELKIND_RELATION)
+ elog(ERROR, "unexpected relkind: %d", (int) relkind);
+
+ relkind = RELKIND_PARTITIONED_TABLE;
+ }
+
/*
* Look up the namespace in which we are supposed to create the relation,
* check we have permission to create there, lock it against concurrent
@@ -600,32 +639,46 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
/*
* Look up inheritance ancestors and generate relation schema, including
- * inherited attributes.
+ * inherited attributes. (Note that stmt->tableElts is destructively
+ * modified by MergeAttributes.)
*/
- schema = MergeAttributes(schema, stmt->inhRelations,
- stmt->relation->relpersistence,
- &inheritOids, &old_constraints, &parentOidCount);
+ stmt->tableElts =
+ MergeAttributes(stmt->tableElts, stmt->inhRelations,
+ stmt->relation->relpersistence,
+ stmt->partbound != NULL,
+ &inheritOids, &old_constraints, &parentOidCount);
/*
* Create a tuple descriptor from the relation schema. Note that this
* deals with column names, types, and NOT NULL constraints, but not
* default values or CHECK constraints; we handle those below.
*/
- descriptor = BuildDescForRelation(schema);
+ descriptor = BuildDescForRelation(stmt->tableElts);
/*
- * Notice that we allow OIDs here only for plain tables, even though some
- * other relkinds can support them. This is necessary because the
- * default_with_oids GUC must apply only to plain tables and not any other
- * relkind; doing otherwise would break existing pg_dump files. We could
- * allow explicit "WITH OIDS" while not allowing default_with_oids to
- * affect other relkinds, but it would complicate interpretOidsOption().
+ * Notice that we allow OIDs here only for plain tables and partitioned
+ * tables, even though some other relkinds can support them. This is
+ * necessary because the default_with_oids GUC must apply only to plain
+ * tables and not any other relkind; doing otherwise would break existing
+ * pg_dump files. We could allow explicit "WITH OIDS" while not allowing
+ * default_with_oids to affect other relkinds, but it would complicate
+ * interpretOidsOption().
*/
localHasOids = interpretOidsOption(stmt->options,
- (relkind == RELKIND_RELATION));
+ (relkind == RELKIND_RELATION ||
+ relkind == RELKIND_PARTITIONED_TABLE));
descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
/*
+ * If a partitioned table doesn't have the system OID column, then none of
+ * its partitions should have it.
+ */
+ if (stmt->partbound && parentOidCount == 0 && localHasOids)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot create table with OIDs as partition of table without OIDs")));
+
+ /*
* Find columns with default values and prepare for insertion of the
* defaults. Pre-cooked (that is, inherited) defaults go into a list of
* CookedConstraint structs that we'll pass to heap_create_with_catalog,
@@ -641,7 +694,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
cookedDefaults = NIL;
attnum = 0;
- foreach(listptr, schema)
+ foreach(listptr, stmt->tableElts)
{
ColumnDef *colDef = lfirst(listptr);
@@ -676,6 +729,9 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
cookedDefaults = lappend(cookedDefaults, cooked);
descriptor->attrs[attnum - 1]->atthasdef = true;
}
+
+ if (colDef->identity)
+ descriptor->attrs[attnum - 1]->attidentity = colDef->identity;
}
/*
@@ -707,7 +763,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
typaddress);
/* Store inheritance information for new rel. */
- StoreCatalogInheritance(relationId, inheritOids);
+ StoreCatalogInheritance(relationId, inheritOids, stmt->partbound != NULL);
/*
* We must bump the command counter to make the newly-created relation
@@ -750,6 +806,92 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
*/
rel = relation_open(relationId, AccessExclusiveLock);
+ /* Process and store partition bound, if any. */
+ if (stmt->partbound)
+ {
+ PartitionBoundSpec *bound;
+ ParseState *pstate;
+ Oid parentId = linitial_oid(inheritOids);
+ Relation parent;
+
+ /* Already have strong enough lock on the parent */
+ parent = heap_open(parentId, NoLock);
+
+ /*
+ * We are going to try to validate the partition bound specification
+ * against the partition key of parentRel, so it better have one.
+ */
+ if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("\"%s\" is not partitioned",
+ RelationGetRelationName(parent))));
+
+ /* Tranform the bound values */
+ pstate = make_parsestate(NULL);
+ pstate->p_sourcetext = queryString;
+
+ bound = transformPartitionBound(pstate, parent, stmt->partbound);
+
+ /*
+ * Check first that the new partition's bound is valid and does not
+ * overlap with any of existing partitions of the parent - note that
+ * it does not return on error.
+ */
+ check_new_partition_bound(relname, parent, bound);
+
+ /* Update the pg_class entry. */
+ StorePartitionBound(rel, parent, bound);
+
+ heap_close(parent, NoLock);
+
+ /*
+ * The code that follows may also update the pg_class tuple to update
+ * relnumchecks, so bump up the command counter to avoid the "already
+ * updated by self" error.
+ */
+ CommandCounterIncrement();
+ }
+
+ /*
+ * Process the partitioning specification (if any) and store the partition
+ * key information into the catalog.
+ */
+ if (stmt->partspec)
+ {
+ char strategy;
+ int partnatts;
+ AttrNumber partattrs[PARTITION_MAX_KEYS];
+ Oid partopclass[PARTITION_MAX_KEYS];
+ Oid partcollation[PARTITION_MAX_KEYS];
+ List *partexprs = NIL;
+
+ partnatts = list_length(stmt->partspec->partParams);
+
+ /* Protect fixed-size arrays here and in executor */
+ if (partnatts > PARTITION_MAX_KEYS)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_COLUMNS),
+ errmsg("cannot partition using more than %d columns",
+ PARTITION_MAX_KEYS)));
+
+ /*
+ * We need to transform the raw parsetrees corresponding to partition
+ * expressions into executable expression trees. Like column defaults
+ * and CHECK constraints, we could not have done the transformation
+ * earlier.
+ */
+ stmt->partspec = transformPartitionSpec(rel, stmt->partspec,
+ &strategy);
+
+ ComputePartitionAttrs(rel, stmt->partspec->partParams,
+ partattrs, &partexprs, partopclass,
+ partcollation);
+
+ StorePartitionKey(rel, strategy, partnatts, partattrs, partexprs,
+ partopclass, partcollation);
+ }
+
/*
* Now add any newly specified column default values and CHECK constraints
* to the new relation. These are passed to us in the form of raw
@@ -943,6 +1085,7 @@ RemoveRelations(DropStmt *drop)
/* Look up the appropriate relation using namespace search. */
state.relkind = relkind;
state.heapOid = InvalidOid;
+ state.partParentOid = InvalidOid;
state.concurrent = drop->concurrent;
relOid = RangeVarGetRelidExtended(rel, lockmode, true,
false,
@@ -972,6 +1115,8 @@ RemoveRelations(DropStmt *drop)
/*
* Before acquiring a table lock, check whether we have sufficient rights.
* In the case of DROP INDEX, also try to lock the table before the index.
+ * Also, if the table to be dropped is a partition, we try to lock the parent
+ * first.
*/
static void
RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
@@ -980,6 +1125,8 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
HeapTuple tuple;
struct DropRelationCallbackState *state;
char relkind;
+ char expected_relkind;
+ bool is_partition;
Form_pg_class classform;
LOCKMODE heap_lockmode;
@@ -999,6 +1146,17 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
state->heapOid = InvalidOid;
}
+ /*
+ * Similarly, if we previously locked some other partition's heap, and the
+ * name we're looking up no longer refers to that relation, release the
+ * now-useless lock.
+ */
+ if (relOid != oldRelOid && OidIsValid(state->partParentOid))
+ {
+ UnlockRelationOid(state->partParentOid, AccessExclusiveLock);
+ state->partParentOid = InvalidOid;
+ }
+
/* Didn't find a relation, so no need for locking or permission checks. */
if (!OidIsValid(relOid))
return;
@@ -1007,8 +1165,21 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
if (!HeapTupleIsValid(tuple))
return; /* concurrently dropped, so nothing to do */
classform = (Form_pg_class) GETSTRUCT(tuple);
+ is_partition = classform->relispartition;
+
+ /*
+ * Both RELKIND_RELATION and RELKIND_PARTITIONED_TABLE are OBJECT_TABLE,
+ * but RemoveRelations() can only pass one relkind for a given relation.
+ * It chooses RELKIND_RELATION for both regular and partitioned tables.
+ * That means we must be careful before giving the wrong type error when
+ * the relation is RELKIND_PARTITIONED_TABLE.
+ */
+ if (classform->relkind == RELKIND_PARTITIONED_TABLE)
+ expected_relkind = RELKIND_RELATION;
+ else
+ expected_relkind = classform->relkind;
- if (classform->relkind != relkind)
+ if (relkind != expected_relkind)
DropErrorMsgWrongType(rel->relname, classform->relkind, relkind);
/* Allow DROP to either table owner or schema owner */
@@ -1038,6 +1209,19 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
if (OidIsValid(state->heapOid))
LockRelationOid(state->heapOid, heap_lockmode);
}
+
+ /*
+ * Similarly, if the relation is a partition, we must acquire lock on its
+ * parent before locking the partition. That's because queries lock the
+ * parent before its partitions, so we risk deadlock it we do it the other
+ * way around.
+ */
+ if (is_partition && relOid != oldRelOid)
+ {
+ state->partParentOid = get_partition_parent(relOid);
+ if (OidIsValid(state->partParentOid))
+ LockRelationOid(state->partParentOid, AccessExclusiveLock);
+ }
}
/*
@@ -1079,7 +1263,7 @@ ExecuteTruncate(TruncateStmt *stmt)
{
RangeVar *rv = lfirst(cell);
Relation rel;
- bool recurse = interpretInhOption(rv->inhOpt);
+ bool recurse = rv->inh;
Oid myrelid;
rel = heap_openrv(rv, AccessExclusiveLock);
@@ -1115,6 +1299,11 @@ ExecuteTruncate(TruncateStmt *stmt)
relids = lappend_oid(relids, childrelid);
}
}
+ else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot truncate only a partitioned table"),
+ errhint("Do not specify the ONLY keyword, or use truncate only on the partitions directly.")));
}
/*
@@ -1174,7 +1363,7 @@ ExecuteTruncate(TruncateStmt *stmt)
foreach(cell, rels)
{
Relation rel = (Relation) lfirst(cell);
- List *seqlist = getOwnedSequences(RelationGetRelid(rel));
+ List *seqlist = getOwnedSequences(RelationGetRelid(rel), 0);
ListCell *seqcell;
foreach(seqcell, seqlist)
@@ -1214,6 +1403,7 @@ ExecuteTruncate(TruncateStmt *stmt)
InitResultRelInfo(resultRelInfo,
rel,
0, /* dummy rangetable index */
+ NULL,
0);
resultRelInfo++;
}
@@ -1243,6 +1433,10 @@ ExecuteTruncate(TruncateStmt *stmt)
{
Relation rel = (Relation) lfirst(cell);
+ /* Skip partitioned tables as there is nothing to do */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ continue;
+
/*
* Normally, we need a transaction-safe truncation here. However, if
* the table was either created in the current (sub)transaction or has
@@ -1353,8 +1547,13 @@ truncate_check_rel(Relation rel)
{
AclResult aclresult;
- /* Only allow truncate on regular tables */
- if (rel->rd_rel->relkind != RELKIND_RELATION)
+ /*
+ * Only allow truncate on regular tables and partitioned tables (although,
+ * the latter are only being included here for the following checks; no
+ * physical truncation will occur in their case.)
+ */
+ if (rel->rd_rel->relkind != RELKIND_RELATION &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
@@ -1420,6 +1619,7 @@ storage_name(char c)
* of ColumnDef's.) It is destructively changed.
* 'supers' is a list of names (as RangeVar nodes) of parent relations.
* 'relpersistence' is a persistence type of the table.
+ * 'is_partition' tells if the table is a partition
*
* Output arguments:
* 'supOids' receives a list of the OIDs of the parent relations.
@@ -1471,7 +1671,8 @@ storage_name(char c)
*/
static List *
MergeAttributes(List *schema, List *supers, char relpersistence,
- List **supOids, List **supconstr, int *supOidCount)
+ bool is_partition, List **supOids, List **supconstr,
+ int *supOidCount)
{
ListCell *entry;
List *inhSchema = NIL;
@@ -1481,6 +1682,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
bool have_bogus_defaults = false;
int child_attno;
static Node bogus_marker = {0}; /* marks conflicting defaults */
+ List *saved_schema = NIL;
/*
* Check for and reject tables with too many columns. We perform this
@@ -1490,8 +1692,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
* execute if the user attempts to create a table with hundreds of
* thousands of columns.
*
- * Note that we also need to check that any we do not exceed this figure
- * after including columns from inherited relations.
+ * Note that we also need to check that we do not exceed this figure after
+ * including columns from inherited relations.
*/
if (list_length(schema) > MaxHeapAttributeNumber)
ereport(ERROR,
@@ -1500,6 +1702,17 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
MaxHeapAttributeNumber)));
/*
+ * In case of a partition, there are no new column definitions, only dummy
+ * ColumnDefs created for column constraints. We merge them with the
+ * constraints inherited from the parent.
+ */
+ if (is_partition)
+ {
+ saved_schema = schema;
+ schema = NIL;
+ }
+
+ /*
* Check for duplicate names in the explicit list of attributes.
*
* Although we might consider merging such entries in the same way that we
@@ -1579,11 +1792,35 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
* on the parent table, which might otherwise be attempting to clear
* the parent's relhassubclass field, if its previous children were
* recently dropped.
+ *
+ * If the child table is a partition, then we instead grab an
+ * exclusive lock on the parent because its partition descriptor will
+ * be changed by addition of the new partition.
*/
- relation = heap_openrv(parent, ShareUpdateExclusiveLock);
+ if (!is_partition)
+ relation = heap_openrv(parent, ShareUpdateExclusiveLock);
+ else
+ relation = heap_openrv(parent, AccessExclusiveLock);
+
+ /*
+ * We do not allow partitioned tables and partitions to participate in
+ * regular inheritance.
+ */
+ if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
+ !is_partition)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot inherit from partitioned table \"%s\"",
+ parent->relname)));
+ if (relation->rd_rel->relispartition && !is_partition)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot inherit from partition \"%s\"",
+ parent->relname)));
if (relation->rd_rel->relkind != RELKIND_RELATION &&
- relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("inherited relation \"%s\" is not a table or foreign table",
@@ -1593,7 +1830,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("cannot inherit from temporary relation \"%s\"",
+ errmsg(!is_partition
+ ? "cannot inherit from temporary relation \"%s\""
+ : "cannot create a permanent relation as partition of temporary relation \"%s\"",
parent->relname)));
/* If existing rel is temp, it must belong to this session */
@@ -1601,7 +1840,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
!relation->rd_islocaltemp)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("cannot inherit from temporary relation of another session")));
+ errmsg(!is_partition
+ ? "cannot inherit from temporary relation of another session"
+ : "cannot create as partition of temporary relation of another session")));
/*
* We should have an UNDER permission flag for this, but for now,
@@ -1721,6 +1962,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
def->is_local = false;
def->is_not_null = attribute->attnotnull;
def->is_from_type = false;
+ def->is_from_parent = true;
def->storage = attribute->attstorage;
def->raw_default = NULL;
def->cooked_default = NULL;
@@ -1838,9 +2080,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
pfree(newattno);
/*
- * Close the parent rel, but keep our ShareUpdateExclusiveLock on it
- * until xact commit. That will prevent someone else from deleting or
- * ALTERing the parent before the child is committed.
+ * Close the parent rel, but keep our lock on it until xact commit.
+ * That will prevent someone else from deleting or ALTERing the parent
+ * before the child is committed.
*/
heap_close(relation, NoLock);
}
@@ -1848,7 +2090,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
/*
* If we had no inherited attributes, the result schema is just the
* explicitly declared columns. Otherwise, we need to merge the declared
- * columns into the inherited schema list.
+ * columns into the inherited schema list. Although, we never have any
+ * explicitly declared columns if the table is a partition.
*/
if (inhSchema != NIL)
{
@@ -1877,6 +2120,12 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
newcollid;
/*
+ * Partitions have only one parent and have no column
+ * definitions of their own, so conflict should never occur.
+ */
+ Assert(!is_partition);
+
+ /*
* Yes, try to merge the two column definitions. They must
* have the same type, typmod, and collation.
*/
@@ -1912,6 +2161,12 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
get_collation_name(defcollid),
get_collation_name(newcollid))));
+ /*
+ * Identity is never inherited. The new column can have an
+ * identity definition, so we always just take that one.
+ */
+ def->identity = newdef->identity;
+
/* Copy storage parameter */
if (def->storage == 0)
def->storage = newdef->storage;
@@ -1958,6 +2213,65 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
}
/*
+ * Now that we have the column definition list for a partition, we can
+ * check whether the columns referenced in the column constraint specs
+ * actually exist. Also, we merge the constraints into the corresponding
+ * column definitions.
+ */
+ if (is_partition && list_length(saved_schema) > 0)
+ {
+ schema = list_concat(schema, saved_schema);
+
+ foreach(entry, schema)
+ {
+ ColumnDef *coldef = lfirst(entry);
+ ListCell *rest = lnext(entry);
+ ListCell *prev = entry;
+
+ /*
+ * Partition column option that does not belong to a column from
+ * the parent. This works because the columns from the parent
+ * come first in the list (see above).
+ */
+ if (coldef->typeName == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" does not exist",
+ coldef->colname)));
+ while (rest != NULL)
+ {
+ ColumnDef *restdef = lfirst(rest);
+ ListCell *next = lnext(rest); /* need to save it in case we
+ * delete it */
+
+ if (strcmp(coldef->colname, restdef->colname) == 0)
+ {
+ /*
+ * merge the column options into the column from the
+ * parent
+ */
+ if (coldef->is_from_parent)
+ {
+ coldef->is_not_null = restdef->is_not_null;
+ coldef->raw_default = restdef->raw_default;
+ coldef->cooked_default = restdef->cooked_default;
+ coldef->constraints = restdef->constraints;
+ coldef->is_from_parent = false;
+ list_delete_cell(schema, rest, prev);
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_COLUMN),
+ errmsg("column \"%s\" specified more than once",
+ coldef->colname)));
+ }
+ prev = rest;
+ rest = next;
+ }
+ }
+ }
+
+ /*
* If we found any conflicting parent default values, check to make sure
* they were overridden by the child.
*/
@@ -2034,7 +2348,8 @@ MergeCheckConstraint(List *constraints, char *name, Node *expr)
* supers is a list of the OIDs of the new relation's direct ancestors.
*/
static void
-StoreCatalogInheritance(Oid relationId, List *supers)
+StoreCatalogInheritance(Oid relationId, List *supers,
+ bool child_is_partition)
{
Relation relation;
int16 seqNumber;
@@ -2064,7 +2379,8 @@ StoreCatalogInheritance(Oid relationId, List *supers)
{
Oid parentOid = lfirst_oid(entry);
- StoreCatalogInheritance1(relationId, parentOid, seqNumber, relation);
+ StoreCatalogInheritance1(relationId, parentOid, seqNumber, relation,
+ child_is_partition);
seqNumber++;
}
@@ -2077,7 +2393,8 @@ StoreCatalogInheritance(Oid relationId, List *supers)
*/
static void
StoreCatalogInheritance1(Oid relationId, Oid parentOid,
- int16 seqNumber, Relation inhRelation)
+ int16 seqNumber, Relation inhRelation,
+ bool child_is_partition)
{
TupleDesc desc = RelationGetDescr(inhRelation);
Datum values[Natts_pg_inherits];
@@ -2097,9 +2414,7 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid,
tuple = heap_form_tuple(desc, values, nulls);
- simple_heap_insert(inhRelation, tuple);
-
- CatalogUpdateIndexes(inhRelation, tuple);
+ CatalogTupleInsert(inhRelation, tuple);
heap_freetuple(tuple);
@@ -2113,7 +2428,14 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid,
childobject.objectId = relationId;
childobject.objectSubId = 0;
- recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
+ /*
+ * Partition tables are expected to be dropped when the parent partitioned
+ * table gets dropped.
+ */
+ if (child_is_partition)
+ recordDependencyOn(&childobject, &parentobject, DEPENDENCY_AUTO);
+ else
+ recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
/*
* Post creation hook of this inheritance. Since object_access_hook
@@ -2187,10 +2509,7 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass)
if (classtuple->relhassubclass != relhassubclass)
{
classtuple->relhassubclass = relhassubclass;
- simple_heap_update(relationRelation, &tuple->t_self, tuple);
-
- /* keep the catalog indexes up to date */
- CatalogUpdateIndexes(relationRelation, tuple);
+ CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
}
else
{
@@ -2227,7 +2546,8 @@ renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
relkind != RELKIND_MATVIEW &&
relkind != RELKIND_COMPOSITE_TYPE &&
relkind != RELKIND_INDEX &&
- relkind != RELKIND_FOREIGN_TABLE)
+ relkind != RELKIND_FOREIGN_TABLE &&
+ relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, materialized view, composite type, index, or foreign table",
@@ -2380,10 +2700,7 @@ renameatt_internal(Oid myrelid,
/* apply the update */
namestrcpy(&(attform->attname), newattname);
- simple_heap_update(attrelation, &atttup->t_self, atttup);
-
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(attrelation, atttup);
+ CatalogTupleUpdate(attrelation, &atttup->t_self, atttup);
InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
@@ -2444,7 +2761,7 @@ renameatt(RenameStmt *stmt)
renameatt_internal(relid,
stmt->subname, /* old att name */
stmt->newname, /* new att name */
- interpretInhOption(stmt->relation->inhOpt), /* recursive? */
+ stmt->relation->inh, /* recursive? */
false, /* recursing? */
0, /* expected inhcount */
stmt->behavior);
@@ -2567,7 +2884,7 @@ RenameConstraint(RenameStmt *stmt)
Relation rel;
HeapTuple tup;
- typid = typenameTypeId(NULL, makeTypeNameFromNameList(stmt->object));
+ typid = typenameTypeId(NULL, makeTypeNameFromNameList(castNode(List, stmt->object)));
rel = heap_open(TypeRelationId, RowExclusiveLock);
tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
if (!HeapTupleIsValid(tup))
@@ -2596,7 +2913,8 @@ RenameConstraint(RenameStmt *stmt)
rename_constraint_internal(relid, typid,
stmt->subname,
stmt->newname,
- stmt->relation ? interpretInhOption(stmt->relation->inhOpt) : false, /* recursive? */
+ (stmt->relation &&
+ stmt->relation->inh), /* recursive? */
false, /* recursing? */
0 /* expected inhcount */ );
@@ -2689,10 +3007,7 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
*/
namestrcpy(&(relform->relname), newrelname);
- simple_heap_update(relrelation, &reltup->t_self, reltup);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(relrelation, reltup);
+ CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
InvalidOid, is_internal);
@@ -2869,9 +3184,7 @@ AlterTable(Oid relid, LOCKMODE lockmode, AlterTableStmt *stmt)
CheckTableNotInUse(rel, "ALTER TABLE");
- ATController(stmt,
- rel, stmt->cmds, interpretInhOption(stmt->relation->inhOpt),
- lockmode);
+ ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode);
}
/*
@@ -2998,7 +3311,7 @@ AlterTableGetLockLevel(List *cmds)
break;
/*
- * Changing foreign table options may affect optimisation.
+ * Changing foreign table options may affect optimization.
*/
case AT_GenericOptions:
case AT_AlterColumnGenericOptions:
@@ -3042,6 +3355,9 @@ AlterTableGetLockLevel(List *cmds)
case AT_DisableRowSecurity:
case AT_ForceRowSecurity:
case AT_NoForceRowSecurity:
+ case AT_AddIdentity:
+ case AT_DropIdentity:
+ case AT_SetIdentity:
cmd_lockmode = AccessExclusiveLock;
break;
@@ -3158,6 +3474,11 @@ AlterTableGetLockLevel(List *cmds)
cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
break;
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ cmd_lockmode = AccessExclusiveLock;
+ break;
+
default: /* oops */
elog(ERROR, "unrecognized alter table type: %d",
(int) cmd->subtype);
@@ -3345,14 +3666,28 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
/* No command-specific prep needed */
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
break;
+ case AT_AddIdentity:
+ ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+ pass = AT_PASS_ADD_CONSTR;
+ break;
+ case AT_DropIdentity:
+ ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+ pass = AT_PASS_DROP;
+ break;
+ case AT_SetIdentity:
+ ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+ pass = AT_PASS_COL_ATTRS;
+ break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+ ATPrepDropNotNull(rel, recurse, recursing);
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
/* No command-specific prep needed */
pass = AT_PASS_DROP;
break;
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+ ATPrepSetNotNull(rel, recurse, recursing);
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
/* No command-specific prep needed */
pass = AT_PASS_ADD_CONSTR;
@@ -3563,6 +3898,12 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_DISTRIB;
break;
#endif
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ ATSimplePermissions(rel, ATT_TABLE);
+ /* No command-specific prep needed */
+ pass = AT_PASS_MISC;
+ break;
default: /* oops */
elog(ERROR, "unrecognized alter table type: %d",
(int) cmd->subtype);
@@ -3633,7 +3974,14 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
{
AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
- if (tab->relkind == RELKIND_RELATION ||
+ /*
+ * If the table is source table of ATTACH PARTITION command, we did
+ * not modify anything about it that will change its toasting
+ * requirement, so no need to check.
+ */
+ if (((tab->relkind == RELKIND_RELATION ||
+ tab->relkind == RELKIND_PARTITIONED_TABLE) &&
+ tab->partition_constraint == NULL) ||
tab->relkind == RELKIND_MATVIEW)
AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
}
@@ -3665,6 +4013,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
break;
+ case AT_AddIdentity:
+ address = ATExecAddIdentity(rel, cmd->name, cmd->def, lockmode);
+ break;
+ case AT_SetIdentity:
+ address = ATExecSetIdentity(rel, cmd->name, cmd->def, lockmode);
+ break;
+ case AT_DropIdentity:
+ address = ATExecDropIdentity(rel, cmd->name, cmd->missing_ok, lockmode);
+ break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
address = ATExecDropNotNull(rel, cmd->name, lockmode);
break;
@@ -3882,7 +4239,6 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
case AT_GenericOptions:
ATExecGenericOptions(rel, (List *) cmd->def);
break;
-#ifdef PGXC
case AT_DistributeBy:
AtExecDistributeBy(rel, (DistributeBy *) cmd->def);
break;
@@ -3895,7 +4251,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
case AT_DeleteNodeList:
AtExecDeleteNode(rel, (List *) cmd->def);
break;
-#endif
+ case AT_AttachPartition:
+ ATExecAttachPartition(wqueue, rel, (PartitionCmd *) cmd->def);
+ break;
+ case AT_DetachPartition:
+ ATExecDetachPartition(rel, ((PartitionCmd *) cmd->def)->name);
+ break;
default: /* oops */
elog(ERROR, "unrecognized alter table type: %d",
(int) cmd->subtype);
@@ -3937,8 +4298,9 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode)
errmsg("Incompatible operation with data redistribution")));
#endif
- /* Foreign tables have no storage. */
- if (tab->relkind == RELKIND_FOREIGN_TABLE)
+ /* Foreign tables have no storage, nor do partitioned tables. */
+ if (tab->relkind == RELKIND_FOREIGN_TABLE ||
+ tab->relkind == RELKIND_PARTITIONED_TABLE)
continue;
/*
@@ -4091,7 +4453,8 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode)
* Test the current data within the table against new constraints
* generated by ALTER TABLE commands, but don't rebuild data.
*/
- if (tab->constraints != NIL || tab->new_notnull)
+ if (tab->constraints != NIL || tab->new_notnull ||
+ tab->partition_constraint != NULL)
ATRewriteTable(tab, InvalidOid, lockmode);
/*
@@ -4185,6 +4548,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
CommandId mycid;
BulkInsertState bistate;
int hi_options;
+ ExprState *partqualstate = NULL;
/*
* Open the relation(s). We have surely already locked the existing
@@ -4237,8 +4601,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
{
case CONSTR_CHECK:
needscan = true;
- con->qualstate = (List *)
- ExecPrepareExpr((Expr *) con->qual, estate);
+ con->qualstate = ExecPrepareExpr((Expr *) con->qual, estate);
break;
case CONSTR_FOREIGN:
/* Nothing to do here */
@@ -4249,6 +4612,13 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
}
}
+ /* Build expression execution states for partition check quals */
+ if (tab->partition_constraint)
+ {
+ needscan = true;
+ partqualstate = ExecPrepareExpr(tab->partition_constraint, estate);
+ }
+
foreach(l, tab->newvals)
{
NewColumnValue *ex = lfirst(l);
@@ -4378,8 +4748,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
values[ex->attnum - 1] = ExecEvalExpr(ex->exprstate,
econtext,
- &isnull[ex->attnum - 1],
- NULL);
+ &isnull[ex->attnum - 1]);
}
/*
@@ -4422,7 +4791,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
switch (con->contype)
{
case CONSTR_CHECK:
- if (!ExecQual(con->qualstate, econtext, true))
+ if (!ExecCheck(con->qualstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("check constraint \"%s\" is violated by some row",
@@ -4438,6 +4807,11 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
}
}
+ if (partqualstate && !ExecCheck(partqualstate, econtext))
+ ereport(ERROR,
+ (errcode(ERRCODE_CHECK_VIOLATION),
+ errmsg("partition constraint is violated by some row")));
+
/* Write the tuple out to the new relation */
if (newrel)
heap_insert(newrel, tuple, mycid, hi_options, bistate);
@@ -4518,6 +4892,7 @@ ATSimplePermissions(Relation rel, int allowed_targets)
switch (rel->rd_rel->relkind)
{
case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
actual_target = ATT_TABLE;
break;
case RELKIND_VIEW:
@@ -4634,7 +5009,8 @@ ATSimpleRecursion(List **wqueue, Relation rel,
*/
if (recurse &&
(rel->rd_rel->relkind == RELKIND_RELATION ||
- rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE))
+ rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
{
Oid relid = RelationGetRelid(rel);
ListCell *child;
@@ -4754,7 +5130,8 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation,
att = rel->rd_att->attrs[pg_depend->objsubid - 1];
if (rel->rd_rel->relkind == RELKIND_RELATION ||
- rel->rd_rel->relkind == RELKIND_MATVIEW)
+ rel->rd_rel->relkind == RELKIND_MATVIEW ||
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
if (origTypeName)
ereport(ERROR,
@@ -4955,6 +5332,11 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
if (recursing)
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+ if (rel->rd_rel->relispartition && !recursing)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot add column to a partition")));
+
attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
/*
@@ -5003,8 +5385,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Bump the existing child att's inhcount */
childatt->attinhcount++;
- simple_heap_update(attrdesc, &tuple->t_self, tuple);
- CatalogUpdateIndexes(attrdesc, tuple);
+ CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple);
heap_freetuple(tuple);
@@ -5025,6 +5406,17 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
elog(ERROR, "cache lookup failed for relation %u", myrelid);
relkind = ((Form_pg_class) GETSTRUCT(reltup))->relkind;
+ /*
+ * Cannot add identity column if table has children, because identity does
+ * not inherit. (Adding column and identity separately will work.)
+ */
+ if (colDef->identity &&
+ recurse &&
+ find_inheritance_children(myrelid, NoLock) != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot recursively add identity column to table that has child tables")));
+
/* skip if the name already exists and if_not_exists is true */
if (!check_for_column_name_collision(rel, colDef->colname, if_not_exists))
{
@@ -5077,6 +5469,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
attribute.attalign = tform->typalign;
attribute.attnotnull = colDef->is_not_null;
attribute.atthasdef = false;
+ attribute.attidentity = colDef->identity;
attribute.attisdropped = false;
attribute.attislocal = colDef->is_local;
attribute.attinhcount = colDef->inhcount;
@@ -5097,10 +5490,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
else
((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum;
- simple_heap_update(pgclass, &reltup->t_self, reltup);
-
- /* keep catalog indexes current */
- CatalogUpdateIndexes(pgclass, reltup);
+ CatalogTupleUpdate(pgclass, &reltup->t_self, reltup);
heap_freetuple(reltup);
@@ -5401,6 +5791,26 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC
* Return the address of the modified column. If the column was already
* nullable, InvalidObjectAddress is returned.
*/
+
+static void
+ATPrepDropNotNull(Relation rel, bool recurse, bool recursing)
+{
+ /*
+ * If the parent is a partitioned table, like check constraints, we do not
+ * support removing the NOT NULL while partitions exist.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ PartitionDesc partdesc = RelationGetPartitionDesc(rel);
+
+ Assert(partdesc != NULL);
+ if (partdesc->nparts > 0 && !recurse && !recursing)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot remove constraint from only the partitioned table when partitions exist"),
+ errhint("Do not specify the ONLY keyword.")));
+ }
+}
static ObjectAddress
ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
{
@@ -5433,6 +5843,12 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
errmsg("cannot alter system column \"%s\"",
colName)));
+ if (get_attidentity(RelationGetRelid(rel), attnum))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("column \"%s\" of relation \"%s\" is an identity column",
+ colName, RelationGetRelationName(rel))));
+
/*
* Check that the attribute is not in a primary key
*
@@ -5476,6 +5892,23 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
list_free(indexoidlist);
+ /* If rel is partition, shouldn't drop NOT NULL if parent has the same */
+ if (rel->rd_rel->relispartition)
+ {
+ Oid parentId = get_partition_parent(RelationGetRelid(rel));
+ Relation parent = heap_open(parentId, AccessShareLock);
+ TupleDesc tupDesc = RelationGetDescr(parent);
+ AttrNumber parent_attnum;
+
+ parent_attnum = get_attnum(parentId, colName);
+ if (tupDesc->attrs[parent_attnum - 1]->attnotnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("column \"%s\" is marked NOT NULL in parent table",
+ colName)));
+ heap_close(parent, AccessShareLock);
+ }
+
/*
* Okay, actually perform the catalog change ... if needed
*/
@@ -5483,10 +5916,7 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
{
((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = FALSE;
- simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(attr_rel, tuple);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
@@ -5508,6 +5938,27 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
* Return the address of the modified column. If the column was already NOT
* NULL, InvalidObjectAddress is returned.
*/
+
+static void
+ATPrepSetNotNull(Relation rel, bool recurse, bool recursing)
+{
+ /*
+ * If the parent is a partitioned table, like check constraints, NOT NULL
+ * constraints must be added to the child tables. Complain if requested
+ * otherwise and partitions exist.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ PartitionDesc partdesc = RelationGetPartitionDesc(rel);
+
+ if (partdesc && partdesc->nparts > 0 && !recurse && !recursing)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot add constraint to only the partitioned table when partitions exist"),
+ errhint("Do not specify the ONLY keyword.")));
+ }
+}
+
static ObjectAddress
ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
const char *colName, LOCKMODE lockmode)
@@ -5546,10 +5997,7 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
{
((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = TRUE;
- simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(attr_rel, tuple);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
/* Tell Phase 3 it needs to test the constraint */
tab->new_notnull = true;
@@ -5597,6 +6045,13 @@ ATExecColumnDefault(Relation rel, const char *colName,
errmsg("cannot alter system column \"%s\"",
colName)));
+ if (get_attidentity(RelationGetRelid(rel), attnum))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("column \"%s\" of relation \"%s\" is an identity column",
+ colName, RelationGetRelationName(rel)),
+ newDefault ? 0 : errhint("Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY instead.")));
+
/*
* Remove any old default for the column. We use RESTRICT here for
* safety, but at present we do not expect anything to depend on the
@@ -5632,6 +6087,236 @@ ATExecColumnDefault(Relation rel, const char *colName,
}
/*
+ * ALTER TABLE ALTER COLUMN ADD IDENTITY
+ *
+ * Return the address of the affected column.
+ */
+static ObjectAddress
+ATExecAddIdentity(Relation rel, const char *colName,
+ Node *def, LOCKMODE lockmode)
+{
+ Relation attrelation;
+ HeapTuple tuple;
+ Form_pg_attribute attTup;
+ AttrNumber attnum;
+ ObjectAddress address;
+ ColumnDef *cdef = castNode(ColumnDef, def);
+
+ attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colName, RelationGetRelationName(rel))));
+ attTup = (Form_pg_attribute) GETSTRUCT(tuple);
+ attnum = attTup->attnum;
+
+ /* Can't alter a system attribute */
+ if (attnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot alter system column \"%s\"",
+ colName)));
+
+ /*
+ * Creating a column as identity implies NOT NULL, so adding the identity
+ * to an existing column that is not NOT NULL would create a state that
+ * cannot be reproduced without contortions.
+ */
+ if (!attTup->attnotnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added",
+ colName, RelationGetRelationName(rel))));
+
+ if (attTup->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("column \"%s\" of relation \"%s\" is already an identity column",
+ colName, RelationGetRelationName(rel))));
+
+ if (attTup->atthasdef)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("column \"%s\" of relation \"%s\" already has a default value",
+ colName, RelationGetRelationName(rel))));
+
+ attTup->attidentity = cdef->identity;
+ CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
+
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attTup->attnum);
+ ObjectAddressSubSet(address, RelationRelationId,
+ RelationGetRelid(rel), attnum);
+ heap_freetuple(tuple);
+
+ heap_close(attrelation, RowExclusiveLock);
+
+ return address;
+}
+
+/*
+ * ALTER TABLE ALTER COLUMN SET { GENERATED or sequence options }
+ *
+ * Return the address of the affected column.
+ */
+static ObjectAddress
+ATExecSetIdentity(Relation rel, const char *colName, Node *def, LOCKMODE lockmode)
+{
+ ListCell *option;
+ DefElem *generatedEl = NULL;
+ HeapTuple tuple;
+ Form_pg_attribute attTup;
+ AttrNumber attnum;
+ Relation attrelation;
+ ObjectAddress address;
+
+ foreach(option, castNode(List, def))
+ {
+ DefElem *defel = lfirst_node(DefElem, option);
+
+ if (strcmp(defel->defname, "generated") == 0)
+ {
+ if (generatedEl)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ generatedEl = defel;
+ }
+ else
+ elog(ERROR, "option \"%s\" not recognized",
+ defel->defname);
+ }
+
+ /*
+ * Even if there is nothing to change here, we run all the checks. There
+ * will be a subsequent ALTER SEQUENCE that relies on everything being
+ * there.
+ */
+
+ attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colName, RelationGetRelationName(rel))));
+
+ attTup = (Form_pg_attribute) GETSTRUCT(tuple);
+ attnum = attTup->attnum;
+
+ if (attnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot alter system column \"%s\"",
+ colName)));
+
+ if (!attTup->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("column \"%s\" of relation \"%s\" is not an identity column",
+ colName, RelationGetRelationName(rel))));
+
+ if (generatedEl)
+ {
+ attTup->attidentity = defGetInt32(generatedEl);
+ CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
+
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attTup->attnum);
+ ObjectAddressSubSet(address, RelationRelationId,
+ RelationGetRelid(rel), attnum);
+ }
+ else
+ address = InvalidObjectAddress;
+
+ heap_freetuple(tuple);
+ heap_close(attrelation, RowExclusiveLock);
+
+ return address;
+}
+
+/*
+ * ALTER TABLE ALTER COLUMN DROP IDENTITY
+ *
+ * Return the address of the affected column.
+ */
+static ObjectAddress
+ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode)
+{
+ HeapTuple tuple;
+ Form_pg_attribute attTup;
+ AttrNumber attnum;
+ Relation attrelation;
+ ObjectAddress address;
+ Oid seqid;
+ ObjectAddress seqaddress;
+
+ attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colName, RelationGetRelationName(rel))));
+
+ attTup = (Form_pg_attribute) GETSTRUCT(tuple);
+ attnum = attTup->attnum;
+
+ if (attnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot alter system column \"%s\"",
+ colName)));
+
+ if (!attTup->attidentity)
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("column \"%s\" of relation \"%s\" is not an identity column",
+ colName, RelationGetRelationName(rel))));
+ else
+ {
+ ereport(NOTICE,
+ (errmsg("column \"%s\" of relation \"%s\" is not an identity column, skipping",
+ colName, RelationGetRelationName(rel))));
+ heap_freetuple(tuple);
+ heap_close(attrelation, RowExclusiveLock);
+ return InvalidObjectAddress;
+ }
+ }
+
+ attTup->attidentity = '\0';
+ CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
+
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attTup->attnum);
+ ObjectAddressSubSet(address, RelationRelationId,
+ RelationGetRelid(rel), attnum);
+ heap_freetuple(tuple);
+
+ heap_close(attrelation, RowExclusiveLock);
+
+ /* drop the internal sequence */
+ seqid = getOwnedSequence(RelationGetRelid(rel), attnum);
+ deleteDependencyRecordsForClass(RelationRelationId, seqid,
+ RelationRelationId, DEPENDENCY_INTERNAL);
+ CommandCounterIncrement();
+ seqaddress.classId = RelationRelationId;
+ seqaddress.objectId = seqid;
+ seqaddress.objectSubId = 0;
+ performDeletion(&seqaddress, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
+
+ return address;
+}
+
+/*
* ALTER TABLE ALTER COLUMN SET STATISTICS
*/
static void
@@ -5646,7 +6331,8 @@ ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE
if (rel->rd_rel->relkind != RELKIND_RELATION &&
rel->rd_rel->relkind != RELKIND_MATVIEW &&
rel->rd_rel->relkind != RELKIND_INDEX &&
- rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, materialized view, index, or foreign table",
@@ -5713,10 +6399,7 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE
attrtuple->attstattarget = newtarget;
- simple_heap_update(attrelation, &tuple->t_self, tuple);
-
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(attrelation, tuple);
+ CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel),
@@ -5769,12 +6452,11 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
colName)));
/* Generate new proposed attoptions (text array) */
- Assert(IsA(options, List));
datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
&isnull);
newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
- (List *) options, NULL, NULL, false,
- isReset);
+ castNode(List, options), NULL, NULL,
+ false, isReset);
/* Validate new options */
(void) attribute_reloptions(newOptions, true);
@@ -5790,8 +6472,7 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
repl_val, repl_null, repl_repl);
/* Update system catalog. */
- simple_heap_update(attrelation, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(attrelation, newtuple);
+ CatalogTupleUpdate(attrelation, &newtuple->t_self, newtuple);
InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel),
@@ -5874,10 +6555,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
errmsg("column data type %s can only have storage PLAIN",
format_type_be(attrtuple->atttypid))));
- simple_heap_update(attrelation, &tuple->t_self, tuple);
-
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(attrelation, tuple);
+ CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel),
@@ -5919,6 +6597,68 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
}
/*
+ * Checks if attnum is a partition attribute for rel
+ *
+ * Sets *used_in_expr if attnum is found to be referenced in some partition
+ * key expression. It's possible for a column to be both used directly and
+ * as part of an expression; if that happens, *used_in_expr may end up as
+ * either true or false. That's OK for current uses of this function, because
+ * *used_in_expr is only used to tailor the error message text.
+ */
+static bool
+is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr)
+{
+ PartitionKey key;
+ int partnatts;
+ List *partexprs;
+ ListCell *partexprs_item;
+ int i;
+
+ if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ return false;
+
+ key = RelationGetPartitionKey(rel);
+ partnatts = get_partition_natts(key);
+ partexprs = get_partition_exprs(key);
+
+ partexprs_item = list_head(partexprs);
+ for (i = 0; i < partnatts; i++)
+ {
+ AttrNumber partattno = get_partition_col_attnum(key, i);
+
+ if (partattno != 0)
+ {
+ if (attnum == partattno)
+ {
+ if (used_in_expr)
+ *used_in_expr = false;
+ return true;
+ }
+ }
+ else
+ {
+ /* Arbitrary expression */
+ Node *expr = (Node *) lfirst(partexprs_item);
+ Bitmapset *expr_attrs = NULL;
+
+ /* Find all attributes referenced */
+ pull_varattnos(expr, 1, &expr_attrs);
+ partexprs_item = lnext(partexprs_item);
+
+ if (bms_is_member(attnum - FirstLowInvalidHeapAttributeNumber,
+ expr_attrs))
+ {
+ if (used_in_expr)
+ *used_in_expr = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/*
* Return value is the address of the dropped column.
*/
static ObjectAddress
@@ -5932,6 +6672,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
AttrNumber attnum;
List *children;
ObjectAddress object;
+ bool is_expr;
/* At top level, permission check was done in ATPrepCmd, else do it */
if (recursing)
@@ -5976,6 +6717,19 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
errmsg("cannot drop inherited column \"%s\"",
colName)));
+ /* Don't drop columns used in the partition key */
+ if (is_partition_attr(rel, attnum, &is_expr))
+ {
+ if (!is_expr)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot drop column named in partition key")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot drop column referenced in partition key expression")));
+ }
+
ReleaseSysCache(tuple);
/*
@@ -5990,6 +6744,16 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
Relation attr_rel;
ListCell *child;
+ /*
+ * In case of a partitioned table, the column must be dropped from the
+ * partitions as well.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !recurse)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot drop column from only the partitioned table when partitions exist"),
+ errhint("Do not specify the ONLY keyword.")));
+
attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
foreach(child, children)
{
@@ -6030,10 +6794,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
/* Child column must survive my deletion */
childatt->attinhcount--;
- simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(attr_rel, tuple);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
/* Make update visible */
CommandCounterIncrement();
@@ -6049,10 +6810,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
childatt->attinhcount--;
childatt->attislocal = true;
- simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
- /* keep the system catalog indexes current */
- CatalogUpdateIndexes(attr_rel, tuple);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
/* Make update visible */
CommandCounterIncrement();
@@ -6096,10 +6854,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
tuple_class = (Form_pg_class) GETSTRUCT(tuple);
tuple_class->relhasoids = false;
- simple_heap_update(class_rel, &tuple->t_self, tuple);
-
- /* Keep the catalog indexes up to date */
- CatalogUpdateIndexes(class_rel, tuple);
+ CatalogTupleUpdate(class_rel, &tuple->t_self, tuple);
heap_close(class_rel, RowExclusiveLock);
@@ -6377,8 +7132,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
newcon->name = ccon->name;
newcon->contype = ccon->contype;
- /* ExecQual wants implicit-AND format */
- newcon->qual = (Node *) make_ands_implicit((Expr *) ccon->expr);
+ newcon->qual = ccon->expr;
tab->constraints = lappend(tab->constraints, newcon);
}
@@ -6420,7 +7174,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
/*
* Check if ONLY was specified with ALTER TABLE. If so, allow the
- * contraint creation only if there are no children currently. Error out
+ * constraint creation only if there are no children currently. Error out
* otherwise.
*/
if (!recurse && children != NIL)
@@ -6494,6 +7248,12 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
* Validity checks (permission checks wait till we have the column
* numbers)
*/
+ if (pkrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot reference partitioned table \"%s\"",
+ RelationGetRelationName(pkrel))));
+
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -6585,7 +7345,6 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
* Now we can check permissions.
*/
checkFkeyPermissions(pkrel, pkattnum, numpks);
- checkFkeyPermissions(rel, fkattnum, numfks);
/*
* Look up the equality operators to use in the constraint.
@@ -6887,8 +7646,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
bool found = false;
ObjectAddress address;
- Assert(IsA(cmd->def, Constraint));
- cmdcon = (Constraint *) cmd->def;
+ cmdcon = castNode(Constraint, cmd->def);
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
@@ -6943,8 +7701,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
copy_con->condeferrable = cmdcon->deferrable;
copy_con->condeferred = cmdcon->initdeferred;
- simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
- CatalogUpdateIndexes(conrel, copyTuple);
+ CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
InvokeObjectPostAlterHook(ConstraintRelationId,
HeapTupleGetOid(contuple), 0);
@@ -6967,20 +7724,37 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
{
+ Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple);
Form_pg_trigger copy_tg;
+ /*
+ * Remember OIDs of other relation(s) involved in FK constraint.
+ * (Note: it's likely that we could skip forcing a relcache inval
+ * for other rels that don't have a trigger whose properties
+ * change, but let's be conservative.)
+ */
+ if (tgform->tgrelid != RelationGetRelid(rel))
+ otherrelids = list_append_unique_oid(otherrelids,
+ tgform->tgrelid);
+
+ /*
+ * Update deferrability of RI_FKey_noaction_del,
+ * RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd
+ * triggers, but not others; see createForeignKeyTriggers and
+ * CreateFKCheckTrigger.
+ */
+ if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL &&
+ tgform->tgfoid != F_RI_FKEY_NOACTION_UPD &&
+ tgform->tgfoid != F_RI_FKEY_CHECK_INS &&
+ tgform->tgfoid != F_RI_FKEY_CHECK_UPD)
+ continue;
+
copyTuple = heap_copytuple(tgtuple);
copy_tg = (Form_pg_trigger) GETSTRUCT(copyTuple);
- /* Remember OIDs of other relation(s) involved in FK constraint */
- if (copy_tg->tgrelid != RelationGetRelid(rel))
- otherrelids = list_append_unique_oid(otherrelids,
- copy_tg->tgrelid);
-
copy_tg->tgdeferrable = cmdcon->deferrable;
copy_tg->tginitdeferred = cmdcon->initdeferred;
- simple_heap_update(tgrel, &copyTuple->t_self, copyTuple);
- CatalogUpdateIndexes(tgrel, copyTuple);
+ CatalogTupleUpdate(tgrel, &copyTuple->t_self, copyTuple);
InvokeObjectPostAlterHook(TriggerRelationId,
HeapTupleGetOid(tgtuple), 0);
@@ -7111,9 +7885,10 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
/*
* If we're recursing, the parent has already done this, so skip
- * it.
+ * it. Also, if the constraint is a NO INHERIT constraint, we
+ * shouldn't try to look for it in the children.
*/
- if (!recursing)
+ if (!recursing && !con->connoinherit)
children = find_all_inheritors(RelationGetRelid(rel),
lockmode, NULL);
@@ -7135,7 +7910,8 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
/*
* If we are told not to recurse, there had better not be any
- * child tables; else the addition would put them out of step.
+ * child tables, because we can't mark the constraint on the
+ * parent valid unless it is valid for all child tables.
*/
if (!recurse)
ereport(ERROR,
@@ -7165,8 +7941,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
copyTuple = heap_copytuple(tuple);
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
copy_con->convalidated = true;
- simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
- CatalogUpdateIndexes(conrel, copyTuple);
+ CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
InvokeObjectPostAlterHook(ConstraintRelationId,
HeapTupleGetOid(tuple), 0);
@@ -7498,7 +8273,12 @@ findFkeyCast(Oid targetTypeId, Oid sourceTypeId, Oid *funcid)
return ret;
}
-/* Permissions checks for ADD FOREIGN KEY */
+/*
+ * Permissions checks on the referenced table for ADD FOREIGN KEY
+ *
+ * Note: we have already checked that the user owns the referencing table,
+ * else we'd have failed much earlier; no additional checks are needed for it.
+ */
static void
checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
{
@@ -7535,7 +8315,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
Datum val;
char *conbin;
Expr *origexpr;
- List *exprstate;
+ ExprState *exprstate;
TupleDesc tupdesc;
HeapScanDesc scan;
HeapTuple tuple;
@@ -7546,8 +8326,12 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
bool isnull;
Snapshot snapshot;
- /* VALIDATE CONSTRAINT is a no-op for foreign tables */
- if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+ /*
+ * VALIDATE CONSTRAINT is a no-op for foreign tables and partitioned
+ * tables.
+ */
+ if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
return;
constrForm = (Form_pg_constraint) GETSTRUCT(constrtup);
@@ -7566,8 +8350,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
HeapTupleGetOid(constrtup));
conbin = TextDatumGetCString(val);
origexpr = (Expr *) stringToNode(conbin);
- exprstate = (List *)
- ExecPrepareExpr((Expr *) make_ands_implicit(origexpr), estate);
+ exprstate = ExecPrepareExpr(origexpr, estate);
econtext = GetPerTupleExprContext(estate);
tupdesc = RelationGetDescr(rel);
@@ -7587,7 +8370,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
{
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
- if (!ExecQual(exprstate, econtext, true))
+ if (!ExecCheck(exprstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("check constraint \"%s\" is violated by some row",
@@ -7648,7 +8431,7 @@ validateForeignKeyConstraint(char *conname,
trig.tgconstraint = constraintOid;
trig.tgdeferrable = FALSE;
trig.tginitdeferred = FALSE;
- /* we needn't fill in tgargs or tgqual */
+ /* we needn't fill in remaining fields */
/*
* See if we can do it with a single LEFT JOIN query. A FALSE result
@@ -7732,6 +8515,7 @@ CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint,
}
fk_trigger->columns = NIL;
+ fk_trigger->transitionRels = NIL;
fk_trigger->whenClause = NULL;
fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable;
@@ -7748,6 +8532,9 @@ CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint,
/*
* Create the triggers that implement an FK constraint.
+ *
+ * NB: if you change any trigger properties here, see also
+ * ATExecAlterConstraint.
*/
static void
createForeignKeyTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint,
@@ -7772,6 +8559,7 @@ createForeignKeyTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint,
fk_trigger->timing = TRIGGER_TYPE_AFTER;
fk_trigger->events = TRIGGER_TYPE_DELETE;
fk_trigger->columns = NIL;
+ fk_trigger->transitionRels = NIL;
fk_trigger->whenClause = NULL;
fk_trigger->isconstraint = true;
fk_trigger->constrrel = NULL;
@@ -7826,6 +8614,7 @@ createForeignKeyTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint,
fk_trigger->timing = TRIGGER_TYPE_AFTER;
fk_trigger->events = TRIGGER_TYPE_UPDATE;
fk_trigger->columns = NIL;
+ fk_trigger->transitionRels = NIL;
fk_trigger->whenClause = NULL;
fk_trigger->isconstraint = true;
fk_trigger->constrrel = NULL;
@@ -7935,6 +8724,24 @@ ATExecDropConstraint(Relation rel, const char *constrName,
is_no_inherit_constraint = con->connoinherit;
/*
+ * If it's a foreign-key constraint, we'd better lock the referenced
+ * table and check that that's not in use, just as we've already done
+ * for the constrained table (else we might, eg, be dropping a trigger
+ * that has unfired events). But we can/must skip that in the
+ * self-referential case.
+ */
+ if (con->contype == CONSTRAINT_FOREIGN &&
+ con->confrelid != RelationGetRelid(rel))
+ {
+ Relation frel;
+
+ /* Must match lock taken by RemoveTriggerById: */
+ frel = heap_open(con->confrelid, AccessExclusiveLock);
+ CheckTableNotInUse(frel, "ALTER TABLE");
+ heap_close(frel, NoLock);
+ }
+
+ /*
* Perform the actual constraint deletion
*/
conobj.classId = ConstraintRelationId;
@@ -7980,6 +8787,18 @@ ATExecDropConstraint(Relation rel, const char *constrName,
else
children = NIL;
+ /*
+ * For a partitioned table, if partitions exist and we are told not to
+ * recurse, it's a user error. It doesn't make sense to have a constraint
+ * be defined only on the parent, especially if it's a partitioned table.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
+ children != NIL && !recurse)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot remove constraint from only the partitioned table when partitions exist"),
+ errhint("Do not specify the ONLY keyword.")));
+
foreach(child, children)
{
Oid childrelid = lfirst_oid(child);
@@ -8044,8 +8863,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
{
/* Child constraint must survive my deletion */
con->coninhcount--;
- simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
- CatalogUpdateIndexes(conrel, copy_tuple);
+ CatalogTupleUpdate(conrel, &copy_tuple->t_self, copy_tuple);
/* Make update visible */
CommandCounterIncrement();
@@ -8061,8 +8879,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
con->coninhcount--;
con->conislocal = true;
- simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
- CatalogUpdateIndexes(conrel, copy_tuple);
+ CatalogTupleUpdate(conrel, &copy_tuple->t_self, copy_tuple);
/* Make update visible */
CommandCounterIncrement();
@@ -8098,6 +8915,7 @@ ATPrepAlterColumnType(List **wqueue,
NewColumnValue *newval;
ParseState *pstate = make_parsestate(NULL);
AclResult aclresult;
+ bool is_expr;
if (rel->rd_rel->reloftype && !recursing)
ereport(ERROR,
@@ -8128,6 +8946,19 @@ ATPrepAlterColumnType(List **wqueue,
errmsg("cannot alter inherited column \"%s\"",
colName)));
+ /* Don't alter columns used in the partition key */
+ if (is_partition_attr(rel, attnum, &is_expr))
+ {
+ if (!is_expr)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot alter type of column named in partition key")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot alter type of column referenced in partition key expression")));
+ }
+
/* Look up the target type */
typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod);
@@ -8143,7 +8974,8 @@ ATPrepAlterColumnType(List **wqueue,
list_make1_oid(rel->rd_rel->reltype),
false);
- if (tab->relkind == RELKIND_RELATION)
+ if (tab->relkind == RELKIND_RELATION ||
+ tab->relkind == RELKIND_PARTITIONED_TABLE)
{
/*
* Set up an expression to transform the old data value to the new
@@ -8227,12 +9059,69 @@ ATPrepAlterColumnType(List **wqueue,
ReleaseSysCache(tuple);
/*
- * The recursion case is handled by ATSimpleRecursion. However, if we are
- * told not to recurse, there had better not be any child tables; else the
- * alter would put them out of step.
+ * Recurse manually by queueing a new command for each child, if
+ * necessary. We cannot apply ATSimpleRecursion here because we need to
+ * remap attribute numbers in the USING expression, if any.
+ *
+ * If we are told not to recurse, there had better not be any child
+ * tables; else the alter would put them out of step.
*/
if (recurse)
- ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
+ {
+ Oid relid = RelationGetRelid(rel);
+ ListCell *child;
+ List *children;
+
+ children = find_all_inheritors(relid, lockmode, NULL);
+
+ /*
+ * find_all_inheritors does the recursive search of the inheritance
+ * hierarchy, so all we have to do is process all of the relids in the
+ * list that it returns.
+ */
+ foreach(child, children)
+ {
+ Oid childrelid = lfirst_oid(child);
+ Relation childrel;
+
+ if (childrelid == relid)
+ continue;
+
+ /* find_all_inheritors already got lock */
+ childrel = relation_open(childrelid, NoLock);
+ CheckTableNotInUse(childrel, "ALTER TABLE");
+
+ /*
+ * Remap the attribute numbers. If no USING expression was
+ * specified, there is no need for this step.
+ */
+ if (def->cooked_default)
+ {
+ AttrNumber *attmap;
+ bool found_whole_row;
+
+ /* create a copy to scribble on */
+ cmd = copyObject(cmd);
+
+ attmap = convert_tuples_by_name_map(RelationGetDescr(childrel),
+ RelationGetDescr(rel),
+ gettext_noop("could not convert row type"));
+ ((ColumnDef *) cmd->def)->cooked_default =
+ map_variable_attnos(def->cooked_default,
+ 1, 0,
+ attmap, RelationGetDescr(rel)->natts,
+ &found_whole_row);
+ if (found_whole_row)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot convert whole-row table reference"),
+ errdetail("USING expression contains a whole-row table reference.")));
+ pfree(attmap);
+ }
+ ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
+ relation_close(childrel, NoLock);
+ }
+ }
else if (!recursing &&
find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL)
ereport(ERROR,
@@ -8538,6 +9427,17 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
Assert(defaultexpr);
break;
+ case OCLASS_STATISTIC_EXT:
+
+ /*
+ * Give the extended-stats machinery a chance to fix anything
+ * that this column type change would break.
+ */
+ UpdateStatisticsForTypeChange(foundObject.objectId,
+ RelationGetRelid(rel), attnum,
+ attTup->atttypid, targettype);
+ break;
+
case OCLASS_PROC:
case OCLASS_TYPE:
case OCLASS_CAST:
@@ -8548,6 +9448,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
case OCLASS_OPERATOR:
case OCLASS_OPCLASS:
case OCLASS_OPFAMILY:
+ case OCLASS_AM:
case OCLASS_AMOP:
case OCLASS_AMPROC:
case OCLASS_SCHEMA:
@@ -8563,6 +9464,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
case OCLASS_USER_MAPPING:
case OCLASS_DEFACL:
case OCLASS_EXTENSION:
+ case OCLASS_EVENT_TRIGGER:
+ case OCLASS_PUBLICATION:
+ case OCLASS_PUBLICATION_REL:
+ case OCLASS_SUBSCRIPTION:
+ case OCLASS_TRANSFORM:
/*
* We don't expect any of these sorts of objects to depend on
@@ -8572,9 +9478,10 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
getObjectDescription(&foundObject));
break;
- default:
- elog(ERROR, "unrecognized object class: %u",
- foundObject.classId);
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
}
}
@@ -8614,7 +9521,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
foundDep->refobjid == attTup->attcollation))
elog(ERROR, "found unexpected dependency for column");
- simple_heap_delete(depRel, &depTup->t_self);
+ CatalogTupleDelete(depRel, &depTup->t_self);
}
systable_endscan(scan);
@@ -8636,10 +9543,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
ReleaseSysCache(typeTuple);
- simple_heap_update(attrelation, &heapTup->t_self, heapTup);
-
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(attrelation, heapTup);
+ CatalogTupleUpdate(attrelation, &heapTup->t_self, heapTup);
heap_close(attrelation, RowExclusiveLock);
@@ -8777,8 +9681,7 @@ ATExecAlterColumnGenericOptions(Relation rel,
newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel),
repl_val, repl_null, repl_repl);
- simple_heap_update(attrel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(attrel, newtuple);
+ CatalogTupleUpdate(attrel, &newtuple->t_self, newtuple);
InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel),
@@ -8914,7 +9817,8 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
querytree_list = NIL;
foreach(list_item, raw_parsetree_list)
{
- Node *stmt = (Node *) lfirst(list_item);
+ RawStmt *rs = lfirst_node(RawStmt, list_item);
+ Node *stmt = rs->stmt;
if (IsA(stmt, IndexStmt))
querytree_list = lappend(querytree_list,
@@ -8978,9 +9882,7 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
IndexStmt *indstmt;
Oid indoid;
- Assert(IsA(cmd->def, IndexStmt));
-
- indstmt = (IndexStmt *) cmd->def;
+ indstmt = castNode(IndexStmt, cmd->def);
indoid = get_constraint_index(oldId);
if (!rewrite)
@@ -9003,9 +9905,7 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
{
Constraint *con;
- Assert(IsA(cmd->def, Constraint));
-
- con = (Constraint *) cmd->def;
+ con = castNode(Constraint, cmd->def);
con->old_pktable_oid = refRelId;
/* rewriting neither side of a FK */
if (con->contype == CONSTR_FOREIGN &&
@@ -9054,11 +9954,9 @@ RebuildConstraintComment(AlteredTableInfo *tab, int pass, Oid objid,
/* Build node CommentStmt */
cmd = makeNode(CommentStmt);
cmd->objtype = OBJECT_TABCONSTRAINT;
- cmd->objname = list_make3(
- makeString(get_namespace_name(RelationGetNamespace(rel))),
- makeString(RelationGetRelationName(rel)),
- makeString(conname));
- cmd->objargs = NIL;
+ cmd->object = (Node *) list_make3(makeString(get_namespace_name(RelationGetNamespace(rel))),
+ makeString(pstrdup(RelationGetRelationName(rel))),
+ makeString(pstrdup(conname)));
cmd->comment = comment_str;
/* Append it to list of commands */
@@ -9173,6 +10071,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
case RELKIND_VIEW:
case RELKIND_MATVIEW:
case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
/* ok to change owner */
break;
case RELKIND_INDEX:
@@ -9203,7 +10102,8 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
Oid tableId;
int32 colId;
- if (sequenceIsOwned(relationOid, &tableId, &colId))
+ if (sequenceIsOwned(relationOid, DEPENDENCY_AUTO, &tableId, &colId) ||
+ sequenceIsOwned(relationOid, DEPENDENCY_INTERNAL, &tableId, &colId))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot change owner of sequence \"%s\"",
@@ -9296,8 +10196,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
- simple_heap_update(class_rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(class_rel, newtuple);
+ CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple);
heap_freetuple(newtuple);
@@ -9424,8 +10323,7 @@ change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
RelationGetDescr(attRelation),
repl_val, repl_null, repl_repl);
- simple_heap_update(attRelation, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(attRelation, newtuple);
+ CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
heap_freetuple(newtuple);
}
@@ -9476,7 +10374,7 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lock
if (depForm->refobjsubid == 0 ||
depForm->classid != RelationRelationId ||
depForm->objsubid != 0 ||
- depForm->deptype != DEPENDENCY_AUTO)
+ !(depForm->deptype == DEPENDENCY_AUTO || depForm->deptype == DEPENDENCY_INTERNAL))
continue;
/* Use relation_open just in case it's an index */
@@ -9634,6 +10532,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
case RELKIND_RELATION:
case RELKIND_TOASTVALUE:
case RELKIND_MATVIEW:
+ case RELKIND_PARTITIONED_TABLE:
(void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
break;
case RELKIND_VIEW:
@@ -9701,9 +10600,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
repl_val, repl_null, repl_repl);
- simple_heap_update(pgclass, &newtuple->t_self, newtuple);
-
- CatalogUpdateIndexes(pgclass, newtuple);
+ CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple);
InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
@@ -9760,9 +10657,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
repl_val, repl_null, repl_repl);
- simple_heap_update(pgclass, &newtuple->t_self, newtuple);
-
- CatalogUpdateIndexes(pgclass, newtuple);
+ CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple);
InvokeObjectPostAlterHookArg(RelationRelationId,
RelationGetRelid(toastrel), 0,
@@ -9923,8 +10818,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
/* update the pg_class row */
rd_rel->reltablespace = (newTableSpace == MyDatabaseTableSpace) ? InvalidOid : newTableSpace;
rd_rel->relfilenode = newrelfilenode;
- simple_heap_update(pg_class, &tuple->t_self, tuple);
- CatalogUpdateIndexes(pg_class, tuple);
+ CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
@@ -10054,7 +10948,8 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
/* Only move the object type requested */
if ((stmt->objtype == OBJECT_TABLE &&
- relForm->relkind != RELKIND_RELATION) ||
+ relForm->relkind != RELKIND_RELATION &&
+ relForm->relkind != RELKIND_PARTITIONED_TABLE) ||
(stmt->objtype == OBJECT_INDEX &&
relForm->relkind != RELKIND_INDEX) ||
(stmt->objtype == OBJECT_MATVIEW &&
@@ -10233,10 +11128,10 @@ ATExecEnableDisableTrigger(Relation rel, char *trigname,
* We just pass this off to rewriteDefine.c.
*/
static void
-ATExecEnableDisableRule(Relation rel, char *trigname,
+ATExecEnableDisableRule(Relation rel, char *rulename,
char fires_when, LOCKMODE lockmode)
{
- EnableDisableRule(rel, trigname, fires_when);
+ EnableDisableRule(rel, rulename, fires_when);
}
/*
@@ -10253,6 +11148,16 @@ ATPrepAddInherit(Relation child_rel)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot change inheritance of typed table")));
+
+ if (child_rel->rd_rel->relispartition)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot change inheritance of a partition")));
+
+ if (child_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot change inheritance of partitioned table")));
}
/*
@@ -10261,12 +11166,7 @@ ATPrepAddInherit(Relation child_rel)
static ObjectAddress
ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
{
- Relation parent_rel,
- catalogRelation;
- SysScanDesc scan;
- ScanKeyData key;
- HeapTuple inheritsTuple;
- int32 inhseqno;
+ Relation parent_rel;
List *children;
ObjectAddress address;
@@ -10304,37 +11204,18 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot inherit to temporary relation of another session")));
- /*
- * Check for duplicates in the list of parents, and determine the highest
- * inhseqno already present; we'll use the next one for the new parent.
- * (Note: get RowExclusiveLock because we will write pg_inherits below.)
- *
- * Note: we do not reject the case where the child already inherits from
- * the parent indirectly; CREATE TABLE doesn't reject comparable cases.
- */
- catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
- ScanKeyInit(&key,
- Anum_pg_inherits_inhrelid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(RelationGetRelid(child_rel)));
- scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
- true, NULL, 1, &key);
-
- /* inhseqno sequences start at 1 */
- inhseqno = 0;
- while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
- {
- Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inheritsTuple);
+ /* Prevent partitioned tables from becoming inheritance parents */
+ if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot inherit from partitioned table \"%s\"",
+ parent->relname)));
- if (inh->inhparent == RelationGetRelid(parent_rel))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_TABLE),
- errmsg("relation \"%s\" would be inherited from more than once",
- RelationGetRelationName(parent_rel))));
- if (inh->inhseqno > inhseqno)
- inhseqno = inh->inhseqno;
- }
- systable_endscan(scan);
+ /* Likewise for partitions */
+ if (parent_rel->rd_rel->relispartition)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot inherit from a partition")));
/*
* Prevent circularity by seeing if proposed parent inherits from child.
@@ -10369,6 +11250,70 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
RelationGetRelationName(child_rel),
RelationGetRelationName(parent_rel))));
+ /* OK to create inheritance */
+ CreateInheritance(child_rel, parent_rel);
+
+ ObjectAddressSet(address, RelationRelationId,
+ RelationGetRelid(parent_rel));
+
+ /* keep our lock on the parent relation until commit */
+ heap_close(parent_rel, NoLock);
+
+ return address;
+}
+
+/*
+ * CreateInheritance
+ * Catalog manipulation portion of creating inheritance between a child
+ * table and a parent table.
+ *
+ * Common to ATExecAddInherit() and ATExecAttachPartition().
+ */
+static void
+CreateInheritance(Relation child_rel, Relation parent_rel)
+{
+ Relation catalogRelation;
+ SysScanDesc scan;
+ ScanKeyData key;
+ HeapTuple inheritsTuple;
+ int32 inhseqno;
+
+ /* Note: get RowExclusiveLock because we will write pg_inherits below. */
+ catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
+
+ /*
+ * Check for duplicates in the list of parents, and determine the highest
+ * inhseqno already present; we'll use the next one for the new parent.
+ * Also, if proposed child is a partition, it cannot already be
+ * inheriting.
+ *
+ * Note: we do not reject the case where the child already inherits from
+ * the parent indirectly; CREATE TABLE doesn't reject comparable cases.
+ */
+ ScanKeyInit(&key,
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationGetRelid(child_rel)));
+ scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
+ true, NULL, 1, &key);
+
+ /* inhseqno sequences start at 1 */
+ inhseqno = 0;
+ while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
+ {
+ Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inheritsTuple);
+
+ if (inh->inhparent == RelationGetRelid(parent_rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" would be inherited from more than once",
+ RelationGetRelationName(parent_rel))));
+
+ if (inh->inhseqno > inhseqno)
+ inhseqno = inh->inhseqno;
+ }
+ systable_endscan(scan);
+
/* Match up the columns and bump attinhcount as needed */
MergeAttributesIntoExisting(child_rel, parent_rel);
@@ -10381,18 +11326,12 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
StoreCatalogInheritance1(RelationGetRelid(child_rel),
RelationGetRelid(parent_rel),
inhseqno + 1,
- catalogRelation);
-
- ObjectAddressSet(address, RelationRelationId,
- RelationGetRelid(parent_rel));
+ catalogRelation,
+ parent_rel->rd_rel->relkind ==
+ RELKIND_PARTITIONED_TABLE);
/* Now we're done with pg_inherits */
heap_close(catalogRelation, RowExclusiveLock);
-
- /* keep our lock on the parent relation until commit */
- heap_close(parent_rel, NoLock);
-
- return address;
}
/*
@@ -10443,7 +11382,7 @@ constraints_equivalent(HeapTuple a, HeapTuple b, TupleDesc tupleDesc)
* Check columns in child table match up with columns in parent, and increment
* their attinhcount.
*
- * Called by ATExecAddInherit
+ * Called by CreateInheritance
*
* Currently all parent columns must be found in child. Missing columns are an
* error. One day we might consider creating new columns like CREATE TABLE
@@ -10461,12 +11400,17 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
int parent_natts;
TupleDesc tupleDesc;
HeapTuple tuple;
+ bool child_is_partition = false;
attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
tupleDesc = RelationGetDescr(parent_rel);
parent_natts = tupleDesc->natts;
+ /* If parent_rel is a partitioned table, child_rel must be a partition */
+ if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ child_is_partition = true;
+
for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++)
{
Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
@@ -10514,8 +11458,19 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
* later on, this change will just roll back.)
*/
childatt->attinhcount++;
- simple_heap_update(attrrel, &tuple->t_self, tuple);
- CatalogUpdateIndexes(attrrel, tuple);
+
+ /*
+ * In case of partitions, we must enforce that value of attislocal
+ * is same in all partitions. (Note: there are only inherited
+ * attributes in partitions)
+ */
+ if (child_is_partition)
+ {
+ Assert(childatt->attinhcount == 1);
+ childatt->attislocal = false;
+ }
+
+ CatalogTupleUpdate(attrrel, &tuple->t_self, tuple);
heap_freetuple(tuple);
}
else
@@ -10527,6 +11482,45 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
}
}
+ /*
+ * If the parent has an OID column, so must the child, and we'd better
+ * update the child's attinhcount and attislocal the same as for normal
+ * columns. We needn't check data type or not-nullness though.
+ */
+ if (tupleDesc->tdhasoid)
+ {
+ /*
+ * Here we match by column number not name; the match *must* be the
+ * system column, not some random column named "oid".
+ */
+ tuple = SearchSysCacheCopy2(ATTNUM,
+ ObjectIdGetDatum(RelationGetRelid(child_rel)),
+ Int16GetDatum(ObjectIdAttributeNumber));
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ /* See comments above; these changes should be the same */
+ childatt->attinhcount++;
+
+ if (child_is_partition)
+ {
+ Assert(childatt->attinhcount == 1);
+ childatt->attislocal = false;
+ }
+
+ CatalogTupleUpdate(attrrel, &tuple->t_self, tuple);
+ heap_freetuple(tuple);
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("child table is missing column \"%s\"",
+ "oid")));
+ }
+ }
+
heap_close(attrrel, RowExclusiveLock);
}
@@ -10536,7 +11530,7 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
*
* Constraints that are marked ONLY in the parent are ignored.
*
- * Called by ATExecAddInherit
+ * Called by CreateInheritance
*
* Currently all constraints in parent must be present in the child. One day we
* may consider adding new constraints like CREATE TABLE does.
@@ -10555,10 +11549,15 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
SysScanDesc parent_scan;
ScanKeyData parent_key;
HeapTuple parent_tuple;
+ bool child_is_partition = false;
catalog_relation = heap_open(ConstraintRelationId, RowExclusiveLock);
tuple_desc = RelationGetDescr(catalog_relation);
+ /* If parent_rel is a partitioned table, child_rel must be a partition */
+ if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ child_is_partition = true;
+
/* Outer loop scans through the parent's constraint definitions */
ScanKeyInit(&parent_key,
Anum_pg_constraint_conrelid,
@@ -10609,7 +11608,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
RelationGetRelationName(child_rel),
NameStr(parent_con->conname))));
- /* If the constraint is "no inherit" then cannot merge */
+ /* If the child constraint is "no inherit" then cannot merge */
if (child_con->connoinherit)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -10618,14 +11617,36 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
RelationGetRelationName(child_rel))));
/*
+ * If the child constraint is "not valid" then cannot merge with a
+ * valid parent constraint
+ */
+ if (parent_con->convalidated && !child_con->convalidated)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"",
+ NameStr(child_con->conname),
+ RelationGetRelationName(child_rel))));
+
+ /*
* OK, bump the child constraint's inheritance count. (If we fail
* later on, this change will just roll back.)
*/
child_copy = heap_copytuple(child_tuple);
child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
child_con->coninhcount++;
- simple_heap_update(catalog_relation, &child_copy->t_self, child_copy);
- CatalogUpdateIndexes(catalog_relation, child_copy);
+
+ /*
+ * In case of partitions, an inherited constraint must be
+ * inherited only once since it cannot have multiple parents and
+ * it is never considered local.
+ */
+ if (child_is_partition)
+ {
+ Assert(child_con->coninhcount == 1);
+ child_con->conislocal = false;
+ }
+
+ CatalogTupleUpdate(catalog_relation, &child_copy->t_self, child_copy);
heap_freetuple(child_copy);
found = true;
@@ -10648,6 +11669,46 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
/*
* ALTER TABLE NO INHERIT
*
+ * Return value is the address of the relation that is no longer parent.
+ */
+static ObjectAddress
+ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
+{
+ ObjectAddress address;
+ Relation parent_rel;
+
+ if (rel->rd_rel->relispartition)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot change inheritance of a partition")));
+
+ /*
+ * AccessShareLock on the parent is probably enough, seeing that DROP
+ * TABLE doesn't lock parent tables at all. We need some lock since we'll
+ * be inspecting the parent's schema.
+ */
+ parent_rel = heap_openrv(parent, AccessShareLock);
+
+ /*
+ * We don't bother to check ownership of the parent table --- ownership of
+ * the child is presumed enough rights.
+ */
+
+ /* Off to RemoveInheritance() where most of the work happens */
+ RemoveInheritance(rel, parent_rel);
+
+ /* keep our lock on the parent relation until commit */
+ heap_close(parent_rel, NoLock);
+
+ ObjectAddressSet(address, RelationRelationId,
+ RelationGetRelid(parent_rel));
+
+ return address;
+}
+
+/*
+ * RemoveInheritance
+ *
* Drop a parent from the child's parents. This just adjusts the attinhcount
* and attislocal of the columns and removes the pg_inherit and pg_depend
* entries.
@@ -10661,13 +11722,11 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
* coninhcount and conislocal for inherited constraints are adjusted in
* exactly the same way.
*
- * Return value is the address of the relation that is no longer parent.
+ * Common to ATExecDropInherit() and ATExecDetachPartition().
*/
-static ObjectAddress
-ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
+static void
+RemoveInheritance(Relation child_rel, Relation parent_rel)
{
- Relation parent_rel;
- Oid parent_oid;
Relation catalogRelation;
SysScanDesc scan;
ScanKeyData key[3];
@@ -10676,19 +11735,11 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
constraintTuple;
List *connames;
bool found = false;
- ObjectAddress address;
-
- /*
- * AccessShareLock on the parent is probably enough, seeing that DROP
- * TABLE doesn't lock parent tables at all. We need some lock since we'll
- * be inspecting the parent's schema.
- */
- parent_rel = heap_openrv(parent, AccessShareLock);
+ bool child_is_partition = false;
- /*
- * We don't bother to check ownership of the parent table --- ownership of
- * the child is presumed enough rights.
- */
+ /* If parent_rel is a partitioned table, child_rel must be a partition */
+ if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ child_is_partition = true;
/*
* Find and destroy the pg_inherits entry linking the two, or error out if
@@ -10698,7 +11749,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
ScanKeyInit(&key[0],
Anum_pg_inherits_inhrelid,
BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(RelationGetRelid(rel)));
+ ObjectIdGetDatum(RelationGetRelid(child_rel)));
scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
true, NULL, 1, key);
@@ -10709,7 +11760,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
inhparent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
if (inhparent == RelationGetRelid(parent_rel))
{
- simple_heap_delete(catalogRelation, &inheritsTuple->t_self);
+ CatalogTupleDelete(catalogRelation, &inheritsTuple->t_self);
found = true;
break;
}
@@ -10719,11 +11770,20 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
heap_close(catalogRelation, RowExclusiveLock);
if (!found)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_TABLE),
+ {
+ if (child_is_partition)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("relation \"%s\" is not a partition of relation \"%s\"",
+ RelationGetRelationName(child_rel),
+ RelationGetRelationName(parent_rel))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation \"%s\" is not a parent of relation \"%s\"",
RelationGetRelationName(parent_rel),
- RelationGetRelationName(rel))));
+ RelationGetRelationName(child_rel))));
+ }
/*
* Search through child columns looking for ones matching parent rel
@@ -10732,7 +11792,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
ScanKeyInit(&key[0],
Anum_pg_attribute_attrelid,
BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(RelationGetRelid(rel)));
+ ObjectIdGetDatum(RelationGetRelid(child_rel)));
scan = systable_beginscan(catalogRelation, AttributeRelidNumIndexId,
true, NULL, 1, key);
while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
@@ -10756,8 +11816,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
if (copy_att->attinhcount == 0)
copy_att->attislocal = true;
- simple_heap_update(catalogRelation, &copyTuple->t_self, copyTuple);
- CatalogUpdateIndexes(catalogRelation, copyTuple);
+ CatalogTupleUpdate(catalogRelation, &copyTuple->t_self, copyTuple);
heap_freetuple(copyTuple);
}
}
@@ -10794,7 +11853,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
ScanKeyInit(&key[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(RelationGetRelid(rel)));
+ ObjectIdGetDatum(RelationGetRelid(child_rel)));
scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
true, NULL, 1, key);
@@ -10825,24 +11884,21 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
if (copy_con->coninhcount <= 0) /* shouldn't happen */
elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
- RelationGetRelid(rel), NameStr(copy_con->conname));
+ RelationGetRelid(child_rel), NameStr(copy_con->conname));
copy_con->coninhcount--;
if (copy_con->coninhcount == 0)
copy_con->conislocal = true;
- simple_heap_update(catalogRelation, &copyTuple->t_self, copyTuple);
- CatalogUpdateIndexes(catalogRelation, copyTuple);
+ CatalogTupleUpdate(catalogRelation, &copyTuple->t_self, copyTuple);
heap_freetuple(copyTuple);
}
}
- parent_oid = RelationGetRelid(parent_rel);
-
systable_endscan(scan);
heap_close(catalogRelation, RowExclusiveLock);
- drop_parent_dependency(RelationGetRelid(rel),
+ drop_parent_dependency(RelationGetRelid(child_rel),
RelationRelationId,
RelationGetRelid(parent_rel));
@@ -10852,15 +11908,8 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
* auxiliary_id argument.
*/
InvokeObjectPostAlterHookArg(InheritsRelationId,
- RelationGetRelid(rel), 0,
+ RelationGetRelid(child_rel), 0,
RelationGetRelid(parent_rel), false);
-
- /* keep our lock on the parent relation until commit */
- heap_close(parent_rel, NoLock);
-
- ObjectAddressSet(address, RelationRelationId, parent_oid);
-
- return address;
}
/*
@@ -10904,7 +11953,7 @@ drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
dep->refobjid == refobjid &&
dep->refobjsubid == 0 &&
dep->deptype == DEPENDENCY_NORMAL)
- simple_heap_delete(catalogRelation, &depTuple->t_self);
+ CatalogTupleDelete(catalogRelation, &depTuple->t_self);
}
systable_endscan(scan);
@@ -11041,8 +12090,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
if (!HeapTupleIsValid(classtuple))
elog(ERROR, "cache lookup failed for relation %u", relid);
((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid;
- simple_heap_update(relationRelation, &classtuple->t_self, classtuple);
- CatalogUpdateIndexes(relationRelation, classtuple);
+ CatalogTupleUpdate(relationRelation, &classtuple->t_self, classtuple);
InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
@@ -11086,8 +12134,7 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode)
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relid);
((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid;
- simple_heap_update(relationRelation, &tuple->t_self, tuple);
- CatalogUpdateIndexes(relationRelation, tuple);
+ CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
@@ -11127,8 +12174,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
if (pg_class_form->relreplident != ri_type)
{
pg_class_form->relreplident = ri_type;
- simple_heap_update(pg_class, &pg_class_tuple->t_self, pg_class_tuple);
- CatalogUpdateIndexes(pg_class, pg_class_tuple);
+ CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple);
}
heap_close(pg_class, RowExclusiveLock);
heap_freetuple(pg_class_tuple);
@@ -11187,8 +12233,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
if (dirty)
{
- simple_heap_update(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
- CatalogUpdateIndexes(pg_index, pg_index_tuple);
+ CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
InvalidOid, is_internal);
}
@@ -11337,10 +12382,7 @@ ATExecEnableRowSecurity(Relation rel)
elog(ERROR, "cache lookup failed for relation %u", relid);
((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = true;
- simple_heap_update(pg_class, &tuple->t_self, tuple);
-
- /* keep catalog indexes current */
- CatalogUpdateIndexes(pg_class, tuple);
+ CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
heap_close(pg_class, RowExclusiveLock);
heap_freetuple(tuple);
@@ -11364,10 +12406,7 @@ ATExecDisableRowSecurity(Relation rel)
elog(ERROR, "cache lookup failed for relation %u", relid);
((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = false;
- simple_heap_update(pg_class, &tuple->t_self, tuple);
-
- /* keep catalog indexes current */
- CatalogUpdateIndexes(pg_class, tuple);
+ CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
heap_close(pg_class, RowExclusiveLock);
heap_freetuple(tuple);
@@ -11393,10 +12432,7 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
elog(ERROR, "cache lookup failed for relation %u", relid);
((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls;
- simple_heap_update(pg_class, &tuple->t_self, tuple);
-
- /* keep catalog indexes current */
- CatalogUpdateIndexes(pg_class, tuple);
+ CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
heap_close(pg_class, RowExclusiveLock);
heap_freetuple(tuple);
@@ -11464,8 +12500,13 @@ ATExecGenericOptions(Relation rel, List *options)
tuple = heap_modify_tuple(tuple, RelationGetDescr(ftrel),
repl_val, repl_null, repl_repl);
- simple_heap_update(ftrel, &tuple->t_self, tuple);
- CatalogUpdateIndexes(ftrel, tuple);
+ CatalogTupleUpdate(ftrel, &tuple->t_self, tuple);
+
+ /*
+ * Invalidate relcache so that all sessions will refresh any cached plans
+ * that might depend on the old options.
+ */
+ CacheInvalidateRelcache(rel);
InvokeObjectPostAlterHook(ForeignTableRelationId,
RelationGetRelid(rel), 0);
@@ -11935,6 +12976,18 @@ ATPrepChangePersistence(Relation rel, bool toLogged)
}
/*
+ * Check that the table is not part any publication when changing to
+ * UNLOGGED as UNLOGGED tables can't be published.
+ */
+ if (!toLogged &&
+ list_length(GetRelationPublications(RelationGetRelid(rel))) > 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot change table \"%s\" to unlogged because it is part of a publication",
+ RelationGetRelationName(rel)),
+ errdetail("Unlogged relations cannot be replicated.")));
+
+ /*
* Check existing foreign key constraints to preserve the invariant that
* permanent tables cannot reference unlogged ones. Self-referencing
* foreign keys can safely be ignored.
@@ -12041,7 +13094,8 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema)
Oid tableId;
int32 colId;
- if (sequenceIsOwned(relid, &tableId, &colId))
+ if (sequenceIsOwned(relid, DEPENDENCY_AUTO, &tableId, &colId) ||
+ sequenceIsOwned(relid, DEPENDENCY_INTERNAL, &tableId, &colId))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot move an owned sequence into another schema"),
@@ -12097,7 +13151,8 @@ AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid,
/* Fix other dependent stuff */
if (rel->rd_rel->relkind == RELKIND_RELATION ||
- rel->rd_rel->relkind == RELKIND_MATVIEW)
+ rel->rd_rel->relkind == RELKIND_MATVIEW ||
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
@@ -12178,8 +13233,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
/* classTup is a copy, so OK to scribble on */
classForm->relnamespace = newNspOid;
- simple_heap_update(classRel, &classTup->t_self, classTup);
- CatalogUpdateIndexes(classRel, classTup);
+ CatalogTupleUpdate(classRel, &classTup->t_self, classTup);
/* Update dependency on schema if caller said so */
if (hasDependEntry &&
@@ -12246,7 +13300,7 @@ AlterIndexNamespaces(Relation classRel, Relation rel,
}
/*
- * Move all SERIAL-column sequences of the specified relation to another
+ * Move all identity and SERIAL-column sequences of the specified relation to another
* namespace.
*
* Note: we assume adequate permission checking was done by the caller,
@@ -12290,7 +13344,7 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
if (depForm->refobjsubid == 0 ||
depForm->classid != RelationRelationId ||
depForm->objsubid != 0 ||
- depForm->deptype != DEPENDENCY_AUTO)
+ !(depForm->deptype == DEPENDENCY_AUTO || depForm->deptype == DEPENDENCY_INTERNAL))
continue;
/* Use relation_open just in case it's an index */
@@ -12453,7 +13507,7 @@ PreCommit_on_commit_actions(void)
* This optimization does not work in XL since temporary tables
* are handled differently in XL.
*/
- if (MyXactAccessedTempRel)
+ if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPREL))
#endif
oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
break;
@@ -12604,7 +13658,7 @@ RangeVarCallbackOwnsTable(const RangeVar *relation,
if (!relkind)
return;
if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
- relkind != RELKIND_MATVIEW)
+ relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table or materialized view", relation->relname)));
@@ -12761,7 +13815,8 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
relkind != RELKIND_VIEW &&
relkind != RELKIND_MATVIEW &&
relkind != RELKIND_SEQUENCE &&
- relkind != RELKIND_FOREIGN_TABLE)
+ relkind != RELKIND_FOREIGN_TABLE &&
+ relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table",
@@ -12886,3 +13941,728 @@ DropTableThrowErrorExternal(RangeVar *relation, ObjectType removeType, bool miss
DropErrorMsgNonExistent(relation, relkind, missing_ok);
}
#endif
+
+/*
+ * Transform any expressions present in the partition key
+ *
+ * Returns a transformed PartitionSpec, as well as the strategy code
+ */
+static PartitionSpec *
+transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
+{
+ PartitionSpec *newspec;
+ ParseState *pstate;
+ RangeTblEntry *rte;
+ ListCell *l;
+
+ newspec = makeNode(PartitionSpec);
+
+ newspec->strategy = partspec->strategy;
+ newspec->partParams = NIL;
+ newspec->location = partspec->location;
+
+ /* Parse partitioning strategy name */
+ if (pg_strcasecmp(partspec->strategy, "list") == 0)
+ *strategy = PARTITION_STRATEGY_LIST;
+ else if (pg_strcasecmp(partspec->strategy, "range") == 0)
+ *strategy = PARTITION_STRATEGY_RANGE;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized partitioning strategy \"%s\"",
+ partspec->strategy)));
+
+ /* Check valid number of columns for strategy */
+ if (*strategy == PARTITION_STRATEGY_LIST &&
+ list_length(partspec->partParams) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot use \"list\" partition strategy with more than one column")));
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its sole
+ * rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+ rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true);
+ addRTEtoQuery(pstate, rte, true, true, true);
+
+ /* take care of any partition expressions */
+ foreach(l, partspec->partParams)
+ {
+ PartitionElem *pelem = castNode(PartitionElem, lfirst(l));
+ ListCell *lc;
+
+ /* Check for PARTITION BY ... (foo, foo) */
+ foreach(lc, newspec->partParams)
+ {
+ PartitionElem *pparam = castNode(PartitionElem, lfirst(lc));
+
+ if (pelem->name && pparam->name &&
+ strcmp(pelem->name, pparam->name) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_COLUMN),
+ errmsg("column \"%s\" appears more than once in partition key",
+ pelem->name),
+ parser_errposition(pstate, pelem->location)));
+ }
+
+ if (pelem->expr)
+ {
+ /* Copy, to avoid scribbling on the input */
+ pelem = copyObject(pelem);
+
+ /* Now do parse transformation of the expression */
+ pelem->expr = transformExpr(pstate, pelem->expr,
+ EXPR_KIND_PARTITION_EXPRESSION);
+
+ /* we have to fix its collations too */
+ assign_expr_collations(pstate, pelem->expr);
+ }
+
+ newspec->partParams = lappend(newspec->partParams, pelem);
+ }
+
+ return newspec;
+}
+
+/*
+ * Compute per-partition-column information from a list of PartitionElems.
+ * Expressions in the PartitionElems must be parse-analyzed already.
+ */
+static void
+ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
+ List **partexprs, Oid *partopclass, Oid *partcollation)
+{
+ int attn;
+ ListCell *lc;
+
+ attn = 0;
+ foreach(lc, partParams)
+ {
+ PartitionElem *pelem = castNode(PartitionElem, lfirst(lc));
+ Oid atttype;
+ Oid attcollation;
+
+ if (pelem->name != NULL)
+ {
+ /* Simple attribute reference */
+ HeapTuple atttuple;
+ Form_pg_attribute attform;
+
+ atttuple = SearchSysCacheAttName(RelationGetRelid(rel),
+ pelem->name);
+ if (!HeapTupleIsValid(atttuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" named in partition key does not exist",
+ pelem->name)));
+ attform = (Form_pg_attribute) GETSTRUCT(atttuple);
+
+ if (attform->attnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot use system column \"%s\" in partition key",
+ pelem->name)));
+
+ partattrs[attn] = attform->attnum;
+ atttype = attform->atttypid;
+ attcollation = attform->attcollation;
+ ReleaseSysCache(atttuple);
+ }
+ else
+ {
+ /* Expression */
+ Node *expr = pelem->expr;
+
+ Assert(expr != NULL);
+ atttype = exprType(expr);
+ attcollation = exprCollation(expr);
+
+ /*
+ * Strip any top-level COLLATE clause. This ensures that we treat
+ * "x COLLATE y" and "(x COLLATE y)" alike.
+ */
+ while (IsA(expr, CollateExpr))
+ expr = (Node *) ((CollateExpr *) expr)->arg;
+
+ if (IsA(expr, Var) &&
+ ((Var *) expr)->varattno > 0)
+ {
+ /*
+ * User wrote "(column)" or "(column COLLATE something)".
+ * Treat it like simple attribute anyway.
+ */
+ partattrs[attn] = ((Var *) expr)->varattno;
+ }
+ else
+ {
+ Bitmapset *expr_attrs = NULL;
+ int i;
+
+ partattrs[attn] = 0; /* marks the column as expression */
+ *partexprs = lappend(*partexprs, expr);
+
+ /*
+ * Try to simplify the expression before checking for
+ * mutability. The main practical value of doing it in this
+ * order is that an inline-able SQL-language function will be
+ * accepted if its expansion is immutable, whether or not the
+ * function itself is marked immutable.
+ *
+ * Note that expression_planner does not change the passed in
+ * expression destructively and we have already saved the
+ * expression to be stored into the catalog above.
+ */
+ expr = (Node *) expression_planner((Expr *) expr);
+
+ /*
+ * Partition expression cannot contain mutable functions,
+ * because a given row must always map to the same partition
+ * as long as there is no change in the partition boundary
+ * structure.
+ */
+ if (contain_mutable_functions(expr))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("functions in partition key expression must be marked IMMUTABLE")));
+
+ /*
+ * transformPartitionSpec() should have already rejected
+ * subqueries, aggregates, window functions, and SRFs, based
+ * on the EXPR_KIND_ for partition expressions.
+ */
+
+ /*
+ * Cannot have expressions containing whole-row references or
+ * system column references.
+ */
+ pull_varattnos(expr, 1, &expr_attrs);
+ if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
+ expr_attrs))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("partition key expressions cannot contain whole-row references")));
+ for (i = FirstLowInvalidHeapAttributeNumber; i < 0; i++)
+ {
+ if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
+ expr_attrs))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("partition key expressions cannot contain system column references")));
+ }
+
+ /*
+ * While it is not exactly *wrong* for a partition expression
+ * to be a constant, it seems better to reject such keys.
+ */
+ if (IsA(expr, Const))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot use constant expression as partition key")));
+ }
+ }
+
+ /*
+ * Apply collation override if any
+ */
+ if (pelem->collation)
+ attcollation = get_collation_oid(pelem->collation, false);
+
+ /*
+ * Check we have a collation iff it's a collatable type. The only
+ * expected failures here are (1) COLLATE applied to a noncollatable
+ * type, or (2) partition expression had an unresolved collation. But
+ * we might as well code this to be a complete consistency check.
+ */
+ if (type_is_collatable(atttype))
+ {
+ if (!OidIsValid(attcollation))
+ ereport(ERROR,
+ (errcode(ERRCODE_INDETERMINATE_COLLATION),
+ errmsg("could not determine which collation to use for partition expression"),
+ errhint("Use the COLLATE clause to set the collation explicitly.")));
+ }
+ else
+ {
+ if (OidIsValid(attcollation))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("collations are not supported by type %s",
+ format_type_be(atttype))));
+ }
+
+ partcollation[attn] = attcollation;
+
+ /*
+ * Identify a btree opclass to use. Currently, we use only btree
+ * operators, which seems enough for list and range partitioning.
+ */
+ if (!pelem->opclass)
+ {
+ partopclass[attn] = GetDefaultOpClass(atttype, BTREE_AM_OID);
+
+ if (!OidIsValid(partopclass[attn]))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("data type %s has no default btree operator class",
+ format_type_be(atttype)),
+ errhint("You must specify a btree operator class or define a default btree operator class for the data type.")));
+ }
+ else
+ partopclass[attn] = ResolveOpClass(pelem->opclass,
+ atttype,
+ "btree",
+ BTREE_AM_OID);
+
+ attn++;
+ }
+}
+
+/*
+ * ALTER TABLE <name> ATTACH PARTITION <partition-name> FOR VALUES
+ *
+ * Return the address of the newly attached partition.
+ */
+static ObjectAddress
+ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
+{
+ PartitionKey key = RelationGetPartitionKey(rel);
+ Relation attachRel,
+ catalog;
+ List *childrels;
+ TupleConstr *attachRel_constr;
+ List *partConstraint,
+ *existConstraint;
+ SysScanDesc scan;
+ ScanKeyData skey;
+ AttrNumber attno;
+ int natts;
+ TupleDesc tupleDesc;
+ bool skip_validate = false;
+ ObjectAddress address;
+
+ attachRel = heap_openrv(cmd->name, AccessExclusiveLock);
+
+ /*
+ * Must be owner of both parent and source table -- parent was checked by
+ * ATSimplePermissions call in ATPrepCmd
+ */
+ ATSimplePermissions(attachRel, ATT_TABLE | ATT_FOREIGN_TABLE);
+
+ /* A partition can only have one parent */
+ if (attachRel->rd_rel->relispartition)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is already a partition",
+ RelationGetRelationName(attachRel))));
+
+ if (OidIsValid(attachRel->rd_rel->reloftype))
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach a typed table as partition")));
+
+ /*
+ * Table being attached should not already be part of inheritance; either
+ * as a child table...
+ */
+ catalog = heap_open(InheritsRelationId, AccessShareLock);
+ ScanKeyInit(&skey,
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationGetRelid(attachRel)));
+ scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
+ NULL, 1, &skey);
+ if (HeapTupleIsValid(systable_getnext(scan)))
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach inheritance child as partition")));
+ systable_endscan(scan);
+
+ /* ...or as a parent table (except the case when it is partitioned) */
+ ScanKeyInit(&skey,
+ Anum_pg_inherits_inhparent,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationGetRelid(attachRel)));
+ scan = systable_beginscan(catalog, InheritsParentIndexId, true, NULL,
+ 1, &skey);
+ if (HeapTupleIsValid(systable_getnext(scan)) &&
+ attachRel->rd_rel->relkind == RELKIND_RELATION)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach inheritance parent as partition")));
+ systable_endscan(scan);
+ heap_close(catalog, AccessShareLock);
+
+ /*
+ * Prevent circularity by seeing if rel is a partition of attachRel. (In
+ * particular, this disallows making a rel a partition of itself.)
+ */
+ childrels = find_all_inheritors(RelationGetRelid(attachRel),
+ AccessShareLock, NULL);
+ if (list_member_oid(childrels, RelationGetRelid(rel)))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("circular inheritance not allowed"),
+ errdetail("\"%s\" is already a child of \"%s\".",
+ RelationGetRelationName(rel),
+ RelationGetRelationName(attachRel))));
+
+ /* Temp parent cannot have a partition that is itself not a temp */
+ if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
+ attachRel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach a permanent relation as partition of temporary relation \"%s\"",
+ RelationGetRelationName(rel))));
+
+ /* If the parent is temp, it must belong to this session */
+ if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
+ !rel->rd_islocaltemp)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach as partition of temporary relation of another session")));
+
+ /* Ditto for the partition */
+ if (attachRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
+ !attachRel->rd_islocaltemp)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach temporary relation of another session as partition")));
+
+ /* If parent has OIDs then child must have OIDs */
+ if (rel->rd_rel->relhasoids && !attachRel->rd_rel->relhasoids)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach table \"%s\" without OIDs as partition of"
+ " table \"%s\" with OIDs", RelationGetRelationName(attachRel),
+ RelationGetRelationName(rel))));
+
+ /* OTOH, if parent doesn't have them, do not allow in attachRel either */
+ if (attachRel->rd_rel->relhasoids && !rel->rd_rel->relhasoids)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot attach table \"%s\" with OIDs as partition of table"
+ " \"%s\" without OIDs", RelationGetRelationName(attachRel),
+ RelationGetRelationName(rel))));
+
+ /* Check if there are any columns in attachRel that aren't in the parent */
+ tupleDesc = RelationGetDescr(attachRel);
+ natts = tupleDesc->natts;
+ for (attno = 1; attno <= natts; attno++)
+ {
+ Form_pg_attribute attribute = tupleDesc->attrs[attno - 1];
+ char *attributeName = NameStr(attribute->attname);
+
+ /* Ignore dropped */
+ if (attribute->attisdropped)
+ continue;
+
+ /* Try to find the column in parent (matching on column name) */
+ if (!SearchSysCacheExists2(ATTNAME,
+ ObjectIdGetDatum(RelationGetRelid(rel)),
+ CStringGetDatum(attributeName)))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("table \"%s\" contains column \"%s\" not found in parent \"%s\"",
+ RelationGetRelationName(attachRel), attributeName,
+ RelationGetRelationName(rel)),
+ errdetail("New partition should contain only the columns present in parent.")));
+ }
+
+ /* OK to create inheritance. Rest of the checks performed there */
+ CreateInheritance(attachRel, rel);
+
+ /*
+ * Check that the new partition's bound is valid and does not overlap any
+ * of existing partitions of the parent - note that it does not return on
+ * error.
+ */
+ check_new_partition_bound(RelationGetRelationName(attachRel), rel,
+ cmd->bound);
+
+ /* Update the pg_class entry. */
+ StorePartitionBound(attachRel, rel, cmd->bound);
+
+ /*
+ * Generate partition constraint from the partition bound specification.
+ * If the parent itself is a partition, make sure to include its
+ * constraint as well.
+ */
+ partConstraint = list_concat(get_qual_from_partbound(attachRel, rel,
+ cmd->bound),
+ RelationGetPartitionQual(rel));
+ partConstraint = (List *) eval_const_expressions(NULL,
+ (Node *) partConstraint);
+ partConstraint = (List *) canonicalize_qual((Expr *) partConstraint);
+ partConstraint = list_make1(make_ands_explicit(partConstraint));
+
+ /*
+ * Check if we can do away with having to scan the table being attached to
+ * validate the partition constraint, by *proving* that the existing
+ * constraints of the table *imply* the partition predicate. We include
+ * the table's check constraints and NOT NULL constraints in the list of
+ * clauses passed to predicate_implied_by().
+ *
+ * There is a case in which we cannot rely on just the result of the
+ * proof.
+ */
+ attachRel_constr = tupleDesc->constr;
+ existConstraint = NIL;
+ if (attachRel_constr != NULL)
+ {
+ int num_check = attachRel_constr->num_check;
+ int i;
+ Bitmapset *not_null_attrs = NULL;
+ List *part_constr;
+ ListCell *lc;
+ bool partition_accepts_null = true;
+ int partnatts;
+
+ if (attachRel_constr->has_not_null)
+ {
+ int natts = attachRel->rd_att->natts;
+
+ for (i = 1; i <= natts; i++)
+ {
+ Form_pg_attribute att = attachRel->rd_att->attrs[i - 1];
+
+ if (att->attnotnull && !att->attisdropped)
+ {
+ NullTest *ntest = makeNode(NullTest);
+
+ ntest->arg = (Expr *) makeVar(1,
+ i,
+ att->atttypid,
+ att->atttypmod,
+ att->attcollation,
+ 0);
+ ntest->nulltesttype = IS_NOT_NULL;
+
+ /*
+ * argisrow=false is correct even for a composite column,
+ * because attnotnull does not represent a SQL-spec IS NOT
+ * NULL test in such a case, just IS DISTINCT FROM NULL.
+ */
+ ntest->argisrow = false;
+ ntest->location = -1;
+ existConstraint = lappend(existConstraint, ntest);
+ not_null_attrs = bms_add_member(not_null_attrs, i);
+ }
+ }
+ }
+
+ for (i = 0; i < num_check; i++)
+ {
+ Node *cexpr;
+
+ /*
+ * If this constraint hasn't been fully validated yet, we must
+ * ignore it here.
+ */
+ if (!attachRel_constr->check[i].ccvalid)
+ continue;
+
+ cexpr = stringToNode(attachRel_constr->check[i].ccbin);
+
+ /*
+ * Run each expression through const-simplification and
+ * canonicalization. It is necessary, because we will be
+ * comparing it to similarly-processed qual clauses, and may fail
+ * to detect valid matches without this.
+ */
+ cexpr = eval_const_expressions(NULL, cexpr);
+ cexpr = (Node *) canonicalize_qual((Expr *) cexpr);
+
+ existConstraint = list_concat(existConstraint,
+ make_ands_implicit((Expr *) cexpr));
+ }
+
+ existConstraint = list_make1(make_ands_explicit(existConstraint));
+
+ /* And away we go ... */
+ if (predicate_implied_by(partConstraint, existConstraint))
+ skip_validate = true;
+
+ /*
+ * We choose to err on the safer side, i.e., give up on skipping the
+ * validation scan, if the partition key column doesn't have the NOT
+ * NULL constraint and the table is to become a list partition that
+ * does not accept nulls. In this case, the partition predicate
+ * (partConstraint) does include an 'key IS NOT NULL' expression,
+ * however, because of the way predicate_implied_by_simple_clause() is
+ * designed to handle IS NOT NULL predicates in the absence of a IS
+ * NOT NULL clause, we cannot rely on just the above proof.
+ *
+ * That is not an issue in case of a range partition, because if there
+ * were no NOT NULL constraint defined on the key columns, an error
+ * would be thrown before we get here anyway. That is not true,
+ * however, if any of the partition keys is an expression, which is
+ * handled below.
+ */
+ part_constr = linitial(partConstraint);
+ part_constr = make_ands_implicit((Expr *) part_constr);
+
+ /*
+ * part_constr contains an IS NOT NULL expression, if this is a list
+ * partition that does not accept nulls (in fact, also if this is a
+ * range partition and some partition key is an expression, but we
+ * never skip validation in that case anyway; see below)
+ */
+ foreach(lc, part_constr)
+ {
+ Node *expr = lfirst(lc);
+
+ if (IsA(expr, NullTest) &&
+ ((NullTest *) expr)->nulltesttype == IS_NOT_NULL)
+ {
+ partition_accepts_null = false;
+ break;
+ }
+ }
+
+ partnatts = get_partition_natts(key);
+ for (i = 0; i < partnatts; i++)
+ {
+ AttrNumber partattno;
+
+ partattno = get_partition_col_attnum(key, i);
+
+ /* If partition key is an expression, must not skip validation */
+ if (!partition_accepts_null &&
+ (partattno == 0 ||
+ !bms_is_member(partattno, not_null_attrs)))
+ skip_validate = false;
+ }
+ }
+
+ /* It's safe to skip the validation scan after all */
+ if (skip_validate)
+ ereport(INFO,
+ (errmsg("partition constraint for table \"%s\" is implied by existing constraints",
+ RelationGetRelationName(attachRel))));
+
+ /*
+ * Set up to have the table be scanned to validate the partition
+ * constraint (see partConstraint above). If it's a partitioned table, we
+ * instead schedule its leaf partitions to be scanned.
+ */
+ if (!skip_validate)
+ {
+ List *all_parts;
+ ListCell *lc;
+
+ /* Take an exclusive lock on the partitions to be checked */
+ if (attachRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ all_parts = find_all_inheritors(RelationGetRelid(attachRel),
+ AccessExclusiveLock, NULL);
+ else
+ all_parts = list_make1_oid(RelationGetRelid(attachRel));
+
+ foreach(lc, all_parts)
+ {
+ AlteredTableInfo *tab;
+ Oid part_relid = lfirst_oid(lc);
+ Relation part_rel;
+ Expr *constr;
+
+ /* Lock already taken */
+ if (part_relid != RelationGetRelid(attachRel))
+ part_rel = heap_open(part_relid, NoLock);
+ else
+ part_rel = attachRel;
+
+ /*
+ * Skip if it's a partitioned table. Only RELKIND_RELATION
+ * relations (ie, leaf partitions) need to be scanned.
+ */
+ if (part_rel != attachRel &&
+ part_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ heap_close(part_rel, NoLock);
+ continue;
+ }
+
+ /* Grab a work queue entry */
+ tab = ATGetQueueEntry(wqueue, part_rel);
+
+ /* Adjust constraint to match this partition */
+ constr = linitial(partConstraint);
+ tab->partition_constraint = (Expr *)
+ map_partition_varattnos((List *) constr, 1,
+ part_rel, rel);
+ /* keep our lock until commit */
+ if (part_rel != attachRel)
+ heap_close(part_rel, NoLock);
+ }
+ }
+
+ ObjectAddressSet(address, RelationRelationId, RelationGetRelid(attachRel));
+
+ /* keep our lock until commit */
+ heap_close(attachRel, NoLock);
+
+ return address;
+}
+
+/*
+ * ALTER TABLE DETACH PARTITION
+ *
+ * Return the address of the relation that is no longer a partition of rel.
+ */
+static ObjectAddress
+ATExecDetachPartition(Relation rel, RangeVar *name)
+{
+ Relation partRel,
+ classRel;
+ HeapTuple tuple,
+ newtuple;
+ Datum new_val[Natts_pg_class];
+ bool isnull,
+ new_null[Natts_pg_class],
+ new_repl[Natts_pg_class];
+ ObjectAddress address;
+
+ partRel = heap_openrv(name, AccessShareLock);
+
+ /* All inheritance related checks are performed within the function */
+ RemoveInheritance(partRel, rel);
+
+ /* Update pg_class tuple */
+ classRel = heap_open(RelationRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(RelationGetRelid(partRel)));
+ Assert(((Form_pg_class) GETSTRUCT(tuple))->relispartition);
+
+ (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
+ &isnull);
+ Assert(!isnull);
+
+ /* Clear relpartbound and reset relispartition */
+ memset(new_val, 0, sizeof(new_val));
+ memset(new_null, false, sizeof(new_null));
+ memset(new_repl, false, sizeof(new_repl));
+ new_val[Anum_pg_class_relpartbound - 1] = (Datum) 0;
+ new_null[Anum_pg_class_relpartbound - 1] = true;
+ new_repl[Anum_pg_class_relpartbound - 1] = true;
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
+ new_val, new_null, new_repl);
+
+ ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = false;
+ CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
+ heap_freetuple(newtuple);
+ heap_close(classRel, RowExclusiveLock);
+
+ /*
+ * Invalidate the parent's relcache so that the partition is no longer
+ * included in its partition descriptor.
+ */
+ CacheInvalidateRelcache(rel);
+
+ ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel));
+
+ /* keep our lock until commit */
+ heap_close(partRel, NoLock);
+
+ return address;
+}
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index b43d61075a..dc4d3ab02d 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -35,7 +35,7 @@
* and munge the system catalogs of the new database.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -48,7 +48,6 @@
#include <unistd.h>
#include <dirent.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include "access/heapam.h"
@@ -87,6 +86,7 @@
#include "pgxc/nodemgr.h"
#include "pgxc/pgxc.h"
#endif
+#include "utils/varlena.h"
/* GUC variables */
@@ -357,9 +357,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
tuple = heap_form_tuple(rel->rd_att, values, nulls);
- tablespaceoid = simple_heap_insert(rel, tuple);
-
- CatalogUpdateIndexes(rel, tuple);
+ tablespaceoid = CatalogTupleInsert(rel, tuple);
heap_freetuple(tuple);
@@ -484,7 +482,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
/*
* Remove the pg_tablespace tuple (this will roll back if we fail below)
*/
- simple_heap_delete(rel, &tuple->t_self);
+ CatalogTupleDelete(rel, &tuple->t_self);
heap_endscan(scandesc);
@@ -1079,8 +1077,7 @@ RenameTableSpace(const char *oldname, const char *newname)
/* OK, update the entry */
namestrcpy(&(newform->spcname), newname);
- simple_heap_update(rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0);
@@ -1152,8 +1149,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
repl_null, repl_repl);
/* Update system catalog. */
- simple_heap_update(rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
InvokeObjectPostAlterHook(TableSpaceRelationId, HeapTupleGetOid(tup), 0);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 3dec336556..619d422e62 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -4,7 +4,7 @@
* PostgreSQL TRIGGERs support code.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -171,6 +171,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
Oid constrrelid = InvalidOid;
ObjectAddress myself,
referenced;
+ char *oldtablename = NULL;
+ char *newtablename = NULL;
if (OidIsValid(relOid))
rel = heap_open(relOid, ShareRowExclusiveLock);
@@ -181,7 +183,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
* Triggers must be on tables or views, and there are additional
* relation-type-specific restrictions.
*/
- if (rel->rd_rel->relkind == RELKIND_RELATION)
+ if (rel->rd_rel->relkind == RELKIND_RELATION ||
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
/* Tables can't have INSTEAD OF triggers */
if (stmt->timing != TRIGGER_TYPE_BEFORE &&
@@ -191,6 +194,13 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
errmsg("\"%s\" is a table",
RelationGetRelationName(rel)),
errdetail("Tables cannot have INSTEAD OF triggers.")));
+ /* Disallow ROW triggers on partitioned tables */
+ if (stmt->row && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is a partitioned table",
+ RelationGetRelationName(rel)),
+ errdetail("Partitioned tables cannot have ROW triggers.")));
}
else if (rel->rd_rel->relkind == RELKIND_VIEW)
{
@@ -317,6 +327,111 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
}
/*
+ * We don't yet support naming ROW transition variables, but the parser
+ * recognizes the syntax so we can give a nicer message here.
+ *
+ * Per standard, REFERENCING TABLE names are only allowed on AFTER
+ * triggers. Per standard, REFERENCING ROW names are not allowed with FOR
+ * EACH STATEMENT. Per standard, each OLD/NEW, ROW/TABLE permutation is
+ * only allowed once. Per standard, OLD may not be specified when
+ * creating a trigger only for INSERT, and NEW may not be specified when
+ * creating a trigger only for DELETE.
+ *
+ * Notice that the standard allows an AFTER ... FOR EACH ROW trigger to
+ * reference both ROW and TABLE transition data.
+ */
+ if (stmt->transitionRels != NIL)
+ {
+ List *varList = stmt->transitionRels;
+ ListCell *lc;
+
+ foreach(lc, varList)
+ {
+ TriggerTransition *tt = lfirst_node(TriggerTransition, lc);
+
+ if (!(tt->isTable))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("ROW variable naming in the REFERENCING clause is not supported"),
+ errhint("Use OLD TABLE or NEW TABLE for naming transition tables.")));
+
+ /*
+ * Because of the above test, we omit further ROW-related testing
+ * below. If we later allow naming OLD and NEW ROW variables,
+ * adjustments will be needed below.
+ */
+
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is a partitioned table",
+ RelationGetRelationName(rel)),
+ errdetail("Triggers on partitioned tables cannot have transition tables.")));
+
+ if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is a foreign table",
+ RelationGetRelationName(rel)),
+ errdetail("Triggers on foreign tables cannot have transition tables.")));
+
+ if (rel->rd_rel->relkind == RELKIND_VIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is a view",
+ RelationGetRelationName(rel)),
+ errdetail("Triggers on views cannot have transition tables.")));
+
+ if (stmt->timing != TRIGGER_TYPE_AFTER)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("transition table name can only be specified for an AFTER trigger")));
+
+ if (TRIGGER_FOR_TRUNCATE(tgtype))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("TRUNCATE triggers with transition tables are not supported")));
+
+ if (tt->isNew)
+ {
+ if (!(TRIGGER_FOR_INSERT(tgtype) ||
+ TRIGGER_FOR_UPDATE(tgtype)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
+
+ if (newtablename != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("NEW TABLE cannot be specified multiple times")));
+
+ newtablename = tt->name;
+ }
+ else
+ {
+ if (!(TRIGGER_FOR_DELETE(tgtype) ||
+ TRIGGER_FOR_UPDATE(tgtype)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
+
+ if (oldtablename != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("OLD TABLE cannot be specified multiple times")));
+
+ oldtablename = tt->name;
+ }
+ }
+
+ if (newtablename != NULL && oldtablename != NULL &&
+ strcmp(newtablename, oldtablename) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
+ }
+
+ /*
* Parse the WHEN clause, if any
*/
if (stmt->whenClause)
@@ -438,8 +553,9 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
if (funcrettype == OPAQUEOID)
{
ereport(WARNING,
- (errmsg("changing return type of function %s from \"opaque\" to \"trigger\"",
- NameListToString(stmt->funcname))));
+ (errmsg("changing return type of function %s from %s to %s",
+ NameListToString(stmt->funcname),
+ "opaque", "trigger")));
SetFunctionReturnType(funcoid, TRIGGEROID);
}
else
@@ -671,6 +787,17 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
else
nulls[Anum_pg_trigger_tgqual - 1] = true;
+ if (oldtablename)
+ values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein,
+ CStringGetDatum(oldtablename));
+ else
+ nulls[Anum_pg_trigger_tgoldtable - 1] = true;
+ if (newtablename)
+ values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein,
+ CStringGetDatum(newtablename));
+ else
+ nulls[Anum_pg_trigger_tgnewtable - 1] = true;
+
tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
/* force tuple to have the desired OID */
@@ -679,9 +806,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
/*
* Insert tuple into pg_trigger.
*/
- simple_heap_insert(tgrel, tuple);
-
- CatalogUpdateIndexes(tgrel, tuple);
+ CatalogTupleInsert(tgrel, tuple);
heap_freetuple(tuple);
heap_close(tgrel, RowExclusiveLock);
@@ -689,6 +814,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
+ if (oldtablename)
+ pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1]));
+ if (newtablename)
+ pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1]));
/*
* Update relation's pg_class entry. Crucial side-effect: other backends
@@ -704,9 +833,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
- simple_heap_update(pgrel, &tuple->t_self, tuple);
-
- CatalogUpdateIndexes(pgrel, tuple);
+ CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
heap_freetuple(tuple);
heap_close(pgrel, RowExclusiveLock);
@@ -979,6 +1106,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
AlterTableStmt *atstmt = makeNode(AlterTableStmt);
AlterTableCmd *atcmd = makeNode(AlterTableCmd);
Constraint *fkcon = makeNode(Constraint);
+ PlannedStmt *wrapper = makeNode(PlannedStmt);
ereport(NOTICE,
(errmsg("converting trigger group into constraint \"%s\" %s",
@@ -1068,14 +1196,19 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
fkcon->skip_validation = false;
fkcon->initially_valid = true;
+ /* finally, wrap it in a dummy PlannedStmt */
+ wrapper->commandType = CMD_UTILITY;
+ wrapper->canSetTag = false;
+ wrapper->utilityStmt = (Node *) atstmt;
+ wrapper->stmt_location = -1;
+ wrapper->stmt_len = -1;
+
/* ... and execute it */
- ProcessUtility((Node *) atstmt,
+ ProcessUtility(wrapper,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
- PROCESS_UTILITY_SUBCOMMAND, NULL,
+ PROCESS_UTILITY_SUBCOMMAND, NULL, NULL,
None_Receiver,
-#ifdef PGXC
false,
-#endif /* PGXC */
NULL);
/* Remove the matched item from the list */
@@ -1124,7 +1257,8 @@ RemoveTriggerById(Oid trigOid)
if (rel->rd_rel->relkind != RELKIND_RELATION &&
rel->rd_rel->relkind != RELKIND_VIEW &&
- rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, or foreign table",
@@ -1139,7 +1273,7 @@ RemoveTriggerById(Oid trigOid)
/*
* Delete the pg_trigger tuple.
*/
- simple_heap_delete(tgrel, &tup->t_self);
+ CatalogTupleDelete(tgrel, &tup->t_self);
systable_endscan(tgscan);
heap_close(tgrel, RowExclusiveLock);
@@ -1229,7 +1363,8 @@ RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
/* only tables and views can have triggers */
if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
- form->relkind != RELKIND_FOREIGN_TABLE)
+ form->relkind != RELKIND_FOREIGN_TABLE &&
+ form->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, or foreign table",
@@ -1340,10 +1475,7 @@ renametrig(RenameStmt *stmt)
namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
stmt->newname);
- simple_heap_update(tgrel, &tuple->t_self, tuple);
-
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(tgrel, tuple);
+ CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(TriggerRelationId,
HeapTupleGetOid(tuple), 0);
@@ -1456,10 +1588,7 @@ EnableDisableTrigger(Relation rel, const char *tgname,
newtrig->tgenabled = fires_when;
- simple_heap_update(tgrel, &newtup->t_self, newtup);
-
- /* Keep catalog indexes current */
- CatalogUpdateIndexes(tgrel, newtup);
+ CatalogTupleUpdate(tgrel, &newtup->t_self, newtup);
heap_freetuple(newtup);
@@ -1579,13 +1708,13 @@ RelationBuildTriggers(Relation relation)
bytea *val;
char *p;
- val = DatumGetByteaP(fastgetattr(htup,
- Anum_pg_trigger_tgargs,
- tgrel->rd_att, &isnull));
+ val = DatumGetByteaPP(fastgetattr(htup,
+ Anum_pg_trigger_tgargs,
+ tgrel->rd_att, &isnull));
if (isnull)
elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
RelationGetRelationName(relation));
- p = (char *) VARDATA(val);
+ p = (char *) VARDATA_ANY(val);
build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
for (i = 0; i < build->tgnargs; i++)
{
@@ -1595,6 +1724,23 @@ RelationBuildTriggers(Relation relation)
}
else
build->tgargs = NULL;
+
+ datum = fastgetattr(htup, Anum_pg_trigger_tgoldtable,
+ tgrel->rd_att, &isnull);
+ if (!isnull)
+ build->tgoldtable =
+ DatumGetCString(DirectFunctionCall1(nameout, datum));
+ else
+ build->tgoldtable = NULL;
+
+ datum = fastgetattr(htup, Anum_pg_trigger_tgnewtable,
+ tgrel->rd_att, &isnull);
+ if (!isnull)
+ build->tgnewtable =
+ DatumGetCString(DirectFunctionCall1(nameout, datum));
+ else
+ build->tgnewtable = NULL;
+
datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
tgrel->rd_att, &isnull);
if (!isnull)
@@ -1691,6 +1837,19 @@ SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
trigdesc->trig_truncate_after_statement |=
TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
+
+ trigdesc->trig_insert_new_table |=
+ (TRIGGER_FOR_INSERT(tgtype) &&
+ TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
+ trigdesc->trig_update_old_table |=
+ (TRIGGER_FOR_UPDATE(tgtype) &&
+ TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
+ trigdesc->trig_update_new_table |=
+ (TRIGGER_FOR_UPDATE(tgtype) &&
+ TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
+ trigdesc->trig_delete_old_table |=
+ (TRIGGER_FOR_DELETE(tgtype) &&
+ TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
}
/*
@@ -1740,6 +1899,10 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
}
if (trigger->tgqual)
trigger->tgqual = pstrdup(trigger->tgqual);
+ if (trigger->tgoldtable)
+ trigger->tgoldtable = pstrdup(trigger->tgoldtable);
+ if (trigger->tgnewtable)
+ trigger->tgnewtable = pstrdup(trigger->tgnewtable);
trigger++;
}
@@ -1772,6 +1935,10 @@ FreeTriggerDesc(TriggerDesc *trigdesc)
}
if (trigger->tgqual)
pfree(trigger->tgqual);
+ if (trigger->tgoldtable)
+ pfree(trigger->tgoldtable);
+ if (trigger->tgnewtable)
+ pfree(trigger->tgnewtable);
trigger++;
}
pfree(trigdesc->triggers);
@@ -1850,6 +2017,18 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
return false;
else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
return false;
+ if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL)
+ /* ok */ ;
+ else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL)
+ return false;
+ else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0)
+ return false;
+ if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL)
+ /* ok */ ;
+ else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL)
+ return false;
+ else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0)
+ return false;
}
}
else if (trigdesc2 != NULL)
@@ -1881,6 +2060,18 @@ ExecCallTriggerFunc(TriggerData *trigdata,
Datum result;
MemoryContext oldContext;
+ /*
+ * Protect against code paths that may fail to initialize transition table
+ * info.
+ */
+ Assert(((TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) ||
+ TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) ||
+ TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) &&
+ TRIGGER_FIRED_AFTER(trigdata->tg_event) &&
+ !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) &&
+ !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) ||
+ (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL));
+
finfo += tgindx;
/*
@@ -1971,6 +2162,8 @@ ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_trigtuple = NULL;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
@@ -2028,6 +2221,8 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
TRIGGER_EVENT_BEFORE;
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
{
@@ -2081,7 +2276,8 @@ ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
- if (trigdesc && trigdesc->trig_insert_after_row)
+ if (trigdesc &&
+ (trigdesc->trig_insert_after_row || trigdesc->trig_insert_new_table))
AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
true, NULL, trigtuple, recheckIndexes, NULL);
}
@@ -2103,6 +2299,8 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
TRIGGER_EVENT_INSTEAD;
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
{
@@ -2170,6 +2368,8 @@ ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_trigtuple = NULL;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
@@ -2241,6 +2441,8 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate,
TRIGGER_EVENT_BEFORE;
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
{
@@ -2284,7 +2486,8 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
- if (trigdesc && trigdesc->trig_delete_after_row)
+ if (trigdesc &&
+ (trigdesc->trig_delete_after_row || trigdesc->trig_delete_old_table))
{
HeapTuple trigtuple;
@@ -2321,6 +2524,8 @@ ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
TRIGGER_EVENT_INSTEAD;
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
{
@@ -2374,6 +2579,8 @@ ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_trigtuple = NULL;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
@@ -2475,6 +2682,8 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
TRIGGER_EVENT_ROW |
TRIGGER_EVENT_BEFORE;
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
updatedCols = GetUpdatedColumns(relinfo, estate);
for (i = 0; i < trigdesc->numtriggers; i++)
{
@@ -2539,7 +2748,8 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
- if (trigdesc && trigdesc->trig_update_after_row)
+ if (trigdesc && (trigdesc->trig_update_after_row ||
+ trigdesc->trig_update_old_table || trigdesc->trig_update_new_table))
{
HeapTuple trigtuple;
@@ -2578,6 +2788,8 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
TRIGGER_EVENT_ROW |
TRIGGER_EVENT_INSTEAD;
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
for (i = 0; i < trigdesc->numtriggers; i++)
{
Trigger *trigger = &trigdesc->triggers[i];
@@ -2646,6 +2858,8 @@ ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
LocTriggerData.tg_trigtuple = NULL;
LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_oldtable = NULL;
+ LocTriggerData.tg_newtable = NULL;
LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
LocTriggerData.tg_newtuplebuf = InvalidBuffer;
for (i = 0; i < trigdesc->numtriggers; i++)
@@ -2881,7 +3095,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
if (trigger->tgqual)
{
TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
- List **predicate;
+ ExprState **predicate;
ExprContext *econtext;
TupleTableSlot *oldslot = NULL;
TupleTableSlot *newslot = NULL;
@@ -2902,7 +3116,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
* nodetrees for it. Keep them in the per-query memory context so
* they'll survive throughout the query.
*/
- if (*predicate == NIL)
+ if (*predicate == NULL)
{
Node *tgqual;
@@ -2911,9 +3125,9 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
/* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0);
ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0);
- /* ExecQual wants implicit-AND form */
+ /* ExecPrepareQual wants implicit-AND form */
tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
- *predicate = (List *) ExecPrepareExpr((Expr *) tgqual, estate);
+ *predicate = ExecPrepareQual((List *) tgqual, estate);
MemoryContextSwitchTo(oldContext);
}
@@ -2961,7 +3175,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
*/
econtext->ecxt_innertuple = oldslot;
econtext->ecxt_outertuple = newslot;
- if (!ExecQual(*predicate, econtext, false))
+ if (!ExecQual(*predicate, econtext))
return false;
}
@@ -3177,8 +3391,11 @@ typedef struct AfterTriggerEventList
* fdw_tuplestores[query_depth] is a tuplestore containing the foreign tuples
* needed for the current query.
*
- * maxquerydepth is just the allocated length of query_stack and
- * fdw_tuplestores.
+ * old_tuplestores[query_depth] and new_tuplestores[query_depth] hold the
+ * transition relations for the current query.
+ *
+ * maxquerydepth is just the allocated length of query_stack and the
+ * tuplestores.
*
* state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
* state data; each subtransaction level that modifies that state first
@@ -3207,7 +3424,10 @@ typedef struct AfterTriggersData
AfterTriggerEventList events; /* deferred-event list */
int query_depth; /* current query list index */
AfterTriggerEventList *query_stack; /* events pending from each query */
- Tuplestorestate **fdw_tuplestores; /* foreign tuples from each query */
+ Tuplestorestate **fdw_tuplestores; /* foreign tuples for one row from
+ * each query */
+ Tuplestorestate **old_tuplestores; /* all old tuples from each query */
+ Tuplestorestate **new_tuplestores; /* all new tuples from each query */
int maxquerydepth; /* allocated len of above array */
MemoryContext event_cxt; /* memory context for events, if any */
@@ -3236,14 +3456,16 @@ static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
/*
- * Gets the current query fdw tuplestore and initializes it if necessary
+ * Gets a current query transition tuplestore and initializes it if necessary.
+ * This can be holding a single transition row tuple (in the case of an FDW)
+ * or a transition table (for an AFTER trigger).
*/
static Tuplestorestate *
-GetCurrentFDWTuplestore(void)
+GetTriggerTransitionTuplestore(Tuplestorestate **tss)
{
Tuplestorestate *ret;
- ret = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
+ ret = tss[afterTriggers.query_depth];
if (ret == NULL)
{
MemoryContext oldcxt;
@@ -3270,7 +3492,7 @@ GetCurrentFDWTuplestore(void)
CurrentResourceOwner = saveResourceOwner;
MemoryContextSwitchTo(oldcxt);
- afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = ret;
+ tss[afterTriggers.query_depth] = ret;
}
return ret;
@@ -3353,9 +3575,7 @@ afterTriggerAddEvent(AfterTriggerEventList *events,
afterTriggers.event_cxt =
AllocSetContextCreate(TopTransactionContext,
"AfterTriggerEvents",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* Chunk size starts at 1KB and is allowed to increase up to 1MB.
@@ -3570,7 +3790,9 @@ AfterTriggerExecute(AfterTriggerEvent event,
{
case AFTER_TRIGGER_FDW_FETCH:
{
- Tuplestorestate *fdw_tuplestore = GetCurrentFDWTuplestore();
+ Tuplestorestate *fdw_tuplestore =
+ GetTriggerTransitionTuplestore
+ (afterTriggers.fdw_tuplestores);
if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
trig_tuple_slot1))
@@ -3640,6 +3862,20 @@ AfterTriggerExecute(AfterTriggerEvent event,
}
/*
+ * Set up the tuplestore information.
+ */
+ if (LocTriggerData.tg_trigger->tgoldtable)
+ LocTriggerData.tg_oldtable =
+ GetTriggerTransitionTuplestore(afterTriggers.old_tuplestores);
+ else
+ LocTriggerData.tg_oldtable = NULL;
+ if (LocTriggerData.tg_trigger->tgnewtable)
+ LocTriggerData.tg_newtable =
+ GetTriggerTransitionTuplestore(afterTriggers.new_tuplestores);
+ else
+ LocTriggerData.tg_newtable = NULL;
+
+ /*
* Setup the remaining trigger information
*/
LocTriggerData.type = T_TriggerData;
@@ -3794,9 +4030,7 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
per_tuple_context =
AllocSetContextCreate(CurrentMemoryContext,
"AfterTriggerTupleContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
for_each_chunk(chunk, *events)
{
@@ -3889,16 +4123,7 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
if (local_estate)
{
- ListCell *l;
-
- foreach(l, estate->es_trig_target_relations)
- {
- ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
-
- /* Close indices and then the relation itself */
- ExecCloseIndices(resultRelInfo);
- heap_close(resultRelInfo->ri_RelationDesc, NoLock);
- }
+ ExecCleanUpTriggerState(estate);
FreeExecutorState(estate);
}
@@ -3930,6 +4155,8 @@ AfterTriggerBeginXact(void)
Assert(afterTriggers.state == NULL);
Assert(afterTriggers.query_stack == NULL);
Assert(afterTriggers.fdw_tuplestores == NULL);
+ Assert(afterTriggers.old_tuplestores == NULL);
+ Assert(afterTriggers.new_tuplestores == NULL);
Assert(afterTriggers.maxquerydepth == 0);
Assert(afterTriggers.event_cxt == NULL);
Assert(afterTriggers.events.head == NULL);
@@ -3998,6 +4225,8 @@ AfterTriggerEndQuery(EState *estate)
{
AfterTriggerEventList *events;
Tuplestorestate *fdw_tuplestore;
+ Tuplestorestate *old_tuplestore;
+ Tuplestorestate *new_tuplestore;
/* Must be inside a query, too */
Assert(afterTriggers.query_depth >= 0);
@@ -4056,6 +4285,18 @@ AfterTriggerEndQuery(EState *estate)
tuplestore_end(fdw_tuplestore);
afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
}
+ old_tuplestore = afterTriggers.old_tuplestores[afterTriggers.query_depth];
+ if (old_tuplestore)
+ {
+ tuplestore_end(old_tuplestore);
+ afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
+ }
+ new_tuplestore = afterTriggers.new_tuplestores[afterTriggers.query_depth];
+ if (new_tuplestore)
+ {
+ tuplestore_end(new_tuplestore);
+ afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
+ }
afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
afterTriggers.query_depth--;
@@ -4169,6 +4410,8 @@ AfterTriggerEndXact(bool isCommit)
*/
afterTriggers.query_stack = NULL;
afterTriggers.fdw_tuplestores = NULL;
+ afterTriggers.old_tuplestores = NULL;
+ afterTriggers.new_tuplestores = NULL;
afterTriggers.maxquerydepth = 0;
afterTriggers.state = NULL;
@@ -4301,6 +4544,18 @@ AfterTriggerEndSubXact(bool isCommit)
tuplestore_end(ts);
afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
}
+ ts = afterTriggers.old_tuplestores[afterTriggers.query_depth];
+ if (ts)
+ {
+ tuplestore_end(ts);
+ afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
+ }
+ ts = afterTriggers.new_tuplestores[afterTriggers.query_depth];
+ if (ts)
+ {
+ tuplestore_end(ts);
+ afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
+ }
afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
}
@@ -4380,6 +4635,12 @@ AfterTriggerEnlargeQueryState(void)
afterTriggers.fdw_tuplestores = (Tuplestorestate **)
MemoryContextAllocZero(TopTransactionContext,
new_alloc * sizeof(Tuplestorestate *));
+ afterTriggers.old_tuplestores = (Tuplestorestate **)
+ MemoryContextAllocZero(TopTransactionContext,
+ new_alloc * sizeof(Tuplestorestate *));
+ afterTriggers.new_tuplestores = (Tuplestorestate **)
+ MemoryContextAllocZero(TopTransactionContext,
+ new_alloc * sizeof(Tuplestorestate *));
afterTriggers.maxquerydepth = new_alloc;
}
else
@@ -4395,9 +4656,19 @@ AfterTriggerEnlargeQueryState(void)
afterTriggers.fdw_tuplestores = (Tuplestorestate **)
repalloc(afterTriggers.fdw_tuplestores,
new_alloc * sizeof(Tuplestorestate *));
+ afterTriggers.old_tuplestores = (Tuplestorestate **)
+ repalloc(afterTriggers.old_tuplestores,
+ new_alloc * sizeof(Tuplestorestate *));
+ afterTriggers.new_tuplestores = (Tuplestorestate **)
+ repalloc(afterTriggers.new_tuplestores,
+ new_alloc * sizeof(Tuplestorestate *));
/* Clear newly-allocated slots for subsequent lazy initialization. */
memset(afterTriggers.fdw_tuplestores + old_alloc,
0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
+ memset(afterTriggers.old_tuplestores + old_alloc,
+ 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
+ memset(afterTriggers.new_tuplestores + old_alloc,
+ 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
afterTriggers.maxquerydepth = new_alloc;
}
@@ -4850,7 +5121,14 @@ AfterTriggerPendingOnRel(Oid relid)
*
* NOTE: this is called whenever there are any triggers associated with
* the event (even if they are disabled). This function decides which
- * triggers actually need to be queued.
+ * triggers actually need to be queued. It is also called after each row,
+ * even if there are no triggers for that event, if there are any AFTER
+ * STATEMENT triggers for the statement which use transition tables, so that
+ * the transition tuplestores can be built.
+ *
+ * Transition tuplestores are built now, rather than when events are pulled
+ * off of the queue because AFTER ROW triggers are allowed to select from the
+ * transition tables for the statement.
* ----------
*/
static void
@@ -4882,6 +5160,46 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
AfterTriggerEnlargeQueryState();
/*
+ * If the relation has AFTER ... FOR EACH ROW triggers, capture rows into
+ * transition tuplestores for this depth.
+ */
+ if (row_trigger)
+ {
+ if ((event == TRIGGER_EVENT_DELETE &&
+ trigdesc->trig_delete_old_table) ||
+ (event == TRIGGER_EVENT_UPDATE &&
+ trigdesc->trig_update_old_table))
+ {
+ Tuplestorestate *old_tuplestore;
+
+ Assert(oldtup != NULL);
+ old_tuplestore =
+ GetTriggerTransitionTuplestore
+ (afterTriggers.old_tuplestores);
+ tuplestore_puttuple(old_tuplestore, oldtup);
+ }
+ if ((event == TRIGGER_EVENT_INSERT &&
+ trigdesc->trig_insert_new_table) ||
+ (event == TRIGGER_EVENT_UPDATE &&
+ trigdesc->trig_update_new_table))
+ {
+ Tuplestorestate *new_tuplestore;
+
+ Assert(newtup != NULL);
+ new_tuplestore =
+ GetTriggerTransitionTuplestore
+ (afterTriggers.new_tuplestores);
+ tuplestore_puttuple(new_tuplestore, newtup);
+ }
+
+ /* If transition tables are the only reason we're here, return. */
+ if ((event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
+ (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
+ (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row))
+ return;
+ }
+
+ /*
* Validate the event code and collect the associated tuple CTIDs.
*
* The event code will be used both as a bitmask and an array offset, so
@@ -4978,7 +5296,9 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
{
if (fdw_tuplestore == NULL)
{
- fdw_tuplestore = GetCurrentFDWTuplestore();
+ fdw_tuplestore =
+ GetTriggerTransitionTuplestore
+ (afterTriggers.fdw_tuplestores);
new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
}
else
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 69c038c52b..dfb95a1ed3 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -4,7 +4,7 @@
*
* Routines for tsearch manipulation commands
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -271,9 +271,7 @@ DefineTSParser(List *names, List *parameters)
tup = heap_form_tuple(prsRel->rd_att, values, nulls);
- prsOid = simple_heap_insert(prsRel, tup);
-
- CatalogUpdateIndexes(prsRel, tup);
+ prsOid = CatalogTupleInsert(prsRel, tup);
address = makeParserDependencies(tup);
@@ -303,7 +301,7 @@ RemoveTSParserById(Oid prsId)
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for text search parser %u", prsId);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -482,9 +480,7 @@ DefineTSDictionary(List *names, List *parameters)
tup = heap_form_tuple(dictRel->rd_att, values, nulls);
- dictOid = simple_heap_insert(dictRel, tup);
-
- CatalogUpdateIndexes(dictRel, tup);
+ dictOid = CatalogTupleInsert(dictRel, tup);
address = makeDictionaryDependencies(tup);
@@ -515,7 +511,7 @@ RemoveTSDictionaryById(Oid dictId)
elog(ERROR, "cache lookup failed for text search dictionary %u",
dictId);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -620,9 +616,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &newtup->t_self, newtup);
-
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &newtup->t_self, newtup);
InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
@@ -806,9 +800,7 @@ DefineTSTemplate(List *names, List *parameters)
tup = heap_form_tuple(tmplRel->rd_att, values, nulls);
- tmplOid = simple_heap_insert(tmplRel, tup);
-
- CatalogUpdateIndexes(tmplRel, tup);
+ tmplOid = CatalogTupleInsert(tmplRel, tup);
address = makeTSTemplateDependencies(tup);
@@ -839,7 +831,7 @@ RemoveTSTemplateById(Oid tmplId)
elog(ERROR, "cache lookup failed for text search template %u",
tmplId);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
@@ -1066,9 +1058,7 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
tup = heap_form_tuple(cfgRel->rd_att, values, nulls);
- cfgOid = simple_heap_insert(cfgRel, tup);
-
- CatalogUpdateIndexes(cfgRel, tup);
+ cfgOid = CatalogTupleInsert(cfgRel, tup);
if (OidIsValid(sourceOid))
{
@@ -1106,9 +1096,7 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
newmaptup = heap_form_tuple(mapRel->rd_att, mapvalues, mapnulls);
- simple_heap_insert(mapRel, newmaptup);
-
- CatalogUpdateIndexes(mapRel, newmaptup);
+ CatalogTupleInsert(mapRel, newmaptup);
heap_freetuple(newmaptup);
}
@@ -1151,7 +1139,7 @@ RemoveTSConfigurationById(Oid cfgId)
elog(ERROR, "cache lookup failed for text search dictionary %u",
cfgId);
- simple_heap_delete(relCfg, &tup->t_self);
+ CatalogTupleDelete(relCfg, &tup->t_self);
ReleaseSysCache(tup);
@@ -1170,7 +1158,7 @@ RemoveTSConfigurationById(Oid cfgId)
while (HeapTupleIsValid((tup = systable_getnext(scan))))
{
- simple_heap_delete(relMap, &tup->t_self);
+ CatalogTupleDelete(relMap, &tup->t_self);
}
systable_endscan(scan);
@@ -1215,10 +1203,10 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
/* Update dependencies */
makeConfigurationDependencies(tup, true, relMap);
- InvokeObjectPostAlterHook(TSConfigMapRelationId,
+ InvokeObjectPostAlterHook(TSConfigRelationId,
HeapTupleGetOid(tup), 0);
- ObjectAddressSet(address, TSConfigMapRelationId, cfgId);
+ ObjectAddressSet(address, TSConfigRelationId, cfgId);
heap_close(relMap, RowExclusiveLock);
@@ -1329,7 +1317,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
while (HeapTupleIsValid((maptup = systable_getnext(scan))))
{
- simple_heap_delete(relMap, &maptup->t_self);
+ CatalogTupleDelete(relMap, &maptup->t_self);
}
systable_endscan(scan);
@@ -1409,9 +1397,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
newtup = heap_modify_tuple(maptup,
RelationGetDescr(relMap),
repl_val, repl_null, repl_repl);
- simple_heap_update(relMap, &newtup->t_self, newtup);
-
- CatalogUpdateIndexes(relMap, newtup);
+ CatalogTupleUpdate(relMap, &newtup->t_self, newtup);
}
}
@@ -1436,8 +1422,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]);
tup = heap_form_tuple(relMap->rd_att, values, nulls);
- simple_heap_insert(relMap, tup);
- CatalogUpdateIndexes(relMap, tup);
+ CatalogTupleInsert(relMap, tup);
heap_freetuple(tup);
}
@@ -1487,7 +1472,7 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
while (HeapTupleIsValid((maptup = systable_getnext(scan))))
{
- simple_heap_delete(relMap, &maptup->t_self);
+ CatalogTupleDelete(relMap, &maptup->t_self);
found = true;
}
@@ -1576,9 +1561,9 @@ serialize_deflist(List *deflist)
List *
deserialize_deflist(Datum txt)
{
- text *in = DatumGetTextP(txt); /* in case it's toasted */
+ text *in = DatumGetTextPP(txt); /* in case it's toasted */
List *result = NIL;
- int len = VARSIZE(in) - VARHDRSZ;
+ int len = VARSIZE_ANY_EXHDR(in);
char *ptr,
*endptr,
*workspace,
@@ -1598,7 +1583,7 @@ deserialize_deflist(Datum txt)
ds_state state = CS_WAITKEY;
workspace = (char *) palloc(len + 1); /* certainly enough room */
- ptr = VARDATA(in);
+ ptr = VARDATA_ANY(in);
endptr = ptr + len;
for (; ptr < endptr; ptr++)
{
@@ -1700,7 +1685,7 @@ deserialize_deflist(Datum txt)
*wsptr++ = '\0';
result = lappend(result,
makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue))));
+ (Node *) makeString(pstrdup(startvalue)), -1));
state = CS_WAITKEY;
}
}
@@ -1732,7 +1717,7 @@ deserialize_deflist(Datum txt)
*wsptr++ = '\0';
result = lappend(result,
makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue))));
+ (Node *) makeString(pstrdup(startvalue)), -1));
state = CS_WAITKEY;
}
}
@@ -1747,7 +1732,7 @@ deserialize_deflist(Datum txt)
*wsptr++ = '\0';
result = lappend(result,
makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue))));
+ (Node *) makeString(pstrdup(startvalue)), -1));
state = CS_WAITKEY;
}
else
@@ -1766,7 +1751,7 @@ deserialize_deflist(Datum txt)
*wsptr++ = '\0';
result = lappend(result,
makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue))));
+ (Node *) makeString(pstrdup(startvalue)), -1));
}
else if (state != CS_WAITKEY)
ereport(ERROR,
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index ce04211067..e7ecc4ed7e 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3,7 +3,7 @@
* typecmds.c
* Routines for SQL commands that manipulate types (and domains).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -104,6 +104,8 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
Oid baseTypeOid,
int typMod, Constraint *constr,
char *domainName, ObjectAddress *constrAddr);
+static Node *replace_domain_constraint_value(ParseState *pstate,
+ ColumnRef *cref);
/*
@@ -111,7 +113,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
* Registers a new base type.
*/
ObjectAddress
-DefineType(List *names, List *parameters)
+DefineType(ParseState *pstate, List *names, List *parameters)
{
char *typeName;
Oid typeNamespace;
@@ -286,13 +288,15 @@ DefineType(List *names, List *parameters)
ereport(WARNING,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("type attribute \"%s\" not recognized",
- defel->defname)));
+ defel->defname),
+ parser_errposition(pstate, defel->location)));
continue;
}
if (*defelp != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
*defelp = defel;
}
@@ -693,7 +697,7 @@ RemoveTypeById(Oid typeOid)
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", typeOid);
- simple_heap_delete(relation, &tup->t_self);
+ CatalogTupleDelete(relation, &tup->t_self);
/*
* If it is an enum, delete the pg_enum entries too; we don't bother with
@@ -1221,7 +1225,7 @@ DefineEnum(CreateEnumStmt *stmt)
* Adds a new label to an existing enum.
*/
ObjectAddress
-AlterEnum(AlterEnumStmt *stmt, bool isTopLevel)
+AlterEnum(AlterEnumStmt *stmt)
{
Oid enum_type_oid;
TypeName *typename;
@@ -1236,39 +1240,28 @@ AlterEnum(AlterEnumStmt *stmt, bool isTopLevel)
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
- /*
- * Ordinarily we disallow adding values within transaction blocks, because
- * we can't cope with enum OID values getting into indexes and then having
- * their defining pg_enum entries go away. However, it's okay if the enum
- * type was created in the current transaction, since then there can be no
- * such indexes that wouldn't themselves go away on rollback. (We support
- * this case because pg_dump --binary-upgrade needs it.) We test this by
- * seeing if the pg_type row has xmin == current XID and is not
- * HEAP_UPDATED. If it is HEAP_UPDATED, we can't be sure whether the type
- * was created or only modified in this xact. So we are disallowing some
- * cases that could theoretically be safe; but fortunately pg_dump only
- * needs the simplest case.
- */
- if (HeapTupleHeaderGetXmin(tup->t_data) == GetCurrentTransactionId() &&
- !(tup->t_data->t_infomask & HEAP_UPDATED))
- /* safe to do inside transaction block */ ;
- else
- PreventTransactionChain(isTopLevel, "ALTER TYPE ... ADD");
-
/* Check it's an enum and check user has permission to ALTER the enum */
checkEnumOwner(tup);
- /* Add the new label */
- AddEnumLabel(enum_type_oid, stmt->newVal,
- stmt->newValNeighbor, stmt->newValIsAfter,
- stmt->skipIfExists);
+ ReleaseSysCache(tup);
+
+ if (stmt->oldVal)
+ {
+ /* Rename an existing label */
+ RenameEnumLabel(enum_type_oid, stmt->oldVal, stmt->newVal);
+ }
+ else
+ {
+ /* Add a new label */
+ AddEnumLabel(enum_type_oid, stmt->newVal,
+ stmt->newValNeighbor, stmt->newValIsAfter,
+ stmt->skipIfNewValExists);
+ }
InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
ObjectAddressSet(address, TypeRelationId, enum_type_oid);
- ReleaseSysCache(tup);
-
return address;
}
@@ -2116,7 +2109,8 @@ DefineCompositeType(RangeVar *typevar, List *coldeflist)
/*
* Finally create the relation. This also creates the type.
*/
- DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address);
+ DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address,
+ NULL);
return address;
}
@@ -2227,9 +2221,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
new_record, new_record_nulls,
new_record_repl);
- simple_heap_update(rel, &tup->t_self, newtuple);
-
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &tup->t_self, newtuple);
/* Rebuild dependencies */
GenerateTypeDependencies(typTup->typnamespace,
@@ -2366,9 +2358,7 @@ AlterDomainNotNull(List *names, bool notNull)
*/
typTup->typnotnull = notNull;
- simple_heap_update(typrel, &tup->t_self, tup);
-
- CatalogUpdateIndexes(typrel, tup);
+ CatalogTupleUpdate(typrel, &tup->t_self, tup);
InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
@@ -2668,8 +2658,7 @@ AlterDomainValidateConstraint(List *names, char *constrName)
copyTuple = heap_copytuple(tuple);
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
copy_con->convalidated = true;
- simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
- CatalogUpdateIndexes(conrel, copyTuple);
+ CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
InvokeObjectPostAlterHook(ConstraintRelationId,
HeapTupleGetOid(copyTuple), 0);
@@ -2741,7 +2730,7 @@ validateDomainConstraint(Oid domainoid, char *ccbin)
conResult = ExecEvalExprSwitchContext(exprstate,
econtext,
- &isNull, NULL);
+ &isNull);
if (!isNull && !DatumGetBool(conResult))
{
@@ -3030,7 +3019,8 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
domVal->collation = get_typcollation(baseTypeOid);
domVal->location = -1; /* will be set when/if used */
- pstate->p_value_substitute = (Node *) domVal;
+ pstate->p_pre_columnref_hook = replace_domain_constraint_value;
+ pstate->p_ref_hook_state = (void *) domVal;
expr = transformExpr(pstate, constr->raw_expr, EXPR_KIND_DOMAIN_CHECK);
@@ -3107,6 +3097,35 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
return ccbin;
}
+/* Parser pre_columnref_hook for domain CHECK constraint parsing */
+static Node *
+replace_domain_constraint_value(ParseState *pstate, ColumnRef *cref)
+{
+ /*
+ * Check for a reference to "value", and if that's what it is, replace
+ * with a CoerceToDomainValue as prepared for us by domainAddConstraint.
+ * (We handle VALUE as a name, not a keyword, to avoid breaking a lot of
+ * applications that have used VALUE as a column name in the past.)
+ */
+ if (list_length(cref->fields) == 1)
+ {
+ Node *field1 = (Node *) linitial(cref->fields);
+ char *colname;
+
+ Assert(IsA(field1, String));
+ colname = strVal(field1);
+ if (strcmp(colname, "value") == 0)
+ {
+ CoerceToDomainValue *domVal = copyObject(pstate->p_ref_hook_state);
+
+ /* Propagate location knowledge, if any */
+ domVal->location = cref->location;
+ return (Node *) domVal;
+ }
+ }
+ return NULL;
+}
+
/*
* Execute ALTER TYPE RENAME
@@ -3114,7 +3133,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
ObjectAddress
RenameType(RenameStmt *stmt)
{
- List *names = stmt->object;
+ List *names = castNode(List, stmt->object);
const char *newTypeName = stmt->newname;
TypeName *typename;
Oid typeOid;
@@ -3143,7 +3162,7 @@ RenameType(RenameStmt *stmt)
if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a domain",
+ errmsg("%s is not a domain",
format_type_be(typeOid))));
/*
@@ -3380,9 +3399,7 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
repl_repl);
- simple_heap_update(rel, &tup->t_self, tup);
-
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
/* If it has an array type, update that too */
if (OidIsValid(typTup->typarray))
@@ -3512,7 +3529,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
/* check for duplicate name (more friendly than unique-index failure) */
if (SearchSysCacheExists2(TYPENAMENSP,
- CStringGetDatum(NameStr(typform->typname)),
+ NameGetDatum(&typform->typname),
ObjectIdGetDatum(nspOid)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
@@ -3542,8 +3559,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
/* tup is a copy, so we can scribble directly on it */
typform->typnamespace = nspOid;
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
}
/*
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index b6ea95061d..10d6ba9e04 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -3,7 +3,7 @@
* user.c
* Commands for manipulating roles (formerly called users).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/commands/user.c
@@ -29,7 +29,7 @@
#include "commands/dbcommands.h"
#include "commands/seclabel.h"
#include "commands/user.h"
-#include "libpq/md5.h"
+#include "libpq/crypt.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
@@ -44,7 +44,7 @@ Oid binary_upgrade_next_pg_authid_oid = InvalidOid;
/* GUC parameter */
-extern bool Password_encryption;
+int Password_encryption = PASSWORD_TYPE_MD5;
/* Hook to check passwords in CreateRole() and AlterRole() */
check_password_hook_type check_password_hook = NULL;
@@ -69,7 +69,7 @@ have_createrole_privilege(void)
* CREATE ROLE
*/
Oid
-CreateRole(CreateRoleStmt *stmt)
+CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
{
Relation pg_authid_rel;
TupleDesc pg_authid_dsc;
@@ -80,8 +80,6 @@ CreateRole(CreateRoleStmt *stmt)
ListCell *item;
ListCell *option;
char *password = NULL; /* user password */
- bool encrypt_password = Password_encryption; /* encrypt password? */
- char encrypted_password[MD5_PASSWD_LEN + 1];
bool issuper = false; /* Make the user a superuser? */
bool inherit = true; /* Auto inherit privileges? */
bool createrole = false; /* Can this user create roles? */
@@ -129,19 +127,14 @@ CreateRole(CreateRoleStmt *stmt)
{
DefElem *defel = (DefElem *) lfirst(option);
- if (strcmp(defel->defname, "password") == 0 ||
- strcmp(defel->defname, "encryptedPassword") == 0 ||
- strcmp(defel->defname, "unencryptedPassword") == 0)
+ if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dpassword = defel;
- if (strcmp(defel->defname, "encryptedPassword") == 0)
- encrypt_password = true;
- else if (strcmp(defel->defname, "unencryptedPassword") == 0)
- encrypt_password = false;
}
else if (strcmp(defel->defname, "sysid") == 0)
{
@@ -153,7 +146,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dissuper)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dissuper = defel;
}
else if (strcmp(defel->defname, "inherit") == 0)
@@ -161,7 +155,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dinherit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dinherit = defel;
}
else if (strcmp(defel->defname, "createrole") == 0)
@@ -169,7 +164,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
@@ -177,7 +173,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dcreatedb)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dcreatedb = defel;
}
else if (strcmp(defel->defname, "canlogin") == 0)
@@ -185,7 +182,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dcanlogin = defel;
}
else if (strcmp(defel->defname, "isreplication") == 0)
@@ -193,7 +191,8 @@ CreateRole(CreateRoleStmt *stmt)
if (disreplication)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
disreplication = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
@@ -201,7 +200,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dconnlimit)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dconnlimit = defel;
}
else if (strcmp(defel->defname, "addroleto") == 0)
@@ -209,7 +209,8 @@ CreateRole(CreateRoleStmt *stmt)
if (daddroleto)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
daddroleto = defel;
}
else if (strcmp(defel->defname, "rolemembers") == 0)
@@ -217,7 +218,8 @@ CreateRole(CreateRoleStmt *stmt)
if (drolemembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
drolemembers = defel;
}
else if (strcmp(defel->defname, "adminmembers") == 0)
@@ -225,7 +227,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dadminmembers)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dadminmembers = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
@@ -233,7 +236,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dvalidUntil)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dvalidUntil = defel;
}
else if (strcmp(defel->defname, "bypassrls") == 0)
@@ -241,7 +245,8 @@ CreateRole(CreateRoleStmt *stmt)
if (dbypassRLS)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
dbypassRLS = defel;
}
else
@@ -357,7 +362,7 @@ CreateRole(CreateRoleStmt *stmt)
if (check_password_hook && password)
(*check_password_hook) (stmt->role,
password,
- isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
+ get_password_type(password),
validUntil_datum,
validUntil_null);
@@ -380,17 +385,13 @@ CreateRole(CreateRoleStmt *stmt)
if (password)
{
- if (!encrypt_password || isMD5(password))
- new_record[Anum_pg_authid_rolpassword - 1] =
- CStringGetTextDatum(password);
- else
- {
- if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
- encrypted_password))
- elog(ERROR, "password encryption failed");
- new_record[Anum_pg_authid_rolpassword - 1] =
- CStringGetTextDatum(encrypted_password);
- }
+ /* Encrypt the password to the requested format. */
+ char *shadow_pass;
+
+ shadow_pass = encrypt_password(Password_encryption, stmt->role,
+ password);
+ new_record[Anum_pg_authid_rolpassword - 1] =
+ CStringGetTextDatum(shadow_pass);
}
else
new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
@@ -420,8 +421,7 @@ CreateRole(CreateRoleStmt *stmt)
/*
* Insert new record in the pg_authid table
*/
- roleid = simple_heap_insert(pg_authid_rel, tuple);
- CatalogUpdateIndexes(pg_authid_rel, tuple);
+ roleid = CatalogTupleInsert(pg_authid_rel, tuple);
/*
* Advance command counter so we can see new record; else tests in
@@ -436,7 +436,7 @@ CreateRole(CreateRoleStmt *stmt)
foreach(item, addroleto)
{
RoleSpec *oldrole = lfirst(item);
- HeapTuple oldroletup = get_rolespec_tuple((Node *) oldrole);
+ HeapTuple oldroletup = get_rolespec_tuple(oldrole);
Oid oldroleid = HeapTupleGetOid(oldroletup);
char *oldrolename = NameStr(((Form_pg_authid) GETSTRUCT(oldroletup))->rolname);
@@ -492,8 +492,6 @@ AlterRole(AlterRoleStmt *stmt)
ListCell *option;
char *rolename = NULL;
char *password = NULL; /* user password */
- bool encrypt_password = Password_encryption; /* encrypt password? */
- char encrypted_password[MD5_PASSWD_LEN + 1];
int issuper = -1; /* Make the user a superuser? */
int inherit = -1; /* Auto inherit privileges? */
int createrole = -1; /* Can this user create roles? */
@@ -527,19 +525,13 @@ AlterRole(AlterRoleStmt *stmt)
{
DefElem *defel = (DefElem *) lfirst(option);
- if (strcmp(defel->defname, "password") == 0 ||
- strcmp(defel->defname, "encryptedPassword") == 0 ||
- strcmp(defel->defname, "unencryptedPassword") == 0)
+ if (strcmp(defel->defname, "password") == 0)
{
if (dpassword)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
dpassword = defel;
- if (strcmp(defel->defname, "encryptedPassword") == 0)
- encrypt_password = true;
- else if (strcmp(defel->defname, "unencryptedPassword") == 0)
- encrypt_password = false;
}
else if (strcmp(defel->defname, "superuser") == 0)
{
@@ -732,7 +724,7 @@ AlterRole(AlterRoleStmt *stmt)
if (check_password_hook && password)
(*check_password_hook) (rolename,
password,
- isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
+ get_password_type(password),
validUntil_datum,
validUntil_null);
@@ -791,17 +783,13 @@ AlterRole(AlterRoleStmt *stmt)
/* password */
if (password)
{
- if (!encrypt_password || isMD5(password))
- new_record[Anum_pg_authid_rolpassword - 1] =
- CStringGetTextDatum(password);
- else
- {
- if (!pg_md5_encrypt(password, rolename, strlen(rolename),
- encrypted_password))
- elog(ERROR, "password encryption failed");
- new_record[Anum_pg_authid_rolpassword - 1] =
- CStringGetTextDatum(encrypted_password);
- }
+ /* Encrypt the password to the requested format. */
+ char *shadow_pass;
+
+ shadow_pass = encrypt_password(Password_encryption, rolename,
+ password);
+ new_record[Anum_pg_authid_rolpassword - 1] =
+ CStringGetTextDatum(shadow_pass);
new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
}
@@ -825,10 +813,7 @@ AlterRole(AlterRoleStmt *stmt)
new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(pg_authid_rel, &tuple->t_self, new_tuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(pg_authid_rel, new_tuple);
+ CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple);
InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
@@ -1047,7 +1032,7 @@ DropRole(DropRoleStmt *stmt)
/*
* Remove the role from the pg_authid table
*/
- simple_heap_delete(pg_authid_rel, &tuple->t_self);
+ CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
ReleaseSysCache(tuple);
@@ -1067,7 +1052,7 @@ DropRole(DropRoleStmt *stmt)
while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
{
- simple_heap_delete(pg_auth_members_rel, &tmp_tuple->t_self);
+ CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
}
systable_endscan(sscan);
@@ -1082,7 +1067,7 @@ DropRole(DropRoleStmt *stmt)
while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
{
- simple_heap_delete(pg_auth_members_rel, &tmp_tuple->t_self);
+ CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
}
systable_endscan(sscan);
@@ -1219,7 +1204,7 @@ RenameRole(const char *oldname, const char *newname)
datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
- if (!isnull && isMD5(TextDatumGetCString(datum)))
+ if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
{
/* MD5 uses the username as salt, so just clear it on a rename */
repl_repl[Anum_pg_authid_rolpassword - 1] = true;
@@ -1230,9 +1215,7 @@ RenameRole(const char *oldname, const char *newname)
}
newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
- simple_heap_update(rel, &oldtuple->t_self, newtuple);
-
- CatalogUpdateIndexes(rel, newtuple);
+ CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
@@ -1383,7 +1366,7 @@ roleSpecsToIds(List *memberNames)
foreach(l, memberNames)
{
- Node *rolespec = (Node *) lfirst(l);
+ RoleSpec *rolespec = lfirst_node(RoleSpec, l);
Oid roleid;
roleid = get_rolespec_oid(rolespec, false);
@@ -1480,7 +1463,7 @@ AddRoleMems(const char *rolename, Oid roleid,
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
(errmsg("role \"%s\" is a member of role \"%s\"",
- rolename, get_rolespec_name((Node *) memberRole)))));
+ rolename, get_rolespec_name(memberRole)))));
/*
* Check if entry for this role/member already exists; if so, give
@@ -1495,7 +1478,7 @@ AddRoleMems(const char *rolename, Oid roleid,
{
ereport(NOTICE,
(errmsg("role \"%s\" is already a member of role \"%s\"",
- get_rolespec_name((Node *) memberRole), rolename)));
+ get_rolespec_name(memberRole), rolename)));
ReleaseSysCache(authmem_tuple);
continue;
}
@@ -1517,16 +1500,14 @@ AddRoleMems(const char *rolename, Oid roleid,
tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
- CatalogUpdateIndexes(pg_authmem_rel, tuple);
+ CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
ReleaseSysCache(authmem_tuple);
}
else
{
tuple = heap_form_tuple(pg_authmem_dsc,
new_record, new_record_nulls);
- simple_heap_insert(pg_authmem_rel, tuple);
- CatalogUpdateIndexes(pg_authmem_rel, tuple);
+ CatalogTupleInsert(pg_authmem_rel, tuple);
}
/* CCI after each change, in case there are duplicates in list */
@@ -1606,14 +1587,14 @@ DelRoleMems(const char *rolename, Oid roleid,
{
ereport(WARNING,
(errmsg("role \"%s\" is not a member of role \"%s\"",
- get_rolespec_name((Node *) memberRole), rolename)));
+ get_rolespec_name(memberRole), rolename)));
continue;
}
if (!admin_opt)
{
/* Remove the entry altogether */
- simple_heap_delete(pg_authmem_rel, &authmem_tuple->t_self);
+ CatalogTupleDelete(pg_authmem_rel, &authmem_tuple->t_self);
}
else
{
@@ -1634,8 +1615,7 @@ DelRoleMems(const char *rolename, Oid roleid,
tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
- CatalogUpdateIndexes(pg_authmem_rel, tuple);
+ CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
}
ReleaseSysCache(authmem_tuple);
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 4181dfd167..24edf48b68 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -10,7 +10,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -34,6 +34,7 @@
#include "access/xact.h"
#include "catalog/namespace.h"
#include "catalog/pg_database.h"
+#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_namespace.h"
#include "commands/cluster.h"
#include "commands/vacuum.h"
@@ -222,9 +223,7 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
*/
vac_context = AllocSetContextCreate(PortalContext,
"Vacuum",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* If caller didn't give us a buffer strategy object, make one in the
@@ -371,7 +370,7 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
{
/*
- * Update pg_database.datfrozenxid, and truncate pg_clog if possible.
+ * Update pg_database.datfrozenxid, and truncate pg_xact if possible.
* (autovacuum.c does this for itself.)
*/
vac_update_datfrozenxid();
@@ -409,6 +408,9 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
{
/* Process a specific relation */
Oid relid;
+ HeapTuple tuple;
+ Form_pg_class classForm;
+ bool include_parts;
/*
* Since we don't take a lock here, the relation might be gone, or the
@@ -421,9 +423,29 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
*/
relid = RangeVarGetRelid(vacrel, NoLock, false);
- /* Make a relation list entry for this guy */
+ /*
+ * To check whether the relation is a partitioned table, fetch its
+ * syscache entry.
+ */
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+ classForm = (Form_pg_class) GETSTRUCT(tuple);
+ include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE);
+ ReleaseSysCache(tuple);
+
+ /*
+ * Make relation list entries for this guy and its partitions, if any.
+ * Note that the list returned by find_all_inheritors() include the
+ * passed-in OID at its head. Also note that we did not request a
+ * lock to be taken to match what would be done otherwise.
+ */
oldcontext = MemoryContextSwitchTo(vac_context);
- oid_list = lappend_oid(oid_list, relid);
+ if (include_parts)
+ oid_list = list_concat(oid_list,
+ find_all_inheritors(relid, NoLock, NULL));
+ else
+ oid_list = lappend_oid(oid_list, relid);
MemoryContextSwitchTo(oldcontext);
}
else
@@ -444,8 +466,14 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
{
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
+ /*
+ * We include partitioned tables here; depending on which
+ * operation is to be performed, caller will decide whether to
+ * process or ignore them.
+ */
if (classForm->relkind != RELKIND_RELATION &&
- classForm->relkind != RELKIND_MATVIEW)
+ classForm->relkind != RELKIND_MATVIEW &&
+ classForm->relkind != RELKIND_PARTITIONED_TABLE)
continue;
/* Make a relation list entry for this guy */
@@ -512,7 +540,7 @@ vacuum_set_xid_limits(Relation rel,
* always an independent transaction.
*/
*oldestXmin =
- TransactionIdLimitedForOldSnapshots(GetOldestXmin(rel, true), rel);
+ TransactionIdLimitedForOldSnapshots(GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM), rel);
Assert(TransactionIdIsNormal(*oldestXmin));
@@ -899,7 +927,7 @@ vac_update_relstats(Relation relation,
* pg_class.relminmxid values.
*
* If we are able to advance either pg_database value, also try to
- * truncate pg_clog and pg_multixact.
+ * truncate pg_xact and pg_multixact.
*
* We violate transaction semantics here by overwriting the database's
* existing pg_database tuple with the new values. This is reasonably
@@ -928,7 +956,7 @@ vac_update_datfrozenxid(void)
* committed pg_class entries for new tables; see AddNewRelationTuple().
* So we cannot produce a wrong minimum by starting with this.
*/
- newFrozenXid = GetOldestXmin(NULL, true);
+ newFrozenXid = GetOldestXmin(NULL, PROCARRAY_FLAGS_VACUUM);
/*
* Similarly, initialize the MultiXact "min" with the value that would be
@@ -1048,7 +1076,7 @@ vac_update_datfrozenxid(void)
/*
* If we were able to advance datfrozenxid or datminmxid, see if we can
- * truncate pg_clog and/or pg_multixact. Also do it if the shared
+ * truncate pg_xact and/or pg_multixact. Also do it if the shared
* XID-wrap-limit info is stale, since this action will update that too.
*/
if (dirty || ForceTransactionIdLimitUpdate())
@@ -1061,7 +1089,7 @@ vac_update_datfrozenxid(void)
* vac_truncate_clog() -- attempt to truncate the commit log
*
* Scan pg_database to determine the system-wide oldest datfrozenxid,
- * and use it to truncate the transaction commit log (pg_clog).
+ * and use it to truncate the transaction commit log (pg_xact).
* Also update the XID wrap limit info maintained by varsup.c.
* Likewise for datminmxid.
*
@@ -1108,7 +1136,7 @@ vac_truncate_clog(TransactionId frozenXID,
* of the interlock against copying a DB containing an active backend.
* Hence the new entry will not reduce the minimum. Also, if two VACUUMs
* concurrently modify the datfrozenxid's of different databases, the
- * worst possible outcome is that pg_clog is not truncated as aggressively
+ * worst possible outcome is that pg_xact is not truncated as aggressively
* as it could be.
*/
relation = heap_open(DatabaseRelationId, AccessShareLock);
@@ -1178,9 +1206,18 @@ vac_truncate_clog(TransactionId frozenXID,
return;
/*
+ * Advance the oldest value for commit timestamps before truncating, so
+ * that if a user requests a timestamp for a transaction we're truncating
+ * away right after this point, they get NULL instead of an ugly "file not
+ * found" error from slru.c. This doesn't matter for xact/multixact
+ * because they are not subject to arbitrary lookups from users.
+ */
+ AdvanceOldestCommitTsXid(frozenXID);
+
+ /*
* Truncate CLOG, multixact and CommitTs to the oldest computed value.
*/
- TruncateCLOG(frozenXID);
+ TruncateCLOG(frozenXID, oldestxid_datoid);
TruncateCommitTs(frozenXID);
TruncateMultiXact(minMulti, minmulti_datoid);
@@ -1191,8 +1228,7 @@ vac_truncate_clog(TransactionId frozenXID,
* signalling twice?
*/
SetTransactionIdLimit(frozenXID, oldestxid_datoid);
- SetMultiXactIdLimit(minMulti, minmulti_datoid);
- AdvanceOldestCommitTsXid(frozenXID);
+ SetMultiXactIdLimit(minMulti, minmulti_datoid, false);
}
@@ -1355,7 +1391,8 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
*/
if (onerel->rd_rel->relkind != RELKIND_RELATION &&
onerel->rd_rel->relkind != RELKIND_MATVIEW &&
- onerel->rd_rel->relkind != RELKIND_TOASTVALUE)
+ onerel->rd_rel->relkind != RELKIND_TOASTVALUE &&
+ onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
{
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot vacuum non-tables or special system tables",
@@ -1382,6 +1419,21 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
}
/*
+ * Ignore partitioned tables as there is no work to be done. Since we
+ * release the lock here, it's possible that any partitions added from
+ * this point on will not get processed, but that seems harmless.
+ */
+ if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ relation_close(onerel, lmode);
+ PopActiveSnapshot();
+ CommitTransactionCommand();
+
+ /* It's OK for other commands to look at this table */
+ return true;
+ }
+
+ /*
* Get a session-level lock too. This will protect our access to the
* relation across multiple transactions, so that we can vacuum the
* relation's TOAST table (if any) secure in the knowledge that no one is
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 231e92d8e4..56356de670 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -24,7 +24,7 @@
* the TID array, just enough to hold as many heap tuples as fit on one page.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -98,6 +98,12 @@
*/
#define SKIP_PAGES_THRESHOLD ((BlockNumber) 32)
+/*
+ * Size of the prefetch window for lazy vacuum backwards truncation scan.
+ * Needs to be a power of 2.
+ */
+#define PREFETCH_SIZE ((BlockNumber) 32)
+
typedef struct LVRelStats
{
/* hasindex = true means two-pass strategy; false means one-pass */
@@ -108,7 +114,8 @@ typedef struct LVRelStats
BlockNumber scanned_pages; /* number of pages we examined */
BlockNumber pinskipped_pages; /* # of pages we skipped due to a pin */
BlockNumber frozenskipped_pages; /* # of frozen pages we skipped */
- double scanned_tuples; /* counts only tuples on scanned pages */
+ BlockNumber tupcount_pages; /* pages whose tuples we counted */
+ double scanned_tuples; /* counts only tuples on tupcount_pages */
double old_rel_tuples; /* previous value of pg_class.reltuples */
double new_rel_tuples; /* new estimated total # of tuples */
double new_dead_tuples; /* new estimated total # of dead tuples */
@@ -293,6 +300,10 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
* density") with nonzero relpages and reltuples=0 (which means "zero
* tuple density") unless there's some actual evidence for the latter.
*
+ * It's important that we use tupcount_pages and not scanned_pages for the
+ * check described above; scanned_pages counts pages where we could not
+ * get cleanup lock, and which were processed only for frozenxid purposes.
+ *
* We do update relallvisible even in the corner case, since if the table
* is all-visible we'd definitely like to know that. But clamp the value
* to be not more than what we're setting relpages to.
@@ -302,7 +313,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
*/
new_rel_pages = vacrelstats->rel_pages;
new_rel_tuples = vacrelstats->new_rel_tuples;
- if (vacrelstats->scanned_pages == 0 && new_rel_pages > 0)
+ if (vacrelstats->tupcount_pages == 0 && new_rel_pages > 0)
{
new_rel_pages = vacrelstats->old_rel_pages;
new_rel_tuples = vacrelstats->old_rel_tuples;
@@ -374,10 +385,11 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
vacrelstats->pinskipped_pages,
vacrelstats->frozenskipped_pages);
appendStringInfo(&buf,
- _("tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"),
+ _("tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable, oldest xmin: %u\n"),
vacrelstats->tuples_deleted,
vacrelstats->new_rel_tuples,
- vacrelstats->new_dead_tuples);
+ vacrelstats->new_dead_tuples,
+ OldestXmin);
appendStringInfo(&buf,
_("buffer usage: %d hits, %d misses, %d dirtied\n"),
VacuumPageHit,
@@ -489,6 +501,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
nblocks = RelationGetNumberOfBlocks(onerel);
vacrelstats->rel_pages = nblocks;
vacrelstats->scanned_pages = 0;
+ vacrelstats->tupcount_pages = 0;
vacrelstats->nonempty_pages = 0;
vacrelstats->latestRemovedXid = InvalidTransactionId;
@@ -811,6 +824,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
}
vacrelstats->scanned_pages++;
+ vacrelstats->tupcount_pages++;
page = BufferGetPage(buf);
@@ -1254,7 +1268,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
/* now we can compute the new value for pg_class.reltuples */
vacrelstats->new_rel_tuples = vac_estimate_reltuples(onerel, false,
nblocks,
- vacrelstats->scanned_pages,
+ vacrelstats->tupcount_pages,
num_tuples);
/*
@@ -1323,14 +1337,18 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
*/
initStringInfo(&buf);
appendStringInfo(&buf,
- _("%.0f dead row versions cannot be removed yet.\n"),
- nkeep);
+ _("%.0f dead row versions cannot be removed yet, oldest xmin: %u\n"),
+ nkeep, OldestXmin);
appendStringInfo(&buf, _("There were %.0f unused item pointers.\n"),
nunused);
- appendStringInfo(&buf, ngettext("Skipped %u page due to buffer pins.\n",
- "Skipped %u pages due to buffer pins.\n",
+ appendStringInfo(&buf, ngettext("Skipped %u page due to buffer pins, ",
+ "Skipped %u pages due to buffer pins, ",
vacrelstats->pinskipped_pages),
vacrelstats->pinskipped_pages);
+ appendStringInfo(&buf, ngettext("%u frozen page.\n",
+ "%u frozen pages.\n",
+ vacrelstats->frozenskipped_pages),
+ vacrelstats->frozenskipped_pages);
appendStringInfo(&buf, ngettext("%u page is entirely empty.\n",
"%u pages are entirely empty.\n",
empty_pages),
@@ -1618,7 +1636,7 @@ lazy_cleanup_index(Relation indrel,
ivinfo.index = indrel;
ivinfo.analyze_only = false;
- ivinfo.estimated_count = (vacrelstats->scanned_pages < vacrelstats->rel_pages);
+ ivinfo.estimated_count = (vacrelstats->tupcount_pages < vacrelstats->rel_pages);
ivinfo.message_level = elevel;
ivinfo.num_heap_tuples = vacrelstats->new_rel_tuples;
ivinfo.strategy = vac_strategy;
@@ -1747,7 +1765,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
return;
}
- pg_usleep(VACUUM_TRUNCATE_LOCK_WAIT_INTERVAL);
+ pg_usleep(VACUUM_TRUNCATE_LOCK_WAIT_INTERVAL * 1000L);
}
/*
@@ -1826,13 +1844,22 @@ static BlockNumber
count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
{
BlockNumber blkno;
+ BlockNumber prefetchedUntil;
instr_time starttime;
/* Initialize the starttime if we check for conflicting lock requests */
INSTR_TIME_SET_CURRENT(starttime);
- /* Strange coding of loop control is needed because blkno is unsigned */
+ /*
+ * Start checking blocks at what we believe relation end to be and move
+ * backwards. (Strange coding of loop control is needed because blkno is
+ * unsigned.) To make the scan faster, we prefetch a few blocks at a time
+ * in forward direction, so that OS-level readahead can kick in.
+ */
blkno = vacrelstats->rel_pages;
+ StaticAssertStmt((PREFETCH_SIZE & (PREFETCH_SIZE - 1)) == 0,
+ "prefetch size must be power of 2");
+ prefetchedUntil = InvalidBlockNumber;
while (blkno > vacrelstats->nonempty_pages)
{
Buffer buf;
@@ -1882,6 +1909,21 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
blkno--;
+ /* If we haven't prefetched this lot yet, do so now. */
+ if (prefetchedUntil > blkno)
+ {
+ BlockNumber prefetchStart;
+ BlockNumber pblkno;
+
+ prefetchStart = blkno & ~(PREFETCH_SIZE - 1);
+ for (pblkno = prefetchStart; pblkno <= blkno; pblkno++)
+ {
+ PrefetchBuffer(onerel, MAIN_FORKNUM, pblkno);
+ CHECK_FOR_INTERRUPTS();
+ }
+ prefetchedUntil = prefetchStart;
+ }
+
buf = ReadBufferExtended(onerel, MAIN_FORKNUM, blkno,
RBM_NORMAL, vac_strategy);
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index aafa748595..ed3b2484ae 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -5,7 +5,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -34,6 +34,7 @@
#include "utils/syscache.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
+#include "utils/varlena.h"
#include "mb/pg_wchar.h"
/*
@@ -311,11 +312,7 @@ check_timezone(char **newval, void **extra, GucSource source)
}
/* Here we change from SQL to Unix sign convention */
-#ifdef HAVE_INT64_TIMESTAMP
gmtoffset = -(interval->time / USECS_PER_SEC);
-#else
- gmtoffset = -interval->time;
-#endif
new_tz = pg_tzset_offset(gmtoffset);
pfree(interval);
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index a809a203e9..2ca5b5cfd2 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -4,7 +4,7 @@
* use rewrite rules to construct views
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -63,15 +63,13 @@ validateWithCheckOption(char *value)
/*---------------------------------------------------------------------
* DefineVirtualRelation
*
- * Create the "view" relation. `DefineRelation' does all the work,
- * we just provide the correct arguments ... at least when we're
- * creating a view. If we're updating an existing view, we have to
- * work harder.
+ * Create a view relation and use the rules system to store the query
+ * for the view.
*---------------------------------------------------------------------
*/
static ObjectAddress
DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
- List *options)
+ List *options, Query *viewParse)
{
Oid viewOid;
LOCKMODE lockmode;
@@ -166,18 +164,13 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
checkViewTupleDesc(descriptor, rel->rd_att);
/*
- * The new options list replaces the existing options list, even if
- * it's empty.
- */
- atcmd = makeNode(AlterTableCmd);
- atcmd->subtype = AT_ReplaceRelOptions;
- atcmd->def = (Node *) options;
- atcmds = lappend(atcmds, atcmd);
-
- /*
* If new attributes have been added, we must add pg_attribute entries
* for them. It is convenient (although overkill) to use the ALTER
* TABLE ADD COLUMN infrastructure for this.
+ *
+ * Note that we must do this before updating the query for the view,
+ * since the rules system requires that the correct view columns be in
+ * place when defining the new rules.
*/
if (list_length(attrList) > rel->rd_att->natts)
{
@@ -196,9 +189,38 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
atcmd->def = (Node *) lfirst(c);
atcmds = lappend(atcmds, atcmd);
}
+
+ AlterTableInternal(viewOid, atcmds, true);
+
+ /* Make the new view columns visible */
+ CommandCounterIncrement();
}
- /* OK, let's do it. */
+ /*
+ * Update the query for the view.
+ *
+ * Note that we must do this before updating the view options, because
+ * the new options may not be compatible with the old view query (for
+ * example if we attempt to add the WITH CHECK OPTION, we require that
+ * the new view be automatically updatable, but the old view may not
+ * have been).
+ */
+ StoreViewQuery(viewOid, viewParse, replace);
+
+ /* Make the new view query visible */
+ CommandCounterIncrement();
+
+ /*
+ * Finally update the view options.
+ *
+ * The new options list replaces the existing options list, even if
+ * it's empty.
+ */
+ atcmd = makeNode(AlterTableCmd);
+ atcmd->subtype = AT_ReplaceRelOptions;
+ atcmd->def = (Node *) options;
+ atcmds = list_make1(atcmd);
+
AlterTableInternal(viewOid, atcmds, true);
ObjectAddressSet(address, RelationRelationId, viewOid);
@@ -215,7 +237,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
ObjectAddress address;
/*
- * now set the parameters for keys/inheritance etc. All of these are
+ * Set the parameters for keys/inheritance etc. All of these are
* uninteresting for views...
*/
createStmt->relation = relation;
@@ -228,12 +250,20 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
createStmt->if_not_exists = false;
/*
- * finally create the relation (this will error out if there's an
- * existing view, so we don't need more code to complain if "replace"
- * is false).
+ * Create the relation (this will error out if there's an existing
+ * view, so we don't need more code to complain if "replace" is
+ * false).
*/
- address = DefineRelation(createStmt, RELKIND_VIEW, InvalidOid, NULL);
+ address = DefineRelation(createStmt, RELKIND_VIEW, InvalidOid, NULL,
+ NULL);
Assert(address.objectId != InvalidOid);
+
+ /* Make the new view relation visible */
+ CommandCounterIncrement();
+
+ /* Store the query for the view */
+ StoreViewQuery(address.objectId, viewParse, replace);
+
return address;
}
}
@@ -347,7 +377,7 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
* Var node twice. copyObject will expand any multiply-referenced subtree
* into multiple copies.
*/
- viewParse = (Query *) copyObject(viewParse);
+ viewParse = copyObject(viewParse);
/* Create a dummy ParseState for addRangeTableEntryForRelation */
pstate = make_parsestate(NULL);
@@ -388,8 +418,10 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
* Execute a CREATE VIEW command.
*/
ObjectAddress
-DefineView(ViewStmt *stmt, const char *queryString)
+DefineView(ViewStmt *stmt, const char *queryString,
+ int stmt_location, int stmt_len)
{
+ RawStmt *rawstmt;
Query *viewParse;
RangeVar *view;
ListCell *cell;
@@ -403,8 +435,12 @@ DefineView(ViewStmt *stmt, const char *queryString)
* Since parse analysis scribbles on its input, copy the raw parse tree;
* this ensures we don't corrupt a prepared statement, for example.
*/
- viewParse = parse_analyze((Node *) copyObject(stmt->query),
- queryString, NULL, 0);
+ rawstmt = makeNode(RawStmt);
+ rawstmt->stmt = (Node *) copyObject(stmt->query);
+ rawstmt->stmt_location = stmt_location;
+ rawstmt->stmt_len = stmt_len;
+
+ viewParse = parse_analyze(rawstmt, queryString, NULL, 0, NULL);
/*
* The grammar should ensure that the result is a single SELECT Query.
@@ -417,8 +453,7 @@ DefineView(ViewStmt *stmt, const char *queryString)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("views must not contain SELECT INTO")));
- if (viewParse->commandType != CMD_SELECT ||
- viewParse->utilityStmt != NULL)
+ if (viewParse->commandType != CMD_SELECT)
elog(ERROR, "unexpected parse analysis result");
/*
@@ -438,11 +473,11 @@ DefineView(ViewStmt *stmt, const char *queryString)
if (stmt->withCheckOption == LOCAL_CHECK_OPTION)
stmt->options = lappend(stmt->options,
makeDefElem("check_option",
- (Node *) makeString("local")));
+ (Node *) makeString("local"), -1));
else if (stmt->withCheckOption == CASCADED_CHECK_OPTION)
stmt->options = lappend(stmt->options,
makeDefElem("check_option",
- (Node *) makeString("cascaded")));
+ (Node *) makeString("cascaded"), -1));
/*
* Check that the view is auto-updatable if WITH CHECK OPTION was
@@ -485,9 +520,8 @@ DefineView(ViewStmt *stmt, const char *queryString)
foreach(targetList, viewParse->targetList)
{
- TargetEntry *te = (TargetEntry *) lfirst(targetList);
+ TargetEntry *te = lfirst_node(TargetEntry, targetList);
- Assert(IsA(te, TargetEntry));
/* junk columns don't get aliases */
if (te->resjunk)
continue;
@@ -541,16 +575,7 @@ DefineView(ViewStmt *stmt, const char *queryString)
* aborted.
*/
address = DefineVirtualRelation(view, viewParse->targetList,
- stmt->replace, stmt->options);
-
- /*
- * The relation we have just created is not visible to any other commands
- * running with the same transaction & command id. So, increment the
- * command id counter (but do NOT pfree any memory!!!!)
- */
- CommandCounterIncrement();
-
- StoreViewQuery(address.objectId, viewParse, stmt->replace);
+ stmt->replace, stmt->options, viewParse);
return address;
}
diff --git a/src/backend/common.mk b/src/backend/common.mk
index 5d599dbd0c..0b57543bc4 100644
--- a/src/backend/common.mk
+++ b/src/backend/common.mk
@@ -8,6 +8,8 @@
# this directory and SUBDIRS to subdirectories containing more things
# to build.
+override CPPFLAGS := $(CPPFLAGS) $(ICU_CFLAGS)
+
ifdef PARTIAL_LINKING
# old style: linking using SUBSYS.o
subsysfilename = SUBSYS.o
diff --git a/src/backend/executor/Makefile b/src/backend/executor/Makefile
index 6625d56b97..fef60fb4c9 100644
--- a/src/backend/executor/Makefile
+++ b/src/backend/executor/Makefile
@@ -12,19 +12,23 @@ subdir = src/backend/executor
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-OBJS = execAmi.o execCurrent.o execGrouping.o execIndexing.o execJunk.o \
- execMain.o execParallel.o execProcnode.o execQual.o \
- execScan.o execTuples.o \
+OBJS = execAmi.o execCurrent.o execExpr.o execExprInterp.o \
+ execGrouping.o execIndexing.o execJunk.o \
+ execMain.o execParallel.o execProcnode.o \
+ execReplication.o execScan.o execSRF.o execTuples.o \
execUtils.o functions.o instrument.o nodeAppend.o nodeAgg.o \
nodeBitmapAnd.o nodeBitmapOr.o \
- nodeBitmapHeapscan.o nodeBitmapIndexscan.o nodeCustom.o nodeGather.o \
+ nodeBitmapHeapscan.o nodeBitmapIndexscan.o \
+ nodeCustom.o nodeFunctionscan.o nodeGather.o \
nodeHash.o nodeHashjoin.o nodeIndexscan.o nodeIndexonlyscan.o \
- nodeLimit.o nodeLockRows.o \
+ nodeLimit.o nodeLockRows.o nodeGatherMerge.o \
nodeMaterial.o nodeMergeAppend.o nodeMergejoin.o nodeModifyTable.o \
- nodeNestloop.o nodeFunctionscan.o nodeRecursiveunion.o nodeResult.o \
+ nodeNestloop.o nodeProjectSet.o nodeRecursiveunion.o nodeResult.o \
nodeSamplescan.o nodeSeqscan.o nodeSetOp.o nodeSort.o nodeUnique.o \
- nodeValuesscan.o nodeCtescan.o nodeWorktablescan.o \
+ nodeValuesscan.o \
+ nodeCtescan.o nodeNamedtuplestorescan.o nodeWorktablescan.o \
nodeGroup.o nodeSubplan.o nodeSubqueryscan.o nodeTidscan.o \
- nodeForeignscan.o nodeWindowAgg.o producerReceiver.o tstoreReceiver.o tqueue.o spi.o
+ nodeForeignscan.o nodeWindowAgg.o producerReceiver.o tstoreReceiver.o tqueue.o spi.o \
+ nodeTableFuncscan.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/executor/README b/src/backend/executor/README
index 8afa1e3e4a..a0045067fb 100644
--- a/src/backend/executor/README
+++ b/src/backend/executor/README
@@ -44,21 +44,171 @@ Plan Trees and State Trees
--------------------------
The plan tree delivered by the planner contains a tree of Plan nodes (struct
-types derived from struct Plan). Each Plan node may have expression trees
-associated with it, to represent its target list, qualification conditions,
-etc. During executor startup we build a parallel tree of identical structure
-containing executor state nodes --- every plan and expression node type has
-a corresponding executor state node type. Each node in the state tree has a
-pointer to its corresponding node in the plan tree, plus executor state data
-as needed to implement that node type. This arrangement allows the plan
-tree to be completely read-only as far as the executor is concerned: all data
-that is modified during execution is in the state tree. Read-only plan trees
-make life much simpler for plan caching and reuse.
+types derived from struct Plan). During executor startup we build a parallel
+tree of identical structure containing executor state nodes --- every plan
+node type has a corresponding executor state node type. Each node in the
+state tree has a pointer to its corresponding node in the plan tree, plus
+executor state data as needed to implement that node type. This arrangement
+allows the plan tree to be completely read-only so far as the executor is
+concerned: all data that is modified during execution is in the state tree.
+Read-only plan trees make life much simpler for plan caching and reuse.
+
+Each Plan node may have expression trees associated with it, to represent
+its target list, qualification conditions, etc. These trees are also
+read-only to the executor, but the executor state for expression evaluation
+does not mirror the Plan expression's tree shape, as explained below.
+Rather, there's just one ExprState node per expression tree, although this
+may have sub-nodes for some complex expression node types.
Altogether there are four classes of nodes used in these trees: Plan nodes,
-their corresponding PlanState nodes, Expr nodes, and their corresponding
-ExprState nodes. (Actually, there are also List nodes, which are used as
-"glue" in all four kinds of tree.)
+their corresponding PlanState nodes, Expr nodes, and ExprState nodes.
+(Actually, there are also List nodes, which are used as "glue" in all
+three tree-based representations.)
+
+
+Expression Trees and ExprState nodes
+------------------------------------
+
+Expression trees, in contrast to Plan trees, are not mirrored into a
+corresponding tree of state nodes. Instead each separately executable
+expression tree (e.g. a Plan's qual or targetlist) is represented by one
+ExprState node. The ExprState node contains the information needed to
+evaluate the expression in a compact, linear form. That compact form is
+stored as a flat array in ExprState->steps[] (an array of ExprEvalStep,
+not ExprEvalStep *).
+
+The reasons for choosing such a representation include:
+- commonly the amount of work needed to evaluate one Expr-type node is
+ small enough that the overhead of having to perform a tree-walk
+ during evaluation is significant.
+- the flat representation can be evaluated non-recursively within a single
+ function, reducing stack depth and function call overhead.
+- such a representation is usable both for fast interpreted execution,
+ and for compiling into native code.
+
+The Plan-tree representation of an expression is compiled into an
+ExprState node by ExecInitExpr(). As much complexity as possible should
+be handled by ExecInitExpr() (and helpers), instead of execution time
+where both interpreted and compiled versions would need to deal with the
+complexity. Besides duplicating effort between execution approaches,
+runtime initialization checks also have a small but noticeable cost every
+time the expression is evaluated. Therefore, we allow ExecInitExpr() to
+precompute information that we do not expect to vary across execution of a
+single query, for example the set of CHECK constraint expressions to be
+applied to a domain type. This could not be done at plan time without
+greatly increasing the number of events that require plan invalidation.
+(Previously, some information of this kind was rechecked on each
+expression evaluation, but that seems like unnecessary overhead.)
+
+
+Expression Initialization
+-------------------------
+
+During ExecInitExpr() and similar routines, Expr trees are converted
+into the flat representation. Each Expr node might be represented by
+zero, one, or more ExprEvalSteps.
+
+Each ExprEvalStep's work is determined by its opcode (of enum ExprEvalOp)
+and it stores the result of its work into the Datum variable and boolean
+null flag variable pointed to by ExprEvalStep->resvalue/resnull.
+Complex expressions are performed by chaining together several steps.
+For example, "a + b" (one OpExpr, with two Var expressions) would be
+represented as two steps to fetch the Var values, and one step for the
+evaluation of the function underlying the + operator. The steps for the
+Vars would have their resvalue/resnull pointing directly to the appropriate
+arg[] and argnull[] array elements in the FunctionCallInfoData struct that
+is used by the function evaluation step, thus avoiding extra work to copy
+the result values around.
+
+The last entry in a completed ExprState->steps array is always an
+EEOP_DONE step; this removes the need to test for end-of-array while
+iterating. Also, if the expression contains any variable references (to
+user columns of the ExprContext's INNER, OUTER, or SCAN tuples), the steps
+array begins with EEOP_*_FETCHSOME steps that ensure that the relevant
+tuples have been deconstructed to make the required columns directly
+available (cf. slot_getsomeattrs()). This allows individual Var-fetching
+steps to be little more than an array lookup.
+
+Most of ExecInitExpr()'s work is done by the recursive function
+ExecInitExprRec() and its subroutines. ExecInitExprRec() maps one Expr
+node into the steps required for execution, recursing as needed for
+sub-expressions.
+
+Each ExecInitExprRec() call has to specify where that subexpression's
+results are to be stored (via the resv/resnull parameters). This allows
+the above scenario of evaluating a (sub-)expression directly into
+fcinfo->arg/argnull, but also requires some care: target Datum/isnull
+variables may not be shared with another ExecInitExprRec() unless the
+results are only needed by steps executing before further usages of those
+target Datum/isnull variables. Due to the non-recursiveness of the
+ExprEvalStep representation that's usually easy to guarantee.
+
+ExecInitExprRec() pushes new operations into the ExprState->steps array
+using ExprEvalPushStep(). To keep the steps as a consecutively laid out
+array, ExprEvalPushStep() has to repalloc the entire array when there's
+not enough space. Because of that it is *not* allowed to point directly
+into any of the steps during expression initialization. Therefore, the
+resv/resnull for a subexpression usually point to some storage that is
+palloc'd separately from the steps array. For instance, the
+FunctionCallInfoData for a function call step is separately allocated
+rather than being part of the ExprEvalStep array. The overall result
+of a complete expression is typically returned into the resvalue/resnull
+fields of the ExprState node itself.
+
+Some steps, e.g. boolean expressions, allow skipping evaluation of
+certain subexpressions. In the flat representation this amounts to
+jumping to some later step rather than just continuing consecutively
+with the next step. The target for such a jump is represented by
+the integer index in the ExprState->steps array of the step to execute
+next. (Compare the EEO_NEXT and EEO_JUMP macros in execExprInterp.c.)
+
+Typically, ExecInitExprRec() has to push a jumping step into the steps
+array, then recursively generate steps for the subexpression that might
+get skipped over, then go back and fix up the jump target index using
+the now-known length of the subexpression's steps. This is handled by
+adjust_jumps lists in execExpr.c.
+
+The last step in constructing an ExprState is to apply ExecReadyExpr(),
+which readies it for execution using whichever execution method has been
+selected.
+
+
+Expression Evaluation
+---------------------
+
+To allow for different methods of expression evaluation, and for
+better branch/jump target prediction, expressions are evaluated by
+calling ExprState->evalfunc (via ExprEvalExpr() and friends).
+
+ExprReadyExpr() can choose the method of interpretation by setting
+evalfunc to an appropriate function. The default execution function,
+ExecInterpExpr, is implemented in execExprInterp.c; see its header
+comment for details. Special-case evalfuncs are used for certain
+especially-simple expressions.
+
+Note that a lot of the more complex expression evaluation steps, which are
+less performance-critical than the simpler ones, are implemented as
+separate functions outside the fast-path of expression execution, allowing
+their implementation to be shared between interpreted and compiled
+expression evaluation. This means that these helper functions are not
+allowed to perform expression step dispatch themselves, as the method of
+dispatch will vary based on the caller. The helpers therefore cannot call
+for the execution of subexpressions; all subexpression results they need
+must be computed by earlier steps. And dispatch to the following
+expression step must be performed after returning from the helper.
+
+
+Targetlist Evaluation
+---------------------
+
+ExecBuildProjectionInfo builds an ExprState that has the effect of
+evaluating a targetlist into ExprState->resultslot. A generic targetlist
+expression is executed by evaluating it as discussed above (storing the
+result into the ExprState's resvalue/resnull fields) and then using an
+EEOP_ASSIGN_TMP step to move the result into the appropriate tts_values[]
+and tts_isnull[] array elements of the result slot. There are special
+fast-path step types (EEOP_ASSIGN_*_VAR) to handle targetlist entries that
+are simple Vars using only one step instead of two.
Memory Management
@@ -195,8 +345,7 @@ the entire row value in the join output row.
We disallow set-returning functions in the targetlist of SELECT FOR UPDATE,
so as to ensure that at most one tuple can be returned for any particular
set of scan tuples. Otherwise we'd get duplicates due to the original
-query returning the same set of scan tuples multiple times. (Note: there
-is no explicit prohibition on SRFs in UPDATE, but the net effect will be
-that only the first result row of an SRF counts, because all subsequent
-rows will result in attempts to re-update an already updated target row.
-This is historical behavior and seems not worth changing.)
+query returning the same set of scan tuples multiple times. Likewise,
+SRFs are disallowed in an UPDATE's targetlist. There, they would have the
+effect of the same row being updated multiple times, which is not very
+useful --- and updates after the first would have no effect anyway.
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index 2cb83d75a7..b802ad6956 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -4,7 +4,7 @@
* miscellaneous executor access method routines
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/executor/execAmi.c
@@ -39,7 +39,9 @@
#include "executor/nodeMergeAppend.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeModifyTable.h"
+#include "executor/nodeNamedtuplestorescan.h"
#include "executor/nodeNestloop.h"
+#include "executor/nodeProjectSet.h"
#include "executor/nodeRecursiveunion.h"
#include "executor/nodeResult.h"
#include "executor/nodeSamplescan.h"
@@ -48,6 +50,7 @@
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h"
+#include "executor/nodeTableFuncscan.h"
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
#include "executor/nodeValuesscan.h"
@@ -62,7 +65,6 @@
#endif
-static bool TargetListSupportsBackwardScan(List *targetlist);
static bool IndexSupportsBackwardScan(Oid indexid);
@@ -123,7 +125,7 @@ ExecReScan(PlanState *node)
UpdateChangedParamSet(node->righttree, node->chgParam);
}
- /* Shut down any SRFs in the plan node's targetlist */
+ /* Call expression callbacks */
if (node->ps_ExprContext)
ReScanExprContext(node->ps_ExprContext);
@@ -134,6 +136,10 @@ ExecReScan(PlanState *node)
ExecReScanResult((ResultState *) node);
break;
+ case T_ProjectSetState:
+ ExecReScanProjectSet((ProjectSetState *) node);
+ break;
+
case T_ModifyTableState:
ExecReScanModifyTable((ModifyTableState *) node);
break;
@@ -198,6 +204,10 @@ ExecReScan(PlanState *node)
ExecReScanFunctionScan((FunctionScanState *) node);
break;
+ case T_TableFuncScanState:
+ ExecReScanTableFuncScan((TableFuncScanState *) node);
+ break;
+
case T_ValuesScanState:
ExecReScanValuesScan((ValuesScanState *) node);
break;
@@ -206,6 +216,10 @@ ExecReScan(PlanState *node)
ExecReScanCteScan((CteScanState *) node);
break;
+ case T_NamedTuplestoreScanState:
+ ExecReScanNamedTuplestoreScan((NamedTuplestoreScanState *) node);
+ break;
+
case T_WorkTableScanState:
ExecReScanWorkTableScan((WorkTableScanState *) node);
break;
@@ -408,11 +422,13 @@ ExecSupportsMarkRestore(Path *pathnode)
return true;
case T_CustomScan:
- Assert(IsA(pathnode, CustomPath));
- if (((CustomPath *) pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
- return true;
- return false;
+ {
+ CustomPath *customPath = castNode(CustomPath, pathnode);
+ if (customPath->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
+ return true;
+ return false;
+ }
case T_Result:
/*
@@ -464,8 +480,7 @@ ExecSupportsBackwardScan(Plan *node)
{
case T_Result:
if (outerPlan(node) != NULL)
- return ExecSupportsBackwardScan(outerPlan(node)) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return ExecSupportsBackwardScan(outerPlan(node));
else
return false;
@@ -482,13 +497,6 @@ ExecSupportsBackwardScan(Plan *node)
return true;
}
- case T_SeqScan:
- case T_TidScan:
- case T_FunctionScan:
- case T_ValuesScan:
- case T_CteScan:
- return TargetListSupportsBackwardScan(node->targetlist);
-
case T_SampleScan:
/* Simplify life for tablesample methods by disallowing this */
return false;
@@ -497,35 +505,34 @@ ExecSupportsBackwardScan(Plan *node)
return false;
case T_IndexScan:
- return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return IndexSupportsBackwardScan(((IndexScan *) node)->indexid);
case T_IndexOnlyScan:
- return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid);
case T_SubqueryScan:
- return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
case T_CustomScan:
{
uint32 flags = ((CustomScan *) node)->flags;
- if ((flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) &&
- TargetListSupportsBackwardScan(node->targetlist))
+ if (flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN)
return true;
}
return false;
+ case T_SeqScan:
+ case T_TidScan:
+ case T_FunctionScan:
+ case T_ValuesScan:
+ case T_CteScan:
case T_Material:
case T_Sort:
- /* these don't evaluate tlist */
return true;
case T_LockRows:
case T_Limit:
- /* these don't evaluate tlist */
return ExecSupportsBackwardScan(outerPlan(node));
default:
@@ -534,18 +541,6 @@ ExecSupportsBackwardScan(Plan *node)
}
/*
- * If the tlist contains set-returning functions, we can't support backward
- * scan, because the TupFromTlist code is direction-ignorant.
- */
-static bool
-TargetListSupportsBackwardScan(List *targetlist)
-{
- if (expression_returns_set((Node *) targetlist))
- return false;
- return true;
-}
-
-/*
* An IndexScan or IndexOnlyScan node supports backward scan only if the
* index's AM does.
*/
@@ -589,7 +584,9 @@ ExecMaterializesOutput(NodeTag plantype)
{
case T_Material:
case T_FunctionScan:
+ case T_TableFuncScan:
case T_CteScan:
+ case T_NamedTuplestoreScan:
case T_WorkTableScan:
case T_Sort:
return true;
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index 757ea8dddc..0224b9e4af 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -4,7 +4,7 @@
* executor support for WHERE CURRENT OF cursor
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/executor/execCurrent.c
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
new file mode 100644
index 0000000000..fe12326336
--- /dev/null
+++ b/src/backend/executor/execExpr.c
@@ -0,0 +1,2677 @@
+/*-------------------------------------------------------------------------
+ *
+ * execExpr.c
+ * Expression evaluation infrastructure.
+ *
+ * During executor startup, we compile each expression tree (which has
+ * previously been processed by the parser and planner) into an ExprState,
+ * using ExecInitExpr() et al. This converts the tree into a flat array
+ * of ExprEvalSteps, which may be thought of as instructions in a program.
+ * At runtime, we'll execute steps, starting with the first, until we reach
+ * an EEOP_DONE opcode.
+ *
+ * This file contains the "compilation" logic. It is independent of the
+ * specific execution technology we use (switch statement, computed goto,
+ * JIT compilation, etc).
+ *
+ * See src/backend/executor/README for some background, specifically the
+ * "Expression Trees and ExprState nodes", "Expression Initialization",
+ * and "Expression Evaluation" sections.
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/execExpr.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/nbtree.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_type.h"
+#include "executor/execExpr.h"
+#include "executor/nodeSubplan.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
+#include "optimizer/clauses.h"
+#include "optimizer/planner.h"
+#include "pgstat.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/typcache.h"
+
+
+typedef struct LastAttnumInfo
+{
+ AttrNumber last_inner;
+ AttrNumber last_outer;
+ AttrNumber last_scan;
+} LastAttnumInfo;
+
+static void ExecReadyExpr(ExprState *state);
+static void ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
+ Datum *resv, bool *resnull);
+static void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
+static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
+ Oid funcid, Oid inputcollid, PlanState *parent,
+ ExprState *state);
+static void ExecInitExprSlots(ExprState *state, Node *node);
+static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
+static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
+ PlanState *parent);
+static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
+ PlanState *parent, ExprState *state,
+ Datum *resv, bool *resnull);
+static bool isAssignmentIndirectionExpr(Expr *expr);
+static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
+ PlanState *parent, ExprState *state,
+ Datum *resv, bool *resnull);
+
+
+/*
+ * ExecInitExpr: prepare an expression tree for execution
+ *
+ * This function builds and returns an ExprState implementing the given
+ * Expr node tree. The return ExprState can then be handed to ExecEvalExpr
+ * for execution. Because the Expr tree itself is read-only as far as
+ * ExecInitExpr and ExecEvalExpr are concerned, several different executions
+ * of the same plan tree can occur concurrently. (But note that an ExprState
+ * does mutate at runtime, so it can't be re-used concurrently.)
+ *
+ * This must be called in a memory context that will last as long as repeated
+ * executions of the expression are needed. Typically the context will be
+ * the same as the per-query context of the associated ExprContext.
+ *
+ * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
+ * the lists of such nodes held by the parent PlanState (or more accurately,
+ * the AggrefExprState etc. nodes created for them are added).
+ *
+ * Note: there is no ExecEndExpr function; we assume that any resource
+ * cleanup needed will be handled by just releasing the memory context
+ * in which the state tree is built. Functions that require additional
+ * cleanup work can register a shutdown callback in the ExprContext.
+ *
+ * 'node' is the root of the expression tree to compile.
+ * 'parent' is the PlanState node that owns the expression.
+ *
+ * 'parent' may be NULL if we are preparing an expression that is not
+ * associated with a plan tree. (If so, it can't have aggs or subplans.)
+ * Such cases should usually come through ExecPrepareExpr, not directly here.
+ *
+ * Also, if 'node' is NULL, we just return NULL. This is convenient for some
+ * callers that may or may not have an expression that needs to be compiled.
+ * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
+ * although ExecQual and ExecCheck will accept one (and treat it as "true").
+ */
+ExprState *
+ExecInitExpr(Expr *node, PlanState *parent)
+{
+ ExprState *state;
+ ExprEvalStep scratch;
+
+ /* Special case: NULL expression produces a NULL ExprState pointer */
+ if (node == NULL)
+ return NULL;
+
+ /* Initialize ExprState with empty step list */
+ state = makeNode(ExprState);
+ state->expr = node;
+
+ /* Insert EEOP_*_FETCHSOME steps as needed */
+ ExecInitExprSlots(state, (Node *) node);
+
+ /* Compile the expression proper */
+ ExecInitExprRec(node, parent, state, &state->resvalue, &state->resnull);
+
+ /* Finally, append a DONE step */
+ scratch.opcode = EEOP_DONE;
+ ExprEvalPushStep(state, &scratch);
+
+ ExecReadyExpr(state);
+
+ return state;
+}
+
+/*
+ * ExecInitQual: prepare a qual for execution by ExecQual
+ *
+ * Prepares for the evaluation of a conjunctive boolean expression (qual list
+ * with implicit AND semantics) that returns true if none of the
+ * subexpressions are false.
+ *
+ * We must return true if the list is empty. Since that's a very common case,
+ * we optimize it a bit further by translating to a NULL ExprState pointer
+ * rather than setting up an ExprState that computes constant TRUE. (Some
+ * especially hot-spot callers of ExecQual detect this and avoid calling
+ * ExecQual at all.)
+ *
+ * If any of the subexpressions yield NULL, then the result of the conjunction
+ * is false. This makes ExecQual primarily useful for evaluating WHERE
+ * clauses, since SQL specifies that tuples with null WHERE results do not
+ * get selected.
+ */
+ExprState *
+ExecInitQual(List *qual, PlanState *parent)
+{
+ ExprState *state;
+ ExprEvalStep scratch;
+ List *adjust_jumps = NIL;
+ ListCell *lc;
+
+ /* short-circuit (here and in ExecQual) for empty restriction list */
+ if (qual == NIL)
+ return NULL;
+
+ Assert(IsA(qual, List));
+
+ state = makeNode(ExprState);
+ state->expr = (Expr *) qual;
+ /* mark expression as to be used with ExecQual() */
+ state->flags = EEO_FLAG_IS_QUAL;
+
+ /* Insert EEOP_*_FETCHSOME steps as needed */
+ ExecInitExprSlots(state, (Node *) qual);
+
+ /*
+ * ExecQual() needs to return false for an expression returning NULL. That
+ * allows us to short-circuit the evaluation the first time a NULL is
+ * encountered. As qual evaluation is a hot-path this warrants using a
+ * special opcode for qual evaluation that's simpler than BOOL_AND (which
+ * has more complex NULL handling).
+ */
+ scratch.opcode = EEOP_QUAL;
+
+ /*
+ * We can use ExprState's resvalue/resnull as target for each qual expr.
+ */
+ scratch.resvalue = &state->resvalue;
+ scratch.resnull = &state->resnull;
+
+ foreach(lc, qual)
+ {
+ Expr *node = (Expr *) lfirst(lc);
+
+ /* first evaluate expression */
+ ExecInitExprRec(node, parent, state, &state->resvalue, &state->resnull);
+
+ /* then emit EEOP_QUAL to detect if it's false (or null) */
+ scratch.d.qualexpr.jumpdone = -1;
+ ExprEvalPushStep(state, &scratch);
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ }
+
+ /* adjust jump targets */
+ foreach(lc, adjust_jumps)
+ {
+ ExprEvalStep *as = &state->steps[lfirst_int(lc)];
+
+ Assert(as->opcode == EEOP_QUAL);
+ Assert(as->d.qualexpr.jumpdone == -1);
+ as->d.qualexpr.jumpdone = state->steps_len;
+ }
+
+ /*
+ * At the end, we don't need to do anything more. The last qual expr must
+ * have yielded TRUE, and since its result is stored in the desired output
+ * location, we're done.
+ */
+ scratch.opcode = EEOP_DONE;
+ ExprEvalPushStep(state, &scratch);
+
+ ExecReadyExpr(state);
+
+ return state;
+}
+
+/*
+ * ExecInitCheck: prepare a check constraint for execution by ExecCheck
+ *
+ * This is much like ExecInitQual/ExecQual, except that a null result from
+ * the conjunction is treated as TRUE. This behavior is appropriate for
+ * evaluating CHECK constraints, since SQL specifies that NULL constraint
+ * conditions are not failures.
+ *
+ * Note that like ExecInitQual, this expects input in implicit-AND format.
+ * Users of ExecCheck that have expressions in normal explicit-AND format
+ * can just apply ExecInitExpr to produce suitable input for ExecCheck.
+ */
+ExprState *
+ExecInitCheck(List *qual, PlanState *parent)
+{
+ /* short-circuit (here and in ExecCheck) for empty restriction list */
+ if (qual == NIL)
+ return NULL;
+
+ Assert(IsA(qual, List));
+
+ /*
+ * Just convert the implicit-AND list to an explicit AND (if there's more
+ * than one entry), and compile normally. Unlike ExecQual, we can't
+ * short-circuit on NULL results, so the regular AND behavior is needed.
+ */
+ return ExecInitExpr(make_ands_explicit(qual), parent);
+}
+
+/*
+ * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
+ */
+List *
+ExecInitExprList(List *nodes, PlanState *parent)
+{
+ List *result = NIL;
+ ListCell *lc;
+
+ foreach(lc, nodes)
+ {
+ Expr *e = lfirst(lc);
+
+ result = lappend(result, ExecInitExpr(e, parent));
+ }
+
+ return result;
+}
+
+/*
+ * ExecBuildProjectionInfo
+ *
+ * Build a ProjectionInfo node for evaluating the given tlist in the given
+ * econtext, and storing the result into the tuple slot. (Caller must have
+ * ensured that tuple slot has a descriptor matching the tlist!)
+ *
+ * inputDesc can be NULL, but if it is not, we check to see whether simple
+ * Vars in the tlist match the descriptor. It is important to provide
+ * inputDesc for relation-scan plan nodes, as a cross check that the relation
+ * hasn't been changed since the plan was made. At higher levels of a plan,
+ * there is no need to recheck.
+ *
+ * This is implemented by internally building an ExprState that performs the
+ * whole projection in one go.
+ *
+ * Caution: before PG v10, the targetList was a list of ExprStates; now it
+ * should be the planner-created targetlist, since we do the compilation here.
+ */
+ProjectionInfo *
+ExecBuildProjectionInfo(List *targetList,
+ ExprContext *econtext,
+ TupleTableSlot *slot,
+ PlanState *parent,
+ TupleDesc inputDesc)
+{
+ ProjectionInfo *projInfo = makeNode(ProjectionInfo);
+ ExprState *state;
+ ExprEvalStep scratch;
+ ListCell *lc;
+
+ projInfo->pi_exprContext = econtext;
+ /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
+ projInfo->pi_state.tag.type = T_ExprState;
+ state = &projInfo->pi_state;
+ state->expr = (Expr *) targetList;
+ state->resultslot = slot;
+
+ /* Insert EEOP_*_FETCHSOME steps as needed */
+ ExecInitExprSlots(state, (Node *) targetList);
+
+ /* Now compile each tlist column */
+ foreach(lc, targetList)
+ {
+ TargetEntry *tle = lfirst_node(TargetEntry, lc);
+ Var *variable = NULL;
+ AttrNumber attnum = 0;
+ bool isSafeVar = false;
+
+ /*
+ * If tlist expression is a safe non-system Var, use the fast-path
+ * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
+ * CheckVarSlotCompatibility() during plan startup. If a source slot
+ * was provided, we make the equivalent tests here; if a slot was not
+ * provided, we assume that no check is needed because we're dealing
+ * with a non-relation-scan-level expression.
+ */
+ if (tle->expr != NULL &&
+ IsA(tle->expr, Var) &&
+ ((Var *) tle->expr)->varattno > 0)
+ {
+ /* Non-system Var, but how safe is it? */
+ variable = (Var *) tle->expr;
+ attnum = variable->varattno;
+
+ if (inputDesc == NULL)
+ isSafeVar = true; /* can't check, just assume OK */
+ else if (attnum <= inputDesc->natts)
+ {
+ Form_pg_attribute attr = inputDesc->attrs[attnum - 1];
+
+ /*
+ * If user attribute is dropped or has a type mismatch, don't
+ * use ASSIGN_*_VAR. Instead let the normal expression
+ * machinery handle it (which'll possibly error out).
+ */
+ if (!attr->attisdropped && variable->vartype == attr->atttypid)
+ {
+ isSafeVar = true;
+ }
+ }
+ }
+
+ if (isSafeVar)
+ {
+ /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
+ switch (variable->varno)
+ {
+ case INNER_VAR:
+ /* get the tuple from the inner node */
+ scratch.opcode = EEOP_ASSIGN_INNER_VAR;
+ break;
+
+ case OUTER_VAR:
+ /* get the tuple from the outer node */
+ scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
+ break;
+
+ /* INDEX_VAR is handled by default case */
+
+ default:
+ /* get the tuple from the relation being scanned */
+ scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
+ break;
+ }
+
+ scratch.d.assign_var.attnum = attnum - 1;
+ scratch.d.assign_var.resultnum = tle->resno - 1;
+ ExprEvalPushStep(state, &scratch);
+ }
+ else
+ {
+ /*
+ * Otherwise, compile the column expression normally.
+ *
+ * We can't tell the expression to evaluate directly into the
+ * result slot, as the result slot (and the exprstate for that
+ * matter) can change between executions. We instead evaluate
+ * into the ExprState's resvalue/resnull and then move.
+ */
+ ExecInitExprRec(tle->expr, parent, state,
+ &state->resvalue, &state->resnull);
+
+ /*
+ * Column might be referenced multiple times in upper nodes, so
+ * force value to R/O - but only if it could be an expanded datum.
+ */
+ if (get_typlen(exprType((Node *) tle->expr)) == -1)
+ scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
+ else
+ scratch.opcode = EEOP_ASSIGN_TMP;
+ scratch.d.assign_tmp.resultnum = tle->resno - 1;
+ ExprEvalPushStep(state, &scratch);
+ }
+ }
+
+ scratch.opcode = EEOP_DONE;
+ ExprEvalPushStep(state, &scratch);
+
+ ExecReadyExpr(state);
+
+ return projInfo;
+}
+
+/*
+ * ExecPrepareExpr --- initialize for expression execution outside a normal
+ * Plan tree context.
+ *
+ * This differs from ExecInitExpr in that we don't assume the caller is
+ * already running in the EState's per-query context. Also, we run the
+ * passed expression tree through expression_planner() to prepare it for
+ * execution. (In ordinary Plan trees the regular planning process will have
+ * made the appropriate transformations on expressions, but for standalone
+ * expressions this won't have happened.)
+ */
+ExprState *
+ExecPrepareExpr(Expr *node, EState *estate)
+{
+ ExprState *result;
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
+
+ node = expression_planner(node);
+
+ result = ExecInitExpr(node, NULL);
+
+ MemoryContextSwitchTo(oldcontext);
+
+ return result;
+}
+
+/*
+ * ExecPrepareQual --- initialize for qual execution outside a normal
+ * Plan tree context.
+ *
+ * This differs from ExecInitQual in that we don't assume the caller is
+ * already running in the EState's per-query context. Also, we run the
+ * passed expression tree through expression_planner() to prepare it for
+ * execution. (In ordinary Plan trees the regular planning process will have
+ * made the appropriate transformations on expressions, but for standalone
+ * expressions this won't have happened.)
+ */
+ExprState *
+ExecPrepareQual(List *qual, EState *estate)
+{
+ ExprState *result;
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
+
+ qual = (List *) expression_planner((Expr *) qual);
+
+ result = ExecInitQual(qual, NULL);
+
+ MemoryContextSwitchTo(oldcontext);
+
+ return result;
+}
+
+/*
+ * ExecPrepareCheck -- initialize check constraint for execution outside a
+ * normal Plan tree context.
+ *
+ * See ExecPrepareExpr() and ExecInitCheck() for details.
+ */
+ExprState *
+ExecPrepareCheck(List *qual, EState *estate)
+{
+ ExprState *result;
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
+
+ qual = (List *) expression_planner((Expr *) qual);
+
+ result = ExecInitCheck(qual, NULL);
+
+ MemoryContextSwitchTo(oldcontext);
+
+ return result;
+}
+
+/*
+ * Call ExecPrepareExpr() on each member of a list of Exprs, and return
+ * a list of ExprStates.
+ *
+ * See ExecPrepareExpr() for details.
+ */
+List *
+ExecPrepareExprList(List *nodes, EState *estate)
+{
+ List *result = NIL;
+ MemoryContext oldcontext;
+ ListCell *lc;
+
+ /* Ensure that the list cell nodes are in the right context too */
+ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
+
+ foreach(lc, nodes)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+
+ result = lappend(result, ExecPrepareExpr(e, estate));
+ }
+
+ MemoryContextSwitchTo(oldcontext);
+
+ return result;
+}
+
+/*
+ * ExecCheck - evaluate a check constraint
+ *
+ * For check constraints, a null result is taken as TRUE, ie the constraint
+ * passes.
+ *
+ * The check constraint may have been prepared with ExecInitCheck
+ * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
+ * format, but a regular boolean expression prepared with ExecInitExpr or
+ * ExecPrepareExpr works too.
+ */
+bool
+ExecCheck(ExprState *state, ExprContext *econtext)
+{
+ Datum ret;
+ bool isnull;
+
+ /* short-circuit (here and in ExecInitCheck) for empty restriction list */
+ if (state == NULL)
+ return true;
+
+ /* verify that expression was not compiled using ExecInitQual */
+ Assert(!(state->flags & EEO_FLAG_IS_QUAL));
+
+ ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
+
+ if (isnull)
+ return true;
+
+ return DatumGetBool(ret);
+}
+
+/*
+ * Prepare a compiled expression for execution. This has to be called for
+ * every ExprState before it can be executed.
+ *
+ * NB: While this currently only calls ExecReadyInterpretedExpr(),
+ * this will likely get extended to further expression evaluation methods.
+ * Therefore this should be used instead of directly calling
+ * ExecReadyInterpretedExpr().
+ */
+static void
+ExecReadyExpr(ExprState *state)
+{
+ ExecReadyInterpretedExpr(state);
+}
+
+/*
+ * Append the steps necessary for the evaluation of node to ExprState->steps,
+ * possibly recursing into sub-expressions of node.
+ *
+ * node - expression to evaluate
+ * parent - parent executor node (or NULL if a standalone expression)
+ * state - ExprState to whose ->steps to append the necessary operations
+ * resv / resnull - where to store the result of the node into
+ */
+static void
+ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
+ Datum *resv, bool *resnull)
+{
+ ExprEvalStep scratch;
+
+ /* Guard against stack overflow due to overly complex expressions */
+ check_stack_depth();
+
+ /* Step's output location is always what the caller gave us */
+ Assert(resv != NULL && resnull != NULL);
+ scratch.resvalue = resv;
+ scratch.resnull = resnull;
+
+ /* cases should be ordered as they are in enum NodeTag */
+ switch (nodeTag(node))
+ {
+ case T_Var:
+ {
+ Var *variable = (Var *) node;
+
+ if (variable->varattno == InvalidAttrNumber)
+ {
+ /* whole-row Var */
+ ExecInitWholeRowVar(&scratch, variable, parent);
+ }
+ else if (variable->varattno <= 0)
+ {
+ /* system column */
+ scratch.d.var.attnum = variable->varattno;
+ scratch.d.var.vartype = variable->vartype;
+ switch (variable->varno)
+ {
+ case INNER_VAR:
+ scratch.opcode = EEOP_INNER_SYSVAR;
+ break;
+ case OUTER_VAR:
+ scratch.opcode = EEOP_OUTER_SYSVAR;
+ break;
+
+ /* INDEX_VAR is handled by default case */
+
+ default:
+ scratch.opcode = EEOP_SCAN_SYSVAR;
+ break;
+ }
+ }
+ else
+ {
+ /* regular user column */
+ scratch.d.var.attnum = variable->varattno - 1;
+ scratch.d.var.vartype = variable->vartype;
+ /* select EEOP_*_FIRST opcode to force one-time checks */
+ switch (variable->varno)
+ {
+ case INNER_VAR:
+ scratch.opcode = EEOP_INNER_VAR_FIRST;
+ break;
+ case OUTER_VAR:
+ scratch.opcode = EEOP_OUTER_VAR_FIRST;
+ break;
+
+ /* INDEX_VAR is handled by default case */
+
+ default:
+ scratch.opcode = EEOP_SCAN_VAR_FIRST;
+ break;
+ }
+ }
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_Const:
+ {
+ Const *con = (Const *) node;
+
+ scratch.opcode = EEOP_CONST;
+ scratch.d.constval.value = con->constvalue;
+ scratch.d.constval.isnull = con->constisnull;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_Param:
+ {
+ Param *param = (Param *) node;
+
+ switch (param->paramkind)
+ {
+ case PARAM_EXEC:
+ scratch.opcode = EEOP_PARAM_EXEC;
+ scratch.d.param.paramid = param->paramid;
+ scratch.d.param.paramtype = param->paramtype;
+ break;
+ case PARAM_EXTERN:
+ scratch.opcode = EEOP_PARAM_EXTERN;
+ scratch.d.param.paramid = param->paramid;
+ scratch.d.param.paramtype = param->paramtype;
+ break;
+ default:
+ elog(ERROR, "unrecognized paramkind: %d",
+ (int) param->paramkind);
+ break;
+ }
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_Aggref:
+ {
+ Aggref *aggref = (Aggref *) node;
+ AggrefExprState *astate = makeNode(AggrefExprState);
+
+ scratch.opcode = EEOP_AGGREF;
+ scratch.d.aggref.astate = astate;
+ astate->aggref = aggref;
+
+ if (parent && IsA(parent, AggState))
+ {
+ AggState *aggstate = (AggState *) parent;
+
+ aggstate->aggs = lcons(astate, aggstate->aggs);
+ aggstate->numaggs++;
+ }
+ else
+ {
+ /* planner messed up */
+ elog(ERROR, "Aggref found in non-Agg plan node");
+ }
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_GroupingFunc:
+ {
+ GroupingFunc *grp_node = (GroupingFunc *) node;
+ Agg *agg;
+
+ if (!parent || !IsA(parent, AggState) ||
+ !IsA(parent->plan, Agg))
+ elog(ERROR, "GroupingFunc found in non-Agg plan node");
+
+ scratch.opcode = EEOP_GROUPING_FUNC;
+ scratch.d.grouping_func.parent = (AggState *) parent;
+
+ agg = (Agg *) (parent->plan);
+
+ if (agg->groupingSets)
+ scratch.d.grouping_func.clauses = grp_node->cols;
+ else
+ scratch.d.grouping_func.clauses = NIL;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_WindowFunc:
+ {
+ WindowFunc *wfunc = (WindowFunc *) node;
+ WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
+
+ wfstate->wfunc = wfunc;
+
+ if (parent && IsA(parent, WindowAggState))
+ {
+ WindowAggState *winstate = (WindowAggState *) parent;
+ int nfuncs;
+
+ winstate->funcs = lcons(wfstate, winstate->funcs);
+ nfuncs = ++winstate->numfuncs;
+ if (wfunc->winagg)
+ winstate->numaggs++;
+
+ /* for now initialize agg using old style expressions */
+ wfstate->args = ExecInitExprList(wfunc->args, parent);
+ wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
+ parent);
+
+ /*
+ * Complain if the windowfunc's arguments contain any
+ * windowfuncs; nested window functions are semantically
+ * nonsensical. (This should have been caught earlier,
+ * but we defend against it here anyway.)
+ */
+ if (nfuncs != winstate->numfuncs)
+ ereport(ERROR,
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("window function calls cannot be nested")));
+ }
+ else
+ {
+ /* planner messed up */
+ elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
+ }
+
+ scratch.opcode = EEOP_WINDOW_FUNC;
+ scratch.d.window_func.wfstate = wfstate;
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_ArrayRef:
+ {
+ ArrayRef *aref = (ArrayRef *) node;
+
+ ExecInitArrayRef(&scratch, aref, parent, state, resv, resnull);
+ break;
+ }
+
+ case T_FuncExpr:
+ {
+ FuncExpr *func = (FuncExpr *) node;
+
+ ExecInitFunc(&scratch, node,
+ func->args, func->funcid, func->inputcollid,
+ parent, state);
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_OpExpr:
+ {
+ OpExpr *op = (OpExpr *) node;
+
+ ExecInitFunc(&scratch, node,
+ op->args, op->opfuncid, op->inputcollid,
+ parent, state);
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_DistinctExpr:
+ {
+ DistinctExpr *op = (DistinctExpr *) node;
+
+ ExecInitFunc(&scratch, node,
+ op->args, op->opfuncid, op->inputcollid,
+ parent, state);
+
+ /*
+ * Change opcode of call instruction to EEOP_DISTINCT.
+ *
+ * XXX: historically we've not called the function usage
+ * pgstat infrastructure - that seems inconsistent given that
+ * we do so for normal function *and* operator evaluation. If
+ * we decided to do that here, we'd probably want separate
+ * opcodes for FUSAGE or not.
+ */
+ scratch.opcode = EEOP_DISTINCT;
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_NullIfExpr:
+ {
+ NullIfExpr *op = (NullIfExpr *) node;
+
+ ExecInitFunc(&scratch, node,
+ op->args, op->opfuncid, op->inputcollid,
+ parent, state);
+
+ /*
+ * Change opcode of call instruction to EEOP_NULLIF.
+ *
+ * XXX: historically we've not called the function usage
+ * pgstat infrastructure - that seems inconsistent given that
+ * we do so for normal function *and* operator evaluation. If
+ * we decided to do that here, we'd probably want separate
+ * opcodes for FUSAGE or not.
+ */
+ scratch.opcode = EEOP_NULLIF;
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_ScalarArrayOpExpr:
+ {
+ ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
+ Expr *scalararg;
+ Expr *arrayarg;
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo;
+ AclResult aclresult;
+
+ Assert(list_length(opexpr->args) == 2);
+ scalararg = (Expr *) linitial(opexpr->args);
+ arrayarg = (Expr *) lsecond(opexpr->args);
+
+ /* Check permission to call function */
+ aclresult = pg_proc_aclcheck(opexpr->opfuncid,
+ GetUserId(),
+ ACL_EXECUTE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_PROC,
+ get_func_name(opexpr->opfuncid));
+ InvokeFunctionExecuteHook(opexpr->opfuncid);
+
+ /* Set up the primary fmgr lookup information */
+ finfo = palloc0(sizeof(FmgrInfo));
+ fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fmgr_info(opexpr->opfuncid, finfo);
+ fmgr_info_set_expr((Node *) node, finfo);
+ InitFunctionCallInfoData(*fcinfo, finfo, 2,
+ opexpr->inputcollid, NULL, NULL);
+
+ /* Evaluate scalar directly into left function argument */
+ ExecInitExprRec(scalararg, parent, state,
+ &fcinfo->arg[0], &fcinfo->argnull[0]);
+
+ /*
+ * Evaluate array argument into our return value. There's no
+ * danger in that, because the return value is guaranteed to
+ * be overwritten by EEOP_SCALARARRAYOP, and will not be
+ * passed to any other expression.
+ */
+ ExecInitExprRec(arrayarg, parent, state, resv, resnull);
+
+ /* And perform the operation */
+ scratch.opcode = EEOP_SCALARARRAYOP;
+ scratch.d.scalararrayop.element_type = InvalidOid;
+ scratch.d.scalararrayop.useOr = opexpr->useOr;
+ scratch.d.scalararrayop.finfo = finfo;
+ scratch.d.scalararrayop.fcinfo_data = fcinfo;
+ scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_BoolExpr:
+ {
+ BoolExpr *boolexpr = (BoolExpr *) node;
+ int nargs = list_length(boolexpr->args);
+ List *adjust_jumps = NIL;
+ int off;
+ ListCell *lc;
+
+ /* allocate scratch memory used by all steps of AND/OR */
+ if (boolexpr->boolop != NOT_EXPR)
+ scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
+
+ /*
+ * For each argument evaluate the argument itself, then
+ * perform the bool operation's appropriate handling.
+ *
+ * We can evaluate each argument into our result area, since
+ * the short-circuiting logic means we only need to remember
+ * previous NULL values.
+ *
+ * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
+ * or more) / STEP_LAST (one) steps, as each of those has to
+ * perform different work. The FIRST/LAST split is valid
+ * because AND/OR have at least two arguments.
+ */
+ off = 0;
+ foreach(lc, boolexpr->args)
+ {
+ Expr *arg = (Expr *) lfirst(lc);
+
+ /* Evaluate argument into our output variable */
+ ExecInitExprRec(arg, parent, state, resv, resnull);
+
+ /* Perform the appropriate step type */
+ switch (boolexpr->boolop)
+ {
+ case AND_EXPR:
+ Assert(nargs >= 2);
+
+ if (off == 0)
+ scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
+ else if (off + 1 == nargs)
+ scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
+ else
+ scratch.opcode = EEOP_BOOL_AND_STEP;
+ break;
+ case OR_EXPR:
+ Assert(nargs >= 2);
+
+ if (off == 0)
+ scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
+ else if (off + 1 == nargs)
+ scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
+ else
+ scratch.opcode = EEOP_BOOL_OR_STEP;
+ break;
+ case NOT_EXPR:
+ Assert(nargs == 1);
+
+ scratch.opcode = EEOP_BOOL_NOT_STEP;
+ break;
+ default:
+ elog(ERROR, "unrecognized boolop: %d",
+ (int) boolexpr->boolop);
+ break;
+ }
+
+ scratch.d.boolexpr.jumpdone = -1;
+ ExprEvalPushStep(state, &scratch);
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ off++;
+ }
+
+ /* adjust jump targets */
+ foreach(lc, adjust_jumps)
+ {
+ ExprEvalStep *as = &state->steps[lfirst_int(lc)];
+
+ Assert(as->d.boolexpr.jumpdone == -1);
+ as->d.boolexpr.jumpdone = state->steps_len;
+ }
+
+ break;
+ }
+
+ case T_SubPlan:
+ {
+ SubPlan *subplan = (SubPlan *) node;
+ SubPlanState *sstate;
+
+ if (!parent)
+ elog(ERROR, "SubPlan found with no parent plan");
+
+ sstate = ExecInitSubPlan(subplan, parent);
+
+ /* add SubPlanState nodes to parent->subPlan */
+ parent->subPlan = lappend(parent->subPlan, sstate);
+
+ scratch.opcode = EEOP_SUBPLAN;
+ scratch.d.subplan.sstate = sstate;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_AlternativeSubPlan:
+ {
+ AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
+ AlternativeSubPlanState *asstate;
+
+ if (!parent)
+ elog(ERROR, "AlternativeSubPlan found with no parent plan");
+
+ asstate = ExecInitAlternativeSubPlan(asplan, parent);
+
+ scratch.opcode = EEOP_ALTERNATIVE_SUBPLAN;
+ scratch.d.alternative_subplan.asstate = asstate;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_FieldSelect:
+ {
+ FieldSelect *fselect = (FieldSelect *) node;
+
+ /* evaluate row/record argument into result area */
+ ExecInitExprRec(fselect->arg, parent, state, resv, resnull);
+
+ /* and extract field */
+ scratch.opcode = EEOP_FIELDSELECT;
+ scratch.d.fieldselect.fieldnum = fselect->fieldnum;
+ scratch.d.fieldselect.resulttype = fselect->resulttype;
+ scratch.d.fieldselect.argdesc = NULL;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_FieldStore:
+ {
+ FieldStore *fstore = (FieldStore *) node;
+ TupleDesc tupDesc;
+ TupleDesc *descp;
+ Datum *values;
+ bool *nulls;
+ int ncolumns;
+ ListCell *l1,
+ *l2;
+
+ /* find out the number of columns in the composite type */
+ tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
+ ncolumns = tupDesc->natts;
+ DecrTupleDescRefCount(tupDesc);
+
+ /* create workspace for column values */
+ values = (Datum *) palloc(sizeof(Datum) * ncolumns);
+ nulls = (bool *) palloc(sizeof(bool) * ncolumns);
+
+ /* create workspace for runtime tupdesc cache */
+ descp = (TupleDesc *) palloc(sizeof(TupleDesc));
+ *descp = NULL;
+
+ /* emit code to evaluate the composite input value */
+ ExecInitExprRec(fstore->arg, parent, state, resv, resnull);
+
+ /* next, deform the input tuple into our workspace */
+ scratch.opcode = EEOP_FIELDSTORE_DEFORM;
+ scratch.d.fieldstore.fstore = fstore;
+ scratch.d.fieldstore.argdesc = descp;
+ scratch.d.fieldstore.values = values;
+ scratch.d.fieldstore.nulls = nulls;
+ scratch.d.fieldstore.ncolumns = ncolumns;
+ ExprEvalPushStep(state, &scratch);
+
+ /* evaluate new field values, store in workspace columns */
+ forboth(l1, fstore->newvals, l2, fstore->fieldnums)
+ {
+ Expr *e = (Expr *) lfirst(l1);
+ AttrNumber fieldnum = lfirst_int(l2);
+ Datum *save_innermost_caseval;
+ bool *save_innermost_casenull;
+
+ if (fieldnum <= 0 || fieldnum > ncolumns)
+ elog(ERROR, "field number %d is out of range in FieldStore",
+ fieldnum);
+
+ /*
+ * Use the CaseTestExpr mechanism to pass down the old
+ * value of the field being replaced; this is needed in
+ * case the newval is itself a FieldStore or ArrayRef that
+ * has to obtain and modify the old value. It's safe to
+ * reuse the CASE mechanism because there cannot be a CASE
+ * between here and where the value would be needed, and a
+ * field assignment can't be within a CASE either. (So
+ * saving and restoring innermost_caseval is just
+ * paranoia, but let's do it anyway.)
+ */
+ save_innermost_caseval = state->innermost_caseval;
+ save_innermost_casenull = state->innermost_casenull;
+ state->innermost_caseval = &values[fieldnum - 1];
+ state->innermost_casenull = &nulls[fieldnum - 1];
+
+ ExecInitExprRec(e, parent, state,
+ &values[fieldnum - 1],
+ &nulls[fieldnum - 1]);
+
+ state->innermost_caseval = save_innermost_caseval;
+ state->innermost_casenull = save_innermost_casenull;
+ }
+
+ /* finally, form result tuple */
+ scratch.opcode = EEOP_FIELDSTORE_FORM;
+ scratch.d.fieldstore.fstore = fstore;
+ scratch.d.fieldstore.argdesc = descp;
+ scratch.d.fieldstore.values = values;
+ scratch.d.fieldstore.nulls = nulls;
+ scratch.d.fieldstore.ncolumns = ncolumns;
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_RelabelType:
+ {
+ /* relabel doesn't need to do anything at runtime */
+ RelabelType *relabel = (RelabelType *) node;
+
+ ExecInitExprRec(relabel->arg, parent, state, resv, resnull);
+ break;
+ }
+
+ case T_CoerceViaIO:
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+ Oid iofunc;
+ bool typisvarlena;
+ Oid typioparam;
+ FunctionCallInfo fcinfo_in;
+
+ /* evaluate argument into step's result area */
+ ExecInitExprRec(iocoerce->arg, parent, state, resv, resnull);
+
+ /*
+ * Prepare both output and input function calls, to be
+ * evaluated inside a single evaluation step for speed - this
+ * can be a very common operation.
+ *
+ * We don't check permissions here as a type's input/output
+ * function are assumed to be executable by everyone.
+ */
+ scratch.opcode = EEOP_IOCOERCE;
+
+ /* lookup the source type's output function */
+ scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
+ scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData));
+
+ getTypeOutputInfo(exprType((Node *) iocoerce->arg),
+ &iofunc, &typisvarlena);
+ fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
+ fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
+ InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
+ scratch.d.iocoerce.finfo_out,
+ 1, InvalidOid, NULL, NULL);
+
+ /* lookup the result type's input function */
+ scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
+ scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData));
+
+ getTypeInputInfo(iocoerce->resulttype,
+ &iofunc, &typioparam);
+ fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
+ fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
+ InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
+ scratch.d.iocoerce.finfo_in,
+ 3, InvalidOid, NULL, NULL);
+
+ /*
+ * We can preload the second and third arguments for the input
+ * function, since they're constants.
+ */
+ fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
+ fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam);
+ fcinfo_in->argnull[1] = false;
+ fcinfo_in->arg[2] = Int32GetDatum(-1);
+ fcinfo_in->argnull[2] = false;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_ArrayCoerceExpr:
+ {
+ ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
+ Oid resultelemtype;
+
+ /* evaluate argument into step's result area */
+ ExecInitExprRec(acoerce->arg, parent, state, resv, resnull);
+
+ resultelemtype = get_element_type(acoerce->resulttype);
+ if (!OidIsValid(resultelemtype))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("target type is not an array")));
+ /* Arrays over domains aren't supported yet */
+ Assert(getBaseType(resultelemtype) == resultelemtype);
+
+ scratch.opcode = EEOP_ARRAYCOERCE;
+ scratch.d.arraycoerce.coerceexpr = acoerce;
+ scratch.d.arraycoerce.resultelemtype = resultelemtype;
+
+ if (OidIsValid(acoerce->elemfuncid))
+ {
+ AclResult aclresult;
+
+ /* Check permission to call function */
+ aclresult = pg_proc_aclcheck(acoerce->elemfuncid,
+ GetUserId(),
+ ACL_EXECUTE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_PROC,
+ get_func_name(acoerce->elemfuncid));
+ InvokeFunctionExecuteHook(acoerce->elemfuncid);
+
+ /* Set up the primary fmgr lookup information */
+ scratch.d.arraycoerce.elemfunc =
+ (FmgrInfo *) palloc0(sizeof(FmgrInfo));
+ fmgr_info(acoerce->elemfuncid,
+ scratch.d.arraycoerce.elemfunc);
+ fmgr_info_set_expr((Node *) acoerce,
+ scratch.d.arraycoerce.elemfunc);
+
+ /* Set up workspace for array_map */
+ scratch.d.arraycoerce.amstate =
+ (ArrayMapState *) palloc0(sizeof(ArrayMapState));
+ }
+ else
+ {
+ /* Don't need workspace if there's no conversion func */
+ scratch.d.arraycoerce.elemfunc = NULL;
+ scratch.d.arraycoerce.amstate = NULL;
+ }
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_ConvertRowtypeExpr:
+ {
+ ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
+
+ /* evaluate argument into step's result area */
+ ExecInitExprRec(convert->arg, parent, state, resv, resnull);
+
+ /* and push conversion step */
+ scratch.opcode = EEOP_CONVERT_ROWTYPE;
+ scratch.d.convert_rowtype.convert = convert;
+ scratch.d.convert_rowtype.indesc = NULL;
+ scratch.d.convert_rowtype.outdesc = NULL;
+ scratch.d.convert_rowtype.map = NULL;
+ scratch.d.convert_rowtype.initialized = false;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ /* note that CaseWhen expressions are handled within this block */
+ case T_CaseExpr:
+ {
+ CaseExpr *caseExpr = (CaseExpr *) node;
+ List *adjust_jumps = NIL;
+ Datum *caseval = NULL;
+ bool *casenull = NULL;
+ ListCell *lc;
+
+ /*
+ * If there's a test expression, we have to evaluate it and
+ * save the value where the CaseTestExpr placeholders can find
+ * it.
+ */
+ if (caseExpr->arg != NULL)
+ {
+ /* Evaluate testexpr into caseval/casenull workspace */
+ caseval = palloc(sizeof(Datum));
+ casenull = palloc(sizeof(bool));
+
+ ExecInitExprRec(caseExpr->arg, parent, state,
+ caseval, casenull);
+
+ /*
+ * Since value might be read multiple times, force to R/O
+ * - but only if it could be an expanded datum.
+ */
+ if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
+ {
+ /* change caseval in-place */
+ scratch.opcode = EEOP_MAKE_READONLY;
+ scratch.resvalue = caseval;
+ scratch.resnull = casenull;
+ scratch.d.make_readonly.value = caseval;
+ scratch.d.make_readonly.isnull = casenull;
+ ExprEvalPushStep(state, &scratch);
+ /* restore normal settings of scratch fields */
+ scratch.resvalue = resv;
+ scratch.resnull = resnull;
+ }
+ }
+
+ /*
+ * Prepare to evaluate each of the WHEN clauses in turn; as
+ * soon as one is true we return the value of the
+ * corresponding THEN clause. If none are true then we return
+ * the value of the ELSE clause, or NULL if there is none.
+ */
+ foreach(lc, caseExpr->args)
+ {
+ CaseWhen *when = (CaseWhen *) lfirst(lc);
+ Datum *save_innermost_caseval;
+ bool *save_innermost_casenull;
+ int whenstep;
+
+ /*
+ * Make testexpr result available to CaseTestExpr nodes
+ * within the condition. We must save and restore prior
+ * setting of innermost_caseval fields, in case this node
+ * is itself within a larger CASE.
+ *
+ * If there's no test expression, we don't actually need
+ * to save and restore these fields; but it's less code to
+ * just do so unconditionally.
+ */
+ save_innermost_caseval = state->innermost_caseval;
+ save_innermost_casenull = state->innermost_casenull;
+ state->innermost_caseval = caseval;
+ state->innermost_casenull = casenull;
+
+ /* evaluate condition into CASE's result variables */
+ ExecInitExprRec(when->expr, parent, state, resv, resnull);
+
+ state->innermost_caseval = save_innermost_caseval;
+ state->innermost_casenull = save_innermost_casenull;
+
+ /* If WHEN result isn't true, jump to next CASE arm */
+ scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
+ scratch.d.jump.jumpdone = -1; /* computed later */
+ ExprEvalPushStep(state, &scratch);
+ whenstep = state->steps_len - 1;
+
+ /*
+ * If WHEN result is true, evaluate THEN result, storing
+ * it into the CASE's result variables.
+ */
+ ExecInitExprRec(when->result, parent, state, resv, resnull);
+
+ /* Emit JUMP step to jump to end of CASE's code */
+ scratch.opcode = EEOP_JUMP;
+ scratch.d.jump.jumpdone = -1; /* computed later */
+ ExprEvalPushStep(state, &scratch);
+
+ /*
+ * Don't know address for that jump yet, compute once the
+ * whole CASE expression is built.
+ */
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+
+ /*
+ * But we can set WHEN test's jump target now, to make it
+ * jump to the next WHEN subexpression or the ELSE.
+ */
+ state->steps[whenstep].d.jump.jumpdone = state->steps_len;
+ }
+
+ /* transformCaseExpr always adds a default */
+ Assert(caseExpr->defresult);
+
+ /* evaluate ELSE expr into CASE's result variables */
+ ExecInitExprRec(caseExpr->defresult, parent, state,
+ resv, resnull);
+
+ /* adjust jump targets */
+ foreach(lc, adjust_jumps)
+ {
+ ExprEvalStep *as = &state->steps[lfirst_int(lc)];
+
+ Assert(as->opcode == EEOP_JUMP);
+ Assert(as->d.jump.jumpdone == -1);
+ as->d.jump.jumpdone = state->steps_len;
+ }
+
+ break;
+ }
+
+ case T_CaseTestExpr:
+ {
+ /*
+ * Read from location identified by innermost_caseval. Note
+ * that innermost_caseval could be NULL, if this node isn't
+ * actually within a CASE structure; some parts of the system
+ * abuse CaseTestExpr to cause a read of a value externally
+ * supplied in econtext->caseValue_datum. We'll take care of
+ * that scenario at runtime.
+ */
+ scratch.opcode = EEOP_CASE_TESTVAL;
+ scratch.d.casetest.value = state->innermost_caseval;
+ scratch.d.casetest.isnull = state->innermost_casenull;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_ArrayExpr:
+ {
+ ArrayExpr *arrayexpr = (ArrayExpr *) node;
+ int nelems = list_length(arrayexpr->elements);
+ ListCell *lc;
+ int elemoff;
+
+ /*
+ * Evaluate by computing each element, and then forming the
+ * array. Elements are computed into scratch arrays
+ * associated with the ARRAYEXPR step.
+ */
+ scratch.opcode = EEOP_ARRAYEXPR;
+ scratch.d.arrayexpr.elemvalues =
+ (Datum *) palloc(sizeof(Datum) * nelems);
+ scratch.d.arrayexpr.elemnulls =
+ (bool *) palloc(sizeof(bool) * nelems);
+ scratch.d.arrayexpr.nelems = nelems;
+
+ /* fill remaining fields of step */
+ scratch.d.arrayexpr.multidims = arrayexpr->multidims;
+ scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
+
+ /* do one-time catalog lookup for type info */
+ get_typlenbyvalalign(arrayexpr->element_typeid,
+ &scratch.d.arrayexpr.elemlength,
+ &scratch.d.arrayexpr.elembyval,
+ &scratch.d.arrayexpr.elemalign);
+
+ /* prepare to evaluate all arguments */
+ elemoff = 0;
+ foreach(lc, arrayexpr->elements)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+
+ ExecInitExprRec(e, parent, state,
+ &scratch.d.arrayexpr.elemvalues[elemoff],
+ &scratch.d.arrayexpr.elemnulls[elemoff]);
+ elemoff++;
+ }
+
+ /* and then collect all into an array */
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_RowExpr:
+ {
+ RowExpr *rowexpr = (RowExpr *) node;
+ int nelems = list_length(rowexpr->args);
+ TupleDesc tupdesc;
+ Form_pg_attribute *attrs;
+ int i;
+ ListCell *l;
+
+ /* Build tupdesc to describe result tuples */
+ if (rowexpr->row_typeid == RECORDOID)
+ {
+ /* generic record, use types of given expressions */
+ tupdesc = ExecTypeFromExprList(rowexpr->args);
+ }
+ else
+ {
+ /* it's been cast to a named type, use that */
+ tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
+ }
+ /* In either case, adopt RowExpr's column aliases */
+ ExecTypeSetColNames(tupdesc, rowexpr->colnames);
+ /* Bless the tupdesc in case it's now of type RECORD */
+ BlessTupleDesc(tupdesc);
+
+ /*
+ * In the named-type case, the tupdesc could have more columns
+ * than are in the args list, since the type might have had
+ * columns added since the ROW() was parsed. We want those
+ * extra columns to go to nulls, so we make sure that the
+ * workspace arrays are large enough and then initialize any
+ * extra columns to read as NULLs.
+ */
+ Assert(nelems <= tupdesc->natts);
+ nelems = Max(nelems, tupdesc->natts);
+
+ /*
+ * Evaluate by first building datums for each field, and then
+ * a final step forming the composite datum.
+ */
+ scratch.opcode = EEOP_ROW;
+ scratch.d.row.tupdesc = tupdesc;
+
+ /* space for the individual field datums */
+ scratch.d.row.elemvalues =
+ (Datum *) palloc(sizeof(Datum) * nelems);
+ scratch.d.row.elemnulls =
+ (bool *) palloc(sizeof(bool) * nelems);
+ /* as explained above, make sure any extra columns are null */
+ memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
+
+ /* Set up evaluation, skipping any deleted columns */
+ attrs = tupdesc->attrs;
+ i = 0;
+ foreach(l, rowexpr->args)
+ {
+ Expr *e = (Expr *) lfirst(l);
+
+ if (!attrs[i]->attisdropped)
+ {
+ /*
+ * Guard against ALTER COLUMN TYPE on rowtype since
+ * the RowExpr was created. XXX should we check
+ * typmod too? Not sure we can be sure it'll be the
+ * same.
+ */
+ if (exprType((Node *) e) != attrs[i]->atttypid)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("ROW() column has type %s instead of type %s",
+ format_type_be(exprType((Node *) e)),
+ format_type_be(attrs[i]->atttypid))));
+ }
+ else
+ {
+ /*
+ * Ignore original expression and insert a NULL. We
+ * don't really care what type of NULL it is, so
+ * always make an int4 NULL.
+ */
+ e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
+ }
+
+ /* Evaluate column expr into appropriate workspace slot */
+ ExecInitExprRec(e, parent, state,
+ &scratch.d.row.elemvalues[i],
+ &scratch.d.row.elemnulls[i]);
+ i++;
+ }
+
+ /* And finally build the row value */
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_RowCompareExpr:
+ {
+ RowCompareExpr *rcexpr = (RowCompareExpr *) node;
+ int nopers = list_length(rcexpr->opnos);
+ List *adjust_jumps = NIL;
+ ListCell *l_left_expr,
+ *l_right_expr,
+ *l_opno,
+ *l_opfamily,
+ *l_inputcollid;
+ ListCell *lc;
+ int off;
+
+ /*
+ * Iterate over each field, prepare comparisons. To handle
+ * NULL results, prepare jumps to after the expression. If a
+ * comparison yields a != 0 result, jump to the final step.
+ */
+ Assert(list_length(rcexpr->largs) == nopers);
+ Assert(list_length(rcexpr->rargs) == nopers);
+ Assert(list_length(rcexpr->opfamilies) == nopers);
+ Assert(list_length(rcexpr->inputcollids) == nopers);
+
+ off = 0;
+ for (off = 0,
+ l_left_expr = list_head(rcexpr->largs),
+ l_right_expr = list_head(rcexpr->rargs),
+ l_opno = list_head(rcexpr->opnos),
+ l_opfamily = list_head(rcexpr->opfamilies),
+ l_inputcollid = list_head(rcexpr->inputcollids);
+ off < nopers;
+ off++,
+ l_left_expr = lnext(l_left_expr),
+ l_right_expr = lnext(l_right_expr),
+ l_opno = lnext(l_opno),
+ l_opfamily = lnext(l_opfamily),
+ l_inputcollid = lnext(l_inputcollid))
+ {
+ Expr *left_expr = (Expr *) lfirst(l_left_expr);
+ Expr *right_expr = (Expr *) lfirst(l_right_expr);
+ Oid opno = lfirst_oid(l_opno);
+ Oid opfamily = lfirst_oid(l_opfamily);
+ Oid inputcollid = lfirst_oid(l_inputcollid);
+ int strategy;
+ Oid lefttype;
+ Oid righttype;
+ Oid proc;
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo;
+
+ get_op_opfamily_properties(opno, opfamily, false,
+ &strategy,
+ &lefttype,
+ &righttype);
+ proc = get_opfamily_proc(opfamily,
+ lefttype,
+ righttype,
+ BTORDER_PROC);
+
+ /* Set up the primary fmgr lookup information */
+ finfo = palloc0(sizeof(FmgrInfo));
+ fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fmgr_info(proc, finfo);
+ fmgr_info_set_expr((Node *) node, finfo);
+ InitFunctionCallInfoData(*fcinfo, finfo, 2,
+ inputcollid, NULL, NULL);
+
+ /*
+ * If we enforced permissions checks on index support
+ * functions, we'd need to make a check here. But the
+ * index support machinery doesn't do that, and thus
+ * neither does this code.
+ */
+
+ /* evaluate left and right args directly into fcinfo */
+ ExecInitExprRec(left_expr, parent, state,
+ &fcinfo->arg[0], &fcinfo->argnull[0]);
+ ExecInitExprRec(right_expr, parent, state,
+ &fcinfo->arg[1], &fcinfo->argnull[1]);
+
+ scratch.opcode = EEOP_ROWCOMPARE_STEP;
+ scratch.d.rowcompare_step.finfo = finfo;
+ scratch.d.rowcompare_step.fcinfo_data = fcinfo;
+ scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
+ /* jump targets filled below */
+ scratch.d.rowcompare_step.jumpnull = -1;
+ scratch.d.rowcompare_step.jumpdone = -1;
+
+ ExprEvalPushStep(state, &scratch);
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ }
+
+ /*
+ * We could have a zero-column rowtype, in which case the rows
+ * necessarily compare equal.
+ */
+ if (nopers == 0)
+ {
+ scratch.opcode = EEOP_CONST;
+ scratch.d.constval.value = Int32GetDatum(0);
+ scratch.d.constval.isnull = false;
+ ExprEvalPushStep(state, &scratch);
+ }
+
+ /* Finally, examine the last comparison result */
+ scratch.opcode = EEOP_ROWCOMPARE_FINAL;
+ scratch.d.rowcompare_final.rctype = rcexpr->rctype;
+ ExprEvalPushStep(state, &scratch);
+
+ /* adjust jump targetss */
+ foreach(lc, adjust_jumps)
+ {
+ ExprEvalStep *as = &state->steps[lfirst_int(lc)];
+
+ Assert(as->opcode == EEOP_ROWCOMPARE_STEP);
+ Assert(as->d.rowcompare_step.jumpdone == -1);
+ Assert(as->d.rowcompare_step.jumpnull == -1);
+
+ /* jump to comparison evaluation */
+ as->d.rowcompare_step.jumpdone = state->steps_len - 1;
+ /* jump to the following expression */
+ as->d.rowcompare_step.jumpnull = state->steps_len;
+ }
+
+ break;
+ }
+
+ case T_CoalesceExpr:
+ {
+ CoalesceExpr *coalesce = (CoalesceExpr *) node;
+ List *adjust_jumps = NIL;
+ ListCell *lc;
+
+ /* We assume there's at least one arg */
+ Assert(coalesce->args != NIL);
+
+ /*
+ * Prepare evaluation of all coalesced arguments, after each
+ * one push a step that short-circuits if not null.
+ */
+ foreach(lc, coalesce->args)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+
+ /* evaluate argument, directly into result datum */
+ ExecInitExprRec(e, parent, state, resv, resnull);
+
+ /* if it's not null, skip to end of COALESCE expr */
+ scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
+ scratch.d.jump.jumpdone = -1; /* adjust later */
+ ExprEvalPushStep(state, &scratch);
+
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ }
+
+ /*
+ * No need to add a constant NULL return - we only can get to
+ * the end of the expression if a NULL already is being
+ * returned.
+ */
+
+ /* adjust jump targets */
+ foreach(lc, adjust_jumps)
+ {
+ ExprEvalStep *as = &state->steps[lfirst_int(lc)];
+
+ Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL);
+ Assert(as->d.jump.jumpdone == -1);
+ as->d.jump.jumpdone = state->steps_len;
+ }
+
+ break;
+ }
+
+ case T_MinMaxExpr:
+ {
+ MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
+ int nelems = list_length(minmaxexpr->args);
+ TypeCacheEntry *typentry;
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo;
+ ListCell *lc;
+ int off;
+
+ /* Look up the btree comparison function for the datatype */
+ typentry = lookup_type_cache(minmaxexpr->minmaxtype,
+ TYPECACHE_CMP_PROC);
+ if (!OidIsValid(typentry->cmp_proc))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify a comparison function for type %s",
+ format_type_be(minmaxexpr->minmaxtype))));
+
+ /*
+ * If we enforced permissions checks on index support
+ * functions, we'd need to make a check here. But the index
+ * support machinery doesn't do that, and thus neither does
+ * this code.
+ */
+
+ /* Perform function lookup */
+ finfo = palloc0(sizeof(FmgrInfo));
+ fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fmgr_info(typentry->cmp_proc, finfo);
+ fmgr_info_set_expr((Node *) node, finfo);
+ InitFunctionCallInfoData(*fcinfo, finfo, 2,
+ minmaxexpr->inputcollid, NULL, NULL);
+
+ scratch.opcode = EEOP_MINMAX;
+ /* allocate space to store arguments */
+ scratch.d.minmax.values =
+ (Datum *) palloc(sizeof(Datum) * nelems);
+ scratch.d.minmax.nulls =
+ (bool *) palloc(sizeof(bool) * nelems);
+ scratch.d.minmax.nelems = nelems;
+
+ scratch.d.minmax.op = minmaxexpr->op;
+ scratch.d.minmax.finfo = finfo;
+ scratch.d.minmax.fcinfo_data = fcinfo;
+
+ /* evaluate expressions into minmax->values/nulls */
+ off = 0;
+ foreach(lc, minmaxexpr->args)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+
+ ExecInitExprRec(e, parent, state,
+ &scratch.d.minmax.values[off],
+ &scratch.d.minmax.nulls[off]);
+ off++;
+ }
+
+ /* and push the final comparison */
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_SQLValueFunction:
+ {
+ SQLValueFunction *svf = (SQLValueFunction *) node;
+
+ scratch.opcode = EEOP_SQLVALUEFUNCTION;
+ scratch.d.sqlvaluefunction.svf = svf;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_XmlExpr:
+ {
+ XmlExpr *xexpr = (XmlExpr *) node;
+ int nnamed = list_length(xexpr->named_args);
+ int nargs = list_length(xexpr->args);
+ int off;
+ ListCell *arg;
+
+ scratch.opcode = EEOP_XMLEXPR;
+ scratch.d.xmlexpr.xexpr = xexpr;
+
+ /* allocate space for storing all the arguments */
+ if (nnamed)
+ {
+ scratch.d.xmlexpr.named_argvalue =
+ (Datum *) palloc(sizeof(Datum) * nnamed);
+ scratch.d.xmlexpr.named_argnull =
+ (bool *) palloc(sizeof(bool) * nnamed);
+ }
+ else
+ {
+ scratch.d.xmlexpr.named_argvalue = NULL;
+ scratch.d.xmlexpr.named_argnull = NULL;
+ }
+
+ if (nargs)
+ {
+ scratch.d.xmlexpr.argvalue =
+ (Datum *) palloc(sizeof(Datum) * nargs);
+ scratch.d.xmlexpr.argnull =
+ (bool *) palloc(sizeof(bool) * nargs);
+ }
+ else
+ {
+ scratch.d.xmlexpr.argvalue = NULL;
+ scratch.d.xmlexpr.argnull = NULL;
+ }
+
+ /* prepare argument execution */
+ off = 0;
+ foreach(arg, xexpr->named_args)
+ {
+ Expr *e = (Expr *) lfirst(arg);
+
+ ExecInitExprRec(e, parent, state,
+ &scratch.d.xmlexpr.named_argvalue[off],
+ &scratch.d.xmlexpr.named_argnull[off]);
+ off++;
+ }
+
+ off = 0;
+ foreach(arg, xexpr->args)
+ {
+ Expr *e = (Expr *) lfirst(arg);
+
+ ExecInitExprRec(e, parent, state,
+ &scratch.d.xmlexpr.argvalue[off],
+ &scratch.d.xmlexpr.argnull[off]);
+ off++;
+ }
+
+ /* and evaluate the actual XML expression */
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_NullTest:
+ {
+ NullTest *ntest = (NullTest *) node;
+
+ if (ntest->nulltesttype == IS_NULL)
+ {
+ if (ntest->argisrow)
+ scratch.opcode = EEOP_NULLTEST_ROWISNULL;
+ else
+ scratch.opcode = EEOP_NULLTEST_ISNULL;
+ }
+ else if (ntest->nulltesttype == IS_NOT_NULL)
+ {
+ if (ntest->argisrow)
+ scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL;
+ else
+ scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
+ }
+ else
+ {
+ elog(ERROR, "unrecognized nulltesttype: %d",
+ (int) ntest->nulltesttype);
+ }
+ /* initialize cache in case it's a row test */
+ scratch.d.nulltest_row.argdesc = NULL;
+
+ /* first evaluate argument into result variable */
+ ExecInitExprRec(ntest->arg, parent, state,
+ resv, resnull);
+
+ /* then push the test of that argument */
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_BooleanTest:
+ {
+ BooleanTest *btest = (BooleanTest *) node;
+
+ /*
+ * Evaluate argument, directly into result datum. That's ok,
+ * because resv/resnull is definitely not used anywhere else,
+ * and will get overwritten by the below EEOP_BOOLTEST_IS_*
+ * step.
+ */
+ ExecInitExprRec(btest->arg, parent, state, resv, resnull);
+
+ switch (btest->booltesttype)
+ {
+ case IS_TRUE:
+ scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
+ break;
+ case IS_NOT_TRUE:
+ scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE;
+ break;
+ case IS_FALSE:
+ scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
+ break;
+ case IS_NOT_FALSE:
+ scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE;
+ break;
+ case IS_UNKNOWN:
+ /* Same as scalar IS NULL test */
+ scratch.opcode = EEOP_NULLTEST_ISNULL;
+ break;
+ case IS_NOT_UNKNOWN:
+ /* Same as scalar IS NOT NULL test */
+ scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
+ break;
+ default:
+ elog(ERROR, "unrecognized booltesttype: %d",
+ (int) btest->booltesttype);
+ }
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_CoerceToDomain:
+ {
+ CoerceToDomain *ctest = (CoerceToDomain *) node;
+
+ ExecInitCoerceToDomain(&scratch, ctest, parent, state,
+ resv, resnull);
+ break;
+ }
+
+ case T_CoerceToDomainValue:
+ {
+ /*
+ * Read from location identified by innermost_domainval. Note
+ * that innermost_domainval could be NULL, if we're compiling
+ * a standalone domain check rather than one embedded in a
+ * larger expression. In that case we must read from
+ * econtext->domainValue_datum. We'll take care of that
+ * scenario at runtime.
+ */
+ scratch.opcode = EEOP_DOMAIN_TESTVAL;
+ /* we share instruction union variant with case testval */
+ scratch.d.casetest.value = state->innermost_domainval;
+ scratch.d.casetest.isnull = state->innermost_domainnull;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_CurrentOfExpr:
+ {
+ scratch.opcode = EEOP_CURRENTOFEXPR;
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ case T_NextValueExpr:
+ {
+ NextValueExpr *nve = (NextValueExpr *) node;
+
+ scratch.opcode = EEOP_NEXTVALUEEXPR;
+ scratch.d.nextvalueexpr.seqid = nve->seqid;
+ scratch.d.nextvalueexpr.seqtypid = nve->typeId;
+
+ ExprEvalPushStep(state, &scratch);
+ break;
+ }
+
+ default:
+ elog(ERROR, "unrecognized node type: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+/*
+ * Add another expression evaluation step to ExprState->steps.
+ *
+ * Note that this potentially re-allocates es->steps, therefore no pointer
+ * into that array may be used while the expression is still being built.
+ */
+static void
+ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
+{
+ if (es->steps_alloc == 0)
+ {
+ es->steps_alloc = 16;
+ es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
+ }
+ else if (es->steps_alloc == es->steps_len)
+ {
+ es->steps_alloc *= 2;
+ es->steps = repalloc(es->steps,
+ sizeof(ExprEvalStep) * es->steps_alloc);
+ }
+
+ memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
+}
+
+/*
+ * Perform setup necessary for the evaluation of a function-like expression,
+ * appending argument evaluation steps to the steps list in *state, and
+ * setting up *scratch so it is ready to be pushed.
+ *
+ * *scratch is not pushed here, so that callers may override the opcode,
+ * which is useful for function-like cases like DISTINCT.
+ */
+static void
+ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
+ Oid inputcollid, PlanState *parent, ExprState *state)
+{
+ int nargs = list_length(args);
+ AclResult aclresult;
+ FmgrInfo *flinfo;
+ FunctionCallInfo fcinfo;
+ int argno;
+ ListCell *lc;
+
+ /* Check permission to call function */
+ aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(funcid));
+ InvokeFunctionExecuteHook(funcid);
+
+ /*
+ * Safety check on nargs. Under normal circumstances this should never
+ * fail, as parser should check sooner. But possibly it might fail if
+ * server has been compiled with FUNC_MAX_ARGS smaller than some functions
+ * declared in pg_proc?
+ */
+ if (nargs > FUNC_MAX_ARGS)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+ errmsg_plural("cannot pass more than %d argument to a function",
+ "cannot pass more than %d arguments to a function",
+ FUNC_MAX_ARGS,
+ FUNC_MAX_ARGS)));
+
+ /* Allocate function lookup data and parameter workspace for this call */
+ scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
+ scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
+ flinfo = scratch->d.func.finfo;
+ fcinfo = scratch->d.func.fcinfo_data;
+
+ /* Set up the primary fmgr lookup information */
+ fmgr_info(funcid, flinfo);
+ fmgr_info_set_expr((Node *) node, flinfo);
+
+ /* Initialize function call parameter structure too */
+ InitFunctionCallInfoData(*fcinfo, flinfo,
+ nargs, inputcollid, NULL, NULL);
+
+ /* Keep extra copies of this info to save an indirection at runtime */
+ scratch->d.func.fn_addr = flinfo->fn_addr;
+ scratch->d.func.nargs = nargs;
+
+ /* We only support non-set functions here */
+ if (flinfo->fn_retset)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("set-valued function called in context that cannot accept a set"),
+ parent ? executor_errposition(parent->state,
+ exprLocation((Node *) node)) : 0));
+
+ /* Build code to evaluate arguments directly into the fcinfo struct */
+ argno = 0;
+ foreach(lc, args)
+ {
+ Expr *arg = (Expr *) lfirst(lc);
+
+ if (IsA(arg, Const))
+ {
+ /*
+ * Don't evaluate const arguments every round; especially
+ * interesting for constants in comparisons.
+ */
+ Const *con = (Const *) arg;
+
+ fcinfo->arg[argno] = con->constvalue;
+ fcinfo->argnull[argno] = con->constisnull;
+ }
+ else
+ {
+ ExecInitExprRec(arg, parent, state,
+ &fcinfo->arg[argno], &fcinfo->argnull[argno]);
+ }
+ argno++;
+ }
+
+ /* Insert appropriate opcode depending on strictness and stats level */
+ if (pgstat_track_functions <= flinfo->fn_stats)
+ {
+ if (flinfo->fn_strict && nargs > 0)
+ scratch->opcode = EEOP_FUNCEXPR_STRICT;
+ else
+ scratch->opcode = EEOP_FUNCEXPR;
+ }
+ else
+ {
+ if (flinfo->fn_strict && nargs > 0)
+ scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE;
+ else
+ scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
+ }
+}
+
+/*
+ * Add expression steps deforming the ExprState's inner/outer/scan slots
+ * as much as required by the expression.
+ */
+static void
+ExecInitExprSlots(ExprState *state, Node *node)
+{
+ LastAttnumInfo info = {0, 0, 0};
+ ExprEvalStep scratch;
+
+ /*
+ * Figure out which attributes we're going to need.
+ */
+ get_last_attnums_walker(node, &info);
+
+ /* Emit steps as needed */
+ if (info.last_inner > 0)
+ {
+ scratch.opcode = EEOP_INNER_FETCHSOME;
+ scratch.d.fetch.last_var = info.last_inner;
+ ExprEvalPushStep(state, &scratch);
+ }
+ if (info.last_outer > 0)
+ {
+ scratch.opcode = EEOP_OUTER_FETCHSOME;
+ scratch.d.fetch.last_var = info.last_outer;
+ ExprEvalPushStep(state, &scratch);
+ }
+ if (info.last_scan > 0)
+ {
+ scratch.opcode = EEOP_SCAN_FETCHSOME;
+ scratch.d.fetch.last_var = info.last_scan;
+ ExprEvalPushStep(state, &scratch);
+ }
+}
+
+/*
+ * get_last_attnums_walker: expression walker for ExecInitExprSlots
+ */
+static bool
+get_last_attnums_walker(Node *node, LastAttnumInfo *info)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Var))
+ {
+ Var *variable = (Var *) node;
+ AttrNumber attnum = variable->varattno;
+
+ switch (variable->varno)
+ {
+ case INNER_VAR:
+ info->last_inner = Max(info->last_inner, attnum);
+ break;
+
+ case OUTER_VAR:
+ info->last_outer = Max(info->last_outer, attnum);
+ break;
+
+ /* INDEX_VAR is handled by default case */
+
+ default:
+ info->last_scan = Max(info->last_scan, attnum);
+ break;
+ }
+ return false;
+ }
+
+ /*
+ * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
+ * because those do not represent expressions to be evaluated within the
+ * calling expression's econtext. GroupingFunc arguments are never
+ * evaluated at all.
+ */
+ if (IsA(node, Aggref))
+ return false;
+ if (IsA(node, WindowFunc))
+ return false;
+ if (IsA(node, GroupingFunc))
+ return false;
+ return expression_tree_walker(node, get_last_attnums_walker,
+ (void *) info);
+}
+
+/*
+ * Prepare step for the evaluation of a whole-row variable.
+ * The caller still has to push the step.
+ */
+static void
+ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, PlanState *parent)
+{
+ /* fill in all but the target */
+ scratch->opcode = EEOP_WHOLEROW;
+ scratch->d.wholerow.var = variable;
+ scratch->d.wholerow.first = true;
+ scratch->d.wholerow.slow = false;
+ scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
+ scratch->d.wholerow.junkFilter = NULL;
+
+ /*
+ * If the input tuple came from a subquery, it might contain "resjunk"
+ * columns (such as GROUP BY or ORDER BY columns), which we don't want to
+ * keep in the whole-row result. We can get rid of such columns by
+ * passing the tuple through a JunkFilter --- but to make one, we have to
+ * lay our hands on the subquery's targetlist. Fortunately, there are not
+ * very many cases where this can happen, and we can identify all of them
+ * by examining our parent PlanState. We assume this is not an issue in
+ * standalone expressions that don't have parent plans. (Whole-row Vars
+ * can occur in such expressions, but they will always be referencing
+ * table rows.)
+ */
+ if (parent)
+ {
+ PlanState *subplan = NULL;
+
+ switch (nodeTag(parent))
+ {
+ case T_SubqueryScanState:
+ subplan = ((SubqueryScanState *) parent)->subplan;
+ break;
+ case T_CteScanState:
+ subplan = ((CteScanState *) parent)->cteplanstate;
+ break;
+ default:
+ break;
+ }
+
+ if (subplan)
+ {
+ bool junk_filter_needed = false;
+ ListCell *tlist;
+
+ /* Detect whether subplan tlist actually has any junk columns */
+ foreach(tlist, subplan->plan->targetlist)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(tlist);
+
+ if (tle->resjunk)
+ {
+ junk_filter_needed = true;
+ break;
+ }
+ }
+
+ /* If so, build the junkfilter now */
+ if (junk_filter_needed)
+ {
+ scratch->d.wholerow.junkFilter =
+ ExecInitJunkFilter(subplan->plan->targetlist,
+ ExecGetResultType(subplan)->tdhasoid,
+ ExecInitExtraTupleSlot(parent->state));
+ }
+ }
+ }
+}
+
+/*
+ * Prepare evaluation of an ArrayRef expression.
+ */
+static void
+ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, PlanState *parent,
+ ExprState *state, Datum *resv, bool *resnull)
+{
+ bool isAssignment = (aref->refassgnexpr != NULL);
+ ArrayRefState *arefstate = palloc0(sizeof(ArrayRefState));
+ List *adjust_jumps = NIL;
+ ListCell *lc;
+ int i;
+
+ /* Fill constant fields of ArrayRefState */
+ arefstate->isassignment = isAssignment;
+ arefstate->refelemtype = aref->refelemtype;
+ arefstate->refattrlength = get_typlen(aref->refarraytype);
+ get_typlenbyvalalign(aref->refelemtype,
+ &arefstate->refelemlength,
+ &arefstate->refelembyval,
+ &arefstate->refelemalign);
+
+ /*
+ * Evaluate array input. It's safe to do so into resv/resnull, because we
+ * won't use that as target for any of the other subexpressions, and it'll
+ * be overwritten by the final EEOP_ARRAYREF_FETCH/ASSIGN step, which is
+ * pushed last.
+ */
+ ExecInitExprRec(aref->refexpr, parent, state, resv, resnull);
+
+ /*
+ * If refexpr yields NULL, and it's a fetch, then result is NULL. We can
+ * implement this with just JUMP_IF_NULL, since we evaluated the array
+ * into the desired target location.
+ */
+ if (!isAssignment)
+ {
+ scratch->opcode = EEOP_JUMP_IF_NULL;
+ scratch->d.jump.jumpdone = -1; /* adjust later */
+ ExprEvalPushStep(state, scratch);
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ }
+
+ /* Verify subscript list lengths are within limit */
+ if (list_length(aref->refupperindexpr) > MAXDIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
+ list_length(aref->refupperindexpr), MAXDIM)));
+
+ if (list_length(aref->reflowerindexpr) > MAXDIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
+ list_length(aref->reflowerindexpr), MAXDIM)));
+
+ /* Evaluate upper subscripts */
+ i = 0;
+ foreach(lc, aref->refupperindexpr)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+
+ /* When slicing, individual subscript bounds can be omitted */
+ if (!e)
+ {
+ arefstate->upperprovided[i] = false;
+ i++;
+ continue;
+ }
+
+ arefstate->upperprovided[i] = true;
+
+ /* Each subscript is evaluated into subscriptvalue/subscriptnull */
+ ExecInitExprRec(e, parent, state,
+ &arefstate->subscriptvalue, &arefstate->subscriptnull);
+
+ /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */
+ scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT;
+ scratch->d.arrayref_subscript.state = arefstate;
+ scratch->d.arrayref_subscript.off = i;
+ scratch->d.arrayref_subscript.isupper = true;
+ scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */
+ ExprEvalPushStep(state, scratch);
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ i++;
+ }
+ arefstate->numupper = i;
+
+ /* Evaluate lower subscripts similarly */
+ i = 0;
+ foreach(lc, aref->reflowerindexpr)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+
+ /* When slicing, individual subscript bounds can be omitted */
+ if (!e)
+ {
+ arefstate->lowerprovided[i] = false;
+ i++;
+ continue;
+ }
+
+ arefstate->lowerprovided[i] = true;
+
+ /* Each subscript is evaluated into subscriptvalue/subscriptnull */
+ ExecInitExprRec(e, parent, state,
+ &arefstate->subscriptvalue, &arefstate->subscriptnull);
+
+ /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */
+ scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT;
+ scratch->d.arrayref_subscript.state = arefstate;
+ scratch->d.arrayref_subscript.off = i;
+ scratch->d.arrayref_subscript.isupper = false;
+ scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */
+ ExprEvalPushStep(state, scratch);
+ adjust_jumps = lappend_int(adjust_jumps,
+ state->steps_len - 1);
+ i++;
+ }
+ arefstate->numlower = i;
+
+ /* Should be impossible if parser is sane, but check anyway: */
+ if (arefstate->numlower != 0 &&
+ arefstate->numupper != arefstate->numlower)
+ elog(ERROR, "upper and lower index lists are not same length");
+
+ if (isAssignment)
+ {
+ Datum *save_innermost_caseval;
+ bool *save_innermost_casenull;
+
+ /*
+ * We might have a nested-assignment situation, in which the
+ * refassgnexpr is itself a FieldStore or ArrayRef that needs to
+ * obtain and modify the previous value of the array element or slice
+ * being replaced. If so, we have to extract that value from the
+ * array and pass it down via the CaseTextExpr mechanism. It's safe
+ * to reuse the CASE mechanism because there cannot be a CASE between
+ * here and where the value would be needed, and an array assignment
+ * can't be within a CASE either. (So saving and restoring
+ * innermost_caseval is just paranoia, but let's do it anyway.)
+ *
+ * Since fetching the old element might be a nontrivial expense, do it
+ * only if the argument appears to actually need it.
+ */
+ if (isAssignmentIndirectionExpr(aref->refassgnexpr))
+ {
+ scratch->opcode = EEOP_ARRAYREF_OLD;
+ scratch->d.arrayref.state = arefstate;
+ ExprEvalPushStep(state, scratch);
+ }
+
+ /* ARRAYREF_OLD puts extracted value into prevvalue/prevnull */
+ save_innermost_caseval = state->innermost_caseval;
+ save_innermost_casenull = state->innermost_casenull;
+ state->innermost_caseval = &arefstate->prevvalue;
+ state->innermost_casenull = &arefstate->prevnull;
+
+ /* evaluate replacement value into replacevalue/replacenull */
+ ExecInitExprRec(aref->refassgnexpr, parent, state,
+ &arefstate->replacevalue, &arefstate->replacenull);
+
+ state->innermost_caseval = save_innermost_caseval;
+ state->innermost_casenull = save_innermost_casenull;
+
+ /* and perform the assignment */
+ scratch->opcode = EEOP_ARRAYREF_ASSIGN;
+ scratch->d.arrayref.state = arefstate;
+ ExprEvalPushStep(state, scratch);
+ }
+ else
+ {
+ /* array fetch is much simpler */
+ scratch->opcode = EEOP_ARRAYREF_FETCH;
+ scratch->d.arrayref.state = arefstate;
+ ExprEvalPushStep(state, scratch);
+ }
+
+ /* adjust jump targets */
+ foreach(lc, adjust_jumps)
+ {
+ ExprEvalStep *as = &state->steps[lfirst_int(lc)];
+
+ if (as->opcode == EEOP_ARRAYREF_SUBSCRIPT)
+ {
+ Assert(as->d.arrayref_subscript.jumpdone == -1);
+ as->d.arrayref_subscript.jumpdone = state->steps_len;
+ }
+ else
+ {
+ Assert(as->opcode == EEOP_JUMP_IF_NULL);
+ Assert(as->d.jump.jumpdone == -1);
+ as->d.jump.jumpdone = state->steps_len;
+ }
+ }
+}
+
+/*
+ * Helper for preparing ArrayRef expressions for evaluation: is expr a nested
+ * FieldStore or ArrayRef that might need the old element value passed down?
+ *
+ * (We could use this in FieldStore too, but in that case passing the old
+ * value is so cheap there's no need.)
+ */
+static bool
+isAssignmentIndirectionExpr(Expr *expr)
+{
+ if (expr == NULL)
+ return false; /* just paranoia */
+ if (IsA(expr, FieldStore))
+ {
+ FieldStore *fstore = (FieldStore *) expr;
+
+ if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
+ return true;
+ }
+ else if (IsA(expr, ArrayRef))
+ {
+ ArrayRef *arrayRef = (ArrayRef *) expr;
+
+ if (arrayRef->refexpr && IsA(arrayRef->refexpr, CaseTestExpr))
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Prepare evaluation of a CoerceToDomain expression.
+ */
+static void
+ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
+ PlanState *parent, ExprState *state,
+ Datum *resv, bool *resnull)
+{
+ ExprEvalStep scratch2;
+ DomainConstraintRef *constraint_ref;
+ Datum *domainval = NULL;
+ bool *domainnull = NULL;
+ Datum *save_innermost_domainval;
+ bool *save_innermost_domainnull;
+ ListCell *l;
+
+ scratch->d.domaincheck.resulttype = ctest->resulttype;
+ /* we'll allocate workspace only if needed */
+ scratch->d.domaincheck.checkvalue = NULL;
+ scratch->d.domaincheck.checknull = NULL;
+
+ /*
+ * Evaluate argument - it's fine to directly store it into resv/resnull,
+ * if there's constraint failures there'll be errors, otherwise it's what
+ * needs to be returned.
+ */
+ ExecInitExprRec(ctest->arg, parent, state, resv, resnull);
+
+ /*
+ * Note: if the argument is of varlena type, it could be a R/W expanded
+ * object. We want to return the R/W pointer as the final result, but we
+ * have to pass a R/O pointer as the value to be tested by any functions
+ * in check expressions. We don't bother to emit a MAKE_READONLY step
+ * unless there's actually at least one check expression, though. Until
+ * we've tested that, domainval/domainnull are NULL.
+ */
+
+ /*
+ * Collect the constraints associated with the domain.
+ *
+ * Note: before PG v10 we'd recheck the set of constraints during each
+ * evaluation of the expression. Now we bake them into the ExprState
+ * during executor initialization. That means we don't need typcache.c to
+ * provide compiled exprs.
+ */
+ constraint_ref = (DomainConstraintRef *)
+ palloc(sizeof(DomainConstraintRef));
+ InitDomainConstraintRef(ctest->resulttype,
+ constraint_ref,
+ CurrentMemoryContext,
+ false);
+
+ /*
+ * Compile code to check each domain constraint. NOTNULL constraints can
+ * just be applied on the resv/resnull value, but for CHECK constraints we
+ * need more pushups.
+ */
+ foreach(l, constraint_ref->constraints)
+ {
+ DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
+
+ scratch->d.domaincheck.constraintname = con->name;
+
+ switch (con->constrainttype)
+ {
+ case DOM_CONSTRAINT_NOTNULL:
+ scratch->opcode = EEOP_DOMAIN_NOTNULL;
+ ExprEvalPushStep(state, scratch);
+ break;
+ case DOM_CONSTRAINT_CHECK:
+ /* Allocate workspace for CHECK output if we didn't yet */
+ if (scratch->d.domaincheck.checkvalue == NULL)
+ {
+ scratch->d.domaincheck.checkvalue =
+ (Datum *) palloc(sizeof(Datum));
+ scratch->d.domaincheck.checknull =
+ (bool *) palloc(sizeof(bool));
+ }
+
+ /*
+ * If first time through, determine where CoerceToDomainValue
+ * nodes should read from.
+ */
+ if (domainval == NULL)
+ {
+ /*
+ * Since value might be read multiple times, force to R/O
+ * - but only if it could be an expanded datum.
+ */
+ if (get_typlen(ctest->resulttype) == -1)
+ {
+ /* Yes, so make output workspace for MAKE_READONLY */
+ domainval = (Datum *) palloc(sizeof(Datum));
+ domainnull = (bool *) palloc(sizeof(bool));
+
+ /* Emit MAKE_READONLY */
+ scratch2.opcode = EEOP_MAKE_READONLY;
+ scratch2.resvalue = domainval;
+ scratch2.resnull = domainnull;
+ scratch2.d.make_readonly.value = resv;
+ scratch2.d.make_readonly.isnull = resnull;
+ ExprEvalPushStep(state, &scratch2);
+ }
+ else
+ {
+ /* No, so it's fine to read from resv/resnull */
+ domainval = resv;
+ domainnull = resnull;
+ }
+ }
+
+ /*
+ * Set up value to be returned by CoerceToDomainValue nodes.
+ * We must save and restore innermost_domainval/null fields,
+ * in case this node is itself within a check expression for
+ * another domain.
+ */
+ save_innermost_domainval = state->innermost_domainval;
+ save_innermost_domainnull = state->innermost_domainnull;
+ state->innermost_domainval = domainval;
+ state->innermost_domainnull = domainnull;
+
+ /* evaluate check expression value */
+ ExecInitExprRec(con->check_expr, parent, state,
+ scratch->d.domaincheck.checkvalue,
+ scratch->d.domaincheck.checknull);
+
+ state->innermost_domainval = save_innermost_domainval;
+ state->innermost_domainnull = save_innermost_domainnull;
+
+ /* now test result */
+ scratch->opcode = EEOP_DOMAIN_CHECK;
+ ExprEvalPushStep(state, scratch);
+
+ break;
+ default:
+ elog(ERROR, "unrecognized constraint type: %d",
+ (int) con->constrainttype);
+ break;
+ }
+ }
+}
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
new file mode 100644
index 0000000000..fed0052fc6
--- /dev/null
+++ b/src/backend/executor/execExprInterp.c
@@ -0,0 +1,3565 @@
+/*-------------------------------------------------------------------------
+ *
+ * execExprInterp.c
+ * Interpreted evaluation of an expression step list.
+ *
+ * This file provides either a "direct threaded" (for gcc, clang and
+ * compatible) or a "switch threaded" (for all compilers) implementation of
+ * expression evaluation. The former is amongst the fastest known methods
+ * of interpreting programs without resorting to assembly level work, or
+ * just-in-time compilation, but it requires support for computed gotos.
+ * The latter is amongst the fastest approaches doable in standard C.
+ *
+ * In either case we use ExprEvalStep->opcode to dispatch to the code block
+ * within ExecInterpExpr() that implements the specific opcode type.
+ *
+ * Switch-threading uses a plain switch() statement to perform the
+ * dispatch. This has the advantages of being plain C and allowing the
+ * compiler to warn if implementation of a specific opcode has been forgotten.
+ * The disadvantage is that dispatches will, as commonly implemented by
+ * compilers, happen from a single location, requiring more jumps and causing
+ * bad branch prediction.
+ *
+ * In direct threading, we use gcc's label-as-values extension - also adopted
+ * by some other compilers - to replace ExprEvalStep->opcode with the address
+ * of the block implementing the instruction. Dispatch to the next instruction
+ * is done by a "computed goto". This allows for better branch prediction
+ * (as the jumps are happening from different locations) and fewer jumps
+ * (as no preparatory jump to a common dispatch location is needed).
+ *
+ * When using direct threading, ExecReadyInterpretedExpr will replace
+ * each step's opcode field with the address of the relevant code block and
+ * ExprState->flags will contain EEO_FLAG_DIRECT_THREADED to remember that
+ * that's been done.
+ *
+ * For very simple instructions the overhead of the full interpreter
+ * "startup", as minimal as it is, is noticeable. Therefore
+ * ExecReadyInterpretedExpr will choose to implement simple scalar Var
+ * and Const expressions using special fast-path routines (ExecJust*).
+ * Benchmarking shows anything more complex than those may as well use the
+ * "full interpreter".
+ *
+ * Complex or uncommon instructions are not implemented in-line in
+ * ExecInterpExpr(), rather we call out to a helper function appearing later
+ * in this file. For one reason, there'd not be a noticeable performance
+ * benefit, but more importantly those complex routines are intended to be
+ * shared between different expression evaluation approaches. For instance
+ * a JIT compiler would generate calls to them. (This is why they are
+ * exported rather than being "static" in this file.)
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/executor/execExprInterp.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/tuptoaster.h"
+#include "catalog/pg_type.h"
+#include "commands/sequence.h"
+#include "executor/execExpr.h"
+#include "executor/nodeSubplan.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "nodes/nodeFuncs.h"
+#include "parser/parsetree.h"
+#include "pgstat.h"
+#include "utils/builtins.h"
+#include "utils/date.h"
+#include "utils/lsyscache.h"
+#include "utils/timestamp.h"
+#include "utils/typcache.h"
+#include "utils/xml.h"
+
+
+/*
+ * Use computed-goto-based opcode dispatch when computed gotos are available.
+ * But use a separate symbol so that it's easy to adjust locally in this file
+ * for development and testing.
+ */
+#ifdef HAVE_COMPUTED_GOTO
+#define EEO_USE_COMPUTED_GOTO
+#endif /* HAVE_COMPUTED_GOTO */
+
+/*
+ * Macros for opcode dispatch.
+ *
+ * EEO_SWITCH - just hides the switch if not in use.
+ * EEO_CASE - labels the implementation of named expression step type.
+ * EEO_DISPATCH - jump to the implementation of the step type for 'op'.
+ * EEO_OPCODE - compute opcode required by used expression evaluation method.
+ * EEO_NEXT - increment 'op' and jump to correct next step type.
+ * EEO_JUMP - jump to the specified step number within the current expression.
+ */
+#if defined(EEO_USE_COMPUTED_GOTO)
+
+/* to make dispatch_table accessible outside ExecInterpExpr() */
+static const void **dispatch_table = NULL;
+
+#define EEO_SWITCH()
+#define EEO_CASE(name) CASE_##name:
+#define EEO_DISPATCH() goto *((void *) op->opcode)
+#define EEO_OPCODE(opcode) ((intptr_t) dispatch_table[opcode])
+
+#else /* !EEO_USE_COMPUTED_GOTO */
+
+#define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode)
+#define EEO_CASE(name) case name:
+#define EEO_DISPATCH() goto starteval
+#define EEO_OPCODE(opcode) (opcode)
+
+#endif /* EEO_USE_COMPUTED_GOTO */
+
+#define EEO_NEXT() \
+ do { \
+ op++; \
+ EEO_DISPATCH(); \
+ } while (0)
+
+#define EEO_JUMP(stepno) \
+ do { \
+ op = &state->steps[stepno]; \
+ EEO_DISPATCH(); \
+ } while (0)
+
+
+static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull);
+static void ExecInitInterpreter(void);
+
+/* support functions */
+static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype);
+static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
+ TupleDesc *cache_field, ExprContext *econtext);
+static void ShutdownTupleDescRef(Datum arg);
+static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext, bool checkisnull);
+
+/* fast-path evaluation functions */
+static Datum ExecJustInnerVarFirst(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustOuterVarFirst(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustScanVarFirst(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
+static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
+
+
+/*
+ * Prepare ExprState for interpreted execution.
+ */
+void
+ExecReadyInterpretedExpr(ExprState *state)
+{
+ /* Ensure one-time interpreter setup has been done */
+ ExecInitInterpreter();
+
+ /* Simple validity checks on expression */
+ Assert(state->steps_len >= 1);
+ Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE);
+
+ /*
+ * Don't perform redundant initialization. This is unreachable in current
+ * cases, but might be hit if there's additional expression evaluation
+ * methods that rely on interpreted execution to work.
+ */
+ if (state->flags & EEO_FLAG_INTERPRETER_INITIALIZED)
+ return;
+
+ /* DIRECT_THREADED should not already be set */
+ Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0);
+
+ /*
+ * There shouldn't be any errors before the expression is fully
+ * initialized, and even if so, it'd lead to the expression being
+ * abandoned. So we can set the flag now and save some code.
+ */
+ state->flags |= EEO_FLAG_INTERPRETER_INITIALIZED;
+
+ /*
+ * Select fast-path evalfuncs for very simple expressions. "Starting up"
+ * the full interpreter is a measurable overhead for these. Plain Vars
+ * and Const seem to be the only ones where the intrinsic cost is small
+ * enough that the overhead of ExecInterpExpr matters. For more complex
+ * expressions it's cheaper to use ExecInterpExpr always.
+ */
+ if (state->steps_len == 3)
+ {
+ ExprEvalOp step0 = state->steps[0].opcode;
+ ExprEvalOp step1 = state->steps[1].opcode;
+
+ if (step0 == EEOP_INNER_FETCHSOME &&
+ step1 == EEOP_INNER_VAR_FIRST)
+ {
+ state->evalfunc = ExecJustInnerVarFirst;
+ return;
+ }
+ else if (step0 == EEOP_OUTER_FETCHSOME &&
+ step1 == EEOP_OUTER_VAR_FIRST)
+ {
+ state->evalfunc = ExecJustOuterVarFirst;
+ return;
+ }
+ else if (step0 == EEOP_SCAN_FETCHSOME &&
+ step1 == EEOP_SCAN_VAR_FIRST)
+ {
+ state->evalfunc = ExecJustScanVarFirst;
+ return;
+ }
+ else if (step0 == EEOP_INNER_FETCHSOME &&
+ step1 == EEOP_ASSIGN_INNER_VAR)
+ {
+ state->evalfunc = ExecJustAssignInnerVar;
+ return;
+ }
+ else if (step0 == EEOP_OUTER_FETCHSOME &&
+ step1 == EEOP_ASSIGN_OUTER_VAR)
+ {
+ state->evalfunc = ExecJustAssignOuterVar;
+ return;
+ }
+ else if (step0 == EEOP_SCAN_FETCHSOME &&
+ step1 == EEOP_ASSIGN_SCAN_VAR)
+ {
+ state->evalfunc = ExecJustAssignScanVar;
+ return;
+ }
+ }
+ else if (state->steps_len == 2 &&
+ state->steps[0].opcode == EEOP_CONST)
+ {
+ state->evalfunc = ExecJustConst;
+ return;
+ }
+
+#if defined(EEO_USE_COMPUTED_GOTO)
+
+ /*
+ * In the direct-threaded implementation, replace each opcode with the
+ * address to jump to. (Use ExecEvalStepOp() to get back the opcode.)
+ */
+ {
+ int off;
+
+ for (off = 0; off < state->steps_len; off++)
+ {
+ ExprEvalStep *op = &state->steps[off];
+
+ op->opcode = EEO_OPCODE(op->opcode);
+ }
+
+ state->flags |= EEO_FLAG_DIRECT_THREADED;
+ }
+#endif /* EEO_USE_COMPUTED_GOTO */
+
+ state->evalfunc = ExecInterpExpr;
+}
+
+
+/*
+ * Evaluate expression identified by "state" in the execution context
+ * given by "econtext". *isnull is set to the is-null flag for the result,
+ * and the Datum value is the function result.
+ *
+ * As a special case, return the dispatch table's address if state is NULL.
+ * This is used by ExecInitInterpreter to set up the dispatch_table global.
+ * (Only applies when EEO_USE_COMPUTED_GOTO is defined.)
+ */
+static Datum
+ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op;
+ TupleTableSlot *resultslot;
+ TupleTableSlot *innerslot;
+ TupleTableSlot *outerslot;
+ TupleTableSlot *scanslot;
+
+ /*
+ * This array has to be in the same order as enum ExprEvalOp.
+ */
+#if defined(EEO_USE_COMPUTED_GOTO)
+ static const void *const dispatch_table[] = {
+ &&CASE_EEOP_DONE,
+ &&CASE_EEOP_INNER_FETCHSOME,
+ &&CASE_EEOP_OUTER_FETCHSOME,
+ &&CASE_EEOP_SCAN_FETCHSOME,
+ &&CASE_EEOP_INNER_VAR_FIRST,
+ &&CASE_EEOP_INNER_VAR,
+ &&CASE_EEOP_OUTER_VAR_FIRST,
+ &&CASE_EEOP_OUTER_VAR,
+ &&CASE_EEOP_SCAN_VAR_FIRST,
+ &&CASE_EEOP_SCAN_VAR,
+ &&CASE_EEOP_INNER_SYSVAR,
+ &&CASE_EEOP_OUTER_SYSVAR,
+ &&CASE_EEOP_SCAN_SYSVAR,
+ &&CASE_EEOP_WHOLEROW,
+ &&CASE_EEOP_ASSIGN_INNER_VAR,
+ &&CASE_EEOP_ASSIGN_OUTER_VAR,
+ &&CASE_EEOP_ASSIGN_SCAN_VAR,
+ &&CASE_EEOP_ASSIGN_TMP,
+ &&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
+ &&CASE_EEOP_CONST,
+ &&CASE_EEOP_FUNCEXPR,
+ &&CASE_EEOP_FUNCEXPR_STRICT,
+ &&CASE_EEOP_FUNCEXPR_FUSAGE,
+ &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
+ &&CASE_EEOP_BOOL_AND_STEP_FIRST,
+ &&CASE_EEOP_BOOL_AND_STEP,
+ &&CASE_EEOP_BOOL_AND_STEP_LAST,
+ &&CASE_EEOP_BOOL_OR_STEP_FIRST,
+ &&CASE_EEOP_BOOL_OR_STEP,
+ &&CASE_EEOP_BOOL_OR_STEP_LAST,
+ &&CASE_EEOP_BOOL_NOT_STEP,
+ &&CASE_EEOP_QUAL,
+ &&CASE_EEOP_JUMP,
+ &&CASE_EEOP_JUMP_IF_NULL,
+ &&CASE_EEOP_JUMP_IF_NOT_NULL,
+ &&CASE_EEOP_JUMP_IF_NOT_TRUE,
+ &&CASE_EEOP_NULLTEST_ISNULL,
+ &&CASE_EEOP_NULLTEST_ISNOTNULL,
+ &&CASE_EEOP_NULLTEST_ROWISNULL,
+ &&CASE_EEOP_NULLTEST_ROWISNOTNULL,
+ &&CASE_EEOP_BOOLTEST_IS_TRUE,
+ &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
+ &&CASE_EEOP_BOOLTEST_IS_FALSE,
+ &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
+ &&CASE_EEOP_PARAM_EXEC,
+ &&CASE_EEOP_PARAM_EXTERN,
+ &&CASE_EEOP_CASE_TESTVAL,
+ &&CASE_EEOP_MAKE_READONLY,
+ &&CASE_EEOP_IOCOERCE,
+ &&CASE_EEOP_DISTINCT,
+ &&CASE_EEOP_NULLIF,
+ &&CASE_EEOP_SQLVALUEFUNCTION,
+ &&CASE_EEOP_CURRENTOFEXPR,
+ &&CASE_EEOP_NEXTVALUEEXPR,
+ &&CASE_EEOP_ARRAYEXPR,
+ &&CASE_EEOP_ARRAYCOERCE,
+ &&CASE_EEOP_ROW,
+ &&CASE_EEOP_ROWCOMPARE_STEP,
+ &&CASE_EEOP_ROWCOMPARE_FINAL,
+ &&CASE_EEOP_MINMAX,
+ &&CASE_EEOP_FIELDSELECT,
+ &&CASE_EEOP_FIELDSTORE_DEFORM,
+ &&CASE_EEOP_FIELDSTORE_FORM,
+ &&CASE_EEOP_ARRAYREF_SUBSCRIPT,
+ &&CASE_EEOP_ARRAYREF_OLD,
+ &&CASE_EEOP_ARRAYREF_ASSIGN,
+ &&CASE_EEOP_ARRAYREF_FETCH,
+ &&CASE_EEOP_DOMAIN_TESTVAL,
+ &&CASE_EEOP_DOMAIN_NOTNULL,
+ &&CASE_EEOP_DOMAIN_CHECK,
+ &&CASE_EEOP_CONVERT_ROWTYPE,
+ &&CASE_EEOP_SCALARARRAYOP,
+ &&CASE_EEOP_XMLEXPR,
+ &&CASE_EEOP_AGGREF,
+ &&CASE_EEOP_GROUPING_FUNC,
+ &&CASE_EEOP_WINDOW_FUNC,
+ &&CASE_EEOP_SUBPLAN,
+ &&CASE_EEOP_ALTERNATIVE_SUBPLAN,
+ &&CASE_EEOP_LAST
+ };
+
+ StaticAssertStmt(EEOP_LAST + 1 == lengthof(dispatch_table),
+ "dispatch_table out of whack with ExprEvalOp");
+
+ if (unlikely(state == NULL))
+ return PointerGetDatum(dispatch_table);
+#else
+ Assert(state != NULL);
+#endif /* EEO_USE_COMPUTED_GOTO */
+
+ /* setup state */
+ op = state->steps;
+ resultslot = state->resultslot;
+ innerslot = econtext->ecxt_innertuple;
+ outerslot = econtext->ecxt_outertuple;
+ scanslot = econtext->ecxt_scantuple;
+
+#if defined(EEO_USE_COMPUTED_GOTO)
+ EEO_DISPATCH();
+#endif
+
+ EEO_SWITCH()
+ {
+ EEO_CASE(EEOP_DONE)
+ {
+ goto out;
+ }
+
+ EEO_CASE(EEOP_INNER_FETCHSOME)
+ {
+ /* XXX: worthwhile to check tts_nvalid inline first? */
+ slot_getsomeattrs(innerslot, op->d.fetch.last_var);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_OUTER_FETCHSOME)
+ {
+ slot_getsomeattrs(outerslot, op->d.fetch.last_var);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_SCAN_FETCHSOME)
+ {
+ slot_getsomeattrs(scanslot, op->d.fetch.last_var);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_INNER_VAR_FIRST)
+ {
+ int attnum = op->d.var.attnum;
+
+ /*
+ * First time through, check whether attribute matches Var. Might
+ * not be ok anymore, due to schema changes.
+ */
+ CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
+
+ /* Skip that check on subsequent evaluations */
+ op->opcode = EEO_OPCODE(EEOP_INNER_VAR);
+
+ /* FALL THROUGH to EEOP_INNER_VAR */
+ }
+
+ EEO_CASE(EEOP_INNER_VAR)
+ {
+ int attnum = op->d.var.attnum;
+
+ /*
+ * Since we already extracted all referenced columns from the
+ * tuple with a FETCHSOME step, we can just grab the value
+ * directly out of the slot's decomposed-data arrays. But let's
+ * have an Assert to check that that did happen.
+ */
+ Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
+ *op->resvalue = innerslot->tts_values[attnum];
+ *op->resnull = innerslot->tts_isnull[attnum];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_OUTER_VAR_FIRST)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* See EEOP_INNER_VAR_FIRST comments */
+
+ CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
+ op->opcode = EEO_OPCODE(EEOP_OUTER_VAR);
+
+ /* FALL THROUGH to EEOP_OUTER_VAR */
+ }
+
+ EEO_CASE(EEOP_OUTER_VAR)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* See EEOP_INNER_VAR comments */
+
+ Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
+ *op->resvalue = outerslot->tts_values[attnum];
+ *op->resnull = outerslot->tts_isnull[attnum];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_SCAN_VAR_FIRST)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* See EEOP_INNER_VAR_FIRST comments */
+
+ CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
+ op->opcode = EEO_OPCODE(EEOP_SCAN_VAR);
+
+ /* FALL THROUGH to EEOP_SCAN_VAR */
+ }
+
+ EEO_CASE(EEOP_SCAN_VAR)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* See EEOP_INNER_VAR comments */
+
+ Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
+ *op->resvalue = scanslot->tts_values[attnum];
+ *op->resnull = scanslot->tts_isnull[attnum];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_INNER_SYSVAR)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* these asserts must match defenses in slot_getattr */
+ Assert(innerslot->tts_tuple != NULL);
+ Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
+ /* heap_getsysattr has sufficient defenses against bad attnums */
+
+ *op->resvalue = heap_getsysattr(innerslot->tts_tuple, attnum,
+ innerslot->tts_tupleDescriptor,
+ op->resnull);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_OUTER_SYSVAR)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* these asserts must match defenses in slot_getattr */
+ Assert(outerslot->tts_tuple != NULL);
+ Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
+
+ /* heap_getsysattr has sufficient defenses against bad attnums */
+ *op->resvalue = heap_getsysattr(outerslot->tts_tuple, attnum,
+ outerslot->tts_tupleDescriptor,
+ op->resnull);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_SCAN_SYSVAR)
+ {
+ int attnum = op->d.var.attnum;
+
+ /* these asserts must match defenses in slot_getattr */
+ Assert(scanslot->tts_tuple != NULL);
+ Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
+ /* heap_getsysattr has sufficient defenses against bad attnums */
+
+ *op->resvalue = heap_getsysattr(scanslot->tts_tuple, attnum,
+ scanslot->tts_tupleDescriptor,
+ op->resnull);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_WHOLEROW)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalWholeRowVar(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ASSIGN_INNER_VAR)
+ {
+ int resultnum = op->d.assign_var.resultnum;
+ int attnum = op->d.assign_var.attnum;
+
+ /*
+ * We do not need CheckVarSlotCompatibility here; that was taken
+ * care of at compilation time. But see EEOP_INNER_VAR comments.
+ */
+ Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
+ resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
+ resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ASSIGN_OUTER_VAR)
+ {
+ int resultnum = op->d.assign_var.resultnum;
+ int attnum = op->d.assign_var.attnum;
+
+ /*
+ * We do not need CheckVarSlotCompatibility here; that was taken
+ * care of at compilation time. But see EEOP_INNER_VAR comments.
+ */
+ Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
+ resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
+ resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ASSIGN_SCAN_VAR)
+ {
+ int resultnum = op->d.assign_var.resultnum;
+ int attnum = op->d.assign_var.attnum;
+
+ /*
+ * We do not need CheckVarSlotCompatibility here; that was taken
+ * care of at compilation time. But see EEOP_INNER_VAR comments.
+ */
+ Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
+ resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
+ resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ASSIGN_TMP)
+ {
+ int resultnum = op->d.assign_tmp.resultnum;
+
+ resultslot->tts_values[resultnum] = state->resvalue;
+ resultslot->tts_isnull[resultnum] = state->resnull;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ASSIGN_TMP_MAKE_RO)
+ {
+ int resultnum = op->d.assign_tmp.resultnum;
+
+ resultslot->tts_isnull[resultnum] = state->resnull;
+ if (!resultslot->tts_isnull[resultnum])
+ resultslot->tts_values[resultnum] =
+ MakeExpandedObjectReadOnlyInternal(state->resvalue);
+ else
+ resultslot->tts_values[resultnum] = state->resvalue;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_CONST)
+ {
+ *op->resnull = op->d.constval.isnull;
+ *op->resvalue = op->d.constval.value;
+
+ EEO_NEXT();
+ }
+
+ /*
+ * Function-call implementations. Arguments have previously been
+ * evaluated directly into fcinfo->args.
+ *
+ * As both STRICT checks and function-usage are noticeable performance
+ * wise, and function calls are a very hot-path (they also back
+ * operators!), it's worth having so many separate opcodes.
+ */
+ EEO_CASE(EEOP_FUNCEXPR)
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+
+ fcinfo->isnull = false;
+ *op->resvalue = (op->d.func.fn_addr) (fcinfo);
+ *op->resnull = fcinfo->isnull;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_FUNCEXPR_STRICT)
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+ bool *argnull = fcinfo->argnull;
+ int argno;
+
+ /* strict function, so check for NULL args */
+ for (argno = 0; argno < op->d.func.nargs; argno++)
+ {
+ if (argnull[argno])
+ {
+ *op->resnull = true;
+ goto strictfail;
+ }
+ }
+ fcinfo->isnull = false;
+ *op->resvalue = (op->d.func.fn_addr) (fcinfo);
+ *op->resnull = fcinfo->isnull;
+
+ strictfail:
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_FUNCEXPR_FUSAGE)
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+ PgStat_FunctionCallUsage fcusage;
+
+ pgstat_init_function_usage(fcinfo, &fcusage);
+
+ fcinfo->isnull = false;
+ *op->resvalue = (op->d.func.fn_addr) (fcinfo);
+ *op->resnull = fcinfo->isnull;
+
+ pgstat_end_function_usage(&fcusage, true);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE)
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+ PgStat_FunctionCallUsage fcusage;
+ bool *argnull = fcinfo->argnull;
+ int argno;
+
+ /* strict function, so check for NULL args */
+ for (argno = 0; argno < op->d.func.nargs; argno++)
+ {
+ if (argnull[argno])
+ {
+ *op->resnull = true;
+ goto strictfail_fusage;
+ }
+ }
+
+ pgstat_init_function_usage(fcinfo, &fcusage);
+
+ fcinfo->isnull = false;
+ *op->resvalue = (op->d.func.fn_addr) (fcinfo);
+ *op->resnull = fcinfo->isnull;
+
+ pgstat_end_function_usage(&fcusage, true);
+
+ strictfail_fusage:
+ EEO_NEXT();
+ }
+
+ /*
+ * If any of its clauses is FALSE, an AND's result is FALSE regardless
+ * of the states of the rest of the clauses, so we can stop evaluating
+ * and return FALSE immediately. If none are FALSE and one or more is
+ * NULL, we return NULL; otherwise we return TRUE. This makes sense
+ * when you interpret NULL as "don't know": perhaps one of the "don't
+ * knows" would have been FALSE if we'd known its value. Only when
+ * all the inputs are known to be TRUE can we state confidently that
+ * the AND's result is TRUE.
+ */
+ EEO_CASE(EEOP_BOOL_AND_STEP_FIRST)
+ {
+ *op->d.boolexpr.anynull = false;
+
+ /*
+ * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
+ * same as EEOP_BOOL_AND_STEP - so fall through to that.
+ */
+
+ /* FALL THROUGH */
+ }
+
+ EEO_CASE(EEOP_BOOL_AND_STEP)
+ {
+ if (*op->resnull)
+ {
+ *op->d.boolexpr.anynull = true;
+ }
+ else if (!DatumGetBool(*op->resvalue))
+ {
+ /* result is already set to FALSE, need not change it */
+ /* bail out early */
+ EEO_JUMP(op->d.boolexpr.jumpdone);
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_BOOL_AND_STEP_LAST)
+ {
+ if (*op->resnull)
+ {
+ /* result is already set to NULL, need not change it */
+ }
+ else if (!DatumGetBool(*op->resvalue))
+ {
+ /* result is already set to FALSE, need not change it */
+
+ /*
+ * No point jumping early to jumpdone - would be same target
+ * (as this is the last argument to the AND expression),
+ * except more expensive.
+ */
+ }
+ else if (*op->d.boolexpr.anynull)
+ {
+ *op->resvalue = (Datum) 0;
+ *op->resnull = true;
+ }
+ else
+ {
+ /* result is already set to TRUE, need not change it */
+ }
+
+ EEO_NEXT();
+ }
+
+ /*
+ * If any of its clauses is TRUE, an OR's result is TRUE regardless of
+ * the states of the rest of the clauses, so we can stop evaluating
+ * and return TRUE immediately. If none are TRUE and one or more is
+ * NULL, we return NULL; otherwise we return FALSE. This makes sense
+ * when you interpret NULL as "don't know": perhaps one of the "don't
+ * knows" would have been TRUE if we'd known its value. Only when all
+ * the inputs are known to be FALSE can we state confidently that the
+ * OR's result is FALSE.
+ */
+ EEO_CASE(EEOP_BOOL_OR_STEP_FIRST)
+ {
+ *op->d.boolexpr.anynull = false;
+
+ /*
+ * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
+ * as EEOP_BOOL_OR_STEP - so fall through to that.
+ */
+
+ /* FALL THROUGH */
+ }
+
+ EEO_CASE(EEOP_BOOL_OR_STEP)
+ {
+ if (*op->resnull)
+ {
+ *op->d.boolexpr.anynull = true;
+ }
+ else if (DatumGetBool(*op->resvalue))
+ {
+ /* result is already set to TRUE, need not change it */
+ /* bail out early */
+ EEO_JUMP(op->d.boolexpr.jumpdone);
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_BOOL_OR_STEP_LAST)
+ {
+ if (*op->resnull)
+ {
+ /* result is already set to NULL, need not change it */
+ }
+ else if (DatumGetBool(*op->resvalue))
+ {
+ /* result is already set to TRUE, need not change it */
+
+ /*
+ * No point jumping to jumpdone - would be same target (as
+ * this is the last argument to the AND expression), except
+ * more expensive.
+ */
+ }
+ else if (*op->d.boolexpr.anynull)
+ {
+ *op->resvalue = (Datum) 0;
+ *op->resnull = true;
+ }
+ else
+ {
+ /* result is already set to FALSE, need not change it */
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_BOOL_NOT_STEP)
+ {
+ /*
+ * Evaluation of 'not' is simple... if expr is false, then return
+ * 'true' and vice versa. It's safe to do this even on a
+ * nominally null value, so we ignore resnull; that means that
+ * NULL in produces NULL out, which is what we want.
+ */
+ *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_QUAL)
+ {
+ /* simplified version of BOOL_AND_STEP for use by ExecQual() */
+
+ /* If argument (also result) is false or null ... */
+ if (*op->resnull ||
+ !DatumGetBool(*op->resvalue))
+ {
+ /* ... bail out early, returning FALSE */
+ *op->resnull = false;
+ *op->resvalue = BoolGetDatum(false);
+ EEO_JUMP(op->d.qualexpr.jumpdone);
+ }
+
+ /*
+ * Otherwise, leave the TRUE value in place, in case this is the
+ * last qual. Then, TRUE is the correct answer.
+ */
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_JUMP)
+ {
+ /* Unconditionally jump to target step */
+ EEO_JUMP(op->d.jump.jumpdone);
+ }
+
+ EEO_CASE(EEOP_JUMP_IF_NULL)
+ {
+ /* Transfer control if current result is null */
+ if (*op->resnull)
+ EEO_JUMP(op->d.jump.jumpdone);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_JUMP_IF_NOT_NULL)
+ {
+ /* Transfer control if current result is non-null */
+ if (!*op->resnull)
+ EEO_JUMP(op->d.jump.jumpdone);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_JUMP_IF_NOT_TRUE)
+ {
+ /* Transfer control if current result is null or false */
+ if (*op->resnull || !DatumGetBool(*op->resvalue))
+ EEO_JUMP(op->d.jump.jumpdone);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_NULLTEST_ISNULL)
+ {
+ *op->resvalue = BoolGetDatum(*op->resnull);
+ *op->resnull = false;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_NULLTEST_ISNOTNULL)
+ {
+ *op->resvalue = BoolGetDatum(!*op->resnull);
+ *op->resnull = false;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_NULLTEST_ROWISNULL)
+ {
+ /* out of line implementation: too large */
+ ExecEvalRowNull(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL)
+ {
+ /* out of line implementation: too large */
+ ExecEvalRowNotNull(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ /* BooleanTest implementations for all booltesttypes */
+
+ EEO_CASE(EEOP_BOOLTEST_IS_TRUE)
+ {
+ if (*op->resnull)
+ {
+ *op->resvalue = BoolGetDatum(false);
+ *op->resnull = false;
+ }
+ /* else, input value is the correct output as well */
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_BOOLTEST_IS_NOT_TRUE)
+ {
+ if (*op->resnull)
+ {
+ *op->resvalue = BoolGetDatum(true);
+ *op->resnull = false;
+ }
+ else
+ *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_BOOLTEST_IS_FALSE)
+ {
+ if (*op->resnull)
+ {
+ *op->resvalue = BoolGetDatum(false);
+ *op->resnull = false;
+ }
+ else
+ *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_BOOLTEST_IS_NOT_FALSE)
+ {
+ if (*op->resnull)
+ {
+ *op->resvalue = BoolGetDatum(true);
+ *op->resnull = false;
+ }
+ /* else, input value is the correct output as well */
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_PARAM_EXEC)
+ {
+ /* out of line implementation: too large */
+ ExecEvalParamExec(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_PARAM_EXTERN)
+ {
+ /* out of line implementation: too large */
+ ExecEvalParamExtern(state, op, econtext);
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_CASE_TESTVAL)
+ {
+ /*
+ * Normally upper parts of the expression tree have setup the
+ * values to be returned here, but some parts of the system
+ * currently misuse {caseValue,domainValue}_{datum,isNull} to set
+ * run-time data. So if no values have been set-up, use
+ * ExprContext's. This isn't pretty, but also not *that* ugly,
+ * and this is unlikely to be performance sensitive enough to
+ * worry about an extra branch.
+ */
+ if (op->d.casetest.value)
+ {
+ *op->resvalue = *op->d.casetest.value;
+ *op->resnull = *op->d.casetest.isnull;
+ }
+ else
+ {
+ *op->resvalue = econtext->caseValue_datum;
+ *op->resnull = econtext->caseValue_isNull;
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_DOMAIN_TESTVAL)
+ {
+ /*
+ * See EEOP_CASE_TESTVAL comment.
+ */
+ if (op->d.casetest.value)
+ {
+ *op->resvalue = *op->d.casetest.value;
+ *op->resnull = *op->d.casetest.isnull;
+ }
+ else
+ {
+ *op->resvalue = econtext->domainValue_datum;
+ *op->resnull = econtext->domainValue_isNull;
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_MAKE_READONLY)
+ {
+ /*
+ * Force a varlena value that might be read multiple times to R/O
+ */
+ if (!*op->d.make_readonly.isnull)
+ *op->resvalue =
+ MakeExpandedObjectReadOnlyInternal(*op->d.make_readonly.value);
+ *op->resnull = *op->d.make_readonly.isnull;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_IOCOERCE)
+ {
+ /*
+ * Evaluate a CoerceViaIO node. This can be quite a hot path, so
+ * inline as much work as possible. The source value is in our
+ * result variable.
+ */
+ char *str;
+
+ /* call output function (similar to OutputFunctionCall) */
+ if (*op->resnull)
+ {
+ /* output functions are not called on nulls */
+ str = NULL;
+ }
+ else
+ {
+ FunctionCallInfo fcinfo_out;
+
+ fcinfo_out = op->d.iocoerce.fcinfo_data_out;
+ fcinfo_out->arg[0] = *op->resvalue;
+ fcinfo_out->argnull[0] = false;
+
+ fcinfo_out->isnull = false;
+ str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
+
+ /* OutputFunctionCall assumes result isn't null */
+ Assert(!fcinfo_out->isnull);
+ }
+
+ /* call input function (similar to InputFunctionCall) */
+ if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
+ {
+ FunctionCallInfo fcinfo_in;
+
+ fcinfo_in = op->d.iocoerce.fcinfo_data_in;
+ fcinfo_in->arg[0] = PointerGetDatum(str);
+ fcinfo_in->argnull[0] = *op->resnull;
+ /* second and third arguments are already set up */
+
+ fcinfo_in->isnull = false;
+ *op->resvalue = FunctionCallInvoke(fcinfo_in);
+
+ /* Should get null result if and only if str is NULL */
+ if (str == NULL)
+ {
+ Assert(*op->resnull);
+ Assert(fcinfo_in->isnull);
+ }
+ else
+ {
+ Assert(!*op->resnull);
+ Assert(!fcinfo_in->isnull);
+ }
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_DISTINCT)
+ {
+ /*
+ * IS DISTINCT FROM must evaluate arguments (already done into
+ * fcinfo->arg/argnull) to determine whether they are NULL; if
+ * either is NULL then the result is determined. If neither is
+ * NULL, then proceed to evaluate the comparison function, which
+ * is just the type's standard equality operator. We need not
+ * care whether that function is strict. Because the handling of
+ * nulls is different, we can't just reuse EEOP_FUNCEXPR.
+ */
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+
+ /* check function arguments for NULLness */
+ if (fcinfo->argnull[0] && fcinfo->argnull[1])
+ {
+ /* Both NULL? Then is not distinct... */
+ *op->resvalue = BoolGetDatum(false);
+ *op->resnull = false;
+ }
+ else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+ {
+ /* Only one is NULL? Then is distinct... */
+ *op->resvalue = BoolGetDatum(true);
+ *op->resnull = false;
+ }
+ else
+ {
+ /* Neither null, so apply the equality function */
+ Datum eqresult;
+
+ fcinfo->isnull = false;
+ eqresult = (op->d.func.fn_addr) (fcinfo);
+ /* Must invert result of "="; safe to do even if null */
+ *op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
+ *op->resnull = fcinfo->isnull;
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_NULLIF)
+ {
+ /*
+ * The arguments are already evaluated into fcinfo->arg/argnull.
+ */
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+
+ /* if either argument is NULL they can't be equal */
+ if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
+ {
+ Datum result;
+
+ fcinfo->isnull = false;
+ result = (op->d.func.fn_addr) (fcinfo);
+
+ /* if the arguments are equal return null */
+ if (!fcinfo->isnull && DatumGetBool(result))
+ {
+ *op->resvalue = (Datum) 0;
+ *op->resnull = true;
+
+ EEO_NEXT();
+ }
+ }
+
+ /* Arguments aren't equal, so return the first one */
+ *op->resvalue = fcinfo->arg[0];
+ *op->resnull = fcinfo->argnull[0];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_SQLVALUEFUNCTION)
+ {
+ /*
+ * Doesn't seem worthwhile to have an inline implementation
+ * efficiency-wise.
+ */
+ ExecEvalSQLValueFunction(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_CURRENTOFEXPR)
+ {
+ /* error invocation uses space, and shouldn't ever occur */
+ ExecEvalCurrentOfExpr(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_NEXTVALUEEXPR)
+ {
+ switch (op->d.nextvalueexpr.seqtypid)
+ {
+ case INT2OID:
+ *op->resvalue = Int16GetDatum((int16) nextval_internal(op->d.nextvalueexpr.seqid, false));
+ break;
+ case INT4OID:
+ *op->resvalue = Int32GetDatum((int32) nextval_internal(op->d.nextvalueexpr.seqid, false));
+ break;
+ case INT8OID:
+ *op->resvalue = Int64GetDatum((int64) nextval_internal(op->d.nextvalueexpr.seqid, false));
+ break;
+ default:
+ elog(ERROR, "unsupported sequence type %u", op->d.nextvalueexpr.seqtypid);
+ }
+ *op->resnull = false;
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ARRAYEXPR)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalArrayExpr(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ARRAYCOERCE)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalArrayCoerce(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ROW)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalRow(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ROWCOMPARE_STEP)
+ {
+ FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
+
+ /* force NULL result if strict fn and NULL input */
+ if (op->d.rowcompare_step.finfo->fn_strict &&
+ (fcinfo->argnull[0] || fcinfo->argnull[1]))
+ {
+ *op->resnull = true;
+ EEO_JUMP(op->d.rowcompare_step.jumpnull);
+ }
+
+ /* Apply comparison function */
+ fcinfo->isnull = false;
+ *op->resvalue = (op->d.rowcompare_step.fn_addr) (fcinfo);
+
+ /* force NULL result if NULL function result */
+ if (fcinfo->isnull)
+ {
+ *op->resnull = true;
+ EEO_JUMP(op->d.rowcompare_step.jumpnull);
+ }
+ *op->resnull = false;
+
+ /* If unequal, no need to compare remaining columns */
+ if (DatumGetInt32(*op->resvalue) != 0)
+ {
+ EEO_JUMP(op->d.rowcompare_step.jumpdone);
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ROWCOMPARE_FINAL)
+ {
+ int32 cmpresult = DatumGetInt32(*op->resvalue);
+ RowCompareType rctype = op->d.rowcompare_final.rctype;
+
+ *op->resnull = false;
+ switch (rctype)
+ {
+ /* EQ and NE cases aren't allowed here */
+ case ROWCOMPARE_LT:
+ *op->resvalue = BoolGetDatum(cmpresult < 0);
+ break;
+ case ROWCOMPARE_LE:
+ *op->resvalue = BoolGetDatum(cmpresult <= 0);
+ break;
+ case ROWCOMPARE_GE:
+ *op->resvalue = BoolGetDatum(cmpresult >= 0);
+ break;
+ case ROWCOMPARE_GT:
+ *op->resvalue = BoolGetDatum(cmpresult > 0);
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_MINMAX)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalMinMax(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_FIELDSELECT)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalFieldSelect(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_FIELDSTORE_DEFORM)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalFieldStoreDeForm(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_FIELDSTORE_FORM)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalFieldStoreForm(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ARRAYREF_SUBSCRIPT)
+ {
+ /* Process an array subscript */
+
+ /* too complex for an inline implementation */
+ if (ExecEvalArrayRefSubscript(state, op))
+ {
+ EEO_NEXT();
+ }
+ else
+ {
+ /* Subscript is null, short-circuit ArrayRef to NULL */
+ EEO_JUMP(op->d.arrayref_subscript.jumpdone);
+ }
+ }
+
+ EEO_CASE(EEOP_ARRAYREF_OLD)
+ {
+ /*
+ * Fetch the old value in an arrayref assignment, in case it's
+ * referenced (via a CaseTestExpr) inside the assignment
+ * expression.
+ */
+
+ /* too complex for an inline implementation */
+ ExecEvalArrayRefOld(state, op);
+
+ EEO_NEXT();
+ }
+
+ /*
+ * Perform ArrayRef assignment
+ */
+ EEO_CASE(EEOP_ARRAYREF_ASSIGN)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalArrayRefAssign(state, op);
+
+ EEO_NEXT();
+ }
+
+ /*
+ * Fetch subset of an array.
+ */
+ EEO_CASE(EEOP_ARRAYREF_FETCH)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalArrayRefFetch(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_CONVERT_ROWTYPE)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalConvertRowtype(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_SCALARARRAYOP)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalScalarArrayOp(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_DOMAIN_NOTNULL)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalConstraintNotNull(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_DOMAIN_CHECK)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalConstraintCheck(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_XMLEXPR)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalXmlExpr(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_AGGREF)
+ {
+ /*
+ * Returns a Datum whose value is the precomputed aggregate value
+ * found in the given expression context.
+ */
+ AggrefExprState *aggref = op->d.aggref.astate;
+
+ Assert(econtext->ecxt_aggvalues != NULL);
+
+ *op->resvalue = econtext->ecxt_aggvalues[aggref->aggno];
+ *op->resnull = econtext->ecxt_aggnulls[aggref->aggno];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_GROUPING_FUNC)
+ {
+ /* too complex/uncommon for an inline implementation */
+ ExecEvalGroupingFunc(state, op);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_WINDOW_FUNC)
+ {
+ /*
+ * Like Aggref, just return a precomputed value from the econtext.
+ */
+ WindowFuncExprState *wfunc = op->d.window_func.wfstate;
+
+ Assert(econtext->ecxt_aggvalues != NULL);
+
+ *op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
+ *op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_SUBPLAN)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalSubPlan(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_ALTERNATIVE_SUBPLAN)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalAlternativeSubPlan(state, op, econtext);
+
+ EEO_NEXT();
+ }
+
+ EEO_CASE(EEOP_LAST)
+ {
+ /* unreachable */
+ Assert(false);
+ goto out;
+ }
+ }
+
+out:
+ *isnull = state->resnull;
+ return state->resvalue;
+}
+
+/*
+ * Check whether a user attribute in a slot can be referenced by a Var
+ * expression. This should succeed unless there have been schema changes
+ * since the expression tree has been created.
+ */
+static void
+CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
+{
+ /*
+ * What we have to check for here is the possibility of an attribute
+ * having been dropped or changed in type since the plan tree was created.
+ * Ideally the plan will get invalidated and not re-used, but just in
+ * case, we keep these defenses. Fortunately it's sufficient to check
+ * once on the first time through.
+ *
+ * Note: ideally we'd check typmod as well as typid, but that seems
+ * impractical at the moment: in many cases the tupdesc will have been
+ * generated by ExecTypeFromTL(), and that can't guarantee to generate an
+ * accurate typmod in all cases, because some expression node types don't
+ * carry typmod. Fortunately, for precisely that reason, there should be
+ * no places with a critical dependency on the typmod of a value.
+ *
+ * System attributes don't require checking since their types never
+ * change.
+ */
+ if (attnum > 0)
+ {
+ TupleDesc slot_tupdesc = slot->tts_tupleDescriptor;
+ Form_pg_attribute attr;
+
+ if (attnum > slot_tupdesc->natts) /* should never happen */
+ elog(ERROR, "attribute number %d exceeds number of columns %d",
+ attnum, slot_tupdesc->natts);
+
+ attr = slot_tupdesc->attrs[attnum - 1];
+
+ if (attr->attisdropped)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("attribute %d of type %s has been dropped",
+ attnum, format_type_be(slot_tupdesc->tdtypeid))));
+
+ if (vartype != attr->atttypid)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("attribute %d of type %s has wrong type",
+ attnum, format_type_be(slot_tupdesc->tdtypeid)),
+ errdetail("Table has type %s, but query expects %s.",
+ format_type_be(attr->atttypid),
+ format_type_be(vartype))));
+ }
+}
+
+/*
+ * get_cached_rowtype: utility function to lookup a rowtype tupdesc
+ *
+ * type_id, typmod: identity of the rowtype
+ * cache_field: where to cache the TupleDesc pointer in expression state node
+ * (field must be initialized to NULL)
+ * econtext: expression context we are executing in
+ *
+ * NOTE: because the shutdown callback will be called during plan rescan,
+ * must be prepared to re-do this during any node execution; cannot call
+ * just once during expression initialization.
+ */
+static TupleDesc
+get_cached_rowtype(Oid type_id, int32 typmod,
+ TupleDesc *cache_field, ExprContext *econtext)
+{
+ TupleDesc tupDesc = *cache_field;
+
+ /* Do lookup if no cached value or if requested type changed */
+ if (tupDesc == NULL ||
+ type_id != tupDesc->tdtypeid ||
+ typmod != tupDesc->tdtypmod)
+ {
+ tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
+
+ if (*cache_field)
+ {
+ /* Release old tupdesc; but callback is already registered */
+ ReleaseTupleDesc(*cache_field);
+ }
+ else
+ {
+ /* Need to register shutdown callback to release tupdesc */
+ RegisterExprContextCallback(econtext,
+ ShutdownTupleDescRef,
+ PointerGetDatum(cache_field));
+ }
+ *cache_field = tupDesc;
+ }
+ return tupDesc;
+}
+
+/*
+ * Callback function to release a tupdesc refcount at econtext shutdown
+ */
+static void
+ShutdownTupleDescRef(Datum arg)
+{
+ TupleDesc *cache_field = (TupleDesc *) DatumGetPointer(arg);
+
+ if (*cache_field)
+ ReleaseTupleDesc(*cache_field);
+ *cache_field = NULL;
+}
+
+/*
+ * Fast-path functions, for very simple expressions
+ */
+
+/* Simple reference to inner Var, first time through */
+static Datum
+ExecJustInnerVarFirst(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.var.attnum + 1;
+ TupleTableSlot *slot = econtext->ecxt_innertuple;
+
+ /* See ExecInterpExpr()'s comments for EEOP_INNER_VAR_FIRST */
+
+ CheckVarSlotCompatibility(slot, attnum, op->d.var.vartype);
+ op->opcode = EEOP_INNER_VAR; /* just for cleanliness */
+ state->evalfunc = ExecJustInnerVar;
+
+ /*
+ * Since we use slot_getattr(), we don't need to implement the FETCHSOME
+ * step explicitly, and we also needn't Assert that the attnum is in range
+ * --- slot_getattr() will take care of any problems.
+ */
+ return slot_getattr(slot, attnum, isnull);
+}
+
+/* Simple reference to inner Var */
+static Datum
+ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.var.attnum + 1;
+ TupleTableSlot *slot = econtext->ecxt_innertuple;
+
+ /* See comments in ExecJustInnerVarFirst */
+ return slot_getattr(slot, attnum, isnull);
+}
+
+/* Simple reference to outer Var, first time through */
+static Datum
+ExecJustOuterVarFirst(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.var.attnum + 1;
+ TupleTableSlot *slot = econtext->ecxt_outertuple;
+
+ CheckVarSlotCompatibility(slot, attnum, op->d.var.vartype);
+ op->opcode = EEOP_OUTER_VAR; /* just for cleanliness */
+ state->evalfunc = ExecJustOuterVar;
+
+ /* See comments in ExecJustInnerVarFirst */
+ return slot_getattr(slot, attnum, isnull);
+}
+
+/* Simple reference to outer Var */
+static Datum
+ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.var.attnum + 1;
+ TupleTableSlot *slot = econtext->ecxt_outertuple;
+
+ /* See comments in ExecJustInnerVarFirst */
+ return slot_getattr(slot, attnum, isnull);
+}
+
+/* Simple reference to scan Var, first time through */
+static Datum
+ExecJustScanVarFirst(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.var.attnum + 1;
+ TupleTableSlot *slot = econtext->ecxt_scantuple;
+
+ CheckVarSlotCompatibility(slot, attnum, op->d.var.vartype);
+ op->opcode = EEOP_SCAN_VAR; /* just for cleanliness */
+ state->evalfunc = ExecJustScanVar;
+
+ /* See comments in ExecJustInnerVarFirst */
+ return slot_getattr(slot, attnum, isnull);
+}
+
+/* Simple reference to scan Var */
+static Datum
+ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.var.attnum + 1;
+ TupleTableSlot *slot = econtext->ecxt_scantuple;
+
+ /* See comments in ExecJustInnerVarFirst */
+ return slot_getattr(slot, attnum, isnull);
+}
+
+/* Simple Const expression */
+static Datum
+ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[0];
+
+ *isnull = op->d.constval.isnull;
+ return op->d.constval.value;
+}
+
+/* Evaluate inner Var and assign to appropriate column of result tuple */
+static Datum
+ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.assign_var.attnum + 1;
+ int resultnum = op->d.assign_var.resultnum;
+ TupleTableSlot *inslot = econtext->ecxt_innertuple;
+ TupleTableSlot *outslot = state->resultslot;
+
+ /*
+ * We do not need CheckVarSlotCompatibility here; that was taken care of
+ * at compilation time.
+ *
+ * Since we use slot_getattr(), we don't need to implement the FETCHSOME
+ * step explicitly, and we also needn't Assert that the attnum is in range
+ * --- slot_getattr() will take care of any problems.
+ */
+ outslot->tts_values[resultnum] =
+ slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
+ return 0;
+}
+
+/* Evaluate outer Var and assign to appropriate column of result tuple */
+static Datum
+ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.assign_var.attnum + 1;
+ int resultnum = op->d.assign_var.resultnum;
+ TupleTableSlot *inslot = econtext->ecxt_outertuple;
+ TupleTableSlot *outslot = state->resultslot;
+
+ /* See comments in ExecJustAssignInnerVar */
+ outslot->tts_values[resultnum] =
+ slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
+ return 0;
+}
+
+/* Evaluate scan Var and assign to appropriate column of result tuple */
+static Datum
+ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
+{
+ ExprEvalStep *op = &state->steps[1];
+ int attnum = op->d.assign_var.attnum + 1;
+ int resultnum = op->d.assign_var.resultnum;
+ TupleTableSlot *inslot = econtext->ecxt_scantuple;
+ TupleTableSlot *outslot = state->resultslot;
+
+ /* See comments in ExecJustAssignInnerVar */
+ outslot->tts_values[resultnum] =
+ slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
+ return 0;
+}
+
+
+/*
+ * Do one-time initialization of interpretation machinery.
+ */
+static void
+ExecInitInterpreter(void)
+{
+#if defined(EEO_USE_COMPUTED_GOTO)
+ /* Set up externally-visible pointer to dispatch table */
+ if (dispatch_table == NULL)
+ dispatch_table = (const void **)
+ DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
+#endif
+}
+
+/*
+ * Function to return the opcode of an expression step.
+ *
+ * When direct-threading is in use, ExprState->opcode isn't easily
+ * decipherable. This function returns the appropriate enum member.
+ *
+ * This currently is only supposed to be used in paths that aren't critical
+ * performance-wise. If that changes, we could add an inverse dispatch_table
+ * that's sorted on the address, so a binary search can be performed.
+ */
+ExprEvalOp
+ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
+{
+#if defined(EEO_USE_COMPUTED_GOTO)
+ if (state->flags & EEO_FLAG_DIRECT_THREADED)
+ {
+ int i;
+
+ for (i = 0; i < EEOP_LAST; i++)
+ {
+ if ((void *) op->opcode == dispatch_table[i])
+ {
+ return (ExprEvalOp) i;
+ }
+ }
+ elog(ERROR, "unknown opcode");
+ }
+#endif
+ return (ExprEvalOp) op->opcode;
+}
+
+
+/*
+ * Out-of-line helper functions for complex instructions.
+ */
+
+/*
+ * Evaluate a PARAM_EXEC parameter.
+ *
+ * PARAM_EXEC params (internal executor parameters) are stored in the
+ * ecxt_param_exec_vals array, and can be accessed by array index.
+ */
+void
+ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ ParamExecData *prm;
+
+ prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
+ if (unlikely(prm->execPlan != NULL))
+ {
+ /* Parameter not evaluated yet, so go do it */
+ ExecSetParamPlan(prm->execPlan, econtext);
+ /* ExecSetParamPlan should have processed this param... */
+ Assert(prm->execPlan == NULL);
+ }
+ *op->resvalue = prm->value;
+ *op->resnull = prm->isnull;
+}
+
+/*
+ * Evaluate a PARAM_EXTERN parameter.
+ *
+ * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
+ */
+void
+ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ ParamListInfo paramInfo = econtext->ecxt_param_list_info;
+ int paramId = op->d.param.paramid;
+
+ if (likely(paramInfo &&
+ paramId > 0 && paramId <= paramInfo->numParams))
+ {
+ ParamExternData *prm = &paramInfo->params[paramId - 1];
+
+ /* give hook a chance in case parameter is dynamic */
+ if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
+ (*paramInfo->paramFetch) (paramInfo, paramId);
+
+ if (likely(OidIsValid(prm->ptype)))
+ {
+ /* safety check in case hook did something unexpected */
+ if (unlikely(prm->ptype != op->d.param.paramtype))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
+ paramId,
+ format_type_be(prm->ptype),
+ format_type_be(op->d.param.paramtype))));
+ *op->resvalue = prm->value;
+ *op->resnull = prm->isnull;
+ return;
+ }
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("no value found for parameter %d", paramId)));
+}
+
+/*
+ * Evaluate a SQLValueFunction expression.
+ */
+void
+ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
+{
+ SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
+ FunctionCallInfoData fcinfo;
+
+ *op->resnull = false;
+
+ /*
+ * Note: current_schema() can return NULL. current_user() etc currently
+ * cannot, but might as well code those cases the same way for safety.
+ */
+ switch (svf->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ *op->resvalue = DateADTGetDatum(GetSQLCurrentDate());
+ break;
+ case SVFOP_CURRENT_TIME:
+ case SVFOP_CURRENT_TIME_N:
+ *op->resvalue = TimeTzADTPGetDatum(GetSQLCurrentTime(svf->typmod));
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ *op->resvalue = TimestampTzGetDatum(GetSQLCurrentTimestamp(svf->typmod));
+ break;
+ case SVFOP_LOCALTIME:
+ case SVFOP_LOCALTIME_N:
+ *op->resvalue = TimeADTGetDatum(GetSQLLocalTime(svf->typmod));
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ case SVFOP_LOCALTIMESTAMP_N:
+ *op->resvalue = TimestampGetDatum(GetSQLLocalTimestamp(svf->typmod));
+ break;
+ case SVFOP_CURRENT_ROLE:
+ case SVFOP_CURRENT_USER:
+ case SVFOP_USER:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_user(&fcinfo);
+ *op->resnull = fcinfo.isnull;
+ break;
+ case SVFOP_SESSION_USER:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = session_user(&fcinfo);
+ *op->resnull = fcinfo.isnull;
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_database(&fcinfo);
+ *op->resnull = fcinfo.isnull;
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_schema(&fcinfo);
+ *op->resnull = fcinfo.isnull;
+ break;
+ }
+}
+
+/*
+ * Raise error if a CURRENT OF expression is evaluated.
+ *
+ * The planner should convert CURRENT OF into a TidScan qualification, or some
+ * other special handling in a ForeignScan node. So we have to be able to do
+ * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
+ * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
+ * table whose FDW doesn't handle it, and complain accordingly.
+ */
+void
+ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("WHERE CURRENT OF is not supported for this table type")));
+}
+
+/*
+ * Evaluate NullTest / IS NULL for rows.
+ */
+void
+ExecEvalRowNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ ExecEvalRowNullInt(state, op, econtext, true);
+}
+
+/*
+ * Evaluate NullTest / IS NOT NULL for rows.
+ */
+void
+ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ ExecEvalRowNullInt(state, op, econtext, false);
+}
+
+/* Common code for IS [NOT] NULL on a row value */
+static void
+ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext, bool checkisnull)
+{
+ Datum value = *op->resvalue;
+ bool isnull = *op->resnull;
+ HeapTupleHeader tuple;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupDesc;
+ HeapTupleData tmptup;
+ int att;
+
+ *op->resnull = false;
+
+ /* NULL row variables are treated just as NULL scalar columns */
+ if (isnull)
+ {
+ *op->resvalue = BoolGetDatum(checkisnull);
+ return;
+ }
+
+ /*
+ * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
+ * as:
+ *
+ * "R IS NULL" is true if every field is the null value.
+ *
+ * "R IS NOT NULL" is true if no field is the null value.
+ *
+ * This definition is (apparently intentionally) not recursive; so our
+ * tests on the fields are primitive attisnull tests, not recursive checks
+ * to see if they are all-nulls or no-nulls rowtypes.
+ *
+ * The standard does not consider the possibility of zero-field rows, but
+ * here we consider them to vacuously satisfy both predicates.
+ */
+
+ tuple = DatumGetHeapTupleHeader(value);
+
+ tupType = HeapTupleHeaderGetTypeId(tuple);
+ tupTypmod = HeapTupleHeaderGetTypMod(tuple);
+
+ /* Lookup tupdesc if first time through or if type changes */
+ tupDesc = get_cached_rowtype(tupType, tupTypmod,
+ &op->d.nulltest_row.argdesc,
+ econtext);
+
+ /*
+ * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
+ */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+ tmptup.t_data = tuple;
+
+ for (att = 1; att <= tupDesc->natts; att++)
+ {
+ /* ignore dropped columns */
+ if (tupDesc->attrs[att - 1]->attisdropped)
+ continue;
+ if (heap_attisnull(&tmptup, att))
+ {
+ /* null field disproves IS NOT NULL */
+ if (!checkisnull)
+ {
+ *op->resvalue = BoolGetDatum(false);
+ return;
+ }
+ }
+ else
+ {
+ /* non-null field disproves IS NULL */
+ if (checkisnull)
+ {
+ *op->resvalue = BoolGetDatum(false);
+ return;
+ }
+ }
+ }
+
+ *op->resvalue = BoolGetDatum(true);
+}
+
+/*
+ * Evaluate an ARRAY[] expression.
+ *
+ * The individual array elements (or subarrays) have already been evaluated
+ * into op->d.arrayexpr.elemvalues[]/elemnulls[].
+ */
+void
+ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
+{
+ ArrayType *result;
+ Oid element_type = op->d.arrayexpr.elemtype;
+ int nelems = op->d.arrayexpr.nelems;
+ int ndims = 0;
+ int dims[MAXDIM];
+ int lbs[MAXDIM];
+
+ /* Set non-null as default */
+ *op->resnull = false;
+
+ if (!op->d.arrayexpr.multidims)
+ {
+ /* Elements are presumably of scalar type */
+ Datum *dvalues = op->d.arrayexpr.elemvalues;
+ bool *dnulls = op->d.arrayexpr.elemnulls;
+
+ /* Shouldn't happen here, but if length is 0, return empty array */
+ if (nelems == 0)
+ {
+ *op->resvalue =
+ PointerGetDatum(construct_empty_array(element_type));
+ return;
+ }
+
+ /* setup for 1-D array of the given length */
+ ndims = 1;
+ dims[0] = nelems;
+ lbs[0] = 1;
+
+ result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
+ element_type,
+ op->d.arrayexpr.elemlength,
+ op->d.arrayexpr.elembyval,
+ op->d.arrayexpr.elemalign);
+ }
+ else
+ {
+ /* Must be nested array expressions */
+ int nbytes = 0;
+ int nitems = 0;
+ int outer_nelems = 0;
+ int elem_ndims = 0;
+ int *elem_dims = NULL;
+ int *elem_lbs = NULL;
+ bool firstone = true;
+ bool havenulls = false;
+ bool haveempty = false;
+ char **subdata;
+ bits8 **subbitmaps;
+ int *subbytes;
+ int *subnitems;
+ int32 dataoffset;
+ char *dat;
+ int iitem;
+ int elemoff;
+ int i;
+
+ subdata = (char **) palloc(nelems * sizeof(char *));
+ subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
+ subbytes = (int *) palloc(nelems * sizeof(int));
+ subnitems = (int *) palloc(nelems * sizeof(int));
+
+ /* loop through and get data area from each element */
+ for (elemoff = 0; elemoff < nelems; elemoff++)
+ {
+ Datum arraydatum;
+ bool eisnull;
+ ArrayType *array;
+ int this_ndims;
+
+ arraydatum = op->d.arrayexpr.elemvalues[elemoff];
+ eisnull = op->d.arrayexpr.elemnulls[elemoff];
+
+ /* temporarily ignore null subarrays */
+ if (eisnull)
+ {
+ haveempty = true;
+ continue;
+ }
+
+ array = DatumGetArrayTypeP(arraydatum);
+
+ /* run-time double-check on element type */
+ if (element_type != ARR_ELEMTYPE(array))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot merge incompatible arrays"),
+ errdetail("Array with element type %s cannot be "
+ "included in ARRAY construct with element type %s.",
+ format_type_be(ARR_ELEMTYPE(array)),
+ format_type_be(element_type))));
+
+ this_ndims = ARR_NDIM(array);
+ /* temporarily ignore zero-dimensional subarrays */
+ if (this_ndims <= 0)
+ {
+ haveempty = true;
+ continue;
+ }
+
+ if (firstone)
+ {
+ /* Get sub-array details from first member */
+ elem_ndims = this_ndims;
+ ndims = elem_ndims + 1;
+ if (ndims <= 0 || ndims > MAXDIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("number of array dimensions (%d) exceeds " \
+ "the maximum allowed (%d)", ndims, MAXDIM)));
+
+ elem_dims = (int *) palloc(elem_ndims * sizeof(int));
+ memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
+ elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
+ memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
+
+ firstone = false;
+ }
+ else
+ {
+ /* Check other sub-arrays are compatible */
+ if (elem_ndims != this_ndims ||
+ memcmp(elem_dims, ARR_DIMS(array),
+ elem_ndims * sizeof(int)) != 0 ||
+ memcmp(elem_lbs, ARR_LBOUND(array),
+ elem_ndims * sizeof(int)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ errmsg("multidimensional arrays must have array "
+ "expressions with matching dimensions")));
+ }
+
+ subdata[outer_nelems] = ARR_DATA_PTR(array);
+ subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
+ subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
+ nbytes += subbytes[outer_nelems];
+ subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
+ ARR_DIMS(array));
+ nitems += subnitems[outer_nelems];
+ havenulls |= ARR_HASNULL(array);
+ outer_nelems++;
+ }
+
+ /*
+ * If all items were null or empty arrays, return an empty array;
+ * otherwise, if some were and some weren't, raise error. (Note: we
+ * must special-case this somehow to avoid trying to generate a 1-D
+ * array formed from empty arrays. It's not ideal...)
+ */
+ if (haveempty)
+ {
+ if (ndims == 0) /* didn't find any nonempty array */
+ {
+ *op->resvalue = PointerGetDatum(construct_empty_array(element_type));
+ return;
+ }
+ ereport(ERROR,
+ (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+ errmsg("multidimensional arrays must have array "
+ "expressions with matching dimensions")));
+ }
+
+ /* setup for multi-D array */
+ dims[0] = outer_nelems;
+ lbs[0] = 1;
+ for (i = 1; i < ndims; i++)
+ {
+ dims[i] = elem_dims[i - 1];
+ lbs[i] = elem_lbs[i - 1];
+ }
+
+ if (havenulls)
+ {
+ dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
+ nbytes += dataoffset;
+ }
+ else
+ {
+ dataoffset = 0; /* marker for no null bitmap */
+ nbytes += ARR_OVERHEAD_NONULLS(ndims);
+ }
+
+ result = (ArrayType *) palloc(nbytes);
+ SET_VARSIZE(result, nbytes);
+ result->ndim = ndims;
+ result->dataoffset = dataoffset;
+ result->elemtype = element_type;
+ memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
+ memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
+
+ dat = ARR_DATA_PTR(result);
+ iitem = 0;
+ for (i = 0; i < outer_nelems; i++)
+ {
+ memcpy(dat, subdata[i], subbytes[i]);
+ dat += subbytes[i];
+ if (havenulls)
+ array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
+ subbitmaps[i], 0,
+ subnitems[i]);
+ iitem += subnitems[i];
+ }
+ }
+
+ *op->resvalue = PointerGetDatum(result);
+}
+
+/*
+ * Evaluate an ArrayCoerceExpr expression.
+ *
+ * Source array is in step's result variable.
+ */
+void
+ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op)
+{
+ ArrayCoerceExpr *acoerce = op->d.arraycoerce.coerceexpr;
+ Datum arraydatum;
+ FunctionCallInfoData locfcinfo;
+
+ /* NULL array -> NULL result */
+ if (*op->resnull)
+ return;
+
+ arraydatum = *op->resvalue;
+
+ /*
+ * If it's binary-compatible, modify the element type in the array header,
+ * but otherwise leave the array as we received it.
+ */
+ if (!OidIsValid(acoerce->elemfuncid))
+ {
+ /* Detoast input array if necessary, and copy in any case */
+ ArrayType *array = DatumGetArrayTypePCopy(arraydatum);
+
+ ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
+ *op->resvalue = PointerGetDatum(array);
+ return;
+ }
+
+ /*
+ * Use array_map to apply the function to each array element.
+ *
+ * We pass on the desttypmod and isExplicit flags whether or not the
+ * function wants them.
+ *
+ * Note: coercion functions are assumed to not use collation.
+ */
+ InitFunctionCallInfoData(locfcinfo, op->d.arraycoerce.elemfunc, 3,
+ InvalidOid, NULL, NULL);
+ locfcinfo.arg[0] = arraydatum;
+ locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod);
+ locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit);
+ locfcinfo.argnull[0] = false;
+ locfcinfo.argnull[1] = false;
+ locfcinfo.argnull[2] = false;
+
+ *op->resvalue = array_map(&locfcinfo, op->d.arraycoerce.resultelemtype,
+ op->d.arraycoerce.amstate);
+}
+
+/*
+ * Evaluate a ROW() expression.
+ *
+ * The individual columns have already been evaluated into
+ * op->d.row.elemvalues[]/elemnulls[].
+ */
+void
+ExecEvalRow(ExprState *state, ExprEvalStep *op)
+{
+ HeapTuple tuple;
+
+ /* build tuple from evaluated field values */
+ tuple = heap_form_tuple(op->d.row.tupdesc,
+ op->d.row.elemvalues,
+ op->d.row.elemnulls);
+
+ *op->resvalue = HeapTupleGetDatum(tuple);
+ *op->resnull = false;
+}
+
+/*
+ * Evaluate GREATEST() or LEAST() expression (note this is *not* MIN()/MAX()).
+ *
+ * All of the to-be-compared expressions have already been evaluated into
+ * op->d.minmax.values[]/nulls[].
+ */
+void
+ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
+{
+ Datum *values = op->d.minmax.values;
+ bool *nulls = op->d.minmax.nulls;
+ FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
+ MinMaxOp operator = op->d.minmax.op;
+ int off;
+
+ /* set at initialization */
+ Assert(fcinfo->argnull[0] == false);
+ Assert(fcinfo->argnull[1] == false);
+
+ /* default to null result */
+ *op->resnull = true;
+
+ for (off = 0; off < op->d.minmax.nelems; off++)
+ {
+ /* ignore NULL inputs */
+ if (nulls[off])
+ continue;
+
+ if (*op->resnull)
+ {
+ /* first nonnull input, adopt value */
+ *op->resvalue = values[off];
+ *op->resnull = false;
+ }
+ else
+ {
+ int cmpresult;
+
+ /* apply comparison function */
+ fcinfo->arg[0] = *op->resvalue;
+ fcinfo->arg[1] = values[off];
+
+ fcinfo->isnull = false;
+ cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
+ if (fcinfo->isnull) /* probably should not happen */
+ continue;
+
+ if (cmpresult > 0 && operator == IS_LEAST)
+ *op->resvalue = values[off];
+ else if (cmpresult < 0 && operator == IS_GREATEST)
+ *op->resvalue = values[off];
+ }
+ }
+}
+
+/*
+ * Evaluate a FieldSelect node.
+ *
+ * Source record is in step's result variable.
+ */
+void
+ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ AttrNumber fieldnum = op->d.fieldselect.fieldnum;
+ Datum tupDatum;
+ HeapTupleHeader tuple;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupDesc;
+ Form_pg_attribute attr;
+ HeapTupleData tmptup;
+
+ /* NULL record -> NULL result */
+ if (*op->resnull)
+ return;
+
+ /* Get the composite datum and extract its type fields */
+ tupDatum = *op->resvalue;
+ tuple = DatumGetHeapTupleHeader(tupDatum);
+
+ tupType = HeapTupleHeaderGetTypeId(tuple);
+ tupTypmod = HeapTupleHeaderGetTypMod(tuple);
+
+ /* Lookup tupdesc if first time through or if type changes */
+ tupDesc = get_cached_rowtype(tupType, tupTypmod,
+ &op->d.fieldselect.argdesc,
+ econtext);
+
+ /*
+ * Find field's attr record. Note we don't support system columns here: a
+ * datum tuple doesn't have valid values for most of the interesting
+ * system columns anyway.
+ */
+ if (fieldnum <= 0) /* should never happen */
+ elog(ERROR, "unsupported reference to system column %d in FieldSelect",
+ fieldnum);
+ if (fieldnum > tupDesc->natts) /* should never happen */
+ elog(ERROR, "attribute number %d exceeds number of columns %d",
+ fieldnum, tupDesc->natts);
+ attr = tupDesc->attrs[fieldnum - 1];
+
+ /* Check for dropped column, and force a NULL result if so */
+ if (attr->attisdropped)
+ {
+ *op->resnull = true;
+ return;
+ }
+
+ /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
+ /* As in CheckVarSlotCompatibility, we should but can't check typmod */
+ if (op->d.fieldselect.resulttype != attr->atttypid)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("attribute %d has wrong type", fieldnum),
+ errdetail("Table has type %s, but query expects %s.",
+ format_type_be(attr->atttypid),
+ format_type_be(op->d.fieldselect.resulttype))));
+
+ /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+ tmptup.t_data = tuple;
+
+ /* extract the field */
+ *op->resvalue = heap_getattr(&tmptup,
+ fieldnum,
+ tupDesc,
+ op->resnull);
+}
+
+/*
+ * Deform source tuple, filling in the step's values/nulls arrays, before
+ * evaluating individual new values as part of a FieldStore expression.
+ * Subsequent steps will overwrite individual elements of the values/nulls
+ * arrays with the new field values, and then FIELDSTORE_FORM will build the
+ * new tuple value.
+ *
+ * Source record is in step's result variable.
+ */
+void
+ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ TupleDesc tupDesc;
+
+ /* Lookup tupdesc if first time through or after rescan */
+ tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
+ op->d.fieldstore.argdesc, econtext);
+
+ /* Check that current tupdesc doesn't have more fields than we allocated */
+ if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
+ elog(ERROR, "too many columns in composite type %u",
+ op->d.fieldstore.fstore->resulttype);
+
+ if (*op->resnull)
+ {
+ /* Convert null input tuple into an all-nulls row */
+ memset(op->d.fieldstore.nulls, true,
+ op->d.fieldstore.ncolumns * sizeof(bool));
+ }
+ else
+ {
+ /*
+ * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
+ * set all the fields in the struct just in case.
+ */
+ Datum tupDatum = *op->resvalue;
+ HeapTupleHeader tuphdr;
+ HeapTupleData tmptup;
+
+ tuphdr = DatumGetHeapTupleHeader(tupDatum);
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
+ ItemPointerSetInvalid(&(tmptup.t_self));
+ tmptup.t_tableOid = InvalidOid;
+ tmptup.t_data = tuphdr;
+
+ heap_deform_tuple(&tmptup, tupDesc,
+ op->d.fieldstore.values,
+ op->d.fieldstore.nulls);
+ }
+}
+
+/*
+ * Compute the new composite datum after each individual field value of a
+ * FieldStore expression has been evaluated.
+ */
+void
+ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ HeapTuple tuple;
+
+ /* argdesc should already be valid from the DeForm step */
+ tuple = heap_form_tuple(*op->d.fieldstore.argdesc,
+ op->d.fieldstore.values,
+ op->d.fieldstore.nulls);
+
+ *op->resvalue = HeapTupleGetDatum(tuple);
+ *op->resnull = false;
+}
+
+/*
+ * Process a subscript in an ArrayRef expression.
+ *
+ * If subscript is NULL, throw error in assignment case, or in fetch case
+ * set result to NULL and return false (instructing caller to skip the rest
+ * of the ArrayRef sequence).
+ *
+ * Subscript expression result is in subscriptvalue/subscriptnull.
+ * On success, integer subscript value has been saved in upperindex[] or
+ * lowerindex[] for use later.
+ */
+bool
+ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op)
+{
+ ArrayRefState *arefstate = op->d.arrayref_subscript.state;
+ int *indexes;
+ int off;
+
+ /* If any index expr yields NULL, result is NULL or error */
+ if (arefstate->subscriptnull)
+ {
+ if (arefstate->isassignment)
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("array subscript in assignment must not be null")));
+ *op->resnull = true;
+ return false;
+ }
+
+ /* Convert datum to int, save in appropriate place */
+ if (op->d.arrayref_subscript.isupper)
+ indexes = arefstate->upperindex;
+ else
+ indexes = arefstate->lowerindex;
+ off = op->d.arrayref_subscript.off;
+
+ indexes[off] = DatumGetInt32(arefstate->subscriptvalue);
+
+ return true;
+}
+
+/*
+ * Evaluate ArrayRef fetch.
+ *
+ * Source array is in step's result variable.
+ */
+void
+ExecEvalArrayRefFetch(ExprState *state, ExprEvalStep *op)
+{
+ ArrayRefState *arefstate = op->d.arrayref.state;
+
+ /* Should not get here if source array (or any subscript) is null */
+ Assert(!(*op->resnull));
+
+ if (arefstate->numlower == 0)
+ {
+ /* Scalar case */
+ *op->resvalue = array_get_element(*op->resvalue,
+ arefstate->numupper,
+ arefstate->upperindex,
+ arefstate->refattrlength,
+ arefstate->refelemlength,
+ arefstate->refelembyval,
+ arefstate->refelemalign,
+ op->resnull);
+ }
+ else
+ {
+ /* Slice case */
+ *op->resvalue = array_get_slice(*op->resvalue,
+ arefstate->numupper,
+ arefstate->upperindex,
+ arefstate->lowerindex,
+ arefstate->upperprovided,
+ arefstate->lowerprovided,
+ arefstate->refattrlength,
+ arefstate->refelemlength,
+ arefstate->refelembyval,
+ arefstate->refelemalign);
+ }
+}
+
+/*
+ * Compute old array element/slice value for an ArrayRef assignment
+ * expression. Will only be generated if the new-value subexpression
+ * contains ArrayRef or FieldStore. The value is stored into the
+ * ArrayRefState's prevvalue/prevnull fields.
+ */
+void
+ExecEvalArrayRefOld(ExprState *state, ExprEvalStep *op)
+{
+ ArrayRefState *arefstate = op->d.arrayref.state;
+
+ if (*op->resnull)
+ {
+ /* whole array is null, so any element or slice is too */
+ arefstate->prevvalue = (Datum) 0;
+ arefstate->prevnull = true;
+ }
+ else if (arefstate->numlower == 0)
+ {
+ /* Scalar case */
+ arefstate->prevvalue = array_get_element(*op->resvalue,
+ arefstate->numupper,
+ arefstate->upperindex,
+ arefstate->refattrlength,
+ arefstate->refelemlength,
+ arefstate->refelembyval,
+ arefstate->refelemalign,
+ &arefstate->prevnull);
+ }
+ else
+ {
+ /* Slice case */
+ /* this is currently unreachable */
+ arefstate->prevvalue = array_get_slice(*op->resvalue,
+ arefstate->numupper,
+ arefstate->upperindex,
+ arefstate->lowerindex,
+ arefstate->upperprovided,
+ arefstate->lowerprovided,
+ arefstate->refattrlength,
+ arefstate->refelemlength,
+ arefstate->refelembyval,
+ arefstate->refelemalign);
+ arefstate->prevnull = false;
+ }
+}
+
+/*
+ * Evaluate ArrayRef assignment.
+ *
+ * Input array (possibly null) is in result area, replacement value is in
+ * ArrayRefState's replacevalue/replacenull.
+ */
+void
+ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op)
+{
+ ArrayRefState *arefstate = op->d.arrayref.state;
+
+ /*
+ * For an assignment to a fixed-length array type, both the original array
+ * and the value to be assigned into it must be non-NULL, else we punt and
+ * return the original array.
+ */
+ if (arefstate->refattrlength > 0) /* fixed-length array? */
+ {
+ if (*op->resnull || arefstate->replacenull)
+ return;
+ }
+
+ /*
+ * For assignment to varlena arrays, we handle a NULL original array by
+ * substituting an empty (zero-dimensional) array; insertion of the new
+ * element will result in a singleton array value. It does not matter
+ * whether the new element is NULL.
+ */
+ if (*op->resnull)
+ {
+ *op->resvalue = PointerGetDatum(construct_empty_array(arefstate->refelemtype));
+ *op->resnull = false;
+ }
+
+ if (arefstate->numlower == 0)
+ {
+ /* Scalar case */
+ *op->resvalue = array_set_element(*op->resvalue,
+ arefstate->numupper,
+ arefstate->upperindex,
+ arefstate->replacevalue,
+ arefstate->replacenull,
+ arefstate->refattrlength,
+ arefstate->refelemlength,
+ arefstate->refelembyval,
+ arefstate->refelemalign);
+ }
+ else
+ {
+ /* Slice case */
+ *op->resvalue = array_set_slice(*op->resvalue,
+ arefstate->numupper,
+ arefstate->upperindex,
+ arefstate->lowerindex,
+ arefstate->upperprovided,
+ arefstate->lowerprovided,
+ arefstate->replacevalue,
+ arefstate->replacenull,
+ arefstate->refattrlength,
+ arefstate->refelemlength,
+ arefstate->refelembyval,
+ arefstate->refelemalign);
+ }
+}
+
+/*
+ * Evaluate a rowtype coercion operation.
+ * This may require rearranging field positions.
+ *
+ * Source record is in step's result variable.
+ */
+void
+ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ ConvertRowtypeExpr *convert = op->d.convert_rowtype.convert;
+ HeapTuple result;
+ Datum tupDatum;
+ HeapTupleHeader tuple;
+ HeapTupleData tmptup;
+ TupleDesc indesc,
+ outdesc;
+
+ /* NULL in -> NULL out */
+ if (*op->resnull)
+ return;
+
+ tupDatum = *op->resvalue;
+ tuple = DatumGetHeapTupleHeader(tupDatum);
+
+ /* Lookup tupdescs if first time through or after rescan */
+ if (op->d.convert_rowtype.indesc == NULL)
+ {
+ get_cached_rowtype(exprType((Node *) convert->arg), -1,
+ &op->d.convert_rowtype.indesc,
+ econtext);
+ op->d.convert_rowtype.initialized = false;
+ }
+ if (op->d.convert_rowtype.outdesc == NULL)
+ {
+ get_cached_rowtype(convert->resulttype, -1,
+ &op->d.convert_rowtype.outdesc,
+ econtext);
+ op->d.convert_rowtype.initialized = false;
+ }
+
+ indesc = op->d.convert_rowtype.indesc;
+ outdesc = op->d.convert_rowtype.outdesc;
+
+ /*
+ * We used to be able to assert that incoming tuples are marked with
+ * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
+ * might change the tuples' marking to plain RECORD due to inserting
+ * aliases, we can only make this weak test:
+ */
+ Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
+ HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
+
+ /* if first time through, initialize conversion map */
+ if (!op->d.convert_rowtype.initialized)
+ {
+ MemoryContext old_cxt;
+
+ /* allocate map in long-lived memory context */
+ old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+
+ /* prepare map from old to new attribute numbers */
+ op->d.convert_rowtype.map =
+ convert_tuples_by_name(indesc, outdesc,
+ gettext_noop("could not convert row type"));
+ op->d.convert_rowtype.initialized = true;
+
+ MemoryContextSwitchTo(old_cxt);
+ }
+
+ /* Following steps need a HeapTuple not a bare HeapTupleHeader */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+ tmptup.t_data = tuple;
+
+ if (op->d.convert_rowtype.map != NULL)
+ {
+ /* Full conversion with attribute rearrangement needed */
+ result = do_convert_tuple(&tmptup, op->d.convert_rowtype.map);
+ /* Result already has appropriate composite-datum header fields */
+ *op->resvalue = HeapTupleGetDatum(result);
+ }
+ else
+ {
+ /*
+ * The tuple is physically compatible as-is, but we need to insert the
+ * destination rowtype OID in its composite-datum header field, so we
+ * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
+ * for this since it will both make the physical copy and insert the
+ * correct composite header fields. Note that we aren't expecting to
+ * have to flatten any toasted fields: the input was a composite
+ * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
+ * is overkill here, but its check for external fields is cheap.
+ */
+ *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
+ }
+}
+
+/*
+ * Evaluate "scalar op ANY/ALL (array)".
+ *
+ * Source array is in our result area, scalar arg is already evaluated into
+ * fcinfo->arg[0]/argnull[0].
+ *
+ * The operator always yields boolean, and we combine the results across all
+ * array elements using OR and AND (for ANY and ALL respectively). Of course
+ * we short-circuit as soon as the result is known.
+ */
+void
+ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
+{
+ FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
+ bool useOr = op->d.scalararrayop.useOr;
+ bool strictfunc = op->d.scalararrayop.finfo->fn_strict;
+ ArrayType *arr;
+ int nitems;
+ Datum result;
+ bool resultnull;
+ int i;
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+ char *s;
+ bits8 *bitmap;
+ int bitmask;
+
+ /*
+ * If the array is NULL then we return NULL --- it's not very meaningful
+ * to do anything else, even if the operator isn't strict.
+ */
+ if (*op->resnull)
+ return;
+
+ /* Else okay to fetch and detoast the array */
+ arr = DatumGetArrayTypeP(*op->resvalue);
+
+ /*
+ * If the array is empty, we return either FALSE or TRUE per the useOr
+ * flag. This is correct even if the scalar is NULL; since we would
+ * evaluate the operator zero times, it matters not whether it would want
+ * to return NULL.
+ */
+ nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
+ if (nitems <= 0)
+ {
+ *op->resvalue = BoolGetDatum(!useOr);
+ *op->resnull = false;
+ return;
+ }
+
+ /*
+ * If the scalar is NULL, and the function is strict, return NULL; no
+ * point in iterating the loop.
+ */
+ if (fcinfo->argnull[0] && strictfunc)
+ {
+ *op->resnull = true;
+ return;
+ }
+
+ /*
+ * We arrange to look up info about the element type only once per series
+ * of calls, assuming the element type doesn't change underneath us.
+ */
+ if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
+ {
+ get_typlenbyvalalign(ARR_ELEMTYPE(arr),
+ &op->d.scalararrayop.typlen,
+ &op->d.scalararrayop.typbyval,
+ &op->d.scalararrayop.typalign);
+ op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
+ }
+
+ typlen = op->d.scalararrayop.typlen;
+ typbyval = op->d.scalararrayop.typbyval;
+ typalign = op->d.scalararrayop.typalign;
+
+ /* Initialize result appropriately depending on useOr */
+ result = BoolGetDatum(!useOr);
+ resultnull = false;
+
+ /* Loop over the array elements */
+ s = (char *) ARR_DATA_PTR(arr);
+ bitmap = ARR_NULLBITMAP(arr);
+ bitmask = 1;
+
+ for (i = 0; i < nitems; i++)
+ {
+ Datum elt;
+ Datum thisresult;
+
+ /* Get array element, checking for NULL */
+ if (bitmap && (*bitmap & bitmask) == 0)
+ {
+ fcinfo->arg[1] = (Datum) 0;
+ fcinfo->argnull[1] = true;
+ }
+ else
+ {
+ elt = fetch_att(s, typbyval, typlen);
+ s = att_addlength_pointer(s, typlen, s);
+ s = (char *) att_align_nominal(s, typalign);
+ fcinfo->arg[1] = elt;
+ fcinfo->argnull[1] = false;
+ }
+
+ /* Call comparison function */
+ if (fcinfo->argnull[1] && strictfunc)
+ {
+ fcinfo->isnull = true;
+ thisresult = (Datum) 0;
+ }
+ else
+ {
+ fcinfo->isnull = false;
+ thisresult = (op->d.scalararrayop.fn_addr) (fcinfo);
+ }
+
+ /* Combine results per OR or AND semantics */
+ if (fcinfo->isnull)
+ resultnull = true;
+ else if (useOr)
+ {
+ if (DatumGetBool(thisresult))
+ {
+ result = BoolGetDatum(true);
+ resultnull = false;
+ break; /* needn't look at any more elements */
+ }
+ }
+ else
+ {
+ if (!DatumGetBool(thisresult))
+ {
+ result = BoolGetDatum(false);
+ resultnull = false;
+ break; /* needn't look at any more elements */
+ }
+ }
+
+ /* advance bitmap pointer if any */
+ if (bitmap)
+ {
+ bitmask <<= 1;
+ if (bitmask == 0x100)
+ {
+ bitmap++;
+ bitmask = 1;
+ }
+ }
+ }
+
+ *op->resvalue = result;
+ *op->resnull = resultnull;
+}
+
+/*
+ * Evaluate a NOT NULL domain constraint.
+ */
+void
+ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op)
+{
+ if (*op->resnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_NOT_NULL_VIOLATION),
+ errmsg("domain %s does not allow null values",
+ format_type_be(op->d.domaincheck.resulttype)),
+ errdatatype(op->d.domaincheck.resulttype)));
+}
+
+/*
+ * Evaluate a CHECK domain constraint.
+ */
+void
+ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
+{
+ if (!*op->d.domaincheck.checknull &&
+ !DatumGetBool(*op->d.domaincheck.checkvalue))
+ ereport(ERROR,
+ (errcode(ERRCODE_CHECK_VIOLATION),
+ errmsg("value for domain %s violates check constraint \"%s\"",
+ format_type_be(op->d.domaincheck.resulttype),
+ op->d.domaincheck.constraintname),
+ errdomainconstraint(op->d.domaincheck.resulttype,
+ op->d.domaincheck.constraintname)));
+}
+
+/*
+ * Evaluate the various forms of XmlExpr.
+ *
+ * Arguments have been evaluated into named_argvalue/named_argnull
+ * and/or argvalue/argnull arrays.
+ */
+void
+ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
+{
+ XmlExpr *xexpr = op->d.xmlexpr.xexpr;
+ Datum value;
+ int i;
+
+ *op->resnull = true; /* until we get a result */
+ *op->resvalue = (Datum) 0;
+
+ switch (xexpr->op)
+ {
+ case IS_XMLCONCAT:
+ {
+ Datum *argvalue = op->d.xmlexpr.argvalue;
+ bool *argnull = op->d.xmlexpr.argnull;
+ List *values = NIL;
+
+ for (i = 0; i < list_length(xexpr->args); i++)
+ {
+ if (!argnull[i])
+ values = lappend(values, DatumGetPointer(argvalue[i]));
+ }
+
+ if (values != NIL)
+ {
+ *op->resvalue = PointerGetDatum(xmlconcat(values));
+ *op->resnull = false;
+ }
+ }
+ break;
+
+ case IS_XMLFOREST:
+ {
+ Datum *argvalue = op->d.xmlexpr.named_argvalue;
+ bool *argnull = op->d.xmlexpr.named_argnull;
+ StringInfoData buf;
+ ListCell *lc;
+ ListCell *lc2;
+
+ initStringInfo(&buf);
+
+ i = 0;
+ forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
+ {
+ Expr *e = (Expr *) lfirst(lc);
+ char *argname = strVal(lfirst(lc2));
+
+ if (!argnull[i])
+ {
+ value = argvalue[i];
+ appendStringInfo(&buf, "<%s>%s</%s>",
+ argname,
+ map_sql_value_to_xml_value(value,
+ exprType((Node *) e), true),
+ argname);
+ *op->resnull = false;
+ }
+ i++;
+ }
+
+ if (!*op->resnull)
+ {
+ text *result;
+
+ result = cstring_to_text_with_len(buf.data, buf.len);
+ *op->resvalue = PointerGetDatum(result);
+ }
+
+ pfree(buf.data);
+ }
+ break;
+
+ case IS_XMLELEMENT:
+ *op->resvalue = PointerGetDatum(xmlelement(xexpr,
+ op->d.xmlexpr.named_argvalue,
+ op->d.xmlexpr.named_argnull,
+ op->d.xmlexpr.argvalue,
+ op->d.xmlexpr.argnull));
+ *op->resnull = false;
+ break;
+
+ case IS_XMLPARSE:
+ {
+ Datum *argvalue = op->d.xmlexpr.argvalue;
+ bool *argnull = op->d.xmlexpr.argnull;
+ text *data;
+ bool preserve_whitespace;
+
+ /* arguments are known to be text, bool */
+ Assert(list_length(xexpr->args) == 2);
+
+ if (argnull[0])
+ return;
+ value = argvalue[0];
+ data = DatumGetTextPP(value);
+
+ if (argnull[1]) /* probably can't happen */
+ return;
+ value = argvalue[1];
+ preserve_whitespace = DatumGetBool(value);
+
+ *op->resvalue = PointerGetDatum(xmlparse(data,
+ xexpr->xmloption,
+ preserve_whitespace));
+ *op->resnull = false;
+ }
+ break;
+
+ case IS_XMLPI:
+ {
+ text *arg;
+ bool isnull;
+
+ /* optional argument is known to be text */
+ Assert(list_length(xexpr->args) <= 1);
+
+ if (xexpr->args)
+ {
+ isnull = op->d.xmlexpr.argnull[0];
+ if (isnull)
+ arg = NULL;
+ else
+ arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
+ }
+ else
+ {
+ arg = NULL;
+ isnull = false;
+ }
+
+ *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
+ arg,
+ isnull,
+ op->resnull));
+ }
+ break;
+
+ case IS_XMLROOT:
+ {
+ Datum *argvalue = op->d.xmlexpr.argvalue;
+ bool *argnull = op->d.xmlexpr.argnull;
+ xmltype *data;
+ text *version;
+ int standalone;
+
+ /* arguments are known to be xml, text, int */
+ Assert(list_length(xexpr->args) == 3);
+
+ if (argnull[0])
+ return;
+ data = DatumGetXmlP(argvalue[0]);
+
+ if (argnull[1])
+ version = NULL;
+ else
+ version = DatumGetTextPP(argvalue[1]);
+
+ Assert(!argnull[2]); /* always present */
+ standalone = DatumGetInt32(argvalue[2]);
+
+ *op->resvalue = PointerGetDatum(xmlroot(data,
+ version,
+ standalone));
+ *op->resnull = false;
+ }
+ break;
+
+ case IS_XMLSERIALIZE:
+ {
+ Datum *argvalue = op->d.xmlexpr.argvalue;
+ bool *argnull = op->d.xmlexpr.argnull;
+
+ /* argument type is known to be xml */
+ Assert(list_length(xexpr->args) == 1);
+
+ if (argnull[0])
+ return;
+ value = argvalue[0];
+
+ *op->resvalue = PointerGetDatum(
+ xmltotext_with_xmloption(DatumGetXmlP(value),
+ xexpr->xmloption));
+ *op->resnull = false;
+ }
+ break;
+
+ case IS_DOCUMENT:
+ {
+ Datum *argvalue = op->d.xmlexpr.argvalue;
+ bool *argnull = op->d.xmlexpr.argnull;
+
+ /* optional argument is known to be xml */
+ Assert(list_length(xexpr->args) == 1);
+
+ if (argnull[0])
+ return;
+ value = argvalue[0];
+
+ *op->resvalue =
+ BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
+ *op->resnull = false;
+ }
+ break;
+
+ default:
+ elog(ERROR, "unrecognized XML operation");
+ break;
+ }
+}
+
+/*
+ * ExecEvalGroupingFunc
+ *
+ * Computes a bitmask with a bit for each (unevaluated) argument expression
+ * (rightmost arg is least significant bit).
+ *
+ * A bit is set if the corresponding expression is NOT part of the set of
+ * grouping expressions in the current grouping set.
+ */
+void
+ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op)
+{
+ int result = 0;
+ Bitmapset *grouped_cols = op->d.grouping_func.parent->grouped_cols;
+ ListCell *lc;
+
+ foreach(lc, op->d.grouping_func.clauses)
+ {
+ int attnum = lfirst_int(lc);
+
+ result <<= 1;
+
+ if (!bms_is_member(attnum, grouped_cols))
+ result |= 1;
+ }
+
+ *op->resvalue = Int32GetDatum(result);
+ *op->resnull = false;
+}
+
+/*
+ * Hand off evaluation of a subplan to nodeSubplan.c
+ */
+void
+ExecEvalSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ SubPlanState *sstate = op->d.subplan.sstate;
+
+ /* could potentially be nested, so make sure there's enough stack */
+ check_stack_depth();
+
+ *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
+}
+
+/*
+ * Hand off evaluation of an alternative subplan to nodeSubplan.c
+ */
+void
+ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ AlternativeSubPlanState *asstate = op->d.alternative_subplan.asstate;
+
+ /* could potentially be nested, so make sure there's enough stack */
+ check_stack_depth();
+
+ *op->resvalue = ExecAlternativeSubPlan(asstate, econtext, op->resnull);
+}
+
+/*
+ * Evaluate a wholerow Var expression.
+ *
+ * Returns a Datum whose value is the value of a whole-row range variable
+ * with respect to given expression context.
+ */
+void
+ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
+{
+ Var *variable = op->d.wholerow.var;
+ TupleTableSlot *slot;
+ TupleDesc output_tupdesc;
+ MemoryContext oldcontext;
+ HeapTupleHeader dtuple;
+ HeapTuple tuple;
+
+ /* This was checked by ExecInitExpr */
+ Assert(variable->varattno == InvalidAttrNumber);
+
+ /* Get the input slot we want */
+ switch (variable->varno)
+ {
+ case INNER_VAR:
+ /* get the tuple from the inner node */
+ slot = econtext->ecxt_innertuple;
+ break;
+
+ case OUTER_VAR:
+ /* get the tuple from the outer node */
+ slot = econtext->ecxt_outertuple;
+ break;
+
+ /* INDEX_VAR is handled by default case */
+
+ default:
+ /* get the tuple from the relation being scanned */
+ slot = econtext->ecxt_scantuple;
+ break;
+ }
+
+ /* Apply the junkfilter if any */
+ if (op->d.wholerow.junkFilter != NULL)
+ slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
+
+ /*
+ * If first time through, obtain tuple descriptor and check compatibility.
+ *
+ * XXX: It'd be great if this could be moved to the expression
+ * initialization phase, but due to using slots that's currently not
+ * feasible.
+ */
+ if (op->d.wholerow.first)
+ {
+ /* optimistically assume we don't need slow path */
+ op->d.wholerow.slow = false;
+
+ /*
+ * If the Var identifies a named composite type, we must check that
+ * the actual tuple type is compatible with it.
+ */
+ if (variable->vartype != RECORDOID)
+ {
+ TupleDesc var_tupdesc;
+ TupleDesc slot_tupdesc;
+ int i;
+
+ /*
+ * We really only care about numbers of attributes and data types.
+ * Also, we can ignore type mismatch on columns that are dropped
+ * in the destination type, so long as (1) the physical storage
+ * matches or (2) the actual column value is NULL. Case (1) is
+ * helpful in some cases involving out-of-date cached plans, while
+ * case (2) is expected behavior in situations such as an INSERT
+ * into a table with dropped columns (the planner typically
+ * generates an INT4 NULL regardless of the dropped column type).
+ * If we find a dropped column and cannot verify that case (1)
+ * holds, we have to use the slow path to check (2) for each row.
+ */
+ var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1);
+
+ slot_tupdesc = slot->tts_tupleDescriptor;
+
+ if (var_tupdesc->natts != slot_tupdesc->natts)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("table row type and query-specified row type do not match"),
+ errdetail_plural("Table row contains %d attribute, but query expects %d.",
+ "Table row contains %d attributes, but query expects %d.",
+ slot_tupdesc->natts,
+ slot_tupdesc->natts,
+ var_tupdesc->natts)));
+
+ for (i = 0; i < var_tupdesc->natts; i++)
+ {
+ Form_pg_attribute vattr = var_tupdesc->attrs[i];
+ Form_pg_attribute sattr = slot_tupdesc->attrs[i];
+
+ if (vattr->atttypid == sattr->atttypid)
+ continue; /* no worries */
+ if (!vattr->attisdropped)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("table row type and query-specified row type do not match"),
+ errdetail("Table has type %s at ordinal position %d, but query expects %s.",
+ format_type_be(sattr->atttypid),
+ i + 1,
+ format_type_be(vattr->atttypid))));
+
+ if (vattr->attlen != sattr->attlen ||
+ vattr->attalign != sattr->attalign)
+ op->d.wholerow.slow = true; /* need to check for nulls */
+ }
+
+ /*
+ * Use the variable's declared rowtype as the descriptor for the
+ * output values, modulo possibly assigning new column names
+ * below. In particular, we *must* absorb any attisdropped
+ * markings.
+ */
+ oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ output_tupdesc = CreateTupleDescCopy(var_tupdesc);
+ MemoryContextSwitchTo(oldcontext);
+
+ ReleaseTupleDesc(var_tupdesc);
+ }
+ else
+ {
+ /*
+ * In the RECORD case, we use the input slot's rowtype as the
+ * descriptor for the output values, modulo possibly assigning new
+ * column names below.
+ */
+ oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /*
+ * Construct a tuple descriptor for the composite values we'll
+ * produce, and make sure its record type is "blessed". The main
+ * reason to do this is to be sure that operations such as
+ * row_to_json() will see the desired column names when they look up
+ * the descriptor from the type information embedded in the composite
+ * values.
+ *
+ * We already got the correct physical datatype info above, but now we
+ * should try to find the source RTE and adopt its column aliases, in
+ * case they are different from the original rowtype's names. For
+ * example, in "SELECT foo(t) FROM tab t(x,y)", the first two columns
+ * in the composite output should be named "x" and "y" regardless of
+ * tab's column names.
+ *
+ * If we can't locate the RTE, assume the column names we've got are
+ * OK. (As of this writing, the only cases where we can't locate the
+ * RTE are in execution of trigger WHEN clauses, and then the Var will
+ * have the trigger's relation's rowtype, so its names are fine.)
+ * Also, if the creator of the RTE didn't bother to fill in an eref
+ * field, assume our column names are OK. (This happens in COPY, and
+ * perhaps other places.)
+ */
+ if (econtext->ecxt_estate &&
+ variable->varno <= list_length(econtext->ecxt_estate->es_range_table))
+ {
+ RangeTblEntry *rte = rt_fetch(variable->varno,
+ econtext->ecxt_estate->es_range_table);
+
+ if (rte->eref)
+ ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
+ }
+
+ /* Bless the tupdesc if needed, and save it in the execution state */
+ op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
+
+ op->d.wholerow.first = false;
+ }
+
+ /*
+ * Make sure all columns of the slot are accessible in the slot's
+ * Datum/isnull arrays.
+ */
+ slot_getallattrs(slot);
+
+ if (op->d.wholerow.slow)
+ {
+ /* Check to see if any dropped attributes are non-null */
+ TupleDesc tupleDesc = slot->tts_tupleDescriptor;
+ TupleDesc var_tupdesc = op->d.wholerow.tupdesc;
+ int i;
+
+ Assert(var_tupdesc->natts == tupleDesc->natts);
+
+ for (i = 0; i < var_tupdesc->natts; i++)
+ {
+ Form_pg_attribute vattr = var_tupdesc->attrs[i];
+ Form_pg_attribute sattr = tupleDesc->attrs[i];
+
+ if (!vattr->attisdropped)
+ continue; /* already checked non-dropped cols */
+ if (slot->tts_isnull[i])
+ continue; /* null is always okay */
+ if (vattr->attlen != sattr->attlen ||
+ vattr->attalign != sattr->attalign)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("table row type and query-specified row type do not match"),
+ errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
+ i + 1)));
+ }
+ }
+
+ /*
+ * Build a composite datum, making sure any toasted fields get detoasted.
+ *
+ * (Note: it is critical that we not change the slot's state here.)
+ */
+ tuple = toast_build_flattened_tuple(slot->tts_tupleDescriptor,
+ slot->tts_values,
+ slot->tts_isnull);
+ dtuple = tuple->t_data;
+
+ /*
+ * Label the datum with the composite type info we identified before.
+ *
+ * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
+ * the tuple build step; but that seems a tad risky so let's not.)
+ */
+ HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
+ HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
+
+ *op->resvalue = PointerGetDatum(dtuple);
+ *op->resnull = false;
+}
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 808275a094..07c8852fca 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -7,7 +7,7 @@
* collation-sensitive, so the code in this file has no support for passing
* collation settings through from callers. That may have to change someday.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -18,17 +18,32 @@
*/
#include "postgres.h"
+#include "access/hash.h"
+#include "access/parallel.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+static uint32 TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple);
+static int TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2);
-static TupleHashTable CurTupleHashTable = NULL;
-
-static uint32 TupleHashTableHash(const void *key, Size keysize);
-static int TupleHashTableMatch(const void *key1, const void *key2,
- Size keysize);
+/*
+ * Define parameters for tuple hash table code generation. The interface is
+ * *also* declared in execnodes.h (to generate the types, which are externally
+ * visible).
+ */
+#define SH_PREFIX tuplehash
+#define SH_ELEMENT_TYPE TupleHashEntryData
+#define SH_KEY_TYPE MinimalTuple
+#define SH_KEY firstTuple
+#define SH_HASH_KEY(tb, key) TupleHashTableHash(tb, key)
+#define SH_EQUAL(tb, a, b) TupleHashTableMatch(tb, a, b) == 0
+#define SH_SCOPE extern
+#define SH_STORE_HASH
+#define SH_GET_HASH(tb, a) a->hash
+#define SH_DEFINE
+#include "lib/simplehash.h"
/*****************************************************************************
@@ -260,7 +275,7 @@ execTuplesHashPrepare(int numCols,
* eqfunctions: equality comparison functions to use
* hashfunctions: datatype-specific hashing functions to use
* nbuckets: initial estimate of hashtable size
- * entrysize: size of each entry (at least sizeof(TupleHashEntryData))
+ * additionalsize: size of data stored in ->additional
* tablecxt: memory context in which to store table and table entries
* tempcxt: short-lived context for evaluation hash and comparison functions
*
@@ -275,20 +290,20 @@ TupleHashTable
BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
FmgrInfo *eqfunctions,
FmgrInfo *hashfunctions,
- long nbuckets, Size entrysize,
- MemoryContext tablecxt, MemoryContext tempcxt)
+ long nbuckets, Size additionalsize,
+ MemoryContext tablecxt, MemoryContext tempcxt,
+ bool use_variable_hash_iv)
{
TupleHashTable hashtable;
- HASHCTL hash_ctl;
+ Size entrysize = sizeof(TupleHashEntryData) + additionalsize;
Assert(nbuckets > 0);
- Assert(entrysize >= sizeof(TupleHashEntryData));
/* Limit initial table size request to not more than work_mem */
nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));
- hashtable = (TupleHashTable) MemoryContextAlloc(tablecxt,
- sizeof(TupleHashTableData));
+ hashtable = (TupleHashTable)
+ MemoryContextAlloc(tablecxt, sizeof(TupleHashTableData));
hashtable->numCols = numCols;
hashtable->keyColIdx = keyColIdx;
@@ -302,15 +317,20 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
hashtable->in_hash_funcs = NULL;
hashtable->cur_eq_funcs = NULL;
- MemSet(&hash_ctl, 0, sizeof(hash_ctl));
- hash_ctl.keysize = sizeof(TupleHashEntryData);
- hash_ctl.entrysize = entrysize;
- hash_ctl.hash = TupleHashTableHash;
- hash_ctl.match = TupleHashTableMatch;
- hash_ctl.hcxt = tablecxt;
- hashtable->hashtab = hash_create("TupleHashTable", nbuckets,
- &hash_ctl,
- HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
+ /*
+ * If parallelism is in use, even if the master backend is performing the
+ * scan itself, we don't want to create the hashtable exactly the same way
+ * in all workers. As hashtables are iterated over in keyspace-order,
+ * doing so in all processes in the same way is likely to lead to
+ * "unbalanced" hashtables when the table size initially is
+ * underestimated.
+ */
+ if (use_variable_hash_iv)
+ hashtable->hash_iv = hash_uint32(ParallelWorkerNumber);
+ else
+ hashtable->hash_iv = 0;
+
+ hashtable->hashtab = tuplehash_create(tablecxt, nbuckets, hashtable);
return hashtable;
}
@@ -324,18 +344,17 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
*
* If isnew isn't NULL, then a new entry is created if no existing entry
* matches. On return, *isnew is true if the entry is newly created,
- * false if it existed already. Any extra space in a new entry has been
- * zeroed.
+ * false if it existed already. ->additional_data in the new entry has
+ * been zeroed.
*/
TupleHashEntry
LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
bool *isnew)
{
- TupleHashEntry entry;
+ TupleHashEntryData *entry;
MemoryContext oldContext;
- TupleHashTable saveCurHT;
- TupleHashEntryData dummy;
bool found;
+ MinimalTuple key;
/* If first time through, clone the input slot to make table slot */
if (hashtable->tableslot == NULL)
@@ -356,28 +375,17 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
/* Need to run the hash functions in short-lived context */
oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
- /*
- * Set up data needed by hash and match functions
- *
- * We save and restore CurTupleHashTable just in case someone manages to
- * invoke this code re-entrantly.
- */
+ /* set up data needed by hash and match functions */
hashtable->inputslot = slot;
hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
hashtable->cur_eq_funcs = hashtable->tab_eq_funcs;
- saveCurHT = CurTupleHashTable;
- CurTupleHashTable = hashtable;
-
- /* Search the hash table */
- dummy.firstTuple = NULL; /* flag to reference inputslot */
- entry = (TupleHashEntry) hash_search(hashtable->hashtab,
- &dummy,
- isnew ? HASH_ENTER : HASH_FIND,
- &found);
+ key = NULL; /* flag to reference inputslot */
if (isnew)
{
+ entry = tuplehash_insert(hashtable->hashtab, key, &found);
+
if (found)
{
/* found pre-existing entry */
@@ -385,24 +393,19 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
}
else
{
- /*
- * created new entry
- *
- * Zero any caller-requested space in the entry. (This zaps the
- * "key data" dynahash.c copied into the new entry, but we don't
- * care since we're about to overwrite it anyway.)
- */
- MemSet(entry, 0, hashtable->entrysize);
-
- /* Copy the first tuple into the table context */
+ /* created new entry */
+ *isnew = true;
+ /* zero caller data */
+ entry->additional = NULL;
MemoryContextSwitchTo(hashtable->tablecxt);
+ /* Copy the first tuple into the table context */
entry->firstTuple = ExecCopySlotMinimalTuple(slot);
-
- *isnew = true;
}
}
-
- CurTupleHashTable = saveCurHT;
+ else
+ {
+ entry = tuplehash_lookup(hashtable->hashtab, key);
+ }
MemoryContextSwitchTo(oldContext);
@@ -425,34 +428,19 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
{
TupleHashEntry entry;
MemoryContext oldContext;
- TupleHashTable saveCurHT;
- TupleHashEntryData dummy;
+ MinimalTuple key;
/* Need to run the hash functions in short-lived context */
oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
- /*
- * Set up data needed by hash and match functions
- *
- * We save and restore CurTupleHashTable just in case someone manages to
- * invoke this code re-entrantly.
- */
+ /* Set up data needed by hash and match functions */
hashtable->inputslot = slot;
hashtable->in_hash_funcs = hashfunctions;
hashtable->cur_eq_funcs = eqfunctions;
- saveCurHT = CurTupleHashTable;
- CurTupleHashTable = hashtable;
-
/* Search the hash table */
- dummy.firstTuple = NULL; /* flag to reference inputslot */
- entry = (TupleHashEntry) hash_search(hashtable->hashtab,
- &dummy,
- HASH_FIND,
- NULL);
-
- CurTupleHashTable = saveCurHT;
-
+ key = NULL; /* flag to reference inputslot */
+ entry = tuplehash_lookup(hashtable->hashtab, key);
MemoryContextSwitchTo(oldContext);
return entry;
@@ -468,22 +456,18 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
* This convention avoids the need to materialize virtual input tuples unless
* they actually need to get copied into the table.
*
- * CurTupleHashTable must be set before calling this, since dynahash.c
- * doesn't provide any API that would let us get at the hashtable otherwise.
- *
* Also, the caller must select an appropriate memory context for running
* the hash functions. (dynahash.c doesn't change CurrentMemoryContext.)
*/
static uint32
-TupleHashTableHash(const void *key, Size keysize)
+TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
{
- MinimalTuple tuple = ((const TupleHashEntryData *) key)->firstTuple;
- TupleTableSlot *slot;
- TupleHashTable hashtable = CurTupleHashTable;
+ TupleHashTable hashtable = (TupleHashTable) tb->private_data;
int numCols = hashtable->numCols;
AttrNumber *keyColIdx = hashtable->keyColIdx;
+ uint32 hashkey = hashtable->hash_iv;
+ TupleTableSlot *slot;
FmgrInfo *hashfunctions;
- uint32 hashkey = 0;
int i;
if (tuple == NULL)
@@ -494,8 +478,12 @@ TupleHashTableHash(const void *key, Size keysize)
}
else
{
- /* Process a tuple already stored in the table */
- /* (this case never actually occurs in current dynahash.c code) */
+ /*
+ * Process a tuple already stored in the table.
+ *
+ * (this case never actually occurs due to the way simplehash.h is
+ * used, as the hash-value is stored in the entries)
+ */
slot = hashtable->tableslot;
ExecStoreMinimalTuple(tuple, slot, false);
hashfunctions = hashtable->tab_hash_funcs;
@@ -530,29 +518,21 @@ TupleHashTableHash(const void *key, Size keysize)
*
* As above, the passed pointers are pointers to TupleHashEntryData.
*
- * CurTupleHashTable must be set before calling this, since dynahash.c
- * doesn't provide any API that would let us get at the hashtable otherwise.
- *
* Also, the caller must select an appropriate memory context for running
* the compare functions. (dynahash.c doesn't change CurrentMemoryContext.)
*/
static int
-TupleHashTableMatch(const void *key1, const void *key2, Size keysize)
+TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2)
{
- MinimalTuple tuple1 = ((const TupleHashEntryData *) key1)->firstTuple;
-
-#ifdef USE_ASSERT_CHECKING
- MinimalTuple tuple2 = ((const TupleHashEntryData *) key2)->firstTuple;
-#endif
TupleTableSlot *slot1;
TupleTableSlot *slot2;
- TupleHashTable hashtable = CurTupleHashTable;
+ TupleHashTable hashtable = (TupleHashTable) tb->private_data;
/*
- * We assume that dynahash.c will only ever call us with the first
+ * We assume that simplehash.h will only ever call us with the first
* argument being an actual table entry, and the second argument being
* LookupTupleHashEntry's dummy TupleHashEntryData. The other direction
- * could be supported too, but is not currently used by dynahash.c.
+ * could be supported too, but is not currently required.
*/
Assert(tuple1 != NULL);
slot1 = hashtable->tableslot;
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index 0e2d834ed1..108060ac0f 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -2,7 +2,7 @@
*
* execIndexing.c
* routines for inserting index tuples and enforcing unique and
- * exclusive constraints.
+ * exclusion constraints.
*
* ExecInsertIndexTuples() is the main entry point. It's called after
* inserting a tuple to the heap, and it inserts corresponding index tuples
@@ -95,7 +95,7 @@
* with the higher XID backs out.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -327,23 +327,21 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
/* Check for partial index */
if (indexInfo->ii_Predicate != NIL)
{
- List *predicate;
+ ExprState *predicate;
/*
* If predicate state not set up yet, create it (in the estate's
* per-query context)
*/
predicate = indexInfo->ii_PredicateState;
- if (predicate == NIL)
+ if (predicate == NULL)
{
- predicate = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
- estate);
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
indexInfo->ii_PredicateState = predicate;
}
/* Skip this index-update if the predicate isn't satisfied */
- if (!ExecQual(predicate, econtext, false))
+ if (!ExecQual(predicate, econtext))
continue;
}
@@ -391,7 +389,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
isnull, /* null flags */
tupleid, /* tid of heap tuple */
heapRelation, /* heap relation */
- checkUnique); /* type of uniqueness check to do */
+ checkUnique, /* type of uniqueness check to do */
+ indexInfo); /* index AM may need this */
/*
* If the index has an associated exclusion constraint, check that.
@@ -550,23 +549,21 @@ ExecCheckIndexConstraints(TupleTableSlot *slot,
/* Check for partial index */
if (indexInfo->ii_Predicate != NIL)
{
- List *predicate;
+ ExprState *predicate;
/*
* If predicate state not set up yet, create it (in the estate's
* per-query context)
*/
predicate = indexInfo->ii_PredicateState;
- if (predicate == NIL)
+ if (predicate == NULL)
{
- predicate = (List *)
- ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
- estate);
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
indexInfo->ii_PredicateState = predicate;
}
/* Skip this index-update if the predicate isn't satisfied */
- if (!ExecQual(predicate, econtext, false))
+ if (!ExecQual(predicate, econtext))
continue;
}
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 74a10048a2..a422327c88 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -3,7 +3,7 @@
* execJunk.c
* Junk attribute support stuff....
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 2eaa33455c..7232b0911f 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
* which should also omit ExecutorRun.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -43,6 +43,8 @@
#include "access/transam.h"
#include "access/xact.h"
#include "catalog/namespace.h"
+#include "catalog/partition.h"
+#include "catalog/pg_publication.h"
#include "commands/matview.h"
#include "commands/trigger.h"
#include "executor/execdebug.h"
@@ -51,6 +53,7 @@
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "parser/parsetree.h"
+#include "rewrite/rewriteManip.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "tcop/utility.h"
@@ -58,6 +61,7 @@
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rls.h"
+#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
#ifdef PGXC
@@ -90,7 +94,8 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
bool sendTuples,
uint64 numberTuples,
ScanDirection direction,
- DestReceiver *dest);
+ DestReceiver *dest,
+ bool execute_once);
static bool ExecCheckRTEPerms(RangeTblEntry *rte);
static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid,
Bitmapset *modifiedCols,
@@ -101,6 +106,10 @@ static char *ExecBuildSlotValueDescription(Oid reloid,
TupleDesc tupdesc,
Bitmapset *modifiedCols,
int maxfieldlen);
+static char *ExecBuildSlotPartitionKeyDescription(Relation rel,
+ Datum *values,
+ bool *isnull,
+ int maxfieldlen);
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan *planTree);
@@ -234,6 +243,13 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData));
#endif
+ estate->es_sourceText = queryDesc->sourceText;
+
+ /*
+ * Fill in the query environment, if any, from queryDesc.
+ */
+ estate->es_queryEnv = queryDesc->queryEnv;
+
/*
* If non-read-only query, set the command ID to mark output tuples with
*/
@@ -325,17 +341,18 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
*/
void
ExecutorRun(QueryDesc *queryDesc,
- ScanDirection direction, uint64 count)
+ ScanDirection direction, uint64 count,
+ bool execute_once)
{
if (ExecutorRun_hook)
- (*ExecutorRun_hook) (queryDesc, direction, count);
+ (*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
else
- standard_ExecutorRun(queryDesc, direction, count);
+ standard_ExecutorRun(queryDesc, direction, count, execute_once);
}
void
standard_ExecutorRun(QueryDesc *queryDesc,
- ScanDirection direction, uint64 count)
+ ScanDirection direction, uint64 count, bool execute_once)
{
EState *estate;
CmdType operation;
@@ -382,6 +399,11 @@ standard_ExecutorRun(QueryDesc *queryDesc,
* run plan
*/
if (!ScanDirectionIsNoMovement(direction))
+ {
+ if (execute_once && queryDesc->already_executed)
+ elog(ERROR, "can't re-execute query flagged for single execution");
+ queryDesc->already_executed = true;
+
ExecutePlan(estate,
queryDesc->planstate,
queryDesc->plannedstmt->parallelModeNeeded,
@@ -389,7 +411,9 @@ standard_ExecutorRun(QueryDesc *queryDesc,
sendTuples,
count,
direction,
- dest);
+ dest,
+ execute_once);
+ }
/*
* shutdown tuple receiver, if we started it
@@ -628,8 +652,8 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
/*
* Only plain-relation RTEs need to be checked here. Function RTEs are
- * checked by init_fcache when the function is prepared for execution.
- * Join, subquery, and special RTEs need no checks.
+ * checked when the function is prepared for execution. Join, subquery,
+ * and special RTEs need no checks.
*/
if (rte->rtekind != RTE_RELATION)
return true;
@@ -869,9 +893,11 @@ InitPlan(QueryDesc *queryDesc, int eflags)
resultRelationOid = getrelid(resultRelationIndex, rangeTable);
resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
+
InitResultRelInfo(resultRelInfo,
resultRelation,
resultRelationIndex,
+ NULL,
estate->es_instrument);
resultRelInfo++;
}
@@ -879,6 +905,57 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_num_result_relations = numResultRelations;
/* es_result_relation_info is NULL except when within ModifyTable */
estate->es_result_relation_info = NULL;
+
+ /*
+ * In the partitioned result relation case, lock the non-leaf result
+ * relations too. A subset of these are the roots of respective
+ * partitioned tables, for which we also allocate ResulRelInfos.
+ */
+ estate->es_root_result_relations = NULL;
+ estate->es_num_root_result_relations = 0;
+ if (plannedstmt->nonleafResultRelations)
+ {
+ int num_roots = list_length(plannedstmt->rootResultRelations);
+
+ /*
+ * Firstly, build ResultRelInfos for all the partitioned table
+ * roots, because we will need them to fire the statement-level
+ * triggers, if any.
+ */
+ resultRelInfos = (ResultRelInfo *)
+ palloc(num_roots * sizeof(ResultRelInfo));
+ resultRelInfo = resultRelInfos;
+ foreach(l, plannedstmt->rootResultRelations)
+ {
+ Index resultRelIndex = lfirst_int(l);
+ Oid resultRelOid;
+ Relation resultRelDesc;
+
+ resultRelOid = getrelid(resultRelIndex, rangeTable);
+ resultRelDesc = heap_open(resultRelOid, RowExclusiveLock);
+ InitResultRelInfo(resultRelInfo,
+ resultRelDesc,
+ lfirst_int(l),
+ NULL,
+ estate->es_instrument);
+ resultRelInfo++;
+ }
+
+ estate->es_root_result_relations = resultRelInfos;
+ estate->es_num_root_result_relations = num_roots;
+
+ /* Simply lock the rest of them. */
+ foreach(l, plannedstmt->nonleafResultRelations)
+ {
+ Index resultRelIndex = lfirst_int(l);
+
+ /* We locked the roots above. */
+ if (!list_member_int(plannedstmt->rootResultRelations,
+ resultRelIndex))
+ LockRelationOid(getrelid(resultRelIndex, rangeTable),
+ RowExclusiveLock);
+ }
+ }
}
else
{
@@ -888,12 +965,18 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_result_relations = NULL;
estate->es_num_result_relations = 0;
estate->es_result_relation_info = NULL;
+ estate->es_root_result_relations = NULL;
+ estate->es_num_root_result_relations = 0;
}
/*
* Similarly, we have to lock relations selected FOR [KEY] UPDATE/SHARE
* before we initialize the plan tree, else we'd be risking lock upgrades.
- * While we are at it, build the ExecRowMark list.
+ * While we are at it, build the ExecRowMark list. Any partitioned child
+ * tables are ignored here (because isParent=true) and will be locked by
+ * the first Append or MergeAppend node that references them. (Note that
+ * the RowMarks corresponding to partitioned child tables are present in
+ * the same list as the rest, i.e., plannedstmt->rowMarks.)
*/
estate->es_rowMarks = NIL;
foreach(l, plannedstmt->rowMarks)
@@ -1084,7 +1167,8 @@ CheckValidResultRel(Relation resultRel, CmdType operation)
switch (resultRel->rd_rel->relkind)
{
case RELKIND_RELATION:
- /* OK */
+ case RELKIND_PARTITIONED_TABLE:
+ CheckCmdReplicaIdentity(resultRel, operation);
break;
case RELKIND_SEQUENCE:
ereport(ERROR,
@@ -1217,6 +1301,7 @@ CheckValidRowMarkRel(Relation rel, RowMarkType markType)
switch (rel->rd_rel->relkind)
{
case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
/* OK */
break;
case RELKIND_SEQUENCE:
@@ -1277,8 +1362,11 @@ void
InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation resultRelationDesc,
Index resultRelationIndex,
+ Relation partition_root,
int instrument_options)
{
+ List *partition_check = NIL;
+
MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
resultRelInfo->type = T_ResultRelInfo;
resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
@@ -1294,8 +1382,8 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
palloc0(n * sizeof(FmgrInfo));
- resultRelInfo->ri_TrigWhenExprs = (List **)
- palloc0(n * sizeof(List *));
+ resultRelInfo->ri_TrigWhenExprs = (ExprState **)
+ palloc0(n * sizeof(ExprState *));
if (instrument_options)
resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
}
@@ -1314,6 +1402,39 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_ConstraintExprs = NULL;
resultRelInfo->ri_junkFilter = NULL;
resultRelInfo->ri_projectReturning = NULL;
+
+ /*
+ * If partition_root has been specified, that means we are building the
+ * ResultRelInfo for one of its leaf partitions. In that case, we need
+ * *not* initialize the leaf partition's constraint, but rather the
+ * partition_root's (if any). We must do that explicitly like this,
+ * because implicit partition constraints are not inherited like user-
+ * defined constraints and would fail to be enforced by ExecConstraints()
+ * after a tuple is routed to a leaf partition.
+ */
+ if (partition_root)
+ {
+ /*
+ * Root table itself may or may not be a partition; partition_check
+ * would be NIL in the latter case.
+ */
+ partition_check = RelationGetPartitionQual(partition_root);
+
+ /*
+ * This is not our own partition constraint, but rather an ancestor's.
+ * So any Vars in it bear the ancestor's attribute numbers. We must
+ * switch them to our own. (dummy varno = 1)
+ */
+ if (partition_check != NIL)
+ partition_check = map_partition_varattnos(partition_check, 1,
+ resultRelationDesc,
+ partition_root);
+ }
+ else
+ partition_check = RelationGetPartitionQual(resultRelationDesc);
+
+ resultRelInfo->ri_PartitionCheck = partition_check;
+ resultRelInfo->ri_PartitionRoot = partition_root;
}
/*
@@ -1376,6 +1497,7 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
InitResultRelInfo(rInfo,
rel,
0, /* dummy rangetable index */
+ NULL,
estate->es_instrument);
estate->es_trig_target_relations =
lappend(estate->es_trig_target_relations, rInfo);
@@ -1390,6 +1512,24 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
}
/*
+ * Close any relations that have been opened by ExecGetTriggerResultRel().
+ */
+void
+ExecCleanUpTriggerState(EState *estate)
+{
+ ListCell *l;
+
+ foreach(l, estate->es_trig_target_relations)
+ {
+ ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
+
+ /* Close indices and then the relation itself */
+ ExecCloseIndices(resultRelInfo);
+ heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+ }
+}
+
+/*
* ExecContextForcesOids
*
* This is pretty grotty: when doing INSERT, UPDATE, or CREATE TABLE AS,
@@ -1545,17 +1685,17 @@ ExecEndPlan(PlanState *planstate, EState *estate)
resultRelInfo++;
}
- /*
- * likewise close any trigger target relations
- */
- foreach(l, estate->es_trig_target_relations)
+ /* Close the root target relation(s). */
+ resultRelInfo = estate->es_root_result_relations;
+ for (i = estate->es_num_root_result_relations; i > 0; i--)
{
- resultRelInfo = (ResultRelInfo *) lfirst(l);
- /* Close indices and then the relation itself */
- ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+ resultRelInfo++;
}
+ /* likewise close any trigger target relations */
+ ExecCleanUpTriggerState(estate);
+
/*
* close any relations selected FOR [KEY] UPDATE/SHARE, again keeping
* locks
@@ -1589,7 +1729,8 @@ ExecutePlan(EState *estate,
bool sendTuples,
uint64 numberTuples,
ScanDirection direction,
- DestReceiver *dest)
+ DestReceiver *dest,
+ bool execute_once)
{
TupleTableSlot *slot;
uint64 current_tuple_count;
@@ -1605,16 +1746,14 @@ ExecutePlan(EState *estate,
estate->es_direction = direction;
/*
- * If a tuple count was supplied, we must force the plan to run without
- * parallelism, because we might exit early.
+ * If the plan might potentially be executed multiple times, we must force
+ * it to run without parallelism, because we might exit early. Also
+ * disable parallelism when writing into a relation, because no database
+ * changes are allowed in parallel mode.
*/
- if (numberTuples)
+ if (!execute_once || dest->mydest == DestIntoRel)
use_parallel_mode = false;
- /*
- * If a tuple count was supplied, we must force the plan to run without
- * parallelism, because we might exit early.
- */
if (use_parallel_mode)
EnterParallelMode();
@@ -1683,7 +1822,11 @@ ExecutePlan(EState *estate,
*/
current_tuple_count++;
if (numberTuples && numberTuples == current_tuple_count)
+ {
+ /* Allow nodes to release or shut down resources. */
+ (void) ExecShutdownNode(planstate);
break;
+ }
}
if (use_parallel_mode)
@@ -1705,7 +1848,6 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
ConstrCheck *check = rel->rd_att->constr->check;
ExprContext *econtext;
MemoryContext oldContext;
- List *qual;
int i;
/*
@@ -1717,13 +1859,14 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
{
oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
resultRelInfo->ri_ConstraintExprs =
- (List **) palloc(ncheck * sizeof(List *));
+ (ExprState **) palloc(ncheck * sizeof(ExprState *));
for (i = 0; i < ncheck; i++)
{
- /* ExecQual wants implicit-AND form */
- qual = make_ands_implicit(stringToNode(check[i].ccbin));
- resultRelInfo->ri_ConstraintExprs[i] = (List *)
- ExecPrepareExpr((Expr *) qual, estate);
+ Expr *checkconstr;
+
+ checkconstr = stringToNode(check[i].ccbin);
+ resultRelInfo->ri_ConstraintExprs[i] =
+ ExecPrepareExpr(checkconstr, estate);
}
MemoryContextSwitchTo(oldContext);
}
@@ -1740,14 +1883,14 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
/* And evaluate the constraints */
for (i = 0; i < ncheck; i++)
{
- qual = resultRelInfo->ri_ConstraintExprs[i];
+ ExprState *checkconstr = resultRelInfo->ri_ConstraintExprs[i];
/*
* NOTE: SQL specifies that a NULL result from a constraint expression
- * is not to be treated as a failure. Therefore, tell ExecQual to
- * return TRUE for NULL.
+ * is not to be treated as a failure. Therefore, use ExecCheck not
+ * ExecQual.
*/
- if (!ExecQual(qual, econtext, true))
+ if (!ExecCheck(checkconstr, econtext))
return check[i].ccname;
}
@@ -1755,6 +1898,55 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
return NULL;
}
+/*
+ * ExecPartitionCheck --- check that tuple meets the partition constraint.
+ *
+ * Note: This is called *iff* resultRelInfo is the main target table.
+ */
+static bool
+ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
+ EState *estate)
+{
+ ExprContext *econtext;
+
+ /*
+ * If first time through, build expression state tree for the partition
+ * check expression. Keep it in the per-query memory context so they'll
+ * survive throughout the query.
+ */
+ if (resultRelInfo->ri_PartitionCheckExpr == NULL)
+ {
+ List *qual = resultRelInfo->ri_PartitionCheck;
+
+ resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
+ }
+
+ /*
+ * We will use the EState's per-tuple context for evaluating constraint
+ * expressions (creating it if it's not already there).
+ */
+ econtext = GetPerTupleExprContext(estate);
+
+ /* Arrange for econtext's scan tuple to be the tuple under test */
+ econtext->ecxt_scantuple = slot;
+
+ /*
+ * As in case of the catalogued constraints, we treat a NULL result as
+ * success here, not a failure.
+ */
+ return ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
+}
+
+/*
+ * ExecConstraints - check constraints of the tuple in 'slot'
+ *
+ * This checks the traditional NOT NULL and check constraints, as well as
+ * the partition constraint, if any.
+ *
+ * Note: 'slot' contains the tuple to check the constraints of, which may
+ * have been converted from the original input tuple after tuple routing.
+ * 'resultRelInfo' is the original result relation, before tuple routing.
+ */
void
ExecConstraints(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate)
@@ -1766,9 +1958,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
Bitmapset *insertedCols;
Bitmapset *updatedCols;
- Assert(constr);
+ Assert(constr || resultRelInfo->ri_PartitionCheck);
- if (constr->has_not_null)
+ if (constr && constr->has_not_null)
{
int natts = tupdesc->natts;
int attrChk;
@@ -1779,6 +1971,32 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
slot_attisnull(slot, attrChk))
{
char *val_desc;
+ Relation orig_rel = rel;
+ TupleDesc orig_tupdesc = RelationGetDescr(rel);
+
+ /*
+ * If the tuple has been routed, it's been converted to the
+ * partition's rowtype, which might differ from the root
+ * table's. We must convert it back to the root table's
+ * rowtype so that val_desc shown error message matches the
+ * input tuple.
+ */
+ if (resultRelInfo->ri_PartitionRoot)
+ {
+ HeapTuple tuple = ExecFetchSlotTuple(slot);
+ TupleConversionMap *map;
+
+ rel = resultRelInfo->ri_PartitionRoot;
+ tupdesc = RelationGetDescr(rel);
+ /* a reverse map */
+ map = convert_tuples_by_name(orig_tupdesc, tupdesc,
+ gettext_noop("could not convert row type"));
+ if (map != NULL)
+ {
+ tuple = do_convert_tuple(tuple, map);
+ ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ }
+ }
insertedCols = GetInsertedColumns(resultRelInfo, estate);
updatedCols = GetUpdatedColumns(resultRelInfo, estate);
@@ -1792,20 +2010,40 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
errmsg("null value in column \"%s\" violates not-null constraint",
- NameStr(tupdesc->attrs[attrChk - 1]->attname)),
+ NameStr(orig_tupdesc->attrs[attrChk - 1]->attname)),
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
- errtablecol(rel, attrChk)));
+ errtablecol(orig_rel, attrChk)));
}
}
}
- if (constr->num_check > 0)
+ if (constr && constr->num_check > 0)
{
const char *failed;
if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
{
char *val_desc;
+ Relation orig_rel = rel;
+
+ /* See the comment above. */
+ if (resultRelInfo->ri_PartitionRoot)
+ {
+ HeapTuple tuple = ExecFetchSlotTuple(slot);
+ TupleDesc old_tupdesc = RelationGetDescr(rel);
+ TupleConversionMap *map;
+
+ rel = resultRelInfo->ri_PartitionRoot;
+ tupdesc = RelationGetDescr(rel);
+ /* a reverse map */
+ map = convert_tuples_by_name(old_tupdesc, tupdesc,
+ gettext_noop("could not convert row type"));
+ if (map != NULL)
+ {
+ tuple = do_convert_tuple(tuple, map);
+ ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ }
+ }
insertedCols = GetInsertedColumns(resultRelInfo, estate);
updatedCols = GetUpdatedColumns(resultRelInfo, estate);
@@ -1818,10 +2056,50 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
- RelationGetRelationName(rel), failed),
+ RelationGetRelationName(orig_rel), failed),
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
- errtableconstraint(rel, failed)));
+ errtableconstraint(orig_rel, failed)));
+ }
+ }
+
+ if (resultRelInfo->ri_PartitionCheck &&
+ !ExecPartitionCheck(resultRelInfo, slot, estate))
+ {
+ char *val_desc;
+ Relation orig_rel = rel;
+
+ /* See the comment above. */
+ if (resultRelInfo->ri_PartitionRoot)
+ {
+ HeapTuple tuple = ExecFetchSlotTuple(slot);
+ TupleDesc old_tupdesc = RelationGetDescr(rel);
+ TupleConversionMap *map;
+
+ rel = resultRelInfo->ri_PartitionRoot;
+ tupdesc = RelationGetDescr(rel);
+ /* a reverse map */
+ map = convert_tuples_by_name(old_tupdesc, tupdesc,
+ gettext_noop("could not convert row type"));
+ if (map != NULL)
+ {
+ tuple = do_convert_tuple(tuple, map);
+ ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ }
}
+
+ insertedCols = GetInsertedColumns(resultRelInfo, estate);
+ updatedCols = GetUpdatedColumns(resultRelInfo, estate);
+ modifiedCols = bms_union(insertedCols, updatedCols);
+ val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
+ slot,
+ tupdesc,
+ modifiedCols,
+ 64);
+ ereport(ERROR,
+ (errcode(ERRCODE_CHECK_VIOLATION),
+ errmsg("new row for relation \"%s\" violates partition constraint",
+ RelationGetRelationName(orig_rel)),
+ val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
}
}
@@ -1872,11 +2150,9 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
* is visible (in the case of a view) or that it passes the
* 'with-check' policy (in the case of row security). If the qual
* evaluates to NULL or FALSE, then the new tuple won't be included in
- * the view or doesn't pass the 'with-check' policy for the table. We
- * need ExecQual to return FALSE for NULL to handle the view case (the
- * opposite of what we do above for CHECK constraints).
+ * the view or doesn't pass the 'with-check' policy for the table.
*/
- if (!ExecQual((List *) wcoExpr, econtext, false))
+ if (!ExecQual(wcoExpr, econtext))
{
char *val_desc;
Bitmapset *modifiedCols;
@@ -2977,14 +3253,7 @@ EvalPlanQualEnd(EPQState *epqstate)
ExecResetTupleTable(estate->es_tupleTable, false);
/* close any trigger target relations attached to this EState */
- foreach(l, estate->es_trig_target_relations)
- {
- ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
-
- /* Close indices and then the relation itself */
- ExecCloseIndices(resultRelInfo);
- heap_close(resultRelInfo->ri_RelationDesc, NoLock);
- }
+ ExecCleanUpTriggerState(estate);
MemoryContextSwitchTo(oldcontext);
@@ -2995,3 +3264,242 @@ EvalPlanQualEnd(EPQState *epqstate)
epqstate->planstate = NULL;
epqstate->origslot = NULL;
}
+
+/*
+ * ExecSetupPartitionTupleRouting - set up information needed during
+ * tuple routing for partitioned tables
+ *
+ * Output arguments:
+ * 'pd' receives an array of PartitionDispatch objects with one entry for
+ * every partitioned table in the partition tree
+ * 'partitions' receives an array of ResultRelInfo objects with one entry for
+ * every leaf partition in the partition tree
+ * 'tup_conv_maps' receives an array of TupleConversionMap objects with one
+ * entry for every leaf partition (required to convert input tuple based
+ * on the root table's rowtype to a leaf partition's rowtype after tuple
+ * routing is done
+ * 'partition_tuple_slot' receives a standalone TupleTableSlot to be used
+ * to manipulate any given leaf partition's rowtype after that partition
+ * is chosen by tuple-routing.
+ * 'num_parted' receives the number of partitioned tables in the partition
+ * tree (= the number of entries in the 'pd' output array)
+ * 'num_partitions' receives the number of leaf partitions in the partition
+ * tree (= the number of entries in the 'partitions' and 'tup_conv_maps'
+ * output arrays
+ *
+ * Note that all the relations in the partition tree are locked using the
+ * RowExclusiveLock mode upon return from this function.
+ */
+void
+ExecSetupPartitionTupleRouting(Relation rel,
+ PartitionDispatch **pd,
+ ResultRelInfo **partitions,
+ TupleConversionMap ***tup_conv_maps,
+ TupleTableSlot **partition_tuple_slot,
+ int *num_parted, int *num_partitions)
+{
+ TupleDesc tupDesc = RelationGetDescr(rel);
+ List *leaf_parts;
+ ListCell *cell;
+ int i;
+ ResultRelInfo *leaf_part_rri;
+
+ /* Get the tuple-routing information and lock partitions */
+ *pd = RelationGetPartitionDispatchInfo(rel, RowExclusiveLock, num_parted,
+ &leaf_parts);
+ *num_partitions = list_length(leaf_parts);
+ *partitions = (ResultRelInfo *) palloc(*num_partitions *
+ sizeof(ResultRelInfo));
+ *tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
+ sizeof(TupleConversionMap *));
+
+ /*
+ * Initialize an empty slot that will be used to manipulate tuples of any
+ * given partition's rowtype. It is attached to the caller-specified node
+ * (such as ModifyTableState) and released when the node finishes
+ * processing.
+ */
+ *partition_tuple_slot = MakeTupleTableSlot();
+
+ leaf_part_rri = *partitions;
+ i = 0;
+ foreach(cell, leaf_parts)
+ {
+ Relation partrel;
+ TupleDesc part_tupdesc;
+
+ /*
+ * We locked all the partitions above including the leaf partitions.
+ * Note that each of the relations in *partitions are eventually
+ * closed by the caller.
+ */
+ partrel = heap_open(lfirst_oid(cell), NoLock);
+ part_tupdesc = RelationGetDescr(partrel);
+
+ /*
+ * Verify result relation is a valid target for the current operation.
+ */
+ CheckValidResultRel(partrel, CMD_INSERT);
+
+ /*
+ * Save a tuple conversion map to convert a tuple routed to this
+ * partition from the parent's type to the partition's.
+ */
+ (*tup_conv_maps)[i] = convert_tuples_by_name(tupDesc, part_tupdesc,
+ gettext_noop("could not convert row type"));
+
+ InitResultRelInfo(leaf_part_rri,
+ partrel,
+ 1, /* dummy */
+ rel,
+ 0);
+
+ /*
+ * Open partition indices (remember we do not support ON CONFLICT in
+ * case of partitioned tables, so we do not need support information
+ * for speculative insertion)
+ */
+ if (leaf_part_rri->ri_RelationDesc->rd_rel->relhasindex &&
+ leaf_part_rri->ri_IndexRelationDescs == NULL)
+ ExecOpenIndices(leaf_part_rri, false);
+
+ leaf_part_rri++;
+ i++;
+ }
+}
+
+/*
+ * ExecFindPartition -- Find a leaf partition in the partition tree rooted
+ * at parent, for the heap tuple contained in *slot
+ *
+ * estate must be non-NULL; we'll need it to compute any expressions in the
+ * partition key(s)
+ *
+ * If no leaf partition is found, this routine errors out with the appropriate
+ * error message, else it returns the leaf partition sequence number returned
+ * by get_partition_for_tuple() unchanged.
+ */
+int
+ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
+ TupleTableSlot *slot, EState *estate)
+{
+ int result;
+ PartitionDispatchData *failed_at;
+ TupleTableSlot *failed_slot;
+
+ result = get_partition_for_tuple(pd, slot, estate,
+ &failed_at, &failed_slot);
+ if (result < 0)
+ {
+ Relation failed_rel;
+ Datum key_values[PARTITION_MAX_KEYS];
+ bool key_isnull[PARTITION_MAX_KEYS];
+ char *val_desc;
+ ExprContext *ecxt = GetPerTupleExprContext(estate);
+
+ failed_rel = failed_at->reldesc;
+ ecxt->ecxt_scantuple = failed_slot;
+ FormPartitionKeyDatum(failed_at, failed_slot, estate,
+ key_values, key_isnull);
+ val_desc = ExecBuildSlotPartitionKeyDescription(failed_rel,
+ key_values,
+ key_isnull,
+ 64);
+ Assert(OidIsValid(RelationGetRelid(failed_rel)));
+ ereport(ERROR,
+ (errcode(ERRCODE_CHECK_VIOLATION),
+ errmsg("no partition of relation \"%s\" found for row",
+ RelationGetRelationName(failed_rel)),
+ val_desc ? errdetail("Partition key of the failing row contains %s.", val_desc) : 0));
+ }
+
+ return result;
+}
+
+/*
+ * BuildSlotPartitionKeyDescription
+ *
+ * This works very much like BuildIndexValueDescription() and is currently
+ * used for building error messages when ExecFindPartition() fails to find
+ * partition for a row.
+ */
+static char *
+ExecBuildSlotPartitionKeyDescription(Relation rel,
+ Datum *values,
+ bool *isnull,
+ int maxfieldlen)
+{
+ StringInfoData buf;
+ PartitionKey key = RelationGetPartitionKey(rel);
+ int partnatts = get_partition_natts(key);
+ int i;
+ Oid relid = RelationGetRelid(rel);
+ AclResult aclresult;
+
+ if (check_enable_rls(relid, InvalidOid, true) == RLS_ENABLED)
+ return NULL;
+
+ /* If the user has table-level access, just go build the description. */
+ aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_SELECT);
+ if (aclresult != ACLCHECK_OK)
+ {
+ /*
+ * Step through the columns of the partition key and make sure the
+ * user has SELECT rights on all of them.
+ */
+ for (i = 0; i < partnatts; i++)
+ {
+ AttrNumber attnum = get_partition_col_attnum(key, i);
+
+ /*
+ * If this partition key column is an expression, we return no
+ * detail rather than try to figure out what column(s) the
+ * expression includes and if the user has SELECT rights on them.
+ */
+ if (attnum == InvalidAttrNumber ||
+ pg_attribute_aclcheck(relid, attnum, GetUserId(),
+ ACL_SELECT) != ACLCHECK_OK)
+ return NULL;
+ }
+ }
+
+ initStringInfo(&buf);
+ appendStringInfo(&buf, "(%s) = (",
+ pg_get_partkeydef_columns(relid, true));
+
+ for (i = 0; i < partnatts; i++)
+ {
+ char *val;
+ int vallen;
+
+ if (isnull[i])
+ val = "null";
+ else
+ {
+ Oid foutoid;
+ bool typisvarlena;
+
+ getTypeOutputInfo(get_partition_col_typid(key, i),
+ &foutoid, &typisvarlena);
+ val = OidOutputFunctionCall(foutoid, values[i]);
+ }
+
+ if (i > 0)
+ appendStringInfoString(&buf, ", ");
+
+ /* truncate if needed */
+ vallen = strlen(val);
+ if (vallen <= maxfieldlen)
+ appendStringInfoString(&buf, val);
+ else
+ {
+ vallen = pg_mbcliplen(val, vallen, maxfieldlen);
+ appendBinaryStringInfo(&buf, val, vallen);
+ appendStringInfoString(&buf, "...");
+ }
+ }
+
+ appendStringInfoChar(&buf, ')');
+
+ return buf.data;
+}
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 380d743f6c..0610180016 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -3,7 +3,7 @@
* execParallel.c
* Support routines for parallel execution.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* This file contains routines that are intended to support setting up,
@@ -25,17 +25,22 @@
#include "executor/execParallel.h"
#include "executor/executor.h"
+#include "executor/nodeBitmapHeapscan.h"
#include "executor/nodeCustom.h"
#include "executor/nodeForeignscan.h"
#include "executor/nodeSeqscan.h"
+#include "executor/nodeIndexscan.h"
+#include "executor/nodeIndexonlyscan.h"
#include "executor/tqueue.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "storage/spin.h"
#include "tcop/tcopprot.h"
+#include "utils/dsa.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
+#include "pgstat.h"
/*
* Magic numbers for parallel executor communication. We use constants
@@ -47,6 +52,8 @@
#define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xE000000000000003)
#define PARALLEL_KEY_TUPLE_QUEUE UINT64CONST(0xE000000000000004)
#define PARALLEL_KEY_INSTRUMENTATION UINT64CONST(0xE000000000000005)
+#define PARALLEL_KEY_DSA UINT64CONST(0xE000000000000006)
+#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xE000000000000007)
#define PARALLEL_TUPLE_QUEUE_SIZE 65536
@@ -105,8 +112,7 @@ static shm_mq_handle **ExecParallelSetupTupleQueues(ParallelContext *pcxt,
static bool ExecParallelRetrieveInstrumentation(PlanState *planstate,
SharedExecutorInstrumentation *instrumentation);
-/* Helper functions that run in the parallel worker. */
-static void ParallelQueryMain(dsm_segment *seg, shm_toc *toc);
+/* Helper function that runs in the parallel worker. */
static DestReceiver *ExecParallelGetReceiver(dsm_segment *seg, shm_toc *toc);
/*
@@ -116,7 +122,7 @@ static char *
ExecSerializePlan(Plan *plan, EState *estate)
{
PlannedStmt *pstmt;
- ListCell *tlist;
+ ListCell *lc;
/* We can't scribble on the original plan, so make a copy. */
plan = copyObject(plan);
@@ -130,9 +136,9 @@ ExecSerializePlan(Plan *plan, EState *estate)
* accordingly. This is sort of a hack; there might be better ways to do
* this...
*/
- foreach(tlist, plan->targetlist)
+ foreach(lc, plan->targetlist)
{
- TargetEntry *tle = (TargetEntry *) lfirst(tlist);
+ TargetEntry *tle = lfirst_node(TargetEntry, lc);
tle->resjunk = false;
}
@@ -154,13 +160,33 @@ ExecSerializePlan(Plan *plan, EState *estate)
pstmt->planTree = plan;
pstmt->rtable = estate->es_range_table;
pstmt->resultRelations = NIL;
- pstmt->utilityStmt = NULL;
+ pstmt->nonleafResultRelations = NIL;
+
+ /*
+ * Transfer only parallel-safe subplans, leaving a NULL "hole" in the list
+ * for unsafe ones (so that the list indexes of the safe ones are
+ * preserved). This positively ensures that the worker won't try to run,
+ * or even do ExecInitNode on, an unsafe subplan. That's important to
+ * protect, eg, non-parallel-aware FDWs from getting into trouble.
+ */
pstmt->subplans = NIL;
+ foreach(lc, estate->es_plannedstmt->subplans)
+ {
+ Plan *subplan = (Plan *) lfirst(lc);
+
+ if (subplan && !subplan->parallel_safe)
+ subplan = NULL;
+ pstmt->subplans = lappend(pstmt->subplans, subplan);
+ }
+
pstmt->rewindPlanIDs = NULL;
pstmt->rowMarks = NIL;
pstmt->relationOids = NIL;
pstmt->invalItems = NIL; /* workers can't replan anyway... */
pstmt->nParamExec = estate->es_plannedstmt->nParamExec;
+ pstmt->utilityStmt = NULL;
+ pstmt->stmt_location = -1;
+ pstmt->stmt_len = -1;
/* Return serialized copy of our dummy PlannedStmt. */
return nodeToString(pstmt);
@@ -193,6 +219,14 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
ExecSeqScanEstimate((SeqScanState *) planstate,
e->pcxt);
break;
+ case T_IndexScanState:
+ ExecIndexScanEstimate((IndexScanState *) planstate,
+ e->pcxt);
+ break;
+ case T_IndexOnlyScanState:
+ ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate,
+ e->pcxt);
+ break;
case T_ForeignScanState:
ExecForeignScanEstimate((ForeignScanState *) planstate,
e->pcxt);
@@ -201,6 +235,10 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
ExecCustomScanEstimate((CustomScanState *) planstate,
e->pcxt);
break;
+ case T_BitmapHeapScanState:
+ ExecBitmapHeapEstimate((BitmapHeapScanState *) planstate,
+ e->pcxt);
+ break;
default:
break;
}
@@ -245,6 +283,14 @@ ExecParallelInitializeDSM(PlanState *planstate,
ExecSeqScanInitializeDSM((SeqScanState *) planstate,
d->pcxt);
break;
+ case T_IndexScanState:
+ ExecIndexScanInitializeDSM((IndexScanState *) planstate,
+ d->pcxt);
+ break;
+ case T_IndexOnlyScanState:
+ ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate,
+ d->pcxt);
+ break;
case T_ForeignScanState:
ExecForeignScanInitializeDSM((ForeignScanState *) planstate,
d->pcxt);
@@ -253,6 +299,11 @@ ExecParallelInitializeDSM(PlanState *planstate,
ExecCustomScanInitializeDSM((CustomScanState *) planstate,
d->pcxt);
break;
+ case T_BitmapHeapScanState:
+ ExecBitmapHeapInitializeDSM((BitmapHeapScanState *) planstate,
+ d->pcxt);
+ break;
+
default:
break;
}
@@ -345,6 +396,9 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
int param_len;
int instrumentation_len = 0;
int instrument_offset = 0;
+ Size dsa_minsize = dsa_minimum_size();
+ char *query_string;
+ int query_len;
/* Allocate object for return value. */
pei = palloc0(sizeof(ParallelExecutorInfo));
@@ -355,7 +409,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
pstmt_data = ExecSerializePlan(planstate->plan, estate);
/* Create a parallel context. */
- pcxt = CreateParallelContext(ParallelQueryMain, nworkers);
+ pcxt = CreateParallelContext("postgres", "ParallelQueryMain", nworkers);
pei->pcxt = pcxt;
/*
@@ -364,6 +418,11 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
* for the various things we need to store.
*/
+ /* Estimate space for query text. */
+ query_len = strlen(estate->es_sourceText);
+ shm_toc_estimate_chunk(&pcxt->estimator, query_len);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+
/* Estimate space for serialized PlannedStmt. */
pstmt_len = strlen(pstmt_data) + 1;
shm_toc_estimate_chunk(&pcxt->estimator, pstmt_len);
@@ -413,6 +472,10 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
shm_toc_estimate_keys(&pcxt->estimator, 1);
}
+ /* Estimate space for DSA area. */
+ shm_toc_estimate_chunk(&pcxt->estimator, dsa_minsize);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+
/* Everyone's had a chance to ask for space, so now create the DSM. */
InitializeParallelDSM(pcxt);
@@ -424,6 +487,11 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
* asked for has been allocated or initialized yet, though, so do that.
*/
+ /* Store query string */
+ query_string = shm_toc_allocate(pcxt->toc, query_len);
+ memcpy(query_string, estate->es_sourceText, query_len);
+ shm_toc_insert(pcxt->toc, PARALLEL_KEY_QUERY_TEXT, query_string);
+
/* Store serialized PlannedStmt. */
pstmt_space = shm_toc_allocate(pcxt->toc, pstmt_len);
memcpy(pstmt_space, pstmt_data, pstmt_len);
@@ -467,6 +535,28 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
}
/*
+ * Create a DSA area that can be used by the leader and all workers.
+ * (However, if we failed to create a DSM and are using private memory
+ * instead, then skip this.)
+ */
+ if (pcxt->seg != NULL)
+ {
+ char *area_space;
+
+ area_space = shm_toc_allocate(pcxt->toc, dsa_minsize);
+ shm_toc_insert(pcxt->toc, PARALLEL_KEY_DSA, area_space);
+ pei->area = dsa_create_in_place(area_space, dsa_minsize,
+ LWTRANCHE_PARALLEL_QUERY_DSA,
+ pcxt->seg);
+ }
+
+ /*
+ * Make the area available to executor nodes running in the leader. See
+ * also ParallelQueryMain which makes it available to workers.
+ */
+ estate->es_query_dsa = pei->area;
+
+ /*
* Give parallel-aware nodes a chance to initialize their shared data.
* This also initializes the elements of instrumentation->ps_instrument,
* if it exists.
@@ -488,7 +578,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
}
/*
- * Copy instrumentation information about this node and its descendents from
+ * Copy instrumentation information about this node and its descendants from
* dynamic shared memory.
*/
static bool
@@ -500,8 +590,9 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
int n;
int ibytes;
int plan_node_id = planstate->plan->plan_node_id;
+ MemoryContext oldcontext;
- /* Find the instumentation for this node. */
+ /* Find the instrumentation for this node. */
for (i = 0; i < instrumentation->num_plan_nodes; ++i)
if (instrumentation->plan_node_id[i] == plan_node_id)
break;
@@ -514,10 +605,19 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
for (n = 0; n < instrumentation->num_workers; ++n)
InstrAggNode(planstate->instrument, &instrument[n]);
- /* Also store the per-worker detail. */
+ /*
+ * Also store the per-worker detail.
+ *
+ * Worker instrumentation should be allocated in the same context as the
+ * regular instrumentation information, which is the per-query context.
+ * Switch into per-query memory context.
+ */
+ oldcontext = MemoryContextSwitchTo(planstate->state->es_query_cxt);
ibytes = mul_size(instrumentation->num_workers, sizeof(Instrumentation));
planstate->worker_instrument =
palloc(ibytes + offsetof(WorkerInstrumentation, instrument));
+ MemoryContextSwitchTo(oldcontext);
+
planstate->worker_instrument->num_workers = instrumentation->num_workers;
memcpy(&planstate->worker_instrument->instrument, instrument, ibytes);
@@ -553,7 +653,7 @@ ExecParallelFinish(ParallelExecutorInfo *pei)
}
/*
- * Clean up whatever ParallelExecutreInfo resources still exist after
+ * Clean up whatever ParallelExecutorInfo resources still exist after
* ExecParallelFinish. We separate these routines because someone might
* want to examine the contents of the DSM after ExecParallelFinish and
* before calling this routine.
@@ -561,6 +661,11 @@ ExecParallelFinish(ParallelExecutorInfo *pei)
void
ExecParallelCleanup(ParallelExecutorInfo *pei)
{
+ if (pei->area != NULL)
+ {
+ dsa_detach(pei->area);
+ pei->area = NULL;
+ }
if (pei->pcxt != NULL)
{
DestroyParallelContext(pei->pcxt);
@@ -597,6 +702,10 @@ ExecParallelGetQueryDesc(shm_toc *toc, DestReceiver *receiver,
char *paramspace;
PlannedStmt *pstmt;
ParamListInfo paramLI;
+ char *queryString;
+
+ /* Get the query string from shared memory */
+ queryString = shm_toc_lookup(toc, PARALLEL_KEY_QUERY_TEXT);
/* Reconstruct leader-supplied PlannedStmt. */
pstmtspace = shm_toc_lookup(toc, PARALLEL_KEY_PLANNEDSTMT);
@@ -615,13 +724,13 @@ ExecParallelGetQueryDesc(shm_toc *toc, DestReceiver *receiver,
* revising this someday.
*/
return CreateQueryDesc(pstmt,
- "<parallel query>",
+ queryString,
GetActiveSnapshot(), InvalidSnapshot,
- receiver, paramLI, instrument_options);
+ receiver, paramLI, NULL, instrument_options);
}
/*
- * Copy instrumentation information from this node and its descendents into
+ * Copy instrumentation information from this node and its descendants into
* dynamic shared memory, so that the parallel leader can retrieve it.
*/
static bool
@@ -661,7 +770,7 @@ ExecParallelReportInstrumentation(PlanState *planstate,
}
/*
- * Initialize the PlanState and its descendents with the information
+ * Initialize the PlanState and its descendants with the information
* retrieved from shared memory. This has to be done once the PlanState
* is allocated and initialized by executor; that is, after ExecutorStart().
*/
@@ -679,6 +788,12 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_toc *toc)
case T_SeqScanState:
ExecSeqScanInitializeWorker((SeqScanState *) planstate, toc);
break;
+ case T_IndexScanState:
+ ExecIndexScanInitializeWorker((IndexScanState *) planstate, toc);
+ break;
+ case T_IndexOnlyScanState:
+ ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate, toc);
+ break;
case T_ForeignScanState:
ExecForeignScanInitializeWorker((ForeignScanState *) planstate,
toc);
@@ -687,6 +802,10 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_toc *toc)
ExecCustomScanInitializeWorker((CustomScanState *) planstate,
toc);
break;
+ case T_BitmapHeapScanState:
+ ExecBitmapHeapInitializeWorker(
+ (BitmapHeapScanState *) planstate, toc);
+ break;
default:
break;
}
@@ -698,10 +817,11 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_toc *toc)
/*
* Main entrypoint for parallel query worker processes.
*
- * We reach this function from ParallelMain, so the setup necessary to create
- * a sensible parallel environment has already been done; ParallelMain worries
- * about stuff like the transaction state, combo CID mappings, and GUC values,
- * so we don't need to deal with any of that here.
+ * We reach this function from ParallelWorkerMain, so the setup necessary to
+ * create a sensible parallel environment has already been done;
+ * ParallelWorkerMain worries about stuff like the transaction state, combo
+ * CID mappings, and GUC values, so we don't need to deal with any of that
+ * here.
*
* Our job is to deal with concerns specific to the executor. The parallel
* group leader will have stored a serialized PlannedStmt, and it's our job
@@ -710,7 +830,7 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_toc *toc)
* to do this are also stored in the dsm_segment and can be accessed through
* the shm_toc.
*/
-static void
+void
ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
{
BufferUsage *buffer_usage;
@@ -718,6 +838,8 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
QueryDesc *queryDesc;
SharedExecutorInstrumentation *instrumentation;
int instrument_options = 0;
+ void *area_space;
+ dsa_area *area;
/* Set up DestReceiver, SharedExecutorInstrumentation, and QueryDesc. */
receiver = ExecParallelGetReceiver(seg, toc);
@@ -726,13 +848,30 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
instrument_options = instrumentation->instrument_options;
queryDesc = ExecParallelGetQueryDesc(toc, receiver, instrument_options);
+ /* Setting debug_query_string for individual workers */
+ debug_query_string = queryDesc->sourceText;
+
+ /* Report workers' query for monitoring purposes */
+ pgstat_report_activity(STATE_RUNNING, debug_query_string);
+
/* Prepare to track buffer usage during query execution. */
InstrStartParallelQuery();
- /* Start up the executor, have it run the plan, and then shut it down. */
+ /* Attach to the dynamic shared memory area. */
+ area_space = shm_toc_lookup(toc, PARALLEL_KEY_DSA);
+ area = dsa_attach_in_place(area_space, seg);
+
+ /* Start up the executor */
ExecutorStart(queryDesc, 0);
+
+ /* Special executor initialization steps for parallel workers */
+ queryDesc->planstate->state->es_query_dsa = area;
ExecParallelInitializeWorker(queryDesc->planstate, toc);
- ExecutorRun(queryDesc, ForwardScanDirection, 0L);
+
+ /* Run the plan */
+ ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
+
+ /* Shut down the executor */
ExecutorFinish(queryDesc);
/* Report buffer usage during parallel execution. */
@@ -748,6 +887,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
ExecutorEnd(queryDesc);
/* Cleanup. */
+ dsa_detach(area);
FreeQueryDesc(queryDesc);
(*receiver->rDestroy) (receiver);
}
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index fa7bdfc923..f2d9ccb130 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -8,7 +8,7 @@
* processing.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -89,6 +89,8 @@
#include "executor/nodeCustom.h"
#include "executor/nodeForeignscan.h"
#include "executor/nodeFunctionscan.h"
+#include "executor/nodeGather.h"
+#include "executor/nodeGatherMerge.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
@@ -100,8 +102,9 @@
#include "executor/nodeMergeAppend.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeModifyTable.h"
+#include "executor/nodeNamedtuplestorescan.h"
#include "executor/nodeNestloop.h"
-#include "executor/nodeGather.h"
+#include "executor/nodeProjectSet.h"
#include "executor/nodeRecursiveunion.h"
#include "executor/nodeResult.h"
#include "executor/nodeSamplescan.h"
@@ -110,6 +113,7 @@
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h"
+#include "executor/nodeTableFuncscan.h"
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
#include "executor/nodeValuesscan.h"
@@ -158,6 +162,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
estate, eflags);
break;
+ case T_ProjectSet:
+ result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
+ estate, eflags);
+ break;
+
case T_ModifyTable:
result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
estate, eflags);
@@ -236,6 +245,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
estate, eflags);
break;
+ case T_TableFuncScan:
+ result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
+ estate, eflags);
+ break;
+
case T_ValuesScan:
result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
estate, eflags);
@@ -246,6 +260,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
estate, eflags);
break;
+ case T_NamedTuplestoreScan:
+ result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
+ estate, eflags);
+ break;
+
case T_WorkTableScan:
result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
estate, eflags);
@@ -317,6 +336,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
estate, eflags);
break;
+ case T_GatherMerge:
+ result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
+ estate, eflags);
+ break;
+
case T_Hash:
result = (PlanState *) ExecInitHash((Hash *) node,
estate, eflags);
@@ -492,6 +516,10 @@ ExecProcNode(PlanState *node)
result = ExecResult((ResultState *) node);
break;
+ case T_ProjectSetState:
+ result = ExecProjectSet((ProjectSetState *) node);
+ break;
+
case T_ModifyTableState:
result = ExecModifyTable((ModifyTableState *) node);
break;
@@ -549,6 +577,10 @@ ExecProcNode(PlanState *node)
result = ExecFunctionScan((FunctionScanState *) node);
break;
+ case T_TableFuncScanState:
+ result = ExecTableFuncScan((TableFuncScanState *) node);
+ break;
+
case T_ValuesScanState:
result = ExecValuesScan((ValuesScanState *) node);
break;
@@ -557,6 +589,10 @@ ExecProcNode(PlanState *node)
result = ExecCteScan((CteScanState *) node);
break;
+ case T_NamedTuplestoreScanState:
+ result = ExecNamedTuplestoreScan((NamedTuplestoreScanState *) node);
+ break;
+
case T_WorkTableScanState:
result = ExecWorkTableScan((WorkTableScanState *) node);
break;
@@ -615,6 +651,10 @@ ExecProcNode(PlanState *node)
result = ExecGather((GatherState *) node);
break;
+ case T_GatherMergeState:
+ result = ExecGatherMerge((GatherMergeState *) node);
+ break;
+
case T_HashState:
result = ExecHash((HashState *) node);
break;
@@ -745,6 +785,10 @@ ExecEndNode(PlanState *node)
ExecEndResult((ResultState *) node);
break;
+ case T_ProjectSetState:
+ ExecEndProjectSet((ProjectSetState *) node);
+ break;
+
case T_ModifyTableState:
ExecEndModifyTable((ModifyTableState *) node);
break;
@@ -784,6 +828,10 @@ ExecEndNode(PlanState *node)
ExecEndGather((GatherState *) node);
break;
+ case T_GatherMergeState:
+ ExecEndGatherMerge((GatherMergeState *) node);
+ break;
+
case T_IndexScanState:
ExecEndIndexScan((IndexScanState *) node);
break;
@@ -812,6 +860,10 @@ ExecEndNode(PlanState *node)
ExecEndFunctionScan((FunctionScanState *) node);
break;
+ case T_TableFuncScanState:
+ ExecEndTableFuncScan((TableFuncScanState *) node);
+ break;
+
case T_ValuesScanState:
ExecEndValuesScan((ValuesScanState *) node);
break;
@@ -820,6 +872,10 @@ ExecEndNode(PlanState *node)
ExecEndCteScan((CteScanState *) node);
break;
+ case T_NamedTuplestoreScanState:
+ ExecEndNamedTuplestoreScan((NamedTuplestoreScanState *) node);
+ break;
+
case T_WorkTableScanState:
ExecEndWorkTableScan((WorkTableScanState *) node);
break;
@@ -923,14 +979,25 @@ ExecShutdownNode(PlanState *node)
if (node == NULL)
return false;
+ planstate_tree_walker(node, ExecShutdownNode, NULL);
+
switch (nodeTag(node))
{
case T_GatherState:
ExecShutdownGather((GatherState *) node);
break;
+ case T_ForeignScanState:
+ ExecShutdownForeignScan((ForeignScanState *) node);
+ break;
+ case T_CustomScanState:
+ ExecShutdownCustomScan((CustomScanState *) node);
+ break;
+ case T_GatherMergeState:
+ ExecShutdownGatherMerge((GatherMergeState *) node);
+ break;
default:
break;
}
- return planstate_tree_walker(node, ExecShutdownNode, NULL);
+ return false;
}
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
deleted file mode 100644
index 98b85af92f..0000000000
--- a/src/backend/executor/execQual.c
+++ /dev/null
@@ -1,5656 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * execQual.c
- * Routines to evaluate qualification and targetlist expressions
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/backend/executor/execQual.c
- *
- *-------------------------------------------------------------------------
- */
-/*
- * INTERFACE ROUTINES
- * ExecEvalExpr - (now a macro) evaluate an expression, return a datum
- * ExecEvalExprSwitchContext - same, but switch into eval memory context
- * ExecQual - return true/false if qualification is satisfied
- * ExecProject - form a new tuple by projecting the given tuple
- *
- * NOTES
- * The more heavily used ExecEvalExpr routines, such as ExecEvalScalarVar,
- * are hotspots. Making these faster will speed up the entire system.
- *
- * ExecProject() is used to make tuple projections. Rather then
- * trying to speed it up, the execution plan should be pre-processed
- * to facilitate attribute sharing between nodes wherever possible,
- * instead of doing needless copying. -cim 5/31/91
- *
- * During expression evaluation, we check_stack_depth only in
- * ExecMakeFunctionResult (and substitute routines) rather than at every
- * single node. This is a compromise that trades off precision of the
- * stack limit setting to gain speed.
- */
-
-#include "postgres.h"
-
-#include "access/htup_details.h"
-#include "access/nbtree.h"
-#include "access/tupconvert.h"
-#include "catalog/objectaccess.h"
-#include "catalog/pg_type.h"
-#include "executor/execdebug.h"
-#include "executor/nodeSubplan.h"
-#include "funcapi.h"
-#include "miscadmin.h"
-#include "nodes/makefuncs.h"
-#include "nodes/nodeFuncs.h"
-#include "optimizer/planner.h"
-#include "parser/parse_coerce.h"
-#include "parser/parsetree.h"
-#include "pgstat.h"
-#include "utils/acl.h"
-#include "utils/builtins.h"
-#include "utils/lsyscache.h"
-#include "utils/memutils.h"
-#include "utils/typcache.h"
-#include "utils/xml.h"
-
-
-/* static function decls */
-static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static bool isAssignmentIndirectionExpr(ExprState *exprstate);
-static Datum ExecEvalAggref(AggrefExprState *aggref,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalWindowFunc(WindowFuncExprState *wfunc,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalScalarVarFast(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static void init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
- MemoryContext fcacheCxt, bool needDescForSets);
-static void ShutdownFuncExpr(Datum arg);
-static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
- TupleDesc *cache_field, ExprContext *econtext);
-static void ShutdownTupleDescRef(Datum arg);
-static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
- List *argList, ExprContext *econtext);
-static void ExecPrepareTuplestoreResult(FuncExprState *fcache,
- ExprContext *econtext,
- Tuplestorestate *resultStore,
- TupleDesc resultDesc);
-static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc);
-static Datum ExecMakeFunctionResult(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone);
-static Datum ExecMakeFunctionResultNoSets(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalArray(ArrayExprState *astate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalRow(RowExprState *rstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalRowCompare(RowCompareExprState *rstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalNullTest(NullTestState *nstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalBooleanTest(GenericExprState *bstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCoerceToDomain(CoerceToDomainState *cstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCoerceToDomainValue(ExprState *exprstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalFieldSelect(FieldSelectState *fstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalFieldStore(FieldStoreState *fstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalRelabelType(GenericExprState *exprstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-
-
-/* ----------------------------------------------------------------
- * ExecEvalExpr routines
- *
- * Recursively evaluate a targetlist or qualification expression.
- *
- * Each of the following routines having the signature
- * Datum ExecEvalFoo(ExprState *expression,
- * ExprContext *econtext,
- * bool *isNull,
- * ExprDoneCond *isDone);
- * is responsible for evaluating one type or subtype of ExprState node.
- * They are normally called via the ExecEvalExpr macro, which makes use of
- * the function pointer set up when the ExprState node was built by
- * ExecInitExpr. (In some cases, we change this pointer later to avoid
- * re-executing one-time overhead.)
- *
- * Note: for notational simplicity we declare these functions as taking the
- * specific type of ExprState that they work on. This requires casting when
- * assigning the function pointer in ExecInitExpr. Be careful that the
- * function signature is declared correctly, because the cast suppresses
- * automatic checking!
- *
- *
- * All these functions share this calling convention:
- *
- * Inputs:
- * expression: the expression state tree to evaluate
- * econtext: evaluation context information
- *
- * Outputs:
- * return value: Datum value of result
- * *isNull: set to TRUE if result is NULL (actual return value is
- * meaningless if so); set to FALSE if non-null result
- * *isDone: set to indicator of set-result status
- *
- * A caller that can only accept a singleton (non-set) result should pass
- * NULL for isDone; if the expression computes a set result then an error
- * will be reported via ereport. If the caller does pass an isDone pointer
- * then *isDone is set to one of these three states:
- * ExprSingleResult singleton result (not a set)
- * ExprMultipleResult return value is one element of a set
- * ExprEndResult there are no more elements in the set
- * When ExprMultipleResult is returned, the caller should invoke
- * ExecEvalExpr() repeatedly until ExprEndResult is returned. ExprEndResult
- * is returned after the last real set element. For convenience isNull will
- * always be set TRUE when ExprEndResult is returned, but this should not be
- * taken as indicating a NULL element of the set. Note that these return
- * conventions allow us to distinguish among a singleton NULL, a NULL element
- * of a set, and an empty set.
- *
- * The caller should already have switched into the temporary memory
- * context econtext->ecxt_per_tuple_memory. The convenience entry point
- * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
- * do the switch in an outer loop. We do not do the switch in these routines
- * because it'd be a waste of cycles during nested expression evaluation.
- * ----------------------------------------------------------------
- */
-
-
-/*----------
- * ExecEvalArrayRef
- *
- * This function takes an ArrayRef and returns the extracted Datum
- * if it's a simple reference, or the modified array value if it's
- * an array assignment (i.e., array element or slice insertion).
- *
- * NOTE: if we get a NULL result from a subscript expression, we return NULL
- * when it's an array reference, or raise an error when it's an assignment.
- *----------
- */
-static Datum
-ExecEvalArrayRef(ArrayRefExprState *astate,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- ArrayRef *arrayRef = (ArrayRef *) astate->xprstate.expr;
- Datum array_source;
- bool isAssignment = (arrayRef->refassgnexpr != NULL);
- bool eisnull;
- ListCell *l;
- int i = 0,
- j = 0;
- IntArray upper,
- lower;
- bool upperProvided[MAXDIM],
- lowerProvided[MAXDIM];
- int *lIndex;
-
- array_source = ExecEvalExpr(astate->refexpr,
- econtext,
- isNull,
- isDone);
-
- /*
- * If refexpr yields NULL, and it's a fetch, then result is NULL. In the
- * assignment case, we'll cons up something below.
- */
- if (*isNull)
- {
- if (isDone && *isDone == ExprEndResult)
- return (Datum) NULL; /* end of set result */
- if (!isAssignment)
- return (Datum) NULL;
- }
-
- foreach(l, astate->refupperindexpr)
- {
- ExprState *eltstate = (ExprState *) lfirst(l);
-
- if (i >= MAXDIM)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
- i + 1, MAXDIM)));
-
- if (eltstate == NULL)
- {
- /* Slice bound is omitted, so use array's upper bound */
- Assert(astate->reflowerindexpr != NIL);
- upperProvided[i++] = false;
- continue;
- }
- upperProvided[i] = true;
-
- upper.indx[i++] = DatumGetInt32(ExecEvalExpr(eltstate,
- econtext,
- &eisnull,
- NULL));
- /* If any index expr yields NULL, result is NULL or error */
- if (eisnull)
- {
- if (isAssignment)
- ereport(ERROR,
- (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
- errmsg("array subscript in assignment must not be null")));
- *isNull = true;
- return (Datum) NULL;
- }
- }
-
- if (astate->reflowerindexpr != NIL)
- {
- foreach(l, astate->reflowerindexpr)
- {
- ExprState *eltstate = (ExprState *) lfirst(l);
-
- if (j >= MAXDIM)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
- j + 1, MAXDIM)));
-
- if (eltstate == NULL)
- {
- /* Slice bound is omitted, so use array's lower bound */
- lowerProvided[j++] = false;
- continue;
- }
- lowerProvided[j] = true;
-
- lower.indx[j++] = DatumGetInt32(ExecEvalExpr(eltstate,
- econtext,
- &eisnull,
- NULL));
- /* If any index expr yields NULL, result is NULL or error */
- if (eisnull)
- {
- if (isAssignment)
- ereport(ERROR,
- (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
- errmsg("array subscript in assignment must not be null")));
- *isNull = true;
- return (Datum) NULL;
- }
- }
- /* this can't happen unless parser messed up */
- if (i != j)
- elog(ERROR, "upper and lower index lists are not same length");
- lIndex = lower.indx;
- }
- else
- lIndex = NULL;
-
- if (isAssignment)
- {
- Datum sourceData;
- Datum save_datum;
- bool save_isNull;
-
- /*
- * We might have a nested-assignment situation, in which the
- * refassgnexpr is itself a FieldStore or ArrayRef that needs to
- * obtain and modify the previous value of the array element or slice
- * being replaced. If so, we have to extract that value from the
- * array and pass it down via the econtext's caseValue. It's safe to
- * reuse the CASE mechanism because there cannot be a CASE between
- * here and where the value would be needed, and an array assignment
- * can't be within a CASE either. (So saving and restoring the
- * caseValue is just paranoia, but let's do it anyway.)
- *
- * Since fetching the old element might be a nontrivial expense, do it
- * only if the argument appears to actually need it.
- */
- save_datum = econtext->caseValue_datum;
- save_isNull = econtext->caseValue_isNull;
-
- if (isAssignmentIndirectionExpr(astate->refassgnexpr))
- {
- if (*isNull)
- {
- /* whole array is null, so any element or slice is too */
- econtext->caseValue_datum = (Datum) 0;
- econtext->caseValue_isNull = true;
- }
- else if (lIndex == NULL)
- {
- econtext->caseValue_datum =
- array_get_element(array_source, i,
- upper.indx,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign,
- &econtext->caseValue_isNull);
- }
- else
- {
- econtext->caseValue_datum =
- array_get_slice(array_source, i,
- upper.indx, lower.indx,
- upperProvided, lowerProvided,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
- econtext->caseValue_isNull = false;
- }
- }
- else
- {
- /* argument shouldn't need caseValue, but for safety set it null */
- econtext->caseValue_datum = (Datum) 0;
- econtext->caseValue_isNull = true;
- }
-
- /*
- * Evaluate the value to be assigned into the array.
- */
- sourceData = ExecEvalExpr(astate->refassgnexpr,
- econtext,
- &eisnull,
- NULL);
-
- econtext->caseValue_datum = save_datum;
- econtext->caseValue_isNull = save_isNull;
-
- /*
- * For an assignment to a fixed-length array type, both the original
- * array and the value to be assigned into it must be non-NULL, else
- * we punt and return the original array.
- */
- if (astate->refattrlength > 0) /* fixed-length array? */
- if (eisnull || *isNull)
- return array_source;
-
- /*
- * For assignment to varlena arrays, we handle a NULL original array
- * by substituting an empty (zero-dimensional) array; insertion of the
- * new element will result in a singleton array value. It does not
- * matter whether the new element is NULL.
- */
- if (*isNull)
- {
- array_source = PointerGetDatum(construct_empty_array(arrayRef->refelemtype));
- *isNull = false;
- }
-
- if (lIndex == NULL)
- return array_set_element(array_source, i,
- upper.indx,
- sourceData,
- eisnull,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
- else
- return array_set_slice(array_source, i,
- upper.indx, lower.indx,
- upperProvided, lowerProvided,
- sourceData,
- eisnull,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
- }
-
- if (lIndex == NULL)
- return array_get_element(array_source, i,
- upper.indx,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign,
- isNull);
- else
- return array_get_slice(array_source, i,
- upper.indx, lower.indx,
- upperProvided, lowerProvided,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
-}
-
-/*
- * Helper for ExecEvalArrayRef: is expr a nested FieldStore or ArrayRef
- * that might need the old element value passed down?
- *
- * (We could use this in ExecEvalFieldStore too, but in that case passing
- * the old value is so cheap there's no need.)
- */
-static bool
-isAssignmentIndirectionExpr(ExprState *exprstate)
-{
- if (exprstate == NULL)
- return false; /* just paranoia */
- if (IsA(exprstate, FieldStoreState))
- {
- FieldStore *fstore = (FieldStore *) exprstate->expr;
-
- if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
- return true;
- }
- else if (IsA(exprstate, ArrayRefExprState))
- {
- ArrayRef *arrayRef = (ArrayRef *) exprstate->expr;
-
- if (arrayRef->refexpr && IsA(arrayRef->refexpr, CaseTestExpr))
- return true;
- }
- return false;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalAggref
- *
- * Returns a Datum whose value is the value of the precomputed
- * aggregate found in the given expression context.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- if (isDone)
- *isDone = ExprSingleResult;
-
- if (econtext->ecxt_aggvalues == NULL) /* safety check */
- elog(ERROR, "no aggregates in this expression context");
-
- *isNull = econtext->ecxt_aggnulls[aggref->aggno];
- return econtext->ecxt_aggvalues[aggref->aggno];
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalWindowFunc
- *
- * Returns a Datum whose value is the value of the precomputed
- * window function found in the given expression context.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalWindowFunc(WindowFuncExprState *wfunc, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- if (isDone)
- *isDone = ExprSingleResult;
-
- if (econtext->ecxt_aggvalues == NULL) /* safety check */
- elog(ERROR, "no window functions in this expression context");
-
- *isNull = econtext->ecxt_aggnulls[wfunc->wfuncno];
- return econtext->ecxt_aggvalues[wfunc->wfuncno];
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalScalarVar
- *
- * Returns a Datum whose value is the value of a scalar (not whole-row)
- * range variable with respect to given expression context.
- *
- * Note: ExecEvalScalarVar is executed only the first time through in a given
- * plan; it changes the ExprState's function pointer to pass control directly
- * to ExecEvalScalarVarFast after making one-time checks.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Var *variable = (Var *) exprstate->expr;
- TupleTableSlot *slot;
- AttrNumber attnum;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /* Get the input slot and attribute number we want */
- switch (variable->varno)
- {
- case INNER_VAR: /* get the tuple from the inner node */
- slot = econtext->ecxt_innertuple;
- break;
-
- case OUTER_VAR: /* get the tuple from the outer node */
- slot = econtext->ecxt_outertuple;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default: /* get the tuple from the relation being
- * scanned */
- slot = econtext->ecxt_scantuple;
- break;
- }
-
- attnum = variable->varattno;
-
- /* This was checked by ExecInitExpr */
- Assert(attnum != InvalidAttrNumber);
-
- /*
- * If it's a user attribute, check validity (bogus system attnums will be
- * caught inside slot_getattr). What we have to check for here is the
- * possibility of an attribute having been changed in type since the plan
- * tree was created. Ideally the plan will get invalidated and not
- * re-used, but just in case, we keep these defenses. Fortunately it's
- * sufficient to check once on the first time through.
- *
- * Note: we allow a reference to a dropped attribute. slot_getattr will
- * force a NULL result in such cases.
- *
- * Note: ideally we'd check typmod as well as typid, but that seems
- * impractical at the moment: in many cases the tupdesc will have been
- * generated by ExecTypeFromTL(), and that can't guarantee to generate an
- * accurate typmod in all cases, because some expression node types don't
- * carry typmod.
- */
- if (attnum > 0)
- {
- TupleDesc slot_tupdesc = slot->tts_tupleDescriptor;
- Form_pg_attribute attr;
-
- if (attnum > slot_tupdesc->natts) /* should never happen */
- elog(ERROR, "attribute number %d exceeds number of columns %d",
- attnum, slot_tupdesc->natts);
-
- attr = slot_tupdesc->attrs[attnum - 1];
-
- /* can't check type if dropped, since atttypid is probably 0 */
- if (!attr->attisdropped)
- {
- if (variable->vartype != attr->atttypid)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("attribute %d has wrong type", attnum),
- errdetail("Table has type %s, but query expects %s.",
- format_type_be(attr->atttypid),
- format_type_be(variable->vartype))));
- }
- }
-
- /* Skip the checking on future executions of node */
- exprstate->evalfunc = ExecEvalScalarVarFast;
-
- /* Fetch the value from the slot */
- return slot_getattr(slot, attnum, isNull);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalScalarVarFast
- *
- * Returns a Datum for a scalar variable.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalScalarVarFast(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Var *variable = (Var *) exprstate->expr;
- TupleTableSlot *slot;
- AttrNumber attnum;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /* Get the input slot and attribute number we want */
- switch (variable->varno)
- {
- case INNER_VAR: /* get the tuple from the inner node */
- slot = econtext->ecxt_innertuple;
- break;
-
- case OUTER_VAR: /* get the tuple from the outer node */
- slot = econtext->ecxt_outertuple;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default: /* get the tuple from the relation being
- * scanned */
- slot = econtext->ecxt_scantuple;
- break;
- }
-
- attnum = variable->varattno;
-
- /* Fetch the value from the slot */
- return slot_getattr(slot, attnum, isNull);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalWholeRowVar
- *
- * Returns a Datum whose value is the value of a whole-row range
- * variable with respect to given expression context.
- *
- * Note: ExecEvalWholeRowVar is executed only the first time through in a
- * given plan; it changes the ExprState's function pointer to pass control
- * directly to ExecEvalWholeRowFast or ExecEvalWholeRowSlow after making
- * one-time checks.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Var *variable = (Var *) wrvstate->xprstate.expr;
- TupleTableSlot *slot;
- TupleDesc output_tupdesc;
- MemoryContext oldcontext;
- bool needslow = false;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /* This was checked by ExecInitExpr */
- Assert(variable->varattno == InvalidAttrNumber);
-
- /* Get the input slot we want */
- switch (variable->varno)
- {
- case INNER_VAR: /* get the tuple from the inner node */
- slot = econtext->ecxt_innertuple;
- break;
-
- case OUTER_VAR: /* get the tuple from the outer node */
- slot = econtext->ecxt_outertuple;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default: /* get the tuple from the relation being
- * scanned */
- slot = econtext->ecxt_scantuple;
- break;
- }
-
- /*
- * If the input tuple came from a subquery, it might contain "resjunk"
- * columns (such as GROUP BY or ORDER BY columns), which we don't want to
- * keep in the whole-row result. We can get rid of such columns by
- * passing the tuple through a JunkFilter --- but to make one, we have to
- * lay our hands on the subquery's targetlist. Fortunately, there are not
- * very many cases where this can happen, and we can identify all of them
- * by examining our parent PlanState. We assume this is not an issue in
- * standalone expressions that don't have parent plans. (Whole-row Vars
- * can occur in such expressions, but they will always be referencing
- * table rows.)
- */
- if (wrvstate->parent)
- {
- PlanState *subplan = NULL;
-
- switch (nodeTag(wrvstate->parent))
- {
- case T_SubqueryScanState:
- subplan = ((SubqueryScanState *) wrvstate->parent)->subplan;
- break;
- case T_CteScanState:
- subplan = ((CteScanState *) wrvstate->parent)->cteplanstate;
- break;
- default:
- break;
- }
-
- if (subplan)
- {
- bool junk_filter_needed = false;
- ListCell *tlist;
-
- /* Detect whether subplan tlist actually has any junk columns */
- foreach(tlist, subplan->plan->targetlist)
- {
- TargetEntry *tle = (TargetEntry *) lfirst(tlist);
-
- if (tle->resjunk)
- {
- junk_filter_needed = true;
- break;
- }
- }
-
- /* If so, build the junkfilter in the query memory context */
- if (junk_filter_needed)
- {
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- wrvstate->wrv_junkFilter =
- ExecInitJunkFilter(subplan->plan->targetlist,
- ExecGetResultType(subplan)->tdhasoid,
- ExecInitExtraTupleSlot(wrvstate->parent->state));
- MemoryContextSwitchTo(oldcontext);
- }
- }
- }
-
- /* Apply the junkfilter if any */
- if (wrvstate->wrv_junkFilter != NULL)
- slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
-
- /*
- * If the Var identifies a named composite type, we must check that the
- * actual tuple type is compatible with it.
- */
- if (variable->vartype != RECORDOID)
- {
- TupleDesc var_tupdesc;
- TupleDesc slot_tupdesc;
- int i;
-
- /*
- * We really only care about numbers of attributes and data types.
- * Also, we can ignore type mismatch on columns that are dropped in
- * the destination type, so long as (1) the physical storage matches
- * or (2) the actual column value is NULL. Case (1) is helpful in
- * some cases involving out-of-date cached plans, while case (2) is
- * expected behavior in situations such as an INSERT into a table with
- * dropped columns (the planner typically generates an INT4 NULL
- * regardless of the dropped column type). If we find a dropped
- * column and cannot verify that case (1) holds, we have to use
- * ExecEvalWholeRowSlow to check (2) for each row.
- */
- var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1);
-
- slot_tupdesc = slot->tts_tupleDescriptor;
-
- if (var_tupdesc->natts != slot_tupdesc->natts)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("table row type and query-specified row type do not match"),
- errdetail_plural("Table row contains %d attribute, but query expects %d.",
- "Table row contains %d attributes, but query expects %d.",
- slot_tupdesc->natts,
- slot_tupdesc->natts,
- var_tupdesc->natts)));
-
- for (i = 0; i < var_tupdesc->natts; i++)
- {
- Form_pg_attribute vattr = var_tupdesc->attrs[i];
- Form_pg_attribute sattr = slot_tupdesc->attrs[i];
-
- if (vattr->atttypid == sattr->atttypid)
- continue; /* no worries */
- if (!vattr->attisdropped)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("table row type and query-specified row type do not match"),
- errdetail("Table has type %s at ordinal position %d, but query expects %s.",
- format_type_be(sattr->atttypid),
- i + 1,
- format_type_be(vattr->atttypid))));
-
- if (vattr->attlen != sattr->attlen ||
- vattr->attalign != sattr->attalign)
- needslow = true; /* need runtime check for null */
- }
-
- /*
- * Use the variable's declared rowtype as the descriptor for the
- * output values, modulo possibly assigning new column names below. In
- * particular, we *must* absorb any attisdropped markings.
- */
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- output_tupdesc = CreateTupleDescCopy(var_tupdesc);
- MemoryContextSwitchTo(oldcontext);
-
- ReleaseTupleDesc(var_tupdesc);
- }
- else
- {
- /*
- * In the RECORD case, we use the input slot's rowtype as the
- * descriptor for the output values, modulo possibly assigning new
- * column names below.
- */
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
- MemoryContextSwitchTo(oldcontext);
- }
-
- /*
- * Construct a tuple descriptor for the composite values we'll produce,
- * and make sure its record type is "blessed". The main reason to do this
- * is to be sure that operations such as row_to_json() will see the
- * desired column names when they look up the descriptor from the type
- * information embedded in the composite values.
- *
- * We already got the correct physical datatype info above, but now we
- * should try to find the source RTE and adopt its column aliases, in case
- * they are different from the original rowtype's names. For example, in
- * "SELECT foo(t) FROM tab t(x,y)", the first two columns in the composite
- * output should be named "x" and "y" regardless of tab's column names.
- *
- * If we can't locate the RTE, assume the column names we've got are OK.
- * (As of this writing, the only cases where we can't locate the RTE are
- * in execution of trigger WHEN clauses, and then the Var will have the
- * trigger's relation's rowtype, so its names are fine.) Also, if the
- * creator of the RTE didn't bother to fill in an eref field, assume our
- * column names are OK. (This happens in COPY, and perhaps other places.)
- */
- if (econtext->ecxt_estate &&
- variable->varno <= list_length(econtext->ecxt_estate->es_range_table))
- {
- RangeTblEntry *rte = rt_fetch(variable->varno,
- econtext->ecxt_estate->es_range_table);
-
- if (rte->eref)
- ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
- }
-
- /* Bless the tupdesc if needed, and save it in the execution state */
- wrvstate->wrv_tupdesc = BlessTupleDesc(output_tupdesc);
-
- /* Skip all the above on future executions of node */
- if (needslow)
- wrvstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalWholeRowSlow;
- else
- wrvstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalWholeRowFast;
-
- /* Fetch the value */
- return (*wrvstate->xprstate.evalfunc) ((ExprState *) wrvstate, econtext,
- isNull, isDone);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalWholeRowFast
- *
- * Returns a Datum for a whole-row variable.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Var *variable = (Var *) wrvstate->xprstate.expr;
- TupleTableSlot *slot;
- HeapTupleHeader dtuple;
-
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = false;
-
- /* Get the input slot we want */
- switch (variable->varno)
- {
- case INNER_VAR: /* get the tuple from the inner node */
- slot = econtext->ecxt_innertuple;
- break;
-
- case OUTER_VAR: /* get the tuple from the outer node */
- slot = econtext->ecxt_outertuple;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default: /* get the tuple from the relation being
- * scanned */
- slot = econtext->ecxt_scantuple;
- break;
- }
-
- /* Apply the junkfilter if any */
- if (wrvstate->wrv_junkFilter != NULL)
- slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
-
- /*
- * Copy the slot tuple and make sure any toasted fields get detoasted.
- */
- dtuple = DatumGetHeapTupleHeader(ExecFetchSlotTupleDatum(slot));
-
- /*
- * Label the datum with the composite type info we identified before.
- */
- HeapTupleHeaderSetTypeId(dtuple, wrvstate->wrv_tupdesc->tdtypeid);
- HeapTupleHeaderSetTypMod(dtuple, wrvstate->wrv_tupdesc->tdtypmod);
-
- return PointerGetDatum(dtuple);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalWholeRowSlow
- *
- * Returns a Datum for a whole-row variable, in the "slow" case where
- * we can't just copy the subplan's output.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Var *variable = (Var *) wrvstate->xprstate.expr;
- TupleTableSlot *slot;
- HeapTuple tuple;
- TupleDesc tupleDesc;
- TupleDesc var_tupdesc;
- HeapTupleHeader dtuple;
- int i;
-
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = false;
-
- /* Get the input slot we want */
- switch (variable->varno)
- {
- case INNER_VAR: /* get the tuple from the inner node */
- slot = econtext->ecxt_innertuple;
- break;
-
- case OUTER_VAR: /* get the tuple from the outer node */
- slot = econtext->ecxt_outertuple;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default: /* get the tuple from the relation being
- * scanned */
- slot = econtext->ecxt_scantuple;
- break;
- }
-
- /* Apply the junkfilter if any */
- if (wrvstate->wrv_junkFilter != NULL)
- slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
-
- tuple = ExecFetchSlotTuple(slot);
- tupleDesc = slot->tts_tupleDescriptor;
-
- /* wrv_tupdesc is a good enough representation of the Var's rowtype */
- Assert(variable->vartype != RECORDOID);
- var_tupdesc = wrvstate->wrv_tupdesc;
-
- /* Check to see if any dropped attributes are non-null */
- for (i = 0; i < var_tupdesc->natts; i++)
- {
- Form_pg_attribute vattr = var_tupdesc->attrs[i];
- Form_pg_attribute sattr = tupleDesc->attrs[i];
-
- if (!vattr->attisdropped)
- continue; /* already checked non-dropped cols */
- if (heap_attisnull(tuple, i + 1))
- continue; /* null is always okay */
- if (vattr->attlen != sattr->attlen ||
- vattr->attalign != sattr->attalign)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("table row type and query-specified row type do not match"),
- errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
- i + 1)));
- }
-
- /*
- * Copy the slot tuple and make sure any toasted fields get detoasted.
- */
- dtuple = DatumGetHeapTupleHeader(ExecFetchSlotTupleDatum(slot));
-
- /*
- * Label the datum with the composite type info we identified before.
- */
- HeapTupleHeaderSetTypeId(dtuple, wrvstate->wrv_tupdesc->tdtypeid);
- HeapTupleHeaderSetTypMod(dtuple, wrvstate->wrv_tupdesc->tdtypmod);
-
- return PointerGetDatum(dtuple);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalConst
- *
- * Returns the value of a constant.
- *
- * Note that for pass-by-ref datatypes, we return a pointer to the
- * actual constant node. This is one of the reasons why functions
- * must treat their input arguments as read-only.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Const *con = (Const *) exprstate->expr;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- *isNull = con->constisnull;
- return con->constvalue;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalParamExec
- *
- * Returns the value of a PARAM_EXEC parameter.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Param *expression = (Param *) exprstate->expr;
- int thisParamId = expression->paramid;
- ParamExecData *prm;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * PARAM_EXEC params (internal executor parameters) are stored in the
- * ecxt_param_exec_vals array, and can be accessed by array index.
- */
- prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
- if (prm->execPlan != NULL)
- {
- /* Parameter not evaluated yet, so go do it */
- ExecSetParamPlan(prm->execPlan, econtext);
- /* ExecSetParamPlan should have processed this param... */
- Assert(prm->execPlan == NULL);
- }
- *isNull = prm->isnull;
- return prm->value;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalParamExtern
- *
- * Returns the value of a PARAM_EXTERN parameter.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Param *expression = (Param *) exprstate->expr;
- int thisParamId = expression->paramid;
- ParamListInfo paramInfo = econtext->ecxt_param_list_info;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
- */
- if (paramInfo &&
- thisParamId > 0 && thisParamId <= paramInfo->numParams)
- {
- ParamExternData *prm = &paramInfo->params[thisParamId - 1];
-
- /* give hook a chance in case parameter is dynamic */
- if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
- (*paramInfo->paramFetch) (paramInfo, thisParamId);
-
- if (OidIsValid(prm->ptype))
- {
- /* safety check in case hook did something unexpected */
- if (prm->ptype != expression->paramtype)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
- thisParamId,
- format_type_be(prm->ptype),
- format_type_be(expression->paramtype))));
-
- *isNull = prm->isnull;
- return prm->value;
- }
- }
-
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("no value found for parameter %d", thisParamId)));
- return (Datum) 0; /* keep compiler quiet */
-}
-
-
-/* ----------------------------------------------------------------
- * ExecEvalOper / ExecEvalFunc support routines
- * ----------------------------------------------------------------
- */
-
-/*
- * GetAttributeByName
- * GetAttributeByNum
- *
- * These functions return the value of the requested attribute
- * out of the given tuple Datum.
- * C functions which take a tuple as an argument are expected
- * to use these. Ex: overpaid(EMP) might call GetAttributeByNum().
- * Note: these are actually rather slow because they do a typcache
- * lookup on each call.
- */
-Datum
-GetAttributeByNum(HeapTupleHeader tuple,
- AttrNumber attrno,
- bool *isNull)
-{
- Datum result;
- Oid tupType;
- int32 tupTypmod;
- TupleDesc tupDesc;
- HeapTupleData tmptup;
-
- if (!AttributeNumberIsValid(attrno))
- elog(ERROR, "invalid attribute number %d", attrno);
-
- if (isNull == NULL)
- elog(ERROR, "a NULL isNull pointer was passed");
-
- if (tuple == NULL)
- {
- /* Kinda bogus but compatible with old behavior... */
- *isNull = true;
- return (Datum) 0;
- }
-
- tupType = HeapTupleHeaderGetTypeId(tuple);
- tupTypmod = HeapTupleHeaderGetTypMod(tuple);
- tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
-
- /*
- * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
- * the fields in the struct just in case user tries to inspect system
- * columns.
- */
- tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
- ItemPointerSetInvalid(&(tmptup.t_self));
- tmptup.t_tableOid = InvalidOid;
-#ifdef PGXC
- tmptup.t_xc_node_id = 0;
-#endif
- tmptup.t_data = tuple;
-
- result = heap_getattr(&tmptup,
- attrno,
- tupDesc,
- isNull);
-
- ReleaseTupleDesc(tupDesc);
-
- return result;
-}
-
-Datum
-GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
-{
- AttrNumber attrno;
- Datum result;
- Oid tupType;
- int32 tupTypmod;
- TupleDesc tupDesc;
- HeapTupleData tmptup;
- int i;
-
- if (attname == NULL)
- elog(ERROR, "invalid attribute name");
-
- if (isNull == NULL)
- elog(ERROR, "a NULL isNull pointer was passed");
-
- if (tuple == NULL)
- {
- /* Kinda bogus but compatible with old behavior... */
- *isNull = true;
- return (Datum) 0;
- }
-
- tupType = HeapTupleHeaderGetTypeId(tuple);
- tupTypmod = HeapTupleHeaderGetTypMod(tuple);
- tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
-
- attrno = InvalidAttrNumber;
- for (i = 0; i < tupDesc->natts; i++)
- {
- if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0)
- {
- attrno = tupDesc->attrs[i]->attnum;
- break;
- }
- }
-
- if (attrno == InvalidAttrNumber)
- elog(ERROR, "attribute \"%s\" does not exist", attname);
-
- /*
- * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
- * the fields in the struct just in case user tries to inspect system
- * columns.
- */
- tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
- ItemPointerSetInvalid(&(tmptup.t_self));
- tmptup.t_tableOid = InvalidOid;
-#ifdef PGXC
- tmptup.t_xc_node_id = 0;
-#endif
- tmptup.t_data = tuple;
-
- result = heap_getattr(&tmptup,
- attrno,
- tupDesc,
- isNull);
-
- ReleaseTupleDesc(tupDesc);
-
- return result;
-}
-
-/*
- * init_fcache - initialize a FuncExprState node during first use
- */
-static void
-init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
- MemoryContext fcacheCxt, bool needDescForSets)
-{
- AclResult aclresult;
-
- /* Check permission to call function */
- aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));
- InvokeFunctionExecuteHook(foid);
-
- /*
- * Safety check on nargs. Under normal circumstances this should never
- * fail, as parser should check sooner. But possibly it might fail if
- * server has been compiled with FUNC_MAX_ARGS smaller than some functions
- * declared in pg_proc?
- */
- if (list_length(fcache->args) > FUNC_MAX_ARGS)
- ereport(ERROR,
- (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
- errmsg_plural("cannot pass more than %d argument to a function",
- "cannot pass more than %d arguments to a function",
- FUNC_MAX_ARGS,
- FUNC_MAX_ARGS)));
-
- /* Set up the primary fmgr lookup information */
- fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
- fmgr_info_set_expr((Node *) fcache->xprstate.expr, &(fcache->func));
-
- /* Initialize the function call parameter struct as well */
- InitFunctionCallInfoData(fcache->fcinfo_data, &(fcache->func),
- list_length(fcache->args),
- input_collation, NULL, NULL);
-
- /* If function returns set, prepare expected tuple descriptor */
- if (fcache->func.fn_retset && needDescForSets)
- {
- TypeFuncClass functypclass;
- Oid funcrettype;
- TupleDesc tupdesc;
- MemoryContext oldcontext;
-
- functypclass = get_expr_result_type(fcache->func.fn_expr,
- &funcrettype,
- &tupdesc);
-
- /* Must save tupdesc in fcache's context */
- oldcontext = MemoryContextSwitchTo(fcacheCxt);
-
- if (functypclass == TYPEFUNC_COMPOSITE)
- {
- /* Composite data type, e.g. a table's row type */
- Assert(tupdesc);
- /* Must copy it out of typcache for safety */
- fcache->funcResultDesc = CreateTupleDescCopy(tupdesc);
- fcache->funcReturnsTuple = true;
- }
- else if (functypclass == TYPEFUNC_SCALAR)
- {
- /* Base data type, i.e. scalar */
- tupdesc = CreateTemplateTupleDesc(1, false);
- TupleDescInitEntry(tupdesc,
- (AttrNumber) 1,
- NULL,
- funcrettype,
- -1,
- 0);
- fcache->funcResultDesc = tupdesc;
- fcache->funcReturnsTuple = false;
- }
- else if (functypclass == TYPEFUNC_RECORD)
- {
- /* This will work if function doesn't need an expectedDesc */
- fcache->funcResultDesc = NULL;
- fcache->funcReturnsTuple = true;
- }
- else
- {
- /* Else, we will fail if function needs an expectedDesc */
- fcache->funcResultDesc = NULL;
- }
-
- MemoryContextSwitchTo(oldcontext);
- }
- else
- fcache->funcResultDesc = NULL;
-
- /* Initialize additional state */
- fcache->funcResultStore = NULL;
- fcache->funcResultSlot = NULL;
- fcache->setArgsValid = false;
- fcache->shutdown_reg = false;
-}
-
-/*
- * callback function in case a FuncExpr returning a set needs to be shut down
- * before it has been run to completion
- */
-static void
-ShutdownFuncExpr(Datum arg)
-{
- FuncExprState *fcache = (FuncExprState *) DatumGetPointer(arg);
-
- /* If we have a slot, make sure it's let go of any tuplestore pointer */
- if (fcache->funcResultSlot)
- ExecClearTuple(fcache->funcResultSlot);
-
- /* Release any open tuplestore */
- if (fcache->funcResultStore)
- tuplestore_end(fcache->funcResultStore);
- fcache->funcResultStore = NULL;
-
- /* Clear any active set-argument state */
- fcache->setArgsValid = false;
-
- /* execUtils will deregister the callback... */
- fcache->shutdown_reg = false;
-}
-
-/*
- * get_cached_rowtype: utility function to lookup a rowtype tupdesc
- *
- * type_id, typmod: identity of the rowtype
- * cache_field: where to cache the TupleDesc pointer in expression state node
- * (field must be initialized to NULL)
- * econtext: expression context we are executing in
- *
- * NOTE: because the shutdown callback will be called during plan rescan,
- * must be prepared to re-do this during any node execution; cannot call
- * just once during expression initialization
- */
-static TupleDesc
-get_cached_rowtype(Oid type_id, int32 typmod,
- TupleDesc *cache_field, ExprContext *econtext)
-{
- TupleDesc tupDesc = *cache_field;
-
- /* Do lookup if no cached value or if requested type changed */
- if (tupDesc == NULL ||
- type_id != tupDesc->tdtypeid ||
- typmod != tupDesc->tdtypmod)
- {
- tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
-
- if (*cache_field)
- {
- /* Release old tupdesc; but callback is already registered */
- ReleaseTupleDesc(*cache_field);
- }
- else
- {
- /* Need to register shutdown callback to release tupdesc */
- RegisterExprContextCallback(econtext,
- ShutdownTupleDescRef,
- PointerGetDatum(cache_field));
- }
- *cache_field = tupDesc;
- }
- return tupDesc;
-}
-
-/*
- * Callback function to release a tupdesc refcount at expression tree shutdown
- */
-static void
-ShutdownTupleDescRef(Datum arg)
-{
- TupleDesc *cache_field = (TupleDesc *) DatumGetPointer(arg);
-
- if (*cache_field)
- ReleaseTupleDesc(*cache_field);
- *cache_field = NULL;
-}
-
-/*
- * Evaluate arguments for a function.
- */
-static ExprDoneCond
-ExecEvalFuncArgs(FunctionCallInfo fcinfo,
- List *argList,
- ExprContext *econtext)
-{
- ExprDoneCond argIsDone;
- int i;
- ListCell *arg;
-
- argIsDone = ExprSingleResult; /* default assumption */
-
- i = 0;
- foreach(arg, argList)
- {
- ExprState *argstate = (ExprState *) lfirst(arg);
- ExprDoneCond thisArgIsDone;
-
- fcinfo->arg[i] = ExecEvalExpr(argstate,
- econtext,
- &fcinfo->argnull[i],
- &thisArgIsDone);
-
- if (thisArgIsDone != ExprSingleResult)
- {
- /*
- * We allow only one argument to have a set value; we'd need much
- * more complexity to keep track of multiple set arguments (cf.
- * ExecTargetList) and it doesn't seem worth it.
- */
- if (argIsDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("functions and operators can take at most one set argument")));
- argIsDone = thisArgIsDone;
- }
- i++;
- }
-
- Assert(i == fcinfo->nargs);
-
- return argIsDone;
-}
-
-/*
- * ExecPrepareTuplestoreResult
- *
- * Subroutine for ExecMakeFunctionResult: prepare to extract rows from a
- * tuplestore function result. We must set up a funcResultSlot (unless
- * already done in a previous call cycle) and verify that the function
- * returned the expected tuple descriptor.
- */
-static void
-ExecPrepareTuplestoreResult(FuncExprState *fcache,
- ExprContext *econtext,
- Tuplestorestate *resultStore,
- TupleDesc resultDesc)
-{
- fcache->funcResultStore = resultStore;
-
- if (fcache->funcResultSlot == NULL)
- {
- /* Create a slot so we can read data out of the tuplestore */
- TupleDesc slotDesc;
- MemoryContext oldcontext;
-
- oldcontext = MemoryContextSwitchTo(fcache->func.fn_mcxt);
-
- /*
- * If we were not able to determine the result rowtype from context,
- * and the function didn't return a tupdesc, we have to fail.
- */
- if (fcache->funcResultDesc)
- slotDesc = fcache->funcResultDesc;
- else if (resultDesc)
- {
- /* don't assume resultDesc is long-lived */
- slotDesc = CreateTupleDescCopy(resultDesc);
- }
- else
- {
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("function returning setof record called in "
- "context that cannot accept type record")));
- slotDesc = NULL; /* keep compiler quiet */
- }
-
- fcache->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
- MemoryContextSwitchTo(oldcontext);
- }
-
- /*
- * If function provided a tupdesc, cross-check it. We only really need to
- * do this for functions returning RECORD, but might as well do it always.
- */
- if (resultDesc)
- {
- if (fcache->funcResultDesc)
- tupledesc_match(fcache->funcResultDesc, resultDesc);
-
- /*
- * If it is a dynamically-allocated TupleDesc, free it: it is
- * typically allocated in a per-query context, so we must avoid
- * leaking it across multiple usages.
- */
- if (resultDesc->tdrefcount == -1)
- FreeTupleDesc(resultDesc);
- }
-
- /* Register cleanup callback if we didn't already */
- if (!fcache->shutdown_reg)
- {
- RegisterExprContextCallback(econtext,
- ShutdownFuncExpr,
- PointerGetDatum(fcache));
- fcache->shutdown_reg = true;
- }
-}
-
-/*
- * Check that function result tuple type (src_tupdesc) matches or can
- * be considered to match what the query expects (dst_tupdesc). If
- * they don't match, ereport.
- *
- * We really only care about number of attributes and data type.
- * Also, we can ignore type mismatch on columns that are dropped in the
- * destination type, so long as the physical storage matches. This is
- * helpful in some cases involving out-of-date cached plans.
- */
-static void
-tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
-{
- int i;
-
- if (dst_tupdesc->natts != src_tupdesc->natts)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("function return row and query-specified return row do not match"),
- errdetail_plural("Returned row contains %d attribute, but query expects %d.",
- "Returned row contains %d attributes, but query expects %d.",
- src_tupdesc->natts,
- src_tupdesc->natts, dst_tupdesc->natts)));
-
- for (i = 0; i < dst_tupdesc->natts; i++)
- {
- Form_pg_attribute dattr = dst_tupdesc->attrs[i];
- Form_pg_attribute sattr = src_tupdesc->attrs[i];
-
- if (IsBinaryCoercible(sattr->atttypid, dattr->atttypid))
- continue; /* no worries */
- if (!dattr->attisdropped)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("function return row and query-specified return row do not match"),
- errdetail("Returned type %s at ordinal position %d, but query expects %s.",
- format_type_be(sattr->atttypid),
- i + 1,
- format_type_be(dattr->atttypid))));
-
- if (dattr->attlen != sattr->attlen ||
- dattr->attalign != sattr->attalign)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("function return row and query-specified return row do not match"),
- errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
- i + 1)));
- }
-}
-
-/*
- * ExecMakeFunctionResult
- *
- * Evaluate the arguments to a function and then the function itself.
- * init_fcache is presumed already run on the FuncExprState.
- *
- * This function handles the most general case, wherein the function or
- * one of its arguments can return a set.
- */
-static Datum
-ExecMakeFunctionResult(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- List *arguments;
- Datum result;
- FunctionCallInfo fcinfo;
- PgStat_FunctionCallUsage fcusage;
- ReturnSetInfo rsinfo; /* for functions returning sets */
- ExprDoneCond argDone;
- bool hasSetArg;
- int i;
-
-restart:
-
- /* Guard against stack overflow due to overly complex expressions */
- check_stack_depth();
-
- /*
- * If a previous call of the function returned a set result in the form of
- * a tuplestore, continue reading rows from the tuplestore until it's
- * empty.
- */
- if (fcache->funcResultStore)
- {
- Assert(isDone); /* it was provided before ... */
- if (tuplestore_gettupleslot(fcache->funcResultStore, true, false,
- fcache->funcResultSlot))
- {
- *isDone = ExprMultipleResult;
- if (fcache->funcReturnsTuple)
- {
- /* We must return the whole tuple as a Datum. */
- *isNull = false;
- return ExecFetchSlotTupleDatum(fcache->funcResultSlot);
- }
- else
- {
- /* Extract the first column and return it as a scalar. */
- return slot_getattr(fcache->funcResultSlot, 1, isNull);
- }
- }
- /* Exhausted the tuplestore, so clean up */
- tuplestore_end(fcache->funcResultStore);
- fcache->funcResultStore = NULL;
- /* We are done unless there was a set-valued argument */
- if (!fcache->setHasSetArg)
- {
- *isDone = ExprEndResult;
- *isNull = true;
- return (Datum) 0;
- }
- /* If there was, continue evaluating the argument values */
- Assert(!fcache->setArgsValid);
- }
-
- /*
- * arguments is a list of expressions to evaluate before passing to the
- * function manager. We skip the evaluation if it was already done in the
- * previous call (ie, we are continuing the evaluation of a set-valued
- * function). Otherwise, collect the current argument values into fcinfo.
- */
- fcinfo = &fcache->fcinfo_data;
- arguments = fcache->args;
- if (!fcache->setArgsValid)
- {
- argDone = ExecEvalFuncArgs(fcinfo, arguments, econtext);
- if (argDone == ExprEndResult)
- {
- /* input is an empty set, so return an empty set. */
- *isNull = true;
- if (isDone)
- *isDone = ExprEndResult;
- else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- return (Datum) 0;
- }
- hasSetArg = (argDone != ExprSingleResult);
- }
- else
- {
- /* Re-use callinfo from previous evaluation */
- hasSetArg = fcache->setHasSetArg;
- /* Reset flag (we may set it again below) */
- fcache->setArgsValid = false;
- }
-
- /*
- * Now call the function, passing the evaluated parameter values.
- */
- if (fcache->func.fn_retset || hasSetArg)
- {
- /*
- * We need to return a set result. Complain if caller not ready to
- * accept one.
- */
- if (isDone == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
-
- /*
- * Prepare a resultinfo node for communication. If the function
- * doesn't itself return set, we don't pass the resultinfo to the
- * function, but we need to fill it in anyway for internal use.
- */
- if (fcache->func.fn_retset)
- fcinfo->resultinfo = (Node *) &rsinfo;
- rsinfo.type = T_ReturnSetInfo;
- rsinfo.econtext = econtext;
- rsinfo.expectedDesc = fcache->funcResultDesc;
- rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
- /* note we do not set SFRM_Materialize_Random or _Preferred */
- rsinfo.returnMode = SFRM_ValuePerCall;
- /* isDone is filled below */
- rsinfo.setResult = NULL;
- rsinfo.setDesc = NULL;
-
- /*
- * This loop handles the situation where we have both a set argument
- * and a set-valued function. Once we have exhausted the function's
- * value(s) for a particular argument value, we have to get the next
- * argument value and start the function over again. We might have to
- * do it more than once, if the function produces an empty result set
- * for a particular input value.
- */
- for (;;)
- {
- /*
- * If function is strict, and there are any NULL arguments, skip
- * calling the function (at least for this set of args).
- */
- bool callit = true;
-
- if (fcache->func.fn_strict)
- {
- for (i = 0; i < fcinfo->nargs; i++)
- {
- if (fcinfo->argnull[i])
- {
- callit = false;
- break;
- }
- }
- }
-
- if (callit)
- {
- pgstat_init_function_usage(fcinfo, &fcusage);
-
- fcinfo->isnull = false;
- rsinfo.isDone = ExprSingleResult;
- result = FunctionCallInvoke(fcinfo);
- *isNull = fcinfo->isnull;
- *isDone = rsinfo.isDone;
-
- pgstat_end_function_usage(&fcusage,
- rsinfo.isDone != ExprMultipleResult);
- }
- else if (fcache->func.fn_retset)
- {
- /* for a strict SRF, result for NULL is an empty set */
- result = (Datum) 0;
- *isNull = true;
- *isDone = ExprEndResult;
- }
- else
- {
- /* for a strict non-SRF, result for NULL is a NULL */
- result = (Datum) 0;
- *isNull = true;
- *isDone = ExprSingleResult;
- }
-
- /* Which protocol does function want to use? */
- if (rsinfo.returnMode == SFRM_ValuePerCall)
- {
- if (*isDone != ExprEndResult)
- {
- /*
- * Got a result from current argument. If function itself
- * returns set, save the current argument values to re-use
- * on the next call.
- */
- if (fcache->func.fn_retset &&
- *isDone == ExprMultipleResult)
- {
- fcache->setHasSetArg = hasSetArg;
- fcache->setArgsValid = true;
- /* Register cleanup callback if we didn't already */
- if (!fcache->shutdown_reg)
- {
- RegisterExprContextCallback(econtext,
- ShutdownFuncExpr,
- PointerGetDatum(fcache));
- fcache->shutdown_reg = true;
- }
- }
-
- /*
- * Make sure we say we are returning a set, even if the
- * function itself doesn't return sets.
- */
- if (hasSetArg)
- *isDone = ExprMultipleResult;
- break;
- }
- }
- else if (rsinfo.returnMode == SFRM_Materialize)
- {
- /* check we're on the same page as the function author */
- if (rsinfo.isDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
- errmsg("table-function protocol for materialize mode was not followed")));
- if (rsinfo.setResult != NULL)
- {
- /* prepare to return values from the tuplestore */
- ExecPrepareTuplestoreResult(fcache, econtext,
- rsinfo.setResult,
- rsinfo.setDesc);
- /* remember whether we had set arguments */
- fcache->setHasSetArg = hasSetArg;
- /* loop back to top to start returning from tuplestore */
- goto restart;
- }
- /* if setResult was left null, treat it as empty set */
- *isDone = ExprEndResult;
- *isNull = true;
- result = (Datum) 0;
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
- errmsg("unrecognized table-function returnMode: %d",
- (int) rsinfo.returnMode)));
-
- /* Else, done with this argument */
- if (!hasSetArg)
- break; /* input not a set, so done */
-
- /* Re-eval args to get the next element of the input set */
- argDone = ExecEvalFuncArgs(fcinfo, arguments, econtext);
-
- if (argDone != ExprMultipleResult)
- {
- /* End of argument set, so we're done. */
- *isNull = true;
- *isDone = ExprEndResult;
- result = (Datum) 0;
- break;
- }
-
- /*
- * If we reach here, loop around to run the function on the new
- * argument.
- */
- }
- }
- else
- {
- /*
- * Non-set case: much easier.
- *
- * In common cases, this code path is unreachable because we'd have
- * selected ExecMakeFunctionResultNoSets instead. However, it's
- * possible to get here if an argument sometimes produces set results
- * and sometimes scalar results. For example, a CASE expression might
- * call a set-returning function in only some of its arms.
- */
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * If function is strict, and there are any NULL arguments, skip
- * calling the function and return NULL.
- */
- if (fcache->func.fn_strict)
- {
- for (i = 0; i < fcinfo->nargs; i++)
- {
- if (fcinfo->argnull[i])
- {
- *isNull = true;
- return (Datum) 0;
- }
- }
- }
-
- pgstat_init_function_usage(fcinfo, &fcusage);
-
- fcinfo->isnull = false;
- result = FunctionCallInvoke(fcinfo);
- *isNull = fcinfo->isnull;
-
- pgstat_end_function_usage(&fcusage, true);
- }
-
- return result;
-}
-
-/*
- * ExecMakeFunctionResultNoSets
- *
- * Simplified version of ExecMakeFunctionResult that can only handle
- * non-set cases. Hand-tuned for speed.
- */
-static Datum
-ExecMakeFunctionResultNoSets(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- ListCell *arg;
- Datum result;
- FunctionCallInfo fcinfo;
- PgStat_FunctionCallUsage fcusage;
- int i;
-
- /* Guard against stack overflow due to overly complex expressions */
- check_stack_depth();
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /* inlined, simplified version of ExecEvalFuncArgs */
- fcinfo = &fcache->fcinfo_data;
- i = 0;
- foreach(arg, fcache->args)
- {
- ExprState *argstate = (ExprState *) lfirst(arg);
-
- fcinfo->arg[i] = ExecEvalExpr(argstate,
- econtext,
- &fcinfo->argnull[i],
- NULL);
- i++;
- }
-
- /*
- * If function is strict, and there are any NULL arguments, skip calling
- * the function and return NULL.
- */
- if (fcache->func.fn_strict)
- {
- while (--i >= 0)
- {
- if (fcinfo->argnull[i])
- {
- *isNull = true;
- return (Datum) 0;
- }
- }
- }
-
- pgstat_init_function_usage(fcinfo, &fcusage);
-
- fcinfo->isnull = false;
- result = FunctionCallInvoke(fcinfo);
- *isNull = fcinfo->isnull;
-
- pgstat_end_function_usage(&fcusage, true);
-
- return result;
-}
-
-
-/*
- * ExecMakeTableFunctionResult
- *
- * Evaluate a table function, producing a materialized result in a Tuplestore
- * object.
- */
-Tuplestorestate *
-ExecMakeTableFunctionResult(ExprState *funcexpr,
- ExprContext *econtext,
- MemoryContext argContext,
- TupleDesc expectedDesc,
- bool randomAccess)
-{
- Tuplestorestate *tupstore = NULL;
- TupleDesc tupdesc = NULL;
- Oid funcrettype;
- bool returnsTuple;
- bool returnsSet = false;
- FunctionCallInfoData fcinfo;
- PgStat_FunctionCallUsage fcusage;
- ReturnSetInfo rsinfo;
- HeapTupleData tmptup;
- MemoryContext callerContext;
- MemoryContext oldcontext;
- bool direct_function_call;
- bool first_time = true;
-
- callerContext = CurrentMemoryContext;
-
- funcrettype = exprType((Node *) funcexpr->expr);
-
- returnsTuple = type_is_rowtype(funcrettype);
-
- /*
- * Prepare a resultinfo node for communication. We always do this even if
- * not expecting a set result, so that we can pass expectedDesc. In the
- * generic-expression case, the expression doesn't actually get to see the
- * resultinfo, but set it up anyway because we use some of the fields as
- * our own state variables.
- */
- rsinfo.type = T_ReturnSetInfo;
- rsinfo.econtext = econtext;
- rsinfo.expectedDesc = expectedDesc;
- rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize | SFRM_Materialize_Preferred);
- if (randomAccess)
- rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
- rsinfo.returnMode = SFRM_ValuePerCall;
- /* isDone is filled below */
- rsinfo.setResult = NULL;
- rsinfo.setDesc = NULL;
-
- /*
- * Normally the passed expression tree will be a FuncExprState, since the
- * grammar only allows a function call at the top level of a table
- * function reference. However, if the function doesn't return set then
- * the planner might have replaced the function call via constant-folding
- * or inlining. So if we see any other kind of expression node, execute
- * it via the general ExecEvalExpr() code; the only difference is that we
- * don't get a chance to pass a special ReturnSetInfo to any functions
- * buried in the expression.
- */
- if (funcexpr && IsA(funcexpr, FuncExprState) &&
- IsA(funcexpr->expr, FuncExpr))
- {
- FuncExprState *fcache = (FuncExprState *) funcexpr;
- ExprDoneCond argDone;
-
- /*
- * This path is similar to ExecMakeFunctionResult.
- */
- direct_function_call = true;
-
- /*
- * Initialize function cache if first time through
- */
- if (fcache->func.fn_oid == InvalidOid)
- {
- FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;
-
- init_fcache(func->funcid, func->inputcollid, fcache,
- econtext->ecxt_per_query_memory, false);
- }
- returnsSet = fcache->func.fn_retset;
- InitFunctionCallInfoData(fcinfo, &(fcache->func),
- list_length(fcache->args),
- fcache->fcinfo_data.fncollation,
- NULL, (Node *) &rsinfo);
-
- /*
- * Evaluate the function's argument list.
- *
- * We can't do this in the per-tuple context: the argument values
- * would disappear when we reset that context in the inner loop. And
- * the caller's CurrentMemoryContext is typically a query-lifespan
- * context, so we don't want to leak memory there. We require the
- * caller to pass a separate memory context that can be used for this,
- * and can be reset each time through to avoid bloat.
- */
- MemoryContextReset(argContext);
- oldcontext = MemoryContextSwitchTo(argContext);
- argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
- MemoryContextSwitchTo(oldcontext);
-
- /* We don't allow sets in the arguments of the table function */
- if (argDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
-
- /*
- * If function is strict, and there are any NULL arguments, skip
- * calling the function and act like it returned NULL (or an empty
- * set, in the returns-set case).
- */
- if (fcache->func.fn_strict)
- {
- int i;
-
- for (i = 0; i < fcinfo.nargs; i++)
- {
- if (fcinfo.argnull[i])
- goto no_function_result;
- }
- }
- }
- else
- {
- /* Treat funcexpr as a generic expression */
- direct_function_call = false;
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- }
-
- /*
- * Switch to short-lived context for calling the function or expression.
- */
- MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
-
- /*
- * Loop to handle the ValuePerCall protocol (which is also the same
- * behavior needed in the generic ExecEvalExpr path).
- */
- for (;;)
- {
- Datum result;
-
- CHECK_FOR_INTERRUPTS();
-
- /*
- * reset per-tuple memory context before each call of the function or
- * expression. This cleans up any local memory the function may leak
- * when called.
- */
- ResetExprContext(econtext);
-
- /* Call the function or expression one time */
- if (direct_function_call)
- {
- pgstat_init_function_usage(&fcinfo, &fcusage);
-
- fcinfo.isnull = false;
- rsinfo.isDone = ExprSingleResult;
- result = FunctionCallInvoke(&fcinfo);
-
- pgstat_end_function_usage(&fcusage,
- rsinfo.isDone != ExprMultipleResult);
- }
- else
- {
- result = ExecEvalExpr(funcexpr, econtext,
- &fcinfo.isnull, &rsinfo.isDone);
- }
-
- /* Which protocol does function want to use? */
- if (rsinfo.returnMode == SFRM_ValuePerCall)
- {
- /*
- * Check for end of result set.
- */
- if (rsinfo.isDone == ExprEndResult)
- break;
-
- /*
- * If first time through, build tuplestore for result. For a
- * scalar function result type, also make a suitable tupdesc.
- */
- if (first_time)
- {
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
- rsinfo.setResult = tupstore;
- if (!returnsTuple)
- {
- tupdesc = CreateTemplateTupleDesc(1, false);
- TupleDescInitEntry(tupdesc,
- (AttrNumber) 1,
- "column",
- funcrettype,
- -1,
- 0);
- rsinfo.setDesc = tupdesc;
- }
- MemoryContextSwitchTo(oldcontext);
- }
-
- /*
- * Store current resultset item.
- */
- if (returnsTuple)
- {
- if (!fcinfo.isnull)
- {
- HeapTupleHeader td = DatumGetHeapTupleHeader(result);
-
- if (tupdesc == NULL)
- {
- /*
- * This is the first non-NULL result from the
- * function. Use the type info embedded in the
- * rowtype Datum to look up the needed tupdesc. Make
- * a copy for the query.
- */
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td),
- HeapTupleHeaderGetTypMod(td));
- rsinfo.setDesc = tupdesc;
- MemoryContextSwitchTo(oldcontext);
- }
- else
- {
- /*
- * Verify all later returned rows have same subtype;
- * necessary in case the type is RECORD.
- */
- if (HeapTupleHeaderGetTypeId(td) != tupdesc->tdtypeid ||
- HeapTupleHeaderGetTypMod(td) != tupdesc->tdtypmod)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("rows returned by function are not all of the same row type")));
- }
-
- /*
- * tuplestore_puttuple needs a HeapTuple not a bare
- * HeapTupleHeader, but it doesn't need all the fields.
- */
- tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
- tmptup.t_data = td;
-
- tuplestore_puttuple(tupstore, &tmptup);
- }
- else
- {
- /*
- * NULL result from a tuple-returning function; expand it
- * to a row of all nulls. We rely on the expectedDesc to
- * form such rows. (Note: this would be problematic if
- * tuplestore_putvalues saved the tdtypeid/tdtypmod from
- * the provided descriptor, since that might not match
- * what we get from the function itself. But it doesn't.)
- */
- int natts = expectedDesc->natts;
- bool *nullflags;
-
- nullflags = (bool *) palloc(natts * sizeof(bool));
- memset(nullflags, true, natts * sizeof(bool));
- tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
- }
- }
- else
- {
- /* Scalar-type case: just store the function result */
- tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
- }
-
- /*
- * Are we done?
- */
- if (rsinfo.isDone != ExprMultipleResult)
- break;
- }
- else if (rsinfo.returnMode == SFRM_Materialize)
- {
- /* check we're on the same page as the function author */
- if (!first_time || rsinfo.isDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
- errmsg("table-function protocol for materialize mode was not followed")));
- /* Done evaluating the set result */
- break;
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
- errmsg("unrecognized table-function returnMode: %d",
- (int) rsinfo.returnMode)));
-
- first_time = false;
- }
-
-no_function_result:
-
- /*
- * If we got nothing from the function (ie, an empty-set or NULL result),
- * we have to create the tuplestore to return, and if it's a
- * non-set-returning function then insert a single all-nulls row. As
- * above, we depend on the expectedDesc to manufacture the dummy row.
- */
- if (rsinfo.setResult == NULL)
- {
- MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
- rsinfo.setResult = tupstore;
- if (!returnsSet)
- {
- int natts = expectedDesc->natts;
- bool *nullflags;
-
- MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
- nullflags = (bool *) palloc(natts * sizeof(bool));
- memset(nullflags, true, natts * sizeof(bool));
- tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
- }
- }
-
- /*
- * If function provided a tupdesc, cross-check it. We only really need to
- * do this for functions returning RECORD, but might as well do it always.
- */
- if (rsinfo.setDesc)
- {
- tupledesc_match(expectedDesc, rsinfo.setDesc);
-
- /*
- * If it is a dynamically-allocated TupleDesc, free it: it is
- * typically allocated in a per-query context, so we must avoid
- * leaking it across multiple usages.
- */
- if (rsinfo.setDesc->tdrefcount == -1)
- FreeTupleDesc(rsinfo.setDesc);
- }
-
- MemoryContextSwitchTo(callerContext);
-
- /* All done, pass back the tuplestore */
- return rsinfo.setResult;
-}
-
-
-/* ----------------------------------------------------------------
- * ExecEvalFunc
- * ExecEvalOper
- *
- * Evaluate the functional result of a list of arguments by calling the
- * function manager.
- * ----------------------------------------------------------------
- */
-
-/* ----------------------------------------------------------------
- * ExecEvalFunc
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalFunc(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- /* This is called only the first time through */
- FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;
-
- /* Initialize function lookup info */
- init_fcache(func->funcid, func->inputcollid, fcache,
- econtext->ecxt_per_query_memory, true);
-
- /*
- * We need to invoke ExecMakeFunctionResult if either the function itself
- * or any of its input expressions can return a set. Otherwise, invoke
- * ExecMakeFunctionResultNoSets. In either case, change the evalfunc
- * pointer to go directly there on subsequent uses.
- */
- if (fcache->func.fn_retset || expression_returns_set((Node *) func->args))
- {
- fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;
- return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
- }
- else
- {
- fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
- return ExecMakeFunctionResultNoSets(fcache, econtext, isNull, isDone);
- }
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalOper
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalOper(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- /* This is called only the first time through */
- OpExpr *op = (OpExpr *) fcache->xprstate.expr;
-
- /* Initialize function lookup info */
- init_fcache(op->opfuncid, op->inputcollid, fcache,
- econtext->ecxt_per_query_memory, true);
-
- /*
- * We need to invoke ExecMakeFunctionResult if either the function itself
- * or any of its input expressions can return a set. Otherwise, invoke
- * ExecMakeFunctionResultNoSets. In either case, change the evalfunc
- * pointer to go directly there on subsequent uses.
- */
- if (fcache->func.fn_retset || expression_returns_set((Node *) op->args))
- {
- fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;
- return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
- }
- else
- {
- fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
- return ExecMakeFunctionResultNoSets(fcache, econtext, isNull, isDone);
- }
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalDistinct
- *
- * IS DISTINCT FROM must evaluate arguments to determine whether
- * they are NULL; if either is NULL then the result is already
- * known. If neither is NULL, then proceed to evaluate the
- * function. Note that this is *always* derived from the equals
- * operator, but since we need special processing of the arguments
- * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalDistinct(FuncExprState *fcache,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- Datum result;
- FunctionCallInfo fcinfo;
- ExprDoneCond argDone;
-
- /* Set default values for result flags: non-null, not a set result */
- *isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * Initialize function cache if first time through
- */
- if (fcache->func.fn_oid == InvalidOid)
- {
- DistinctExpr *op = (DistinctExpr *) fcache->xprstate.expr;
-
- init_fcache(op->opfuncid, op->inputcollid, fcache,
- econtext->ecxt_per_query_memory, true);
- Assert(!fcache->func.fn_retset);
- }
-
- /*
- * Evaluate arguments
- */
- fcinfo = &fcache->fcinfo_data;
- argDone = ExecEvalFuncArgs(fcinfo, fcache->args, econtext);
- if (argDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("IS DISTINCT FROM does not support set arguments")));
- Assert(fcinfo->nargs == 2);
-
- if (fcinfo->argnull[0] && fcinfo->argnull[1])
- {
- /* Both NULL? Then is not distinct... */
- result = BoolGetDatum(FALSE);
- }
- else if (fcinfo->argnull[0] || fcinfo->argnull[1])
- {
- /* Only one is NULL? Then is distinct... */
- result = BoolGetDatum(TRUE);
- }
- else
- {
- fcinfo->isnull = false;
- result = FunctionCallInvoke(fcinfo);
- *isNull = fcinfo->isnull;
- /* Must invert result of "=" */
- result = BoolGetDatum(!DatumGetBool(result));
- }
-
- return result;
-}
-
-/*
- * ExecEvalScalarArrayOp
- *
- * Evaluate "scalar op ANY/ALL (array)". The operator always yields boolean,
- * and we combine the results across all array elements using OR and AND
- * (for ANY and ALL respectively). Of course we short-circuit as soon as
- * the result is known.
- */
-static Datum
-ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) sstate->fxprstate.xprstate.expr;
- bool useOr = opexpr->useOr;
- ArrayType *arr;
- int nitems;
- Datum result;
- bool resultnull;
- FunctionCallInfo fcinfo;
- ExprDoneCond argDone;
- int i;
- int16 typlen;
- bool typbyval;
- char typalign;
- char *s;
- bits8 *bitmap;
- int bitmask;
-
- /* Set default values for result flags: non-null, not a set result */
- *isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * Initialize function cache if first time through
- */
- if (sstate->fxprstate.func.fn_oid == InvalidOid)
- {
- init_fcache(opexpr->opfuncid, opexpr->inputcollid, &sstate->fxprstate,
- econtext->ecxt_per_query_memory, true);
- Assert(!sstate->fxprstate.func.fn_retset);
- }
-
- /*
- * Evaluate arguments
- */
- fcinfo = &sstate->fxprstate.fcinfo_data;
- argDone = ExecEvalFuncArgs(fcinfo, sstate->fxprstate.args, econtext);
- if (argDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("op ANY/ALL (array) does not support set arguments")));
- Assert(fcinfo->nargs == 2);
-
- /*
- * If the array is NULL then we return NULL --- it's not very meaningful
- * to do anything else, even if the operator isn't strict.
- */
- if (fcinfo->argnull[1])
- {
- *isNull = true;
- return (Datum) 0;
- }
- /* Else okay to fetch and detoast the array */
- arr = DatumGetArrayTypeP(fcinfo->arg[1]);
-
- /*
- * If the array is empty, we return either FALSE or TRUE per the useOr
- * flag. This is correct even if the scalar is NULL; since we would
- * evaluate the operator zero times, it matters not whether it would want
- * to return NULL.
- */
- nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
- if (nitems <= 0)
- return BoolGetDatum(!useOr);
-
- /*
- * If the scalar is NULL, and the function is strict, return NULL; no
- * point in iterating the loop.
- */
- if (fcinfo->argnull[0] && sstate->fxprstate.func.fn_strict)
- {
- *isNull = true;
- return (Datum) 0;
- }
-
- /*
- * We arrange to look up info about the element type only once per series
- * of calls, assuming the element type doesn't change underneath us.
- */
- if (sstate->element_type != ARR_ELEMTYPE(arr))
- {
- get_typlenbyvalalign(ARR_ELEMTYPE(arr),
- &sstate->typlen,
- &sstate->typbyval,
- &sstate->typalign);
- sstate->element_type = ARR_ELEMTYPE(arr);
- }
- typlen = sstate->typlen;
- typbyval = sstate->typbyval;
- typalign = sstate->typalign;
-
- result = BoolGetDatum(!useOr);
- resultnull = false;
-
- /* Loop over the array elements */
- s = (char *) ARR_DATA_PTR(arr);
- bitmap = ARR_NULLBITMAP(arr);
- bitmask = 1;
-
- for (i = 0; i < nitems; i++)
- {
- Datum elt;
- Datum thisresult;
-
- /* Get array element, checking for NULL */
- if (bitmap && (*bitmap & bitmask) == 0)
- {
- fcinfo->arg[1] = (Datum) 0;
- fcinfo->argnull[1] = true;
- }
- else
- {
- elt = fetch_att(s, typbyval, typlen);
- s = att_addlength_pointer(s, typlen, s);
- s = (char *) att_align_nominal(s, typalign);
- fcinfo->arg[1] = elt;
- fcinfo->argnull[1] = false;
- }
-
- /* Call comparison function */
- if (fcinfo->argnull[1] && sstate->fxprstate.func.fn_strict)
- {
- fcinfo->isnull = true;
- thisresult = (Datum) 0;
- }
- else
- {
- fcinfo->isnull = false;
- thisresult = FunctionCallInvoke(fcinfo);
- }
-
- /* Combine results per OR or AND semantics */
- if (fcinfo->isnull)
- resultnull = true;
- else if (useOr)
- {
- if (DatumGetBool(thisresult))
- {
- result = BoolGetDatum(true);
- resultnull = false;
- break; /* needn't look at any more elements */
- }
- }
- else
- {
- if (!DatumGetBool(thisresult))
- {
- result = BoolGetDatum(false);
- resultnull = false;
- break; /* needn't look at any more elements */
- }
- }
-
- /* advance bitmap pointer if any */
- if (bitmap)
- {
- bitmask <<= 1;
- if (bitmask == 0x100)
- {
- bitmap++;
- bitmask = 1;
- }
- }
- }
-
- *isNull = resultnull;
- return result;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalNot
- * ExecEvalOr
- * ExecEvalAnd
- *
- * Evaluate boolean expressions, with appropriate short-circuiting.
- *
- * The query planner reformulates clause expressions in the
- * qualification to conjunctive normal form. If we ever get
- * an AND to evaluate, we can be sure that it's not a top-level
- * clause in the qualification, but appears lower (as a function
- * argument, for example), or in the target list. Not that you
- * need to know this, mind you...
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ExprState *clause = linitial(notclause->args);
- Datum expr_value;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
-
- /*
- * if the expression evaluates to null, then we just cascade the null back
- * to whoever called us.
- */
- if (*isNull)
- return expr_value;
-
- /*
- * evaluation of 'not' is simple.. expr is false, then return 'true' and
- * vice versa.
- */
- return BoolGetDatum(!DatumGetBool(expr_value));
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalOr
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- List *clauses = orExpr->args;
- ListCell *clause;
- bool AnyNull;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- AnyNull = false;
-
- /*
- * If any of the clauses is TRUE, the OR result is TRUE regardless of the
- * states of the rest of the clauses, so we can stop evaluating and return
- * TRUE immediately. If none are TRUE and one or more is NULL, we return
- * NULL; otherwise we return FALSE. This makes sense when you interpret
- * NULL as "don't know": if we have a TRUE then the OR is TRUE even if we
- * aren't sure about some of the other inputs. If all the known inputs are
- * FALSE, but we have one or more "don't knows", then we have to report
- * that we "don't know" what the OR's result should be --- perhaps one of
- * the "don't knows" would have been TRUE if we'd known its value. Only
- * when all the inputs are known to be FALSE can we state confidently that
- * the OR's result is FALSE.
- */
- foreach(clause, clauses)
- {
- ExprState *clausestate = (ExprState *) lfirst(clause);
- Datum clause_value;
-
- clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
-
- /*
- * if we have a non-null true result, then return it.
- */
- if (*isNull)
- AnyNull = true; /* remember we got a null */
- else if (DatumGetBool(clause_value))
- return clause_value;
- }
-
- /* AnyNull is true if at least one clause evaluated to NULL */
- *isNull = AnyNull;
- return BoolGetDatum(false);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalAnd
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- List *clauses = andExpr->args;
- ListCell *clause;
- bool AnyNull;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- AnyNull = false;
-
- /*
- * If any of the clauses is FALSE, the AND result is FALSE regardless of
- * the states of the rest of the clauses, so we can stop evaluating and
- * return FALSE immediately. If none are FALSE and one or more is NULL,
- * we return NULL; otherwise we return TRUE. This makes sense when you
- * interpret NULL as "don't know", using the same sort of reasoning as for
- * OR, above.
- */
-
- foreach(clause, clauses)
- {
- ExprState *clausestate = (ExprState *) lfirst(clause);
- Datum clause_value;
-
- clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
-
- /*
- * if we have a non-null false result, then return it.
- */
- if (*isNull)
- AnyNull = true; /* remember we got a null */
- else if (!DatumGetBool(clause_value))
- return clause_value;
- }
-
- /* AnyNull is true if at least one clause evaluated to NULL */
- *isNull = AnyNull;
- return BoolGetDatum(!AnyNull);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalConvertRowtype
- *
- * Evaluate a rowtype coercion operation. This may require
- * rearranging field positions.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) cstate->xprstate.expr;
- HeapTuple result;
- Datum tupDatum;
- HeapTupleHeader tuple;
- HeapTupleData tmptup;
-
- tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
-
- /* this test covers the isDone exception too: */
- if (*isNull)
- return tupDatum;
-
- tuple = DatumGetHeapTupleHeader(tupDatum);
-
- /* Lookup tupdescs if first time through or after rescan */
- if (cstate->indesc == NULL)
- {
- get_cached_rowtype(exprType((Node *) convert->arg), -1,
- &cstate->indesc, econtext);
- cstate->initialized = false;
- }
- if (cstate->outdesc == NULL)
- {
- get_cached_rowtype(convert->resulttype, -1,
- &cstate->outdesc, econtext);
- cstate->initialized = false;
- }
-
- /*
- * We used to be able to assert that incoming tuples are marked with
- * exactly the rowtype of cstate->indesc. However, now that
- * ExecEvalWholeRowVar might change the tuples' marking to plain RECORD
- * due to inserting aliases, we can only make this weak test:
- */
- Assert(HeapTupleHeaderGetTypeId(tuple) == cstate->indesc->tdtypeid ||
- HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
-
- /* if first time through, initialize conversion map */
- if (!cstate->initialized)
- {
- MemoryContext old_cxt;
-
- /* allocate map in long-lived memory context */
- old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
-
- /* prepare map from old to new attribute numbers */
- cstate->map = convert_tuples_by_name(cstate->indesc,
- cstate->outdesc,
- gettext_noop("could not convert row type"));
- cstate->initialized = true;
-
- MemoryContextSwitchTo(old_cxt);
- }
-
- /*
- * No-op if no conversion needed (not clear this can happen here).
- */
- if (cstate->map == NULL)
- return tupDatum;
-
- /*
- * do_convert_tuple needs a HeapTuple not a bare HeapTupleHeader.
- */
- tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
- tmptup.t_data = tuple;
-
- result = do_convert_tuple(&tmptup, cstate->map);
-
- return HeapTupleGetDatum(result);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalCase
- *
- * Evaluate a CASE clause. Will have boolean expressions
- * inside the WHEN clauses, and will have expressions
- * for results.
- * - thomas 1998-11-09
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- List *clauses = caseExpr->args;
- ListCell *clause;
- Datum save_datum;
- bool save_isNull;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * If there's a test expression, we have to evaluate it and save the value
- * where the CaseTestExpr placeholders can find it. We must save and
- * restore prior setting of econtext's caseValue fields, in case this node
- * is itself within a larger CASE. Furthermore, don't assign to the
- * econtext fields until after returning from evaluation of the test
- * expression. We used to pass &econtext->caseValue_isNull to the
- * recursive call, but that leads to aliasing that variable within said
- * call, which can (and did) produce bugs when the test expression itself
- * contains a CASE.
- *
- * If there's no test expression, we don't actually need to save and
- * restore these fields; but it's less code to just do so unconditionally.
- */
- save_datum = econtext->caseValue_datum;
- save_isNull = econtext->caseValue_isNull;
-
- if (caseExpr->arg)
- {
- bool arg_isNull;
-
- econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
- econtext,
- &arg_isNull,
- NULL);
- econtext->caseValue_isNull = arg_isNull;
- }
-
- /*
- * we evaluate each of the WHEN clauses in turn, as soon as one is true we
- * return the corresponding result. If none are true then we return the
- * value of the default clause, or NULL if there is none.
- */
- foreach(clause, clauses)
- {
- CaseWhenState *wclause = lfirst(clause);
- Datum clause_value;
- bool clause_isNull;
-
- clause_value = ExecEvalExpr(wclause->expr,
- econtext,
- &clause_isNull,
- NULL);
-
- /*
- * if we have a true test, then we return the result, since the case
- * statement is satisfied. A NULL result from the test is not
- * considered true.
- */
- if (DatumGetBool(clause_value) && !clause_isNull)
- {
- econtext->caseValue_datum = save_datum;
- econtext->caseValue_isNull = save_isNull;
- return ExecEvalExpr(wclause->result,
- econtext,
- isNull,
- isDone);
- }
- }
-
- econtext->caseValue_datum = save_datum;
- econtext->caseValue_isNull = save_isNull;
-
- if (caseExpr->defresult)
- {
- return ExecEvalExpr(caseExpr->defresult,
- econtext,
- isNull,
- isDone);
- }
-
- *isNull = true;
- return (Datum) 0;
-}
-
-/*
- * ExecEvalCaseTestExpr
- *
- * Return the value stored by CASE.
- */
-static Datum
-ExecEvalCaseTestExpr(ExprState *exprstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = econtext->caseValue_isNull;
- return econtext->caseValue_datum;
-}
-
-/*
- * ExecEvalGroupingFuncExpr
- *
- * Return a bitmask with a bit for each (unevaluated) argument expression
- * (rightmost arg is least significant bit).
- *
- * A bit is set if the corresponding expression is NOT part of the set of
- * grouping expressions in the current grouping set.
- */
-static Datum
-ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- int result = 0;
- int attnum = 0;
- Bitmapset *grouped_cols = gstate->aggstate->grouped_cols;
- ListCell *lc;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- *isNull = false;
-
- foreach(lc, (gstate->clauses))
- {
- attnum = lfirst_int(lc);
-
- result = result << 1;
-
- if (!bms_is_member(attnum, grouped_cols))
- result = result | 1;
- }
-
- return (Datum) result;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalArray - ARRAY[] expressions
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ArrayExpr *arrayExpr = (ArrayExpr *) astate->xprstate.expr;
- ArrayType *result;
- ListCell *element;
- Oid element_type = arrayExpr->element_typeid;
- int ndims = 0;
- int dims[MAXDIM];
- int lbs[MAXDIM];
-
- /* Set default values for result flags: non-null, not a set result */
- *isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
-
- if (!arrayExpr->multidims)
- {
- /* Elements are presumably of scalar type */
- int nelems;
- Datum *dvalues;
- bool *dnulls;
- int i = 0;
-
- ndims = 1;
- nelems = list_length(astate->elements);
-
- /* Shouldn't happen here, but if length is 0, return empty array */
- if (nelems == 0)
- return PointerGetDatum(construct_empty_array(element_type));
-
- dvalues = (Datum *) palloc(nelems * sizeof(Datum));
- dnulls = (bool *) palloc(nelems * sizeof(bool));
-
- /* loop through and build array of datums */
- foreach(element, astate->elements)
- {
- ExprState *e = (ExprState *) lfirst(element);
-
- dvalues[i] = ExecEvalExpr(e, econtext, &dnulls[i], NULL);
- i++;
- }
-
- /* setup for 1-D array of the given length */
- dims[0] = nelems;
- lbs[0] = 1;
-
- result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
- element_type,
- astate->elemlength,
- astate->elembyval,
- astate->elemalign);
- }
- else
- {
- /* Must be nested array expressions */
- int nbytes = 0;
- int nitems = 0;
- int outer_nelems = 0;
- int elem_ndims = 0;
- int *elem_dims = NULL;
- int *elem_lbs = NULL;
- bool firstone = true;
- bool havenulls = false;
- bool haveempty = false;
- char **subdata;
- bits8 **subbitmaps;
- int *subbytes;
- int *subnitems;
- int i;
- int32 dataoffset;
- char *dat;
- int iitem;
-
- i = list_length(astate->elements);
- subdata = (char **) palloc(i * sizeof(char *));
- subbitmaps = (bits8 **) palloc(i * sizeof(bits8 *));
- subbytes = (int *) palloc(i * sizeof(int));
- subnitems = (int *) palloc(i * sizeof(int));
-
- /* loop through and get data area from each element */
- foreach(element, astate->elements)
- {
- ExprState *e = (ExprState *) lfirst(element);
- bool eisnull;
- Datum arraydatum;
- ArrayType *array;
- int this_ndims;
-
- arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
- /* temporarily ignore null subarrays */
- if (eisnull)
- {
- haveempty = true;
- continue;
- }
-
- array = DatumGetArrayTypeP(arraydatum);
-
- /* run-time double-check on element type */
- if (element_type != ARR_ELEMTYPE(array))
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("cannot merge incompatible arrays"),
- errdetail("Array with element type %s cannot be "
- "included in ARRAY construct with element type %s.",
- format_type_be(ARR_ELEMTYPE(array)),
- format_type_be(element_type))));
-
- this_ndims = ARR_NDIM(array);
- /* temporarily ignore zero-dimensional subarrays */
- if (this_ndims <= 0)
- {
- haveempty = true;
- continue;
- }
-
- if (firstone)
- {
- /* Get sub-array details from first member */
- elem_ndims = this_ndims;
- ndims = elem_ndims + 1;
- if (ndims <= 0 || ndims > MAXDIM)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("number of array dimensions (%d) exceeds " \
- "the maximum allowed (%d)", ndims, MAXDIM)));
-
- elem_dims = (int *) palloc(elem_ndims * sizeof(int));
- memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
- elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
- memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
-
- firstone = false;
- }
- else
- {
- /* Check other sub-arrays are compatible */
- if (elem_ndims != this_ndims ||
- memcmp(elem_dims, ARR_DIMS(array),
- elem_ndims * sizeof(int)) != 0 ||
- memcmp(elem_lbs, ARR_LBOUND(array),
- elem_ndims * sizeof(int)) != 0)
- ereport(ERROR,
- (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
- errmsg("multidimensional arrays must have array "
- "expressions with matching dimensions")));
- }
-
- subdata[outer_nelems] = ARR_DATA_PTR(array);
- subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
- subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
- nbytes += subbytes[outer_nelems];
- subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
- ARR_DIMS(array));
- nitems += subnitems[outer_nelems];
- havenulls |= ARR_HASNULL(array);
- outer_nelems++;
- }
-
- /*
- * If all items were null or empty arrays, return an empty array;
- * otherwise, if some were and some weren't, raise error. (Note: we
- * must special-case this somehow to avoid trying to generate a 1-D
- * array formed from empty arrays. It's not ideal...)
- */
- if (haveempty)
- {
- if (ndims == 0) /* didn't find any nonempty array */
- return PointerGetDatum(construct_empty_array(element_type));
- ereport(ERROR,
- (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
- errmsg("multidimensional arrays must have array "
- "expressions with matching dimensions")));
- }
-
- /* setup for multi-D array */
- dims[0] = outer_nelems;
- lbs[0] = 1;
- for (i = 1; i < ndims; i++)
- {
- dims[i] = elem_dims[i - 1];
- lbs[i] = elem_lbs[i - 1];
- }
-
- if (havenulls)
- {
- dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
- nbytes += dataoffset;
- }
- else
- {
- dataoffset = 0; /* marker for no null bitmap */
- nbytes += ARR_OVERHEAD_NONULLS(ndims);
- }
-
- result = (ArrayType *) palloc(nbytes);
- SET_VARSIZE(result, nbytes);
- result->ndim = ndims;
- result->dataoffset = dataoffset;
- result->elemtype = element_type;
- memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
- memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
-
- dat = ARR_DATA_PTR(result);
- iitem = 0;
- for (i = 0; i < outer_nelems; i++)
- {
- memcpy(dat, subdata[i], subbytes[i]);
- dat += subbytes[i];
- if (havenulls)
- array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
- subbitmaps[i], 0,
- subnitems[i]);
- iitem += subnitems[i];
- }
- }
-
- return PointerGetDatum(result);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalRow - ROW() expressions
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalRow(RowExprState *rstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- HeapTuple tuple;
- Datum *values;
- bool *isnull;
- int natts;
- ListCell *arg;
- int i;
-
- /* Set default values for result flags: non-null, not a set result */
- *isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
-
- /* Allocate workspace */
- natts = rstate->tupdesc->natts;
- values = (Datum *) palloc0(natts * sizeof(Datum));
- isnull = (bool *) palloc(natts * sizeof(bool));
-
- /* preset to nulls in case rowtype has some later-added columns */
- memset(isnull, true, natts * sizeof(bool));
-
- /* Evaluate field values */
- i = 0;
- foreach(arg, rstate->args)
- {
- ExprState *e = (ExprState *) lfirst(arg);
-
- values[i] = ExecEvalExpr(e, econtext, &isnull[i], NULL);
- i++;
- }
-
- tuple = heap_form_tuple(rstate->tupdesc, values, isnull);
-
- pfree(values);
- pfree(isnull);
-
- return HeapTupleGetDatum(tuple);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalRowCompare - ROW() comparison-op ROW()
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalRowCompare(RowCompareExprState *rstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- bool result;
- RowCompareType rctype = ((RowCompareExpr *) rstate->xprstate.expr)->rctype;
- int32 cmpresult = 0;
- ListCell *l;
- ListCell *r;
- int i;
-
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = true; /* until we get a result */
-
- i = 0;
- forboth(l, rstate->largs, r, rstate->rargs)
- {
- ExprState *le = (ExprState *) lfirst(l);
- ExprState *re = (ExprState *) lfirst(r);
- FunctionCallInfoData locfcinfo;
-
- InitFunctionCallInfoData(locfcinfo, &(rstate->funcs[i]), 2,
- rstate->collations[i],
- NULL, NULL);
- locfcinfo.arg[0] = ExecEvalExpr(le, econtext,
- &locfcinfo.argnull[0], NULL);
- locfcinfo.arg[1] = ExecEvalExpr(re, econtext,
- &locfcinfo.argnull[1], NULL);
- if (rstate->funcs[i].fn_strict &&
- (locfcinfo.argnull[0] || locfcinfo.argnull[1]))
- return (Datum) 0; /* force NULL result */
- locfcinfo.isnull = false;
- cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
- if (locfcinfo.isnull)
- return (Datum) 0; /* force NULL result */
- if (cmpresult != 0)
- break; /* no need to compare remaining columns */
- i++;
- }
-
- switch (rctype)
- {
- /* EQ and NE cases aren't allowed here */
- case ROWCOMPARE_LT:
- result = (cmpresult < 0);
- break;
- case ROWCOMPARE_LE:
- result = (cmpresult <= 0);
- break;
- case ROWCOMPARE_GE:
- result = (cmpresult >= 0);
- break;
- case ROWCOMPARE_GT:
- result = (cmpresult > 0);
- break;
- default:
- elog(ERROR, "unrecognized RowCompareType: %d", (int) rctype);
- result = 0; /* keep compiler quiet */
- break;
- }
-
- *isNull = false;
- return BoolGetDatum(result);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalCoalesce
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ListCell *arg;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /* Simply loop through until something NOT NULL is found */
- foreach(arg, coalesceExpr->args)
- {
- ExprState *e = (ExprState *) lfirst(arg);
- Datum value;
-
- value = ExecEvalExpr(e, econtext, isNull, NULL);
- if (!*isNull)
- return value;
- }
-
- /* Else return NULL */
- *isNull = true;
- return (Datum) 0;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalMinMax
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Datum result = (Datum) 0;
- MinMaxExpr *minmax = (MinMaxExpr *) minmaxExpr->xprstate.expr;
- Oid collation = minmax->inputcollid;
- MinMaxOp op = minmax->op;
- FunctionCallInfoData locfcinfo;
- ListCell *arg;
-
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = true; /* until we get a result */
-
- InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2,
- collation, NULL, NULL);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
-
- foreach(arg, minmaxExpr->args)
- {
- ExprState *e = (ExprState *) lfirst(arg);
- Datum value;
- bool valueIsNull;
- int32 cmpresult;
-
- value = ExecEvalExpr(e, econtext, &valueIsNull, NULL);
- if (valueIsNull)
- continue; /* ignore NULL inputs */
-
- if (*isNull)
- {
- /* first nonnull input, adopt value */
- result = value;
- *isNull = false;
- }
- else
- {
- /* apply comparison function */
- locfcinfo.arg[0] = result;
- locfcinfo.arg[1] = value;
- locfcinfo.isnull = false;
- cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
- if (locfcinfo.isnull) /* probably should not happen */
- continue;
- if (cmpresult > 0 && op == IS_LEAST)
- result = value;
- else if (cmpresult < 0 && op == IS_GREATEST)
- result = value;
- }
- }
-
- return result;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalXml
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- XmlExpr *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
- Datum value;
- bool isnull;
- ListCell *arg;
- ListCell *narg;
-
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = true; /* until we get a result */
-
- switch (xexpr->op)
- {
- case IS_XMLCONCAT:
- {
- List *values = NIL;
-
- foreach(arg, xmlExpr->args)
- {
- ExprState *e = (ExprState *) lfirst(arg);
-
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (!isnull)
- values = lappend(values, DatumGetPointer(value));
- }
-
- if (list_length(values) > 0)
- {
- *isNull = false;
- return PointerGetDatum(xmlconcat(values));
- }
- else
- return (Datum) 0;
- }
- break;
-
- case IS_XMLFOREST:
- {
- StringInfoData buf;
-
- initStringInfo(&buf);
- forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
- {
- ExprState *e = (ExprState *) lfirst(arg);
- char *argname = strVal(lfirst(narg));
-
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (!isnull)
- {
- appendStringInfo(&buf, "<%s>%s</%s>",
- argname,
- map_sql_value_to_xml_value(value, exprType((Node *) e->expr), true),
- argname);
- *isNull = false;
- }
- }
-
- if (*isNull)
- {
- pfree(buf.data);
- return (Datum) 0;
- }
- else
- {
- text *result;
-
- result = cstring_to_text_with_len(buf.data, buf.len);
- pfree(buf.data);
-
- return PointerGetDatum(result);
- }
- }
- break;
-
- case IS_XMLELEMENT:
- *isNull = false;
- return PointerGetDatum(xmlelement(xmlExpr, econtext));
- break;
-
- case IS_XMLPARSE:
- {
- ExprState *e;
- text *data;
- bool preserve_whitespace;
-
- /* arguments are known to be text, bool */
- Assert(list_length(xmlExpr->args) == 2);
-
- e = (ExprState *) linitial(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull)
- return (Datum) 0;
- data = DatumGetTextP(value);
-
- e = (ExprState *) lsecond(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull) /* probably can't happen */
- return (Datum) 0;
- preserve_whitespace = DatumGetBool(value);
-
- *isNull = false;
-
- return PointerGetDatum(xmlparse(data,
- xexpr->xmloption,
- preserve_whitespace));
- }
- break;
-
- case IS_XMLPI:
- {
- ExprState *e;
- text *arg;
-
- /* optional argument is known to be text */
- Assert(list_length(xmlExpr->args) <= 1);
-
- if (xmlExpr->args)
- {
- e = (ExprState *) linitial(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull)
- arg = NULL;
- else
- arg = DatumGetTextP(value);
- }
- else
- {
- arg = NULL;
- isnull = false;
- }
-
- return PointerGetDatum(xmlpi(xexpr->name, arg, isnull, isNull));
- }
- break;
-
- case IS_XMLROOT:
- {
- ExprState *e;
- xmltype *data;
- text *version;
- int standalone;
-
- /* arguments are known to be xml, text, int */
- Assert(list_length(xmlExpr->args) == 3);
-
- e = (ExprState *) linitial(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull)
- return (Datum) 0;
- data = DatumGetXmlP(value);
-
- e = (ExprState *) lsecond(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull)
- version = NULL;
- else
- version = DatumGetTextP(value);
-
- e = (ExprState *) lthird(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- standalone = DatumGetInt32(value);
-
- *isNull = false;
-
- return PointerGetDatum(xmlroot(data,
- version,
- standalone));
- }
- break;
-
- case IS_XMLSERIALIZE:
- {
- ExprState *e;
-
- /* argument type is known to be xml */
- Assert(list_length(xmlExpr->args) == 1);
-
- e = (ExprState *) linitial(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull)
- return (Datum) 0;
-
- *isNull = false;
-
- return PointerGetDatum(xmltotext_with_xmloption(DatumGetXmlP(value), xexpr->xmloption));
- }
- break;
-
- case IS_DOCUMENT:
- {
- ExprState *e;
-
- /* optional argument is known to be xml */
- Assert(list_length(xmlExpr->args) == 1);
-
- e = (ExprState *) linitial(xmlExpr->args);
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (isnull)
- return (Datum) 0;
- else
- {
- *isNull = false;
- return BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
- }
- }
- break;
- }
-
- elog(ERROR, "unrecognized XML operation");
- return (Datum) 0;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalNullIf
- *
- * Note that this is *always* derived from the equals operator,
- * but since we need special processing of the arguments
- * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalNullIf(FuncExprState *nullIfExpr,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Datum result;
- FunctionCallInfo fcinfo;
- ExprDoneCond argDone;
-
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * Initialize function cache if first time through
- */
- if (nullIfExpr->func.fn_oid == InvalidOid)
- {
- NullIfExpr *op = (NullIfExpr *) nullIfExpr->xprstate.expr;
-
- init_fcache(op->opfuncid, op->inputcollid, nullIfExpr,
- econtext->ecxt_per_query_memory, true);
- Assert(!nullIfExpr->func.fn_retset);
- }
-
- /*
- * Evaluate arguments
- */
- fcinfo = &nullIfExpr->fcinfo_data;
- argDone = ExecEvalFuncArgs(fcinfo, nullIfExpr->args, econtext);
- if (argDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("NULLIF does not support set arguments")));
- Assert(fcinfo->nargs == 2);
-
- /* if either argument is NULL they can't be equal */
- if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
- {
- fcinfo->isnull = false;
- result = FunctionCallInvoke(fcinfo);
- /* if the arguments are equal return null */
- if (!fcinfo->isnull && DatumGetBool(result))
- {
- *isNull = true;
- return (Datum) 0;
- }
- }
-
- /* else return first argument */
- *isNull = fcinfo->argnull[0];
- return fcinfo->arg[0];
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalNullTest
- *
- * Evaluate a NullTest node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalNullTest(NullTestState *nstate,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- NullTest *ntest = (NullTest *) nstate->xprstate.expr;
- Datum result;
-
- result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone);
-
- if (isDone && *isDone == ExprEndResult)
- return result; /* nothing to check */
-
- if (ntest->argisrow && !(*isNull))
- {
- /*
- * The SQL standard defines IS [NOT] NULL for a non-null rowtype
- * argument as:
- *
- * "R IS NULL" is true if every field is the null value.
- *
- * "R IS NOT NULL" is true if no field is the null value.
- *
- * This definition is (apparently intentionally) not recursive; so our
- * tests on the fields are primitive attisnull tests, not recursive
- * checks to see if they are all-nulls or no-nulls rowtypes.
- *
- * The standard does not consider the possibility of zero-field rows,
- * but here we consider them to vacuously satisfy both predicates.
- */
- HeapTupleHeader tuple;
- Oid tupType;
- int32 tupTypmod;
- TupleDesc tupDesc;
- HeapTupleData tmptup;
- int att;
-
- tuple = DatumGetHeapTupleHeader(result);
-
- tupType = HeapTupleHeaderGetTypeId(tuple);
- tupTypmod = HeapTupleHeaderGetTypMod(tuple);
-
- /* Lookup tupdesc if first time through or if type changes */
- tupDesc = get_cached_rowtype(tupType, tupTypmod,
- &nstate->argdesc, econtext);
-
- /*
- * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
- */
- tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
- tmptup.t_data = tuple;
-
- for (att = 1; att <= tupDesc->natts; att++)
- {
- /* ignore dropped columns */
- if (tupDesc->attrs[att - 1]->attisdropped)
- continue;
- if (heap_attisnull(&tmptup, att))
- {
- /* null field disproves IS NOT NULL */
- if (ntest->nulltesttype == IS_NOT_NULL)
- return BoolGetDatum(false);
- }
- else
- {
- /* non-null field disproves IS NULL */
- if (ntest->nulltesttype == IS_NULL)
- return BoolGetDatum(false);
- }
- }
-
- return BoolGetDatum(true);
- }
- else
- {
- /* Simple scalar-argument case, or a null rowtype datum */
- switch (ntest->nulltesttype)
- {
- case IS_NULL:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(true);
- }
- else
- return BoolGetDatum(false);
- case IS_NOT_NULL:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(false);
- }
- else
- return BoolGetDatum(true);
- default:
- elog(ERROR, "unrecognized nulltesttype: %d",
- (int) ntest->nulltesttype);
- return (Datum) 0; /* keep compiler quiet */
- }
- }
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalBooleanTest
- *
- * Evaluate a BooleanTest node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalBooleanTest(GenericExprState *bstate,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr;
- Datum result;
-
- result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone);
-
- if (isDone && *isDone == ExprEndResult)
- return result; /* nothing to check */
-
- switch (btest->booltesttype)
- {
- case IS_TRUE:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(false);
- }
- else if (DatumGetBool(result))
- return BoolGetDatum(true);
- else
- return BoolGetDatum(false);
- case IS_NOT_TRUE:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(true);
- }
- else if (DatumGetBool(result))
- return BoolGetDatum(false);
- else
- return BoolGetDatum(true);
- case IS_FALSE:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(false);
- }
- else if (DatumGetBool(result))
- return BoolGetDatum(false);
- else
- return BoolGetDatum(true);
- case IS_NOT_FALSE:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(true);
- }
- else if (DatumGetBool(result))
- return BoolGetDatum(true);
- else
- return BoolGetDatum(false);
- case IS_UNKNOWN:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(true);
- }
- else
- return BoolGetDatum(false);
- case IS_NOT_UNKNOWN:
- if (*isNull)
- {
- *isNull = false;
- return BoolGetDatum(false);
- }
- else
- return BoolGetDatum(true);
- default:
- elog(ERROR, "unrecognized booltesttype: %d",
- (int) btest->booltesttype);
- return (Datum) 0; /* keep compiler quiet */
- }
-}
-
-/*
- * ExecEvalCoerceToDomain
- *
- * Test the provided data against the domain constraint(s). If the data
- * passes the constraint specifications, pass it through (return the
- * datum) otherwise throw an error.
- */
-static Datum
-ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- CoerceToDomain *ctest = (CoerceToDomain *) cstate->xprstate.expr;
- Datum result;
- ListCell *l;
-
- result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
-
- if (isDone && *isDone == ExprEndResult)
- return result; /* nothing to check */
-
- /* Make sure we have up-to-date constraints */
- UpdateDomainConstraintRef(cstate->constraint_ref);
-
- foreach(l, cstate->constraint_ref->constraints)
- {
- DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
-
- switch (con->constrainttype)
- {
- case DOM_CONSTRAINT_NOTNULL:
- if (*isNull)
- ereport(ERROR,
- (errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("domain %s does not allow null values",
- format_type_be(ctest->resulttype)),
- errdatatype(ctest->resulttype)));
- break;
- case DOM_CONSTRAINT_CHECK:
- {
- Datum conResult;
- bool conIsNull;
- Datum save_datum;
- bool save_isNull;
-
- /*
- * Set up value to be returned by CoerceToDomainValue
- * nodes. We must save and restore prior setting of
- * econtext's domainValue fields, in case this node is
- * itself within a check expression for another domain.
- */
- save_datum = econtext->domainValue_datum;
- save_isNull = econtext->domainValue_isNull;
-
- econtext->domainValue_datum = result;
- econtext->domainValue_isNull = *isNull;
-
- conResult = ExecEvalExpr(con->check_expr,
- econtext, &conIsNull, NULL);
-
- if (!conIsNull &&
- !DatumGetBool(conResult))
- ereport(ERROR,
- (errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("value for domain %s violates check constraint \"%s\"",
- format_type_be(ctest->resulttype),
- con->name),
- errdomainconstraint(ctest->resulttype,
- con->name)));
- econtext->domainValue_datum = save_datum;
- econtext->domainValue_isNull = save_isNull;
-
- break;
- }
- default:
- elog(ERROR, "unrecognized constraint type: %d",
- (int) con->constrainttype);
- break;
- }
- }
-
- /* If all has gone well (constraints did not fail) return the datum */
- return result;
-}
-
-/*
- * ExecEvalCoerceToDomainValue
- *
- * Return the value stored by CoerceToDomain.
- */
-static Datum
-ExecEvalCoerceToDomainValue(ExprState *exprstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- if (isDone)
- *isDone = ExprSingleResult;
- *isNull = econtext->domainValue_isNull;
- return econtext->domainValue_datum;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalFieldSelect
- *
- * Evaluate a FieldSelect node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalFieldSelect(FieldSelectState *fstate,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr;
- AttrNumber fieldnum = fselect->fieldnum;
- Datum result;
- Datum tupDatum;
- HeapTupleHeader tuple;
- Oid tupType;
- int32 tupTypmod;
- TupleDesc tupDesc;
- Form_pg_attribute attr;
- HeapTupleData tmptup;
-
- tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
-
- /* this test covers the isDone exception too: */
- if (*isNull)
- return tupDatum;
-
- tuple = DatumGetHeapTupleHeader(tupDatum);
-
- tupType = HeapTupleHeaderGetTypeId(tuple);
- tupTypmod = HeapTupleHeaderGetTypMod(tuple);
-
- /* Lookup tupdesc if first time through or if type changes */
- tupDesc = get_cached_rowtype(tupType, tupTypmod,
- &fstate->argdesc, econtext);
-
- /*
- * Find field's attr record. Note we don't support system columns here: a
- * datum tuple doesn't have valid values for most of the interesting
- * system columns anyway.
- */
- if (fieldnum <= 0) /* should never happen */
- elog(ERROR, "unsupported reference to system column %d in FieldSelect",
- fieldnum);
- if (fieldnum > tupDesc->natts) /* should never happen */
- elog(ERROR, "attribute number %d exceeds number of columns %d",
- fieldnum, tupDesc->natts);
- attr = tupDesc->attrs[fieldnum - 1];
-
- /* Check for dropped column, and force a NULL result if so */
- if (attr->attisdropped)
- {
- *isNull = true;
- return (Datum) 0;
- }
-
- /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
- /* As in ExecEvalScalarVar, we should but can't check typmod */
- if (fselect->resulttype != attr->atttypid)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("attribute %d has wrong type", fieldnum),
- errdetail("Table has type %s, but query expects %s.",
- format_type_be(attr->atttypid),
- format_type_be(fselect->resulttype))));
-
- /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
- tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
- tmptup.t_data = tuple;
-
- result = heap_getattr(&tmptup,
- fieldnum,
- tupDesc,
- isNull);
- return result;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalFieldStore
- *
- * Evaluate a FieldStore node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalFieldStore(FieldStoreState *fstate,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- FieldStore *fstore = (FieldStore *) fstate->xprstate.expr;
- HeapTuple tuple;
- Datum tupDatum;
- TupleDesc tupDesc;
- Datum *values;
- bool *isnull;
- Datum save_datum;
- bool save_isNull;
- ListCell *l1,
- *l2;
-
- tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
-
- if (isDone && *isDone == ExprEndResult)
- return tupDatum;
-
- /* Lookup tupdesc if first time through or after rescan */
- tupDesc = get_cached_rowtype(fstore->resulttype, -1,
- &fstate->argdesc, econtext);
-
- /* Allocate workspace */
- values = (Datum *) palloc(tupDesc->natts * sizeof(Datum));
- isnull = (bool *) palloc(tupDesc->natts * sizeof(bool));
-
- if (!*isNull)
- {
- /*
- * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
- * set all the fields in the struct just in case.
- */
- HeapTupleHeader tuphdr;
- HeapTupleData tmptup;
-
- tuphdr = DatumGetHeapTupleHeader(tupDatum);
- tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
- ItemPointerSetInvalid(&(tmptup.t_self));
- tmptup.t_tableOid = InvalidOid;
-#ifdef PGXC
- tmptup.t_xc_node_id = 0;
-#endif
- tmptup.t_data = tuphdr;
-
- heap_deform_tuple(&tmptup, tupDesc, values, isnull);
- }
- else
- {
- /* Convert null input tuple into an all-nulls row */
- memset(isnull, true, tupDesc->natts * sizeof(bool));
- }
-
- /* Result is never null */
- *isNull = false;
-
- save_datum = econtext->caseValue_datum;
- save_isNull = econtext->caseValue_isNull;
-
- forboth(l1, fstate->newvals, l2, fstore->fieldnums)
- {
- ExprState *newval = (ExprState *) lfirst(l1);
- AttrNumber fieldnum = lfirst_int(l2);
-
- Assert(fieldnum > 0 && fieldnum <= tupDesc->natts);
-
- /*
- * Use the CaseTestExpr mechanism to pass down the old value of the
- * field being replaced; this is needed in case the newval is itself a
- * FieldStore or ArrayRef that has to obtain and modify the old value.
- * It's safe to reuse the CASE mechanism because there cannot be a
- * CASE between here and where the value would be needed, and a field
- * assignment can't be within a CASE either. (So saving and restoring
- * the caseValue is just paranoia, but let's do it anyway.)
- */
- econtext->caseValue_datum = values[fieldnum - 1];
- econtext->caseValue_isNull = isnull[fieldnum - 1];
-
- values[fieldnum - 1] = ExecEvalExpr(newval,
- econtext,
- &isnull[fieldnum - 1],
- NULL);
- }
-
- econtext->caseValue_datum = save_datum;
- econtext->caseValue_isNull = save_isNull;
-
- tuple = heap_form_tuple(tupDesc, values, isnull);
-
- pfree(values);
- pfree(isnull);
-
- return HeapTupleGetDatum(tuple);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalRelabelType
- *
- * Evaluate a RelabelType node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalRelabelType(GenericExprState *exprstate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalCoerceViaIO
- *
- * Evaluate a CoerceViaIO node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- Datum result;
- Datum inputval;
- char *string;
-
- inputval = ExecEvalExpr(iostate->arg, econtext, isNull, isDone);
-
- if (isDone && *isDone == ExprEndResult)
- return inputval; /* nothing to do */
-
- if (*isNull)
- string = NULL; /* output functions are not called on nulls */
- else
- string = OutputFunctionCall(&iostate->outfunc, inputval);
-
- result = InputFunctionCall(&iostate->infunc,
- string,
- iostate->intypioparam,
- -1);
-
- /* The input function cannot change the null/not-null status */
- return result;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalArrayCoerceExpr
- *
- * Evaluate an ArrayCoerceExpr node.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
- ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) astate->xprstate.expr;
- Datum result;
- FunctionCallInfoData locfcinfo;
-
- result = ExecEvalExpr(astate->arg, econtext, isNull, isDone);
-
- if (isDone && *isDone == ExprEndResult)
- return result; /* nothing to do */
- if (*isNull)
- return result; /* nothing to do */
-
- /*
- * If it's binary-compatible, modify the element type in the array header,
- * but otherwise leave the array as we received it.
- */
- if (!OidIsValid(acoerce->elemfuncid))
- {
- /* Detoast input array if necessary, and copy in any case */
- ArrayType *array = DatumGetArrayTypePCopy(result);
-
- ARR_ELEMTYPE(array) = astate->resultelemtype;
- PG_RETURN_ARRAYTYPE_P(array);
- }
-
- /* Initialize function cache if first time through */
- if (astate->elemfunc.fn_oid == InvalidOid)
- {
- AclResult aclresult;
-
- /* Check permission to call function */
- aclresult = pg_proc_aclcheck(acoerce->elemfuncid, GetUserId(),
- ACL_EXECUTE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_PROC,
- get_func_name(acoerce->elemfuncid));
- InvokeFunctionExecuteHook(acoerce->elemfuncid);
-
- /* Set up the primary fmgr lookup information */
- fmgr_info_cxt(acoerce->elemfuncid, &(astate->elemfunc),
- econtext->ecxt_per_query_memory);
- fmgr_info_set_expr((Node *) acoerce, &(astate->elemfunc));
- }
-
- /*
- * Use array_map to apply the function to each array element.
- *
- * We pass on the desttypmod and isExplicit flags whether or not the
- * function wants them.
- *
- * Note: coercion functions are assumed to not use collation.
- */
- InitFunctionCallInfoData(locfcinfo, &(astate->elemfunc), 3,
- InvalidOid, NULL, NULL);
- locfcinfo.arg[0] = result;
- locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod);
- locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.argnull[2] = false;
-
- return array_map(&locfcinfo, astate->resultelemtype, astate->amstate);
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalCurrentOfExpr
- *
- * The planner should convert CURRENT OF into a TidScan qualification, or some
- * other special handling in a ForeignScan node. So we have to be able to do
- * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
- * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
- * table whose FDW doesn't handle it, and complain accordingly.
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
-{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WHERE CURRENT OF is not supported for this table type")));
- return 0; /* keep compiler quiet */
-}
-
-
-/*
- * ExecEvalExprSwitchContext
- *
- * Same as ExecEvalExpr, but get into the right allocation context explicitly.
- */
-Datum
-ExecEvalExprSwitchContext(ExprState *expression,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- Datum retDatum;
- MemoryContext oldContext;
-
- oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
- retDatum = ExecEvalExpr(expression, econtext, isNull, isDone);
- MemoryContextSwitchTo(oldContext);
- return retDatum;
-}
-
-
-/*
- * ExecInitExpr: prepare an expression tree for execution
- *
- * This function builds and returns an ExprState tree paralleling the given
- * Expr node tree. The ExprState tree can then be handed to ExecEvalExpr
- * for execution. Because the Expr tree itself is read-only as far as
- * ExecInitExpr and ExecEvalExpr are concerned, several different executions
- * of the same plan tree can occur concurrently.
- *
- * This must be called in a memory context that will last as long as repeated
- * executions of the expression are needed. Typically the context will be
- * the same as the per-query context of the associated ExprContext.
- *
- * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to the
- * lists of such nodes held by the parent PlanState. Otherwise, we do very
- * little initialization here other than building the state-node tree. Any
- * nontrivial work associated with initializing runtime info for a node should
- * happen during the first actual evaluation of that node. (This policy lets
- * us avoid work if the node is never actually evaluated.)
- *
- * Note: there is no ExecEndExpr function; we assume that any resource
- * cleanup needed will be handled by just releasing the memory context
- * in which the state tree is built. Functions that require additional
- * cleanup work can register a shutdown callback in the ExprContext.
- *
- * 'node' is the root of the expression tree to examine
- * 'parent' is the PlanState node that owns the expression.
- *
- * 'parent' may be NULL if we are preparing an expression that is not
- * associated with a plan tree. (If so, it can't have aggs or subplans.)
- * This case should usually come through ExecPrepareExpr, not directly here.
- */
-ExprState *
-ExecInitExpr(Expr *node, PlanState *parent)
-{
- ExprState *state;
-
- if (node == NULL)
- return NULL;
-
- /* Guard against stack overflow due to overly complex expressions */
- check_stack_depth();
-
- switch (nodeTag(node))
- {
- case T_Var:
- /* varattno == InvalidAttrNumber means it's a whole-row Var */
- if (((Var *) node)->varattno == InvalidAttrNumber)
- {
- WholeRowVarExprState *wstate = makeNode(WholeRowVarExprState);
-
- wstate->parent = parent;
- wstate->wrv_tupdesc = NULL;
- wstate->wrv_junkFilter = NULL;
- state = (ExprState *) wstate;
- state->evalfunc = (ExprStateEvalFunc) ExecEvalWholeRowVar;
- }
- else
- {
- state = (ExprState *) makeNode(ExprState);
- state->evalfunc = ExecEvalScalarVar;
- }
- break;
- case T_Const:
- state = (ExprState *) makeNode(ExprState);
- state->evalfunc = ExecEvalConst;
- break;
- case T_Param:
- state = (ExprState *) makeNode(ExprState);
- switch (((Param *) node)->paramkind)
- {
- case PARAM_EXEC:
- state->evalfunc = ExecEvalParamExec;
- break;
- case PARAM_EXTERN:
- state->evalfunc = ExecEvalParamExtern;
- break;
- default:
- elog(ERROR, "unrecognized paramkind: %d",
- (int) ((Param *) node)->paramkind);
- break;
- }
- break;
- case T_CoerceToDomainValue:
- state = (ExprState *) makeNode(ExprState);
- state->evalfunc = ExecEvalCoerceToDomainValue;
- break;
- case T_CaseTestExpr:
- state = (ExprState *) makeNode(ExprState);
- state->evalfunc = ExecEvalCaseTestExpr;
- break;
- case T_Aggref:
- {
- AggrefExprState *astate = makeNode(AggrefExprState);
-
- astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAggref;
- if (parent && IsA(parent, AggState))
- {
- AggState *aggstate = (AggState *) parent;
-
- aggstate->aggs = lcons(astate, aggstate->aggs);
- aggstate->numaggs++;
- }
- else
- {
- /* planner messed up */
- elog(ERROR, "Aggref found in non-Agg plan node");
- }
- state = (ExprState *) astate;
- }
- break;
- case T_GroupingFunc:
- {
- GroupingFunc *grp_node = (GroupingFunc *) node;
- GroupingFuncExprState *grp_state = makeNode(GroupingFuncExprState);
- Agg *agg = NULL;
-
- if (!parent || !IsA(parent, AggState) ||!IsA(parent->plan, Agg))
- elog(ERROR, "parent of GROUPING is not Agg node");
-
- grp_state->aggstate = (AggState *) parent;
-
- agg = (Agg *) (parent->plan);
-
- if (agg->groupingSets)
- grp_state->clauses = grp_node->cols;
- else
- grp_state->clauses = NIL;
-
- state = (ExprState *) grp_state;
- state->evalfunc = (ExprStateEvalFunc) ExecEvalGroupingFuncExpr;
- }
- break;
- case T_WindowFunc:
- {
- WindowFunc *wfunc = (WindowFunc *) node;
- WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
-
- wfstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalWindowFunc;
- if (parent && IsA(parent, WindowAggState))
- {
- WindowAggState *winstate = (WindowAggState *) parent;
- int nfuncs;
-
- winstate->funcs = lcons(wfstate, winstate->funcs);
- nfuncs = ++winstate->numfuncs;
- if (wfunc->winagg)
- winstate->numaggs++;
-
- wfstate->args = (List *) ExecInitExpr((Expr *) wfunc->args,
- parent);
- wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
- parent);
-
- /*
- * Complain if the windowfunc's arguments contain any
- * windowfuncs; nested window functions are semantically
- * nonsensical. (This should have been caught earlier,
- * but we defend against it here anyway.)
- */
- if (nfuncs != winstate->numfuncs)
- ereport(ERROR,
- (errcode(ERRCODE_WINDOWING_ERROR),
- errmsg("window function calls cannot be nested")));
- }
- else
- {
- /* planner messed up */
- elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
- }
- state = (ExprState *) wfstate;
- }
- break;
- case T_ArrayRef:
- {
- ArrayRef *aref = (ArrayRef *) node;
- ArrayRefExprState *astate = makeNode(ArrayRefExprState);
-
- astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayRef;
- astate->refupperindexpr = (List *)
- ExecInitExpr((Expr *) aref->refupperindexpr, parent);
- astate->reflowerindexpr = (List *)
- ExecInitExpr((Expr *) aref->reflowerindexpr, parent);
- astate->refexpr = ExecInitExpr(aref->refexpr, parent);
- astate->refassgnexpr = ExecInitExpr(aref->refassgnexpr,
- parent);
- /* do one-time catalog lookups for type info */
- astate->refattrlength = get_typlen(aref->refarraytype);
- get_typlenbyvalalign(aref->refelemtype,
- &astate->refelemlength,
- &astate->refelembyval,
- &astate->refelemalign);
- state = (ExprState *) astate;
- }
- break;
- case T_FuncExpr:
- {
- FuncExpr *funcexpr = (FuncExpr *) node;
- FuncExprState *fstate = makeNode(FuncExprState);
-
- fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFunc;
- fstate->args = (List *)
- ExecInitExpr((Expr *) funcexpr->args, parent);
- fstate->func.fn_oid = InvalidOid; /* not initialized */
- state = (ExprState *) fstate;
- }
- break;
- case T_OpExpr:
- {
- OpExpr *opexpr = (OpExpr *) node;
- FuncExprState *fstate = makeNode(FuncExprState);
-
- fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOper;
- fstate->args = (List *)
- ExecInitExpr((Expr *) opexpr->args, parent);
- fstate->func.fn_oid = InvalidOid; /* not initialized */
- state = (ExprState *) fstate;
- }
- break;
- case T_DistinctExpr:
- {
- DistinctExpr *distinctexpr = (DistinctExpr *) node;
- FuncExprState *fstate = makeNode(FuncExprState);
-
- fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalDistinct;
- fstate->args = (List *)
- ExecInitExpr((Expr *) distinctexpr->args, parent);
- fstate->func.fn_oid = InvalidOid; /* not initialized */
- state = (ExprState *) fstate;
- }
- break;
- case T_NullIfExpr:
- {
- NullIfExpr *nullifexpr = (NullIfExpr *) node;
- FuncExprState *fstate = makeNode(FuncExprState);
-
- fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullIf;
- fstate->args = (List *)
- ExecInitExpr((Expr *) nullifexpr->args, parent);
- fstate->func.fn_oid = InvalidOid; /* not initialized */
- state = (ExprState *) fstate;
- }
- break;
- case T_ScalarArrayOpExpr:
- {
- ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
- ScalarArrayOpExprState *sstate = makeNode(ScalarArrayOpExprState);
-
- sstate->fxprstate.xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalScalarArrayOp;
- sstate->fxprstate.args = (List *)
- ExecInitExpr((Expr *) opexpr->args, parent);
- sstate->fxprstate.func.fn_oid = InvalidOid; /* not initialized */
- sstate->element_type = InvalidOid; /* ditto */
- state = (ExprState *) sstate;
- }
- break;
- case T_BoolExpr:
- {
- BoolExpr *boolexpr = (BoolExpr *) node;
- BoolExprState *bstate = makeNode(BoolExprState);
-
- switch (boolexpr->boolop)
- {
- case AND_EXPR:
- bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAnd;
- break;
- case OR_EXPR:
- bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOr;
- break;
- case NOT_EXPR:
- bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNot;
- break;
- default:
- elog(ERROR, "unrecognized boolop: %d",
- (int) boolexpr->boolop);
- break;
- }
- bstate->args = (List *)
- ExecInitExpr((Expr *) boolexpr->args, parent);
- state = (ExprState *) bstate;
- }
- break;
- case T_SubPlan:
- {
- SubPlan *subplan = (SubPlan *) node;
- SubPlanState *sstate;
-
- if (!parent)
- elog(ERROR, "SubPlan found with no parent plan");
-
- sstate = ExecInitSubPlan(subplan, parent);
-
- /* Add SubPlanState nodes to parent->subPlan */
- parent->subPlan = lappend(parent->subPlan, sstate);
-
- state = (ExprState *) sstate;
- }
- break;
- case T_AlternativeSubPlan:
- {
- AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
- AlternativeSubPlanState *asstate;
-
- if (!parent)
- elog(ERROR, "AlternativeSubPlan found with no parent plan");
-
- asstate = ExecInitAlternativeSubPlan(asplan, parent);
-
- state = (ExprState *) asstate;
- }
- break;
- case T_FieldSelect:
- {
- FieldSelect *fselect = (FieldSelect *) node;
- FieldSelectState *fstate = makeNode(FieldSelectState);
-
- fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldSelect;
- fstate->arg = ExecInitExpr(fselect->arg, parent);
- fstate->argdesc = NULL;
- state = (ExprState *) fstate;
- }
- break;
- case T_FieldStore:
- {
- FieldStore *fstore = (FieldStore *) node;
- FieldStoreState *fstate = makeNode(FieldStoreState);
-
- fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldStore;
- fstate->arg = ExecInitExpr(fstore->arg, parent);
- fstate->newvals = (List *) ExecInitExpr((Expr *) fstore->newvals, parent);
- fstate->argdesc = NULL;
- state = (ExprState *) fstate;
- }
- break;
- case T_RelabelType:
- {
- RelabelType *relabel = (RelabelType *) node;
- GenericExprState *gstate = makeNode(GenericExprState);
-
- gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRelabelType;
- gstate->arg = ExecInitExpr(relabel->arg, parent);
- state = (ExprState *) gstate;
- }
- break;
- case T_CoerceViaIO:
- {
- CoerceViaIO *iocoerce = (CoerceViaIO *) node;
- CoerceViaIOState *iostate = makeNode(CoerceViaIOState);
- Oid iofunc;
- bool typisvarlena;
-
- iostate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceViaIO;
- iostate->arg = ExecInitExpr(iocoerce->arg, parent);
- /* lookup the result type's input function */
- getTypeInputInfo(iocoerce->resulttype, &iofunc,
- &iostate->intypioparam);
- fmgr_info(iofunc, &iostate->infunc);
- /* lookup the input type's output function */
- getTypeOutputInfo(exprType((Node *) iocoerce->arg),
- &iofunc, &typisvarlena);
- fmgr_info(iofunc, &iostate->outfunc);
- state = (ExprState *) iostate;
- }
- break;
- case T_ArrayCoerceExpr:
- {
- ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
- ArrayCoerceExprState *astate = makeNode(ArrayCoerceExprState);
-
- astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayCoerceExpr;
- astate->arg = ExecInitExpr(acoerce->arg, parent);
- astate->resultelemtype = get_element_type(acoerce->resulttype);
- if (astate->resultelemtype == InvalidOid)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("target type is not an array")));
- /* Arrays over domains aren't supported yet */
- Assert(getBaseType(astate->resultelemtype) ==
- astate->resultelemtype);
- astate->elemfunc.fn_oid = InvalidOid; /* not initialized */
- astate->amstate = (ArrayMapState *) palloc0(sizeof(ArrayMapState));
- state = (ExprState *) astate;
- }
- break;
- case T_ConvertRowtypeExpr:
- {
- ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
- ConvertRowtypeExprState *cstate = makeNode(ConvertRowtypeExprState);
-
- cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalConvertRowtype;
- cstate->arg = ExecInitExpr(convert->arg, parent);
- state = (ExprState *) cstate;
- }
- break;
- case T_CaseExpr:
- {
- CaseExpr *caseexpr = (CaseExpr *) node;
- CaseExprState *cstate = makeNode(CaseExprState);
- List *outlist = NIL;
- ListCell *l;
-
- cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCase;
- cstate->arg = ExecInitExpr(caseexpr->arg, parent);
- foreach(l, caseexpr->args)
- {
- CaseWhen *when = (CaseWhen *) lfirst(l);
- CaseWhenState *wstate = makeNode(CaseWhenState);
-
- Assert(IsA(when, CaseWhen));
- wstate->xprstate.evalfunc = NULL; /* not used */
- wstate->xprstate.expr = (Expr *) when;
- wstate->expr = ExecInitExpr(when->expr, parent);
- wstate->result = ExecInitExpr(when->result, parent);
- outlist = lappend(outlist, wstate);
- }
- cstate->args = outlist;
- cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
- state = (ExprState *) cstate;
- }
- break;
- case T_ArrayExpr:
- {
- ArrayExpr *arrayexpr = (ArrayExpr *) node;
- ArrayExprState *astate = makeNode(ArrayExprState);
- List *outlist = NIL;
- ListCell *l;
-
- astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArray;
- foreach(l, arrayexpr->elements)
- {
- Expr *e = (Expr *) lfirst(l);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- astate->elements = outlist;
- /* do one-time catalog lookup for type info */
- get_typlenbyvalalign(arrayexpr->element_typeid,
- &astate->elemlength,
- &astate->elembyval,
- &astate->elemalign);
- state = (ExprState *) astate;
- }
- break;
- case T_RowExpr:
- {
- RowExpr *rowexpr = (RowExpr *) node;
- RowExprState *rstate = makeNode(RowExprState);
- Form_pg_attribute *attrs;
- List *outlist = NIL;
- ListCell *l;
- int i;
-
- rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRow;
- /* Build tupdesc to describe result tuples */
- if (rowexpr->row_typeid == RECORDOID)
- {
- /* generic record, use types of given expressions */
- rstate->tupdesc = ExecTypeFromExprList(rowexpr->args);
- }
- else
- {
- /* it's been cast to a named type, use that */
- rstate->tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
- }
- /* In either case, adopt RowExpr's column aliases */
- ExecTypeSetColNames(rstate->tupdesc, rowexpr->colnames);
- /* Bless the tupdesc in case it's now of type RECORD */
- BlessTupleDesc(rstate->tupdesc);
- /* Set up evaluation, skipping any deleted columns */
- Assert(list_length(rowexpr->args) <= rstate->tupdesc->natts);
- attrs = rstate->tupdesc->attrs;
- i = 0;
- foreach(l, rowexpr->args)
- {
- Expr *e = (Expr *) lfirst(l);
- ExprState *estate;
-
- if (!attrs[i]->attisdropped)
- {
- /*
- * Guard against ALTER COLUMN TYPE on rowtype since
- * the RowExpr was created. XXX should we check
- * typmod too? Not sure we can be sure it'll be the
- * same.
- */
- if (exprType((Node *) e) != attrs[i]->atttypid)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("ROW() column has type %s instead of type %s",
- format_type_be(exprType((Node *) e)),
- format_type_be(attrs[i]->atttypid))));
- }
- else
- {
- /*
- * Ignore original expression and insert a NULL. We
- * don't really care what type of NULL it is, so
- * always make an int4 NULL.
- */
- e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
- }
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- i++;
- }
- rstate->args = outlist;
- state = (ExprState *) rstate;
- }
- break;
- case T_RowCompareExpr:
- {
- RowCompareExpr *rcexpr = (RowCompareExpr *) node;
- RowCompareExprState *rstate = makeNode(RowCompareExprState);
- int nopers = list_length(rcexpr->opnos);
- List *outlist;
- ListCell *l;
- ListCell *l2;
- ListCell *l3;
- int i;
-
- rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRowCompare;
- Assert(list_length(rcexpr->largs) == nopers);
- outlist = NIL;
- foreach(l, rcexpr->largs)
- {
- Expr *e = (Expr *) lfirst(l);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- rstate->largs = outlist;
- Assert(list_length(rcexpr->rargs) == nopers);
- outlist = NIL;
- foreach(l, rcexpr->rargs)
- {
- Expr *e = (Expr *) lfirst(l);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- rstate->rargs = outlist;
- Assert(list_length(rcexpr->opfamilies) == nopers);
- rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
- rstate->collations = (Oid *) palloc(nopers * sizeof(Oid));
- i = 0;
- forthree(l, rcexpr->opnos, l2, rcexpr->opfamilies, l3, rcexpr->inputcollids)
- {
- Oid opno = lfirst_oid(l);
- Oid opfamily = lfirst_oid(l2);
- Oid inputcollid = lfirst_oid(l3);
- int strategy;
- Oid lefttype;
- Oid righttype;
- Oid proc;
-
- get_op_opfamily_properties(opno, opfamily, false,
- &strategy,
- &lefttype,
- &righttype);
- proc = get_opfamily_proc(opfamily,
- lefttype,
- righttype,
- BTORDER_PROC);
-
- /*
- * If we enforced permissions checks on index support
- * functions, we'd need to make a check here. But the
- * index support machinery doesn't do that, and neither
- * does this code.
- */
- fmgr_info(proc, &(rstate->funcs[i]));
- rstate->collations[i] = inputcollid;
- i++;
- }
- state = (ExprState *) rstate;
- }
- break;
- case T_CoalesceExpr:
- {
- CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
- CoalesceExprState *cstate = makeNode(CoalesceExprState);
- List *outlist = NIL;
- ListCell *l;
-
- cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoalesce;
- foreach(l, coalesceexpr->args)
- {
- Expr *e = (Expr *) lfirst(l);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- cstate->args = outlist;
- state = (ExprState *) cstate;
- }
- break;
- case T_MinMaxExpr:
- {
- MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
- MinMaxExprState *mstate = makeNode(MinMaxExprState);
- List *outlist = NIL;
- ListCell *l;
- TypeCacheEntry *typentry;
-
- mstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalMinMax;
- foreach(l, minmaxexpr->args)
- {
- Expr *e = (Expr *) lfirst(l);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- mstate->args = outlist;
- /* Look up the btree comparison function for the datatype */
- typentry = lookup_type_cache(minmaxexpr->minmaxtype,
- TYPECACHE_CMP_PROC);
- if (!OidIsValid(typentry->cmp_proc))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("could not identify a comparison function for type %s",
- format_type_be(minmaxexpr->minmaxtype))));
-
- /*
- * If we enforced permissions checks on index support
- * functions, we'd need to make a check here. But the index
- * support machinery doesn't do that, and neither does this
- * code.
- */
- fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
- state = (ExprState *) mstate;
- }
- break;
- case T_XmlExpr:
- {
- XmlExpr *xexpr = (XmlExpr *) node;
- XmlExprState *xstate = makeNode(XmlExprState);
- List *outlist;
- ListCell *arg;
-
- xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
- outlist = NIL;
- foreach(arg, xexpr->named_args)
- {
- Expr *e = (Expr *) lfirst(arg);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- xstate->named_args = outlist;
-
- outlist = NIL;
- foreach(arg, xexpr->args)
- {
- Expr *e = (Expr *) lfirst(arg);
- ExprState *estate;
-
- estate = ExecInitExpr(e, parent);
- outlist = lappend(outlist, estate);
- }
- xstate->args = outlist;
-
- state = (ExprState *) xstate;
- }
- break;
- case T_NullTest:
- {
- NullTest *ntest = (NullTest *) node;
- NullTestState *nstate = makeNode(NullTestState);
-
- nstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest;
- nstate->arg = ExecInitExpr(ntest->arg, parent);
- nstate->argdesc = NULL;
- state = (ExprState *) nstate;
- }
- break;
- case T_BooleanTest:
- {
- BooleanTest *btest = (BooleanTest *) node;
- GenericExprState *gstate = makeNode(GenericExprState);
-
- gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalBooleanTest;
- gstate->arg = ExecInitExpr(btest->arg, parent);
- state = (ExprState *) gstate;
- }
- break;
- case T_CoerceToDomain:
- {
- CoerceToDomain *ctest = (CoerceToDomain *) node;
- CoerceToDomainState *cstate = makeNode(CoerceToDomainState);
-
- cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceToDomain;
- cstate->arg = ExecInitExpr(ctest->arg, parent);
- /* We spend an extra palloc to reduce header inclusions */
- cstate->constraint_ref = (DomainConstraintRef *)
- palloc(sizeof(DomainConstraintRef));
- InitDomainConstraintRef(ctest->resulttype,
- cstate->constraint_ref,
- CurrentMemoryContext);
- state = (ExprState *) cstate;
- }
- break;
- case T_CurrentOfExpr:
- state = (ExprState *) makeNode(ExprState);
- state->evalfunc = ExecEvalCurrentOfExpr;
- break;
- case T_TargetEntry:
- {
- TargetEntry *tle = (TargetEntry *) node;
- GenericExprState *gstate = makeNode(GenericExprState);
-
- gstate->xprstate.evalfunc = NULL; /* not used */
- gstate->arg = ExecInitExpr(tle->expr, parent);
- state = (ExprState *) gstate;
- }
- break;
- case T_List:
- {
- List *outlist = NIL;
- ListCell *l;
-
- foreach(l, (List *) node)
- {
- outlist = lappend(outlist,
- ExecInitExpr((Expr *) lfirst(l),
- parent));
- }
- /* Don't fall through to the "common" code below */
- return (ExprState *) outlist;
- }
- default:
- elog(ERROR, "unrecognized node type: %d",
- (int) nodeTag(node));
- state = NULL; /* keep compiler quiet */
- break;
- }
-
- /* Common code for all state-node types */
- state->expr = node;
-
- return state;
-}
-
-/*
- * ExecPrepareExpr --- initialize for expression execution outside a normal
- * Plan tree context.
- *
- * This differs from ExecInitExpr in that we don't assume the caller is
- * already running in the EState's per-query context. Also, we run the
- * passed expression tree through expression_planner() to prepare it for
- * execution. (In ordinary Plan trees the regular planning process will have
- * made the appropriate transformations on expressions, but for standalone
- * expressions this won't have happened.)
- */
-ExprState *
-ExecPrepareExpr(Expr *node, EState *estate)
-{
- ExprState *result;
- MemoryContext oldcontext;
-
- oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
-
- node = expression_planner(node);
-
- result = ExecInitExpr(node, NULL);
-
- MemoryContextSwitchTo(oldcontext);
-
- return result;
-}
-
-
-/* ----------------------------------------------------------------
- * ExecQual / ExecTargetList / ExecProject
- * ----------------------------------------------------------------
- */
-
-/* ----------------------------------------------------------------
- * ExecQual
- *
- * Evaluates a conjunctive boolean expression (qual list) and
- * returns true iff none of the subexpressions are false.
- * (We also return true if the list is empty.)
- *
- * If some of the subexpressions yield NULL but none yield FALSE,
- * then the result of the conjunction is NULL (ie, unknown)
- * according to three-valued boolean logic. In this case,
- * we return the value specified by the "resultForNull" parameter.
- *
- * Callers evaluating WHERE clauses should pass resultForNull=FALSE,
- * since SQL specifies that tuples with null WHERE results do not
- * get selected. On the other hand, callers evaluating constraint
- * conditions should pass resultForNull=TRUE, since SQL also specifies
- * that NULL constraint conditions are not failures.
- *
- * NOTE: it would not be correct to use this routine to evaluate an
- * AND subclause of a boolean expression; for that purpose, a NULL
- * result must be returned as NULL so that it can be properly treated
- * in the next higher operator (cf. ExecEvalAnd and ExecEvalOr).
- * This routine is only used in contexts where a complete expression
- * is being evaluated and we know that NULL can be treated the same
- * as one boolean result or the other.
- *
- * ----------------------------------------------------------------
- */
-bool
-ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
-{
- bool result;
- MemoryContext oldContext;
- ListCell *l;
-
- /*
- * debugging stuff
- */
- EV_printf("ExecQual: qual is ");
- EV_nodeDisplay(qual);
- EV_printf("\n");
-
- /*
- * Run in short-lived per-tuple context while computing expressions.
- */
- oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
-
- /*
- * Evaluate the qual conditions one at a time. If we find a FALSE result,
- * we can stop evaluating and return FALSE --- the AND result must be
- * FALSE. Also, if we find a NULL result when resultForNull is FALSE, we
- * can stop and return FALSE --- the AND result must be FALSE or NULL in
- * that case, and the caller doesn't care which.
- *
- * If we get to the end of the list, we can return TRUE. This will happen
- * when the AND result is indeed TRUE, or when the AND result is NULL (one
- * or more NULL subresult, with all the rest TRUE) and the caller has
- * specified resultForNull = TRUE.
- */
- result = true;
-
- foreach(l, qual)
- {
- ExprState *clause = (ExprState *) lfirst(l);
- Datum expr_value;
- bool isNull;
-
- expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
-
- if (isNull)
- {
- if (resultForNull == false)
- {
- result = false; /* treat NULL as FALSE */
- break;
- }
- }
- else
- {
- if (!DatumGetBool(expr_value))
- {
- result = false; /* definitely FALSE */
- break;
- }
- }
- }
-
- MemoryContextSwitchTo(oldContext);
-
- return result;
-}
-
-/*
- * Number of items in a tlist (including any resjunk items!)
- */
-int
-ExecTargetListLength(List *targetlist)
-{
- /* This used to be more complex, but fjoins are dead */
- return list_length(targetlist);
-}
-
-/*
- * Number of items in a tlist, not including any resjunk items
- */
-int
-ExecCleanTargetListLength(List *targetlist)
-{
- int len = 0;
- ListCell *tl;
-
- foreach(tl, targetlist)
- {
- TargetEntry *curTle = (TargetEntry *) lfirst(tl);
-
- Assert(IsA(curTle, TargetEntry));
- if (!curTle->resjunk)
- len++;
- }
- return len;
-}
-
-/*
- * ExecTargetList
- * Evaluates a targetlist with respect to the given
- * expression context. Returns TRUE if we were able to create
- * a result, FALSE if we have exhausted a set-valued expression.
- *
- * Results are stored into the passed values and isnull arrays.
- * The caller must provide an itemIsDone array that persists across calls.
- *
- * As with ExecEvalExpr, the caller should pass isDone = NULL if not
- * prepared to deal with sets of result tuples. Otherwise, a return
- * of *isDone = ExprMultipleResult signifies a set element, and a return
- * of *isDone = ExprEndResult signifies end of the set of tuple.
- * We assume that *isDone has been initialized to ExprSingleResult by caller.
- *
- * Since fields of the result tuple might be multiply referenced in higher
- * plan nodes, we have to force any read/write expanded values to read-only
- * status. It's a bit annoying to have to do that for every projected
- * expression; in the future, consider teaching the planner to detect
- * actually-multiply-referenced Vars and insert an expression node that
- * would do that only where really required.
- */
-static bool
-ExecTargetList(List *targetlist,
- TupleDesc tupdesc,
- ExprContext *econtext,
- Datum *values,
- bool *isnull,
- ExprDoneCond *itemIsDone,
- ExprDoneCond *isDone)
-{
- Form_pg_attribute *att = tupdesc->attrs;
- MemoryContext oldContext;
- ListCell *tl;
- bool haveDoneSets;
-
- /*
- * Run in short-lived per-tuple context while computing expressions.
- */
- oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
-
- /*
- * evaluate all the expressions in the target list
- */
- haveDoneSets = false; /* any exhausted set exprs in tlist? */
-
- foreach(tl, targetlist)
- {
- GenericExprState *gstate = (GenericExprState *) lfirst(tl);
- TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resno - 1;
-
- values[resind] = ExecEvalExpr(gstate->arg,
- econtext,
- &isnull[resind],
- &itemIsDone[resind]);
-
- values[resind] = MakeExpandedObjectReadOnly(values[resind],
- isnull[resind],
- att[resind]->attlen);
-
- if (itemIsDone[resind] != ExprSingleResult)
- {
- /* We have a set-valued expression in the tlist */
- if (isDone == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- if (itemIsDone[resind] == ExprMultipleResult)
- {
- /* we have undone sets in the tlist, set flag */
- *isDone = ExprMultipleResult;
- }
- else
- {
- /* we have done sets in the tlist, set flag for that */
- haveDoneSets = true;
- }
- }
- }
-
- if (haveDoneSets)
- {
- /*
- * note: can't get here unless we verified isDone != NULL
- */
- if (*isDone == ExprSingleResult)
- {
- /*
- * all sets are done, so report that tlist expansion is complete.
- */
- *isDone = ExprEndResult;
- MemoryContextSwitchTo(oldContext);
- return false;
- }
- else
- {
- /*
- * We have some done and some undone sets. Restart the done ones
- * so that we can deliver a tuple (if possible).
- */
- foreach(tl, targetlist)
- {
- GenericExprState *gstate = (GenericExprState *) lfirst(tl);
- TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resno - 1;
-
- if (itemIsDone[resind] == ExprEndResult)
- {
- values[resind] = ExecEvalExpr(gstate->arg,
- econtext,
- &isnull[resind],
- &itemIsDone[resind]);
-
- values[resind] = MakeExpandedObjectReadOnly(values[resind],
- isnull[resind],
- att[resind]->attlen);
-
- if (itemIsDone[resind] == ExprEndResult)
- {
- /*
- * Oh dear, this item is returning an empty set. Guess
- * we can't make a tuple after all.
- */
- *isDone = ExprEndResult;
- break;
- }
- }
- }
-
- /*
- * If we cannot make a tuple because some sets are empty, we still
- * have to cycle the nonempty sets to completion, else resources
- * will not be released from subplans etc.
- *
- * XXX is that still necessary?
- */
- if (*isDone == ExprEndResult)
- {
- foreach(tl, targetlist)
- {
- GenericExprState *gstate = (GenericExprState *) lfirst(tl);
- TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resno - 1;
-
- while (itemIsDone[resind] == ExprMultipleResult)
- {
- values[resind] = ExecEvalExpr(gstate->arg,
- econtext,
- &isnull[resind],
- &itemIsDone[resind]);
- /* no need for MakeExpandedObjectReadOnly */
- }
- }
-
- MemoryContextSwitchTo(oldContext);
- return false;
- }
- }
- }
-
- /* Report success */
- MemoryContextSwitchTo(oldContext);
-
- return true;
-}
-
-/*
- * ExecProject
- *
- * projects a tuple based on projection info and stores
- * it in the previously specified tuple table slot.
- *
- * Note: the result is always a virtual tuple; therefore it
- * may reference the contents of the exprContext's scan tuples
- * and/or temporary results constructed in the exprContext.
- * If the caller wishes the result to be valid longer than that
- * data will be valid, he must call ExecMaterializeSlot on the
- * result slot.
- */
-TupleTableSlot *
-ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
-{
- TupleTableSlot *slot;
- ExprContext *econtext;
- int numSimpleVars;
-
- /*
- * sanity checks
- */
- Assert(projInfo != NULL);
-
- /*
- * get the projection info we want
- */
- slot = projInfo->pi_slot;
- econtext = projInfo->pi_exprContext;
-
- /* Assume single result row until proven otherwise */
- if (isDone)
- *isDone = ExprSingleResult;
-
- /*
- * Clear any former contents of the result slot. This makes it safe for
- * us to use the slot's Datum/isnull arrays as workspace. (Also, we can
- * return the slot as-is if we decide no rows can be projected.)
- */
- ExecClearTuple(slot);
-
- /*
- * Force extraction of all input values that we'll need. The
- * Var-extraction loops below depend on this, and we are also prefetching
- * all attributes that will be referenced in the generic expressions.
- */
- if (projInfo->pi_lastInnerVar > 0)
- slot_getsomeattrs(econtext->ecxt_innertuple,
- projInfo->pi_lastInnerVar);
- if (projInfo->pi_lastOuterVar > 0)
- slot_getsomeattrs(econtext->ecxt_outertuple,
- projInfo->pi_lastOuterVar);
- if (projInfo->pi_lastScanVar > 0)
- slot_getsomeattrs(econtext->ecxt_scantuple,
- projInfo->pi_lastScanVar);
-
- /*
- * Assign simple Vars to result by direct extraction of fields from source
- * slots ... a mite ugly, but fast ...
- */
- numSimpleVars = projInfo->pi_numSimpleVars;
- if (numSimpleVars > 0)
- {
- Datum *values = slot->tts_values;
- bool *isnull = slot->tts_isnull;
- int *varSlotOffsets = projInfo->pi_varSlotOffsets;
- int *varNumbers = projInfo->pi_varNumbers;
- int i;
-
- if (projInfo->pi_directMap)
- {
- /* especially simple case where vars go to output in order */
- for (i = 0; i < numSimpleVars; i++)
- {
- char *slotptr = ((char *) econtext) + varSlotOffsets[i];
- TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
- int varNumber = varNumbers[i] - 1;
-
- values[i] = varSlot->tts_values[varNumber];
- isnull[i] = varSlot->tts_isnull[varNumber];
- }
- }
- else
- {
- /* we have to pay attention to varOutputCols[] */
- int *varOutputCols = projInfo->pi_varOutputCols;
-
- for (i = 0; i < numSimpleVars; i++)
- {
- char *slotptr = ((char *) econtext) + varSlotOffsets[i];
- TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
- int varNumber = varNumbers[i] - 1;
- int varOutputCol = varOutputCols[i] - 1;
-
- values[varOutputCol] = varSlot->tts_values[varNumber];
- isnull[varOutputCol] = varSlot->tts_isnull[varNumber];
- }
- }
- }
-
- /*
- * If there are any generic expressions, evaluate them. It's possible
- * that there are set-returning functions in such expressions; if so and
- * we have reached the end of the set, we return the result slot, which we
- * already marked empty.
- */
- if (projInfo->pi_targetlist)
- {
- if (!ExecTargetList(projInfo->pi_targetlist,
- slot->tts_tupleDescriptor,
- econtext,
- slot->tts_values,
- slot->tts_isnull,
- projInfo->pi_itemIsDone,
- isDone))
- return slot; /* no more result rows, return empty slot */
- }
-
- /*
- * Successfully formed a result row. Mark the result slot as containing a
- * valid virtual tuple.
- */
- return ExecStoreVirtualTuple(slot);
-}
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
new file mode 100644
index 0000000000..c6a66b6195
--- /dev/null
+++ b/src/backend/executor/execReplication.c
@@ -0,0 +1,573 @@
+/*-------------------------------------------------------------------------
+ *
+ * execReplication.c
+ * miscellaneous executor routines for logical replication
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/executor/execReplication.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/relscan.h"
+#include "access/transam.h"
+#include "access/xact.h"
+#include "commands/trigger.h"
+#include "executor/executor.h"
+#include "nodes/nodeFuncs.h"
+#include "parser/parse_relation.h"
+#include "parser/parsetree.h"
+#include "storage/bufmgr.h"
+#include "storage/lmgr.h"
+#include "utils/datum.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+#include "utils/snapmgr.h"
+#include "utils/syscache.h"
+#include "utils/tqual.h"
+
+
+/*
+ * Setup a ScanKey for a search in the relation 'rel' for a tuple 'key' that
+ * is setup to match 'rel' (*NOT* idxrel!).
+ *
+ * Returns whether any column contains NULLs.
+ *
+ * This is not generic routine, it expects the idxrel to be replication
+ * identity of a rel and meet all limitations associated with that.
+ */
+static bool
+build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel,
+ TupleTableSlot *searchslot)
+{
+ int attoff;
+ bool isnull;
+ Datum indclassDatum;
+ oidvector *opclass;
+ int2vector *indkey = &idxrel->rd_index->indkey;
+ bool hasnulls = false;
+
+ Assert(RelationGetReplicaIndex(rel) == RelationGetRelid(idxrel));
+
+ indclassDatum = SysCacheGetAttr(INDEXRELID, idxrel->rd_indextuple,
+ Anum_pg_index_indclass, &isnull);
+ Assert(!isnull);
+ opclass = (oidvector *) DatumGetPointer(indclassDatum);
+
+ /* Build scankey for every attribute in the index. */
+ for (attoff = 0; attoff < RelationGetNumberOfAttributes(idxrel); attoff++)
+ {
+ Oid operator;
+ Oid opfamily;
+ RegProcedure regop;
+ int pkattno = attoff + 1;
+ int mainattno = indkey->values[attoff];
+ Oid optype = get_opclass_input_type(opclass->values[attoff]);
+
+ /*
+ * Load the operator info. We need this to get the equality operator
+ * function for the scan key.
+ */
+ opfamily = get_opclass_family(opclass->values[attoff]);
+
+ operator = get_opfamily_member(opfamily, optype,
+ optype,
+ BTEqualStrategyNumber);
+
+ if (!OidIsValid(operator))
+ elog(ERROR, "could not find member %d(%u,%u) of opfamily %u",
+ BTEqualStrategyNumber, optype, optype, opfamily);
+
+ regop = get_opcode(operator);
+
+ /* Initialize the scankey. */
+ ScanKeyInit(&skey[attoff],
+ pkattno,
+ BTEqualStrategyNumber,
+ regop,
+ searchslot->tts_values[mainattno - 1]);
+
+ /* Check for null value. */
+ if (searchslot->tts_isnull[mainattno - 1])
+ {
+ hasnulls = true;
+ skey[attoff].sk_flags |= SK_ISNULL;
+ }
+ }
+
+ return hasnulls;
+}
+
+/*
+ * Search the relation 'rel' for tuple using the index.
+ *
+ * If a matching tuple is found, lock it with lockmode, fill the slot with its
+ * contents, and return true. Return false otherwise.
+ */
+bool
+RelationFindReplTupleByIndex(Relation rel, Oid idxoid,
+ LockTupleMode lockmode,
+ TupleTableSlot *searchslot,
+ TupleTableSlot *outslot)
+{
+ HeapTuple scantuple;
+ ScanKeyData skey[INDEX_MAX_KEYS];
+ IndexScanDesc scan;
+ SnapshotData snap;
+ TransactionId xwait;
+ Relation idxrel;
+ bool found;
+
+ /* Open the index. */
+ idxrel = index_open(idxoid, RowExclusiveLock);
+
+ /* Start an index scan. */
+ InitDirtySnapshot(snap);
+ scan = index_beginscan(rel, idxrel, &snap,
+ RelationGetNumberOfAttributes(idxrel),
+ 0);
+
+ /* Build scan key. */
+ build_replindex_scan_key(skey, rel, idxrel, searchslot);
+
+retry:
+ found = false;
+
+ index_rescan(scan, skey, RelationGetNumberOfAttributes(idxrel), NULL, 0);
+
+ /* Try to find the tuple */
+ if ((scantuple = index_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ found = true;
+ ExecStoreTuple(scantuple, outslot, InvalidBuffer, false);
+ ExecMaterializeSlot(outslot);
+
+ xwait = TransactionIdIsValid(snap.xmin) ?
+ snap.xmin : snap.xmax;
+
+ /*
+ * If the tuple is locked, wait for locking transaction to finish and
+ * retry.
+ */
+ if (TransactionIdIsValid(xwait))
+ {
+ XactLockTableWait(xwait, NULL, NULL, XLTW_None);
+ goto retry;
+ }
+ }
+
+ /* Found tuple, try to lock it in the lockmode. */
+ if (found)
+ {
+ Buffer buf;
+ HeapUpdateFailureData hufd;
+ HTSU_Result res;
+ HeapTupleData locktup;
+
+ ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+
+ PushActiveSnapshot(GetLatestSnapshot());
+
+ res = heap_lock_tuple(rel, &locktup, GetCurrentCommandId(false),
+ lockmode,
+ LockWaitBlock,
+ false /* don't follow updates */ ,
+ &buf, &hufd);
+ /* the tuple slot already has the buffer pinned */
+ ReleaseBuffer(buf);
+
+ PopActiveSnapshot();
+
+ switch (res)
+ {
+ case HeapTupleMayBeUpdated:
+ break;
+ case HeapTupleUpdated:
+ /* XXX: Improve handling here */
+ ereport(LOG,
+ (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+ errmsg("concurrent update, retrying")));
+ goto retry;
+ case HeapTupleInvisible:
+ elog(ERROR, "attempted to lock invisible tuple");
+ default:
+ elog(ERROR, "unexpected heap_lock_tuple status: %u", res);
+ break;
+ }
+ }
+
+ index_endscan(scan);
+
+ /* Don't release lock until commit. */
+ index_close(idxrel, NoLock);
+
+ return found;
+}
+
+/*
+ * Compare the tuple and slot and check if they have equal values.
+ *
+ * We use binary datum comparison which might return false negatives but
+ * that's the best we can do here as there may be multiple notions of
+ * equality for the data types and table columns don't specify which one
+ * to use.
+ */
+static bool
+tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot)
+{
+ Datum values[MaxTupleAttributeNumber];
+ bool isnull[MaxTupleAttributeNumber];
+ int attrnum;
+ Form_pg_attribute att;
+
+ heap_deform_tuple(tup, desc, values, isnull);
+
+ /* Check equality of the attributes. */
+ for (attrnum = 0; attrnum < desc->natts; attrnum++)
+ {
+ /*
+ * If one value is NULL and other is not, then they are certainly not
+ * equal
+ */
+ if (isnull[attrnum] != slot->tts_isnull[attrnum])
+ return false;
+
+ /*
+ * If both are NULL, they can be considered equal.
+ */
+ if (isnull[attrnum])
+ continue;
+
+ att = desc->attrs[attrnum];
+ if (!datumIsEqual(values[attrnum], slot->tts_values[attrnum],
+ att->attbyval, att->attlen))
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Search the relation 'rel' for tuple using the sequential scan.
+ *
+ * If a matching tuple is found, lock it with lockmode, fill the slot with its
+ * contents, and return true. Return false otherwise.
+ *
+ * Note that this stops on the first matching tuple.
+ *
+ * This can obviously be quite slow on tables that have more than few rows.
+ */
+bool
+RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
+ TupleTableSlot *searchslot, TupleTableSlot *outslot)
+{
+ HeapTuple scantuple;
+ HeapScanDesc scan;
+ SnapshotData snap;
+ TransactionId xwait;
+ bool found;
+ TupleDesc desc = RelationGetDescr(rel);
+
+ Assert(equalTupleDescs(desc, outslot->tts_tupleDescriptor));
+
+ /* Start an index scan. */
+ InitDirtySnapshot(snap);
+ scan = heap_beginscan(rel, &snap, 0, NULL);
+
+retry:
+ found = false;
+
+ heap_rescan(scan, NULL);
+
+ /* Try to find the tuple */
+ while ((scantuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ if (!tuple_equals_slot(desc, scantuple, searchslot))
+ continue;
+
+ found = true;
+ ExecStoreTuple(scantuple, outslot, InvalidBuffer, false);
+ ExecMaterializeSlot(outslot);
+
+ xwait = TransactionIdIsValid(snap.xmin) ?
+ snap.xmin : snap.xmax;
+
+ /*
+ * If the tuple is locked, wait for locking transaction to finish and
+ * retry.
+ */
+ if (TransactionIdIsValid(xwait))
+ {
+ XactLockTableWait(xwait, NULL, NULL, XLTW_None);
+ goto retry;
+ }
+ }
+
+ /* Found tuple, try to lock it in the lockmode. */
+ if (found)
+ {
+ Buffer buf;
+ HeapUpdateFailureData hufd;
+ HTSU_Result res;
+ HeapTupleData locktup;
+
+ ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+
+ PushActiveSnapshot(GetLatestSnapshot());
+
+ res = heap_lock_tuple(rel, &locktup, GetCurrentCommandId(false),
+ lockmode,
+ LockWaitBlock,
+ false /* don't follow updates */ ,
+ &buf, &hufd);
+ /* the tuple slot already has the buffer pinned */
+ ReleaseBuffer(buf);
+
+ PopActiveSnapshot();
+
+ switch (res)
+ {
+ case HeapTupleMayBeUpdated:
+ break;
+ case HeapTupleUpdated:
+ /* XXX: Improve handling here */
+ ereport(LOG,
+ (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+ errmsg("concurrent update, retrying")));
+ goto retry;
+ case HeapTupleInvisible:
+ elog(ERROR, "attempted to lock invisible tuple");
+ default:
+ elog(ERROR, "unexpected heap_lock_tuple status: %u", res);
+ break;
+ }
+ }
+
+ heap_endscan(scan);
+
+ return found;
+}
+
+/*
+ * Insert tuple represented in the slot to the relation, update the indexes,
+ * and execute any constraints and per-row triggers.
+ *
+ * Caller is responsible for opening the indexes.
+ */
+void
+ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
+{
+ bool skip_tuple = false;
+ HeapTuple tuple;
+ ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
+ Relation rel = resultRelInfo->ri_RelationDesc;
+
+ /* For now we support only tables. */
+ Assert(rel->rd_rel->relkind == RELKIND_RELATION);
+
+ CheckCmdReplicaIdentity(rel, CMD_INSERT);
+
+ /* BEFORE ROW INSERT Triggers */
+ if (resultRelInfo->ri_TrigDesc &&
+ resultRelInfo->ri_TrigDesc->trig_insert_before_row)
+ {
+ slot = ExecBRInsertTriggers(estate, resultRelInfo, slot);
+
+ if (slot == NULL) /* "do nothing" */
+ skip_tuple = true;
+ }
+
+ if (!skip_tuple)
+ {
+ List *recheckIndexes = NIL;
+
+ /* Check the constraints of the tuple */
+ if (rel->rd_att->constr)
+ ExecConstraints(resultRelInfo, slot, estate);
+
+ /* Store the slot into tuple that we can inspect. */
+ tuple = ExecMaterializeSlot(slot);
+
+ /* OK, store the tuple and create index entries for it */
+ simple_heap_insert(rel, tuple);
+
+ if (resultRelInfo->ri_NumIndices > 0)
+ recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
+ estate, false, NULL,
+ NIL);
+
+ /* AFTER ROW INSERT Triggers */
+ ExecARInsertTriggers(estate, resultRelInfo, tuple,
+ recheckIndexes);
+
+ list_free(recheckIndexes);
+ }
+}
+
+/*
+ * Find the searchslot tuple and update it with data in the slot,
+ * update the indexes, and execute any constraints and per-row triggers.
+ *
+ * Caller is responsible for opening the indexes.
+ */
+void
+ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
+ TupleTableSlot *searchslot, TupleTableSlot *slot)
+{
+ bool skip_tuple = false;
+ HeapTuple tuple;
+ ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
+ Relation rel = resultRelInfo->ri_RelationDesc;
+
+ /* For now we support only tables. */
+ Assert(rel->rd_rel->relkind == RELKIND_RELATION);
+
+ CheckCmdReplicaIdentity(rel, CMD_UPDATE);
+
+ /* BEFORE ROW INSERT Triggers */
+ if (resultRelInfo->ri_TrigDesc &&
+ resultRelInfo->ri_TrigDesc->trig_update_before_row)
+ {
+ slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
+ &searchslot->tts_tuple->t_self,
+ NULL, slot);
+
+ if (slot == NULL) /* "do nothing" */
+ skip_tuple = true;
+ }
+
+ if (!skip_tuple)
+ {
+ List *recheckIndexes = NIL;
+
+ /* Check the constraints of the tuple */
+ if (rel->rd_att->constr)
+ ExecConstraints(resultRelInfo, slot, estate);
+
+ /* Store the slot into tuple that we can write. */
+ tuple = ExecMaterializeSlot(slot);
+
+ /* OK, update the tuple and index entries for it */
+ simple_heap_update(rel, &searchslot->tts_tuple->t_self,
+ slot->tts_tuple);
+
+ if (resultRelInfo->ri_NumIndices > 0 &&
+ !HeapTupleIsHeapOnly(slot->tts_tuple))
+ recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
+ estate, false, NULL,
+ NIL);
+
+ /* AFTER ROW UPDATE Triggers */
+ ExecARUpdateTriggers(estate, resultRelInfo,
+ &searchslot->tts_tuple->t_self,
+ NULL, tuple, recheckIndexes);
+
+ list_free(recheckIndexes);
+ }
+}
+
+/*
+ * Find the searchslot tuple and delete it, and execute any constraints
+ * and per-row triggers.
+ *
+ * Caller is responsible for opening the indexes.
+ */
+void
+ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
+ TupleTableSlot *searchslot)
+{
+ bool skip_tuple = false;
+ ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
+ Relation rel = resultRelInfo->ri_RelationDesc;
+
+ /* For now we support only tables. */
+ Assert(rel->rd_rel->relkind == RELKIND_RELATION);
+
+ CheckCmdReplicaIdentity(rel, CMD_DELETE);
+
+ /* BEFORE ROW INSERT Triggers */
+ if (resultRelInfo->ri_TrigDesc &&
+ resultRelInfo->ri_TrigDesc->trig_update_before_row)
+ {
+ skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
+ &searchslot->tts_tuple->t_self,
+ NULL);
+ }
+
+ if (!skip_tuple)
+ {
+ List *recheckIndexes = NIL;
+
+ /* OK, delete the tuple */
+ simple_heap_delete(rel, &searchslot->tts_tuple->t_self);
+
+ /* AFTER ROW DELETE Triggers */
+ ExecARDeleteTriggers(estate, resultRelInfo,
+ &searchslot->tts_tuple->t_self, NULL);
+
+ list_free(recheckIndexes);
+ }
+}
+
+/*
+ * Check if command can be executed with current replica identity.
+ */
+void
+CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
+{
+ PublicationActions *pubactions;
+
+ /* We only need to do checks for UPDATE and DELETE. */
+ if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
+ return;
+
+ /* If relation has replica identity we are always good. */
+ if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
+ OidIsValid(RelationGetReplicaIndex(rel)))
+ return;
+
+ /*
+ * This is either UPDATE OR DELETE and there is no replica identity.
+ *
+ * Check if the table publishes UPDATES or DELETES.
+ */
+ pubactions = GetRelationPublicationActions(rel);
+ if (cmd == CMD_UPDATE && pubactions->pubupdate)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot update table \"%s\" because it does not have replica identity and publishes updates",
+ RelationGetRelationName(rel)),
+ errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
+ else if (cmd == CMD_DELETE && pubactions->pubdelete)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot delete from table \"%s\" because it does not have replica identity and publishes deletes",
+ RelationGetRelationName(rel)),
+ errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
+}
+
+
+/*
+ * Check if we support writing into specific relkind.
+ *
+ * The nspname and relname are only needed for error reporting.
+ */
+void
+CheckSubscriptionRelkind(char relkind, const char *nspname,
+ const char *relname)
+{
+ /*
+ * We currently only support writing to regular tables.
+ */
+ if (relkind != RELKIND_RELATION)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("logical replication target relation \"%s.%s\" is not a table",
+ nspname, relname)));
+}
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
new file mode 100644
index 0000000000..077ac208c1
--- /dev/null
+++ b/src/backend/executor/execSRF.c
@@ -0,0 +1,928 @@
+/*-------------------------------------------------------------------------
+ *
+ * execSRF.c
+ * Routines implementing the API for set-returning functions
+ *
+ * This file serves nodeFunctionscan.c and nodeProjectSet.c, providing
+ * common code for calling set-returning functions according to the
+ * ReturnSetInfo API.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/execSRF.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "catalog/objectaccess.h"
+#include "executor/execdebug.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "nodes/nodeFuncs.h"
+#include "parser/parse_coerce.h"
+#include "pgstat.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/typcache.h"
+
+
+/* static function decls */
+static void init_sexpr(Oid foid, Oid input_collation, Expr *node,
+ SetExprState *sexpr, PlanState *parent,
+ MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF);
+static void ShutdownSetExpr(Datum arg);
+static void ExecEvalFuncArgs(FunctionCallInfo fcinfo,
+ List *argList, ExprContext *econtext);
+static void ExecPrepareTuplestoreResult(SetExprState *sexpr,
+ ExprContext *econtext,
+ Tuplestorestate *resultStore,
+ TupleDesc resultDesc);
+static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc);
+
+
+/*
+ * Prepare function call in FROM (ROWS FROM) for execution.
+ *
+ * This is used by nodeFunctionscan.c.
+ */
+SetExprState *
+ExecInitTableFunctionResult(Expr *expr,
+ ExprContext *econtext, PlanState *parent)
+{
+ SetExprState *state = makeNode(SetExprState);
+
+ state->funcReturnsSet = false;
+ state->expr = expr;
+ state->func.fn_oid = InvalidOid;
+
+ /*
+ * Normally the passed expression tree will be a FuncExpr, since the
+ * grammar only allows a function call at the top level of a table
+ * function reference. However, if the function doesn't return set then
+ * the planner might have replaced the function call via constant-folding
+ * or inlining. So if we see any other kind of expression node, execute
+ * it via the general ExecEvalExpr() code. That code path will not
+ * support set-returning functions buried in the expression, though.
+ */
+ if (IsA(expr, FuncExpr))
+ {
+ FuncExpr *func = (FuncExpr *) expr;
+
+ state->funcReturnsSet = func->funcretset;
+ state->args = ExecInitExprList(func->args, parent);
+
+ init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
+ econtext->ecxt_per_query_memory, func->funcretset, false);
+ }
+ else
+ {
+ state->elidedFuncState = ExecInitExpr(expr, parent);
+ }
+
+ return state;
+}
+
+/*
+ * ExecMakeTableFunctionResult
+ *
+ * Evaluate a table function, producing a materialized result in a Tuplestore
+ * object.
+ *
+ * This is used by nodeFunctionscan.c.
+ */
+Tuplestorestate *
+ExecMakeTableFunctionResult(SetExprState *setexpr,
+ ExprContext *econtext,
+ MemoryContext argContext,
+ TupleDesc expectedDesc,
+ bool randomAccess)
+{
+ Tuplestorestate *tupstore = NULL;
+ TupleDesc tupdesc = NULL;
+ Oid funcrettype;
+ bool returnsTuple;
+ bool returnsSet = false;
+ FunctionCallInfoData fcinfo;
+ PgStat_FunctionCallUsage fcusage;
+ ReturnSetInfo rsinfo;
+ HeapTupleData tmptup;
+ MemoryContext callerContext;
+ MemoryContext oldcontext;
+ bool first_time = true;
+
+ callerContext = CurrentMemoryContext;
+
+ funcrettype = exprType((Node *) setexpr->expr);
+
+ returnsTuple = type_is_rowtype(funcrettype);
+
+ /*
+ * Prepare a resultinfo node for communication. We always do this even if
+ * not expecting a set result, so that we can pass expectedDesc. In the
+ * generic-expression case, the expression doesn't actually get to see the
+ * resultinfo, but set it up anyway because we use some of the fields as
+ * our own state variables.
+ */
+ rsinfo.type = T_ReturnSetInfo;
+ rsinfo.econtext = econtext;
+ rsinfo.expectedDesc = expectedDesc;
+ rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize | SFRM_Materialize_Preferred);
+ if (randomAccess)
+ rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
+ rsinfo.returnMode = SFRM_ValuePerCall;
+ /* isDone is filled below */
+ rsinfo.setResult = NULL;
+ rsinfo.setDesc = NULL;
+
+ /*
+ * Normally the passed expression tree will be a SetExprState, since the
+ * grammar only allows a function call at the top level of a table
+ * function reference. However, if the function doesn't return set then
+ * the planner might have replaced the function call via constant-folding
+ * or inlining. So if we see any other kind of expression node, execute
+ * it via the general ExecEvalExpr() code; the only difference is that we
+ * don't get a chance to pass a special ReturnSetInfo to any functions
+ * buried in the expression.
+ */
+ if (!setexpr->elidedFuncState)
+ {
+ /*
+ * This path is similar to ExecMakeFunctionResultSet.
+ */
+ returnsSet = setexpr->funcReturnsSet;
+ InitFunctionCallInfoData(fcinfo, &(setexpr->func),
+ list_length(setexpr->args),
+ setexpr->fcinfo_data.fncollation,
+ NULL, (Node *) &rsinfo);
+
+ /*
+ * Evaluate the function's argument list.
+ *
+ * We can't do this in the per-tuple context: the argument values
+ * would disappear when we reset that context in the inner loop. And
+ * the caller's CurrentMemoryContext is typically a query-lifespan
+ * context, so we don't want to leak memory there. We require the
+ * caller to pass a separate memory context that can be used for this,
+ * and can be reset each time through to avoid bloat.
+ */
+ MemoryContextReset(argContext);
+ oldcontext = MemoryContextSwitchTo(argContext);
+ ExecEvalFuncArgs(&fcinfo, setexpr->args, econtext);
+ MemoryContextSwitchTo(oldcontext);
+
+ /*
+ * If function is strict, and there are any NULL arguments, skip
+ * calling the function and act like it returned NULL (or an empty
+ * set, in the returns-set case).
+ */
+ if (setexpr->func.fn_strict)
+ {
+ int i;
+
+ for (i = 0; i < fcinfo.nargs; i++)
+ {
+ if (fcinfo.argnull[i])
+ goto no_function_result;
+ }
+ }
+ }
+ else
+ {
+ /* Treat setexpr as a generic expression */
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ }
+
+ /*
+ * Switch to short-lived context for calling the function or expression.
+ */
+ MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+
+ /*
+ * Loop to handle the ValuePerCall protocol (which is also the same
+ * behavior needed in the generic ExecEvalExpr path).
+ */
+ for (;;)
+ {
+ Datum result;
+
+ CHECK_FOR_INTERRUPTS();
+
+ /*
+ * reset per-tuple memory context before each call of the function or
+ * expression. This cleans up any local memory the function may leak
+ * when called.
+ */
+ ResetExprContext(econtext);
+
+ /* Call the function or expression one time */
+ if (!setexpr->elidedFuncState)
+ {
+ pgstat_init_function_usage(&fcinfo, &fcusage);
+
+ fcinfo.isnull = false;
+ rsinfo.isDone = ExprSingleResult;
+ result = FunctionCallInvoke(&fcinfo);
+
+ pgstat_end_function_usage(&fcusage,
+ rsinfo.isDone != ExprMultipleResult);
+ }
+ else
+ {
+ result =
+ ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.isnull);
+ rsinfo.isDone = ExprSingleResult;
+ }
+
+ /* Which protocol does function want to use? */
+ if (rsinfo.returnMode == SFRM_ValuePerCall)
+ {
+ /*
+ * Check for end of result set.
+ */
+ if (rsinfo.isDone == ExprEndResult)
+ break;
+
+ /*
+ * If first time through, build tuplestore for result. For a
+ * scalar function result type, also make a suitable tupdesc.
+ */
+ if (first_time)
+ {
+ oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
+ rsinfo.setResult = tupstore;
+ if (!returnsTuple)
+ {
+ tupdesc = CreateTemplateTupleDesc(1, false);
+ TupleDescInitEntry(tupdesc,
+ (AttrNumber) 1,
+ "column",
+ funcrettype,
+ -1,
+ 0);
+ rsinfo.setDesc = tupdesc;
+ }
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /*
+ * Store current resultset item.
+ */
+ if (returnsTuple)
+ {
+ if (!fcinfo.isnull)
+ {
+ HeapTupleHeader td = DatumGetHeapTupleHeader(result);
+
+ if (tupdesc == NULL)
+ {
+ /*
+ * This is the first non-NULL result from the
+ * function. Use the type info embedded in the
+ * rowtype Datum to look up the needed tupdesc. Make
+ * a copy for the query.
+ */
+ oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td),
+ HeapTupleHeaderGetTypMod(td));
+ rsinfo.setDesc = tupdesc;
+ MemoryContextSwitchTo(oldcontext);
+ }
+ else
+ {
+ /*
+ * Verify all later returned rows have same subtype;
+ * necessary in case the type is RECORD.
+ */
+ if (HeapTupleHeaderGetTypeId(td) != tupdesc->tdtypeid ||
+ HeapTupleHeaderGetTypMod(td) != tupdesc->tdtypmod)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("rows returned by function are not all of the same row type")));
+ }
+
+ /*
+ * tuplestore_puttuple needs a HeapTuple not a bare
+ * HeapTupleHeader, but it doesn't need all the fields.
+ */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
+ tmptup.t_data = td;
+
+ tuplestore_puttuple(tupstore, &tmptup);
+ }
+ else
+ {
+ /*
+ * NULL result from a tuple-returning function; expand it
+ * to a row of all nulls. We rely on the expectedDesc to
+ * form such rows. (Note: this would be problematic if
+ * tuplestore_putvalues saved the tdtypeid/tdtypmod from
+ * the provided descriptor, since that might not match
+ * what we get from the function itself. But it doesn't.)
+ */
+ int natts = expectedDesc->natts;
+ bool *nullflags;
+
+ nullflags = (bool *) palloc(natts * sizeof(bool));
+ memset(nullflags, true, natts * sizeof(bool));
+ tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
+ }
+ }
+ else
+ {
+ /* Scalar-type case: just store the function result */
+ tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
+ }
+
+ /*
+ * Are we done?
+ */
+ if (rsinfo.isDone != ExprMultipleResult)
+ break;
+ }
+ else if (rsinfo.returnMode == SFRM_Materialize)
+ {
+ /* check we're on the same page as the function author */
+ if (!first_time || rsinfo.isDone != ExprSingleResult)
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
+ errmsg("table-function protocol for materialize mode was not followed")));
+ /* Done evaluating the set result */
+ break;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
+ errmsg("unrecognized table-function returnMode: %d",
+ (int) rsinfo.returnMode)));
+
+ first_time = false;
+ }
+
+no_function_result:
+
+ /*
+ * If we got nothing from the function (ie, an empty-set or NULL result),
+ * we have to create the tuplestore to return, and if it's a
+ * non-set-returning function then insert a single all-nulls row. As
+ * above, we depend on the expectedDesc to manufacture the dummy row.
+ */
+ if (rsinfo.setResult == NULL)
+ {
+ MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
+ rsinfo.setResult = tupstore;
+ if (!returnsSet)
+ {
+ int natts = expectedDesc->natts;
+ bool *nullflags;
+
+ MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+ nullflags = (bool *) palloc(natts * sizeof(bool));
+ memset(nullflags, true, natts * sizeof(bool));
+ tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
+ }
+ }
+
+ /*
+ * If function provided a tupdesc, cross-check it. We only really need to
+ * do this for functions returning RECORD, but might as well do it always.
+ */
+ if (rsinfo.setDesc)
+ {
+ tupledesc_match(expectedDesc, rsinfo.setDesc);
+
+ /*
+ * If it is a dynamically-allocated TupleDesc, free it: it is
+ * typically allocated in a per-query context, so we must avoid
+ * leaking it across multiple usages.
+ */
+ if (rsinfo.setDesc->tdrefcount == -1)
+ FreeTupleDesc(rsinfo.setDesc);
+ }
+
+ MemoryContextSwitchTo(callerContext);
+
+ /* All done, pass back the tuplestore */
+ return rsinfo.setResult;
+}
+
+
+/*
+ * Prepare targetlist SRF function call for execution.
+ *
+ * This is used by nodeProjectSet.c.
+ */
+SetExprState *
+ExecInitFunctionResultSet(Expr *expr,
+ ExprContext *econtext, PlanState *parent)
+{
+ SetExprState *state = makeNode(SetExprState);
+
+ state->funcReturnsSet = true;
+ state->expr = expr;
+ state->func.fn_oid = InvalidOid;
+
+ /*
+ * Initialize metadata. The expression node could be either a FuncExpr or
+ * an OpExpr.
+ */
+ if (IsA(expr, FuncExpr))
+ {
+ FuncExpr *func = (FuncExpr *) expr;
+
+ state->args = ExecInitExprList(func->args, parent);
+ init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
+ econtext->ecxt_per_query_memory, true, true);
+ }
+ else if (IsA(expr, OpExpr))
+ {
+ OpExpr *op = (OpExpr *) expr;
+
+ state->args = ExecInitExprList(op->args, parent);
+ init_sexpr(op->opfuncid, op->inputcollid, expr, state, parent,
+ econtext->ecxt_per_query_memory, true, true);
+ }
+ else
+ elog(ERROR, "unrecognized node type: %d",
+ (int) nodeTag(expr));
+
+ /* shouldn't get here unless the selected function returns set */
+ Assert(state->func.fn_retset);
+
+ return state;
+}
+
+/*
+ * ExecMakeFunctionResultSet
+ *
+ * Evaluate the arguments to a set-returning function and then call the
+ * function itself. The argument expressions may not contain set-returning
+ * functions (the planner is supposed to have separated evaluation for those).
+ *
+ * This is used by nodeProjectSet.c.
+ */
+Datum
+ExecMakeFunctionResultSet(SetExprState *fcache,
+ ExprContext *econtext,
+ bool *isNull,
+ ExprDoneCond *isDone)
+{
+ List *arguments;
+ Datum result;
+ FunctionCallInfo fcinfo;
+ PgStat_FunctionCallUsage fcusage;
+ ReturnSetInfo rsinfo;
+ bool callit;
+ int i;
+
+restart:
+
+ /* Guard against stack overflow due to overly complex expressions */
+ check_stack_depth();
+
+ /*
+ * If a previous call of the function returned a set result in the form of
+ * a tuplestore, continue reading rows from the tuplestore until it's
+ * empty.
+ */
+ if (fcache->funcResultStore)
+ {
+ if (tuplestore_gettupleslot(fcache->funcResultStore, true, false,
+ fcache->funcResultSlot))
+ {
+ *isDone = ExprMultipleResult;
+ if (fcache->funcReturnsTuple)
+ {
+ /* We must return the whole tuple as a Datum. */
+ *isNull = false;
+ return ExecFetchSlotTupleDatum(fcache->funcResultSlot);
+ }
+ else
+ {
+ /* Extract the first column and return it as a scalar. */
+ return slot_getattr(fcache->funcResultSlot, 1, isNull);
+ }
+ }
+ /* Exhausted the tuplestore, so clean up */
+ tuplestore_end(fcache->funcResultStore);
+ fcache->funcResultStore = NULL;
+ *isDone = ExprEndResult;
+ *isNull = true;
+ return (Datum) 0;
+ }
+
+ /*
+ * arguments is a list of expressions to evaluate before passing to the
+ * function manager. We skip the evaluation if it was already done in the
+ * previous call (ie, we are continuing the evaluation of a set-valued
+ * function). Otherwise, collect the current argument values into fcinfo.
+ */
+ fcinfo = &fcache->fcinfo_data;
+ arguments = fcache->args;
+ if (!fcache->setArgsValid)
+ ExecEvalFuncArgs(fcinfo, arguments, econtext);
+ else
+ {
+ /* Reset flag (we may set it again below) */
+ fcache->setArgsValid = false;
+ }
+
+ /*
+ * Now call the function, passing the evaluated parameter values.
+ */
+
+ /* Prepare a resultinfo node for communication. */
+ fcinfo->resultinfo = (Node *) &rsinfo;
+ rsinfo.type = T_ReturnSetInfo;
+ rsinfo.econtext = econtext;
+ rsinfo.expectedDesc = fcache->funcResultDesc;
+ rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
+ /* note we do not set SFRM_Materialize_Random or _Preferred */
+ rsinfo.returnMode = SFRM_ValuePerCall;
+ /* isDone is filled below */
+ rsinfo.setResult = NULL;
+ rsinfo.setDesc = NULL;
+
+ /*
+ * If function is strict, and there are any NULL arguments, skip calling
+ * the function.
+ */
+ callit = true;
+ if (fcache->func.fn_strict)
+ {
+ for (i = 0; i < fcinfo->nargs; i++)
+ {
+ if (fcinfo->argnull[i])
+ {
+ callit = false;
+ break;
+ }
+ }
+ }
+
+ if (callit)
+ {
+ pgstat_init_function_usage(fcinfo, &fcusage);
+
+ fcinfo->isnull = false;
+ rsinfo.isDone = ExprSingleResult;
+ result = FunctionCallInvoke(fcinfo);
+ *isNull = fcinfo->isnull;
+ *isDone = rsinfo.isDone;
+
+ pgstat_end_function_usage(&fcusage,
+ rsinfo.isDone != ExprMultipleResult);
+ }
+ else
+ {
+ /* for a strict SRF, result for NULL is an empty set */
+ result = (Datum) 0;
+ *isNull = true;
+ *isDone = ExprEndResult;
+ }
+
+ /* Which protocol does function want to use? */
+ if (rsinfo.returnMode == SFRM_ValuePerCall)
+ {
+ if (*isDone != ExprEndResult)
+ {
+ /*
+ * Save the current argument values to re-use on the next call.
+ */
+ if (*isDone == ExprMultipleResult)
+ {
+ fcache->setArgsValid = true;
+ /* Register cleanup callback if we didn't already */
+ if (!fcache->shutdown_reg)
+ {
+ RegisterExprContextCallback(econtext,
+ ShutdownSetExpr,
+ PointerGetDatum(fcache));
+ fcache->shutdown_reg = true;
+ }
+ }
+ }
+ }
+ else if (rsinfo.returnMode == SFRM_Materialize)
+ {
+ /* check we're on the same page as the function author */
+ if (rsinfo.isDone != ExprSingleResult)
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
+ errmsg("table-function protocol for materialize mode was not followed")));
+ if (rsinfo.setResult != NULL)
+ {
+ /* prepare to return values from the tuplestore */
+ ExecPrepareTuplestoreResult(fcache, econtext,
+ rsinfo.setResult,
+ rsinfo.setDesc);
+ /* loop back to top to start returning from tuplestore */
+ goto restart;
+ }
+ /* if setResult was left null, treat it as empty set */
+ *isDone = ExprEndResult;
+ *isNull = true;
+ result = (Datum) 0;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
+ errmsg("unrecognized table-function returnMode: %d",
+ (int) rsinfo.returnMode)));
+
+ return result;
+}
+
+
+/*
+ * init_sexpr - initialize a SetExprState node during first use
+ */
+static void
+init_sexpr(Oid foid, Oid input_collation, Expr *node,
+ SetExprState *sexpr, PlanState *parent,
+ MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF)
+{
+ AclResult aclresult;
+
+ /* Check permission to call function */
+ aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));
+ InvokeFunctionExecuteHook(foid);
+
+ /*
+ * Safety check on nargs. Under normal circumstances this should never
+ * fail, as parser should check sooner. But possibly it might fail if
+ * server has been compiled with FUNC_MAX_ARGS smaller than some functions
+ * declared in pg_proc?
+ */
+ if (list_length(sexpr->args) > FUNC_MAX_ARGS)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+ errmsg_plural("cannot pass more than %d argument to a function",
+ "cannot pass more than %d arguments to a function",
+ FUNC_MAX_ARGS,
+ FUNC_MAX_ARGS)));
+
+ /* Set up the primary fmgr lookup information */
+ fmgr_info_cxt(foid, &(sexpr->func), sexprCxt);
+ fmgr_info_set_expr((Node *) sexpr->expr, &(sexpr->func));
+
+ /* Initialize the function call parameter struct as well */
+ InitFunctionCallInfoData(sexpr->fcinfo_data, &(sexpr->func),
+ list_length(sexpr->args),
+ input_collation, NULL, NULL);
+
+ /* If function returns set, check if that's allowed by caller */
+ if (sexpr->func.fn_retset && !allowSRF)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("set-valued function called in context that cannot accept a set"),
+ parent ? executor_errposition(parent->state,
+ exprLocation((Node *) node)) : 0));
+
+ /* Otherwise, caller should have marked the sexpr correctly */
+ Assert(sexpr->func.fn_retset == sexpr->funcReturnsSet);
+
+ /* If function returns set, prepare expected tuple descriptor */
+ if (sexpr->func.fn_retset && needDescForSRF)
+ {
+ TypeFuncClass functypclass;
+ Oid funcrettype;
+ TupleDesc tupdesc;
+ MemoryContext oldcontext;
+
+ functypclass = get_expr_result_type(sexpr->func.fn_expr,
+ &funcrettype,
+ &tupdesc);
+
+ /* Must save tupdesc in sexpr's context */
+ oldcontext = MemoryContextSwitchTo(sexprCxt);
+
+ if (functypclass == TYPEFUNC_COMPOSITE)
+ {
+ /* Composite data type, e.g. a table's row type */
+ Assert(tupdesc);
+ /* Must copy it out of typcache for safety */
+ sexpr->funcResultDesc = CreateTupleDescCopy(tupdesc);
+ sexpr->funcReturnsTuple = true;
+ }
+ else if (functypclass == TYPEFUNC_SCALAR)
+ {
+ /* Base data type, i.e. scalar */
+ tupdesc = CreateTemplateTupleDesc(1, false);
+ TupleDescInitEntry(tupdesc,
+ (AttrNumber) 1,
+ NULL,
+ funcrettype,
+ -1,
+ 0);
+ sexpr->funcResultDesc = tupdesc;
+ sexpr->funcReturnsTuple = false;
+ }
+ else if (functypclass == TYPEFUNC_RECORD)
+ {
+ /* This will work if function doesn't need an expectedDesc */
+ sexpr->funcResultDesc = NULL;
+ sexpr->funcReturnsTuple = true;
+ }
+ else
+ {
+ /* Else, we will fail if function needs an expectedDesc */
+ sexpr->funcResultDesc = NULL;
+ }
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+ else
+ sexpr->funcResultDesc = NULL;
+
+ /* Initialize additional state */
+ sexpr->funcResultStore = NULL;
+ sexpr->funcResultSlot = NULL;
+ sexpr->shutdown_reg = false;
+}
+
+/*
+ * callback function in case a SetExprState needs to be shut down before it
+ * has been run to completion
+ */
+static void
+ShutdownSetExpr(Datum arg)
+{
+ SetExprState *sexpr = castNode(SetExprState, DatumGetPointer(arg));
+
+ /* If we have a slot, make sure it's let go of any tuplestore pointer */
+ if (sexpr->funcResultSlot)
+ ExecClearTuple(sexpr->funcResultSlot);
+
+ /* Release any open tuplestore */
+ if (sexpr->funcResultStore)
+ tuplestore_end(sexpr->funcResultStore);
+ sexpr->funcResultStore = NULL;
+
+ /* Clear any active set-argument state */
+ sexpr->setArgsValid = false;
+
+ /* execUtils will deregister the callback... */
+ sexpr->shutdown_reg = false;
+}
+
+/*
+ * Evaluate arguments for a function.
+ */
+static void
+ExecEvalFuncArgs(FunctionCallInfo fcinfo,
+ List *argList,
+ ExprContext *econtext)
+{
+ int i;
+ ListCell *arg;
+
+ i = 0;
+ foreach(arg, argList)
+ {
+ ExprState *argstate = (ExprState *) lfirst(arg);
+
+ fcinfo->arg[i] = ExecEvalExpr(argstate,
+ econtext,
+ &fcinfo->argnull[i]);
+ i++;
+ }
+
+ Assert(i == fcinfo->nargs);
+}
+
+/*
+ * ExecPrepareTuplestoreResult
+ *
+ * Subroutine for ExecMakeFunctionResultSet: prepare to extract rows from a
+ * tuplestore function result. We must set up a funcResultSlot (unless
+ * already done in a previous call cycle) and verify that the function
+ * returned the expected tuple descriptor.
+ */
+static void
+ExecPrepareTuplestoreResult(SetExprState *sexpr,
+ ExprContext *econtext,
+ Tuplestorestate *resultStore,
+ TupleDesc resultDesc)
+{
+ sexpr->funcResultStore = resultStore;
+
+ if (sexpr->funcResultSlot == NULL)
+ {
+ /* Create a slot so we can read data out of the tuplestore */
+ TupleDesc slotDesc;
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(sexpr->func.fn_mcxt);
+
+ /*
+ * If we were not able to determine the result rowtype from context,
+ * and the function didn't return a tupdesc, we have to fail.
+ */
+ if (sexpr->funcResultDesc)
+ slotDesc = sexpr->funcResultDesc;
+ else if (resultDesc)
+ {
+ /* don't assume resultDesc is long-lived */
+ slotDesc = CreateTupleDescCopy(resultDesc);
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function returning setof record called in "
+ "context that cannot accept type record")));
+ slotDesc = NULL; /* keep compiler quiet */
+ }
+
+ sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /*
+ * If function provided a tupdesc, cross-check it. We only really need to
+ * do this for functions returning RECORD, but might as well do it always.
+ */
+ if (resultDesc)
+ {
+ if (sexpr->funcResultDesc)
+ tupledesc_match(sexpr->funcResultDesc, resultDesc);
+
+ /*
+ * If it is a dynamically-allocated TupleDesc, free it: it is
+ * typically allocated in a per-query context, so we must avoid
+ * leaking it across multiple usages.
+ */
+ if (resultDesc->tdrefcount == -1)
+ FreeTupleDesc(resultDesc);
+ }
+
+ /* Register cleanup callback if we didn't already */
+ if (!sexpr->shutdown_reg)
+ {
+ RegisterExprContextCallback(econtext,
+ ShutdownSetExpr,
+ PointerGetDatum(sexpr));
+ sexpr->shutdown_reg = true;
+ }
+}
+
+/*
+ * Check that function result tuple type (src_tupdesc) matches or can
+ * be considered to match what the query expects (dst_tupdesc). If
+ * they don't match, ereport.
+ *
+ * We really only care about number of attributes and data type.
+ * Also, we can ignore type mismatch on columns that are dropped in the
+ * destination type, so long as the physical storage matches. This is
+ * helpful in some cases involving out-of-date cached plans.
+ */
+static void
+tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
+{
+ int i;
+
+ if (dst_tupdesc->natts != src_tupdesc->natts)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("function return row and query-specified return row do not match"),
+ errdetail_plural("Returned row contains %d attribute, but query expects %d.",
+ "Returned row contains %d attributes, but query expects %d.",
+ src_tupdesc->natts,
+ src_tupdesc->natts, dst_tupdesc->natts)));
+
+ for (i = 0; i < dst_tupdesc->natts; i++)
+ {
+ Form_pg_attribute dattr = dst_tupdesc->attrs[i];
+ Form_pg_attribute sattr = src_tupdesc->attrs[i];
+
+ if (IsBinaryCoercible(sattr->atttypid, dattr->atttypid))
+ continue; /* no worries */
+ if (!dattr->attisdropped)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("function return row and query-specified return row do not match"),
+ errdetail("Returned type %s at ordinal position %d, but query expects %s.",
+ format_type_be(sattr->atttypid),
+ i + 1,
+ format_type_be(dattr->atttypid))));
+
+ if (dattr->attlen != sattr->attlen ||
+ dattr->attalign != sattr->attalign)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("function return row and query-specified return row do not match"),
+ errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
+ i + 1)));
+ }
+}
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index fb0013dc53..4f131b3ee0 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -7,7 +7,7 @@
* stuff - checking the qualification and projecting the tuple
* appropriately.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -123,10 +123,8 @@ ExecScan(ScanState *node,
ExecScanRecheckMtd recheckMtd)
{
ExprContext *econtext;
- List *qual;
+ ExprState *qual;
ProjectionInfo *projInfo;
- ExprDoneCond isDone;
- TupleTableSlot *resultSlot;
/*
* Fetch data from node
@@ -146,24 +144,8 @@ ExecScan(ScanState *node,
}
/*
- * Check to see if we're still projecting out tuples from a previous scan
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->ps.ps_TupFromTlist)
- {
- Assert(projInfo); /* can't get here if not projecting */
- resultSlot = ExecProject(projInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return resultSlot;
- /* Done with that source tuple... */
- node->ps.ps_TupFromTlist = false;
- }
-
- /*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't happen
- * until we're done projecting out tuples from a scan tuple.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -188,7 +170,7 @@ ExecScan(ScanState *node,
if (TupIsNull(slot))
{
if (projInfo)
- return ExecClearTuple(projInfo->pi_slot);
+ return ExecClearTuple(projInfo->pi_state.resultslot);
else
return slot;
}
@@ -201,11 +183,11 @@ ExecScan(ScanState *node,
/*
* check that the current tuple satisfies the qual-clause
*
- * check for non-nil qual here to avoid a function call to ExecQual()
- * when the qual is nil ... saves only a few cycles, but they add up
+ * check for non-null qual here to avoid a function call to ExecQual()
+ * when the qual is null ... saves only a few cycles, but they add up
* ...
*/
- if (!qual || ExecQual(qual, econtext, false))
+ if (qual == NULL || ExecQual(qual, econtext))
{
/*
* Found a satisfactory scan tuple.
@@ -214,15 +196,9 @@ ExecScan(ScanState *node,
{
/*
* Form a projection tuple, store it in the result tuple slot
- * and return it --- unless we find we can project no tuples
- * from this scan tuple, in which case continue scan.
+ * and return it.
*/
- resultSlot = ExecProject(projInfo, &isDone);
- if (isDone != ExprEndResult)
- {
- node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
- return resultSlot;
- }
+ return ExecProject(projInfo);
}
else
{
@@ -352,9 +328,6 @@ ExecScanReScan(ScanState *node)
{
EState *estate = node->ps.state;
- /* Stop projecting any tuples from SRFs in the targetlist */
- node->ps.ps_TupFromTlist = false;
-
/* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */
if (estate->es_epqScanDone != NULL)
{
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 63375dc825..489ca5edb9 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -13,7 +13,7 @@
* (getattribute, formtuple, etc.).
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -170,10 +170,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
foreach(lc, tupleTable)
{
- TupleTableSlot *slot = (TupleTableSlot *) lfirst(lc);
-
- /* Sanity checks */
- Assert(IsA(slot, TupleTableSlot));
+ TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 4bdf76cf56..b1178552e5 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -4,7 +4,7 @@
* miscellaneous executor utility routines
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -29,9 +29,14 @@
* ExecOpenScanRelation Common code for scan node init routines.
* ExecCloseScanRelation
*
+ * executor_errposition Report syntactic position of an error.
+ *
* RegisterExprContextCallback Register function shutdown callback
* UnregisterExprContextCallback Deregister function shutdown callback
*
+ * GetAttributeByName Runtime extraction of columns from tuples.
+ * GetAttributeByNum
+ *
* NOTES
* This file has traditionally been the place to stick misc.
* executor support stuff that doesn't really go anyplace else.
@@ -42,13 +47,16 @@
#include "access/relscan.h"
#include "access/transam.h"
#include "executor/executor.h"
+#include "mb/pg_wchar.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
+#include "storage/lmgr.h"
+#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
+#include "utils/typcache.h"
-static bool get_last_attnums(Node *node, ProjectionInfo *projInfo);
static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
@@ -81,9 +89,7 @@ CreateExecutorState(void)
*/
qcontext = AllocSetContextCreate(CurrentMemoryContext,
"ExecutorState",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* Make the EState node within the per-query context. This way, we don't
@@ -118,6 +124,8 @@ CreateExecutorState(void)
estate->es_param_list_info = NULL;
estate->es_param_exec_vals = NULL;
+ estate->es_queryEnv = NULL;
+
estate->es_query_cxt = qcontext;
estate->es_tupleTable = NIL;
@@ -142,6 +150,7 @@ CreateExecutorState(void)
estate->es_epqTuple = NULL;
estate->es_epqTupleSet = NULL;
estate->es_epqScanDone = NULL;
+ estate->es_sourceText = NULL;
/*
* Return the executor state structure
@@ -230,9 +239,7 @@ CreateExprContext(EState *estate)
econtext->ecxt_per_tuple_memory =
AllocSetContextCreate(estate->es_query_cxt,
"ExprContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
econtext->ecxt_param_list_info = estate->es_param_list_info;
@@ -301,9 +308,7 @@ CreateStandaloneExprContext(void)
econtext->ecxt_per_tuple_memory =
AllocSetContextCreate(CurrentMemoryContext,
"ExprContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
econtext->ecxt_param_exec_vals = NULL;
econtext->ecxt_param_list_info = NULL;
@@ -469,192 +474,6 @@ ExecGetResultType(PlanState *planstate)
return slot->tts_tupleDescriptor;
}
-/* ----------------
- * ExecBuildProjectionInfo
- *
- * Build a ProjectionInfo node for evaluating the given tlist in the given
- * econtext, and storing the result into the tuple slot. (Caller must have
- * ensured that tuple slot has a descriptor matching the tlist!) Note that
- * the given tlist should be a list of ExprState nodes, not Expr nodes.
- *
- * inputDesc can be NULL, but if it is not, we check to see whether simple
- * Vars in the tlist match the descriptor. It is important to provide
- * inputDesc for relation-scan plan nodes, as a cross check that the relation
- * hasn't been changed since the plan was made. At higher levels of a plan,
- * there is no need to recheck.
- * ----------------
- */
-ProjectionInfo *
-ExecBuildProjectionInfo(List *targetList,
- ExprContext *econtext,
- TupleTableSlot *slot,
- TupleDesc inputDesc)
-{
- ProjectionInfo *projInfo = makeNode(ProjectionInfo);
- int len = ExecTargetListLength(targetList);
- int *workspace;
- int *varSlotOffsets;
- int *varNumbers;
- int *varOutputCols;
- List *exprlist;
- int numSimpleVars;
- bool directMap;
- ListCell *tl;
-
- projInfo->pi_exprContext = econtext;
- projInfo->pi_slot = slot;
- /* since these are all int arrays, we need do just one palloc */
- workspace = (int *) palloc(len * 3 * sizeof(int));
- projInfo->pi_varSlotOffsets = varSlotOffsets = workspace;
- projInfo->pi_varNumbers = varNumbers = workspace + len;
- projInfo->pi_varOutputCols = varOutputCols = workspace + len * 2;
- projInfo->pi_lastInnerVar = 0;
- projInfo->pi_lastOuterVar = 0;
- projInfo->pi_lastScanVar = 0;
-
- /*
- * We separate the target list elements into simple Var references and
- * expressions which require the full ExecTargetList machinery. To be a
- * simple Var, a Var has to be a user attribute and not mismatch the
- * inputDesc. (Note: if there is a type mismatch then ExecEvalScalarVar
- * will probably throw an error at runtime, but we leave that to it.)
- */
- exprlist = NIL;
- numSimpleVars = 0;
- directMap = true;
- foreach(tl, targetList)
- {
- GenericExprState *gstate = (GenericExprState *) lfirst(tl);
- Var *variable = (Var *) gstate->arg->expr;
- bool isSimpleVar = false;
-
- if (variable != NULL &&
- IsA(variable, Var) &&
- variable->varattno > 0)
- {
- if (!inputDesc)
- isSimpleVar = true; /* can't check type, assume OK */
- else if (variable->varattno <= inputDesc->natts)
- {
- Form_pg_attribute attr;
-
- attr = inputDesc->attrs[variable->varattno - 1];
- if (!attr->attisdropped && variable->vartype == attr->atttypid)
- isSimpleVar = true;
- }
- }
-
- if (isSimpleVar)
- {
- TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber attnum = variable->varattno;
-
- varNumbers[numSimpleVars] = attnum;
- varOutputCols[numSimpleVars] = tle->resno;
- if (tle->resno != numSimpleVars + 1)
- directMap = false;
-
- switch (variable->varno)
- {
- case INNER_VAR:
- varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
- ecxt_innertuple);
- if (projInfo->pi_lastInnerVar < attnum)
- projInfo->pi_lastInnerVar = attnum;
- break;
-
- case OUTER_VAR:
- varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
- ecxt_outertuple);
- if (projInfo->pi_lastOuterVar < attnum)
- projInfo->pi_lastOuterVar = attnum;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default:
- varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
- ecxt_scantuple);
- if (projInfo->pi_lastScanVar < attnum)
- projInfo->pi_lastScanVar = attnum;
- break;
- }
- numSimpleVars++;
- }
- else
- {
- /* Not a simple variable, add it to generic targetlist */
- exprlist = lappend(exprlist, gstate);
- /* Examine expr to include contained Vars in lastXXXVar counts */
- get_last_attnums((Node *) variable, projInfo);
- }
- }
- projInfo->pi_targetlist = exprlist;
- projInfo->pi_numSimpleVars = numSimpleVars;
- projInfo->pi_directMap = directMap;
-
- if (exprlist == NIL)
- projInfo->pi_itemIsDone = NULL; /* not needed */
- else
- projInfo->pi_itemIsDone = (ExprDoneCond *)
- palloc(len * sizeof(ExprDoneCond));
-
- return projInfo;
-}
-
-/*
- * get_last_attnums: expression walker for ExecBuildProjectionInfo
- *
- * Update the lastXXXVar counts to be at least as large as the largest
- * attribute numbers found in the expression
- */
-static bool
-get_last_attnums(Node *node, ProjectionInfo *projInfo)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Var))
- {
- Var *variable = (Var *) node;
- AttrNumber attnum = variable->varattno;
-
- switch (variable->varno)
- {
- case INNER_VAR:
- if (projInfo->pi_lastInnerVar < attnum)
- projInfo->pi_lastInnerVar = attnum;
- break;
-
- case OUTER_VAR:
- if (projInfo->pi_lastOuterVar < attnum)
- projInfo->pi_lastOuterVar = attnum;
- break;
-
- /* INDEX_VAR is handled by default case */
-
- default:
- if (projInfo->pi_lastScanVar < attnum)
- projInfo->pi_lastScanVar = attnum;
- break;
- }
- return false;
- }
-
- /*
- * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
- * because those do not represent expressions to be evaluated within the
- * overall targetlist's econtext. GroupingFunc arguments are never
- * evaluated at all.
- */
- if (IsA(node, Aggref))
- return false;
- if (IsA(node, WindowFunc))
- return false;
- if (IsA(node, GroupingFunc))
- return false;
- return expression_tree_walker(node, get_last_attnums,
- (void *) projInfo);
-}
/* ----------------
* ExecAssignProjectionInfo
@@ -670,9 +489,10 @@ ExecAssignProjectionInfo(PlanState *planstate,
TupleDesc inputDesc)
{
planstate->ps_ProjInfo =
- ExecBuildProjectionInfo(planstate->targetlist,
+ ExecBuildProjectionInfo(planstate->plan->targetlist,
planstate->ps_ExprContext,
planstate->ps_ResultTupleSlot,
+ planstate,
inputDesc);
}
@@ -870,6 +690,36 @@ UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
}
/*
+ * executor_errposition
+ * Report an execution-time cursor position, if possible.
+ *
+ * This is expected to be used within an ereport() call. The return value
+ * is a dummy (always 0, in fact).
+ *
+ * The locations stored in parsetrees are byte offsets into the source string.
+ * We have to convert them to 1-based character indexes for reporting to
+ * clients. (We do things this way to avoid unnecessary overhead in the
+ * normal non-error case: computing character indexes would be much more
+ * expensive than storing token offsets.)
+ */
+int
+executor_errposition(EState *estate, int location)
+{
+ int pos;
+
+ /* No-op if location was not provided */
+ if (location < 0)
+ return 0;
+ /* Can't do anything if source text is not available */
+ if (estate == NULL || estate->es_sourceText == NULL)
+ return 0;
+ /* Convert offset to character number */
+ pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
+ /* And pass it to the ereport mechanism */
+ return errposition(pos);
+}
+
+/*
* Register a shutdown callback in an ExprContext.
*
* Shutdown callbacks will be called (in reverse order of registration)
@@ -965,3 +815,207 @@ ShutdownExprContext(ExprContext *econtext, bool isCommit)
MemoryContextSwitchTo(oldcontext);
}
+
+/*
+ * ExecLockNonLeafAppendTables
+ *
+ * Locks, if necessary, the tables indicated by the RT indexes contained in
+ * the partitioned_rels list. These are the non-leaf tables in the partition
+ * tree controlled by a given Append or MergeAppend node.
+ */
+void
+ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
+{
+ PlannedStmt *stmt = estate->es_plannedstmt;
+ ListCell *lc;
+
+ foreach(lc, partitioned_rels)
+ {
+ ListCell *l;
+ Index rti = lfirst_int(lc);
+ bool is_result_rel = false;
+ Oid relid = getrelid(rti, estate->es_range_table);
+
+ /* If this is a result relation, already locked in InitPlan */
+ foreach(l, stmt->nonleafResultRelations)
+ {
+ if (rti == lfirst_int(l))
+ {
+ is_result_rel = true;
+ break;
+ }
+ }
+
+ /*
+ * Not a result relation; check if there is a RowMark that requires
+ * taking a RowShareLock on this rel.
+ */
+ if (!is_result_rel)
+ {
+ PlanRowMark *rc = NULL;
+
+ foreach(l, stmt->rowMarks)
+ {
+ if (((PlanRowMark *) lfirst(l))->rti == rti)
+ {
+ rc = lfirst(l);
+ break;
+ }
+ }
+
+ if (rc && RowMarkRequiresRowShareLock(rc->markType))
+ LockRelationOid(relid, RowShareLock);
+ else
+ LockRelationOid(relid, AccessShareLock);
+ }
+ }
+}
+
+/*
+ * GetAttributeByName
+ * GetAttributeByNum
+ *
+ * These functions return the value of the requested attribute
+ * out of the given tuple Datum.
+ * C functions which take a tuple as an argument are expected
+ * to use these. Ex: overpaid(EMP) might call GetAttributeByNum().
+ * Note: these are actually rather slow because they do a typcache
+ * lookup on each call.
+ */
+Datum
+GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
+{
+ AttrNumber attrno;
+ Datum result;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupDesc;
+ HeapTupleData tmptup;
+ int i;
+
+ if (attname == NULL)
+ elog(ERROR, "invalid attribute name");
+
+ if (isNull == NULL)
+ elog(ERROR, "a NULL isNull pointer was passed");
+
+ if (tuple == NULL)
+ {
+ /* Kinda bogus but compatible with old behavior... */
+ *isNull = true;
+ return (Datum) 0;
+ }
+
+ tupType = HeapTupleHeaderGetTypeId(tuple);
+ tupTypmod = HeapTupleHeaderGetTypMod(tuple);
+ tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
+
+ attrno = InvalidAttrNumber;
+ for (i = 0; i < tupDesc->natts; i++)
+ {
+ if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0)
+ {
+ attrno = tupDesc->attrs[i]->attnum;
+ break;
+ }
+ }
+
+ if (attrno == InvalidAttrNumber)
+ elog(ERROR, "attribute \"%s\" does not exist", attname);
+
+ /*
+ * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
+ * the fields in the struct just in case user tries to inspect system
+ * columns.
+ */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+ ItemPointerSetInvalid(&(tmptup.t_self));
+ tmptup.t_tableOid = InvalidOid;
+ tmptup.t_data = tuple;
+
+ result = heap_getattr(&tmptup,
+ attrno,
+ tupDesc,
+ isNull);
+
+ ReleaseTupleDesc(tupDesc);
+
+ return result;
+}
+
+Datum
+GetAttributeByNum(HeapTupleHeader tuple,
+ AttrNumber attrno,
+ bool *isNull)
+{
+ Datum result;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupDesc;
+ HeapTupleData tmptup;
+
+ if (!AttributeNumberIsValid(attrno))
+ elog(ERROR, "invalid attribute number %d", attrno);
+
+ if (isNull == NULL)
+ elog(ERROR, "a NULL isNull pointer was passed");
+
+ if (tuple == NULL)
+ {
+ /* Kinda bogus but compatible with old behavior... */
+ *isNull = true;
+ return (Datum) 0;
+ }
+
+ tupType = HeapTupleHeaderGetTypeId(tuple);
+ tupTypmod = HeapTupleHeaderGetTypMod(tuple);
+ tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
+
+ /*
+ * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
+ * the fields in the struct just in case user tries to inspect system
+ * columns.
+ */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+ ItemPointerSetInvalid(&(tmptup.t_self));
+ tmptup.t_tableOid = InvalidOid;
+ tmptup.t_data = tuple;
+
+ result = heap_getattr(&tmptup,
+ attrno,
+ tupDesc,
+ isNull);
+
+ ReleaseTupleDesc(tupDesc);
+
+ return result;
+}
+
+/*
+ * Number of items in a tlist (including any resjunk items!)
+ */
+int
+ExecTargetListLength(List *targetlist)
+{
+ /* This used to be more complex, but fjoins are dead */
+ return list_length(targetlist);
+}
+
+/*
+ * Number of items in a tlist, not including any resjunk items
+ */
+int
+ExecCleanTargetListLength(List *targetlist)
+{
+ int len = 0;
+ ListCell *tl;
+
+ foreach(tl, targetlist)
+ {
+ TargetEntry *curTle = lfirst_node(TargetEntry, tl);
+
+ if (!curTle->resjunk)
+ len++;
+ }
+ return len;
+}
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 06b4a57656..3f40fa65ef 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -3,7 +3,7 @@
* functions.c
* Execution of SQL-language functions
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -70,7 +70,7 @@ typedef struct execution_state
ExecStatus status;
bool setsResult; /* true if this query produces func's result */
bool lazyEval; /* true if should fetch one row at a time */
- Node *stmt; /* PlannedStmt or utility statement */
+ PlannedStmt *stmt; /* plan for this query */
QueryDesc *qd; /* null unless status == RUN */
char *src; /* source query resulting in this state */
} execution_state;
@@ -486,7 +486,7 @@ init_execution_state(List *queryTree_list,
forboth(lc1, queryTree_list, lc3, querySource_list)
{
- List *qtlist = (List *) lfirst(lc1);
+ List *qtlist = lfirst_node(List, lc1);
char *querysource = (char *) lfirst(lc3);
execution_state *firstes = NULL;
execution_state *preves = NULL;
@@ -494,34 +494,52 @@ init_execution_state(List *queryTree_list,
foreach(lc2, qtlist)
{
- Query *queryTree = (Query *) lfirst(lc2);
- Node *stmt;
+ Query *queryTree = lfirst_node(Query, lc2);
+ PlannedStmt *stmt;
execution_state *newes;
- Assert(IsA(queryTree, Query));
-
/* Plan the query if needed */
if (queryTree->commandType == CMD_UTILITY)
- stmt = queryTree->utilityStmt;
+ {
+ /* Utility commands require no planning. */
+ stmt = makeNode(PlannedStmt);
+ stmt->commandType = CMD_UTILITY;
+ stmt->canSetTag = queryTree->canSetTag;
+ stmt->utilityStmt = queryTree->utilityStmt;
+ stmt->stmt_location = queryTree->stmt_location;
+ stmt->stmt_len = queryTree->stmt_len;
+ }
else
- stmt = (Node *) pg_plan_query(queryTree,
- fcache->readonly_func ? CURSOR_OPT_PARALLEL_OK : 0,
- NULL);
+ stmt = pg_plan_query(queryTree,
+ CURSOR_OPT_PARALLEL_OK,
+ NULL);
- /* Precheck all commands for validity in a function */
- if (IsA(stmt, TransactionStmt))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- /* translator: %s is a SQL statement name */
- errmsg("%s is not allowed in a SQL function",
- CreateCommandTag(stmt))));
+ /*
+ * Precheck all commands for validity in a function. This should
+ * generally match the restrictions spi.c applies.
+ */
+ if (stmt->commandType == CMD_UTILITY)
+ {
+ if (IsA(stmt->utilityStmt, CopyStmt) &&
+ ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot COPY to/from client in a SQL function")));
+
+ if (IsA(stmt->utilityStmt, TransactionStmt))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ /* translator: %s is a SQL statement name */
+ errmsg("%s is not allowed in a SQL function",
+ CreateCommandTag(stmt->utilityStmt))));
+ }
if (fcache->readonly_func && !CommandIsReadOnly(stmt))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function",
- CreateCommandTag(stmt))));
+ CreateCommandTag((Node *) stmt))));
#ifdef PGXC
if (IS_PGXC_LOCAL_COORDINATOR)
@@ -542,7 +560,7 @@ init_execution_state(List *queryTree_list,
#endif /* PGXC */
if (IsInParallelMode() && !CommandIsReadOnly(stmt))
- PreventCommandIfParallelMode(CreateCommandTag(stmt));
+ PreventCommandIfParallelMode(CreateCommandTag((Node *) stmt));
/* OK, build the execution_state for this query */
newes = (execution_state *) palloc(sizeof(execution_state));
@@ -587,15 +605,9 @@ init_execution_state(List *queryTree_list,
{
lasttages->setsResult = true;
if (lazyEvalOK &&
- IsA(lasttages->stmt, PlannedStmt))
- {
- PlannedStmt *ps = (PlannedStmt *) lasttages->stmt;
-
- if (ps->commandType == CMD_SELECT &&
- ps->utilityStmt == NULL &&
- !ps->hasModifyingCTE)
- fcache->lazyEval = lasttages->lazyEval = true;
- }
+ lasttages->stmt->commandType == CMD_SELECT &&
+ !lasttages->stmt->hasModifyingCTE)
+ fcache->lazyEval = lasttages->lazyEval = true;
}
return eslist;
@@ -628,9 +640,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
*/
fcontext = AllocSetContextCreate(finfo->fn_mcxt,
"SQL function data",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcontext = MemoryContextSwitchTo(fcontext);
@@ -725,14 +735,15 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
flat_query_list = NIL;
forboth(lc, raw_parsetree_list, lc2, querysource_list)
{
- Node *parsetree = (Node *) lfirst(lc);
+ RawStmt *parsetree = lfirst_node(RawStmt, lc);
char *querysource = (char *) lfirst(lc2);
List *queryTree_sublist;
queryTree_sublist = pg_analyze_and_rewrite_params(parsetree,
querysource,
(ParserSetupHook) sql_fn_parser_setup,
- fcache->pinfo);
+ fcache->pinfo,
+ NULL);
queryTree_list = lappend(queryTree_list, queryTree_sublist);
flat_query_list = list_concat(flat_query_list,
list_copy(queryTree_sublist));
@@ -824,22 +835,17 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
else
dest = None_Receiver;
- if (IsA(es->stmt, PlannedStmt))
- es->qd = CreateQueryDesc((PlannedStmt *) es->stmt,
- es->src,
- GetActiveSnapshot(),
- InvalidSnapshot,
- dest,
- fcache->paramLI, 0);
- else
- es->qd = CreateUtilityQueryDesc(es->stmt,
- es->src,
- GetActiveSnapshot(),
- dest,
- fcache->paramLI);
+ es->qd = CreateQueryDesc(es->stmt,
+ es->src,
+ GetActiveSnapshot(),
+ InvalidSnapshot,
+ dest,
+ fcache->paramLI,
+ es->qd ? es->qd->queryEnv : NULL,
+ 0);
/* Utility commands don't need Executor. */
- if (es->qd->utilitystmt == NULL)
+ if (es->qd->operation != CMD_UTILITY)
{
/*
* In lazyEval mode, do not let the executor set up an AfterTrigger
@@ -867,15 +873,13 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
{
bool result;
- if (es->qd->utilitystmt)
+ if (es->qd->operation == CMD_UTILITY)
{
- /* ProcessUtility needs the PlannedStmt for DECLARE CURSOR */
- ProcessUtility((es->qd->plannedstmt ?
- (Node *) es->qd->plannedstmt :
- es->qd->utilitystmt),
+ ProcessUtility(es->qd->plannedstmt,
es->src,
PROCESS_UTILITY_QUERY,
es->qd->params,
+ es->qd->queryEnv,
es->qd->dest,
#ifdef PGXC
false,
@@ -888,7 +892,7 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
/* Run regular commands to completion unless lazyEval */
uint64 count = (es->lazyEval) ? 1 : 0;
- ExecutorRun(es->qd, ForwardScanDirection, count);
+ ExecutorRun(es->qd, ForwardScanDirection, count, !fcache->returnsSet || !es->lazyEval);
/*
* If we requested run to completion OR there was no tuple returned,
@@ -908,7 +912,7 @@ postquel_end(execution_state *es)
es->status = F_EXEC_DONE;
/* Utility commands don't need Executor. */
- if (es->qd->utilitystmt == NULL)
+ if (es->qd->operation != CMD_UTILITY)
{
ExecutorFinish(es->qd);
ExecutorEnd(es->qd);
@@ -1312,7 +1316,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
rsi->returnMode = SFRM_Materialize;
rsi->setResult = fcache->tstore;
fcache->tstore = NULL;
- /* must copy desc because execQual will free it */
+ /* must copy desc because execSRF.c will free it */
if (fcache->junkFilter)
rsi->setDesc = CreateTupleDescCopy(fcache->junkFilter->jf_cleanTupType);
@@ -1584,7 +1588,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
parse = NULL;
foreach(lc, queryTreeList)
{
- Query *q = (Query *) lfirst(lc);
+ Query *q = lfirst_node(Query, lc);
if (q->canSetTag)
parse = q;
@@ -1602,8 +1606,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
* entities.
*/
if (parse &&
- parse->commandType == CMD_SELECT &&
- parse->utilityStmt == NULL)
+ parse->commandType == CMD_SELECT)
{
tlist_ptr = &parse->targetList;
tlist = parse->targetList;
diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c
index 2614bf451f..6ec96ec371 100644
--- a/src/backend/executor/instrument.c
+++ b/src/backend/executor/instrument.c
@@ -4,7 +4,7 @@
* functions for instrumentation of plan execution
*
*
- * Copyright (c) 2001-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2001-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/executor/instrument.c
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 8154522de4..1b94a66484 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -91,10 +91,13 @@
* transition value or a previous function result, and in either case its
* value need not be preserved. See int8inc() for an example. Notice that
* advance_transition_function() is coded to avoid a data copy step when
- * the previous transition value pointer is returned. Also, some
- * transition functions want to store working state in addition to the
- * nominal transition value; they can use the memory context returned by
- * AggCheckCallContext() to do that.
+ * the previous transition value pointer is returned. It is also possible
+ * to avoid repeated data copying when the transition value is an expanded
+ * object: to do that, the transition function must take care to return
+ * an expanded object that is in a child context of the memory context
+ * returned by AggCheckCallContext(). Also, some transition functions want
+ * to store working state in addition to the nominal transition value; they
+ * can use the memory context returned by AggCheckCallContext() to do that.
*
* Note: AggCheckCallContext() is available as of PostgreSQL 9.0. The
* AggState is available as context in earlier releases (back to 8.1),
@@ -119,12 +122,19 @@
* specific).
*
* Where more complex grouping sets are used, we break them down into
- * "phases", where each phase has a different sort order. During each
- * phase but the last, the input tuples are additionally stored in a
- * tuplesort which is keyed to the next phase's sort order; during each
- * phase but the first, the input tuples are drawn from the previously
- * sorted data. (The sorting of the data for the first phase is handled by
- * the planner, as it might be satisfied by underlying nodes.)
+ * "phases", where each phase has a different sort order (except phase 0
+ * which is reserved for hashing). During each phase but the last, the
+ * input tuples are additionally stored in a tuplesort which is keyed to the
+ * next phase's sort order; during each phase but the first, the input
+ * tuples are drawn from the previously sorted data. (The sorting of the
+ * data for the first phase is handled by the planner, as it might be
+ * satisfied by underlying nodes.)
+ *
+ * Hashing can be mixed with sorted grouping. To do this, we have an
+ * AGG_MIXED strategy that populates the hashtables during the first sorted
+ * phase, and switches to reading them out after completing all sort phases.
+ * We can also support AGG_HASHED with multiple hash tables and no sorting
+ * at all.
*
* From the perspective of aggregate transition and final functions, the
* only issue regarding grouping sets is this: a single call site (flinfo)
@@ -136,10 +146,57 @@
* sensitive to the grouping set for which the aggregate function is
* currently being called.
*
- * TODO: AGG_HASHED doesn't support multiple grouping sets yet.
+ * Plan structure:
+ *
+ * What we get from the planner is actually one "real" Agg node which is
+ * part of the plan tree proper, but which optionally has an additional list
+ * of Agg nodes hung off the side via the "chain" field. This is because an
+ * Agg node happens to be a convenient representation of all the data we
+ * need for grouping sets.
+ *
+ * For many purposes, we treat the "real" node as if it were just the first
+ * node in the chain. The chain must be ordered such that hashed entries
+ * come before sorted/plain entries; the real node is marked AGG_MIXED if
+ * there are both types present (in which case the real node describes one
+ * of the hashed groupings, other AGG_HASHED nodes may optionally follow in
+ * the chain, followed in turn by AGG_SORTED or (one) AGG_PLAIN node). If
+ * the real node is marked AGG_HASHED or AGG_SORTED, then all the chained
+ * nodes must be of the same type; if it is AGG_PLAIN, there can be no
+ * chained nodes.
+ *
+ * We collect all hashed nodes into a single "phase", numbered 0, and create
+ * a sorted phase (numbered 1..n) for each AGG_SORTED or AGG_PLAIN node.
+ * Phase 0 is allocated even if there are no hashes, but remains unused in
+ * that case.
+ *
+ * AGG_HASHED nodes actually refer to only a single grouping set each,
+ * because for each hashed grouping we need a separate grpColIdx and
+ * numGroups estimate. AGG_SORTED nodes represent a "rollup", a list of
+ * grouping sets that share a sort order. Each AGG_SORTED node other than
+ * the first one has an associated Sort node which describes the sort order
+ * to be used; the first sorted node takes its input from the outer subtree,
+ * which the planner has already arranged to provide ordered data.
+ *
+ * Memory and ExprContext usage:
+ *
+ * Because we're accumulating aggregate values across input rows, we need to
+ * use more memory contexts than just simple input/output tuple contexts.
+ * In fact, for a rollup, we need a separate context for each grouping set
+ * so that we can reset the inner (finer-grained) aggregates on their group
+ * boundaries while continuing to accumulate values for outer
+ * (coarser-grained) groupings. On top of this, we might be simultaneously
+ * populating hashtables; however, we only need one context for all the
+ * hashtables.
+ *
+ * So we create an array, aggcontexts, with an ExprContext for each grouping
+ * set in the largest rollup that we're going to process, and use the
+ * per-tuple memory context of those ExprContexts to store the aggregate
+ * transition values. hashcontext is the single context created to support
+ * all hash tables.
+ *
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -158,6 +215,7 @@
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
@@ -211,6 +269,9 @@ typedef struct AggStatePerTransData
*/
int numInputs;
+ /* offset of input columns in AggState->evalslot */
+ int inputoff;
+
/*
* Number of aggregated input columns to pass to the transfn. This
* includes the ORDER BY columns for ordered-set aggs, but not for plain
@@ -232,7 +293,6 @@ typedef struct AggStatePerTransData
/* ExprStates of the FILTER and argument expressions. */
ExprState *aggfilter; /* state of FILTER expression, if any */
- List *args; /* states of aggregated-argument expressions */
List *aggdirectargs; /* states of direct-argument expressions */
/*
@@ -289,19 +349,19 @@ typedef struct AggStatePerTransData
transtypeByVal;
/*
- * Stuff for evaluation of inputs. We used to just use ExecEvalExpr, but
- * with the addition of ORDER BY we now need at least a slot for passing
- * data to the sort object, which requires a tupledesc, so we might as
- * well go whole hog and use ExecProject too.
+ * Stuff for evaluation of aggregate inputs in cases where the aggregate
+ * requires sorted input. The arguments themselves will be evaluated via
+ * AggState->evalslot/evalproj for all aggregates at once, but we only
+ * want to sort the relevant columns for individual aggregates.
*/
- TupleDesc evaldesc; /* descriptor of input tuples */
- ProjectionInfo *evalproj; /* projection machinery */
+ TupleDesc sortdesc; /* descriptor of input tuples */
/*
* Slots for holding the evaluated input arguments. These are set up
- * during ExecInitAgg() and then used for each input row.
+ * during ExecInitAgg() and then used for each input row requiring
+ * processing besides what's done in AggState->evalproj.
*/
- TupleTableSlot *evalslot; /* current input tuple */
+ TupleTableSlot *sortslot; /* current input tuple */
TupleTableSlot *uniqslot; /* used for multi-column DISTINCT */
/*
@@ -412,7 +472,7 @@ typedef struct AggStatePerGroupData
* NULL and not auto-replace it with a later input value. Only the first
* non-NULL input will be auto-substituted.
*/
-} AggStatePerGroupData;
+} AggStatePerGroupData;
/*
* AggStatePerPhaseData - per-grouping-set-phase state
@@ -427,6 +487,7 @@ typedef struct AggStatePerGroupData
*/
typedef struct AggStatePerPhaseData
{
+ AggStrategy aggstrategy; /* strategy for this phase */
int numsets; /* number of grouping sets (or 0) */
int *gset_lengths; /* lengths of grouping sets */
Bitmapset **grouped_cols; /* column groupings for rollup */
@@ -436,20 +497,29 @@ typedef struct AggStatePerPhaseData
} AggStatePerPhaseData;
/*
- * To implement hashed aggregation, we need a hashtable that stores a
- * representative tuple and an array of AggStatePerGroup structs for each
- * distinct set of GROUP BY column values. We compute the hash key from
- * the GROUP BY columns.
+ * AggStatePerHashData - per-hashtable state
+ *
+ * When doing grouping sets with hashing, we have one of these for each
+ * grouping set. (When doing hashing without grouping sets, we have just one of
+ * them.)
*/
-typedef struct AggHashEntryData *AggHashEntry;
-
-typedef struct AggHashEntryData
+typedef struct AggStatePerHashData
{
- TupleHashEntryData shared; /* common header for hash table entries */
- /* per-aggregate transition status array */
- AggStatePerGroupData pergroup[FLEXIBLE_ARRAY_MEMBER];
-} AggHashEntryData;
+ TupleHashTable hashtable; /* hash table with one entry per group */
+ TupleHashIterator hashiter; /* for iterating through hash table */
+ TupleTableSlot *hashslot; /* slot for loading hash table */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ FmgrInfo *eqfunctions; /* per-grouping-field equality fns */
+ int numCols; /* number of hash key columns */
+ int numhashGrpCols; /* number of columns in hash table */
+ int largestGrpColIdx; /* largest col required for hashing */
+ AttrNumber *hashGrpColIdxInput; /* hash col indices in input slot */
+ AttrNumber *hashGrpColIdxHash; /* indices in hashtbl tuples */
+ Agg *aggnode; /* original Agg node, for numGroups etc. */
+} AggStatePerHashData;
+
+static void select_current_set(AggState *aggstate, int setno, bool is_hash);
static void initialize_phase(AggState *aggstate, int newphase);
static TupleTableSlot *fetch_input_tuple(AggState *aggstate);
static void initialize_aggregates(AggState *aggstate,
@@ -458,7 +528,8 @@ static void initialize_aggregates(AggState *aggstate,
static void advance_transition_function(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate);
-static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
+static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup,
+ AggStatePerGroup *pergroups);
static void advance_combine_function(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate);
@@ -482,20 +553,19 @@ static void prepare_projection_slot(AggState *aggstate,
int currentSet);
static void finalize_aggregates(AggState *aggstate,
AggStatePerAgg peragg,
- AggStatePerGroup pergroup,
- int currentSet);
+ AggStatePerGroup pergroup);
static TupleTableSlot *project_aggregates(AggState *aggstate);
static Bitmapset *find_unaggregated_cols(AggState *aggstate);
static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
static void build_hash_table(AggState *aggstate);
-static AggHashEntry lookup_hash_entry(AggState *aggstate,
- TupleTableSlot *inputslot);
+static TupleHashEntryData *lookup_hash_entry(AggState *aggstate);
+static AggStatePerGroup *lookup_hash_entries(AggState *aggstate);
static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
static void agg_fill_hash_table(AggState *aggstate);
static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
static void build_pertrans_for_aggref(AggStatePerTrans pertrans,
- AggState *aggsate, EState *estate,
+ AggState *aggstate, EState *estate,
Aggref *aggref, Oid aggtransfn, Oid aggtranstype,
Oid aggserialfn, Oid aggdeserialfn,
Datum initValue, bool initValueIsNull,
@@ -510,13 +580,31 @@ static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
/*
- * Switch to phase "newphase", which must either be 0 (to reset) or
+ * Select the current grouping set; affects current_set and
+ * curaggcontext.
+ */
+static void
+select_current_set(AggState *aggstate, int setno, bool is_hash)
+{
+ if (is_hash)
+ aggstate->curaggcontext = aggstate->hashcontext;
+ else
+ aggstate->curaggcontext = aggstate->aggcontexts[setno];
+
+ aggstate->current_set = setno;
+}
+
+/*
+ * Switch to phase "newphase", which must either be 0 or 1 (to reset) or
* current_phase + 1. Juggle the tuplesorts accordingly.
+ *
+ * Phase 0 is for hashing, which we currently handle last in the AGG_MIXED
+ * case, so when entering phase 0, all we need to do is drop open sorts.
*/
static void
initialize_phase(AggState *aggstate, int newphase)
{
- Assert(newphase == 0 || newphase == aggstate->current_phase + 1);
+ Assert(newphase <= 1 || newphase == aggstate->current_phase + 1);
/*
* Whatever the previous state, we're now done with whatever input
@@ -528,7 +616,7 @@ initialize_phase(AggState *aggstate, int newphase)
aggstate->sort_in = NULL;
}
- if (newphase == 0)
+ if (newphase <= 1)
{
/*
* Discard any existing output tuplesort.
@@ -555,7 +643,7 @@ initialize_phase(AggState *aggstate, int newphase)
* If this isn't the last phase, we need to sort appropriately for the
* next phase in sequence.
*/
- if (newphase < aggstate->numphases - 1)
+ if (newphase > 0 && newphase < aggstate->numphases - 1)
{
Sort *sortnode = aggstate->phases[newphase + 1].sortnode;
PlanState *outerNode = outerPlanState(aggstate);
@@ -576,9 +664,12 @@ initialize_phase(AggState *aggstate, int newphase)
}
/*
- * Fetch a tuple from either the outer plan (for phase 0) or from the sorter
+ * Fetch a tuple from either the outer plan (for phase 1) or from the sorter
* populated by the previous phase. Copy it to the sorter for the next phase
* if any.
+ *
+ * Callers cannot rely on memory for tuple in returned slot remaining valid
+ * past any subsequently fetched tuple.
*/
static TupleTableSlot *
fetch_input_tuple(AggState *aggstate)
@@ -587,8 +678,8 @@ fetch_input_tuple(AggState *aggstate)
if (aggstate->sort_in)
{
- if (!tuplesort_gettupleslot(aggstate->sort_in, true, aggstate->sort_slot,
- NULL))
+ if (!tuplesort_gettupleslot(aggstate->sort_in, true, false,
+ aggstate->sort_slot, NULL))
return NULL;
slot = aggstate->sort_slot;
}
@@ -604,8 +695,8 @@ fetch_input_tuple(AggState *aggstate)
/*
* (Re)Initialize an individual aggregate.
*
- * This function handles only one grouping set (already set in
- * aggstate->current_set).
+ * This function handles only one grouping set, already set in
+ * aggstate->current_set.
*
* When called, CurrentMemoryContext should be the per-query context.
*/
@@ -633,14 +724,14 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
*/
if (pertrans->numInputs == 1)
pertrans->sortstates[aggstate->current_set] =
- tuplesort_begin_datum(pertrans->evaldesc->attrs[0]->atttypid,
+ tuplesort_begin_datum(pertrans->sortdesc->attrs[0]->atttypid,
pertrans->sortOperators[0],
pertrans->sortCollations[0],
pertrans->sortNullsFirst[0],
work_mem, false);
else
pertrans->sortstates[aggstate->current_set] =
- tuplesort_begin_heap(pertrans->evaldesc,
+ tuplesort_begin_heap(pertrans->sortdesc,
pertrans->numSortCols,
pertrans->sortColIdx,
pertrans->sortOperators,
@@ -662,7 +753,7 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
MemoryContext oldContext;
oldContext = MemoryContextSwitchTo(
- aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
+ aggstate->curaggcontext->ecxt_per_tuple_memory);
pergroupstate->transValue = datumCopy(pertrans->initValue,
pertrans->transtypeByVal,
pertrans->transtypeLen);
@@ -685,8 +776,9 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
*
* If there are multiple grouping sets, we initialize only the first numReset
* of them (the grouping sets are ordered so that the most specific one, which
- * is reset most often, is first). As a convenience, if numReset is < 1, we
- * reinitialize all sets.
+ * is reset most often, is first). As a convenience, if numReset is 0, we
+ * reinitialize all sets. numReset is -1 to initialize a hashtable entry, in
+ * which case the caller must have used select_current_set appropriately.
*
* When called, CurrentMemoryContext should be the per-query context.
*/
@@ -698,25 +790,37 @@ initialize_aggregates(AggState *aggstate,
int transno;
int numGroupingSets = Max(aggstate->phase->numsets, 1);
int setno = 0;
+ int numTrans = aggstate->numtrans;
AggStatePerTrans transstates = aggstate->pertrans;
- if (numReset < 1)
+ if (numReset == 0)
numReset = numGroupingSets;
- for (transno = 0; transno < aggstate->numtrans; transno++)
+ for (transno = 0; transno < numTrans; transno++)
{
AggStatePerTrans pertrans = &transstates[transno];
- for (setno = 0; setno < numReset; setno++)
+ if (numReset < 0)
{
AggStatePerGroup pergroupstate;
- pergroupstate = &pergroup[transno + (setno * (aggstate->numtrans))];
-
- aggstate->current_set = setno;
+ pergroupstate = &pergroup[transno];
initialize_aggregate(aggstate, pertrans, pergroupstate);
}
+ else
+ {
+ for (setno = 0; setno < numReset; setno++)
+ {
+ AggStatePerGroup pergroupstate;
+
+ pergroupstate = &pergroup[transno + (setno * numTrans)];
+
+ select_current_set(aggstate, setno, false);
+
+ initialize_aggregate(aggstate, pertrans, pergroupstate);
+ }
+ }
}
}
@@ -766,7 +870,7 @@ advance_transition_function(AggState *aggstate,
* do not need to pfree the old transValue, since it's NULL.
*/
oldContext = MemoryContextSwitchTo(
- aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
+ aggstate->curaggcontext->ecxt_per_tuple_memory);
pergroupstate->transValue = datumCopy(fcinfo->arg[1],
pertrans->transtypeByVal,
pertrans->transtypeLen);
@@ -806,21 +910,36 @@ advance_transition_function(AggState *aggstate,
/*
* If pass-by-ref datatype, must copy the new value into aggcontext and
- * pfree the prior transValue. But if transfn returned a pointer to its
- * first input, we don't need to do anything.
+ * free the prior transValue. But if transfn returned a pointer to its
+ * first input, we don't need to do anything. Also, if transfn returned a
+ * pointer to a R/W expanded object that is already a child of the
+ * aggcontext, assume we can adopt that value without copying it.
*/
if (!pertrans->transtypeByVal &&
DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
{
if (!fcinfo->isnull)
{
- MemoryContextSwitchTo(aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
- newVal = datumCopy(newVal,
- pertrans->transtypeByVal,
- pertrans->transtypeLen);
+ MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory);
+ if (DatumIsReadWriteExpandedObject(newVal,
+ false,
+ pertrans->transtypeLen) &&
+ MemoryContextGetParent(DatumGetEOHP(newVal)->eoh_context) == CurrentMemoryContext)
+ /* do nothing */ ;
+ else
+ newVal = datumCopy(newVal,
+ pertrans->transtypeByVal,
+ pertrans->transtypeLen);
}
if (!pergroupstate->transValueIsNull)
- pfree(DatumGetPointer(pergroupstate->transValue));
+ {
+ if (DatumIsReadWriteExpandedObject(pergroupstate->transValue,
+ false,
+ pertrans->transtypeLen))
+ DeleteExpandedObject(pergroupstate->transValue);
+ else
+ pfree(DatumGetPointer(pergroupstate->transValue));
+ }
}
pergroupstate->transValue = newVal;
@@ -832,18 +951,27 @@ advance_transition_function(AggState *aggstate,
/*
* Advance each aggregate transition state for one input tuple. The input
* tuple has been stored in tmpcontext->ecxt_outertuple, so that it is
- * accessible to ExecEvalExpr. pergroup is the array of per-group structs to
- * use (this might be in a hashtable entry).
+ * accessible to ExecEvalExpr.
+ *
+ * We have two sets of transition states to handle: one for sorted aggregation
+ * and one for hashed; we do them both here, to avoid multiple evaluation of
+ * the inputs.
*
* When called, CurrentMemoryContext should be the per-query context.
*/
static void
-advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
+advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGroup *pergroups)
{
int transno;
int setno = 0;
int numGroupingSets = Max(aggstate->phase->numsets, 1);
+ int numHashes = aggstate->num_hashes;
int numTrans = aggstate->numtrans;
+ TupleTableSlot *slot = aggstate->evalslot;
+
+ /* compute input for all aggregates */
+ if (aggstate->evalproj)
+ aggstate->evalslot = ExecProject(aggstate->evalproj);
for (transno = 0; transno < numTrans; transno++)
{
@@ -851,7 +979,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
ExprState *filter = pertrans->aggfilter;
int numTransInputs = pertrans->numTransInputs;
int i;
- TupleTableSlot *slot;
+ int inputoff = pertrans->inputoff;
/* Skip anything FILTERed out */
if (filter)
@@ -860,18 +988,16 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
bool isnull;
res = ExecEvalExprSwitchContext(filter, aggstate->tmpcontext,
- &isnull, NULL);
+ &isnull);
if (isnull || !DatumGetBool(res))
continue;
}
- /* Evaluate the current input expressions for this aggregate */
- slot = ExecProject(pertrans->evalproj, NULL);
-
if (pertrans->numSortCols > 0)
{
/* DISTINCT and/or ORDER BY case */
- Assert(slot->tts_nvalid == pertrans->numInputs);
+ Assert(slot->tts_nvalid >= (pertrans->numInputs + inputoff));
+ Assert(!pergroups);
/*
* If the transfn is strict, we want to check for nullity before
@@ -884,7 +1010,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
{
for (i = 0; i < numTransInputs; i++)
{
- if (slot->tts_isnull[i])
+ if (slot->tts_isnull[i + inputoff])
break;
}
if (i < numTransInputs)
@@ -896,10 +1022,25 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
/* OK, put the tuple into the tuplesort object */
if (pertrans->numInputs == 1)
tuplesort_putdatum(pertrans->sortstates[setno],
- slot->tts_values[0],
- slot->tts_isnull[0]);
+ slot->tts_values[inputoff],
+ slot->tts_isnull[inputoff]);
else
- tuplesort_puttupleslot(pertrans->sortstates[setno], slot);
+ {
+ /*
+ * Copy slot contents, starting from inputoff, into sort
+ * slot.
+ */
+ ExecClearTuple(pertrans->sortslot);
+ memcpy(pertrans->sortslot->tts_values,
+ &slot->tts_values[inputoff],
+ pertrans->numInputs * sizeof(Datum));
+ memcpy(pertrans->sortslot->tts_isnull,
+ &slot->tts_isnull[inputoff],
+ pertrans->numInputs * sizeof(bool));
+ pertrans->sortslot->tts_nvalid = pertrans->numInputs;
+ ExecStoreVirtualTuple(pertrans->sortslot);
+ tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
+ }
}
}
else
@@ -909,20 +1050,44 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
/* Load values into fcinfo */
/* Start from 1, since the 0th arg will be the transition value */
- Assert(slot->tts_nvalid >= numTransInputs);
+ Assert(slot->tts_nvalid >= (numTransInputs + inputoff));
+
for (i = 0; i < numTransInputs; i++)
{
- fcinfo->arg[i + 1] = slot->tts_values[i];
- fcinfo->argnull[i + 1] = slot->tts_isnull[i];
+ fcinfo->arg[i + 1] = slot->tts_values[i + inputoff];
+ fcinfo->argnull[i + 1] = slot->tts_isnull[i + inputoff];
}
- for (setno = 0; setno < numGroupingSets; setno++)
+ if (pergroup)
{
- AggStatePerGroup pergroupstate = &pergroup[transno + (setno * numTrans)];
+ /* advance transition states for ordered grouping */
- aggstate->current_set = setno;
+ for (setno = 0; setno < numGroupingSets; setno++)
+ {
+ AggStatePerGroup pergroupstate;
+
+ select_current_set(aggstate, setno, false);
+
+ pergroupstate = &pergroup[transno + (setno * numTrans)];
- advance_transition_function(aggstate, pertrans, pergroupstate);
+ advance_transition_function(aggstate, pertrans, pergroupstate);
+ }
+ }
+
+ if (pergroups)
+ {
+ /* advance transition states for hashed grouping */
+
+ for (setno = 0; setno < numHashes; setno++)
+ {
+ AggStatePerGroup pergroupstate;
+
+ select_current_set(aggstate, setno, true);
+
+ pergroupstate = &pergroups[setno][transno];
+
+ advance_transition_function(aggstate, pertrans, pergroupstate);
+ }
}
}
}
@@ -940,20 +1105,22 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
{
int transno;
int numTrans = aggstate->numtrans;
+ TupleTableSlot *slot;
/* combine not supported with grouping sets */
- Assert(aggstate->phase->numsets == 0);
+ Assert(aggstate->phase->numsets <= 1);
+
+ /* compute input for all aggregates */
+ slot = ExecProject(aggstate->evalproj);
for (transno = 0; transno < numTrans; transno++)
{
AggStatePerTrans pertrans = &aggstate->pertrans[transno];
AggStatePerGroup pergroupstate = &pergroup[transno];
- TupleTableSlot *slot;
FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ int inputoff = pertrans->inputoff;
- /* Evaluate the current input expressions for this aggregate */
- slot = ExecProject(pertrans->evalproj, NULL);
- Assert(slot->tts_nvalid >= 1);
+ Assert(slot->tts_nvalid > inputoff);
/*
* deserialfn_oid will be set if we must deserialize the input state
@@ -962,18 +1129,18 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
if (OidIsValid(pertrans->deserialfn_oid))
{
/* Don't call a strict deserialization function with NULL input */
- if (pertrans->deserialfn.fn_strict && slot->tts_isnull[0])
+ if (pertrans->deserialfn.fn_strict && slot->tts_isnull[inputoff])
{
- fcinfo->arg[1] = slot->tts_values[0];
- fcinfo->argnull[1] = slot->tts_isnull[0];
+ fcinfo->arg[1] = slot->tts_values[inputoff];
+ fcinfo->argnull[1] = slot->tts_isnull[inputoff];
}
else
{
FunctionCallInfo dsinfo = &pertrans->deserialfn_fcinfo;
MemoryContext oldContext;
- dsinfo->arg[0] = slot->tts_values[0];
- dsinfo->argnull[0] = slot->tts_isnull[0];
+ dsinfo->arg[0] = slot->tts_values[inputoff];
+ dsinfo->argnull[0] = slot->tts_isnull[inputoff];
/* Dummy second argument for type-safety reasons */
dsinfo->arg[1] = PointerGetDatum(NULL);
dsinfo->argnull[1] = false;
@@ -992,8 +1159,8 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
}
else
{
- fcinfo->arg[1] = slot->tts_values[0];
- fcinfo->argnull[1] = slot->tts_isnull[0];
+ fcinfo->arg[1] = slot->tts_values[inputoff];
+ fcinfo->argnull[1] = slot->tts_isnull[inputoff];
}
advance_combine_function(aggstate, pertrans, pergroupstate);
@@ -1034,7 +1201,7 @@ advance_combine_function(AggState *aggstate,
if (!pertrans->transtypeByVal)
{
oldContext = MemoryContextSwitchTo(
- aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
+ aggstate->curaggcontext->ecxt_per_tuple_memory);
pergroupstate->transValue = datumCopy(fcinfo->arg[1],
pertrans->transtypeByVal,
pertrans->transtypeLen);
@@ -1068,21 +1235,37 @@ advance_combine_function(AggState *aggstate,
/*
* If pass-by-ref datatype, must copy the new value into aggcontext and
- * pfree the prior transValue. But if the combine function returned a
- * pointer to its first input, we don't need to do anything.
+ * free the prior transValue. But if the combine function returned a
+ * pointer to its first input, we don't need to do anything. Also, if the
+ * combine function returned a pointer to a R/W expanded object that is
+ * already a child of the aggcontext, assume we can adopt that value
+ * without copying it.
*/
if (!pertrans->transtypeByVal &&
DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
{
if (!fcinfo->isnull)
{
- MemoryContextSwitchTo(aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
- newVal = datumCopy(newVal,
- pertrans->transtypeByVal,
- pertrans->transtypeLen);
+ MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory);
+ if (DatumIsReadWriteExpandedObject(newVal,
+ false,
+ pertrans->transtypeLen) &&
+ MemoryContextGetParent(DatumGetEOHP(newVal)->eoh_context) == CurrentMemoryContext)
+ /* do nothing */ ;
+ else
+ newVal = datumCopy(newVal,
+ pertrans->transtypeByVal,
+ pertrans->transtypeLen);
}
if (!pergroupstate->transValueIsNull)
- pfree(DatumGetPointer(pergroupstate->transValue));
+ {
+ if (DatumIsReadWriteExpandedObject(pergroupstate->transValue,
+ false,
+ pertrans->transtypeLen))
+ DeleteExpandedObject(pergroupstate->transValue);
+ else
+ pfree(DatumGetPointer(pergroupstate->transValue));
+ }
}
pergroupstate->transValue = newVal;
@@ -1214,7 +1397,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
{
MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
- TupleTableSlot *slot1 = pertrans->evalslot;
+ TupleTableSlot *slot1 = pertrans->sortslot;
TupleTableSlot *slot2 = pertrans->uniqslot;
int numTransInputs = pertrans->numTransInputs;
int numDistinctCols = pertrans->numDistinctCols;
@@ -1230,7 +1413,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
ExecClearTuple(slot2);
while (tuplesort_gettupleslot(pertrans->sortstates[aggstate->current_set],
- true, slot1, &newAbbrevVal))
+ true, true, slot1, &newAbbrevVal))
{
/*
* Extract the first numTransInputs columns as datums to pass to the
@@ -1326,8 +1509,7 @@ finalize_aggregate(AggState *aggstate,
fcinfo.arg[i] = ExecEvalExpr(expr,
aggstate->ss.ps.ps_ExprContext,
- &fcinfo.argnull[i],
- NULL);
+ &fcinfo.argnull[i]);
anynull |= fcinfo.argnull[i];
i++;
}
@@ -1348,7 +1530,9 @@ finalize_aggregate(AggState *aggstate,
(void *) aggstate, NULL);
/* Fill in the transition state value */
- fcinfo.arg[0] = pergroupstate->transValue;
+ fcinfo.arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
+ pergroupstate->transValueIsNull,
+ pertrans->transtypeLen);
fcinfo.argnull[0] = pergroupstate->transValueIsNull;
anynull |= pergroupstate->transValueIsNull;
@@ -1375,6 +1559,7 @@ finalize_aggregate(AggState *aggstate,
}
else
{
+ /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
*resultVal = pergroupstate->transValue;
*resultIsNull = pergroupstate->transValueIsNull;
}
@@ -1425,7 +1610,9 @@ finalize_partialaggregate(AggState *aggstate,
{
FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo;
- fcinfo->arg[0] = pergroupstate->transValue;
+ fcinfo->arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
+ pergroupstate->transValueIsNull,
+ pertrans->transtypeLen);
fcinfo->argnull[0] = pergroupstate->transValueIsNull;
*resultVal = FunctionCallInvoke(fcinfo);
@@ -1434,6 +1621,7 @@ finalize_partialaggregate(AggState *aggstate,
}
else
{
+ /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
*resultVal = pergroupstate->transValue;
*resultIsNull = pergroupstate->transValueIsNull;
}
@@ -1512,38 +1700,38 @@ prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet
/*
* Compute the final value of all aggregates for one group.
*
- * This function handles only one grouping set at a time.
+ * This function handles only one grouping set at a time, which the caller must
+ * have selected. It's also the caller's responsibility to adjust the supplied
+ * pergroup parameter to point to the current set's transvalues.
*
* Results are stored in the output econtext aggvalues/aggnulls.
*/
static void
finalize_aggregates(AggState *aggstate,
AggStatePerAgg peraggs,
- AggStatePerGroup pergroup,
- int currentSet)
+ AggStatePerGroup pergroup)
{
ExprContext *econtext = aggstate->ss.ps.ps_ExprContext;
Datum *aggvalues = econtext->ecxt_aggvalues;
bool *aggnulls = econtext->ecxt_aggnulls;
int aggno;
+ int transno;
- Assert(currentSet == 0 ||
- ((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
-
- aggstate->current_set = currentSet;
-
- for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+ /*
+ * If there were any DISTINCT and/or ORDER BY aggregates, sort their
+ * inputs and run the transition functions.
+ */
+ for (transno = 0; transno < aggstate->numtrans; transno++)
{
- AggStatePerAgg peragg = &peraggs[aggno];
- int transno = peragg->transno;
AggStatePerTrans pertrans = &aggstate->pertrans[transno];
AggStatePerGroup pergroupstate;
- pergroupstate = &pergroup[transno + (currentSet * (aggstate->numtrans))];
+ pergroupstate = &pergroup[transno];
if (pertrans->numSortCols > 0)
{
- Assert(((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
+ Assert(aggstate->aggstrategy != AGG_HASHED &&
+ aggstate->aggstrategy != AGG_MIXED);
if (pertrans->numInputs == 1)
process_ordered_aggregate_single(aggstate,
@@ -1554,6 +1742,18 @@ finalize_aggregates(AggState *aggstate,
pertrans,
pergroupstate);
}
+ }
+
+ /*
+ * Run the final functions.
+ */
+ for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+ {
+ AggStatePerAgg peragg = &peraggs[aggno];
+ int transno = peragg->transno;
+ AggStatePerGroup pergroupstate;
+
+ pergroupstate = &pergroup[transno];
if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
finalize_partialaggregate(aggstate, peragg, pergroupstate,
@@ -1567,7 +1767,7 @@ finalize_aggregates(AggState *aggstate,
/*
* Project the result of a group (whose aggs have already been calculated by
* finalize_aggregates). Returns the result slot, or NULL if no row is
- * projected (suppressed by qual or by an empty SRF).
+ * projected (suppressed by qual).
*/
static TupleTableSlot *
project_aggregates(AggState *aggstate)
@@ -1577,23 +1777,13 @@ project_aggregates(AggState *aggstate)
/*
* Check the qual (HAVING clause); if the group does not match, ignore it.
*/
- if (ExecQual(aggstate->ss.ps.qual, econtext, false))
+ if (ExecQual(aggstate->ss.ps.qual, econtext))
{
/*
- * Form and return or store a projection tuple using the aggregate
- * results and the representative input tuple.
+ * Form and return projection tuple using the aggregate results and
+ * the representative input tuple.
*/
- ExprDoneCond isDone;
- TupleTableSlot *result;
-
- result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- aggstate->ss.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(aggstate->ss.ps.ps_ProjInfo);
}
else
InstrCountFiltered1(aggstate, 1);
@@ -1645,78 +1835,162 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
}
/*
- * Initialize the hash table to empty.
+ * Initialize the hash table(s) to empty.
+ *
+ * To implement hashed aggregation, we need a hashtable that stores a
+ * representative tuple and an array of AggStatePerGroup structs for each
+ * distinct set of GROUP BY column values. We compute the hash key from the
+ * GROUP BY columns. The per-group data is allocated in lookup_hash_entry(),
+ * for each entry.
+ *
+ * We have a separate hashtable and associated perhash data structure for each
+ * grouping set for which we're doing hashing.
*
- * The hash table always lives in the aggcontext memory context.
+ * The hash tables always live in the hashcontext's per-tuple memory context
+ * (there is only one of these for all tables together, since they are all
+ * reset at the same time).
*/
static void
build_hash_table(AggState *aggstate)
{
- Agg *node = (Agg *) aggstate->ss.ps.plan;
MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
- Size entrysize;
+ Size additionalsize;
+ int i;
- Assert(node->aggstrategy == AGG_HASHED);
- Assert(node->numGroups > 0);
+ Assert(aggstate->aggstrategy == AGG_HASHED || aggstate->aggstrategy == AGG_MIXED);
- entrysize = offsetof(AggHashEntryData, pergroup) +
- aggstate->numaggs * sizeof(AggStatePerGroupData);
+ additionalsize = aggstate->numtrans * sizeof(AggStatePerGroupData);
- aggstate->hashtable = BuildTupleHashTable(node->numCols,
- node->grpColIdx,
- aggstate->phase->eqfunctions,
- aggstate->hashfunctions,
- node->numGroups,
- entrysize,
- aggstate->aggcontexts[0]->ecxt_per_tuple_memory,
- tmpmem);
+ for (i = 0; i < aggstate->num_hashes; ++i)
+ {
+ AggStatePerHash perhash = &aggstate->perhash[i];
+
+ Assert(perhash->aggnode->numGroups > 0);
+
+ perhash->hashtable = BuildTupleHashTable(perhash->numCols,
+ perhash->hashGrpColIdxHash,
+ perhash->eqfunctions,
+ perhash->hashfunctions,
+ perhash->aggnode->numGroups,
+ additionalsize,
+ aggstate->hashcontext->ecxt_per_tuple_memory,
+ tmpmem,
+ DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
+ }
}
/*
- * Create a list of the tuple columns that actually need to be stored in
- * hashtable entries. The incoming tuples from the child plan node will
- * contain grouping columns, other columns referenced in our targetlist and
- * qual, columns used to compute the aggregate functions, and perhaps just
- * junk columns we don't use at all. Only columns of the first two types
- * need to be stored in the hashtable, and getting rid of the others can
- * make the table entries significantly smaller. To avoid messing up Var
- * numbering, we keep the same tuple descriptor for hashtable entries as the
- * incoming tuples have, but set unwanted columns to NULL in the tuples that
- * go into the table.
- *
- * To eliminate duplicates, we build a bitmapset of the needed columns, then
- * convert it to an integer list (cheaper to scan at runtime). The list is
- * in decreasing order so that the first entry is the largest;
- * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
- * Note that the list is preserved over ExecReScanAgg, so we allocate it in
- * the per-query context (unlike the hash table itself).
- *
- * Note: at present, searching the tlist/qual is not really necessary since
- * the parser should disallow any unaggregated references to ungrouped
- * columns. However, the search will be needed when we add support for
- * SQL99 semantics that allow use of "functionally dependent" columns that
- * haven't been explicitly grouped by.
+ * Compute columns that actually need to be stored in hashtable entries. The
+ * incoming tuples from the child plan node will contain grouping columns,
+ * other columns referenced in our targetlist and qual, columns used to
+ * compute the aggregate functions, and perhaps just junk columns we don't use
+ * at all. Only columns of the first two types need to be stored in the
+ * hashtable, and getting rid of the others can make the table entries
+ * significantly smaller. The hashtable only contains the relevant columns,
+ * and is packed/unpacked in lookup_hash_entry() / agg_retrieve_hash_table()
+ * into the format of the normal input descriptor.
+ *
+ * Additional columns, in addition to the columns grouped by, come from two
+ * sources: Firstly functionally dependent columns that we don't need to group
+ * by themselves, and secondly ctids for row-marks.
+ *
+ * To eliminate duplicates, we build a bitmapset of the needed columns, and
+ * then build an array of the columns included in the hashtable. Note that
+ * the array is preserved over ExecReScanAgg, so we allocate it in the
+ * per-query context (unlike the hash table itself).
*/
-static List *
+static void
find_hash_columns(AggState *aggstate)
{
- Agg *node = (Agg *) aggstate->ss.ps.plan;
- Bitmapset *colnos;
- List *collist;
- int i;
+ Bitmapset *base_colnos;
+ List *outerTlist = outerPlanState(aggstate)->plan->targetlist;
+ int numHashes = aggstate->num_hashes;
+ int j;
/* Find Vars that will be needed in tlist and qual */
- colnos = find_unaggregated_cols(aggstate);
- /* Add in all the grouping columns */
- for (i = 0; i < node->numCols; i++)
- colnos = bms_add_member(colnos, node->grpColIdx[i]);
- /* Convert to list, using lcons so largest element ends up first */
- collist = NIL;
- while ((i = bms_first_member(colnos)) >= 0)
- collist = lcons_int(i, collist);
- bms_free(colnos);
-
- return collist;
+ base_colnos = find_unaggregated_cols(aggstate);
+
+ for (j = 0; j < numHashes; ++j)
+ {
+ AggStatePerHash perhash = &aggstate->perhash[j];
+ Bitmapset *colnos = bms_copy(base_colnos);
+ AttrNumber *grpColIdx = perhash->aggnode->grpColIdx;
+ List *hashTlist = NIL;
+ TupleDesc hashDesc;
+ int i;
+
+ perhash->largestGrpColIdx = 0;
+
+ /*
+ * If we're doing grouping sets, then some Vars might be referenced in
+ * tlist/qual for the benefit of other grouping sets, but not needed
+ * when hashing; i.e. prepare_projection_slot will null them out, so
+ * there'd be no point storing them. Use prepare_projection_slot's
+ * logic to determine which.
+ */
+ if (aggstate->phases[0].grouped_cols)
+ {
+ Bitmapset *grouped_cols = aggstate->phases[0].grouped_cols[j];
+ ListCell *lc;
+
+ foreach(lc, aggstate->all_grouped_cols)
+ {
+ int attnum = lfirst_int(lc);
+
+ if (!bms_is_member(attnum, grouped_cols))
+ colnos = bms_del_member(colnos, attnum);
+ }
+ }
+ /* Add in all the grouping columns */
+ for (i = 0; i < perhash->numCols; i++)
+ colnos = bms_add_member(colnos, grpColIdx[i]);
+
+ perhash->hashGrpColIdxInput =
+ palloc(bms_num_members(colnos) * sizeof(AttrNumber));
+ perhash->hashGrpColIdxHash =
+ palloc(perhash->numCols * sizeof(AttrNumber));
+
+ /*
+ * First build mapping for columns directly hashed. These are the
+ * first, because they'll be accessed when computing hash values and
+ * comparing tuples for exact matches. We also build simple mapping
+ * for execGrouping, so it knows where to find the to-be-hashed /
+ * compared columns in the input.
+ */
+ for (i = 0; i < perhash->numCols; i++)
+ {
+ perhash->hashGrpColIdxInput[i] = grpColIdx[i];
+ perhash->hashGrpColIdxHash[i] = i + 1;
+ perhash->numhashGrpCols++;
+ /* delete already mapped columns */
+ bms_del_member(colnos, grpColIdx[i]);
+ }
+
+ /* and add the remaining columns */
+ while ((i = bms_first_member(colnos)) >= 0)
+ {
+ perhash->hashGrpColIdxInput[perhash->numhashGrpCols] = i;
+ perhash->numhashGrpCols++;
+ }
+
+ /* and build a tuple descriptor for the hashtable */
+ for (i = 0; i < perhash->numhashGrpCols; i++)
+ {
+ int varNumber = perhash->hashGrpColIdxInput[i] - 1;
+
+ hashTlist = lappend(hashTlist, list_nth(outerTlist, varNumber));
+ perhash->largestGrpColIdx =
+ Max(varNumber + 1, perhash->largestGrpColIdx);
+ }
+
+ hashDesc = ExecTypeFromTL(hashTlist, false);
+ ExecSetSlotDescriptor(perhash->hashslot, hashDesc);
+
+ list_free(hashTlist);
+ bms_free(colnos);
+ }
+
+ bms_free(base_colnos);
}
/*
@@ -1724,6 +1998,8 @@ find_hash_columns(AggState *aggstate)
*
* Note that the estimate does not include space for pass-by-reference
* transition data values, nor for the representative tuple of each group.
+ * Nor does this account of the target fill-factor and growth policy of the
+ * hash table.
*/
Size
hash_agg_entry_size(int numAggs)
@@ -1731,61 +2007,83 @@ hash_agg_entry_size(int numAggs)
Size entrysize;
/* This must match build_hash_table */
- entrysize = offsetof(AggHashEntryData, pergroup) +
+ entrysize = sizeof(TupleHashEntryData) +
numAggs * sizeof(AggStatePerGroupData);
entrysize = MAXALIGN(entrysize);
- /* Account for hashtable overhead (assuming fill factor = 1) */
- entrysize += 3 * sizeof(void *);
+
return entrysize;
}
/*
- * Find or create a hashtable entry for the tuple group containing the
- * given tuple.
+ * Find or create a hashtable entry for the tuple group containing the current
+ * tuple (already set in tmpcontext's outertuple slot), in the current grouping
+ * set (which the caller must have selected - note that initialize_aggregate
+ * depends on this).
*
* When called, CurrentMemoryContext should be the per-query context.
*/
-static AggHashEntry
-lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
+static TupleHashEntryData *
+lookup_hash_entry(AggState *aggstate)
{
- TupleTableSlot *hashslot = aggstate->hashslot;
- ListCell *l;
- AggHashEntry entry;
+ TupleTableSlot *inputslot = aggstate->tmpcontext->ecxt_outertuple;
+ AggStatePerHash perhash = &aggstate->perhash[aggstate->current_set];
+ TupleTableSlot *hashslot = perhash->hashslot;
+ TupleHashEntryData *entry;
bool isnew;
-
- /* if first time through, initialize hashslot by cloning input slot */
- if (hashslot->tts_tupleDescriptor == NULL)
- {
- ExecSetSlotDescriptor(hashslot, inputslot->tts_tupleDescriptor);
- /* Make sure all unused columns are NULLs */
- ExecStoreAllNullTuple(hashslot);
- }
+ int i;
/* transfer just the needed columns into hashslot */
- slot_getsomeattrs(inputslot, linitial_int(aggstate->hash_needed));
- foreach(l, aggstate->hash_needed)
+ slot_getsomeattrs(inputslot, perhash->largestGrpColIdx);
+ ExecClearTuple(hashslot);
+
+ for (i = 0; i < perhash->numhashGrpCols; i++)
{
- int varNumber = lfirst_int(l) - 1;
+ int varNumber = perhash->hashGrpColIdxInput[i] - 1;
- hashslot->tts_values[varNumber] = inputslot->tts_values[varNumber];
- hashslot->tts_isnull[varNumber] = inputslot->tts_isnull[varNumber];
+ hashslot->tts_values[i] = inputslot->tts_values[varNumber];
+ hashslot->tts_isnull[i] = inputslot->tts_isnull[varNumber];
}
+ ExecStoreVirtualTuple(hashslot);
/* find or create the hashtable entry using the filtered tuple */
- entry = (AggHashEntry) LookupTupleHashEntry(aggstate->hashtable,
- hashslot,
- &isnew);
+ entry = LookupTupleHashEntry(perhash->hashtable, hashslot, &isnew);
if (isnew)
{
+ entry->additional = (AggStatePerGroup)
+ MemoryContextAlloc(perhash->hashtable->tablecxt,
+ sizeof(AggStatePerGroupData) * aggstate->numtrans);
/* initialize aggregates for new tuple group */
- initialize_aggregates(aggstate, entry->pergroup, 0);
+ initialize_aggregates(aggstate, (AggStatePerGroup) entry->additional,
+ -1);
}
return entry;
}
/*
+ * Look up hash entries for the current tuple in all hashed grouping sets,
+ * returning an array of pergroup pointers suitable for advance_aggregates.
+ *
+ * Be aware that lookup_hash_entry can reset the tmpcontext.
+ */
+static AggStatePerGroup *
+lookup_hash_entries(AggState *aggstate)
+{
+ int numHashes = aggstate->num_hashes;
+ AggStatePerGroup *pergroup = aggstate->hash_pergroup;
+ int setno;
+
+ for (setno = 0; setno < numHashes; setno++)
+ {
+ select_current_set(aggstate, setno, true);
+ pergroup[setno] = lookup_hash_entry(aggstate)->additional;
+ }
+
+ return pergroup;
+}
+
+/*
* ExecAgg -
*
* ExecAgg receives tuples from its outer subplan and aggregates over
@@ -1801,40 +2099,22 @@ lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
TupleTableSlot *
ExecAgg(AggState *node)
{
- TupleTableSlot *result;
-
- /*
- * Check to see if we're still projecting out tuples from a previous agg
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->ss.ps.ps_TupFromTlist)
- {
- ExprDoneCond isDone;
-
- result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return result;
- /* Done with that source tuple... */
- node->ss.ps.ps_TupFromTlist = false;
- }
+ TupleTableSlot *result = NULL;
- /*
- * (We must do the ps_TupFromTlist check first, because in some cases
- * agg_done gets set before we emit the final aggregate tuple, and we have
- * to finish running SRFs for it.)
- */
if (!node->agg_done)
{
/* Dispatch based on strategy */
- switch (node->phase->aggnode->aggstrategy)
+ switch (node->phase->aggstrategy)
{
case AGG_HASHED:
if (!node->table_filled)
agg_fill_hash_table(node);
+ /* FALLTHROUGH */
+ case AGG_MIXED:
result = agg_retrieve_hash_table(node);
break;
- default:
+ case AGG_PLAIN:
+ case AGG_SORTED:
result = agg_retrieve_direct(node);
break;
}
@@ -1857,6 +2137,7 @@ agg_retrieve_direct(AggState *aggstate)
ExprContext *tmpcontext;
AggStatePerAgg peragg;
AggStatePerGroup pergroup;
+ AggStatePerGroup *hash_pergroups = NULL;
TupleTableSlot *outerslot;
TupleTableSlot *firstSlot;
TupleTableSlot *result;
@@ -1943,6 +2224,19 @@ agg_retrieve_direct(AggState *aggstate)
node = aggstate->phase->aggnode;
numReset = numGroupingSets;
}
+ else if (aggstate->aggstrategy == AGG_MIXED)
+ {
+ /*
+ * Mixed mode; we've output all the grouped stuff and have
+ * full hashtables, so switch to outputting those.
+ */
+ initialize_phase(aggstate, 0);
+ aggstate->table_filled = true;
+ ResetTupleHashIterator(aggstate->perhash[0].hashtable,
+ &aggstate->perhash[0].hashiter);
+ select_current_set(aggstate, 0, true);
+ return agg_retrieve_hash_table(aggstate);
+ }
else
{
aggstate->agg_done = true;
@@ -1979,7 +2273,7 @@ agg_retrieve_direct(AggState *aggstate)
*----------
*/
if (aggstate->input_done ||
- (node->aggstrategy == AGG_SORTED &&
+ (node->aggstrategy != AGG_PLAIN &&
aggstate->projected_set != -1 &&
aggstate->projected_set < (numGroupingSets - 1) &&
nextSetSize > 0 &&
@@ -2092,10 +2386,22 @@ agg_retrieve_direct(AggState *aggstate)
*/
for (;;)
{
+ /*
+ * During phase 1 only of a mixed agg, we need to update
+ * hashtables as well in advance_aggregates.
+ */
+ if (aggstate->aggstrategy == AGG_MIXED &&
+ aggstate->current_phase == 1)
+ {
+ hash_pergroups = lookup_hash_entries(aggstate);
+ }
+ else
+ hash_pergroups = NULL;
+
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
combine_aggregates(aggstate, pergroup);
else
- advance_aggregates(aggstate, pergroup);
+ advance_aggregates(aggstate, pergroup, hash_pergroups);
/* Reset per-input-tuple context after each tuple */
ResetExprContext(tmpcontext);
@@ -2122,7 +2428,7 @@ agg_retrieve_direct(AggState *aggstate)
* If we are grouping, check whether we've crossed a group
* boundary.
*/
- if (node->aggstrategy == AGG_SORTED)
+ if (node->aggstrategy != AGG_PLAIN)
{
if (!execTuplesMatch(firstSlot,
outerslot,
@@ -2155,7 +2461,11 @@ agg_retrieve_direct(AggState *aggstate)
prepare_projection_slot(aggstate, econtext->ecxt_outertuple, currentSet);
- finalize_aggregates(aggstate, peragg, pergroup, currentSet);
+ select_current_set(aggstate, currentSet, false);
+
+ finalize_aggregates(aggstate,
+ peragg,
+ pergroup + (currentSet * aggstate->numtrans));
/*
* If there's no row to project right now, we must continue rather
@@ -2171,21 +2481,13 @@ agg_retrieve_direct(AggState *aggstate)
}
/*
- * ExecAgg for hashed case: phase 1, read input and build hash table
+ * ExecAgg for hashed case: read input and build hash table
*/
static void
agg_fill_hash_table(AggState *aggstate)
{
- ExprContext *tmpcontext;
- AggHashEntry entry;
TupleTableSlot *outerslot;
-
- /*
- * get state info from node
- *
- * tmpcontext is the per-input-tuple expression context
- */
- tmpcontext = aggstate->tmpcontext;
+ ExprContext *tmpcontext = aggstate->tmpcontext;
/*
* Process each outer-plan tuple, and then fetch the next one, until we
@@ -2193,32 +2495,40 @@ agg_fill_hash_table(AggState *aggstate)
*/
for (;;)
{
+ AggStatePerGroup *pergroups;
+
outerslot = fetch_input_tuple(aggstate);
if (TupIsNull(outerslot))
break;
- /* set up for advance_aggregates call */
+
+ /* set up for lookup_hash_entries and advance_aggregates */
tmpcontext->ecxt_outertuple = outerslot;
- /* Find or build hashtable entry for this tuple's group */
- entry = lookup_hash_entry(aggstate, outerslot);
+ /* Find or build hashtable entries */
+ pergroups = lookup_hash_entries(aggstate);
/* Advance the aggregates */
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
- combine_aggregates(aggstate, entry->pergroup);
+ combine_aggregates(aggstate, pergroups[0]);
else
- advance_aggregates(aggstate, entry->pergroup);
+ advance_aggregates(aggstate, NULL, pergroups);
- /* Reset per-input-tuple context after each tuple */
- ResetExprContext(tmpcontext);
+ /*
+ * Reset per-input-tuple context after each tuple, but note that the
+ * hash lookups do this too
+ */
+ ResetExprContext(aggstate->tmpcontext);
}
aggstate->table_filled = true;
- /* Initialize to walk the hash table */
- ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
+ /* Initialize to walk the first hash table */
+ select_current_set(aggstate, 0, true);
+ ResetTupleHashIterator(aggstate->perhash[0].hashtable,
+ &aggstate->perhash[0].hashiter);
}
/*
- * ExecAgg for hashed case: phase 2, retrieving groups from hash table
+ * ExecAgg for hashed case: retrieving groups from hash table
*/
static TupleTableSlot *
agg_retrieve_hash_table(AggState *aggstate)
@@ -2226,33 +2536,63 @@ agg_retrieve_hash_table(AggState *aggstate)
ExprContext *econtext;
AggStatePerAgg peragg;
AggStatePerGroup pergroup;
- AggHashEntry entry;
+ TupleHashEntryData *entry;
TupleTableSlot *firstSlot;
TupleTableSlot *result;
+ AggStatePerHash perhash;
/*
- * get state info from node
+ * get state info from node.
+ *
+ * econtext is the per-output-tuple expression context.
*/
- /* econtext is the per-output-tuple expression context */
econtext = aggstate->ss.ps.ps_ExprContext;
peragg = aggstate->peragg;
firstSlot = aggstate->ss.ss_ScanTupleSlot;
/*
+ * Note that perhash (and therefore anything accessed through it) can
+ * change inside the loop, as we change between grouping sets.
+ */
+ perhash = &aggstate->perhash[aggstate->current_set];
+
+ /*
* We loop retrieving groups until we find one satisfying
* aggstate->ss.ps.qual
*/
while (!aggstate->agg_done)
{
+ TupleTableSlot *hashslot = perhash->hashslot;
+ int i;
+
/*
* Find the next entry in the hash table
*/
- entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter);
+ entry = ScanTupleHashTable(perhash->hashtable, &perhash->hashiter);
if (entry == NULL)
{
- /* No more entries in hashtable, so done */
- aggstate->agg_done = TRUE;
- return NULL;
+ int nextset = aggstate->current_set + 1;
+
+ if (nextset < aggstate->num_hashes)
+ {
+ /*
+ * Switch to next grouping set, reinitialize, and restart the
+ * loop.
+ */
+ select_current_set(aggstate, nextset, true);
+
+ perhash = &aggstate->perhash[aggstate->current_set];
+
+ ResetTupleHashIterator(perhash->hashtable, &perhash->hashiter);
+
+ continue;
+ }
+ else
+ {
+ /* No more hashtables, so done */
+ aggstate->agg_done = TRUE;
+ return NULL;
+ }
}
/*
@@ -2265,16 +2605,26 @@ agg_retrieve_hash_table(AggState *aggstate)
ResetExprContext(econtext);
/*
- * Store the copied first input tuple in the tuple table slot reserved
- * for it, so that it can be used in ExecProject.
+ * Transform representative tuple back into one with the right
+ * columns.
*/
- ExecStoreMinimalTuple(entry->shared.firstTuple,
- firstSlot,
- false);
+ ExecStoreMinimalTuple(entry->firstTuple, hashslot, false);
+ slot_getallattrs(hashslot);
- pergroup = entry->pergroup;
+ ExecClearTuple(firstSlot);
+ memset(firstSlot->tts_isnull, true,
+ firstSlot->tts_tupleDescriptor->natts * sizeof(bool));
- finalize_aggregates(aggstate, peragg, pergroup, 0);
+ for (i = 0; i < perhash->numhashGrpCols; i++)
+ {
+ int varNumber = perhash->hashGrpColIdxInput[i] - 1;
+
+ firstSlot->tts_values[varNumber] = hashslot->tts_values[i];
+ firstSlot->tts_isnull[varNumber] = hashslot->tts_isnull[i];
+ }
+ ExecStoreVirtualTuple(firstSlot);
+
+ pergroup = (AggStatePerGroup) entry->additional;
/*
* Use the representative input tuple for any references to
@@ -2282,6 +2632,12 @@ agg_retrieve_hash_table(AggState *aggstate)
*/
econtext->ecxt_outertuple = firstSlot;
+ prepare_projection_slot(aggstate,
+ econtext->ecxt_outertuple,
+ aggstate->current_set);
+
+ finalize_aggregates(aggstate, peragg, pergroup);
+
result = project_aggregates(aggstate);
if (result)
return result;
@@ -2295,7 +2651,8 @@ agg_retrieve_hash_table(AggState *aggstate)
* ExecInitAgg
*
* Creates the run-time information for the agg node produced by the
- * planner and initializes its outer subtree
+ * planner and initializes its outer subtree.
+ *
* -----------------
*/
AggState *
@@ -2310,12 +2667,18 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
transno,
aggno;
int phase;
+ int phaseidx;
+ List *combined_inputeval;
ListCell *l;
Bitmapset *all_grouped_cols = NULL;
int numGroupingSets = 1;
int numPhases;
+ int numHashes;
+ int column_offset;
int i = 0;
int j = 0;
+ bool use_hashing = (node->aggstrategy == AGG_HASHED ||
+ node->aggstrategy == AGG_MIXED);
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -2330,9 +2693,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->aggs = NIL;
aggstate->numaggs = 0;
aggstate->numtrans = 0;
+ aggstate->aggstrategy = node->aggstrategy;
aggstate->aggsplit = node->aggsplit;
aggstate->maxsets = 0;
- aggstate->hashfunctions = NULL;
aggstate->projected_set = -1;
aggstate->current_set = 0;
aggstate->peragg = NULL;
@@ -2342,18 +2705,22 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->agg_done = false;
aggstate->pergroup = NULL;
aggstate->grp_firstTuple = NULL;
- aggstate->hashtable = NULL;
aggstate->sort_in = NULL;
aggstate->sort_out = NULL;
/*
+ * phases[0] always exists, but is dummy in sorted/plain mode
+ */
+ numPhases = (use_hashing ? 1 : 2);
+ numHashes = (use_hashing ? 1 : 0);
+
+ /*
* Calculate the maximum number of grouping sets in any phase; this
- * determines the size of some allocations.
+ * determines the size of some allocations. Also calculate the number of
+ * phases, since all hashed/mixed nodes contribute to only a single phase.
*/
if (node->groupingSets)
{
- Assert(node->aggstrategy != AGG_HASHED);
-
numGroupingSets = list_length(node->groupingSets);
foreach(l, node->chain)
@@ -2362,22 +2729,32 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
numGroupingSets = Max(numGroupingSets,
list_length(agg->groupingSets));
+
+ /*
+ * additional AGG_HASHED aggs become part of phase 0, but all
+ * others add an extra phase.
+ */
+ if (agg->aggstrategy != AGG_HASHED)
+ ++numPhases;
+ else
+ ++numHashes;
}
}
aggstate->maxsets = numGroupingSets;
- aggstate->numphases = numPhases = 1 + list_length(node->chain);
+ aggstate->numphases = numPhases;
aggstate->aggcontexts = (ExprContext **)
palloc0(sizeof(ExprContext *) * numGroupingSets);
/*
* Create expression contexts. We need three or more, one for
- * per-input-tuple processing, one for per-output-tuple processing, and
- * one for each grouping set. The per-tuple memory context of the
- * per-grouping-set ExprContexts (aggcontexts) replaces the standalone
- * memory context formerly used to hold transition values. We cheat a
- * little by using ExecAssignExprContext() to build all of them.
+ * per-input-tuple processing, one for per-output-tuple processing, one
+ * for all the hashtables, and one for each grouping set. The per-tuple
+ * memory context of the per-grouping-set ExprContexts (aggcontexts)
+ * replaces the standalone memory context formerly used to hold transition
+ * values. We cheat a little by using ExecAssignExprContext() to build
+ * all of them.
*
* NOTE: the details of what is stored in aggcontexts and what is stored
* in the regular per-query memory context are driven by a simple
@@ -2393,31 +2770,37 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
}
+ if (use_hashing)
+ {
+ ExecAssignExprContext(estate, &aggstate->ss.ps);
+ aggstate->hashcontext = aggstate->ss.ps.ps_ExprContext;
+ }
+
ExecAssignExprContext(estate, &aggstate->ss.ps);
/*
- * tuple table initialization
+ * tuple table initialization.
+ *
+ * For hashtables, we create some additional slots below.
*/
ExecInitScanTupleSlot(estate, &aggstate->ss);
ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
- aggstate->hashslot = ExecInitExtraTupleSlot(estate);
aggstate->sort_slot = ExecInitExtraTupleSlot(estate);
/*
* initialize child expressions
*
- * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
- * contain other agg calls in their arguments. This would make no sense
- * under SQL semantics anyway (and it's forbidden by the spec). Because
- * that is true, we don't need to worry about evaluating the aggs in any
- * particular order.
+ * We rely on the parser to have checked that no aggs contain other agg
+ * calls in their arguments. This would make no sense under SQL semantics
+ * (and it's forbidden by the spec). Because it is true, we don't need to
+ * worry about evaluating the aggs in any particular order.
+ *
+ * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
+ * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
+ * in the targetlist are found during ExecAssignProjectionInfo, below.
*/
- aggstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) aggstate);
- aggstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) aggstate);
+ aggstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) aggstate);
/*
* Initialize child nodes.
@@ -2444,10 +2827,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
ExecAssignResultTypeFromTL(&aggstate->ss.ps);
ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
- aggstate->ss.ps.ps_TupFromTlist = false;
-
/*
- * get the count of aggregates in targetlist and quals
+ * We should now have found all Aggrefs in the targetlist and quals.
*/
numaggs = aggstate->numaggs;
Assert(numaggs == list_length(aggstate->aggs));
@@ -2467,21 +2848,27 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
* For each phase, prepare grouping set data and fmgr lookup data for
* compare functions. Accumulate all_grouped_cols in passing.
*/
-
aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
- for (phase = 0; phase < numPhases; ++phase)
+ aggstate->num_hashes = numHashes;
+ if (numHashes)
+ {
+ aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
+ aggstate->phases[0].numsets = 0;
+ aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
+ aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
+ }
+
+ phase = 0;
+ for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
{
- AggStatePerPhase phasedata = &aggstate->phases[phase];
Agg *aggnode;
Sort *sortnode;
- int num_sets;
- if (phase > 0)
+ if (phaseidx > 0)
{
- aggnode = list_nth(node->chain, phase - 1);
- sortnode = (Sort *) aggnode->plan.lefttree;
- Assert(IsA(sortnode, Sort));
+ aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
+ sortnode = castNode(Sort, aggnode->plan.lefttree);
}
else
{
@@ -2489,53 +2876,91 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
sortnode = NULL;
}
- phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
+ Assert(phase <= 1 || sortnode);
- if (num_sets)
+ if (aggnode->aggstrategy == AGG_HASHED
+ || aggnode->aggstrategy == AGG_MIXED)
{
- phasedata->gset_lengths = palloc(num_sets * sizeof(int));
- phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
+ AggStatePerPhase phasedata = &aggstate->phases[0];
+ AggStatePerHash perhash;
+ Bitmapset *cols = NULL;
- i = 0;
- foreach(l, aggnode->groupingSets)
- {
- int current_length = list_length(lfirst(l));
- Bitmapset *cols = NULL;
+ Assert(phase == 0);
+ i = phasedata->numsets++;
+ perhash = &aggstate->perhash[i];
- /* planner forces this to be correct */
- for (j = 0; j < current_length; ++j)
- cols = bms_add_member(cols, aggnode->grpColIdx[j]);
+ /* phase 0 always points to the "real" Agg in the hash case */
+ phasedata->aggnode = node;
+ phasedata->aggstrategy = node->aggstrategy;
- phasedata->grouped_cols[i] = cols;
- phasedata->gset_lengths[i] = current_length;
- ++i;
- }
+ /* but the actual Agg node representing this hash is saved here */
+ perhash->aggnode = aggnode;
- all_grouped_cols = bms_add_members(all_grouped_cols,
- phasedata->grouped_cols[0]);
+ phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
+
+ for (j = 0; j < aggnode->numCols; ++j)
+ cols = bms_add_member(cols, aggnode->grpColIdx[j]);
+
+ phasedata->grouped_cols[i] = cols;
+
+ all_grouped_cols = bms_add_members(all_grouped_cols, cols);
+ continue;
}
else
{
- Assert(phase == 0);
+ AggStatePerPhase phasedata = &aggstate->phases[++phase];
+ int num_sets;
- phasedata->gset_lengths = NULL;
- phasedata->grouped_cols = NULL;
- }
+ phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
- /*
- * If we are grouping, precompute fmgr lookup data for inner loop.
- */
- if (aggnode->aggstrategy == AGG_SORTED)
- {
- Assert(aggnode->numCols > 0);
+ if (num_sets)
+ {
+ phasedata->gset_lengths = palloc(num_sets * sizeof(int));
+ phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
- phasedata->eqfunctions =
- execTuplesMatchPrepare(aggnode->numCols,
- aggnode->grpOperators);
- }
+ i = 0;
+ foreach(l, aggnode->groupingSets)
+ {
+ int current_length = list_length(lfirst(l));
+ Bitmapset *cols = NULL;
+
+ /* planner forces this to be correct */
+ for (j = 0; j < current_length; ++j)
+ cols = bms_add_member(cols, aggnode->grpColIdx[j]);
+
+ phasedata->grouped_cols[i] = cols;
+ phasedata->gset_lengths[i] = current_length;
+
+ ++i;
+ }
+
+ all_grouped_cols = bms_add_members(all_grouped_cols,
+ phasedata->grouped_cols[0]);
+ }
+ else
+ {
+ Assert(phaseidx == 0);
+
+ phasedata->gset_lengths = NULL;
+ phasedata->grouped_cols = NULL;
+ }
+
+ /*
+ * If we are grouping, precompute fmgr lookup data for inner loop.
+ */
+ if (aggnode->aggstrategy == AGG_SORTED)
+ {
+ Assert(aggnode->numCols > 0);
- phasedata->aggnode = aggnode;
- phasedata->sortnode = sortnode;
+ phasedata->eqfunctions =
+ execTuplesMatchPrepare(aggnode->numCols,
+ aggnode->grpOperators);
+ }
+
+ phasedata->aggnode = aggnode;
+ phasedata->aggstrategy = aggnode->aggstrategy;
+ phasedata->sortnode = sortnode;
+ }
}
/*
@@ -2546,23 +2971,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
/*
- * Hashing can only appear in the initial phase.
- */
-
- if (node->aggstrategy == AGG_HASHED)
- execTuplesHashPrepare(node->numCols,
- node->grpOperators,
- &aggstate->phases[0].eqfunctions,
- &aggstate->hashfunctions);
-
- /*
- * Initialize current phase-dependent values to initial phase
- */
-
- aggstate->current_phase = 0;
- initialize_phase(aggstate, 0);
-
- /*
* Set up aggregate-result storage in the output expr context, and also
* allocate my private per-agg working storage
*/
@@ -2576,14 +2984,30 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->peragg = peraggs;
aggstate->pertrans = pertransstates;
- if (node->aggstrategy == AGG_HASHED)
+ /*
+ * Hashing can only appear in the initial phase.
+ */
+ if (use_hashing)
{
+ for (i = 0; i < numHashes; ++i)
+ {
+ aggstate->perhash[i].hashslot = ExecInitExtraTupleSlot(estate);
+
+ execTuplesHashPrepare(aggstate->perhash[i].numCols,
+ aggstate->perhash[i].aggnode->grpOperators,
+ &aggstate->perhash[i].eqfunctions,
+ &aggstate->perhash[i].hashfunctions);
+ }
+
+ /* this is an array of pointers, not structures */
+ aggstate->hash_pergroup = palloc0(sizeof(AggStatePerGroup) * numHashes);
+
+ find_hash_columns(aggstate);
build_hash_table(aggstate);
aggstate->table_filled = false;
- /* Compute the columns we actually need to hash on */
- aggstate->hash_needed = find_hash_columns(aggstate);
}
- else
+
+ if (node->aggstrategy != AGG_HASHED)
{
AggStatePerGroup pergroup;
@@ -2594,6 +3018,25 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->pergroup = pergroup;
}
+ /*
+ * Initialize current phase-dependent values to initial phase. The initial
+ * phase is 1 (first sort pass) for all strategies that use sorting (if
+ * hashing is being done too, then phase 0 is processed last); but if only
+ * hashing is being done, then phase 0 is all there is.
+ */
+ if (node->aggstrategy == AGG_HASHED)
+ {
+ aggstate->current_phase = 0;
+ initialize_phase(aggstate, 0);
+ select_current_set(aggstate, 0, true);
+ }
+ else
+ {
+ aggstate->current_phase = 1;
+ initialize_phase(aggstate, 1);
+ select_current_set(aggstate, 0, false);
+ }
+
/* -----------------
* Perform lookups of aggregate function info, and initialize the
* unchanging fields of the per-agg and per-trans data.
@@ -2633,7 +3076,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
foreach(l, aggstate->aggs)
{
AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
- Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
+ Aggref *aggref = aggrefstate->aggref;
AggStatePerAgg peragg;
AggStatePerTrans pertrans;
int existing_aggno;
@@ -2895,6 +3338,51 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->numaggs = aggno + 1;
aggstate->numtrans = transno + 1;
+ /*
+ * Build a single projection computing the aggregate arguments for all
+ * aggregates at once, that's considerably faster than doing it separately
+ * for each.
+ *
+ * First create a targetlist combining the targetlist of all the
+ * transitions.
+ */
+ combined_inputeval = NIL;
+ column_offset = 0;
+ for (transno = 0; transno < aggstate->numtrans; transno++)
+ {
+ AggStatePerTrans pertrans = &pertransstates[transno];
+ ListCell *arg;
+
+ pertrans->inputoff = column_offset;
+
+ /*
+ * Adjust resno in a copied target entries, to point into the combined
+ * slot.
+ */
+ foreach(arg, pertrans->aggref->args)
+ {
+ TargetEntry *source_tle = lfirst_node(TargetEntry, arg);
+ TargetEntry *tle;
+
+ tle = flatCopyTargetEntry(source_tle);
+ tle->resno += column_offset;
+
+ combined_inputeval = lappend(combined_inputeval, tle);
+ }
+
+ column_offset += list_length(pertrans->aggref->args);
+ }
+
+ /* and then create a projection for that targetlist */
+ aggstate->evaldesc = ExecTypeFromTL(combined_inputeval, false);
+ aggstate->evalslot = ExecInitExtraTupleSlot(estate);
+ aggstate->evalproj = ExecBuildProjectionInfo(combined_inputeval,
+ aggstate->tmpcontext,
+ aggstate->evalslot,
+ &aggstate->ss.ps,
+ NULL);
+ ExecSetSlotDescriptor(aggstate->evalslot, aggstate->evaldesc);
+
return aggstate;
}
@@ -3065,24 +3553,12 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
}
- /*
- * Get a tupledesc corresponding to the aggregated inputs (including sort
- * expressions) of the agg.
- */
- pertrans->evaldesc = ExecTypeFromTL(aggref->args, false);
-
- /* Create slot we're going to do argument evaluation in */
- pertrans->evalslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(pertrans->evalslot, pertrans->evaldesc);
-
/* Initialize the input and FILTER expressions */
naggs = aggstate->numaggs;
pertrans->aggfilter = ExecInitExpr(aggref->aggfilter,
(PlanState *) aggstate);
- pertrans->aggdirectargs = (List *) ExecInitExpr((Expr *) aggref->aggdirectargs,
- (PlanState *) aggstate);
- pertrans->args = (List *) ExecInitExpr((Expr *) aggref->args,
- (PlanState *) aggstate);
+ pertrans->aggdirectargs = ExecInitExprList(aggref->aggdirectargs,
+ (PlanState *) aggstate);
/*
* Complain if the aggregate's arguments contain any aggregates; nested
@@ -3094,12 +3570,6 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregate function calls cannot be nested")));
- /* Set up projection info for evaluation */
- pertrans->evalproj = ExecBuildProjectionInfo(pertrans->args,
- aggstate->tmpcontext,
- pertrans->evalslot,
- NULL);
-
/*
* If we're doing either DISTINCT or ORDER BY for a plain agg, then we
* have a list of SortGroupClause nodes; fish out the data in them and
@@ -3133,10 +3603,18 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
if (numSortCols > 0)
{
/*
+ * Get a tupledesc and slot corresponding to the aggregated inputs
+ * (including sort expressions) of the agg.
+ */
+ pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
+ pertrans->sortslot = ExecInitExtraTupleSlot(estate);
+ ExecSetSlotDescriptor(pertrans->sortslot, pertrans->sortdesc);
+
+ /*
* We don't implement DISTINCT or ORDER BY aggs in the HASHED case
* (yet)
*/
- Assert(((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
+ Assert(aggstate->aggstrategy != AGG_HASHED && aggstate->aggstrategy != AGG_MIXED);
/* If we have only one input, we need its len/byval info. */
if (numInputs == 1)
@@ -3150,7 +3628,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
/* we will need an extra slot to store prior values */
pertrans->uniqslot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(pertrans->uniqslot,
- pertrans->evaldesc);
+ pertrans->sortdesc);
}
/* Extract the sort information for use later */
@@ -3385,6 +3863,8 @@ ExecEndAgg(AggState *node)
/* And ensure any agg shutdown callbacks have been called */
for (setno = 0; setno < numGroupingSets; setno++)
ReScanExprContext(node->aggcontexts[setno]);
+ if (node->hashcontext)
+ ReScanExprContext(node->hashcontext);
/*
* We don't actually free any ExprContexts here (see comment in
@@ -3412,9 +3892,7 @@ ExecReScanAgg(AggState *node)
node->agg_done = false;
- node->ss.ps.ps_TupFromTlist = false;
-
- if (aggnode->aggstrategy == AGG_HASHED)
+ if (node->aggstrategy == AGG_HASHED)
{
/*
* In the hashed case, if we haven't yet built the hash table then we
@@ -3426,13 +3904,17 @@ ExecReScanAgg(AggState *node)
return;
/*
- * If we do have the hash table and the subplan does not have any
- * parameter changes, then we can just rescan the existing hash table;
- * no need to build it again.
+ * If we do have the hash table, and the subplan does not have any
+ * parameter changes, and none of our own parameter changes affect
+ * input expressions of the aggregated functions, then we can just
+ * rescan the existing hash table; no need to build it again.
*/
- if (outerPlan->chgParam == NULL)
+ if (outerPlan->chgParam == NULL &&
+ !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
{
- ResetTupleHashIterator(node->hashtable, &node->hashiter);
+ ResetTupleHashIterator(node->perhash[0].hashtable,
+ &node->perhash[0].hashiter);
+ select_current_set(node, 0, true);
return;
}
}
@@ -3457,11 +3939,7 @@ ExecReScanAgg(AggState *node)
* ExecReScan already did it. But we do need to reset our per-grouping-set
* contexts, which may have transvalues stored in them. (We use rescan
* rather than just reset because transfns may have registered callbacks
- * that need to be run now.)
- *
- * Note that with AGG_HASHED, the hash table is allocated in a sub-context
- * of the aggcontext. This used to be an issue, but now, resetting a
- * context automatically deletes sub-contexts too.
+ * that need to be run now.) For the AGG_HASHED case, see below.
*/
for (setno = 0; setno < numGroupingSets; setno++)
@@ -3481,13 +3959,21 @@ ExecReScanAgg(AggState *node)
MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
- if (aggnode->aggstrategy == AGG_HASHED)
+ /*
+ * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
+ * the hashcontext. This used to be an issue, but now, resetting a context
+ * automatically deletes sub-contexts too.
+ */
+ if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
{
+ ReScanExprContext(node->hashcontext);
/* Rebuild an empty hash table */
build_hash_table(node);
node->table_filled = false;
+ /* iterator will be reset when the table is filled */
}
- else
+
+ if (node->aggstrategy != AGG_HASHED)
{
/*
* Reset the per-group state (in particular, mark transvalues null)
@@ -3495,8 +3981,8 @@ ExecReScanAgg(AggState *node)
MemSet(node->pergroup, 0,
sizeof(AggStatePerGroupData) * node->numaggs * numGroupingSets);
- /* reset to phase 0 */
- initialize_phase(node, 0);
+ /* reset to phase 1 */
+ initialize_phase(node, 1);
node->input_done = false;
node->projected_set = -1;
@@ -3537,7 +4023,7 @@ AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
if (aggcontext)
{
AggState *aggstate = ((AggState *) fcinfo->context);
- ExprContext *cxt = aggstate->aggcontexts[aggstate->current_set];
+ ExprContext *cxt = aggstate->curaggcontext;
*aggcontext = cxt->ecxt_per_tuple_memory;
}
@@ -3626,7 +4112,7 @@ AggRegisterCallback(FunctionCallInfo fcinfo,
if (fcinfo->context && IsA(fcinfo->context, AggState))
{
AggState *aggstate = (AggState *) fcinfo->context;
- ExprContext *cxt = aggstate->aggcontexts[aggstate->current_set];
+ ExprContext *cxt = aggstate->curaggcontext;
RegisterExprContextCallback(cxt, func, arg);
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index a26bd6354c..aae5e3fa63 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -3,7 +3,7 @@
* nodeAppend.c
* routines to handle append nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -129,6 +129,12 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
Assert(!(eflags & EXEC_FLAG_MARK));
/*
+ * Lock the non-leaf tables in the partition tree controlled by this node.
+ * It's a no-op for non-partitioned parent tables.
+ */
+ ExecLockNonLeafAppendTables(node->partitioned_rels, estate);
+
+ /*
* Set up empty vector of subplan states
*/
nplans = list_length(node->appendplans);
diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c
index c39d790f82..e4eb028ff9 100644
--- a/src/backend/executor/nodeBitmapAnd.c
+++ b/src/backend/executor/nodeBitmapAnd.c
@@ -3,7 +3,7 @@
* nodeBitmapAnd.c
* routines to handle BitmapAnd nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 449aacb6e7..c453362230 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -16,7 +16,7 @@
* required index qual conditions.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -35,6 +35,8 @@
*/
#include "postgres.h"
+#include <math.h>
+
#include "access/relscan.h"
#include "access/transam.h"
#include "executor/execdebug.h"
@@ -51,6 +53,15 @@
static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
static void bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres);
+static inline void BitmapDoneInitializingSharedState(
+ ParallelBitmapHeapState *pstate);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
+ TBMIterateResult *tbmres);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+static inline void BitmapPrefetch(BitmapHeapScanState *node,
+ HeapScanDesc scan);
+static bool BitmapShouldInitializeSharedState(
+ ParallelBitmapHeapState *pstate);
/* ----------------------------------------------------------------
@@ -65,14 +76,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
ExprContext *econtext;
HeapScanDesc scan;
TIDBitmap *tbm;
- TBMIterator *tbmiterator;
+ TBMIterator *tbmiterator = NULL;
+ TBMSharedIterator *shared_tbmiterator = NULL;
TBMIterateResult *tbmres;
-
-#ifdef USE_PREFETCH
- TBMIterator *prefetch_iterator;
-#endif
OffsetNumber targoffset;
TupleTableSlot *slot;
+ ParallelBitmapHeapState *pstate = node->pstate;
+ dsa_area *dsa = node->ss.ps.state->es_query_dsa;
/*
* extract necessary information from index scan node
@@ -81,11 +91,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
slot = node->ss.ss_ScanTupleSlot;
scan = node->ss.ss_currentScanDesc;
tbm = node->tbm;
- tbmiterator = node->tbmiterator;
+ if (pstate == NULL)
+ tbmiterator = node->tbmiterator;
+ else
+ shared_tbmiterator = node->shared_tbmiterator;
tbmres = node->tbmres;
-#ifdef USE_PREFETCH
- prefetch_iterator = node->prefetch_iterator;
-#endif
/*
* If we haven't yet performed the underlying index scan, do it, and begin
@@ -99,25 +109,82 @@ BitmapHeapNext(BitmapHeapScanState *node)
* node->prefetch_maximum. This is to avoid doing a lot of prefetching in
* a scan that stops after a few tuples because of a LIMIT.
*/
- if (tbm == NULL)
+ if (!node->initialized)
{
- tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+ if (!pstate)
+ {
+ tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
- if (!tbm || !IsA(tbm, TIDBitmap))
- elog(ERROR, "unrecognized result from subplan");
+ if (!tbm || !IsA(tbm, TIDBitmap))
+ elog(ERROR, "unrecognized result from subplan");
- node->tbm = tbm;
- node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
- node->tbmres = tbmres = NULL;
+ node->tbm = tbm;
+ node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+ node->tbmres = tbmres = NULL;
#ifdef USE_PREFETCH
- if (node->prefetch_maximum > 0)
- {
- node->prefetch_iterator = prefetch_iterator = tbm_begin_iterate(tbm);
- node->prefetch_pages = 0;
- node->prefetch_target = -1;
+ if (node->prefetch_maximum > 0)
+ {
+ node->prefetch_iterator = tbm_begin_iterate(tbm);
+ node->prefetch_pages = 0;
+ node->prefetch_target = -1;
+ }
+#endif /* USE_PREFETCH */
}
+ else
+ {
+ /*
+ * The leader will immediately come out of the function, but
+ * others will be blocked until leader populates the TBM and wakes
+ * them up.
+ */
+ if (BitmapShouldInitializeSharedState(pstate))
+ {
+ tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+ if (!tbm || !IsA(tbm, TIDBitmap))
+ elog(ERROR, "unrecognized result from subplan");
+
+ node->tbm = tbm;
+
+ /*
+ * Prepare to iterate over the TBM. This will return the
+ * dsa_pointer of the iterator state which will be used by
+ * multiple processes to iterate jointly.
+ */
+ pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+#ifdef USE_PREFETCH
+ if (node->prefetch_maximum > 0)
+ {
+ pstate->prefetch_iterator =
+ tbm_prepare_shared_iterate(tbm);
+
+ /*
+ * We don't need the mutex here as we haven't yet woke up
+ * others.
+ */
+ pstate->prefetch_pages = 0;
+ pstate->prefetch_target = -1;
+ }
+#endif
+
+ /* We have initialized the shared state so wake up others. */
+ BitmapDoneInitializingSharedState(pstate);
+ }
+
+ /* Allocate a private iterator and attach the shared state to it */
+ node->shared_tbmiterator = shared_tbmiterator =
+ tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+ node->tbmres = tbmres = NULL;
+
+#ifdef USE_PREFETCH
+ if (node->prefetch_maximum > 0)
+ {
+ node->shared_prefetch_iterator =
+ tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+ }
#endif /* USE_PREFETCH */
+ }
+ node->initialized = true;
}
for (;;)
@@ -130,28 +197,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
*/
if (tbmres == NULL)
{
- node->tbmres = tbmres = tbm_iterate(tbmiterator);
+ if (!pstate)
+ node->tbmres = tbmres = tbm_iterate(tbmiterator);
+ else
+ node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
if (tbmres == NULL)
{
/* no more entries in the bitmap */
break;
}
-#ifdef USE_PREFETCH
- if (node->prefetch_pages > 0)
- {
- /* The main iterator has closed the distance by one page */
- node->prefetch_pages--;
- }
- else if (prefetch_iterator)
- {
- /* Do not let the prefetch iterator get behind the main one */
- TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
- if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
- elog(ERROR, "prefetch and main iterators are out of sync");
- }
-#endif /* USE_PREFETCH */
+ BitmapAdjustPrefetchIterator(node, tbmres);
/*
* Ignore any claimed entries past what we think is the end of the
@@ -180,23 +236,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
*/
scan->rs_cindex = 0;
-#ifdef USE_PREFETCH
-
- /*
- * Increase prefetch target if it's not yet at the max. Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
- if (node->prefetch_target >= node->prefetch_maximum)
- /* don't increase any further */ ;
- else if (node->prefetch_target >= node->prefetch_maximum / 2)
- node->prefetch_target = node->prefetch_maximum;
- else if (node->prefetch_target > 0)
- node->prefetch_target *= 2;
- else
- node->prefetch_target++;
-#endif /* USE_PREFETCH */
+ /* Adjust the prefetch target */
+ BitmapAdjustPrefetchTarget(node);
}
else
{
@@ -211,8 +252,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
* Try to prefetch at least a few pages even before we get to the
* second page if we don't stop reading after the first tuple.
*/
- if (node->prefetch_target < node->prefetch_maximum)
- node->prefetch_target++;
+ if (!pstate)
+ {
+ if (node->prefetch_target < node->prefetch_maximum)
+ node->prefetch_target++;
+ }
+ else if (pstate->prefetch_target < node->prefetch_maximum)
+ {
+ /* take spinlock while updating shared state */
+ SpinLockAcquire(&pstate->mutex);
+ if (pstate->prefetch_target < node->prefetch_maximum)
+ pstate->prefetch_target++;
+ SpinLockRelease(&pstate->mutex);
+ }
#endif /* USE_PREFETCH */
}
@@ -225,8 +277,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
continue;
}
-#ifdef USE_PREFETCH
-
/*
* We issue prefetch requests *after* fetching the current page to try
* to avoid having prefetching interfere with the main I/O. Also, this
@@ -234,24 +284,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
* to do on the current page, else we may uselessly prefetch the same
* page we are just about to request for real.
*/
- if (prefetch_iterator)
- {
- while (node->prefetch_pages < node->prefetch_target)
- {
- TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
- if (tbmpre == NULL)
- {
- /* No more pages to prefetch */
- tbm_end_iterate(prefetch_iterator);
- node->prefetch_iterator = prefetch_iterator = NULL;
- break;
- }
- node->prefetch_pages++;
- PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
- }
- }
-#endif /* USE_PREFETCH */
+ BitmapPrefetch(node, scan);
/*
* Okay to fetch the tuple
@@ -286,7 +319,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
econtext->ecxt_scantuple = slot;
ResetExprContext(econtext);
- if (!ExecQual(node->bitmapqualorig, econtext, false))
+ if (!ExecQual(node->bitmapqualorig, econtext))
{
/* Fails recheck, so drop it and loop back for another */
InstrCountFiltered2(node, 1);
@@ -410,6 +443,201 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres)
}
/*
+ * BitmapDoneInitializingSharedState - Shared state is initialized
+ *
+ * By this time the leader has already populated the TBM and initialized the
+ * shared state so wake up other processes.
+ */
+static inline void
+BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
+{
+ SpinLockAcquire(&pstate->mutex);
+ pstate->state = BM_FINISHED;
+ SpinLockRelease(&pstate->mutex);
+ ConditionVariableBroadcast(&pstate->cv);
+}
+
+/*
+ * BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ */
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
+ TBMIterateResult *tbmres)
+{
+#ifdef USE_PREFETCH
+ ParallelBitmapHeapState *pstate = node->pstate;
+
+ if (pstate == NULL)
+ {
+ TBMIterator *prefetch_iterator = node->prefetch_iterator;
+
+ if (node->prefetch_pages > 0)
+ {
+ /* The main iterator has closed the distance by one page */
+ node->prefetch_pages--;
+ }
+ else if (prefetch_iterator)
+ {
+ /* Do not let the prefetch iterator get behind the main one */
+ TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+
+ if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+ elog(ERROR, "prefetch and main iterators are out of sync");
+ }
+ return;
+ }
+
+ if (node->prefetch_maximum > 0)
+ {
+ TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+
+ SpinLockAcquire(&pstate->mutex);
+ if (pstate->prefetch_pages > 0)
+ {
+ pstate->prefetch_pages--;
+ SpinLockRelease(&pstate->mutex);
+ }
+ else
+ {
+ /* Release the mutex before iterating */
+ SpinLockRelease(&pstate->mutex);
+
+ /*
+ * In case of shared mode, we can not ensure that the current
+ * blockno of the main iterator and that of the prefetch iterator
+ * are same. It's possible that whatever blockno we are
+ * prefetching will be processed by another process. Therefore,
+ * we don't validate the blockno here as we do in non-parallel
+ * case.
+ */
+ if (prefetch_iterator)
+ tbm_shared_iterate(prefetch_iterator);
+ }
+ }
+#endif /* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max. Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+ ParallelBitmapHeapState *pstate = node->pstate;
+
+ if (pstate == NULL)
+ {
+ if (node->prefetch_target >= node->prefetch_maximum)
+ /* don't increase any further */ ;
+ else if (node->prefetch_target >= node->prefetch_maximum / 2)
+ node->prefetch_target = node->prefetch_maximum;
+ else if (node->prefetch_target > 0)
+ node->prefetch_target *= 2;
+ else
+ node->prefetch_target++;
+ return;
+ }
+
+ /* Do an unlocked check first to save spinlock acquisitions. */
+ if (pstate->prefetch_target < node->prefetch_maximum)
+ {
+ SpinLockAcquire(&pstate->mutex);
+ if (pstate->prefetch_target >= node->prefetch_maximum)
+ /* don't increase any further */ ;
+ else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+ pstate->prefetch_target = node->prefetch_maximum;
+ else if (pstate->prefetch_target > 0)
+ pstate->prefetch_target *= 2;
+ else
+ pstate->prefetch_target++;
+ SpinLockRelease(&pstate->mutex);
+ }
+#endif /* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+ ParallelBitmapHeapState *pstate = node->pstate;
+
+ if (pstate == NULL)
+ {
+ TBMIterator *prefetch_iterator = node->prefetch_iterator;
+
+ if (prefetch_iterator)
+ {
+ while (node->prefetch_pages < node->prefetch_target)
+ {
+ TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+
+ if (tbmpre == NULL)
+ {
+ /* No more pages to prefetch */
+ tbm_end_iterate(prefetch_iterator);
+ node->prefetch_iterator = NULL;
+ break;
+ }
+ node->prefetch_pages++;
+ PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+ }
+ }
+
+ return;
+ }
+
+ if (pstate->prefetch_pages < pstate->prefetch_target)
+ {
+ TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+
+ if (prefetch_iterator)
+ {
+ while (1)
+ {
+ TBMIterateResult *tbmpre;
+ bool do_prefetch = false;
+
+ /*
+ * Recheck under the mutex. If some other process has already
+ * done enough prefetching then we need not to do anything.
+ */
+ SpinLockAcquire(&pstate->mutex);
+ if (pstate->prefetch_pages < pstate->prefetch_target)
+ {
+ pstate->prefetch_pages++;
+ do_prefetch = true;
+ }
+ SpinLockRelease(&pstate->mutex);
+
+ if (!do_prefetch)
+ return;
+
+ tbmpre = tbm_shared_iterate(prefetch_iterator);
+ if (tbmpre == NULL)
+ {
+ /* No more pages to prefetch */
+ tbm_end_shared_iterate(prefetch_iterator);
+ node->shared_prefetch_iterator = NULL;
+ break;
+ }
+
+ PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+ }
+ }
+ }
+#endif /* USE_PREFETCH */
+}
+
+/*
* BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
*/
static bool
@@ -427,7 +655,7 @@ BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
ResetExprContext(econtext);
- return ExecQual(node->bitmapqualorig, econtext, false);
+ return ExecQual(node->bitmapqualorig, econtext);
}
/* ----------------------------------------------------------------
@@ -458,12 +686,36 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
tbm_end_iterate(node->tbmiterator);
if (node->prefetch_iterator)
tbm_end_iterate(node->prefetch_iterator);
+ if (node->shared_tbmiterator)
+ tbm_end_shared_iterate(node->shared_tbmiterator);
+ if (node->shared_prefetch_iterator)
+ tbm_end_shared_iterate(node->shared_prefetch_iterator);
if (node->tbm)
tbm_free(node->tbm);
node->tbm = NULL;
node->tbmiterator = NULL;
node->tbmres = NULL;
node->prefetch_iterator = NULL;
+ node->initialized = false;
+ node->shared_tbmiterator = NULL;
+ node->shared_prefetch_iterator = NULL;
+
+ /* Reset parallel bitmap state, if present */
+ if (node->pstate)
+ {
+ dsa_area *dsa = node->ss.ps.state->es_query_dsa;
+
+ node->pstate->state = BM_INITIAL;
+
+ if (DsaPointerIsValid(node->pstate->tbmiterator))
+ tbm_free_shared_area(dsa, node->pstate->tbmiterator);
+
+ if (DsaPointerIsValid(node->pstate->prefetch_iterator))
+ tbm_free_shared_area(dsa, node->pstate->prefetch_iterator);
+
+ node->pstate->tbmiterator = InvalidDsaPointer;
+ node->pstate->prefetch_iterator = InvalidDsaPointer;
+ }
ExecScanReScan(&node->ss);
@@ -516,6 +768,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
tbm_end_iterate(node->prefetch_iterator);
if (node->tbm)
tbm_free(node->tbm);
+ if (node->shared_tbmiterator)
+ tbm_end_shared_iterate(node->shared_tbmiterator);
+ if (node->shared_prefetch_iterator)
+ tbm_end_shared_iterate(node->shared_prefetch_iterator);
/*
* close heap scan
@@ -567,6 +823,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
scanstate->prefetch_target = 0;
/* may be updated below */
scanstate->prefetch_maximum = target_prefetch_pages;
+ scanstate->pscan_len = 0;
+ scanstate->initialized = false;
+ scanstate->shared_tbmiterator = NULL;
+ scanstate->pstate = NULL;
/*
* Miscellaneous initialization
@@ -575,20 +835,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &scanstate->ss.ps);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
- scanstate->bitmapqualorig = (List *)
- ExecInitExpr((Expr *) node->bitmapqualorig,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ scanstate->bitmapqualorig =
+ ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
/*
* tuple table initialization
@@ -653,3 +906,108 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
*/
return scanstate;
}
+
+/*----------------
+ * BitmapShouldInitializeSharedState
+ *
+ * The first process to come here and see the state to the BM_INITIAL
+ * will become the leader for the parallel bitmap scan and will be
+ * responsible for populating the TIDBitmap. The other processes will
+ * be blocked by the condition variable until the leader wakes them up.
+ * ---------------
+ */
+static bool
+BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
+{
+ SharedBitmapState state;
+
+ while (1)
+ {
+ SpinLockAcquire(&pstate->mutex);
+ state = pstate->state;
+ if (pstate->state == BM_INITIAL)
+ pstate->state = BM_INPROGRESS;
+ SpinLockRelease(&pstate->mutex);
+
+ /* Exit if bitmap is done, or if we're the leader. */
+ if (state != BM_INPROGRESS)
+ break;
+
+ /* Wait for the leader to wake us up. */
+ ConditionVariableSleep(&pstate->cv, WAIT_EVENT_PARALLEL_BITMAP_SCAN);
+ }
+
+ ConditionVariableCancelSleep();
+
+ return (state == BM_INITIAL);
+}
+
+/* ----------------------------------------------------------------
+ * ExecBitmapHeapEstimate
+ *
+ * estimates the space required to serialize bitmap scan node.
+ * ----------------------------------------------------------------
+ */
+void
+ExecBitmapHeapEstimate(BitmapHeapScanState *node,
+ ParallelContext *pcxt)
+{
+ EState *estate = node->ss.ps.state;
+
+ node->pscan_len = add_size(offsetof(ParallelBitmapHeapState,
+ phs_snapshot_data),
+ EstimateSnapshotSpace(estate->es_snapshot));
+
+ shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+}
+
+/* ----------------------------------------------------------------
+ * ExecBitmapHeapInitializeDSM
+ *
+ * Set up a parallel bitmap heap scan descriptor.
+ * ----------------------------------------------------------------
+ */
+void
+ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
+ ParallelContext *pcxt)
+{
+ ParallelBitmapHeapState *pstate;
+ EState *estate = node->ss.ps.state;
+
+ pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
+
+ pstate->tbmiterator = 0;
+ pstate->prefetch_iterator = 0;
+
+ /* Initialize the mutex */
+ SpinLockInit(&pstate->mutex);
+ pstate->prefetch_pages = 0;
+ pstate->prefetch_target = 0;
+ pstate->state = BM_INITIAL;
+
+ ConditionVariableInit(&pstate->cv);
+ SerializeSnapshot(estate->es_snapshot, pstate->phs_snapshot_data);
+
+ shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
+ node->pstate = pstate;
+}
+
+/* ----------------------------------------------------------------
+ * ExecBitmapHeapInitializeWorker
+ *
+ * Copy relevant information from TOC into planstate.
+ * ----------------------------------------------------------------
+ */
+void
+ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node, shm_toc *toc)
+{
+ ParallelBitmapHeapState *pstate;
+ Snapshot snapshot;
+
+ pstate = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
+ node->pstate = pstate;
+
+ snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
+ heap_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
+}
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index a364098e59..ce2f3210a4 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -3,7 +3,7 @@
* nodeBitmapIndexscan.c
* Routines to support bitmapped index scans of relations
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -78,7 +78,9 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
else
{
/* XXX should we use less than work_mem for this? */
- tbm = tbm_create(work_mem * 1024L);
+ tbm = tbm_create(work_mem * 1024L,
+ ((BitmapIndexScan *) node->ss.ps.plan)->isshared ?
+ node->ss.ps.state->es_query_dsa : NULL);
}
/*
diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c
index 7e928eb618..c0f261407b 100644
--- a/src/backend/executor/nodeBitmapOr.c
+++ b/src/backend/executor/nodeBitmapOr.c
@@ -3,7 +3,7 @@
* nodeBitmapOr.c
* routines to handle BitmapOr nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -129,7 +129,9 @@ MultiExecBitmapOr(BitmapOrState *node)
if (result == NULL) /* first subplan */
{
/* XXX should we use less than work_mem for this? */
- result = tbm_create(work_mem * 1024L);
+ result = tbm_create(work_mem * 1024L,
+ ((BitmapOr *) node->ps.plan)->isshared ?
+ node->ps.state->es_query_dsa : NULL);
}
((BitmapIndexScanState *) subnode)->biss_result = result;
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index 3c2f684a06..bed7949c5a 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -3,7 +3,7 @@
* nodeCtescan.c
* routines to handle CteScan nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -210,7 +210,7 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
prmdata = &(estate->es_param_exec_vals[node->cteParam]);
Assert(prmdata->execPlan == NULL);
Assert(!prmdata->isnull);
- scanstate->leader = (CteScanState *) DatumGetPointer(prmdata->value);
+ scanstate->leader = castNode(CteScanState, DatumGetPointer(prmdata->value));
if (scanstate->leader == NULL)
{
/* I am the leader */
@@ -223,10 +223,13 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
else
{
/* Not the leader */
- Assert(IsA(scanstate->leader, CteScanState));
+ /* Create my own read pointer, and ensure it is at start */
scanstate->readptr =
tuplestore_alloc_read_pointer(scanstate->leader->cte_table,
scanstate->eflags);
+ tuplestore_select_read_pointer(scanstate->leader->cte_table,
+ scanstate->readptr);
+ tuplestore_rescan(scanstate->leader->cte_table);
}
/*
@@ -239,12 +242,8 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
/*
* tuple table initialization
@@ -265,8 +264,6 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
return scanstate;
}
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index 322abca282..5d309828ef 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -3,7 +3,7 @@
* nodeCustom.c
* Routines to handle execution of custom scan node
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* ------------------------------------------------------------------------
@@ -35,8 +35,8 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
* methods field correctly at this time. Other standard fields should be
* set to zero.
*/
- css = (CustomScanState *) cscan->methods->CreateCustomScanState(cscan);
- Assert(IsA(css, CustomScanState));
+ css = castNode(CustomScanState,
+ cscan->methods->CreateCustomScanState(cscan));
/* ensure flags is filled correctly */
css->flags = cscan->flags;
@@ -48,15 +48,9 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
/* create expression context for node */
ExecAssignExprContext(estate, &css->ss.ps);
- css->ss.ps.ps_TupFromTlist = false;
-
/* initialize child expressions */
- css->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) cscan->scan.plan.targetlist,
- (PlanState *) css);
- css->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) cscan->scan.plan.qual,
- (PlanState *) css);
+ css->ss.ps.qual =
+ ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
/* tuple table initialization */
ExecInitScanTupleSlot(estate, &css->ss);
@@ -204,3 +198,12 @@ ExecCustomScanInitializeWorker(CustomScanState *node, shm_toc *toc)
methods->InitializeWorkerCustomScan(node, toc, coordinate);
}
}
+
+void
+ExecShutdownCustomScan(CustomScanState *node)
+{
+ const CustomExecMethods *methods = node->methods;
+
+ if (methods->ShutdownCustomScan)
+ methods->ShutdownCustomScan(node);
+}
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 583e39021b..707db92178 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -3,7 +3,7 @@
* nodeForeignscan.c
* Routines to support scans of foreign tables
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -109,7 +109,7 @@ ForeignRecheck(ForeignScanState *node, TupleTableSlot *slot)
!fdwroutine->RecheckForeignScan(node, slot))
return false;
- return ExecQual(node->fdw_recheck_quals, econtext, false);
+ return ExecQual(node->fdw_recheck_quals, econtext);
}
/* ----------------------------------------------------------------
@@ -160,20 +160,13 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &scanstate->ss.ps);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
- scanstate->fdw_recheck_quals = (List *)
- ExecInitExpr((Expr *) node->fdw_recheck_quals,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ scanstate->fdw_recheck_quals =
+ ExecInitQual(node->fdw_recheck_quals, (PlanState *) scanstate);
/*
* tuple table initialization
@@ -363,3 +356,19 @@ ExecForeignScanInitializeWorker(ForeignScanState *node, shm_toc *toc)
fdwroutine->InitializeWorkerForeignScan(node, toc, coordinate);
}
}
+
+/* ----------------------------------------------------------------
+ * ExecShutdownForeignScan
+ *
+ * Gives FDW chance to stop asynchronous resource consumption
+ * and release any resources still held.
+ * ----------------------------------------------------------------
+ */
+void
+ExecShutdownForeignScan(ForeignScanState *node)
+{
+ FdwRoutine *fdwroutine = node->fdwroutine;
+
+ if (fdwroutine->ShutdownForeignScan)
+ fdwroutine->ShutdownForeignScan(node);
+}
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index a03f6e73fd..426527d2a2 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -3,7 +3,7 @@
* nodeFunctionscan.c
* Support routines for scanning RangeFunctions (functions in rangetable).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -35,7 +35,7 @@
*/
typedef struct FunctionScanPerFuncState
{
- ExprState *funcexpr; /* state of the expression being evaluated */
+ SetExprState *setexpr; /* state of the expression being evaluated */
TupleDesc tupdesc; /* desc of the function result type */
int colcount; /* expected number of result columns */
Tuplestorestate *tstore; /* holds the function result set */
@@ -92,7 +92,7 @@ FunctionNext(FunctionScanState *node)
if (tstore == NULL)
{
node->funcstates[0].tstore = tstore =
- ExecMakeTableFunctionResult(node->funcstates[0].funcexpr,
+ ExecMakeTableFunctionResult(node->funcstates[0].setexpr,
node->ss.ps.ps_ExprContext,
node->argcontext,
node->funcstates[0].tupdesc,
@@ -151,7 +151,7 @@ FunctionNext(FunctionScanState *node)
if (fs->tstore == NULL)
{
fs->tstore =
- ExecMakeTableFunctionResult(fs->funcexpr,
+ ExecMakeTableFunctionResult(fs->setexpr,
node->ss.ps.ps_ExprContext,
node->argcontext,
fs->tupdesc,
@@ -331,8 +331,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &scanstate->ss.ps);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
/*
* tuple table initialization
*/
@@ -342,12 +340,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
scanstate->funcstates = palloc(nfuncs * sizeof(FunctionScanPerFuncState));
@@ -363,7 +357,10 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
Oid funcrettype;
TupleDesc tupdesc;
- fs->funcexpr = ExecInitExpr((Expr *) funcexpr, (PlanState *) scanstate);
+ fs->setexpr =
+ ExecInitTableFunctionResult((Expr *) funcexpr,
+ scanstate->ss.ps.ps_ExprContext,
+ &scanstate->ss.ps);
/*
* Don't allocate the tuplestores; the actual calls to the functions
@@ -508,9 +505,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
*/
scanstate->argcontext = AllocSetContextCreate(CurrentMemoryContext,
"Table function arguments",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
return scanstate;
}
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 438d1b24fc..c1db2e263b 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -3,7 +3,7 @@
* nodeGather.c
* Support routines for scanning a plan via multiple workers.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* A Gather executor launches parallel workers to run multiple copies of a
@@ -38,6 +38,7 @@
#include "executor/nodeSubplan.h"
#include "executor/tqueue.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -80,12 +81,8 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- gatherstate->ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) gatherstate);
- gatherstate->ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) gatherstate);
+ gatherstate->ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) gatherstate);
/*
* tuple table initialization
@@ -99,8 +96,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
outerNode = outerPlan(node);
outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
- gatherstate->ps.ps_TupFromTlist = false;
-
/*
* Initialize result tuple type and projection info.
*/
@@ -131,15 +126,13 @@ ExecGather(GatherState *node)
TupleTableSlot *fslot = node->funnel_slot;
int i;
TupleTableSlot *slot;
- TupleTableSlot *resultSlot;
- ExprDoneCond isDone;
ExprContext *econtext;
/*
* Initialize the parallel context and workers on first execution. We do
* this on first execution rather than during node initialization, as it
- * needs to allocate large dynamic segment, so it is better to do if it is
- * really needed.
+ * needs to allocate a large dynamic segment, so it is better to do it
+ * only if it is really needed.
*/
if (!node->initialized)
{
@@ -172,6 +165,7 @@ ExecGather(GatherState *node)
if (pcxt->nworkers_launched > 0)
{
node->nreaders = 0;
+ node->nextreader = 0;
node->reader =
palloc(pcxt->nworkers_launched * sizeof(TupleQueueReader *));
@@ -198,57 +192,28 @@ ExecGather(GatherState *node)
}
/*
- * Check to see if we're still projecting out tuples from a previous scan
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->ps.ps_TupFromTlist)
- {
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return resultSlot;
- /* Done with that source tuple... */
- node->ps.ps_TupFromTlist = false;
- }
-
- /*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note we can't do this
- * until we're done projecting. This will also clear any previous tuple
- * returned by a TupleQueueReader; to make sure we don't leave a dangling
- * pointer around, clear the working slot first.
+ * storage allocated in the previous tuple cycle. This will also clear
+ * any previous tuple returned by a TupleQueueReader; to make sure we
+ * don't leave a dangling pointer around, clear the working slot first.
*/
- ExecClearTuple(node->funnel_slot);
+ ExecClearTuple(fslot);
econtext = node->ps.ps_ExprContext;
ResetExprContext(econtext);
- /* Get and return the next tuple, projecting if necessary. */
- for (;;)
- {
- /*
- * Get next tuple, either from one of our workers, or by running the
- * plan ourselves.
- */
- slot = gather_getnext(node);
- if (TupIsNull(slot))
- return NULL;
-
- /*
- * form the result tuple using ExecProject(), and return it --- unless
- * the projection produces an empty set, in which case we must loop
- * back around for another tuple
- */
- econtext->ecxt_outertuple = slot;
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
- return resultSlot;
- }
- }
+ /*
+ * Get next tuple, either from one of our workers, or by running the plan
+ * ourselves.
+ */
+ slot = gather_getnext(node);
+ if (TupIsNull(slot))
+ return NULL;
- return slot;
+ /*
+ * Form the result tuple using ExecProject(), and return it.
+ */
+ econtext->ecxt_outertuple = slot;
+ return ExecProject(node->ps.ps_ProjInfo);
}
/* ----------------------------------------------------------------
@@ -260,10 +225,10 @@ ExecGather(GatherState *node)
void
ExecEndGather(GatherState *node)
{
+ ExecEndNode(outerPlanState(node)); /* let children clean up first */
ExecShutdownGather(node);
ExecFreeExprContext(&node->ps);
ExecClearTuple(node->ps.ps_ResultTupleSlot);
- ExecEndNode(outerPlanState(node));
}
/*
@@ -334,6 +299,7 @@ gather_readnext(GatherState *gatherstate)
CHECK_FOR_INTERRUPTS();
/* Attempt to read a tuple, but don't block if none is available. */
+ Assert(gatherstate->nextreader < gatherstate->nreaders);
reader = gatherstate->reader[gatherstate->nextreader];
tup = TupleQueueReaderNext(reader, true, &readerdone);
@@ -387,7 +353,7 @@ gather_readnext(GatherState *gatherstate)
return NULL;
/* Nothing to do except wait for developments. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WAIT_EVENT_EXECUTE_GATHER);
ResetLatch(MyLatch);
nvisited = 0;
}
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
new file mode 100644
index 0000000000..e066574836
--- /dev/null
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -0,0 +1,681 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGatherMerge.c
+ * Scan a plan in multiple workers, and do order-preserving merge.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/executor/nodeGatherMerge.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/relscan.h"
+#include "access/xact.h"
+#include "executor/execdebug.h"
+#include "executor/execParallel.h"
+#include "executor/nodeGatherMerge.h"
+#include "executor/nodeSubplan.h"
+#include "executor/tqueue.h"
+#include "lib/binaryheap.h"
+#include "miscadmin.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+
+/*
+ * Tuple array for each worker
+ */
+typedef struct GMReaderTupleBuffer
+{
+ HeapTuple *tuple;
+ int readCounter;
+ int nTuples;
+ bool done;
+} GMReaderTupleBuffer;
+
+/*
+ * When we read tuples from workers, it's a good idea to read several at once
+ * for efficiency when possible: this minimizes context-switching overhead.
+ * But reading too many at a time wastes memory without improving performance.
+ */
+#define MAX_TUPLE_STORE 10
+
+static int32 heap_compare_slots(Datum a, Datum b, void *arg);
+static TupleTableSlot *gather_merge_getnext(GatherMergeState *gm_state);
+static HeapTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader,
+ bool nowait, bool *done);
+static void gather_merge_init(GatherMergeState *gm_state);
+static void ExecShutdownGatherMergeWorkers(GatherMergeState *node);
+static bool gather_merge_readnext(GatherMergeState *gm_state, int reader,
+ bool nowait);
+static void form_tuple_array(GatherMergeState *gm_state, int reader);
+
+/* ----------------------------------------------------------------
+ * ExecInitGather
+ * ----------------------------------------------------------------
+ */
+GatherMergeState *
+ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
+{
+ GatherMergeState *gm_state;
+ Plan *outerNode;
+ bool hasoid;
+ TupleDesc tupDesc;
+
+ /* Gather merge node doesn't have innerPlan node. */
+ Assert(innerPlan(node) == NULL);
+
+ /*
+ * create state structure
+ */
+ gm_state = makeNode(GatherMergeState);
+ gm_state->ps.plan = (Plan *) node;
+ gm_state->ps.state = estate;
+
+ /*
+ * Miscellaneous initialization
+ *
+ * create expression context for node
+ */
+ ExecAssignExprContext(estate, &gm_state->ps);
+
+ /*
+ * initialize child expressions
+ */
+ gm_state->ps.qual =
+ ExecInitQual(node->plan.qual, &gm_state->ps);
+
+ /*
+ * tuple table initialization
+ */
+ ExecInitResultTupleSlot(estate, &gm_state->ps);
+
+ /*
+ * now initialize outer plan
+ */
+ outerNode = outerPlan(node);
+ outerPlanState(gm_state) = ExecInitNode(outerNode, estate, eflags);
+
+ /*
+ * Initialize result tuple type and projection info.
+ */
+ ExecAssignResultTypeFromTL(&gm_state->ps);
+ ExecAssignProjectionInfo(&gm_state->ps, NULL);
+
+ gm_state->gm_initialized = false;
+
+ /*
+ * initialize sort-key information
+ */
+ if (node->numCols)
+ {
+ int i;
+
+ gm_state->gm_nkeys = node->numCols;
+ gm_state->gm_sortkeys =
+ palloc0(sizeof(SortSupportData) * node->numCols);
+
+ for (i = 0; i < node->numCols; i++)
+ {
+ SortSupport sortKey = gm_state->gm_sortkeys + i;
+
+ sortKey->ssup_cxt = CurrentMemoryContext;
+ sortKey->ssup_collation = node->collations[i];
+ sortKey->ssup_nulls_first = node->nullsFirst[i];
+ sortKey->ssup_attno = node->sortColIdx[i];
+
+ /*
+ * We don't perform abbreviated key conversion here, for the same
+ * reasons that it isn't used in MergeAppend
+ */
+ sortKey->abbreviate = false;
+
+ PrepareSortSupportFromOrderingOp(node->sortOperators[i], sortKey);
+ }
+ }
+
+ /*
+ * store the tuple descriptor into gather merge state, so we can use it
+ * later while initializing the gather merge slots.
+ */
+ if (!ExecContextForcesOids(&gm_state->ps, &hasoid))
+ hasoid = false;
+ tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid);
+ gm_state->tupDesc = tupDesc;
+
+ return gm_state;
+}
+
+/* ----------------------------------------------------------------
+ * ExecGatherMerge(node)
+ *
+ * Scans the relation via multiple workers and returns
+ * the next qualifying tuple.
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecGatherMerge(GatherMergeState *node)
+{
+ TupleTableSlot *slot;
+ ExprContext *econtext;
+ int i;
+
+ /*
+ * As with Gather, we don't launch workers until this node is actually
+ * executed.
+ */
+ if (!node->initialized)
+ {
+ EState *estate = node->ps.state;
+ GatherMerge *gm = (GatherMerge *) node->ps.plan;
+
+ /*
+ * Sometimes we might have to run without parallelism; but if parallel
+ * mode is active then we can try to fire up some workers.
+ */
+ if (gm->num_workers > 0 && IsInParallelMode())
+ {
+ ParallelContext *pcxt;
+
+ /* Initialize data structures for workers. */
+ if (!node->pei)
+ node->pei = ExecInitParallelPlan(node->ps.lefttree,
+ estate,
+ gm->num_workers);
+
+ /* Try to launch workers. */
+ pcxt = node->pei->pcxt;
+ LaunchParallelWorkers(pcxt);
+ node->nworkers_launched = pcxt->nworkers_launched;
+
+ /* Set up tuple queue readers to read the results. */
+ if (pcxt->nworkers_launched > 0)
+ {
+ node->nreaders = 0;
+ node->reader = palloc(pcxt->nworkers_launched *
+ sizeof(TupleQueueReader *));
+
+ Assert(gm->numCols);
+
+ for (i = 0; i < pcxt->nworkers_launched; ++i)
+ {
+ shm_mq_set_handle(node->pei->tqueue[i],
+ pcxt->worker[i].bgwhandle);
+ node->reader[node->nreaders++] =
+ CreateTupleQueueReader(node->pei->tqueue[i],
+ node->tupDesc);
+ }
+ }
+ else
+ {
+ /* No workers? Then never mind. */
+ ExecShutdownGatherMergeWorkers(node);
+ }
+ }
+
+ /* always allow leader to participate */
+ node->need_to_scan_locally = true;
+ node->initialized = true;
+ }
+
+ /*
+ * Reset per-tuple memory context to free any expression evaluation
+ * storage allocated in the previous tuple cycle.
+ */
+ econtext = node->ps.ps_ExprContext;
+ ResetExprContext(econtext);
+
+ /*
+ * Get next tuple, either from one of our workers, or by running the plan
+ * ourselves.
+ */
+ slot = gather_merge_getnext(node);
+ if (TupIsNull(slot))
+ return NULL;
+
+ /*
+ * form the result tuple using ExecProject(), and return it --- unless the
+ * projection produces an empty set, in which case we must loop back
+ * around for another tuple
+ */
+ econtext->ecxt_outertuple = slot;
+ return ExecProject(node->ps.ps_ProjInfo);
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndGatherMerge
+ *
+ * frees any storage allocated through C routines.
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndGatherMerge(GatherMergeState *node)
+{
+ ExecEndNode(outerPlanState(node)); /* let children clean up first */
+ ExecShutdownGatherMerge(node);
+ ExecFreeExprContext(&node->ps);
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+}
+
+/* ----------------------------------------------------------------
+ * ExecShutdownGatherMerge
+ *
+ * Destroy the setup for parallel workers including parallel context.
+ * Collect all the stats after workers are stopped, else some work
+ * done by workers won't be accounted.
+ * ----------------------------------------------------------------
+ */
+void
+ExecShutdownGatherMerge(GatherMergeState *node)
+{
+ ExecShutdownGatherMergeWorkers(node);
+
+ /* Now destroy the parallel context. */
+ if (node->pei != NULL)
+ {
+ ExecParallelCleanup(node->pei);
+ node->pei = NULL;
+ }
+}
+
+/* ----------------------------------------------------------------
+ * ExecShutdownGatherMergeWorkers
+ *
+ * Destroy the parallel workers. Collect all the stats after
+ * workers are stopped, else some work done by workers won't be
+ * accounted.
+ * ----------------------------------------------------------------
+ */
+static void
+ExecShutdownGatherMergeWorkers(GatherMergeState *node)
+{
+ /* Shut down tuple queue readers before shutting down workers. */
+ if (node->reader != NULL)
+ {
+ int i;
+
+ for (i = 0; i < node->nreaders; ++i)
+ if (node->reader[i])
+ DestroyTupleQueueReader(node->reader[i]);
+
+ pfree(node->reader);
+ node->reader = NULL;
+ }
+
+ /* Now shut down the workers. */
+ if (node->pei != NULL)
+ ExecParallelFinish(node->pei);
+}
+
+/* ----------------------------------------------------------------
+ * ExecReScanGatherMerge
+ *
+ * Re-initialize the workers and rescans a relation via them.
+ * ----------------------------------------------------------------
+ */
+void
+ExecReScanGatherMerge(GatherMergeState *node)
+{
+ /*
+ * Re-initialize the parallel workers to perform rescan of relation. We
+ * want to gracefully shutdown all the workers so that they should be able
+ * to propagate any error or other information to master backend before
+ * dying. Parallel context will be reused for rescan.
+ */
+ ExecShutdownGatherMergeWorkers(node);
+
+ node->initialized = false;
+
+ if (node->pei)
+ ExecParallelReinitialize(node->pei);
+
+ ExecReScan(node->ps.lefttree);
+}
+
+/*
+ * Initialize the Gather merge tuple read.
+ *
+ * Pull at least a single tuple from each worker + leader and set up the heap.
+ */
+static void
+gather_merge_init(GatherMergeState *gm_state)
+{
+ int nreaders = gm_state->nreaders;
+ bool initialize = true;
+ int i;
+
+ /*
+ * Allocate gm_slots for the number of worker + one more slot for leader.
+ * Last slot is always for leader. Leader always calls ExecProcNode() to
+ * read the tuple which will return the TupleTableSlot. Later it will
+ * directly get assigned to gm_slot. So just initialize leader gm_slot
+ * with NULL. For other slots below code will call
+ * ExecInitExtraTupleSlot() which will do the initialization of worker
+ * slots.
+ */
+ gm_state->gm_slots =
+ palloc((gm_state->nreaders + 1) * sizeof(TupleTableSlot *));
+ gm_state->gm_slots[gm_state->nreaders] = NULL;
+
+ /* Initialize the tuple slot and tuple array for each worker */
+ gm_state->gm_tuple_buffers =
+ (GMReaderTupleBuffer *) palloc0(sizeof(GMReaderTupleBuffer) *
+ (gm_state->nreaders + 1));
+ for (i = 0; i < gm_state->nreaders; i++)
+ {
+ /* Allocate the tuple array with MAX_TUPLE_STORE size */
+ gm_state->gm_tuple_buffers[i].tuple =
+ (HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE);
+
+ /* Initialize slot for worker */
+ gm_state->gm_slots[i] = ExecInitExtraTupleSlot(gm_state->ps.state);
+ ExecSetSlotDescriptor(gm_state->gm_slots[i],
+ gm_state->tupDesc);
+ }
+
+ /* Allocate the resources for the merge */
+ gm_state->gm_heap = binaryheap_allocate(gm_state->nreaders + 1,
+ heap_compare_slots,
+ gm_state);
+
+ /*
+ * First, try to read a tuple from each worker (including leader) in
+ * nowait mode, so that we initialize read from each worker as well as
+ * leader. After this, if all active workers are unable to produce a
+ * tuple, then re-read and this time use wait mode. For workers that were
+ * able to produce a tuple in the earlier loop and are still active, just
+ * try to fill the tuple array if more tuples are avaiable.
+ */
+reread:
+ for (i = 0; i < nreaders + 1; i++)
+ {
+ if (!gm_state->gm_tuple_buffers[i].done &&
+ (TupIsNull(gm_state->gm_slots[i]) ||
+ gm_state->gm_slots[i]->tts_isempty))
+ {
+ if (gather_merge_readnext(gm_state, i, initialize))
+ {
+ binaryheap_add_unordered(gm_state->gm_heap,
+ Int32GetDatum(i));
+ }
+ }
+ else
+ form_tuple_array(gm_state, i);
+ }
+ initialize = false;
+
+ for (i = 0; i < nreaders; i++)
+ if (!gm_state->gm_tuple_buffers[i].done &&
+ (TupIsNull(gm_state->gm_slots[i]) ||
+ gm_state->gm_slots[i]->tts_isempty))
+ goto reread;
+
+ binaryheap_build(gm_state->gm_heap);
+ gm_state->gm_initialized = true;
+}
+
+/*
+ * Clear out the tuple table slots for each gather merge input.
+ */
+static void
+gather_merge_clear_slots(GatherMergeState *gm_state)
+{
+ int i;
+
+ for (i = 0; i < gm_state->nreaders; i++)
+ {
+ pfree(gm_state->gm_tuple_buffers[i].tuple);
+ gm_state->gm_slots[i] = ExecClearTuple(gm_state->gm_slots[i]);
+ }
+
+ /* Free tuple array as we don't need it any more */
+ pfree(gm_state->gm_tuple_buffers);
+ /* Free the binaryheap, which was created for sort */
+ binaryheap_free(gm_state->gm_heap);
+}
+
+/*
+ * Read the next tuple for gather merge.
+ *
+ * Fetch the sorted tuple out of the heap.
+ */
+static TupleTableSlot *
+gather_merge_getnext(GatherMergeState *gm_state)
+{
+ int i;
+
+ if (!gm_state->gm_initialized)
+ {
+ /*
+ * First time through: pull the first tuple from each participant, and
+ * set up the heap.
+ */
+ gather_merge_init(gm_state);
+ }
+ else
+ {
+ /*
+ * Otherwise, pull the next tuple from whichever participant we
+ * returned from last time, and reinsert that participant's index into
+ * the heap, because it might now compare differently against the
+ * other elements of the heap.
+ */
+ i = DatumGetInt32(binaryheap_first(gm_state->gm_heap));
+
+ if (gather_merge_readnext(gm_state, i, false))
+ binaryheap_replace_first(gm_state->gm_heap, Int32GetDatum(i));
+ else
+ (void) binaryheap_remove_first(gm_state->gm_heap);
+ }
+
+ if (binaryheap_empty(gm_state->gm_heap))
+ {
+ /* All the queues are exhausted, and so is the heap */
+ gather_merge_clear_slots(gm_state);
+ return NULL;
+ }
+ else
+ {
+ /* Return next tuple from whichever participant has the leading one */
+ i = DatumGetInt32(binaryheap_first(gm_state->gm_heap));
+ return gm_state->gm_slots[i];
+ }
+}
+
+/*
+ * Read the tuple for given reader in nowait mode, and form the tuple array.
+ */
+static void
+form_tuple_array(GatherMergeState *gm_state, int reader)
+{
+ GMReaderTupleBuffer *tuple_buffer = &gm_state->gm_tuple_buffers[reader];
+ int i;
+
+ /* Last slot is for leader and we don't build tuple array for leader */
+ if (reader == gm_state->nreaders)
+ return;
+
+ /*
+ * We here because we already read all the tuples from the tuple array, so
+ * initialize the counter to zero.
+ */
+ if (tuple_buffer->nTuples == tuple_buffer->readCounter)
+ tuple_buffer->nTuples = tuple_buffer->readCounter = 0;
+
+ /* Tuple array is already full? */
+ if (tuple_buffer->nTuples == MAX_TUPLE_STORE)
+ return;
+
+ for (i = tuple_buffer->nTuples; i < MAX_TUPLE_STORE; i++)
+ {
+ tuple_buffer->tuple[i] = heap_copytuple(gm_readnext_tuple(gm_state,
+ reader,
+ false,
+ &tuple_buffer->done));
+ if (!HeapTupleIsValid(tuple_buffer->tuple[i]))
+ break;
+ tuple_buffer->nTuples++;
+ }
+}
+
+/*
+ * Store the next tuple for a given reader into the appropriate slot.
+ *
+ * Returns false if the reader is exhausted, and true otherwise.
+ */
+static bool
+gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait)
+{
+ GMReaderTupleBuffer *tuple_buffer;
+ HeapTuple tup = NULL;
+
+ /*
+ * If we're being asked to generate a tuple from the leader, then we just
+ * call ExecProcNode as normal to produce one.
+ */
+ if (gm_state->nreaders == reader)
+ {
+ if (gm_state->need_to_scan_locally)
+ {
+ PlanState *outerPlan = outerPlanState(gm_state);
+ TupleTableSlot *outerTupleSlot;
+
+ outerTupleSlot = ExecProcNode(outerPlan);
+
+ if (!TupIsNull(outerTupleSlot))
+ {
+ gm_state->gm_slots[reader] = outerTupleSlot;
+ return true;
+ }
+ gm_state->gm_tuple_buffers[reader].done = true;
+ gm_state->need_to_scan_locally = false;
+ }
+ return false;
+ }
+
+ /* Otherwise, check the state of the relevant tuple buffer. */
+ tuple_buffer = &gm_state->gm_tuple_buffers[reader];
+
+ if (tuple_buffer->nTuples > tuple_buffer->readCounter)
+ {
+ /* Return any tuple previously read that is still buffered. */
+ tuple_buffer = &gm_state->gm_tuple_buffers[reader];
+ tup = tuple_buffer->tuple[tuple_buffer->readCounter++];
+ }
+ else if (tuple_buffer->done)
+ {
+ /* Reader is known to be exhausted. */
+ DestroyTupleQueueReader(gm_state->reader[reader]);
+ gm_state->reader[reader] = NULL;
+ return false;
+ }
+ else
+ {
+ /* Read and buffer next tuple. */
+ tup = heap_copytuple(gm_readnext_tuple(gm_state,
+ reader,
+ nowait,
+ &tuple_buffer->done));
+
+ /*
+ * Attempt to read more tuples in nowait mode and store them in the
+ * tuple array.
+ */
+ if (HeapTupleIsValid(tup))
+ form_tuple_array(gm_state, reader);
+ else
+ return false;
+ }
+
+ Assert(HeapTupleIsValid(tup));
+
+ /* Build the TupleTableSlot for the given tuple */
+ ExecStoreTuple(tup, /* tuple to store */
+ gm_state->gm_slots[reader], /* slot in which to store the
+ * tuple */
+ InvalidBuffer, /* buffer associated with this tuple */
+ true); /* pfree this pointer if not from heap */
+
+ return true;
+}
+
+/*
+ * Attempt to read a tuple from given reader.
+ */
+static HeapTuple
+gm_readnext_tuple(GatherMergeState *gm_state, int nreader, bool nowait,
+ bool *done)
+{
+ TupleQueueReader *reader;
+ HeapTuple tup = NULL;
+ MemoryContext oldContext;
+ MemoryContext tupleContext;
+
+ tupleContext = gm_state->ps.ps_ExprContext->ecxt_per_tuple_memory;
+
+ if (done != NULL)
+ *done = false;
+
+ /* Check for async events, particularly messages from workers. */
+ CHECK_FOR_INTERRUPTS();
+
+ /* Attempt to read a tuple. */
+ reader = gm_state->reader[nreader];
+
+ /* Run TupleQueueReaders in per-tuple context */
+ oldContext = MemoryContextSwitchTo(tupleContext);
+ tup = TupleQueueReaderNext(reader, nowait, done);
+ MemoryContextSwitchTo(oldContext);
+
+ return tup;
+}
+
+/*
+ * We have one slot for each item in the heap array. We use SlotNumber
+ * to store slot indexes. This doesn't actually provide any formal
+ * type-safety, but it makes the code more self-documenting.
+ */
+typedef int32 SlotNumber;
+
+/*
+ * Compare the tuples in the two given slots.
+ */
+static int32
+heap_compare_slots(Datum a, Datum b, void *arg)
+{
+ GatherMergeState *node = (GatherMergeState *) arg;
+ SlotNumber slot1 = DatumGetInt32(a);
+ SlotNumber slot2 = DatumGetInt32(b);
+
+ TupleTableSlot *s1 = node->gm_slots[slot1];
+ TupleTableSlot *s2 = node->gm_slots[slot2];
+ int nkey;
+
+ Assert(!TupIsNull(s1));
+ Assert(!TupIsNull(s2));
+
+ for (nkey = 0; nkey < node->gm_nkeys; nkey++)
+ {
+ SortSupport sortKey = node->gm_sortkeys + nkey;
+ AttrNumber attno = sortKey->ssup_attno;
+ Datum datum1,
+ datum2;
+ bool isNull1,
+ isNull2;
+ int compare;
+
+ datum1 = slot_getattr(s1, attno, &isNull1);
+ datum2 = slot_getattr(s2, attno, &isNull2);
+
+ compare = ApplySortComparator(datum1, isNull1,
+ datum2, isNull2,
+ sortKey);
+ if (compare != 0)
+ return -compare;
+ }
+ return 0;
+}
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index dcf5175d9b..af9ba4905e 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -3,7 +3,7 @@
* nodeGroup.c
* Routines to handle group nodes (used for queries with GROUP BY clause).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -50,23 +50,6 @@ ExecGroup(GroupState *node)
grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
/*
- * Check to see if we're still projecting out tuples from a previous group
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->ss.ps.ps_TupFromTlist)
- {
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return result;
- /* Done with that source tuple... */
- node->ss.ps.ps_TupFromTlist = false;
- }
-
- /*
* The ScanTupleSlot holds the (copied) first tuple of each group.
*/
firsttupleslot = node->ss.ss_ScanTupleSlot;
@@ -102,21 +85,12 @@ ExecGroup(GroupState *node)
* Check the qual (HAVING clause); if the group does not match, ignore
* it and fall into scan loop.
*/
- if (ExecQual(node->ss.ps.qual, econtext, false))
+ if (ExecQual(node->ss.ps.qual, econtext))
{
/*
* Form and return a projection tuple using the first input tuple.
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->ss.ps.ps_ProjInfo);
}
else
InstrCountFiltered1(node, 1);
@@ -165,21 +139,12 @@ ExecGroup(GroupState *node)
* Check the qual (HAVING clause); if the group does not match, ignore
* it and loop back to scan the rest of the group.
*/
- if (ExecQual(node->ss.ps.qual, econtext, false))
+ if (ExecQual(node->ss.ps.qual, econtext))
{
/*
* Form and return a projection tuple using the first input tuple.
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->ss.ps.ps_ProjInfo);
}
else
InstrCountFiltered1(node, 1);
@@ -223,12 +188,8 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- grpstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) grpstate);
- grpstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) grpstate);
+ grpstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) grpstate);
/*
* initialize child nodes
@@ -246,8 +207,6 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
ExecAssignResultTypeFromTL(&grpstate->ss.ps);
ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
- grpstate->ss.ps.ps_TupFromTlist = false;
-
/*
* Precompute fmgr lookup data for inner loop
*/
@@ -283,7 +242,6 @@ ExecReScanGroup(GroupState *node)
PlanState *outerPlan = outerPlanState(node);
node->grp_done = FALSE;
- node->ss.ps.ps_TupFromTlist = false;
/* must clear first tuple */
ExecClearTuple(node->ss.ss_ScanTupleSlot);
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 9ed09a7b0c..d9789d0719 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -3,7 +3,7 @@
* nodeHash.c
* Routines to hash relations for hashjoin
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -190,12 +190,8 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- hashstate->ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) hashstate);
- hashstate->ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) hashstate);
+ hashstate->ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) hashstate);
/*
* initialize child nodes
@@ -344,15 +340,11 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
*/
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
"HashTableContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
"HashBatchContext",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/* Allocate data that will live for the life of the hashjoin */
@@ -724,6 +716,9 @@ ExecHashIncreaseNumBatches(HashJoinTable hashtable)
/* next tuple in this chunk */
idx += MAXALIGN(hashTupleSize);
+
+ /* allow this loop to be cancellable */
+ CHECK_FOR_INTERRUPTS();
}
/* we're done with this chunk - free it and proceed to the next one */
@@ -963,7 +958,7 @@ ExecHashGetHashValue(HashJoinTable hashtable,
/*
* Get the join attribute value of the tuple
*/
- keyval = ExecEvalExpr(keyexpr, econtext, &isNull, NULL);
+ keyval = ExecEvalExpr(keyexpr, econtext, &isNull);
/*
* If the attribute is NULL, and the join operator is strict, then
@@ -1064,7 +1059,7 @@ bool
ExecScanHashBucket(HashJoinState *hjstate,
ExprContext *econtext)
{
- List *hjclauses = hjstate->hashclauses;
+ ExprState *hjclauses = hjstate->hashclauses;
HashJoinTable hashtable = hjstate->hj_HashTable;
HashJoinTuple hashTuple = hjstate->hj_CurTuple;
uint32 hashvalue = hjstate->hj_CurHashValue;
@@ -1098,7 +1093,7 @@ ExecScanHashBucket(HashJoinState *hjstate,
/* reset temp memory each time to avoid leaks from qual expr */
ResetExprContext(econtext);
- if (ExecQual(hjclauses, econtext, false))
+ if (ExecQual(hjclauses, econtext))
{
hjstate->hj_CurTuple = hashTuple;
return true;
@@ -1288,10 +1283,7 @@ static void
ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
{
HeapTupleData *statsTuple;
- Datum *values;
- int nvalues;
- float4 *numbers;
- int nnumbers;
+ AttStatsSlot sslot;
/* Do nothing if planner didn't identify the outer relation's join key */
if (!OidIsValid(node->skewTable))
@@ -1310,19 +1302,17 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
if (!HeapTupleIsValid(statsTuple))
return;
- if (get_attstatsslot(statsTuple, node->skewColType, node->skewColTypmod,
+ if (get_attstatsslot(&sslot, statsTuple,
STATISTIC_KIND_MCV, InvalidOid,
- NULL,
- &values, &nvalues,
- &numbers, &nnumbers))
+ ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS))
{
double frac;
int nbuckets;
FmgrInfo *hashfunctions;
int i;
- if (mcvsToUse > nvalues)
- mcvsToUse = nvalues;
+ if (mcvsToUse > sslot.nvalues)
+ mcvsToUse = sslot.nvalues;
/*
* Calculate the expected fraction of outer relation that will
@@ -1331,11 +1321,10 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
*/
frac = 0;
for (i = 0; i < mcvsToUse; i++)
- frac += numbers[i];
+ frac += sslot.numbers[i];
if (frac < SKEW_MIN_OUTER_FRACTION)
{
- free_attstatsslot(node->skewColType,
- values, nvalues, numbers, nnumbers);
+ free_attstatsslot(&sslot);
ReleaseSysCache(statsTuple);
return;
}
@@ -1397,7 +1386,7 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
int bucket;
hashvalue = DatumGetUInt32(FunctionCall1(&hashfunctions[0],
- values[i]));
+ sslot.values[i]));
/*
* While we have not hit a hole in the hashtable and have not hit
@@ -1431,8 +1420,7 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
hashtable->spacePeak = hashtable->spaceUsed;
}
- free_attstatsslot(node->skewColType,
- values, nvalues, numbers, nnumbers);
+ free_attstatsslot(&sslot);
}
ReleaseSysCache(statsTuple);
@@ -1603,6 +1591,9 @@ ExecHashRemoveNextSkewBucket(HashJoinTable hashtable)
}
hashTuple = nextHashTuple;
+
+ /* allow this loop to be cancellable */
+ CHECK_FOR_INTERRUPTS();
}
/*
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 369e666f88..f9ab0d6035 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -3,7 +3,7 @@
* nodeHashjoin.c
* Routines to handle hash join nodes
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -63,10 +63,9 @@ ExecHashJoin(HashJoinState *node)
{
PlanState *outerNode;
HashState *hashNode;
- List *joinqual;
- List *otherqual;
+ ExprState *joinqual;
+ ExprState *otherqual;
ExprContext *econtext;
- ExprDoneCond isDone;
HashJoinTable hashtable;
TupleTableSlot *outerTupleSlot;
uint32 hashvalue;
@@ -83,25 +82,8 @@ ExecHashJoin(HashJoinState *node)
econtext = node->js.ps.ps_ExprContext;
/*
- * Check to see if we're still projecting out tuples from a previous join
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->js.ps.ps_TupFromTlist)
- {
- TupleTableSlot *result;
-
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return result;
- /* Done with that source tuple... */
- node->js.ps.ps_TupFromTlist = false;
- }
-
- /*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't happen
- * until we're done projecting out tuples from a join tuple.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -293,7 +275,7 @@ ExecHashJoin(HashJoinState *node)
* Only the joinquals determine tuple match status, but all
* quals must pass to actually return the tuple.
*/
- if (joinqual == NIL || ExecQual(joinqual, econtext, false))
+ if (joinqual == NULL || ExecQual(joinqual, econtext))
{
node->hj_MatchedOuter = true;
HeapTupleHeaderSetMatch(HJTUPLE_MINTUPLE(node->hj_CurTuple));
@@ -306,26 +288,15 @@ ExecHashJoin(HashJoinState *node)
}
/*
- * In a semijoin, we'll consider returning the first
- * match, but after that we're done with this outer tuple.
+ * If we only need to join to the first matching inner
+ * tuple, then consider returning this one, but after that
+ * continue with next outer tuple.
*/
- if (node->js.jointype == JOIN_SEMI)
+ if (node->js.single_match)
node->hj_JoinState = HJ_NEED_NEW_OUTER;
- if (otherqual == NIL ||
- ExecQual(otherqual, econtext, false))
- {
- TupleTableSlot *result;
-
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ if (otherqual == NULL || ExecQual(otherqual, econtext))
+ return ExecProject(node->js.ps.ps_ProjInfo);
else
InstrCountFiltered2(node, 1);
}
@@ -351,20 +322,8 @@ ExecHashJoin(HashJoinState *node)
*/
econtext->ecxt_innertuple = node->hj_NullInnerTupleSlot;
- if (otherqual == NIL ||
- ExecQual(otherqual, econtext, false))
- {
- TupleTableSlot *result;
-
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ if (otherqual == NULL || ExecQual(otherqual, econtext))
+ return ExecProject(node->js.ps.ps_ProjInfo);
else
InstrCountFiltered2(node, 1);
}
@@ -390,20 +349,8 @@ ExecHashJoin(HashJoinState *node)
*/
econtext->ecxt_outertuple = node->hj_NullOuterTupleSlot;
- if (otherqual == NIL ||
- ExecQual(otherqual, econtext, false))
- {
- TupleTableSlot *result;
-
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ if (otherqual == NULL || ExecQual(otherqual, econtext))
+ return ExecProject(node->js.ps.ps_ProjInfo);
else
InstrCountFiltered2(node, 1);
break;
@@ -462,19 +409,13 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- hjstate->js.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->join.plan.targetlist,
- (PlanState *) hjstate);
- hjstate->js.ps.qual = (List *)
- ExecInitExpr((Expr *) node->join.plan.qual,
- (PlanState *) hjstate);
+ hjstate->js.ps.qual =
+ ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
hjstate->js.jointype = node->join.jointype;
- hjstate->js.joinqual = (List *)
- ExecInitExpr((Expr *) node->join.joinqual,
- (PlanState *) hjstate);
- hjstate->hashclauses = (List *)
- ExecInitExpr((Expr *) node->hashclauses,
- (PlanState *) hjstate);
+ hjstate->js.joinqual =
+ ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
+ hjstate->hashclauses =
+ ExecInitQual(node->hashclauses, (PlanState *) hjstate);
/*
* initialize child nodes
@@ -495,6 +436,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
ExecInitResultTupleSlot(estate, &hjstate->js.ps);
hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
+ /*
+ * detect whether we need only consider the first matching inner tuple
+ */
+ hjstate->js.single_match = (node->join.inner_unique ||
+ node->join.jointype == JOIN_SEMI);
+
/* set up null tuples for outer joins, if needed */
switch (node->join.jointype)
{
@@ -568,16 +515,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
lclauses = NIL;
rclauses = NIL;
hoperators = NIL;
- foreach(l, hjstate->hashclauses)
+ foreach(l, node->hashclauses)
{
- FuncExprState *fstate = (FuncExprState *) lfirst(l);
- OpExpr *hclause;
-
- Assert(IsA(fstate, FuncExprState));
- hclause = (OpExpr *) fstate->xprstate.expr;
- Assert(IsA(hclause, OpExpr));
- lclauses = lappend(lclauses, linitial(fstate->args));
- rclauses = lappend(rclauses, lsecond(fstate->args));
+ OpExpr *hclause = lfirst_node(OpExpr, l);
+
+ lclauses = lappend(lclauses, ExecInitExpr(linitial(hclause->args),
+ (PlanState *) hjstate));
+ rclauses = lappend(rclauses, ExecInitExpr(lsecond(hclause->args),
+ (PlanState *) hjstate));
hoperators = lappend_oid(hoperators, hclause->opno);
}
hjstate->hj_OuterHashKeys = lclauses;
@@ -586,7 +531,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
/* child Hash node needs to evaluate inner hash keys, too */
((HashState *) innerPlanState(hjstate))->hashkeys = rclauses;
- hjstate->js.ps.ps_TupFromTlist = false;
hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
hjstate->hj_MatchedOuter = false;
hjstate->hj_OuterNotEmpty = false;
@@ -912,6 +856,13 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
MinimalTuple tuple;
/*
+ * We check for interrupts here because this is typically taken as an
+ * alternative code path to an ExecProcNode() call, which would include
+ * such a check.
+ */
+ CHECK_FOR_INTERRUPTS();
+
+ /*
* Since both the hash value and the MinimalTuple length word are uint32,
* we can read them both in one BufFileRead() call without any type
* cheating.
@@ -1000,7 +951,6 @@ ExecReScanHashJoin(HashJoinState *node)
node->hj_CurSkewBucketNo = INVALID_SKEW_BUCKET_NO;
node->hj_CurTuple = NULL;
- node->js.ps.ps_TupFromTlist = false;
node->hj_MatchedOuter = false;
node->hj_FirstOuterTupleSlot = NULL;
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 4f6f91c8db..5550f6c0a4 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -3,7 +3,7 @@
* nodeIndexonlyscan.c
* Routines to support index-only scans
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -21,6 +21,11 @@
* ExecEndIndexOnlyScan releases all storage.
* ExecIndexOnlyMarkPos marks scan position.
* ExecIndexOnlyRestrPos restores scan position.
+ * ExecIndexOnlyScanEstimate estimates DSM space needed for
+ * parallel index-only scan
+ * ExecIndexOnlyScanInitializeDSM initialize DSM for parallel
+ * index-only scan
+ * ExecIndexOnlyScanInitializeWorker attach to DSM info in parallel worker
*/
#include "postgres.h"
@@ -73,6 +78,38 @@ IndexOnlyNext(IndexOnlyScanState *node)
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
+ if (scandesc == NULL)
+ {
+ /*
+ * We reach here if the index only scan is not parallel, or if we're
+ * executing a index only scan that was intended to be parallel
+ * serially.
+ */
+ scandesc = index_beginscan(node->ss.ss_currentRelation,
+ node->ioss_RelationDesc,
+ estate->es_snapshot,
+ node->ioss_NumScanKeys,
+ node->ioss_NumOrderByKeys);
+
+ node->ioss_ScanDesc = scandesc;
+
+
+ /* Set it up for index-only scan */
+ node->ioss_ScanDesc->xs_want_itup = true;
+ node->ioss_VMBuffer = InvalidBuffer;
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and
+ * pass the scankeys to the index AM.
+ */
+ if (node->ioss_NumRuntimeKeys == 0 || node->ioss_RuntimeKeysReady)
+ index_rescan(scandesc,
+ node->ioss_ScanKeys,
+ node->ioss_NumScanKeys,
+ node->ioss_OrderByKeys,
+ node->ioss_NumOrderByKeys);
+ }
+
/*
* OK, now that we have what we need, fetch the next tuple.
*/
@@ -144,9 +181,26 @@ IndexOnlyNext(IndexOnlyScanState *node)
}
/*
- * Fill the scan tuple slot with data from the index.
+ * Fill the scan tuple slot with data from the index. This might be
+ * provided in either HeapTuple or IndexTuple format. Conceivably an
+ * index AM might fill both fields, in which case we prefer the heap
+ * format, since it's probably a bit cheaper to fill a slot from.
*/
- StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc);
+ if (scandesc->xs_hitup)
+ {
+ /*
+ * We don't take the trouble to verify that the provided tuple has
+ * exactly the slot's format, but it seems worth doing a quick
+ * check on the number of fields.
+ */
+ Assert(slot->tts_tupleDescriptor->natts ==
+ scandesc->xs_hitupdesc->natts);
+ ExecStoreTuple(scandesc->xs_hitup, slot, InvalidBuffer, false);
+ }
+ else if (scandesc->xs_itup)
+ StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc);
+ else
+ elog(ERROR, "no data returned for index-only scan");
/*
* If the index was lossy, we have to recheck the index quals.
@@ -157,7 +211,7 @@ IndexOnlyNext(IndexOnlyScanState *node)
{
econtext->ecxt_scantuple = slot;
ResetExprContext(econtext);
- if (!ExecQual(node->indexqual, econtext, false))
+ if (!ExecQual(node->indexqual, econtext))
{
/* Fails recheck, so drop it and loop back for another */
InstrCountFiltered2(node, 1);
@@ -277,6 +331,16 @@ ExecIndexOnlyScan(IndexOnlyScanState *node)
void
ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
{
+ bool reset_parallel_scan = true;
+
+ /*
+ * If we are here to just update the scan keys, then don't reset parallel
+ * scan. For detailed reason behind this look in the comments for
+ * ExecReScanIndexScan.
+ */
+ if (node->ioss_NumRuntimeKeys != 0 && !node->ioss_RuntimeKeysReady)
+ reset_parallel_scan = false;
+
/*
* If we are doing runtime key calculations (ie, any of the index key
* values weren't simple Consts), compute the new key values. But first,
@@ -296,10 +360,16 @@ ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
node->ioss_RuntimeKeysReady = true;
/* reset index scan */
- index_rescan(node->ioss_ScanDesc,
- node->ioss_ScanKeys, node->ioss_NumScanKeys,
- node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+ if (node->ioss_ScanDesc)
+ {
+ index_rescan(node->ioss_ScanDesc,
+ node->ioss_ScanKeys, node->ioss_NumScanKeys,
+ node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+
+ if (reset_parallel_scan && node->ioss_ScanDesc->parallel_scan)
+ index_parallelrescan(node->ioss_ScanDesc);
+ }
ExecScanReScan(&node->ss);
}
@@ -412,23 +482,16 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &indexstate->ss.ps);
- indexstate->ss.ps.ps_TupFromTlist = false;
-
/*
* initialize child expressions
*
* Note: we don't initialize all of the indexorderby expression, only the
* sub-parts corresponding to runtime keys (see below).
*/
- indexstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) indexstate);
- indexstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) indexstate);
- indexstate->indexqual = (List *)
- ExecInitExpr((Expr *) node->indexqual,
- (PlanState *) indexstate);
+ indexstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) indexstate);
+ indexstate->indexqual =
+ ExecInitQual(node->indexqual, (PlanState *) indexstate);
/*
* tuple table initialization
@@ -536,31 +599,98 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
}
/*
- * Initialize scan descriptor.
+ * all done.
*/
- indexstate->ioss_ScanDesc = index_beginscan(currentRelation,
- indexstate->ioss_RelationDesc,
- estate->es_snapshot,
- indexstate->ioss_NumScanKeys,
- indexstate->ioss_NumOrderByKeys);
+ return indexstate;
+}
+
+/* ----------------------------------------------------------------
+ * Parallel Index-only Scan Support
+ * ----------------------------------------------------------------
+ */
- /* Set it up for index-only scan */
- indexstate->ioss_ScanDesc->xs_want_itup = true;
- indexstate->ioss_VMBuffer = InvalidBuffer;
+/* ----------------------------------------------------------------
+ * ExecIndexOnlyScanEstimate
+ *
+ * estimates the space required to serialize index-only scan node.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexOnlyScanEstimate(IndexOnlyScanState *node,
+ ParallelContext *pcxt)
+{
+ EState *estate = node->ss.ps.state;
+
+ node->ioss_PscanLen = index_parallelscan_estimate(node->ioss_RelationDesc,
+ estate->es_snapshot);
+ shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+}
+
+/* ----------------------------------------------------------------
+ * ExecIndexOnlyScanInitializeDSM
+ *
+ * Set up a parallel index-only scan descriptor.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt)
+{
+ EState *estate = node->ss.ps.state;
+ ParallelIndexScanDesc piscan;
+
+ piscan = shm_toc_allocate(pcxt->toc, node->ioss_PscanLen);
+ index_parallelscan_initialize(node->ss.ss_currentRelation,
+ node->ioss_RelationDesc,
+ estate->es_snapshot,
+ piscan);
+ shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
+ node->ioss_ScanDesc =
+ index_beginscan_parallel(node->ss.ss_currentRelation,
+ node->ioss_RelationDesc,
+ node->ioss_NumScanKeys,
+ node->ioss_NumOrderByKeys,
+ piscan);
+ node->ioss_ScanDesc->xs_want_itup = true;
+ node->ioss_VMBuffer = InvalidBuffer;
/*
- * If no run-time keys to calculate, go ahead and pass the scankeys to the
- * index AM.
+ * If no run-time keys to calculate or they are ready, go ahead and pass
+ * the scankeys to the index AM.
*/
- if (indexstate->ioss_NumRuntimeKeys == 0)
- index_rescan(indexstate->ioss_ScanDesc,
- indexstate->ioss_ScanKeys,
- indexstate->ioss_NumScanKeys,
- indexstate->ioss_OrderByKeys,
- indexstate->ioss_NumOrderByKeys);
+ if (node->ioss_NumRuntimeKeys == 0 || node->ioss_RuntimeKeysReady)
+ index_rescan(node->ioss_ScanDesc,
+ node->ioss_ScanKeys, node->ioss_NumScanKeys,
+ node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+}
+
+/* ----------------------------------------------------------------
+ * ExecIndexOnlyScanInitializeWorker
+ *
+ * Copy relevant information from TOC into planstate.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, shm_toc *toc)
+{
+ ParallelIndexScanDesc piscan;
+
+ piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
+ node->ioss_ScanDesc =
+ index_beginscan_parallel(node->ss.ss_currentRelation,
+ node->ioss_RelationDesc,
+ node->ioss_NumScanKeys,
+ node->ioss_NumOrderByKeys,
+ piscan);
+ node->ioss_ScanDesc->xs_want_itup = true;
/*
- * all done.
+ * If no run-time keys to calculate or they are ready, go ahead and pass
+ * the scankeys to the index AM.
*/
- return indexstate;
+ if (node->ioss_NumRuntimeKeys == 0 || node->ioss_RuntimeKeysReady)
+ index_rescan(node->ioss_ScanDesc,
+ node->ioss_ScanKeys, node->ioss_NumScanKeys,
+ node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
}
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 3143bd94ec..5afd02e09d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -3,7 +3,7 @@
* nodeIndexscan.c
* Routines to support indexed scans of relations
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,6 +22,9 @@
* ExecEndIndexScan releases all storage.
* ExecIndexMarkPos marks scan position.
* ExecIndexRestrPos restores scan position.
+ * ExecIndexScanEstimate estimates DSM space needed for parallel index scan
+ * ExecIndexScanInitializeDSM initialize DSM for parallel indexscan
+ * ExecIndexScanInitializeWorker attach to DSM info in parallel worker
*/
#include "postgres.h"
@@ -99,6 +102,30 @@ IndexNext(IndexScanState *node)
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
+ if (scandesc == NULL)
+ {
+ /*
+ * We reach here if the index scan is not parallel, or if we're
+ * executing a index scan that was intended to be parallel serially.
+ */
+ scandesc = index_beginscan(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ estate->es_snapshot,
+ node->iss_NumScanKeys,
+ node->iss_NumOrderByKeys);
+
+ node->iss_ScanDesc = scandesc;
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and
+ * pass the scankeys to the index AM.
+ */
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+ index_rescan(scandesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+ }
+
/*
* ok, now that we have what we need, fetch the next tuple.
*/
@@ -122,7 +149,7 @@ IndexNext(IndexScanState *node)
{
econtext->ecxt_scantuple = slot;
ResetExprContext(econtext);
- if (!ExecQual(node->indexqualorig, econtext, false))
+ if (!ExecQual(node->indexqualorig, econtext))
{
/* Fails recheck, so drop it and loop back for another */
InstrCountFiltered2(node, 1);
@@ -151,6 +178,7 @@ IndexNext(IndexScanState *node)
static TupleTableSlot *
IndexNextWithReorder(IndexScanState *node)
{
+ EState *estate;
ExprContext *econtext;
IndexScanDesc scandesc;
HeapTuple tuple;
@@ -161,6 +189,8 @@ IndexNextWithReorder(IndexScanState *node)
bool *lastfetched_nulls;
int cmp;
+ estate = node->ss.ps.state;
+
/*
* Only forward scan is supported with reordering. Note: we can get away
* with just Asserting here because the system will not try to run the
@@ -171,12 +201,36 @@ IndexNextWithReorder(IndexScanState *node)
* explicitly.
*/
Assert(!ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indexorderdir));
- Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
+ Assert(ScanDirectionIsForward(estate->es_direction));
scandesc = node->iss_ScanDesc;
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
+ if (scandesc == NULL)
+ {
+ /*
+ * We reach here if the index scan is not parallel, or if we're
+ * executing a index scan that was intended to be parallel serially.
+ */
+ scandesc = index_beginscan(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ estate->es_snapshot,
+ node->iss_NumScanKeys,
+ node->iss_NumOrderByKeys);
+
+ node->iss_ScanDesc = scandesc;
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and
+ * pass the scankeys to the index AM.
+ */
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+ index_rescan(scandesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+ }
+
for (;;)
{
/*
@@ -241,7 +295,7 @@ next_indextuple:
{
econtext->ecxt_scantuple = slot;
ResetExprContext(econtext);
- if (!ExecQual(node->indexqualorig, econtext, false))
+ if (!ExecQual(node->indexqualorig, econtext))
{
/* Fails recheck, so drop it and loop back for another */
InstrCountFiltered2(node, 1);
@@ -336,8 +390,7 @@ EvalOrderByExpressions(IndexScanState *node, ExprContext *econtext)
node->iss_OrderByValues[i] = ExecEvalExpr(orderby,
econtext,
- &node->iss_OrderByNulls[i],
- NULL);
+ &node->iss_OrderByNulls[i]);
i++;
}
@@ -362,7 +415,7 @@ IndexRecheck(IndexScanState *node, TupleTableSlot *slot)
ResetExprContext(econtext);
- return ExecQual(node->indexqualorig, econtext, false);
+ return ExecQual(node->indexqualorig, econtext);
}
@@ -515,6 +568,18 @@ ExecIndexScan(IndexScanState *node)
void
ExecReScanIndexScan(IndexScanState *node)
{
+ bool reset_parallel_scan = true;
+
+ /*
+ * If we are here to just update the scan keys, then don't reset parallel
+ * scan. We don't want each of the participating process in the parallel
+ * scan to update the shared parallel scan state at the start of the scan.
+ * It is quite possible that one of the participants has already begun
+ * scanning the index when another has yet to start it.
+ */
+ if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
+ reset_parallel_scan = false;
+
/*
* If we are doing runtime key calculations (ie, any of the index key
* values weren't simple Consts), compute the new key values. But first,
@@ -540,10 +605,21 @@ ExecReScanIndexScan(IndexScanState *node)
reorderqueue_pop(node);
}
- /* reset index scan */
- index_rescan(node->iss_ScanDesc,
- node->iss_ScanKeys, node->iss_NumScanKeys,
- node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+ /*
+ * Reset (parallel) index scan. For parallel-aware nodes, the scan
+ * descriptor is initialized during actual execution of node and we can
+ * reach here before that (ex. during execution of nest loop join). So,
+ * avoid updating the scan descriptor at that time.
+ */
+ if (node->iss_ScanDesc)
+ {
+ index_rescan(node->iss_ScanDesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+
+ if (reset_parallel_scan && node->iss_ScanDesc->parallel_scan)
+ index_parallelrescan(node->iss_ScanDesc);
+ }
node->iss_ReachedEnd = false;
ExecScanReScan(&node->ss);
@@ -590,8 +666,7 @@ ExecIndexEvalRuntimeKeys(ExprContext *econtext,
*/
scanvalue = ExecEvalExpr(key_expr,
econtext,
- &isNull,
- NULL);
+ &isNull);
if (isNull)
{
scan_key->sk_argument = scanvalue;
@@ -648,8 +723,7 @@ ExecIndexEvalArrayKeys(ExprContext *econtext,
*/
arraydatum = ExecEvalExpr(array_expr,
econtext,
- &isNull,
- NULL);
+ &isNull);
if (isNull)
{
result = false;
@@ -837,8 +911,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &indexstate->ss.ps);
- indexstate->ss.ps.ps_TupFromTlist = false;
-
/*
* initialize child expressions
*
@@ -849,18 +921,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
* would be nice to improve that. (Problem is that any SubPlans present
* in the expression must be found now...)
*/
- indexstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) indexstate);
- indexstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) indexstate);
- indexstate->indexqualorig = (List *)
- ExecInitExpr((Expr *) node->indexqualorig,
- (PlanState *) indexstate);
- indexstate->indexorderbyorig = (List *)
- ExecInitExpr((Expr *) node->indexorderbyorig,
- (PlanState *) indexstate);
+ indexstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) indexstate);
+ indexstate->indexqualorig =
+ ExecInitQual(node->indexqualorig, (PlanState *) indexstate);
+ indexstate->indexorderbyorig =
+ ExecInitExprList(node->indexorderbyorig, (PlanState *) indexstate);
/*
* tuple table initialization
@@ -1018,24 +1084,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
}
/*
- * Initialize scan descriptor.
- */
- indexstate->iss_ScanDesc = index_beginscan(currentRelation,
- indexstate->iss_RelationDesc,
- estate->es_snapshot,
- indexstate->iss_NumScanKeys,
- indexstate->iss_NumOrderByKeys);
-
- /*
- * If no run-time keys to calculate, go ahead and pass the scankeys to the
- * index AM.
- */
- if (indexstate->iss_NumRuntimeKeys == 0)
- index_rescan(indexstate->iss_ScanDesc,
- indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys,
- indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys);
-
- /*
* all done.
*/
return indexstate;
@@ -1595,3 +1643,91 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
else if (n_array_keys != 0)
elog(ERROR, "ScalarArrayOpExpr index qual found where not allowed");
}
+
+/* ----------------------------------------------------------------
+ * Parallel Scan Support
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------
+ * ExecIndexScanEstimate
+ *
+ * estimates the space required to serialize indexscan node.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexScanEstimate(IndexScanState *node,
+ ParallelContext *pcxt)
+{
+ EState *estate = node->ss.ps.state;
+
+ node->iss_PscanLen = index_parallelscan_estimate(node->iss_RelationDesc,
+ estate->es_snapshot);
+ shm_toc_estimate_chunk(&pcxt->estimator, node->iss_PscanLen);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+}
+
+/* ----------------------------------------------------------------
+ * ExecIndexScanInitializeDSM
+ *
+ * Set up a parallel index scan descriptor.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexScanInitializeDSM(IndexScanState *node,
+ ParallelContext *pcxt)
+{
+ EState *estate = node->ss.ps.state;
+ ParallelIndexScanDesc piscan;
+
+ piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen);
+ index_parallelscan_initialize(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ estate->es_snapshot,
+ piscan);
+ shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
+ node->iss_ScanDesc =
+ index_beginscan_parallel(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ node->iss_NumScanKeys,
+ node->iss_NumOrderByKeys,
+ piscan);
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and pass
+ * the scankeys to the index AM.
+ */
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+ index_rescan(node->iss_ScanDesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+}
+
+/* ----------------------------------------------------------------
+ * ExecIndexScanInitializeWorker
+ *
+ * Copy relevant information from TOC into planstate.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexScanInitializeWorker(IndexScanState *node, shm_toc *toc)
+{
+ ParallelIndexScanDesc piscan;
+
+ piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
+ node->iss_ScanDesc =
+ index_beginscan_parallel(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ node->iss_NumScanKeys,
+ node->iss_NumOrderByKeys,
+ piscan);
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and pass
+ * the scankeys to the index AM.
+ */
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+ index_rescan(node->iss_ScanDesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+}
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index faf32e1aee..aaec132218 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -3,7 +3,7 @@
* nodeLimit.c
* Routines to handle limiting of query results where appropriate
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -239,8 +239,7 @@ recompute_limits(LimitState *node)
{
val = ExecEvalExprSwitchContext(node->limitOffset,
econtext,
- &isNull,
- NULL);
+ &isNull);
/* Interpret NULL offset as no offset */
if (isNull)
node->offset = 0;
@@ -263,8 +262,7 @@ recompute_limits(LimitState *node)
{
val = ExecEvalExprSwitchContext(node->limitCount,
econtext,
- &isNull,
- NULL);
+ &isNull);
/* Interpret NULL count as no count (LIMIT ALL) */
if (isNull)
{
@@ -346,18 +344,11 @@ pass_down_bound(LimitState *node, PlanState *child_node)
else if (IsA(child_node, ResultState))
{
/*
- * An extra consideration here is that if the Result is projecting a
- * targetlist that contains any SRFs, we can't assume that every input
- * tuple generates an output tuple, so a Sort underneath might need to
- * return more than N tuples to satisfy LIMIT N. So we cannot use
- * bounded sort.
- *
* If Result supported qual checking, we'd have to punt on seeing a
- * qual, too. Note that having a resconstantqual is not a
- * showstopper: if that fails we're not getting any rows at all.
+ * qual. Note that having a resconstantqual is not a showstopper: if
+ * that fails we're not getting any rows at all.
*/
- if (outerPlanState(child_node) &&
- !expression_returns_set((Node *) child_node->plan->targetlist))
+ if (outerPlanState(child_node))
pass_down_bound(node, outerPlanState(child_node));
}
}
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index 4ebcaffe69..5630eae53d 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -3,7 +3,7 @@
* nodeLockRows.c
* Routines to handle FOR UPDATE/FOR SHARE row locking
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -401,12 +401,10 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
epq_arowmarks = NIL;
foreach(lc, node->rowMarks)
{
- PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
+ PlanRowMark *rc = lfirst_node(PlanRowMark, lc);
ExecRowMark *erm;
ExecAuxRowMark *aerm;
- Assert(IsA(rc, PlanRowMark));
-
/* ignore "parent" rowmarks; they are irrelevant at runtime */
if (rc->isParent)
continue;
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 9ab03f3f15..aa5d2529f4 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -3,7 +3,7 @@
* nodeMaterial.c
* Routines to handle materialization nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index e271927077..fef83dbdbd 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -3,7 +3,7 @@
* nodeMergeAppend.c
* routines to handle MergeAppend nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -72,6 +72,12 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
/*
+ * Lock the non-leaf tables in the partition tree controlled by this node.
+ * It's a no-op for non-partitioned parent tables.
+ */
+ ExecLockNonLeafAppendTables(node->partitioned_rels, estate);
+
+ /*
* Set up empty vector of subplan states
*/
nplans = list_length(node->mergeplans);
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 6db09b836a..572e9dce94 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -3,7 +3,7 @@
* nodeMergejoin.c
* routines supporting merge joins
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -313,7 +313,7 @@ MJEvalOuterValues(MergeJoinState *mergestate)
MergeJoinClause clause = &mergestate->mj_Clauses[i];
clause->ldatum = ExecEvalExpr(clause->lexpr, econtext,
- &clause->lisnull, NULL);
+ &clause->lisnull);
if (clause->lisnull)
{
/* match is impossible; can we end the join early? */
@@ -360,7 +360,7 @@ MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
MergeJoinClause clause = &mergestate->mj_Clauses[i];
clause->rdatum = ExecEvalExpr(clause->rexpr, econtext,
- &clause->risnull, NULL);
+ &clause->risnull);
if (clause->risnull)
{
/* match is impossible; can we end the join early? */
@@ -452,32 +452,22 @@ static TupleTableSlot *
MJFillOuter(MergeJoinState *node)
{
ExprContext *econtext = node->js.ps.ps_ExprContext;
- List *otherqual = node->js.ps.qual;
+ ExprState *otherqual = node->js.ps.qual;
ResetExprContext(econtext);
econtext->ecxt_outertuple = node->mj_OuterTupleSlot;
econtext->ecxt_innertuple = node->mj_NullInnerTupleSlot;
- if (ExecQual(otherqual, econtext, false))
+ if (ExecQual(otherqual, econtext))
{
/*
* qualification succeeded. now form the desired projection tuple and
* return the slot containing it.
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->js.ps.ps_ProjInfo);
}
else
InstrCountFiltered2(node, 1);
@@ -493,32 +483,22 @@ static TupleTableSlot *
MJFillInner(MergeJoinState *node)
{
ExprContext *econtext = node->js.ps.ps_ExprContext;
- List *otherqual = node->js.ps.qual;
+ ExprState *otherqual = node->js.ps.qual;
ResetExprContext(econtext);
econtext->ecxt_outertuple = node->mj_NullOuterTupleSlot;
econtext->ecxt_innertuple = node->mj_InnerTupleSlot;
- if (ExecQual(otherqual, econtext, false))
+ if (ExecQual(otherqual, econtext))
{
/*
* qualification succeeded. now form the desired projection tuple and
* return the slot containing it.
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->js.ps.ps_ProjInfo);
}
else
InstrCountFiltered2(node, 1);
@@ -607,7 +587,7 @@ ExecMergeTupleDump(MergeJoinState *mergestate)
ExecMergeTupleDumpInner(mergestate);
ExecMergeTupleDumpMarked(mergestate);
- printf("******** \n");
+ printf("********\n");
}
#endif
@@ -618,8 +598,8 @@ ExecMergeTupleDump(MergeJoinState *mergestate)
TupleTableSlot *
ExecMergeJoin(MergeJoinState *node)
{
- List *joinqual;
- List *otherqual;
+ ExprState *joinqual;
+ ExprState *otherqual;
bool qualResult;
int compareResult;
PlanState *innerPlan;
@@ -642,26 +622,8 @@ ExecMergeJoin(MergeJoinState *node)
doFillInner = node->mj_FillInner;
/*
- * Check to see if we're still projecting out tuples from a previous join
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->js.ps.ps_TupFromTlist)
- {
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return result;
- /* Done with that source tuple... */
- node->js.ps.ps_TupFromTlist = false;
- }
-
- /*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't happen
- * until we're done projecting out tuples from a join tuple.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -823,8 +785,8 @@ ExecMergeJoin(MergeJoinState *node)
innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
- qualResult = (joinqual == NIL ||
- ExecQual(joinqual, econtext, false));
+ qualResult = (joinqual == NULL ||
+ ExecQual(joinqual, econtext));
MJ_DEBUG_QUAL(joinqual, qualResult);
if (qualResult)
@@ -840,14 +802,15 @@ ExecMergeJoin(MergeJoinState *node)
}
/*
- * In a semijoin, we'll consider returning the first
- * match, but after that we're done with this outer tuple.
+ * If we only need to join to the first matching inner
+ * tuple, then consider returning this one, but after that
+ * continue with next outer tuple.
*/
- if (node->js.jointype == JOIN_SEMI)
+ if (node->js.single_match)
node->mj_JoinState = EXEC_MJ_NEXTOUTER;
- qualResult = (otherqual == NIL ||
- ExecQual(otherqual, econtext, false));
+ qualResult = (otherqual == NULL ||
+ ExecQual(otherqual, econtext));
MJ_DEBUG_QUAL(otherqual, qualResult);
if (qualResult)
@@ -856,20 +819,9 @@ ExecMergeJoin(MergeJoinState *node)
* qualification succeeded. now form the desired
* projection tuple and return the slot containing it.
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
MJ_printf("ExecMergeJoin: returning tuple\n");
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->js.ps.ps_ProjInfo);
}
else
InstrCountFiltered2(node, 1);
@@ -1099,6 +1051,10 @@ ExecMergeJoin(MergeJoinState *node)
* scan position to the first mark, and go join that tuple
* (and any following ones) to the new outer.
*
+ * If we were able to determine mark and restore are not
+ * needed, then we don't have to back up; the current
+ * inner is already the first possible match.
+ *
* NOTE: we do not need to worry about the MatchedInner
* state for the rescanned inner tuples. We know all of
* them will match this new outer tuple and therefore
@@ -1111,16 +1067,19 @@ ExecMergeJoin(MergeJoinState *node)
* forcing the merge clause to never match, so we never
* get here.
*/
- ExecRestrPos(innerPlan);
+ if (!node->mj_SkipMarkRestore)
+ {
+ ExecRestrPos(innerPlan);
- /*
- * ExecRestrPos probably should give us back a new Slot,
- * but since it doesn't, use the marked slot. (The
- * previously returned mj_InnerTupleSlot cannot be assumed
- * to hold the required tuple.)
- */
- node->mj_InnerTupleSlot = innerTupleSlot;
- /* we need not do MJEvalInnerValues again */
+ /*
+ * ExecRestrPos probably should give us back a new
+ * Slot, but since it doesn't, use the marked slot.
+ * (The previously returned mj_InnerTupleSlot cannot
+ * be assumed to hold the required tuple.)
+ */
+ node->mj_InnerTupleSlot = innerTupleSlot;
+ /* we need not do MJEvalInnerValues again */
+ }
node->mj_JoinState = EXEC_MJ_JOINTUPLES;
}
@@ -1221,7 +1180,8 @@ ExecMergeJoin(MergeJoinState *node)
if (compareResult == 0)
{
- ExecMarkPos(innerPlan);
+ if (!node->mj_SkipMarkRestore)
+ ExecMarkPos(innerPlan);
MarkInnerTuple(node->mj_InnerTupleSlot, node);
@@ -1504,27 +1464,29 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- mergestate->js.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->join.plan.targetlist,
- (PlanState *) mergestate);
- mergestate->js.ps.qual = (List *)
- ExecInitExpr((Expr *) node->join.plan.qual,
- (PlanState *) mergestate);
+ mergestate->js.ps.qual =
+ ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
mergestate->js.jointype = node->join.jointype;
- mergestate->js.joinqual = (List *)
- ExecInitExpr((Expr *) node->join.joinqual,
- (PlanState *) mergestate);
+ mergestate->js.joinqual =
+ ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
mergestate->mj_ConstFalseJoin = false;
/* mergeclauses are handled below */
/*
* initialize child nodes
*
- * inner child must support MARK/RESTORE.
+ * inner child must support MARK/RESTORE, unless we have detected that we
+ * don't need that. Note that skip_mark_restore must never be set if
+ * there are non-mergeclause joinquals, since the logic wouldn't work.
*/
+ Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
+ mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
+
outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
- eflags | EXEC_FLAG_MARK);
+ mergestate->mj_SkipMarkRestore ?
+ eflags :
+ (eflags | EXEC_FLAG_MARK));
/*
* For certain types of inner child nodes, it is advantageous to issue
@@ -1537,7 +1499,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
* only if eflags doesn't specify REWIND.
*/
if (IsA(innerPlan(node), Material) &&
- (eflags & EXEC_FLAG_REWIND) == 0)
+ (eflags & EXEC_FLAG_REWIND) == 0 &&
+ !mergestate->mj_SkipMarkRestore)
mergestate->mj_ExtraMarks = true;
else
mergestate->mj_ExtraMarks = false;
@@ -1551,6 +1514,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
ExecGetResultType(innerPlanState(mergestate)));
+ /*
+ * detect whether we need only consider the first matching inner tuple
+ */
+ mergestate->js.single_match = (node->join.inner_unique ||
+ node->join.jointype == JOIN_SEMI);
+
+ /* set up null tuples for outer joins, if needed */
switch (node->join.jointype)
{
case JOIN_INNER:
@@ -1629,7 +1599,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
* initialize join state
*/
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
- mergestate->js.ps.ps_TupFromTlist = false;
mergestate->mj_MatchedOuter = false;
mergestate->mj_MatchedInner = false;
mergestate->mj_OuterTupleSlot = NULL;
@@ -1684,7 +1653,6 @@ ExecReScanMergeJoin(MergeJoinState *node)
ExecClearTuple(node->mj_MarkedTupleSlot);
node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
- node->js.ps.ps_TupFromTlist = false;
node->mj_MatchedOuter = false;
node->mj_MatchedInner = false;
node->mj_OuterTupleSlot = NULL;
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 439e36ee3a..0ee82e3add 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4,7 +4,7 @@
* routines to handle ModifyTable nodes.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -46,6 +46,7 @@
#include "foreign/fdwapi.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
+#include "parser/parsetree.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
@@ -176,7 +177,7 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo,
econtext->ecxt_outertuple = planSlot;
/* Compute the RETURNING expressions */
- return ExecProject(projectReturning, NULL);
+ return ExecProject(projectReturning);
}
/*
@@ -195,10 +196,25 @@ ExecCheckHeapTupleVisible(EState *estate,
if (!IsolationUsesXactSnapshot())
return;
+ /*
+ * We need buffer pin and lock to call HeapTupleSatisfiesVisibility.
+ * Caller should be holding pin, but not lock.
+ */
+ LockBuffer(buffer, BUFFER_LOCK_SHARE);
if (!HeapTupleSatisfiesVisibility(tuple, estate->es_snapshot, buffer))
- ereport(ERROR,
- (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+ {
+ /*
+ * We should not raise a serialization failure if the conflict is
+ * against a tuple inserted by our own transaction, even if it's not
+ * visible to our snapshot. (This would happen, for example, if
+ * conflicting keys are proposed for insertion in a single command.)
+ */
+ if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple->t_data)))
+ ereport(ERROR,
+ (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update")));
+ }
+ LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
}
/*
@@ -244,9 +260,11 @@ ExecInsert(ModifyTableState *mtstate,
{
HeapTuple tuple;
ResultRelInfo *resultRelInfo;
+ ResultRelInfo *saved_resultRelInfo = NULL;
Relation resultRelationDesc;
Oid newId;
List *recheckIndexes = NIL;
+ TupleTableSlot *result = NULL;
/*
* get the heap tuple out of the tuple table slot, making sure we have a
@@ -258,6 +276,67 @@ ExecInsert(ModifyTableState *mtstate,
* get information on the (current) result relation
*/
resultRelInfo = estate->es_result_relation_info;
+
+ /* Determine the partition to heap_insert the tuple into */
+ if (mtstate->mt_partition_dispatch_info)
+ {
+ int leaf_part_index;
+ TupleConversionMap *map;
+
+ /*
+ * Away we go ... If we end up not finding a partition after all,
+ * ExecFindPartition() does not return and errors out instead.
+ * Otherwise, the returned value is to be used as an index into arrays
+ * mt_partitions[] and mt_partition_tupconv_maps[] that will get us
+ * the ResultRelInfo and TupleConversionMap for the partition,
+ * respectively.
+ */
+ leaf_part_index = ExecFindPartition(resultRelInfo,
+ mtstate->mt_partition_dispatch_info,
+ slot,
+ estate);
+ Assert(leaf_part_index >= 0 &&
+ leaf_part_index < mtstate->mt_num_partitions);
+
+ /*
+ * Save the old ResultRelInfo and switch to the one corresponding to
+ * the selected partition.
+ */
+ saved_resultRelInfo = resultRelInfo;
+ resultRelInfo = mtstate->mt_partitions + leaf_part_index;
+
+ /* We do not yet have a way to insert into a foreign partition */
+ if (resultRelInfo->ri_FdwRoutine)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot route inserted tuples to a foreign table")));
+
+ /* For ExecInsertIndexTuples() to work on the partition's indexes */
+ estate->es_result_relation_info = resultRelInfo;
+
+ /*
+ * We might need to convert from the parent rowtype to the partition
+ * rowtype.
+ */
+ map = mtstate->mt_partition_tupconv_maps[leaf_part_index];
+ if (map)
+ {
+ Relation partrel = resultRelInfo->ri_RelationDesc;
+
+ tuple = do_convert_tuple(tuple, map);
+
+ /*
+ * We must use the partition's tuple descriptor from this point
+ * on, until we're finished dealing with the partition. Use the
+ * dedicated slot for that.
+ */
+ slot = mtstate->mt_partition_tuple_slot;
+ Assert(slot != NULL);
+ ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
+ ExecStoreTuple(tuple, slot, InvalidBuffer, true);
+ }
+ }
+
resultRelationDesc = resultRelInfo->ri_RelationDesc;
/*
* If the result relation has OIDs, force the tuple's OID to zero so that
@@ -354,7 +433,7 @@ ExecInsert(ModifyTableState *mtstate,
/*
* Check the constraints of the tuple
*/
- if (resultRelationDesc->rd_att->constr)
+ if (resultRelationDesc->rd_att->constr || resultRelInfo->ri_PartitionCheck)
ExecConstraints(resultRelInfo, slot, estate);
if (onconflict != ONCONFLICT_NONE && resultRelInfo->ri_NumIndices > 0)
@@ -513,9 +592,12 @@ ExecInsert(ModifyTableState *mtstate,
/* Process RETURNING if present */
if (resultRelInfo->ri_projectReturning)
- return ExecProcessReturning(resultRelInfo, slot, planSlot);
+ result = ExecProcessReturning(resultRelInfo, slot, planSlot);
- return NULL;
+ if (saved_resultRelInfo)
+ estate->es_result_relation_info = saved_resultRelInfo;
+
+ return result;
}
/* ----------------------------------------------------------------
@@ -906,9 +988,11 @@ lreplace:;
resultRelInfo, slot, estate);
/*
- * Check the constraints of the tuple
+ * Check the constraints of the tuple. Note that we pass the same
+ * slot for the orig_slot argument, because unlike ExecInsert(), no
+ * tuple-routing is performed here, hence the slot remains unchanged.
*/
- if (resultRelationDesc->rd_att->constr)
+ if (resultRelationDesc->rd_att->constr || resultRelInfo->ri_PartitionCheck)
ExecConstraints(resultRelInfo, slot, estate);
/*
@@ -1068,7 +1152,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
{
ExprContext *econtext = mtstate->ps.ps_ExprContext;
Relation relation = resultRelInfo->ri_RelationDesc;
- List *onConflictSetWhere = resultRelInfo->ri_onConflictSetWhere;
+ ExprState *onConflictSetWhere = resultRelInfo->ri_onConflictSetWhere;
HeapTupleData tuple;
HeapUpdateFailureData hufd;
LockTupleMode lockmode;
@@ -1187,7 +1271,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
econtext->ecxt_innertuple = excludedSlot;
econtext->ecxt_outertuple = NULL;
- if (!ExecQual(onConflictSetWhere, econtext, false))
+ if (!ExecQual(onConflictSetWhere, econtext))
{
ReleaseBuffer(buffer);
InstrCountFiltered1(&mtstate->ps, 1);
@@ -1217,7 +1301,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
}
/* Project the new tuple version */
- ExecProject(resultRelInfo->ri_onConflictSetProj, NULL);
+ ExecProject(resultRelInfo->ri_onConflictSetProj);
/*
* Note that it is possible that the target tuple has been modified in
@@ -1245,19 +1329,29 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
static void
fireBSTriggers(ModifyTableState *node)
{
+ ResultRelInfo *resultRelInfo = node->resultRelInfo;
+
+ /*
+ * If the node modifies a partitioned table, we must fire its triggers.
+ * Note that in that case, node->resultRelInfo points to the first leaf
+ * partition, not the root table.
+ */
+ if (node->rootResultRelInfo != NULL)
+ resultRelInfo = node->rootResultRelInfo;
+
switch (node->operation)
{
case CMD_INSERT:
- ExecBSInsertTriggers(node->ps.state, node->resultRelInfo);
+ ExecBSInsertTriggers(node->ps.state, resultRelInfo);
if (node->mt_onconflict == ONCONFLICT_UPDATE)
ExecBSUpdateTriggers(node->ps.state,
- node->resultRelInfo);
+ resultRelInfo);
break;
case CMD_UPDATE:
- ExecBSUpdateTriggers(node->ps.state, node->resultRelInfo);
+ ExecBSUpdateTriggers(node->ps.state, resultRelInfo);
break;
case CMD_DELETE:
- ExecBSDeleteTriggers(node->ps.state, node->resultRelInfo);
+ ExecBSDeleteTriggers(node->ps.state, resultRelInfo);
break;
default:
elog(ERROR, "unknown operation");
@@ -1271,19 +1365,29 @@ fireBSTriggers(ModifyTableState *node)
static void
fireASTriggers(ModifyTableState *node)
{
+ ResultRelInfo *resultRelInfo = node->resultRelInfo;
+
+ /*
+ * If the node modifies a partitioned table, we must fire its triggers.
+ * Note that in that case, node->resultRelInfo points to the first leaf
+ * partition, not the root table.
+ */
+ if (node->rootResultRelInfo != NULL)
+ resultRelInfo = node->rootResultRelInfo;
+
switch (node->operation)
{
case CMD_INSERT:
if (node->mt_onconflict == ONCONFLICT_UPDATE)
ExecASUpdateTriggers(node->ps.state,
- node->resultRelInfo);
- ExecASInsertTriggers(node->ps.state, node->resultRelInfo);
+ resultRelInfo);
+ ExecASInsertTriggers(node->ps.state, resultRelInfo);
break;
case CMD_UPDATE:
- ExecASUpdateTriggers(node->ps.state, node->resultRelInfo);
+ ExecASUpdateTriggers(node->ps.state, resultRelInfo);
break;
case CMD_DELETE:
- ExecASDeleteTriggers(node->ps.state, node->resultRelInfo);
+ ExecASDeleteTriggers(node->ps.state, resultRelInfo);
break;
default:
elog(ERROR, "unknown operation");
@@ -1551,6 +1655,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
Plan *subplan;
ListCell *l;
int i;
+ Relation rel;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -1561,7 +1666,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate = makeNode(ModifyTableState);
mtstate->ps.plan = (Plan *) node;
mtstate->ps.state = estate;
- mtstate->ps.targetlist = NIL; /* not actually used */
mtstate->operation = operation;
mtstate->canSetTag = node->canSetTag;
@@ -1569,6 +1673,12 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
+
+ /* If modifying a partitioned table, initialize the root table info */
+ if (node->rootResultRelIndex >= 0)
+ mtstate->rootResultRelInfo = estate->es_root_result_relations +
+ node->rootResultRelIndex;
+
mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
mtstate->mt_nplans = nplans;
mtstate->mt_onconflict = node->onConflictAction;
@@ -1642,6 +1752,44 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
estate->es_result_relation_info = saved_resultRelInfo;
+ /* The root table RT index is at the head of the partitioned_rels list */
+ if (node->partitioned_rels)
+ {
+ Index root_rti;
+ Oid root_oid;
+
+ root_rti = linitial_int(node->partitioned_rels);
+ root_oid = getrelid(root_rti, estate->es_range_table);
+ rel = heap_open(root_oid, NoLock); /* locked by InitPlan */
+ }
+ else
+ rel = mtstate->resultRelInfo->ri_RelationDesc;
+
+ /* Build state for INSERT tuple routing */
+ if (operation == CMD_INSERT &&
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ PartitionDispatch *partition_dispatch_info;
+ ResultRelInfo *partitions;
+ TupleConversionMap **partition_tupconv_maps;
+ TupleTableSlot *partition_tuple_slot;
+ int num_parted,
+ num_partitions;
+
+ ExecSetupPartitionTupleRouting(rel,
+ &partition_dispatch_info,
+ &partitions,
+ &partition_tupconv_maps,
+ &partition_tuple_slot,
+ &num_parted, &num_partitions);
+ mtstate->mt_partition_dispatch_info = partition_dispatch_info;
+ mtstate->mt_num_dispatch = num_parted;
+ mtstate->mt_partitions = partitions;
+ mtstate->mt_num_partitions = num_partitions;
+ mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
+ mtstate->mt_partition_tuple_slot = partition_tuple_slot;
+ }
+
/*
* Initialize any WITH CHECK OPTION constraints if needed.
*/
@@ -1656,7 +1804,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
foreach(ll, wcoList)
{
WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
- ExprState *wcoExpr = ExecInitExpr((Expr *) wco->qual,
+ ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
mtstate->mt_plans[i]);
wcoExprs = lappend(wcoExprs, wcoExpr);
@@ -1669,12 +1817,53 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
}
/*
+ * Build WITH CHECK OPTION constraints for each leaf partition rel. Note
+ * that we didn't build the withCheckOptionList for each partition within
+ * the planner, but simple translation of the varattnos for each partition
+ * will suffice. This only occurs for the INSERT case; UPDATE/DELETE
+ * cases are handled above.
+ */
+ if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
+ {
+ List *wcoList;
+
+ Assert(operation == CMD_INSERT);
+ resultRelInfo = mtstate->mt_partitions;
+ wcoList = linitial(node->withCheckOptionLists);
+ for (i = 0; i < mtstate->mt_num_partitions; i++)
+ {
+ Relation partrel = resultRelInfo->ri_RelationDesc;
+ List *mapped_wcoList;
+ List *wcoExprs = NIL;
+ ListCell *ll;
+
+ /* varno = node->nominalRelation */
+ mapped_wcoList = map_partition_varattnos(wcoList,
+ node->nominalRelation,
+ partrel, rel);
+ foreach(ll, mapped_wcoList)
+ {
+ WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
+ ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
+ mtstate->mt_plans[i]);
+
+ wcoExprs = lappend(wcoExprs, wcoExpr);
+ }
+
+ resultRelInfo->ri_WithCheckOptions = mapped_wcoList;
+ resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
+ resultRelInfo++;
+ }
+ }
+
+ /*
* Initialize RETURNING projections if needed.
*/
if (node->returningLists)
{
TupleTableSlot *slot;
ExprContext *econtext;
+ List *returningList;
/*
* Initialize result tuple slot and assign its rowtype using the first
@@ -1689,8 +1878,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
slot = mtstate->ps.ps_ResultTupleSlot;
/* Need an econtext too */
- econtext = CreateExprContext(estate);
- mtstate->ps.ps_ExprContext = econtext;
+ if (mtstate->ps.ps_ExprContext == NULL)
+ ExecAssignExprContext(estate, &mtstate->ps);
+ econtext = mtstate->ps.ps_ExprContext;
/*
* Build a projection for each result rel.
@@ -1699,11 +1889,33 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
foreach(l, node->returningLists)
{
List *rlist = (List *) lfirst(l);
- List *rliststate;
- rliststate = (List *) ExecInitExpr((Expr *) rlist, &mtstate->ps);
resultRelInfo->ri_projectReturning =
- ExecBuildProjectionInfo(rliststate, econtext, slot,
+ ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
+ resultRelInfo->ri_RelationDesc->rd_att);
+ resultRelInfo++;
+ }
+
+ /*
+ * Build a projection for each leaf partition rel. Note that we
+ * didn't build the returningList for each partition within the
+ * planner, but simple translation of the varattnos for each partition
+ * will suffice. This only occurs for the INSERT case; UPDATE/DELETE
+ * are handled above.
+ */
+ resultRelInfo = mtstate->mt_partitions;
+ returningList = linitial(node->returningLists);
+ for (i = 0; i < mtstate->mt_num_partitions; i++)
+ {
+ Relation partrel = resultRelInfo->ri_RelationDesc;
+ List *rlist;
+
+ /* varno = node->nominalRelation */
+ rlist = map_partition_varattnos(returningList,
+ node->nominalRelation,
+ partrel, rel);
+ resultRelInfo->ri_projectReturning =
+ ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
resultRelInfo->ri_RelationDesc->rd_att);
resultRelInfo++;
}
@@ -1721,6 +1933,10 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->ps.ps_ExprContext = NULL;
}
+ /* Close the root partitioned rel if we opened it above. */
+ if (rel != mtstate->resultRelInfo->ri_RelationDesc)
+ heap_close(rel, NoLock);
+
/*
* If needed, Initialize target list, projection and qual for ON CONFLICT
* DO UPDATE.
@@ -1729,7 +1945,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (node->onConflictAction == ONCONFLICT_UPDATE)
{
ExprContext *econtext;
- ExprState *setexpr;
TupleDesc tupDesc;
/* insert may only have one plan, inheritance is not expanded */
@@ -1755,11 +1970,10 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_conflproj = ExecInitExtraTupleSlot(mtstate->ps.state);
ExecSetSlotDescriptor(mtstate->mt_conflproj, tupDesc);
- /* build UPDATE SET expression and projection state */
- setexpr = ExecInitExpr((Expr *) node->onConflictSet, &mtstate->ps);
+ /* build UPDATE SET projection state */
resultRelInfo->ri_onConflictSetProj =
- ExecBuildProjectionInfo((List *) setexpr, econtext,
- mtstate->mt_conflproj,
+ ExecBuildProjectionInfo(node->onConflictSet, econtext,
+ mtstate->mt_conflproj, &mtstate->ps,
resultRelInfo->ri_RelationDesc->rd_att);
/* build DO UPDATE WHERE clause expression */
@@ -1767,10 +1981,10 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
{
ExprState *qualexpr;
- qualexpr = ExecInitExpr((Expr *) node->onConflictWhere,
+ qualexpr = ExecInitQual((List *) node->onConflictWhere,
&mtstate->ps);
- resultRelInfo->ri_onConflictSetWhere = (List *) qualexpr;
+ resultRelInfo->ri_onConflictSetWhere = qualexpr;
}
}
@@ -1782,11 +1996,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
*/
foreach(l, node->rowMarks)
{
- PlanRowMark *rc = (PlanRowMark *) lfirst(l);
+ PlanRowMark *rc = lfirst_node(PlanRowMark, l);
ExecRowMark *erm;
- Assert(IsA(rc, PlanRowMark));
-
/* ignore "parent" rowmarks; they are irrelevant at runtime */
if (rc->isParent)
continue;
@@ -1873,7 +2085,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
if (relkind == RELKIND_RELATION ||
- relkind == RELKIND_MATVIEW)
+ relkind == RELKIND_MATVIEW ||
+ relkind == RELKIND_PARTITIONED_TABLE)
{
j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
if (!AttributeNumberIsValid(j->jf_junkAttNo))
@@ -1959,6 +2172,33 @@ ExecEndModifyTable(ModifyTableState *node)
}
/*
+ * Close all the partitioned tables, leaf partitions, and their indices
+ *
+ * Remember node->mt_partition_dispatch_info[0] corresponds to the root
+ * partitioned table, which we must not try to close, because it is the
+ * main target table of the query that will be closed by ExecEndPlan().
+ * Also, tupslot is NULL for the root partitioned table.
+ */
+ for (i = 1; i < node->mt_num_dispatch; i++)
+ {
+ PartitionDispatch pd = node->mt_partition_dispatch_info[i];
+
+ heap_close(pd->reldesc, NoLock);
+ ExecDropSingleTupleTableSlot(pd->tupslot);
+ }
+ for (i = 0; i < node->mt_num_partitions; i++)
+ {
+ ResultRelInfo *resultRelInfo = node->mt_partitions + i;
+
+ ExecCloseIndices(resultRelInfo);
+ heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+ }
+
+ /* Release the standalone partition tuple descriptor, if any */
+ if (node->mt_partition_tuple_slot)
+ ExecDropSingleTupleTableSlot(node->mt_partition_tuple_slot);
+
+ /*
* Free the exprcontext
*/
ExecFreeExprContext(&node->ps);
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
new file mode 100644
index 0000000000..62234869ab
--- /dev/null
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -0,0 +1,199 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNamedtuplestorescan.c
+ * routines to handle NamedTuplestoreScan nodes.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/nodeNamedtuplestorescan.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "executor/execdebug.h"
+#include "executor/nodeNamedtuplestorescan.h"
+#include "miscadmin.h"
+#include "utils/queryenvironment.h"
+
+static TupleTableSlot *NamedTuplestoreScanNext(NamedTuplestoreScanState *node);
+
+/* ----------------------------------------------------------------
+ * NamedTuplestoreScanNext
+ *
+ * This is a workhorse for ExecNamedTuplestoreScan
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
+{
+ TupleTableSlot *slot;
+
+ /* We intentionally do not support backward scan. */
+ Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
+
+ /*
+ * Get the next tuple from tuplestore. Return NULL if no more tuples.
+ */
+ slot = node->ss.ss_ScanTupleSlot;
+ (void) tuplestore_gettupleslot(node->relation, true, false, slot);
+ return slot;
+}
+
+/*
+ * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
+ * EvalPlanQual
+ */
+static bool
+NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
+{
+ /* nothing to check */
+ return true;
+}
+
+/* ----------------------------------------------------------------
+ * ExecNamedTuplestoreScan(node)
+ *
+ * Scans the CTE sequentially and returns the next qualifying tuple.
+ * We call the ExecScan() routine and pass it the appropriate
+ * access method functions.
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecNamedTuplestoreScan(NamedTuplestoreScanState *node)
+{
+ return ExecScan(&node->ss,
+ (ExecScanAccessMtd) NamedTuplestoreScanNext,
+ (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
+}
+
+
+/* ----------------------------------------------------------------
+ * ExecInitNamedTuplestoreScan
+ * ----------------------------------------------------------------
+ */
+NamedTuplestoreScanState *
+ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
+{
+ NamedTuplestoreScanState *scanstate;
+ EphemeralNamedRelation enr;
+
+ /* check for unsupported flags */
+ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
+
+ /*
+ * NamedTuplestoreScan should not have any children.
+ */
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
+
+ /*
+ * create new NamedTuplestoreScanState for node
+ */
+ scanstate = makeNode(NamedTuplestoreScanState);
+ scanstate->ss.ps.plan = (Plan *) node;
+ scanstate->ss.ps.state = estate;
+
+ enr = get_ENR(estate->es_queryEnv, node->enrname);
+ if (!enr)
+ elog(ERROR, "executor could not find named tuplestore \"%s\"",
+ node->enrname);
+
+ Assert(enr->reldata);
+ scanstate->relation = (Tuplestorestate *) enr->reldata;
+ scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
+ scanstate->readptr =
+ tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND);
+
+ /*
+ * The new read pointer copies its position from read pointer 0, which
+ * could be anywhere, so explicitly rewind it.
+ */
+ tuplestore_rescan(scanstate->relation);
+
+ /*
+ * XXX: Should we add a function to free that read pointer when done?
+ *
+ * This was attempted, but it did not improve performance or memory usage
+ * in any tested cases.
+ */
+
+ /*
+ * Miscellaneous initialization
+ *
+ * create expression context for node
+ */
+ ExecAssignExprContext(estate, &scanstate->ss.ps);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
+ /*
+ * tuple table initialization
+ */
+ ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &scanstate->ss);
+
+ /*
+ * The scan tuple type is specified for the tuplestore.
+ */
+ ExecAssignScanType(&scanstate->ss, scanstate->tupdesc);
+
+ /*
+ * Initialize result tuple type and projection info.
+ */
+ ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
+
+ return scanstate;
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndNamedTuplestoreScan
+ *
+ * frees any storage allocated through C routines.
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
+{
+ /*
+ * Free exprcontext
+ */
+ ExecFreeExprContext(&node->ss.ps);
+
+ /*
+ * clean out the tuple table
+ */
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+}
+
+/* ----------------------------------------------------------------
+ * ExecReScanNamedTuplestoreScan
+ *
+ * Rescans the relation.
+ * ----------------------------------------------------------------
+ */
+void
+ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
+{
+ Tuplestorestate *tuplestorestate = node->relation;
+
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+
+ ExecScanReScan(&node->ss);
+
+ /*
+ * Rewind my own pointer.
+ */
+ tuplestore_select_read_pointer(tuplestorestate, node->readptr);
+ tuplestore_rescan(tuplestorestate);
+}
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index d67f2e7955..67c8269b96 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -3,7 +3,7 @@
* nodeNestloop.c
* routines to support nest-loop joins
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -64,8 +64,8 @@ ExecNestLoop(NestLoopState *node)
PlanState *outerPlan;
TupleTableSlot *outerTupleSlot;
TupleTableSlot *innerTupleSlot;
- List *joinqual;
- List *otherqual;
+ ExprState *joinqual;
+ ExprState *otherqual;
ExprContext *econtext;
ListCell *lc;
@@ -82,26 +82,8 @@ ExecNestLoop(NestLoopState *node)
econtext = node->js.ps.ps_ExprContext;
/*
- * Check to see if we're still projecting out tuples from a previous join
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->js.ps.ps_TupFromTlist)
- {
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return result;
- /* Done with that source tuple... */
- node->js.ps.ps_TupFromTlist = false;
- }
-
- /*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't happen
- * until we're done projecting out tuples from a join tuple.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -195,26 +177,16 @@ ExecNestLoop(NestLoopState *node)
ENL1_printf("testing qualification for outer-join tuple");
- if (otherqual == NIL || ExecQual(otherqual, econtext, false))
+ if (otherqual == NULL || ExecQual(otherqual, econtext))
{
/*
* qualification was satisfied so we project and return
* the slot containing the result tuple using
* ExecProject().
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
ENL1_printf("qualification succeeded, projecting tuple");
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->js.ps.ps_ProjInfo);
}
else
InstrCountFiltered2(node, 1);
@@ -236,7 +208,7 @@ ExecNestLoop(NestLoopState *node)
*/
ENL1_printf("testing qualification");
- if (ExecQual(joinqual, econtext, false))
+ if (ExecQual(joinqual, econtext))
{
node->nl_MatchedOuter = true;
@@ -248,31 +220,22 @@ ExecNestLoop(NestLoopState *node)
}
/*
- * In a semijoin, we'll consider returning the first match, but
- * after that we're done with this outer tuple.
+ * If we only need to join to the first matching inner tuple, then
+ * consider returning this one, but after that continue with next
+ * outer tuple.
*/
- if (node->js.jointype == JOIN_SEMI)
+ if (node->js.single_match)
node->nl_NeedNewOuter = true;
- if (otherqual == NIL || ExecQual(otherqual, econtext, false))
+ if (otherqual == NULL || ExecQual(otherqual, econtext))
{
/*
* qualification was satisfied so we project and return the
* slot containing the result tuple using ExecProject().
*/
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
ENL1_printf("qualification succeeded, projecting tuple");
- result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
+ return ExecProject(node->js.ps.ps_ProjInfo);
}
else
InstrCountFiltered2(node, 1);
@@ -321,16 +284,11 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- nlstate->js.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->join.plan.targetlist,
- (PlanState *) nlstate);
- nlstate->js.ps.qual = (List *)
- ExecInitExpr((Expr *) node->join.plan.qual,
- (PlanState *) nlstate);
+ nlstate->js.ps.qual =
+ ExecInitQual(node->join.plan.qual, (PlanState *) nlstate);
nlstate->js.jointype = node->join.jointype;
- nlstate->js.joinqual = (List *)
- ExecInitExpr((Expr *) node->join.joinqual,
- (PlanState *) nlstate);
+ nlstate->js.joinqual =
+ ExecInitQual(node->join.joinqual, (PlanState *) nlstate);
/*
* initialize child nodes
@@ -353,6 +311,13 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
*/
ExecInitResultTupleSlot(estate, &nlstate->js.ps);
+ /*
+ * detect whether we need only consider the first matching inner tuple
+ */
+ nlstate->js.single_match = (node->join.inner_unique ||
+ node->join.jointype == JOIN_SEMI);
+
+ /* set up null tuples for outer joins, if needed */
switch (node->join.jointype)
{
case JOIN_INNER:
@@ -378,7 +343,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
/*
* finally, wipe the current outer tuple clean.
*/
- nlstate->js.ps.ps_TupFromTlist = false;
nlstate->nl_NeedNewOuter = true;
nlstate->nl_MatchedOuter = false;
@@ -442,7 +406,6 @@ ExecReScanNestLoop(NestLoopState *node)
* outer Vars are used as run-time keys...
*/
- node->js.ps.ps_TupFromTlist = false;
node->nl_NeedNewOuter = true;
node->nl_MatchedOuter = false;
}
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
new file mode 100644
index 0000000000..2f0a4e647b
--- /dev/null
+++ b/src/backend/executor/nodeProjectSet.c
@@ -0,0 +1,323 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeProjectSet.c
+ * support for evaluating targetlists containing set-returning functions
+ *
+ * DESCRIPTION
+ *
+ * ProjectSet nodes are inserted by the planner to evaluate set-returning
+ * functions in the targetlist. It's guaranteed that all set-returning
+ * functions are directly at the top level of the targetlist, i.e. they
+ * can't be inside more-complex expressions. If that'd otherwise be
+ * the case, the planner adds additional ProjectSet nodes.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/executor/nodeProjectSet.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "executor/executor.h"
+#include "executor/nodeProjectSet.h"
+#include "nodes/nodeFuncs.h"
+#include "utils/memutils.h"
+
+
+static TupleTableSlot *ExecProjectSRF(ProjectSetState *node, bool continuing);
+
+
+/* ----------------------------------------------------------------
+ * ExecProjectSet(node)
+ *
+ * Return tuples after evaluating the targetlist (which contains set
+ * returning functions).
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecProjectSet(ProjectSetState *node)
+{
+ TupleTableSlot *outerTupleSlot;
+ TupleTableSlot *resultSlot;
+ PlanState *outerPlan;
+ ExprContext *econtext;
+
+ econtext = node->ps.ps_ExprContext;
+
+ /*
+ * Check to see if we're still projecting out tuples from a previous scan
+ * tuple (because there is a function-returning-set in the projection
+ * expressions). If so, try to project another one.
+ */
+ if (node->pending_srf_tuples)
+ {
+ resultSlot = ExecProjectSRF(node, true);
+
+ if (resultSlot != NULL)
+ return resultSlot;
+ }
+
+ /*
+ * Reset per-tuple memory context to free any expression evaluation
+ * storage allocated in the previous tuple cycle. Note this can't happen
+ * until we're done projecting out tuples from a scan tuple.
+ */
+ ResetExprContext(econtext);
+
+ /*
+ * Get another input tuple and project SRFs from it.
+ */
+ for (;;)
+ {
+ /*
+ * Retrieve tuples from the outer plan until there are no more.
+ */
+ outerPlan = outerPlanState(node);
+ outerTupleSlot = ExecProcNode(outerPlan);
+
+ if (TupIsNull(outerTupleSlot))
+ return NULL;
+
+ /*
+ * Prepare to compute projection expressions, which will expect to
+ * access the input tuples as varno OUTER.
+ */
+ econtext->ecxt_outertuple = outerTupleSlot;
+
+ /* Evaluate the expressions */
+ resultSlot = ExecProjectSRF(node, false);
+
+ /*
+ * Return the tuple unless the projection produced no rows (due to an
+ * empty set), in which case we must loop back to see if there are
+ * more outerPlan tuples.
+ */
+ if (resultSlot)
+ return resultSlot;
+ }
+
+ return NULL;
+}
+
+/* ----------------------------------------------------------------
+ * ExecProjectSRF
+ *
+ * Project a targetlist containing one or more set-returning functions.
+ *
+ * 'continuing' indicates whether to continue projecting rows for the
+ * same input tuple; or whether a new input tuple is being projected.
+ *
+ * Returns NULL if no output tuple has been produced.
+ *
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+ExecProjectSRF(ProjectSetState *node, bool continuing)
+{
+ TupleTableSlot *resultSlot = node->ps.ps_ResultTupleSlot;
+ ExprContext *econtext = node->ps.ps_ExprContext;
+ bool hassrf PG_USED_FOR_ASSERTS_ONLY;
+ bool hasresult;
+ int argno;
+
+ ExecClearTuple(resultSlot);
+
+ /*
+ * Assume no further tuples are produced unless an ExprMultipleResult is
+ * encountered from a set returning function.
+ */
+ node->pending_srf_tuples = false;
+
+ hassrf = hasresult = false;
+ for (argno = 0; argno < node->nelems; argno++)
+ {
+ Node *elem = node->elems[argno];
+ ExprDoneCond *isdone = &node->elemdone[argno];
+ Datum *result = &resultSlot->tts_values[argno];
+ bool *isnull = &resultSlot->tts_isnull[argno];
+
+ if (continuing && *isdone == ExprEndResult)
+ {
+ /*
+ * If we're continuing to project output rows from a source tuple,
+ * return NULLs once the SRF has been exhausted.
+ */
+ *result = (Datum) 0;
+ *isnull = true;
+ hassrf = true;
+ }
+ else if (IsA(elem, SetExprState))
+ {
+ /*
+ * Evaluate SRF - possibly continuing previously started output.
+ */
+ *result = ExecMakeFunctionResultSet((SetExprState *) elem,
+ econtext, isnull, isdone);
+
+ if (*isdone != ExprEndResult)
+ hasresult = true;
+ if (*isdone == ExprMultipleResult)
+ node->pending_srf_tuples = true;
+ hassrf = true;
+ }
+ else
+ {
+ /* Non-SRF tlist expression, just evaluate normally. */
+ *result = ExecEvalExpr((ExprState *) elem, econtext, isnull);
+ *isdone = ExprSingleResult;
+ }
+ }
+
+ /* ProjectSet should not be used if there's no SRFs */
+ Assert(hassrf);
+
+ /*
+ * If all the SRFs returned EndResult, we consider that as no row being
+ * produced.
+ */
+ if (hasresult)
+ {
+ ExecStoreVirtualTuple(resultSlot);
+ return resultSlot;
+ }
+
+ return NULL;
+}
+
+/* ----------------------------------------------------------------
+ * ExecInitProjectSet
+ *
+ * Creates the run-time state information for the ProjectSet node
+ * produced by the planner and initializes outer relations
+ * (child nodes).
+ * ----------------------------------------------------------------
+ */
+ProjectSetState *
+ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
+{
+ ProjectSetState *state;
+ ListCell *lc;
+ int off;
+
+ /* check for unsupported flags */
+ Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)));
+
+ /*
+ * create state structure
+ */
+ state = makeNode(ProjectSetState);
+ state->ps.plan = (Plan *) node;
+ state->ps.state = estate;
+
+ state->pending_srf_tuples = false;
+
+ /*
+ * Miscellaneous initialization
+ *
+ * create expression context for node
+ */
+ ExecAssignExprContext(estate, &state->ps);
+
+ /*
+ * tuple table initialization
+ */
+ ExecInitResultTupleSlot(estate, &state->ps);
+
+ /* We don't support any qual on ProjectSet nodes */
+ Assert(node->plan.qual == NIL);
+
+ /*
+ * initialize child nodes
+ */
+ outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);
+
+ /*
+ * we don't use inner plan
+ */
+ Assert(innerPlan(node) == NULL);
+
+ /*
+ * initialize tuple type and projection info
+ */
+ ExecAssignResultTypeFromTL(&state->ps);
+
+ /* Create workspace for per-tlist-entry expr state & SRF-is-done state */
+ state->nelems = list_length(node->plan.targetlist);
+ state->elems = (Node **)
+ palloc(sizeof(Node *) * state->nelems);
+ state->elemdone = (ExprDoneCond *)
+ palloc(sizeof(ExprDoneCond) * state->nelems);
+
+ /*
+ * Build expressions to evaluate targetlist. We can't use
+ * ExecBuildProjectionInfo here, since that doesn't deal with SRFs.
+ * Instead compile each expression separately, using
+ * ExecInitFunctionResultSet where applicable.
+ */
+ off = 0;
+ foreach(lc, node->plan.targetlist)
+ {
+ TargetEntry *te = (TargetEntry *) lfirst(lc);
+ Expr *expr = te->expr;
+
+ if ((IsA(expr, FuncExpr) &&((FuncExpr *) expr)->funcretset) ||
+ (IsA(expr, OpExpr) &&((OpExpr *) expr)->opretset))
+ {
+ state->elems[off] = (Node *)
+ ExecInitFunctionResultSet(expr, state->ps.ps_ExprContext,
+ &state->ps);
+ }
+ else
+ {
+ Assert(!expression_returns_set((Node *) expr));
+ state->elems[off] = (Node *) ExecInitExpr(expr, &state->ps);
+ }
+
+ off++;
+ }
+
+ return state;
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndProjectSet
+ *
+ * frees up storage allocated through C routines
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndProjectSet(ProjectSetState *node)
+{
+ /*
+ * Free the exprcontext
+ */
+ ExecFreeExprContext(&node->ps);
+
+ /*
+ * clean out the tuple table
+ */
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+
+ /*
+ * shut down subplans
+ */
+ ExecEndNode(outerPlanState(node));
+}
+
+void
+ExecReScanProjectSet(ProjectSetState *node)
+{
+ /* Forget any incompletely-evaluated SRFs */
+ node->pending_srf_tuples = false;
+
+ /*
+ * If chgParam of subnode is not null then plan will be re-scanned by
+ * first ExecProcNode.
+ */
+ if (node->ps.lefttree->chgParam == NULL)
+ ExecReScan(node->ps.lefttree);
+}
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index e76405a56e..fc1c00d68f 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -3,7 +3,11 @@
* nodeRecursiveunion.c
* routines to handle RecursiveUnion nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * To implement UNION (without ALL), we need a hashtable that stores tuples
+ * already seen. The hash key is computed from the grouping columns.
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -20,17 +24,6 @@
#include "utils/memutils.h"
-/*
- * To implement UNION (without ALL), we need a hashtable that stores tuples
- * already seen. The hash key is computed from the grouping columns.
- */
-typedef struct RUHashEntryData *RUHashEntry;
-
-typedef struct RUHashEntryData
-{
- TupleHashEntryData shared; /* common header for hash table entries */
-} RUHashEntryData;
-
/*
* Initialize the hash table to empty.
@@ -48,9 +41,10 @@ build_hash_table(RecursiveUnionState *rustate)
rustate->eqfunctions,
rustate->hashfunctions,
node->numGroups,
- sizeof(RUHashEntryData),
+ 0,
rustate->tableContext,
- rustate->tempContext);
+ rustate->tempContext,
+ false);
}
@@ -200,15 +194,11 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
rustate->tempContext =
AllocSetContextCreate(CurrentMemoryContext,
"RecursiveUnion",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
rustate->tableContext =
AllocSetContextCreate(CurrentMemoryContext,
"RecursiveUnion hash table",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
}
/*
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index 4007b765bf..a753a53419 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -34,7 +34,7 @@
* plan normally and pass back the results.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -67,10 +67,8 @@ TupleTableSlot *
ExecResult(ResultState *node)
{
TupleTableSlot *outerTupleSlot;
- TupleTableSlot *resultSlot;
PlanState *outerPlan;
ExprContext *econtext;
- ExprDoneCond isDone;
econtext = node->ps.ps_ExprContext;
@@ -79,9 +77,7 @@ ExecResult(ResultState *node)
*/
if (node->rs_checkqual)
{
- bool qualResult = ExecQual((List *) node->resconstantqual,
- econtext,
- false);
+ bool qualResult = ExecQual(node->resconstantqual, econtext);
node->rs_checkqual = false;
if (!qualResult)
@@ -92,23 +88,8 @@ ExecResult(ResultState *node)
}
/*
- * Check to see if we're still projecting out tuples from a previous scan
- * tuple (because there is a function-returning-set in the projection
- * expressions). If so, try to project another one.
- */
- if (node->ps.ps_TupFromTlist)
- {
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return resultSlot;
- /* Done with that source tuple... */
- node->ps.ps_TupFromTlist = false;
- }
-
- /*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't happen
- * until we're done projecting out tuples from a scan tuple.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -147,18 +128,8 @@ ExecResult(ResultState *node)
node->rs_done = true;
}
- /*
- * form the result tuple using ExecProject(), and return it --- unless
- * the projection produces an empty set, in which case we must loop
- * back to see if there are more outerPlan tuples.
- */
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
- return resultSlot;
- }
+ /* form the result tuple using ExecProject(), and return it */
+ return ExecProject(node->ps.ps_ProjInfo);
}
return NULL;
@@ -228,8 +199,6 @@ ExecInitResult(Result *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &resstate->ps);
- resstate->ps.ps_TupFromTlist = false;
-
/*
* tuple table initialization
*/
@@ -238,14 +207,10 @@ ExecInitResult(Result *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- resstate->ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) resstate);
- resstate->ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) resstate);
- resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual,
- (PlanState *) resstate);
+ resstate->ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) resstate);
+ resstate->resconstantqual =
+ ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
/*
* initialize child nodes
@@ -295,7 +260,6 @@ void
ExecReScanResult(ResultState *node)
{
node->rs_done = false;
- node->ps.ps_TupFromTlist = false;
node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
/*
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 9ce7c02aff..0247bd2347 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -3,7 +3,7 @@
* nodeSamplescan.c
* Support routines for sample scans of relations (table sampling).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,6 +22,7 @@
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/predicate.h"
+#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/tqual.h"
@@ -163,19 +164,12 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
-
- scanstate->args = (List *)
- ExecInitExpr((Expr *) tsc->args,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
+ scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
scanstate->repeatable =
- ExecInitExpr(tsc->repeatable,
- (PlanState *) scanstate);
+ ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
/*
* tuple table initialization
@@ -188,8 +182,6 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
*/
InitScanRelation(scanstate, estate, eflags);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
/*
* Initialize result tuple type and projection info.
*/
@@ -299,8 +291,7 @@ tablesample_init(SampleScanState *scanstate)
params[i] = ExecEvalExprSwitchContext(argstate,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
@@ -312,8 +303,7 @@ tablesample_init(SampleScanState *scanstate)
{
datum = ExecEvalExprSwitchContext(scanstate->repeatable,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 00bf3a58b1..5680464fa2 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -3,7 +3,7 @@
* nodeSeqscan.c
* Support routines for sequential scans of relations.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -188,12 +188,8 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) scanstate);
/*
* tuple table initialization
@@ -206,8 +202,6 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
*/
InitScanRelation(scanstate, estate, eflags);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
/*
* Initialize result tuple type and projection info.
*/
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 2d81d46927..9ae53bb8a7 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -32,7 +32,7 @@
* input group.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -64,20 +64,7 @@ typedef struct SetOpStatePerGroupData
{
long numLeft; /* number of left-input dups in group */
long numRight; /* number of right-input dups in group */
-} SetOpStatePerGroupData;
-
-/*
- * To implement hashed mode, we need a hashtable that stores a
- * representative tuple and the duplicate counts for each distinct set
- * of grouping columns. We compute the hash key from the grouping columns.
- */
-typedef struct SetOpHashEntryData *SetOpHashEntry;
-
-typedef struct SetOpHashEntryData
-{
- TupleHashEntryData shared; /* common header for hash table entries */
- SetOpStatePerGroupData pergroup;
-} SetOpHashEntryData;
+} SetOpStatePerGroupData;
static TupleTableSlot *setop_retrieve_direct(SetOpState *setopstate);
@@ -141,9 +128,10 @@ build_hash_table(SetOpState *setopstate)
setopstate->eqfunctions,
setopstate->hashfunctions,
node->numGroups,
- sizeof(SetOpHashEntryData),
+ 0,
setopstate->tableContext,
- setopstate->tempContext);
+ setopstate->tempContext,
+ false);
}
/*
@@ -238,7 +226,7 @@ setop_retrieve_direct(SetOpState *setopstate)
* get state info from node
*/
outerPlan = outerPlanState(setopstate);
- pergroup = setopstate->pergroup;
+ pergroup = (SetOpStatePerGroup) setopstate->pergroup;
resultTupleSlot = setopstate->ps.ps_ResultTupleSlot;
/*
@@ -367,7 +355,7 @@ setop_fill_hash_table(SetOpState *setopstate)
{
TupleTableSlot *outerslot;
int flag;
- SetOpHashEntry entry;
+ TupleHashEntryData *entry;
bool isnew;
outerslot = ExecProcNode(outerPlan);
@@ -383,15 +371,20 @@ setop_fill_hash_table(SetOpState *setopstate)
Assert(in_first_rel);
/* Find or build hashtable entry for this tuple's group */
- entry = (SetOpHashEntry)
- LookupTupleHashEntry(setopstate->hashtable, outerslot, &isnew);
+ entry = LookupTupleHashEntry(setopstate->hashtable, outerslot,
+ &isnew);
/* If new tuple group, initialize counts */
if (isnew)
- initialize_counts(&entry->pergroup);
+ {
+ entry->additional = (SetOpStatePerGroup)
+ MemoryContextAlloc(setopstate->hashtable->tablecxt,
+ sizeof(SetOpStatePerGroupData));
+ initialize_counts((SetOpStatePerGroup) entry->additional);
+ }
/* Advance the counts */
- advance_counts(&entry->pergroup, flag);
+ advance_counts((SetOpStatePerGroup) entry->additional, flag);
}
else
{
@@ -399,12 +392,12 @@ setop_fill_hash_table(SetOpState *setopstate)
in_first_rel = false;
/* For tuples not seen previously, do not make hashtable entry */
- entry = (SetOpHashEntry)
- LookupTupleHashEntry(setopstate->hashtable, outerslot, NULL);
+ entry = LookupTupleHashEntry(setopstate->hashtable, outerslot,
+ NULL);
/* Advance the counts if entry is already present */
if (entry)
- advance_counts(&entry->pergroup, flag);
+ advance_counts((SetOpStatePerGroup) entry->additional, flag);
}
/* Must reset temp context after each hashtable lookup */
@@ -422,7 +415,7 @@ setop_fill_hash_table(SetOpState *setopstate)
static TupleTableSlot *
setop_retrieve_hash_table(SetOpState *setopstate)
{
- SetOpHashEntry entry;
+ TupleHashEntryData *entry;
TupleTableSlot *resultTupleSlot;
/*
@@ -438,7 +431,7 @@ setop_retrieve_hash_table(SetOpState *setopstate)
/*
* Find the next entry in the hash table
*/
- entry = (SetOpHashEntry) ScanTupleHashTable(&setopstate->hashiter);
+ entry = ScanTupleHashTable(setopstate->hashtable, &setopstate->hashiter);
if (entry == NULL)
{
/* No more entries in hashtable, so done */
@@ -450,12 +443,12 @@ setop_retrieve_hash_table(SetOpState *setopstate)
* See if we should emit any copies of this tuple, and if so return
* the first copy.
*/
- set_output_count(setopstate, &entry->pergroup);
+ set_output_count(setopstate, (SetOpStatePerGroup) entry->additional);
if (setopstate->numOutput > 0)
{
setopstate->numOutput--;
- return ExecStoreMinimalTuple(entry->shared.firstTuple,
+ return ExecStoreMinimalTuple(entry->firstTuple,
resultTupleSlot,
false);
}
@@ -507,9 +500,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
setopstate->tempContext =
AllocSetContextCreate(CurrentMemoryContext,
"SetOp",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* If hashing, we also need a longer-lived context to store the hash
@@ -520,9 +511,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
setopstate->tableContext =
AllocSetContextCreate(CurrentMemoryContext,
"SetOp hash table",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* Tuple table initialization
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index a34dcc5135..924b458df8 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -3,7 +3,7 @@
* nodeSort.c
* Routines to handle sorting of relations.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -132,12 +132,13 @@ ExecSort(SortState *node)
/*
* Get the first or next tuple from tuplesort. Returns NULL if no more
- * tuples.
+ * tuples. Note that we only rely on slot tuple remaining valid until the
+ * next fetch from the tuplesort.
*/
slot = node->ss.ps.ps_ResultTupleSlot;
(void) tuplesort_gettupleslot(tuplesortstate,
ScanDirectionIsForward(dir),
- slot, NULL);
+ false, slot, NULL);
return slot;
}
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index fb7461c96c..85e5acf75a 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -14,7 +14,7 @@
* subplans, which are re-evaluated every time their result is required.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -42,14 +42,6 @@
#include "utils/memutils.h"
-static Datum ExecSubPlan(SubPlanState *node,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone);
-static Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone);
static Datum ExecHashSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull);
@@ -69,18 +61,15 @@ static bool slotNoNulls(TupleTableSlot *slot);
* This is the main entry point for execution of a regular SubPlan.
* ----------------------------------------------------------------
*/
-static Datum
+Datum
ExecSubPlan(SubPlanState *node,
ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
+ bool *isNull)
{
- SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ SubPlan *subplan = node->subplan;
- /* Set default values for result flags: non-null, not a set result */
+ /* Set non-null as default */
*isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
/* Sanity checks */
if (subplan->subLinkType == CTE_SUBLINK)
@@ -103,7 +92,7 @@ ExecHashSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull)
{
- SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ SubPlan *subplan = node->subplan;
PlanState *planstate = node->planstate;
TupleTableSlot *slot;
@@ -131,7 +120,7 @@ ExecHashSubPlan(SubPlanState *node,
* have to set the econtext to use (hack alert!).
*/
node->projLeft->pi_exprContext = econtext;
- slot = ExecProject(node->projLeft, NULL);
+ slot = ExecProject(node->projLeft);
/*
* Note: because we are typically called in a per-tuple context, we have
@@ -225,7 +214,7 @@ ExecScanSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull)
{
- SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ SubPlan *subplan = node->subplan;
PlanState *planstate = node->planstate;
SubLinkType subLinkType = subplan->subLinkType;
MemoryContext oldcontext;
@@ -288,8 +277,7 @@ ExecScanSubPlan(SubPlanState *node,
prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
econtext,
- &(prm->isnull),
- NULL);
+ &(prm->isnull));
prm->done = true;
planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
}
@@ -407,7 +395,7 @@ ExecScanSubPlan(SubPlanState *node,
}
rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
- &rownull, NULL);
+ &rownull);
if (subLinkType == ANY_SUBLINK)
{
@@ -472,7 +460,7 @@ ExecScanSubPlan(SubPlanState *node,
static void
buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
{
- SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ SubPlan *subplan = node->subplan;
PlanState *planstate = node->planstate;
int ncols = list_length(subplan->paramIds);
ExprContext *innerecontext = node->innerecontext;
@@ -512,9 +500,10 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
node->tab_eq_funcs,
node->tab_hash_funcs,
nbuckets,
- sizeof(TupleHashEntryData),
+ 0,
node->hashtablecxt,
- node->hashtempcxt);
+ node->hashtempcxt,
+ false);
if (!subplan->unknownEqFalse)
{
@@ -531,9 +520,10 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
node->tab_eq_funcs,
node->tab_hash_funcs,
nbuckets,
- sizeof(TupleHashEntryData),
+ 0,
node->hashtablecxt,
- node->hashtempcxt);
+ node->hashtempcxt,
+ false);
}
/*
@@ -574,7 +564,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
&(prmdata->isnull));
col++;
}
- slot = ExecProject(node->projRight, NULL);
+ slot = ExecProject(node->projRight);
/*
* If result contains any nulls, store separately or not at all.
@@ -604,7 +594,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
* potential for a double free attempt. (XXX possibly no longer needed,
* but can't hurt.)
*/
- ExecClearTuple(node->projRight->pi_slot);
+ ExecClearTuple(node->projRight->pi_state.resultslot);
MemoryContextSwitchTo(oldcontext);
}
@@ -630,7 +620,7 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot,
TupleHashEntry entry;
InitTupleHashIterator(hashtable, &hashiter);
- while ((entry = ScanTupleHashTable(&hashiter)) != NULL)
+ while ((entry = ScanTupleHashTable(hashtable, &hashiter)) != NULL)
{
ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false);
if (!execTuplesUnequal(slot, hashtable->tableslot,
@@ -702,8 +692,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
SubPlanState *sstate = makeNode(SubPlanState);
EState *estate = parent->state;
- sstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecSubPlan;
- sstate->xprstate.expr = (Expr *) subplan;
+ sstate->subplan = subplan;
/* Link the SubPlanState to already-initialized subplan */
sstate->planstate = (PlanState *) list_nth(estate->es_subplanstates,
@@ -719,7 +708,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
/* Initialize subexpressions */
sstate->testexpr = ExecInitExpr((Expr *) subplan->testexpr, parent);
- sstate->args = (List *) ExecInitExpr((Expr *) subplan->args, parent);
+ sstate->args = ExecInitExprList(subplan->args, parent);
/*
* initialize my state
@@ -776,25 +765,19 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
TupleTableSlot *slot;
List *oplist,
*lefttlist,
- *righttlist,
- *leftptlist,
- *rightptlist;
+ *righttlist;
ListCell *l;
/* We need a memory context to hold the hash table(s) */
sstate->hashtablecxt =
AllocSetContextCreate(CurrentMemoryContext,
"Subplan HashTable Context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/* and a small one for the hash tables to use as temp storage */
sstate->hashtempcxt =
AllocSetContextCreate(CurrentMemoryContext,
"Subplan HashTable Temp Context",
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
/* and a short-lived exprcontext for function evaluation */
sstate->innerecontext = CreateExprContext(estate);
/* Silly little array of column numbers 1..n */
@@ -809,36 +792,33 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
* use the sub-select's output tuples directly, but that is not the
* case if we had to insert any run-time coercions of the sub-select's
* output datatypes; anyway this avoids storing any resjunk columns
- * that might be in the sub-select's output.) Run through the
+ * that might be in the sub-select's output.) Run through the
* combining expressions to build tlists for the lefthand and
- * righthand sides. We need both the ExprState list (for ExecProject)
- * and the underlying parse Exprs (for ExecTypeFromTL).
+ * righthand sides.
*
* We also extract the combining operators themselves to initialize
* the equality and hashing functions for the hash tables.
*/
- if (IsA(sstate->testexpr->expr, OpExpr))
+ if (IsA(subplan->testexpr, OpExpr))
{
/* single combining operator */
- oplist = list_make1(sstate->testexpr);
+ oplist = list_make1(subplan->testexpr);
}
- else if (and_clause((Node *) sstate->testexpr->expr))
+ else if (and_clause((Node *) subplan->testexpr))
{
/* multiple combining operators */
- Assert(IsA(sstate->testexpr, BoolExprState));
- oplist = ((BoolExprState *) sstate->testexpr)->args;
+ oplist = castNode(BoolExpr, subplan->testexpr)->args;
}
else
{
/* shouldn't see anything else in a hashable subplan */
elog(ERROR, "unrecognized testexpr type: %d",
- (int) nodeTag(sstate->testexpr->expr));
+ (int) nodeTag(subplan->testexpr));
oplist = NIL; /* keep compiler quiet */
}
Assert(list_length(oplist) == ncols);
lefttlist = righttlist = NIL;
- leftptlist = rightptlist = NIL;
sstate->tab_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
sstate->tab_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
@@ -846,47 +826,30 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
i = 1;
foreach(l, oplist)
{
- FuncExprState *fstate = (FuncExprState *) lfirst(l);
- OpExpr *opexpr = (OpExpr *) fstate->xprstate.expr;
- ExprState *exstate;
+ OpExpr *opexpr = lfirst_node(OpExpr, l);
Expr *expr;
TargetEntry *tle;
- GenericExprState *tlestate;
Oid rhs_eq_oper;
Oid left_hashfn;
Oid right_hashfn;
- Assert(IsA(fstate, FuncExprState));
- Assert(IsA(opexpr, OpExpr));
- Assert(list_length(fstate->args) == 2);
+ Assert(list_length(opexpr->args) == 2);
/* Process lefthand argument */
- exstate = (ExprState *) linitial(fstate->args);
- expr = exstate->expr;
+ expr = (Expr *) linitial(opexpr->args);
tle = makeTargetEntry(expr,
i,
NULL,
false);
- tlestate = makeNode(GenericExprState);
- tlestate->xprstate.expr = (Expr *) tle;
- tlestate->xprstate.evalfunc = NULL;
- tlestate->arg = exstate;
- lefttlist = lappend(lefttlist, tlestate);
- leftptlist = lappend(leftptlist, tle);
+ lefttlist = lappend(lefttlist, tle);
/* Process righthand argument */
- exstate = (ExprState *) lsecond(fstate->args);
- expr = exstate->expr;
+ expr = (Expr *) lsecond(opexpr->args);
tle = makeTargetEntry(expr,
i,
NULL,
false);
- tlestate = makeNode(GenericExprState);
- tlestate->xprstate.expr = (Expr *) tle;
- tlestate->xprstate.evalfunc = NULL;
- tlestate->arg = exstate;
- righttlist = lappend(righttlist, tlestate);
- rightptlist = lappend(rightptlist, tle);
+ righttlist = lappend(righttlist, tle);
/* Lookup the equality function (potentially cross-type) */
fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
@@ -918,20 +881,22 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
* (hack alert!). The righthand expressions will be evaluated in our
* own innerecontext.
*/
- tupDesc = ExecTypeFromTL(leftptlist, false);
+ tupDesc = ExecTypeFromTL(lefttlist, false);
slot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(slot, tupDesc);
sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
NULL,
slot,
+ parent,
NULL);
- tupDesc = ExecTypeFromTL(rightptlist, false);
+ tupDesc = ExecTypeFromTL(righttlist, false);
slot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(slot, tupDesc);
sstate->projRight = ExecBuildProjectionInfo(righttlist,
sstate->innerecontext,
slot,
+ sstate->planstate,
NULL);
}
@@ -954,7 +919,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
void
ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
- SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ SubPlan *subplan = node->subplan;
PlanState *planstate = node->planstate;
SubLinkType subLinkType = subplan->subLinkType;
MemoryContext oldcontext;
@@ -996,8 +961,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
econtext,
- &(prm->isnull),
- NULL);
+ &(prm->isnull));
prm->done = true;
planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
}
@@ -1138,7 +1102,7 @@ void
ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
{
PlanState *planstate = node->planstate;
- SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ SubPlan *subplan = node->subplan;
EState *estate = parent->state;
ListCell *l;
@@ -1189,16 +1153,22 @@ ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
SubPlan *subplan2;
Cost cost1;
Cost cost2;
+ ListCell *lc;
- asstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecAlternativeSubPlan;
- asstate->xprstate.expr = (Expr *) asplan;
+ asstate->subplan = asplan;
/*
* Initialize subplans. (Can we get away with only initializing the one
* we're going to use?)
*/
- asstate->subplans = (List *) ExecInitExpr((Expr *) asplan->subplans,
- parent);
+ foreach(lc, asplan->subplans)
+ {
+ SubPlan *sp = lfirst_node(SubPlan, lc);
+ SubPlanState *sps = ExecInitSubPlan(sp, parent);
+
+ asstate->subplans = lappend(asstate->subplans, sps);
+ parent->subPlan = lappend(parent->subPlan, sps);
+ }
/*
* Select the one to be used. For this, we need an estimate of the number
@@ -1236,20 +1206,14 @@ ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
* Note: in future we might consider changing to different subplans on the
* fly, in case the original rowcount estimate turns out to be way off.
*/
-static Datum
+Datum
ExecAlternativeSubPlan(AlternativeSubPlanState *node,
ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
+ bool *isNull)
{
/* Just pass control to the active subplan */
- SubPlanState *activesp = (SubPlanState *) list_nth(node->subplans,
- node->active);
-
- Assert(IsA(activesp, SubPlanState));
+ SubPlanState *activesp = list_nth_node(SubPlanState,
+ node->subplans, node->active);
- return ExecSubPlan(activesp,
- econtext,
- isNull,
- isDone);
+ return ExecSubPlan(activesp, econtext, isNull);
}
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 9bafc62677..ae184700a6 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -7,7 +7,7 @@
* we need two sets of code. Ought to look at trying to unify the cases.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -120,12 +120,8 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- subquerystate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) subquerystate);
- subquerystate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) subquerystate);
+ subquerystate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
/*
* tuple table initialization
@@ -138,8 +134,6 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
*/
subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
- subquerystate->ss.ps.ps_TupFromTlist = false;
-
/*
* Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
*/
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
new file mode 100644
index 0000000000..da557ceb6f
--- /dev/null
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -0,0 +1,498 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeTableFuncscan.c
+ * Support routines for scanning RangeTableFunc (XMLTABLE like functions).
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/nodeTableFuncscan.c
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ * INTERFACE ROUTINES
+ * ExecTableFuncscan scans a function.
+ * ExecFunctionNext retrieve next tuple in sequential order.
+ * ExecInitTableFuncscan creates and initializes a TableFuncscan node.
+ * ExecEndTableFuncscan releases any storage allocated.
+ * ExecReScanTableFuncscan rescans the function
+ */
+#include "postgres.h"
+
+#include "nodes/execnodes.h"
+#include "executor/executor.h"
+#include "executor/nodeTableFuncscan.h"
+#include "executor/tablefunc.h"
+#include "miscadmin.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/xml.h"
+
+
+static TupleTableSlot *TableFuncNext(TableFuncScanState *node);
+static bool TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot);
+
+static void tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext);
+static void tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc);
+static void tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext);
+
+/* ----------------------------------------------------------------
+ * Scan Support
+ * ----------------------------------------------------------------
+ */
+/* ----------------------------------------------------------------
+ * TableFuncNext
+ *
+ * This is a workhorse for ExecTableFuncscan
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+TableFuncNext(TableFuncScanState *node)
+{
+ TupleTableSlot *scanslot;
+
+ scanslot = node->ss.ss_ScanTupleSlot;
+
+ /*
+ * If first time through, read all tuples from function and put them in a
+ * tuplestore. Subsequent calls just fetch tuples from tuplestore.
+ */
+ if (node->tupstore == NULL)
+ tfuncFetchRows(node, node->ss.ps.ps_ExprContext);
+
+ /*
+ * Get the next tuple from tuplestore.
+ */
+ (void) tuplestore_gettupleslot(node->tupstore,
+ true,
+ false,
+ scanslot);
+ return scanslot;
+}
+
+/*
+ * TableFuncRecheck -- access method routine to recheck a tuple in EvalPlanQual
+ */
+static bool
+TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot)
+{
+ /* nothing to check */
+ return true;
+}
+
+/* ----------------------------------------------------------------
+ * ExecTableFuncscan(node)
+ *
+ * Scans the function sequentially and returns the next qualifying
+ * tuple.
+ * We call the ExecScan() routine and pass it the appropriate
+ * access method functions.
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecTableFuncScan(TableFuncScanState *node)
+{
+ return ExecScan(&node->ss,
+ (ExecScanAccessMtd) TableFuncNext,
+ (ExecScanRecheckMtd) TableFuncRecheck);
+}
+
+/* ----------------------------------------------------------------
+ * ExecInitTableFuncscan
+ * ----------------------------------------------------------------
+ */
+TableFuncScanState *
+ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
+{
+ TableFuncScanState *scanstate;
+ TableFunc *tf = node->tablefunc;
+ TupleDesc tupdesc;
+ int i;
+
+ /* check for unsupported flags */
+ Assert(!(eflags & EXEC_FLAG_MARK));
+
+ /*
+ * TableFuncscan should not have any children.
+ */
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
+
+ /*
+ * create new ScanState for node
+ */
+ scanstate = makeNode(TableFuncScanState);
+ scanstate->ss.ps.plan = (Plan *) node;
+ scanstate->ss.ps.state = estate;
+
+ /*
+ * Miscellaneous initialization
+ *
+ * create expression context for node
+ */
+ ExecAssignExprContext(estate, &scanstate->ss.ps);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
+
+ /*
+ * tuple table initialization
+ */
+ ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &scanstate->ss);
+
+ /*
+ * initialize source tuple type
+ */
+ tupdesc = BuildDescFromLists(tf->colnames,
+ tf->coltypes,
+ tf->coltypmods,
+ tf->colcollations);
+
+ ExecAssignScanType(&scanstate->ss, tupdesc);
+
+ /*
+ * Initialize result tuple type and projection info.
+ */
+ ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
+
+ /* Only XMLTABLE is supported currently */
+ scanstate->routine = &XmlTableRoutine;
+
+ scanstate->perValueCxt =
+ AllocSetContextCreate(CurrentMemoryContext,
+ "TableFunc per value context",
+ ALLOCSET_DEFAULT_SIZES);
+ scanstate->opaque = NULL; /* initialized at runtime */
+
+ scanstate->ns_names = tf->ns_names;
+
+ scanstate->ns_uris =
+ ExecInitExprList(tf->ns_uris, (PlanState *) scanstate);
+ scanstate->docexpr =
+ ExecInitExpr((Expr *) tf->docexpr, (PlanState *) scanstate);
+ scanstate->rowexpr =
+ ExecInitExpr((Expr *) tf->rowexpr, (PlanState *) scanstate);
+ scanstate->colexprs =
+ ExecInitExprList(tf->colexprs, (PlanState *) scanstate);
+ scanstate->coldefexprs =
+ ExecInitExprList(tf->coldefexprs, (PlanState *) scanstate);
+
+ scanstate->notnulls = tf->notnulls;
+
+ /* these are allocated now and initialized later */
+ scanstate->in_functions = palloc(sizeof(FmgrInfo) * tupdesc->natts);
+ scanstate->typioparams = palloc(sizeof(Oid) * tupdesc->natts);
+
+ /*
+ * Fill in the necessary fmgr infos.
+ */
+ for (i = 0; i < tupdesc->natts; i++)
+ {
+ Oid in_funcid;
+
+ getTypeInputInfo(tupdesc->attrs[i]->atttypid,
+ &in_funcid, &scanstate->typioparams[i]);
+ fmgr_info(in_funcid, &scanstate->in_functions[i]);
+ }
+
+ return scanstate;
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndTableFuncscan
+ *
+ * frees any storage allocated through C routines.
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndTableFuncScan(TableFuncScanState *node)
+{
+ /*
+ * Free the exprcontext
+ */
+ ExecFreeExprContext(&node->ss.ps);
+
+ /*
+ * clean out the tuple table
+ */
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+
+ /*
+ * Release tuplestore resources
+ */
+ if (node->tupstore != NULL)
+ tuplestore_end(node->tupstore);
+ node->tupstore = NULL;
+}
+
+/* ----------------------------------------------------------------
+ * ExecReScanTableFuncscan
+ *
+ * Rescans the relation.
+ * ----------------------------------------------------------------
+ */
+void
+ExecReScanTableFuncScan(TableFuncScanState *node)
+{
+ Bitmapset *chgparam = node->ss.ps.chgParam;
+
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecScanReScan(&node->ss);
+
+ /*
+ * Recompute when parameters are changed.
+ */
+ if (chgparam)
+ {
+ if (node->tupstore != NULL)
+ {
+ tuplestore_end(node->tupstore);
+ node->tupstore = NULL;
+ }
+ }
+
+ if (node->tupstore != NULL)
+ tuplestore_rescan(node->tupstore);
+}
+
+/* ----------------------------------------------------------------
+ * tfuncFetchRows
+ *
+ * Read rows from a TableFunc producer
+ * ----------------------------------------------------------------
+ */
+static void
+tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext)
+{
+ const TableFuncRoutine *routine = tstate->routine;
+ MemoryContext oldcxt;
+ Datum value;
+ bool isnull;
+
+ Assert(tstate->opaque == NULL);
+
+ /* build tuplestore for the result */
+ oldcxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ tstate->tupstore = tuplestore_begin_heap(false, false, work_mem);
+
+ PG_TRY();
+ {
+ routine->InitOpaque(tstate,
+ tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor->natts);
+
+ /*
+ * If evaluating the document expression returns NULL, the table
+ * expression is empty and we return immediately.
+ */
+ value = ExecEvalExpr(tstate->docexpr, econtext, &isnull);
+
+ if (!isnull)
+ {
+ /* otherwise, pass the document value to the table builder */
+ tfuncInitialize(tstate, econtext, value);
+
+ /* initialize ordinality counter */
+ tstate->ordinal = 1;
+
+ /* Load all rows into the tuplestore, and we're done */
+ tfuncLoadRows(tstate, econtext);
+ }
+ }
+ PG_CATCH();
+ {
+ if (tstate->opaque != NULL)
+ routine->DestroyOpaque(tstate);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+
+ /* return to original memory context, and clean up */
+ MemoryContextSwitchTo(oldcxt);
+
+ if (tstate->opaque != NULL)
+ {
+ routine->DestroyOpaque(tstate);
+ tstate->opaque = NULL;
+ }
+
+ return;
+}
+
+/*
+ * Fill in namespace declarations, the row filter, and column filters in a
+ * table expression builder context.
+ */
+static void
+tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
+{
+ const TableFuncRoutine *routine = tstate->routine;
+ TupleDesc tupdesc;
+ ListCell *lc1,
+ *lc2;
+ bool isnull;
+ int colno;
+ Datum value;
+ int ordinalitycol =
+ ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol;
+
+ /*
+ * Install the document as a possibly-toasted Datum into the tablefunc
+ * context.
+ */
+ routine->SetDocument(tstate, doc);
+
+ /* Evaluate namespace specifications */
+ forboth(lc1, tstate->ns_uris, lc2, tstate->ns_names)
+ {
+ ExprState *expr = (ExprState *) lfirst(lc1);
+ char *ns_name = strVal(lfirst(lc2));
+ char *ns_uri;
+
+ value = ExecEvalExpr((ExprState *) expr, econtext, &isnull);
+ if (isnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("namespace URI must not be null")));
+ ns_uri = TextDatumGetCString(value);
+
+ routine->SetNamespace(tstate, ns_name, ns_uri);
+ }
+
+ /* Install the row filter expression into the table builder context */
+ value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
+ if (isnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("row filter expression must not be null")));
+
+ routine->SetRowFilter(tstate, TextDatumGetCString(value));
+
+ /*
+ * Install the column filter expressions into the table builder context.
+ * If an expression is given, use that; otherwise the column name itself
+ * is the column filter.
+ */
+ colno = 0;
+ tupdesc = tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+ foreach(lc1, tstate->colexprs)
+ {
+ char *colfilter;
+
+ if (colno != ordinalitycol)
+ {
+ ExprState *colexpr = lfirst(lc1);
+
+ if (colexpr != NULL)
+ {
+ value = ExecEvalExpr(colexpr, econtext, &isnull);
+ if (isnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("column filter expression must not be null"),
+ errdetail("Filter for column \"%s\" is null.",
+ NameStr(tupdesc->attrs[colno]->attname))));
+ colfilter = TextDatumGetCString(value);
+ }
+ else
+ colfilter = NameStr(tupdesc->attrs[colno]->attname);
+
+ routine->SetColumnFilter(tstate, colfilter, colno);
+ }
+
+ colno++;
+ }
+}
+
+/*
+ * Load all the rows from the TableFunc table builder into a tuplestore.
+ */
+static void
+tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext)
+{
+ const TableFuncRoutine *routine = tstate->routine;
+ TupleTableSlot *slot = tstate->ss.ss_ScanTupleSlot;
+ TupleDesc tupdesc = slot->tts_tupleDescriptor;
+ Datum *values = slot->tts_values;
+ bool *nulls = slot->tts_isnull;
+ int natts = tupdesc->natts;
+ MemoryContext oldcxt;
+ int ordinalitycol;
+
+ ordinalitycol =
+ ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol;
+ oldcxt = MemoryContextSwitchTo(tstate->perValueCxt);
+
+ /*
+ * Keep requesting rows from the table builder until there aren't any.
+ */
+ while (routine->FetchRow(tstate))
+ {
+ ListCell *cell = list_head(tstate->coldefexprs);
+ int colno;
+
+ ExecClearTuple(tstate->ss.ss_ScanTupleSlot);
+
+ /*
+ * Obtain the value of each column for this row, installing them into
+ * the slot; then add the tuple to the tuplestore.
+ */
+ for (colno = 0; colno < natts; colno++)
+ {
+ if (colno == ordinalitycol)
+ {
+ /* Fast path for ordinality column */
+ values[colno] = Int32GetDatum(tstate->ordinal++);
+ nulls[colno] = false;
+ }
+ else
+ {
+ bool isnull;
+
+ values[colno] = routine->GetValue(tstate,
+ colno,
+ tupdesc->attrs[colno]->atttypid,
+ tupdesc->attrs[colno]->atttypmod,
+ &isnull);
+
+ /* No value? Evaluate and apply the default, if any */
+ if (isnull && cell != NULL)
+ {
+ ExprState *coldefexpr = (ExprState *) lfirst(cell);
+
+ if (coldefexpr != NULL)
+ values[colno] = ExecEvalExpr(coldefexpr, econtext,
+ &isnull);
+ }
+
+ /* Verify a possible NOT NULL constraint */
+ if (isnull && bms_is_member(colno, tstate->notnulls))
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("null is not allowed in column \"%s\"",
+ NameStr(tupdesc->attrs[colno]->attname))));
+
+ nulls[colno] = isnull;
+ }
+
+ /* advance list of default expressions */
+ if (cell != NULL)
+ cell = lnext(cell);
+ }
+
+ tuplestore_putvalues(tstate->tupstore, tupdesc, values, nulls);
+
+ MemoryContextReset(tstate->perValueCxt);
+ }
+
+ MemoryContextSwitchTo(oldcxt);
+}
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 2604103352..4860ec0f4d 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -3,7 +3,7 @@
* nodeTidscan.c
* Routines to support direct tid scans of relations
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -38,21 +38,94 @@
((Var *) (node))->varattno == SelfItemPointerAttributeNumber && \
((Var *) (node))->varlevelsup == 0)
-static void TidListCreate(TidScanState *tidstate);
+/* one element in tss_tidexprs */
+typedef struct TidExpr
+{
+ ExprState *exprstate; /* ExprState for a TID-yielding subexpr */
+ bool isarray; /* if true, it yields tid[] not just tid */
+ CurrentOfExpr *cexpr; /* alternatively, we can have CURRENT OF */
+} TidExpr;
+
+static void TidExprListCreate(TidScanState *tidstate);
+static void TidListEval(TidScanState *tidstate);
static int itemptr_comparator(const void *a, const void *b);
static TupleTableSlot *TidNext(TidScanState *node);
/*
+ * Extract the qual subexpressions that yield TIDs to search for,
+ * and compile them into ExprStates if they're ordinary expressions.
+ *
+ * CURRENT OF is a special case that we can't compile usefully;
+ * just drop it into the TidExpr list as-is.
+ */
+static void
+TidExprListCreate(TidScanState *tidstate)
+{
+ TidScan *node = (TidScan *) tidstate->ss.ps.plan;
+ ListCell *l;
+
+ tidstate->tss_tidexprs = NIL;
+ tidstate->tss_isCurrentOf = false;
+
+ foreach(l, node->tidquals)
+ {
+ Expr *expr = (Expr *) lfirst(l);
+ TidExpr *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
+
+ if (is_opclause(expr))
+ {
+ Node *arg1;
+ Node *arg2;
+
+ arg1 = get_leftop(expr);
+ arg2 = get_rightop(expr);
+ if (IsCTIDVar(arg1))
+ tidexpr->exprstate = ExecInitExpr((Expr *) arg2,
+ &tidstate->ss.ps);
+ else if (IsCTIDVar(arg2))
+ tidexpr->exprstate = ExecInitExpr((Expr *) arg1,
+ &tidstate->ss.ps);
+ else
+ elog(ERROR, "could not identify CTID variable");
+ tidexpr->isarray = false;
+ }
+ else if (expr && IsA(expr, ScalarArrayOpExpr))
+ {
+ ScalarArrayOpExpr *saex = (ScalarArrayOpExpr *) expr;
+
+ Assert(IsCTIDVar(linitial(saex->args)));
+ tidexpr->exprstate = ExecInitExpr(lsecond(saex->args),
+ &tidstate->ss.ps);
+ tidexpr->isarray = true;
+ }
+ else if (expr && IsA(expr, CurrentOfExpr))
+ {
+ CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
+
+ tidexpr->cexpr = cexpr;
+ tidstate->tss_isCurrentOf = true;
+ }
+ else
+ elog(ERROR, "could not identify CTID expression");
+
+ tidstate->tss_tidexprs = lappend(tidstate->tss_tidexprs, tidexpr);
+ }
+
+ /* CurrentOfExpr could never appear OR'd with something else */
+ Assert(list_length(tidstate->tss_tidexprs) == 1 ||
+ !tidstate->tss_isCurrentOf);
+}
+
+/*
* Compute the list of TIDs to be visited, by evaluating the expressions
* for them.
*
* (The result is actually an array, not a list.)
*/
static void
-TidListCreate(TidScanState *tidstate)
+TidListEval(TidScanState *tidstate)
{
- List *evalList = tidstate->tss_tidquals;
ExprContext *econtext = tidstate->ss.ps.ps_ExprContext;
BlockNumber nblocks;
ItemPointerData *tidList;
@@ -73,39 +146,23 @@ TidListCreate(TidScanState *tidstate)
* are simple OpExprs or CurrentOfExprs. If there are any
* ScalarArrayOpExprs, we may have to enlarge the array.
*/
- numAllocTids = list_length(evalList);
+ numAllocTids = list_length(tidstate->tss_tidexprs);
tidList = (ItemPointerData *)
palloc(numAllocTids * sizeof(ItemPointerData));
numTids = 0;
- tidstate->tss_isCurrentOf = false;
- foreach(l, evalList)
+ foreach(l, tidstate->tss_tidexprs)
{
- ExprState *exstate = (ExprState *) lfirst(l);
- Expr *expr = exstate->expr;
+ TidExpr *tidexpr = (TidExpr *) lfirst(l);
ItemPointer itemptr;
bool isNull;
- if (is_opclause(expr))
+ if (tidexpr->exprstate && !tidexpr->isarray)
{
- FuncExprState *fexstate = (FuncExprState *) exstate;
- Node *arg1;
- Node *arg2;
-
- arg1 = get_leftop(expr);
- arg2 = get_rightop(expr);
- if (IsCTIDVar(arg1))
- exstate = (ExprState *) lsecond(fexstate->args);
- else if (IsCTIDVar(arg2))
- exstate = (ExprState *) linitial(fexstate->args);
- else
- elog(ERROR, "could not identify CTID variable");
-
itemptr = (ItemPointer)
- DatumGetPointer(ExecEvalExprSwitchContext(exstate,
+ DatumGetPointer(ExecEvalExprSwitchContext(tidexpr->exprstate,
econtext,
- &isNull,
- NULL));
+ &isNull));
if (!isNull &&
ItemPointerIsValid(itemptr) &&
ItemPointerGetBlockNumber(itemptr) < nblocks)
@@ -120,9 +177,8 @@ TidListCreate(TidScanState *tidstate)
tidList[numTids++] = *itemptr;
}
}
- else if (expr && IsA(expr, ScalarArrayOpExpr))
+ else if (tidexpr->exprstate && tidexpr->isarray)
{
- ScalarArrayOpExprState *saexstate = (ScalarArrayOpExprState *) exstate;
Datum arraydatum;
ArrayType *itemarray;
Datum *ipdatums;
@@ -130,16 +186,14 @@ TidListCreate(TidScanState *tidstate)
int ndatums;
int i;
- exstate = (ExprState *) lsecond(saexstate->fxprstate.args);
- arraydatum = ExecEvalExprSwitchContext(exstate,
+ arraydatum = ExecEvalExprSwitchContext(tidexpr->exprstate,
econtext,
- &isNull,
- NULL);
+ &isNull);
if (isNull)
continue;
itemarray = DatumGetArrayTypeP(arraydatum);
deconstruct_array(itemarray,
- TIDOID, SizeOfIptrData, false, 's',
+ TIDOID, sizeof(ItemPointerData), false, 's',
&ipdatums, &ipnulls, &ndatums);
if (numTids + ndatums > numAllocTids)
{
@@ -161,12 +215,12 @@ TidListCreate(TidScanState *tidstate)
pfree(ipdatums);
pfree(ipnulls);
}
- else if (expr && IsA(expr, CurrentOfExpr))
+ else
{
- CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
ItemPointerData cursor_tid;
- if (execCurrentOf(cexpr, econtext,
+ Assert(tidexpr->cexpr);
+ if (execCurrentOf(tidexpr->cexpr, econtext,
RelationGetRelid(tidstate->ss.ss_currentRelation),
&cursor_tid))
{
@@ -178,11 +232,8 @@ TidListCreate(TidScanState *tidstate)
numAllocTids * sizeof(ItemPointerData));
}
tidList[numTids++] = cursor_tid;
- tidstate->tss_isCurrentOf = true;
}
}
- else
- elog(ERROR, "could not identify CTID expression");
}
/*
@@ -274,11 +325,15 @@ TidNext(TidScanState *node)
* First time through, compute the list of TIDs to be visited
*/
if (node->tss_TidList == NULL)
- TidListCreate(node);
+ TidListEval(node);
tidList = node->tss_TidList;
numTids = node->tss_NumTids;
+ /*
+ * We use node->tss_htup as the tuple pointer; note this can't just be a
+ * local variable here, as the scan tuple slot will keep a pointer to it.
+ */
tuple = &(node->tss_htup);
/*
@@ -469,21 +524,13 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &tidstate->ss.ps);
- tidstate->ss.ps.ps_TupFromTlist = false;
-
/*
* initialize child expressions
*/
- tidstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) tidstate);
- tidstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) tidstate);
-
- tidstate->tss_tidquals = (List *)
- ExecInitExpr((Expr *) node->tidquals,
- (PlanState *) tidstate);
+ tidstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
+
+ TidExprListCreate(tidstate);
/*
* tuple table initialization
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index 4caae34b97..28cc1e90f8 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -11,7 +11,7 @@
* (It's debatable whether the savings justifies carrying two plan node
* types, though.)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -133,9 +133,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
uniquestate->tempContext =
AllocSetContextCreate(CurrentMemoryContext,
"Unique",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/*
* Tuple table initialization
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index 9c03f8ae16..9ee776c4c3 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -4,7 +4,7 @@
* Support routines for scanning Values lists
* ("VALUES (...), (...), ..." in rangetable).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -120,7 +120,7 @@ ValuesNext(ValuesScanState *node)
* is a SubPlan, and there shouldn't be any (any subselects in the
* VALUES list should be InitPlans).
*/
- exprstatelist = (List *) ExecInitExpr((Expr *) exprlist, NULL);
+ exprstatelist = ExecInitExprList(exprlist, NULL);
/* parser should have checked all sublists are the same length */
Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
@@ -140,8 +140,7 @@ ValuesNext(ValuesScanState *node)
values[resind] = ExecEvalExpr(estate,
econtext,
- &isnull[resind],
- NULL);
+ &isnull[resind]);
/*
* We must force any R/W expanded datums to read-only state, in
@@ -243,12 +242,8 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
/*
* get info about values list
@@ -272,8 +267,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
scanstate->exprlists[i++] = (List *) lfirst(vtl);
}
- scanstate->ss.ps.ps_TupFromTlist = false;
-
/*
* Initialize result tuple type and projection info.
*/
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 0d512543d9..124db68b1f 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -24,7 +24,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -257,7 +257,7 @@ advance_windowaggregate(WindowAggState *winstate,
if (filter)
{
bool isnull;
- Datum res = ExecEvalExpr(filter, econtext, &isnull, NULL);
+ Datum res = ExecEvalExpr(filter, econtext, &isnull);
if (isnull || !DatumGetBool(res))
{
@@ -273,7 +273,7 @@ advance_windowaggregate(WindowAggState *winstate,
ExprState *argstate = (ExprState *) lfirst(arg);
fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
- &fcinfo->argnull[i], NULL);
+ &fcinfo->argnull[i]);
i++;
}
@@ -355,7 +355,7 @@ advance_windowaggregate(WindowAggState *winstate,
/*
* We must track the number of rows included in transValue, since to
- * remove the last input, advance_windowaggregate_base() musn't call the
+ * remove the last input, advance_windowaggregate_base() mustn't call the
* inverse transition function, but simply reset transValue back to its
* initial value.
*/
@@ -363,8 +363,10 @@ advance_windowaggregate(WindowAggState *winstate,
/*
* If pass-by-ref datatype, must copy the new value into aggcontext and
- * pfree the prior transValue. But if transfn returned a pointer to its
- * first input, we don't need to do anything.
+ * free the prior transValue. But if transfn returned a pointer to its
+ * first input, we don't need to do anything. Also, if transfn returned a
+ * pointer to a R/W expanded object that is already a child of the
+ * aggcontext, assume we can adopt that value without copying it.
*/
if (!peraggstate->transtypeByVal &&
DatumGetPointer(newVal) != DatumGetPointer(peraggstate->transValue))
@@ -372,12 +374,25 @@ advance_windowaggregate(WindowAggState *winstate,
if (!fcinfo->isnull)
{
MemoryContextSwitchTo(peraggstate->aggcontext);
- newVal = datumCopy(newVal,
- peraggstate->transtypeByVal,
- peraggstate->transtypeLen);
+ if (DatumIsReadWriteExpandedObject(newVal,
+ false,
+ peraggstate->transtypeLen) &&
+ MemoryContextGetParent(DatumGetEOHP(newVal)->eoh_context) == CurrentMemoryContext)
+ /* do nothing */ ;
+ else
+ newVal = datumCopy(newVal,
+ peraggstate->transtypeByVal,
+ peraggstate->transtypeLen);
}
if (!peraggstate->transValueIsNull)
- pfree(DatumGetPointer(peraggstate->transValue));
+ {
+ if (DatumIsReadWriteExpandedObject(peraggstate->transValue,
+ false,
+ peraggstate->transtypeLen))
+ DeleteExpandedObject(peraggstate->transValue);
+ else
+ pfree(DatumGetPointer(peraggstate->transValue));
+ }
}
MemoryContextSwitchTo(oldContext);
@@ -419,7 +434,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
if (filter)
{
bool isnull;
- Datum res = ExecEvalExpr(filter, econtext, &isnull, NULL);
+ Datum res = ExecEvalExpr(filter, econtext, &isnull);
if (isnull || !DatumGetBool(res))
{
@@ -435,7 +450,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
ExprState *argstate = (ExprState *) lfirst(arg);
fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
- &fcinfo->argnull[i], NULL);
+ &fcinfo->argnull[i]);
i++;
}
@@ -514,8 +529,10 @@ advance_windowaggregate_base(WindowAggState *winstate,
/*
* If pass-by-ref datatype, must copy the new value into aggcontext and
- * pfree the prior transValue. But if invtransfn returned a pointer to
- * its first input, we don't need to do anything.
+ * free the prior transValue. But if invtransfn returned a pointer to its
+ * first input, we don't need to do anything. Also, if invtransfn
+ * returned a pointer to a R/W expanded object that is already a child of
+ * the aggcontext, assume we can adopt that value without copying it.
*
* Note: the checks for null values here will never fire, but it seems
* best to have this stanza look just like advance_windowaggregate.
@@ -526,12 +543,25 @@ advance_windowaggregate_base(WindowAggState *winstate,
if (!fcinfo->isnull)
{
MemoryContextSwitchTo(peraggstate->aggcontext);
- newVal = datumCopy(newVal,
- peraggstate->transtypeByVal,
- peraggstate->transtypeLen);
+ if (DatumIsReadWriteExpandedObject(newVal,
+ false,
+ peraggstate->transtypeLen) &&
+ MemoryContextGetParent(DatumGetEOHP(newVal)->eoh_context) == CurrentMemoryContext)
+ /* do nothing */ ;
+ else
+ newVal = datumCopy(newVal,
+ peraggstate->transtypeByVal,
+ peraggstate->transtypeLen);
}
if (!peraggstate->transValueIsNull)
- pfree(DatumGetPointer(peraggstate->transValue));
+ {
+ if (DatumIsReadWriteExpandedObject(peraggstate->transValue,
+ false,
+ peraggstate->transtypeLen))
+ DeleteExpandedObject(peraggstate->transValue);
+ else
+ pfree(DatumGetPointer(peraggstate->transValue));
+ }
}
MemoryContextSwitchTo(oldContext);
@@ -569,7 +599,9 @@ finalize_windowaggregate(WindowAggState *winstate,
numFinalArgs,
perfuncstate->winCollation,
(void *) winstate, NULL);
- fcinfo.arg[0] = peraggstate->transValue;
+ fcinfo.arg[0] = MakeExpandedObjectReadOnly(peraggstate->transValue,
+ peraggstate->transValueIsNull,
+ peraggstate->transtypeLen);
fcinfo.argnull[0] = peraggstate->transValueIsNull;
anynull = peraggstate->transValueIsNull;
@@ -597,6 +629,7 @@ finalize_windowaggregate(WindowAggState *winstate,
}
else
{
+ /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
*result = peraggstate->transValue;
*isnull = peraggstate->transValueIsNull;
}
@@ -1552,15 +1585,12 @@ update_frametailpos(WindowObject winobj, TupleTableSlot *slot)
* ExecWindowAgg receives tuples from its outer subplan and
* stores them into a tuplestore, then processes window functions.
* This node doesn't reduce nor qualify any row so the number of
- * returned rows is exactly the same as its outer subplan's result
- * (ignoring the case of SRFs in the targetlist, that is).
+ * returned rows is exactly the same as its outer subplan's result.
* -----------------
*/
TupleTableSlot *
ExecWindowAgg(WindowAggState *winstate)
{
- TupleTableSlot *result;
- ExprDoneCond isDone;
ExprContext *econtext;
int i;
int numfuncs;
@@ -1569,23 +1599,6 @@ ExecWindowAgg(WindowAggState *winstate)
return NULL;
/*
- * Check to see if we're still projecting out tuples from a previous
- * output tuple (because there is a function-returning-set in the
- * projection expressions). If so, try to project another one.
- */
- if (winstate->ss.ps.ps_TupFromTlist)
- {
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return result;
- /* Done with that source tuple... */
- winstate->ss.ps.ps_TupFromTlist = false;
- }
-
- /*
* Compute frame offset values, if any, during first call.
*/
if (winstate->all_first)
@@ -1602,8 +1615,7 @@ ExecWindowAgg(WindowAggState *winstate)
Assert(winstate->startOffset != NULL);
value = ExecEvalExprSwitchContext(winstate->startOffset,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
@@ -1628,8 +1640,7 @@ ExecWindowAgg(WindowAggState *winstate)
Assert(winstate->endOffset != NULL);
value = ExecEvalExprSwitchContext(winstate->endOffset,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
@@ -1652,7 +1663,6 @@ ExecWindowAgg(WindowAggState *winstate)
winstate->all_first = false;
}
-restart:
if (winstate->buffer == NULL)
{
/* Initialize for first partition and set current row = 0 */
@@ -1744,17 +1754,8 @@ restart:
* evaluated with respect to that row.
*/
econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
- result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
-
- if (isDone == ExprEndResult)
- {
- /* SRF in tlist returned no rows, so advance to next input tuple */
- goto restart;
- }
- winstate->ss.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
+ return ExecProject(winstate->ss.ps.ps_ProjInfo);
}
/* -----------------
@@ -1802,10 +1803,8 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
/* Create long-lived context for storage of partition-local memory etc */
winstate->partcontext =
AllocSetContextCreate(CurrentMemoryContext,
- "WindowAgg_Partition",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ "WindowAgg Partition",
+ ALLOCSET_DEFAULT_SIZES);
/*
* Create mid-lived context for aggregate trans values etc.
@@ -1815,10 +1814,8 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
*/
winstate->aggcontext =
AllocSetContextCreate(CurrentMemoryContext,
- "WindowAgg_Aggregates",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ "WindowAgg Aggregates",
+ ALLOCSET_DEFAULT_SIZES);
/*
* tuple table initialization
@@ -1830,16 +1827,12 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate);
winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate);
- winstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) winstate);
-
/*
* WindowAgg nodes never have quals, since they can only occur at the
* logical top level of a query (ie, after any WHERE or HAVING filters)
*/
Assert(node->plan.qual == NIL);
- winstate->ss.ps.qual = NIL;
+ winstate->ss.ps.qual = NULL;
/*
* initialize child nodes
@@ -1868,8 +1861,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
ExecAssignResultTypeFromTL(&winstate->ss.ps);
ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
- winstate->ss.ps.ps_TupFromTlist = false;
-
/* Set up data for comparing tuples */
if (node->partNumCols > 0)
winstate->partEqfunctions = execTuplesMatchPrepare(node->partNumCols,
@@ -1900,7 +1891,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
foreach(l, winstate->funcs)
{
WindowFuncExprState *wfuncstate = (WindowFuncExprState *) lfirst(l);
- WindowFunc *wfunc = (WindowFunc *) wfuncstate->xprstate.expr;
+ WindowFunc *wfunc = wfuncstate->wfunc;
WindowStatePerFunc perfuncstate;
AclResult aclresult;
int i;
@@ -2062,8 +2053,6 @@ ExecReScanWindowAgg(WindowAggState *node)
ExprContext *econtext = node->ss.ps.ps_ExprContext;
node->all_done = false;
-
- node->ss.ps.ps_TupFromTlist = false;
node->all_first = true;
/* release tuplestore et al */
@@ -2223,7 +2212,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
numArguments,
0, /* no ordered-set window functions yet */
false, /* no variadic window functions yet */
- wfunc->wintype,
+ aggtranstype,
wfunc->inputcollid,
transfn_oid,
invtransfn_oid,
@@ -2322,10 +2311,8 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
if (OidIsValid(invtransfn_oid))
peraggstate->aggcontext =
AllocSetContextCreate(CurrentMemoryContext,
- "WindowAgg_AggregatePrivate",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ "WindowAgg Per Aggregate",
+ ALLOCSET_DEFAULT_SIZES);
else
peraggstate->aggcontext = winstate->aggcontext;
@@ -2686,7 +2673,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
}
econtext->ecxt_outertuple = slot;
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
- econtext, isnull, NULL);
+ econtext, isnull);
}
}
@@ -2785,7 +2772,7 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno,
}
econtext->ecxt_outertuple = slot;
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
- econtext, isnull, NULL);
+ econtext, isnull);
}
}
@@ -2815,5 +2802,5 @@ WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
- econtext, isnull, NULL);
+ econtext, isnull);
}
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index cfed6e6329..d7616be065 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -3,7 +3,7 @@
* nodeWorktablescan.c
* routines to handle WorkTableScan nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -95,8 +95,8 @@ ExecWorkTableScan(WorkTableScanState *node)
param = &(estate->es_param_exec_vals[plan->wtParam]);
Assert(param->execPlan == NULL);
Assert(!param->isnull);
- node->rustate = (RecursiveUnionState *) DatumGetPointer(param->value);
- Assert(node->rustate && IsA(node->rustate, RecursiveUnionState));
+ node->rustate = castNode(RecursiveUnionState, DatumGetPointer(param->value));
+ Assert(node->rustate);
/*
* The scan tuple type (ie, the rowtype we expect to find in the work
@@ -156,12 +156,8 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
/*
* initialize child expressions
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
/*
* tuple table initialization
@@ -174,8 +170,6 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
*/
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
- scanstate->ss.ps.ps_TupFromTlist = false;
-
return scanstate;
}
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 0a3c65e6f7..ac0870c22d 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -3,7 +3,7 @@
* spi.c
* Server Programming Interface
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -44,8 +44,7 @@ int SPI_result;
static _SPI_connection *_SPI_stack = NULL;
static _SPI_connection *_SPI_current = NULL;
static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
-static int _SPI_connected = -1;
-static int _SPI_curid = -1;
+static int _SPI_connected = -1; /* current stack index */
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
ParamListInfo paramLI, bool read_only);
@@ -91,13 +90,7 @@ SPI_connect(void)
{
int newdepth;
- /*
- * When procedure called by Executor _SPI_curid expected to be equal to
- * _SPI_connected
- */
- if (_SPI_curid != _SPI_connected)
- return SPI_ERROR_CONNECT;
-
+ /* Enlarge stack if necessary */
if (_SPI_stack == NULL)
{
if (_SPI_connected != -1 || _SPI_stack_depth != 0)
@@ -122,9 +115,7 @@ SPI_connect(void)
}
}
- /*
- * We're entering procedure where _SPI_curid == _SPI_connected - 1
- */
+ /* Enter new stack level */
_SPI_connected++;
Assert(_SPI_connected >= 0 && _SPI_connected < _SPI_stack_depth);
@@ -136,6 +127,7 @@ SPI_connect(void)
_SPI_current->procCxt = NULL; /* in case we fail to create 'em */
_SPI_current->execCxt = NULL;
_SPI_current->connectSubid = GetCurrentSubTransactionId();
+ _SPI_current->queryEnv = NULL;
/*
* Create memory contexts for this procedure
@@ -147,14 +139,10 @@ SPI_connect(void)
*/
_SPI_current->procCxt = AllocSetContextCreate(TopTransactionContext,
"SPI Proc",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
_SPI_current->execCxt = AllocSetContextCreate(TopTransactionContext,
"SPI Exec",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
/* ... and switch to procedure's context */
_SPI_current->savedcxt = MemoryContextSwitchTo(_SPI_current->procCxt);
@@ -187,14 +175,9 @@ SPI_finish(void)
SPI_lastoid = InvalidOid;
SPI_tuptable = NULL;
- /*
- * After _SPI_begin_call _SPI_connected == _SPI_curid. Now we are closing
- * connection to SPI and returning to upper Executor and so _SPI_connected
- * must be equal to _SPI_curid.
- */
+ /* Exit stack level */
_SPI_connected--;
- _SPI_curid--;
- if (_SPI_connected == -1)
+ if (_SPI_connected < 0)
_SPI_current = NULL;
else
_SPI_current = &(_SPI_stack[_SPI_connected]);
@@ -221,7 +204,7 @@ AtEOXact_SPI(bool isCommit)
_SPI_current = _SPI_stack = NULL;
_SPI_stack_depth = 0;
- _SPI_connected = _SPI_curid = -1;
+ _SPI_connected = -1;
SPI_processed = 0;
SPI_lastoid = InvalidOid;
SPI_tuptable = NULL;
@@ -267,8 +250,7 @@ AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
* be already gone.
*/
_SPI_connected--;
- _SPI_curid = _SPI_connected;
- if (_SPI_connected == -1)
+ if (_SPI_connected < 0)
_SPI_current = NULL;
else
_SPI_current = &(_SPI_stack[_SPI_connected]);
@@ -322,53 +304,6 @@ AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
}
-/* Pushes SPI stack to allow recursive SPI calls */
-void
-SPI_push(void)
-{
- _SPI_curid++;
-}
-
-/* Pops SPI stack to allow recursive SPI calls */
-void
-SPI_pop(void)
-{
- _SPI_curid--;
-}
-
-/* Conditional push: push only if we're inside a SPI procedure */
-bool
-SPI_push_conditional(void)
-{
- bool pushed = (_SPI_curid != _SPI_connected);
-
- if (pushed)
- {
- _SPI_curid++;
- /* We should now be in a state where SPI_connect would succeed */
- Assert(_SPI_curid == _SPI_connected);
- }
- return pushed;
-}
-
-/* Conditional pop: pop only if SPI_push_conditional pushed */
-void
-SPI_pop_conditional(bool pushed)
-{
- /* We should be in a state where SPI_connect would succeed */
- Assert(_SPI_curid == _SPI_connected);
- if (pushed)
- _SPI_curid--;
-}
-
-/* Restore state of SPI stack after aborting a subtransaction */
-void
-SPI_restore_connection(void)
-{
- Assert(_SPI_connected >= 0);
- _SPI_curid = _SPI_connected - 1;
-}
-
#ifdef PGXC
/* SPI_execute_direct:
* Runs the 'remote_sql' query string on the node 'nodename'
@@ -433,7 +368,7 @@ SPI_execute(const char *src, bool read_only, long tcount)
memset(&plan, 0, sizeof(_SPI_plan));
plan.magic = _SPI_PLAN_MAGIC;
- plan.cursor_options = 0;
+ plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
_SPI_prepare_oneshot_plan(src, &plan);
@@ -577,7 +512,7 @@ SPI_execute_with_args(const char *src,
memset(&plan, 0, sizeof(_SPI_plan));
plan.magic = _SPI_PLAN_MAGIC;
- plan.cursor_options = 0;
+ plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
plan.nargs = nargs;
plan.argtypes = argtypes;
plan.parserSetup = NULL;
@@ -748,7 +683,7 @@ SPI_freeplan(SPIPlanPtr plan)
HeapTuple
SPI_copytuple(HeapTuple tuple)
{
- MemoryContext oldcxt = NULL;
+ MemoryContext oldcxt;
HeapTuple ctuple;
if (tuple == NULL)
@@ -757,17 +692,17 @@ SPI_copytuple(HeapTuple tuple)
return NULL;
}
- if (_SPI_curid + 1 == _SPI_connected) /* connected */
+ if (_SPI_current == NULL)
{
- if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
- elog(ERROR, "SPI stack corrupted");
- oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return NULL;
}
+ oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
+
ctuple = heap_copytuple(tuple);
- if (oldcxt)
- MemoryContextSwitchTo(oldcxt);
+ MemoryContextSwitchTo(oldcxt);
return ctuple;
}
@@ -775,7 +710,7 @@ SPI_copytuple(HeapTuple tuple)
HeapTupleHeader
SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)
{
- MemoryContext oldcxt = NULL;
+ MemoryContext oldcxt;
HeapTupleHeader dtup;
if (tuple == NULL || tupdesc == NULL)
@@ -784,22 +719,22 @@ SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)
return NULL;
}
+ if (_SPI_current == NULL)
+ {
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return NULL;
+ }
+
/* For RECORD results, make sure a typmod has been assigned */
if (tupdesc->tdtypeid == RECORDOID &&
tupdesc->tdtypmod < 0)
assign_record_type_typmod(tupdesc);
- if (_SPI_curid + 1 == _SPI_connected) /* connected */
- {
- if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
- elog(ERROR, "SPI stack corrupted");
- oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
- }
+ oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
dtup = DatumGetHeapTupleHeader(heap_copy_tuple_as_datum(tuple, tupdesc));
- if (oldcxt)
- MemoryContextSwitchTo(oldcxt);
+ MemoryContextSwitchTo(oldcxt);
return dtup;
}
@@ -808,7 +743,7 @@ HeapTuple
SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
Datum *Values, const char *Nulls)
{
- MemoryContext oldcxt = NULL;
+ MemoryContext oldcxt;
HeapTuple mtuple;
int numberOfAttributes;
Datum *v;
@@ -821,13 +756,16 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
return NULL;
}
- if (_SPI_curid + 1 == _SPI_connected) /* connected */
+ if (_SPI_current == NULL)
{
- if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
- elog(ERROR, "SPI stack corrupted");
- oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return NULL;
}
+
+ oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
+
SPI_result = 0;
+
numberOfAttributes = rel->rd_att->natts;
v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
n = (bool *) palloc(numberOfAttributes * sizeof(bool));
@@ -871,8 +809,7 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
pfree(v);
pfree(n);
- if (oldcxt)
- MemoryContextSwitchTo(oldcxt);
+ MemoryContextSwitchTo(oldcxt);
return mtuple;
}
@@ -885,7 +822,8 @@ SPI_fnumber(TupleDesc tupdesc, const char *fname)
for (res = 0; res < tupdesc->natts; res++)
{
- if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0)
+ if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0 &&
+ !tupdesc->attrs[res]->attisdropped)
return res + 1;
}
@@ -1040,22 +978,10 @@ SPI_getnspname(Relation rel)
void *
SPI_palloc(Size size)
{
- MemoryContext oldcxt = NULL;
- void *pointer;
-
- if (_SPI_curid + 1 == _SPI_connected) /* connected */
- {
- if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
- elog(ERROR, "SPI stack corrupted");
- oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
- }
+ if (_SPI_current == NULL)
+ elog(ERROR, "SPI_palloc called while not connected to SPI");
- pointer = palloc(size);
-
- if (oldcxt)
- MemoryContextSwitchTo(oldcxt);
-
- return pointer;
+ return MemoryContextAlloc(_SPI_current->savedcxt, size);
}
void *
@@ -1075,20 +1001,17 @@ SPI_pfree(void *pointer)
Datum
SPI_datumTransfer(Datum value, bool typByVal, int typLen)
{
- MemoryContext oldcxt = NULL;
+ MemoryContext oldcxt;
Datum result;
- if (_SPI_curid + 1 == _SPI_connected) /* connected */
- {
- if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
- elog(ERROR, "SPI stack corrupted");
- oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
- }
+ if (_SPI_current == NULL)
+ elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
+
+ oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
result = datumTransfer(value, typByVal, typLen);
- if (oldcxt)
- MemoryContextSwitchTo(oldcxt);
+ MemoryContextSwitchTo(oldcxt);
return result;
}
@@ -1110,17 +1033,12 @@ SPI_freetuptable(SPITupleTable *tuptable)
return;
/*
- * Since this function might be called during error recovery, it seems
- * best not to insist that the caller be actively connected. We just
- * search the topmost SPI context, connected or not.
+ * Search only the topmost SPI context for a matching tuple table.
*/
- if (_SPI_connected >= 0)
+ if (_SPI_current != NULL)
{
slist_mutable_iter siter;
- if (_SPI_current != &(_SPI_stack[_SPI_connected]))
- elog(ERROR, "SPI stack corrupted");
-
/* find tuptable in active list, then remove it */
slist_foreach_modify(siter, &_SPI_current->tuptables)
{
@@ -1228,13 +1146,9 @@ SPI_cursor_open_with_args(const char *name,
/* We needn't copy the plan; SPI_cursor_open_internal will do so */
- /* Adjust stack so that SPI_cursor_open_internal doesn't complain */
- _SPI_curid--;
-
result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
/* And clean up */
- _SPI_curid++;
_SPI_end_call(true);
return result;
@@ -1337,12 +1251,9 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
*/
/* Replan if needed, and increment plan refcount for portal */
- cplan = GetCachedPlan(plansource, paramLI, false);
+ cplan = GetCachedPlan(plansource, paramLI, false, _SPI_current->queryEnv);
stmt_list = cplan->stmt_list;
- /* Pop the error context stack */
- error_context_stack = spierrcontext.previous;
-
if (!plan->saved)
{
/*
@@ -1376,9 +1287,9 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
{
if (list_length(stmt_list) == 1 &&
- IsA((Node *) linitial(stmt_list), PlannedStmt) &&
- ((PlannedStmt *) linitial(stmt_list))->rowMarks == NIL &&
- ExecSupportsBackwardScan(((PlannedStmt *) linitial(stmt_list))->planTree))
+ linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
+ linitial_node(PlannedStmt, stmt_list)->rowMarks == NIL &&
+ ExecSupportsBackwardScan(linitial_node(PlannedStmt, stmt_list)->planTree))
portal->cursorOptions |= CURSOR_OPT_SCROLL;
else
portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
@@ -1392,14 +1303,17 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
if (portal->cursorOptions & CURSOR_OPT_SCROLL)
{
if (list_length(stmt_list) == 1 &&
- IsA((Node *) linitial(stmt_list), PlannedStmt) &&
- ((PlannedStmt *) linitial(stmt_list))->rowMarks != NIL)
+ linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
+ linitial_node(PlannedStmt, stmt_list)->rowMarks != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
errdetail("Scrollable cursors must be READ ONLY.")));
}
+ /* Make current query environment available to portal at execution time. */
+ portal->queryEnv = _SPI_current->queryEnv;
+
/*
* If told to be read-only, or in parallel mode, verify that this query is
* in fact read-only. This can't be done earlier because we need to look
@@ -1414,7 +1328,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
foreach(lc, stmt_list)
{
- Node *pstmt = (Node *) lfirst(lc);
+ PlannedStmt *pstmt = lfirst_node(PlannedStmt, lc);
if (!CommandIsReadOnly(pstmt))
{
@@ -1423,9 +1337,9 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function",
- CreateCommandTag(pstmt))));
+ CreateCommandTag((Node *) pstmt))));
else
- PreventCommandIfParallelMode(CreateCommandTag(pstmt));
+ PreventCommandIfParallelMode(CreateCommandTag((Node *) pstmt));
}
}
}
@@ -1458,6 +1372,9 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
Assert(portal->strategy != PORTAL_MULTI_QUERY);
+ /* Pop the error context stack */
+ error_context_stack = spierrcontext.previous;
+
/* Pop the SPI stack */
_SPI_end_call(true);
@@ -1676,6 +1593,10 @@ SPI_result_code_string(int code)
return "SPI_ERROR_NOOUTFUNC";
case SPI_ERROR_TYPUNKNOWN:
return "SPI_ERROR_TYPUNKNOWN";
+ case SPI_ERROR_REL_DUPLICATE:
+ return "SPI_ERROR_REL_DUPLICATE";
+ case SPI_ERROR_REL_NOT_FOUND:
+ return "SPI_ERROR_REL_NOT_FOUND";
case SPI_OK_CONNECT:
return "SPI_OK_CONNECT";
case SPI_OK_FINISH:
@@ -1704,6 +1625,10 @@ SPI_result_code_string(int code)
return "SPI_OK_UPDATE_RETURNING";
case SPI_OK_REWRITTEN:
return "SPI_OK_REWRITTEN";
+ case SPI_OK_REL_REGISTER:
+ return "SPI_OK_REL_REGISTER";
+ case SPI_OK_REL_UNREGISTER:
+ return "SPI_OK_REL_UNREGISTER";
}
/* Unrecognized code ... return something useful ... */
sprintf(buf, "Unrecognized SPI code %d", code);
@@ -1714,7 +1639,7 @@ SPI_result_code_string(int code)
* SPI_plan_get_plan_sources --- get a SPI plan's underlying list of
* CachedPlanSources.
*
- * This is exported so that pl/pgsql can use it (this beats letting pl/pgsql
+ * This is exported so that PL/pgSQL can use it (this beats letting PL/pgSQL
* look directly into the SPIPlan for itself). It's not documented in
* spi.sgml because we'd just as soon not have too many places using this.
*/
@@ -1730,7 +1655,7 @@ SPI_plan_get_plan_sources(SPIPlanPtr plan)
* if the SPI plan contains exactly one CachedPlanSource. If not,
* return NULL. Caller is responsible for doing ReleaseCachedPlan().
*
- * This is exported so that pl/pgsql can use it (this beats letting pl/pgsql
+ * This is exported so that PL/pgSQL can use it (this beats letting PL/pgSQL
* look directly into the SPIPlan for itself). It's not documented in
* spi.sgml because we'd just as soon not have too many places using this.
*/
@@ -1759,7 +1684,8 @@ SPI_plan_get_cached_plan(SPIPlanPtr plan)
error_context_stack = &spierrcontext;
/* Get the generic plan for the query */
- cplan = GetCachedPlan(plansource, NULL, plan->saved);
+ cplan = GetCachedPlan(plansource, NULL, plan->saved,
+ _SPI_current->queryEnv);
Assert(cplan == plansource->gplan);
/* Pop the error context stack */
@@ -1783,14 +1709,8 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
MemoryContext oldcxt;
MemoryContext tuptabcxt;
- /*
- * When called by Executor _SPI_curid expected to be equal to
- * _SPI_connected
- */
- if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
- elog(ERROR, "improper call to spi_dest_startup");
- if (_SPI_current != &(_SPI_stack[_SPI_curid]))
- elog(ERROR, "SPI stack corrupted");
+ if (_SPI_current == NULL)
+ elog(ERROR, "spi_dest_startup called while not connected to SPI");
if (_SPI_current->tuptable != NULL)
elog(ERROR, "improper call to spi_dest_startup");
@@ -1801,9 +1721,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
tuptabcxt = AllocSetContextCreate(CurrentMemoryContext,
"SPI TupTable",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
MemoryContextSwitchTo(tuptabcxt);
_SPI_current->tuptable = tuptable = (SPITupleTable *)
@@ -1837,14 +1755,8 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self)
SPITupleTable *tuptable;
MemoryContext oldcxt;
- /*
- * When called by Executor _SPI_curid expected to be equal to
- * _SPI_connected
- */
- if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
- elog(ERROR, "improper call to spi_printtup");
- if (_SPI_current != &(_SPI_stack[_SPI_curid]))
- elog(ERROR, "SPI stack corrupted");
+ if (_SPI_current == NULL)
+ elog(ERROR, "spi_printtup called while not connected to SPI");
tuptable = _SPI_current->tuptable;
if (tuptable == NULL)
@@ -1939,7 +1851,7 @@ _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree,
forboth(list_item, raw_parsetree_list, list_item2, querysource_list)
{
- Node *parsetree = (Node *) lfirst(list_item);
+ RawStmt *parsetree = lfirst_node(RawStmt, list_item);
char *querysource = (char *) lfirst (list_item2);
List *stmt_list;
CachedPlanSource *plansource;
@@ -1953,7 +1865,7 @@ _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree,
#ifdef PGXC
NULL,
#endif
- CreateCommandTag(parsetree));
+ CreateCommandTag(parsetree->stmt));
/*
* Parameter datatypes are driven by parserSetup hook if provided,
@@ -1965,14 +1877,16 @@ _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree,
stmt_list = pg_analyze_and_rewrite_params(parsetree,
querysource,
plan->parserSetup,
- plan->parserSetupArg);
+ plan->parserSetupArg,
+ _SPI_current->queryEnv);
}
else
{
stmt_list = pg_analyze_and_rewrite(parsetree,
querysource,
plan->argtypes,
- plan->nargs);
+ plan->nargs,
+ _SPI_current->queryEnv);
}
/* Finish filling in the CachedPlanSource */
@@ -2046,13 +1960,14 @@ _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
forboth(list_item, raw_parsetree_list, list_item2, querysource_list)
{
- Node *parsetree = (Node *) lfirst(list_item);
+ RawStmt *parsetree = lfirst_node(RawStmt, list_item);
char *querysource = (char *) lfirst (list_item2);
CachedPlanSource *plansource;
+
plansource = CreateOneShotCachedPlan(parsetree,
querysource,
- CreateCommandTag(parsetree));
+ CreateCommandTag(parsetree->stmt));
plancache_list = lappend(plancache_list, plansource);
}
@@ -2147,7 +2062,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
*/
if (plan->oneshot)
{
- Node *parsetree = plansource->raw_parse_tree;
+ RawStmt *parsetree = plansource->raw_parse_tree;
const char *src = plansource->query_string;
List *stmt_list;
@@ -2163,14 +2078,16 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
stmt_list = pg_analyze_and_rewrite_params(parsetree,
src,
plan->parserSetup,
- plan->parserSetupArg);
+ plan->parserSetupArg,
+ _SPI_current->queryEnv);
}
else
{
stmt_list = pg_analyze_and_rewrite(parsetree,
src,
plan->argtypes,
- plan->nargs);
+ plan->nargs,
+ _SPI_current->queryEnv);
}
/* Finish filling in the CachedPlanSource */
@@ -2189,7 +2106,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
* Replan if needed, and increment plan refcount. If it's a saved
* plan, the refcount must be backed by the CurrentResourceOwner.
*/
- cplan = GetCachedPlan(plansource, paramLI, plan->saved);
+ cplan = GetCachedPlan(plansource, paramLI, plan->saved, _SPI_current->queryEnv);
stmt_list = cplan->stmt_list;
/*
@@ -2206,26 +2123,19 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
foreach(lc2, stmt_list)
{
- Node *stmt = (Node *) lfirst(lc2);
- bool canSetTag;
+ PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
+ bool canSetTag = stmt->canSetTag;
DestReceiver *dest;
_SPI_current->processed = 0;
_SPI_current->lastoid = InvalidOid;
_SPI_current->tuptable = NULL;
- if (IsA(stmt, PlannedStmt))
- {
- canSetTag = ((PlannedStmt *) stmt)->canSetTag;
- }
- else
+ if (stmt->utilityStmt)
{
- /* utilities are canSetTag if only thing in list */
- canSetTag = (list_length(stmt_list) == 1);
-
- if (IsA(stmt, CopyStmt))
+ if (IsA(stmt->utilityStmt, CopyStmt))
{
- CopyStmt *cstmt = (CopyStmt *) stmt;
+ CopyStmt *cstmt = (CopyStmt *) stmt->utilityStmt;
if (cstmt->filename == NULL)
{
@@ -2233,7 +2143,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
goto fail;
}
}
- else if (IsA(stmt, TransactionStmt))
+ else if (IsA(stmt->utilityStmt, TransactionStmt))
{
my_res = SPI_ERROR_TRANSACTION;
goto fail;
@@ -2245,10 +2155,10 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function",
- CreateCommandTag(stmt))));
+ CreateCommandTag((Node *) stmt))));
if (IsInParallelMode() && !CommandIsReadOnly(stmt))
- PreventCommandIfParallelMode(CreateCommandTag(stmt));
+ PreventCommandIfParallelMode(CreateCommandTag((Node *) stmt));
/*
* If not read-only mode, advance the command counter before each
@@ -2262,8 +2172,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
dest = CreateDestReceiver(canSetTag ? DestSPI : DestNone);
- if (IsA(stmt, PlannedStmt) &&
- ((PlannedStmt *) stmt)->utilityStmt == NULL)
+ if (stmt->utilityStmt == NULL)
{
QueryDesc *qdesc;
Snapshot snap;
@@ -2273,11 +2182,12 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
else
snap = InvalidSnapshot;
- qdesc = CreateQueryDesc((PlannedStmt *) stmt,
+ qdesc = CreateQueryDesc(stmt,
plansource->query_string,
snap, crosscheck_snapshot,
dest,
- paramLI, 0);
+ paramLI, _SPI_current->queryEnv,
+ 0);
res = _SPI_pquery(qdesc, fire_triggers,
canSetTag ? tcount : 0);
FreeQueryDesc(qdesc);
@@ -2290,6 +2200,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
plansource->query_string,
PROCESS_UTILITY_QUERY,
paramLI,
+ _SPI_current->queryEnv,
dest,
#ifdef PGXC
false,
@@ -2307,9 +2218,9 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
* Some utility statements return a row count, even though the
* tuples are not returned to the caller.
*/
- if (IsA(stmt, CreateTableAsStmt))
+ if (IsA(stmt->utilityStmt, CreateTableAsStmt))
{
- CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt;
+ CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
if (strncmp(completionTag, "SELECT ", 7) == 0)
_SPI_current->processed =
@@ -2332,7 +2243,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
if (ctastmt->is_select_into)
res = SPI_OK_SELINTO;
}
- else if (IsA(stmt, CopyStmt))
+ else if (IsA(stmt->utilityStmt, CopyStmt))
{
Assert(strncmp(completionTag, "COPY ", 5) == 0);
_SPI_current->processed = pg_strtouint64(completionTag + 5,
@@ -2461,7 +2372,6 @@ _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
switch (operation)
{
case CMD_SELECT:
- Assert(queryDesc->plannedstmt->utilityStmt == NULL);
if (queryDesc->dest->mydest != DestSPI)
{
/* Don't return SPI_OK_SELECT if we're discarding result */
@@ -2505,7 +2415,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
ExecutorStart(queryDesc, eflags);
- ExecutorRun(queryDesc, ForwardScanDirection, tcount);
+ ExecutorRun(queryDesc, ForwardScanDirection, tcount, true);
_SPI_current->processed = queryDesc->estate->es_processed;
_SPI_current->lastoid = queryDesc->estate->es_lastoid;
@@ -2629,11 +2539,8 @@ _SPI_procmem(void)
static int
_SPI_begin_call(bool execmem)
{
- if (_SPI_curid + 1 != _SPI_connected)
+ if (_SPI_current == NULL)
return SPI_ERROR_UNCONNECTED;
- _SPI_curid++;
- if (_SPI_current != &(_SPI_stack[_SPI_curid]))
- elog(ERROR, "SPI stack corrupted");
if (execmem) /* switch to the Executor memory context */
_SPI_execmem();
@@ -2649,11 +2556,6 @@ _SPI_begin_call(bool execmem)
static int
_SPI_end_call(bool procmem)
{
- /*
- * We're returning to procedure where _SPI_curid == _SPI_connected - 1
- */
- _SPI_curid--;
-
if (procmem) /* switch to the procedure memory context */
{
_SPI_procmem();
@@ -2705,14 +2607,11 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
/*
* Create a memory context for the plan, underneath the procedure context.
- * We don't expect the plan to be very large, so use smaller-than-default
- * alloc parameters.
+ * We don't expect the plan to be very large.
*/
plancxt = AllocSetContextCreate(parentcxt,
"SPI Plan",
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(plancxt);
/* Copy the SPI_plan struct and subsidiary data into the new context */
@@ -2779,9 +2678,7 @@ _SPI_save_plan(SPIPlanPtr plan)
*/
plancxt = AllocSetContextCreate(CurrentMemoryContext,
"SPI Plan",
- ALLOCSET_SMALL_MINSIZE,
- ALLOCSET_SMALL_INITSIZE,
- ALLOCSET_SMALL_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(plancxt);
/* Copy the SPI plan into its own context */
@@ -2832,3 +2729,133 @@ _SPI_save_plan(SPIPlanPtr plan)
return newplan;
}
+
+/*
+ * Internal lookup of ephemeral named relation by name.
+ */
+static EphemeralNamedRelation
+_SPI_find_ENR_by_name(const char *name)
+{
+ /* internal static function; any error is bug in SPI itself */
+ Assert(name != NULL);
+
+ /* fast exit if no tuplestores have been added */
+ if (_SPI_current->queryEnv == NULL)
+ return NULL;
+
+ return get_ENR(_SPI_current->queryEnv, name);
+}
+
+/*
+ * Register an ephemeral named relation for use by the planner and executor on
+ * subsequent calls using this SPI connection.
+ */
+int
+SPI_register_relation(EphemeralNamedRelation enr)
+{
+ EphemeralNamedRelation match;
+ int res;
+
+ if (enr == NULL || enr->md.name == NULL)
+ return SPI_ERROR_ARGUMENT;
+
+ res = _SPI_begin_call(false); /* keep current memory context */
+ if (res < 0)
+ return res;
+
+ match = _SPI_find_ENR_by_name(enr->md.name);
+ if (match)
+ res = SPI_ERROR_REL_DUPLICATE;
+ else
+ {
+ if (_SPI_current->queryEnv == NULL)
+ _SPI_current->queryEnv = create_queryEnv();
+
+ register_ENR(_SPI_current->queryEnv, enr);
+ res = SPI_OK_REL_REGISTER;
+ }
+
+ _SPI_end_call(false);
+
+ return res;
+}
+
+/*
+ * Unregister an ephemeral named relation by name. This will probably be a
+ * rarely used function, since SPI_finish will clear it automatically.
+ */
+int
+SPI_unregister_relation(const char *name)
+{
+ EphemeralNamedRelation match;
+ int res;
+
+ if (name == NULL)
+ return SPI_ERROR_ARGUMENT;
+
+ res = _SPI_begin_call(false); /* keep current memory context */
+ if (res < 0)
+ return res;
+
+ match = _SPI_find_ENR_by_name(name);
+ if (match)
+ {
+ unregister_ENR(_SPI_current->queryEnv, match->md.name);
+ res = SPI_OK_REL_UNREGISTER;
+ }
+ else
+ res = SPI_ERROR_REL_NOT_FOUND;
+
+ _SPI_end_call(false);
+
+ return res;
+}
+
+/*
+ * Register the transient relations from 'tdata' using this SPI connection.
+ * This should be called by PL implementations' trigger handlers after
+ * connecting, in order to make transition tables visible to any queries run
+ * in this connection.
+ */
+int
+SPI_register_trigger_data(TriggerData *tdata)
+{
+ if (tdata == NULL)
+ return SPI_ERROR_ARGUMENT;
+
+ if (tdata->tg_newtable)
+ {
+ EphemeralNamedRelation enr =
+ palloc(sizeof(EphemeralNamedRelationData));
+ int rc;
+
+ enr->md.name = tdata->tg_trigger->tgnewtable;
+ enr->md.reliddesc = tdata->tg_relation->rd_id;
+ enr->md.tupdesc = NULL;
+ enr->md.enrtype = ENR_NAMED_TUPLESTORE;
+ enr->md.enrtuples = tuplestore_tuple_count(tdata->tg_newtable);
+ enr->reldata = tdata->tg_newtable;
+ rc = SPI_register_relation(enr);
+ if (rc != SPI_OK_REL_REGISTER)
+ return rc;
+ }
+
+ if (tdata->tg_oldtable)
+ {
+ EphemeralNamedRelation enr =
+ palloc(sizeof(EphemeralNamedRelationData));
+ int rc;
+
+ enr->md.name = tdata->tg_trigger->tgoldtable;
+ enr->md.reliddesc = tdata->tg_relation->rd_id;
+ enr->md.tupdesc = NULL;
+ enr->md.enrtype = ENR_NAMED_TUPLESTORE;
+ enr->md.enrtuples = tuplestore_tuple_count(tdata->tg_oldtable);
+ enr->reldata = tdata->tg_oldtable;
+ rc = SPI_register_relation(enr);
+ if (rc != SPI_OK_REL_REGISTER)
+ return rc;
+ }
+
+ return SPI_OK_TD_REGISTER;
+}
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index 58d0eeaf0b..8d7e711b3b 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -23,7 +23,7 @@
* and rewrites the typmods sent by the remote side to the corresponding
* local record typmods.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -281,9 +281,7 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
tqueue->tmpcontext =
AllocSetContextCreate(tqueue->mycontext,
"tqueue sender temp context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcontext = MemoryContextSwitchTo(tqueue->tmpcontext);
}
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index 8f1e1b3f50..1e641c9837 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -9,7 +9,7 @@
* data even if the underlying table is dropped.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index 242d6d2696..a113bf540d 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -3,7 +3,7 @@
* foreign.c
* support for foreign-data wrappers, servers and user mappings.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/foreign/foreign.c
@@ -28,10 +28,6 @@
#include "utils/syscache.h"
-extern Datum pg_options_to_table(PG_FUNCTION_ARGS);
-extern Datum postgresql_fdw_validator(PG_FUNCTION_ARGS);
-
-
/*
* GetForeignDataWrapper - look up the foreign-data wrapper by OID.
*/
@@ -721,14 +717,14 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
{
ListCell *lc;
- Assert(joinrel->reloptkind == RELOPT_JOINREL);
+ Assert(IS_JOIN_REL(joinrel));
foreach(lc, joinrel->pathlist)
{
Path *path = (Path *) lfirst(lc);
JoinPath *joinpath = NULL;
- /* Skip parameterised paths. */
+ /* Skip parameterized paths. */
if (path->param_info != NULL)
continue;
@@ -786,7 +782,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
ForeignPath *foreign_path;
foreign_path = (ForeignPath *) joinpath->outerjoinpath;
- if (foreign_path->path.parent->reloptkind == RELOPT_JOINREL)
+ if (IS_JOIN_REL(foreign_path->path.parent))
joinpath->outerjoinpath = foreign_path->fdw_outerpath;
}
@@ -795,7 +791,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
ForeignPath *foreign_path;
foreign_path = (ForeignPath *) joinpath->innerjoinpath;
- if (foreign_path->path.parent->reloptkind == RELOPT_JOINREL)
+ if (IS_JOIN_REL(foreign_path->path.parent))
joinpath->innerjoinpath = foreign_path->fdw_outerpath;
}
diff --git a/src/backend/lib/Makefile b/src/backend/lib/Makefile
index 2d2ba84fe9..f222c6c20d 100644
--- a/src/backend/lib/Makefile
+++ b/src/backend/lib/Makefile
@@ -12,7 +12,7 @@ subdir = src/backend/lib
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-OBJS = binaryheap.o bipartite_match.o hyperloglog.o ilist.o pairingheap.o \
- rbtree.o stringinfo.o
+OBJS = binaryheap.o bipartite_match.o hyperloglog.o ilist.o knapsack.o \
+ pairingheap.o rbtree.o stringinfo.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/lib/binaryheap.c b/src/backend/lib/binaryheap.c
index d3cd4ad963..9f99e77db0 100644
--- a/src/backend/lib/binaryheap.c
+++ b/src/backend/lib/binaryheap.c
@@ -3,7 +3,7 @@
* binaryheap.c
* A simple binary heap implementation
*
- * Portions Copyright (c) 2012-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2012-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/lib/binaryheap.c
diff --git a/src/backend/lib/bipartite_match.c b/src/backend/lib/bipartite_match.c
index 381627ec3d..4564a463d5 100644
--- a/src/backend/lib/bipartite_match.c
+++ b/src/backend/lib/bipartite_match.c
@@ -7,7 +7,7 @@
*
* http://en.wikipedia.org/w/index.php?title=Hopcroft%E2%80%93Karp_algorithm&oldid=593898016
*
- * Copyright (c) 2015-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2015-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/lib/bipartite_match.c
diff --git a/src/backend/lib/hyperloglog.c b/src/backend/lib/hyperloglog.c
index 6d246ce77b..df7a67e7dc 100644
--- a/src/backend/lib/hyperloglog.c
+++ b/src/backend/lib/hyperloglog.c
@@ -3,7 +3,7 @@
* hyperloglog.c
* HyperLogLog cardinality estimator
*
- * Portions Copyright (c) 2014-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2014-2017, PostgreSQL Global Development Group
*
* Based on Hideaki Ohno's C++ implementation. This is probably not ideally
* suited to estimating the cardinality of very large sets; in particular, we
diff --git a/src/backend/lib/ilist.c b/src/backend/lib/ilist.c
index fb995e30d6..720cecb0e7 100644
--- a/src/backend/lib/ilist.c
+++ b/src/backend/lib/ilist.c
@@ -3,7 +3,7 @@
* ilist.c
* support for integrated/inline doubly- and singly- linked lists
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/lib/knapsack.c b/src/backend/lib/knapsack.c
new file mode 100644
index 0000000000..ddf2b9afa3
--- /dev/null
+++ b/src/backend/lib/knapsack.c
@@ -0,0 +1,114 @@
+/*-------------------------------------------------------------------------
+ *
+ * knapsack.c
+ * Knapsack problem solver
+ *
+ * Given input vectors of integral item weights (must be >= 0) and values
+ * (double >= 0), compute the set of items which produces the greatest total
+ * value without exceeding a specified total weight; each item is included at
+ * most once (this is the 0/1 knapsack problem). Weight 0 items will always be
+ * included.
+ *
+ * The performance of this algorithm is pseudo-polynomial, O(nW) where W is the
+ * weight limit. To use with non-integral weights or approximate solutions,
+ * the caller should pre-scale the input weights to a suitable range. This
+ * allows approximate solutions in polynomial time (the general case of the
+ * exact problem is NP-hard).
+ *
+ * Copyright (c) 2017, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/lib/knapsack.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <math.h>
+#include <limits.h>
+
+#include "lib/knapsack.h"
+#include "miscadmin.h"
+#include "nodes/bitmapset.h"
+#include "utils/builtins.h"
+#include "utils/memutils.h"
+#include "utils/palloc.h"
+
+/*
+ * DiscreteKnapsack
+ *
+ * The item_values input is optional; if omitted, all the items are assumed to
+ * have value 1.
+ *
+ * Returns a Bitmapset of the 0..(n-1) indexes of the items chosen for
+ * inclusion in the solution.
+ *
+ * This uses the usual dynamic-programming algorithm, adapted to reuse the
+ * memory on each pass (by working from larger weights to smaller). At the
+ * start of pass number i, the values[w] array contains the largest value
+ * computed with total weight <= w, using only items with indices < i; and
+ * sets[w] contains the bitmap of items actually used for that value. (The
+ * bitmapsets are all pre-initialized with an unused high bit so that memory
+ * allocation is done only once.)
+ */
+Bitmapset *
+DiscreteKnapsack(int max_weight, int num_items,
+ int *item_weights, double *item_values)
+{
+ MemoryContext local_ctx = AllocSetContextCreate(CurrentMemoryContext,
+ "Knapsack",
+ ALLOCSET_SMALL_MINSIZE,
+ ALLOCSET_SMALL_INITSIZE,
+ ALLOCSET_SMALL_MAXSIZE);
+ MemoryContext oldctx = MemoryContextSwitchTo(local_ctx);
+ double *values;
+ Bitmapset **sets;
+ Bitmapset *result;
+ int i,
+ j;
+
+ Assert(max_weight >= 0);
+ Assert(num_items > 0 && item_weights);
+
+ values = palloc((1 + max_weight) * sizeof(double));
+ sets = palloc((1 + max_weight) * sizeof(Bitmapset *));
+
+ for (i = 0; i <= max_weight; ++i)
+ {
+ values[i] = 0;
+ sets[i] = bms_make_singleton(num_items);
+ }
+
+ for (i = 0; i < num_items; ++i)
+ {
+ int iw = item_weights[i];
+ double iv = item_values ? item_values[i] : 1;
+
+ for (j = max_weight; j >= iw; --j)
+ {
+ int ow = j - iw;
+
+ if (values[j] <= values[ow] + iv)
+ {
+ /* copy sets[ow] to sets[j] without realloc */
+ if (j != ow)
+ {
+ sets[j] = bms_del_members(sets[j], sets[j]);
+ sets[j] = bms_add_members(sets[j], sets[ow]);
+ }
+
+ sets[j] = bms_add_member(sets[j], i);
+
+ values[j] = values[ow] + iv;
+ }
+ }
+ }
+
+ MemoryContextSwitchTo(oldctx);
+
+ result = bms_del_member(bms_copy(sets[max_weight]), num_items);
+
+ MemoryContextDelete(local_ctx);
+
+ return result;
+}
diff --git a/src/backend/lib/pairingheap.c b/src/backend/lib/pairingheap.c
index 3cf83fce0c..7c6bd837c6 100644
--- a/src/backend/lib/pairingheap.c
+++ b/src/backend/lib/pairingheap.c
@@ -14,7 +14,7 @@
* The pairing heap: a new form of self-adjusting heap.
* Algorithmica 1, 1 (January 1986), pages 111-129. DOI: 10.1007/BF01840439
*
- * Portions Copyright (c) 2012-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2012-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/lib/pairingheap.c
diff --git a/src/backend/lib/rbtree.c b/src/backend/lib/rbtree.c
index 4fa8a1dd58..cdf8a73aa5 100644
--- a/src/backend/lib/rbtree.c
+++ b/src/backend/lib/rbtree.c
@@ -17,7 +17,7 @@
* longest path from root to leaf is only about twice as long as the shortest,
* so lookups are guaranteed to run in O(lg n) time.
*
- * Copyright (c) 2009-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2009-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/lib/rbtree.c
@@ -30,17 +30,6 @@
/*
- * Values of RBNode.iteratorState
- *
- * Note that iteratorState has an undefined value except in nodes that are
- * currently being visited by an active iteration.
- */
-#define InitialState (0)
-#define FirstStepDone (1)
-#define SecondStepDone (2)
-#define ThirdStepDone (3)
-
-/*
* Colors of nodes (values of RBNode.color)
*/
#define RBBLACK (0)
@@ -53,10 +42,6 @@ struct RBTree
{
RBNode *root; /* root node, or RBNIL if tree is empty */
- /* Iteration state */
- RBNode *cur; /* current iteration node */
- RBNode *(*iterate) (RBTree *rb);
-
/* Remaining fields are constant after rb_create */
Size node_size; /* actual size of tree nodes */
@@ -75,8 +60,19 @@ struct RBTree
*/
#define RBNIL (&sentinel)
-static RBNode sentinel = {InitialState, RBBLACK, RBNIL, RBNIL, NULL};
+static RBNode sentinel = {RBBLACK, RBNIL, RBNIL, NULL};
+/*
+ * Values used in the RBTreeIterator.next_state field, with an
+ * InvertedWalk iterator.
+ */
+typedef enum InvertedWalkNextStep
+{
+ NextStepBegin,
+ NextStepUp,
+ NextStepLeft,
+ NextStepRight
+} InvertedWalkNextStep;
/*
* rb_create: create an empty RBTree
@@ -123,8 +119,6 @@ rb_create(Size node_size,
Assert(node_size > sizeof(RBNode));
tree->root = RBNIL;
- tree->cur = RBNIL;
- tree->iterate = NULL;
tree->node_size = node_size;
tree->comparator = comparator;
tree->combiner = combiner;
@@ -437,7 +431,6 @@ rb_insert(RBTree *rb, const RBNode *data, bool *isNew)
x = rb->allocfunc (rb->arg);
- x->iteratorState = InitialState;
x->color = RBRED;
x->left = RBNIL;
@@ -653,171 +646,196 @@ rb_delete(RBTree *rb, RBNode *node)
* Traverse *
**********************************************************************/
-/*
- * The iterator routines were originally coded in tail-recursion style,
- * which is nice to look at, but is trouble if your compiler isn't smart
- * enough to optimize it. Now we just use looping.
- */
-#define descend(next_node) \
- do { \
- (next_node)->iteratorState = InitialState; \
- node = rb->cur = (next_node); \
- goto restart; \
- } while (0)
+static RBNode *
+rb_left_right_iterator(RBTreeIterator *iter)
+{
+ if (iter->last_visited == NULL)
+ {
+ iter->last_visited = iter->rb->root;
+ while (iter->last_visited->left != RBNIL)
+ iter->last_visited = iter->last_visited->left;
-#define ascend(next_node) \
- do { \
- node = rb->cur = (next_node); \
- goto restart; \
- } while (0)
+ return iter->last_visited;
+ }
+ if (iter->last_visited->right != RBNIL)
+ {
+ iter->last_visited = iter->last_visited->right;
+ while (iter->last_visited->left != RBNIL)
+ iter->last_visited = iter->last_visited->left;
-static RBNode *
-rb_left_right_iterator(RBTree *rb)
-{
- RBNode *node = rb->cur;
+ return iter->last_visited;
+ }
-restart:
- switch (node->iteratorState)
+ for (;;)
{
- case InitialState:
- if (node->left != RBNIL)
- {
- node->iteratorState = FirstStepDone;
- descend(node->left);
- }
- /* FALL THROUGH */
- case FirstStepDone:
- node->iteratorState = SecondStepDone;
- return node;
- case SecondStepDone:
- if (node->right != RBNIL)
- {
- node->iteratorState = ThirdStepDone;
- descend(node->right);
- }
- /* FALL THROUGH */
- case ThirdStepDone:
- if (node->parent)
- ascend(node->parent);
+ RBNode *came_from = iter->last_visited;
+
+ iter->last_visited = iter->last_visited->parent;
+ if (iter->last_visited == NULL)
+ {
+ iter->is_over = true;
break;
- default:
- elog(ERROR, "unrecognized rbtree node state: %d",
- node->iteratorState);
+ }
+
+ if (iter->last_visited->left == came_from)
+ break; /* came from left sub-tree, return current
+ * node */
+
+ /* else - came from right sub-tree, continue to move up */
}
- return NULL;
+ return iter->last_visited;
}
static RBNode *
-rb_right_left_iterator(RBTree *rb)
+rb_right_left_iterator(RBTreeIterator *iter)
{
- RBNode *node = rb->cur;
+ if (iter->last_visited == NULL)
+ {
+ iter->last_visited = iter->rb->root;
+ while (iter->last_visited->right != RBNIL)
+ iter->last_visited = iter->last_visited->right;
-restart:
- switch (node->iteratorState)
+ return iter->last_visited;
+ }
+
+ if (iter->last_visited->left != RBNIL)
{
- case InitialState:
- if (node->right != RBNIL)
- {
- node->iteratorState = FirstStepDone;
- descend(node->right);
- }
- /* FALL THROUGH */
- case FirstStepDone:
- node->iteratorState = SecondStepDone;
- return node;
- case SecondStepDone:
- if (node->left != RBNIL)
- {
- node->iteratorState = ThirdStepDone;
- descend(node->left);
- }
- /* FALL THROUGH */
- case ThirdStepDone:
- if (node->parent)
- ascend(node->parent);
+ iter->last_visited = iter->last_visited->left;
+ while (iter->last_visited->right != RBNIL)
+ iter->last_visited = iter->last_visited->right;
+
+ return iter->last_visited;
+ }
+
+ for (;;)
+ {
+ RBNode *came_from = iter->last_visited;
+
+ iter->last_visited = iter->last_visited->parent;
+ if (iter->last_visited == NULL)
+ {
+ iter->is_over = true;
break;
- default:
- elog(ERROR, "unrecognized rbtree node state: %d",
- node->iteratorState);
+ }
+
+ if (iter->last_visited->right == came_from)
+ break; /* came from right sub-tree, return current
+ * node */
+
+ /* else - came from left sub-tree, continue to move up */
}
- return NULL;
+ return iter->last_visited;
}
static RBNode *
-rb_direct_iterator(RBTree *rb)
+rb_direct_iterator(RBTreeIterator *iter)
{
- RBNode *node = rb->cur;
+ if (iter->last_visited == NULL)
+ {
+ iter->last_visited = iter->rb->root;
+ return iter->last_visited;
+ }
-restart:
- switch (node->iteratorState)
+ if (iter->last_visited->left != RBNIL)
{
- case InitialState:
- node->iteratorState = FirstStepDone;
- return node;
- case FirstStepDone:
- if (node->left != RBNIL)
+ iter->last_visited = iter->last_visited->left;
+ return iter->last_visited;
+ }
+
+ do
+ {
+ if (iter->last_visited->right != RBNIL)
+ {
+ iter->last_visited = iter->last_visited->right;
+ break;
+ }
+
+ /* go up and one step right */
+ for (;;)
+ {
+ RBNode *came_from = iter->last_visited;
+
+ iter->last_visited = iter->last_visited->parent;
+ if (iter->last_visited == NULL)
{
- node->iteratorState = SecondStepDone;
- descend(node->left);
+ iter->is_over = true;
+ break;
}
- /* FALL THROUGH */
- case SecondStepDone:
- if (node->right != RBNIL)
+
+ if ((iter->last_visited->right != came_from) && (iter->last_visited->right != RBNIL))
{
- node->iteratorState = ThirdStepDone;
- descend(node->right);
+ iter->last_visited = iter->last_visited->right;
+ return iter->last_visited;
}
- /* FALL THROUGH */
- case ThirdStepDone:
- if (node->parent)
- ascend(node->parent);
- break;
- default:
- elog(ERROR, "unrecognized rbtree node state: %d",
- node->iteratorState);
+ }
}
+ while (iter->last_visited != NULL);
- return NULL;
+ return iter->last_visited;
}
static RBNode *
-rb_inverted_iterator(RBTree *rb)
+rb_inverted_iterator(RBTreeIterator *iter)
{
- RBNode *node = rb->cur;
+ RBNode *came_from;
+ RBNode *current;
-restart:
- switch (node->iteratorState)
+ current = iter->last_visited;
+
+loop:
+ switch ((InvertedWalkNextStep) iter->next_step)
{
- case InitialState:
- if (node->left != RBNIL)
+ /* First call, begin from root */
+ case NextStepBegin:
+ current = iter->rb->root;
+ iter->next_step = NextStepLeft;
+ goto loop;
+
+ case NextStepLeft:
+ while (current->left != RBNIL)
+ current = current->left;
+
+ iter->next_step = NextStepRight;
+ goto loop;
+
+ case NextStepRight:
+ if (current->right != RBNIL)
+ {
+ current = current->right;
+ iter->next_step = NextStepLeft;
+ goto loop;
+ }
+ else /* not moved - return current, then go up */
+ iter->next_step = NextStepUp;
+ break;
+
+ case NextStepUp:
+ came_from = current;
+ current = current->parent;
+ if (current == NULL)
{
- node->iteratorState = FirstStepDone;
- descend(node->left);
+ iter->is_over = true;
+ break; /* end of iteration */
}
- /* FALL THROUGH */
- case FirstStepDone:
- if (node->right != RBNIL)
+ else if (came_from == current->right)
{
- node->iteratorState = SecondStepDone;
- descend(node->right);
+ /* return current, then continue to go up */
+ break;
+ }
+ else
+ {
+ /* otherwise we came from the left */
+ Assert(came_from == current->left);
+ iter->next_step = NextStepRight;
+ goto loop;
}
- /* FALL THROUGH */
- case SecondStepDone:
- node->iteratorState = ThirdStepDone;
- return node;
- case ThirdStepDone:
- if (node->parent)
- ascend(node->parent);
- break;
- default:
- elog(ERROR, "unrecognized rbtree node state: %d",
- node->iteratorState);
}
- return NULL;
+ iter->last_visited = current;
+ return current;
}
/*
@@ -827,33 +845,34 @@ restart:
* returns NULL or the traversal stops being of interest.
*
* If the tree is changed during traversal, results of further calls to
- * rb_iterate are unspecified.
+ * rb_iterate are unspecified. Multiple concurrent iterators on the same
+ * tree are allowed.
*
- * Note: this used to return a separately palloc'd iterator control struct,
- * but that's a bit pointless since the data structure is incapable of
- * supporting multiple concurrent traversals. Now we just keep the state
- * in RBTree.
+ * The iterator state is stored in the 'iter' struct. The caller should
+ * treat it as opaque struct.
*/
void
-rb_begin_iterate(RBTree *rb, RBOrderControl ctrl)
+rb_begin_iterate(RBTree *rb, RBOrderControl ctrl, RBTreeIterator *iter)
{
- rb->cur = rb->root;
- if (rb->cur != RBNIL)
- rb->cur->iteratorState = InitialState;
+ /* Common initialization for all traversal orders */
+ iter->rb = rb;
+ iter->last_visited = NULL;
+ iter->is_over = (rb->root == RBNIL);
switch (ctrl)
{
case LeftRightWalk: /* visit left, then self, then right */
- rb->iterate = rb_left_right_iterator;
+ iter->iterate = rb_left_right_iterator;
break;
case RightLeftWalk: /* visit right, then self, then left */
- rb->iterate = rb_right_left_iterator;
+ iter->iterate = rb_right_left_iterator;
break;
case DirectWalk: /* visit self, then left, then right */
- rb->iterate = rb_direct_iterator;
+ iter->iterate = rb_direct_iterator;
break;
case InvertedWalk: /* visit left, then right, then self */
- rb->iterate = rb_inverted_iterator;
+ iter->iterate = rb_inverted_iterator;
+ iter->next_step = NextStepBegin;
break;
default:
elog(ERROR, "unrecognized rbtree iteration order: %d", ctrl);
@@ -864,10 +883,10 @@ rb_begin_iterate(RBTree *rb, RBOrderControl ctrl)
* rb_iterate: return the next node in traversal order, or NULL if no more
*/
RBNode *
-rb_iterate(RBTree *rb)
+rb_iterate(RBTreeIterator *iter)
{
- if (rb->cur == RBNIL)
+ if (iter->is_over)
return NULL;
- return rb->iterate(rb);
+ return iter->iterate(iter);
}
diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c
index 7382e08077..fd15567144 100644
--- a/src/backend/lib/stringinfo.c
+++ b/src/backend/lib/stringinfo.c
@@ -6,7 +6,7 @@
* It can be used to buffer either ordinary C strings (null-terminated text)
* or arbitrary binary data. All storage is allocated with palloc().
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/lib/stringinfo.c
diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile
index 09410c4bb1..7fa2b02743 100644
--- a/src/backend/libpq/Makefile
+++ b/src/backend/libpq/Makefile
@@ -14,8 +14,8 @@ include $(top_builddir)/src/Makefile.global
# be-fsstubs is here for historical reasons, probably belongs elsewhere
-OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o ip.o md5.o pqcomm.o \
- pqformat.o pqmq.o pqsignal.o
+OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o ifaddr.o pqcomm.o \
+ pqformat.o pqmq.o pqsignal.o auth-scram.o
ifeq ($(with_openssl),yes)
OBJS += be-secure-openssl.o
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
new file mode 100644
index 0000000000..99feb0ce94
--- /dev/null
+++ b/src/backend/libpq/auth-scram.c
@@ -0,0 +1,1134 @@
+/*-------------------------------------------------------------------------
+ *
+ * auth-scram.c
+ * Server-side implementation of the SASL SCRAM-SHA-256 mechanism.
+ *
+ * See the following RFCs for more details:
+ * - RFC 5802: https://tools.ietf.org/html/rfc5802
+ * - RFC 5803: https://tools.ietf.org/html/rfc5803
+ * - RFC 7677: https://tools.ietf.org/html/rfc7677
+ *
+ * Here are some differences:
+ *
+ * - Username from the authentication exchange is not used. The client
+ * should send an empty string as the username.
+ *
+ * - If the password isn't valid UTF-8, or contains characters prohibited
+ * by the SASLprep profile, we skip the SASLprep pre-processing and use
+ * the raw bytes in calculating the hash.
+ *
+ * - Channel binding is not supported yet.
+ *
+ *
+ * The password stored in pg_authid consists of the iteration count, salt,
+ * StoredKey and ServerKey.
+ *
+ * SASLprep usage
+ * --------------
+ *
+ * One notable difference to the SCRAM specification is that while the
+ * specification dictates that the password is in UTF-8, and prohibits
+ * certain characters, we are more lenient. If the password isn't a valid
+ * UTF-8 string, or contains prohibited characters, the raw bytes are used
+ * to calculate the hash instead, without SASLprep processing. This is
+ * because PostgreSQL supports other encodings too, and the encoding being
+ * used during authentication is undefined (client_encoding isn't set until
+ * after authentication). In effect, we try to interpret the password as
+ * UTF-8 and apply SASLprep processing, but if it looks invalid, we assume
+ * that it's in some other encoding.
+ *
+ * In the worst case, we misinterpret a password that's in a different
+ * encoding as being Unicode, because it happens to consists entirely of
+ * valid UTF-8 bytes, and we apply Unicode normalization to it. As long
+ * as we do that consistently, that will not lead to failed logins.
+ * Fortunately, the UTF-8 byte sequences that are ignored by SASLprep
+ * don't correspond to any commonly used characters in any of the other
+ * supported encodings, so it should not lead to any significant loss in
+ * entropy, even if the normalization is incorrectly applied to a
+ * non-UTF-8 password.
+ *
+ * Error handling
+ * --------------
+ *
+ * Don't reveal user information to an unauthenticated client. We don't
+ * want an attacker to be able to probe whether a particular username is
+ * valid. In SCRAM, the server has to read the salt and iteration count
+ * from the user's password verifier, and send it to the client. To avoid
+ * revealing whether a user exists, when the client tries to authenticate
+ * with a username that doesn't exist, or doesn't have a valid SCRAM
+ * verifier in pg_authid, we create a fake salt and iteration count
+ * on-the-fly, and proceed with the authentication with that. In the end,
+ * we'll reject the attempt, as if an incorrect password was given. When
+ * we are performing a "mock" authentication, the 'doomed' flag in
+ * scram_state is set.
+ *
+ * In the error messages, avoid printing strings from the client, unless
+ * you check that they are pure ASCII. We don't want an unauthenticated
+ * attacker to be able to spam the logs with characters that are not valid
+ * to the encoding being used, whatever that is. We cannot avoid that in
+ * general, after logging in, but let's do what we can here.
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/backend/libpq/auth-scram.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <unistd.h>
+
+#include "access/xlog.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_control.h"
+#include "common/base64.h"
+#include "common/saslprep.h"
+#include "common/scram-common.h"
+#include "common/sha2.h"
+#include "libpq/auth.h"
+#include "libpq/crypt.h"
+#include "libpq/scram.h"
+#include "miscadmin.h"
+#include "utils/backend_random.h"
+#include "utils/builtins.h"
+#include "utils/timestamp.h"
+
+/*
+ * Status data for a SCRAM authentication exchange. This should be kept
+ * internal to this file.
+ */
+typedef enum
+{
+ SCRAM_AUTH_INIT,
+ SCRAM_AUTH_SALT_SENT,
+ SCRAM_AUTH_FINISHED
+} scram_state_enum;
+
+typedef struct
+{
+ scram_state_enum state;
+
+ const char *username; /* username from startup packet */
+
+ int iterations;
+ char *salt; /* base64-encoded */
+ uint8 StoredKey[SCRAM_KEY_LEN];
+ uint8 ServerKey[SCRAM_KEY_LEN];
+
+ /* Fields of the first message from client */
+ char *client_first_message_bare;
+ char *client_username;
+ char *client_nonce;
+
+ /* Fields from the last message from client */
+ char *client_final_message_without_proof;
+ char *client_final_nonce;
+ char ClientProof[SCRAM_KEY_LEN];
+
+ /* Fields generated in the server */
+ char *server_first_message;
+ char *server_nonce;
+
+ /*
+ * If something goes wrong during the authentication, or we are performing
+ * a "mock" authentication (see comments at top of file), the 'doomed'
+ * flag is set. A reason for the failure, for the server log, is put in
+ * 'logdetail'.
+ */
+ bool doomed;
+ char *logdetail;
+} scram_state;
+
+static void read_client_first_message(scram_state *state, char *input);
+static void read_client_final_message(scram_state *state, char *input);
+static char *build_server_first_message(scram_state *state);
+static char *build_server_final_message(scram_state *state);
+static bool verify_client_proof(scram_state *state);
+static bool verify_final_nonce(scram_state *state);
+static bool parse_scram_verifier(const char *verifier, int *iterations,
+ char **salt, uint8 *stored_key, uint8 *server_key);
+static void mock_scram_verifier(const char *username, int *iterations,
+ char **salt, uint8 *stored_key, uint8 *server_key);
+static bool is_scram_printable(char *p);
+static char *sanitize_char(char c);
+static char *scram_mock_salt(const char *username);
+
+/*
+ * pg_be_scram_init
+ *
+ * Initialize a new SCRAM authentication exchange status tracker. This
+ * needs to be called before doing any exchange. It will be filled later
+ * after the beginning of the exchange with verifier data.
+ *
+ * 'username' is the username provided by the client in the startup message.
+ * 'shadow_pass' is the role's password verifier, from pg_authid.rolpassword.
+ * If 'shadow_pass' is NULL, we still perform an authentication exchange, but
+ * it will fail, as if an incorrect password was given.
+ */
+void *
+pg_be_scram_init(const char *username, const char *shadow_pass)
+{
+ scram_state *state;
+ bool got_verifier;
+
+ state = (scram_state *) palloc0(sizeof(scram_state));
+ state->state = SCRAM_AUTH_INIT;
+ state->username = username;
+
+ /*
+ * Parse the stored password verifier.
+ */
+ if (shadow_pass)
+ {
+ int password_type = get_password_type(shadow_pass);
+
+ if (password_type == PASSWORD_TYPE_SCRAM_SHA_256)
+ {
+ if (parse_scram_verifier(shadow_pass, &state->iterations, &state->salt,
+ state->StoredKey, state->ServerKey))
+ got_verifier = true;
+ else
+ {
+ /*
+ * The password looked like a SCRAM verifier, but could not be
+ * parsed.
+ */
+ elog(LOG, "invalid SCRAM verifier for user \"%s\"", username);
+ got_verifier = false;
+ }
+ }
+ else
+ {
+ /*
+ * The user doesn't have SCRAM verifier. (You cannot do SCRAM
+ * authentication with an MD5 hash.)
+ */
+ state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM verifier."),
+ state->username);
+ got_verifier = false;
+ }
+ }
+ else
+ {
+ /*
+ * The caller requested us to perform a dummy authentication. This is
+ * considered normal, since the caller requested it, so don't set log
+ * detail.
+ */
+ got_verifier = false;
+ }
+
+ /*
+ * If the user did not have a valid SCRAM verifier, we still go through
+ * the motions with a mock one, and fail as if the client supplied an
+ * incorrect password. This is to avoid revealing information to an
+ * attacker.
+ */
+ if (!got_verifier)
+ {
+ mock_scram_verifier(username, &state->iterations, &state->salt,
+ state->StoredKey, state->ServerKey);
+ state->doomed = true;
+ }
+
+ return state;
+}
+
+/*
+ * Continue a SCRAM authentication exchange.
+ *
+ * 'input' is the SCRAM payload sent by the client. On the first call,
+ * 'input' contains the "Initial Client Response" that the client sent as
+ * part of the SASLInitialResponse message, or NULL if no Initial Client
+ * Response was given. (The SASL specification distinguishes between an
+ * empty response and non-existing one.) On subsequent calls, 'input'
+ * cannot be NULL. For convenience in this function, the caller must
+ * ensure that there is a null terminator at input[inputlen].
+ *
+ * The next message to send to client is saved in 'output', for a length
+ * of 'outputlen'. In the case of an error, optionally store a palloc'd
+ * string at *logdetail that will be sent to the postmaster log (but not
+ * the client).
+ */
+int
+pg_be_scram_exchange(void *opaq, char *input, int inputlen,
+ char **output, int *outputlen, char **logdetail)
+{
+ scram_state *state = (scram_state *) opaq;
+ int result;
+
+ *output = NULL;
+
+ /*
+ * If the client didn't include an "Initial Client Response" in the
+ * SASLInitialResponse message, send an empty challenge, to which the
+ * client will respond with the same data that usually comes in the
+ * Initial Client Response.
+ */
+ if (input == NULL)
+ {
+ Assert(state->state == SCRAM_AUTH_INIT);
+
+ *output = pstrdup("");
+ *outputlen = 0;
+ return SASL_EXCHANGE_CONTINUE;
+ }
+
+ /*
+ * Check that the input length agrees with the string length of the input.
+ * We can ignore inputlen after this.
+ */
+ if (inputlen == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (empty message)"))));
+ if (inputlen != strlen(input))
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (length mismatch)"))));
+
+ switch (state->state)
+ {
+ case SCRAM_AUTH_INIT:
+
+ /*
+ * Initialization phase. Receive the first message from client
+ * and be sure that it parsed correctly. Then send the challenge
+ * to the client.
+ */
+ read_client_first_message(state, input);
+
+ /* prepare message to send challenge */
+ *output = build_server_first_message(state);
+
+ state->state = SCRAM_AUTH_SALT_SENT;
+ result = SASL_EXCHANGE_CONTINUE;
+ break;
+
+ case SCRAM_AUTH_SALT_SENT:
+
+ /*
+ * Final phase for the server. Receive the response to the
+ * challenge previously sent, verify, and let the client know that
+ * everything went well (or not).
+ */
+ read_client_final_message(state, input);
+
+ if (!verify_final_nonce(state))
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("invalid SCRAM response (nonce mismatch)"))));
+
+ /*
+ * Now check the final nonce and the client proof.
+ *
+ * If we performed a "mock" authentication that we knew would fail
+ * from the get go, this is where we fail.
+ *
+ * The SCRAM specification includes an error code,
+ * "invalid-proof", for authentication failure, but it also allows
+ * erroring out in an application-specific way. We choose to do
+ * the latter, so that the error message for invalid password is
+ * the same for all authentication methods. The caller will call
+ * ereport(), when we return SASL_EXCHANGE_FAILURE with no output.
+ *
+ * NB: the order of these checks is intentional. We calculate the
+ * client proof even in a mock authentication, even though it's
+ * bound to fail, to thwart timing attacks to determine if a role
+ * with the given name exists or not.
+ */
+ if (!verify_client_proof(state) || state->doomed)
+ {
+ result = SASL_EXCHANGE_FAILURE;
+ break;
+ }
+
+ /* Build final message for client */
+ *output = build_server_final_message(state);
+
+ /* Success! */
+ result = SASL_EXCHANGE_SUCCESS;
+ state->state = SCRAM_AUTH_FINISHED;
+ break;
+
+ default:
+ elog(ERROR, "invalid SCRAM exchange state");
+ result = SASL_EXCHANGE_FAILURE;
+ }
+
+ if (result == SASL_EXCHANGE_FAILURE && state->logdetail && logdetail)
+ *logdetail = state->logdetail;
+
+ if (*output)
+ *outputlen = strlen(*output);
+
+ return result;
+}
+
+/*
+ * Construct a verifier string for SCRAM, stored in pg_authid.rolpassword.
+ *
+ * The result is palloc'd, so caller is responsible for freeing it.
+ */
+char *
+pg_be_scram_build_verifier(const char *password)
+{
+ char *prep_password = NULL;
+ pg_saslprep_rc rc;
+ char saltbuf[SCRAM_DEFAULT_SALT_LEN];
+ char *result;
+
+ /*
+ * Normalize the password with SASLprep. If that doesn't work, because
+ * the password isn't valid UTF-8 or contains prohibited characters, just
+ * proceed with the original password. (See comments at top of file.)
+ */
+ rc = pg_saslprep(password, &prep_password);
+ if (rc == SASLPREP_SUCCESS)
+ password = (const char *) prep_password;
+
+ /* Generate random salt */
+ if (!pg_backend_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("could not generate random salt")));
+ if (prep_password)
+ pfree(prep_password);
+ return NULL;
+ }
+
+ result = scram_build_verifier(saltbuf, SCRAM_DEFAULT_SALT_LEN,
+ SCRAM_DEFAULT_ITERATIONS, password);
+
+ if (prep_password)
+ pfree(prep_password);
+
+ return result;
+}
+
+/*
+ * Verify a plaintext password against a SCRAM verifier. This is used when
+ * performing plaintext password authentication for a user that has a SCRAM
+ * verifier stored in pg_authid.
+ */
+bool
+scram_verify_plain_password(const char *username, const char *password,
+ const char *verifier)
+{
+ char *encoded_salt;
+ char *salt;
+ int saltlen;
+ int iterations;
+ uint8 salted_password[SCRAM_KEY_LEN];
+ uint8 stored_key[SCRAM_KEY_LEN];
+ uint8 server_key[SCRAM_KEY_LEN];
+ uint8 computed_key[SCRAM_KEY_LEN];
+ char *prep_password = NULL;
+ pg_saslprep_rc rc;
+
+ if (!parse_scram_verifier(verifier, &iterations, &encoded_salt,
+ stored_key, server_key))
+ {
+ /*
+ * The password looked like a SCRAM verifier, but could not be parsed.
+ */
+ elog(LOG, "invalid SCRAM verifier for user \"%s\"", username);
+ return false;
+ }
+
+ salt = palloc(pg_b64_dec_len(strlen(encoded_salt)));
+ saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt);
+ if (saltlen == -1)
+ {
+ elog(LOG, "invalid SCRAM verifier for user \"%s\"", username);
+ return false;
+ }
+
+ /* Normalize the password */
+ rc = pg_saslprep(password, &prep_password);
+ if (rc == SASLPREP_SUCCESS)
+ password = prep_password;
+
+ /* Compute Server Key based on the user-supplied plaintext password */
+ scram_SaltedPassword(password, salt, saltlen, iterations, salted_password);
+ scram_ServerKey(salted_password, computed_key);
+
+ if (prep_password)
+ pfree(prep_password);
+
+ /*
+ * Compare the verifier's Server Key with the one computed from the
+ * user-supplied password.
+ */
+ return memcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
+}
+
+
+/*
+ * Parse and validate format of given SCRAM verifier.
+ *
+ * Returns true if the SCRAM verifier has been parsed, and false otherwise.
+ */
+static bool
+parse_scram_verifier(const char *verifier, int *iterations, char **salt,
+ uint8 *stored_key, uint8 *server_key)
+{
+ char *v;
+ char *p;
+ char *scheme_str;
+ char *salt_str;
+ char *iterations_str;
+ char *storedkey_str;
+ char *serverkey_str;
+ int decoded_len;
+ char *decoded_salt_buf;
+
+ /*
+ * The verifier is of form:
+ *
+ * SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
+ */
+ v = pstrdup(verifier);
+ if ((scheme_str = strtok(v, "$")) == NULL)
+ goto invalid_verifier;
+ if ((iterations_str = strtok(NULL, ":")) == NULL)
+ goto invalid_verifier;
+ if ((salt_str = strtok(NULL, "$")) == NULL)
+ goto invalid_verifier;
+ if ((storedkey_str = strtok(NULL, ":")) == NULL)
+ goto invalid_verifier;
+ if ((serverkey_str = strtok(NULL, "")) == NULL)
+ goto invalid_verifier;
+
+ /* Parse the fields */
+ if (strcmp(scheme_str, "SCRAM-SHA-256") != 0)
+ goto invalid_verifier;
+
+ errno = 0;
+ *iterations = strtol(iterations_str, &p, 10);
+ if (*p || errno != 0)
+ goto invalid_verifier;
+
+ /*
+ * Verify that the salt is in Base64-encoded format, by decoding it,
+ * although we return the encoded version to the caller.
+ */
+ decoded_salt_buf = palloc(pg_b64_dec_len(strlen(salt_str)));
+ decoded_len = pg_b64_decode(salt_str, strlen(salt_str), decoded_salt_buf);
+ if (decoded_len < 0)
+ goto invalid_verifier;
+ *salt = pstrdup(salt_str);
+
+ /*
+ * Decode StoredKey and ServerKey.
+ */
+ if (pg_b64_dec_len(strlen(storedkey_str) != SCRAM_KEY_LEN))
+ goto invalid_verifier;
+ decoded_len = pg_b64_decode(storedkey_str, strlen(storedkey_str),
+ (char *) stored_key);
+ if (decoded_len != SCRAM_KEY_LEN)
+ goto invalid_verifier;
+
+ if (pg_b64_dec_len(strlen(serverkey_str) != SCRAM_KEY_LEN))
+ goto invalid_verifier;
+ decoded_len = pg_b64_decode(serverkey_str, strlen(serverkey_str),
+ (char *) server_key);
+ if (decoded_len != SCRAM_KEY_LEN)
+ goto invalid_verifier;
+
+ return true;
+
+invalid_verifier:
+ pfree(v);
+ *salt = NULL;
+ return false;
+}
+
+static void
+mock_scram_verifier(const char *username, int *iterations, char **salt,
+ uint8 *stored_key, uint8 *server_key)
+{
+ char *raw_salt;
+ char *encoded_salt;
+ int encoded_len;
+
+ /* Generate deterministic salt */
+ raw_salt = scram_mock_salt(username);
+
+ encoded_salt = (char *) palloc(pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN) + 1);
+ encoded_len = pg_b64_encode(raw_salt, SCRAM_DEFAULT_SALT_LEN, encoded_salt);
+ encoded_salt[encoded_len] = '\0';
+
+ *salt = encoded_salt;
+ *iterations = SCRAM_DEFAULT_ITERATIONS;
+
+ /* StoredKey and ServerKey are not used in a doomed authentication */
+ memset(stored_key, 0, SCRAM_KEY_LEN);
+ memset(server_key, 0, SCRAM_KEY_LEN);
+}
+
+/*
+ * Read the value in a given SASL exchange message for given attribute.
+ */
+static char *
+read_attr_value(char **input, char attr)
+{
+ char *begin = *input;
+ char *end;
+
+ if (*begin != attr)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (attribute '%c' expected, %s found)",
+ attr, sanitize_char(*begin)))));
+ begin++;
+
+ if (*begin != '=')
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (expected = in attr %c)", attr))));
+ begin++;
+
+ end = begin;
+ while (*end && *end != ',')
+ end++;
+
+ if (*end)
+ {
+ *end = '\0';
+ *input = end + 1;
+ }
+ else
+ *input = end;
+
+ return begin;
+}
+
+static bool
+is_scram_printable(char *p)
+{
+ /*------
+ * Printable characters, as defined by SCRAM spec: (RFC 5802)
+ *
+ * printable = %x21-2B / %x2D-7E
+ * ;; Printable ASCII except ",".
+ * ;; Note that any "printable" is also
+ * ;; a valid "value".
+ *------
+ */
+ for (; *p; p++)
+ {
+ if (*p < 0x21 || *p > 0x7E || *p == 0x2C /* comma */ )
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Convert an arbitrary byte to printable form. For error messages.
+ *
+ * If it's a printable ASCII character, print it as a single character.
+ * otherwise, print it in hex.
+ *
+ * The returned pointer points to a static buffer.
+ */
+static char *
+sanitize_char(char c)
+{
+ static char buf[5];
+
+ if (c >= 0x21 && c <= 0x7E)
+ snprintf(buf, sizeof(buf), "'%c'", c);
+ else
+ snprintf(buf, sizeof(buf), "0x%02x", (unsigned char) c);
+ return buf;
+}
+
+/*
+ * Read the next attribute and value in a SASL exchange message.
+ *
+ * Returns NULL if there is attribute.
+ */
+static char *
+read_any_attr(char **input, char *attr_p)
+{
+ char *begin = *input;
+ char *end;
+ char attr = *begin;
+
+ /*------
+ * attr-val = ALPHA "=" value
+ * ;; Generic syntax of any attribute sent
+ * ;; by server or client
+ *------
+ */
+ if (!((attr >= 'A' && attr <= 'Z') ||
+ (attr >= 'a' && attr <= 'z')))
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (attribute expected, invalid char %s found)",
+ sanitize_char(attr)))));
+ if (attr_p)
+ *attr_p = attr;
+ begin++;
+
+ if (*begin != '=')
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (expected = in attr %c)", attr))));
+ begin++;
+
+ end = begin;
+ while (*end && *end != ',')
+ end++;
+
+ if (*end)
+ {
+ *end = '\0';
+ *input = end + 1;
+ }
+ else
+ *input = end;
+
+ return begin;
+}
+
+/*
+ * Read and parse the first message from client in the context of a SASL
+ * authentication exchange message.
+ *
+ * At this stage, any errors will be reported directly with ereport(ERROR).
+ */
+static void
+read_client_first_message(scram_state *state, char *input)
+{
+ input = pstrdup(input);
+
+ /*------
+ * The syntax for the client-first-message is: (RFC 5802)
+ *
+ * saslname = 1*(value-safe-char / "=2C" / "=3D")
+ * ;; Conforms to <value>.
+ *
+ * authzid = "a=" saslname
+ * ;; Protocol specific.
+ *
+ * cb-name = 1*(ALPHA / DIGIT / "." / "-")
+ * ;; See RFC 5056, Section 7.
+ * ;; E.g., "tls-server-end-point" or
+ * ;; "tls-unique".
+ *
+ * gs2-cbind-flag = ("p=" cb-name) / "n" / "y"
+ * ;; "n" -> client doesn't support channel binding.
+ * ;; "y" -> client does support channel binding
+ * ;; but thinks the server does not.
+ * ;; "p" -> client requires channel binding.
+ * ;; The selected channel binding follows "p=".
+ *
+ * gs2-header = gs2-cbind-flag "," [ authzid ] ","
+ * ;; GS2 header for SCRAM
+ * ;; (the actual GS2 header includes an optional
+ * ;; flag to indicate that the GSS mechanism is not
+ * ;; "standard", but since SCRAM is "standard", we
+ * ;; don't include that flag).
+ *
+ * username = "n=" saslname
+ * ;; Usernames are prepared using SASLprep.
+ *
+ * reserved-mext = "m=" 1*(value-char)
+ * ;; Reserved for signaling mandatory extensions.
+ * ;; The exact syntax will be defined in
+ * ;; the future.
+ *
+ * nonce = "r=" c-nonce [s-nonce]
+ * ;; Second part provided by server.
+ *
+ * c-nonce = printable
+ *
+ * client-first-message-bare =
+ * [reserved-mext ","]
+ * username "," nonce ["," extensions]
+ *
+ * client-first-message =
+ * gs2-header client-first-message-bare
+ *
+ * For example:
+ * n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
+ *
+ * The "n,," in the beginning means that the client doesn't support
+ * channel binding, and no authzid is given. "n=user" is the username.
+ * However, in PostgreSQL the username is sent in the startup packet, and
+ * the username in the SCRAM exchange is ignored. libpq always sends it
+ * as an empty string. The last part, "r=fyko+d2lbbFgONRv9qkxdawL" is
+ * the client nonce.
+ *------
+ */
+
+ /* read gs2-cbind-flag */
+ switch (*input)
+ {
+ case 'n':
+ /* Client does not support channel binding */
+ input++;
+ break;
+ case 'y':
+ /* Client supports channel binding, but we're not doing it today */
+ input++;
+ break;
+ case 'p':
+
+ /*
+ * Client requires channel binding. We don't support it.
+ *
+ * RFC 5802 specifies a particular error code,
+ * e=server-does-support-channel-binding, for this. But it can
+ * only be sent in the server-final message, and we don't want to
+ * go through the motions of the authentication, knowing it will
+ * fail, just to send that error message.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("client requires SCRAM channel binding, but it is not supported")));
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (unexpected channel-binding flag %s)",
+ sanitize_char(*input)))));
+ }
+ if (*input != ',')
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("malformed SCRAM message (comma expected, got %s)",
+ sanitize_char(*input))));
+ input++;
+
+ /*
+ * Forbid optional authzid (authorization identity). We don't support it.
+ */
+ if (*input == 'a')
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("client uses authorization identity, but it is not supported")));
+ if (*input != ',')
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("malformed SCRAM message (unexpected attribute %s in client-first-message)",
+ sanitize_char(*input))));
+ input++;
+
+ state->client_first_message_bare = pstrdup(input);
+
+ /*
+ * Any mandatory extensions would go here. We don't support any.
+ *
+ * RFC 5802 specifies error code "e=extensions-not-supported" for this,
+ * but it can only be sent in the server-final message. We prefer to fail
+ * immediately (which the RFC also allows).
+ */
+ if (*input == 'm')
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("client requires mandatory SCRAM extension")));
+
+ /*
+ * Read username. Note: this is ignored. We use the username from the
+ * startup message instead, still it is kept around if provided as it
+ * proves to be useful for debugging purposes.
+ */
+ state->client_username = read_attr_value(&input, 'n');
+
+ /* read nonce and check that it is made of only printable characters */
+ state->client_nonce = read_attr_value(&input, 'r');
+ if (!is_scram_printable(state->client_nonce))
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("non-printable characters in SCRAM nonce")));
+
+ /*
+ * There can be any number of optional extensions after this. We don't
+ * support any extensions, so ignore them.
+ */
+ while (*input != '\0')
+ read_any_attr(&input, NULL);
+
+ /* success! */
+}
+
+/*
+ * Verify the final nonce contained in the last message received from
+ * client in an exchange.
+ */
+static bool
+verify_final_nonce(scram_state *state)
+{
+ int client_nonce_len = strlen(state->client_nonce);
+ int server_nonce_len = strlen(state->server_nonce);
+ int final_nonce_len = strlen(state->client_final_nonce);
+
+ if (final_nonce_len != client_nonce_len + server_nonce_len)
+ return false;
+ if (memcmp(state->client_final_nonce, state->client_nonce, client_nonce_len) != 0)
+ return false;
+ if (memcmp(state->client_final_nonce + client_nonce_len, state->server_nonce, server_nonce_len) != 0)
+ return false;
+
+ return true;
+}
+
+/*
+ * Verify the client proof contained in the last message received from
+ * client in an exchange.
+ */
+static bool
+verify_client_proof(scram_state *state)
+{
+ uint8 ClientSignature[SCRAM_KEY_LEN];
+ uint8 ClientKey[SCRAM_KEY_LEN];
+ uint8 client_StoredKey[SCRAM_KEY_LEN];
+ scram_HMAC_ctx ctx;
+ int i;
+
+ /* calculate ClientSignature */
+ scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN);
+ scram_HMAC_update(&ctx,
+ state->client_first_message_bare,
+ strlen(state->client_first_message_bare));
+ scram_HMAC_update(&ctx, ",", 1);
+ scram_HMAC_update(&ctx,
+ state->server_first_message,
+ strlen(state->server_first_message));
+ scram_HMAC_update(&ctx, ",", 1);
+ scram_HMAC_update(&ctx,
+ state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof));
+ scram_HMAC_final(ClientSignature, &ctx);
+
+ /* Extract the ClientKey that the client calculated from the proof */
+ for (i = 0; i < SCRAM_KEY_LEN; i++)
+ ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i];
+
+ /* Hash it one more time, and compare with StoredKey */
+ scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey);
+
+ if (memcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0)
+ return false;
+
+ return true;
+}
+
+/*
+ * Build the first server-side message sent to the client in a SASL
+ * communication exchange.
+ */
+static char *
+build_server_first_message(scram_state *state)
+{
+ /*------
+ * The syntax for the server-first-message is: (RFC 5802)
+ *
+ * server-first-message =
+ * [reserved-mext ","] nonce "," salt ","
+ * iteration-count ["," extensions]
+ *
+ * nonce = "r=" c-nonce [s-nonce]
+ * ;; Second part provided by server.
+ *
+ * c-nonce = printable
+ *
+ * s-nonce = printable
+ *
+ * salt = "s=" base64
+ *
+ * iteration-count = "i=" posit-number
+ * ;; A positive number.
+ *
+ * Example:
+ *
+ * r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
+ *------
+ */
+
+ /*
+ * Per the spec, the nonce may consist of any printable ASCII characters.
+ * For convenience, however, we don't use the whole range available,
+ * rather, we generate some random bytes, and base64 encode them.
+ */
+ char raw_nonce[SCRAM_RAW_NONCE_LEN];
+ int encoded_len;
+
+ if (!pg_backend_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
+ ereport(COMMERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("could not generate random nonce")));
+
+ state->server_nonce = palloc(pg_b64_enc_len(SCRAM_RAW_NONCE_LEN) + 1);
+ encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN, state->server_nonce);
+ state->server_nonce[encoded_len] = '\0';
+
+ state->server_first_message =
+ psprintf("r=%s%s,s=%s,i=%u",
+ state->client_nonce, state->server_nonce,
+ state->salt, state->iterations);
+
+ return pstrdup(state->server_first_message);
+}
+
+
+/*
+ * Read and parse the final message received from client.
+ */
+static void
+read_client_final_message(scram_state *state, char *input)
+{
+ char attr;
+ char *channel_binding;
+ char *value;
+ char *begin,
+ *proof;
+ char *p;
+ char *client_proof;
+
+ begin = p = pstrdup(input);
+
+ /*------
+ * The syntax for the server-first-message is: (RFC 5802)
+ *
+ * gs2-header = gs2-cbind-flag "," [ authzid ] ","
+ * ;; GS2 header for SCRAM
+ * ;; (the actual GS2 header includes an optional
+ * ;; flag to indicate that the GSS mechanism is not
+ * ;; "standard", but since SCRAM is "standard", we
+ * ;; don't include that flag).
+ *
+ * cbind-input = gs2-header [ cbind-data ]
+ * ;; cbind-data MUST be present for
+ * ;; gs2-cbind-flag of "p" and MUST be absent
+ * ;; for "y" or "n".
+ *
+ * channel-binding = "c=" base64
+ * ;; base64 encoding of cbind-input.
+ *
+ * proof = "p=" base64
+ *
+ * client-final-message-without-proof =
+ * channel-binding "," nonce [","
+ * extensions]
+ *
+ * client-final-message =
+ * client-final-message-without-proof "," proof
+ *------
+ */
+
+ /*
+ * Read channel-binding. We don't support channel binding, so it's
+ * expected to always be "biws", which is "n,,", base64-encoded.
+ */
+ channel_binding = read_attr_value(&p, 'c');
+ if (strcmp(channel_binding, "biws") != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("unexpected SCRAM channel-binding attribute in client-final-message"))));
+ state->client_final_nonce = read_attr_value(&p, 'r');
+
+ /* ignore optional extensions */
+ do
+ {
+ proof = p - 1;
+ value = read_any_attr(&p, &attr);
+ } while (attr != 'p');
+
+ client_proof = palloc(pg_b64_dec_len(strlen(value)));
+ if (pg_b64_decode(value, strlen(value), client_proof) != SCRAM_KEY_LEN)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (malformed proof in client-final-message"))));
+ memcpy(state->ClientProof, client_proof, SCRAM_KEY_LEN);
+ pfree(client_proof);
+
+ if (*p != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ (errmsg("malformed SCRAM message (garbage at end of client-final-message)"))));
+
+ state->client_final_message_without_proof = palloc(proof - begin + 1);
+ memcpy(state->client_final_message_without_proof, input, proof - begin);
+ state->client_final_message_without_proof[proof - begin] = '\0';
+}
+
+/*
+ * Build the final server-side message of an exchange.
+ */
+static char *
+build_server_final_message(scram_state *state)
+{
+ uint8 ServerSignature[SCRAM_KEY_LEN];
+ char *server_signature_base64;
+ int siglen;
+ scram_HMAC_ctx ctx;
+
+ /* calculate ServerSignature */
+ scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN);
+ scram_HMAC_update(&ctx,
+ state->client_first_message_bare,
+ strlen(state->client_first_message_bare));
+ scram_HMAC_update(&ctx, ",", 1);
+ scram_HMAC_update(&ctx,
+ state->server_first_message,
+ strlen(state->server_first_message));
+ scram_HMAC_update(&ctx, ",", 1);
+ scram_HMAC_update(&ctx,
+ state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof));
+ scram_HMAC_final(ServerSignature, &ctx);
+
+ server_signature_base64 = palloc(pg_b64_enc_len(SCRAM_KEY_LEN) + 1);
+ siglen = pg_b64_encode((const char *) ServerSignature,
+ SCRAM_KEY_LEN, server_signature_base64);
+ server_signature_base64[siglen] = '\0';
+
+ /*------
+ * The syntax for the server-final-message is: (RFC 5802)
+ *
+ * verifier = "v=" base64
+ * ;; base-64 encoded ServerSignature.
+ *
+ * server-final-message = (server-error / verifier)
+ * ["," extensions]
+ *
+ *------
+ */
+ return psprintf("v=%s", server_signature_base64);
+}
+
+
+/*
+ * Determinisitcally generate salt for mock authentication, using a SHA256
+ * hash based on the username and a cluster-level secret key. Returns a
+ * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN.
+ */
+static char *
+scram_mock_salt(const char *username)
+{
+ pg_sha256_ctx ctx;
+ static uint8 sha_digest[PG_SHA256_DIGEST_LENGTH];
+ char *mock_auth_nonce = GetMockAuthenticationNonce();
+
+ /*
+ * Generate salt using a SHA256 hash of the username and the cluster's
+ * mock authentication nonce. (This works as long as the salt length is
+ * not larger the SHA256 digest length. If the salt is smaller, the caller
+ * will just ignore the extra data.)
+ */
+ StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN,
+ "salt length greater than SHA256 digest length");
+
+ pg_sha256_init(&ctx);
+ pg_sha256_update(&ctx, (uint8 *) username, strlen(username));
+ pg_sha256_update(&ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
+ pg_sha256_final(&ctx, sha_digest);
+
+ return (char *) sha_digest;
+}
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 7d8fc3e54d..5b68e3b7a1 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -3,7 +3,7 @@
* auth.c
* Routines to handle network authentication
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -20,26 +20,44 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include "commands/user.h"
+#include "common/ip.h"
+#include "common/md5.h"
#include "libpq/auth.h"
#include "libpq/crypt.h"
-#include "libpq/ip.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
-#include "libpq/md5.h"
+#include "libpq/scram.h"
#include "miscadmin.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
+#include "utils/backend_random.h"
+#include "utils/timestamp.h"
/*----------------------------------------------------------------
* Global authentication functions
*----------------------------------------------------------------
*/
-static void sendAuthRequest(Port *port, AuthRequest areq);
+static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata,
+ int extralen);
static void auth_failed(Port *port, int status, char *logdetail);
static char *recv_password_packet(Port *port);
-static int recv_and_check_password_packet(Port *port, char **logdetail);
+
+
+/*----------------------------------------------------------------
+ * Password-based authentication methods (password, md5, and scram-sha-256)
+ *----------------------------------------------------------------
+ */
+static int CheckPasswordAuth(Port *port, char **logdetail);
+static int CheckPWChallengeAuth(Port *port, char **logdetail);
+
+static int CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail);
+static int CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail);
/*----------------------------------------------------------------
@@ -177,10 +195,8 @@ static int pg_SSPI_make_upn(char *accountname,
* RADIUS Authentication
*----------------------------------------------------------------
*/
-#ifdef USE_OPENSSL
-#include <openssl/rand.h>
-#endif
static int CheckRADIUSAuth(Port *port);
+static int PerformRadiusTransaction(char *server, char *secret, char *portstr, char *identifier, char *user_name, char *passwd);
/*
@@ -198,6 +214,13 @@ static int CheckRADIUSAuth(Port *port);
*/
#define PG_MAX_AUTH_TOKEN_LENGTH 65535
+/*
+ * Maximum accepted size of SASL messages.
+ *
+ * The messages that the server or libpq generate are much smaller than this,
+ * but have some headroom.
+ */
+#define PG_MAX_SASL_MESSAGE_LENGTH 1024
/*----------------------------------------------------------------
* Global authentication functions
@@ -261,6 +284,7 @@ auth_failed(Port *port, int status, char *logdetail)
break;
case uaPassword:
case uaMD5:
+ case uaSCRAM:
errstr = gettext_noop("password authentication failed for user \"%s\"");
/* We use it to indicate if a .pgpass password failed. */
errcode_return = ERRCODE_INVALID_PASSWORD;
@@ -334,28 +358,22 @@ ClientAuthentication(Port *port)
*/
if (port->hba->clientcert)
{
+ /* If we haven't loaded a root certificate store, fail */
+ if (!secure_loaded_verify_locations())
+ ereport(FATAL,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("client certificates can only be checked if a root certificate store is available")));
+
/*
- * When we parse pg_hba.conf, we have already made sure that we have
- * been able to load a certificate store. Thus, if a certificate is
- * present on the client, it has been verified against our root
+ * If we loaded a root certificate store, and if a certificate is
+ * present on the client, then it has been verified against our root
* certificate store, and the connection would have been aborted
* already if it didn't verify ok.
*/
-#ifdef USE_SSL
if (!port->peer_cert_valid)
- {
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("connection requires a valid client certificate")));
- }
-#else
-
- /*
- * hba.c makes sure hba->clientcert can't be set unless OpenSSL is
- * present.
- */
- Assert(false);
-#endif
}
/*
@@ -498,7 +516,7 @@ ClientAuthentication(Port *port)
case uaGSS:
#ifdef ENABLE_GSS
- sendAuthRequest(port, AUTH_REQ_GSS);
+ sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
status = pg_GSS_recvauth(port);
#else
Assert(false);
@@ -507,7 +525,7 @@ ClientAuthentication(Port *port)
case uaSSPI:
#ifdef ENABLE_SSPI
- sendAuthRequest(port, AUTH_REQ_SSPI);
+ sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
status = pg_SSPI_recvauth(port);
#else
Assert(false);
@@ -527,17 +545,12 @@ ClientAuthentication(Port *port)
break;
case uaMD5:
- if (Db_user_namespace)
- ereport(FATAL,
- (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
- errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
- sendAuthRequest(port, AUTH_REQ_MD5);
- status = recv_and_check_password_packet(port, &logdetail);
+ case uaSCRAM:
+ status = CheckPWChallengeAuth(port, &logdetail);
break;
case uaPassword:
- sendAuthRequest(port, AUTH_REQ_PASSWORD);
- status = recv_and_check_password_packet(port, &logdetail);
+ status = CheckPasswordAuth(port, &logdetail);
break;
case uaPAM:
@@ -583,7 +596,7 @@ ClientAuthentication(Port *port)
(*ClientAuthentication_hook) (port, status);
if (status == STATUS_OK)
- sendAuthRequest(port, AUTH_REQ_OK);
+ sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
else
auth_failed(port, status, logdetail);
}
@@ -593,7 +606,7 @@ ClientAuthentication(Port *port)
* Send an authentication request packet to the frontend.
*/
static void
-sendAuthRequest(Port *port, AuthRequest areq)
+sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
{
StringInfoData buf;
@@ -601,36 +614,17 @@ sendAuthRequest(Port *port, AuthRequest areq)
pq_beginmessage(&buf, 'R');
pq_sendint(&buf, (int32) areq, sizeof(int32));
-
- /* Add the salt for encrypted passwords. */
- if (areq == AUTH_REQ_MD5)
- pq_sendbytes(&buf, port->md5Salt, 4);
-
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
-
- /*
- * Add the authentication data for the next step of the GSSAPI or SSPI
- * negotiation.
- */
- else if (areq == AUTH_REQ_GSS_CONT)
- {
- if (port->gss->outbuf.length > 0)
- {
- elog(DEBUG4, "sending GSS token of length %u",
- (unsigned int) port->gss->outbuf.length);
-
- pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
- }
- }
-#endif
+ if (extralen > 0)
+ pq_sendbytes(&buf, extradata, extralen);
pq_endmessage(&buf);
/*
- * Flush message so client will see it, except for AUTH_REQ_OK, which need
- * not be sent until we are ready for queries.
+ * Flush message so client will see it, except for AUTH_REQ_OK and
+ * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
+ * queries.
*/
- if (areq != AUTH_REQ_OK)
+ if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
pq_flush();
CHECK_FOR_INTERRUPTS();
@@ -707,33 +701,303 @@ recv_password_packet(Port *port)
/*----------------------------------------------------------------
- * MD5 authentication
+ * Password-based authentication mechanisms
*----------------------------------------------------------------
*/
/*
- * Called when we have sent an authorization request for a password.
- * Get the response and check it.
- * On error, optionally store a detail string at *logdetail.
+ * Plaintext password authentication.
*/
static int
-recv_and_check_password_packet(Port *port, char **logdetail)
+CheckPasswordAuth(Port *port, char **logdetail)
{
char *passwd;
int result;
+ char *shadow_pass;
+
+ sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
passwd = recv_password_packet(port);
+ if (passwd == NULL)
+ return STATUS_EOF; /* client wouldn't send password */
+
+ shadow_pass = get_role_password(port->user_name, logdetail);
+ if (shadow_pass)
+ {
+ result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
+ logdetail);
+ }
+ else
+ result = STATUS_ERROR;
+
+ if (shadow_pass)
+ pfree(shadow_pass);
+ pfree(passwd);
+
+ return result;
+}
+/*
+ * MD5 and SCRAM authentication.
+ */
+static int
+CheckPWChallengeAuth(Port *port, char **logdetail)
+{
+ int auth_result;
+ char *shadow_pass;
+ PasswordType pwtype;
+
+ Assert(port->hba->auth_method == uaSCRAM ||
+ port->hba->auth_method == uaMD5);
+
+ /* First look up the user's password. */
+ shadow_pass = get_role_password(port->user_name, logdetail);
+
+ /*
+ * If the user does not exist, or has no password or it's expired, we
+ * still go through the motions of authentication, to avoid revealing to
+ * the client that the user didn't exist. If 'md5' is allowed, we choose
+ * whether to use 'md5' or 'scram-sha-256' authentication based on current
+ * password_encryption setting. The idea is that most genuine users
+ * probably have a password of that type, and if we pretend that this user
+ * had a password of that type, too, it "blends in" best.
+ */
+ if (!shadow_pass)
+ pwtype = Password_encryption;
+ else
+ pwtype = get_password_type(shadow_pass);
+
+ /*
+ * If 'md5' authentication is allowed, decide whether to perform 'md5' or
+ * 'scram-sha-256' authentication based on the type of password the user
+ * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
+ * SCRAM verifier, we must do SCRAM authentication.
+ *
+ * If MD5 authentication is not allowed, always use SCRAM. If the user
+ * had an MD5 password, CheckSCRAMAuth() will fail.
+ */
+ if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
+ auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
+ else
+ auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
+
+ if (shadow_pass)
+ pfree(shadow_pass);
+
+ /*
+ * If get_role_password() returned error, return error, even if the
+ * authentication succeeded.
+ */
+ if (!shadow_pass)
+ {
+ Assert(auth_result != STATUS_OK);
+ return STATUS_ERROR;
+ }
+ return auth_result;
+}
+
+static int
+CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
+{
+ char md5Salt[4]; /* Password salt */
+ char *passwd;
+ int result;
+
+ if (Db_user_namespace)
+ ereport(FATAL,
+ (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
+ errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
+
+ /* include the salt to use for computing the response */
+ if (!pg_backend_random(md5Salt, 4))
+ {
+ ereport(LOG,
+ (errmsg("could not generate random MD5 salt")));
+ return STATUS_ERROR;
+ }
+
+ sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
+
+ passwd = recv_password_packet(port);
if (passwd == NULL)
return STATUS_EOF; /* client wouldn't send password */
- result = md5_crypt_verify(port, port->user_name, passwd, logdetail);
+ if (shadow_pass)
+ result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
+ md5Salt, 4, logdetail);
+ else
+ result = STATUS_ERROR;
pfree(passwd);
return result;
}
+static int
+CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
+{
+ int mtype;
+ StringInfoData buf;
+ void *scram_opaq;
+ char *output = NULL;
+ int outputlen = 0;
+ char *input;
+ int inputlen;
+ int result;
+ bool initial;
+
+ /*
+ * SASL auth is not supported for protocol versions before 3, because it
+ * relies on the overall message length word to determine the SASL payload
+ * size in AuthenticationSASLContinue and PasswordMessage messages. (We
+ * used to have a hard rule that protocol messages must be parsable
+ * without relying on the length word, but we hardly care about older
+ * protocol version anymore.)
+ */
+ if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
+ ereport(FATAL,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("SASL authentication is not supported in protocol version 2")));
+
+ /*
+ * Send the SASL authentication request to user. It includes the list of
+ * authentication mechanisms (which is trivial, because we only support
+ * SCRAM-SHA-256 at the moment). The extra "\0" is for an empty string to
+ * terminate the list.
+ */
+ sendAuthRequest(port, AUTH_REQ_SASL, SCRAM_SHA256_NAME "\0",
+ strlen(SCRAM_SHA256_NAME) + 2);
+
+ /*
+ * Initialize the status tracker for message exchanges.
+ *
+ * If the user doesn't exist, or doesn't have a valid password, or it's
+ * expired, we still go through the motions of SASL authentication, but
+ * tell the authentication method that the authentication is "doomed".
+ * That is, it's going to fail, no matter what.
+ *
+ * This is because we don't want to reveal to an attacker what usernames
+ * are valid, nor which users have a valid password.
+ */
+ scram_opaq = pg_be_scram_init(port->user_name, shadow_pass);
+
+ /*
+ * Loop through SASL message exchange. This exchange can consist of
+ * multiple messages sent in both directions. First message is always
+ * from the client. All messages from client to server are password
+ * packets (type 'p').
+ */
+ initial = true;
+ do
+ {
+ pq_startmsgread();
+ mtype = pq_getbyte();
+ if (mtype != 'p')
+ {
+ /* Only log error if client didn't disconnect. */
+ if (mtype != EOF)
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("expected SASL response, got message type %d",
+ mtype)));
+ return STATUS_ERROR;
+ }
+ else
+ return STATUS_EOF;
+ }
+
+ /* Get the actual SASL message */
+ initStringInfo(&buf);
+ if (pq_getmessage(&buf, PG_MAX_SASL_MESSAGE_LENGTH))
+ {
+ /* EOF - pq_getmessage already logged error */
+ pfree(buf.data);
+ return STATUS_ERROR;
+ }
+
+ elog(DEBUG4, "Processing received SASL response of length %d", buf.len);
+
+ /*
+ * The first SASLInitialResponse message is different from the others.
+ * It indicates which SASL mechanism the client selected, and contains
+ * an optional Initial Client Response payload. The subsequent
+ * SASLResponse messages contain just the SASL payload.
+ */
+ if (initial)
+ {
+ const char *selected_mech;
+
+ /*
+ * We only support SCRAM-SHA-256 at the moment, so anything else
+ * is an error.
+ */
+ selected_mech = pq_getmsgrawstring(&buf);
+ if (strcmp(selected_mech, SCRAM_SHA256_NAME) != 0)
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("client selected an invalid SASL authentication mechanism")));
+ pfree(buf.data);
+ return STATUS_ERROR;
+ }
+
+ inputlen = pq_getmsgint(&buf, 4);
+ if (inputlen == -1)
+ input = NULL;
+ else
+ input = (char *) pq_getmsgbytes(&buf, inputlen);
+
+ initial = false;
+ }
+ else
+ {
+ inputlen = buf.len;
+ input = (char *) pq_getmsgbytes(&buf, buf.len);
+ }
+ pq_getmsgend(&buf);
+
+ /*
+ * The StringInfo guarantees that there's a \0 byte after the
+ * response.
+ */
+ Assert(input == NULL || input[inputlen] == '\0');
+
+ /*
+ * we pass 'logdetail' as NULL when doing a mock authentication,
+ * because we should already have a better error message in that case
+ */
+ result = pg_be_scram_exchange(scram_opaq, input, inputlen,
+ &output, &outputlen,
+ logdetail);
+
+ /* input buffer no longer used */
+ pfree(buf.data);
+
+ if (output)
+ {
+ /*
+ * Negotiation generated data to be sent to the client.
+ */
+ elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
+
+ if (result == SASL_EXCHANGE_SUCCESS)
+ sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
+ else
+ sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
+
+ pfree(output);
+ }
+ } while (result == SASL_EXCHANGE_CONTINUE);
+
+ /* Oops, Something bad happened */
+ if (result != SASL_EXCHANGE_SUCCESS)
+ {
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
/*----------------------------------------------------------------
@@ -742,7 +1006,7 @@ recv_and_check_password_packet(Port *port, char **logdetail)
*/
#ifdef ENABLE_GSS
-#if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
+#if defined(WIN32) && !defined(_MSC_VER)
/*
* MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
* that contain the OIDs required. Redefine here, values copied
@@ -934,7 +1198,8 @@ pg_GSS_recvauth(Port *port)
elog(DEBUG4, "sending GSS response token of length %u",
(unsigned int) port->gss->outbuf.length);
- sendAuthRequest(port, AUTH_REQ_GSS_CONT);
+ sendAuthRequest(port, AUTH_REQ_GSS_CONT,
+ port->gss->outbuf.value, port->gss->outbuf.length);
gss_release_buffer(&lmin_s, &port->gss->outbuf);
}
@@ -1179,7 +1444,8 @@ pg_SSPI_recvauth(Port *port)
port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
- sendAuthRequest(port, AUTH_REQ_GSS_CONT);
+ sendAuthRequest(port, AUTH_REQ_GSS_CONT,
+ port->gss->outbuf.value, port->gss->outbuf.length);
FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
}
@@ -1807,7 +2073,7 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
* let's go ask the client to send a password, which we
* then stuff into PAM.
*/
- sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
+ sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD, NULL, 0);
passwd = recv_password_packet(pam_port_cludge);
if (passwd == NULL)
{
@@ -2000,7 +2266,7 @@ CheckBSDAuth(Port *port, char *user)
int retval;
/* Send regular password request to client, and get the response */
- sendAuthRequest(port, AUTH_REQ_PASSWORD);
+ sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
passwd = recv_password_packet(port);
if (passwd == NULL)
@@ -2137,7 +2403,7 @@ CheckLDAPAuth(Port *port)
if (port->hba->ldapport == 0)
port->hba->ldapport = LDAP_PORT;
- sendAuthRequest(port, AUTH_REQ_PASSWORD);
+ sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
passwd = recv_password_packet(port);
if (passwd == NULL)
@@ -2352,14 +2618,16 @@ CheckCertAuth(Port *port)
*/
/*
- * RADIUS authentication is described in RFC2865 (and several
- * others).
+ * RADIUS authentication is described in RFC2865 (and several others).
*/
#define RADIUS_VECTOR_LENGTH 16
#define RADIUS_HEADER_LENGTH 20
#define RADIUS_MAX_PASSWORD_LENGTH 128
+/* Maximum size of a RADIUS packet we will create or accept */
+#define RADIUS_BUFFER_SIZE 1024
+
typedef struct
{
uint8 attribute;
@@ -2373,6 +2641,8 @@ typedef struct
uint8 id;
uint16 length;
uint8 vector[RADIUS_VECTOR_LENGTH];
+ /* this is a bit longer than strictly necessary: */
+ char pad[RADIUS_BUFFER_SIZE - RADIUS_VECTOR_LENGTH];
} radius_packet;
/* RADIUS packet types */
@@ -2389,9 +2659,6 @@ typedef struct
/* RADIUS service types */
#define RADIUS_AUTHENTICATE_ONLY 8
-/* Maximum size of a RADIUS packet we will create or accept */
-#define RADIUS_BUFFER_SIZE 1024
-
/* Seconds to wait - XXX: should be in a config variable! */
#define RADIUS_TIMEOUT 3
@@ -2425,11 +2692,103 @@ static int
CheckRADIUSAuth(Port *port)
{
char *passwd;
- char *identifier = "postgresql";
- char radius_buffer[RADIUS_BUFFER_SIZE];
- char receive_buffer[RADIUS_BUFFER_SIZE];
- radius_packet *packet = (radius_packet *) radius_buffer;
- radius_packet *receivepacket = (radius_packet *) receive_buffer;
+ ListCell *server,
+ *secrets,
+ *radiusports,
+ *identifiers;
+
+ /* Make sure struct alignment is correct */
+ Assert(offsetof(radius_packet, vector) == 4);
+
+ /* Verify parameters */
+ if (list_length(port->hba->radiusservers) < 1)
+ {
+ ereport(LOG,
+ (errmsg("RADIUS server not specified")));
+ return STATUS_ERROR;
+ }
+
+ if (list_length(port->hba->radiussecrets) < 1)
+ {
+ ereport(LOG,
+ (errmsg("RADIUS secret not specified")));
+ return STATUS_ERROR;
+ }
+
+ /* Send regular password request to client, and get the response */
+ sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
+
+ passwd = recv_password_packet(port);
+ if (passwd == NULL)
+ return STATUS_EOF; /* client wouldn't send password */
+
+ if (strlen(passwd) == 0)
+ {
+ ereport(LOG,
+ (errmsg("empty password returned by client")));
+ return STATUS_ERROR;
+ }
+
+ if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
+ {
+ ereport(LOG,
+ (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
+ return STATUS_ERROR;
+ }
+
+ /*
+ * Loop over and try each server in order.
+ */
+ secrets = list_head(port->hba->radiussecrets);
+ radiusports = list_head(port->hba->radiusports);
+ identifiers = list_head(port->hba->radiusidentifiers);
+ foreach(server, port->hba->radiusservers)
+ {
+ int ret = PerformRadiusTransaction(lfirst(server),
+ lfirst(secrets),
+ radiusports ? lfirst(radiusports) : NULL,
+ identifiers ? lfirst(identifiers) : NULL,
+ port->user_name,
+ passwd);
+
+ /*------
+ * STATUS_OK = Login OK
+ * STATUS_ERROR = Login not OK, but try next server
+ * STATUS_EOF = Login not OK, and don't try next server
+ *------
+ */
+ if (ret == STATUS_OK)
+ return STATUS_OK;
+ else if (ret == STATUS_EOF)
+ return STATUS_ERROR;
+
+ /*
+ * secret, port and identifiers either have length 0 (use default),
+ * length 1 (use the same everywhere) or the same length as servers.
+ * So if the length is >1, we advance one step. In other cases, we
+ * don't and will then reuse the correct value.
+ */
+ if (list_length(port->hba->radiussecrets) > 1)
+ secrets = lnext(secrets);
+ if (list_length(port->hba->radiusports) > 1)
+ radiusports = lnext(radiusports);
+ if (list_length(port->hba->radiusidentifiers) > 1)
+ identifiers = lnext(identifiers);
+ }
+
+ /* No servers left to try, so give up */
+ return STATUS_ERROR;
+}
+
+static int
+PerformRadiusTransaction(char *server, char *secret, char *portstr, char *identifier, char *user_name, char *passwd)
+{
+ radius_packet radius_send_pack;
+ radius_packet radius_recv_pack;
+ radius_packet *packet = &radius_send_pack;
+ radius_packet *receivepacket = &radius_recv_pack;
+ char *radius_buffer = (char *) &radius_send_pack;
+ char *receive_buffer = (char *) &radius_recv_pack;
int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
uint8 *cryptvector;
int encryptedpasswordlen;
@@ -2447,7 +2806,7 @@ CheckRADIUSAuth(Port *port)
#endif
struct addrinfo hint;
struct addrinfo *serveraddrs;
- char portstr[128];
+ int port;
ACCEPT_TYPE_ARG3 addrsize;
fd_set fdset;
struct timeval endtime;
@@ -2455,87 +2814,42 @@ CheckRADIUSAuth(Port *port)
j,
r;
- /* Make sure struct alignment is correct */
- Assert(offsetof(radius_packet, vector) == 4);
-
- /* Verify parameters */
- if (!port->hba->radiusserver || port->hba->radiusserver[0] == '\0')
- {
- ereport(LOG,
- (errmsg("RADIUS server not specified")));
- return STATUS_ERROR;
- }
-
- if (!port->hba->radiussecret || port->hba->radiussecret[0] == '\0')
- {
- ereport(LOG,
- (errmsg("RADIUS secret not specified")));
- return STATUS_ERROR;
- }
-
- if (port->hba->radiusport == 0)
- port->hba->radiusport = 1812;
+ /* Assign default values */
+ if (portstr == NULL)
+ portstr = "1812";
+ if (identifier == NULL)
+ identifier = "postgresql";
MemSet(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_DGRAM;
hint.ai_family = AF_UNSPEC;
- snprintf(portstr, sizeof(portstr), "%d", port->hba->radiusport);
+ port = atoi(portstr);
- r = pg_getaddrinfo_all(port->hba->radiusserver, portstr, &hint, &serveraddrs);
+ r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
if (r || !serveraddrs)
{
ereport(LOG,
(errmsg("could not translate RADIUS server name \"%s\" to address: %s",
- port->hba->radiusserver, gai_strerror(r))));
+ server, gai_strerror(r))));
if (serveraddrs)
pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
/* XXX: add support for multiple returned addresses? */
- if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
- identifier = port->hba->radiusidentifier;
-
- /* Send regular password request to client, and get the response */
- sendAuthRequest(port, AUTH_REQ_PASSWORD);
-
- passwd = recv_password_packet(port);
- if (passwd == NULL)
- return STATUS_EOF; /* client wouldn't send password */
-
- if (strlen(passwd) == 0)
- {
- ereport(LOG,
- (errmsg("empty password returned by client")));
- return STATUS_ERROR;
- }
-
- if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
- {
- ereport(LOG,
- (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
- return STATUS_ERROR;
- }
-
-
/* Construct RADIUS packet */
packet->code = RADIUS_ACCESS_REQUEST;
packet->length = RADIUS_HEADER_LENGTH;
-#ifdef USE_OPENSSL
- if (RAND_bytes(packet->vector, RADIUS_VECTOR_LENGTH) != 1)
+ if (!pg_backend_random((char *) packet->vector, RADIUS_VECTOR_LENGTH))
{
ereport(LOG,
(errmsg("could not generate random encryption vector")));
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
-#else
- for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
- /* Use a lower strengh random number of OpenSSL is not available */
- packet->vector[i] = random() % 255;
-#endif
packet->id = packet->vector[0];
radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (unsigned char *) &service, sizeof(service));
- radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) port->user_name, strlen(port->user_name));
+ radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) user_name, strlen(user_name));
radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
/*
@@ -2545,14 +2859,14 @@ CheckRADIUSAuth(Port *port)
* (if necessary)
*/
encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
- cryptvector = palloc(strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH);
- memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
+ cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
+ memcpy(cryptvector, secret, strlen(secret));
/* for the first iteration, we use the Request Authenticator vector */
md5trailer = packet->vector;
for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
{
- memcpy(cryptvector + strlen(port->hba->radiussecret), md5trailer, RADIUS_VECTOR_LENGTH);
+ memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
/*
* .. and for subsequent iterations the result of the previous XOR
@@ -2560,11 +2874,12 @@ CheckRADIUSAuth(Port *port)
*/
md5trailer = encryptedpassword + i;
- if (!pg_md5_binary(cryptvector, strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
+ if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
{
ereport(LOG,
(errmsg("could not perform MD5 encryption of password")));
pfree(cryptvector);
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
@@ -2580,7 +2895,7 @@ CheckRADIUSAuth(Port *port)
radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
- /* Length need to be in network order on the wire */
+ /* Length needs to be in network order on the wire */
packetlength = packet->length;
packet->length = htons(packet->length);
@@ -2606,6 +2921,7 @@ CheckRADIUSAuth(Port *port)
localaddr.sin_addr.s_addr = INADDR_ANY;
addrsize = sizeof(struct sockaddr_in);
#endif
+
if (bind(sock, (struct sockaddr *) & localaddr, addrsize))
{
ereport(LOG,
@@ -2652,7 +2968,8 @@ CheckRADIUSAuth(Port *port)
if (timeoutval <= 0)
{
ereport(LOG,
- (errmsg("timeout waiting for RADIUS response")));
+ (errmsg("timeout waiting for RADIUS response from %s",
+ server)));
closesocket(sock);
return STATUS_ERROR;
}
@@ -2677,7 +2994,8 @@ CheckRADIUSAuth(Port *port)
if (r == 0)
{
ereport(LOG,
- (errmsg("timeout waiting for RADIUS response")));
+ (errmsg("timeout waiting for RADIUS response from %s",
+ server)));
closesocket(sock);
return STATUS_ERROR;
}
@@ -2700,23 +3018,24 @@ CheckRADIUSAuth(Port *port)
{
ereport(LOG,
(errmsg("could not read RADIUS response: %m")));
+ closesocket(sock);
return STATUS_ERROR;
}
#ifdef HAVE_IPV6
- if (remoteaddr.sin6_port != htons(port->hba->radiusport))
+ if (remoteaddr.sin6_port != htons(port))
#else
- if (remoteaddr.sin_port != htons(port->hba->radiusport))
+ if (remoteaddr.sin_port != htons(port))
#endif
{
#ifdef HAVE_IPV6
ereport(LOG,
- (errmsg("RADIUS response was sent from incorrect port: %d",
- ntohs(remoteaddr.sin6_port))));
+ (errmsg("RADIUS response from %s was sent from incorrect port: %d",
+ server, ntohs(remoteaddr.sin6_port))));
#else
ereport(LOG,
- (errmsg("RADIUS response was sent from incorrect port: %d",
- ntohs(remoteaddr.sin_port))));
+ (errmsg("RADIUS response from %s was sent from incorrect port: %d",
+ server, ntohs(remoteaddr.sin_port))));
#endif
continue;
}
@@ -2724,23 +3043,23 @@ CheckRADIUSAuth(Port *port)
if (packetlength < RADIUS_HEADER_LENGTH)
{
ereport(LOG,
- (errmsg("RADIUS response too short: %d", packetlength)));
+ (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
continue;
}
if (packetlength != ntohs(receivepacket->length))
{
ereport(LOG,
- (errmsg("RADIUS response has corrupt length: %d (actual length %d)",
- ntohs(receivepacket->length), packetlength)));
+ (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
+ server, ntohs(receivepacket->length), packetlength)));
continue;
}
if (packet->id != receivepacket->id)
{
ereport(LOG,
- (errmsg("RADIUS response is to a different request: %d (should be %d)",
- receivepacket->id, packet->id)));
+ (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
+ server, receivepacket->id, packet->id)));
continue;
}
@@ -2748,7 +3067,7 @@ CheckRADIUSAuth(Port *port)
* Verify the response authenticator, which is calculated as
* MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
*/
- cryptvector = palloc(packetlength + strlen(port->hba->radiussecret));
+ cryptvector = palloc(packetlength + strlen(secret));
memcpy(cryptvector, receivepacket, 4); /* code+id+length */
memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
@@ -2757,10 +3076,10 @@ CheckRADIUSAuth(Port *port)
if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
* attributes at all */
memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
- memcpy(cryptvector + packetlength, port->hba->radiussecret, strlen(port->hba->radiussecret));
+ memcpy(cryptvector + packetlength, secret, strlen(secret));
if (!pg_md5_binary(cryptvector,
- packetlength + strlen(port->hba->radiussecret),
+ packetlength + strlen(secret),
encryptedpassword))
{
ereport(LOG,
@@ -2773,7 +3092,8 @@ CheckRADIUSAuth(Port *port)
if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
{
ereport(LOG,
- (errmsg("RADIUS response has incorrect MD5 signature")));
+ (errmsg("RADIUS response from %s has incorrect MD5 signature",
+ server)));
continue;
}
@@ -2785,13 +3105,13 @@ CheckRADIUSAuth(Port *port)
else if (receivepacket->code == RADIUS_ACCESS_REJECT)
{
closesocket(sock);
- return STATUS_ERROR;
+ return STATUS_EOF;
}
else
{
ereport(LOG,
- (errmsg("RADIUS response has invalid code (%d) for user \"%s\"",
- receivepacket->code, port->user_name)));
+ (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
+ server, receivepacket->code, user_name)));
continue;
}
} /* while (true) */
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index 75fc3b4845..4773b18df9 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -3,7 +3,7 @@
* be-fsstubs.c
* Builtin functions for open/close/read/write operations on large objects
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -79,9 +79,7 @@ static MemoryContext fscxt = NULL;
if (fscxt == NULL) \
fscxt = AllocSetContextCreate(TopMemoryContext, \
"Filesystem", \
- ALLOCSET_DEFAULT_MINSIZE, \
- ALLOCSET_DEFAULT_INITSIZE, \
- ALLOCSET_DEFAULT_MAXSIZE); \
+ ALLOCSET_DEFAULT_SIZES); \
} while (0)
@@ -95,7 +93,7 @@ static Oid lo_import_internal(text *filename, Oid lobjOid);
*****************************************************************************/
Datum
-lo_open(PG_FUNCTION_ARGS)
+be_lo_open(PG_FUNCTION_ARGS)
{
Oid lobjId = PG_GETARG_OID(0);
int32 mode = PG_GETARG_INT32(1);
@@ -131,7 +129,7 @@ lo_open(PG_FUNCTION_ARGS)
}
Datum
-lo_close(PG_FUNCTION_ARGS)
+be_lo_close(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
@@ -254,7 +252,7 @@ lo_write(int fd, const char *buf, int len)
}
Datum
-lo_lseek(PG_FUNCTION_ARGS)
+be_lo_lseek(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int32 offset = PG_GETARG_INT32(1);
@@ -279,7 +277,7 @@ lo_lseek(PG_FUNCTION_ARGS)
}
Datum
-lo_lseek64(PG_FUNCTION_ARGS)
+be_lo_lseek64(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int64 offset = PG_GETARG_INT64(1);
@@ -304,7 +302,7 @@ lo_lseek64(PG_FUNCTION_ARGS)
}
Datum
-lo_creat(PG_FUNCTION_ARGS)
+be_lo_creat(PG_FUNCTION_ARGS)
{
Oid lobjId;
@@ -327,7 +325,7 @@ lo_creat(PG_FUNCTION_ARGS)
}
Datum
-lo_create(PG_FUNCTION_ARGS)
+be_lo_create(PG_FUNCTION_ARGS)
{
Oid lobjId = PG_GETARG_OID(0);
@@ -350,7 +348,7 @@ lo_create(PG_FUNCTION_ARGS)
}
Datum
-lo_tell(PG_FUNCTION_ARGS)
+be_lo_tell(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int64 offset;
@@ -380,7 +378,7 @@ lo_tell(PG_FUNCTION_ARGS)
}
Datum
-lo_tell64(PG_FUNCTION_ARGS)
+be_lo_tell64(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int64 offset;
@@ -396,7 +394,7 @@ lo_tell64(PG_FUNCTION_ARGS)
}
Datum
-lo_unlink(PG_FUNCTION_ARGS)
+be_lo_unlink(PG_FUNCTION_ARGS)
{
Oid lobjId = PG_GETARG_OID(0);
@@ -443,7 +441,7 @@ lo_unlink(PG_FUNCTION_ARGS)
*****************************************************************************/
Datum
-loread(PG_FUNCTION_ARGS)
+be_loread(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int32 len = PG_GETARG_INT32(1);
@@ -468,10 +466,10 @@ loread(PG_FUNCTION_ARGS)
}
Datum
-lowrite(PG_FUNCTION_ARGS)
+be_lowrite(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
- bytea *wbuf = PG_GETARG_BYTEA_P(1);
+ bytea *wbuf = PG_GETARG_BYTEA_PP(1);
int bytestowrite;
int totalwritten;
@@ -481,9 +479,8 @@ lowrite(PG_FUNCTION_ARGS)
errmsg("Postgres-XL does not yet support large objects"),
errdetail("The feature is not currently supported")));
#endif
-
- bytestowrite = VARSIZE(wbuf) - VARHDRSZ;
- totalwritten = lo_write(fd, VARDATA(wbuf), bytestowrite);
+ bytestowrite = VARSIZE_ANY_EXHDR(wbuf);
+ totalwritten = lo_write(fd, VARDATA_ANY(wbuf), bytestowrite);
PG_RETURN_INT32(totalwritten);
}
@@ -496,7 +493,7 @@ lowrite(PG_FUNCTION_ARGS)
* imports a file as an (inversion) large object.
*/
Datum
-lo_import(PG_FUNCTION_ARGS)
+be_lo_import(PG_FUNCTION_ARGS)
{
text *filename = PG_GETARG_TEXT_PP(0);
@@ -515,7 +512,7 @@ lo_import(PG_FUNCTION_ARGS)
* imports a file as an (inversion) large object specifying oid.
*/
Datum
-lo_import_with_oid(PG_FUNCTION_ARGS)
+be_lo_import_with_oid(PG_FUNCTION_ARGS)
{
text *filename = PG_GETARG_TEXT_PP(0);
Oid oid = PG_GETARG_OID(1);
@@ -595,7 +592,7 @@ lo_import_internal(text *filename, Oid lobjOid)
* exports an (inversion) large object.
*/
Datum
-lo_export(PG_FUNCTION_ARGS)
+be_lo_export(PG_FUNCTION_ARGS)
{
Oid lobjId = PG_GETARG_OID(0);
text *filename = PG_GETARG_TEXT_PP(1);
@@ -713,7 +710,7 @@ lo_truncate_internal(int32 fd, int64 len)
}
Datum
-lo_truncate(PG_FUNCTION_ARGS)
+be_lo_truncate(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int32 len = PG_GETARG_INT32(1);
@@ -723,7 +720,7 @@ lo_truncate(PG_FUNCTION_ARGS)
}
Datum
-lo_truncate64(PG_FUNCTION_ARGS)
+be_lo_truncate64(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int64 len = PG_GETARG_INT64(1);
@@ -935,7 +932,7 @@ lo_get_fragment_internal(Oid loOid, int64 offset, int32 nbytes)
* Read entire LO
*/
Datum
-lo_get(PG_FUNCTION_ARGS)
+be_lo_get(PG_FUNCTION_ARGS)
{
Oid loOid = PG_GETARG_OID(0);
bytea *result;
@@ -956,7 +953,7 @@ lo_get(PG_FUNCTION_ARGS)
* Read range within LO
*/
Datum
-lo_get_fragment(PG_FUNCTION_ARGS)
+be_lo_get_fragment(PG_FUNCTION_ARGS)
{
Oid loOid = PG_GETARG_OID(0);
int64 offset = PG_GETARG_INT64(1);
@@ -984,7 +981,7 @@ lo_get_fragment(PG_FUNCTION_ARGS)
* Create LO with initial contents given by a bytea argument
*/
Datum
-lo_from_bytea(PG_FUNCTION_ARGS)
+be_lo_from_bytea(PG_FUNCTION_ARGS)
{
Oid loOid = PG_GETARG_OID(0);
bytea *str = PG_GETARG_BYTEA_PP(1);
@@ -1013,7 +1010,7 @@ lo_from_bytea(PG_FUNCTION_ARGS)
* Update range within LO
*/
Datum
-lo_put(PG_FUNCTION_ARGS)
+be_lo_put(PG_FUNCTION_ARGS)
{
Oid loOid = PG_GETARG_OID(0);
int64 offset = PG_GETARG_INT64(1);
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index f6adb155c6..44c84a7869 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -4,7 +4,7 @@
* functions for OpenSSL support in the backend.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -53,15 +53,14 @@
#include <openssl/ssl.h>
#include <openssl/dh.h>
-#if SSLEAY_VERSION_NUMBER >= 0x0907000L
#include <openssl/conf.h>
-#endif
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH)
+#ifndef OPENSSL_NO_ECDH
#include <openssl/ec.h>
#endif
#include "libpq/libpq.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/latch.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
@@ -74,15 +73,19 @@ static int my_SSL_set_fd(Port *port, int fd);
static DH *load_dh_file(int keylength);
static DH *load_dh_buffer(const char *, size_t);
+static DH *generate_dh_parameters(int prime_len, int generator);
static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
+static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
static int verify_cb(int, X509_STORE_CTX *);
static void info_cb(const SSL *ssl, int type, int args);
-static void initialize_ecdh(void);
+static bool initialize_ecdh(SSL_CTX *context, bool isServerStart);
static const char *SSLerrmessage(unsigned long ecode);
static char *X509_NAME_to_cstring(X509_NAME *name);
static SSL_CTX *SSL_context = NULL;
+static bool SSL_initialized = false;
+static bool ssl_passwd_cb_called = false;
/* ------------------------------------------------------------ */
/* Hardcoded values */
@@ -156,136 +159,200 @@ KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
/*
* Initialize global SSL context.
+ *
+ * If isServerStart is true, report any errors as FATAL (so we don't return).
+ * Otherwise, log errors at LOG level and return -1 to indicate trouble,
+ * preserving the old SSL state if any. Returns 0 if OK.
*/
-void
-be_tls_init(void)
+int
+be_tls_init(bool isServerStart)
{
- struct stat buf;
-
STACK_OF(X509_NAME) *root_cert_list = NULL;
+ SSL_CTX *context;
+ struct stat buf;
- if (!SSL_context)
+ /* This stuff need be done only once. */
+ if (!SSL_initialized)
{
-#if SSLEAY_VERSION_NUMBER >= 0x0907000L
+#ifdef HAVE_OPENSSL_INIT_SSL
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#else
OPENSSL_config(NULL);
-#endif
SSL_library_init();
SSL_load_error_strings();
+#endif
+ SSL_initialized = true;
+ }
- /*
- * We use SSLv23_method() because it can negotiate use of the highest
- * mutually supported protocol version, while alternatives like
- * TLSv1_2_method() permit only one specific version. Note that we
- * don't actually allow SSL v2 or v3, only TLS protocols (see below).
- */
- SSL_context = SSL_CTX_new(SSLv23_method());
- if (!SSL_context)
- ereport(FATAL,
- (errmsg("could not create SSL context: %s",
- SSLerrmessage(ERR_get_error()))));
+ /*
+ * We use SSLv23_method() because it can negotiate use of the highest
+ * mutually supported protocol version, while alternatives like
+ * TLSv1_2_method() permit only one specific version. Note that we don't
+ * actually allow SSL v2 or v3, only TLS protocols (see below).
+ */
+ context = SSL_CTX_new(SSLv23_method());
+ if (!context)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errmsg("could not create SSL context: %s",
+ SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
- /*
- * Disable OpenSSL's moving-write-buffer sanity check, because it
- * causes unnecessary failures in nonblocking send cases.
- */
- SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ /*
+ * Disable OpenSSL's moving-write-buffer sanity check, because it causes
+ * unnecessary failures in nonblocking send cases.
+ */
+ SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
- /*
- * Load and verify server's certificate and private key
- */
- if (SSL_CTX_use_certificate_chain_file(SSL_context,
- ssl_cert_file) != 1)
- ereport(FATAL,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("could not load server certificate file \"%s\": %s",
- ssl_cert_file, SSLerrmessage(ERR_get_error()))));
+ /*
+ * If reloading, override OpenSSL's default handling of
+ * passphrase-protected files, because we don't want to prompt for a
+ * passphrase in an already-running server. (Not that the default
+ * handling is very desirable during server start either, but some people
+ * insist we need to keep it.)
+ */
+ if (!isServerStart)
+ SSL_CTX_set_default_passwd_cb(context, ssl_passwd_cb);
- if (stat(ssl_key_file, &buf) != 0)
- ereport(FATAL,
- (errcode_for_file_access(),
- errmsg("could not access private key file \"%s\": %m",
- ssl_key_file)));
+ /*
+ * Load and verify server's certificate and private key
+ */
+ if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_file) != 1)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not load server certificate file \"%s\": %s",
+ ssl_cert_file, SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
- if (!S_ISREG(buf.st_mode))
- ereport(FATAL,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("private key file \"%s\" is not a regular file",
- ssl_key_file)));
+ if (stat(ssl_key_file, &buf) != 0)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode_for_file_access(),
+ errmsg("could not access private key file \"%s\": %m",
+ ssl_key_file)));
+ goto error;
+ }
- /*
- * Refuse to load files owned by users other than us or root.
- *
- * XXX surely we can check this on Windows somehow, too.
- */
+ if (!S_ISREG(buf.st_mode))
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("private key file \"%s\" is not a regular file",
+ ssl_key_file)));
+ goto error;
+ }
+
+ /*
+ * Refuse to load key files owned by users other than us or root.
+ *
+ * XXX surely we can check this on Windows somehow, too.
+ */
#if !defined(WIN32) && !defined(__CYGWIN__)
- if (buf.st_uid != geteuid() && buf.st_uid != 0)
- ereport(FATAL,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("private key file \"%s\" must be owned by the database user or root",
- ssl_key_file)));
+ if (buf.st_uid != geteuid() && buf.st_uid != 0)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("private key file \"%s\" must be owned by the database user or root",
+ ssl_key_file)));
+ goto error;
+ }
#endif
- /*
- * Require no public access to key file. If the file is owned by us,
- * require mode 0600 or less. If owned by root, require 0640 or less
- * to allow read access through our gid, or a supplementary gid that
- * allows to read system-wide certificates.
- *
- * XXX temporarily suppress check when on Windows, because there may
- * not be proper support for Unix-y file permissions. Need to think
- * of a reasonable check to apply on Windows. (See also the data
- * directory permission check in postmaster.c)
- */
+ /*
+ * Require no public access to key file. If the file is owned by us,
+ * require mode 0600 or less. If owned by root, require 0640 or less to
+ * allow read access through our gid, or a supplementary gid that allows
+ * to read system-wide certificates.
+ *
+ * XXX temporarily suppress check when on Windows, because there may not
+ * be proper support for Unix-y file permissions. Need to think of a
+ * reasonable check to apply on Windows. (See also the data directory
+ * permission check in postmaster.c)
+ */
#if !defined(WIN32) && !defined(__CYGWIN__)
- if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
- (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
- ereport(FATAL,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("private key file \"%s\" has group or world access",
- ssl_key_file),
- errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
+ if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
+ (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("private key file \"%s\" has group or world access",
+ ssl_key_file),
+ errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
+ goto error;
+ }
#endif
- if (SSL_CTX_use_PrivateKey_file(SSL_context,
- ssl_key_file,
- SSL_FILETYPE_PEM) != 1)
- ereport(FATAL,
- (errmsg("could not load private key file \"%s\": %s",
+ /*
+ * OK, try to load the private key file.
+ */
+ ssl_passwd_cb_called = false;
+
+ if (SSL_CTX_use_PrivateKey_file(context,
+ ssl_key_file,
+ SSL_FILETYPE_PEM) != 1)
+ {
+ if (ssl_passwd_cb_called)
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase",
+ ssl_key_file)));
+ else
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not load private key file \"%s\": %s",
ssl_key_file, SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
- if (SSL_CTX_check_private_key(SSL_context) != 1)
- ereport(FATAL,
- (errmsg("check of private key failed: %s",
- SSLerrmessage(ERR_get_error()))));
+ if (SSL_CTX_check_private_key(context) != 1)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("check of private key failed: %s",
+ SSLerrmessage(ERR_get_error()))));
+ goto error;
}
/* set up ephemeral DH keys, and disallow SSL v2/v3 while at it */
- SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
- SSL_CTX_set_options(SSL_context,
+ SSL_CTX_set_tmp_dh_callback(context, tmp_dh_cb);
+ SSL_CTX_set_options(context,
SSL_OP_SINGLE_DH_USE |
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
/* set up ephemeral ECDH keys */
- initialize_ecdh();
+ if (!initialize_ecdh(context, isServerStart))
+ goto error;
/* set up the allowed cipher list */
- if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1)
- elog(FATAL, "could not set the cipher list (no valid ciphers available)");
+ if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not set the cipher list (no valid ciphers available)")));
+ goto error;
+ }
/* Let server choose order */
if (SSLPreferServerCiphers)
- SSL_CTX_set_options(SSL_context, SSL_OP_CIPHER_SERVER_PREFERENCE);
+ SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
/*
* Load CA store, so we can verify client certificates if needed.
*/
if (ssl_ca_file[0])
{
- if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 ||
+ if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 ||
(root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
- ereport(FATAL,
- (errmsg("could not load root certificate file \"%s\": %s",
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not load root certificate file \"%s\": %s",
ssl_ca_file, SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
}
/*----------
@@ -295,7 +362,7 @@ be_tls_init(void)
*/
if (ssl_crl_file[0])
{
- X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context);
+ X509_STORE *cvstore = SSL_CTX_get_cert_store(context);
if (cvstore)
{
@@ -308,15 +375,20 @@ be_tls_init(void)
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
#else
ereport(LOG,
- (errmsg("SSL certificate revocation list file \"%s\" ignored",
- ssl_crl_file),
- errdetail("SSL library does not support certificate revocation lists.")));
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("SSL certificate revocation list file \"%s\" ignored",
+ ssl_crl_file),
+ errdetail("SSL library does not support certificate revocation lists.")));
#endif
}
else
- ereport(FATAL,
- (errmsg("could not load SSL certificate revocation list file \"%s\": %s",
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not load SSL certificate revocation list file \"%s\": %s",
ssl_crl_file, SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
}
}
@@ -327,21 +399,53 @@ be_tls_init(void)
* presented. We might fail such connections later, depending on what
* we find in pg_hba.conf.
*/
- SSL_CTX_set_verify(SSL_context,
+ SSL_CTX_set_verify(context,
(SSL_VERIFY_PEER |
SSL_VERIFY_CLIENT_ONCE),
verify_cb);
- /* Set flag to remember CA store is successfully loaded */
- ssl_loaded_verify_locations = true;
-
/*
* Tell OpenSSL to send the list of root certs we trust to clients in
* CertificateRequests. This lets a client with a keystore select the
* appropriate client certificate to send to us.
*/
- SSL_CTX_set_client_CA_list(SSL_context, root_cert_list);
+ SSL_CTX_set_client_CA_list(context, root_cert_list);
}
+
+ /*
+ * Success! Replace any existing SSL_context.
+ */
+ if (SSL_context)
+ SSL_CTX_free(SSL_context);
+
+ SSL_context = context;
+
+ /*
+ * Set flag to remember whether CA store has been loaded into SSL_context.
+ */
+ if (ssl_ca_file[0])
+ ssl_loaded_verify_locations = true;
+ else
+ ssl_loaded_verify_locations = false;
+
+ return 0;
+
+error:
+ if (context)
+ SSL_CTX_free(context);
+ return -1;
+}
+
+/*
+ * Destroy global SSL context, if any.
+ */
+void
+be_tls_destroy(void)
+{
+ if (SSL_context)
+ SSL_CTX_free(SSL_context);
+ SSL_context = NULL;
+ ssl_loaded_verify_locations = false;
}
/*
@@ -358,6 +462,14 @@ be_tls_open_server(Port *port)
Assert(!port->ssl);
Assert(!port->peer);
+ if (!SSL_context)
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("could not initialize SSL connection: SSL context not set up")));
+ return -1;
+ }
+
if (!(port->ssl = SSL_new(SSL_context)))
{
ereport(COMMERROR,
@@ -418,7 +530,8 @@ aloop:
else
waitfor = WL_SOCKET_WRITEABLE;
- WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0);
+ WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
+ WAIT_EVENT_SSL_OPEN_SERVER);
goto aloop;
case SSL_ERROR_SYSCALL:
if (r < 0)
@@ -451,8 +564,6 @@ aloop:
return -1;
}
- port->count = 0;
-
/* Get client certificate, if available. */
port->peer = SSL_get_peer_certificate(port->ssl);
@@ -553,7 +664,7 @@ be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
switch (err)
{
case SSL_ERROR_NONE:
- port->count += n;
+ /* a-ok */
break;
case SSL_ERROR_WANT_READ:
*waitfor = WL_SOCKET_READABLE;
@@ -613,7 +724,7 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
switch (err)
{
case SSL_ERROR_NONE:
- port->count += n;
+ /* a-ok */
break;
case SSL_ERROR_WANT_READ:
*waitfor = WL_SOCKET_READABLE;
@@ -673,8 +784,12 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
* to retry; do we need to adopt their logic for that?
*/
-static bool my_bio_initialized = false;
-static BIO_METHOD my_bio_methods;
+#ifndef HAVE_BIO_GET_DATA
+#define BIO_get_data(bio) (bio->ptr)
+#define BIO_set_data(bio, data) (bio->ptr = data)
+#endif
+
+static BIO_METHOD *my_bio_methods = NULL;
static int
my_sock_read(BIO *h, char *buf, int size)
@@ -683,7 +798,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL)
{
- res = secure_raw_read(((Port *) h->ptr), buf, size);
+ res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -703,7 +818,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res = 0;
- res = secure_raw_write(((Port *) h->ptr), buf, size);
+ res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -720,14 +835,41 @@ my_sock_write(BIO *h, const char *buf, int size)
static BIO_METHOD *
my_BIO_s_socket(void)
{
- if (!my_bio_initialized)
+ if (!my_bio_methods)
{
- memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
- my_bio_methods.bread = my_sock_read;
- my_bio_methods.bwrite = my_sock_write;
- my_bio_initialized = true;
+ BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
+#ifdef HAVE_BIO_METH_NEW
+ int my_bio_index;
+
+ my_bio_index = BIO_get_new_index();
+ if (my_bio_index == -1)
+ return NULL;
+ my_bio_methods = BIO_meth_new(my_bio_index, "PostgreSQL backend socket");
+ if (!my_bio_methods)
+ return NULL;
+ if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
+ !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
+ !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
+ !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
+ !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
+ !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
+ !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
+ !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
+ {
+ BIO_meth_free(my_bio_methods);
+ my_bio_methods = NULL;
+ return NULL;
+ }
+#else
+ my_bio_methods = malloc(sizeof(BIO_METHOD));
+ if (!my_bio_methods)
+ return NULL;
+ memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
+ my_bio_methods->bread = my_sock_read;
+ my_bio_methods->bwrite = my_sock_write;
+#endif
}
- return &my_bio_methods;
+ return my_bio_methods;
}
/* This should exactly match openssl's SSL_set_fd except for using my BIO */
@@ -735,17 +877,23 @@ static int
my_SSL_set_fd(Port *port, int fd)
{
int ret = 0;
- BIO *bio = NULL;
+ BIO *bio;
+ BIO_METHOD *bio_method;
- bio = BIO_new(my_BIO_s_socket());
+ bio_method = my_BIO_s_socket();
+ if (bio_method == NULL)
+ {
+ SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
+ goto err;
+ }
+ bio = BIO_new(bio_method);
if (bio == NULL)
{
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- /* Use 'ptr' to store pointer to PGconn */
- bio->ptr = port;
+ BIO_set_data(bio, port);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(port->ssl, bio, bio);
@@ -840,6 +988,27 @@ load_dh_buffer(const char *buffer, size_t len)
}
/*
+ * Generate DH parameters.
+ *
+ * Last resort if we can't load precomputed nor hardcoded
+ * parameters.
+ */
+static DH *
+generate_dh_parameters(int prime_len, int generator)
+{
+ DH *dh;
+
+ if ((dh = DH_new()) == NULL)
+ return NULL;
+
+ if (DH_generate_parameters_ex(dh, prime_len, generator, NULL))
+ return dh;
+
+ DH_free(dh);
+ return NULL;
+}
+
+/*
* Generate an ephemeral DH key. Because this can take a long
* time to compute, we can use precomputed parameters of the
* common key sizes.
@@ -908,13 +1077,33 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
ereport(DEBUG2,
(errmsg_internal("DH: generating parameters (%d bits)",
keylength)));
- r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
+ r = generate_dh_parameters(keylength, DH_GENERATOR_2);
}
return r;
}
/*
+ * Passphrase collection callback
+ *
+ * If OpenSSL is told to use a passphrase-protected server key, by default
+ * it will issue a prompt on /dev/tty and try to read a key from there.
+ * That's no good during a postmaster SIGHUP cycle, not to mention SSL context
+ * reload in an EXEC_BACKEND postmaster child. So override it with this dummy
+ * function that just returns an empty passphrase, guaranteeing failure.
+ */
+static int
+ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
+{
+ /* Set flag to change the error message we'll report */
+ ssl_passwd_cb_called = true;
+ /* And return empty string */
+ Assert(size > 0);
+ buf[0] = '\0';
+ return 0;
+}
+
+/*
* Certificate verification callback
*
* This callback allows us to log intermediate problems during
@@ -975,27 +1164,37 @@ info_cb(const SSL *ssl, int type, int args)
}
}
-static void
-initialize_ecdh(void)
+static bool
+initialize_ecdh(SSL_CTX *context, bool isServerStart)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH)
+#ifndef OPENSSL_NO_ECDH
EC_KEY *ecdh;
int nid;
nid = OBJ_sn2nid(SSLECDHCurve);
if (!nid)
- ereport(FATAL,
- (errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
+ return false;
+ }
ecdh = EC_KEY_new_by_curve_name(nid);
if (!ecdh)
- ereport(FATAL,
- (errmsg("ECDH: could not create key")));
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("ECDH: could not create key")));
+ return false;
+ }
- SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_ECDH_USE);
- SSL_CTX_set_tmp_ecdh(SSL_context, ecdh);
+ SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
+ SSL_CTX_set_tmp_ecdh(context, ecdh);
EC_KEY_free(ecdh);
#endif
+
+ return true;
}
/*
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index cdd07d577b..785dadb6c2 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -6,7 +6,7 @@
* message integrity and endpoint authentication.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -33,6 +33,7 @@
#include "libpq/libpq.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
#include "storage/ipc.h"
@@ -62,16 +63,31 @@ bool SSLPreferServerCiphers;
/* ------------------------------------------------------------ */
/*
- * Initialize global context
+ * Initialize global context.
+ *
+ * If isServerStart is true, report any errors as FATAL (so we don't return).
+ * Otherwise, log errors at LOG level and return -1 to indicate trouble,
+ * preserving the old SSL state if any. Returns 0 if OK.
*/
int
-secure_initialize(void)
+secure_initialize(bool isServerStart)
{
#ifdef USE_SSL
- be_tls_init();
+ return be_tls_init(isServerStart);
+#else
+ return 0;
#endif
+}
- return 0;
+/*
+ * Destroy global context, if any.
+ */
+void
+secure_destroy(void)
+{
+#ifdef USE_SSL
+ be_tls_destroy();
+#endif
}
/*
@@ -146,7 +162,8 @@ retry:
ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
- WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+ WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+ WAIT_EVENT_CLIENT_READ);
/*
* If the postmaster has died, it's not safe to continue running,
@@ -247,7 +264,8 @@ retry:
ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
- WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+ WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+ WAIT_EVENT_CLIENT_WRITE);
/* See comments in secure_read. */
if (event.events & WL_POSTMASTER_DEATH)
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index d79f5a2496..0013ee3878 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -1,12 +1,10 @@
/*-------------------------------------------------------------------------
*
* crypt.c
- * Look into the password file and check the encrypted password with
- * the one passed in from the frontend.
+ * Functions for dealing with encrypted passwords stored in
+ * pg_authid.rolpassword.
*
- * Original coding by Todd A. Brandys
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/libpq/crypt.c
@@ -21,8 +19,9 @@
#endif
#include "catalog/pg_authid.h"
+#include "common/md5.h"
#include "libpq/crypt.h"
-#include "libpq/md5.h"
+#include "libpq/scram.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
@@ -30,22 +29,20 @@
/*
- * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
- * In the error case, optionally store a palloc'd string at *logdetail
- * that will be sent to the postmaster log (but not the client).
+ * Fetch stored password for a user, for authentication.
+ *
+ * On error, returns NULL, and stores a palloc'd string describing the reason,
+ * for the postmaster log, in *logdetail. The error reason should *not* be
+ * sent to the client, to avoid giving away user information!
*/
-int
-md5_crypt_verify(const Port *port, const char *role, char *client_pass,
- char **logdetail)
+char *
+get_role_password(const char *role, char **logdetail)
{
- int retval = STATUS_ERROR;
- char *shadow_pass,
- *crypt_pwd;
TimestampTz vuntil = 0;
- char *crypt_client_pass = client_pass;
HeapTuple roleTup;
Datum datum;
bool isnull;
+ char *shadow_pass;
/* Get role info from pg_authid */
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
@@ -53,7 +50,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
{
*logdetail = psprintf(_("Role \"%s\" does not exist."),
role);
- return STATUS_ERROR; /* no such user */
+ return NULL; /* no such user */
}
datum = SysCacheGetAttr(AUTHNAME, roleTup,
@@ -63,7 +60,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
ReleaseSysCache(roleTup);
*logdetail = psprintf(_("User \"%s\" has no password assigned."),
role);
- return STATUS_ERROR; /* user has no password */
+ return NULL; /* user has no password */
}
shadow_pass = TextDatumGetCString(datum);
@@ -78,99 +75,218 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass,
{
*logdetail = psprintf(_("User \"%s\" has an empty password."),
role);
- return STATUS_ERROR; /* empty password */
+ pfree(shadow_pass);
+ return NULL; /* empty password */
+ }
+
+ /*
+ * Password OK, but check to be sure we are not past rolvaliduntil
+ */
+ if (!isnull && vuntil < GetCurrentTimestamp())
+ {
+ *logdetail = psprintf(_("User \"%s\" has an expired password."),
+ role);
+ return NULL;
+ }
+
+ return shadow_pass;
+}
+
+/*
+ * What kind of a password verifier is 'shadow_pass'?
+ */
+PasswordType
+get_password_type(const char *shadow_pass)
+{
+ if (strncmp(shadow_pass, "md5", 3) == 0 && strlen(shadow_pass) == MD5_PASSWD_LEN)
+ return PASSWORD_TYPE_MD5;
+ if (strncmp(shadow_pass, "SCRAM-SHA-256$", strlen("SCRAM-SHA-256$")) == 0)
+ return PASSWORD_TYPE_SCRAM_SHA_256;
+ return PASSWORD_TYPE_PLAINTEXT;
+}
+
+/*
+ * Given a user-supplied password, convert it into a verifier of
+ * 'target_type' kind.
+ *
+ * If the password is already in encrypted form, we cannot reverse the
+ * hash, so it is stored as it is regardless of the requested type.
+ */
+char *
+encrypt_password(PasswordType target_type, const char *role,
+ const char *password)
+{
+ PasswordType guessed_type = get_password_type(password);
+ char *encrypted_password;
+
+ if (guessed_type != PASSWORD_TYPE_PLAINTEXT)
+ {
+ /*
+ * Cannot convert an already-encrypted password from one format to
+ * another, so return it as it is.
+ */
+ return pstrdup(password);
+ }
+
+ switch (target_type)
+ {
+ case PASSWORD_TYPE_MD5:
+ encrypted_password = palloc(MD5_PASSWD_LEN + 1);
+
+ if (!pg_md5_encrypt(password, role, strlen(role),
+ encrypted_password))
+ elog(ERROR, "password encryption failed");
+ return encrypted_password;
+
+ case PASSWORD_TYPE_SCRAM_SHA_256:
+ return pg_be_scram_build_verifier(password);
+
+ case PASSWORD_TYPE_PLAINTEXT:
+ elog(ERROR, "cannot encrypt password with 'plaintext'");
+ }
+
+ /*
+ * This shouldn't happen, because the above switch statements should
+ * handle every combination of source and target password types.
+ */
+ elog(ERROR, "cannot encrypt password to requested type");
+ return NULL; /* keep compiler quiet */
+}
+
+/*
+ * Check MD5 authentication response, and return STATUS_OK or STATUS_ERROR.
+ *
+ * 'shadow_pass' is the user's correct password or password hash, as stored
+ * in pg_authid.rolpassword.
+ * 'client_pass' is the response given by the remote user to the MD5 challenge.
+ * 'md5_salt' is the salt used in the MD5 authentication challenge.
+ *
+ * In the error case, optionally store a palloc'd string at *logdetail
+ * that will be sent to the postmaster log (but not the client).
+ */
+int
+md5_crypt_verify(const char *role, const char *shadow_pass,
+ const char *client_pass,
+ const char *md5_salt, int md5_salt_len,
+ char **logdetail)
+{
+ int retval;
+ char crypt_pwd[MD5_PASSWD_LEN + 1];
+
+ Assert(md5_salt_len > 0);
+
+ if (get_password_type(shadow_pass) != PASSWORD_TYPE_MD5)
+ {
+ /* incompatible password hash format. */
+ *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
+ role);
+ return STATUS_ERROR;
+ }
+
+ /*
+ * Compute the correct answer for the MD5 challenge.
+ *
+ * We do not bother setting logdetail for any pg_md5_encrypt failure
+ * below: the only possible error is out-of-memory, which is unlikely, and
+ * if it did happen adding a psprintf call would only make things worse.
+ */
+ /* stored password already encrypted, only do salt */
+ if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
+ md5_salt, md5_salt_len,
+ crypt_pwd))
+ {
+ return STATUS_ERROR;
+ }
+
+ if (strcmp(client_pass, crypt_pwd) == 0)
+ retval = STATUS_OK;
+ else
+ {
+ *logdetail = psprintf(_("Password does not match for user \"%s\"."),
+ role);
+ retval = STATUS_ERROR;
}
+ return retval;
+}
+
+/*
+ * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
+ *
+ * 'shadow_pass' is the user's correct password hash, as stored in
+ * pg_authid.rolpassword.
+ * 'client_pass' is the password given by the remote user.
+ *
+ * In the error case, optionally store a palloc'd string at *logdetail
+ * that will be sent to the postmaster log (but not the client).
+ */
+int
+plain_crypt_verify(const char *role, const char *shadow_pass,
+ const char *client_pass,
+ char **logdetail)
+{
+ char crypt_client_pass[MD5_PASSWD_LEN + 1];
+
/*
- * Compare with the encrypted or plain password depending on the
- * authentication method being used for this connection. (We do not
- * bother setting logdetail for pg_md5_encrypt failure: the only possible
- * error is out-of-memory, which is unlikely, and if it did happen adding
- * a psprintf call would only make things worse.)
+ * Client sent password in plaintext. If we have an MD5 hash stored, hash
+ * the password the client sent, and compare the hashes. Otherwise
+ * compare the plaintext passwords directly.
*/
- switch (port->hba->auth_method)
+ switch (get_password_type(shadow_pass))
{
- case uaMD5:
- crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
- if (isMD5(shadow_pass))
+ case PASSWORD_TYPE_SCRAM_SHA_256:
+ if (scram_verify_plain_password(role,
+ client_pass,
+ shadow_pass))
{
- /* stored password already encrypted, only do salt */
- if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
- port->md5Salt,
- sizeof(port->md5Salt), crypt_pwd))
- {
- pfree(crypt_pwd);
- return STATUS_ERROR;
- }
+ return STATUS_OK;
}
else
{
- /* stored password is plain, double-encrypt */
- char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);
-
- if (!pg_md5_encrypt(shadow_pass,
- port->user_name,
- strlen(port->user_name),
- crypt_pwd2))
- {
- pfree(crypt_pwd);
- pfree(crypt_pwd2);
- return STATUS_ERROR;
- }
- if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"),
- port->md5Salt,
- sizeof(port->md5Salt),
- crypt_pwd))
- {
- pfree(crypt_pwd);
- pfree(crypt_pwd2);
- return STATUS_ERROR;
- }
- pfree(crypt_pwd2);
+ *logdetail = psprintf(_("Password does not match for user \"%s\"."),
+ role);
+ return STATUS_ERROR;
}
break;
- default:
- if (isMD5(shadow_pass))
+
+ case PASSWORD_TYPE_MD5:
+ if (!pg_md5_encrypt(client_pass,
+ role,
+ strlen(role),
+ crypt_client_pass))
+ {
+ /*
+ * We do not bother setting logdetail for pg_md5_encrypt
+ * failure: the only possible error is out-of-memory, which is
+ * unlikely, and if it did happen adding a psprintf call would
+ * only make things worse.
+ */
+ return STATUS_ERROR;
+ }
+ if (strcmp(crypt_client_pass, shadow_pass) == 0)
+ return STATUS_OK;
+ else
{
- /* Encrypt user-supplied password to match stored MD5 */
- crypt_client_pass = palloc(MD5_PASSWD_LEN + 1);
- if (!pg_md5_encrypt(client_pass,
- port->user_name,
- strlen(port->user_name),
- crypt_client_pass))
- {
- pfree(crypt_client_pass);
- return STATUS_ERROR;
- }
+ *logdetail = psprintf(_("Password does not match for user \"%s\"."),
+ role);
+ return STATUS_ERROR;
}
- crypt_pwd = shadow_pass;
break;
- }
- if (strcmp(crypt_client_pass, crypt_pwd) == 0)
- {
- /*
- * Password OK, now check to be sure we are not past rolvaliduntil
- */
- if (isnull)
- retval = STATUS_OK;
- else if (vuntil < GetCurrentTimestamp())
- {
- *logdetail = psprintf(_("User \"%s\" has an expired password."),
- role);
- retval = STATUS_ERROR;
- }
- else
- retval = STATUS_OK;
- }
- else
- *logdetail = psprintf(_("Password does not match for user \"%s\"."),
- role);
+ case PASSWORD_TYPE_PLAINTEXT:
- if (port->hba->auth_method == uaMD5)
- pfree(crypt_pwd);
- if (crypt_client_pass != client_pass)
- pfree(crypt_client_pass);
+ /*
+ * We never store passwords in plaintext, so this shouldn't
+ * happen.
+ */
+ break;
+ }
- return retval;
+ /*
+ * This shouldn't happen. Plain "password" authentication is possible
+ * with any kind of stored password hash.
+ */
+ *logdetail = psprintf(_("Password of user \"%s\" is in unrecognized format."),
+ role);
+ return STATUS_ERROR;
}
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 1b4bbce42d..823880ebff 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -5,7 +5,7 @@
* wherein you authenticate a user by seeing what IP address the system
* says he comes from and choosing authentication method based on it).
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -25,14 +25,21 @@
#include <arpa/inet.h>
#include <unistd.h>
+#include "access/htup_details.h"
#include "catalog/pg_collation.h"
-#include "libpq/ip.h"
+#include "catalog/pg_type.h"
+#include "common/ip.h"
+#include "funcapi.h"
+#include "libpq/ifaddr.h"
#include "libpq/libpq.h"
+#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "regex/regex.h"
#include "replication/walsender.h"
#include "storage/fd.h"
#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/varlena.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
@@ -46,9 +53,6 @@
#endif
-#define atooid(x) ((Oid) strtoul((x), NULL, 10))
-#define atoxid(x) ((TransactionId) strtoul((x), NULL, 10))
-
#define MAX_TOKEN 256
#define MAX_LINE 8192
@@ -65,7 +69,7 @@ typedef struct check_network_data
#define token_matches(t, k) (strcmp(t->string, k) == 0)
/*
- * A single string token lexed from the HBA config file, together with whether
+ * A single string token lexed from a config file, together with whether
* the token had been quoted.
*/
typedef struct HbaToken
@@ -75,6 +79,22 @@ typedef struct HbaToken
} HbaToken;
/*
+ * TokenizedLine represents one line lexed from a config file.
+ * Each item in the "fields" list is a sub-list of HbaTokens.
+ * We don't emit a TokenizedLine for empty or all-comment lines,
+ * so "fields" is never NIL (nor are any of its sub-lists).
+ * Exception: if an error occurs during tokenization, we might
+ * have fields == NIL, in which case err_msg != NULL.
+ */
+typedef struct TokenizedLine
+{
+ List *fields; /* List of lists of HbaTokens */
+ int line_num; /* Line number */
+ char *raw_line; /* Raw line text */
+ char *err_msg; /* Error message if any */
+} TokenizedLine;
+
+/*
* pre-parsed content of HBA config file: list of HbaLine structs.
* parsed_hba_context is the memory context where it lives.
*/
@@ -87,18 +107,50 @@ static MemoryContext parsed_hba_context = NULL;
*
* NOTE: the IdentLine structs can contain pre-compiled regular expressions
* that live outside the memory context. Before destroying or resetting the
- * memory context, they need to be expliticly free'd.
+ * memory context, they need to be explicitly free'd.
*/
static List *parsed_ident_lines = NIL;
static MemoryContext parsed_ident_context = NULL;
+/*
+ * The following character array represents the names of the authentication
+ * methods that are supported by PostgreSQL.
+ *
+ * Note: keep this in sync with the UserAuth enum in hba.h.
+ */
+static const char *const UserAuthName[] =
+{
+ "reject",
+ "implicit reject", /* Not a user-visible option */
+ "trust",
+ "ident",
+ "password",
+ "md5",
+ "scram-sha256",
+ "gss",
+ "sspi",
+ "pam",
+ "bsd",
+ "ldap",
+ "cert",
+ "radius",
+ "peer"
+};
+
static MemoryContext tokenize_file(const char *filename, FILE *file,
- List **lines, List **line_nums, List **raw_lines);
+ List **tok_lines, int elevel);
static List *tokenize_inc_file(List *tokens, const char *outer_filename,
- const char *inc_filename);
+ const char *inc_filename, int elevel, char **err_msg);
static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
- int line_num);
+ int elevel, char **err_msg);
+static bool verify_option_list_length(List *options, char *optionname,
+ List *masters, char *mastername, int line_num);
+static ArrayType *gethba_options(HbaLine *hba);
+static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
+ int lineno, HbaLine *hba, const char *err_msg);
+static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
+
/*
* isblank() exists in the ISO C99 spec, but it's not very portable yet,
@@ -112,88 +164,86 @@ pg_isblank(const char c)
/*
- * Grab one token out of the string pointed to by lineptr.
+ * Grab one token out of the string pointed to by *lineptr.
+ *
* Tokens are strings of non-blank
* characters bounded by blank characters, commas, beginning of line, and
* end of line. Blank means space or tab. Tokens can be delimited by
* double quotes (this allows the inclusion of blanks, but not newlines).
+ * Comments (started by an unquoted '#') are skipped.
+ *
+ * The token, if any, is returned at *buf (a buffer of size bufsz), and
+ * *lineptr is advanced past the token.
*
- * The token, if any, is returned at *buf (a buffer of size bufsz).
* Also, we set *initial_quote to indicate whether there was quoting before
* the first character. (We use that to prevent "@x" from being treated
* as a file inclusion request. Note that @"x" should be so treated;
* we want to allow that to support embedded spaces in file paths.)
+ *
* We set *terminating_comma to indicate whether the token is terminated by a
- * comma (which is not returned.)
+ * comma (which is not returned).
+ *
+ * In event of an error, log a message at ereport level elevel, and also
+ * set *err_msg to a string describing the error. Currently the only
+ * possible error is token too long for buf.
*
* If successful: store null-terminated token at *buf and return TRUE.
* If no more tokens on line: set *buf = '\0' and return FALSE.
- *
- * Leave file positioned at the character immediately after the token or EOF,
- * whichever comes first. If no more tokens on line, position the file to the
- * beginning of the next line or EOF, whichever comes first.
- *
- * Handle comments.
+ * If error: fill buf with truncated or misformatted token and return FALSE.
*/
static bool
-next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,
- bool *terminating_comma)
+next_token(char **lineptr, char *buf, int bufsz,
+ bool *initial_quote, bool *terminating_comma,
+ int elevel, char **err_msg)
{
int c;
char *start_buf = buf;
- char *end_buf = buf + (bufsz - 2);
+ char *end_buf = buf + (bufsz - 1);
bool in_quote = false;
bool was_quote = false;
bool saw_quote = false;
- /* end_buf reserves two bytes to ensure we can append \n and \0 */
Assert(end_buf > start_buf);
*initial_quote = false;
*terminating_comma = false;
- /* Move over initial whitespace and commas */
+ /* Move over any whitespace and commas preceding the next token */
while ((c = (*(*lineptr)++)) != '\0' && (pg_isblank(c) || c == ','))
;
- if (c == '\0' || c == '\n')
- {
- *buf = '\0';
- return false;
- }
-
/*
- * Build a token in buf of next characters up to EOF, EOL, unquoted comma,
- * or unquoted whitespace.
+ * Build a token in buf of next characters up to EOL, unquoted comma, or
+ * unquoted whitespace.
*/
- while (c != '\0' && c != '\n' &&
+ while (c != '\0' &&
(!pg_isblank(c) || in_quote))
{
/* skip comments to EOL */
if (c == '#' && !in_quote)
{
- while ((c = (*(*lineptr)++)) != '\0' && c != '\n')
+ while ((c = (*(*lineptr)++)) != '\0')
;
- /* If only comment, consume EOL too; return EOL */
- if (c != '\0' && buf == start_buf)
- (*lineptr)++;
break;
}
if (buf >= end_buf)
{
*buf = '\0';
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("authentication file token too long, skipping: \"%s\"",
start_buf)));
+ *err_msg = "authentication file token too long";
/* Discard remainder of line */
- while ((c = (*(*lineptr)++)) != '\0' && c != '\n')
+ while ((c = (*(*lineptr)++)) != '\0')
;
- break;
+ /* Un-eat the '\0', in case we're called again */
+ (*lineptr)--;
+ return false;
}
- /* we do not pass back the comma in the token */
+ /* we do not pass back a terminating comma in the token */
if (c == ',' && !in_quote)
{
*terminating_comma = true;
@@ -221,8 +271,8 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,
}
/*
- * Put back the char right after the token (critical in case it is EOL,
- * since we need to detect end-of-line at next call).
+ * Un-eat the char right after the token (critical in case it is '\0',
+ * else next call will read past end of string).
*/
(*lineptr)--;
@@ -231,13 +281,17 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,
return (saw_quote || buf > start_buf);
}
+/*
+ * Construct a palloc'd HbaToken struct, copying the given string.
+ */
static HbaToken *
-make_hba_token(char *token, bool quoted)
+make_hba_token(const char *token, bool quoted)
{
HbaToken *hbatoken;
int toklen;
toklen = strlen(token);
+ /* we copy string into same palloc block as the struct */
hbatoken = (HbaToken *) palloc(sizeof(HbaToken) + toklen + 1);
hbatoken->string = (char *) hbatoken + sizeof(HbaToken);
hbatoken->quoted = quoted;
@@ -261,11 +315,20 @@ copy_hba_token(HbaToken *in)
/*
* Tokenize one HBA field from a line, handling file inclusion and comma lists.
*
- * The result is a List of HbaToken structs for each individual token,
+ * filename: current file's pathname (needed to resolve relative pathnames)
+ * *lineptr: current line pointer, which will be advanced past field
+ *
+ * In event of an error, log a message at ereport level elevel, and also
+ * set *err_msg to a string describing the error. Note that the result
+ * may be non-NIL anyway, so *err_msg must be tested to determine whether
+ * there was an error.
+ *
+ * The result is a List of HbaToken structs, one for each token in the field,
* or NIL if we reached EOL.
*/
static List *
-next_field_expand(const char *filename, char **lineptr)
+next_field_expand(const char *filename, char **lineptr,
+ int elevel, char **err_msg)
{
char buf[MAX_TOKEN];
bool trailing_comma;
@@ -274,15 +337,18 @@ next_field_expand(const char *filename, char **lineptr)
do
{
- if (!next_token(lineptr, buf, sizeof(buf), &initial_quote, &trailing_comma))
+ if (!next_token(lineptr, buf, sizeof(buf),
+ &initial_quote, &trailing_comma,
+ elevel, err_msg))
break;
/* Is this referencing a file? */
if (!initial_quote && buf[0] == '@' && buf[1] != '\0')
- tokens = tokenize_inc_file(tokens, filename, buf + 1);
+ tokens = tokenize_inc_file(tokens, filename, buf + 1,
+ elevel, err_msg);
else
tokens = lappend(tokens, make_hba_token(buf, initial_quote));
- } while (trailing_comma);
+ } while (trailing_comma && (*err_msg == NULL));
return tokens;
}
@@ -293,18 +359,25 @@ next_field_expand(const char *filename, char **lineptr)
*
* Opens and tokenises a file included from another HBA config file with @,
* and returns all values found therein as a flat list of HbaTokens. If a
- * @-token is found, recursively expand it. The given token list is used as
- * initial contents of list (so foo,bar,@baz does what you expect).
+ * @-token is found, recursively expand it. The newly read tokens are
+ * appended to "tokens" (so that foo,bar,@baz does what you expect).
+ * All new tokens are allocated in caller's memory context.
+ *
+ * In event of an error, log a message at ereport level elevel, and also
+ * set *err_msg to a string describing the error. Note that the result
+ * may be non-NIL anyway, so *err_msg must be tested to determine whether
+ * there was an error.
*/
static List *
tokenize_inc_file(List *tokens,
const char *outer_filename,
- const char *inc_filename)
+ const char *inc_filename,
+ int elevel,
+ char **err_msg)
{
char *inc_fullname;
FILE *inc_file;
List *inc_lines;
- List *inc_line_nums;
ListCell *inc_line;
MemoryContext linecxt;
@@ -327,26 +400,38 @@ tokenize_inc_file(List *tokens,
inc_file = AllocateFile(inc_fullname, "r");
if (inc_file == NULL)
{
- ereport(LOG,
+ int save_errno = errno;
+
+ ereport(elevel,
(errcode_for_file_access(),
errmsg("could not open secondary authentication file \"@%s\" as \"%s\": %m",
inc_filename, inc_fullname)));
+ *err_msg = psprintf("could not open secondary authentication file \"@%s\" as \"%s\": %s",
+ inc_filename, inc_fullname, strerror(save_errno));
pfree(inc_fullname);
return tokens;
}
/* There is possible recursion here if the file contains @ */
- linecxt = tokenize_file(inc_fullname, inc_file, &inc_lines, &inc_line_nums, NULL);
+ linecxt = tokenize_file(inc_fullname, inc_file, &inc_lines, elevel);
FreeFile(inc_file);
pfree(inc_fullname);
+ /* Copy all tokens found in the file and append to the tokens list */
foreach(inc_line, inc_lines)
{
- List *inc_fields = lfirst(inc_line);
+ TokenizedLine *tok_line = (TokenizedLine *) lfirst(inc_line);
ListCell *inc_field;
- foreach(inc_field, inc_fields)
+ /* If any line has an error, propagate that up to caller */
+ if (tok_line->err_msg)
+ {
+ *err_msg = pstrdup(tok_line->err_msg);
+ break;
+ }
+
+ foreach(inc_field, tok_line->fields)
{
List *inc_tokens = lfirst(inc_field);
ListCell *inc_token;
@@ -365,82 +450,99 @@ tokenize_inc_file(List *tokens,
}
/*
- * Tokenize the given file, storing the resulting data into three Lists: a
- * List of lines, a List of line numbers, and a List of raw line contents.
+ * Tokenize the given file.
+ *
+ * The output is a list of TokenizedLine structs; see struct definition above.
*
- * The list of lines is a triple-nested List structure. Each line is a List of
- * fields, and each field is a List of HbaTokens.
+ * filename: the absolute path to the target file
+ * file: the already-opened target file
+ * tok_lines: receives output list
+ * elevel: message logging level
*
- * filename must be the absolute path to the target file.
+ * Errors are reported by logging messages at ereport level elevel and by
+ * adding TokenizedLine structs containing non-null err_msg fields to the
+ * output list.
*
* Return value is a memory context which contains all memory allocated by
- * this function.
+ * this function (it's a child of caller's context).
*/
static MemoryContext
-tokenize_file(const char *filename, FILE *file,
- List **lines, List **line_nums, List **raw_lines)
+tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
{
- List *current_line = NIL;
- List *current_field = NIL;
int line_number = 1;
MemoryContext linecxt;
MemoryContext oldcxt;
linecxt = AllocSetContextCreate(CurrentMemoryContext,
- "tokenize file cxt",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ "tokenize_file",
+ ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(linecxt);
- *lines = *line_nums = NIL;
+ *tok_lines = NIL;
while (!feof(file) && !ferror(file))
{
char rawline[MAX_LINE];
char *lineptr;
+ List *current_line = NIL;
+ char *err_msg = NULL;
if (!fgets(rawline, sizeof(rawline), file))
- break;
+ {
+ int save_errno = errno;
+
+ if (!ferror(file))
+ break; /* normal EOF */
+ /* I/O error! */
+ ereport(elevel,
+ (errcode_for_file_access(),
+ errmsg("could not read file \"%s\": %m", filename)));
+ err_msg = psprintf("could not read file \"%s\": %s",
+ filename, strerror(save_errno));
+ rawline[0] = '\0';
+ }
if (strlen(rawline) == MAX_LINE - 1)
+ {
/* Line too long! */
- ereport(ERROR,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("authentication file line too long"),
errcontext("line %d of configuration file \"%s\"",
line_number, filename)));
+ err_msg = "authentication file line too long";
+ }
/* Strip trailing linebreak from rawline */
lineptr = rawline + strlen(rawline) - 1;
while (lineptr >= rawline && (*lineptr == '\n' || *lineptr == '\r'))
*lineptr-- = '\0';
+ /* Parse fields */
lineptr = rawline;
- while (strlen(lineptr) > 0)
+ while (*lineptr && err_msg == NULL)
{
- current_field = next_field_expand(filename, &lineptr);
+ List *current_field;
- /* add tokens to list, unless we are at EOL or comment start */
- if (list_length(current_field) > 0)
- {
- if (current_line == NIL)
- {
- /* make a new line List, record its line number */
- current_line = lappend(current_line, current_field);
- *lines = lappend(*lines, current_line);
- *line_nums = lappend_int(*line_nums, line_number);
- if (raw_lines)
- *raw_lines = lappend(*raw_lines, pstrdup(rawline));
- }
- else
- {
- /* append tokens to current line's list */
- current_line = lappend(current_line, current_field);
- }
- }
+ current_field = next_field_expand(filename, &lineptr,
+ elevel, &err_msg);
+ /* add field to line, unless we are at EOL or comment start */
+ if (current_field != NIL)
+ current_line = lappend(current_line, current_field);
+ }
+
+ /* Reached EOL; emit line to TokenizedLine list unless it's boring */
+ if (current_line != NIL || err_msg != NULL)
+ {
+ TokenizedLine *tok_line;
+
+ tok_line = (TokenizedLine *) palloc(sizeof(TokenizedLine));
+ tok_line->fields = current_line;
+ tok_line->line_num = line_number;
+ tok_line->raw_line = pstrdup(rawline);
+ tok_line->err_msg = err_msg;
+ *tok_lines = lappend(*tok_lines, tok_line);
}
- /* we are at real or logical EOL, so force a new line List */
- current_line = NIL;
+
line_number++;
}
@@ -513,9 +615,12 @@ check_db(const char *dbname, const char *role, Oid roleid, List *tokens)
foreach(cell, tokens)
{
tok = lfirst(cell);
- if (am_walsender)
+ if (am_walsender && !am_db_walsender)
{
- /* walsender connections can only match replication keyword */
+ /*
+ * physical replication walsender connections can only match
+ * replication keyword
+ */
if (token_is_keyword(tok, "replication"))
return true;
}
@@ -740,6 +845,10 @@ check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
/*
* Macros used to check and report on invalid configuration options.
+ * On error: log a message at level elevel, set *err_msg, and exit the function.
+ * These macros are not as general-purpose as they look, because they know
+ * what the calling function's error-exit value is.
+ *
* INVALID_AUTH_OPTION = reports when an option is specified for a method where it's
* not supported.
* REQUIRE_AUTH_OPTION = same as INVALID_AUTH_OPTION, except it also checks if the
@@ -748,79 +857,95 @@ check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
* MANDATORY_AUTH_ARG = check if a required option is set for an authentication method,
* reporting error if it's not.
*/
-#define INVALID_AUTH_OPTION(optname, validmethods) do {\
- ereport(LOG, \
+#define INVALID_AUTH_OPTION(optname, validmethods) \
+do { \
+ ereport(elevel, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
/* translator: the second %s is a list of auth methods */ \
errmsg("authentication option \"%s\" is only valid for authentication methods %s", \
optname, _(validmethods)), \
errcontext("line %d of configuration file \"%s\"", \
line_num, HbaFileName))); \
+ *err_msg = psprintf("authentication option \"%s\" is only valid for authentication methods %s", \
+ optname, validmethods); \
return false; \
-} while (0);
+} while (0)
-#define REQUIRE_AUTH_OPTION(methodval, optname, validmethods) do {\
+#define REQUIRE_AUTH_OPTION(methodval, optname, validmethods) \
+do { \
if (hbaline->auth_method != methodval) \
INVALID_AUTH_OPTION(optname, validmethods); \
-} while (0);
+} while (0)
-#define MANDATORY_AUTH_ARG(argvar, argname, authname) do {\
- if (argvar == NULL) {\
- ereport(LOG, \
+#define MANDATORY_AUTH_ARG(argvar, argname, authname) \
+do { \
+ if (argvar == NULL) { \
+ ereport(elevel, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("authentication method \"%s\" requires argument \"%s\" to be set", \
authname, argname), \
errcontext("line %d of configuration file \"%s\"", \
line_num, HbaFileName))); \
+ *err_msg = psprintf("authentication method \"%s\" requires argument \"%s\" to be set", \
+ authname, argname); \
return NULL; \
} \
-} while (0);
+} while (0)
/*
+ * Macros for handling pg_ident problems.
+ * Much as above, but currently the message level is hardwired as LOG
+ * and there is no provision for an err_msg string.
+ *
* IDENT_FIELD_ABSENT:
- * Throw an error and exit the function if the given ident field ListCell is
+ * Log a message and exit the function if the given ident field ListCell is
* not populated.
*
* IDENT_MULTI_VALUE:
- * Throw an error and exit the function if the given ident token List has more
+ * Log a message and exit the function if the given ident token List has more
* than one element.
*/
-#define IDENT_FIELD_ABSENT(field) do {\
+#define IDENT_FIELD_ABSENT(field) \
+do { \
if (!field) { \
ereport(LOG, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("missing entry in file \"%s\" at end of line %d", \
- IdentFileName, line_number))); \
+ IdentFileName, line_num))); \
return NULL; \
} \
-} while (0);
+} while (0)
-#define IDENT_MULTI_VALUE(tokens) do {\
+#define IDENT_MULTI_VALUE(tokens) \
+do { \
if (tokens->length > 1) { \
ereport(LOG, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("multiple values in ident field"), \
errcontext("line %d of configuration file \"%s\"", \
- line_number, IdentFileName))); \
+ line_num, IdentFileName))); \
return NULL; \
} \
-} while (0);
+} while (0)
/*
* Parse one tokenised line from the hba config file and store the result in a
- * HbaLine structure, or NULL if parsing fails.
+ * HbaLine structure.
*
- * The tokenised line is a List of fields, each field being a List of
- * HbaTokens.
+ * If parsing fails, log a message at ereport level elevel, store an error
+ * string in tok_line->err_msg, and return NULL. (Some non-error conditions
+ * can also result in such messages.)
*
* Note: this function leaks memory when an error occurs. Caller is expected
* to have set a memory context that will be reset if this function returns
* NULL.
*/
static HbaLine *
-parse_hba_line(List *line, int line_num, char *raw_line)
+parse_hba_line(TokenizedLine *tok_line, int elevel)
{
+ int line_num = tok_line->line_num;
+ char **err_msg = &tok_line->err_msg;
char *str;
struct addrinfo *gai_result;
struct addrinfo hints;
@@ -835,19 +960,21 @@ parse_hba_line(List *line, int line_num, char *raw_line)
parsedline = palloc0(sizeof(HbaLine));
parsedline->linenumber = line_num;
- parsedline->rawline = pstrdup(raw_line);
+ parsedline->rawline = pstrdup(tok_line->raw_line);
/* Check the record type. */
- field = list_head(line);
+ Assert(tok_line->fields != NIL);
+ field = list_head(tok_line->fields);
tokens = lfirst(field);
if (tokens->length > 1)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("multiple values specified for connection type"),
errhint("Specify exactly one connection type per line."),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "multiple values specified for connection type";
return NULL;
}
token = linitial(tokens);
@@ -856,11 +983,12 @@ parse_hba_line(List *line, int line_num, char *raw_line)
#ifdef HAVE_UNIX_SOCKETS
parsedline->conntype = ctLocal;
#else
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("local connections are not supported by this build"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "local connections are not supported by this build";
return NULL;
#endif
}
@@ -871,28 +999,27 @@ parse_hba_line(List *line, int line_num, char *raw_line)
if (token->string[4] == 's') /* "hostssl" */
{
- /* SSL support must be actually active, else complain */
+ parsedline->conntype = ctHostSSL;
+ /* Log a warning if SSL support is not active */
#ifdef USE_SSL
- if (EnableSSL)
- parsedline->conntype = ctHostSSL;
- else
+ if (!EnableSSL)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("hostssl requires SSL to be turned on"),
+ errmsg("hostssl record cannot match because SSL is disabled"),
errhint("Set ssl = on in postgresql.conf."),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
- return NULL;
+ *err_msg = "hostssl record cannot match because SSL is disabled";
}
#else
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("hostssl is not supported by this build"),
+ errmsg("hostssl record cannot match because SSL is not supported by this build"),
errhint("Compile with --with-openssl to use SSL connections."),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
- return NULL;
+ *err_msg = "hostssl record cannot match because SSL is not supported by this build";
#endif
}
else if (token->string[4] == 'n') /* "hostnossl" */
@@ -907,12 +1034,13 @@ parse_hba_line(List *line, int line_num, char *raw_line)
} /* record type */
else
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid connection type \"%s\"",
token->string),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid connection type \"%s\"", token->string);
return NULL;
}
@@ -920,11 +1048,12 @@ parse_hba_line(List *line, int line_num, char *raw_line)
field = lnext(field);
if (!field)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("end-of-line before database specification"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "end-of-line before database specification";
return NULL;
}
parsedline->databases = NIL;
@@ -939,11 +1068,12 @@ parse_hba_line(List *line, int line_num, char *raw_line)
field = lnext(field);
if (!field)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("end-of-line before role specification"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "end-of-line before role specification";
return NULL;
}
parsedline->roles = NIL;
@@ -960,22 +1090,24 @@ parse_hba_line(List *line, int line_num, char *raw_line)
field = lnext(field);
if (!field)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("end-of-line before IP address specification"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "end-of-line before IP address specification";
return NULL;
}
tokens = lfirst(field);
if (tokens->length > 1)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("multiple values specified for host address"),
errhint("Specify one address range per line."),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "multiple values specified for host address";
return NULL;
}
token = linitial(tokens);
@@ -1025,12 +1157,14 @@ parse_hba_line(List *line, int line_num, char *raw_line)
parsedline->hostname = str;
else
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid IP address \"%s\": %s",
str, gai_strerror(ret)),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid IP address \"%s\": %s",
+ str, gai_strerror(ret));
if (gai_result)
pg_freeaddrinfo_all(hints.ai_family, gai_result);
return NULL;
@@ -1043,24 +1177,28 @@ parse_hba_line(List *line, int line_num, char *raw_line)
{
if (parsedline->hostname)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("specifying both host name and CIDR mask is invalid: \"%s\"",
token->string),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("specifying both host name and CIDR mask is invalid: \"%s\"",
+ token->string);
return NULL;
}
if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1,
parsedline->addr.ss_family) < 0)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid CIDR mask in address \"%s\"",
token->string),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid CIDR mask in address \"%s\"",
+ token->string);
return NULL;
}
pfree(str);
@@ -1072,22 +1210,24 @@ parse_hba_line(List *line, int line_num, char *raw_line)
field = lnext(field);
if (!field)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("end-of-line before netmask specification"),
errhint("Specify an address range in CIDR notation, or provide a separate netmask."),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "end-of-line before netmask specification";
return NULL;
}
tokens = lfirst(field);
if (tokens->length > 1)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("multiple values specified for netmask"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "multiple values specified for netmask";
return NULL;
}
token = linitial(tokens);
@@ -1096,12 +1236,14 @@ parse_hba_line(List *line, int line_num, char *raw_line)
&hints, &gai_result);
if (ret || !gai_result)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid IP mask \"%s\": %s",
token->string, gai_strerror(ret)),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid IP mask \"%s\": %s",
+ token->string, gai_strerror(ret));
if (gai_result)
pg_freeaddrinfo_all(hints.ai_family, gai_result);
return NULL;
@@ -1113,11 +1255,12 @@ parse_hba_line(List *line, int line_num, char *raw_line)
if (parsedline->addr.ss_family != parsedline->mask.ss_family)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("IP address and mask do not match"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "IP address and mask do not match";
return NULL;
}
}
@@ -1128,22 +1271,24 @@ parse_hba_line(List *line, int line_num, char *raw_line)
field = lnext(field);
if (!field)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("end-of-line before authentication method"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "end-of-line before authentication method";
return NULL;
}
tokens = lfirst(field);
if (tokens->length > 1)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("multiple values specified for authentication type"),
errhint("Specify exactly one authentication type per line."),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "multiple values specified for authentication type";
return NULL;
}
token = linitial(tokens);
@@ -1175,15 +1320,18 @@ parse_hba_line(List *line, int line_num, char *raw_line)
{
if (Db_user_namespace)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "MD5 authentication is not supported when \"db_user_namespace\" is enabled";
return NULL;
}
parsedline->auth_method = uaMD5;
}
+ else if (strcmp(token->string, "scram-sha-256") == 0)
+ parsedline->auth_method = uaSCRAM;
else if (strcmp(token->string, "pam") == 0)
#ifdef USE_PAM
parsedline->auth_method = uaPAM;
@@ -1212,23 +1360,27 @@ parse_hba_line(List *line, int line_num, char *raw_line)
parsedline->auth_method = uaRADIUS;
else
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid authentication method \"%s\"",
token->string),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid authentication method \"%s\"",
+ token->string);
return NULL;
}
if (unsupauth)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid authentication method \"%s\": not supported by this build",
token->string),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid authentication method \"%s\": not supported by this build",
+ token->string);
return NULL;
}
@@ -1244,22 +1396,24 @@ parse_hba_line(List *line, int line_num, char *raw_line)
if (parsedline->conntype == ctLocal &&
parsedline->auth_method == uaGSS)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("gssapi authentication is not supported on local sockets"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "gssapi authentication is not supported on local sockets";
return NULL;
}
if (parsedline->conntype != ctLocal &&
parsedline->auth_method == uaPeer)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("peer authentication is only supported on local sockets"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "peer authentication is only supported on local sockets";
return NULL;
}
@@ -1272,11 +1426,12 @@ parse_hba_line(List *line, int line_num, char *raw_line)
if (parsedline->conntype != ctHostSSL &&
parsedline->auth_method == uaCert)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("cert authentication is only supported on hostssl connections"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "cert authentication is only supported on hostssl connections";
return NULL;
}
@@ -1321,16 +1476,18 @@ parse_hba_line(List *line, int line_num, char *raw_line)
/*
* Got something that's not a name=value pair.
*/
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("authentication option not in name=value format: %s", token->string),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("authentication option not in name=value format: %s",
+ token->string);
return NULL;
}
*val++ = '\0'; /* str now holds "name", val holds "value" */
- if (!parse_hba_auth_opt(str, val, parsedline, line_num))
+ if (!parse_hba_auth_opt(str, val, parsedline, elevel, err_msg))
/* parse_hba_auth_opt already logged the error message */
return NULL;
pfree(str);
@@ -1358,29 +1515,75 @@ parse_hba_line(List *line, int line_num, char *raw_line)
parsedline->ldapbindpasswd ||
parsedline->ldapsearchattribute)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix";
return NULL;
}
}
else if (!parsedline->ldapbasedn)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set";
return NULL;
}
}
if (parsedline->auth_method == uaRADIUS)
{
- MANDATORY_AUTH_ARG(parsedline->radiusserver, "radiusserver", "radius");
- MANDATORY_AUTH_ARG(parsedline->radiussecret, "radiussecret", "radius");
+ MANDATORY_AUTH_ARG(parsedline->radiusservers, "radiusservers", "radius");
+ MANDATORY_AUTH_ARG(parsedline->radiussecrets, "radiussecrets", "radius");
+
+ if (list_length(parsedline->radiusservers) < 1)
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("list of RADIUS servers cannot be empty"),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ return NULL;
+ }
+
+ if (list_length(parsedline->radiussecrets) < 1)
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("list of RADIUS secrets cannot be empty"),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ return NULL;
+ }
+
+ /*
+ * Verify length of option lists - each can be 0 (except for secrets,
+ * but that's already checked above), 1 (use the same value
+ * everywhere) or the same as the number of servers.
+ */
+ if (!verify_option_list_length(parsedline->radiussecrets,
+ "RADIUS secrets",
+ parsedline->radiusservers,
+ "RADIUS servers",
+ line_num))
+ return NULL;
+ if (!verify_option_list_length(parsedline->radiusports,
+ "RADIUS ports",
+ parsedline->radiusservers,
+ "RADIUS servers",
+ line_num))
+ return NULL;
+ if (!verify_option_list_length(parsedline->radiusidentifiers,
+ "RADIUS identifiers",
+ parsedline->radiusservers,
+ "RADIUS servers",
+ line_num))
+ return NULL;
}
/*
@@ -1394,14 +1597,40 @@ parse_hba_line(List *line, int line_num, char *raw_line)
return parsedline;
}
+
+static bool
+verify_option_list_length(List *options, char *optionname, List *masters, char *mastername, int line_num)
+{
+ if (list_length(options) == 0 ||
+ list_length(options) == 1 ||
+ list_length(options) == list_length(masters))
+ return true;
+
+ ereport(LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("the number of %s (%i) must be 1 or the same as the number of %s (%i)",
+ optionname,
+ list_length(options),
+ mastername,
+ list_length(masters)
+ ),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ return false;
+}
+
/*
* Parse one name-value pair as an authentication option into the given
* HbaLine. Return true if we successfully parse the option, false if we
- * encounter an error.
+ * encounter an error. In the event of an error, also log a message at
+ * ereport level elevel, and store a message string into *err_msg.
*/
static bool
-parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
+parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
+ int elevel, char **err_msg)
{
+ int line_num = hbaline->linenumber;
+
#ifdef USE_LDAP
hbaline->ldapscope = LDAP_SCOPE_SUBTREE;
#endif
@@ -1418,42 +1647,30 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
}
else if (strcmp(name, "clientcert") == 0)
{
- /*
- * Since we require ctHostSSL, this really can never happen on
- * non-SSL-enabled builds, so don't bother checking for USE_SSL.
- */
if (hbaline->conntype != ctHostSSL)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("clientcert can only be configured for \"hostssl\" rows"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "clientcert can only be configured for \"hostssl\" rows";
return false;
}
if (strcmp(val, "1") == 0)
{
- if (!secure_loaded_verify_locations())
- {
- ereport(LOG,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("client certificates can only be checked if a root certificate store is available"),
- errhint("Make sure the configuration parameter \"%s\" is set.", "ssl_ca_file"),
- errcontext("line %d of configuration file \"%s\"",
- line_num, HbaFileName)));
- return false;
- }
hbaline->clientcert = true;
}
else
{
if (hbaline->auth_method == uaCert)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("clientcert can not be set to 0 when using \"cert\" authentication"),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = "clientcert can not be set to 0 when using \"cert\" authentication";
return false;
}
hbaline->clientcert = false;
@@ -1485,17 +1702,21 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
rc = ldap_url_parse(val, &urldata);
if (rc != LDAP_SUCCESS)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("could not parse LDAP URL \"%s\": %s", val, ldap_err2string(rc))));
+ *err_msg = psprintf("could not parse LDAP URL \"%s\": %s",
+ val, ldap_err2string(rc));
return false;
}
if (strcmp(urldata->lud_scheme, "ldap") != 0)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("unsupported LDAP URL scheme: %s", urldata->lud_scheme)));
+ *err_msg = psprintf("unsupported LDAP URL scheme: %s",
+ urldata->lud_scheme);
ldap_free_urldesc(urldata);
return false;
}
@@ -1509,17 +1730,19 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
hbaline->ldapscope = urldata->lud_scope;
if (urldata->lud_filter)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("filters not supported in LDAP URLs")));
+ *err_msg = "filters not supported in LDAP URLs";
ldap_free_urldesc(urldata);
return false;
}
ldap_free_urldesc(urldata);
#else /* not OpenLDAP */
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("LDAP URLs not supported on this platform")));
+ *err_msg = "LDAP URLs not supported on this platform";
#endif /* not OpenLDAP */
}
else if (strcmp(name, "ldaptls") == 0)
@@ -1541,11 +1764,12 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
hbaline->ldapport = atoi(val);
if (hbaline->ldapport == 0)
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid LDAP port number: \"%s\"", val),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid LDAP port number: \"%s\"", val);
return false;
}
}
@@ -1614,66 +1838,148 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
else
hbaline->upn_username = false;
}
- else if (strcmp(name, "radiusserver") == 0)
+ else if (strcmp(name, "radiusservers") == 0)
{
struct addrinfo *gai_result;
struct addrinfo hints;
int ret;
+ List *parsed_servers;
+ ListCell *l;
+ char *dupval = pstrdup(val);
- REQUIRE_AUTH_OPTION(uaRADIUS, "radiusserver", "radius");
-
- MemSet(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_family = AF_UNSPEC;
+ REQUIRE_AUTH_OPTION(uaRADIUS, "radiusservers", "radius");
- ret = pg_getaddrinfo_all(val, NULL, &hints, &gai_result);
- if (ret || !gai_result)
+ if (!SplitIdentifierString(dupval, ',', &parsed_servers))
{
- ereport(LOG,
+ /* syntax error in list */
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("could not translate RADIUS server name \"%s\" to address: %s",
- val, gai_strerror(ret)),
+ errmsg("could not parse RADIUS server list \"%s\"",
+ val),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
- if (gai_result)
- pg_freeaddrinfo_all(hints.ai_family, gai_result);
return false;
}
- pg_freeaddrinfo_all(hints.ai_family, gai_result);
- hbaline->radiusserver = pstrdup(val);
+
+ /* For each entry in the list, translate it */
+ foreach(l, parsed_servers)
+ {
+ MemSet(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_family = AF_UNSPEC;
+
+ ret = pg_getaddrinfo_all((char *) lfirst(l), NULL, &hints, &gai_result);
+ if (ret || !gai_result)
+ {
+ ereport(elevel,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not translate RADIUS server name \"%s\" to address: %s",
+ (char *) lfirst(l), gai_strerror(ret)),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ if (gai_result)
+ pg_freeaddrinfo_all(hints.ai_family, gai_result);
+
+ list_free(parsed_servers);
+ return false;
+ }
+ pg_freeaddrinfo_all(hints.ai_family, gai_result);
+ }
+
+ /* All entries are OK, so store them */
+ hbaline->radiusservers = parsed_servers;
+ hbaline->radiusservers_s = pstrdup(val);
}
- else if (strcmp(name, "radiusport") == 0)
+ else if (strcmp(name, "radiusports") == 0)
{
- REQUIRE_AUTH_OPTION(uaRADIUS, "radiusport", "radius");
- hbaline->radiusport = atoi(val);
- if (hbaline->radiusport == 0)
+ List *parsed_ports;
+ ListCell *l;
+ char *dupval = pstrdup(val);
+
+ REQUIRE_AUTH_OPTION(uaRADIUS, "radiusports", "radius");
+
+ if (!SplitIdentifierString(dupval, ',', &parsed_ports))
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("invalid RADIUS port number: \"%s\"", val),
+ errmsg("could not parse RADIUS port list \"%s\"",
+ val),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("invalid RADIUS port number: \"%s\"", val);
return false;
}
+
+ foreach(l, parsed_ports)
+ {
+ if (atoi(lfirst(l)) == 0)
+ {
+ ereport(elevel,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid RADIUS port number: \"%s\"", val),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+
+ return false;
+ }
+ }
+ hbaline->radiusports = parsed_ports;
+ hbaline->radiusports_s = pstrdup(val);
}
- else if (strcmp(name, "radiussecret") == 0)
+ else if (strcmp(name, "radiussecrets") == 0)
{
- REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret", "radius");
- hbaline->radiussecret = pstrdup(val);
+ List *parsed_secrets;
+ char *dupval = pstrdup(val);
+
+ REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecrets", "radius");
+
+ if (!SplitIdentifierString(dupval, ',', &parsed_secrets))
+ {
+ /* syntax error in list */
+ ereport(elevel,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not parse RADIUS secret list \"%s\"",
+ val),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ return false;
+ }
+
+ hbaline->radiussecrets = parsed_secrets;
+ hbaline->radiussecrets_s = pstrdup(val);
}
- else if (strcmp(name, "radiusidentifier") == 0)
+ else if (strcmp(name, "radiusidentifiers") == 0)
{
- REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifier", "radius");
- hbaline->radiusidentifier = pstrdup(val);
+ List *parsed_identifiers;
+ char *dupval = pstrdup(val);
+
+ REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifiers", "radius");
+
+ if (!SplitIdentifierString(dupval, ',', &parsed_identifiers))
+ {
+ /* syntax error in list */
+ ereport(elevel,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not parse RADIUS identifiers list \"%s\"",
+ val),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ return false;
+ }
+
+ hbaline->radiusidentifiers = parsed_identifiers;
+ hbaline->radiusidentifiers_s = pstrdup(val);
}
else
{
- ereport(LOG,
+ ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("unrecognized authentication option name: \"%s\"",
name),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ *err_msg = psprintf("unrecognized authentication option name: \"%s\"",
+ name);
return false;
}
return true;
@@ -1789,11 +2095,7 @@ load_hba(void)
{
FILE *file;
List *hba_lines = NIL;
- List *hba_line_nums = NIL;
- List *hba_raw_lines = NIL;
- ListCell *line,
- *line_num,
- *raw_line;
+ ListCell *line;
List *new_parsed_lines = NIL;
bool ok = true;
MemoryContext linecxt;
@@ -1810,36 +2112,36 @@ load_hba(void)
return false;
}
- linecxt = tokenize_file(HbaFileName, file, &hba_lines, &hba_line_nums, &hba_raw_lines);
+ linecxt = tokenize_file(HbaFileName, file, &hba_lines, LOG);
FreeFile(file);
/* Now parse all the lines */
Assert(PostmasterContext);
hbacxt = AllocSetContextCreate(PostmasterContext,
"hba parser context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(hbacxt);
- forthree(line, hba_lines, line_num, hba_line_nums, raw_line, hba_raw_lines)
+ foreach(line, hba_lines)
{
+ TokenizedLine *tok_line = (TokenizedLine *) lfirst(line);
HbaLine *newline;
- if ((newline = parse_hba_line(lfirst(line), lfirst_int(line_num), lfirst(raw_line))) == NULL)
+ /* don't parse lines that already have errors */
+ if (tok_line->err_msg != NULL)
{
- /*
- * Parse error in the file, so indicate there's a problem. NB: a
- * problem in a line will free the memory for all previous lines
- * as well!
- */
- MemoryContextReset(hbacxt);
- new_parsed_lines = NIL;
+ ok = false;
+ continue;
+ }
+
+ if ((newline = parse_hba_line(tok_line, LOG)) == NULL)
+ {
+ /* Parse error; remember there's trouble */
ok = false;
/*
* Keep parsing the rest of the file so we can report errors on
- * more than the first row. Error has already been reported in the
- * parsing function, so no need to log it here.
+ * more than the first line. Error has already been logged, no
+ * need for more chatter here.
*/
continue;
}
@@ -1882,10 +2184,418 @@ load_hba(void)
}
/*
+ * This macro specifies the maximum number of authentication options
+ * that are possible with any given authentication method that is supported.
+ * Currently LDAP supports 10, so the macro value is well above the most any
+ * method needs.
+ */
+#define MAX_HBA_OPTIONS 12
+
+/*
+ * Create a text array listing the options specified in the HBA line.
+ * Return NULL if no options are specified.
+ */
+static ArrayType *
+gethba_options(HbaLine *hba)
+{
+ int noptions;
+ Datum options[MAX_HBA_OPTIONS];
+
+ noptions = 0;
+
+ if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
+ {
+ if (hba->include_realm)
+ options[noptions++] =
+ CStringGetTextDatum("include_realm=true");
+
+ if (hba->krb_realm)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("krb_realm=%s", hba->krb_realm));
+ }
+
+ if (hba->usermap)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("map=%s", hba->usermap));
+
+ if (hba->clientcert)
+ options[noptions++] =
+ CStringGetTextDatum("clientcert=true");
+
+ if (hba->pamservice)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
+
+ if (hba->auth_method == uaLDAP)
+ {
+ if (hba->ldapserver)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapserver=%s", hba->ldapserver));
+
+ if (hba->ldapport)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport));
+
+ if (hba->ldaptls)
+ options[noptions++] =
+ CStringGetTextDatum("ldaptls=true");
+
+ if (hba->ldapprefix)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapprefix=%s", hba->ldapprefix));
+
+ if (hba->ldapsuffix)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapsuffix=%s", hba->ldapsuffix));
+
+ if (hba->ldapbasedn)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapbasedn=%s", hba->ldapbasedn));
+
+ if (hba->ldapbinddn)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapbinddn=%s", hba->ldapbinddn));
+
+ if (hba->ldapbindpasswd)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapbindpasswd=%s",
+ hba->ldapbindpasswd));
+
+ if (hba->ldapsearchattribute)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
+ hba->ldapsearchattribute));
+
+ if (hba->ldapscope)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope));
+ }
+
+ if (hba->auth_method == uaRADIUS)
+ {
+ if (hba->radiusservers_s)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s));
+
+ if (hba->radiussecrets_s)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s));
+
+ if (hba->radiusidentifiers_s)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s));
+
+ if (hba->radiusports_s)
+ options[noptions++] =
+ CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s));
+ }
+
+ Assert(noptions <= MAX_HBA_OPTIONS);
+
+ if (noptions > 0)
+ return construct_array(options, noptions, TEXTOID, -1, false, 'i');
+ else
+ return NULL;
+}
+
+/* Number of columns in pg_hba_file_rules view */
+#define NUM_PG_HBA_FILE_RULES_ATTS 9
+
+/*
+ * fill_hba_line: build one row of pg_hba_file_rules view, add it to tuplestore
+ *
+ * tuple_store: where to store data
+ * tupdesc: tuple descriptor for the view
+ * lineno: pg_hba.conf line number (must always be valid)
+ * hba: parsed line data (can be NULL, in which case err_msg should be set)
+ * err_msg: error message (NULL if none)
+ *
+ * Note: leaks memory, but we don't care since this is run in a short-lived
+ * memory context.
+ */
+static void
+fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
+ int lineno, HbaLine *hba, const char *err_msg)
+{
+ Datum values[NUM_PG_HBA_FILE_RULES_ATTS];
+ bool nulls[NUM_PG_HBA_FILE_RULES_ATTS];
+ char buffer[NI_MAXHOST];
+ HeapTuple tuple;
+ int index;
+ ListCell *lc;
+ const char *typestr;
+ const char *addrstr;
+ const char *maskstr;
+ ArrayType *options;
+
+ Assert(tupdesc->natts == NUM_PG_HBA_FILE_RULES_ATTS);
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, 0, sizeof(nulls));
+ index = 0;
+
+ /* line_number */
+ values[index++] = Int32GetDatum(lineno);
+
+ if (hba != NULL)
+ {
+ /* type */
+ /* Avoid a default: case so compiler will warn about missing cases */
+ typestr = NULL;
+ switch (hba->conntype)
+ {
+ case ctLocal:
+ typestr = "local";
+ break;
+ case ctHost:
+ typestr = "host";
+ break;
+ case ctHostSSL:
+ typestr = "hostssl";
+ break;
+ case ctHostNoSSL:
+ typestr = "hostnossl";
+ break;
+ }
+ if (typestr)
+ values[index++] = CStringGetTextDatum(typestr);
+ else
+ nulls[index++] = true;
+
+ /* database */
+ if (hba->databases)
+ {
+ /*
+ * Flatten HbaToken list to string list. It might seem that we
+ * should re-quote any quoted tokens, but that has been rejected
+ * on the grounds that it makes it harder to compare the array
+ * elements to other system catalogs. That makes entries like
+ * "all" or "samerole" formally ambiguous ... but users who name
+ * databases/roles that way are inflicting their own pain.
+ */
+ List *names = NIL;
+
+ foreach(lc, hba->databases)
+ {
+ HbaToken *tok = lfirst(lc);
+
+ names = lappend(names, tok->string);
+ }
+ values[index++] = PointerGetDatum(strlist_to_textarray(names));
+ }
+ else
+ nulls[index++] = true;
+
+ /* user */
+ if (hba->roles)
+ {
+ /* Flatten HbaToken list to string list; see comment above */
+ List *roles = NIL;
+
+ foreach(lc, hba->roles)
+ {
+ HbaToken *tok = lfirst(lc);
+
+ roles = lappend(roles, tok->string);
+ }
+ values[index++] = PointerGetDatum(strlist_to_textarray(roles));
+ }
+ else
+ nulls[index++] = true;
+
+ /* address and netmask */
+ /* Avoid a default: case so compiler will warn about missing cases */
+ addrstr = maskstr = NULL;
+ switch (hba->ip_cmp_method)
+ {
+ case ipCmpMask:
+ if (hba->hostname)
+ {
+ addrstr = hba->hostname;
+ }
+ else
+ {
+ if (pg_getnameinfo_all(&hba->addr, sizeof(hba->addr),
+ buffer, sizeof(buffer),
+ NULL, 0,
+ NI_NUMERICHOST) == 0)
+ {
+ clean_ipv6_addr(hba->addr.ss_family, buffer);
+ addrstr = pstrdup(buffer);
+ }
+ if (pg_getnameinfo_all(&hba->mask, sizeof(hba->mask),
+ buffer, sizeof(buffer),
+ NULL, 0,
+ NI_NUMERICHOST) == 0)
+ {
+ clean_ipv6_addr(hba->mask.ss_family, buffer);
+ maskstr = pstrdup(buffer);
+ }
+ }
+ break;
+ case ipCmpAll:
+ addrstr = "all";
+ break;
+ case ipCmpSameHost:
+ addrstr = "samehost";
+ break;
+ case ipCmpSameNet:
+ addrstr = "samenet";
+ break;
+ }
+ if (addrstr)
+ values[index++] = CStringGetTextDatum(addrstr);
+ else
+ nulls[index++] = true;
+ if (maskstr)
+ values[index++] = CStringGetTextDatum(maskstr);
+ else
+ nulls[index++] = true;
+
+ /*
+ * Make sure UserAuthName[] tracks additions to the UserAuth enum
+ */
+ StaticAssertStmt(lengthof(UserAuthName) == USER_AUTH_LAST + 1,
+ "UserAuthName[] must match the UserAuth enum");
+
+ /* auth_method */
+ values[index++] = CStringGetTextDatum(UserAuthName[hba->auth_method]);
+
+ /* options */
+ options = gethba_options(hba);
+ if (options)
+ values[index++] = PointerGetDatum(options);
+ else
+ nulls[index++] = true;
+ }
+ else
+ {
+ /* no parsing result, so set relevant fields to nulls */
+ memset(&nulls[1], true, (NUM_PG_HBA_FILE_RULES_ATTS - 2) * sizeof(bool));
+ }
+
+ /* error */
+ if (err_msg)
+ values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
+ else
+ nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
+
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+ tuplestore_puttuple(tuple_store, tuple);
+}
+
+/*
+ * Read the pg_hba.conf file and fill the tuplestore with view records.
+ */
+static void
+fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
+{
+ FILE *file;
+ List *hba_lines = NIL;
+ ListCell *line;
+ MemoryContext linecxt;
+ MemoryContext hbacxt;
+ MemoryContext oldcxt;
+
+ /*
+ * In the unlikely event that we can't open pg_hba.conf, we throw an
+ * error, rather than trying to report it via some sort of view entry.
+ * (Most other error conditions should result in a message in a view
+ * entry.)
+ */
+ file = AllocateFile(HbaFileName, "r");
+ if (file == NULL)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open configuration file \"%s\": %m",
+ HbaFileName)));
+
+ linecxt = tokenize_file(HbaFileName, file, &hba_lines, DEBUG3);
+ FreeFile(file);
+
+ /* Now parse all the lines */
+ hbacxt = AllocSetContextCreate(CurrentMemoryContext,
+ "hba parser context",
+ ALLOCSET_SMALL_SIZES);
+ oldcxt = MemoryContextSwitchTo(hbacxt);
+ foreach(line, hba_lines)
+ {
+ TokenizedLine *tok_line = (TokenizedLine *) lfirst(line);
+ HbaLine *hbaline = NULL;
+
+ /* don't parse lines that already have errors */
+ if (tok_line->err_msg == NULL)
+ hbaline = parse_hba_line(tok_line, DEBUG3);
+
+ fill_hba_line(tuple_store, tupdesc, tok_line->line_num,
+ hbaline, tok_line->err_msg);
+ }
+
+ /* Free tokenizer memory */
+ MemoryContextDelete(linecxt);
+ /* Free parse_hba_line memory */
+ MemoryContextSwitchTo(oldcxt);
+ MemoryContextDelete(hbacxt);
+}
+
+/*
+ * SQL-accessible SRF to return all the entries in the pg_hba.conf file.
+ */
+Datum
+pg_hba_file_rules(PG_FUNCTION_ARGS)
+{
+ Tuplestorestate *tuple_store;
+ TupleDesc tupdesc;
+ MemoryContext old_cxt;
+ ReturnSetInfo *rsi;
+
+ /*
+ * We must use the Materialize mode to be safe against HBA file changes
+ * while the cursor is open. It's also more efficient than having to look
+ * up our current position in the parsed list every time.
+ */
+ rsi = (ReturnSetInfo *) fcinfo->resultinfo;
+
+ /* Check to see if caller supports us returning a tuplestore */
+ if (rsi == NULL || !IsA(rsi, ReturnSetInfo))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("set-valued function called in context that cannot accept a set")));
+ if (!(rsi->allowedModes & SFRM_Materialize))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("materialize mode required, but it is not " \
+ "allowed in this context")));
+
+ rsi->returnMode = SFRM_Materialize;
+
+ /* Build a tuple descriptor for our result type */
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+
+ /* Build tuplestore to hold the result rows */
+ old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
+
+ tuple_store =
+ tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
+ false, work_mem);
+ rsi->setDesc = tupdesc;
+ rsi->setResult = tuple_store;
+
+ MemoryContextSwitchTo(old_cxt);
+
+ /* Fill the tuplestore */
+ fill_hba_view(tuple_store, tupdesc);
+
+ PG_RETURN_NULL();
+}
+
+
+/*
* Parse one tokenised line from the ident config file and store the result in
- * an IdentLine structure, or NULL if parsing fails.
+ * an IdentLine structure.
*
- * The tokenised line is a nested List of fields and tokens.
+ * If parsing fails, log a message and return NULL.
*
* If ident_user is a regular expression (ie. begins with a slash), it is
* compiled and stored in IdentLine structure.
@@ -1895,18 +2605,19 @@ load_hba(void)
* NULL.
*/
static IdentLine *
-parse_ident_line(List *line, int line_number)
+parse_ident_line(TokenizedLine *tok_line)
{
+ int line_num = tok_line->line_num;
ListCell *field;
List *tokens;
HbaToken *token;
IdentLine *parsedline;
- Assert(line != NIL);
- field = list_head(line);
+ Assert(tok_line->fields != NIL);
+ field = list_head(tok_line->fields);
parsedline = palloc0(sizeof(IdentLine));
- parsedline->linenumber = line_number;
+ parsedline->linenumber = line_num;
/* Get the map token (must exist) */
tokens = lfirst(field);
@@ -2166,9 +2877,7 @@ load_ident(void)
{
FILE *file;
List *ident_lines = NIL;
- List *ident_line_nums = NIL;
ListCell *line_cell,
- *num_cell,
*parsed_line_cell;
List *new_parsed_lines = NIL;
bool ok = true;
@@ -2188,39 +2897,35 @@ load_ident(void)
return false;
}
- linecxt = tokenize_file(IdentFileName, file, &ident_lines, &ident_line_nums, NULL);
+ linecxt = tokenize_file(IdentFileName, file, &ident_lines, LOG);
FreeFile(file);
/* Now parse all the lines */
Assert(PostmasterContext);
ident_context = AllocSetContextCreate(PostmasterContext,
"ident parser context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(ident_context);
- forboth(line_cell, ident_lines, num_cell, ident_line_nums)
+ foreach(line_cell, ident_lines)
{
- if ((newline = parse_ident_line(lfirst(line_cell), lfirst_int(num_cell))) == NULL)
+ TokenizedLine *tok_line = (TokenizedLine *) lfirst(line_cell);
+
+ /* don't parse lines that already have errors */
+ if (tok_line->err_msg != NULL)
{
- /*
- * Parse error in the file, so indicate there's a problem. Free
- * all the memory and regular expressions of lines parsed so far.
- */
- foreach(parsed_line_cell, new_parsed_lines)
- {
- newline = (IdentLine *) lfirst(parsed_line_cell);
- if (newline->ident_user[0] == '/')
- pg_regfree(&newline->re);
- }
- MemoryContextReset(ident_context);
- new_parsed_lines = NIL;
+ ok = false;
+ continue;
+ }
+
+ if ((newline = parse_ident_line(tok_line)) == NULL)
+ {
+ /* Parse error; remember there's trouble */
ok = false;
/*
* Keep parsing the rest of the file so we can report errors on
- * more than the first row. Error has already been reported in the
- * parsing function, so no need to log it here.
+ * more than the first line. Error has already been logged, no
+ * need for more chatter here.
*/
continue;
}
@@ -2234,7 +2939,11 @@ load_ident(void)
if (!ok)
{
- /* File contained one or more errors, so bail out */
+ /*
+ * File contained one or more errors, so bail out, first being careful
+ * to clean up whatever we allocated. Most stuff will go away via
+ * MemoryContextDelete, but we have to clean up regexes explicitly.
+ */
foreach(parsed_line_cell, new_parsed_lines)
{
newline = (IdentLine *) lfirst(parsed_line_cell);
diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ifaddr.c
index 9591ed2862..10643978c7 100644
--- a/src/backend/libpq/ip.c
+++ b/src/backend/libpq/ifaddr.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
- * ip.c
- * IPv6-aware network access.
+ * ifaddr.c
+ * IP netmask calculations, and enumerating network interfaces.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * src/backend/libpq/ip.c
+ * src/backend/libpq/ifaddr.c
*
* This file and the IPV6 implementation were initially provided by
* Nigel Kukard <[email protected]>, Linux Based Systems Design
@@ -17,11 +17,9 @@
*-------------------------------------------------------------------------
*/
-/* This is intended to be used in both frontend and backend, so use c.h */
-#include "c.h"
+#include "postgres.h"
#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
@@ -32,8 +30,7 @@
#include <arpa/inet.h>
#include <sys/file.h>
-#include "libpq/ip.h"
-
+#include "libpq/ifaddr.h"
static int range_sockaddr_AF_INET(const struct sockaddr_in * addr,
const struct sockaddr_in * netaddr,
@@ -45,226 +42,6 @@ static int range_sockaddr_AF_INET6(const struct sockaddr_in6 * addr,
const struct sockaddr_in6 * netmask);
#endif
-#ifdef HAVE_UNIX_SOCKETS
-static int getaddrinfo_unix(const char *path,
- const struct addrinfo * hintsp,
- struct addrinfo ** result);
-
-static int getnameinfo_unix(const struct sockaddr_un * sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags);
-#endif
-
-
-/*
- * pg_getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets
- */
-int
-pg_getaddrinfo_all(const char *hostname, const char *servname,
- const struct addrinfo * hintp, struct addrinfo ** result)
-{
- int rc;
-
- /* not all versions of getaddrinfo() zero *result on failure */
- *result = NULL;
-
-#ifdef HAVE_UNIX_SOCKETS
- if (hintp->ai_family == AF_UNIX)
- return getaddrinfo_unix(servname, hintp, result);
-#endif
-
- /* NULL has special meaning to getaddrinfo(). */
- rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
- servname, hintp, result);
-
- return rc;
-}
-
-
-/*
- * pg_freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix
- *
- * Note: the ai_family field of the original hint structure must be passed
- * so that we can tell whether the addrinfo struct was built by the system's
- * getaddrinfo() routine or our own getaddrinfo_unix() routine. Some versions
- * of getaddrinfo() might be willing to return AF_UNIX addresses, so it's
- * not safe to look at ai_family in the addrinfo itself.
- */
-void
-pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai)
-{
-#ifdef HAVE_UNIX_SOCKETS
- if (hint_ai_family == AF_UNIX)
- {
- /* struct was built by getaddrinfo_unix (see pg_getaddrinfo_all) */
- while (ai != NULL)
- {
- struct addrinfo *p = ai;
-
- ai = ai->ai_next;
- free(p->ai_addr);
- free(p);
- }
- }
- else
-#endif /* HAVE_UNIX_SOCKETS */
- {
- /* struct was built by getaddrinfo() */
- if (ai != NULL)
- freeaddrinfo(ai);
- }
-}
-
-
-/*
- * pg_getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets
- *
- * The API of this routine differs from the standard getnameinfo() definition
- * in two ways: first, the addr parameter is declared as sockaddr_storage
- * rather than struct sockaddr, and second, the node and service fields are
- * guaranteed to be filled with something even on failure return.
- */
-int
-pg_getnameinfo_all(const struct sockaddr_storage * addr, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags)
-{
- int rc;
-
-#ifdef HAVE_UNIX_SOCKETS
- if (addr && addr->ss_family == AF_UNIX)
- rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen,
- node, nodelen,
- service, servicelen,
- flags);
- else
-#endif
- rc = getnameinfo((const struct sockaddr *) addr, salen,
- node, nodelen,
- service, servicelen,
- flags);
-
- if (rc != 0)
- {
- if (node)
- strlcpy(node, "???", nodelen);
- if (service)
- strlcpy(service, "???", servicelen);
- }
-
- return rc;
-}
-
-
-#if defined(HAVE_UNIX_SOCKETS)
-
-/* -------
- * getaddrinfo_unix - get unix socket info using IPv6-compatible API
- *
- * Bugs: only one addrinfo is set even though hintsp is NULL or
- * ai_socktype is 0
- * AI_CANONNAME is not supported.
- * -------
- */
-static int
-getaddrinfo_unix(const char *path, const struct addrinfo * hintsp,
- struct addrinfo ** result)
-{
- struct addrinfo hints;
- struct addrinfo *aip;
- struct sockaddr_un *unp;
-
- *result = NULL;
-
- MemSet(&hints, 0, sizeof(hints));
-
- if (strlen(path) >= sizeof(unp->sun_path))
- return EAI_FAIL;
-
- if (hintsp == NULL)
- {
- hints.ai_family = AF_UNIX;
- hints.ai_socktype = SOCK_STREAM;
- }
- else
- memcpy(&hints, hintsp, sizeof(hints));
-
- if (hints.ai_socktype == 0)
- hints.ai_socktype = SOCK_STREAM;
-
- if (hints.ai_family != AF_UNIX)
- {
- /* shouldn't have been called */
- return EAI_FAIL;
- }
-
- aip = calloc(1, sizeof(struct addrinfo));
- if (aip == NULL)
- return EAI_MEMORY;
-
- unp = calloc(1, sizeof(struct sockaddr_un));
- if (unp == NULL)
- {
- free(aip);
- return EAI_MEMORY;
- }
-
- aip->ai_family = AF_UNIX;
- aip->ai_socktype = hints.ai_socktype;
- aip->ai_protocol = hints.ai_protocol;
- aip->ai_next = NULL;
- aip->ai_canonname = NULL;
- *result = aip;
-
- unp->sun_family = AF_UNIX;
- aip->ai_addr = (struct sockaddr *) unp;
- aip->ai_addrlen = sizeof(struct sockaddr_un);
-
- strcpy(unp->sun_path, path);
-
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
- unp->sun_len = sizeof(struct sockaddr_un);
-#endif
-
- return 0;
-}
-
-/*
- * Convert an address to a hostname.
- */
-static int
-getnameinfo_unix(const struct sockaddr_un * sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags)
-{
- int ret = -1;
-
- /* Invalid arguments. */
- if (sa == NULL || sa->sun_family != AF_UNIX ||
- (node == NULL && service == NULL))
- return EAI_FAIL;
-
- if (node)
- {
- ret = snprintf(node, nodelen, "%s", "[local]");
- if (ret == -1 || ret > nodelen)
- return EAI_MEMORY;
- }
-
- if (service)
- {
- ret = snprintf(service, servicelen, "%s", sa->sun_path);
- if (ret == -1 || ret > servicelen)
- return EAI_MEMORY;
- }
-
- return 0;
-}
-#endif /* HAVE_UNIX_SOCKETS */
-
/*
* pg_range_sockaddr - is addr within the subnet specified by netaddr/netmask ?
@@ -545,9 +322,7 @@ pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
}
#else /* !HAVE_GETIFADDRS && !WIN32 */
-#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
-#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 86a89edf9a..c853e36232 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -42,10 +42,10 @@
# or "samenet" to match any address in any subnet that the server is
# directly connected to.
#
-# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi",
-# "ident", "peer", "pam", "ldap", "radius" or "cert". Note that
-# "password" sends passwords in clear text; "md5" is preferred since
-# it sends encrypted passwords.
+# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256",
+# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert".
+# Note that "password" sends passwords in clear text; "md5" or
+# "scram-sha-256" are preferred since they send encrypted passwords.
#
# OPTIONS are a set of options for the authentication in the format
# NAME=VALUE. The available options depend on the different
@@ -59,11 +59,11 @@
# its special character, and just match a database or username with
# that name.
#
-# This file is read on server startup and when the postmaster receives
-# a SIGHUP signal. If you edit the file on a running system, you have
-# to SIGHUP the postmaster for the changes to take effect. You can
-# use "pg_ctl reload" to do that.
-
+# This file is read on server startup and when the server receives a
+# SIGHUP signal. If you edit the file on a running system, you have to
+# SIGHUP the server for the changes to take effect, run "pg_ctl reload",
+# or execute "SELECT pg_reload_conf()".
+#
# Put your actual configuration here
# ----------------------------------
#
@@ -84,6 +84,6 @@ host all all 127.0.0.1/32 @authmethodhost@
host all all ::1/128 @authmethodhost@
# Allow replication connections from localhost, by a user with the
# replication privilege.
-@remove-line-for-nolocal@#local replication @default_username@ @authmethodlocal@
-#host replication @default_username@ 127.0.0.1/32 @authmethodhost@
-#host replication @default_username@ ::1/128 @authmethodhost@
+@remove-line-for-nolocal@local replication all @authmethodlocal@
+host replication all 127.0.0.1/32 @authmethodhost@
+host replication all ::1/128 @authmethodhost@
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index ba42753c06..d1cc38beb2 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -27,7 +27,7 @@
* the backend's "backend/libpq" is quite separate from "interfaces/libpq".
* All that remains is similarities of names to trap the unwary...
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/libpq/pqcomm.c
@@ -85,11 +85,11 @@
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
-#ifdef WIN32_ONLY_COMPILER /* mstcpip.h is missing on mingw */
+#ifdef _MSC_VER /* mstcpip.h is missing on mingw */
#include <mstcpip.h>
#endif
-#include "libpq/ip.h"
+#include "common/ip.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "storage/ipc.h"
@@ -145,7 +145,6 @@ static void socket_startcopyout(void);
static void socket_endcopyout(bool errorAbort);
static int internal_putbytes(const char *s, size_t len);
static int internal_flush(void);
-static void socket_set_nonblocking(bool nonblocking);
#ifdef HAVE_UNIX_SOCKETS
static int Lock_AF_UNIX(char *unixSocketDir, char *unixSocketPath);
@@ -320,6 +319,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
char portNumberStr[32];
const char *familyDesc;
char familyDescBuf[64];
+ const char *addrDesc;
+ char addrBuf[NI_MAXHOST];
char *service;
struct addrinfo *addrs = NULL,
*addr;
@@ -408,7 +409,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
break;
}
- /* set up family name for possible error messages */
+ /* set up address family name for log messages */
switch (addr->ai_family)
{
case AF_INET:
@@ -432,13 +433,28 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
break;
}
+ /* set up text form of address for log messages */
+#ifdef HAVE_UNIX_SOCKETS
+ if (addr->ai_family == AF_UNIX)
+ addrDesc = unixSocketPath;
+ else
+#endif
+ {
+ pg_getnameinfo_all((const struct sockaddr_storage *) addr->ai_addr,
+ addr->ai_addrlen,
+ addrBuf, sizeof(addrBuf),
+ NULL, 0,
+ NI_NUMERICHOST);
+ addrDesc = addrBuf;
+ }
+
if ((fd = socket(addr->ai_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
{
ereport(LOG,
(errcode_for_socket_access(),
- /* translator: %s is IPv4, IPv6, or Unix */
- errmsg("could not create %s socket: %m",
- familyDesc)));
+ /* translator: first %s is IPv4, IPv6, or Unix */
+ errmsg("could not create %s socket for address \"%s\": %m",
+ familyDesc, addrDesc)));
continue;
}
@@ -462,7 +478,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
{
ereport(LOG,
(errcode_for_socket_access(),
- errmsg("setsockopt(SO_REUSEADDR) failed: %m")));
+ /* translator: first %s is IPv4, IPv6, or Unix */
+ errmsg("setsockopt(SO_REUSEADDR) failed for %s address \"%s\": %m",
+ familyDesc, addrDesc)));
closesocket(fd);
continue;
}
@@ -477,7 +495,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
{
ereport(LOG,
(errcode_for_socket_access(),
- errmsg("setsockopt(IPV6_V6ONLY) failed: %m")));
+ /* translator: first %s is IPv4, IPv6, or Unix */
+ errmsg("setsockopt(IPV6_V6ONLY) failed for %s address \"%s\": %m",
+ familyDesc, addrDesc)));
closesocket(fd);
continue;
}
@@ -495,9 +515,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
{
ereport(LOG,
(errcode_for_socket_access(),
- /* translator: %s is IPv4, IPv6, or Unix */
- errmsg("could not bind %s socket: %m",
- familyDesc),
+ /* translator: first %s is IPv4, IPv6, or Unix */
+ errmsg("could not bind %s address \"%s\": %m",
+ familyDesc, addrDesc),
(IS_AF_UNIX(addr->ai_family)) ?
errhint("Is another postmaster already running on port %d?"
" If not, remove socket file \"%s\" and retry.",
@@ -534,12 +554,25 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
{
ereport(LOG,
(errcode_for_socket_access(),
- /* translator: %s is IPv4, IPv6, or Unix */
- errmsg("could not listen on %s socket: %m",
- familyDesc)));
+ /* translator: first %s is IPv4, IPv6, or Unix */
+ errmsg("could not listen on %s address \"%s\": %m",
+ familyDesc, addrDesc)));
closesocket(fd);
continue;
}
+
+#ifdef HAVE_UNIX_SOCKETS
+ if (addr->ai_family == AF_UNIX)
+ ereport(LOG,
+ (errmsg("listening on Unix socket \"%s\"",
+ addrDesc)));
+ else
+#endif
+ ereport(LOG,
+ /* translator: first %s is IPv4 or IPv6 */
+ (errmsg("listening on %s address \"%s\", port %d",
+ familyDesc, addrDesc, (int) portNumber)));
+
ListenSocket[listen_index] = fd;
added++;
}
@@ -684,16 +717,6 @@ StreamConnection(pgsocket server_fd, Port *port)
return STATUS_ERROR;
}
-#ifdef SCO_ACCEPT_BUG
-
- /*
- * UnixWare 7+ and OpenServer 5.0.4 are known to have this bug, but it
- * shouldn't hurt to catch it for all versions of those platforms.
- */
- if (port->raddr.addr.ss_family == 0)
- port->raddr.addr.ss_family = AF_UNIX;
-#endif
-
/* fill in the server (local) address */
port->laddr.salen = sizeof(port->laddr.addr);
if (getsockname(port->sock,
diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c
index b5d9d64e54..c8cf67c041 100644
--- a/src/backend/libpq/pqformat.c
+++ b/src/backend/libpq/pqformat.c
@@ -21,7 +21,7 @@
* are different.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/libpq/pqformat.c
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index 921242fbc4..96939327c3 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -3,7 +3,7 @@
* pqmq.c
* Use the frontend/backend protocol for communication over a shm_mq
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/libpq/pqmq.c
@@ -17,6 +17,7 @@
#include "libpq/pqformat.h"
#include "libpq/pqmq.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
@@ -171,7 +172,8 @@ mq_putmessage(char msgtype, const char *s, size_t len)
if (result != SHM_MQ_WOULD_BLOCK)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0,
+ WAIT_EVENT_MQ_PUT_MESSAGE);
ResetLatch(&MyProc->procLatch);
CHECK_FOR_INTERRUPTS();
}
@@ -237,10 +239,26 @@ pq_parse_errornotice(StringInfo msg, ErrorData *edata)
switch (code)
{
case PG_DIAG_SEVERITY:
+ /* ignore, trusting we'll get a nonlocalized version */
+ break;
+ case PG_DIAG_SEVERITY_NONLOCALIZED:
if (strcmp(value, "DEBUG") == 0)
- edata->elevel = DEBUG1; /* or some other DEBUG level */
+ {
+ /*
+ * We can't reconstruct the exact DEBUG level, but
+ * presumably it was >= client_min_messages, so select
+ * DEBUG1 to ensure we'll pass it on to the client.
+ */
+ edata->elevel = DEBUG1;
+ }
else if (strcmp(value, "LOG") == 0)
- edata->elevel = LOG; /* can't be COMMERROR */
+ {
+ /*
+ * It can't be LOG_SERVER_ONLY, or the worker wouldn't
+ * have sent it to us; so LOG is the correct value.
+ */
+ edata->elevel = LOG;
+ }
else if (strcmp(value, "INFO") == 0)
edata->elevel = INFO;
else if (strcmp(value, "NOTICE") == 0)
@@ -254,11 +272,11 @@ pq_parse_errornotice(StringInfo msg, ErrorData *edata)
else if (strcmp(value, "PANIC") == 0)
edata->elevel = PANIC;
else
- elog(ERROR, "unknown error severity");
+ elog(ERROR, "unrecognized error severity: \"%s\"", value);
break;
case PG_DIAG_SQLSTATE:
if (strlen(value) != 5)
- elog(ERROR, "malformed sql state");
+ elog(ERROR, "invalid SQLSTATE: \"%s\"", value);
edata->sqlerrcode = MAKE_SQLSTATE(value[0], value[1], value[2],
value[3], value[4]);
break;
@@ -308,7 +326,7 @@ pq_parse_errornotice(StringInfo msg, ErrorData *edata)
edata->funcname = pstrdup(value);
break;
default:
- elog(ERROR, "unknown error field: %d", (int) code);
+ elog(ERROR, "unrecognized error field code: %d", (int) code);
break;
}
}
diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c
index b5c1855557..476e883a68 100644
--- a/src/backend/libpq/pqsignal.c
+++ b/src/backend/libpq/pqsignal.c
@@ -3,7 +3,7 @@
* pqsignal.c
* Backend signal(2) support (see also src/port/pqsignal.c)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 4c470c3442..78ee4cbc18 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -9,7 +9,7 @@
* proper FooMain() routine for the incarnation.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -33,8 +33,8 @@
#include "bootstrap/bootstrap.h"
#include "common/username.h"
+#include "port/atomics.h"
#include "postmaster/postmaster.h"
-#include "storage/barrier.h"
#include "storage/s_lock.h"
#include "storage/spin.h"
#include "tcop/tcopprot.h"
diff --git a/src/backend/nls.mk b/src/backend/nls.mk
index c021ab87da..627492df17 100644
--- a/src/backend/nls.mk
+++ b/src/backend/nls.mk
@@ -1,6 +1,6 @@
# src/backend/nls.mk
CATALOG_NAME = postgres
-AVAIL_LANGUAGES = de es fr id it ja pl pt_BR ru zh_CN
+AVAIL_LANGUAGES = de es fr id it ja ko pl pt_BR ru zh_CN
GETTEXT_FILES = + gettext-files
GETTEXT_TRIGGERS = $(BACKEND_COMMON_GETTEXT_TRIGGERS) \
GUC_check_errmsg GUC_check_errdetail GUC_check_errhint \
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 0626a49238..3348a22742 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -11,7 +11,7 @@
* bms_is_empty() in preference to testing for NULL.)
*
*
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2003-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/nodes/bitmapset.c
@@ -21,6 +21,7 @@
#include "postgres.h"
#include "access/hash.h"
+#include "nodes/pg_list.h"
#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)
@@ -458,6 +459,35 @@ bms_overlap(const Bitmapset *a, const Bitmapset *b)
}
/*
+ * bms_overlap_list - does a set overlap an integer list?
+ */
+bool
+bms_overlap_list(const Bitmapset *a, const List *b)
+{
+ ListCell *lc;
+ int wordnum,
+ bitnum;
+
+ if (a == NULL || b == NIL)
+ return false;
+
+ foreach(lc, b)
+ {
+ int x = lfirst_int(lc);
+
+ if (x < 0)
+ elog(ERROR, "negative bitmapset member not allowed");
+ wordnum = WORDNUM(x);
+ bitnum = BITNUM(x);
+ if (wordnum < a->nwords)
+ if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
+ return true;
+ }
+
+ return false;
+}
+
+/*
* bms_nonempty_difference - do sets have a nonempty difference?
*/
bool
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 0cdd6559d0..fc21909ea3 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -12,7 +12,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -52,7 +52,7 @@
/* Copy a field that is a pointer to some kind of Node or Node tree */
#define COPY_NODE_FIELD(fldname) \
- (newnode->fldname = copyObject(from->fldname))
+ (newnode->fldname = copyObjectImpl(from->fldname))
/* Copy a field that is a pointer to a Bitmapset */
#define COPY_BITMAPSET_FIELD(fldname) \
@@ -99,7 +99,8 @@ _copyPlannedStmt(const PlannedStmt *from)
COPY_NODE_FIELD(planTree);
COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(resultRelations);
- COPY_NODE_FIELD(utilityStmt);
+ COPY_NODE_FIELD(nonleafResultRelations);
+ COPY_NODE_FIELD(rootResultRelations);
COPY_NODE_FIELD(subplans);
COPY_BITMAPSET_FIELD(rewindPlanIDs);
COPY_NODE_FIELD(rowMarks);
@@ -116,6 +117,9 @@ _copyPlannedStmt(const PlannedStmt *from)
COPY_NODE_FIELD(distributionNodes);
COPY_NODE_FIELD(distributionRestrict);
#endif
+ COPY_NODE_FIELD(utilityStmt);
+ COPY_LOCATION_FIELD(stmt_location);
+ COPY_LOCATION_FIELD(stmt_len);
return newnode;
}
@@ -134,6 +138,7 @@ CopyPlanFields(const Plan *from, Plan *newnode)
COPY_SCALAR_FIELD(plan_rows);
COPY_SCALAR_FIELD(plan_width);
COPY_SCALAR_FIELD(parallel_aware);
+ COPY_SCALAR_FIELD(parallel_safe);
COPY_SCALAR_FIELD(plan_node_id);
COPY_NODE_FIELD(targetlist);
COPY_NODE_FIELD(qual);
@@ -183,6 +188,22 @@ _copyResult(const Result *from)
}
/*
+ * _copyProjectSet
+ */
+static ProjectSet *
+_copyProjectSet(const ProjectSet *from)
+{
+ ProjectSet *newnode = makeNode(ProjectSet);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ return newnode;
+}
+
+/*
* _copyModifyTable
*/
static ModifyTable *
@@ -201,8 +222,10 @@ _copyModifyTable(const ModifyTable *from)
COPY_SCALAR_FIELD(operation);
COPY_SCALAR_FIELD(canSetTag);
COPY_SCALAR_FIELD(nominalRelation);
+ COPY_NODE_FIELD(partitioned_rels);
COPY_NODE_FIELD(resultRelations);
COPY_SCALAR_FIELD(resultRelIndex);
+ COPY_SCALAR_FIELD(rootResultRelIndex);
COPY_NODE_FIELD(plans);
COPY_NODE_FIELD(withCheckOptionLists);
COPY_NODE_FIELD(returningLists);
@@ -236,6 +259,7 @@ _copyAppend(const Append *from)
/*
* copy remainder of node
*/
+ COPY_NODE_FIELD(partitioned_rels);
COPY_NODE_FIELD(appendplans);
return newnode;
@@ -257,6 +281,7 @@ _copyMergeAppend(const MergeAppend *from)
/*
* copy remainder of node
*/
+ COPY_NODE_FIELD(partitioned_rels);
COPY_NODE_FIELD(mergeplans);
COPY_SCALAR_FIELD(numCols);
COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));
@@ -332,6 +357,7 @@ _copyBitmapOr(const BitmapOr *from)
/*
* copy remainder of node
*/
+ COPY_SCALAR_FIELD(isshared);
COPY_NODE_FIELD(bitmapplans);
return newnode;
@@ -360,6 +386,31 @@ _copyGather(const Gather *from)
return newnode;
}
+/*
+ * _copyGatherMerge
+ */
+static GatherMerge *
+_copyGatherMerge(const GatherMerge *from)
+{
+ GatherMerge *newnode = makeNode(GatherMerge);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(num_workers);
+ COPY_SCALAR_FIELD(numCols);
+ COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(collations, from->numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(nullsFirst, from->numCols * sizeof(bool));
+
+ return newnode;
+}
/*
* CopyScanFields
@@ -497,6 +548,7 @@ _copyBitmapIndexScan(const BitmapIndexScan *from)
* copy remainder of node
*/
COPY_SCALAR_FIELD(indexid);
+ COPY_SCALAR_FIELD(isshared);
COPY_NODE_FIELD(indexqual);
COPY_NODE_FIELD(indexqualorig);
@@ -589,6 +641,27 @@ _copyFunctionScan(const FunctionScan *from)
}
/*
+ * _copyTableFuncScan
+ */
+static TableFuncScan *
+_copyTableFuncScan(const TableFuncScan *from)
+{
+ TableFuncScan *newnode = makeNode(TableFuncScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(tablefunc);
+
+ return newnode;
+}
+
+/*
* _copyValuesScan
*/
static ValuesScan *
@@ -632,6 +705,27 @@ _copyCteScan(const CteScan *from)
}
/*
+ * _copyNamedTuplestoreScan
+ */
+static NamedTuplestoreScan *
+_copyNamedTuplestoreScan(const NamedTuplestoreScan *from)
+{
+ NamedTuplestoreScan *newnode = makeNode(NamedTuplestoreScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_STRING_FIELD(enrname);
+
+ return newnode;
+}
+
+/*
* _copyWorkTableScan
*/
static WorkTableScan *
@@ -725,6 +819,7 @@ CopyJoinFields(const Join *from, Join *newnode)
CopyPlanFields((const Plan *) from, (Plan *) newnode);
COPY_SCALAR_FIELD(jointype);
+ COPY_SCALAR_FIELD(inner_unique);
COPY_NODE_FIELD(joinqual);
}
@@ -785,6 +880,7 @@ _copyMergeJoin(const MergeJoin *from)
/*
* copy remainder of node
*/
+ COPY_SCALAR_FIELD(skip_mark_restore);
COPY_NODE_FIELD(mergeclauses);
numCols = list_length(from->mergeclauses);
if (numCols > 0)
@@ -896,6 +992,7 @@ _copyAgg(const Agg *from)
COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid));
}
COPY_SCALAR_FIELD(numGroups);
+ COPY_BITMAPSET_FIELD(aggParams);
COPY_NODE_FIELD(groupingSets);
COPY_NODE_FIELD(chain);
@@ -974,8 +1071,6 @@ _copyHash(const Hash *from)
COPY_SCALAR_FIELD(skewTable);
COPY_SCALAR_FIELD(skewColumn);
COPY_SCALAR_FIELD(skewInherit);
- COPY_SCALAR_FIELD(skewColType);
- COPY_SCALAR_FIELD(skewColTypmod);
return newnode;
}
@@ -1283,7 +1378,7 @@ _copyRangeVar(const RangeVar *from)
COPY_STRING_FIELD(catalogname);
COPY_STRING_FIELD(schemaname);
COPY_STRING_FIELD(relname);
- COPY_SCALAR_FIELD(inhOpt);
+ COPY_SCALAR_FIELD(inh);
COPY_SCALAR_FIELD(relpersistence);
COPY_NODE_FIELD(alias);
COPY_LOCATION_FIELD(location);
@@ -1292,6 +1387,31 @@ _copyRangeVar(const RangeVar *from)
}
/*
+ * _copyTableFunc
+ */
+static TableFunc *
+_copyTableFunc(const TableFunc *from)
+{
+ TableFunc *newnode = makeNode(TableFunc);
+
+ COPY_NODE_FIELD(ns_names);
+ COPY_NODE_FIELD(ns_uris);
+ COPY_NODE_FIELD(docexpr);
+ COPY_NODE_FIELD(rowexpr);
+ COPY_NODE_FIELD(colnames);
+ COPY_NODE_FIELD(coltypes);
+ COPY_NODE_FIELD(coltypmods);
+ COPY_NODE_FIELD(colcollations);
+ COPY_NODE_FIELD(colexprs);
+ COPY_NODE_FIELD(coldefexprs);
+ COPY_BITMAPSET_FIELD(notnulls);
+ COPY_SCALAR_FIELD(ordinalitycol);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+/*
* _copyIntoClause
*/
static IntoClause *
@@ -1652,6 +1772,7 @@ _copySubPlan(const SubPlan *from)
COPY_SCALAR_FIELD(firstColCollation);
COPY_SCALAR_FIELD(useHashTable);
COPY_SCALAR_FIELD(unknownEqFalse);
+ COPY_SCALAR_FIELD(parallel_safe);
COPY_NODE_FIELD(setParam);
COPY_NODE_FIELD(parParam);
COPY_NODE_FIELD(args);
@@ -1929,6 +2050,22 @@ _copyMinMaxExpr(const MinMaxExpr *from)
}
/*
+ * _copySQLValueFunction
+ */
+static SQLValueFunction *
+_copySQLValueFunction(const SQLValueFunction *from)
+{
+ SQLValueFunction *newnode = makeNode(SQLValueFunction);
+
+ COPY_SCALAR_FIELD(op);
+ COPY_SCALAR_FIELD(type);
+ COPY_SCALAR_FIELD(typmod);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+/*
* _copyXmlExpr
*/
static XmlExpr *
@@ -2045,6 +2182,20 @@ _copyCurrentOfExpr(const CurrentOfExpr *from)
return newnode;
}
+ /*
+ * _copyNextValueExpr
+ */
+static NextValueExpr *
+_copyNextValueExpr(const NextValueExpr *from)
+{
+ NextValueExpr *newnode = makeNode(NextValueExpr);
+
+ COPY_SCALAR_FIELD(seqid);
+ COPY_SCALAR_FIELD(typeId);
+
+ return newnode;
+}
+
/*
* _copyInferenceElem
*/
@@ -2184,6 +2335,8 @@ _copyRestrictInfo(const RestrictInfo *from)
COPY_SCALAR_FIELD(outerjoin_delayed);
COPY_SCALAR_FIELD(can_join);
COPY_SCALAR_FIELD(pseudoconstant);
+ COPY_SCALAR_FIELD(leakproof);
+ COPY_SCALAR_FIELD(security_level);
COPY_BITMAPSET_FIELD(clause_relids);
COPY_BITMAPSET_FIELD(required_relids);
COPY_BITMAPSET_FIELD(outer_relids);
@@ -2270,6 +2423,20 @@ _copyAppendRelInfo(const AppendRelInfo *from)
}
/*
+ * _copyPartitionedChildRelInfo
+ */
+static PartitionedChildRelInfo *
+_copyPartitionedChildRelInfo(const PartitionedChildRelInfo *from)
+{
+ PartitionedChildRelInfo *newnode = makeNode(PartitionedChildRelInfo);
+
+ COPY_SCALAR_FIELD(parent_relid);
+ COPY_NODE_FIELD(child_rels);
+
+ return newnode;
+}
+
+/*
* _copyPlaceHolderInfo
*/
static PlaceHolderInfo *
@@ -2308,14 +2475,15 @@ _copyRangeTblEntry(const RangeTblEntry *from)
COPY_NODE_FIELD(joinaliasvars);
COPY_NODE_FIELD(functions);
COPY_SCALAR_FIELD(funcordinality);
+ COPY_NODE_FIELD(tablefunc);
COPY_NODE_FIELD(values_lists);
- COPY_NODE_FIELD(values_collations);
COPY_STRING_FIELD(ctename);
COPY_SCALAR_FIELD(ctelevelsup);
COPY_SCALAR_FIELD(self_reference);
- COPY_NODE_FIELD(ctecoltypes);
- COPY_NODE_FIELD(ctecoltypmods);
- COPY_NODE_FIELD(ctecolcollations);
+ COPY_STRING_FIELD(enrname);
+ COPY_NODE_FIELD(coltypes);
+ COPY_NODE_FIELD(coltypmods);
+ COPY_NODE_FIELD(colcollations);
COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(eref);
COPY_SCALAR_FIELD(lateral);
@@ -2730,6 +2898,38 @@ _copyRangeTableSample(const RangeTableSample *from)
return newnode;
}
+static RangeTableFunc *
+_copyRangeTableFunc(const RangeTableFunc *from)
+{
+ RangeTableFunc *newnode = makeNode(RangeTableFunc);
+
+ COPY_SCALAR_FIELD(lateral);
+ COPY_NODE_FIELD(docexpr);
+ COPY_NODE_FIELD(rowexpr);
+ COPY_NODE_FIELD(namespaces);
+ COPY_NODE_FIELD(columns);
+ COPY_NODE_FIELD(alias);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+static RangeTableFuncCol *
+_copyRangeTableFuncCol(const RangeTableFuncCol *from)
+{
+ RangeTableFuncCol *newnode = makeNode(RangeTableFuncCol);
+
+ COPY_STRING_FIELD(colname);
+ COPY_NODE_FIELD(typeName);
+ COPY_SCALAR_FIELD(for_ordinality);
+ COPY_SCALAR_FIELD(is_not_null);
+ COPY_NODE_FIELD(colexpr);
+ COPY_NODE_FIELD(coldefexpr);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
static TypeCast *
_copyTypeCast(const TypeCast *from)
{
@@ -2781,9 +2981,11 @@ _copyColumnDef(const ColumnDef *from)
COPY_SCALAR_FIELD(is_local);
COPY_SCALAR_FIELD(is_not_null);
COPY_SCALAR_FIELD(is_from_type);
+ COPY_SCALAR_FIELD(is_from_parent);
COPY_SCALAR_FIELD(storage);
COPY_NODE_FIELD(raw_default);
COPY_NODE_FIELD(cooked_default);
+ COPY_SCALAR_FIELD(identity);
COPY_NODE_FIELD(collClause);
COPY_SCALAR_FIELD(collOid);
COPY_NODE_FIELD(constraints);
@@ -2806,6 +3008,7 @@ _copyConstraint(const Constraint *from)
COPY_SCALAR_FIELD(is_no_inherit);
COPY_NODE_FIELD(raw_expr);
COPY_STRING_FIELD(cooked_expr);
+ COPY_SCALAR_FIELD(generated_when);
COPY_NODE_FIELD(keys);
COPY_NODE_FIELD(exclusions);
COPY_NODE_FIELD(options);
@@ -2836,6 +3039,7 @@ _copyDefElem(const DefElem *from)
COPY_STRING_FIELD(defname);
COPY_NODE_FIELD(arg);
COPY_SCALAR_FIELD(defaction);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
@@ -2877,6 +3081,18 @@ _copyRoleSpec(const RoleSpec *from)
return newnode;
}
+static TriggerTransition *
+_copyTriggerTransition(const TriggerTransition *from)
+{
+ TriggerTransition *newnode = makeNode(TriggerTransition);
+
+ COPY_STRING_FIELD(name);
+ COPY_SCALAR_FIELD(isNew);
+ COPY_SCALAR_FIELD(isTable);
+
+ return newnode;
+}
+
static Query *
_copyQuery(const Query *from)
{
@@ -2890,6 +3106,7 @@ _copyQuery(const Query *from)
COPY_SCALAR_FIELD(resultRelation);
COPY_SCALAR_FIELD(hasAggs);
COPY_SCALAR_FIELD(hasWindowFuncs);
+ COPY_SCALAR_FIELD(hasTargetSRFs);
COPY_SCALAR_FIELD(hasSubLinks);
COPY_SCALAR_FIELD(hasDistinctOn);
COPY_SCALAR_FIELD(hasRecursive);
@@ -2900,6 +3117,7 @@ _copyQuery(const Query *from)
COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(jointree);
COPY_NODE_FIELD(targetList);
+ COPY_SCALAR_FIELD(override);
COPY_NODE_FIELD(onConflict);
COPY_NODE_FIELD(returningList);
COPY_NODE_FIELD(groupClause);
@@ -2914,6 +3132,20 @@ _copyQuery(const Query *from)
COPY_NODE_FIELD(setOperations);
COPY_NODE_FIELD(constraintDeps);
COPY_NODE_FIELD(withCheckOptions);
+ COPY_LOCATION_FIELD(stmt_location);
+ COPY_LOCATION_FIELD(stmt_len);
+
+ return newnode;
+}
+
+static RawStmt *
+_copyRawStmt(const RawStmt *from)
+{
+ RawStmt *newnode = makeNode(RawStmt);
+
+ COPY_NODE_FIELD(stmt);
+ COPY_LOCATION_FIELD(stmt_location);
+ COPY_LOCATION_FIELD(stmt_len);
return newnode;
}
@@ -2929,6 +3161,7 @@ _copyInsertStmt(const InsertStmt *from)
COPY_NODE_FIELD(onConflictClause);
COPY_NODE_FIELD(returningList);
COPY_NODE_FIELD(withClause);
+ COPY_SCALAR_FIELD(override);
return newnode;
}
@@ -3034,6 +3267,16 @@ _copyAlterTableCmd(const AlterTableCmd *from)
return newnode;
}
+static AlterCollationStmt *
+_copyAlterCollationStmt(const AlterCollationStmt *from)
+{
+ AlterCollationStmt *newnode = makeNode(AlterCollationStmt);
+
+ COPY_NODE_FIELD(collname);
+
+ return newnode;
+}
+
static AlterDomainStmt *
_copyAlterDomainStmt(const AlterDomainStmt *from)
{
@@ -3066,13 +3309,14 @@ _copyGrantStmt(const GrantStmt *from)
return newnode;
}
-static FuncWithArgs *
-_copyFuncWithArgs(const FuncWithArgs *from)
+static ObjectWithArgs *
+_copyObjectWithArgs(const ObjectWithArgs *from)
{
- FuncWithArgs *newnode = makeNode(FuncWithArgs);
+ ObjectWithArgs *newnode = makeNode(ObjectWithArgs);
- COPY_NODE_FIELD(funcname);
- COPY_NODE_FIELD(funcargs);
+ COPY_NODE_FIELD(objname);
+ COPY_NODE_FIELD(objargs);
+ COPY_SCALAR_FIELD(args_unspecified);
return newnode;
}
@@ -3200,6 +3444,8 @@ CopyCreateStmtFields(const CreateStmt *from, CreateStmt *newnode)
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(tableElts);
COPY_NODE_FIELD(inhRelations);
+ COPY_NODE_FIELD(partspec);
+ COPY_NODE_FIELD(partbound);
COPY_NODE_FIELD(ofTypename);
COPY_NODE_FIELD(constraints);
COPY_NODE_FIELD(options);
@@ -3245,6 +3491,7 @@ _copyDefineStmt(const DefineStmt *from)
COPY_NODE_FIELD(defnames);
COPY_NODE_FIELD(args);
COPY_NODE_FIELD(definition);
+ COPY_SCALAR_FIELD(if_not_exists);
return newnode;
}
@@ -3255,7 +3502,6 @@ _copyDropStmt(const DropStmt *from)
DropStmt *newnode = makeNode(DropStmt);
COPY_NODE_FIELD(objects);
- COPY_NODE_FIELD(arguments);
COPY_SCALAR_FIELD(removeType);
COPY_SCALAR_FIELD(behavior);
COPY_SCALAR_FIELD(missing_ok);
@@ -3282,8 +3528,7 @@ _copyCommentStmt(const CommentStmt *from)
CommentStmt *newnode = makeNode(CommentStmt);
COPY_SCALAR_FIELD(objtype);
- COPY_NODE_FIELD(objname);
- COPY_NODE_FIELD(objargs);
+ COPY_NODE_FIELD(object);
COPY_STRING_FIELD(comment);
return newnode;
@@ -3295,8 +3540,7 @@ _copySecLabelStmt(const SecLabelStmt *from)
SecLabelStmt *newnode = makeNode(SecLabelStmt);
COPY_SCALAR_FIELD(objtype);
- COPY_NODE_FIELD(objname);
- COPY_NODE_FIELD(objargs);
+ COPY_NODE_FIELD(object);
COPY_STRING_FIELD(provider);
COPY_STRING_FIELD(label);
@@ -3344,6 +3588,20 @@ _copyIndexStmt(const IndexStmt *from)
return newnode;
}
+static CreateStatsStmt *
+_copyCreateStatsStmt(const CreateStatsStmt *from)
+{
+ CreateStatsStmt *newnode = makeNode(CreateStatsStmt);
+
+ COPY_NODE_FIELD(defnames);
+ COPY_NODE_FIELD(stat_types);
+ COPY_NODE_FIELD(exprs);
+ COPY_NODE_FIELD(relations);
+ COPY_SCALAR_FIELD(if_not_exists);
+
+ return newnode;
+}
+
static CreateFunctionStmt *
_copyCreateFunctionStmt(const CreateFunctionStmt *from)
{
@@ -3402,7 +3660,6 @@ _copyRenameStmt(const RenameStmt *from)
COPY_SCALAR_FIELD(relationType);
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(object);
- COPY_NODE_FIELD(objarg);
COPY_STRING_FIELD(subname);
COPY_STRING_FIELD(newname);
COPY_SCALAR_FIELD(behavior);
@@ -3418,8 +3675,7 @@ _copyAlterObjectDependsStmt(const AlterObjectDependsStmt *from)
COPY_SCALAR_FIELD(objectType);
COPY_NODE_FIELD(relation);
- COPY_NODE_FIELD(objname);
- COPY_NODE_FIELD(objargs);
+ COPY_NODE_FIELD(object);
COPY_NODE_FIELD(extname);
return newnode;
@@ -3433,7 +3689,6 @@ _copyAlterObjectSchemaStmt(const AlterObjectSchemaStmt *from)
COPY_SCALAR_FIELD(objectType);
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(object);
- COPY_NODE_FIELD(objarg);
COPY_STRING_FIELD(newschema);
COPY_SCALAR_FIELD(missing_ok);
@@ -3448,7 +3703,6 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from)
COPY_SCALAR_FIELD(objectType);
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(object);
- COPY_NODE_FIELD(objarg);
COPY_NODE_FIELD(newowner);
return newnode;
@@ -3460,7 +3714,6 @@ _copyAlterOperatorStmt(const AlterOperatorStmt *from)
AlterOperatorStmt *newnode = makeNode(AlterOperatorStmt);
COPY_NODE_FIELD(opername);
- COPY_NODE_FIELD(operargs);
COPY_NODE_FIELD(options);
return newnode;
@@ -3564,10 +3817,11 @@ _copyAlterEnumStmt(const AlterEnumStmt *from)
AlterEnumStmt *newnode = makeNode(AlterEnumStmt);
COPY_NODE_FIELD(typeName);
+ COPY_STRING_FIELD(oldVal);
COPY_STRING_FIELD(newVal);
COPY_STRING_FIELD(newValNeighbor);
COPY_SCALAR_FIELD(newValIsAfter);
- COPY_SCALAR_FIELD(skipIfExists);
+ COPY_SCALAR_FIELD(skipIfNewValExists);
return newnode;
}
@@ -3632,7 +3886,6 @@ _copyCreateOpClassItem(const CreateOpClassItem *from)
COPY_SCALAR_FIELD(itemtype);
COPY_NODE_FIELD(name);
- COPY_NODE_FIELD(args);
COPY_SCALAR_FIELD(number);
COPY_NODE_FIELD(order_family);
COPY_NODE_FIELD(class_args);
@@ -3790,6 +4043,7 @@ _copyCreateSeqStmt(const CreateSeqStmt *from)
COPY_NODE_FIELD(sequence);
COPY_NODE_FIELD(options);
COPY_SCALAR_FIELD(ownerId);
+ COPY_SCALAR_FIELD(for_identity);
COPY_SCALAR_FIELD(if_not_exists);
return newnode;
@@ -3802,6 +4056,7 @@ _copyAlterSeqStmt(const AlterSeqStmt *from)
COPY_NODE_FIELD(sequence);
COPY_NODE_FIELD(options);
+ COPY_SCALAR_FIELD(for_identity);
COPY_SCALAR_FIELD(missing_ok);
return newnode;
@@ -3921,8 +4176,7 @@ _copyAlterExtensionContentsStmt(const AlterExtensionContentsStmt *from)
COPY_STRING_FIELD(extname);
COPY_SCALAR_FIELD(action);
COPY_SCALAR_FIELD(objtype);
- COPY_NODE_FIELD(objname);
- COPY_NODE_FIELD(objargs);
+ COPY_NODE_FIELD(object);
return newnode;
}
@@ -3961,6 +4215,7 @@ _copyCreateForeignServerStmt(const CreateForeignServerStmt *from)
COPY_STRING_FIELD(version);
COPY_STRING_FIELD(fdwname);
COPY_NODE_FIELD(options);
+ COPY_SCALAR_FIELD(if_not_exists);
return newnode;
}
@@ -3986,6 +4241,7 @@ _copyCreateUserMappingStmt(const CreateUserMappingStmt *from)
COPY_NODE_FIELD(user);
COPY_STRING_FIELD(servername);
COPY_NODE_FIELD(options);
+ COPY_SCALAR_FIELD(if_not_exists);
return newnode;
}
@@ -4083,6 +4339,7 @@ _copyCreateTrigStmt(const CreateTrigStmt *from)
COPY_NODE_FIELD(columns);
COPY_NODE_FIELD(whenClause);
COPY_SCALAR_FIELD(isconstraint);
+ COPY_NODE_FIELD(transitionRels);
COPY_SCALAR_FIELD(deferrable);
COPY_SCALAR_FIELD(initdeferred);
COPY_NODE_FIELD(constrrel);
@@ -4343,6 +4600,7 @@ _copyCreatePolicyStmt(const CreatePolicyStmt *from)
COPY_STRING_FIELD(policy_name);
COPY_NODE_FIELD(table);
COPY_STRING_FIELD(cmd_name);
+ COPY_SCALAR_FIELD(permissive);
COPY_NODE_FIELD(roles);
COPY_NODE_FIELD(qual);
COPY_NODE_FIELD(with_check);
@@ -4364,6 +4622,135 @@ _copyAlterPolicyStmt(const AlterPolicyStmt *from)
return newnode;
}
+static PartitionElem *
+_copyPartitionElem(const PartitionElem *from)
+{
+ PartitionElem *newnode = makeNode(PartitionElem);
+
+ COPY_STRING_FIELD(name);
+ COPY_NODE_FIELD(expr);
+ COPY_NODE_FIELD(collation);
+ COPY_NODE_FIELD(opclass);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+static PartitionSpec *
+_copyPartitionSpec(const PartitionSpec *from)
+{
+ PartitionSpec *newnode = makeNode(PartitionSpec);
+
+ COPY_STRING_FIELD(strategy);
+ COPY_NODE_FIELD(partParams);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+static PartitionBoundSpec *
+_copyPartitionBoundSpec(const PartitionBoundSpec *from)
+{
+ PartitionBoundSpec *newnode = makeNode(PartitionBoundSpec);
+
+ COPY_SCALAR_FIELD(strategy);
+ COPY_NODE_FIELD(listdatums);
+ COPY_NODE_FIELD(lowerdatums);
+ COPY_NODE_FIELD(upperdatums);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+static PartitionRangeDatum *
+_copyPartitionRangeDatum(const PartitionRangeDatum *from)
+{
+ PartitionRangeDatum *newnode = makeNode(PartitionRangeDatum);
+
+ COPY_SCALAR_FIELD(infinite);
+ COPY_NODE_FIELD(value);
+ COPY_LOCATION_FIELD(location);
+
+ return newnode;
+}
+
+static PartitionCmd *
+_copyPartitionCmd(const PartitionCmd *from)
+{
+ PartitionCmd *newnode = makeNode(PartitionCmd);
+
+ COPY_NODE_FIELD(name);
+ COPY_NODE_FIELD(bound);
+
+ return newnode;
+}
+
+static CreatePublicationStmt *
+_copyCreatePublicationStmt(const CreatePublicationStmt *from)
+{
+ CreatePublicationStmt *newnode = makeNode(CreatePublicationStmt);
+
+ COPY_STRING_FIELD(pubname);
+ COPY_NODE_FIELD(options);
+ COPY_NODE_FIELD(tables);
+ COPY_SCALAR_FIELD(for_all_tables);
+
+ return newnode;
+}
+
+static AlterPublicationStmt *
+_copyAlterPublicationStmt(const AlterPublicationStmt *from)
+{
+ AlterPublicationStmt *newnode = makeNode(AlterPublicationStmt);
+
+ COPY_STRING_FIELD(pubname);
+ COPY_NODE_FIELD(options);
+ COPY_NODE_FIELD(tables);
+ COPY_SCALAR_FIELD(for_all_tables);
+ COPY_SCALAR_FIELD(tableAction);
+
+ return newnode;
+}
+
+static CreateSubscriptionStmt *
+_copyCreateSubscriptionStmt(const CreateSubscriptionStmt *from)
+{
+ CreateSubscriptionStmt *newnode = makeNode(CreateSubscriptionStmt);
+
+ COPY_STRING_FIELD(subname);
+ COPY_STRING_FIELD(conninfo);
+ COPY_NODE_FIELD(publication);
+ COPY_NODE_FIELD(options);
+
+ return newnode;
+}
+
+static AlterSubscriptionStmt *
+_copyAlterSubscriptionStmt(const AlterSubscriptionStmt *from)
+{
+ AlterSubscriptionStmt *newnode = makeNode(AlterSubscriptionStmt);
+
+ COPY_SCALAR_FIELD(kind);
+ COPY_STRING_FIELD(subname);
+ COPY_STRING_FIELD(conninfo);
+ COPY_NODE_FIELD(publication);
+ COPY_NODE_FIELD(options);
+
+ return newnode;
+}
+
+static DropSubscriptionStmt *
+_copyDropSubscriptionStmt(const DropSubscriptionStmt *from)
+{
+ DropSubscriptionStmt *newnode = makeNode(DropSubscriptionStmt);
+
+ COPY_STRING_FIELD(subname);
+ COPY_SCALAR_FIELD(missing_ok);
+ COPY_SCALAR_FIELD(behavior);
+
+ return newnode;
+}
+
/* ****************************************************************
* pg_list.h copy functions
* ****************************************************************
@@ -4376,7 +4763,7 @@ _copyAlterPolicyStmt(const AlterPolicyStmt *from)
*/
#define COPY_NODE_CELL(new, old) \
(new) = (ListCell *) palloc(sizeof(ListCell)); \
- lfirst(new) = copyObject(lfirst(old));
+ lfirst(new) = copyObjectImpl(lfirst(old));
static List *
_copyList(const List *from)
@@ -4581,13 +4968,13 @@ _copyCleanConnStmt(const CleanConnStmt *from)
#endif
/*
- * copyObject
+ * copyObjectImpl -- implementation of copyObject(); see nodes/nodes.h
*
* Create a copy of a Node tree or list. This is a "deep" copy: all
* substructure is copied too, recursively.
*/
void *
-copyObject(const void *from)
+copyObjectImpl(const void *from)
{
void *retval;
@@ -4611,6 +4998,9 @@ copyObject(const void *from)
case T_Result:
retval = _copyResult(from);
break;
+ case T_ProjectSet:
+ retval = _copyProjectSet(from);
+ break;
case T_ModifyTable:
retval = _copyModifyTable(from);
break;
@@ -4635,6 +5025,9 @@ copyObject(const void *from)
case T_Gather:
retval = _copyGather(from);
break;
+ case T_GatherMerge:
+ retval = _copyGatherMerge(from);
+ break;
case T_SeqScan:
retval = _copySeqScan(from);
break;
@@ -4662,12 +5055,18 @@ copyObject(const void *from)
case T_FunctionScan:
retval = _copyFunctionScan(from);
break;
+ case T_TableFuncScan:
+ retval = _copyTableFuncScan(from);
+ break;
case T_ValuesScan:
retval = _copyValuesScan(from);
break;
case T_CteScan:
retval = _copyCteScan(from);
break;
+ case T_NamedTuplestoreScan:
+ retval = _copyNamedTuplestoreScan(from);
+ break;
case T_WorkTableScan:
retval = _copyWorkTableScan(from);
break;
@@ -4762,6 +5161,9 @@ copyObject(const void *from)
case T_RangeVar:
retval = _copyRangeVar(from);
break;
+ case T_TableFunc:
+ retval = _copyTableFunc(from);
+ break;
case T_IntoClause:
retval = _copyIntoClause(from);
break;
@@ -4861,6 +5263,9 @@ copyObject(const void *from)
case T_MinMaxExpr:
retval = _copyMinMaxExpr(from);
break;
+ case T_SQLValueFunction:
+ retval = _copySQLValueFunction(from);
+ break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;
@@ -4882,6 +5287,9 @@ copyObject(const void *from)
case T_CurrentOfExpr:
retval = _copyCurrentOfExpr(from);
break;
+ case T_NextValueExpr:
+ retval = _copyNextValueExpr(from);
+ break;
case T_InferenceElem:
retval = _copyInferenceElem(from);
break;
@@ -4919,6 +5327,9 @@ copyObject(const void *from)
case T_AppendRelInfo:
retval = _copyAppendRelInfo(from);
break;
+ case T_PartitionedChildRelInfo:
+ retval = _copyPartitionedChildRelInfo(from);
+ break;
case T_PlaceHolderInfo:
retval = _copyPlaceHolderInfo(from);
break;
@@ -4963,6 +5374,9 @@ copyObject(const void *from)
case T_Query:
retval = _copyQuery(from);
break;
+ case T_RawStmt:
+ retval = _copyRawStmt(from);
+ break;
case T_InsertStmt:
retval = _copyInsertStmt(from);
break;
@@ -4984,6 +5398,9 @@ copyObject(const void *from)
case T_AlterTableCmd:
retval = _copyAlterTableCmd(from);
break;
+ case T_AlterCollationStmt:
+ retval = _copyAlterCollationStmt(from);
+ break;
case T_AlterDomainStmt:
retval = _copyAlterDomainStmt(from);
break;
@@ -5035,6 +5452,9 @@ copyObject(const void *from)
case T_IndexStmt:
retval = _copyIndexStmt(from);
break;
+ case T_CreateStatsStmt:
+ retval = _copyCreateStatsStmt(from);
+ break;
case T_CreateFunctionStmt:
retval = _copyCreateFunctionStmt(from);
break;
@@ -5307,6 +5727,21 @@ copyObject(const void *from)
case T_AlterPolicyStmt:
retval = _copyAlterPolicyStmt(from);
break;
+ case T_CreatePublicationStmt:
+ retval = _copyCreatePublicationStmt(from);
+ break;
+ case T_AlterPublicationStmt:
+ retval = _copyAlterPublicationStmt(from);
+ break;
+ case T_CreateSubscriptionStmt:
+ retval = _copyCreateSubscriptionStmt(from);
+ break;
+ case T_AlterSubscriptionStmt:
+ retval = _copyAlterSubscriptionStmt(from);
+ break;
+ case T_DropSubscriptionStmt:
+ retval = _copyDropSubscriptionStmt(from);
+ break;
case T_A_Expr:
retval = _copyAExpr(from);
break;
@@ -5361,6 +5796,12 @@ copyObject(const void *from)
case T_RangeTableSample:
retval = _copyRangeTableSample(from);
break;
+ case T_RangeTableFunc:
+ retval = _copyRangeTableFunc(from);
+ break;
+ case T_RangeTableFuncCol:
+ retval = _copyRangeTableFuncCol(from);
+ break;
case T_TypeName:
retval = _copyTypeName(from);
break;
@@ -5415,8 +5856,8 @@ copyObject(const void *from)
case T_CommonTableExpr:
retval = _copyCommonTableExpr(from);
break;
- case T_FuncWithArgs:
- retval = _copyFuncWithArgs(from);
+ case T_ObjectWithArgs:
+ retval = _copyObjectWithArgs(from);
break;
case T_AccessPriv:
retval = _copyAccessPriv(from);
@@ -5436,6 +5877,24 @@ copyObject(const void *from)
case T_RoleSpec:
retval = _copyRoleSpec(from);
break;
+ case T_TriggerTransition:
+ retval = _copyTriggerTransition(from);
+ break;
+ case T_PartitionElem:
+ retval = _copyPartitionElem(from);
+ break;
+ case T_PartitionSpec:
+ retval = _copyPartitionSpec(from);
+ break;
+ case T_PartitionBoundSpec:
+ retval = _copyPartitionBoundSpec(from);
+ break;
+ case T_PartitionRangeDatum:
+ retval = _copyPartitionRangeDatum(from);
+ break;
+ case T_PartitionCmd:
+ retval = _copyPartitionCmd(from);
+ break;
/*
* MISCELLANEOUS NODES
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e6f44f1cf8..c644aba4c1 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -19,7 +19,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -110,7 +110,7 @@ _equalRangeVar(const RangeVar *a, const RangeVar *b)
COMPARE_STRING_FIELD(catalogname);
COMPARE_STRING_FIELD(schemaname);
COMPARE_STRING_FIELD(relname);
- COMPARE_SCALAR_FIELD(inhOpt);
+ COMPARE_SCALAR_FIELD(inh);
COMPARE_SCALAR_FIELD(relpersistence);
COMPARE_NODE_FIELD(alias);
COMPARE_LOCATION_FIELD(location);
@@ -119,6 +119,26 @@ _equalRangeVar(const RangeVar *a, const RangeVar *b)
}
static bool
+_equalTableFunc(const TableFunc *a, const TableFunc *b)
+{
+ COMPARE_NODE_FIELD(ns_names);
+ COMPARE_NODE_FIELD(ns_uris);
+ COMPARE_NODE_FIELD(docexpr);
+ COMPARE_NODE_FIELD(rowexpr);
+ COMPARE_NODE_FIELD(colnames);
+ COMPARE_NODE_FIELD(coltypes);
+ COMPARE_NODE_FIELD(coltypes);
+ COMPARE_NODE_FIELD(colcollations);
+ COMPARE_NODE_FIELD(colexprs);
+ COMPARE_NODE_FIELD(coldefexprs);
+ COMPARE_BITMAPSET_FIELD(notnulls);
+ COMPARE_SCALAR_FIELD(ordinalitycol);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
_equalIntoClause(const IntoClause *a, const IntoClause *b)
{
COMPARE_NODE_FIELD(rel);
@@ -447,6 +467,7 @@ _equalSubPlan(const SubPlan *a, const SubPlan *b)
COMPARE_SCALAR_FIELD(firstColCollation);
COMPARE_SCALAR_FIELD(useHashTable);
COMPARE_SCALAR_FIELD(unknownEqFalse);
+ COMPARE_SCALAR_FIELD(parallel_safe);
COMPARE_NODE_FIELD(setParam);
COMPARE_NODE_FIELD(parParam);
COMPARE_NODE_FIELD(args);
@@ -644,6 +665,17 @@ _equalMinMaxExpr(const MinMaxExpr *a, const MinMaxExpr *b)
}
static bool
+_equalSQLValueFunction(const SQLValueFunction *a, const SQLValueFunction *b)
+{
+ COMPARE_SCALAR_FIELD(op);
+ COMPARE_SCALAR_FIELD(type);
+ COMPARE_SCALAR_FIELD(typmod);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
_equalXmlExpr(const XmlExpr *a, const XmlExpr *b)
{
COMPARE_SCALAR_FIELD(op);
@@ -726,6 +758,15 @@ _equalCurrentOfExpr(const CurrentOfExpr *a, const CurrentOfExpr *b)
}
static bool
+_equalNextValueExpr(const NextValueExpr *a, const NextValueExpr *b)
+{
+ COMPARE_SCALAR_FIELD(seqid);
+ COMPARE_SCALAR_FIELD(typeId);
+
+ return true;
+}
+
+static bool
_equalInferenceElem(const InferenceElem *a, const InferenceElem *b)
{
COMPARE_NODE_FIELD(expr);
@@ -818,6 +859,7 @@ _equalRestrictInfo(const RestrictInfo *a, const RestrictInfo *b)
COMPARE_NODE_FIELD(clause);
COMPARE_SCALAR_FIELD(is_pushed_down);
COMPARE_SCALAR_FIELD(outerjoin_delayed);
+ COMPARE_SCALAR_FIELD(security_level);
COMPARE_BITMAPSET_FIELD(required_relids);
COMPARE_BITMAPSET_FIELD(outer_relids);
COMPARE_BITMAPSET_FIELD(nullable_relids);
@@ -887,6 +929,15 @@ _equalAppendRelInfo(const AppendRelInfo *a, const AppendRelInfo *b)
}
static bool
+_equalPartitionedChildRelInfo(const PartitionedChildRelInfo *a, const PartitionedChildRelInfo *b)
+{
+ COMPARE_SCALAR_FIELD(parent_relid);
+ COMPARE_NODE_FIELD(child_rels);
+
+ return true;
+}
+
+static bool
_equalPlaceHolderInfo(const PlaceHolderInfo *a, const PlaceHolderInfo *b)
{
COMPARE_SCALAR_FIELD(phid);
@@ -934,6 +985,7 @@ _equalQuery(const Query *a, const Query *b)
COMPARE_SCALAR_FIELD(resultRelation);
COMPARE_SCALAR_FIELD(hasAggs);
COMPARE_SCALAR_FIELD(hasWindowFuncs);
+ COMPARE_SCALAR_FIELD(hasTargetSRFs);
COMPARE_SCALAR_FIELD(hasSubLinks);
COMPARE_SCALAR_FIELD(hasDistinctOn);
COMPARE_SCALAR_FIELD(hasRecursive);
@@ -944,6 +996,7 @@ _equalQuery(const Query *a, const Query *b)
COMPARE_NODE_FIELD(rtable);
COMPARE_NODE_FIELD(jointree);
COMPARE_NODE_FIELD(targetList);
+ COMPARE_SCALAR_FIELD(override);
COMPARE_NODE_FIELD(onConflict);
COMPARE_NODE_FIELD(returningList);
COMPARE_NODE_FIELD(groupClause);
@@ -958,6 +1011,18 @@ _equalQuery(const Query *a, const Query *b)
COMPARE_NODE_FIELD(setOperations);
COMPARE_NODE_FIELD(constraintDeps);
COMPARE_NODE_FIELD(withCheckOptions);
+ COMPARE_LOCATION_FIELD(stmt_location);
+ COMPARE_LOCATION_FIELD(stmt_len);
+
+ return true;
+}
+
+static bool
+_equalRawStmt(const RawStmt *a, const RawStmt *b)
+{
+ COMPARE_NODE_FIELD(stmt);
+ COMPARE_LOCATION_FIELD(stmt_location);
+ COMPARE_LOCATION_FIELD(stmt_len);
return true;
}
@@ -971,6 +1036,7 @@ _equalInsertStmt(const InsertStmt *a, const InsertStmt *b)
COMPARE_NODE_FIELD(onConflictClause);
COMPARE_NODE_FIELD(returningList);
COMPARE_NODE_FIELD(withClause);
+ COMPARE_SCALAR_FIELD(override);
return true;
}
@@ -1065,6 +1131,14 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b)
}
static bool
+_equalAlterCollationStmt(const AlterCollationStmt *a, const AlterCollationStmt *b)
+{
+ COMPARE_NODE_FIELD(collname);
+
+ return true;
+}
+
+static bool
_equalAlterDomainStmt(const AlterDomainStmt *a, const AlterDomainStmt *b)
{
COMPARE_SCALAR_FIELD(subtype);
@@ -1093,10 +1167,11 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b)
}
static bool
-_equalFuncWithArgs(const FuncWithArgs *a, const FuncWithArgs *b)
+_equalObjectWithArgs(const ObjectWithArgs *a, const ObjectWithArgs *b)
{
- COMPARE_NODE_FIELD(funcname);
- COMPARE_NODE_FIELD(funcargs);
+ COMPARE_NODE_FIELD(objname);
+ COMPARE_NODE_FIELD(objargs);
+ COMPARE_SCALAR_FIELD(args_unspecified);
return true;
}
@@ -1180,6 +1255,8 @@ _equalCreateStmt(const CreateStmt *a, const CreateStmt *b)
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(tableElts);
COMPARE_NODE_FIELD(inhRelations);
+ COMPARE_NODE_FIELD(partspec);
+ COMPARE_NODE_FIELD(partbound);
COMPARE_NODE_FIELD(ofTypename);
COMPARE_NODE_FIELD(constraints);
COMPARE_NODE_FIELD(options);
@@ -1213,6 +1290,7 @@ _equalDefineStmt(const DefineStmt *a, const DefineStmt *b)
COMPARE_NODE_FIELD(defnames);
COMPARE_NODE_FIELD(args);
COMPARE_NODE_FIELD(definition);
+ COMPARE_SCALAR_FIELD(if_not_exists);
return true;
}
@@ -1221,7 +1299,6 @@ static bool
_equalDropStmt(const DropStmt *a, const DropStmt *b)
{
COMPARE_NODE_FIELD(objects);
- COMPARE_NODE_FIELD(arguments);
COMPARE_SCALAR_FIELD(removeType);
COMPARE_SCALAR_FIELD(behavior);
COMPARE_SCALAR_FIELD(missing_ok);
@@ -1244,8 +1321,7 @@ static bool
_equalCommentStmt(const CommentStmt *a, const CommentStmt *b)
{
COMPARE_SCALAR_FIELD(objtype);
- COMPARE_NODE_FIELD(objname);
- COMPARE_NODE_FIELD(objargs);
+ COMPARE_NODE_FIELD(object);
COMPARE_STRING_FIELD(comment);
return true;
@@ -1255,8 +1331,7 @@ static bool
_equalSecLabelStmt(const SecLabelStmt *a, const SecLabelStmt *b)
{
COMPARE_SCALAR_FIELD(objtype);
- COMPARE_NODE_FIELD(objname);
- COMPARE_NODE_FIELD(objargs);
+ COMPARE_NODE_FIELD(object);
COMPARE_STRING_FIELD(provider);
COMPARE_STRING_FIELD(label);
@@ -1301,6 +1376,18 @@ _equalIndexStmt(const IndexStmt *a, const IndexStmt *b)
}
static bool
+_equalCreateStatsStmt(const CreateStatsStmt *a, const CreateStatsStmt *b)
+{
+ COMPARE_NODE_FIELD(defnames);
+ COMPARE_NODE_FIELD(stat_types);
+ COMPARE_NODE_FIELD(exprs);
+ COMPARE_NODE_FIELD(relations);
+ COMPARE_SCALAR_FIELD(if_not_exists);
+
+ return true;
+}
+
+static bool
_equalCreateFunctionStmt(const CreateFunctionStmt *a, const CreateFunctionStmt *b)
{
COMPARE_SCALAR_FIELD(replace);
@@ -1348,7 +1435,6 @@ _equalRenameStmt(const RenameStmt *a, const RenameStmt *b)
COMPARE_SCALAR_FIELD(relationType);
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(object);
- COMPARE_NODE_FIELD(objarg);
COMPARE_STRING_FIELD(subname);
COMPARE_STRING_FIELD(newname);
COMPARE_SCALAR_FIELD(behavior);
@@ -1362,8 +1448,7 @@ _equalAlterObjectDependsStmt(const AlterObjectDependsStmt *a, const AlterObjectD
{
COMPARE_SCALAR_FIELD(objectType);
COMPARE_NODE_FIELD(relation);
- COMPARE_NODE_FIELD(objname);
- COMPARE_NODE_FIELD(objargs);
+ COMPARE_NODE_FIELD(object);
COMPARE_NODE_FIELD(extname);
return true;
@@ -1375,7 +1460,6 @@ _equalAlterObjectSchemaStmt(const AlterObjectSchemaStmt *a, const AlterObjectSch
COMPARE_SCALAR_FIELD(objectType);
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(object);
- COMPARE_NODE_FIELD(objarg);
COMPARE_STRING_FIELD(newschema);
COMPARE_SCALAR_FIELD(missing_ok);
@@ -1388,7 +1472,6 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b)
COMPARE_SCALAR_FIELD(objectType);
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(object);
- COMPARE_NODE_FIELD(objarg);
COMPARE_NODE_FIELD(newowner);
return true;
@@ -1398,7 +1481,6 @@ static bool
_equalAlterOperatorStmt(const AlterOperatorStmt *a, const AlterOperatorStmt *b)
{
COMPARE_NODE_FIELD(opername);
- COMPARE_NODE_FIELD(operargs);
COMPARE_NODE_FIELD(options);
return true;
@@ -1484,10 +1566,11 @@ static bool
_equalAlterEnumStmt(const AlterEnumStmt *a, const AlterEnumStmt *b)
{
COMPARE_NODE_FIELD(typeName);
+ COMPARE_STRING_FIELD(oldVal);
COMPARE_STRING_FIELD(newVal);
COMPARE_STRING_FIELD(newValNeighbor);
COMPARE_SCALAR_FIELD(newValIsAfter);
- COMPARE_SCALAR_FIELD(skipIfExists);
+ COMPARE_SCALAR_FIELD(skipIfNewValExists);
return true;
}
@@ -1542,7 +1625,6 @@ _equalCreateOpClassItem(const CreateOpClassItem *a, const CreateOpClassItem *b)
{
COMPARE_SCALAR_FIELD(itemtype);
COMPARE_NODE_FIELD(name);
- COMPARE_NODE_FIELD(args);
COMPARE_SCALAR_FIELD(number);
COMPARE_NODE_FIELD(order_family);
COMPARE_NODE_FIELD(class_args);
@@ -1675,6 +1757,7 @@ _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b)
COMPARE_NODE_FIELD(sequence);
COMPARE_NODE_FIELD(options);
COMPARE_SCALAR_FIELD(ownerId);
+ COMPARE_SCALAR_FIELD(for_identity);
COMPARE_SCALAR_FIELD(if_not_exists);
return true;
@@ -1685,6 +1768,7 @@ _equalAlterSeqStmt(const AlterSeqStmt *a, const AlterSeqStmt *b)
{
COMPARE_NODE_FIELD(sequence);
COMPARE_NODE_FIELD(options);
+ COMPARE_SCALAR_FIELD(for_identity);
COMPARE_SCALAR_FIELD(missing_ok);
return true;
@@ -1786,8 +1870,7 @@ _equalAlterExtensionContentsStmt(const AlterExtensionContentsStmt *a, const Alte
COMPARE_STRING_FIELD(extname);
COMPARE_SCALAR_FIELD(action);
COMPARE_SCALAR_FIELD(objtype);
- COMPARE_NODE_FIELD(objname);
- COMPARE_NODE_FIELD(objargs);
+ COMPARE_NODE_FIELD(object);
return true;
}
@@ -1820,6 +1903,7 @@ _equalCreateForeignServerStmt(const CreateForeignServerStmt *a, const CreateFore
COMPARE_STRING_FIELD(version);
COMPARE_STRING_FIELD(fdwname);
COMPARE_NODE_FIELD(options);
+ COMPARE_SCALAR_FIELD(if_not_exists);
return true;
}
@@ -1841,6 +1925,7 @@ _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMapp
COMPARE_NODE_FIELD(user);
COMPARE_STRING_FIELD(servername);
COMPARE_NODE_FIELD(options);
+ COMPARE_SCALAR_FIELD(if_not_exists);
return true;
}
@@ -1925,6 +2010,7 @@ _equalCreateTrigStmt(const CreateTrigStmt *a, const CreateTrigStmt *b)
COMPARE_NODE_FIELD(columns);
COMPARE_NODE_FIELD(whenClause);
COMPARE_SCALAR_FIELD(isconstraint);
+ COMPARE_NODE_FIELD(transitionRels);
COMPARE_SCALAR_FIELD(deferrable);
COMPARE_SCALAR_FIELD(initdeferred);
COMPARE_NODE_FIELD(constrrel);
@@ -2139,11 +2225,73 @@ _equalAlterTSConfigurationStmt(const AlterTSConfigurationStmt *a,
}
static bool
+_equalCreatePublicationStmt(const CreatePublicationStmt *a,
+ const CreatePublicationStmt *b)
+{
+ COMPARE_STRING_FIELD(pubname);
+ COMPARE_NODE_FIELD(options);
+ COMPARE_NODE_FIELD(tables);
+ COMPARE_SCALAR_FIELD(for_all_tables);
+
+ return true;
+}
+
+static bool
+_equalAlterPublicationStmt(const AlterPublicationStmt *a,
+ const AlterPublicationStmt *b)
+{
+ COMPARE_STRING_FIELD(pubname);
+ COMPARE_NODE_FIELD(options);
+ COMPARE_NODE_FIELD(tables);
+ COMPARE_SCALAR_FIELD(for_all_tables);
+ COMPARE_SCALAR_FIELD(tableAction);
+
+ return true;
+}
+
+static bool
+_equalCreateSubscriptionStmt(const CreateSubscriptionStmt *a,
+ const CreateSubscriptionStmt *b)
+{
+ COMPARE_STRING_FIELD(subname);
+ COMPARE_STRING_FIELD(conninfo);
+ COMPARE_NODE_FIELD(publication);
+ COMPARE_NODE_FIELD(options);
+
+ return true;
+}
+
+static bool
+_equalAlterSubscriptionStmt(const AlterSubscriptionStmt *a,
+ const AlterSubscriptionStmt *b)
+{
+ COMPARE_SCALAR_FIELD(kind);
+ COMPARE_STRING_FIELD(subname);
+ COMPARE_STRING_FIELD(conninfo);
+ COMPARE_NODE_FIELD(publication);
+ COMPARE_NODE_FIELD(options);
+
+ return true;
+}
+
+static bool
+_equalDropSubscriptionStmt(const DropSubscriptionStmt *a,
+ const DropSubscriptionStmt *b)
+{
+ COMPARE_STRING_FIELD(subname);
+ COMPARE_SCALAR_FIELD(missing_ok);
+ COMPARE_SCALAR_FIELD(behavior);
+
+ return true;
+}
+
+static bool
_equalCreatePolicyStmt(const CreatePolicyStmt *a, const CreatePolicyStmt *b)
{
COMPARE_STRING_FIELD(policy_name);
COMPARE_NODE_FIELD(table);
COMPARE_STRING_FIELD(cmd_name);
+ COMPARE_SCALAR_FIELD(permissive);
COMPARE_NODE_FIELD(roles);
COMPARE_NODE_FIELD(qual);
COMPARE_NODE_FIELD(with_check);
@@ -2373,6 +2521,36 @@ _equalRangeTableSample(const RangeTableSample *a, const RangeTableSample *b)
}
static bool
+_equalRangeTableFunc(const RangeTableFunc *a, const RangeTableFunc *b)
+{
+ COMPARE_SCALAR_FIELD(lateral);
+ COMPARE_NODE_FIELD(docexpr);
+ COMPARE_NODE_FIELD(rowexpr);
+ COMPARE_NODE_FIELD(namespaces);
+ COMPARE_NODE_FIELD(columns);
+ COMPARE_NODE_FIELD(alias);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
+_equalRangeTableFuncCol(const RangeTableFuncCol *a, const RangeTableFuncCol *b)
+{
+ COMPARE_STRING_FIELD(colname);
+ COMPARE_NODE_FIELD(typeName);
+ COMPARE_SCALAR_FIELD(for_ordinality);
+ COMPARE_NODE_FIELD(typeName);
+ COMPARE_SCALAR_FIELD(is_not_null);
+ COMPARE_NODE_FIELD(colexpr);
+ COMPARE_NODE_FIELD(coldefexpr);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+
+static bool
_equalIndexElem(const IndexElem *a, const IndexElem *b)
{
COMPARE_STRING_FIELD(name);
@@ -2395,9 +2573,11 @@ _equalColumnDef(const ColumnDef *a, const ColumnDef *b)
COMPARE_SCALAR_FIELD(is_local);
COMPARE_SCALAR_FIELD(is_not_null);
COMPARE_SCALAR_FIELD(is_from_type);
+ COMPARE_SCALAR_FIELD(is_from_parent);
COMPARE_SCALAR_FIELD(storage);
COMPARE_NODE_FIELD(raw_default);
COMPARE_NODE_FIELD(cooked_default);
+ COMPARE_SCALAR_FIELD(identity);
COMPARE_NODE_FIELD(collClause);
COMPARE_SCALAR_FIELD(collOid);
COMPARE_NODE_FIELD(constraints);
@@ -2418,6 +2598,7 @@ _equalConstraint(const Constraint *a, const Constraint *b)
COMPARE_SCALAR_FIELD(is_no_inherit);
COMPARE_NODE_FIELD(raw_expr);
COMPARE_STRING_FIELD(cooked_expr);
+ COMPARE_SCALAR_FIELD(generated_when);
COMPARE_NODE_FIELD(keys);
COMPARE_NODE_FIELD(exclusions);
COMPARE_NODE_FIELD(options);
@@ -2446,6 +2627,7 @@ _equalDefElem(const DefElem *a, const DefElem *b)
COMPARE_STRING_FIELD(defname);
COMPARE_NODE_FIELD(arg);
COMPARE_SCALAR_FIELD(defaction);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
@@ -2456,6 +2638,7 @@ _equalLockingClause(const LockingClause *a, const LockingClause *b)
COMPARE_NODE_FIELD(lockedRels);
COMPARE_SCALAR_FIELD(strength);
COMPARE_SCALAR_FIELD(waitPolicy);
+ COMPARE_LOCATION_FIELD(location);
return true;
}
@@ -2472,15 +2655,15 @@ _equalRangeTblEntry(const RangeTblEntry *a, const RangeTblEntry *b)
COMPARE_SCALAR_FIELD(jointype);
COMPARE_NODE_FIELD(joinaliasvars);
COMPARE_NODE_FIELD(functions);
+ COMPARE_NODE_FIELD(tablefunc);
COMPARE_SCALAR_FIELD(funcordinality);
COMPARE_NODE_FIELD(values_lists);
- COMPARE_NODE_FIELD(values_collations);
COMPARE_STRING_FIELD(ctename);
COMPARE_SCALAR_FIELD(ctelevelsup);
COMPARE_SCALAR_FIELD(self_reference);
- COMPARE_NODE_FIELD(ctecoltypes);
- COMPARE_NODE_FIELD(ctecoltypmods);
- COMPARE_NODE_FIELD(ctecolcollations);
+ COMPARE_NODE_FIELD(coltypes);
+ COMPARE_NODE_FIELD(coltypmods);
+ COMPARE_NODE_FIELD(colcollations);
COMPARE_NODE_FIELD(alias);
COMPARE_NODE_FIELD(eref);
COMPARE_SCALAR_FIELD(lateral);
@@ -2682,6 +2865,69 @@ _equalRoleSpec(const RoleSpec *a, const RoleSpec *b)
return true;
}
+static bool
+_equalTriggerTransition(const TriggerTransition *a, const TriggerTransition *b)
+{
+ COMPARE_STRING_FIELD(name);
+ COMPARE_SCALAR_FIELD(isNew);
+ COMPARE_SCALAR_FIELD(isTable);
+
+ return true;
+}
+
+static bool
+_equalPartitionElem(const PartitionElem *a, const PartitionElem *b)
+{
+ COMPARE_STRING_FIELD(name);
+ COMPARE_NODE_FIELD(expr);
+ COMPARE_NODE_FIELD(collation);
+ COMPARE_NODE_FIELD(opclass);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
+_equalPartitionSpec(const PartitionSpec *a, const PartitionSpec *b)
+{
+ COMPARE_STRING_FIELD(strategy);
+ COMPARE_NODE_FIELD(partParams);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
+_equalPartitionBoundSpec(const PartitionBoundSpec *a, const PartitionBoundSpec *b)
+{
+ COMPARE_SCALAR_FIELD(strategy);
+ COMPARE_NODE_FIELD(listdatums);
+ COMPARE_NODE_FIELD(lowerdatums);
+ COMPARE_NODE_FIELD(upperdatums);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
+_equalPartitionRangeDatum(const PartitionRangeDatum *a, const PartitionRangeDatum *b)
+{
+ COMPARE_SCALAR_FIELD(infinite);
+ COMPARE_NODE_FIELD(value);
+ COMPARE_LOCATION_FIELD(location);
+
+ return true;
+}
+
+static bool
+_equalPartitionCmd(const PartitionCmd *a, const PartitionCmd *b)
+{
+ COMPARE_NODE_FIELD(name);
+ COMPARE_NODE_FIELD(bound);
+
+ return true;
+}
+
/*
* Stuff from pg_list.h
*/
@@ -2891,6 +3137,9 @@ equal(const void *a, const void *b)
case T_RangeVar:
retval = _equalRangeVar(a, b);
break;
+ case T_TableFunc:
+ retval = _equalTableFunc(a, b);
+ break;
case T_IntoClause:
retval = _equalIntoClause(a, b);
break;
@@ -2990,6 +3239,9 @@ equal(const void *a, const void *b)
case T_MinMaxExpr:
retval = _equalMinMaxExpr(a, b);
break;
+ case T_SQLValueFunction:
+ retval = _equalSQLValueFunction(a, b);
+ break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;
@@ -3011,6 +3263,9 @@ equal(const void *a, const void *b)
case T_CurrentOfExpr:
retval = _equalCurrentOfExpr(a, b);
break;
+ case T_NextValueExpr:
+ retval = _equalNextValueExpr(a, b);
+ break;
case T_InferenceElem:
retval = _equalInferenceElem(a, b);
break;
@@ -3048,6 +3303,9 @@ equal(const void *a, const void *b)
case T_AppendRelInfo:
retval = _equalAppendRelInfo(a, b);
break;
+ case T_PartitionedChildRelInfo:
+ retval = _equalPartitionedChildRelInfo(a, b);
+ break;
case T_PlaceHolderInfo:
retval = _equalPlaceHolderInfo(a, b);
break;
@@ -3079,6 +3337,9 @@ equal(const void *a, const void *b)
case T_Query:
retval = _equalQuery(a, b);
break;
+ case T_RawStmt:
+ retval = _equalRawStmt(a, b);
+ break;
case T_InsertStmt:
retval = _equalInsertStmt(a, b);
break;
@@ -3100,6 +3361,9 @@ equal(const void *a, const void *b)
case T_AlterTableCmd:
retval = _equalAlterTableCmd(a, b);
break;
+ case T_AlterCollationStmt:
+ retval = _equalAlterCollationStmt(a, b);
+ break;
case T_AlterDomainStmt:
retval = _equalAlterDomainStmt(a, b);
break;
@@ -3151,6 +3415,9 @@ equal(const void *a, const void *b)
case T_IndexStmt:
retval = _equalIndexStmt(a, b);
break;
+ case T_CreateStatsStmt:
+ retval = _equalCreateStatsStmt(a, b);
+ break;
case T_CreateFunctionStmt:
retval = _equalCreateFunctionStmt(a, b);
break;
@@ -3423,6 +3690,21 @@ equal(const void *a, const void *b)
case T_AlterPolicyStmt:
retval = _equalAlterPolicyStmt(a, b);
break;
+ case T_CreatePublicationStmt:
+ retval = _equalCreatePublicationStmt(a, b);
+ break;
+ case T_AlterPublicationStmt:
+ retval = _equalAlterPublicationStmt(a, b);
+ break;
+ case T_CreateSubscriptionStmt:
+ retval = _equalCreateSubscriptionStmt(a, b);
+ break;
+ case T_AlterSubscriptionStmt:
+ retval = _equalAlterSubscriptionStmt(a, b);
+ break;
+ case T_DropSubscriptionStmt:
+ retval = _equalDropSubscriptionStmt(a, b);
+ break;
case T_A_Expr:
retval = _equalAExpr(a, b);
break;
@@ -3477,6 +3759,12 @@ equal(const void *a, const void *b)
case T_RangeTableSample:
retval = _equalRangeTableSample(a, b);
break;
+ case T_RangeTableFunc:
+ retval = _equalRangeTableFunc(a, b);
+ break;
+ case T_RangeTableFuncCol:
+ retval = _equalRangeTableFuncCol(a, b);
+ break;
case T_TypeName:
retval = _equalTypeName(a, b);
break;
@@ -3531,8 +3819,8 @@ equal(const void *a, const void *b)
case T_CommonTableExpr:
retval = _equalCommonTableExpr(a, b);
break;
- case T_FuncWithArgs:
- retval = _equalFuncWithArgs(a, b);
+ case T_ObjectWithArgs:
+ retval = _equalObjectWithArgs(a, b);
break;
case T_AccessPriv:
retval = _equalAccessPriv(a, b);
@@ -3548,6 +3836,24 @@ equal(const void *a, const void *b)
case T_RoleSpec:
retval = _equalRoleSpec(a, b);
break;
+ case T_TriggerTransition:
+ retval = _equalTriggerTransition(a, b);
+ break;
+ case T_PartitionElem:
+ retval = _equalPartitionElem(a, b);
+ break;
+ case T_PartitionSpec:
+ retval = _equalPartitionSpec(a, b);
+ break;
+ case T_PartitionBoundSpec:
+ retval = _equalPartitionBoundSpec(a, b);
+ break;
+ case T_PartitionRangeDatum:
+ retval = _equalPartitionRangeDatum(a, b);
+ break;
+ case T_PartitionCmd:
+ retval = _equalPartitionCmd(a, b);
+ break;
default:
elog(ERROR, "unrecognized node type: %d",
diff --git a/src/backend/nodes/extensible.c b/src/backend/nodes/extensible.c
index a4f1c99016..01cd3c84fb 100644
--- a/src/backend/nodes/extensible.c
+++ b/src/backend/nodes/extensible.c
@@ -10,7 +10,7 @@
* and GetExtensibleNodeMethods to get information about a previously
* registered type of extensible node.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
index 085b68cd1f..f09aa248d8 100644
--- a/src/backend/nodes/list.c
+++ b/src/backend/nodes/list.c
@@ -4,7 +4,7 @@
* implementation for PostgreSQL generic linked list package
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index b564d403a5..f138afd706 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -4,7 +4,7 @@
* creator functions for primitive nodes. The functions here are for
* the most frequently created nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -216,10 +216,10 @@ makeWholeRowVar(RangeTblEntry *rte,
default:
/*
- * RTE is a join, subselect, or VALUES. We represent this as a
- * whole-row Var of RECORD type. (Note that in most cases the Var
- * will be expanded to a RowExpr during planning, but that is not
- * our concern here.)
+ * RTE is a join, subselect, tablefunc, or VALUES. We represent
+ * this as a whole-row Var of RECORD type. (Note that in most
+ * cases the Var will be expanded to a RowExpr during planning,
+ * but that is not our concern here.)
*/
result = makeVar(varno,
InvalidAttrNumber,
@@ -429,7 +429,7 @@ makeRangeVar(char *schemaname, char *relname, int location)
r->catalogname = NULL;
r->schemaname = schemaname;
r->relname = relname;
- r->inhOpt = INH_DEFAULT;
+ r->inh = true;
r->relpersistence = RELPERSISTENCE_PERMANENT;
r->alias = NULL;
r->location = location;
@@ -500,6 +500,7 @@ makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
n->is_local = true;
n->is_not_null = false;
n->is_from_type = false;
+ n->is_from_parent = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
@@ -546,7 +547,7 @@ makeFuncExpr(Oid funcid, Oid rettype, List *args,
* and no special action.
*/
DefElem *
-makeDefElem(char *name, Node *arg)
+makeDefElem(char *name, Node *arg, int location)
{
DefElem *res = makeNode(DefElem);
@@ -554,6 +555,7 @@ makeDefElem(char *name, Node *arg)
res->defname = name;
res->arg = arg;
res->defaction = DEFELEM_UNSPEC;
+ res->location = location;
return res;
}
@@ -564,7 +566,7 @@ makeDefElem(char *name, Node *arg)
*/
DefElem *
makeDefElemExtended(char *nameSpace, char *name, Node *arg,
- DefElemAction defaction)
+ DefElemAction defaction, int location)
{
DefElem *res = makeNode(DefElem);
@@ -572,6 +574,7 @@ makeDefElemExtended(char *nameSpace, char *name, Node *arg,
res->defname = name;
res->arg = arg;
res->defaction = defaction;
+ res->location = location;
return res;
}
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index d05332c10a..eb3e1ce1c1 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -3,7 +3,7 @@
* nodeFuncs.c
* Various general-purpose manipulations of Node trees
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -111,8 +111,7 @@ exprType(const Node *expr)
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot get type for untransformed sublink");
- tent = (TargetEntry *) linitial(qtree->targetList);
- Assert(IsA(tent, TargetEntry));
+ tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
type = exprType((Node *) tent->expr);
if (sublink->subLinkType == ARRAY_SUBLINK)
@@ -218,6 +217,9 @@ exprType(const Node *expr)
case T_MinMaxExpr:
type = ((const MinMaxExpr *) expr)->minmaxtype;
break;
+ case T_SQLValueFunction:
+ type = ((const SQLValueFunction *) expr)->type;
+ break;
case T_XmlExpr:
if (((const XmlExpr *) expr)->op == IS_DOCUMENT)
type = BOOLOID;
@@ -244,6 +246,9 @@ exprType(const Node *expr)
case T_CurrentOfExpr:
type = BOOLOID;
break;
+ case T_NextValueExpr:
+ type = ((const NextValueExpr *) expr)->typeId;
+ break;
case T_InferenceElem:
{
const InferenceElem *n = (const InferenceElem *) expr;
@@ -319,8 +324,7 @@ exprTypmod(const Node *expr)
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot get type for untransformed sublink");
- tent = (TargetEntry *) linitial(qtree->targetList);
- Assert(IsA(tent, TargetEntry));
+ tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
return exprTypmod((Node *) tent->expr);
/* note we don't need to care if it's an array */
@@ -378,9 +382,8 @@ exprTypmod(const Node *expr)
return -1; /* no point in trying harder */
foreach(arg, cexpr->args)
{
- CaseWhen *w = (CaseWhen *) lfirst(arg);
+ CaseWhen *w = lfirst_node(CaseWhen, arg);
- Assert(IsA(w, CaseWhen));
if (exprType((Node *) w->result) != casetype)
return -1;
if (exprTypmod((Node *) w->result) != typmod)
@@ -479,6 +482,8 @@ exprTypmod(const Node *expr)
return typmod;
}
break;
+ case T_SQLValueFunction:
+ return ((const SQLValueFunction *) expr)->typmod;
case T_CoerceToDomain:
return ((const CoerceToDomain *) expr)->resulttypmod;
case T_CoerceToDomainValue:
@@ -718,6 +723,8 @@ expression_returns_set_walker(Node *node, void *context)
return false;
if (IsA(node, MinMaxExpr))
return false;
+ if (IsA(node, SQLValueFunction))
+ return false;
if (IsA(node, XmlExpr))
return false;
@@ -802,8 +809,7 @@ exprCollation(const Node *expr)
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot get collation for untransformed sublink");
- tent = (TargetEntry *) linitial(qtree->targetList);
- Assert(IsA(tent, TargetEntry));
+ tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
coll = exprCollation((Node *) tent->expr);
/* collation doesn't change if it's converted to array */
@@ -883,6 +889,9 @@ exprCollation(const Node *expr)
case T_MinMaxExpr:
coll = ((const MinMaxExpr *) expr)->minmaxcollid;
break;
+ case T_SQLValueFunction:
+ coll = InvalidOid; /* all cases return non-collatable types */
+ break;
case T_XmlExpr:
/*
@@ -913,6 +922,9 @@ exprCollation(const Node *expr)
case T_CurrentOfExpr:
coll = InvalidOid; /* result is always boolean */
break;
+ case T_NextValueExpr:
+ coll = InvalidOid; /* result is always an integer type */
+ break;
case T_InferenceElem:
coll = exprCollation((Node *) ((const InferenceElem *) expr)->expr);
break;
@@ -1042,8 +1054,7 @@ exprSetCollation(Node *expr, Oid collation)
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot set collation for untransformed sublink");
- tent = (TargetEntry *) linitial(qtree->targetList);
- Assert(IsA(tent, TargetEntry));
+ tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
Assert(collation == exprCollation((Node *) tent->expr));
}
@@ -1091,6 +1102,9 @@ exprSetCollation(Node *expr, Oid collation)
case T_MinMaxExpr:
((MinMaxExpr *) expr)->minmaxcollid = collation;
break;
+ case T_SQLValueFunction:
+ Assert(!OidIsValid(collation)); /* no collatable results */
+ break;
case T_XmlExpr:
Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ?
(collation == DEFAULT_COLLATION_OID) :
@@ -1114,6 +1128,10 @@ exprSetCollation(Node *expr, Oid collation)
case T_CurrentOfExpr:
Assert(!OidIsValid(collation)); /* result is always boolean */
break;
+ case T_NextValueExpr:
+ Assert(!OidIsValid(collation)); /* result is always an integer
+ * type */
+ break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
break;
@@ -1204,6 +1222,9 @@ exprLocation(const Node *expr)
case T_RangeVar:
loc = ((const RangeVar *) expr)->location;
break;
+ case T_TableFunc:
+ loc = ((const TableFunc *) expr)->location;
+ break;
case T_Var:
loc = ((const Var *) expr)->location;
break;
@@ -1364,6 +1385,10 @@ exprLocation(const Node *expr)
/* GREATEST/LEAST keyword should always be the first thing */
loc = ((const MinMaxExpr *) expr)->location;
break;
+ case T_SQLValueFunction:
+ /* function keyword should always be the first thing */
+ loc = ((const SQLValueFunction *) expr)->location;
+ break;
case T_XmlExpr:
{
const XmlExpr *xexpr = (const XmlExpr *) expr;
@@ -1535,6 +1560,18 @@ exprLocation(const Node *expr)
/* just use nested expr's location */
loc = exprLocation((Node *) ((const InferenceElem *) expr)->expr);
break;
+ case T_PartitionElem:
+ loc = ((const PartitionElem *) expr)->location;
+ break;
+ case T_PartitionSpec:
+ loc = ((const PartitionSpec *) expr)->location;
+ break;
+ case T_PartitionBoundSpec:
+ loc = ((const PartitionBoundSpec *) expr)->location;
+ break;
+ case T_PartitionRangeDatum:
+ loc = ((const PartitionRangeDatum *) expr)->location;
+ break;
default:
/* for any other node type it's just unknown... */
loc = -1;
@@ -1633,9 +1670,10 @@ set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
* for themselves, in case additional checks should be made, or because they
* have special rules about which parts of the tree need to be visited.
*
- * Note: we ignore MinMaxExpr, XmlExpr, and CoerceToDomain nodes, because they
- * do not contain SQL function OIDs. However, they can invoke SQL-visible
- * functions, so callers should take thought about how to treat them.
+ * Note: we ignore MinMaxExpr, SQLValueFunction, XmlExpr, and CoerceToDomain
+ * nodes, because they do not contain SQL function OIDs. However, they can
+ * invoke SQL-visible functions, so callers should take thought about how to
+ * treat them.
*/
bool
check_functions_in_node(Node *node, check_function_callback checker,
@@ -1859,6 +1897,8 @@ expression_tree_walker(Node *node,
case T_CaseTestExpr:
case T_SetToDefault:
case T_CurrentOfExpr:
+ case T_NextValueExpr:
+ case T_SQLValueFunction:
case T_RangeTblRef:
case T_SortGroupClause:
/* primitive node types with no expression subnodes */
@@ -2025,9 +2065,8 @@ expression_tree_walker(Node *node,
/* we assume walker doesn't care about CaseWhens, either */
foreach(temp, caseexpr->args)
{
- CaseWhen *when = (CaseWhen *) lfirst(temp);
+ CaseWhen *when = lfirst_node(CaseWhen, temp);
- Assert(IsA(when, CaseWhen));
if (walker(when->expr, context))
return true;
if (walker(when->result, context))
@@ -2192,6 +2231,22 @@ expression_tree_walker(Node *node,
return true;
}
break;
+ case T_TableFunc:
+ {
+ TableFunc *tf = (TableFunc *) node;
+
+ if (walker(tf->ns_uris, context))
+ return true;
+ if (walker(tf->docexpr, context))
+ return true;
+ if (walker(tf->rowexpr, context))
+ return true;
+ if (walker(tf->colexprs, context))
+ return true;
+ if (walker(tf->coldefexprs, context))
+ return true;
+ }
+ break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));
@@ -2283,6 +2338,7 @@ range_table_walker(List *rtable,
return true;
break;
case RTE_CTE:
+ case RTE_NAMEDTUPLESTORE:
/* nothing to do */
break;
case RTE_SUBQUERY:
@@ -2299,6 +2355,10 @@ range_table_walker(List *rtable,
if (walker(rte->functions, context))
return true;
break;
+ case RTE_TABLEFUNC:
+ if (walker(rte->tablefunc, context))
+ return true;
+ break;
case RTE_VALUES:
if (walker(rte->values_lists, context))
return true;
@@ -2438,6 +2498,8 @@ expression_tree_mutator(Node *node,
case T_CaseTestExpr:
case T_SetToDefault:
case T_CurrentOfExpr:
+ case T_NextValueExpr:
+ case T_SQLValueFunction:
case T_RangeTblRef:
case T_SortGroupClause:
return (Node *) copyObject(node);
@@ -2992,6 +3054,20 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
+ case T_TableFunc:
+ {
+ TableFunc *tf = (TableFunc *) node;
+ TableFunc *newnode;
+
+ FLATCOPY(newnode, tf, TableFunc);
+ MUTATE(newnode->ns_uris, tf->ns_uris, List *);
+ MUTATE(newnode->docexpr, tf->docexpr, Node *);
+ MUTATE(newnode->rowexpr, tf->rowexpr, Node *);
+ MUTATE(newnode->colexprs, tf->colexprs, List *);
+ MUTATE(newnode->coldefexprs, tf->coldefexprs, List *);
+ return (Node *) newnode;
+ }
+ break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));
@@ -3086,6 +3162,7 @@ range_table_mutator(List *rtable,
#ifdef PGXC
case RTE_REMOTE_DUMMY:
#endif /* PGXC */
+ case RTE_NAMEDTUPLESTORE:
/* nothing to do */
break;
case RTE_SUBQUERY:
@@ -3112,6 +3189,9 @@ range_table_mutator(List *rtable,
case RTE_FUNCTION:
MUTATE(newrte->functions, rte->functions, List *);
break;
+ case RTE_TABLEFUNC:
+ MUTATE(newrte->tablefunc, rte->tablefunc, TableFunc *);
+ break;
case RTE_VALUES:
MUTATE(newrte->values_lists, rte->values_lists, List *);
break;
@@ -3205,6 +3285,7 @@ raw_expression_tree_walker(Node *node,
{
case T_SetToDefault:
case T_CurrentOfExpr:
+ case T_SQLValueFunction:
case T_Integer:
case T_Float:
case T_String:
@@ -3242,9 +3323,8 @@ raw_expression_tree_walker(Node *node,
/* we assume walker doesn't care about CaseWhens, either */
foreach(temp, caseexpr->args)
{
- CaseWhen *when = (CaseWhen *) lfirst(temp);
+ CaseWhen *when = lfirst_node(CaseWhen, temp);
- Assert(IsA(when, CaseWhen));
if (walker(when->expr, context))
return true;
if (walker(when->result, context))
@@ -3536,6 +3616,32 @@ raw_expression_tree_walker(Node *node,
return true;
}
break;
+ case T_RangeTableFunc:
+ {
+ RangeTableFunc *rtf = (RangeTableFunc *) node;
+
+ if (walker(rtf->docexpr, context))
+ return true;
+ if (walker(rtf->rowexpr, context))
+ return true;
+ if (walker(rtf->namespaces, context))
+ return true;
+ if (walker(rtf->columns, context))
+ return true;
+ if (walker(rtf->alias, context))
+ return true;
+ }
+ break;
+ case T_RangeTableFuncCol:
+ {
+ RangeTableFuncCol *rtfc = (RangeTableFuncCol *) node;
+
+ if (walker(rtfc->colexpr, context))
+ return true;
+ if (walker(rtfc->coldefexpr, context))
+ return true;
+ }
+ break;
case T_TypeName:
{
TypeName *tn = (TypeName *) node;
@@ -3716,9 +3822,8 @@ planstate_walk_subplans(List *plans,
foreach(lc, plans)
{
- SubPlanState *sps = (SubPlanState *) lfirst(lc);
+ SubPlanState *sps = lfirst_node(SubPlanState, lc);
- Assert(IsA(sps, SubPlanState));
if (walker(sps->planstate, context))
return true;
}
diff --git a/src/backend/nodes/nodes.c b/src/backend/nodes/nodes.c
index aea3880858..d3345aae6d 100644
--- a/src/backend/nodes/nodes.c
+++ b/src/backend/nodes/nodes.c
@@ -4,7 +4,7 @@
* support code for nodes (now that we have removed the home-brew
* inheritance system, our support code for nodes is much simpler)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 522387a3f8..d5165ddd4e 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -4,7 +4,7 @@
* Output functions for Postgres tree nodes.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -118,7 +118,7 @@ set_portable_output(bool value)
/* Write a character-string (possibly NULL) field */
#define WRITE_STRING_FIELD(fldname) \
(appendStringInfo(str, " :" CppAsString(fldname) " "), \
- _outToken(str, node->fldname))
+ outToken(str, node->fldname))
/* Write a parse location field (actually same as INT case) */
#define WRITE_LOCATION_FIELD(fldname) \
@@ -134,7 +134,7 @@ set_portable_output(bool value)
/* Write a bitmapset field */
#define WRITE_BITMAPSET_FIELD(fldname) \
(appendStringInfo(str, " :" CppAsString(fldname) " "), \
- _outBitmapset(str, node->fldname))
+ outBitmapset(str, node->fldname))
#ifdef XCP
#define NSP_NAME(oid) \
@@ -146,9 +146,9 @@ set_portable_output(bool value)
*/
#define WRITE_RELID_INTERNAL(relid) \
- (_outToken(str, OidIsValid((relid)) ? NSP_NAME(get_rel_namespace((relid))) : NULL), \
+ (outToken(str, OidIsValid((relid)) ? NSP_NAME(get_rel_namespace((relid))) : NULL), \
appendStringInfoChar(str, ' '), \
- _outToken(str, OidIsValid((relid)) ? get_rel_name((relid)) : NULL))
+ outToken(str, OidIsValid((relid)) ? get_rel_name((relid)) : NULL))
/* write an OID which is a relation OID */
#define WRITE_RELID_FIELD(fldname) \
@@ -179,9 +179,9 @@ set_portable_output(bool value)
/* write an OID which is a data type OID */
#define WRITE_TYPID_FIELD(fldname) \
(appendStringInfo(str, " :" CppAsString(fldname) " "), \
- _outToken(str, OidIsValid(node->fldname) ? NSP_NAME(get_typ_namespace(node->fldname)) : NULL), \
+ outToken(str, OidIsValid(node->fldname) ? NSP_NAME(get_typ_namespace(node->fldname)) : NULL), \
appendStringInfoChar(str, ' '), \
- _outToken(str, OidIsValid(node->fldname) ? get_typ_name(node->fldname) : NULL))
+ outToken(str, OidIsValid(node->fldname) ? get_typ_name(node->fldname) : NULL))
/* write an OID which is a function OID */
#define WRITE_FUNCID_FIELD(fldname) \
@@ -191,18 +191,18 @@ set_portable_output(bool value)
{ \
Oid *argtypes; \
int i, nargs; \
- _outToken(str, NSP_NAME(get_func_namespace(node->fldname))); \
+ outToken(str, NSP_NAME(get_func_namespace(node->fldname))); \
appendStringInfoChar(str, ' '); \
- _outToken(str, get_func_name(node->fldname)); \
+ outToken(str, get_func_name(node->fldname)); \
appendStringInfoChar(str, ' '); \
get_func_signature(node->fldname, &argtypes, &nargs); \
appendStringInfo(str, "%d", nargs); \
for (i = 0; i < nargs; i++) \
{ \
appendStringInfoChar(str, ' '); \
- _outToken(str, NSP_NAME(get_typ_namespace(argtypes[i]))); \
+ outToken(str, NSP_NAME(get_typ_namespace(argtypes[i]))); \
appendStringInfoChar(str, ' '); \
- _outToken(str, get_typ_name(argtypes[i])); \
+ outToken(str, get_typ_name(argtypes[i])); \
} \
} \
else \
@@ -216,20 +216,20 @@ set_portable_output(bool value)
if (OidIsValid(node->fldname)) \
{ \
Oid oprleft, oprright; \
- _outToken(str, NSP_NAME(get_opnamespace(node->fldname))); \
+ outToken(str, NSP_NAME(get_opnamespace(node->fldname))); \
appendStringInfoChar(str, ' '); \
- _outToken(str, get_opname(node->fldname)); \
+ outToken(str, get_opname(node->fldname)); \
appendStringInfoChar(str, ' '); \
op_input_types(node->fldname, &oprleft, &oprright); \
- _outToken(str, OidIsValid(oprleft) ? \
+ outToken(str, OidIsValid(oprleft) ? \
NSP_NAME(get_typ_namespace(oprleft)) : NULL); \
appendStringInfoChar(str, ' '); \
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); \
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); \
appendStringInfoChar(str, ' '); \
- _outToken(str, OidIsValid(oprright) ? \
+ outToken(str, OidIsValid(oprright) ? \
NSP_NAME(get_typ_namespace(oprright)) : NULL); \
appendStringInfoChar(str, ' '); \
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); \
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); \
appendStringInfoChar(str, ' '); \
} \
else \
@@ -242,9 +242,9 @@ set_portable_output(bool value)
appendStringInfo(str, " :" CppAsString(fldname) " "); \
if (OidIsValid(node->fldname)) \
{ \
- _outToken(str, NSP_NAME(get_collation_namespace(node->fldname))); \
+ outToken(str, NSP_NAME(get_collation_namespace(node->fldname))); \
appendStringInfoChar(str, ' '); \
- _outToken(str, get_collation_name(node->fldname)); \
+ outToken(str, get_collation_name(node->fldname)); \
appendStringInfo(str, " %d", get_collation_encoding(node->fldname)); \
} \
else \
@@ -258,14 +258,14 @@ set_portable_output(bool value)
/*
- * _outToken
+ * outToken
* Convert an ordinary string (eg, an identifier) into a form that
* will be decoded back to a plain token by read.c's functions.
*
* If a null or empty string is given, it is encoded as "<>".
*/
-static void
-_outToken(StringInfo str, const char *s)
+void
+outToken(StringInfo str, const char *s)
{
if (s == NULL || *s == '\0')
{
@@ -296,13 +296,6 @@ _outToken(StringInfo str, const char *s)
}
}
-/* for use by extensions which define extensible nodes */
-void
-outToken(StringInfo str, const char *s)
-{
- _outToken(str, s);
-}
-
static void
_outList(StringInfo str, const List *node)
{
@@ -341,13 +334,13 @@ _outList(StringInfo str, const List *node)
}
/*
- * _outBitmapset -
+ * outBitmapset -
* converts a bitmap set of integers
*
* Note: the output format is "(b int int ...)", similar to an integer List.
*/
-static void
-_outBitmapset(StringInfo str, const Bitmapset *bms)
+void
+outBitmapset(StringInfo str, const Bitmapset *bms)
{
int x;
@@ -359,13 +352,6 @@ _outBitmapset(StringInfo str, const Bitmapset *bms)
appendStringInfoChar(str, ')');
}
-/* for use by extensions which define extensible nodes */
-void
-outBitmapset(StringInfo str, const Bitmapset *bms)
-{
- _outBitmapset(str, bms);
-}
-
/*
* Print the value of a Datum given its type.
*/
@@ -437,7 +423,7 @@ _printDatum(StringInfo str, Datum value, Oid typid)
DateStyle = USE_ISO_DATES;
textvalue = DatumGetCString(FunctionCall1(&finfo, tmpval));
- _outToken(str, textvalue);
+ outToken(str, textvalue);
DateStyle = saveDateStyle;
}
@@ -464,13 +450,17 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node)
WRITE_NODE_FIELD(planTree);
WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(resultRelations);
- WRITE_NODE_FIELD(utilityStmt);
+ WRITE_NODE_FIELD(nonleafResultRelations);
+ WRITE_NODE_FIELD(rootResultRelations);
WRITE_NODE_FIELD(subplans);
WRITE_BITMAPSET_FIELD(rewindPlanIDs);
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(relationOids);
WRITE_NODE_FIELD(invalItems);
WRITE_INT_FIELD(nParamExec);
+ WRITE_NODE_FIELD(utilityStmt);
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_LOCATION_FIELD(stmt_len);
}
/*
@@ -484,6 +474,7 @@ _outPlanInfo(StringInfo str, const Plan *node)
WRITE_FLOAT_FIELD(plan_rows, "%.0f");
WRITE_INT_FIELD(plan_width);
WRITE_BOOL_FIELD(parallel_aware);
+ WRITE_BOOL_FIELD(parallel_safe);
WRITE_INT_FIELD(plan_node_id);
WRITE_NODE_FIELD(targetlist);
WRITE_NODE_FIELD(qual);
@@ -514,6 +505,7 @@ _outJoinPlanInfo(StringInfo str, const Join *node)
_outPlanInfo(str, (const Plan *) node);
WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(inner_unique);
WRITE_NODE_FIELD(joinqual);
}
@@ -537,6 +529,14 @@ _outResult(StringInfo str, const Result *node)
}
static void
+_outProjectSet(StringInfo str, const ProjectSet *node)
+{
+ WRITE_NODE_TYPE("PROJECTSET");
+
+ _outPlanInfo(str, (const Plan *) node);
+}
+
+static void
_outModifyTable(StringInfo str, const ModifyTable *node)
{
WRITE_NODE_TYPE("MODIFYTABLE");
@@ -546,8 +546,10 @@ _outModifyTable(StringInfo str, const ModifyTable *node)
WRITE_ENUM_FIELD(operation, CmdType);
WRITE_BOOL_FIELD(canSetTag);
WRITE_UINT_FIELD(nominalRelation);
+ WRITE_NODE_FIELD(partitioned_rels);
WRITE_NODE_FIELD(resultRelations);
WRITE_INT_FIELD(resultRelIndex);
+ WRITE_INT_FIELD(rootResultRelIndex);
WRITE_NODE_FIELD(plans);
WRITE_NODE_FIELD(withCheckOptionLists);
WRITE_NODE_FIELD(returningLists);
@@ -579,6 +581,7 @@ _outAppend(StringInfo str, const Append *node)
_outPlanInfo(str, (const Plan *) node);
+ WRITE_NODE_FIELD(partitioned_rels);
WRITE_NODE_FIELD(appendplans);
}
@@ -591,6 +594,7 @@ _outMergeAppend(StringInfo str, const MergeAppend *node)
_outPlanInfo(str, (const Plan *) node);
+ WRITE_NODE_FIELD(partitioned_rels);
WRITE_NODE_FIELD(mergeplans);
WRITE_INT_FIELD(numCols);
@@ -609,20 +613,20 @@ _outMergeAppend(StringInfo str, const MergeAppend *node)
/* Sort operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
}
else
#endif
@@ -637,9 +641,9 @@ _outMergeAppend(StringInfo str, const MergeAppend *node)
if (OidIsValid(coll))
{
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_collation_namespace(coll)));
+ outToken(str, NSP_NAME(get_collation_namespace(coll)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_collation_name(coll));
+ outToken(str, get_collation_name(coll));
appendStringInfo(str, " %d", get_collation_encoding(coll));
}
else
@@ -680,20 +684,20 @@ _outRecursiveUnion(StringInfo str, const RecursiveUnion *node)
/* Unique operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
appendStringInfoChar(str, ' ');
}
else
@@ -720,6 +724,7 @@ _outBitmapOr(StringInfo str, const BitmapOr *node)
_outPlanInfo(str, (const Plan *) node);
+ WRITE_BOOL_FIELD(isshared);
WRITE_NODE_FIELD(bitmapplans);
}
@@ -736,6 +741,35 @@ _outGather(StringInfo str, const Gather *node)
}
static void
+_outGatherMerge(StringInfo str, const GatherMerge *node)
+{
+ int i;
+
+ WRITE_NODE_TYPE("GATHERMERGE");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(num_workers);
+ WRITE_INT_FIELD(numCols);
+
+ appendStringInfoString(str, " :sortColIdx");
+ for (i = 0; i < node->numCols; i++)
+ appendStringInfo(str, " %d", node->sortColIdx[i]);
+
+ appendStringInfoString(str, " :sortOperators");
+ for (i = 0; i < node->numCols; i++)
+ appendStringInfo(str, " %u", node->sortOperators[i]);
+
+ appendStringInfoString(str, " :collations");
+ for (i = 0; i < node->numCols; i++)
+ appendStringInfo(str, " %u", node->collations[i]);
+
+ appendStringInfoString(str, " :nullsFirst");
+ for (i = 0; i < node->numCols; i++)
+ appendStringInfo(str, " %s", booltostr(node->nullsFirst[i]));
+}
+
+static void
_outScan(StringInfo str, const Scan *node)
{
WRITE_NODE_TYPE("SCAN");
@@ -857,6 +891,7 @@ _outBitmapIndexScan(StringInfo str, const BitmapIndexScan *node)
else
#endif
WRITE_OID_FIELD(indexid);
+ WRITE_BOOL_FIELD(isshared);
WRITE_NODE_FIELD(indexqual);
WRITE_NODE_FIELD(indexqualorig);
}
@@ -903,6 +938,16 @@ _outFunctionScan(StringInfo str, const FunctionScan *node)
}
static void
+_outTableFuncScan(StringInfo str, const TableFuncScan *node)
+{
+ WRITE_NODE_TYPE("TABLEFUNCSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(tablefunc);
+}
+
+static void
_outValuesScan(StringInfo str, const ValuesScan *node)
{
WRITE_NODE_TYPE("VALUESSCAN");
@@ -924,6 +969,16 @@ _outCteScan(StringInfo str, const CteScan *node)
}
static void
+_outNamedTuplestoreScan(StringInfo str, const NamedTuplestoreScan *node)
+{
+ WRITE_NODE_TYPE("NAMEDTUPLESTORESCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_STRING_FIELD(enrname);
+}
+
+static void
_outWorkTableScan(StringInfo str, const WorkTableScan *node)
{
WRITE_NODE_TYPE("WORKTABLESCAN");
@@ -965,7 +1020,7 @@ _outCustomScan(StringInfo str, const CustomScan *node)
WRITE_BITMAPSET_FIELD(custom_relids);
/* CustomName is a key to lookup CustomScanMethods */
appendStringInfoString(str, " :methods ");
- _outToken(str, node->methods->CustomName);
+ outToken(str, node->methods->CustomName);
}
static void
@@ -996,6 +1051,7 @@ _outMergeJoin(StringInfo str, const MergeJoin *node)
_outJoinPlanInfo(str, (const Join *) node);
+ WRITE_BOOL_FIELD(skip_mark_restore);
WRITE_NODE_FIELD(mergeclauses);
numCols = list_length(node->mergeclauses);
@@ -1013,9 +1069,9 @@ _outMergeJoin(StringInfo str, const MergeJoin *node)
if (OidIsValid(coll))
{
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_collation_namespace(coll)));
+ outToken(str, NSP_NAME(get_collation_namespace(coll)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_collation_name(coll));
+ outToken(str, get_collation_name(coll));
appendStringInfo(str, " %d", get_collation_encoding(coll));
}
else
@@ -1071,20 +1127,20 @@ _outAgg(StringInfo str, const Agg *node)
/* Group operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
appendStringInfoChar(str, ' ');
}
else
@@ -1092,6 +1148,7 @@ _outAgg(StringInfo str, const Agg *node)
appendStringInfo(str, " %u", node->grpOperators[i]);
WRITE_LONG_FIELD(numGroups);
+ WRITE_BITMAPSET_FIELD(aggParams);
WRITE_NODE_FIELD(groupingSets);
WRITE_NODE_FIELD(chain);
}
@@ -1122,20 +1179,20 @@ _outWindowAgg(StringInfo str, const WindowAgg *node)
/* The operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
appendStringInfoChar(str, ' ');
}
else
@@ -1158,20 +1215,20 @@ _outWindowAgg(StringInfo str, const WindowAgg *node)
/* Group operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
appendStringInfoChar(str, ' ');
}
else
@@ -1208,20 +1265,20 @@ _outGroup(StringInfo str, const Group *node)
/* Group operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
appendStringInfoChar(str, ' ');
}
else
@@ -1262,20 +1319,20 @@ _outSort(StringInfo str, const Sort *node)
/* Sort operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
}
else
#endif
@@ -1290,9 +1347,9 @@ _outSort(StringInfo str, const Sort *node)
if (OidIsValid(coll))
{
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_collation_namespace(coll)));
+ outToken(str, NSP_NAME(get_collation_namespace(coll)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_collation_name(coll));
+ outToken(str, get_collation_name(coll));
appendStringInfo(str, " %d", get_collation_encoding(coll));
}
else
@@ -1332,20 +1389,20 @@ _outUnique(StringInfo str, const Unique *node)
/* Unique operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
appendStringInfoChar(str, ' ');
}
else
@@ -1368,13 +1425,6 @@ _outHash(StringInfo str, const Hash *node)
WRITE_OID_FIELD(skewTable);
WRITE_INT_FIELD(skewColumn);
WRITE_BOOL_FIELD(skewInherit);
-#ifdef XCP
- if (portable_output)
- WRITE_TYPID_FIELD(skewColType);
- else
-#endif
- WRITE_OID_FIELD(skewColType);
- WRITE_INT_FIELD(skewColTypmod);
}
static void
@@ -1404,20 +1454,20 @@ _outSetOp(StringInfo str, const SetOp *node)
/* Unique operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
}
else
#endif
@@ -1503,9 +1553,9 @@ _outRemoteStmt(StringInfo str, const RemoteStmt *node)
Oid ptype = rparam->paramtype;
Assert(OidIsValid(ptype));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_typ_namespace(ptype)));
+ outToken(str, NSP_NAME(get_typ_namespace(ptype)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_typ_name(ptype));
+ outToken(str, get_typ_name(ptype));
}
else
appendStringInfo(str, " %u", rparam->paramtype);
@@ -1539,20 +1589,20 @@ _outSimpleSort(StringInfo str, const SimpleSort *node)
/* Sort operator is always valid */
Assert(OidIsValid(oper));
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_opnamespace(oper)));
+ outToken(str, NSP_NAME(get_opnamespace(oper)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_opname(oper));
+ outToken(str, get_opname(oper));
appendStringInfoChar(str, ' ');
op_input_types(oper, &oprleft, &oprright);
- _outToken(str, OidIsValid(oprleft) ?
+ outToken(str, OidIsValid(oprleft) ?
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
+ outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ?
+ outToken(str, OidIsValid(oprright) ?
NSP_NAME(get_typ_namespace(oprright)) : NULL);
appendStringInfoChar(str, ' ');
- _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
+ outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
}
else
appendStringInfo(str, " %u", node->sortOperators[i]);
@@ -1565,9 +1615,9 @@ _outSimpleSort(StringInfo str, const SimpleSort *node)
if (OidIsValid(coll))
{
appendStringInfoChar(str, ' ');
- _outToken(str, NSP_NAME(get_collation_namespace(coll)));
+ outToken(str, NSP_NAME(get_collation_namespace(coll)));
appendStringInfoChar(str, ' ');
- _outToken(str, get_collation_name(coll));
+ outToken(str, get_collation_name(coll));
appendStringInfo(str, " %d", get_collation_encoding(coll));
}
else
@@ -1641,13 +1691,33 @@ _outRangeVar(StringInfo str, const RangeVar *node)
*/
WRITE_STRING_FIELD(schemaname);
WRITE_STRING_FIELD(relname);
- WRITE_ENUM_FIELD(inhOpt, InhOption);
+ WRITE_BOOL_FIELD(inh);
WRITE_CHAR_FIELD(relpersistence);
WRITE_NODE_FIELD(alias);
WRITE_LOCATION_FIELD(location);
}
static void
+_outTableFunc(StringInfo str, const TableFunc *node)
+{
+ WRITE_NODE_TYPE("TABLEFUNC");
+
+ WRITE_NODE_FIELD(ns_names);
+ WRITE_NODE_FIELD(ns_uris);
+ WRITE_NODE_FIELD(docexpr);
+ WRITE_NODE_FIELD(rowexpr);
+ WRITE_NODE_FIELD(colnames);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
+ WRITE_NODE_FIELD(colexprs);
+ WRITE_NODE_FIELD(coldefexprs);
+ WRITE_BITMAPSET_FIELD(notnulls);
+ WRITE_INT_FIELD(ordinalitycol);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
_outIntoClause(StringInfo str, const IntoClause *node)
{
WRITE_NODE_TYPE("INTOCLAUSE");
@@ -2089,7 +2159,7 @@ _outBoolExpr(StringInfo str, const BoolExpr *node)
break;
}
appendStringInfoString(str, " :boolop ");
- _outToken(str, opstr);
+ outToken(str, opstr);
WRITE_NODE_FIELD(args);
WRITE_LOCATION_FIELD(location);
@@ -2133,6 +2203,7 @@ _outSubPlan(StringInfo str, const SubPlan *node)
WRITE_OID_FIELD(firstColCollation);
WRITE_BOOL_FIELD(useHashTable);
WRITE_BOOL_FIELD(unknownEqFalse);
+ WRITE_BOOL_FIELD(parallel_safe);
WRITE_NODE_FIELD(setParam);
WRITE_NODE_FIELD(parParam);
WRITE_NODE_FIELD(args);
@@ -2448,6 +2519,17 @@ _outMinMaxExpr(StringInfo str, const MinMaxExpr *node)
}
static void
+_outSQLValueFunction(StringInfo str, const SQLValueFunction *node)
+{
+ WRITE_NODE_TYPE("SQLVALUEFUNCTION");
+
+ WRITE_ENUM_FIELD(op, SQLValueFunctionOp);
+ WRITE_OID_FIELD(type);
+ WRITE_INT_FIELD(typmod);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
_outXmlExpr(StringInfo str, const XmlExpr *node)
{
WRITE_NODE_TYPE("XMLEXPR");
@@ -2661,14 +2743,14 @@ _outPathInfo(StringInfo str, const Path *node)
{
WRITE_ENUM_FIELD(pathtype, NodeTag);
appendStringInfoString(str, " :parent_relids ");
- _outBitmapset(str, node->parent->relids);
+ outBitmapset(str, node->parent->relids);
if (node->pathtarget != node->parent->reltarget)
WRITE_NODE_FIELD(pathtarget);
appendStringInfoString(str, " :required_outer ");
if (node->param_info)
- _outBitmapset(str, node->param_info->ppi_req_outer);
+ outBitmapset(str, node->param_info->ppi_req_outer);
else
- _outBitmapset(str, NULL);
+ outBitmapset(str, NULL);
WRITE_BOOL_FIELD(parallel_aware);
WRITE_BOOL_FIELD(parallel_safe);
WRITE_INT_FIELD(parallel_workers);
@@ -2687,6 +2769,7 @@ _outJoinPathInfo(StringInfo str, const JoinPath *node)
_outPathInfo(str, (const Path *) node);
WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(inner_unique);
WRITE_NODE_FIELD(outerjoinpath);
WRITE_NODE_FIELD(innerjoinpath);
WRITE_NODE_FIELD(joinrestrictinfo);
@@ -2793,7 +2876,7 @@ _outCustomPath(StringInfo str, const CustomPath *node)
WRITE_NODE_FIELD(custom_paths);
WRITE_NODE_FIELD(custom_private);
appendStringInfoString(str, " :methods ");
- _outToken(str, node->methods->CustomName);
+ outToken(str, node->methods->CustomName);
}
static void
@@ -2803,6 +2886,7 @@ _outAppendPath(StringInfo str, const AppendPath *node)
_outPathInfo(str, (const Path *) node);
+ WRITE_NODE_FIELD(partitioned_rels);
WRITE_NODE_FIELD(subpaths);
}
@@ -2813,6 +2897,7 @@ _outMergeAppendPath(StringInfo str, const MergeAppendPath *node)
_outPathInfo(str, (const Path *) node);
+ WRITE_NODE_FIELD(partitioned_rels);
WRITE_NODE_FIELD(subpaths);
WRITE_FLOAT_FIELD(limit_tuples, "%.0f");
}
@@ -2859,6 +2944,7 @@ _outGatherPath(StringInfo str, const GatherPath *node)
WRITE_NODE_FIELD(subpath);
WRITE_BOOL_FIELD(single_copy);
+ WRITE_INT_FIELD(num_workers);
}
static void
@@ -2873,6 +2959,16 @@ _outProjectionPath(StringInfo str, const ProjectionPath *node)
}
static void
+_outProjectSetPath(StringInfo str, const ProjectSetPath *node)
+{
+ WRITE_NODE_TYPE("PROJECTSETPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+}
+
+static void
_outSortPath(StringInfo str, const SortPath *node)
{
WRITE_NODE_TYPE("SORTPATH");
@@ -2921,6 +3017,28 @@ _outAggPath(StringInfo str, const AggPath *node)
}
static void
+_outRollupData(StringInfo str, const RollupData *node)
+{
+ WRITE_NODE_TYPE("ROLLUP");
+
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(gsets);
+ WRITE_NODE_FIELD(gsets_data);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+ WRITE_BOOL_FIELD(hashable);
+ WRITE_BOOL_FIELD(is_hashed);
+}
+
+static void
+_outGroupingSetData(StringInfo str, const GroupingSetData *node)
+{
+ WRITE_NODE_TYPE("GSDATA");
+
+ WRITE_NODE_FIELD(set);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+}
+
+static void
_outGroupingSetsPath(StringInfo str, const GroupingSetsPath *node)
{
WRITE_NODE_TYPE("GROUPINGSETSPATH");
@@ -2928,8 +3046,8 @@ _outGroupingSetsPath(StringInfo str, const GroupingSetsPath *node)
_outPathInfo(str, (const Path *) node);
WRITE_NODE_FIELD(subpath);
- WRITE_NODE_FIELD(rollup_groupclauses);
- WRITE_NODE_FIELD(rollup_lists);
+ WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
+ WRITE_NODE_FIELD(rollups);
WRITE_NODE_FIELD(qual);
}
@@ -3008,6 +3126,7 @@ _outModifyTablePath(StringInfo str, const ModifyTablePath *node)
WRITE_ENUM_FIELD(operation, CmdType);
WRITE_BOOL_FIELD(canSetTag);
WRITE_UINT_FIELD(nominalRelation);
+ WRITE_NODE_FIELD(partitioned_rels);
WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(subpaths);
WRITE_NODE_FIELD(subroots);
@@ -3031,6 +3150,17 @@ _outLimitPath(StringInfo str, const LimitPath *node)
}
static void
+_outGatherMergePath(StringInfo str, const GatherMergePath *node)
+{
+ WRITE_NODE_TYPE("GATHERMERGEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_INT_FIELD(num_workers);
+}
+
+static void
_outNestPath(StringInfo str, const NestPath *node)
{
WRITE_NODE_TYPE("NESTPATH");
@@ -3048,6 +3178,7 @@ _outMergePath(StringInfo str, const MergePath *node)
WRITE_NODE_FIELD(path_mergeclauses);
WRITE_NODE_FIELD(outersortkeys);
WRITE_NODE_FIELD(innersortkeys);
+ WRITE_BOOL_FIELD(skip_mark_restore);
WRITE_BOOL_FIELD(materialize_inner);
}
@@ -3073,6 +3204,8 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node)
WRITE_NODE_FIELD(finalrtable);
WRITE_NODE_FIELD(finalrowmarks);
WRITE_NODE_FIELD(resultRelations);
+ WRITE_NODE_FIELD(nonleafResultRelations);
+ WRITE_NODE_FIELD(rootResultRelations);
WRITE_NODE_FIELD(relationOids);
WRITE_NODE_FIELD(invalItems);
WRITE_INT_FIELD(nParamExec);
@@ -3083,6 +3216,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node)
WRITE_BOOL_FIELD(dependsOnRole);
WRITE_BOOL_FIELD(parallelModeOK);
WRITE_BOOL_FIELD(parallelModeNeeded);
+ WRITE_CHAR_FIELD(maxParallelHazard);
}
static void
@@ -3110,6 +3244,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node)
WRITE_NODE_FIELD(full_join_clauses);
WRITE_NODE_FIELD(join_info_list);
WRITE_NODE_FIELD(append_rel_list);
+ WRITE_NODE_FIELD(pcinfo_list);
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(placeholder_list);
WRITE_NODE_FIELD(fkey_list);
@@ -3123,6 +3258,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node)
WRITE_FLOAT_FIELD(total_table_pages, "%.0f");
WRITE_FLOAT_FIELD(tuple_fraction, "%.4f");
WRITE_FLOAT_FIELD(limit_tuples, "%.0f");
+ WRITE_UINT_FIELD(qual_security_level);
WRITE_BOOL_FIELD(hasInheritedTarget);
WRITE_BOOL_FIELD(hasJoinRTEs);
WRITE_BOOL_FIELD(hasLateralRTEs);
@@ -3165,6 +3301,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node)
WRITE_NODE_FIELD(lateral_vars);
WRITE_BITMAPSET_FIELD(lateral_referencers);
WRITE_NODE_FIELD(indexlist);
+ WRITE_NODE_FIELD(statlist);
WRITE_UINT_FIELD(pages);
WRITE_FLOAT_FIELD(tuples, "%.0f");
WRITE_FLOAT_FIELD(allvisfrac, "%.6f");
@@ -3175,9 +3312,12 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node)
WRITE_OID_FIELD(userid);
WRITE_BOOL_FIELD(useridiscurrent);
/* we don't try to print fdwroutine or fdw_private */
+ /* can't print unique_for_rels/non_unique_for_rels; BMSes aren't Nodes */
WRITE_NODE_FIELD(baserestrictinfo);
+ WRITE_UINT_FIELD(baserestrict_min_security);
WRITE_NODE_FIELD(joininfo);
WRITE_BOOL_FIELD(has_eclass_joins);
+ WRITE_BITMAPSET_FIELD(top_parent_relids);
}
static void
@@ -3237,6 +3377,18 @@ _outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node)
}
static void
+_outStatisticExtInfo(StringInfo str, const StatisticExtInfo *node)
+{
+ WRITE_NODE_TYPE("STATISTICEXTINFO");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_OID_FIELD(statOid);
+ /* don't write rel, leads to infinite recursion in plan tree dump */
+ WRITE_CHAR_FIELD(kind);
+ WRITE_BITMAPSET_FIELD(keys);
+}
+
+static void
_outEquivalenceClass(StringInfo str, const EquivalenceClass *node)
{
/*
@@ -3264,6 +3416,8 @@ _outEquivalenceClass(StringInfo str, const EquivalenceClass *node)
WRITE_BOOL_FIELD(ec_below_outer_join);
WRITE_BOOL_FIELD(ec_broken);
WRITE_UINT_FIELD(ec_sortref);
+ WRITE_UINT_FIELD(ec_min_security);
+ WRITE_UINT_FIELD(ec_max_security);
}
static void
@@ -3330,6 +3484,8 @@ _outRestrictInfo(StringInfo str, const RestrictInfo *node)
WRITE_BOOL_FIELD(outerjoin_delayed);
WRITE_BOOL_FIELD(can_join);
WRITE_BOOL_FIELD(pseudoconstant);
+ WRITE_BOOL_FIELD(leakproof);
+ WRITE_UINT_FIELD(security_level);
WRITE_BITMAPSET_FIELD(clause_relids);
WRITE_BITMAPSET_FIELD(required_relids);
WRITE_BITMAPSET_FIELD(outer_relids);
@@ -3397,6 +3553,15 @@ _outAppendRelInfo(StringInfo str, const AppendRelInfo *node)
}
static void
+_outPartitionedChildRelInfo(StringInfo str, const PartitionedChildRelInfo *node)
+{
+ WRITE_NODE_TYPE("PARTITIONEDCHILDRELINFO");
+
+ WRITE_UINT_FIELD(parent_relid);
+ WRITE_NODE_FIELD(child_rels);
+}
+
+static void
_outPlaceHolderInfo(StringInfo str, const PlaceHolderInfo *node)
{
WRITE_NODE_TYPE("PLACEHOLDERINFO");
@@ -3468,6 +3633,8 @@ _outCreateStmtInfo(StringInfo str, const CreateStmt *node)
WRITE_NODE_FIELD(relation);
WRITE_NODE_FIELD(tableElts);
WRITE_NODE_FIELD(inhRelations);
+ WRITE_NODE_FIELD(partspec);
+ WRITE_NODE_FIELD(partbound);
WRITE_NODE_FIELD(ofTypename);
WRITE_NODE_FIELD(constraints);
WRITE_NODE_FIELD(options);
@@ -3535,6 +3702,18 @@ _outIndexStmt(StringInfo str, const IndexStmt *node)
}
static void
+_outCreateStatsStmt(StringInfo str, const CreateStatsStmt *node)
+{
+ WRITE_NODE_TYPE("CREATESTATSSTMT");
+
+ WRITE_NODE_FIELD(defnames);
+ WRITE_NODE_FIELD(stat_types);
+ WRITE_NODE_FIELD(exprs);
+ WRITE_NODE_FIELD(relations);
+ WRITE_BOOL_FIELD(if_not_exists);
+}
+
+static void
_outNotifyStmt(StringInfo str, const NotifyStmt *node)
{
WRITE_NODE_TYPE("NOTIFY");
@@ -3604,6 +3783,7 @@ _outDefElem(StringInfo str, const DefElem *node)
WRITE_STRING_FIELD(defname);
WRITE_NODE_FIELD(arg);
WRITE_ENUM_FIELD(defaction, DefElemAction);
+ WRITE_LOCATION_FIELD(location);
}
static void
@@ -3637,6 +3817,16 @@ _outXmlSerialize(StringInfo str, const XmlSerialize *node)
}
static void
+_outTriggerTransition(StringInfo str, const TriggerTransition *node)
+{
+ WRITE_NODE_TYPE("TRIGGERTRANSITION");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_BOOL_FIELD(isNew);
+ WRITE_BOOL_FIELD(isTable);
+}
+
+static void
_outColumnDef(StringInfo str, const ColumnDef *node)
{
WRITE_NODE_TYPE("COLUMNDEF");
@@ -3647,9 +3837,11 @@ _outColumnDef(StringInfo str, const ColumnDef *node)
WRITE_BOOL_FIELD(is_local);
WRITE_BOOL_FIELD(is_not_null);
WRITE_BOOL_FIELD(is_from_type);
+ WRITE_BOOL_FIELD(is_from_parent);
WRITE_CHAR_FIELD(storage);
WRITE_NODE_FIELD(raw_default);
WRITE_NODE_FIELD(cooked_default);
+ WRITE_CHAR_FIELD(identity);
WRITE_NODE_FIELD(collClause);
WRITE_OID_FIELD(collOid);
WRITE_NODE_FIELD(constraints);
@@ -3744,6 +3936,7 @@ _outQuery(StringInfo str, const Query *node)
WRITE_INT_FIELD(resultRelation);
WRITE_BOOL_FIELD(hasAggs);
WRITE_BOOL_FIELD(hasWindowFuncs);
+ WRITE_BOOL_FIELD(hasTargetSRFs);
WRITE_BOOL_FIELD(hasSubLinks);
WRITE_BOOL_FIELD(hasDistinctOn);
WRITE_BOOL_FIELD(hasRecursive);
@@ -3754,6 +3947,7 @@ _outQuery(StringInfo str, const Query *node)
WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(jointree);
WRITE_NODE_FIELD(targetList);
+ WRITE_ENUM_FIELD(override, OverridingKind);
WRITE_NODE_FIELD(onConflict);
WRITE_NODE_FIELD(returningList);
WRITE_NODE_FIELD(groupClause);
@@ -3767,6 +3961,9 @@ _outQuery(StringInfo str, const Query *node)
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(setOperations);
WRITE_NODE_FIELD(constraintDeps);
+ /* withCheckOptions intentionally omitted, see comment in parsenodes.h */
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_LOCATION_FIELD(stmt_len);
}
static void
@@ -3916,17 +4113,29 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
WRITE_NODE_FIELD(functions);
WRITE_BOOL_FIELD(funcordinality);
break;
+ case RTE_TABLEFUNC:
+ WRITE_NODE_FIELD(tablefunc);
+ break;
case RTE_VALUES:
WRITE_NODE_FIELD(values_lists);
- WRITE_NODE_FIELD(values_collations);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
break;
case RTE_CTE:
WRITE_STRING_FIELD(ctename);
WRITE_UINT_FIELD(ctelevelsup);
WRITE_BOOL_FIELD(self_reference);
- WRITE_NODE_FIELD(ctecoltypes);
- WRITE_NODE_FIELD(ctecoltypmods);
- WRITE_NODE_FIELD(ctecolcollations);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
+ break;
+ case RTE_NAMEDTUPLESTORE:
+ WRITE_STRING_FIELD(enrname);
+ WRITE_OID_FIELD(relid);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
break;
#ifdef PGXC
case RTE_REMOTE_DUMMY:
@@ -4091,12 +4300,12 @@ _outValue(StringInfo str, const Value *value)
case T_String:
/*
- * We use _outToken to provide escaping of the string's content,
+ * We use outToken to provide escaping of the string's content,
* but we don't want it to do anything with an empty string.
*/
appendStringInfoChar(str, '"');
if (value->val.str[0] != '\0')
- _outToken(str, value->val.str);
+ outToken(str, value->val.str);
appendStringInfoChar(str, '"');
break;
case T_BitString:
@@ -4259,6 +4468,34 @@ _outRangeTableSample(StringInfo str, const RangeTableSample *node)
}
static void
+_outRangeTableFunc(StringInfo str, const RangeTableFunc *node)
+{
+ WRITE_NODE_TYPE("RANGETABLEFUNC");
+
+ WRITE_BOOL_FIELD(lateral);
+ WRITE_NODE_FIELD(docexpr);
+ WRITE_NODE_FIELD(rowexpr);
+ WRITE_NODE_FIELD(namespaces);
+ WRITE_NODE_FIELD(columns);
+ WRITE_NODE_FIELD(alias);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outRangeTableFuncCol(StringInfo str, const RangeTableFuncCol *node)
+{
+ WRITE_NODE_TYPE("RANGETABLEFUNCCOL");
+
+ WRITE_STRING_FIELD(colname);
+ WRITE_NODE_FIELD(typeName);
+ WRITE_BOOL_FIELD(for_ordinality);
+ WRITE_BOOL_FIELD(is_not_null);
+ WRITE_NODE_FIELD(colexpr);
+ WRITE_NODE_FIELD(coldefexpr);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
_outConstraint(StringInfo str, const Constraint *node)
{
WRITE_NODE_TYPE("CONSTRAINT");
@@ -4285,6 +4522,13 @@ _outConstraint(StringInfo str, const Constraint *node)
WRITE_STRING_FIELD(cooked_expr);
break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "IDENTITY");
+ WRITE_NODE_FIELD(raw_expr);
+ WRITE_STRING_FIELD(cooked_expr);
+ WRITE_CHAR_FIELD(generated_when);
+ break;
+
case CONSTR_CHECK:
appendStringInfoString(str, "CHECK");
WRITE_BOOL_FIELD(is_no_inherit);
@@ -4378,6 +4622,49 @@ _outForeignKeyCacheInfo(StringInfo str, const ForeignKeyCacheInfo *node)
appendStringInfo(str, " %u", node->conpfeqop[i]);
}
+static void
+_outPartitionElem(StringInfo str, const PartitionElem *node)
+{
+ WRITE_NODE_TYPE("PARTITIONELEM");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(expr);
+ WRITE_NODE_FIELD(collation);
+ WRITE_NODE_FIELD(opclass);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outPartitionSpec(StringInfo str, const PartitionSpec *node)
+{
+ WRITE_NODE_TYPE("PARTITIONBY");
+
+ WRITE_STRING_FIELD(strategy);
+ WRITE_NODE_FIELD(partParams);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outPartitionBoundSpec(StringInfo str, const PartitionBoundSpec *node)
+{
+ WRITE_NODE_TYPE("PARTITIONBOUND");
+
+ WRITE_CHAR_FIELD(strategy);
+ WRITE_NODE_FIELD(listdatums);
+ WRITE_NODE_FIELD(lowerdatums);
+ WRITE_NODE_FIELD(upperdatums);
+ /* XXX somebody forgot location field; too late to change for v10 */
+}
+
+static void
+_outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node)
+{
+ WRITE_NODE_TYPE("PARTRANGEDATUM");
+
+ WRITE_BOOL_FIELD(infinite);
+ WRITE_NODE_FIELD(value);
+ /* XXX somebody forgot location field; too late to change for v10 */
+}
/*
* outNode -
@@ -4412,6 +4699,9 @@ outNode(StringInfo str, const void *obj)
case T_Result:
_outResult(str, obj);
break;
+ case T_ProjectSet:
+ _outProjectSet(str, obj);
+ break;
case T_ModifyTable:
_outModifyTable(str, obj);
break;
@@ -4433,6 +4723,9 @@ outNode(StringInfo str, const void *obj)
case T_Gather:
_outGather(str, obj);
break;
+ case T_GatherMerge:
+ _outGatherMerge(str, obj);
+ break;
case T_Scan:
_outScan(str, obj);
break;
@@ -4468,12 +4761,18 @@ outNode(StringInfo str, const void *obj)
case T_FunctionScan:
_outFunctionScan(str, obj);
break;
+ case T_TableFuncScan:
+ _outTableFuncScan(str, obj);
+ break;
case T_ValuesScan:
_outValuesScan(str, obj);
break;
case T_CteScan:
_outCteScan(str, obj);
break;
+ case T_NamedTuplestoreScan:
+ _outNamedTuplestoreScan(str, obj);
+ break;
case T_WorkTableScan:
_outWorkTableScan(str, obj);
break;
@@ -4551,6 +4850,9 @@ outNode(StringInfo str, const void *obj)
case T_RangeVar:
_outRangeVar(str, obj);
break;
+ case T_TableFunc:
+ _outTableFunc(str, obj);
+ break;
case T_IntoClause:
_outIntoClause(str, obj);
break;
@@ -4650,6 +4952,9 @@ outNode(StringInfo str, const void *obj)
case T_MinMaxExpr:
_outMinMaxExpr(str, obj);
break;
+ case T_SQLValueFunction:
+ _outSQLValueFunction(str, obj);
+ break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;
@@ -4737,6 +5042,9 @@ outNode(StringInfo str, const void *obj)
case T_ProjectionPath:
_outProjectionPath(str, obj);
break;
+ case T_ProjectSetPath:
+ _outProjectSetPath(str, obj);
+ break;
case T_SortPath:
_outSortPath(str, obj);
break;
@@ -4773,6 +5081,9 @@ outNode(StringInfo str, const void *obj)
case T_LimitPath:
_outLimitPath(str, obj);
break;
+ case T_GatherMergePath:
+ _outGatherMergePath(str, obj);
+ break;
case T_NestPath:
_outNestPath(str, obj);
break;
@@ -4824,6 +5135,9 @@ outNode(StringInfo str, const void *obj)
case T_AppendRelInfo:
_outAppendRelInfo(str, obj);
break;
+ case T_PartitionedChildRelInfo:
+ _outPartitionedChildRelInfo(str, obj);
+ break;
case T_PlaceHolderInfo:
_outPlaceHolderInfo(str, obj);
break;
@@ -4833,11 +5147,18 @@ outNode(StringInfo str, const void *obj)
case T_PlannerParamItem:
_outPlannerParamItem(str, obj);
break;
-
+ case T_RollupData:
+ _outRollupData(str, obj);
+ break;
+ case T_GroupingSetData:
+ _outGroupingSetData(str, obj);
+ break;
+ case T_StatisticExtInfo:
+ _outStatisticExtInfo(str, obj);
+ break;
case T_ExtensibleNode:
_outExtensibleNode(str, obj);
break;
-
case T_CreateStmt:
_outCreateStmt(str, obj);
break;
@@ -4850,6 +5171,9 @@ outNode(StringInfo str, const void *obj)
case T_IndexStmt:
_outIndexStmt(str, obj);
break;
+ case T_CreateStatsStmt:
+ _outCreateStatsStmt(str, obj);
+ break;
case T_NotifyStmt:
_outNotifyStmt(str, obj);
break;
@@ -4955,6 +5279,12 @@ outNode(StringInfo str, const void *obj)
case T_RangeTableSample:
_outRangeTableSample(str, obj);
break;
+ case T_RangeTableFunc:
+ _outRangeTableFunc(str, obj);
+ break;
+ case T_RangeTableFuncCol:
+ _outRangeTableFuncCol(str, obj);
+ break;
case T_Constraint:
_outConstraint(str, obj);
break;
@@ -4981,6 +5311,21 @@ outNode(StringInfo str, const void *obj)
_outExecNodes(str, obj);
break;
#endif
+ case T_TriggerTransition:
+ _outTriggerTransition(str, obj);
+ break;
+ case T_PartitionElem:
+ _outPartitionElem(str, obj);
+ break;
+ case T_PartitionSpec:
+ _outPartitionSpec(str, obj);
+ break;
+ case T_PartitionBoundSpec:
+ _outPartitionBoundSpec(str, obj);
+ break;
+ case T_PartitionRangeDatum:
+ _outPartitionRangeDatum(str, obj);
+ break;
default:
@@ -5010,3 +5355,18 @@ nodeToString(const void *obj)
outNode(&str, obj);
return str.data;
}
+
+/*
+ * bmsToString -
+ * returns the ascii representation of the Bitmapset as a palloc'd string
+ */
+char *
+bmsToString(const Bitmapset *bms)
+{
+ StringInfoData str;
+
+ /* see stringinfo.h for an explanation of this maneuver */
+ initStringInfo(&str);
+ outBitmapset(&str, bms);
+ return str.data;
+}
diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c
index f2e26b80c4..0fb08b94db 100644
--- a/src/backend/nodes/params.c
+++ b/src/backend/nodes/params.c
@@ -4,7 +4,7 @@
* Support for finding the values associated with Param nodes.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index a5b4d24262..0cf7f40c8c 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -3,7 +3,7 @@
* print.c
* various print routines (used mostly for debugging)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -282,6 +282,10 @@ print_rt(const List *rtable)
printf("%d\t%s\t[rangefunction]",
i, rte->eref->aliasname);
break;
+ case RTE_TABLEFUNC:
+ printf("%d\t%s\t[table function]",
+ i, rte->eref->aliasname);
+ break;
case RTE_VALUES:
printf("%d\t%s\t[values list]",
i, rte->eref->aliasname);
@@ -290,6 +294,10 @@ print_rt(const List *rtable)
printf("%d\t%s\t[cte]",
i, rte->eref->aliasname);
break;
+ case RTE_NAMEDTUPLESTORE:
+ printf("%d\t%s\t[tuplestore]",
+ i, rte->eref->aliasname);
+ break;
default:
printf("%d\t%s\t[unknown rtekind]",
i, rte->eref->aliasname);
diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c
index c1ab494d77..b56f28e15f 100644
--- a/src/backend/nodes/read.c
+++ b/src/backend/nodes/read.c
@@ -4,7 +4,7 @@
* routines to convert a string (legal ascii representation of node) back
* to nodes
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 933825cd74..23091c2bcc 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -4,7 +4,7 @@
* Reader functions for Postgres tree nodes.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -451,8 +451,6 @@ set_portable_input(bool value)
*/
#define atoui(x) ((unsigned int) strtoul((x), NULL, 10))
-#define atooid(x) ((Oid) strtoul((x), NULL, 10))
-
#define strtobool(x) ((*(x) == 't') ? true : false)
#define nullable_string(token,length) \
@@ -528,6 +526,7 @@ _readQuery(void)
READ_INT_FIELD(resultRelation);
READ_BOOL_FIELD(hasAggs);
READ_BOOL_FIELD(hasWindowFuncs);
+ READ_BOOL_FIELD(hasTargetSRFs);
READ_BOOL_FIELD(hasSubLinks);
READ_BOOL_FIELD(hasDistinctOn);
READ_BOOL_FIELD(hasRecursive);
@@ -538,6 +537,7 @@ _readQuery(void)
READ_NODE_FIELD(rtable);
READ_NODE_FIELD(jointree);
READ_NODE_FIELD(targetList);
+ READ_ENUM_FIELD(override, OverridingKind);
READ_NODE_FIELD(onConflict);
READ_NODE_FIELD(returningList);
READ_NODE_FIELD(groupClause);
@@ -551,6 +551,9 @@ _readQuery(void)
READ_NODE_FIELD(rowMarks);
READ_NODE_FIELD(setOperations);
READ_NODE_FIELD(constraintDeps);
+ /* withCheckOptions intentionally omitted, see comment in parsenodes.h */
+ READ_LOCATION_FIELD(stmt_location);
+ READ_LOCATION_FIELD(stmt_len);
READ_DONE();
}
@@ -748,7 +751,7 @@ _readRangeVar(void)
READ_STRING_FIELD(schemaname);
READ_STRING_FIELD(relname);
- READ_ENUM_FIELD(inhOpt, InhOption);
+ READ_BOOL_FIELD(inh);
READ_CHAR_FIELD(relpersistence);
READ_NODE_FIELD(alias);
READ_LOCATION_FIELD(location);
@@ -756,6 +759,31 @@ _readRangeVar(void)
READ_DONE();
}
+/*
+ * _readTableFunc
+ */
+static TableFunc *
+_readTableFunc(void)
+{
+ READ_LOCALS(TableFunc);
+
+ READ_NODE_FIELD(ns_names);
+ READ_NODE_FIELD(ns_uris);
+ READ_NODE_FIELD(docexpr);
+ READ_NODE_FIELD(rowexpr);
+ READ_NODE_FIELD(colnames);
+ READ_NODE_FIELD(coltypes);
+ READ_NODE_FIELD(coltypmods);
+ READ_NODE_FIELD(colcollations);
+ READ_NODE_FIELD(colexprs);
+ READ_NODE_FIELD(coldefexprs);
+ READ_BITMAPSET_FIELD(notnulls);
+ READ_INT_FIELD(ordinalitycol);
+ READ_LOCATION_FIELD(location);
+
+ READ_DONE();
+}
+
static IntoClause *
_readIntoClause(void)
{
@@ -1679,6 +1707,22 @@ _readMinMaxExpr(void)
}
/*
+ * _readSQLValueFunction
+ */
+static SQLValueFunction *
+_readSQLValueFunction(void)
+{
+ READ_LOCALS(SQLValueFunction);
+
+ READ_ENUM_FIELD(op, SQLValueFunctionOp);
+ READ_OID_FIELD(type);
+ READ_INT_FIELD(typmod);
+ READ_LOCATION_FIELD(location);
+
+ READ_DONE();
+}
+
+/*
* _readXmlExpr
*/
static XmlExpr *
@@ -1983,17 +2027,29 @@ _readRangeTblEntry(void)
READ_NODE_FIELD(functions);
READ_BOOL_FIELD(funcordinality);
break;
+ case RTE_TABLEFUNC:
+ READ_NODE_FIELD(tablefunc);
+ break;
case RTE_VALUES:
READ_NODE_FIELD(values_lists);
- READ_NODE_FIELD(values_collations);
+ READ_NODE_FIELD(coltypes);
+ READ_NODE_FIELD(coltypmods);
+ READ_NODE_FIELD(colcollations);
break;
case RTE_CTE:
READ_STRING_FIELD(ctename);
READ_UINT_FIELD(ctelevelsup);
READ_BOOL_FIELD(self_reference);
- READ_NODE_FIELD(ctecoltypes);
- READ_NODE_FIELD(ctecoltypmods);
- READ_NODE_FIELD(ctecolcollations);
+ READ_NODE_FIELD(coltypes);
+ READ_NODE_FIELD(coltypmods);
+ READ_NODE_FIELD(colcollations);
+ break;
+ case RTE_NAMEDTUPLESTORE:
+ READ_STRING_FIELD(enrname);
+ READ_OID_FIELD(relid);
+ READ_NODE_FIELD(coltypes);
+ READ_NODE_FIELD(coltypmods);
+ READ_NODE_FIELD(colcollations);
break;
#ifdef PGXC
case RTE_REMOTE_DUMMY:
@@ -2105,6 +2161,7 @@ _readDefElem(void)
READ_STRING_FIELD(defname);
READ_NODE_FIELD(arg);
READ_ENUM_FIELD(defaction, DefElemAction);
+ READ_LOCATION_FIELD(location);
READ_DONE();
}
@@ -2141,13 +2198,17 @@ _readPlannedStmt(void)
READ_NODE_FIELD(planTree);
READ_NODE_FIELD(rtable);
READ_NODE_FIELD(resultRelations);
- READ_NODE_FIELD(utilityStmt);
+ READ_NODE_FIELD(nonleafResultRelations);
+ READ_NODE_FIELD(rootResultRelations);
READ_NODE_FIELD(subplans);
READ_BITMAPSET_FIELD(rewindPlanIDs);
READ_NODE_FIELD(rowMarks);
READ_NODE_FIELD(relationOids);
READ_NODE_FIELD(invalItems);
READ_INT_FIELD(nParamExec);
+ READ_NODE_FIELD(utilityStmt);
+ READ_LOCATION_FIELD(stmt_location);
+ READ_LOCATION_FIELD(stmt_len);
READ_DONE();
}
@@ -2168,6 +2229,19 @@ _readResult(void)
}
/*
+ * _readProjectSet
+ */
+static ProjectSet *
+_readProjectSet(void)
+{
+ READ_LOCALS_NO_FIELDS(ProjectSet);
+
+ ReadCommonPlan(&local_node->plan);
+
+ READ_DONE();
+}
+
+/*
* _readModifyTable
*/
static ModifyTable *
@@ -2180,8 +2254,10 @@ _readModifyTable(void)
READ_ENUM_FIELD(operation, CmdType);
READ_BOOL_FIELD(canSetTag);
READ_UINT_FIELD(nominalRelation);
+ READ_NODE_FIELD(partitioned_rels);
READ_NODE_FIELD(resultRelations);
READ_INT_FIELD(resultRelIndex);
+ READ_INT_FIELD(rootResultRelIndex);
READ_NODE_FIELD(plans);
READ_NODE_FIELD(withCheckOptionLists);
READ_NODE_FIELD(returningLists);
@@ -2212,6 +2288,7 @@ _readAppend(void)
ReadCommonPlan(&local_node->plan);
+ READ_NODE_FIELD(partitioned_rels);
READ_NODE_FIELD(appendplans);
READ_DONE();
@@ -2228,6 +2305,7 @@ _readMergeAppend(void)
ReadCommonPlan(&local_node->plan);
+ READ_NODE_FIELD(partitioned_rels);
READ_NODE_FIELD(mergeplans);
READ_INT_FIELD(numCols);
READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);
@@ -2354,6 +2432,7 @@ _readBitmapOr(void)
ReadCommonPlan(&local_node->plan);
+ READ_BOOL_FIELD(isshared);
READ_NODE_FIELD(bitmapplans);
READ_DONE();
@@ -2474,6 +2553,7 @@ _readBitmapIndexScan(void)
READ_RELID_FIELD(indexid);
else
READ_OID_FIELD(indexid);
+ READ_BOOL_FIELD(isshared);
READ_NODE_FIELD(indexqual);
READ_NODE_FIELD(indexqualorig);
@@ -2557,6 +2637,21 @@ _readValuesScan(void)
}
/*
+ * _readTableFuncScan
+ */
+static TableFuncScan *
+_readTableFuncScan(void)
+{
+ READ_LOCALS(TableFuncScan);
+
+ ReadCommonScan(&local_node->scan);
+
+ READ_NODE_FIELD(tablefunc);
+
+ READ_DONE();
+}
+
+/*
* _readCteScan
*/
static CteScan *
@@ -2650,6 +2745,7 @@ ReadCommonJoin(Join *local_node)
ReadCommonPlan(&local_node->plan);
READ_ENUM_FIELD(jointype, JoinType);
+ READ_BOOL_FIELD(inner_unique);
READ_NODE_FIELD(joinqual);
}
@@ -2694,6 +2790,7 @@ _readMergeJoin(void)
ReadCommonJoin(&local_node->join);
+ READ_BOOL_FIELD(skip_mark_restore);
READ_NODE_FIELD(mergeclauses);
numCols = list_length(local_node->mergeclauses);
@@ -3001,6 +3098,7 @@ _readAgg(void)
#endif
READ_LONG_FIELD(numGroups);
+ READ_BITMAPSET_FIELD(aggParams);
READ_NODE_FIELD(groupingSets);
READ_NODE_FIELD(chain);
@@ -3218,6 +3316,26 @@ _readGather(void)
}
/*
+ * _readGatherMerge
+ */
+static GatherMerge *
+_readGatherMerge(void)
+{
+ READ_LOCALS(GatherMerge);
+
+ ReadCommonPlan(&local_node->plan);
+
+ READ_INT_FIELD(num_workers);
+ READ_INT_FIELD(numCols);
+ READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);
+ READ_OID_ARRAY(sortOperators, local_node->numCols);
+ READ_OID_ARRAY(collations, local_node->numCols);
+ READ_BOOL_ARRAY(nullsFirst, local_node->numCols);
+
+ READ_DONE();
+}
+
+/*
* _readHash
*/
static Hash *
@@ -3233,11 +3351,6 @@ _readHash(void)
READ_OID_FIELD(skewTable);
READ_INT_FIELD(skewColumn);
READ_BOOL_FIELD(skewInherit);
- if (portable_input)
- READ_TYPID_FIELD(skewColType);
- else
- READ_OID_FIELD(skewColType);
- READ_INT_FIELD(skewColTypmod);
READ_DONE();
}
@@ -3434,6 +3547,7 @@ _readSubPlan(void)
READ_OID_FIELD(firstColCollation);
READ_BOOL_FIELD(useHashTable);
READ_BOOL_FIELD(unknownEqFalse);
+ READ_BOOL_FIELD(parallel_safe);
READ_NODE_FIELD(setParam);
READ_NODE_FIELD(parParam);
READ_NODE_FIELD(args);
@@ -3685,6 +3799,40 @@ _readSimpleSort(void)
/*
+ * _readPartitionBoundSpec
+ */
+static PartitionBoundSpec *
+_readPartitionBoundSpec(void)
+{
+ READ_LOCALS(PartitionBoundSpec);
+
+ READ_CHAR_FIELD(strategy);
+ READ_NODE_FIELD(listdatums);
+ READ_NODE_FIELD(lowerdatums);
+ READ_NODE_FIELD(upperdatums);
+ /* XXX somebody forgot location field; too late to change for v10 */
+ local_node->location = -1;
+
+ READ_DONE();
+}
+
+/*
+ * _readPartitionRangeDatum
+ */
+static PartitionRangeDatum *
+_readPartitionRangeDatum(void)
+{
+ READ_LOCALS(PartitionRangeDatum);
+
+ READ_BOOL_FIELD(infinite);
+ READ_NODE_FIELD(value);
+ /* XXX somebody forgot location field; too late to change for v10 */
+ local_node->location = -1;
+
+ READ_DONE();
+}
+
+/*
* parseNodeString
*
* Given a character string representing a node tree, parseNodeString creates
@@ -3726,6 +3874,8 @@ parseNodeString(void)
return_value = _readRangeVar();
else if (MATCH("INTOCLAUSE", 10))
return_value = _readIntoClause();
+ else if (MATCH("TABLEFUNC", 9))
+ return_value = _readTableFunc();
else if (MATCH("VAR", 3))
return_value = _readVar();
else if (MATCH("CONST", 5))
@@ -3786,6 +3936,8 @@ parseNodeString(void)
return_value = _readCoalesceExpr();
else if (MATCH("MINMAX", 6))
return_value = _readMinMaxExpr();
+ else if (MATCH("SQLVALUEFUNCTION", 16))
+ return_value = _readSQLValueFunction();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("NULLTEST", 8))
@@ -3830,6 +3982,8 @@ parseNodeString(void)
return_value = _readPlan();
else if (MATCH("RESULT", 6))
return_value = _readResult();
+ else if (MATCH("PROJECTSET", 10))
+ return_value = _readProjectSet();
else if (MATCH("MODIFYTABLE", 11))
return_value = _readModifyTable();
else if (MATCH("APPEND", 6))
@@ -3864,6 +4018,8 @@ parseNodeString(void)
return_value = _readFunctionScan();
else if (MATCH("VALUESSCAN", 10))
return_value = _readValuesScan();
+ else if (MATCH("TABLEFUNCSCAN", 13))
+ return_value = _readTableFuncScan();
else if (MATCH("CTESCAN", 7))
return_value = _readCteScan();
else if (MATCH("WORKTABLESCAN", 13))
@@ -3894,6 +4050,8 @@ parseNodeString(void)
return_value = _readUnique();
else if (MATCH("GATHER", 6))
return_value = _readGather();
+ else if (MATCH("GATHERMERGE", 11))
+ return_value = _readGatherMerge();
else if (MATCH("HASH", 4))
return_value = _readHash();
else if (MATCH("SETOP", 5))
@@ -3920,6 +4078,10 @@ parseNodeString(void)
return_value = _readRemoteStmt();
else if (MATCH("SIMPLESORT", 10))
return_value = _readSimpleSort();
+ else if (MATCH("PARTITIONBOUND", 14))
+ return_value = _readPartitionBoundSpec();
+ else if (MATCH("PARTRANGEDATUM", 14))
+ return_value = _readPartitionRangeDatum();
else
{
elog(ERROR, "badly formatted node string \"%.32s\"...", token);
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index dfeb7d5c63..bbd39a2ed9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -29,7 +29,7 @@
* and a non-lossy page.
*
*
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2003-2017, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/nodes/tidbitmap.c
@@ -43,7 +43,8 @@
#include "access/htup_details.h"
#include "nodes/bitmapset.h"
#include "nodes/tidbitmap.h"
-#include "utils/hsearch.h"
+#include "storage/lwlock.h"
+#include "utils/dsa.h"
/*
* The maximum number of tuples per page is not large (typically 256 with
@@ -61,12 +62,12 @@
* for that page in the page table.
*
* We actually store both exact pages and lossy chunks in the same hash
- * table, using identical data structures. (This is because dynahash.c's
- * memory management doesn't allow space to be transferred easily from one
- * hashtable to another.) Therefore it's best if PAGES_PER_CHUNK is the
- * same as MAX_TUPLES_PER_PAGE, or at least not too different. But we
- * also want PAGES_PER_CHUNK to be a power of 2 to avoid expensive integer
- * remainder operations. So, define it like this:
+ * table, using identical data structures. (This is because the memory
+ * management for hashtables doesn't easily/efficiently allow space to be
+ * transferred easily from one hashtable to another.) Therefore it's best
+ * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * too different. But we also want PAGES_PER_CHUNK to be a power of 2 to
+ * avoid expensive integer remainder operations. So, define it like this:
*/
#define PAGES_PER_CHUNK (BLCKSZ / 32)
@@ -97,21 +98,31 @@
typedef struct PagetableEntry
{
BlockNumber blockno; /* page number (hashtable key) */
+ char status; /* hash entry status */
bool ischunk; /* T = lossy storage, F = exact */
bool recheck; /* should the tuples be rechecked? */
bitmapword words[Max(WORDS_PER_PAGE, WORDS_PER_CHUNK)];
} PagetableEntry;
/*
- * dynahash.c is optimized for relatively large, long-lived hash tables.
- * This is not ideal for TIDBitMap, particularly when we are using a bitmap
- * scan on the inside of a nestloop join: a bitmap may well live only long
- * enough to accumulate one entry in such cases. We therefore avoid creating
- * an actual hashtable until we need two pagetable entries. When just one
- * pagetable entry is needed, we store it in a fixed field of TIDBitMap.
- * (NOTE: we don't get rid of the hashtable if the bitmap later shrinks down
- * to zero or one page again. So, status can be TBM_HASH even when nentries
- * is zero or one.)
+ * Holds array of pagetable entries.
+ */
+typedef struct PTEntryArray
+{
+ pg_atomic_uint32 refcount; /* no. of iterator attached */
+ PagetableEntry ptentry[FLEXIBLE_ARRAY_MEMBER];
+} PTEntryArray;
+
+/*
+ * We want to avoid the overhead of creating the hashtable, which is
+ * comparatively large, when not necessary. Particularly when we are using a
+ * bitmap scan on the inside of a nestloop join: a bitmap may well live only
+ * long enough to accumulate one entry in such cases. We therefore avoid
+ * creating an actual hashtable until we need two pagetable entries. When
+ * just one pagetable entry is needed, we store it in a fixed field of
+ * TIDBitMap. (NOTE: we don't get rid of the hashtable if the bitmap later
+ * shrinks down to zero or one page again. So, status can be TBM_HASH even
+ * when nentries is zero or one.)
*/
typedef enum
{
@@ -121,6 +132,16 @@ typedef enum
} TBMStatus;
/*
+ * Current iterating state of the TBM.
+ */
+typedef enum
+{
+ TBM_NOT_ITERATING, /* not yet converted to page and chunk array */
+ TBM_ITERATING_PRIVATE, /* converted to local page and chunk array */
+ TBM_ITERATING_SHARED /* converted to shared page and chunk array */
+} TBMIteratingState;
+
+/*
* Here is the representation for a whole TIDBitMap:
*/
struct TIDBitmap
@@ -128,16 +149,22 @@ struct TIDBitmap
NodeTag type; /* to make it a valid Node */
MemoryContext mcxt; /* memory context containing me */
TBMStatus status; /* see codes above */
- HTAB *pagetable; /* hash table of PagetableEntry's */
+ struct pagetable_hash *pagetable; /* hash table of PagetableEntry's */
int nentries; /* number of entries in pagetable */
int maxentries; /* limit on same to meet maxbytes */
int npages; /* number of exact entries in pagetable */
int nchunks; /* number of lossy entries in pagetable */
- bool iterating; /* tbm_begin_iterate called? */
+ TBMIteratingState iterating; /* tbm_begin_iterate called? */
+ uint32 lossify_start; /* offset to start lossifying hashtable at */
PagetableEntry entry1; /* used when status == TBM_ONE_PAGE */
/* these are valid when iterating is true: */
PagetableEntry **spages; /* sorted exact-page list, or NULL */
PagetableEntry **schunks; /* sorted lossy-chunk list, or NULL */
+ dsa_pointer dsapagetable; /* dsa_pointer to the element array */
+ dsa_pointer dsapagetableold; /* dsa_pointer to the old element array */
+ dsa_pointer ptpages; /* dsa_pointer to the page array */
+ dsa_pointer ptchunks; /* dsa_pointer to the chunk array */
+ dsa_area *dsa; /* reference to per-query dsa area */
};
/*
@@ -155,6 +182,46 @@ struct TBMIterator
TBMIterateResult output; /* MUST BE LAST (because variable-size) */
};
+/*
+ * Holds the shared members of the iterator so that multiple processes
+ * can jointly iterate.
+ */
+typedef struct TBMSharedIteratorState
+{
+ int nentries; /* number of entries in pagetable */
+ int maxentries; /* limit on same to meet maxbytes */
+ int npages; /* number of exact entries in pagetable */
+ int nchunks; /* number of lossy entries in pagetable */
+ dsa_pointer pagetable; /* dsa pointers to head of pagetable data */
+ dsa_pointer spages; /* dsa pointer to page array */
+ dsa_pointer schunks; /* dsa pointer to chunk array */
+ LWLock lock; /* lock to protect below members */
+ int spageptr; /* next spages index */
+ int schunkptr; /* next schunks index */
+ int schunkbit; /* next bit to check in current schunk */
+} TBMSharedIteratorState;
+
+/*
+ * pagetable iteration array.
+ */
+typedef struct PTIterationArray
+{
+ pg_atomic_uint32 refcount; /* no. of iterator attached */
+ int index[FLEXIBLE_ARRAY_MEMBER]; /* index array */
+} PTIterationArray;
+
+/*
+ * same as TBMIterator, but it is used for joint iteration, therefore this
+ * also holds a reference to the shared state.
+ */
+struct TBMSharedIterator
+{
+ TBMSharedIteratorState *state; /* shared state */
+ PTEntryArray *ptbase; /* pagetable element array */
+ PTIterationArray *ptpages; /* sorted exact page index list */
+ PTIterationArray *ptchunks; /* sorted lossy page index list */
+ TBMIterateResult output; /* MUST BE LAST (because variable-size) */
+};
/* Local function prototypes */
static void tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage);
@@ -167,6 +234,38 @@ static bool tbm_page_is_lossy(const TIDBitmap *tbm, BlockNumber pageno);
static void tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno);
static void tbm_lossify(TIDBitmap *tbm);
static int tbm_comparator(const void *left, const void *right);
+static int tbm_shared_comparator(const void *left, const void *right,
+ void *arg);
+
+/*
+ * Simple inline murmur hash implementation for the exact width required, for
+ * performance.
+ */
+static inline uint32
+hash_blockno(BlockNumber b)
+{
+ uint32 h = b;
+
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+ return h;
+}
+
+/* define hashtable mapping block numbers to PagetableEntry's */
+#define SH_USE_NONDEFAULT_ALLOCATOR
+#define SH_PREFIX pagetable
+#define SH_ELEMENT_TYPE PagetableEntry
+#define SH_KEY_TYPE BlockNumber
+#define SH_KEY blockno
+#define SH_HASH_KEY(tb, key) hash_blockno(key)
+#define SH_EQUAL(tb, a, b) a == b
+#define SH_SCOPE static inline
+#define SH_DEFINE
+#define SH_DECLARE
+#include "lib/simplehash.h"
/*
@@ -174,10 +273,12 @@ static int tbm_comparator(const void *left, const void *right);
*
* The bitmap will live in the memory context that is CurrentMemoryContext
* at the time of this call. It will be limited to (approximately) maxbytes
- * total memory consumption.
+ * total memory consumption. If the DSA passed to this function is not NULL
+ * then the memory for storing elements of the underlying page table will
+ * be allocated from the DSA.
*/
TIDBitmap *
-tbm_create(long maxbytes)
+tbm_create(long maxbytes, dsa_area *dsa)
{
TIDBitmap *tbm;
long nbuckets;
@@ -190,17 +291,21 @@ tbm_create(long maxbytes)
/*
* Estimate number of hashtable entries we can have within maxbytes. This
- * estimates the hash overhead at MAXALIGN(sizeof(HASHELEMENT)) plus a
- * pointer per hash entry, which is crude but good enough for our purpose.
- * Also count an extra Pointer per entry for the arrays created during
- * iteration readout.
+ * estimates the hash cost as sizeof(PagetableEntry), which is good enough
+ * for our purpose. Also count an extra Pointer per entry for the arrays
+ * created during iteration readout.
*/
nbuckets = maxbytes /
- (MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(sizeof(PagetableEntry))
- + sizeof(Pointer) + sizeof(Pointer));
+ (sizeof(PagetableEntry) + sizeof(Pointer) + sizeof(Pointer));
nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */
nbuckets = Max(nbuckets, 16); /* sanity limit */
tbm->maxentries = (int) nbuckets;
+ tbm->lossify_start = 0;
+ tbm->dsa = dsa;
+ tbm->dsapagetable = InvalidDsaPointer;
+ tbm->dsapagetableold = InvalidDsaPointer;
+ tbm->ptpages = InvalidDsaPointer;
+ tbm->ptchunks = InvalidDsaPointer;
return tbm;
}
@@ -212,32 +317,25 @@ tbm_create(long maxbytes)
static void
tbm_create_pagetable(TIDBitmap *tbm)
{
- HASHCTL hash_ctl;
-
Assert(tbm->status != TBM_HASH);
Assert(tbm->pagetable == NULL);
- /* Create the hashtable proper */
- MemSet(&hash_ctl, 0, sizeof(hash_ctl));
- hash_ctl.keysize = sizeof(BlockNumber);
- hash_ctl.entrysize = sizeof(PagetableEntry);
- hash_ctl.hcxt = tbm->mcxt;
- tbm->pagetable = hash_create("TIDBitmap",
- 128, /* start small and extend */
- &hash_ctl,
- HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+ tbm->pagetable = pagetable_create(tbm->mcxt, 128, tbm);
/* If entry1 is valid, push it into the hashtable */
if (tbm->status == TBM_ONE_PAGE)
{
PagetableEntry *page;
bool found;
+ char oldstatus;
- page = (PagetableEntry *) hash_search(tbm->pagetable,
- (void *) &tbm->entry1.blockno,
- HASH_ENTER, &found);
+ page = pagetable_insert(tbm->pagetable,
+ tbm->entry1.blockno,
+ &found);
Assert(!found);
+ oldstatus = page->status;
memcpy(page, &tbm->entry1, sizeof(PagetableEntry));
+ page->status = oldstatus;
}
tbm->status = TBM_HASH;
@@ -250,7 +348,7 @@ void
tbm_free(TIDBitmap *tbm)
{
if (tbm->pagetable)
- hash_destroy(tbm->pagetable);
+ pagetable_destroy(tbm->pagetable);
if (tbm->spages)
pfree(tbm->spages);
if (tbm->schunks)
@@ -259,6 +357,43 @@ tbm_free(TIDBitmap *tbm)
}
/*
+ * tbm_free_shared_area - free shared state
+ *
+ * Free shared iterator state, Also free shared pagetable and iterator arrays
+ * memory if they are not referred by any of the shared iterator i.e recount
+ * is becomes 0.
+ */
+void
+tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp)
+{
+ TBMSharedIteratorState *istate = dsa_get_address(dsa, dp);
+ PTEntryArray *ptbase;
+ PTIterationArray *ptpages;
+ PTIterationArray *ptchunks;
+
+ if (DsaPointerIsValid(istate->pagetable))
+ {
+ ptbase = dsa_get_address(dsa, istate->pagetable);
+ if (pg_atomic_sub_fetch_u32(&ptbase->refcount, 1) == 0)
+ dsa_free(dsa, istate->pagetable);
+ }
+ if (DsaPointerIsValid(istate->spages))
+ {
+ ptpages = dsa_get_address(dsa, istate->spages);
+ if (pg_atomic_sub_fetch_u32(&ptpages->refcount, 1) == 0)
+ dsa_free(dsa, istate->spages);
+ }
+ if (DsaPointerIsValid(istate->schunks))
+ {
+ ptchunks = dsa_get_address(dsa, istate->schunks);
+ if (pg_atomic_sub_fetch_u32(&ptchunks->refcount, 1) == 0)
+ dsa_free(dsa, istate->schunks);
+ }
+
+ dsa_free(dsa, dp);
+}
+
+/*
* tbm_add_tuples - add some tuple IDs to a TIDBitmap
*
* If recheck is true, then the recheck flag will be set in the
@@ -272,7 +407,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
PagetableEntry *page = NULL; /* only valid when currblk is valid */
int i;
- Assert(!tbm->iterating);
+ Assert(tbm->iterating == TBM_NOT_ITERATING);
for (i = 0; i < ntids; i++)
{
BlockNumber blk = ItemPointerGetBlockNumber(tids + i);
@@ -357,12 +492,12 @@ tbm_union(TIDBitmap *a, const TIDBitmap *b)
tbm_union_page(a, &b->entry1);
else
{
- HASH_SEQ_STATUS status;
+ pagetable_iterator i;
PagetableEntry *bpage;
Assert(b->status == TBM_HASH);
- hash_seq_init(&status, b->pagetable);
- while ((bpage = (PagetableEntry *) hash_seq_search(&status)) != NULL)
+ pagetable_start_iterate(b->pagetable, &i);
+ while ((bpage = pagetable_iterate(b->pagetable, &i)) != NULL)
tbm_union_page(a, bpage);
}
}
@@ -449,12 +584,12 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b)
}
else
{
- HASH_SEQ_STATUS status;
+ pagetable_iterator i;
PagetableEntry *apage;
Assert(a->status == TBM_HASH);
- hash_seq_init(&status, a->pagetable);
- while ((apage = (PagetableEntry *) hash_seq_search(&status)) != NULL)
+ pagetable_start_iterate(a->pagetable, &i);
+ while ((apage = pagetable_iterate(a->pagetable, &i)) != NULL)
{
if (tbm_intersect_page(a, apage, b))
{
@@ -464,9 +599,7 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b)
else
a->npages--;
a->nentries--;
- if (hash_search(a->pagetable,
- (void *) &apage->blockno,
- HASH_REMOVE, NULL) == NULL)
+ if (!pagetable_delete(a->pagetable, apage->blockno))
elog(ERROR, "hash table corrupted");
}
}
@@ -583,6 +716,8 @@ tbm_begin_iterate(TIDBitmap *tbm)
{
TBMIterator *iterator;
+ Assert(tbm->iterating != TBM_ITERATING_SHARED);
+
/*
* Create the TBMIterator struct, with enough trailing space to serve the
* needs of the TBMIterateResult sub-struct.
@@ -604,9 +739,9 @@ tbm_begin_iterate(TIDBitmap *tbm)
* attached to the bitmap not the iterator, so they can be used by more
* than one iterator.
*/
- if (tbm->status == TBM_HASH && !tbm->iterating)
+ if (tbm->status == TBM_HASH && tbm->iterating == TBM_NOT_ITERATING)
{
- HASH_SEQ_STATUS status;
+ pagetable_iterator i;
PagetableEntry *page;
int npages;
int nchunks;
@@ -620,9 +755,9 @@ tbm_begin_iterate(TIDBitmap *tbm)
MemoryContextAlloc(tbm->mcxt,
tbm->nchunks * sizeof(PagetableEntry *));
- hash_seq_init(&status, tbm->pagetable);
npages = nchunks = 0;
- while ((page = (PagetableEntry *) hash_seq_search(&status)) != NULL)
+ pagetable_start_iterate(tbm->pagetable, &i);
+ while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
{
if (page->ischunk)
tbm->schunks[nchunks++] = page;
@@ -639,12 +774,214 @@ tbm_begin_iterate(TIDBitmap *tbm)
tbm_comparator);
}
- tbm->iterating = true;
+ tbm->iterating = TBM_ITERATING_PRIVATE;
return iterator;
}
/*
+ * tbm_prepare_shared_iterate - prepare shared iteration state for a TIDBitmap.
+ *
+ * The necessary shared state will be allocated from the DSA passed to
+ * tbm_create, so that multiple processes can attach to it and iterate jointly.
+ *
+ * This will convert the pagetable hash into page and chunk array of the index
+ * into pagetable array.
+ */
+dsa_pointer
+tbm_prepare_shared_iterate(TIDBitmap *tbm)
+{
+ dsa_pointer dp;
+ TBMSharedIteratorState *istate;
+ PTEntryArray *ptbase = NULL;
+ PTIterationArray *ptpages = NULL;
+ PTIterationArray *ptchunks = NULL;
+
+ Assert(tbm->dsa != NULL);
+ Assert(tbm->iterating != TBM_ITERATING_PRIVATE);
+
+ /*
+ * Allocate TBMSharedIteratorState from DSA to hold the shared members and
+ * lock, this will also be used by multiple worker for shared iterate.
+ */
+ dp = dsa_allocate0(tbm->dsa, sizeof(TBMSharedIteratorState));
+ istate = dsa_get_address(tbm->dsa, dp);
+
+ /*
+ * If we're not already iterating, create and fill the sorted page lists.
+ * (If we are, the sorted page lists are already stored in the TIDBitmap,
+ * and we can just reuse them.)
+ */
+ if (tbm->iterating == TBM_NOT_ITERATING)
+ {
+ pagetable_iterator i;
+ PagetableEntry *page;
+ int idx;
+ int npages;
+ int nchunks;
+
+ /*
+ * Allocate the page and chunk array memory from the DSA to share
+ * across multiple processes.
+ */
+ if (tbm->npages)
+ {
+ tbm->ptpages = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) +
+ tbm->npages * sizeof(int));
+ ptpages = dsa_get_address(tbm->dsa, tbm->ptpages);
+ pg_atomic_init_u32(&ptpages->refcount, 0);
+ }
+ if (tbm->nchunks)
+ {
+ tbm->ptchunks = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) +
+ tbm->nchunks * sizeof(int));
+ ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
+ pg_atomic_init_u32(&ptchunks->refcount, 0);
+ }
+
+ /*
+ * If TBM status is TBM_HASH then iterate over the pagetable and
+ * convert it to page and chunk arrays. But if it's in the
+ * TBM_ONE_PAGE mode then directly allocate the space for one entry
+ * from the DSA.
+ */
+ npages = nchunks = 0;
+ if (tbm->status == TBM_HASH)
+ {
+ ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
+
+ pagetable_start_iterate(tbm->pagetable, &i);
+ while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
+ {
+ idx = page - ptbase->ptentry;
+ if (page->ischunk)
+ ptchunks->index[nchunks++] = idx;
+ else
+ ptpages->index[npages++] = idx;
+ }
+
+ Assert(npages == tbm->npages);
+ Assert(nchunks == tbm->nchunks);
+ }
+ else if (tbm->status == TBM_ONE_PAGE)
+ {
+ /*
+ * In one page mode allocate the space for one pagetable entry,
+ * initialize it, and directly store its index (i.e. 0) in the
+ * page array.
+ */
+ tbm->dsapagetable = dsa_allocate(tbm->dsa, sizeof(PTEntryArray) +
+ sizeof(PagetableEntry));
+ ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
+ memcpy(ptbase->ptentry, &tbm->entry1, sizeof(PagetableEntry));
+ ptpages->index[0] = 0;
+ }
+
+ if (ptbase != NULL)
+ pg_atomic_init_u32(&ptbase->refcount, 0);
+ if (npages > 1)
+ qsort_arg((void *) (ptpages->index), npages, sizeof(int),
+ tbm_shared_comparator, (void *) ptbase->ptentry);
+ if (nchunks > 1)
+ qsort_arg((void *) (ptchunks->index), nchunks, sizeof(int),
+ tbm_shared_comparator, (void *) ptbase->ptentry);
+ }
+
+ /*
+ * Store the TBM members in the shared state so that we can share them
+ * across multiple processes.
+ */
+ istate->nentries = tbm->nentries;
+ istate->maxentries = tbm->maxentries;
+ istate->npages = tbm->npages;
+ istate->nchunks = tbm->nchunks;
+ istate->pagetable = tbm->dsapagetable;
+ istate->spages = tbm->ptpages;
+ istate->schunks = tbm->ptchunks;
+
+ ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
+ ptpages = dsa_get_address(tbm->dsa, tbm->ptpages);
+ ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
+
+ /*
+ * For every shared iterator, referring to pagetable and iterator array,
+ * increase the refcount by 1 so that while freeing the shared iterator we
+ * don't free pagetable and iterator array until its refcount becomes 0.
+ */
+ if (ptbase != NULL)
+ pg_atomic_add_fetch_u32(&ptbase->refcount, 1);
+ if (ptpages != NULL)
+ pg_atomic_add_fetch_u32(&ptpages->refcount, 1);
+ if (ptchunks != NULL)
+ pg_atomic_add_fetch_u32(&ptchunks->refcount, 1);
+
+ /* Initialize the iterator lock */
+ LWLockInitialize(&istate->lock, LWTRANCHE_TBM);
+
+ /* Initialize the shared iterator state */
+ istate->schunkbit = 0;
+ istate->schunkptr = 0;
+ istate->spageptr = 0;
+
+ tbm->iterating = TBM_ITERATING_SHARED;
+
+ return dp;
+}
+
+/*
+ * tbm_extract_page_tuple - extract the tuple offsets from a page
+ *
+ * The extracted offsets are stored into TBMIterateResult.
+ */
+static inline int
+tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
+{
+ int wordnum;
+ int ntuples = 0;
+
+ for (wordnum = 0; wordnum < WORDS_PER_PAGE; wordnum++)
+ {
+ bitmapword w = page->words[wordnum];
+
+ if (w != 0)
+ {
+ int off = wordnum * BITS_PER_BITMAPWORD + 1;
+
+ while (w != 0)
+ {
+ if (w & 1)
+ output->offsets[ntuples++] = (OffsetNumber) off;
+ off++;
+ w >>= 1;
+ }
+ }
+ }
+
+ return ntuples;
+}
+
+/*
+ * tbm_advance_schunkbit - Advance the chunkbit
+ */
+static inline void
+tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
+{
+ int schunkbit = *schunkbitp;
+
+ while (schunkbit < PAGES_PER_CHUNK)
+ {
+ int wordnum = WORDNUM(schunkbit);
+ int bitnum = BITNUM(schunkbit);
+
+ if ((chunk->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
+ break;
+ schunkbit++;
+ }
+
+ *schunkbitp = schunkbit;
+}
+
+/*
* tbm_iterate - scan through next page of a TIDBitmap
*
* Returns a TBMIterateResult representing one page, or NULL if there are
@@ -662,7 +999,7 @@ tbm_iterate(TBMIterator *iterator)
TIDBitmap *tbm = iterator->tbm;
TBMIterateResult *output = &(iterator->output);
- Assert(tbm->iterating);
+ Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
/*
* If lossy chunk pages remain, make sure we've advanced schunkptr/
@@ -673,15 +1010,7 @@ tbm_iterate(TBMIterator *iterator)
PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
int schunkbit = iterator->schunkbit;
- while (schunkbit < PAGES_PER_CHUNK)
- {
- int wordnum = WORDNUM(schunkbit);
- int bitnum = BITNUM(schunkbit);
-
- if ((chunk->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
- break;
- schunkbit++;
- }
+ tbm_advance_schunkbit(chunk, &schunkbit);
if (schunkbit < PAGES_PER_CHUNK)
{
iterator->schunkbit = schunkbit;
@@ -718,7 +1047,6 @@ tbm_iterate(TBMIterator *iterator)
{
PagetableEntry *page;
int ntuples;
- int wordnum;
/* In ONE_PAGE state, we don't allocate an spages[] array */
if (tbm->status == TBM_ONE_PAGE)
@@ -727,31 +1055,108 @@ tbm_iterate(TBMIterator *iterator)
page = tbm->spages[iterator->spageptr];
/* scan bitmap to extract individual offset numbers */
- ntuples = 0;
- for (wordnum = 0; wordnum < WORDS_PER_PAGE; wordnum++)
+ ntuples = tbm_extract_page_tuple(page, output);
+ output->blockno = page->blockno;
+ output->ntuples = ntuples;
+ output->recheck = page->recheck;
+ iterator->spageptr++;
+ return output;
+ }
+
+ /* Nothing more in the bitmap */
+ return NULL;
+}
+
+/*
+ * tbm_shared_iterate - scan through next page of a TIDBitmap
+ *
+ * As above, but this will iterate using an iterator which is shared
+ * across multiple processes. We need to acquire the iterator LWLock,
+ * before accessing the shared members.
+ */
+TBMIterateResult *
+tbm_shared_iterate(TBMSharedIterator *iterator)
+{
+ TBMIterateResult *output = &iterator->output;
+ TBMSharedIteratorState *istate = iterator->state;
+ PagetableEntry *ptbase = NULL;
+ int *idxpages = NULL;
+ int *idxchunks = NULL;
+
+ if (iterator->ptbase != NULL)
+ ptbase = iterator->ptbase->ptentry;
+ if (iterator->ptpages != NULL)
+ idxpages = iterator->ptpages->index;
+ if (iterator->ptchunks != NULL)
+ idxchunks = iterator->ptchunks->index;
+
+ /* Acquire the LWLock before accessing the shared members */
+ LWLockAcquire(&istate->lock, LW_EXCLUSIVE);
+
+ /*
+ * If lossy chunk pages remain, make sure we've advanced schunkptr/
+ * schunkbit to the next set bit.
+ */
+ while (istate->schunkptr < istate->nchunks)
+ {
+ PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
+ int schunkbit = istate->schunkbit;
+
+ tbm_advance_schunkbit(chunk, &schunkbit);
+ if (schunkbit < PAGES_PER_CHUNK)
{
- bitmapword w = page->words[wordnum];
+ istate->schunkbit = schunkbit;
+ break;
+ }
+ /* advance to next chunk */
+ istate->schunkptr++;
+ istate->schunkbit = 0;
+ }
- if (w != 0)
- {
- int off = wordnum * BITS_PER_BITMAPWORD + 1;
+ /*
+ * If both chunk and per-page data remain, must output the numerically
+ * earlier page.
+ */
+ if (istate->schunkptr < istate->nchunks)
+ {
+ PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
+ BlockNumber chunk_blockno;
- while (w != 0)
- {
- if (w & 1)
- output->offsets[ntuples++] = (OffsetNumber) off;
- off++;
- w >>= 1;
- }
- }
+ chunk_blockno = chunk->blockno + istate->schunkbit;
+
+ if (istate->spageptr >= istate->npages ||
+ chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
+ {
+ /* Return a lossy page indicator from the chunk */
+ output->blockno = chunk_blockno;
+ output->ntuples = -1;
+ output->recheck = true;
+ istate->schunkbit++;
+
+ LWLockRelease(&istate->lock);
+ return output;
}
+ }
+
+ if (istate->spageptr < istate->npages)
+ {
+ PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
+ int ntuples;
+
+ /* scan bitmap to extract individual offset numbers */
+ ntuples = tbm_extract_page_tuple(page, output);
output->blockno = page->blockno;
output->ntuples = ntuples;
output->recheck = page->recheck;
- iterator->spageptr++;
+ istate->spageptr++;
+
+ LWLockRelease(&istate->lock);
+
return output;
}
+ LWLockRelease(&istate->lock);
+
/* Nothing more in the bitmap */
return NULL;
}
@@ -770,6 +1175,18 @@ tbm_end_iterate(TBMIterator *iterator)
}
/*
+ * tbm_end_shared_iterate - finish a shared iteration over a TIDBitmap
+ *
+ * This doesn't free any of the shared state associated with the iterator,
+ * just our backend-private state.
+ */
+void
+tbm_end_shared_iterate(TBMSharedIterator *iterator)
+{
+ pfree(iterator);
+}
+
+/*
* tbm_find_pageentry - find a PagetableEntry for the pageno
*
* Returns NULL if there is no non-lossy entry for the pageno.
@@ -791,9 +1208,7 @@ tbm_find_pageentry(const TIDBitmap *tbm, BlockNumber pageno)
return page;
}
- page = (PagetableEntry *) hash_search(tbm->pagetable,
- (void *) &pageno,
- HASH_FIND, NULL);
+ page = pagetable_lookup(tbm->pagetable, pageno);
if (page == NULL)
return NULL;
if (page->ischunk)
@@ -834,15 +1249,16 @@ tbm_get_pageentry(TIDBitmap *tbm, BlockNumber pageno)
}
/* Look up or create an entry */
- page = (PagetableEntry *) hash_search(tbm->pagetable,
- (void *) &pageno,
- HASH_ENTER, &found);
+ page = pagetable_insert(tbm->pagetable, pageno, &found);
}
/* Initialize it if not present before */
if (!found)
{
+ char oldstatus = page->status;
+
MemSet(page, 0, sizeof(PagetableEntry));
+ page->status = oldstatus;
page->blockno = pageno;
/* must count it too */
tbm->nentries++;
@@ -869,9 +1285,9 @@ tbm_page_is_lossy(const TIDBitmap *tbm, BlockNumber pageno)
bitno = pageno % PAGES_PER_CHUNK;
chunk_pageno = pageno - bitno;
- page = (PagetableEntry *) hash_search(tbm->pagetable,
- (void *) &chunk_pageno,
- HASH_FIND, NULL);
+
+ page = pagetable_lookup(tbm->pagetable, chunk_pageno);
+
if (page != NULL && page->ischunk)
{
int wordnum = WORDNUM(bitno);
@@ -912,9 +1328,7 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno)
*/
if (bitno != 0)
{
- if (hash_search(tbm->pagetable,
- (void *) &pageno,
- HASH_REMOVE, NULL) != NULL)
+ if (pagetable_delete(tbm->pagetable, pageno))
{
/* It was present, so adjust counts */
tbm->nentries--;
@@ -923,14 +1337,15 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno)
}
/* Look up or create entry for chunk-header page */
- page = (PagetableEntry *) hash_search(tbm->pagetable,
- (void *) &chunk_pageno,
- HASH_ENTER, &found);
+ page = pagetable_insert(tbm->pagetable, chunk_pageno, &found);
/* Initialize it if not present before */
if (!found)
{
+ char oldstatus = page->status;
+
MemSet(page, 0, sizeof(PagetableEntry));
+ page->status = oldstatus;
page->blockno = chunk_pageno;
page->ischunk = true;
/* must count it too */
@@ -939,8 +1354,11 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno)
}
else if (!page->ischunk)
{
+ char oldstatus = page->status;
+
/* chunk header page was formerly non-lossy, make it lossy */
MemSet(page, 0, sizeof(PagetableEntry));
+ page->status = oldstatus;
page->blockno = chunk_pageno;
page->ischunk = true;
/* we assume it had some tuple bit(s) set, so mark it lossy */
@@ -962,7 +1380,7 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno)
static void
tbm_lossify(TIDBitmap *tbm)
{
- HASH_SEQ_STATUS status;
+ pagetable_iterator i;
PagetableEntry *page;
/*
@@ -974,11 +1392,11 @@ tbm_lossify(TIDBitmap *tbm)
* push nentries down to significantly less than maxentries, or else we'll
* just end up doing this again very soon. We shoot for maxentries/2.
*/
- Assert(!tbm->iterating);
+ Assert(tbm->iterating == TBM_NOT_ITERATING);
Assert(tbm->status == TBM_HASH);
- hash_seq_init(&status, tbm->pagetable);
- while ((page = (PagetableEntry *) hash_seq_search(&status)) != NULL)
+ pagetable_start_iterate_at(tbm->pagetable, &i, tbm->lossify_start);
+ while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
{
if (page->ischunk)
continue; /* already a chunk header */
@@ -995,15 +1413,19 @@ tbm_lossify(TIDBitmap *tbm)
if (tbm->nentries <= tbm->maxentries / 2)
{
- /* we have done enough */
- hash_seq_term(&status);
+ /*
+ * We have made enough room. Remember where to start lossifying
+ * next round, so we evenly iterate over the hashtable.
+ */
+ tbm->lossify_start = i.cur;
break;
}
/*
* Note: tbm_mark_page_lossy may have inserted a lossy chunk into the
- * hashtable. We can continue the same seq_search scan since we do
- * not care whether we visit lossy chunks or not.
+ * hashtable and may have deleted the non-lossy chunk. We can
+ * continue the same hash table scan, since failure to visit one
+ * element or visiting the newly inserted element, isn't fatal.
*/
}
@@ -1036,3 +1458,107 @@ tbm_comparator(const void *left, const void *right)
return 1;
return 0;
}
+
+/*
+ * As above, but this will get index into PagetableEntry array. Therefore,
+ * it needs to get actual PagetableEntry using the index before comparing the
+ * blockno.
+ */
+static int
+tbm_shared_comparator(const void *left, const void *right, void *arg)
+{
+ PagetableEntry *base = (PagetableEntry *) arg;
+ PagetableEntry *lpage = &base[*(int *) left];
+ PagetableEntry *rpage = &base[*(int *) right];
+
+ if (lpage->blockno < rpage->blockno)
+ return -1;
+ else if (lpage->blockno > rpage->blockno)
+ return 1;
+ return 0;
+}
+
+/*
+ * tbm_attach_shared_iterate
+ *
+ * Allocate a backend-private iterator and attach the shared iterator state
+ * to it so that multiple processed can iterate jointly.
+ *
+ * We also converts the DSA pointers to local pointers and store them into
+ * our private iterator.
+ */
+TBMSharedIterator *
+tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
+{
+ TBMSharedIterator *iterator;
+ TBMSharedIteratorState *istate;
+
+ /*
+ * Create the TBMSharedIterator struct, with enough trailing space to
+ * serve the needs of the TBMIterateResult sub-struct.
+ */
+ iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
+ MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+
+ istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
+
+ iterator->state = istate;
+
+ iterator->ptbase = dsa_get_address(dsa, istate->pagetable);
+
+ if (istate->npages)
+ iterator->ptpages = dsa_get_address(dsa, istate->spages);
+ if (istate->nchunks)
+ iterator->ptchunks = dsa_get_address(dsa, istate->schunks);
+
+ return iterator;
+}
+
+/*
+ * pagetable_allocate
+ *
+ * Callback function for allocating the memory for hashtable elements.
+ * Allocate memory for hashtable elements, using DSA if available.
+ */
+static inline void *
+pagetable_allocate(pagetable_hash *pagetable, Size size)
+{
+ TIDBitmap *tbm = (TIDBitmap *) pagetable->private_data;
+ PTEntryArray *ptbase;
+
+ if (tbm->dsa == NULL)
+ return MemoryContextAllocExtended(pagetable->ctx, size,
+ MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+
+ /*
+ * Save the dsapagetable reference in dsapagetableold before allocating
+ * new memory so that pagetable_free can free the old entry.
+ */
+ tbm->dsapagetableold = tbm->dsapagetable;
+ tbm->dsapagetable = dsa_allocate_extended(tbm->dsa,
+ sizeof(PTEntryArray) + size,
+ DSA_ALLOC_HUGE | DSA_ALLOC_ZERO);
+ ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
+
+ return ptbase->ptentry;
+}
+
+/*
+ * pagetable_free
+ *
+ * Callback function for freeing hash table elements.
+ */
+static inline void
+pagetable_free(pagetable_hash *pagetable, void *pointer)
+{
+ TIDBitmap *tbm = (TIDBitmap *) pagetable->private_data;
+
+ /* pfree the input pointer if DSA is not available */
+ if (tbm->dsa == NULL)
+ pfree(pointer);
+ else if (DsaPointerIsValid(tbm->dsapagetableold))
+ {
+ dsa_free(tbm->dsa, tbm->dsapagetableold);
+ tbm->dsapagetableold = InvalidDsaPointer;
+ }
+}
diff --git a/src/backend/nodes/value.c b/src/backend/nodes/value.c
index a5ed5bc7c2..5d2f96c103 100644
--- a/src/backend/nodes/value.c
+++ b/src/backend/nodes/value.c
@@ -4,7 +4,7 @@
* implementation of Value nodes
*
*
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
+ * Copyright (c) 2003-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
diff --git a/src/backend/optimizer/README b/src/backend/optimizer/README
index 775bcc3b73..fc0fca4107 100644
--- a/src/backend/optimizer/README
+++ b/src/backend/optimizer/README
@@ -375,6 +375,7 @@ RelOptInfo - a relation or joined relations
UniquePath - remove duplicate rows (either by hashing or sorting)
GatherPath - collect the results of parallel workers
ProjectionPath - a Result plan node with child (used for projection)
+ ProjectSetPath - a ProjectSet plan node applied to some sub-path
SortPath - a Sort plan node applied to some sub-path
GroupPath - a Group plan node applied to some sub-path
UpperUniquePath - a Unique plan node applied to some sub-path
@@ -756,9 +757,8 @@ to create a plan like
-> Seq Scan on SmallTable1 A
NestLoop
-> Seq Scan on SmallTable2 B
- NestLoop
- -> Index Scan using XYIndex on LargeTable C
- Index Condition: C.X = A.AID and C.Y = B.BID
+ -> Index Scan using XYIndex on LargeTable C
+ Index Condition: C.X = A.AID and C.Y = B.BID
so we should be willing to pass down A.AID through a join even though
there is no join order constraint forcing the plan to look like this.
@@ -877,6 +877,108 @@ lateral reference. (Perhaps now that that stuff works, we could relax the
pullup restriction?)
+Security-level constraints on qual clauses
+------------------------------------------
+
+To support row-level security and security-barrier views efficiently,
+we mark qual clauses (RestrictInfo nodes) with a "security_level" field.
+The basic concept is that a qual with a lower security_level must be
+evaluated before one with a higher security_level. This ensures that
+"leaky" quals that might expose sensitive data are not evaluated until
+after the security barrier quals that are supposed to filter out
+security-sensitive rows. However, many qual conditions are "leakproof",
+that is we trust the functions they use to not expose data. To avoid
+unnecessarily inefficient plans, a leakproof qual is not delayed by
+security-level considerations, even if it has a higher syntactic
+security_level than another qual.
+
+In a query that contains no use of RLS or security-barrier views, all
+quals will have security_level zero, so that none of these restrictions
+kick in; we don't even need to check leakproofness of qual conditions.
+
+If there are security-barrier quals, they get security_level zero (and
+possibly higher, if there are multiple layers of barriers). Regular quals
+coming from the query text get a security_level one more than the highest
+level used for barrier quals.
+
+When new qual clauses are generated by EquivalenceClass processing,
+they must be assigned a security_level. This is trickier than it seems.
+One's first instinct is that it would be safe to use the largest level
+found among the source quals for the EquivalenceClass, but that isn't
+safe at all, because it allows unwanted delays of security-barrier quals.
+Consider a barrier qual "t.x = t.y" plus a query qual "t.x = constant",
+and suppose there is another query qual "leaky_function(t.z)" that
+we mustn't evaluate before the barrier qual has been checked.
+We will have an EC {t.x, t.y, constant} which will lead us to replace
+the EC quals with "t.x = constant AND t.y = constant". (We do not want
+to give up that behavior, either, since the latter condition could allow
+use of an index on t.y, which we would never discover from the original
+quals.) If these generated quals are assigned the same security_level as
+the query quals, then it's possible for the leaky_function qual to be
+evaluated first, allowing leaky_function to see data from rows that
+possibly don't pass the barrier condition.
+
+Instead, our handling of security levels with ECs works like this:
+* Quals are not accepted as source clauses for ECs in the first place
+unless they are leakproof or have security_level zero.
+* EC-derived quals are assigned the minimum (not maximum) security_level
+found among the EC's source clauses.
+* If the maximum security_level found among the EC's source clauses is
+above zero, then the equality operators selected for derived quals must
+be leakproof. When no such operator can be found, the EC is treated as
+"broken" and we fall back to emitting its source clauses without any
+additional derived quals.
+
+These rules together ensure that an untrusted qual clause (one with
+security_level above zero) cannot cause an EC to generate a leaky derived
+clause. This makes it safe to use the minimum not maximum security_level
+for derived clauses. The rules could result in poor plans due to not
+being able to generate derived clauses at all, but the risk of that is
+small in practice because most btree equality operators are leakproof.
+Also, by making exceptions for level-zero quals, we ensure that there is
+no plan degradation when no barrier quals are present.
+
+Once we have security levels assigned to all clauses, enforcement
+of barrier-qual ordering restrictions boils down to two rules:
+
+* Table scan plan nodes must not select quals for early execution
+(for example, use them as index qualifiers in an indexscan) unless
+they are leakproof or have security_level no higher than any other
+qual that is due to be executed at the same plan node. (Use the
+utility function restriction_is_securely_promotable() to check
+whether it's okay to select a qual for early execution.)
+
+* Normal execution of a list of quals must execute them in an order
+that satisfies the same security rule, ie higher security_levels must
+be evaluated later unless leakproof. (This is handled in a single place
+by order_qual_clauses() in createplan.c.)
+
+order_qual_clauses() uses a heuristic to decide exactly what to do with
+leakproof clauses. Normally it sorts clauses by security_level then cost,
+being careful that the sort is stable so that we don't reorder clauses
+without a clear reason. But this could result in a very expensive qual
+being done before a cheaper one that is of higher security_level.
+If the cheaper qual is leaky we have no choice, but if it is leakproof
+we could put it first. We choose to sort leakproof quals as if they
+have security_level zero, but only when their cost is less than 10X
+cpu_operator_cost; that restriction alleviates the opposite problem of
+doing expensive quals first just because they're leakproof.
+
+Additional rules will be needed to support safe handling of join quals
+when there is a mix of security levels among join quals; for example, it
+will be necessary to prevent leaky higher-security-level quals from being
+evaluated at a lower join level than other quals of lower security level.
+Currently there is no need to consider that since security-prioritized
+quals can only be single-table restriction quals coming from RLS policies
+or security-barrier views, and security-barrier view subqueries are never
+flattened into the parent query. Hence enforcement of security-prioritized
+quals only happens at the table scan level. With extra rules for safe
+handling of security levels among join quals, it should be possible to let
+security-barrier views be flattened into the parent query, allowing more
+flexibility of planning while still preserving required ordering of qual
+evaluation. But that will come later.
+
+
Post scan/join planning
-----------------------
diff --git a/src/backend/optimizer/geqo/geqo_copy.c b/src/backend/optimizer/geqo/geqo_copy.c
index 475d221dd2..8fd20c5986 100644
--- a/src/backend/optimizer/geqo/geqo_copy.c
+++ b/src/backend/optimizer/geqo/geqo_copy.c
@@ -2,7 +2,7 @@
*
* geqo_copy.c
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_copy.c
diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c
index 1a43ab7288..133fe32348 100644
--- a/src/backend/optimizer/geqo/geqo_erx.c
+++ b/src/backend/optimizer/geqo/geqo_erx.c
@@ -111,7 +111,7 @@ gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2,
for (index1 = 0; index1 < num_gene; index1++)
{
/*
- * presume the tour is circular, i.e. 1->2, 2->3, 3->1 this operaton
+ * presume the tour is circular, i.e. 1->2, 2->3, 3->1 this operation
* maps n back to 1
*/
@@ -314,7 +314,7 @@ gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table)
/*
* give priority to candidates with fewest remaining unused edges;
* find out what the minimum number of unused edges is
- * (minimum_edges); if there is more than one cadidate with the
+ * (minimum_edges); if there is more than one candidate with the
* minimum number of unused edges keep count of this number
* (minimum_count);
*/
@@ -458,7 +458,7 @@ edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num
if (edge_table[i].unused_edges >= 0)
return (Gene) i;
- elog(LOG, "no edge found via looking for the last ununsed point");
+ elog(LOG, "no edge found via looking for the last unused point");
}
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 88acebc1f2..b5cab0c351 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -3,7 +3,7 @@
* geqo_eval.c
* Routines to evaluate query trees
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_eval.c
@@ -74,9 +74,7 @@ geqo_eval(PlannerInfo *root, Gene *tour, int num_gene)
*/
mycontext = AllocSetContextCreate(CurrentMemoryContext,
"GEQO",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(mycontext);
/*
diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c
index 73fc38b907..52bd428187 100644
--- a/src/backend/optimizer/geqo/geqo_main.c
+++ b/src/backend/optimizer/geqo/geqo_main.c
@@ -4,7 +4,7 @@
* solution to the query optimization problem
* by means of a Genetic Algorithm (GA)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_main.c
diff --git a/src/backend/optimizer/geqo/geqo_misc.c b/src/backend/optimizer/geqo/geqo_misc.c
index b1d99cc0b1..503a19f6d6 100644
--- a/src/backend/optimizer/geqo/geqo_misc.c
+++ b/src/backend/optimizer/geqo/geqo_misc.c
@@ -3,7 +3,7 @@
* geqo_misc.c
* misc. printout and debug stuff
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_misc.c
diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c
index 727c356032..0f7a26c9a1 100644
--- a/src/backend/optimizer/geqo/geqo_pool.c
+++ b/src/backend/optimizer/geqo/geqo_pool.c
@@ -3,7 +3,7 @@
* geqo_pool.c
* Genetic Algorithm (GA) pool stuff
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_pool.c
diff --git a/src/backend/optimizer/geqo/geqo_random.c b/src/backend/optimizer/geqo/geqo_random.c
index 2368b8fa96..6f3500649c 100644
--- a/src/backend/optimizer/geqo/geqo_random.c
+++ b/src/backend/optimizer/geqo/geqo_random.c
@@ -3,7 +3,7 @@
* geqo_random.c
* random number generator
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_random.c
diff --git a/src/backend/optimizer/geqo/geqo_selection.c b/src/backend/optimizer/geqo/geqo_selection.c
index 991b2e36f9..4d0f6b0881 100644
--- a/src/backend/optimizer/geqo/geqo_selection.c
+++ b/src/backend/optimizer/geqo/geqo_selection.c
@@ -3,7 +3,7 @@
* geqo_selection.c
* linear selection scheme for the genetic query optimizer
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/optimizer/geqo/geqo_selection.c
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 34bc42b196..196c6194cb 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -4,7 +4,7 @@
* Routines to find possible search paths for processing a query
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -63,7 +63,8 @@ typedef struct pushdown_safety_info
/* These parameters are set by GUC */
bool enable_geqo = false; /* just in case GUC doesn't set it */
int geqo_threshold;
-int min_parallel_relation_size;
+int min_parallel_table_scan_size;
+int min_parallel_index_scan_size;
/* Hook for plugins to get control in set_rel_pathlist() */
set_rel_pathlist_hook_type set_rel_pathlist_hook = NULL;
@@ -84,7 +85,6 @@ static void set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel,
static void create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel);
static void set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
-static bool function_rte_parallel_ok(RangeTblEntry *rte);
static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
static void set_tablesample_rel_size(PlannerInfo *root, RelOptInfo *rel,
@@ -101,7 +101,8 @@ static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
Index rti, RangeTblEntry *rte);
static void generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
List *live_childrels,
- List *all_child_pathkeys);
+ List *all_child_pathkeys,
+ List *partitioned_rels);
static Path *get_cheapest_parameterized_child_path(PlannerInfo *root,
RelOptInfo *rel,
Relids required_outer);
@@ -112,8 +113,12 @@ static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
+static void set_tablefunc_pathlist(PlannerInfo *root, RelOptInfo *rel,
+ RangeTblEntry *rte);
static void set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
+static void set_namedtuplestore_pathlist(PlannerInfo *root, RelOptInfo *rel,
+ RangeTblEntry *rte);
static void set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
@@ -133,6 +138,8 @@ static void subquery_push_qual(Query *subquery,
static void recurse_push_qual(Node *setOp, Query *topquery,
RangeTblEntry *rte, Index rti, Node *qual);
static void remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel);
+static void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
+ List *live_childrels);
/*
@@ -348,6 +355,14 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel,
/* Foreign table */
set_foreign_size(root, rel, rte);
}
+ else if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ /*
+ * A partitioned table without leaf partitions is marked
+ * as a dummy rel.
+ */
+ set_dummy_rel_pathlist(rel);
+ }
else if (rte->tablesample != NULL)
{
/* Sampled relation */
@@ -371,6 +386,9 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel,
case RTE_FUNCTION:
set_function_size_estimates(root, rel);
break;
+ case RTE_TABLEFUNC:
+ set_tablefunc_size_estimates(root, rel);
+ break;
case RTE_VALUES:
set_values_size_estimates(root, rel);
break;
@@ -386,6 +404,9 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel,
else
set_cte_pathlist(root, rel, rte);
break;
+ case RTE_NAMEDTUPLESTORE:
+ set_namedtuplestore_pathlist(root, rel, rte);
+ break;
default:
elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);
break;
@@ -443,6 +464,10 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
/* RangeFunction */
set_function_pathlist(root, rel, rte);
break;
+ case RTE_TABLEFUNC:
+ /* Table Function */
+ set_tablefunc_pathlist(root, rel, rte);
+ break;
case RTE_VALUES:
/* Values list */
set_values_pathlist(root, rel, rte);
@@ -450,6 +475,9 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
case RTE_CTE:
/* CTE reference --- fully handled during set_rel_size */
break;
+ case RTE_NAMEDTUPLESTORE:
+ /* tuplestore reference --- fully handled during set_rel_size */
+ break;
default:
elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);
break;
@@ -518,8 +546,7 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
Assert(root->glob->parallelModeOK);
/* This should only be called for baserels and appendrel children. */
- Assert(rel->reloptkind == RELOPT_BASEREL ||
- rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
+ Assert(IS_SIMPLE_REL(rel));
/* Assorted checks based on rtekind. */
switch (rte->rtekind)
@@ -545,12 +572,11 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
*/
if (rte->tablesample != NULL)
{
- Oid proparallel = func_parallel(rte->tablesample->tsmhandler);
+ char proparallel = func_parallel(rte->tablesample->tsmhandler);
if (proparallel != PROPARALLEL_SAFE)
return;
- if (has_parallel_hazard((Node *) rte->tablesample->args,
- false))
+ if (!is_parallel_safe(root, (Node *) rte->tablesample->args))
return;
}
@@ -603,16 +629,18 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
case RTE_FUNCTION:
/* Check for parallel-restricted functions. */
- if (!function_rte_parallel_ok(rte))
+ if (!is_parallel_safe(root, (Node *) rte->functions))
return;
break;
- case RTE_VALUES:
+ case RTE_TABLEFUNC:
+ /* not parallel safe */
+ return;
- /*
- * The data for a VALUES clause is stored in the plan tree itself,
- * so scanning it in a worker is fine.
- */
+ case RTE_VALUES:
+ /* Check for parallel-restricted functions. */
+ if (!is_parallel_safe(root, (Node *) rte->values_lists))
+ return;
break;
case RTE_CTE:
@@ -625,6 +653,17 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
* executed only once.
*/
return;
+
+ case RTE_NAMEDTUPLESTORE:
+
+ /*
+ * tuplestore cannot be shared, at least without more
+ * infrastructure to support that.
+ */
+ return;
+
+ case RTE_REMOTE_DUMMY:
+ return;
}
/*
@@ -636,14 +675,14 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
* outer join clauses work correctly. It would likely break equivalence
* classes, too.
*/
- if (has_parallel_hazard((Node *) rel->baserestrictinfo, false))
+ if (!is_parallel_safe(root, (Node *) rel->baserestrictinfo))
return;
/*
* Likewise, if the relation's outputs are not parallel-safe, give up.
* (Usually, they're just Vars, but sometimes they're not.)
*/
- if (has_parallel_hazard((Node *) rel->reltarget->exprs, false))
+ if (!is_parallel_safe(root, (Node *) rel->reltarget->exprs))
return;
/* We have a winner. */
@@ -651,26 +690,6 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
}
/*
- * Check whether a function RTE is scanning something parallel-restricted.
- */
-static bool
-function_rte_parallel_ok(RangeTblEntry *rte)
-{
- ListCell *lc;
-
- foreach(lc, rte->functions)
- {
- RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
-
- Assert(IsA(rtfunc, RangeTblFunction));
- if (has_parallel_hazard(rtfunc->funcexpr, false))
- return false;
- }
-
- return true;
-}
-
-/*
* set_plain_rel_pathlist
* Build access paths for a plain relation (no subquery, no inheritance)
*/
@@ -709,49 +728,7 @@ create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel)
{
int parallel_workers;
- /*
- * If the user has set the parallel_workers reloption, use that; otherwise
- * select a default number of workers.
- */
- if (rel->rel_parallel_workers != -1)
- parallel_workers = rel->rel_parallel_workers;
- else
- {
- int parallel_threshold;
-
- /*
- * If this relation is too small to be worth a parallel scan, just
- * return without doing anything ... unless it's an inheritance child.
- * In that case, we want to generate a parallel path here anyway. It
- * might not be worthwhile just for this relation, but when combined
- * with all of its inheritance siblings it may well pay off.
- */
- if (rel->pages < (BlockNumber) min_parallel_relation_size &&
- rel->reloptkind == RELOPT_BASEREL)
- return;
-
- /*
- * Select the number of workers based on the log of the size of the
- * relation. This probably needs to be a good deal more
- * sophisticated, but we need something here for now. Note that the
- * upper limit of the min_parallel_relation_size GUC is chosen to
- * prevent overflow here.
- */
- parallel_workers = 1;
- parallel_threshold = Max(min_parallel_relation_size, 1);
- while (rel->pages >= (BlockNumber) (parallel_threshold * 3))
- {
- parallel_workers++;
- parallel_threshold *= 3;
- if (parallel_threshold > INT_MAX / 3)
- break; /* avoid overflow */
- }
- }
-
- /*
- * In no case use more than max_parallel_workers_per_gather workers.
- */
- parallel_workers = Min(parallel_workers, max_parallel_workers_per_gather);
+ parallel_workers = compute_parallel_worker(rel, rel->pages, -1);
/* If any limit was set to zero, the user doesn't want a parallel scan. */
if (parallel_workers <= 0)
@@ -879,7 +856,7 @@ set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* set_append_rel_size
- * Set size estimates for an "append relation"
+ * Set size estimates for a simple "append relation"
*
* The passed-in rel and RTE represent the entire append relation. The
* relation's contents are computed by appending together the output of
@@ -900,6 +877,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
int nattrs;
ListCell *l;
+ Assert(IS_SIMPLE_REL(rel));
+
/*
* Initialize to compute size estimates for whole append relation.
*
@@ -927,9 +906,11 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *childRTE;
RelOptInfo *childrel;
List *childquals;
- Node *childqual;
+ Index cq_min_security;
+ bool have_const_false_cq;
ListCell *parentvars;
ListCell *childvars;
+ ListCell *lc;
/* append_rel_list contains all append rels; ignore others */
if (appinfo->parent_relid != parentRTindex)
@@ -952,34 +933,120 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
* constraint exclusion; so do that first and then check to see if we
* can disregard this child.
*
- * As of 8.4, the child rel's targetlist might contain non-Var
- * expressions, which means that substitution into the quals could
- * produce opportunities for const-simplification, and perhaps even
- * pseudoconstant quals. To deal with this, we strip the RestrictInfo
- * nodes, do the substitution, do const-simplification, and then
- * reconstitute the RestrictInfo layer.
+ * The child rel's targetlist might contain non-Var expressions, which
+ * means that substitution into the quals could produce opportunities
+ * for const-simplification, and perhaps even pseudoconstant quals.
+ * Therefore, transform each RestrictInfo separately to see if it
+ * reduces to a constant or pseudoconstant. (We must process them
+ * separately to keep track of the security level of each qual.)
+ */
+ childquals = NIL;
+ cq_min_security = UINT_MAX;
+ have_const_false_cq = false;
+ foreach(lc, rel->baserestrictinfo)
+ {
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ Node *childqual;
+ ListCell *lc2;
+
+ Assert(IsA(rinfo, RestrictInfo));
+ childqual = adjust_appendrel_attrs(root,
+ (Node *) rinfo->clause,
+ appinfo);
+ childqual = eval_const_expressions(root, childqual);
+ /* check for flat-out constant */
+ if (childqual && IsA(childqual, Const))
+ {
+ if (((Const *) childqual)->constisnull ||
+ !DatumGetBool(((Const *) childqual)->constvalue))
+ {
+ /* Restriction reduces to constant FALSE or NULL */
+ have_const_false_cq = true;
+ break;
+ }
+ /* Restriction reduces to constant TRUE, so drop it */
+ continue;
+ }
+ /* might have gotten an AND clause, if so flatten it */
+ foreach(lc2, make_ands_implicit((Expr *) childqual))
+ {
+ Node *onecq = (Node *) lfirst(lc2);
+ bool pseudoconstant;
+
+ /* check for pseudoconstant (no Vars or volatile functions) */
+ pseudoconstant =
+ !contain_vars_of_level(onecq, 0) &&
+ !contain_volatile_functions(onecq);
+ if (pseudoconstant)
+ {
+ /* tell createplan.c to check for gating quals */
+ root->hasPseudoConstantQuals = true;
+ }
+ /* reconstitute RestrictInfo with appropriate properties */
+ childquals = lappend(childquals,
+ make_restrictinfo((Expr *) onecq,
+ rinfo->is_pushed_down,
+ rinfo->outerjoin_delayed,
+ pseudoconstant,
+ rinfo->security_level,
+ NULL, NULL, NULL));
+ /* track minimum security level among child quals */
+ cq_min_security = Min(cq_min_security, rinfo->security_level);
+ }
+ }
+
+ /*
+ * In addition to the quals inherited from the parent, we might have
+ * securityQuals associated with this particular child node.
+ * (Currently this can only happen in appendrels originating from
+ * UNION ALL; inheritance child tables don't have their own
+ * securityQuals, see expand_inherited_rtentry().) Pull any such
+ * securityQuals up into the baserestrictinfo for the child. This is
+ * similar to process_security_barrier_quals() for the parent rel,
+ * except that we can't make any general deductions from such quals,
+ * since they don't hold for the whole appendrel.
*/
- childquals = get_all_actual_clauses(rel->baserestrictinfo);
- childquals = (List *) adjust_appendrel_attrs(root,
- (Node *) childquals,
- appinfo);
- childqual = eval_const_expressions(root, (Node *)
- make_ands_explicit(childquals));
- if (childqual && IsA(childqual, Const) &&
- (((Const *) childqual)->constisnull ||
- !DatumGetBool(((Const *) childqual)->constvalue)))
+ if (childRTE->securityQuals)
+ {
+ Index security_level = 0;
+
+ foreach(lc, childRTE->securityQuals)
+ {
+ List *qualset = (List *) lfirst(lc);
+ ListCell *lc2;
+
+ foreach(lc2, qualset)
+ {
+ Expr *qual = (Expr *) lfirst(lc2);
+
+ /* not likely that we'd see constants here, so no check */
+ childquals = lappend(childquals,
+ make_restrictinfo(qual,
+ true, false, false,
+ security_level,
+ NULL, NULL, NULL));
+ cq_min_security = Min(cq_min_security, security_level);
+ }
+ security_level++;
+ }
+ Assert(security_level <= root->qual_security_level);
+ }
+
+ /*
+ * OK, we've got all the baserestrictinfo quals for this child.
+ */
+ childrel->baserestrictinfo = childquals;
+ childrel->baserestrict_min_security = cq_min_security;
+
+ if (have_const_false_cq)
{
/*
- * Restriction reduces to constant FALSE or constant NULL after
+ * Some restriction clause reduced to constant FALSE or NULL after
* substitution, so this child need not be scanned.
*/
set_dummy_rel_pathlist(childrel);
continue;
}
- childquals = make_ands_implicit((Expr *) childqual);
- childquals = make_restrictinfos_from_actual_clauses(root,
- childquals);
- childrel->baserestrictinfo = childquals;
if (relation_excluded_by_constraints(root, childrel, childRTE))
{
@@ -1153,19 +1220,11 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
{
int parentRTindex = rti;
List *live_childrels = NIL;
- List *subpaths = NIL;
- bool subpaths_valid = true;
- List *partial_subpaths = NIL;
- bool partial_subpaths_valid = true;
- List *all_child_pathkeys = NIL;
- List *all_child_outers = NIL;
ListCell *l;
/*
* Generate access paths for each member relation, and remember the
- * cheapest path for each one. Also, identify all pathkeys (orderings)
- * and parameterizations (required_outer sets) available for the member
- * relations.
+ * non-dummy children.
*/
foreach(l, root->append_rel_list)
{
@@ -1173,7 +1232,6 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
int childRTindex;
RangeTblEntry *childRTE;
RelOptInfo *childrel;
- ListCell *lcp;
/* append_rel_list contains all append rels; ignore others */
if (appinfo->parent_relid != parentRTindex)
@@ -1208,6 +1266,55 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
* Child is live, so add it to the live_childrels list for use below.
*/
live_childrels = lappend(live_childrels, childrel);
+ }
+
+ /* Add paths to the "append" relation. */
+ add_paths_to_append_rel(root, rel, live_childrels);
+}
+
+
+/*
+ * add_paths_to_append_rel
+ * Generate paths for given "append" relation given the set of non-dummy
+ * child rels.
+ *
+ * The function collects all parameterizations and orderings supported by the
+ * non-dummy children. For every such parameterization or ordering, it creates
+ * an append path collecting one path from each non-dummy child with given
+ * parameterization or ordering. Similarly it collects partial paths from
+ * non-dummy children to create partial append paths.
+ */
+static void
+add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
+ List *live_childrels)
+{
+ List *subpaths = NIL;
+ bool subpaths_valid = true;
+ List *partial_subpaths = NIL;
+ bool partial_subpaths_valid = true;
+ List *all_child_pathkeys = NIL;
+ List *all_child_outers = NIL;
+ ListCell *l;
+ List *partitioned_rels = NIL;
+ RangeTblEntry *rte;
+
+ rte = planner_rt_fetch(rel->relid, root);
+ if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ partitioned_rels = get_partitioned_child_rels(root, rel->relid);
+ /* The root partitioned table is included as a child rel */
+ Assert(list_length(partitioned_rels) >= 1);
+ }
+
+ /*
+ * For every non-dummy child, remember the cheapest path. Also, identify
+ * all pathkeys (orderings) and parameterizations (required_outer sets)
+ * available for the non-dummy member relations.
+ */
+ foreach(l, live_childrels)
+ {
+ RelOptInfo *childrel = lfirst(l);
+ ListCell *lcp;
/*
* If child has an unparameterized cheapest-total path, add that to
@@ -1298,7 +1405,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
* if we have zero or one live subpath due to constraint exclusion.)
*/
if (subpaths_valid)
- add_path(rel, (Path *) create_append_path(rel, subpaths, NULL, 0));
+ add_path(rel, (Path *) create_append_path(rel, subpaths, NULL, 0,
+ partitioned_rels));
/*
* Consider an append of partial unordered, unparameterized partial paths.
@@ -1325,7 +1433,7 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
/* Generate a partial append path. */
appendpath = create_append_path(rel, partial_subpaths, NULL,
- parallel_workers);
+ parallel_workers, partitioned_rels);
/*
* XL: In case we had to re-distribute the child relations, don't
@@ -1341,7 +1449,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
*/
if (subpaths_valid)
generate_mergeappend_paths(root, rel, live_childrels,
- all_child_pathkeys);
+ all_child_pathkeys,
+ partitioned_rels);
/*
* Build Append paths for each parameterization seen among the child rels.
@@ -1383,7 +1492,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
if (subpaths_valid)
add_path(rel, (Path *)
- create_append_path(rel, subpaths, required_outer, 0));
+ create_append_path(rel, subpaths, required_outer, 0,
+ partitioned_rels));
}
}
@@ -1413,7 +1523,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
static void
generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
List *live_childrels,
- List *all_child_pathkeys)
+ List *all_child_pathkeys,
+ List *partitioned_rels)
{
ListCell *lcp;
@@ -1437,12 +1548,14 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
get_cheapest_path_for_pathkeys(childrel->pathlist,
pathkeys,
NULL,
- STARTUP_COST);
+ STARTUP_COST,
+ false);
cheapest_total =
get_cheapest_path_for_pathkeys(childrel->pathlist,
pathkeys,
NULL,
- TOTAL_COST);
+ TOTAL_COST,
+ false);
/*
* If we can't find any paths with the right order just use the
@@ -1475,13 +1588,15 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
rel,
startup_subpaths,
pathkeys,
- NULL));
+ NULL,
+ partitioned_rels));
if (startup_neq_total)
add_path(rel, (Path *) create_merge_append_path(root,
rel,
total_subpaths,
pathkeys,
- NULL));
+ NULL,
+ partitioned_rels));
}
}
@@ -1507,7 +1622,8 @@ get_cheapest_parameterized_child_path(PlannerInfo *root, RelOptInfo *rel,
cheapest = get_cheapest_path_for_pathkeys(rel->pathlist,
NIL,
required_outer,
- TOTAL_COST);
+ TOTAL_COST,
+ false);
Assert(cheapest != NULL);
if (bms_equal(PATH_REQ_OUTER(cheapest), required_outer))
return cheapest;
@@ -1613,7 +1729,7 @@ set_dummy_rel_pathlist(RelOptInfo *rel)
rel->pathlist = NIL;
rel->partial_pathlist = NIL;
- add_path(rel, (Path *) create_append_path(rel, NIL, NULL, 0));
+ add_path(rel, (Path *) create_append_path(rel, NIL, NULL, 0, NIL));
/*
* We set the cheapest path immediately, to ensure that IS_DUMMY_REL()
@@ -1753,6 +1869,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
}
}
rel->baserestrictinfo = upperrestrictlist;
+ /* We don't bother recomputing baserestrict_min_security */
}
pfree(safetyInfo.unsafeColumns);
@@ -1974,6 +2091,27 @@ set_values_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
}
/*
+ * set_tablefunc_pathlist
+ * Build the (single) access path for a table func RTE
+ */
+static void
+set_tablefunc_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
+{
+ Relids required_outer;
+
+ /*
+ * We don't support pushing join clauses into the quals of a tablefunc
+ * scan, but it could still have required parameterization due to LATERAL
+ * refs in the function expression.
+ */
+ required_outer = rel->lateral_relids;
+
+ /* Generate appropriate path */
+ add_path(rel, create_tablefuncscan_path(root, rel,
+ required_outer));
+}
+
+/*
* set_cte_pathlist
* Build the (single) access path for a non-self-reference CTE RTE
*
@@ -2040,6 +2178,36 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
}
/*
+ * set_namedtuplestore_pathlist
+ * Build the (single) access path for a named tuplestore RTE
+ *
+ * There's no need for a separate set_namedtuplestore_size phase, since we
+ * don't support join-qual-parameterized paths for tuplestores.
+ */
+static void
+set_namedtuplestore_pathlist(PlannerInfo *root, RelOptInfo *rel,
+ RangeTblEntry *rte)
+{
+ Relids required_outer;
+
+ /* Mark rel with estimated output rows, width, etc */
+ set_namedtuplestore_size_estimates(root, rel);
+
+ /*
+ * We don't support pushing join clauses into the quals of a tuplestore
+ * scan, but it could still have required parameterization due to LATERAL
+ * refs in its tlist.
+ */
+ required_outer = rel->lateral_relids;
+
+ /* Generate appropriate path */
+ add_path(rel, create_namedtuplestorescan_path(root, rel, required_outer));
+
+ /* Select cheapest path (pretty easy in this case...) */
+ set_cheapest(rel);
+}
+
+/*
* set_worktable_pathlist
* Build the (single) access path for a self-reference CTE RTE
*
@@ -2091,39 +2259,51 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* generate_gather_paths
- * Generate parallel access paths for a relation by pushing a Gather on
- * top of a partial path.
+ * Generate parallel access paths for a relation by pushing a Gather or
+ * Gather Merge on top of a partial path.
*
* This must not be called until after we're done creating all partial paths
* for the specified relation. (Otherwise, add_partial_path might delete a
- * path that some GatherPath has a reference to.)
+ * path that some GatherPath or GatherMergePath has a reference to.)
*/
void
generate_gather_paths(PlannerInfo *root, RelOptInfo *rel)
{
Path *cheapest_partial_path;
Path *simple_gather_path;
+ ListCell *lc;
/* If there are no partial paths, there's nothing to do here. */
if (rel->partial_pathlist == NIL)
return;
/*
- * The output of Gather is currently always unsorted, so there's only one
- * partial path of interest: the cheapest one. That will be the one at
- * the front of partial_pathlist because of the way add_partial_path
- * works.
- *
- * Eventually, we should have a Gather Merge operation that can merge
- * multiple tuple streams together while preserving their ordering. We
- * could usefully generate such a path from each partial path that has
- * non-NIL pathkeys.
+ * The output of Gather is always unsorted, so there's only one partial
+ * path of interest: the cheapest one. That will be the one at the front
+ * of partial_pathlist because of the way add_partial_path works.
*/
cheapest_partial_path = linitial(rel->partial_pathlist);
simple_gather_path = (Path *)
create_gather_path(root, rel, cheapest_partial_path, rel->reltarget,
NULL, NULL);
add_path(rel, simple_gather_path);
+
+ /*
+ * For each useful ordering, we can consider an order-preserving Gather
+ * Merge.
+ */
+ foreach(lc, rel->partial_pathlist)
+ {
+ Path *subpath = (Path *) lfirst(lc);
+ GatherMergePath *path;
+
+ if (subpath->pathkeys == NIL)
+ continue;
+
+ path = create_gather_merge_path(root, rel, subpath, rel->reltarget,
+ subpath->pathkeys, NULL, NULL);
+ add_path(rel, &path->path);
+ }
}
/*
@@ -2346,6 +2526,12 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
* thereby changing the partition contents and thus the window functions'
* results for rows that remain.
*
+ * 5. If the subquery contains any set-returning functions in its targetlist,
+ * we cannot push volatile quals into it. That would push them below the SRFs
+ * and thereby change the number of times they are evaluated. Also, a
+ * volatile qual could succeed for some SRF output rows and fail for others,
+ * a behavior that cannot occur if it's evaluated before SRF expansion.
+ *
* In addition, we make several checks on the subquery's output columns to see
* if it is safe to reference them in pushed-down quals. If output column k
* is found to be unsafe to reference, we set safetyInfo->unsafeColumns[k]
@@ -2390,8 +2576,10 @@ subquery_is_pushdown_safe(Query *subquery, Query *topquery,
if (subquery->limitOffset != NULL || subquery->limitCount != NULL)
return false;
- /* Check points 3 and 4 */
- if (subquery->distinctClause || subquery->hasWindowFuncs)
+ /* Check points 3, 4, and 5 */
+ if (subquery->distinctClause ||
+ subquery->hasWindowFuncs ||
+ subquery->hasTargetSRFs)
safetyInfo->unsafeVolatile = true;
/*
@@ -2418,8 +2606,8 @@ subquery_is_pushdown_safe(Query *subquery, Query *topquery,
if (subquery->setOperations != NULL)
return false;
/* Check whether setop component output types match top level */
- topop = (SetOperationStmt *) topquery->setOperations;
- Assert(topop && IsA(topop, SetOperationStmt));
+ topop = castNode(SetOperationStmt, topquery->setOperations);
+ Assert(topop);
compare_tlist_datatypes(subquery->targetList,
topop->colTypes,
safetyInfo);
@@ -2514,7 +2702,8 @@ check_output_expressions(Query *subquery, pushdown_safety_info *safetyInfo)
continue;
/* Functions returning sets are unsafe (point 1) */
- if (expression_returns_set((Node *) tle->expr))
+ if (subquery->hasTargetSRFs &&
+ expression_returns_set((Node *) tle->expr))
{
safetyInfo->unsafeColumns[tle->resno] = true;
continue;
@@ -2723,46 +2912,6 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
recurse_push_qual(subquery->setOperations, subquery,
rte, rti, qual);
}
- else if (IsA(qual, CurrentOfExpr))
- {
- /*
- * This is possible when a WHERE CURRENT OF expression is applied to a
- * table with row-level security. In that case, the subquery should
- * contain precisely one rtable entry for the table, and we can safely
- * push the expression down into the subquery. This will cause a TID
- * scan subquery plan to be generated allowing the target relation to
- * be updated.
- *
- * Someday we might also be able to use a WHERE CURRENT OF expression
- * on a view, but currently the rewriter prevents that, so we should
- * never see any other case here, but generate sane error messages in
- * case it does somehow happen.
- */
- if (subquery->rtable == NIL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WHERE CURRENT OF is not supported on a view with no underlying relation")));
-
- if (list_length(subquery->rtable) > 1)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WHERE CURRENT OF is not supported on a view with more than one underlying relation")));
-
- if (subquery->hasAggs || subquery->groupClause || subquery->groupingSets || subquery->havingQual)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WHERE CURRENT OF is not supported on a view with grouping or aggregation")));
-
- /*
- * Adjust the CURRENT OF expression to refer to the underlying table
- * in the subquery, and attach it to the subquery's WHERE clause.
- */
- qual = copyObject(qual);
- ((CurrentOfExpr *) qual)->cvarno = 1;
-
- subquery->jointree->quals =
- make_and_qual(subquery->jointree->quals, qual);
- }
else
{
/*
@@ -2791,7 +2940,7 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
make_and_qual(subquery->jointree->quals, qual);
/*
- * We need not change the subquery's hasAggs or hasSublinks flags,
+ * We need not change the subquery's hasAggs or hasSubLinks flags,
* since we can't be pushing down any aggregates that weren't there
* before, and we don't push down subselects at all.
*/
@@ -2927,7 +3076,8 @@ remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel)
* If it contains a set-returning function, we can't remove it since
* that could change the number of rows returned by the subquery.
*/
- if (expression_returns_set(texpr))
+ if (subquery->hasTargetSRFs &&
+ expression_returns_set(texpr))
continue;
/*
@@ -2948,6 +3098,123 @@ remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel)
}
}
+/*
+ * create_partial_bitmap_paths
+ * Build partial bitmap heap path for the relation
+ */
+void
+create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel,
+ Path *bitmapqual)
+{
+ int parallel_workers;
+ double pages_fetched;
+
+ /* Compute heap pages for bitmap heap scan */
+ pages_fetched = compute_bitmap_pages(root, rel, bitmapqual, 1.0,
+ NULL, NULL);
+
+ parallel_workers = compute_parallel_worker(rel, pages_fetched, -1);
+
+ if (parallel_workers <= 0)
+ return;
+
+ add_partial_path(rel, (Path *) create_bitmap_heap_path(root, rel,
+ bitmapqual, rel->lateral_relids, 1.0, parallel_workers));
+}
+
+/*
+ * Compute the number of parallel workers that should be used to scan a
+ * relation. We compute the parallel workers based on the size of the heap to
+ * be scanned and the size of the index to be scanned, then choose a minimum
+ * of those.
+ *
+ * "heap_pages" is the number of pages from the table that we expect to scan, or
+ * -1 if we don't expect to scan any.
+ *
+ * "index_pages" is the number of pages from the index that we expect to scan, or
+ * -1 if we don't expect to scan any.
+ */
+int
+compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages)
+{
+ int parallel_workers = 0;
+
+ /*
+ * If the user has set the parallel_workers reloption, use that; otherwise
+ * select a default number of workers.
+ */
+ if (rel->rel_parallel_workers != -1)
+ parallel_workers = rel->rel_parallel_workers;
+ else
+ {
+ /*
+ * If the number of pages being scanned is insufficient to justify a
+ * parallel scan, just return zero ... unless it's an inheritance
+ * child. In that case, we want to generate a parallel path here
+ * anyway. It might not be worthwhile just for this relation, but
+ * when combined with all of its inheritance siblings it may well pay
+ * off.
+ */
+ if (rel->reloptkind == RELOPT_BASEREL &&
+ ((heap_pages >= 0 && heap_pages < min_parallel_table_scan_size) ||
+ (index_pages >= 0 && index_pages < min_parallel_index_scan_size)))
+ return 0;
+
+ if (heap_pages >= 0)
+ {
+ int heap_parallel_threshold;
+ int heap_parallel_workers = 1;
+
+ /*
+ * Select the number of workers based on the log of the size of
+ * the relation. This probably needs to be a good deal more
+ * sophisticated, but we need something here for now. Note that
+ * the upper limit of the min_parallel_table_scan_size GUC is
+ * chosen to prevent overflow here.
+ */
+ heap_parallel_threshold = Max(min_parallel_table_scan_size, 1);
+ while (heap_pages >= (BlockNumber) (heap_parallel_threshold * 3))
+ {
+ heap_parallel_workers++;
+ heap_parallel_threshold *= 3;
+ if (heap_parallel_threshold > INT_MAX / 3)
+ break; /* avoid overflow */
+ }
+
+ parallel_workers = heap_parallel_workers;
+ }
+
+ if (index_pages >= 0)
+ {
+ int index_parallel_workers = 1;
+ int index_parallel_threshold;
+
+ /* same calculation as for heap_pages above */
+ index_parallel_threshold = Max(min_parallel_index_scan_size, 1);
+ while (index_pages >= (BlockNumber) (index_parallel_threshold * 3))
+ {
+ index_parallel_workers++;
+ index_parallel_threshold *= 3;
+ if (index_parallel_threshold > INT_MAX / 3)
+ break; /* avoid overflow */
+ }
+
+ if (parallel_workers > 0)
+ parallel_workers = Min(parallel_workers, index_parallel_workers);
+ else
+ parallel_workers = index_parallel_workers;
+ }
+ }
+
+ /*
+ * In no case use more than max_parallel_workers_per_gather workers.
+ */
+ parallel_workers = Min(parallel_workers, max_parallel_workers_per_gather);
+
+ return parallel_workers;
+}
+
+
/*****************************************************************************
* DEBUG SUPPORT
*****************************************************************************/
@@ -3014,6 +3281,9 @@ print_path(PlannerInfo *root, Path *path, int indent)
case T_FunctionScan:
ptype = "FunctionScan";
break;
+ case T_TableFuncScan:
+ ptype = "TableFuncScan";
+ break;
case T_ValuesScan:
ptype = "ValuesScan";
break;
@@ -3074,6 +3344,10 @@ print_path(PlannerInfo *root, Path *path, int indent)
ptype = "Projection";
subpath = ((ProjectionPath *) path)->subpath;
break;
+ case T_ProjectSetPath:
+ ptype = "ProjectSet";
+ subpath = ((ProjectSetPath *) path)->subpath;
+ break;
case T_SortPath:
ptype = "Sort";
subpath = ((SortPath *) path)->subpath;
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index 02660c2ba5..758ddea4a5 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -3,7 +3,7 @@
* clausesel.c
* Routines to compute clause selectivities
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,6 +22,7 @@
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
+#include "statistics/statistics.h"
/*
@@ -40,7 +41,8 @@ typedef struct RangeQueryClause
static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
bool varonleft, bool isLTsel, Selectivity s2);
-
+static RelOptInfo *find_single_rel_for_clauses(PlannerInfo *root,
+ List *clauses);
/****************************************************************************
* ROUTINES TO COMPUTE SELECTIVITIES
@@ -60,23 +62,28 @@ static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
* subclauses. However, that's only right if the subclauses have independent
* probabilities, and in reality they are often NOT independent. So,
* we want to be smarter where we can.
-
- * Currently, the only extra smarts we have is to recognize "range queries",
- * such as "x > 34 AND x < 42". Clauses are recognized as possible range
- * query components if they are restriction opclauses whose operators have
- * scalarltsel() or scalargtsel() as their restriction selectivity estimator.
- * We pair up clauses of this form that refer to the same variable. An
- * unpairable clause of this kind is simply multiplied into the selectivity
- * product in the normal way. But when we find a pair, we know that the
- * selectivities represent the relative positions of the low and high bounds
- * within the column's range, so instead of figuring the selectivity as
- * hisel * losel, we can figure it as hisel + losel - 1. (To visualize this,
- * see that hisel is the fraction of the range below the high bound, while
- * losel is the fraction above the low bound; so hisel can be interpreted
- * directly as a 0..1 value but we need to convert losel to 1-losel before
- * interpreting it as a value. Then the available range is 1-losel to hisel.
- * However, this calculation double-excludes nulls, so really we need
- * hisel + losel + null_frac - 1.)
+ *
+ * If the clauses taken together refer to just one relation, we'll try to
+ * apply selectivity estimates using any extended statistics for that rel.
+ * Currently we only have (soft) functional dependencies, so apply these in as
+ * many cases as possible, and fall back on normal estimates for remaining
+ * clauses.
+ *
+ * We also recognize "range queries", such as "x > 34 AND x < 42". Clauses
+ * are recognized as possible range query components if they are restriction
+ * opclauses whose operators have scalarltsel() or scalargtsel() as their
+ * restriction selectivity estimator. We pair up clauses of this form that
+ * refer to the same variable. An unpairable clause of this kind is simply
+ * multiplied into the selectivity product in the normal way. But when we
+ * find a pair, we know that the selectivities represent the relative
+ * positions of the low and high bounds within the column's range, so instead
+ * of figuring the selectivity as hisel * losel, we can figure it as hisel +
+ * losel - 1. (To visualize this, see that hisel is the fraction of the range
+ * below the high bound, while losel is the fraction above the low bound; so
+ * hisel can be interpreted directly as a 0..1 value but we need to convert
+ * losel to 1-losel before interpreting it as a value. Then the available
+ * range is 1-losel to hisel. However, this calculation double-excludes
+ * nulls, so really we need hisel + losel + null_frac - 1.)
*
* If either selectivity is exactly DEFAULT_INEQ_SEL, we forget this equation
* and instead use DEFAULT_RANGE_INEQ_SEL. The same applies if the equation
@@ -96,28 +103,67 @@ clauselist_selectivity(PlannerInfo *root,
SpecialJoinInfo *sjinfo)
{
Selectivity s1 = 1.0;
+ RelOptInfo *rel;
+ Bitmapset *estimatedclauses = NULL;
RangeQueryClause *rqlist = NULL;
ListCell *l;
+ int listidx;
/*
- * If there's exactly one clause, then no use in trying to match up pairs,
- * so just go directly to clause_selectivity().
+ * If there's exactly one clause, just go directly to
+ * clause_selectivity(). None of what we might do below is relevant.
*/
if (list_length(clauses) == 1)
return clause_selectivity(root, (Node *) linitial(clauses),
varRelid, jointype, sjinfo);
/*
- * Initial scan over clauses. Anything that doesn't look like a potential
- * rangequery clause gets multiplied into s1 and forgotten. Anything that
- * does gets inserted into an rqlist entry.
+ * Determine if these clauses reference a single relation. If so, and if
+ * it has extended statistics, try to apply those.
*/
+ rel = find_single_rel_for_clauses(root, clauses);
+ if (rel && rel->rtekind == RTE_RELATION && rel->statlist != NIL)
+ {
+ /*
+ * Perform selectivity estimations on any clauses found applicable by
+ * dependencies_clauselist_selectivity. 'estimatedclauses' will be
+ * filled with the 0-based list positions of clauses used that way, so
+ * that we can ignore them below.
+ */
+ s1 *= dependencies_clauselist_selectivity(root, clauses, varRelid,
+ jointype, sjinfo, rel,
+ &estimatedclauses);
+
+ /*
+ * This would be the place to apply any other types of extended
+ * statistics selectivity estimations for remaining clauses.
+ */
+ }
+
+ /*
+ * Apply normal selectivity estimates for remaining clauses. We'll be
+ * careful to skip any clauses which were already estimated above.
+ *
+ * Anything that doesn't look like a potential rangequery clause gets
+ * multiplied into s1 and forgotten. Anything that does gets inserted into
+ * an rqlist entry.
+ */
+ listidx = -1;
foreach(l, clauses)
{
Node *clause = (Node *) lfirst(l);
RestrictInfo *rinfo;
Selectivity s2;
+ listidx++;
+
+ /*
+ * Skip this clause if it's already been estimated by some other
+ * statistics above.
+ */
+ if (bms_is_member(listidx, estimatedclauses))
+ continue;
+
/* Always compute the selectivity using clause_selectivity */
s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
@@ -373,6 +419,49 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
}
/*
+ * find_single_rel_for_clauses
+ * Examine each clause in 'clauses' and determine if all clauses
+ * reference only a single relation. If so return that relation,
+ * otherwise return NULL.
+ */
+static RelOptInfo *
+find_single_rel_for_clauses(PlannerInfo *root, List *clauses)
+{
+ int lastrelid = 0;
+ ListCell *l;
+
+ foreach(l, clauses)
+ {
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ int relid;
+
+ /*
+ * If we have a list of bare clauses rather than RestrictInfos, we
+ * could pull out their relids the hard way with pull_varnos().
+ * However, currently the extended-stats machinery won't do anything
+ * with non-RestrictInfo clauses anyway, so there's no point in
+ * spending extra cycles; just fail if that's what we have.
+ */
+ if (!IsA(rinfo, RestrictInfo))
+ return NULL;
+
+ if (bms_is_empty(rinfo->clause_relids))
+ continue; /* we can ignore variable-free clauses */
+ if (!bms_get_singleton_member(rinfo->clause_relids, &relid))
+ return NULL; /* multiple relations in this clause */
+ if (lastrelid == 0)
+ lastrelid = relid; /* first clause referencing a relation */
+ else if (relid != lastrelid)
+ return NULL; /* relation not same as last one */
+ }
+
+ if (lastrelid != 0)
+ return find_base_rel(root, lastrelid);
+
+ return NULL; /* no clauses */
+}
+
+/*
* bms_is_subset_singleton
*
* Same result as bms_is_subset(s, bms_make_singleton(x)),
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 485717acce..6e4808d51b 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -61,7 +61,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -132,6 +132,7 @@ bool enable_material = true;
bool enable_mergejoin = true;
bool enable_hashjoin = true;
bool enable_fast_query_shipping = true;
+bool enable_gathermerge = true;
typedef struct
{
@@ -167,6 +168,7 @@ static Selectivity get_foreign_key_join_selectivity(PlannerInfo *root,
static void set_rel_width(PlannerInfo *root, RelOptInfo *rel);
static double relation_byte_size(double tuples, int width);
static double page_size(double tuples, int width);
+static double get_parallel_divisor(Path *path);
/*
@@ -244,32 +246,7 @@ cost_seqscan(Path *path, PlannerInfo *root,
/* Adjust costing for parallelism, if used. */
if (path->parallel_workers > 0)
{
- double parallel_divisor = path->parallel_workers;
- double leader_contribution;
-
- /*
- * Early experience with parallel query suggests that when there is
- * only one worker, the leader often makes a very substantial
- * contribution to executing the parallel portion of the plan, but as
- * more workers are added, it does less and less, because it's busy
- * reading tuples from the workers and doing whatever non-parallel
- * post-processing is needed. By the time we reach 4 workers, the
- * leader no longer makes a meaningful contribution. Thus, for now,
- * estimate that the leader spends 30% of its time servicing each
- * worker, and the remainder executing the parallel plan.
- */
- leader_contribution = 1.0 - (0.3 * path->parallel_workers);
- if (leader_contribution > 0)
- parallel_divisor += leader_contribution;
-
- /*
- * In the case of a parallel plan, the row count needs to represent
- * the number of tuples processed per worker. Otherwise, higher-level
- * plan nodes that appear below the gather will be costed incorrectly,
- * because they'll anticipate receiving more rows than any given copy
- * will actually get.
- */
- path->rows = clamp_row_est(path->rows / parallel_divisor);
+ double parallel_divisor = get_parallel_divisor(path);
/* The CPU cost is divided among all the workers. */
cpu_run_cost /= parallel_divisor;
@@ -280,6 +257,12 @@ cost_seqscan(Path *path, PlannerInfo *root,
* prefetching. For now, we assume that the disk run cost can't be
* amortized at all.
*/
+
+ /*
+ * In the case of a parallel plan, the row count needs to represent
+ * the number of tuples processed per worker.
+ */
+ path->rows = clamp_row_est(path->rows / parallel_divisor);
}
path->startup_cost = startup_cost;
@@ -397,6 +380,73 @@ cost_gather(GatherPath *path, PlannerInfo *root,
}
/*
+ * cost_gather_merge
+ * Determines and returns the cost of gather merge path.
+ *
+ * GatherMerge merges several pre-sorted input streams, using a heap that at
+ * any given instant holds the next tuple from each stream. If there are N
+ * streams, we need about N*log2(N) tuple comparisons to construct the heap at
+ * startup, and then for each output tuple, about log2(N) comparisons to
+ * replace the top heap entry with the next tuple from the same stream.
+ */
+void
+cost_gather_merge(GatherMergePath *path, PlannerInfo *root,
+ RelOptInfo *rel, ParamPathInfo *param_info,
+ Cost input_startup_cost, Cost input_total_cost,
+ double *rows)
+{
+ Cost startup_cost = 0;
+ Cost run_cost = 0;
+ Cost comparison_cost;
+ double N;
+ double logN;
+
+ /* Mark the path with the correct row estimate */
+ if (rows)
+ path->path.rows = *rows;
+ else if (param_info)
+ path->path.rows = param_info->ppi_rows;
+ else
+ path->path.rows = rel->rows;
+
+ if (!enable_gathermerge)
+ startup_cost += disable_cost;
+
+ /*
+ * Add one to the number of workers to account for the leader. This might
+ * be overgenerous since the leader will do less work than other workers
+ * in typical cases, but we'll go with it for now.
+ */
+ Assert(path->num_workers > 0);
+ N = (double) path->num_workers + 1;
+ logN = LOG2(N);
+
+ /* Assumed cost per tuple comparison */
+ comparison_cost = 2.0 * cpu_operator_cost;
+
+ /* Heap creation cost */
+ startup_cost += comparison_cost * N * logN;
+
+ /* Per-tuple heap maintenance cost */
+ run_cost += path->path.rows * comparison_cost * logN;
+
+ /* small cost for heap management, like cost_merge_append */
+ run_cost += cpu_operator_cost * path->path.rows;
+
+ /*
+ * Parallel setup and communication cost. Since Gather Merge, unlike
+ * Gather, requires us to block until a tuple is available from every
+ * worker, we bump the IPC cost up a little bit as compared with Gather.
+ * For lack of a better idea, charge an extra 5%.
+ */
+ startup_cost += parallel_setup_cost;
+ run_cost += parallel_tuple_cost * path->path.rows * 1.05;
+
+ path->path.startup_cost = startup_cost + input_startup_cost;
+ path->path.total_cost = (startup_cost + run_cost + input_total_cost);
+}
+
+/*
* cost_index
* Determines and returns the cost of scanning a relation using an index.
*
@@ -415,7 +465,8 @@ cost_gather(GatherPath *path, PlannerInfo *root,
* we have to fetch from the table, so they don't reduce the scan cost.
*/
void
-cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
+cost_index(IndexPath *path, PlannerInfo *root, double loop_count,
+ bool partial_path)
{
IndexOptInfo *index = path->indexinfo;
RelOptInfo *baserel = index->rel;
@@ -424,6 +475,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
List *qpquals;
Cost startup_cost = 0;
Cost run_cost = 0;
+ Cost cpu_run_cost = 0;
Cost indexStartupCost;
Cost indexTotalCost;
Selectivity indexSelectivity;
@@ -437,6 +489,8 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
Cost cpu_per_tuple;
double tuples_fetched;
double pages_fetched;
+ double rand_heap_pages;
+ double index_pages;
/* Should only be applied to base relations */
Assert(IsA(baserel, RelOptInfo) &&
@@ -483,7 +537,8 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
amcostestimate = (amcostestimate_function) index->amcostestimate;
amcostestimate(root, path, loop_count,
&indexStartupCost, &indexTotalCost,
- &indexSelectivity, &indexCorrelation);
+ &indexSelectivity, &indexCorrelation,
+ &index_pages);
/*
* Save amcostestimate's results for possible use in bitmap scan planning.
@@ -550,6 +605,8 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
if (indexonly)
pages_fetched = ceil(pages_fetched * (1.0 - baserel->allvisfrac));
+ rand_heap_pages = pages_fetched;
+
max_IO_cost = (pages_fetched * spc_random_page_cost) / loop_count;
/*
@@ -588,6 +645,8 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
if (indexonly)
pages_fetched = ceil(pages_fetched * (1.0 - baserel->allvisfrac));
+ rand_heap_pages = pages_fetched;
+
/* max_IO_cost is for the perfectly uncorrelated case (csquared=0) */
max_IO_cost = pages_fetched * spc_random_page_cost;
@@ -607,6 +666,36 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
min_IO_cost = 0;
}
+ if (partial_path)
+ {
+ /*
+ * For index only scans compute workers based on number of index pages
+ * fetched; the number of heap pages we fetch might be so small as to
+ * effectively rule out parallelism, which we don't want to do.
+ */
+ if (indexonly)
+ rand_heap_pages = -1;
+
+ /*
+ * Estimate the number of parallel workers required to scan index. Use
+ * the number of heap pages computed considering heap fetches won't be
+ * sequential as for parallel scans the pages are accessed in random
+ * order.
+ */
+ path->path.parallel_workers = compute_parallel_worker(baserel,
+ rand_heap_pages, index_pages);
+
+ /*
+ * Fall out if workers can't be assigned for parallel scan, because in
+ * such a case this path will be rejected. So there is no benefit in
+ * doing extra computation.
+ */
+ if (path->path.parallel_workers <= 0)
+ return;
+
+ path->path.parallel_aware = true;
+ }
+
/*
* Now interpolate based on estimated index order correlation to get total
* disk I/O cost for main table accesses.
@@ -626,11 +715,24 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
startup_cost += qpqual_cost.startup;
cpu_per_tuple = cpu_tuple_cost + qpqual_cost.per_tuple;
- run_cost += cpu_per_tuple * tuples_fetched;
+ cpu_run_cost += cpu_per_tuple * tuples_fetched;
/* tlist eval costs are paid per output row, not per tuple scanned */
startup_cost += path->path.pathtarget->cost.startup;
- run_cost += path->path.pathtarget->cost.per_tuple * path->path.rows;
+ cpu_run_cost += path->path.pathtarget->cost.per_tuple * path->path.rows;
+
+ /* Adjust costing for parallelism, if used. */
+ if (path->path.parallel_workers > 0)
+ {
+ double parallel_divisor = get_parallel_divisor(&path->path);
+
+ path->path.rows = clamp_row_est(path->path.rows / parallel_divisor);
+
+ /* The CPU cost is divided among all the workers. */
+ cpu_run_cost /= parallel_divisor;
+ }
+
+ run_cost += cpu_run_cost;
path->path.startup_cost = startup_cost;
path->path.total_cost = startup_cost + run_cost;
@@ -661,9 +763,8 @@ extract_nonindex_conditions(List *qual_clauses, List *indexquals)
foreach(lc, qual_clauses)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
- Assert(IsA(rinfo, RestrictInfo));
if (rinfo->pseudoconstant)
continue; /* we may drop pseudoconstants here */
if (list_member_ptr(indexquals, rinfo))
@@ -837,10 +938,10 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
Cost startup_cost = 0;
Cost run_cost = 0;
Cost indexTotalCost;
- Selectivity indexSelectivity;
QualCost qpqual_cost;
Cost cpu_per_tuple;
Cost cost_per_page;
+ Cost cpu_run_cost;
double tuples_fetched;
double pages_fetched;
double spc_seq_page_cost,
@@ -861,13 +962,12 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
if (!enable_bitmapscan)
startup_cost += disable_cost;
- /*
- * Fetch total cost of obtaining the bitmap, as well as its total
- * selectivity.
- */
- cost_bitmap_tree_node(bitmapqual, &indexTotalCost, &indexSelectivity);
+ pages_fetched = compute_bitmap_pages(root, baserel, bitmapqual,
+ loop_count, &indexTotalCost,
+ &tuples_fetched);
startup_cost += indexTotalCost;
+ T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;
/* Fetch estimated page costs for tablespace containing table. */
get_tablespace_page_costs(baserel->reltablespace,
@@ -875,41 +975,6 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
&spc_seq_page_cost);
/*
- * Estimate number of main-table pages fetched.
- */
- tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples);
-
- T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;
-
- if (loop_count > 1)
- {
- /*
- * For repeated bitmap scans, scale up the number of tuples fetched in
- * the Mackert and Lohman formula by the number of scans, so that we
- * estimate the number of pages fetched by all the scans. Then
- * pro-rate for one scan.
- */
- pages_fetched = index_pages_fetched(tuples_fetched * loop_count,
- baserel->pages,
- get_indexpath_pages(bitmapqual),
- root);
- pages_fetched /= loop_count;
- }
- else
- {
- /*
- * For a single scan, the number of heap pages that need to be fetched
- * is the same as the Mackert and Lohman formula for the case T <= b
- * (ie, no re-reads needed).
- */
- pages_fetched = (2.0 * T * tuples_fetched) / (2.0 * T + tuples_fetched);
- }
- if (pages_fetched >= T)
- pages_fetched = T;
- else
- pages_fetched = ceil(pages_fetched);
-
- /*
* For small numbers of pages we should charge spc_random_page_cost
* apiece, while if nearly all the table's pages are being read, it's more
* appropriate to charge spc_seq_page_cost apiece. The effect is
@@ -938,8 +1003,21 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
startup_cost += qpqual_cost.startup;
cpu_per_tuple = cpu_tuple_cost + qpqual_cost.per_tuple;
+ cpu_run_cost = cpu_per_tuple * tuples_fetched;
- run_cost += cpu_per_tuple * tuples_fetched;
+ /* Adjust costing for parallelism, if used. */
+ if (path->parallel_workers > 0)
+ {
+ double parallel_divisor = get_parallel_divisor(path);
+
+ /* The CPU cost is divided among all the workers. */
+ cpu_run_cost /= parallel_divisor;
+
+ path->rows = clamp_row_est(path->rows / parallel_divisor);
+ }
+
+
+ run_cost += cpu_run_cost;
/* tlist eval costs are paid per output row, not per tuple scanned */
startup_cost += path->pathtarget->cost.startup;
@@ -1295,6 +1373,62 @@ cost_functionscan(Path *path, PlannerInfo *root,
}
/*
+ * cost_tablefuncscan
+ * Determines and returns the cost of scanning a table function.
+ *
+ * 'baserel' is the relation to be scanned
+ * 'param_info' is the ParamPathInfo if this is a parameterized path, else NULL
+ */
+void
+cost_tablefuncscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info)
+{
+ Cost startup_cost = 0;
+ Cost run_cost = 0;
+ QualCost qpqual_cost;
+ Cost cpu_per_tuple;
+ RangeTblEntry *rte;
+ QualCost exprcost;
+
+ /* Should only be applied to base relations that are functions */
+ Assert(baserel->relid > 0);
+ rte = planner_rt_fetch(baserel->relid, root);
+ Assert(rte->rtekind == RTE_TABLEFUNC);
+
+ /* Mark the path with the correct row estimate */
+ if (param_info)
+ path->rows = param_info->ppi_rows;
+ else
+ path->rows = baserel->rows;
+
+ /*
+ * Estimate costs of executing the table func expression(s).
+ *
+ * XXX in principle we ought to charge tuplestore spill costs if the
+ * number of rows is large. However, given how phony our rowcount
+ * estimates for tablefuncs tend to be, there's not a lot of point in that
+ * refinement right now.
+ */
+ cost_qual_eval_node(&exprcost, (Node *) rte->tablefunc, root);
+
+ startup_cost += exprcost.startup + exprcost.per_tuple;
+
+ /* Add scanning CPU costs */
+ get_restriction_qual_cost(root, baserel, param_info, &qpqual_cost);
+
+ startup_cost += qpqual_cost.startup;
+ cpu_per_tuple = cpu_tuple_cost + qpqual_cost.per_tuple;
+ run_cost += cpu_per_tuple * baserel->tuples;
+
+ /* tlist eval costs are paid per output row, not per tuple scanned */
+ startup_cost += path->pathtarget->cost.startup;
+ run_cost += path->pathtarget->cost.per_tuple * path->rows;
+
+ path->startup_cost = startup_cost;
+ path->total_cost = startup_cost + run_cost;
+}
+
+/*
* cost_valuesscan
* Determines and returns the cost of scanning a VALUES RTE.
*
@@ -1389,6 +1523,43 @@ cost_ctescan(Path *path, PlannerInfo *root,
}
/*
+ * cost_namedtuplestorescan
+ * Determines and returns the cost of scanning a named tuplestore.
+ */
+void
+cost_namedtuplestorescan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info)
+{
+ Cost startup_cost = 0;
+ Cost run_cost = 0;
+ QualCost qpqual_cost;
+ Cost cpu_per_tuple;
+
+ /* Should only be applied to base relations that are Tuplestores */
+ Assert(baserel->relid > 0);
+ Assert(baserel->rtekind == RTE_NAMEDTUPLESTORE);
+
+ /* Mark the path with the correct row estimate */
+ if (param_info)
+ path->rows = param_info->ppi_rows;
+ else
+ path->rows = baserel->rows;
+
+ /* Charge one CPU tuple cost per row for tuplestore manipulation */
+ cpu_per_tuple = cpu_tuple_cost;
+
+ /* Add scanning CPU costs */
+ get_restriction_qual_cost(root, baserel, param_info, &qpqual_cost);
+
+ startup_cost += qpqual_cost.startup;
+ cpu_per_tuple += cpu_tuple_cost + qpqual_cost.per_tuple;
+ run_cost += cpu_per_tuple * baserel->tuples;
+
+ path->startup_cost = startup_cost;
+ path->total_cost = startup_cost + run_cost;
+}
+
+/*
* cost_recursive_union
* Determines and returns the cost of performing a recursive union,
* and also the estimated output size.
@@ -1583,8 +1754,7 @@ cost_sort(Path *path, PlannerInfo *root,
* at any given instant holds the next tuple from each stream. If there
* are N streams, we need about N*log2(N) tuple comparisons to construct
* the heap at startup, and then for each output tuple, about log2(N)
- * comparisons to delete the top heap entry and another log2(N) comparisons
- * to insert its successor from the same stream.
+ * comparisons to replace the top entry.
*
* (The effective value of N will drop once some of the input streams are
* exhausted, but it seems unlikely to be worth trying to account for that.)
@@ -1625,7 +1795,7 @@ cost_merge_append(Path *path, PlannerInfo *root,
startup_cost += comparison_cost * N * logN;
/* Per-tuple heap maintenance cost */
- run_cost += tuples * comparison_cost * 2.0 * logN;
+ run_cost += tuples * comparison_cost * logN;
/*
* Also charge a small amount (arbitrarily set equal to operator cost) per
@@ -1757,11 +1927,16 @@ cost_agg(Path *path, PlannerInfo *root,
total_cost = startup_cost + cpu_tuple_cost;
output_tuples = 1;
}
- else if (aggstrategy == AGG_SORTED)
+ else if (aggstrategy == AGG_SORTED || aggstrategy == AGG_MIXED)
{
/* Here we are able to deliver output on-the-fly */
startup_cost = input_startup_cost;
total_cost = input_total_cost;
+ if (aggstrategy == AGG_MIXED && !enable_hashagg)
+ {
+ startup_cost += disable_cost;
+ total_cost += disable_cost;
+ }
/* calcs phrased this way to match HASHED case, see note above */
total_cost += aggcosts->transCost.startup;
total_cost += aggcosts->transCost.per_tuple * input_tuples;
@@ -1821,12 +1996,10 @@ cost_windowagg(Path *path, PlannerInfo *root,
*/
foreach(lc, windowFuncs)
{
- WindowFunc *wfunc = (WindowFunc *) lfirst(lc);
+ WindowFunc *wfunc = lfirst_node(WindowFunc, lc);
Cost wfunccost;
QualCost argcosts;
- Assert(IsA(wfunc, WindowFunc));
-
wfunccost = get_func_cost(wfunc->winfnoid) * cpu_operator_cost;
/* also add the input expressions' cost to per-input-row costs */
@@ -1914,15 +2087,13 @@ cost_group(Path *path, PlannerInfo *root,
* 'jointype' is the type of join to be performed
* 'outer_path' is the outer input to the join
* 'inner_path' is the inner input to the join
- * 'sjinfo' is extra info about the join for selectivity estimation
- * 'semifactors' contains valid data if jointype is SEMI or ANTI
+ * 'extra' contains miscellaneous information about the join
*/
void
initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace,
JoinType jointype,
Path *outer_path, Path *inner_path,
- SpecialJoinInfo *sjinfo,
- SemiAntiJoinFactors *semifactors)
+ JoinPathExtraData *extra)
{
Cost startup_cost = 0;
Cost run_cost = 0;
@@ -1953,10 +2124,12 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace,
inner_run_cost = inner_path->total_cost - inner_path->startup_cost;
inner_rescan_run_cost = inner_rescan_total_cost - inner_rescan_start_cost;
- if (jointype == JOIN_SEMI || jointype == JOIN_ANTI)
+ if (jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
+ extra->inner_unique)
{
/*
- * SEMI or ANTI join: executor will stop after first match.
+ * With a SEMI or ANTI join, or if the innerrel is known unique, the
+ * executor will stop after the first match.
*
* Getting decent estimates requires inspection of the join quals,
* which we choose to postpone to final_cost_nestloop.
@@ -1989,14 +2162,12 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace,
*
* 'path' is already filled in except for the rows and cost fields
* 'workspace' is the result from initial_cost_nestloop
- * 'sjinfo' is extra info about the join for selectivity estimation
- * 'semifactors' contains valid data if path->jointype is SEMI or ANTI
+ * 'extra' contains miscellaneous information about the join
*/
void
final_cost_nestloop(PlannerInfo *root, NestPath *path,
JoinCostWorkspace *workspace,
- SpecialJoinInfo *sjinfo,
- SemiAntiJoinFactors *semifactors)
+ JoinPathExtraData *extra)
{
Path *outer_path = path->outerjoinpath;
Path *inner_path = path->innerjoinpath;
@@ -2020,6 +2191,15 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
else
path->path.rows = path->path.parent->rows;
+ /* For partial paths, scale row estimate. */
+ if (path->path.parallel_workers > 0)
+ {
+ double parallel_divisor = get_parallel_divisor(&path->path);
+
+ path->path.rows =
+ clamp_row_est(path->path.rows / parallel_divisor);
+ }
+
/*
* We could include disable_cost in the preliminary estimate, but that
* would amount to optimizing for the case where the join method is
@@ -2030,10 +2210,12 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
/* cost of inner-relation source data (we already dealt with outer rel) */
- if (path->jointype == JOIN_SEMI || path->jointype == JOIN_ANTI)
+ if (path->jointype == JOIN_SEMI || path->jointype == JOIN_ANTI ||
+ extra->inner_unique)
{
/*
- * SEMI or ANTI join: executor will stop after first match.
+ * With a SEMI or ANTI join, or if the innerrel is known unique, the
+ * executor will stop after the first match.
*/
Cost inner_run_cost = workspace->inner_run_cost;
Cost inner_rescan_run_cost = workspace->inner_rescan_run_cost;
@@ -2049,8 +2231,8 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
* clamp inner_scan_frac to at most 1.0; but since match_count is at
* least 1, no such clamp is needed now.)
*/
- outer_matched_rows = rint(outer_path_rows * semifactors->outer_match_frac);
- inner_scan_frac = 2.0 / (semifactors->match_count + 1.0);
+ outer_matched_rows = rint(outer_path_rows * extra->semifactors.outer_match_frac);
+ inner_scan_frac = 2.0 / (extra->semifactors.match_count + 1.0);
/*
* Compute number of tuples processed (not number emitted!). First,
@@ -2174,7 +2356,7 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
* 'inner_path' is the inner input to the join
* 'outersortkeys' is the list of sort keys for the outer path
* 'innersortkeys' is the list of sort keys for the inner path
- * 'sjinfo' is extra info about the join for selectivity estimation
+ * 'extra' contains miscellaneous information about the join
*
* Note: outersortkeys and innersortkeys should be NIL if no explicit
* sort is needed because the respective source path is already ordered.
@@ -2185,7 +2367,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
List *mergeclauses,
Path *outer_path, Path *inner_path,
List *outersortkeys, List *innersortkeys,
- SpecialJoinInfo *sjinfo)
+ JoinPathExtraData *extra)
{
Cost startup_cost = 0;
Cost run_cost = 0;
@@ -2386,26 +2568,33 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
* final_cost_mergejoin
* Final estimate of the cost and result size of a mergejoin path.
*
- * Unlike other costsize functions, this routine makes one actual decision:
- * whether we should materialize the inner path. We do that either because
- * the inner path can't support mark/restore, or because it's cheaper to
- * use an interposed Material node to handle mark/restore. When the decision
- * is cost-based it would be logically cleaner to build and cost two separate
- * paths with and without that flag set; but that would require repeating most
- * of the cost calculations, which are not all that cheap. Since the choice
- * will not affect output pathkeys or startup cost, only total cost, there is
- * no possibility of wanting to keep both paths. So it seems best to make
- * the decision here and record it in the path's materialize_inner field.
+ * Unlike other costsize functions, this routine makes two actual decisions:
+ * whether the executor will need to do mark/restore, and whether we should
+ * materialize the inner path. It would be logically cleaner to build
+ * separate paths testing these alternatives, but that would require repeating
+ * most of the cost calculations, which are not all that cheap. Since the
+ * choice will not affect output pathkeys or startup cost, only total cost,
+ * there is no possibility of wanting to keep more than one path. So it seems
+ * best to make the decisions here and record them in the path's
+ * skip_mark_restore and materialize_inner fields.
+ *
+ * Mark/restore overhead is usually required, but can be skipped if we know
+ * that the executor need find only one match per outer tuple, and that the
+ * mergeclauses are sufficient to identify a match.
+ *
+ * We materialize the inner path if we need mark/restore and either the inner
+ * path can't support mark/restore, or it's cheaper to use an interposed
+ * Material node to handle mark/restore.
*
* 'path' is already filled in except for the rows and cost fields and
- * materialize_inner
+ * skip_mark_restore and materialize_inner
* 'workspace' is the result from initial_cost_mergejoin
- * 'sjinfo' is extra info about the join for selectivity estimation
+ * 'extra' contains miscellaneous information about the join
*/
void
final_cost_mergejoin(PlannerInfo *root, MergePath *path,
JoinCostWorkspace *workspace,
- SpecialJoinInfo *sjinfo)
+ JoinPathExtraData *extra)
{
Path *outer_path = path->jpath.outerjoinpath;
Path *inner_path = path->jpath.innerjoinpath;
@@ -2438,6 +2627,15 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
else
path->jpath.path.rows = path->jpath.path.parent->rows;
+ /* For partial paths, scale row estimate. */
+ if (path->jpath.path.parallel_workers > 0)
+ {
+ double parallel_divisor = get_parallel_divisor(&path->jpath.path);
+
+ path->jpath.path.rows =
+ clamp_row_est(path->jpath.path.rows / parallel_divisor);
+ }
+
/*
* We could include disable_cost in the preliminary estimate, but that
* would amount to optimizing for the case where the join method is
@@ -2456,6 +2654,21 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
qp_qual_cost.per_tuple -= merge_qual_cost.per_tuple;
/*
+ * With a SEMI or ANTI join, or if the innerrel is known unique, the
+ * executor will stop scanning for matches after the first match. When
+ * all the joinclauses are merge clauses, this means we don't ever need to
+ * back up the merge, and so we can skip mark/restore overhead.
+ */
+ if ((path->jpath.jointype == JOIN_SEMI ||
+ path->jpath.jointype == JOIN_ANTI ||
+ extra->inner_unique) &&
+ (list_length(path->jpath.joinrestrictinfo) ==
+ list_length(path->path_mergeclauses)))
+ path->skip_mark_restore = true;
+ else
+ path->skip_mark_restore = false;
+
+ /*
* Get approx # tuples passing the mergequals. We use approx_tuple_count
* here because we need an estimate done with JOIN_INNER semantics.
*/
@@ -2485,9 +2698,9 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
* computations?
*
* The whole issue is moot if we are working from a unique-ified outer
- * input.
+ * input, or if we know we don't need to mark/restore at all.
*/
- if (IsA(outer_path, UniquePath))
+ if (IsA(outer_path, UniquePath) ||path->skip_mark_restore)
rescannedtuples = 0;
else
{
@@ -2527,10 +2740,16 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
cpu_operator_cost * inner_path_rows * rescanratio;
/*
+ * If we don't need mark/restore at all, we don't need materialization.
+ */
+ if (path->skip_mark_restore)
+ path->materialize_inner = false;
+
+ /*
* Prefer materializing if it looks cheaper, unless the user has asked to
* suppress materialization.
*/
- if (enable_material && mat_inner_cost < bare_inner_cost)
+ else if (enable_material && mat_inner_cost < bare_inner_cost)
path->materialize_inner = true;
/*
@@ -2700,16 +2919,14 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
* 'hashclauses' is the list of joinclauses to be used as hash clauses
* 'outer_path' is the outer input to the join
* 'inner_path' is the inner input to the join
- * 'sjinfo' is extra info about the join for selectivity estimation
- * 'semifactors' contains valid data if jointype is SEMI or ANTI
+ * 'extra' contains miscellaneous information about the join
*/
void
initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace,
JoinType jointype,
List *hashclauses,
Path *outer_path, Path *inner_path,
- SpecialJoinInfo *sjinfo,
- SemiAntiJoinFactors *semifactors)
+ JoinPathExtraData *extra)
{
Cost startup_cost = 0;
Cost run_cost = 0;
@@ -2794,14 +3011,12 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace,
* 'path' is already filled in except for the rows and cost fields and
* num_batches
* 'workspace' is the result from initial_cost_hashjoin
- * 'sjinfo' is extra info about the join for selectivity estimation
- * 'semifactors' contains valid data if path->jointype is SEMI or ANTI
+ * 'extra' contains miscellaneous information about the join
*/
void
final_cost_hashjoin(PlannerInfo *root, HashPath *path,
JoinCostWorkspace *workspace,
- SpecialJoinInfo *sjinfo,
- SemiAntiJoinFactors *semifactors)
+ JoinPathExtraData *extra)
{
Path *outer_path = path->jpath.outerjoinpath;
Path *inner_path = path->jpath.innerjoinpath;
@@ -2826,6 +3041,15 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
else
path->jpath.path.rows = path->jpath.path.parent->rows;
+ /* For partial paths, scale row estimate. */
+ if (path->jpath.path.parallel_workers > 0)
+ {
+ double parallel_divisor = get_parallel_divisor(&path->jpath.path);
+
+ path->jpath.path.rows =
+ clamp_row_est(path->jpath.path.rows / parallel_divisor);
+ }
+
/*
* We could include disable_cost in the preliminary estimate, but that
* would amount to optimizing for the case where the join method is
@@ -2857,11 +3081,9 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
innerbucketsize = 1.0;
foreach(hcl, hashclauses)
{
- RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(hcl);
+ RestrictInfo *restrictinfo = lfirst_node(RestrictInfo, hcl);
Selectivity thisbucketsize;
- Assert(IsA(restrictinfo, RestrictInfo));
-
/*
* First we have to figure out which side of the hashjoin clause
* is the inner side.
@@ -2918,13 +3140,16 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
/* CPU costs */
- if (path->jpath.jointype == JOIN_SEMI || path->jpath.jointype == JOIN_ANTI)
+ if (path->jpath.jointype == JOIN_SEMI ||
+ path->jpath.jointype == JOIN_ANTI ||
+ extra->inner_unique)
{
double outer_matched_rows;
Selectivity inner_scan_frac;
/*
- * SEMI or ANTI join: executor will stop after first match.
+ * With a SEMI or ANTI join, or if the innerrel is known unique, the
+ * executor will stop after the first match.
*
* For an outer-rel row that has at least one match, we can expect the
* bucket scan to stop after a fraction 1/(match_count+1) of the
@@ -2934,8 +3159,8 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
* to clamp inner_scan_frac to at most 1.0; but since match_count is
* at least 1, no such clamp is needed now.)
*/
- outer_matched_rows = rint(outer_path_rows * semifactors->outer_match_frac);
- inner_scan_frac = 2.0 / (semifactors->match_count + 1.0);
+ outer_matched_rows = rint(outer_path_rows * extra->semifactors.outer_match_frac);
+ inner_scan_frac = 2.0 / (extra->semifactors.match_count + 1.0);
startup_cost += hash_qual_cost.startup;
run_cost += hash_qual_cost.per_tuple * outer_matched_rows *
@@ -3360,7 +3585,7 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
/*
* Aggref and WindowFunc nodes are (and should be) treated like Vars,
* ie, zero execution cost in the current model, because they behave
- * essentially like Vars in execQual.c. We disregard the costs of
+ * essentially like Vars at execution. We disregard the costs of
* their input expressions for the same reason. The actual execution
* costs of the aggregate/window functions and their arguments have to
* be factored into plan-node-specific costing of the Agg or WindowAgg
@@ -3501,11 +3726,12 @@ get_restriction_qual_cost(PlannerInfo *root, RelOptInfo *baserel,
/*
* compute_semi_anti_join_factors
- * Estimate how much of the inner input a SEMI or ANTI join
+ * Estimate how much of the inner input a SEMI, ANTI, or inner_unique join
* can be expected to scan.
*
* In a hash or nestloop SEMI/ANTI join, the executor will stop scanning
* inner rows as soon as it finds a match to the current outer row.
+ * The same happens if we have detected the inner rel is unique.
* We should therefore adjust some of the cost components for this effect.
* This function computes some estimates needed for these adjustments.
* These estimates will be the same regardless of the particular paths used
@@ -3515,7 +3741,7 @@ get_restriction_qual_cost(PlannerInfo *root, RelOptInfo *baserel,
* Input parameters:
* outerrel: outer relation under consideration
* innerrel: inner relation under consideration
- * jointype: must be JOIN_SEMI or JOIN_ANTI
+ * jointype: if not JOIN_SEMI or JOIN_ANTI, we assume it's inner_unique
* sjinfo: SpecialJoinInfo relevant to this join
* restrictlist: join quals
* Output parameters:
@@ -3537,23 +3763,20 @@ compute_semi_anti_join_factors(PlannerInfo *root,
List *joinquals;
ListCell *l;
- /* Should only be called in these cases */
- Assert(jointype == JOIN_SEMI || jointype == JOIN_ANTI);
-
/*
* In an ANTI join, we must ignore clauses that are "pushed down", since
* those won't affect the match logic. In a SEMI join, we do not
* distinguish joinquals from "pushed down" quals, so just use the whole
- * restrictinfo list.
+ * restrictinfo list. For other outer join types, we should consider only
+ * non-pushed-down quals, so that this devolves to an IS_OUTER_JOIN check.
*/
- if (jointype == JOIN_ANTI)
+ if (IS_OUTER_JOIN(jointype))
{
joinquals = NIL;
foreach(l, restrictlist)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
- Assert(IsA(rinfo, RestrictInfo));
if (!rinfo->is_pushed_down)
joinquals = lappend(joinquals, rinfo);
}
@@ -3567,7 +3790,7 @@ compute_semi_anti_join_factors(PlannerInfo *root,
jselec = clauselist_selectivity(root,
joinquals,
0,
- jointype,
+ (jointype == JOIN_ANTI) ? JOIN_ANTI : JOIN_SEMI,
sjinfo);
/*
@@ -3594,7 +3817,7 @@ compute_semi_anti_join_factors(PlannerInfo *root,
&norm_sjinfo);
/* Avoid leaking a lot of ListCells */
- if (jointype == JOIN_ANTI)
+ if (IS_OUTER_JOIN(jointype))
list_free(joinquals);
/*
@@ -3984,9 +4207,8 @@ calc_joinrel_size_estimate(PlannerInfo *root,
/* Grovel through the clauses to separate into two lists */
foreach(l, restrictlist)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
- Assert(IsA(rinfo, RestrictInfo));
if (rinfo->is_pushed_down)
pushedquals = lappend(pushedquals, rinfo);
else
@@ -4101,6 +4323,7 @@ get_foreign_key_join_selectivity(PlannerInfo *root,
{
ForeignKeyOptInfo *fkinfo = (ForeignKeyOptInfo *) lfirst(lc);
bool ref_is_outer;
+ bool use_smallest_selectivity = false;
List *removedlist;
ListCell *cell;
ListCell *prev;
@@ -4221,9 +4444,9 @@ get_foreign_key_join_selectivity(PlannerInfo *root,
* be double-counting the null fraction, and (2) it's not very clear
* how to combine null fractions for multiple referencing columns.
*
- * In the first branch of the logic below, null derating is done
- * implicitly by relying on clause_selectivity(); in the other two
- * paths, we do nothing for now about correcting for nulls.
+ * In the use_smallest_selectivity code below, null derating is done
+ * implicitly by relying on clause_selectivity(); in the other cases,
+ * we do nothing for now about correcting for nulls.
*
* XXX another point here is that if either side of an FK constraint
* is an inheritance parent, we estimate as though the constraint
@@ -4246,28 +4469,41 @@ get_foreign_key_join_selectivity(PlannerInfo *root,
* the smallest per-column selectivity, instead. (This should
* correspond to the FK column with the most nulls.)
*/
- Selectivity thisfksel = 1.0;
-
- foreach(cell, removedlist)
- {
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
- Selectivity csel;
-
- csel = clause_selectivity(root, (Node *) rinfo,
- 0, jointype, sjinfo);
- thisfksel = Min(thisfksel, csel);
- }
- fkselec *= thisfksel;
+ use_smallest_selectivity = true;
}
else if (jointype == JOIN_SEMI || jointype == JOIN_ANTI)
{
/*
* For JOIN_SEMI and JOIN_ANTI, the selectivity is defined as the
- * fraction of LHS rows that have matches. If the referenced
- * table is on the inner side, that means the selectivity is 1.0
- * (modulo nulls, which we're ignoring for now). We already
- * covered the other case, so no work here.
+ * fraction of LHS rows that have matches. The referenced table
+ * is on the inner side (we already handled the other case above),
+ * so the FK implies that every LHS row has a match *in the
+ * referenced table*. But any restriction or join clauses below
+ * here will reduce the number of matches.
*/
+ if (bms_membership(inner_relids) == BMS_SINGLETON)
+ {
+ /*
+ * When the inner side of the semi/anti join is just the
+ * referenced table, we may take the FK selectivity as equal
+ * to the selectivity of the table's restriction clauses.
+ */
+ RelOptInfo *ref_rel = find_base_rel(root, fkinfo->ref_relid);
+ double ref_tuples = Max(ref_rel->tuples, 1.0);
+
+ fkselec *= ref_rel->rows / ref_tuples;
+ }
+ else
+ {
+ /*
+ * When the inner side of the semi/anti join is itself a join,
+ * it's hard to guess what fraction of the referenced table
+ * will get through the join. But we still don't want to
+ * multiply per-column estimates together. Take the smallest
+ * per-column selectivity, instead.
+ */
+ use_smallest_selectivity = true;
+ }
}
else
{
@@ -4281,6 +4517,26 @@ get_foreign_key_join_selectivity(PlannerInfo *root,
fkselec *= 1.0 / ref_tuples;
}
+
+ /*
+ * Common code for cases where we should use the smallest selectivity
+ * that would be computed for any one of the FK's clauses.
+ */
+ if (use_smallest_selectivity)
+ {
+ Selectivity thisfksel = 1.0;
+
+ foreach(cell, removedlist)
+ {
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
+ Selectivity csel;
+
+ csel = clause_selectivity(root, (Node *) rinfo,
+ 0, jointype, sjinfo);
+ thisfksel = Min(thisfksel, csel);
+ }
+ fkselec *= thisfksel;
+ }
}
*restrictlist = worklist;
@@ -4307,8 +4563,10 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)
/* Should only be applied to base relations that are subqueries */
Assert(rel->relid > 0);
+#ifdef USE_ASSERT_CHECKING
rte = planner_rt_fetch(rel->relid, root);
Assert(rte->rtekind == RTE_SUBQUERY);
+#endif
/*
* Copy raw number of output rows from subquery. All of its paths should
@@ -4325,11 +4583,10 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)
*/
foreach(lc, subroot->parse->targetList)
{
- TargetEntry *te = (TargetEntry *) lfirst(lc);
+ TargetEntry *te = lfirst_node(TargetEntry, lc);
Node *texpr = (Node *) te->expr;
int32 item_width = 0;
- Assert(IsA(te, TargetEntry));
/* junk columns aren't visible to upper query */
if (te->resjunk)
continue;
@@ -4410,6 +4667,33 @@ set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel)
}
/*
+ * set_function_size_estimates
+ * Set the size estimates for a base relation that is a function call.
+ *
+ * The rel's targetlist and restrictinfo list must have been constructed
+ * already.
+ *
+ * We set the same fields as set_tablefunc_size_estimates.
+ */
+void
+set_tablefunc_size_estimates(PlannerInfo *root, RelOptInfo *rel)
+{
+ RangeTblEntry *rte PG_USED_FOR_ASSERTS_ONLY;
+
+ /* Should only be applied to base relations that are functions */
+ Assert(rel->relid > 0);
+#ifdef USE_ASSERT_CHECKING
+ rte = planner_rt_fetch(rel->relid, root);
+ Assert(rte->rtekind == RTE_TABLEFUNC);
+#endif
+
+ rel->tuples = 100;
+
+ /* Now estimate number of output rows, etc */
+ set_baserel_size_estimates(root, rel);
+}
+
+/*
* set_values_size_estimates
* Set the size estimates for a base relation that is a values list.
*
@@ -4479,6 +4763,39 @@ set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel, double cte_rows)
}
/*
+ * set_namedtuplestore_size_estimates
+ * Set the size estimates for a base relation that is a tuplestore reference.
+ *
+ * The rel's targetlist and restrictinfo list must have been constructed
+ * already.
+ *
+ * We set the same fields as set_baserel_size_estimates.
+ */
+void
+set_namedtuplestore_size_estimates(PlannerInfo *root, RelOptInfo *rel)
+{
+ RangeTblEntry *rte;
+
+ /* Should only be applied to base relations that are tuplestore references */
+ Assert(rel->relid > 0);
+ rte = planner_rt_fetch(rel->relid, root);
+ Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
+
+ /*
+ * Use the estimate provided by the code which is generating the named
+ * tuplestore. In some cases, the actual number might be available; in
+ * others the same plan will be re-used, so a "typical" value might be
+ * estimated and used.
+ */
+ rel->tuples = rte->enrtuples;
+ if (rel->tuples < 0)
+ rel->tuples = 1000;
+
+ /* Now estimate number of output rows, etc */
+ set_baserel_size_estimates(root, rel);
+}
+
+/*
* set_foreign_size_estimates
* Set the size estimates for a base relation that is a foreign table.
*
@@ -4781,7 +5098,6 @@ page_size(double tuples, int width)
return ceil(relation_byte_size(tuples, width) / BLCKSZ);
}
-
#ifdef XCP
void
cost_remote_subplan(Path *path,
@@ -4807,3 +5123,97 @@ cost_remote_subplan(Path *path,
path->total_cost = startup_cost + run_cost;
}
#endif
+
+/*
+ * Estimate the fraction of the work that each worker will do given the
+ * number of workers budgeted for the path.
+ */
+static double
+get_parallel_divisor(Path *path)
+{
+ double parallel_divisor = path->parallel_workers;
+ double leader_contribution;
+
+ /*
+ * Early experience with parallel query suggests that when there is only
+ * one worker, the leader often makes a very substantial contribution to
+ * executing the parallel portion of the plan, but as more workers are
+ * added, it does less and less, because it's busy reading tuples from the
+ * workers and doing whatever non-parallel post-processing is needed. By
+ * the time we reach 4 workers, the leader no longer makes a meaningful
+ * contribution. Thus, for now, estimate that the leader spends 30% of
+ * its time servicing each worker, and the remainder executing the
+ * parallel plan.
+ */
+ leader_contribution = 1.0 - (0.3 * path->parallel_workers);
+ if (leader_contribution > 0)
+ parallel_divisor += leader_contribution;
+
+ return parallel_divisor;
+}
+
+/*
+ * compute_bitmap_pages
+ *
+ * compute number of pages fetched from heap in bitmap heap scan.
+ */
+double
+compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual,
+ int loop_count, Cost *cost, double *tuple)
+{
+ Cost indexTotalCost;
+ Selectivity indexSelectivity;
+ double T;
+ double pages_fetched;
+ double tuples_fetched;
+
+ /*
+ * Fetch total cost of obtaining the bitmap, as well as its total
+ * selectivity.
+ */
+ cost_bitmap_tree_node(bitmapqual, &indexTotalCost, &indexSelectivity);
+
+ /*
+ * Estimate number of main-table pages fetched.
+ */
+ tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples);
+
+ T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;
+
+ if (loop_count > 1)
+ {
+ /*
+ * For repeated bitmap scans, scale up the number of tuples fetched in
+ * the Mackert and Lohman formula by the number of scans, so that we
+ * estimate the number of pages fetched by all the scans. Then
+ * pro-rate for one scan.
+ */
+ pages_fetched = index_pages_fetched(tuples_fetched * loop_count,
+ baserel->pages,
+ get_indexpath_pages(bitmapqual),
+ root);
+ pages_fetched /= loop_count;
+ }
+ else
+ {
+ /*
+ * For a single scan, the number of heap pages that need to be fetched
+ * is the same as the Mackert and Lohman formula for the case T <= b
+ * (ie, no re-reads needed).
+ */
+ pages_fetched =
+ (2.0 * T * tuples_fetched) / (2.0 * T + tuples_fetched);
+ }
+
+ if (pages_fetched >= T)
+ pages_fetched = T;
+ else
+ pages_fetched = ceil(pages_fetched);
+
+ if (cost)
+ *cost = indexTotalCost;
+ if (tuple)
+ *tuple = tuples_fetched;
+
+ return pages_fetched;
+}
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 0e50ad5f34..67bd760fb4 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -6,7 +6,7 @@
* See src/backend/optimizer/README for discussion of EquivalenceClasses.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -16,6 +16,8 @@
*/
#include "postgres.h"
+#include <limits.h>
+
#include "access/stratnum.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
@@ -78,9 +80,16 @@ static bool reconsider_full_join_clause(PlannerInfo *root,
* care to mark an EquivalenceClass if it came from any such clauses. Also,
* we have to check that both sides are either pseudo-constants or strict
* functions of Vars, else they might not both go to NULL above the outer
- * join. (This is the reason why we need a failure return. It's more
+ * join. (This is the main reason why we need a failure return. It's more
* convenient to check this case here than at the call sites...)
*
+ * We also reject proposed equivalence clauses if they contain leaky functions
+ * and have security_level above zero. The EC evaluation rules require us to
+ * apply certain tests at certain joining levels, and we can't tolerate
+ * delaying any test on security_level grounds. By rejecting candidate clauses
+ * that might require security delays, we ensure it's safe to apply an EC
+ * clause as soon as it's supposed to be applied.
+ *
* On success return, we have also initialized the clause's left_ec/right_ec
* fields to point to the EquivalenceClass representing it. This saves lookup
* effort later.
@@ -120,6 +129,10 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
Assert(restrictinfo->left_ec == NULL);
Assert(restrictinfo->right_ec == NULL);
+ /* Reject if it is potentially postponable by security considerations */
+ if (restrictinfo->security_level > 0 && !restrictinfo->leakproof)
+ return false;
+
/* Extract info from given clause */
Assert(is_opclause(clause));
opno = ((OpExpr *) clause)->opno;
@@ -275,6 +288,10 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
{
ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
ec1->ec_below_outer_join |= below_outer_join;
+ ec1->ec_min_security = Min(ec1->ec_min_security,
+ restrictinfo->security_level);
+ ec1->ec_max_security = Max(ec1->ec_max_security,
+ restrictinfo->security_level);
/* mark the RI as associated with this eclass */
restrictinfo->left_ec = ec1;
restrictinfo->right_ec = ec1;
@@ -306,6 +323,10 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
ec1->ec_has_const |= ec2->ec_has_const;
/* can't need to set has_volatile */
ec1->ec_below_outer_join |= ec2->ec_below_outer_join;
+ ec1->ec_min_security = Min(ec1->ec_min_security,
+ ec2->ec_min_security);
+ ec1->ec_max_security = Max(ec1->ec_max_security,
+ ec2->ec_max_security);
ec2->ec_merged = ec1;
root->eq_classes = list_delete_ptr(root->eq_classes, ec2);
/* just to avoid debugging confusion w/ dangling pointers: */
@@ -315,6 +336,10 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
ec2->ec_relids = NULL;
ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
ec1->ec_below_outer_join |= below_outer_join;
+ ec1->ec_min_security = Min(ec1->ec_min_security,
+ restrictinfo->security_level);
+ ec1->ec_max_security = Max(ec1->ec_max_security,
+ restrictinfo->security_level);
/* mark the RI as associated with this eclass */
restrictinfo->left_ec = ec1;
restrictinfo->right_ec = ec1;
@@ -329,6 +354,10 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
false, item2_type);
ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
ec1->ec_below_outer_join |= below_outer_join;
+ ec1->ec_min_security = Min(ec1->ec_min_security,
+ restrictinfo->security_level);
+ ec1->ec_max_security = Max(ec1->ec_max_security,
+ restrictinfo->security_level);
/* mark the RI as associated with this eclass */
restrictinfo->left_ec = ec1;
restrictinfo->right_ec = ec1;
@@ -343,6 +372,10 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
false, item1_type);
ec2->ec_sources = lappend(ec2->ec_sources, restrictinfo);
ec2->ec_below_outer_join |= below_outer_join;
+ ec2->ec_min_security = Min(ec2->ec_min_security,
+ restrictinfo->security_level);
+ ec2->ec_max_security = Max(ec2->ec_max_security,
+ restrictinfo->security_level);
/* mark the RI as associated with this eclass */
restrictinfo->left_ec = ec2;
restrictinfo->right_ec = ec2;
@@ -366,6 +399,8 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
ec->ec_below_outer_join = below_outer_join;
ec->ec_broken = false;
ec->ec_sortref = 0;
+ ec->ec_min_security = restrictinfo->security_level;
+ ec->ec_max_security = restrictinfo->security_level;
ec->ec_merged = NULL;
em1 = add_eq_member(ec, item1, item1_relids, item1_nullable_relids,
false, item1_type);
@@ -639,6 +674,8 @@ get_eclass_for_sort_expr(PlannerInfo *root,
newec->ec_below_outer_join = false;
newec->ec_broken = false;
newec->ec_sortref = sortref;
+ newec->ec_min_security = UINT_MAX;
+ newec->ec_max_security = 0;
newec->ec_merged = NULL;
if (newec->ec_has_volatile && sortref == 0) /* should not happen */
@@ -834,6 +871,7 @@ generate_base_implied_equalities_const(PlannerInfo *root,
bms_copy(ec->ec_relids),
bms_union(cur_em->em_nullable_relids,
const_em->em_nullable_relids),
+ ec->ec_min_security,
ec->ec_below_outer_join,
cur_em->em_is_const);
}
@@ -890,6 +928,7 @@ generate_base_implied_equalities_no_const(PlannerInfo *root,
bms_copy(ec->ec_relids),
bms_union(prev_em->em_nullable_relids,
cur_em->em_nullable_relids),
+ ec->ec_min_security,
ec->ec_below_outer_join,
false);
}
@@ -1021,10 +1060,12 @@ generate_join_implied_equalities_for_ecs(PlannerInfo *root,
ListCell *lc;
/* If inner rel is a child, extra setup work is needed */
- if (inner_rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
+ if (IS_OTHER_REL(inner_rel))
{
+ Assert(!bms_is_empty(inner_rel->top_parent_relids));
+
/* Fetch relid set for the topmost parent rel */
- nominal_inner_relids = find_childrel_top_parent(root, inner_rel)->relids;
+ nominal_inner_relids = inner_rel->top_parent_relids;
/* ECs will be marked with the parent's relid, not the child's */
nominal_join_relids = bms_union(outer_relids, nominal_inner_relids);
}
@@ -1285,8 +1326,7 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
* mentioned in the ec_sources clauses, we have to be prepared to apply
* multiple levels of Var translation.
*/
- if (inner_rel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
- result != NIL)
+ if (IS_OTHER_REL(inner_rel) && result != NIL)
result = (List *) adjust_appendrel_attrs_multilevel(root,
(Node *) result,
inner_rel);
@@ -1313,7 +1353,13 @@ select_equality_operator(EquivalenceClass *ec, Oid lefttype, Oid righttype)
opno = get_opfamily_member(opfamily, lefttype, righttype,
BTEqualStrategyNumber);
- if (OidIsValid(opno))
+ if (!OidIsValid(opno))
+ continue;
+ /* If no barrier quals in query, don't worry about leaky operators */
+ if (ec->ec_max_security == 0)
+ return opno;
+ /* Otherwise, insist that selected operators be leakproof */
+ if (get_func_leakproof(get_opcode(opno)))
return opno;
}
return InvalidOid;
@@ -1380,7 +1426,8 @@ create_join_clause(PlannerInfo *root,
bms_union(leftem->em_relids,
rightem->em_relids),
bms_union(leftem->em_nullable_relids,
- rightem->em_nullable_relids));
+ rightem->em_nullable_relids),
+ ec->ec_min_security);
/* Mark the clause as redundant, or not */
rinfo->parent_ec = parent_ec;
@@ -1691,7 +1738,8 @@ reconsider_outer_join_clause(PlannerInfo *root, RestrictInfo *rinfo,
innervar,
cur_em->em_expr,
bms_copy(inner_relids),
- bms_copy(inner_nullable_relids));
+ bms_copy(inner_nullable_relids),
+ cur_ec->ec_min_security);
if (process_equivalence(root, newrinfo, true))
match = true;
}
@@ -1833,7 +1881,8 @@ reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo)
leftvar,
cur_em->em_expr,
bms_copy(left_relids),
- bms_copy(left_nullable_relids));
+ bms_copy(left_nullable_relids),
+ cur_ec->ec_min_security);
if (process_equivalence(root, newrinfo, true))
matchleft = true;
}
@@ -1847,7 +1896,8 @@ reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo)
rightvar,
cur_em->em_expr,
bms_copy(right_relids),
- bms_copy(right_nullable_relids));
+ bms_copy(right_nullable_relids),
+ cur_ec->ec_min_security);
if (process_equivalence(root, newrinfo, true))
matchright = true;
}
@@ -2131,6 +2181,9 @@ generate_implied_equalities_for_column(PlannerInfo *root,
Relids parent_relids;
ListCell *lc1;
+ /* Indexes are available only on base or "other" member relations. */
+ Assert(IS_SIMPLE_REL(rel));
+
/* If it's a child rel, we'll need to know what its parent(s) are */
if (is_child_rel)
parent_relids = find_childrel_parents(root, rel);
@@ -2364,8 +2417,11 @@ eclass_useful_for_merging(PlannerInfo *root,
*/
/* If specified rel is a child, we must consider the topmost parent rel */
- if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
- relids = find_childrel_top_parent(root, rel)->relids;
+ if (IS_OTHER_REL(rel))
+ {
+ Assert(!bms_is_empty(rel->top_parent_relids));
+ relids = rel->top_parent_relids;
+ }
else
relids = rel->relids;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 2952bfb7c2..607a8f97bf 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -4,7 +4,7 @@
* Routines to determine which indexes are usable for scanning a
* given relation, and create Paths accordingly.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -337,8 +337,12 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
bitmapqual = choose_bitmap_and(root, rel, bitindexpaths);
bpath = create_bitmap_heap_path(root, rel, bitmapqual,
- rel->lateral_relids, 1.0);
+ rel->lateral_relids, 1.0, 0);
add_path(rel, (Path *) bpath);
+
+ /* create a partial bitmap heap path */
+ if (rel->consider_parallel && rel->lateral_relids == NULL)
+ create_partial_bitmap_paths(root, rel, bitmapqual);
}
/*
@@ -410,7 +414,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
required_outer = get_bitmap_tree_required_outer(bitmapqual);
loop_count = get_loop_count(root, rel->relid, required_outer);
bpath = create_bitmap_heap_path(root, rel, bitmapqual,
- required_outer, loop_count);
+ required_outer, loop_count, 0);
add_path(rel, (Path *) bpath);
}
}
@@ -813,7 +817,7 @@ get_index_paths(PlannerInfo *root, RelOptInfo *rel,
/*
* build_index_paths
* Given an index and a set of index clauses for it, construct zero
- * or more IndexPaths.
+ * or more IndexPaths. It also constructs zero or more partial IndexPaths.
*
* We return a list of paths because (1) this routine checks some cases
* that should cause us to not generate any IndexPath, and (2) in some
@@ -1042,8 +1046,41 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
NoMovementScanDirection,
index_only_scan,
outer_relids,
- loop_count);
+ loop_count,
+ false);
result = lappend(result, ipath);
+
+ /*
+ * If appropriate, consider parallel index scan. We don't allow
+ * parallel index scan for bitmap index scans.
+ */
+ if (index->amcanparallel &&
+ rel->consider_parallel && outer_relids == NULL &&
+ scantype != ST_BITMAPSCAN)
+ {
+ ipath = create_index_path(root, index,
+ index_clauses,
+ clause_columns,
+ orderbyclauses,
+ orderbyclausecols,
+ useful_pathkeys,
+ index_is_ordered ?
+ ForwardScanDirection :
+ NoMovementScanDirection,
+ index_only_scan,
+ outer_relids,
+ loop_count,
+ true);
+
+ /*
+ * if, after costing the path, we find that it's not worth using
+ * parallel workers, just free it.
+ */
+ if (ipath->path.parallel_workers > 0)
+ add_partial_path(rel, (Path *) ipath);
+ else
+ pfree(ipath);
+ }
}
/*
@@ -1066,8 +1103,36 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
BackwardScanDirection,
index_only_scan,
outer_relids,
- loop_count);
+ loop_count,
+ false);
result = lappend(result, ipath);
+
+ /* If appropriate, consider parallel index scan */
+ if (index->amcanparallel &&
+ rel->consider_parallel && outer_relids == NULL &&
+ scantype != ST_BITMAPSCAN)
+ {
+ ipath = create_index_path(root, index,
+ index_clauses,
+ clause_columns,
+ NIL,
+ NIL,
+ useful_pathkeys,
+ BackwardScanDirection,
+ index_only_scan,
+ outer_relids,
+ loop_count,
+ true);
+
+ /*
+ * if, after costing the path, we find that it's not worth
+ * using parallel workers, just free it.
+ */
+ if (ipath->path.parallel_workers > 0)
+ add_partial_path(rel, (Path *) ipath);
+ else
+ pfree(ipath);
+ }
}
}
@@ -1212,12 +1277,11 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
foreach(lc, clauses)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
List *pathlist;
Path *bitmapqual;
ListCell *j;
- Assert(IsA(rinfo, RestrictInfo));
/* Ignore RestrictInfos that aren't ORs */
if (!restriction_is_or_clause(rinfo))
continue;
@@ -1249,11 +1313,11 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
}
else
{
+ RestrictInfo *rinfo = castNode(RestrictInfo, orarg);
List *orargs;
- Assert(IsA(orarg, RestrictInfo));
- Assert(!restriction_is_or_clause((RestrictInfo *) orarg));
- orargs = list_make1(orarg);
+ Assert(!restriction_is_or_clause(rinfo));
+ orargs = list_make1(rinfo);
indlist = build_paths_for_OR(root, rel,
orargs,
@@ -1557,6 +1621,11 @@ bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath)
bpath.path.pathkeys = NIL;
bpath.bitmapqual = ipath;
+ /*
+ * Check the cost of temporary path without considering parallelism.
+ * Parallel bitmap heap path will be considered at later stage.
+ */
+ bpath.path.parallel_workers = 0;
cost_bitmap_heap_scan(&bpath.path, root, rel,
bpath.path.param_info,
ipath,
@@ -1599,6 +1668,12 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
bpath.path.pathkeys = NIL;
bpath.bitmapqual = (Path *) &apath;
+ /*
+ * Check the cost of temporary path without considering parallelism.
+ * Parallel bitmap heap path will be considered at later stage.
+ */
+ bpath.path.parallel_workers = 0;
+
/* Now we can do cost_bitmap_heap_scan */
cost_bitmap_heap_scan(&bpath.path, root, rel,
bpath.path.param_info,
@@ -2113,9 +2188,8 @@ match_clauses_to_index(IndexOptInfo *index,
foreach(lc, clauses)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
- Assert(IsA(rinfo, RestrictInfo));
match_clause_to_index(index, rinfo, clauseset);
}
}
@@ -2143,6 +2217,23 @@ match_clause_to_index(IndexOptInfo *index,
{
int indexcol;
+ /*
+ * Never match pseudoconstants to indexes. (Normally a match could not
+ * happen anyway, since a pseudoconstant clause couldn't contain a Var,
+ * but what if someone builds an expression index on a constant? It's not
+ * totally unreasonable to do so with a partial index, either.)
+ */
+ if (rinfo->pseudoconstant)
+ return;
+
+ /*
+ * If clause can't be used as an indexqual because it must wait till after
+ * some lower-security-level restriction clause, reject it.
+ */
+ if (!restriction_is_securely_promotable(rinfo, index->rel))
+ return;
+
+ /* OK, check each index column for a match */
for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
{
if (match_clause_to_indexcol(index,
@@ -2237,15 +2328,6 @@ match_clause_to_indexcol(IndexOptInfo *index,
Oid expr_coll;
bool plain_op;
- /*
- * Never match pseudoconstants to indexes. (Normally this could not
- * happen anyway, since a pseudoconstant clause couldn't contain a Var,
- * but what if someone builds an expression index on a constant? It's not
- * totally unreasonable to do so with a partial index, either.)
- */
- if (rinfo->pseudoconstant)
- return false;
-
/* First check for boolean-index cases. */
if (IsBooleanOpfamily(opfamily))
{
@@ -2697,6 +2779,9 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
Relids otherrels;
ListCell *lc;
+ /* Indexes are available only on base or "other" member relations. */
+ Assert(IS_SIMPLE_REL(rel));
+
/*
* Initialize the indrestrictinfo lists to be identical to
* baserestrictinfo, and check whether there are any partial indexes. If
@@ -3025,6 +3110,52 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
return false;
}
+/*
+ * indexcol_is_bool_constant_for_query
+ *
+ * If an index column is constrained to have a constant value by the query's
+ * WHERE conditions, then it's irrelevant for sort-order considerations.
+ * Usually that means we have a restriction clause WHERE indexcol = constant,
+ * which gets turned into an EquivalenceClass containing a constant, which
+ * is recognized as redundant by build_index_pathkeys(). But if the index
+ * column is a boolean variable (or expression), then we are not going to
+ * see WHERE indexcol = constant, because expression preprocessing will have
+ * simplified that to "WHERE indexcol" or "WHERE NOT indexcol". So we are not
+ * going to have a matching EquivalenceClass (unless the query also contains
+ * "ORDER BY indexcol"). To allow such cases to work the same as they would
+ * for non-boolean values, this function is provided to detect whether the
+ * specified index column matches a boolean restriction clause.
+ */
+bool
+indexcol_is_bool_constant_for_query(IndexOptInfo *index, int indexcol)
+{
+ ListCell *lc;
+
+ /* If the index isn't boolean, we can't possibly get a match */
+ if (!IsBooleanOpfamily(index->opfamily[indexcol]))
+ return false;
+
+ /* Check each restriction clause for the index's rel */
+ foreach(lc, index->rel->baserestrictinfo)
+ {
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+
+ /*
+ * As in match_clause_to_indexcol, never match pseudoconstants to
+ * indexes. (It might be semantically okay to do so here, but the
+ * odds of getting a match are negligible, so don't waste the cycles.)
+ */
+ if (rinfo->pseudoconstant)
+ continue;
+
+ /* See if we can match the clause's expression to the index column */
+ if (match_boolean_index_clause((Node *) rinfo->clause, indexcol, index))
+ return true;
+ }
+
+ return false;
+}
+
/****************************************************************************
* ---- ROUTINES TO CHECK OPERANDS ----
@@ -3876,9 +4007,9 @@ adjust_rowcompare_for_index(RowCompareExpr *clause,
matching_cols);
rc->inputcollids = list_truncate(list_copy(clause->inputcollids),
matching_cols);
- rc->largs = list_truncate((List *) copyObject(clause->largs),
+ rc->largs = list_truncate(copyObject(clause->largs),
matching_cols);
- rc->rargs = list_truncate((List *) copyObject(clause->rargs),
+ rc->rargs = list_truncate(copyObject(clause->rargs),
matching_cols);
return (Expr *) rc;
}
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index cc7384f7e5..c130d2f17f 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -3,7 +3,7 @@
* joinpath.c
* Routines to find all possible paths for processing a set of joins
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -21,6 +21,7 @@
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
+#include "optimizer/planmain.h"
/* Hook for plugins to get control in add_paths_to_joinrel() */
set_join_pathlist_hook_type set_join_pathlist_hook = NULL;
@@ -28,6 +29,16 @@ set_join_pathlist_hook_type set_join_pathlist_hook = NULL;
#define PATH_PARAM_BY_REL(path, rel) \
((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids))
+static void try_partial_mergejoin_path(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ Path *outer_path,
+ Path *inner_path,
+ List *pathkeys,
+ List *mergeclauses,
+ List *outersortkeys,
+ List *innersortkeys,
+ JoinType jointype,
+ JoinPathExtraData *extra);
static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *outerrel, RelOptInfo *innerrel,
JoinType jointype, JoinPathExtraData *extra);
@@ -40,6 +51,13 @@ static void consider_parallel_nestloop(PlannerInfo *root,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
+static void consider_parallel_mergejoin(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ JoinPathExtraData *extra,
+ Path *inner_cheapest_total);
static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *outerrel, RelOptInfo *innerrel,
JoinType jointype, JoinPathExtraData *extra);
@@ -50,6 +68,16 @@ static List *select_mergejoin_clauses(PlannerInfo *root,
List *restrictlist,
JoinType jointype,
bool *mergejoin_allowed);
+static void generate_mergejoin_paths(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *innerrel,
+ Path *outerpath,
+ JoinType jointype,
+ JoinPathExtraData *extra,
+ bool useallclauses,
+ Path *inner_cheapest_total,
+ List *merge_pathkeys,
+ bool is_partial);
/*
@@ -94,6 +122,49 @@ add_paths_to_joinrel(PlannerInfo *root,
extra.param_source_rels = NULL;
/*
+ * See if the inner relation is provably unique for this outer rel.
+ *
+ * We have some special cases: for JOIN_SEMI and JOIN_ANTI, it doesn't
+ * matter since the executor can make the equivalent optimization anyway;
+ * we need not expend planner cycles on proofs. For JOIN_UNIQUE_INNER, we
+ * must be considering a semijoin whose inner side is not provably unique
+ * (else reduce_unique_semijoins would've simplified it), so there's no
+ * point in calling innerrel_is_unique. However, if the LHS covers all of
+ * the semijoin's min_lefthand, then it's appropriate to set inner_unique
+ * because the path produced by create_unique_path will be unique relative
+ * to the LHS. (If we have an LHS that's only part of the min_lefthand,
+ * that is *not* true.) For JOIN_UNIQUE_OUTER, pass JOIN_INNER to avoid
+ * letting that value escape this module.
+ */
+ switch (jointype)
+ {
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ extra.inner_unique = false; /* well, unproven */
+ break;
+ case JOIN_UNIQUE_INNER:
+ extra.inner_unique = bms_is_subset(sjinfo->min_lefthand,
+ outerrel->relids);
+ break;
+ case JOIN_UNIQUE_OUTER:
+ extra.inner_unique = innerrel_is_unique(root,
+ outerrel->relids,
+ innerrel,
+ JOIN_INNER,
+ restrictlist,
+ false);
+ break;
+ default:
+ extra.inner_unique = innerrel_is_unique(root,
+ outerrel->relids,
+ innerrel,
+ jointype,
+ restrictlist,
+ false);
+ break;
+ }
+
+ /*
* Find potential mergejoin clauses. We can skip this if we are not
* interested in doing a mergejoin. However, mergejoin may be our only
* way of implementing a full outer join, so override enable_mergejoin if
@@ -109,10 +180,10 @@ add_paths_to_joinrel(PlannerInfo *root,
&mergejoin_allowed);
/*
- * If it's SEMI or ANTI join, compute correction factors for cost
- * estimation. These will be the same for all paths.
+ * If it's SEMI, ANTI, or inner_unique join, compute correction factors
+ * for cost estimation. These will be the same for all paths.
*/
- if (jointype == JOIN_SEMI || jointype == JOIN_ANTI)
+ if (jointype == JOIN_SEMI || jointype == JOIN_ANTI || extra.inner_unique)
compute_semi_anti_join_factors(root, outerrel, innerrel,
jointype, sjinfo, restrictlist,
&extra.semifactors);
@@ -131,7 +202,7 @@ add_paths_to_joinrel(PlannerInfo *root,
*/
foreach(lc, root->join_info_list)
{
- SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
+ SpecialJoinInfo *sjinfo2 = (SpecialJoinInfo *) lfirst(lc);
/*
* SJ is relevant to this join if we have some part of its RHS
@@ -140,19 +211,19 @@ add_paths_to_joinrel(PlannerInfo *root,
* join has already been proven legal.) If the SJ is relevant, it
* presents constraints for joining to anything not in its RHS.
*/
- if (bms_overlap(joinrel->relids, sjinfo->min_righthand) &&
- !bms_overlap(joinrel->relids, sjinfo->min_lefthand))
+ if (bms_overlap(joinrel->relids, sjinfo2->min_righthand) &&
+ !bms_overlap(joinrel->relids, sjinfo2->min_lefthand))
extra.param_source_rels = bms_join(extra.param_source_rels,
bms_difference(root->all_baserels,
- sjinfo->min_righthand));
+ sjinfo2->min_righthand));
/* full joins constrain both sides symmetrically */
- if (sjinfo->jointype == JOIN_FULL &&
- bms_overlap(joinrel->relids, sjinfo->min_lefthand) &&
- !bms_overlap(joinrel->relids, sjinfo->min_righthand))
+ if (sjinfo2->jointype == JOIN_FULL &&
+ bms_overlap(joinrel->relids, sjinfo2->min_lefthand) &&
+ !bms_overlap(joinrel->relids, sjinfo2->min_righthand))
extra.param_source_rels = bms_join(extra.param_source_rels,
bms_difference(root->all_baserels,
- sjinfo->min_lefthand));
+ sjinfo2->min_lefthand));
}
/*
@@ -309,8 +380,7 @@ try_nestloop_path(PlannerInfo *root,
* methodology worthwhile.
*/
initial_cost_nestloop(root, &workspace, jointype,
- outer_path, inner_path,
- extra->sjinfo, &extra->semifactors);
+ outer_path, inner_path, extra);
if (add_path_precheck(joinrel,
workspace.startup_cost, workspace.total_cost,
@@ -321,8 +391,7 @@ try_nestloop_path(PlannerInfo *root,
joinrel,
jointype,
&workspace,
- extra->sjinfo,
- &extra->semifactors,
+ extra,
outer_path,
inner_path,
extra->restrictlist,
@@ -372,8 +441,7 @@ try_partial_nestloop_path(PlannerInfo *root,
* cost. Bail out right away if it looks terrible.
*/
initial_cost_nestloop(root, &workspace, jointype,
- outer_path, inner_path,
- extra->sjinfo, &extra->semifactors);
+ outer_path, inner_path, extra);
if (!add_partial_path_precheck(joinrel, workspace.total_cost, pathkeys))
return;
@@ -383,8 +451,7 @@ try_partial_nestloop_path(PlannerInfo *root,
joinrel,
jointype,
&workspace,
- extra->sjinfo,
- &extra->semifactors,
+ extra,
outer_path,
inner_path,
extra->restrictlist,
@@ -407,11 +474,27 @@ try_mergejoin_path(PlannerInfo *root,
List *outersortkeys,
List *innersortkeys,
JoinType jointype,
- JoinPathExtraData *extra)
+ JoinPathExtraData *extra,
+ bool is_partial)
{
Relids required_outer;
JoinCostWorkspace workspace;
+ if (is_partial)
+ {
+ try_partial_mergejoin_path(root,
+ joinrel,
+ outer_path,
+ inner_path,
+ pathkeys,
+ mergeclauses,
+ outersortkeys,
+ innersortkeys,
+ jointype,
+ extra);
+ return;
+ }
+
/*
* Check to see if proposed path is still parameterized, and reject if the
* parameterization wouldn't be sensible.
@@ -443,7 +526,7 @@ try_mergejoin_path(PlannerInfo *root,
initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
outer_path, inner_path,
outersortkeys, innersortkeys,
- extra->sjinfo);
+ extra);
if (add_path_precheck(joinrel,
workspace.startup_cost, workspace.total_cost,
@@ -454,7 +537,7 @@ try_mergejoin_path(PlannerInfo *root,
joinrel,
jointype,
&workspace,
- extra->sjinfo,
+ extra,
outer_path,
inner_path,
extra->restrictlist,
@@ -472,6 +555,76 @@ try_mergejoin_path(PlannerInfo *root,
}
/*
+ * try_partial_mergejoin_path
+ * Consider a partial merge join path; if it appears useful, push it into
+ * the joinrel's pathlist via add_partial_path().
+ */
+static void
+try_partial_mergejoin_path(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ Path *outer_path,
+ Path *inner_path,
+ List *pathkeys,
+ List *mergeclauses,
+ List *outersortkeys,
+ List *innersortkeys,
+ JoinType jointype,
+ JoinPathExtraData *extra)
+{
+ JoinCostWorkspace workspace;
+
+ /*
+ * See comments in try_partial_hashjoin_path().
+ */
+ Assert(bms_is_empty(joinrel->lateral_relids));
+ if (inner_path->param_info != NULL)
+ {
+ Relids inner_paramrels = inner_path->param_info->ppi_req_outer;
+
+ if (!bms_is_empty(inner_paramrels))
+ return;
+ }
+
+ /*
+ * If the given paths are already well enough ordered, we can skip doing
+ * an explicit sort.
+ */
+ if (outersortkeys &&
+ pathkeys_contained_in(outersortkeys, outer_path->pathkeys))
+ outersortkeys = NIL;
+ if (innersortkeys &&
+ pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
+ innersortkeys = NIL;
+
+ /*
+ * See comments in try_partial_nestloop_path().
+ */
+ initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
+ outer_path, inner_path,
+ outersortkeys, innersortkeys,
+ extra);
+
+ if (!add_partial_path_precheck(joinrel, workspace.total_cost, pathkeys))
+ return;
+
+ /* Might be good enough to be worth trying, so let's try it. */
+ add_partial_path(joinrel, (Path *)
+ create_mergejoin_path(root,
+ joinrel,
+ jointype,
+ &workspace,
+ extra,
+ outer_path,
+ inner_path,
+ extra->restrictlist,
+ pathkeys,
+ NULL,
+ mergeclauses,
+ outersortkeys,
+ innersortkeys));
+}
+
+/*
* try_hashjoin_path
* Consider a hash join path; if it appears useful, push it into
* the joinrel's pathlist via add_path().
@@ -507,8 +660,7 @@ try_hashjoin_path(PlannerInfo *root,
* never have any output pathkeys, per comments in create_hashjoin_path.
*/
initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
- outer_path, inner_path,
- extra->sjinfo, &extra->semifactors);
+ outer_path, inner_path, extra);
if (add_path_precheck(joinrel,
workspace.startup_cost, workspace.total_cost,
@@ -519,8 +671,7 @@ try_hashjoin_path(PlannerInfo *root,
joinrel,
jointype,
&workspace,
- extra->sjinfo,
- &extra->semifactors,
+ extra,
outer_path,
inner_path,
extra->restrictlist,
@@ -570,8 +721,7 @@ try_partial_hashjoin_path(PlannerInfo *root,
* cost. Bail out right away if it looks terrible.
*/
initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
- outer_path, inner_path,
- extra->sjinfo, &extra->semifactors);
+ outer_path, inner_path, extra);
if (!add_partial_path_precheck(joinrel, workspace.total_cost, NIL))
return;
@@ -581,8 +731,7 @@ try_partial_hashjoin_path(PlannerInfo *root,
joinrel,
jointype,
&workspace,
- extra->sjinfo,
- &extra->semifactors,
+ extra,
outer_path,
inner_path,
extra->restrictlist,
@@ -640,8 +789,11 @@ sort_inner_and_outer(PlannerInfo *root,
JoinType jointype,
JoinPathExtraData *extra)
{
+ JoinType save_jointype = jointype;
Path *outer_path;
Path *inner_path;
+ Path *cheapest_partial_outer = NULL;
+ Path *cheapest_safe_inner = NULL;
List *all_pathkeys;
ListCell *l;
@@ -691,6 +843,30 @@ sort_inner_and_outer(PlannerInfo *root,
}
/*
+ * If the joinrel is parallel-safe, we may be able to consider a partial
+ * merge join. However, we can't handle JOIN_UNIQUE_OUTER, because the
+ * outer path will be partial, and therefore we won't be able to properly
+ * guarantee uniqueness. Similarly, we can't handle JOIN_FULL and
+ * JOIN_RIGHT, because they can produce false null extended rows. Also,
+ * the resulting path must not be parameterized.
+ */
+ if (joinrel->consider_parallel &&
+ save_jointype != JOIN_UNIQUE_OUTER &&
+ save_jointype != JOIN_FULL &&
+ save_jointype != JOIN_RIGHT &&
+ outerrel->partial_pathlist != NIL &&
+ bms_is_empty(joinrel->lateral_relids))
+ {
+ cheapest_partial_outer = (Path *) linitial(outerrel->partial_pathlist);
+
+ if (inner_path->parallel_safe)
+ cheapest_safe_inner = inner_path;
+ else if (save_jointype != JOIN_UNIQUE_INNER)
+ cheapest_safe_inner =
+ get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
+ }
+
+ /*
* Each possible ordering of the available mergejoin clauses will generate
* a differently-sorted result path at essentially the same cost. We have
* no basis for choosing one over another at this level of joining, but
@@ -772,7 +948,265 @@ sort_inner_and_outer(PlannerInfo *root,
outerkeys,
innerkeys,
jointype,
- extra);
+ extra,
+ false);
+
+ /*
+ * If we have partial outer and parallel safe inner path then try
+ * partial mergejoin path.
+ */
+ if (cheapest_partial_outer && cheapest_safe_inner)
+ try_partial_mergejoin_path(root,
+ joinrel,
+ cheapest_partial_outer,
+ cheapest_safe_inner,
+ merge_pathkeys,
+ cur_mergeclauses,
+ outerkeys,
+ innerkeys,
+ jointype,
+ extra);
+ }
+}
+
+/*
+ * generate_mergejoin_paths
+ * Creates possible mergejoin paths for input outerpath.
+ *
+ * We generate mergejoins if mergejoin clauses are available. We have
+ * two ways to generate the inner path for a mergejoin: sort the cheapest
+ * inner path, or use an inner path that is already suitably ordered for the
+ * merge. If we have several mergeclauses, it could be that there is no inner
+ * path (or only a very expensive one) for the full list of mergeclauses, but
+ * better paths exist if we truncate the mergeclause list (thereby discarding
+ * some sort key requirements). So, we consider truncations of the
+ * mergeclause list as well as the full list. (Ideally we'd consider all
+ * subsets of the mergeclause list, but that seems way too expensive.)
+ */
+static void
+generate_mergejoin_paths(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *innerrel,
+ Path *outerpath,
+ JoinType jointype,
+ JoinPathExtraData *extra,
+ bool useallclauses,
+ Path *inner_cheapest_total,
+ List *merge_pathkeys,
+ bool is_partial)
+{
+ List *mergeclauses;
+ List *innersortkeys;
+ List *trialsortkeys;
+ Path *cheapest_startup_inner;
+ Path *cheapest_total_inner;
+ JoinType save_jointype = jointype;
+ int num_sortkeys;
+ int sortkeycnt;
+
+ if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
+ jointype = JOIN_INNER;
+
+ /* Look for useful mergeclauses (if any) */
+ mergeclauses = find_mergeclauses_for_pathkeys(root,
+ outerpath->pathkeys,
+ true,
+ extra->mergeclause_list);
+
+ /*
+ * Done with this outer path if no chance for a mergejoin.
+ *
+ * Special corner case: for "x FULL JOIN y ON true", there will be no join
+ * clauses at all. Ordinarily we'd generate a clauseless nestloop path,
+ * but since mergejoin is our only join type that supports FULL JOIN
+ * without any join clauses, it's necessary to generate a clauseless
+ * mergejoin path instead.
+ */
+ if (mergeclauses == NIL)
+ {
+ if (jointype == JOIN_FULL)
+ /* okay to try for mergejoin */ ;
+ else
+ return;
+ }
+ if (useallclauses &&
+ list_length(mergeclauses) != list_length(extra->mergeclause_list))
+ return;
+
+ /* Compute the required ordering of the inner path */
+ innersortkeys = make_inner_pathkeys_for_merge(root,
+ mergeclauses,
+ outerpath->pathkeys);
+
+ /*
+ * Generate a mergejoin on the basis of sorting the cheapest inner. Since
+ * a sort will be needed, only cheapest total cost matters. (But
+ * try_mergejoin_path will do the right thing if inner_cheapest_total is
+ * already correctly sorted.)
+ */
+ try_mergejoin_path(root,
+ joinrel,
+ outerpath,
+ inner_cheapest_total,
+ merge_pathkeys,
+ mergeclauses,
+ NIL,
+ innersortkeys,
+ jointype,
+ extra,
+ is_partial);
+
+ /* Can't do anything else if inner path needs to be unique'd */
+ if (save_jointype == JOIN_UNIQUE_INNER)
+ return;
+
+ /*
+ * Look for presorted inner paths that satisfy the innersortkey list ---
+ * or any truncation thereof, if we are allowed to build a mergejoin using
+ * a subset of the merge clauses. Here, we consider both cheap startup
+ * cost and cheap total cost.
+ *
+ * Currently we do not consider parameterized inner paths here. This
+ * interacts with decisions elsewhere that also discriminate against
+ * mergejoins with parameterized inputs; see comments in
+ * src/backend/optimizer/README.
+ *
+ * As we shorten the sortkey list, we should consider only paths that are
+ * strictly cheaper than (in particular, not the same as) any path found
+ * in an earlier iteration. Otherwise we'd be intentionally using fewer
+ * merge keys than a given path allows (treating the rest as plain
+ * joinquals), which is unlikely to be a good idea. Also, eliminating
+ * paths here on the basis of compare_path_costs is a lot cheaper than
+ * building the mergejoin path only to throw it away.
+ *
+ * If inner_cheapest_total is well enough sorted to have not required a
+ * sort in the path made above, we shouldn't make a duplicate path with
+ * it, either. We handle that case with the same logic that handles the
+ * previous consideration, by initializing the variables that track
+ * cheapest-so-far properly. Note that we do NOT reject
+ * inner_cheapest_total if we find it matches some shorter set of
+ * pathkeys. That case corresponds to using fewer mergekeys to avoid
+ * sorting inner_cheapest_total, whereas we did sort it above, so the
+ * plans being considered are different.
+ */
+ if (pathkeys_contained_in(innersortkeys,
+ inner_cheapest_total->pathkeys))
+ {
+ /* inner_cheapest_total didn't require a sort */
+ cheapest_startup_inner = inner_cheapest_total;
+ cheapest_total_inner = inner_cheapest_total;
+ }
+ else
+ {
+ /* it did require a sort, at least for the full set of keys */
+ cheapest_startup_inner = NULL;
+ cheapest_total_inner = NULL;
+ }
+ num_sortkeys = list_length(innersortkeys);
+ if (num_sortkeys > 1 && !useallclauses)
+ trialsortkeys = list_copy(innersortkeys); /* need modifiable copy */
+ else
+ trialsortkeys = innersortkeys; /* won't really truncate */
+
+ for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
+ {
+ Path *innerpath;
+ List *newclauses = NIL;
+
+ /*
+ * Look for an inner path ordered well enough for the first
+ * 'sortkeycnt' innersortkeys. NB: trialsortkeys list is modified
+ * destructively, which is why we made a copy...
+ */
+ trialsortkeys = list_truncate(trialsortkeys, sortkeycnt);
+ innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
+ trialsortkeys,
+ NULL,
+ TOTAL_COST,
+ is_partial);
+ if (innerpath != NULL &&
+ (cheapest_total_inner == NULL ||
+ compare_path_costs(innerpath, cheapest_total_inner,
+ TOTAL_COST) < 0))
+ {
+ /* Found a cheap (or even-cheaper) sorted path */
+ /* Select the right mergeclauses, if we didn't already */
+ if (sortkeycnt < num_sortkeys)
+ {
+ newclauses =
+ find_mergeclauses_for_pathkeys(root,
+ trialsortkeys,
+ false,
+ mergeclauses);
+ Assert(newclauses != NIL);
+ }
+ else
+ newclauses = mergeclauses;
+ try_mergejoin_path(root,
+ joinrel,
+ outerpath,
+ innerpath,
+ merge_pathkeys,
+ newclauses,
+ NIL,
+ NIL,
+ jointype,
+ extra,
+ is_partial);
+ cheapest_total_inner = innerpath;
+ }
+ /* Same on the basis of cheapest startup cost ... */
+ innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
+ trialsortkeys,
+ NULL,
+ STARTUP_COST,
+ is_partial);
+ if (innerpath != NULL &&
+ (cheapest_startup_inner == NULL ||
+ compare_path_costs(innerpath, cheapest_startup_inner,
+ STARTUP_COST) < 0))
+ {
+ /* Found a cheap (or even-cheaper) sorted path */
+ if (innerpath != cheapest_total_inner)
+ {
+ /*
+ * Avoid rebuilding clause list if we already made one; saves
+ * memory in big join trees...
+ */
+ if (newclauses == NIL)
+ {
+ if (sortkeycnt < num_sortkeys)
+ {
+ newclauses =
+ find_mergeclauses_for_pathkeys(root,
+ trialsortkeys,
+ false,
+ mergeclauses);
+ Assert(newclauses != NIL);
+ }
+ else
+ newclauses = mergeclauses;
+ }
+ try_mergejoin_path(root,
+ joinrel,
+ outerpath,
+ innerpath,
+ merge_pathkeys,
+ newclauses,
+ NIL,
+ NIL,
+ jointype,
+ extra,
+ is_partial);
+ }
+ cheapest_startup_inner = innerpath;
+ }
+
+ /*
+ * Don't consider truncated sortkeys if we need all clauses.
+ */
+ if (useallclauses)
+ break;
}
}
@@ -790,15 +1224,8 @@ sort_inner_and_outer(PlannerInfo *root,
* cheapest-total inner-indexscan path (if any), and one on the
* cheapest-startup inner-indexscan path (if different).
*
- * We also consider mergejoins if mergejoin clauses are available. We have
- * two ways to generate the inner path for a mergejoin: sort the cheapest
- * inner path, or use an inner path that is already suitably ordered for the
- * merge. If we have several mergeclauses, it could be that there is no inner
- * path (or only a very expensive one) for the full list of mergeclauses, but
- * better paths exist if we truncate the mergeclause list (thereby discarding
- * some sort key requirements). So, we consider truncations of the
- * mergeclause list as well as the full list. (Ideally we'd consider all
- * subsets of the mergeclause list, but that seems way too expensive.)
+ * We also consider mergejoins if mergejoin clauses are available. See
+ * detailed comments in generate_mergejoin_paths.
*
* 'joinrel' is the join relation
* 'outerrel' is the outer join relation
@@ -894,13 +1321,6 @@ match_unsorted_outer(PlannerInfo *root,
{
Path *outerpath = (Path *) lfirst(lc1);
List *merge_pathkeys;
- List *mergeclauses;
- List *innersortkeys;
- List *trialsortkeys;
- Path *cheapest_startup_inner;
- Path *cheapest_total_inner;
- int num_sortkeys;
- int sortkeycnt;
/*
* We cannot use an outer path that is parameterized by the inner rel.
@@ -986,216 +1406,94 @@ match_unsorted_outer(PlannerInfo *root,
if (inner_cheapest_total == NULL)
continue;
- /* Look for useful mergeclauses (if any) */
- mergeclauses = find_mergeclauses_for_pathkeys(root,
- outerpath->pathkeys,
- true,
- extra->mergeclause_list);
+ /* Generate merge join paths */
+ generate_mergejoin_paths(root, joinrel, innerrel, outerpath,
+ save_jointype, extra, useallclauses,
+ inner_cheapest_total, merge_pathkeys,
+ false);
+ }
+
+ /*
+ * Consider partial nestloop and mergejoin plan if outerrel has any
+ * partial path and the joinrel is parallel-safe. However, we can't
+ * handle JOIN_UNIQUE_OUTER, because the outer path will be partial, and
+ * therefore we won't be able to properly guarantee uniqueness. Nor can
+ * we handle extra_lateral_rels, since partial paths must not be
+ * parameterized. Similarly, we can't handle JOIN_FULL and JOIN_RIGHT,
+ * because they can produce false null extended rows.
+ */
+ if (joinrel->consider_parallel &&
+ save_jointype != JOIN_UNIQUE_OUTER &&
+ save_jointype != JOIN_FULL &&
+ save_jointype != JOIN_RIGHT &&
+ outerrel->partial_pathlist != NIL &&
+ bms_is_empty(joinrel->lateral_relids))
+ {
+ if (nestjoinOK)
+ consider_parallel_nestloop(root, joinrel, outerrel, innerrel,
+ save_jointype, extra);
/*
- * Done with this outer path if no chance for a mergejoin.
- *
- * Special corner case: for "x FULL JOIN y ON true", there will be no
- * join clauses at all. Ordinarily we'd generate a clauseless
- * nestloop path, but since mergejoin is our only join type that
- * supports FULL JOIN without any join clauses, it's necessary to
- * generate a clauseless mergejoin path instead.
+ * If inner_cheapest_total is NULL or non parallel-safe then find the
+ * cheapest total parallel safe path. If doing JOIN_UNIQUE_INNER, we
+ * can't use any alternative inner path.
*/
- if (mergeclauses == NIL)
+ if (inner_cheapest_total == NULL ||
+ !inner_cheapest_total->parallel_safe)
{
- if (jointype == JOIN_FULL)
- /* okay to try for mergejoin */ ;
- else
- continue;
+ if (save_jointype == JOIN_UNIQUE_INNER)
+ return;
+
+ inner_cheapest_total = get_cheapest_parallel_safe_total_inner(
+ innerrel->pathlist);
}
- if (useallclauses && list_length(mergeclauses) != list_length(extra->mergeclause_list))
- continue;
- /* Compute the required ordering of the inner path */
- innersortkeys = make_inner_pathkeys_for_merge(root,
- mergeclauses,
- outerpath->pathkeys);
+ if (inner_cheapest_total)
+ consider_parallel_mergejoin(root, joinrel, outerrel, innerrel,
+ save_jointype, extra,
+ inner_cheapest_total);
+ }
+}
- /*
- * Generate a mergejoin on the basis of sorting the cheapest inner.
- * Since a sort will be needed, only cheapest total cost matters. (But
- * try_mergejoin_path will do the right thing if inner_cheapest_total
- * is already correctly sorted.)
- */
- try_mergejoin_path(root,
- joinrel,
- outerpath,
- inner_cheapest_total,
- merge_pathkeys,
- mergeclauses,
- NIL,
- innersortkeys,
- jointype,
- extra);
+/*
+ * consider_parallel_mergejoin
+ * Try to build partial paths for a joinrel by joining a partial path
+ * for the outer relation to a complete path for the inner relation.
+ *
+ * 'joinrel' is the join relation
+ * 'outerrel' is the outer join relation
+ * 'innerrel' is the inner join relation
+ * 'jointype' is the type of join to do
+ * 'extra' contains additional input values
+ * 'inner_cheapest_total' cheapest total path for innerrel
+ */
+static void
+consider_parallel_mergejoin(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ JoinPathExtraData *extra,
+ Path *inner_cheapest_total)
+{
+ ListCell *lc1;
- /* Can't do anything else if inner path needs to be unique'd */
- if (save_jointype == JOIN_UNIQUE_INNER)
- continue;
+ /* generate merge join path for each partial outer path */
+ foreach(lc1, outerrel->partial_pathlist)
+ {
+ Path *outerpath = (Path *) lfirst(lc1);
+ List *merge_pathkeys;
/*
- * Look for presorted inner paths that satisfy the innersortkey list
- * --- or any truncation thereof, if we are allowed to build a
- * mergejoin using a subset of the merge clauses. Here, we consider
- * both cheap startup cost and cheap total cost.
- *
- * Currently we do not consider parameterized inner paths here. This
- * interacts with decisions elsewhere that also discriminate against
- * mergejoins with parameterized inputs; see comments in
- * src/backend/optimizer/README.
- *
- * As we shorten the sortkey list, we should consider only paths that
- * are strictly cheaper than (in particular, not the same as) any path
- * found in an earlier iteration. Otherwise we'd be intentionally
- * using fewer merge keys than a given path allows (treating the rest
- * as plain joinquals), which is unlikely to be a good idea. Also,
- * eliminating paths here on the basis of compare_path_costs is a lot
- * cheaper than building the mergejoin path only to throw it away.
- *
- * If inner_cheapest_total is well enough sorted to have not required
- * a sort in the path made above, we shouldn't make a duplicate path
- * with it, either. We handle that case with the same logic that
- * handles the previous consideration, by initializing the variables
- * that track cheapest-so-far properly. Note that we do NOT reject
- * inner_cheapest_total if we find it matches some shorter set of
- * pathkeys. That case corresponds to using fewer mergekeys to avoid
- * sorting inner_cheapest_total, whereas we did sort it above, so the
- * plans being considered are different.
+ * Figure out what useful ordering any paths we create will have.
*/
- if (pathkeys_contained_in(innersortkeys,
- inner_cheapest_total->pathkeys))
- {
- /* inner_cheapest_total didn't require a sort */
- cheapest_startup_inner = inner_cheapest_total;
- cheapest_total_inner = inner_cheapest_total;
- }
- else
- {
- /* it did require a sort, at least for the full set of keys */
- cheapest_startup_inner = NULL;
- cheapest_total_inner = NULL;
- }
- num_sortkeys = list_length(innersortkeys);
- if (num_sortkeys > 1 && !useallclauses)
- trialsortkeys = list_copy(innersortkeys); /* need modifiable copy */
- else
- trialsortkeys = innersortkeys; /* won't really truncate */
-
- for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
- {
- Path *innerpath;
- List *newclauses = NIL;
-
- /*
- * Look for an inner path ordered well enough for the first
- * 'sortkeycnt' innersortkeys. NB: trialsortkeys list is modified
- * destructively, which is why we made a copy...
- */
- trialsortkeys = list_truncate(trialsortkeys, sortkeycnt);
- innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
- trialsortkeys,
- NULL,
- TOTAL_COST);
- if (innerpath != NULL &&
- (cheapest_total_inner == NULL ||
- compare_path_costs(innerpath, cheapest_total_inner,
- TOTAL_COST) < 0))
- {
- /* Found a cheap (or even-cheaper) sorted path */
- /* Select the right mergeclauses, if we didn't already */
- if (sortkeycnt < num_sortkeys)
- {
- newclauses =
- find_mergeclauses_for_pathkeys(root,
- trialsortkeys,
- false,
- mergeclauses);
- Assert(newclauses != NIL);
- }
- else
- newclauses = mergeclauses;
- try_mergejoin_path(root,
- joinrel,
- outerpath,
- innerpath,
- merge_pathkeys,
- newclauses,
- NIL,
- NIL,
- jointype,
- extra);
- cheapest_total_inner = innerpath;
- }
- /* Same on the basis of cheapest startup cost ... */
- innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
- trialsortkeys,
- NULL,
- STARTUP_COST);
- if (innerpath != NULL &&
- (cheapest_startup_inner == NULL ||
- compare_path_costs(innerpath, cheapest_startup_inner,
- STARTUP_COST) < 0))
- {
- /* Found a cheap (or even-cheaper) sorted path */
- if (innerpath != cheapest_total_inner)
- {
- /*
- * Avoid rebuilding clause list if we already made one;
- * saves memory in big join trees...
- */
- if (newclauses == NIL)
- {
- if (sortkeycnt < num_sortkeys)
- {
- newclauses =
- find_mergeclauses_for_pathkeys(root,
- trialsortkeys,
- false,
- mergeclauses);
- Assert(newclauses != NIL);
- }
- else
- newclauses = mergeclauses;
- }
- try_mergejoin_path(root,
- joinrel,
- outerpath,
- innerpath,
- merge_pathkeys,
- newclauses,
- NIL,
- NIL,
- jointype,
- extra);
- }
- cheapest_startup_inner = innerpath;
- }
+ merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
+ outerpath->pathkeys);
- /*
- * Don't consider truncated sortkeys if we need all clauses.
- */
- if (useallclauses)
- break;
- }
+ generate_mergejoin_paths(root, joinrel, innerrel, outerpath, jointype,
+ extra, false, inner_cheapest_total,
+ merge_pathkeys, true);
}
-
- /*
- * If the joinrel is parallel-safe and the join type supports nested
- * loops, we may be able to consider a partial nestloop plan. However, we
- * can't handle JOIN_UNIQUE_OUTER, because the outer path will be partial,
- * and therefore we won't be able to properly guarantee uniqueness. Nor
- * can we handle extra_lateral_rels, since partial paths must not be
- * parameterized.
- */
- if (joinrel->consider_parallel && nestjoinOK &&
- save_jointype != JOIN_UNIQUE_OUTER &&
- bms_is_empty(joinrel->lateral_relids))
- consider_parallel_nestloop(root, joinrel, outerrel, innerrel,
- save_jointype, extra);
}
/*
@@ -1217,8 +1515,12 @@ consider_parallel_nestloop(PlannerInfo *root,
JoinType jointype,
JoinPathExtraData *extra)
{
+ JoinType save_jointype = jointype;
ListCell *lc1;
+ if (jointype == JOIN_UNIQUE_INNER)
+ jointype = JOIN_INNER;
+
foreach(lc1, outerrel->partial_pathlist)
{
Path *outerpath = (Path *) lfirst(lc1);
@@ -1244,18 +1546,19 @@ consider_parallel_nestloop(PlannerInfo *root,
continue;
/*
- * Like match_unsorted_outer, we only consider a single nestloop
- * path when the jointype is JOIN_UNIQUE_INNER. But we have to
- * scan cheapest_parameterized_paths to find the one we want to
- * consider, because cheapest_total_path might not be
- * parallel-safe.
+ * If we're doing JOIN_UNIQUE_INNER, we can only use the inner's
+ * cheapest_total_path, and we have to unique-ify it. (We might
+ * be able to relax this to allow other safe, unparameterized
+ * inner paths, but right now create_unique_path is not on board
+ * with that.)
*/
- if (jointype == JOIN_UNIQUE_INNER)
+ if (save_jointype == JOIN_UNIQUE_INNER)
{
- if (!bms_is_empty(PATH_REQ_OUTER(innerpath)))
+ if (innerpath != innerrel->cheapest_total_path)
continue;
innerpath = (Path *) create_unique_path(root, innerrel,
- innerpath, extra->sjinfo);
+ innerpath,
+ extra->sjinfo);
Assert(innerpath);
}
@@ -1284,6 +1587,7 @@ hash_inner_and_outer(PlannerInfo *root,
JoinType jointype,
JoinPathExtraData *extra)
{
+ JoinType save_jointype = jointype;
bool isouterjoin = IS_OUTER_JOIN(jointype);
List *hashclauses;
ListCell *l;
@@ -1450,9 +1754,9 @@ hash_inner_and_outer(PlannerInfo *root,
* extended rows. Also, the resulting path must not be parameterized.
*/
if (joinrel->consider_parallel &&
- jointype != JOIN_UNIQUE_OUTER &&
- jointype != JOIN_FULL &&
- jointype != JOIN_RIGHT &&
+ save_jointype != JOIN_UNIQUE_OUTER &&
+ save_jointype != JOIN_FULL &&
+ save_jointype != JOIN_RIGHT &&
outerrel->partial_pathlist != NIL &&
bms_is_empty(joinrel->lateral_relids))
{
@@ -1465,27 +1769,15 @@ hash_inner_and_outer(PlannerInfo *root,
/*
* Normally, given that the joinrel is parallel-safe, the cheapest
* total inner path will also be parallel-safe, but if not, we'll
- * have to search cheapest_parameterized_paths for the cheapest
- * unparameterized inner path.
+ * have to search for the cheapest safe, unparameterized inner
+ * path. If doing JOIN_UNIQUE_INNER, we can't use any alternative
+ * inner path.
*/
if (cheapest_total_inner->parallel_safe)
cheapest_safe_inner = cheapest_total_inner;
- else
- {
- ListCell *lc;
-
- foreach(lc, innerrel->cheapest_parameterized_paths)
- {
- Path *innerpath = (Path *) lfirst(lc);
-
- if (innerpath->parallel_safe &&
- bms_is_empty(PATH_REQ_OUTER(innerpath)))
- {
- cheapest_safe_inner = innerpath;
- break;
- }
- }
- }
+ else if (save_jointype != JOIN_UNIQUE_INNER)
+ cheapest_safe_inner =
+ get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
if (cheapest_safe_inner != NULL)
try_partial_hashjoin_path(root, joinrel,
@@ -1572,7 +1864,7 @@ select_mergejoin_clauses(PlannerInfo *root,
/*
* Insist that each side have a non-redundant eclass. This
* restriction is needed because various bits of the planner expect
- * that each clause in a merge be associatable with some pathkey in a
+ * that each clause in a merge be associable with some pathkey in a
* canonical pathkey list, but redundant eclasses can't appear in
* canonical sort orderings. (XXX it might be worth relaxing this,
* but not enough time to address it for 8.3.)
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 01d4fea78c..5a68de3cc8 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -3,7 +3,7 @@
* joinrels.c
* Routines to determine which relations should be joined
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -32,6 +32,9 @@ static bool is_dummy_rel(RelOptInfo *rel);
static void mark_dummy_rel(RelOptInfo *rel);
static bool restriction_is_constant_false(List *restrictlist,
bool only_pushed_down);
+static void populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
+ RelOptInfo *rel2, RelOptInfo *joinrel,
+ SpecialJoinInfo *sjinfo, List *restrictlist);
/*
@@ -724,6 +727,27 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
return joinrel;
}
+ /* Add paths to the join relation. */
+ populate_joinrel_with_paths(root, rel1, rel2, joinrel, sjinfo,
+ restrictlist);
+
+ bms_free(joinrelids);
+
+ return joinrel;
+}
+
+/*
+ * populate_joinrel_with_paths
+ * Add paths to the given joinrel for given pair of joining relations. The
+ * SpecialJoinInfo provides details about the join and the restrictlist
+ * contains the join clauses and the other clauses applicable for given pair
+ * of the joining relations.
+ */
+static void
+populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
+ RelOptInfo *rel2, RelOptInfo *joinrel,
+ SpecialJoinInfo *sjinfo, List *restrictlist)
+{
/*
* Consider paths using each rel as both outer and inner. Depending on
* the join type, a provably empty outer or inner rel might mean the join
@@ -868,10 +892,6 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
elog(ERROR, "unrecognized join type: %d", (int) sjinfo->jointype);
break;
}
-
- bms_free(joinrelids);
-
- return joinrel;
}
@@ -1197,7 +1217,7 @@ mark_dummy_rel(RelOptInfo *rel)
rel->partial_pathlist = NIL;
/* Set up the dummy path */
- add_path(rel, (Path *) create_append_path(rel, NIL, NULL, 0));
+ add_path(rel, (Path *) create_append_path(rel, NIL, NULL, 0, NIL));
/* Set or update cheapest_total_path and related fields */
set_cheapest(rel);
@@ -1230,9 +1250,8 @@ restriction_is_constant_false(List *restrictlist, bool only_pushed_down)
*/
foreach(lc, restrictlist)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
- Assert(IsA(rinfo, RestrictInfo));
if (only_pushed_down && !rinfo->is_pushed_down)
continue;
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 4436ac111d..2c269062ec 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -7,7 +7,7 @@
* the nature and use of path keys.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -337,11 +337,13 @@ pathkeys_contained_in(List *keys1, List *keys2)
* 'pathkeys' represents a required ordering (in canonical form!)
* 'required_outer' denotes allowable outer relations for parameterized paths
* 'cost_criterion' is STARTUP_COST or TOTAL_COST
+ * 'require_parallel_safe' causes us to consider only parallel-safe paths
*/
Path *
get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
Relids required_outer,
- CostSelector cost_criterion)
+ CostSelector cost_criterion,
+ bool require_parallel_safe)
{
Path *matched_path = NULL;
ListCell *l;
@@ -358,6 +360,9 @@ get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
compare_path_costs(matched_path, path, cost_criterion) <= 0)
continue;
+ if (require_parallel_safe && !path->parallel_safe)
+ continue;
+
if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
bms_is_subset(PATH_REQ_OUTER(path), required_outer))
matched_path = path;
@@ -407,6 +412,28 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
return matched_path;
}
+
+/*
+ * get_cheapest_parallel_safe_total_inner
+ * Find the unparameterized parallel-safe path with the least total cost.
+ */
+Path *
+get_cheapest_parallel_safe_total_inner(List *paths)
+{
+ ListCell *l;
+
+ foreach(l, paths)
+ {
+ Path *innerpath = (Path *) lfirst(l);
+
+ if (innerpath->parallel_safe &&
+ bms_is_empty(PATH_REQ_OUTER(innerpath)))
+ return innerpath;
+ }
+
+ return NULL;
+}
+
/****************************************************************************
* NEW PATHKEY FORMATION
****************************************************************************/
@@ -480,17 +507,30 @@ build_index_pathkeys(PlannerInfo *root,
index->rel->relids,
false);
- /*
- * If the sort key isn't already present in any EquivalenceClass, then
- * it's not an interesting sort order for this query. So we can stop
- * now --- lower-order sort keys aren't useful either.
- */
- if (!cpathkey)
- break;
-
- /* Add to list unless redundant */
- if (!pathkey_is_redundant(cpathkey, retval))
- retval = lappend(retval, cpathkey);
+ if (cpathkey)
+ {
+ /*
+ * We found the sort key in an EquivalenceClass, so it's relevant
+ * for this query. Add it to list, unless it's redundant.
+ */
+ if (!pathkey_is_redundant(cpathkey, retval))
+ retval = lappend(retval, cpathkey);
+ }
+ else
+ {
+ /*
+ * Boolean index keys might be redundant even if they do not
+ * appear in an EquivalenceClass, because of our special treatment
+ * of boolean equality conditions --- see the comment for
+ * indexcol_is_bool_constant_for_query(). If that applies, we can
+ * continue to examine lower-order index columns. Otherwise, the
+ * sort key is not an interesting sort order for this query, so we
+ * should stop considering index columns; any lower-order sort
+ * keys won't be useful either.
+ */
+ if (!indexcol_is_bool_constant_for_query(index, i))
+ break;
+ }
i++;
}
diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c
index 530e1347e0..a2fe661075 100644
--- a/src/backend/optimizer/path/tidpath.c
+++ b/src/backend/optimizer/path/tidpath.c
@@ -25,7 +25,7 @@
* for that.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -43,12 +43,13 @@
#include "optimizer/clauses.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
+#include "optimizer/restrictinfo.h"
static bool IsTidEqualClause(OpExpr *node, int varno);
static bool IsTidEqualAnyClause(ScalarArrayOpExpr *node, int varno);
static List *TidQualFromExpr(Node *expr, int varno);
-static List *TidQualFromRestrictinfo(List *restrictinfo, int varno);
+static List *TidQualFromBaseRestrictinfo(RelOptInfo *rel);
/*
@@ -216,24 +217,26 @@ TidQualFromExpr(Node *expr, int varno)
}
/*
- * Extract a set of CTID conditions from the given restrictinfo list
- *
- * This is essentially identical to the AND case of TidQualFromExpr,
- * except for the format of the input.
+ * Extract a set of CTID conditions from the rel's baserestrictinfo list
*/
static List *
-TidQualFromRestrictinfo(List *restrictinfo, int varno)
+TidQualFromBaseRestrictinfo(RelOptInfo *rel)
{
List *rlst = NIL;
ListCell *l;
- foreach(l, restrictinfo)
+ foreach(l, rel->baserestrictinfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
- if (!IsA(rinfo, RestrictInfo))
- continue; /* probably should never happen */
- rlst = TidQualFromExpr((Node *) rinfo->clause, varno);
+ /*
+ * If clause must wait till after some lower-security-level
+ * restriction clause, reject it.
+ */
+ if (!restriction_is_securely_promotable(rinfo, rel))
+ continue;
+
+ rlst = TidQualFromExpr((Node *) rinfo->clause, rel->relid);
if (rlst)
break;
}
@@ -259,7 +262,7 @@ create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel)
*/
required_outer = rel->lateral_relids;
- tidquals = TidQualFromRestrictinfo(rel->baserestrictinfo, rel->relid);
+ tidquals = TidQualFromBaseRestrictinfo(rel);
if (tidquals)
add_path(rel, (Path *) create_tidscan_path(root, rel, tidquals,
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index e28a8dc533..34317fe778 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -11,7 +11,7 @@
* is that we have to work harder to clean up after ourselves when we modify
* the query, since the derived data structures have to be updated too.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -41,6 +41,11 @@ static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel);
static bool rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel,
List *clause_list);
static Oid distinct_col_search(int colno, List *colnos, List *opids);
+static bool is_innerrel_unique_for(PlannerInfo *root,
+ Relids outerrelids,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ List *restrictlist);
/*
@@ -491,6 +496,88 @@ remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved)
/*
+ * reduce_unique_semijoins
+ * Check for semijoins that can be simplified to plain inner joins
+ * because the inner relation is provably unique for the join clauses.
+ *
+ * Ideally this would happen during reduce_outer_joins, but we don't have
+ * enough information at that point.
+ *
+ * To perform the strength reduction when applicable, we need only delete
+ * the semijoin's SpecialJoinInfo from root->join_info_list. (We don't
+ * bother fixing the join type attributed to it in the query jointree,
+ * since that won't be consulted again.)
+ */
+void
+reduce_unique_semijoins(PlannerInfo *root)
+{
+ ListCell *lc;
+ ListCell *next;
+
+ /*
+ * Scan the join_info_list to find semijoins. We can't use foreach
+ * because we may delete the current cell.
+ */
+ for (lc = list_head(root->join_info_list); lc != NULL; lc = next)
+ {
+ SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
+ int innerrelid;
+ RelOptInfo *innerrel;
+ Relids joinrelids;
+ List *restrictlist;
+
+ next = lnext(lc);
+
+ /*
+ * Must be a non-delaying semijoin to a single baserel, else we aren't
+ * going to be able to do anything with it. (It's probably not
+ * possible for delay_upper_joins to be set on a semijoin, but we
+ * might as well check.)
+ */
+ if (sjinfo->jointype != JOIN_SEMI ||
+ sjinfo->delay_upper_joins)
+ continue;
+
+ if (!bms_get_singleton_member(sjinfo->min_righthand, &innerrelid))
+ continue;
+
+ innerrel = find_base_rel(root, innerrelid);
+
+ /*
+ * Before we trouble to run generate_join_implied_equalities, make a
+ * quick check to eliminate cases in which we will surely be unable to
+ * prove uniqueness of the innerrel.
+ */
+ if (!rel_supports_distinctness(root, innerrel))
+ continue;
+
+ /* Compute the relid set for the join we are considering */
+ joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
+
+ /*
+ * Since we're only considering a single-rel RHS, any join clauses it
+ * has must be clauses linking it to the semijoin's min_lefthand. We
+ * can also consider EC-derived join clauses.
+ */
+ restrictlist =
+ list_concat(generate_join_implied_equalities(root,
+ joinrelids,
+ sjinfo->min_lefthand,
+ innerrel),
+ innerrel->joininfo);
+
+ /* Test whether the innerrel is unique for those clauses. */
+ if (!innerrel_is_unique(root, sjinfo->min_lefthand, innerrel,
+ JOIN_SEMI, restrictlist, true))
+ continue;
+
+ /* OK, remove the SpecialJoinInfo from the list. */
+ root->join_info_list = list_delete_ptr(root->join_info_list, sjinfo);
+ }
+}
+
+
+/*
* rel_supports_distinctness
* Could the relation possibly be proven distinct on some set of columns?
*
@@ -596,7 +683,7 @@ rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list)
*/
foreach(l, clause_list)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
Oid op;
Var *var;
@@ -608,8 +695,7 @@ rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list)
* caller's mergejoinability test should have selected only
* OpExprs.
*/
- Assert(IsA(rinfo->clause, OpExpr));
- op = ((OpExpr *) rinfo->clause)->opno;
+ op = castNode(OpExpr, rinfo->clause)->opno;
/* caller identified the inner side for us */
if (rinfo->outer_is_left)
@@ -650,6 +736,11 @@ rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list)
bool
query_supports_distinctness(Query *query)
{
+ /* we don't cope with SRFs, see comment below */
+ if (query->hasTargetSRFs)
+ return false;
+
+ /* check for features we can prove distinctness with */
if (query->distinctClause != NIL ||
query->groupClause != NIL ||
query->groupingSets != NIL ||
@@ -695,7 +786,7 @@ query_is_distinct_for(Query *query, List *colnos, List *opids)
* specified columns, since those must be evaluated before de-duplication;
* but it doesn't presently seem worth the complication to check that.)
*/
- if (expression_returns_set((Node *) query->targetList))
+ if (query->hasTargetSRFs)
return false;
/*
@@ -777,9 +868,8 @@ query_is_distinct_for(Query *query, List *colnos, List *opids)
*/
if (query->setOperations)
{
- SetOperationStmt *topop = (SetOperationStmt *) query->setOperations;
+ SetOperationStmt *topop = castNode(SetOperationStmt, query->setOperations);
- Assert(IsA(topop, SetOperationStmt));
Assert(topop->op != SETOP_NONE);
if (!topop->all)
@@ -842,3 +932,184 @@ distinct_col_search(int colno, List *colnos, List *opids)
}
return InvalidOid;
}
+
+
+/*
+ * innerrel_is_unique
+ * Check if the innerrel provably contains at most one tuple matching any
+ * tuple from the outerrel, based on join clauses in the 'restrictlist'.
+ *
+ * We need an actual RelOptInfo for the innerrel, but it's sufficient to
+ * identify the outerrel by its Relids. This asymmetry supports use of this
+ * function before joinrels have been built.
+ *
+ * The proof must be made based only on clauses that will be "joinquals"
+ * rather than "otherquals" at execution. For an inner join there's no
+ * difference; but if the join is outer, we must ignore pushed-down quals,
+ * as those will become "otherquals". Note that this means the answer might
+ * vary depending on whether IS_OUTER_JOIN(jointype); since we cache the
+ * answer without regard to that, callers must take care not to call this
+ * with jointypes that would be classified differently by IS_OUTER_JOIN().
+ *
+ * The actual proof is undertaken by is_innerrel_unique_for(); this function
+ * is a frontend that is mainly concerned with caching the answers.
+ * In particular, the force_cache argument allows overriding the internal
+ * heuristic about whether to cache negative answers; it should be "true"
+ * if making an inquiry that is not part of the normal bottom-up join search
+ * sequence.
+ */
+bool
+innerrel_is_unique(PlannerInfo *root,
+ Relids outerrelids,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ List *restrictlist,
+ bool force_cache)
+{
+ MemoryContext old_context;
+ ListCell *lc;
+
+ /* Certainly can't prove uniqueness when there are no joinclauses */
+ if (restrictlist == NIL)
+ return false;
+
+ /*
+ * Make a quick check to eliminate cases in which we will surely be unable
+ * to prove uniqueness of the innerrel.
+ */
+ if (!rel_supports_distinctness(root, innerrel))
+ return false;
+
+ /*
+ * Query the cache to see if we've managed to prove that innerrel is
+ * unique for any subset of this outerrel. We don't need an exact match,
+ * as extra outerrels can't make the innerrel any less unique (or more
+ * formally, the restrictlist for a join to a superset outerrel must be a
+ * superset of the conditions we successfully used before).
+ */
+ foreach(lc, innerrel->unique_for_rels)
+ {
+ Relids unique_for_rels = (Relids) lfirst(lc);
+
+ if (bms_is_subset(unique_for_rels, outerrelids))
+ return true; /* Success! */
+ }
+
+ /*
+ * Conversely, we may have already determined that this outerrel, or some
+ * superset thereof, cannot prove this innerrel to be unique.
+ */
+ foreach(lc, innerrel->non_unique_for_rels)
+ {
+ Relids unique_for_rels = (Relids) lfirst(lc);
+
+ if (bms_is_subset(outerrelids, unique_for_rels))
+ return false;
+ }
+
+ /* No cached information, so try to make the proof. */
+ if (is_innerrel_unique_for(root, outerrelids, innerrel,
+ jointype, restrictlist))
+ {
+ /*
+ * Cache the positive result for future probes, being sure to keep it
+ * in the planner_cxt even if we are working in GEQO.
+ *
+ * Note: one might consider trying to isolate the minimal subset of
+ * the outerrels that proved the innerrel unique. But it's not worth
+ * the trouble, because the planner builds up joinrels incrementally
+ * and so we'll see the minimally sufficient outerrels before any
+ * supersets of them anyway.
+ */
+ old_context = MemoryContextSwitchTo(root->planner_cxt);
+ innerrel->unique_for_rels = lappend(innerrel->unique_for_rels,
+ bms_copy(outerrelids));
+ MemoryContextSwitchTo(old_context);
+
+ return true; /* Success! */
+ }
+ else
+ {
+ /*
+ * None of the join conditions for outerrel proved innerrel unique, so
+ * we can safely reject this outerrel or any subset of it in future
+ * checks.
+ *
+ * However, in normal planning mode, caching this knowledge is totally
+ * pointless; it won't be queried again, because we build up joinrels
+ * from smaller to larger. It is useful in GEQO mode, where the
+ * knowledge can be carried across successive planning attempts; and
+ * it's likely to be useful when using join-search plugins, too. Hence
+ * cache when join_search_private is non-NULL. (Yeah, that's a hack,
+ * but it seems reasonable.)
+ *
+ * Also, allow callers to override that heuristic and force caching;
+ * that's useful for reduce_unique_semijoins, which calls here before
+ * the normal join search starts.
+ */
+ if (force_cache || root->join_search_private)
+ {
+ old_context = MemoryContextSwitchTo(root->planner_cxt);
+ innerrel->non_unique_for_rels =
+ lappend(innerrel->non_unique_for_rels,
+ bms_copy(outerrelids));
+ MemoryContextSwitchTo(old_context);
+ }
+
+ return false;
+ }
+}
+
+/*
+ * is_innerrel_unique_for
+ * Check if the innerrel provably contains at most one tuple matching any
+ * tuple from the outerrel, based on join clauses in the 'restrictlist'.
+ */
+static bool
+is_innerrel_unique_for(PlannerInfo *root,
+ Relids outerrelids,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ List *restrictlist)
+{
+ List *clause_list = NIL;
+ ListCell *lc;
+
+ /*
+ * Search for mergejoinable clauses that constrain the inner rel against
+ * the outer rel. If an operator is mergejoinable then it behaves like
+ * equality for some btree opclass, so it's what we want. The
+ * mergejoinability test also eliminates clauses containing volatile
+ * functions, which we couldn't depend on.
+ */
+ foreach(lc, restrictlist)
+ {
+ RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
+
+ /*
+ * As noted above, if it's a pushed-down clause and we're at an outer
+ * join, we can't use it.
+ */
+ if (restrictinfo->is_pushed_down && IS_OUTER_JOIN(jointype))
+ continue;
+
+ /* Ignore if it's not a mergejoinable clause */
+ if (!restrictinfo->can_join ||
+ restrictinfo->mergeopfamilies == NIL)
+ continue; /* not mergejoinable */
+
+ /*
+ * Check if clause has the form "outer op inner" or "inner op outer",
+ * and if so mark which side is inner.
+ */
+ if (!clause_sides_match_join(restrictinfo, outerrelids,
+ innerrel->relids))
+ continue; /* no good for these input relations */
+
+ /* OK, add to list */
+ clause_list = lappend(clause_list, restrictinfo);
+ }
+
+ /* Let rel_is_distinct_for() do the hard work */
+ return rel_is_distinct_for(root, innerrel, clause_list);
+}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 637926ff3a..af89e9d288 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -6,7 +6,7 @@
* Path into a Plan.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -110,13 +110,14 @@ static RemoteSubplan *create_remotescan_plan(PlannerInfo *root,
RemoteSubPath *best_path);
static char *get_internal_cursor(void);
#endif
+static ProjectSet *create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path);
static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path,
int flags);
static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path,
int flags);
static Gather *create_gather_plan(PlannerInfo *root, GatherPath *best_path);
static Plan *create_projection_plan(PlannerInfo *root, ProjectionPath *best_path);
-static Plan *inject_projection_plan(Plan *subplan, List *tlist);
+static Plan *inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe);
static Sort *create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags);
static Group *create_group_plan(PlannerInfo *root, GroupPath *best_path);
static Unique *create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path,
@@ -153,6 +154,7 @@ static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,
List *tlist, List *scan_clauses);
static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
List **qual, List **indexqual, List **indexECs);
+static void bitmap_subplan_mark_shared(Plan *plan);
static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
List *tlist, List *scan_clauses);
static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root,
@@ -162,8 +164,12 @@ static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path
List *tlist, List *scan_clauses);
static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path,
List *tlist, List *scan_clauses);
+static TableFuncScan *create_tablefuncscan_plan(PlannerInfo *root, Path *best_path,
+ List *tlist, List *scan_clauses);
static CteScan *create_ctescan_plan(PlannerInfo *root, Path *best_path,
List *tlist, List *scan_clauses);
+static NamedTuplestoreScan *create_namedtuplestorescan_plan(PlannerInfo *root,
+ Path *best_path, List *tlist, List *scan_clauses);
static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_path,
List *tlist, List *scan_clauses);
static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
@@ -218,11 +224,15 @@ static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
Index scanrelid, List *functions, bool funcordinality);
static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
Index scanrelid, List *values_lists);
+static TableFuncScan *make_tablefuncscan(List *qptlist, List *qpqual,
+ Index scanrelid, TableFunc *tablefunc);
static CteScan *make_ctescan(List *qptlist, List *qpqual,
Index scanrelid, int ctePlanId, int cteParam);
+static NamedTuplestoreScan *make_namedtuplestorescan(List *qptlist, List *qpqual,
+ Index scanrelid, char *enrname);
static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual,
Index scanrelid, int wtParam);
-static Append *make_append(List *appendplans, List *tlist);
+static Append *make_append(List *appendplans, List *tlist, List *partitioned_rels);
static RecursiveUnion *make_recursive_union(PlannerInfo *root,
List *tlist,
Plan *lefttree,
@@ -235,18 +245,16 @@ static BitmapOr *make_bitmap_or(List *bitmapplans);
static NestLoop *make_nestloop(List *tlist,
List *joinclauses, List *otherclauses, List *nestParams,
Plan *lefttree, Plan *righttree,
- JoinType jointype);
+ JoinType jointype, bool inner_unique);
static HashJoin *make_hashjoin(List *tlist,
List *joinclauses, List *otherclauses,
List *hashclauses,
Plan *lefttree, Plan *righttree,
- JoinType jointype);
+ JoinType jointype, bool inner_unique);
static Hash *make_hash(Plan *lefttree,
Oid skewTable,
AttrNumber skewColumn,
- bool skewInherit,
- Oid skewColType,
- int32 skewColTypmod);
+ bool skewInherit);
static MergeJoin *make_mergejoin(List *tlist,
List *joinclauses, List *otherclauses,
List *mergeclauses,
@@ -255,7 +263,8 @@ static MergeJoin *make_mergejoin(List *tlist,
int *mergestrategies,
bool *mergenullsfirst,
Plan *lefttree, Plan *righttree,
- JoinType jointype);
+ JoinType jointype, bool inner_unique,
+ bool skip_mark_restore);
static Sort *make_sort(Plan *lefttree, int numCols,
AttrNumber *sortColIdx, Oid *sortOperators,
Oid *collations, bool *nullsFirst);
@@ -294,12 +303,15 @@ static SetOp *make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
long numGroups);
static LockRows *make_lockrows(Plan *lefttree, List *rowMarks, int epqParam);
static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
+static ProjectSet *make_project_set(List *tlist, Plan *subplan);
static ModifyTable *make_modifytable(PlannerInfo *root,
CmdType operation, bool canSetTag,
- Index nominalRelation,
+ Index nominalRelation, List *partitioned_rels,
List *resultRelations, List *subplans,
List *withCheckOptionLists, List *returningLists,
List *rowMarks, OnConflictExpr *onconflict, int epqParam);
+static GatherMerge *create_gather_merge_plan(PlannerInfo *root,
+ GatherMergePath *best_path);
#ifdef XCP
static int add_sort_column(AttrNumber colIdx, Oid sortOp, Oid coll,
@@ -395,9 +407,11 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
case T_TidScan:
case T_SubqueryScan:
case T_FunctionScan:
+ case T_TableFuncScan:
case T_ValuesScan:
case T_CteScan:
case T_WorkTableScan:
+ case T_NamedTuplestoreScan:
case T_ForeignScan:
case T_CustomScan:
plan = create_scan_plan(root, best_path, flags);
@@ -440,6 +454,10 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
(ResultPath *) best_path);
}
break;
+ case T_ProjectSet:
+ plan = (Plan *) create_project_set_plan(root,
+ (ProjectSetPath *) best_path);
+ break;
case T_Material:
plan = (Plan *) create_material_plan(root,
(MaterialPath *) best_path,
@@ -511,6 +529,10 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
(LimitPath *) best_path,
flags, 0, 1);
break;
+ case T_GatherMerge:
+ plan = (Plan *) create_gather_merge_plan(root,
+ (GatherMergePath *) best_path);
+ break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) best_path->pathtype);
@@ -550,8 +572,7 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
{
case T_IndexScan:
case T_IndexOnlyScan:
- Assert(IsA(best_path, IndexPath));
- scan_clauses = ((IndexPath *) best_path)->indexinfo->indrestrictinfo;
+ scan_clauses = castNode(IndexPath, best_path)->indexinfo->indrestrictinfo;
break;
default:
scan_clauses = rel->baserestrictinfo;
@@ -678,6 +699,13 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
scan_clauses);
break;
+ case T_TableFuncScan:
+ plan = (Plan *) create_tablefuncscan_plan(root,
+ best_path,
+ tlist,
+ scan_clauses);
+ break;
+
case T_ValuesScan:
plan = (Plan *) create_valuesscan_plan(root,
best_path,
@@ -692,6 +720,13 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
scan_clauses);
break;
+ case T_NamedTuplestoreScan:
+ plan = (Plan *) create_namedtuplestorescan_plan(root,
+ best_path,
+ tlist,
+ scan_clauses);
+ break;
+
case T_WorkTableScan:
plan = (Plan *) create_worktablescan_plan(root,
best_path,
@@ -792,11 +827,12 @@ use_physical_tlist(PlannerInfo *root, Path *path, int flags)
/*
* We can do this for real relation scans, subquery scans, function scans,
- * values scans, and CTE scans (but not for, eg, joins).
+ * tablefunc scans, values scans, and CTE scans (but not for, eg, joins).
*/
if (rel->rtekind != RTE_RELATION &&
rel->rtekind != RTE_SUBQUERY &&
rel->rtekind != RTE_FUNCTION &&
+ rel->rtekind != RTE_TABLEFUNC &&
rel->rtekind != RTE_VALUES &&
rel->rtekind != RTE_CTE)
return false;
@@ -810,6 +846,15 @@ use_physical_tlist(PlannerInfo *root, Path *path, int flags)
return false;
/*
+ * Also, don't do it to a CustomPath; the premise that we're extracting
+ * columns from a simple physical tuple is unlikely to hold for those.
+ * (When it does make sense, the custom path creator can set up the path's
+ * pathtarget that way.)
+ */
+ if (IsA(path, CustomPath))
+ return false;
+
+ /*
* Can't do it if any system columns or whole-row Vars are requested.
* (This could possibly be fixed but would take some fragile assumptions
* in setrefs.c, I think.)
@@ -930,6 +975,9 @@ create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
*/
copy_plan_costsize(gplan, plan);
+ /* Gating quals could be unsafe, so better use the Path's safety flag */
+ gplan->parallel_safe = path->parallel_safe;
+
return gplan;
}
@@ -1049,7 +1097,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path)
* parent-rel Vars it'll be asked to emit.
*/
- plan = make_append(subplans, tlist);
+ plan = make_append(subplans, tlist, best_path->partitioned_rels);
copy_generic_path_info(&plan->plan, (Path *) best_path);
@@ -1157,6 +1205,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
subplans = lappend(subplans, subplan);
}
+ node->partitioned_rels = best_path->partitioned_rels;
node->mergeplans = subplans;
return (Plan *) node;
@@ -1190,6 +1239,31 @@ create_result_plan(PlannerInfo *root, ResultPath *best_path)
}
/*
+ * create_project_set_plan
+ * Create a ProjectSet plan for 'best_path'.
+ *
+ * Returns a Plan node.
+ */
+static ProjectSet *
+create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
+{
+ ProjectSet *plan;
+ Plan *subplan;
+ List *tlist;
+
+ /* Since we intend to project, we don't need to constrain child tlist */
+ subplan = create_plan_recurse(root, best_path->subpath, 0);
+
+ tlist = build_path_tlist(root, &best_path->path);
+
+ plan = make_project_set(tlist, subplan);
+
+ copy_generic_path_info(&plan->plan, (Path *) best_path);
+
+ return plan;
+}
+
+/*
* create_material_plan
* Create a Material plan for 'best_path' and (recursively) plans
* for its subpaths.
@@ -1272,7 +1346,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
foreach(l, uniq_exprs)
{
- Node *uniqexpr = lfirst(l);
+ Expr *uniqexpr = lfirst(l);
TargetEntry *tle;
tle = tlist_member(uniqexpr, newtlist);
@@ -1297,7 +1371,8 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
*/
if (!is_projection_capable_plan(subplan) &&
!tlist_same_exprs(newtlist, subplan->targetlist))
- subplan = inject_projection_plan(subplan, newtlist);
+ subplan = inject_projection_plan(subplan, newtlist,
+ best_path->path.parallel_safe);
else
subplan->targetlist = newtlist;
#ifdef XCP
@@ -1323,7 +1398,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
groupColPos = 0;
foreach(l, uniq_exprs)
{
- Node *uniqexpr = lfirst(l);
+ Expr *uniqexpr = lfirst(l);
TargetEntry *tle;
tle = tlist_member(uniqexpr, newtlist);
@@ -1451,7 +1526,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
gather_plan = make_gather(tlist,
NIL,
- best_path->path.parallel_workers,
+ best_path->num_workers,
best_path->single_copy,
subplan);
@@ -1464,6 +1539,61 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
}
/*
+ * create_gather_merge_plan
+ *
+ * Create a Gather Merge plan for 'best_path' and (recursively)
+ * plans for its subpaths.
+ */
+static GatherMerge *
+create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
+{
+ GatherMerge *gm_plan;
+ Plan *subplan;
+ List *pathkeys = best_path->path.pathkeys;
+ List *tlist = build_path_tlist(root, &best_path->path);
+
+ /* As with Gather, it's best to project away columns in the workers. */
+ subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
+
+ /* Create a shell for a GatherMerge plan. */
+ gm_plan = makeNode(GatherMerge);
+ gm_plan->plan.targetlist = tlist;
+ gm_plan->num_workers = best_path->num_workers;
+ copy_generic_path_info(&gm_plan->plan, &best_path->path);
+
+ /* Gather Merge is pointless with no pathkeys; use Gather instead. */
+ Assert(pathkeys != NIL);
+
+ /* Compute sort column info, and adjust subplan's tlist as needed */
+ subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
+ best_path->subpath->parent->relids,
+ gm_plan->sortColIdx,
+ false,
+ &gm_plan->numCols,
+ &gm_plan->sortColIdx,
+ &gm_plan->sortOperators,
+ &gm_plan->collations,
+ &gm_plan->nullsFirst);
+
+
+ /* Now, insert a Sort node if subplan isn't sufficiently ordered */
+ if (!pathkeys_contained_in(pathkeys, best_path->subpath->pathkeys))
+ subplan = (Plan *) make_sort(subplan, gm_plan->numCols,
+ gm_plan->sortColIdx,
+ gm_plan->sortOperators,
+ gm_plan->collations,
+ gm_plan->nullsFirst);
+
+ /* Now insert the subplan under GatherMerge. */
+ gm_plan->plan.lefttree = subplan;
+
+ /* use parallel mode for parallel plans. */
+ root->glob->parallelModeNeeded = true;
+
+ return gm_plan;
+}
+
+/*
* create_projection_plan
*
* Create a plan tree to do a projection step and (recursively) plans
@@ -1509,7 +1639,8 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
plan->total_cost = best_path->path.total_cost;
plan->plan_rows = best_path->path.rows;
plan->plan_width = best_path->path.pathtarget->width;
- /* ... but be careful not to munge subplan's parallel-aware flag */
+ plan->parallel_safe = best_path->path.parallel_safe;
+ /* ... but don't change subplan's parallel_aware flag */
}
else
{
@@ -1529,9 +1660,12 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
* This is used in a few places where we decide on-the-fly that we need a
* projection step as part of the tree generated for some Path node.
* We should try to get rid of this in favor of doing it more honestly.
+ *
+ * One reason it's ugly is we have to be told the right parallel_safe marking
+ * to apply (since the tlist might be unsafe even if the child plan is safe).
*/
static Plan *
-inject_projection_plan(Plan *subplan, List *tlist)
+inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
{
Plan *plan;
@@ -1545,6 +1679,7 @@ inject_projection_plan(Plan *subplan, List *tlist)
* consistent not more so. Hence, just copy the subplan's cost.
*/
copy_plan_costsize(plan, subplan);
+ plan->parallel_safe = parallel_safe;
return plan;
}
@@ -1733,18 +1868,15 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
{
Agg *plan;
Plan *subplan;
- List *rollup_groupclauses = best_path->rollup_groupclauses;
- List *rollup_lists = best_path->rollup_lists;
+ List *rollups = best_path->rollups;
AttrNumber *grouping_map;
int maxref;
List *chain;
- ListCell *lc,
- *lc2;
+ ListCell *lc;
/* Shouldn't get here without grouping sets */
Assert(root->parse->groupingSets);
- Assert(rollup_lists != NIL);
- Assert(list_length(rollup_lists) == list_length(rollup_groupclauses));
+ Assert(rollups != NIL);
/*
* Agg can project, so no need to be terribly picky about child tlist, but
@@ -1796,72 +1928,86 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
* costs will be shown by EXPLAIN.
*/
chain = NIL;
- if (list_length(rollup_groupclauses) > 1)
+ if (list_length(rollups) > 1)
{
- forboth(lc, rollup_groupclauses, lc2, rollup_lists)
+ ListCell *lc2 = lnext(list_head(rollups));
+ bool is_first_sort = ((RollupData *) linitial(rollups))->is_hashed;
+
+ for_each_cell(lc, lc2)
{
- List *groupClause = (List *) lfirst(lc);
- List *gsets = (List *) lfirst(lc2);
+ RollupData *rollup = lfirst(lc);
AttrNumber *new_grpColIdx;
- Plan *sort_plan;
+ Plan *sort_plan = NULL;
Plan *agg_plan;
+ AggStrategy strat;
- /* We want to iterate over all but the last rollup list elements */
- if (lnext(lc) == NULL)
- break;
+ new_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
- new_grpColIdx = remap_groupColIdx(root, groupClause);
+ if (!rollup->is_hashed && !is_first_sort)
+ {
+ sort_plan = (Plan *)
+ make_sort_from_groupcols(rollup->groupClause,
+ new_grpColIdx,
+ subplan);
+ }
- sort_plan = (Plan *)
- make_sort_from_groupcols(groupClause,
- new_grpColIdx,
- subplan);
+ if (!rollup->is_hashed)
+ is_first_sort = false;
+
+ if (rollup->is_hashed)
+ strat = AGG_HASHED;
+ else if (list_length(linitial(rollup->gsets)) == 0)
+ strat = AGG_PLAIN;
+ else
+ strat = AGG_SORTED;
agg_plan = (Plan *) make_agg(NIL,
NIL,
- AGG_SORTED,
+ strat,
AGGSPLIT_SIMPLE,
- list_length((List *) linitial(gsets)),
+ list_length((List *) linitial(rollup->gsets)),
new_grpColIdx,
- extract_grouping_ops(groupClause),
- gsets,
+ extract_grouping_ops(rollup->groupClause),
+ rollup->gsets,
NIL,
- 0, /* numGroups not needed */
+ rollup->numGroups,
sort_plan);
/*
- * Nuke stuff we don't need to avoid bloating debug output.
+ * Remove stuff we don't need to avoid bloating debug output.
*/
- sort_plan->targetlist = NIL;
- sort_plan->lefttree = NULL;
+ if (sort_plan)
+ {
+ sort_plan->targetlist = NIL;
+ sort_plan->lefttree = NULL;
+ }
chain = lappend(chain, agg_plan);
}
}
/*
- * Now make the final Agg node
+ * Now make the real Agg node
*/
{
- List *groupClause = (List *) llast(rollup_groupclauses);
- List *gsets = (List *) llast(rollup_lists);
+ RollupData *rollup = linitial(rollups);
AttrNumber *top_grpColIdx;
int numGroupCols;
- top_grpColIdx = remap_groupColIdx(root, groupClause);
+ top_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
- numGroupCols = list_length((List *) linitial(gsets));
+ numGroupCols = list_length((List *) linitial(rollup->gsets));
plan = make_agg(build_path_tlist(root, &best_path->path),
best_path->qual,
- (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
+ best_path->aggstrategy,
AGGSPLIT_SIMPLE,
numGroupCols,
top_grpColIdx,
- extract_grouping_ops(groupClause),
- gsets,
+ extract_grouping_ops(rollup->groupClause),
+ rollup->gsets,
chain,
- 0, /* numGroups not needed */
+ rollup->numGroups,
subplan);
/* Copy cost data from Path to Plan */
@@ -1911,6 +2057,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
plan->plan_rows = 1;
plan->plan_width = mminfo->path->pathtarget->width;
plan->parallel_aware = false;
+ plan->parallel_safe = mminfo->path->parallel_safe;
/*
* XL: Add a remote subplan, splitting the LIMIT into a remote and
@@ -2296,6 +2443,7 @@ create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
best_path->operation,
best_path->canSetTag,
best_path->nominalRelation,
+ best_path->partitioned_rels,
best_path->resultRelations,
subplans,
best_path->withCheckOptionLists,
@@ -2703,9 +2851,8 @@ create_indexscan_plan(PlannerInfo *root,
qpqual = NIL;
foreach(l, scan_clauses)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
- Assert(IsA(rinfo, RestrictInfo));
if (rinfo->pseudoconstant)
continue; /* we may drop pseudoconstants here */
if (list_member_ptr(indexquals, rinfo))
@@ -2832,6 +2979,9 @@ create_bitmap_scan_plan(PlannerInfo *root,
&bitmapqualorig, &indexquals,
&indexECs);
+ if (best_path->path.parallel_aware)
+ bitmap_subplan_mark_shared(bitmapqualplan);
+
/*
* The qpqual list must contain all restrictions not automatically handled
* by the index, other than pseudoconstant clauses which will be handled
@@ -2861,10 +3011,9 @@ create_bitmap_scan_plan(PlannerInfo *root,
qpqual = NIL;
foreach(l, scan_clauses)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
Node *clause = (Node *) rinfo->clause;
- Assert(IsA(rinfo, RestrictInfo));
if (rinfo->pseudoconstant)
continue; /* we may drop pseudoconstants here */
if (list_member(indexquals, clause))
@@ -2981,6 +3130,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
plan->plan_width = 0; /* meaningless */
plan->parallel_aware = false;
+ plan->parallel_safe = apath->path.parallel_safe;
*qual = subquals;
*indexqual = subindexquals;
*indexECs = subindexECs;
@@ -3044,6 +3194,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
plan->plan_width = 0; /* meaningless */
plan->parallel_aware = false;
+ plan->parallel_safe = opath->path.parallel_safe;
}
/*
@@ -3073,9 +3224,9 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
ListCell *l;
/* Use the regular indexscan plan build machinery... */
- iscan = (IndexScan *) create_indexscan_plan(root, ipath,
- NIL, NIL, false);
- Assert(IsA(iscan, IndexScan));
+ iscan = castNode(IndexScan,
+ create_indexscan_plan(root, ipath,
+ NIL, NIL, false));
/* then convert to a bitmap indexscan */
plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
iscan->indexid,
@@ -3088,6 +3239,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
plan->plan_width = 0; /* meaningless */
plan->parallel_aware = false;
+ plan->parallel_safe = ipath->path.parallel_safe;
*qual = get_actual_clauses(ipath->indexclauses);
*indexqual = get_actual_clauses(ipath->indexquals);
foreach(l, ipath->indexinfo->indpred)
@@ -3271,6 +3423,49 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
}
/*
+ * create_tablefuncscan_plan
+ * Returns a tablefuncscan plan for the base relation scanned by 'best_path'
+ * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
+ */
+static TableFuncScan *
+create_tablefuncscan_plan(PlannerInfo *root, Path *best_path,
+ List *tlist, List *scan_clauses)
+{
+ TableFuncScan *scan_plan;
+ Index scan_relid = best_path->parent->relid;
+ RangeTblEntry *rte;
+ TableFunc *tablefunc;
+
+ /* it should be a function base rel... */
+ Assert(scan_relid > 0);
+ rte = planner_rt_fetch(scan_relid, root);
+ Assert(rte->rtekind == RTE_TABLEFUNC);
+ tablefunc = rte->tablefunc;
+
+ /* Sort clauses into best execution order */
+ scan_clauses = order_qual_clauses(root, scan_clauses);
+
+ /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
+ scan_clauses = extract_actual_clauses(scan_clauses, false);
+
+ /* Replace any outer-relation variables with nestloop params */
+ if (best_path->param_info)
+ {
+ scan_clauses = (List *)
+ replace_nestloop_params(root, (Node *) scan_clauses);
+ /* The function expressions could contain nestloop params, too */
+ tablefunc = (TableFunc *) replace_nestloop_params(root, (Node *) tablefunc);
+ }
+
+ scan_plan = make_tablefuncscan(tlist, scan_clauses, scan_relid,
+ tablefunc);
+
+ copy_generic_path_info(&scan_plan->scan.plan, best_path);
+
+ return scan_plan;
+}
+
+/*
* create_valuesscan_plan
* Returns a valuesscan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
@@ -3408,6 +3603,45 @@ create_ctescan_plan(PlannerInfo *root, Path *best_path,
}
/*
+ * create_namedtuplestorescan_plan
+ * Returns a tuplestorescan plan for the base relation scanned by
+ * 'best_path' with restriction clauses 'scan_clauses' and targetlist
+ * 'tlist'.
+ */
+static NamedTuplestoreScan *
+create_namedtuplestorescan_plan(PlannerInfo *root, Path *best_path,
+ List *tlist, List *scan_clauses)
+{
+ NamedTuplestoreScan *scan_plan;
+ Index scan_relid = best_path->parent->relid;
+ RangeTblEntry *rte;
+
+ Assert(scan_relid > 0);
+ rte = planner_rt_fetch(scan_relid, root);
+ Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
+
+ /* Sort clauses into best execution order */
+ scan_clauses = order_qual_clauses(root, scan_clauses);
+
+ /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
+ scan_clauses = extract_actual_clauses(scan_clauses, false);
+
+ /* Replace any outer-relation variables with nestloop params */
+ if (best_path->param_info)
+ {
+ scan_clauses = (List *)
+ replace_nestloop_params(root, (Node *) scan_clauses);
+ }
+
+ scan_plan = make_namedtuplestorescan(tlist, scan_clauses, scan_relid,
+ rte->enrname);
+
+ copy_generic_path_info(&scan_plan->scan.plan, best_path);
+
+ return scan_plan;
+}
+
+/*
* create_worktablescan_plan
* Returns a worktablescan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
@@ -3527,8 +3761,15 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
/* Copy foreign server OID; likewise, no need to make FDW do this */
scan_plan->fs_server = rel->serverid;
- /* Likewise, copy the relids that are represented by this foreign scan */
- scan_plan->fs_relids = best_path->path.parent->relids;
+ /*
+ * Likewise, copy the relids that are represented by this foreign scan. An
+ * upper rel doesn't have relids set, but it covers all the base relations
+ * participating in the underlying scan, so use root's all_baserels.
+ */
+ if (IS_UPPER_REL(rel))
+ scan_plan->fs_relids = root->all_baserels;
+ else
+ scan_plan->fs_relids = best_path->path.parent->relids;
/*
* If this is a foreign join, and to make it valid to push down we had to
@@ -3637,13 +3878,13 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
* Invoke custom plan provider to create the Plan node represented by the
* CustomPath.
*/
- cplan = (CustomScan *) best_path->methods->PlanCustomPath(root,
- rel,
- best_path,
- tlist,
- scan_clauses,
- custom_plans);
- Assert(IsA(cplan, CustomScan));
+ cplan = castNode(CustomScan,
+ best_path->methods->PlanCustomPath(root,
+ rel,
+ best_path,
+ tlist,
+ scan_clauses,
+ custom_plans));
/*
* Copy cost data from Path to Plan; no need to make custom-plan providers
@@ -3799,7 +4040,8 @@ create_nestloop_plan(PlannerInfo *root,
nestParams,
outer_plan,
inner_plan,
- best_path->jointype);
+ best_path->jointype,
+ best_path->inner_unique);
copy_generic_path_info(&join_plan->join.plan, &best_path->path);
@@ -3950,7 +4192,7 @@ create_mergejoin_plan(PlannerInfo *root,
i = 0;
foreach(lc, best_path->path_mergeclauses)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
EquivalenceClass *oeclass;
EquivalenceClass *ieclass;
PathKey *opathkey;
@@ -3960,7 +4202,6 @@ create_mergejoin_plan(PlannerInfo *root,
ListCell *l2;
/* fetch outer/inner eclass from mergeclause */
- Assert(IsA(rinfo, RestrictInfo));
if (rinfo->outer_is_left)
{
oeclass = rinfo->left_ec;
@@ -4102,7 +4343,9 @@ create_mergejoin_plan(PlannerInfo *root,
mergenullsfirst,
outer_plan,
inner_plan,
- best_path->jpath.jointype);
+ best_path->jpath.jointype,
+ best_path->jpath.inner_unique,
+ best_path->skip_mark_restore);
/* Costs of sort and material steps are included in path cost already */
copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
@@ -4125,8 +4368,6 @@ create_hashjoin_plan(PlannerInfo *root,
Oid skewTable = InvalidOid;
AttrNumber skewColumn = InvalidAttrNumber;
bool skewInherit = false;
- Oid skewColType = InvalidOid;
- int32 skewColTypmod = -1;
/*
* HashJoin can project, so we don't have to demand exact tlists from the
@@ -4213,8 +4454,6 @@ create_hashjoin_plan(PlannerInfo *root,
skewTable = rte->relid;
skewColumn = var->varattno;
skewInherit = rte->inh;
- skewColType = var->vartype;
- skewColTypmod = var->vartypmod;
}
}
}
@@ -4225,9 +4464,7 @@ create_hashjoin_plan(PlannerInfo *root,
hash_plan = make_hash(inner_plan,
skewTable,
skewColumn,
- skewInherit,
- skewColType,
- skewColTypmod);
+ skewInherit);
/*
* Set Hash node's startup & total costs equal to total cost of input
@@ -4242,7 +4479,8 @@ create_hashjoin_plan(PlannerInfo *root,
hashclauses,
outer_plan,
(Plan *) hash_plan,
- best_path->jpath.jointype);
+ best_path->jpath.jointype,
+ best_path->jpath.inner_unique);
copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
@@ -4455,7 +4693,7 @@ process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
/* No, so add it */
nlp = makeNode(NestLoopParam);
nlp->paramno = pitem->paramId;
- nlp->paramval = copyObject(phv);
+ nlp->paramval = (Var *) copyObject(phv);
root->curOuterParams = lappend(root->curOuterParams, nlp);
}
}
@@ -4495,12 +4733,10 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path)
forboth(lcc, index_path->indexquals, lci, index_path->indexqualcols)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lcc);
int indexcol = lfirst_int(lci);
Node *clause;
- Assert(IsA(rinfo, RestrictInfo));
-
/*
* Replace any outer-relation variables with nestloop params.
*
@@ -4734,7 +4970,7 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
}
}
- /* Ooops... */
+ /* Oops... */
elog(ERROR, "index key does not match expected index column");
return NULL; /* keep compiler quiet */
}
@@ -4798,21 +5034,32 @@ get_switched_clauses(List *clauses, Relids outerrelids)
* plan node, sort the list into the order we want to check the quals
* in at runtime.
*
+ * When security barrier quals are used in the query, we may have quals with
+ * different security levels in the list. Quals of lower security_level
+ * must go before quals of higher security_level, except that we can grant
+ * exceptions to move up quals that are leakproof. When security level
+ * doesn't force the decision, we prefer to order clauses by estimated
+ * execution cost, cheapest first.
+ *
* Ideally the order should be driven by a combination of execution cost and
* selectivity, but it's not immediately clear how to account for both,
* and given the uncertainty of the estimates the reliability of the decisions
- * would be doubtful anyway. So we just order by estimated per-tuple cost,
- * being careful not to change the order when (as is often the case) the
- * estimates are identical.
+ * would be doubtful anyway. So we just order by security level then
+ * estimated per-tuple cost, being careful not to change the order when
+ * (as is often the case) the estimates are identical.
*
* Although this will work on either bare clauses or RestrictInfos, it's
* much faster to apply it to RestrictInfos, since it can re-use cost
- * information that is cached in RestrictInfos.
+ * information that is cached in RestrictInfos. XXX in the bare-clause
+ * case, we are also not able to apply security considerations. That is
+ * all right for the moment, because the bare-clause case doesn't occur
+ * anywhere that barrier quals could be present, but it would be better to
+ * get rid of it.
*
* Note: some callers pass lists that contain entries that will later be
* removed; this is the easiest way to let this routine see RestrictInfos
- * instead of bare clauses. It's OK because we only sort by cost, but
- * a cost/selectivity combination would likely do the wrong thing.
+ * instead of bare clauses. This is another reason why trying to consider
+ * selectivity in the ordering would likely do the wrong thing.
*/
static List *
order_qual_clauses(PlannerInfo *root, List *clauses)
@@ -4821,6 +5068,7 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
{
Node *clause;
Cost cost;
+ Index security_level;
} QualItem;
int nitems = list_length(clauses);
QualItem *items;
@@ -4846,6 +5094,27 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
cost_qual_eval_node(&qcost, clause, root);
items[i].clause = clause;
items[i].cost = qcost.per_tuple;
+ if (IsA(clause, RestrictInfo))
+ {
+ RestrictInfo *rinfo = (RestrictInfo *) clause;
+
+ /*
+ * If a clause is leakproof, it doesn't have to be constrained by
+ * its nominal security level. If it's also reasonably cheap
+ * (here defined as 10X cpu_operator_cost), pretend it has
+ * security_level 0, which will allow it to go in front of
+ * more-expensive quals of lower security levels. Of course, that
+ * will also force it to go in front of cheaper quals of its own
+ * security level, which is not so great, but we can alleviate
+ * that risk by applying the cost limit cutoff.
+ */
+ if (rinfo->leakproof && items[i].cost < 10 * cpu_operator_cost)
+ items[i].security_level = 0;
+ else
+ items[i].security_level = rinfo->security_level;
+ }
+ else
+ items[i].security_level = 0;
i++;
}
@@ -4862,9 +5131,13 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
/* insert newitem into the already-sorted subarray */
for (j = i; j > 0; j--)
{
- if (newitem.cost >= items[j - 1].cost)
+ QualItem *olditem = &items[j - 1];
+
+ if (newitem.security_level > olditem->security_level ||
+ (newitem.security_level == olditem->security_level &&
+ newitem.cost >= olditem->cost))
break;
- items[j] = items[j - 1];
+ items[j] = *olditem;
}
items[j] = newitem;
}
@@ -4880,7 +5153,7 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
/*
* Copy cost and size info from a Path node to the Plan node created from it.
* The executor usually won't use this info, but it's needed by EXPLAIN.
- * Also copy the parallel-aware flag, which the executor *will* use.
+ * Also copy the parallel-related flags, which the executor *will* use.
*/
static void
copy_generic_path_info(Plan *dest, Path *src)
@@ -4890,6 +5163,7 @@ copy_generic_path_info(Plan *dest, Path *src)
dest->plan_rows = src->rows;
dest->plan_width = src->pathtarget->width;
dest->parallel_aware = src->parallel_aware;
+ dest->parallel_safe = src->parallel_safe;
}
/*
@@ -4905,6 +5179,8 @@ copy_plan_costsize(Plan *dest, Plan *src)
dest->plan_width = src->plan_width;
/* Assume the inserted node is not parallel-aware. */
dest->parallel_aware = false;
+ /* Assume the inserted node is parallel-safe, if child plan is. */
+ dest->parallel_safe = src->parallel_safe;
}
/*
@@ -4934,8 +5210,27 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
plan->plan.plan_rows = lefttree->plan_rows;
plan->plan.plan_width = lefttree->plan_width;
plan->plan.parallel_aware = false;
+ plan->plan.parallel_safe = lefttree->parallel_safe;
}
+/*
+ * bitmap_subplan_mark_shared
+ * Set isshared flag in bitmap subplan so that it will be created in
+ * shared memory.
+ */
+static void
+bitmap_subplan_mark_shared(Plan *plan)
+{
+ if (IsA(plan, BitmapAnd))
+ bitmap_subplan_mark_shared(
+ linitial(((BitmapAnd *) plan)->bitmapplans));
+ else if (IsA(plan, BitmapOr))
+ ((BitmapOr *) plan)->isshared = true;
+ else if (IsA(plan, BitmapIndexScan))
+ ((BitmapIndexScan *) plan)->isshared = true;
+ else
+ elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
+}
/*****************************************************************************
*
@@ -5145,6 +5440,25 @@ make_functionscan(List *qptlist,
return node;
}
+static TableFuncScan *
+make_tablefuncscan(List *qptlist,
+ List *qpqual,
+ Index scanrelid,
+ TableFunc *tablefunc)
+{
+ TableFuncScan *node = makeNode(TableFuncScan);
+ Plan *plan = &node->scan.plan;
+
+ plan->targetlist = qptlist;
+ plan->qual = qpqual;
+ plan->lefttree = NULL;
+ plan->righttree = NULL;
+ node->scan.scanrelid = scanrelid;
+ node->tablefunc = tablefunc;
+
+ return node;
+}
+
static ValuesScan *
make_valuesscan(List *qptlist,
List *qpqual,
@@ -5185,6 +5499,26 @@ make_ctescan(List *qptlist,
return node;
}
+static NamedTuplestoreScan *
+make_namedtuplestorescan(List *qptlist,
+ List *qpqual,
+ Index scanrelid,
+ char *enrname)
+{
+ NamedTuplestoreScan *node = makeNode(NamedTuplestoreScan);
+ Plan *plan = &node->scan.plan;
+
+ /* cost should be inserted by caller */
+ plan->targetlist = qptlist;
+ plan->qual = qpqual;
+ plan->lefttree = NULL;
+ plan->righttree = NULL;
+ node->scan.scanrelid = scanrelid;
+ node->enrname = enrname;
+
+ return node;
+}
+
static WorkTableScan *
make_worktablescan(List *qptlist,
List *qpqual,
@@ -5433,7 +5767,7 @@ make_remotesubplan(PlannerInfo *root,
if (em->em_is_const)
continue;
- tle = tlist_member((Node *) em->em_expr, tlist);
+ tle = tlist_member(em->em_expr, tlist);
if (tle)
{
pk_datatype = em->em_datatype;
@@ -5447,7 +5781,7 @@ make_remotesubplan(PlannerInfo *root,
* We prefer an exact match, though, so we do the basic search
* first.
*/
- tle = tlist_member_ignore_relabel((Node *) em->em_expr, tlist);
+ tle = tlist_member_ignore_relabel(em->em_expr, tlist);
if (tle)
{
pk_datatype = em->em_datatype;
@@ -5595,7 +5929,7 @@ make_foreignscan(List *qptlist,
}
static Append *
-make_append(List *appendplans, List *tlist)
+make_append(List *appendplans, List *tlist, List *partitioned_rels)
{
Append *node = makeNode(Append);
Plan *plan = &node->plan;
@@ -5604,6 +5938,7 @@ make_append(List *appendplans, List *tlist)
plan->qual = NIL;
plan->lefttree = NULL;
plan->righttree = NULL;
+ node->partitioned_rels = partitioned_rels;
node->appendplans = appendplans;
return node;
@@ -5699,7 +6034,8 @@ make_nestloop(List *tlist,
List *nestParams,
Plan *lefttree,
Plan *righttree,
- JoinType jointype)
+ JoinType jointype,
+ bool inner_unique)
{
NestLoop *node = makeNode(NestLoop);
Plan *plan = &node->join.plan;
@@ -5709,6 +6045,7 @@ make_nestloop(List *tlist,
plan->lefttree = lefttree;
plan->righttree = righttree;
node->join.jointype = jointype;
+ node->join.inner_unique = inner_unique;
node->join.joinqual = joinclauses;
node->nestParams = nestParams;
@@ -5722,7 +6059,8 @@ make_hashjoin(List *tlist,
List *hashclauses,
Plan *lefttree,
Plan *righttree,
- JoinType jointype)
+ JoinType jointype,
+ bool inner_unique)
{
HashJoin *node = makeNode(HashJoin);
Plan *plan = &node->join.plan;
@@ -5733,6 +6071,7 @@ make_hashjoin(List *tlist,
plan->righttree = righttree;
node->hashclauses = hashclauses;
node->join.jointype = jointype;
+ node->join.inner_unique = inner_unique;
node->join.joinqual = joinclauses;
return node;
@@ -5742,9 +6081,7 @@ static Hash *
make_hash(Plan *lefttree,
Oid skewTable,
AttrNumber skewColumn,
- bool skewInherit,
- Oid skewColType,
- int32 skewColTypmod)
+ bool skewInherit)
{
Hash *node = makeNode(Hash);
Plan *plan = &node->plan;
@@ -5757,8 +6094,6 @@ make_hash(Plan *lefttree,
node->skewTable = skewTable;
node->skewColumn = skewColumn;
node->skewInherit = skewInherit;
- node->skewColType = skewColType;
- node->skewColTypmod = skewColTypmod;
return node;
}
@@ -5774,7 +6109,9 @@ make_mergejoin(List *tlist,
bool *mergenullsfirst,
Plan *lefttree,
Plan *righttree,
- JoinType jointype)
+ JoinType jointype,
+ bool inner_unique,
+ bool skip_mark_restore)
{
MergeJoin *node = makeNode(MergeJoin);
Plan *plan = &node->join.plan;
@@ -5783,12 +6120,14 @@ make_mergejoin(List *tlist,
plan->qual = otherclauses;
plan->lefttree = lefttree;
plan->righttree = righttree;
+ node->skip_mark_restore = skip_mark_restore;
node->mergeclauses = mergeclauses;
node->mergeFamilies = mergefamilies;
node->mergeCollations = mergecollations;
node->mergeStrategies = mergestrategies;
node->mergeNullsFirst = mergenullsfirst;
node->join.jointype = jointype;
+ node->join.inner_unique = inner_unique;
node->join.joinqual = joinclauses;
return node;
@@ -5875,9 +6214,9 @@ add_sort_column(AttrNumber colIdx, Oid sortOp, Oid coll, bool nulls_first,
* prepare_sort_from_pathkeys
* Prepare to sort according to given pathkeys
*
- * This is used to set up for both Sort and MergeAppend nodes. It calculates
- * the executor's representation of the sort key information, and adjusts the
- * plan targetlist if needed to add resjunk sort columns.
+ * This is used to set up for Sort, MergeAppend, and Gather Merge nodes. It
+ * calculates the executor's representation of the sort key information, and
+ * adjusts the plan targetlist if needed to add resjunk sort columns.
*
* Input parameters:
* 'lefttree' is the plan node which yields input tuples
@@ -5901,7 +6240,7 @@ add_sort_column(AttrNumber colIdx, Oid sortOp, Oid coll, bool nulls_first,
*
* If the pathkeys include expressions that aren't simple Vars, we will
* usually need to add resjunk items to the input plan's targetlist to
- * compute these expressions, since the Sort/MergeAppend node itself won't
+ * compute these expressions, since a Sort or MergeAppend node itself won't
* do any such calculations. If the input plan type isn't one that can do
* projections, this means adding a Result node just to do the projection.
* However, the caller can pass adjust_tlist_in_place = TRUE to force the
@@ -6083,7 +6422,8 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
{
/* copy needed so we don't modify input's tlist below */
tlist = copyObject(tlist);
- lefttree = inject_projection_plan(lefttree, tlist);
+ lefttree = inject_projection_plan(lefttree, tlist,
+ lefttree->parallel_safe);
}
/* Don't bother testing is_projection_capable_plan again */
@@ -6349,6 +6689,16 @@ materialize_finished_plan(Plan *subplan)
matplan = (Plan *) make_material(subplan);
+ /*
+ * XXX horrid kluge: if there are any initPlans attached to the subplan,
+ * move them up to the Material node, which is now effectively the top
+ * plan node in its query level. This prevents failure in
+ * SS_finalize_plan(), which see for comments. We don't bother adjusting
+ * the subplan's cost estimate for this.
+ */
+ matplan->initPlan = subplan->initPlan;
+ subplan->initPlan = NIL;
+
/* Set cost data */
cost_material(&matpath,
subplan->startup_cost,
@@ -6360,6 +6710,7 @@ materialize_finished_plan(Plan *subplan)
matplan->plan_rows = subplan->plan_rows;
matplan->plan_width = subplan->plan_width;
matplan->parallel_aware = false;
+ matplan->parallel_safe = subplan->parallel_safe;
return matplan;
}
@@ -6384,6 +6735,7 @@ make_agg(List *tlist, List *qual,
node->grpColIdx = grpColIdx;
node->grpOperators = grpOperators;
node->numGroups = numGroups;
+ node->aggParams = NULL; /* SS_finalize_plan() will fill this */
node->groupingSets = groupingSets;
node->chain = chain;
@@ -6834,13 +7186,32 @@ make_result(List *tlist,
}
/*
+ * make_project_set
+ * Build a ProjectSet plan node
+ */
+static ProjectSet *
+make_project_set(List *tlist,
+ Plan *subplan)
+{
+ ProjectSet *node = makeNode(ProjectSet);
+ Plan *plan = &node->plan;
+
+ plan->targetlist = tlist;
+ plan->qual = NIL;
+ plan->lefttree = subplan;
+ plan->righttree = NULL;
+
+ return node;
+}
+
+/*
* make_modifytable
* Build a ModifyTable plan node
*/
static ModifyTable *
make_modifytable(PlannerInfo *root,
CmdType operation, bool canSetTag,
- Index nominalRelation,
+ Index nominalRelation, List *partitioned_rels,
List *resultRelations, List *subplans,
List *withCheckOptionLists, List *returningLists,
List *rowMarks, OnConflictExpr *onconflict, int epqParam)
@@ -6866,8 +7237,10 @@ make_modifytable(PlannerInfo *root,
node->operation = operation;
node->canSetTag = canSetTag;
node->nominalRelation = nominalRelation;
+ node->partitioned_rels = partitioned_rels;
node->resultRelations = resultRelations;
node->resultRelIndex = -1; /* will be set correctly in setrefs.c */
+ node->rootResultRelIndex = -1; /* will be set correctly in setrefs.c */
node->plans = subplans;
if (!onconflict)
{
@@ -6999,6 +7372,15 @@ is_projection_capable_path(Path *path)
* projection to its dummy path.
*/
return IS_DUMMY_PATH(path);
+ case T_ProjectSet:
+
+ /*
+ * Although ProjectSet certainly projects, say "no" because we
+ * don't want the planner to randomly replace its tlist with
+ * something else; the SRFs have to stay at top level. This might
+ * get relaxed later.
+ */
+ return false;
default:
break;
}
@@ -7036,6 +7418,15 @@ is_projection_capable_plan(Plan *plan)
return ((RemoteSubplan *) plan)->sort == NULL &&
is_projection_capable_plan(plan->lefttree);
#endif
+ case T_ProjectSet:
+
+ /*
+ * Although ProjectSet certainly projects, say "no" because we
+ * don't want the planner to randomly replace its tlist with
+ * something else; the SRFs have to stay at top level. This might
+ * get relaxed later.
+ */
+ return false;
default:
break;
}
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 84ce6b3125..ebd442ad4d 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -3,7 +3,7 @@
* initsplan.c
* Target list, qualification, joininfo initialization routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -51,6 +51,9 @@ static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode,
bool below_outer_join,
Relids *qualscope, Relids *inner_join_rels,
List **postponed_qual_list);
+static void process_security_barrier_quals(PlannerInfo *root,
+ int rti, Relids qualscope,
+ bool below_outer_join);
static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root,
Relids left_rels, Relids right_rels,
Relids inner_join_rels,
@@ -60,6 +63,7 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
bool is_deduced,
bool below_outer_join,
JoinType jointype,
+ Index security_level,
Relids qualscope,
Relids ojscope,
Relids outerjoin_nonnullable,
@@ -105,7 +109,7 @@ add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
{
int varno = ((RangeTblRef *) jtnode)->rtindex;
- (void) build_simple_rel(root, varno, RELOPT_BASEREL);
+ (void) build_simple_rel(root, varno, NULL);
}
else if (IsA(jtnode, FromExpr))
{
@@ -331,6 +335,8 @@ extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
vars = pull_vars_of_level((Node *) rte->subquery, 1);
else if (rte->rtekind == RTE_FUNCTION)
vars = pull_vars_of_level((Node *) rte->functions, 0);
+ else if (rte->rtekind == RTE_TABLEFUNC)
+ vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
else if (rte->rtekind == RTE_VALUES)
vars = pull_vars_of_level((Node *) rte->values_lists, 0);
else
@@ -745,8 +751,14 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
{
int varno = ((RangeTblRef *) jtnode)->rtindex;
- /* No quals to deal with, just return correct result */
+ /* qualscope is just the one RTE */
*qualscope = bms_make_singleton(varno);
+ /* Deal with any securityQuals attached to the RTE */
+ if (root->qual_security_level > 0)
+ process_security_barrier_quals(root,
+ varno,
+ *qualscope,
+ below_outer_join);
/* A single baserel does not create an inner join */
*inner_join_rels = NULL;
joinlist = list_make1(jtnode);
@@ -810,6 +822,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
if (bms_is_subset(pq->relids, *qualscope))
distribute_qual_to_rels(root, pq->qual,
false, below_outer_join, JOIN_INNER,
+ root->qual_security_level,
*qualscope, NULL, NULL, NULL,
NULL);
else
@@ -825,6 +838,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
distribute_qual_to_rels(root, qual,
false, below_outer_join, JOIN_INNER,
+ root->qual_security_level,
*qualscope, NULL, NULL, NULL,
postponed_qual_list);
}
@@ -1002,6 +1016,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
distribute_qual_to_rels(root, qual,
false, below_outer_join, j->jointype,
+ root->qual_security_level,
*qualscope,
ojscope, nonnullable_rels, NULL,
postponed_qual_list);
@@ -1059,6 +1074,67 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
}
/*
+ * process_security_barrier_quals
+ * Transfer security-barrier quals into relation's baserestrictinfo list.
+ *
+ * The rewriter put any relevant security-barrier conditions into the RTE's
+ * securityQuals field, but it's now time to copy them into the rel's
+ * baserestrictinfo.
+ *
+ * In inheritance cases, we only consider quals attached to the parent rel
+ * here; they will be valid for all children too, so it's okay to consider
+ * them for purposes like equivalence class creation. Quals attached to
+ * individual child rels will be dealt with during path creation.
+ */
+static void
+process_security_barrier_quals(PlannerInfo *root,
+ int rti, Relids qualscope,
+ bool below_outer_join)
+{
+ RangeTblEntry *rte = root->simple_rte_array[rti];
+ Index security_level = 0;
+ ListCell *lc;
+
+ /*
+ * Each element of the securityQuals list has been preprocessed into an
+ * implicitly-ANDed list of clauses. All the clauses in a given sublist
+ * should get the same security level, but successive sublists get higher
+ * levels.
+ */
+ foreach(lc, rte->securityQuals)
+ {
+ List *qualset = (List *) lfirst(lc);
+ ListCell *lc2;
+
+ foreach(lc2, qualset)
+ {
+ Node *qual = (Node *) lfirst(lc2);
+
+ /*
+ * We cheat to the extent of passing ojscope = qualscope rather
+ * than its more logical value of NULL. The only effect this has
+ * is to force a Var-free qual to be evaluated at the rel rather
+ * than being pushed up to top of tree, which we don't want.
+ */
+ distribute_qual_to_rels(root, qual,
+ false,
+ below_outer_join,
+ JOIN_INNER,
+ security_level,
+ qualscope,
+ qualscope,
+ NULL,
+ NULL,
+ NULL);
+ }
+ security_level++;
+ }
+
+ /* Assert that qual_security_level is higher than anything we just used */
+ Assert(security_level <= root->qual_security_level);
+}
+
+/*
* make_outerjoininfo
* Build a SpecialJoinInfo for the current outer join
*
@@ -1516,6 +1592,7 @@ compute_semijoin_info(SpecialJoinInfo *sjinfo, List *clause)
* 'below_outer_join': TRUE if the qual is from a JOIN/ON that is below the
* nullable side of a higher-level outer join
* 'jointype': type of join the qual is from (JOIN_INNER for a WHERE clause)
+ * 'security_level': security_level to assign to the qual
* 'qualscope': set of baserels the qual's syntactic scope covers
* 'ojscope': NULL if not an outer-join qual, else the minimum set of baserels
* needed to form this join
@@ -1545,6 +1622,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
bool is_deduced,
bool below_outer_join,
JoinType jointype,
+ Index security_level,
Relids qualscope,
Relids ojscope,
Relids outerjoin_nonnullable,
@@ -1794,6 +1872,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
relids,
outerjoin_nonnullable,
nullable_relids);
@@ -2142,6 +2221,9 @@ distribute_restrictinfo_to_rels(PlannerInfo *root,
/* Add clause to rel's restriction list */
rel->baserestrictinfo = lappend(rel->baserestrictinfo,
restrictinfo);
+ /* Update security level info */
+ rel->baserestrict_min_security = Min(rel->baserestrict_min_security,
+ restrictinfo->security_level);
break;
case BMS_MULTIPLE:
@@ -2189,6 +2271,8 @@ distribute_restrictinfo_to_rels(PlannerInfo *root,
* caller because this function is used after deconstruct_jointree, so we
* don't have knowledge of where the clause items came from.)
*
+ * "security_level" is the security level to assign to the new restrictinfo.
+ *
* "both_const" indicates whether both items are known pseudo-constant;
* in this case it is worth applying eval_const_expressions() in case we
* can produce constant TRUE or constant FALSE. (Otherwise it's not,
@@ -2209,6 +2293,7 @@ process_implied_equality(PlannerInfo *root,
Expr *item2,
Relids qualscope,
Relids nullable_relids,
+ Index security_level,
bool below_outer_join,
bool both_const)
{
@@ -2221,8 +2306,8 @@ process_implied_equality(PlannerInfo *root,
clause = make_opclause(opno,
BOOLOID, /* opresulttype */
false, /* opretset */
- (Expr *) copyObject(item1),
- (Expr *) copyObject(item2),
+ copyObject(item1),
+ copyObject(item2),
InvalidOid,
collation);
@@ -2247,6 +2332,7 @@ process_implied_equality(PlannerInfo *root,
*/
distribute_qual_to_rels(root, (Node *) clause,
true, below_outer_join, JOIN_INNER,
+ security_level,
qualscope, NULL, NULL, nullable_relids,
NULL);
}
@@ -2270,7 +2356,8 @@ build_implied_join_equality(Oid opno,
Expr *item1,
Expr *item2,
Relids qualscope,
- Relids nullable_relids)
+ Relids nullable_relids,
+ Index security_level)
{
RestrictInfo *restrictinfo;
Expr *clause;
@@ -2282,8 +2369,8 @@ build_implied_join_equality(Oid opno,
clause = make_opclause(opno,
BOOLOID, /* opresulttype */
false, /* opretset */
- (Expr *) copyObject(item1),
- (Expr *) copyObject(item2),
+ copyObject(item1),
+ copyObject(item2),
InvalidOid,
collation);
@@ -2294,6 +2381,7 @@ build_implied_join_equality(Oid opno,
true, /* is_pushed_down */
false, /* outerjoin_delayed */
false, /* pseudoconstant */
+ security_level, /* security_level */
qualscope, /* required_relids */
NULL, /* outer_relids */
nullable_relids); /* nullable_relids */
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index f7d6dace59..c9331d272a 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -18,7 +18,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -105,6 +105,14 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
return;
/*
+ * Reject if query contains any CTEs; there's no way to build an indexscan
+ * on one so we couldn't succeed here. (If the CTEs are unreferenced,
+ * that's not true, but it doesn't seem worth expending cycles to check.)
+ */
+ if (parse->cteList)
+ return;
+
+ /*
* We also restrict the query to reference exactly one table, since join
* conditions can't be handled reasonably. (We could perhaps handle a
* query containing cartesian-product joins, but it hardly seems worth the
@@ -361,13 +369,12 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
subroot->plan_params = NIL;
subroot->outer_params = NULL;
subroot->init_plans = NIL;
- subroot->cte_plan_ids = NIL;
- subroot->parse = parse = (Query *) copyObject(root->parse);
+ subroot->parse = parse = copyObject(root->parse);
IncrementVarSublevelsUp((Node *) parse, 1, 1);
/* append_rel_list might contain outer Vars? */
- subroot->append_rel_list = (List *) copyObject(root->append_rel_list);
+ subroot->append_rel_list = copyObject(root->append_rel_list);
IncrementVarSublevelsUp((Node *) subroot->append_rel_list, 1, 1);
/* There shouldn't be any OJ info to translate, as yet */
Assert(subroot->join_info_list == NIL);
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index 27234ffa22..74de3b818f 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -9,7 +9,7 @@
* shorn of features like subselects, inheritance, aggregates, grouping,
* and so on. (Those are the things planner.c deals with.)
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -71,14 +71,13 @@ query_planner(PlannerInfo *root, List *tlist,
/*
* If query allows parallelism in general, check whether the quals are
- * parallel-restricted. There's currently no real benefit to setting
- * this flag correctly because we can't yet reference subplans from
- * parallel workers. But that might change someday, so set this
- * correctly anyway.
+ * parallel-restricted. (We need not check final_rel->reltarget
+ * because it's empty at this point. Anything parallel-restricted in
+ * the query tlist will be dealt with later.)
*/
if (root->glob->parallelModeOK)
final_rel->consider_parallel =
- !has_parallel_hazard(parse->jointree->quals, false);
+ is_parallel_safe(root, parse->jointree->quals);
/* The only path for it is a trivial Result path */
add_path(final_rel, (Path *)
@@ -194,9 +193,15 @@ query_planner(PlannerInfo *root, List *tlist,
joinlist = remove_useless_joins(root, joinlist);
/*
+ * Also, reduce any semijoins with unique inner rels to plain inner joins.
+ * Likewise, this can't be done until now for lack of needed info.
+ */
+ reduce_unique_semijoins(root);
+
+ /*
* Now distribute "placeholders" to base rels as needed. This has to be
* done after join removal because removal could change whether a
- * placeholder is evaluatable at a base rel.
+ * placeholder is evaluable at a base rel.
*/
add_placeholders_to_base_rels(root);
@@ -243,8 +248,7 @@ query_planner(PlannerInfo *root, List *tlist,
Assert(brel->relid == rti); /* sanity check on array */
- if (brel->reloptkind == RELOPT_BASEREL ||
- brel->reloptkind == RELOPT_OTHER_MEMBER_REL)
+ if (IS_SIMPLE_REL(brel))
total_pages += (double) brel->pages;
}
root->total_table_pages = total_pages;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 89031d265e..b49a91a3b0 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -4,7 +4,7 @@
* The query optimizer external interface.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -24,12 +24,14 @@
#include "access/sysattr.h"
#include "access/xact.h"
#include "catalog/pg_constraint_fn.h"
+#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
#include "lib/bipartite_match.h"
+#include "lib/knapsack.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#ifdef OPTIMIZER_DEBUG
@@ -74,17 +76,19 @@ create_upper_paths_hook_type create_upper_paths_hook = NULL;
/* Expression kind codes for preprocess_expression */
-#define EXPRKIND_QUAL 0
-#define EXPRKIND_TARGET 1
-#define EXPRKIND_RTFUNC 2
-#define EXPRKIND_RTFUNC_LATERAL 3
-#define EXPRKIND_VALUES 4
-#define EXPRKIND_VALUES_LATERAL 5
-#define EXPRKIND_LIMIT 6
-#define EXPRKIND_APPINFO 7
-#define EXPRKIND_PHV 8
-#define EXPRKIND_TABLESAMPLE 9
-#define EXPRKIND_ARBITER_ELEM 10
+#define EXPRKIND_QUAL 0
+#define EXPRKIND_TARGET 1
+#define EXPRKIND_RTFUNC 2
+#define EXPRKIND_RTFUNC_LATERAL 3
+#define EXPRKIND_VALUES 4
+#define EXPRKIND_VALUES_LATERAL 5
+#define EXPRKIND_LIMIT 6
+#define EXPRKIND_APPINFO 7
+#define EXPRKIND_PHV 8
+#define EXPRKIND_TABLESAMPLE 9
+#define EXPRKIND_ARBITER_ELEM 10
+#define EXPRKIND_TABLEFUNC 11
+#define EXPRKIND_TABLEFUNC_LATERAL 12
/* Passthrough data for standard_qp_callback */
typedef struct
@@ -94,12 +98,31 @@ typedef struct
List *groupClause; /* overrides parse->groupClause */
} standard_qp_extra;
+/*
+ * Data specific to grouping sets
+ */
+
+typedef struct
+{
+ List *rollups;
+ List *hash_sets_idx;
+ double dNumHashGroups;
+ bool any_hashable;
+ Bitmapset *unsortable_refs;
+ Bitmapset *unhashable_refs;
+ List *unsortable_sets;
+ int *tleref_to_colnum_map;
+} grouping_sets_data;
+
/* Local functions */
static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
static void inheritance_planner(PlannerInfo *root);
static void grouping_planner(PlannerInfo *root, bool inheritance_update,
double tuple_fraction);
+static grouping_sets_data *preprocess_grouping_sets(PlannerInfo *root);
+static List *remap_to_groupclause_idx(List *groupClause, List *gsets,
+ int *tleref_to_colnum_map);
static void preprocess_rowmarks(PlannerInfo *root);
static double preprocess_limit(PlannerInfo *root,
double tuple_fraction,
@@ -112,8 +135,7 @@ static List *reorder_grouping_sets(List *groupingSets, List *sortclause);
static void standard_qp_callback(PlannerInfo *root, void *extra);
static double get_number_of_groups(PlannerInfo *root,
double path_rows,
- List *rollup_lists,
- List *rollup_groupclauses);
+ grouping_sets_data *gd);
static Size estimate_hashagg_tablesize(Path *path,
const AggClauseCosts *agg_costs,
double dNumGroups);
@@ -121,8 +143,16 @@ static RelOptInfo *create_grouping_paths(PlannerInfo *root,
RelOptInfo *input_rel,
PathTarget *target,
const AggClauseCosts *agg_costs,
- List *rollup_lists,
- List *rollup_groupclauses);
+ grouping_sets_data *gd);
+static void consider_groupingsets_paths(PlannerInfo *root,
+ RelOptInfo *grouped_rel,
+ Path *path,
+ bool is_sorted,
+ bool can_hash,
+ PathTarget *target,
+ grouping_sets_data *gd,
+ const AggClauseCosts *agg_costs,
+ double dNumGroups);
static RelOptInfo *create_window_paths(PlannerInfo *root,
RelOptInfo *input_rel,
PathTarget *input_target,
@@ -168,6 +198,9 @@ static Path *adjust_path_distribution(PlannerInfo *root, Query *parse,
Path *path);
static bool can_push_down_grouping(PlannerInfo *root, Query *parse, Path *path);
static bool can_push_down_window(PlannerInfo *root, Path *path);
+static void adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel,
+ List *targets, List *targets_contain_srfs);
+
/*****************************************************************************
*
@@ -221,12 +254,6 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
IsA(parse->utilityStmt, RemoteQuery))
return pgxc_direct_planner(parse, cursorOptions, boundParams);
#endif
-
- /* Cursor options may come from caller or from DECLARE CURSOR stmt */
- if (parse->utilityStmt &&
- IsA(parse->utilityStmt, DeclareCursorStmt))
- cursorOptions |= ((DeclareCursorStmt *) parse->utilityStmt)->options;
-
/*
* Set up global state for this planner invocation. This data is needed
* across all levels of sub-Query that might exist in the given command,
@@ -242,6 +269,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->finalrtable = NIL;
glob->finalrowmarks = NIL;
glob->resultRelations = NIL;
+ glob->nonleafResultRelations = NIL;
+ glob->rootResultRelations = NIL;
glob->relationOids = NIL;
glob->invalItems = NIL;
glob->nParamExec = 0;
@@ -271,12 +300,25 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
* time and execution time, so don't generate a parallel plan if we're in
* serializable mode.
*/
- glob->parallelModeOK = (cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
- IsUnderPostmaster && dynamic_shared_memory_type != DSM_IMPL_NONE &&
- parse->commandType == CMD_SELECT && !parse->hasModifyingCTE &&
- parse->utilityStmt == NULL && max_parallel_workers_per_gather > 0 &&
- !IsParallelWorker() && !IsolationIsSerializable() &&
- !has_parallel_hazard((Node *) parse, true);
+ if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
+ IsUnderPostmaster &&
+ dynamic_shared_memory_type != DSM_IMPL_NONE &&
+ parse->commandType == CMD_SELECT &&
+ !parse->hasModifyingCTE &&
+ max_parallel_workers_per_gather > 0 &&
+ !IsParallelWorker() &&
+ !IsolationIsSerializable())
+ {
+ /* all the cheap tests pass, so scan the query tree */
+ glob->maxParallelHazard = max_parallel_hazard(parse);
+ glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
+ }
+ else
+ {
+ /* skip the query tree scan, just assume it's unsafe */
+ glob->maxParallelHazard = PROPARALLEL_UNSAFE;
+ glob->parallelModeOK = false;
+ }
/*
* glob->parallelModeNeeded should tell us whether it's necessary to
@@ -348,33 +390,14 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
if (cursorOptions & CURSOR_OPT_SCROLL)
{
if (!ExecSupportsBackwardScan(top_plan))
- {
- Plan *sub_plan = top_plan;
-
- top_plan = materialize_finished_plan(sub_plan);
-
- /*
- * XXX horrid kluge: if there are any initPlans attached to the
- * formerly-top plan node, move them up to the Material node. This
- * prevents failure in SS_finalize_plan, which see for comments.
- * We don't bother adjusting the sub_plan's cost estimate for
- * this.
- */
- top_plan->initPlan = sub_plan->initPlan;
- sub_plan->initPlan = NIL;
- }
+ top_plan = materialize_finished_plan(top_plan);
}
/*
* Optionally add a Gather node for testing purposes, provided this is
- * actually a safe thing to do. (Note: we assume adding a Material node
- * above did not change the parallel safety of the plan, so we can still
- * rely on best_path->parallel_safe. However, that flag doesn't account
- * for initPlans, which render the plan parallel-unsafe.)
+ * actually a safe thing to do.
*/
- if (force_parallel_mode != FORCE_PARALLEL_OFF &&
- best_path->parallel_safe &&
- top_plan->initPlan == NIL)
+ if (force_parallel_mode != FORCE_PARALLEL_OFF && top_plan->parallel_safe)
{
Gather *gather = makeNode(Gather);
@@ -397,6 +420,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
gather->plan.plan_rows = top_plan->plan_rows;
gather->plan.plan_width = top_plan->plan_width;
gather->plan.parallel_aware = false;
+ gather->plan.parallel_safe = false;
/* use parallel mode for parallel plans. */
root->glob->parallelModeNeeded = true;
@@ -427,6 +451,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Assert(glob->finalrtable == NIL);
Assert(glob->finalrowmarks == NIL);
Assert(glob->resultRelations == NIL);
+ Assert(glob->nonleafResultRelations == NIL);
+ Assert(glob->rootResultRelations == NIL);
top_plan = set_plan_references(root, top_plan);
/* ... and the subplans (both regular subplans and initplans) */
Assert(list_length(glob->subplans) == list_length(glob->subroots));
@@ -452,7 +478,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->planTree = top_plan;
result->rtable = glob->finalrtable;
result->resultRelations = glob->resultRelations;
- result->utilityStmt = parse->utilityStmt;
+ result->nonleafResultRelations = glob->nonleafResultRelations;
+ result->rootResultRelations = glob->rootResultRelations;
result->subplans = glob->subplans;
result->rewindPlanIDs = glob->rewindPlanIDs;
result->rowMarks = glob->finalrowmarks;
@@ -464,6 +491,10 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->distributionNodes = NULL;
#endif
result->nParamExec = glob->nParamExec;
+ /* utilityStmt should be null, but we might as well copy it */
+ result->utilityStmt = parse->utilityStmt;
+ result->stmt_location = parse->stmt_location;
+ result->stmt_len = parse->stmt_len;
return result;
}
@@ -533,6 +564,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
root->multiexpr_params = NIL;
root->eq_classes = NIL;
root->append_rel_list = NIL;
+ root->pcinfo_list = NIL;
root->rowMarks = NIL;
memset(root->upper_rels, 0, sizeof(root->upper_rels));
memset(root->upper_targets, 0, sizeof(root->upper_targets));
@@ -541,6 +573,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
root->recursiveOk = true;
root->minmax_aggs = NIL;
+ root->qual_security_level = 0;
root->hasInheritedTarget = false;
root->hasRecursion = hasRecursion;
if (hasRecursion)
@@ -649,6 +682,10 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
preprocess_expression(root, (Node *) parse->targetList,
EXPRKIND_TARGET);
+ /* Constant-folding might have removed all set-returning functions */
+ if (parse->hasTargetSRFs)
+ parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList);
+
newWithCheckOptions = NIL;
foreach(l, parse->withCheckOptions)
{
@@ -716,6 +753,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
int kind;
+ ListCell *lcsq;
if (rte->rtekind == RTE_RELATION)
{
@@ -742,7 +780,15 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
{
/* Preprocess the function expression(s) fully */
kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
- rte->functions = (List *) preprocess_expression(root, (Node *) rte->functions, kind);
+ rte->functions = (List *)
+ preprocess_expression(root, (Node *) rte->functions, kind);
+ }
+ else if (rte->rtekind == RTE_TABLEFUNC)
+ {
+ /* Preprocess the function expression(s) fully */
+ kind = rte->lateral ? EXPRKIND_TABLEFUNC_LATERAL : EXPRKIND_TABLEFUNC;
+ rte->tablefunc = (TableFunc *)
+ preprocess_expression(root, (Node *) rte->tablefunc, kind);
}
else if (rte->rtekind == RTE_VALUES)
{
@@ -751,6 +797,19 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
rte->values_lists = (List *)
preprocess_expression(root, (Node *) rte->values_lists, kind);
}
+
+ /*
+ * Process each element of the securityQuals list as if it were a
+ * separate qual expression (as indeed it is). We need to do it this
+ * way to get proper canonicalization of AND/OR structure. Note that
+ * this converts each element into an implicit-AND sublist.
+ */
+ foreach(lcsq, rte->securityQuals)
+ {
+ lfirst(lcsq) = preprocess_expression(root,
+ (Node *) lfirst(lcsq),
+ EXPRKIND_QUAL);
+ }
}
/*
@@ -841,10 +900,10 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
SS_identify_outer_params(root);
/*
- * If any initPlans were created in this query level, increment the
- * surviving Paths' costs to account for them. They won't actually get
- * attached to the plan tree till create_plan() runs, but we want to be
- * sure their costs are included now.
+ * If any initPlans were created in this query level, adjust the surviving
+ * Paths' costs and parallel-safety flags to account for them. The
+ * initPlans won't actually get attached to the plan tree till
+ * create_plan() runs, but we must include their effects now.
*/
final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
SS_charge_for_initplans(root, final_rel);
@@ -953,7 +1012,8 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
if (root->hasJoinRTEs &&
!(kind == EXPRKIND_RTFUNC ||
kind == EXPRKIND_VALUES ||
- kind == EXPRKIND_TABLESAMPLE))
+ kind == EXPRKIND_TABLESAMPLE ||
+ kind == EXPRKIND_TABLEFUNC))
expr = flatten_join_alias_vars(root, expr);
/*
@@ -1090,7 +1150,6 @@ inheritance_planner(PlannerInfo *root)
{
Query *parse = root->parse;
int parentRTindex = parse->resultRelation;
- Bitmapset *resultRTindexes;
Bitmapset *subqueryRTindexes;
Bitmapset *modifiableARIindexes;
int nominalRelation = -1;
@@ -1106,6 +1165,8 @@ inheritance_planner(PlannerInfo *root)
RelOptInfo *final_rel;
ListCell *lc;
Index rti;
+ RangeTblEntry *parent_rte;
+ List *partitioned_rels = NIL;
Assert(parse->commandType != CMD_INSERT);
@@ -1124,26 +1185,7 @@ inheritance_planner(PlannerInfo *root)
* at least O(N^3) work expended here; and (2) would greatly complicate
* management of the rowMarks list.
*
- * Note that any RTEs with security barrier quals will be turned into
- * subqueries during planning, and so we must create copies of them too,
- * except where they are target relations, which will each only be used in
- * a single plan.
- *
- * To begin with, we'll need a bitmapset of the target relation relids.
- */
- resultRTindexes = bms_make_singleton(parentRTindex);
- foreach(lc, root->append_rel_list)
- {
- AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
-
- if (appinfo->parent_relid == parentRTindex)
- resultRTindexes = bms_add_member(resultRTindexes,
- appinfo->child_relid);
- }
-
- /*
- * Now, generate a bitmapset of the relids of the subquery RTEs, including
- * security-barrier RTEs that will become subqueries, as just explained.
+ * To begin with, generate a bitmapset of the relids of the subquery RTEs.
*/
subqueryRTindexes = NULL;
rti = 1;
@@ -1151,9 +1193,7 @@ inheritance_planner(PlannerInfo *root)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
- if (rte->rtekind == RTE_SUBQUERY ||
- (rte->securityQuals != NIL &&
- !bms_is_member(rti, resultRTindexes)))
+ if (rte->rtekind == RTE_SUBQUERY)
subqueryRTindexes = bms_add_member(subqueryRTindexes, rti);
rti++;
}
@@ -1185,12 +1225,25 @@ inheritance_planner(PlannerInfo *root)
}
/*
+ * If the parent RTE is a partitioned table, we should use that as the
+ * nominal relation, because the RTEs added for partitioned tables
+ * (including the root parent) as child members of the inheritance set do
+ * not appear anywhere else in the plan. The situation is exactly the
+ * opposite in the case of non-partitioned inheritance parent as described
+ * below.
+ */
+ parent_rte = rt_fetch(parentRTindex, root->parse->rtable);
+ if (parent_rte->relkind == RELKIND_PARTITIONED_TABLE)
+ nominalRelation = parentRTindex;
+
+ /*
* And now we can get on with generating a plan for each child table.
*/
foreach(lc, root->append_rel_list)
{
AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
PlannerInfo *subroot;
+ RangeTblEntry *child_rte;
RelOptInfo *sub_final_rel;
Path *subpath;
@@ -1217,12 +1270,21 @@ inheritance_planner(PlannerInfo *root)
appinfo);
/*
+ * If there are securityQuals attached to the parent, move them to the
+ * child rel (they've already been transformed properly for that).
+ */
+ parent_rte = rt_fetch(parentRTindex, subroot->parse->rtable);
+ child_rte = rt_fetch(appinfo->child_relid, subroot->parse->rtable);
+ child_rte->securityQuals = parent_rte->securityQuals;
+ parent_rte->securityQuals = NIL;
+
+ /*
* The rowMarks list might contain references to subquery RTEs, so
* make a copy that we can apply ChangeVarNodes to. (Fortunately, the
* executor doesn't need to see the modified copies --- we can just
* pass it the original rowMarks list.)
*/
- subroot->rowMarks = (List *) copyObject(root->rowMarks);
+ subroot->rowMarks = copyObject(root->rowMarks);
/*
* The append_rel_list likewise might contain references to subquery
@@ -1244,7 +1306,7 @@ inheritance_planner(PlannerInfo *root)
AppendRelInfo *appinfo2 = (AppendRelInfo *) lfirst(lc2);
if (bms_is_member(appinfo2->child_relid, modifiableARIindexes))
- appinfo2 = (AppendRelInfo *) copyObject(appinfo2);
+ appinfo2 = copyObject(appinfo2);
subroot->append_rel_list = lappend(subroot->append_rel_list,
appinfo2);
@@ -1263,11 +1325,11 @@ inheritance_planner(PlannerInfo *root)
/*
* If this isn't the first child Query, generate duplicates of all
- * subquery (or subquery-to-be) RTEs, and adjust Var numbering to
- * reference the duplicates. To simplify the loop logic, we scan the
- * original rtable not the copy just made by adjust_appendrel_attrs;
- * that should be OK since subquery RTEs couldn't contain any
- * references to the target rel.
+ * subquery RTEs, and adjust Var numbering to reference the
+ * duplicates. To simplify the loop logic, we scan the original rtable
+ * not the copy just made by adjust_appendrel_attrs; that should be OK
+ * since subquery RTEs couldn't contain any references to the target
+ * rel.
*/
if (final_rtable != NIL && subqueryRTindexes != NULL)
{
@@ -1284,9 +1346,9 @@ inheritance_planner(PlannerInfo *root)
/*
* The RTE can't contain any references to its own RT
- * index, except in the security barrier quals, so we can
- * save a few cycles by applying ChangeVarNodes before we
- * append the RTE to the rangetable.
+ * index, except in its securityQuals, so we can save a
+ * few cycles by applying ChangeVarNodes to the rest of
+ * the rangetable before we append the RTE to it.
*/
newrti = list_length(subroot->parse->rtable) + 1;
ChangeVarNodes((Node *) subroot->parse, rti, newrti, 0);
@@ -1325,21 +1387,25 @@ inheritance_planner(PlannerInfo *root)
grouping_planner(subroot, true, 0.0 /* retrieve all tuples */ );
/*
- * Planning may have modified the query result relation (if there were
- * security barrier quals on the result RTE).
- */
- appinfo->child_relid = subroot->parse->resultRelation;
-
- /*
- * We'll use the first child relation (even if it's excluded) as the
- * nominal target relation of the ModifyTable node. Because of the
- * way expand_inherited_rtentry works, this should always be the RTE
- * representing the parent table in its role as a simple member of the
- * inheritance set. (It would be logically cleaner to use the
- * inheritance parent RTE as the nominal target; but since that RTE
- * will not be otherwise referenced in the plan, doing so would give
- * rise to confusing use of multiple aliases in EXPLAIN output for
- * what the user will think is the "same" table.)
+ * Set the nomimal target relation of the ModifyTable node if not
+ * already done. We use the inheritance parent RTE as the nominal
+ * target relation if it's a partitioned table (see just above this
+ * loop). In the non-partitioned parent case, we'll use the first
+ * child relation (even if it's excluded) as the nominal target
+ * relation. Because of the way expand_inherited_rtentry works, the
+ * latter should be the RTE representing the parent table in its role
+ * as a simple member of the inheritance set.
+ *
+ * It would be logically cleaner to *always* use the inheritance
+ * parent RTE as the nominal relation; but that RTE is not otherwise
+ * referenced in the plan in the non-partitioned inheritance case.
+ * Instead the duplicate child RTE created by expand_inherited_rtentry
+ * is used elsewhere in the plan, so using the original parent RTE
+ * would give rise to confusing use of multiple aliases in EXPLAIN
+ * output for what the user will think is the "same" table. OTOH,
+ * it's not a problem in the partitioned inheritance case, because the
+ * duplicate child RTE added for the parent does not appear anywhere
+ * else in the plan tree.
*/
if (nominalRelation < 0)
nominalRelation = appinfo->child_relid;
@@ -1402,41 +1468,9 @@ inheritance_planner(PlannerInfo *root)
if (final_rtable == NIL)
final_rtable = subroot->parse->rtable;
else
- {
- List *tmp_rtable = NIL;
- ListCell *cell1,
- *cell2;
-
- /*
- * Check to see if any of the original RTEs were turned into
- * subqueries during planning. Currently, this should only ever
- * happen due to securityQuals being involved which push a
- * relation down under a subquery, to ensure that the security
- * barrier quals are evaluated first.
- *
- * When this happens, we want to use the new subqueries in the
- * final rtable.
- */
- forboth(cell1, final_rtable, cell2, subroot->parse->rtable)
- {
- RangeTblEntry *rte1 = (RangeTblEntry *) lfirst(cell1);
- RangeTblEntry *rte2 = (RangeTblEntry *) lfirst(cell2);
-
- if (rte1->rtekind == RTE_RELATION &&
- rte2->rtekind == RTE_SUBQUERY)
- {
- /* Should only be when there are securityQuals today */
- Assert(rte1->securityQuals != NIL);
- tmp_rtable = lappend(tmp_rtable, rte2);
- }
- else
- tmp_rtable = lappend(tmp_rtable, rte1);
- }
-
- final_rtable = list_concat(tmp_rtable,
+ final_rtable = list_concat(final_rtable,
list_copy_tail(subroot->parse->rtable,
list_length(final_rtable)));
- }
/*
* We need to collect all the RelOptInfos from all child plans into
@@ -1479,6 +1513,13 @@ inheritance_planner(PlannerInfo *root)
Assert(!parse->onConflict);
}
+ if (parent_rte->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ partitioned_rels = get_partitioned_child_rels(root, parentRTindex);
+ /* The root partitioned table is included as a child rel */
+ Assert(list_length(partitioned_rels) >= 1);
+ }
+
/* Result path must go into outer query's FINAL upperrel */
final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
@@ -1532,6 +1573,7 @@ inheritance_planner(PlannerInfo *root)
parse->commandType,
parse->canSetTag,
nominalRelation,
+ partitioned_rels,
resultRelations,
subpaths,
subroots,
@@ -1580,8 +1622,9 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
int64 count_est = 0;
double limit_tuples = -1.0;
bool have_postponed_srfs = false;
- double tlist_rows;
PathTarget *final_target;
+ List *final_targets;
+ List *final_targets_contain_srfs;
RelOptInfo *current_rel;
RelOptInfo *final_rel;
ListCell *lc;
@@ -1644,6 +1687,10 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
/* Also extract the PathTarget form of the setop result tlist */
final_target = current_rel->cheapest_total_path->pathtarget;
+ /* The setop result tlist couldn't contain any SRFs */
+ Assert(!parse->hasTargetSRFs);
+ final_targets = final_targets_contain_srfs = NIL;
+
/*
* Can't handle FOR [KEY] UPDATE/SHARE here (parser should have
* checked already, but let's make sure).
@@ -1669,14 +1716,19 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
{
/* No set operations, do regular planning */
PathTarget *sort_input_target;
+ List *sort_input_targets;
+ List *sort_input_targets_contain_srfs;
PathTarget *grouping_target;
+ List *grouping_targets;
+ List *grouping_targets_contain_srfs;
PathTarget *scanjoin_target;
+ List *scanjoin_targets;
+ List *scanjoin_targets_contain_srfs;
bool have_grouping;
AggClauseCosts agg_costs;
WindowFuncLists *wflists = NULL;
List *activeWindows = NIL;
- List *rollup_lists = NIL;
- List *rollup_groupclauses = NIL;
+ grouping_sets_data *gset_data = NULL;
standard_qp_extra qp_extra;
/* A recursive query should always have setOperations */
@@ -1685,84 +1737,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
/* Preprocess grouping sets and GROUP BY clause, if any */
if (parse->groupingSets)
{
- int *tleref_to_colnum_map;
- List *sets;
- int maxref;
- ListCell *lc;
- ListCell *lc2;
- ListCell *lc_set;
-
- parse->groupingSets = expand_grouping_sets(parse->groupingSets, -1);
-
- /* Identify max SortGroupRef in groupClause, for array sizing */
- maxref = 0;
- foreach(lc, parse->groupClause)
- {
- SortGroupClause *gc = lfirst(lc);
-
- if (gc->tleSortGroupRef > maxref)
- maxref = gc->tleSortGroupRef;
- }
-
- /* Allocate workspace array for remapping */
- tleref_to_colnum_map = (int *) palloc((maxref + 1) * sizeof(int));
-
- /* Examine the rollup sets */
- sets = extract_rollup_sets(parse->groupingSets);
-
- foreach(lc_set, sets)
- {
- List *current_sets = (List *) lfirst(lc_set);
- List *groupclause;
- int ref;
-
- /*
- * Reorder the current list of grouping sets into correct
- * prefix order. If only one aggregation pass is needed, try
- * to make the list match the ORDER BY clause; if more than
- * one pass is needed, we don't bother with that.
- */
- current_sets = reorder_grouping_sets(current_sets,
- (list_length(sets) == 1
- ? parse->sortClause
- : NIL));
-
- /*
- * Order the groupClause appropriately. If the first grouping
- * set is empty, this can match regular GROUP BY
- * preprocessing, otherwise we have to force the groupClause
- * to match that grouping set's order.
- */
- groupclause = preprocess_groupclause(root,
- linitial(current_sets));
-
- /*
- * Now that we've pinned down an order for the groupClause for
- * this list of grouping sets, we need to remap the entries in
- * the grouping sets from sortgrouprefs to plain indices
- * (0-based) into the groupClause for this collection of
- * grouping sets.
- */
- ref = 0;
- foreach(lc, groupclause)
- {
- SortGroupClause *gc = lfirst(lc);
-
- tleref_to_colnum_map[gc->tleSortGroupRef] = ref++;
- }
-
- foreach(lc, current_sets)
- {
- foreach(lc2, (List *) lfirst(lc))
- {
- lfirst_int(lc2) = tleref_to_colnum_map[lfirst_int(lc2)];
- }
- }
-
- /* Save the reordered sets and corresponding groupclauses */
- rollup_lists = lcons(current_sets, rollup_lists);
- rollup_groupclauses = lcons(groupclause, rollup_groupclauses);
- }
+ gset_data = preprocess_grouping_sets(root);
}
else
{
@@ -1781,12 +1756,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
parse->rtable);
/*
- * Expand any rangetable entries that have security barrier quals.
- * This may add new security barrier subquery RTEs to the rangetable.
- */
- expand_security_quals(root, tlist);
-
- /*
* We are now done hacking up the query's targetlist. Most of the
* remaining planning work will be done with the PathTarget
* representation of tlists, but save aside the full representation so
@@ -1846,16 +1815,14 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
* Figure out whether there's a hard limit on the number of rows that
* query_planner's result subplan needs to return. Even if we know a
* hard limit overall, it doesn't apply if the query has any
- * grouping/aggregation operations. (XXX it also doesn't apply if the
- * tlist contains any SRFs; but checking for that here seems more
- * costly than it's worth, since root->limit_tuples is only used for
- * cost estimates, and only in a small number of cases.)
+ * grouping/aggregation operations, or SRFs in the tlist.
*/
if (parse->groupClause ||
parse->groupingSets ||
parse->distinctClause ||
parse->hasAggs ||
parse->hasWindowFuncs ||
+ parse->hasTargetSRFs ||
root->hasHavingQual)
root->limit_tuples = -1.0;
else
@@ -1864,8 +1831,9 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
/* Set up data needed by standard_qp_callback */
qp_extra.tlist = tlist;
qp_extra.activeWindows = activeWindows;
- qp_extra.groupClause =
- parse->groupingSets ? llast(rollup_groupclauses) : parse->groupClause;
+ qp_extra.groupClause = (gset_data
+ ? (gset_data->rollups ? ((RollupData *) linitial(gset_data->rollups))->groupClause : NIL)
+ : parse->groupClause);
/*
* Generate the best unsorted and presorted paths for the scan/join
@@ -1923,8 +1891,50 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
scanjoin_target = grouping_target;
/*
- * Forcibly apply scan/join target to all the Paths for the scan/join
- * rel.
+ * If there are any SRFs in the targetlist, we must separate each of
+ * these PathTargets into SRF-computing and SRF-free targets. Replace
+ * each of the named targets with a SRF-free version, and remember the
+ * list of additional projection steps we need to add afterwards.
+ */
+ if (parse->hasTargetSRFs)
+ {
+ /* final_target doesn't recompute any SRFs in sort_input_target */
+ split_pathtarget_at_srfs(root, final_target, sort_input_target,
+ &final_targets,
+ &final_targets_contain_srfs);
+ final_target = (PathTarget *) linitial(final_targets);
+ Assert(!linitial_int(final_targets_contain_srfs));
+ /* likewise for sort_input_target vs. grouping_target */
+ split_pathtarget_at_srfs(root, sort_input_target, grouping_target,
+ &sort_input_targets,
+ &sort_input_targets_contain_srfs);
+ sort_input_target = (PathTarget *) linitial(sort_input_targets);
+ Assert(!linitial_int(sort_input_targets_contain_srfs));
+ /* likewise for grouping_target vs. scanjoin_target */
+ split_pathtarget_at_srfs(root, grouping_target, scanjoin_target,
+ &grouping_targets,
+ &grouping_targets_contain_srfs);
+ grouping_target = (PathTarget *) linitial(grouping_targets);
+ Assert(!linitial_int(grouping_targets_contain_srfs));
+ /* scanjoin_target will not have any SRFs precomputed for it */
+ split_pathtarget_at_srfs(root, scanjoin_target, NULL,
+ &scanjoin_targets,
+ &scanjoin_targets_contain_srfs);
+ scanjoin_target = (PathTarget *) linitial(scanjoin_targets);
+ Assert(!linitial_int(scanjoin_targets_contain_srfs));
+ }
+ else
+ {
+ /* initialize lists, just to keep compiler quiet */
+ final_targets = final_targets_contain_srfs = NIL;
+ sort_input_targets = sort_input_targets_contain_srfs = NIL;
+ grouping_targets = grouping_targets_contain_srfs = NIL;
+ scanjoin_targets = scanjoin_targets_contain_srfs = NIL;
+ }
+
+ /*
+ * Forcibly apply SRF-free scan/join target to all the Paths for the
+ * scan/join rel.
*
* In principle we should re-run set_cheapest() here to identify the
* cheapest path, but it seems unlikely that adding the same tlist
@@ -1961,7 +1971,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
* computed by partial paths.
*/
if (current_rel->partial_pathlist &&
- !has_parallel_hazard((Node *) scanjoin_target->exprs, false))
+ is_parallel_safe(root, (Node *) scanjoin_target->exprs))
{
/* Apply the scan/join target to each partial path */
foreach(lc, current_rel->partial_pathlist)
@@ -1995,6 +2005,12 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
current_rel->partial_pathlist = NIL;
}
+ /* Now fix things up if scan/join target contains SRFs */
+ if (parse->hasTargetSRFs)
+ adjust_paths_for_srfs(root, current_rel,
+ scanjoin_targets,
+ scanjoin_targets_contain_srfs);
+
/*
* Save the various upper-rel PathTargets we just computed into
* root->upper_targets[]. The core code doesn't use this, but it
@@ -2017,8 +2033,12 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
current_rel,
grouping_target,
&agg_costs,
- rollup_lists,
- rollup_groupclauses);
+ gset_data);
+ /* Fix things up if grouping_target contains SRFs */
+ if (parse->hasTargetSRFs)
+ adjust_paths_for_srfs(root, current_rel,
+ grouping_targets,
+ grouping_targets_contain_srfs);
}
/*
@@ -2034,6 +2054,11 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
tlist,
wflists,
activeWindows);
+ /* Fix things up if sort_input_target contains SRFs */
+ if (parse->hasTargetSRFs)
+ adjust_paths_for_srfs(root, current_rel,
+ sort_input_targets,
+ sort_input_targets_contain_srfs);
}
/*
@@ -2045,7 +2070,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
current_rel = create_distinct_paths(root,
current_rel);
}
-
} /* end of if (setOperations) */
/*
@@ -2062,36 +2086,11 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
final_target,
have_postponed_srfs ? -1.0 :
limit_tuples);
- }
-
- /*
- * If there are set-returning functions in the tlist, scale up the output
- * rowcounts of all surviving Paths to account for that. Note that if any
- * SRFs appear in sorting or grouping columns, we'll have underestimated
- * the numbers of rows passing through earlier steps; but that's such a
- * weird usage that it doesn't seem worth greatly complicating matters to
- * account for it.
- */
- tlist_rows = tlist_returns_set_rows(tlist);
- if (tlist_rows > 1)
- {
- foreach(lc, current_rel->pathlist)
- {
- Path *path = (Path *) lfirst(lc);
-
- /*
- * We assume that execution costs of the tlist as such were
- * already accounted for. However, it still seems appropriate to
- * charge something more for the executor's general costs of
- * processing the added tuples. The cost is probably less than
- * cpu_tuple_cost, though, so we arbitrarily use half of that.
- */
- path->total_cost += path->rows * (tlist_rows - 1) *
- cpu_tuple_cost / 2;
-
- path->rows *= tlist_rows;
- }
- /* No need to run set_cheapest; we're keeping all paths anyway. */
+ /* Fix things up if final_target contains SRFs */
+ if (parse->hasTargetSRFs)
+ adjust_paths_for_srfs(root, current_rel,
+ final_targets,
+ final_targets_contain_srfs);
}
/*
@@ -2107,8 +2106,8 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
* query.
*/
if (current_rel->consider_parallel &&
- !has_parallel_hazard(parse->limitOffset, false) &&
- !has_parallel_hazard(parse->limitCount, false))
+ is_parallel_safe(root, parse->limitOffset) &&
+ is_parallel_safe(root, parse->limitCount))
final_rel->consider_parallel = true;
/*
@@ -2234,6 +2233,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
parse->commandType,
parse->canSetTag,
parse->resultRelation,
+ NIL,
list_make1_int(parse->resultRelation),
list_make1(path),
list_make1(root),
@@ -2268,6 +2268,221 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
/* Note: currently, we leave it to callers to do set_cheapest() */
}
+/*
+ * Do preprocessing for groupingSets clause and related data. This handles the
+ * preliminary steps of expanding the grouping sets, organizing them into lists
+ * of rollups, and preparing annotations which will later be filled in with
+ * size estimates.
+ */
+static grouping_sets_data *
+preprocess_grouping_sets(PlannerInfo *root)
+{
+ Query *parse = root->parse;
+ List *sets;
+ int maxref = 0;
+ ListCell *lc;
+ ListCell *lc_set;
+ grouping_sets_data *gd = palloc0(sizeof(grouping_sets_data));
+
+ parse->groupingSets = expand_grouping_sets(parse->groupingSets, -1);
+
+ gd->any_hashable = false;
+ gd->unhashable_refs = NULL;
+ gd->unsortable_refs = NULL;
+ gd->unsortable_sets = NIL;
+
+ if (parse->groupClause)
+ {
+ ListCell *lc;
+
+ foreach(lc, parse->groupClause)
+ {
+ SortGroupClause *gc = lfirst(lc);
+ Index ref = gc->tleSortGroupRef;
+
+ if (ref > maxref)
+ maxref = ref;
+
+ if (!gc->hashable)
+ gd->unhashable_refs = bms_add_member(gd->unhashable_refs, ref);
+
+ if (!OidIsValid(gc->sortop))
+ gd->unsortable_refs = bms_add_member(gd->unsortable_refs, ref);
+ }
+ }
+
+ /* Allocate workspace array for remapping */
+ gd->tleref_to_colnum_map = (int *) palloc((maxref + 1) * sizeof(int));
+
+ /*
+ * If we have any unsortable sets, we must extract them before trying to
+ * prepare rollups. Unsortable sets don't go through
+ * reorder_grouping_sets, so we must apply the GroupingSetData annotation
+ * here.
+ */
+ if (!bms_is_empty(gd->unsortable_refs))
+ {
+ List *sortable_sets = NIL;
+
+ foreach(lc, parse->groupingSets)
+ {
+ List *gset = lfirst(lc);
+
+ if (bms_overlap_list(gd->unsortable_refs, gset))
+ {
+ GroupingSetData *gs = makeNode(GroupingSetData);
+
+ gs->set = gset;
+ gd->unsortable_sets = lappend(gd->unsortable_sets, gs);
+
+ /*
+ * We must enforce here that an unsortable set is hashable;
+ * later code assumes this. Parse analysis only checks that
+ * every individual column is either hashable or sortable.
+ *
+ * Note that passing this test doesn't guarantee we can
+ * generate a plan; there might be other showstoppers.
+ */
+ if (bms_overlap_list(gd->unhashable_refs, gset))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("could not implement GROUP BY"),
+ errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
+ }
+ else
+ sortable_sets = lappend(sortable_sets, gset);
+ }
+
+ if (sortable_sets)
+ sets = extract_rollup_sets(sortable_sets);
+ else
+ sets = NIL;
+ }
+ else
+ sets = extract_rollup_sets(parse->groupingSets);
+
+ foreach(lc_set, sets)
+ {
+ List *current_sets = (List *) lfirst(lc_set);
+ RollupData *rollup = makeNode(RollupData);
+ GroupingSetData *gs;
+
+ /*
+ * Reorder the current list of grouping sets into correct prefix
+ * order. If only one aggregation pass is needed, try to make the
+ * list match the ORDER BY clause; if more than one pass is needed, we
+ * don't bother with that.
+ *
+ * Note that this reorders the sets from smallest-member-first to
+ * largest-member-first, and applies the GroupingSetData annotations,
+ * though the data will be filled in later.
+ */
+ current_sets = reorder_grouping_sets(current_sets,
+ (list_length(sets) == 1
+ ? parse->sortClause
+ : NIL));
+
+ /*
+ * Get the initial (and therefore largest) grouping set.
+ */
+ gs = linitial(current_sets);
+
+ /*
+ * Order the groupClause appropriately. If the first grouping set is
+ * empty, then the groupClause must also be empty; otherwise we have
+ * to force the groupClause to match that grouping set's order.
+ *
+ * (The first grouping set can be empty even though parse->groupClause
+ * is not empty only if all non-empty grouping sets are unsortable.
+ * The groupClauses for hashed grouping sets are built later on.)
+ */
+ if (gs->set)
+ rollup->groupClause = preprocess_groupclause(root, gs->set);
+ else
+ rollup->groupClause = NIL;
+
+ /*
+ * Is it hashable? We pretend empty sets are hashable even though we
+ * actually force them not to be hashed later. But don't bother if
+ * there's nothing but empty sets (since in that case we can't hash
+ * anything).
+ */
+ if (gs->set &&
+ !bms_overlap_list(gd->unhashable_refs, gs->set))
+ {
+ rollup->hashable = true;
+ gd->any_hashable = true;
+ }
+
+ /*
+ * Now that we've pinned down an order for the groupClause for this
+ * list of grouping sets, we need to remap the entries in the grouping
+ * sets from sortgrouprefs to plain indices (0-based) into the
+ * groupClause for this collection of grouping sets. We keep the
+ * original form for later use, though.
+ */
+ rollup->gsets = remap_to_groupclause_idx(rollup->groupClause,
+ current_sets,
+ gd->tleref_to_colnum_map);
+ rollup->gsets_data = current_sets;
+
+ gd->rollups = lappend(gd->rollups, rollup);
+ }
+
+ if (gd->unsortable_sets)
+ {
+ /*
+ * We have not yet pinned down a groupclause for this, but we will
+ * need index-based lists for estimation purposes. Construct
+ * hash_sets_idx based on the entire original groupclause for now.
+ */
+ gd->hash_sets_idx = remap_to_groupclause_idx(parse->groupClause,
+ gd->unsortable_sets,
+ gd->tleref_to_colnum_map);
+ gd->any_hashable = true;
+ }
+
+ return gd;
+}
+
+/*
+ * Given a groupclause and a list of GroupingSetData, return equivalent sets
+ * (without annotation) mapped to indexes into the given groupclause.
+ */
+static List *
+remap_to_groupclause_idx(List *groupClause,
+ List *gsets,
+ int *tleref_to_colnum_map)
+{
+ int ref = 0;
+ List *result = NIL;
+ ListCell *lc;
+
+ foreach(lc, groupClause)
+ {
+ SortGroupClause *gc = lfirst(lc);
+
+ tleref_to_colnum_map[gc->tleSortGroupRef] = ref++;
+ }
+
+ foreach(lc, gsets)
+ {
+ List *set = NIL;
+ ListCell *lc2;
+ GroupingSetData *gs = lfirst(lc);
+
+ foreach(lc2, gs->set)
+ {
+ set = lappend_int(set, tleref_to_colnum_map[lfirst_int(lc2)]);
+ }
+
+ result = lappend(result, set);
+ }
+
+ return result;
+}
+
+
/*
* Detect whether a plan node is a "dummy" plan created when a relation
@@ -2301,52 +2516,6 @@ is_dummy_plan(Plan *plan)
}
/*
- * Create a bitmapset of the RT indexes of live base relations
- *
- * Helper for preprocess_rowmarks ... at this point in the proceedings,
- * the only good way to distinguish baserels from appendrel children
- * is to see what is in the join tree.
- */
-static Bitmapset *
-get_base_rel_indexes(Node *jtnode)
-{
- Bitmapset *result;
-
- if (jtnode == NULL)
- return NULL;
- if (IsA(jtnode, RangeTblRef))
- {
- int varno = ((RangeTblRef *) jtnode)->rtindex;
-
- result = bms_make_singleton(varno);
- }
- else if (IsA(jtnode, FromExpr))
- {
- FromExpr *f = (FromExpr *) jtnode;
- ListCell *l;
-
- result = NULL;
- foreach(l, f->fromlist)
- result = bms_join(result,
- get_base_rel_indexes(lfirst(l)));
- }
- else if (IsA(jtnode, JoinExpr))
- {
- JoinExpr *j = (JoinExpr *) jtnode;
-
- result = bms_join(get_base_rel_indexes(j->larg),
- get_base_rel_indexes(j->rarg));
- }
- else
- {
- elog(ERROR, "unrecognized node type: %d",
- (int) nodeTag(jtnode));
- result = NULL; /* keep compiler quiet */
- }
- return result;
-}
-
-/*
* preprocess_rowmarks - set up PlanRowMarks if needed
*/
static void
@@ -2371,7 +2540,8 @@ preprocess_rowmarks(PlannerInfo *root)
if (parse->jointree)
{
- Bitmapset *baserels = get_base_rel_indexes((Node *) parse->jointree);
+ Bitmapset *baserels = get_relids_in_jointree((Node *)
+ parse->jointree, false);
int x, num_rels = 0;
bool dist_found = false;
@@ -2410,7 +2580,7 @@ preprocess_rowmarks(PlannerInfo *root)
* make a bitmapset of all base rels and then remove the items we don't
* need or have FOR [KEY] UPDATE/SHARE marks for.
*/
- rels = get_base_rel_indexes((Node *) parse->jointree);
+ rels = get_relids_in_jointree((Node *) parse->jointree, false);
if (parse->resultRelation)
rels = bms_del_member(rels, parse->resultRelation);
@@ -2513,17 +2683,8 @@ select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
/*
* We don't need a tuple lock, only the ability to re-fetch
- * the row. Regular tables support ROW_MARK_REFERENCE, but if
- * this RTE has security barrier quals, it will be turned into
- * a subquery during planning, so use ROW_MARK_COPY.
- *
- * This is only necessary for LCS_NONE, since real tuple locks
- * on an RTE with security barrier quals are supported by
- * pushing the lock down into the subquery --- see
- * expand_security_qual.
+ * the row.
*/
- if (rte->securityQuals != NIL)
- return ROW_MARK_COPY;
return ROW_MARK_REFERENCE;
break;
case LCS_FORKEYSHARE:
@@ -3264,7 +3425,7 @@ extract_rollup_sets(List *groupingSets)
/*
* Reorder the elements of a list of grouping sets such that they have correct
- * prefix relationships.
+ * prefix relationships. Also inserts the GroupingSetData annotations.
*
* The input must be ordered with smallest sets first; the result is returned
* with largest sets first. Note that the result shares no list substructure
@@ -3287,6 +3448,7 @@ reorder_grouping_sets(List *groupingsets, List *sortclause)
{
List *candidate = lfirst(lc);
List *new_elems = list_difference_int(candidate, previous);
+ GroupingSetData *gs = makeNode(GroupingSetData);
if (list_length(new_elems) > 0)
{
@@ -3314,7 +3476,8 @@ reorder_grouping_sets(List *groupingsets, List *sortclause)
}
}
- result = lcons(list_copy(previous), result);
+ gs->set = list_copy(previous);
+ result = lcons(gs, result);
list_free(new_elems);
}
@@ -3409,15 +3572,16 @@ standard_qp_callback(PlannerInfo *root, void *extra)
* Estimate number of groups produced by grouping clauses (1 if not grouping)
*
* path_rows: number of output rows from scan/join step
- * rollup_lists: list of grouping sets, or NIL if not doing grouping sets
- * rollup_groupclauses: list of grouping clauses for grouping sets,
- * or NIL if not doing grouping sets
+ * gsets: grouping set data, or NULL if not doing grouping sets
+ *
+ * If doing grouping sets, we also annotate the gsets data with the estimates
+ * for each set and each individual rollup list, with a view to later
+ * determining whether some combination of them could be hashed instead.
*/
static double
get_number_of_groups(PlannerInfo *root,
double path_rows,
- List *rollup_lists,
- List *rollup_groupclauses)
+ grouping_sets_data *gd)
{
Query *parse = root->parse;
double dNumGroups;
@@ -3429,28 +3593,62 @@ get_number_of_groups(PlannerInfo *root,
if (parse->groupingSets)
{
/* Add up the estimates for each grouping set */
- ListCell *lc,
- *lc2;
+ ListCell *lc;
+ ListCell *lc2;
+
+ Assert(gd); /* keep Coverity happy */
dNumGroups = 0;
- forboth(lc, rollup_groupclauses, lc2, rollup_lists)
+
+ foreach(lc, gd->rollups)
{
- List *groupClause = (List *) lfirst(lc);
- List *gsets = (List *) lfirst(lc2);
- ListCell *lc3;
+ RollupData *rollup = lfirst(lc);
+ ListCell *lc;
- groupExprs = get_sortgrouplist_exprs(groupClause,
+ groupExprs = get_sortgrouplist_exprs(rollup->groupClause,
parse->targetList);
- foreach(lc3, gsets)
+ rollup->numGroups = 0.0;
+
+ forboth(lc, rollup->gsets, lc2, rollup->gsets_data)
{
- List *gset = (List *) lfirst(lc3);
+ List *gset = (List *) lfirst(lc);
+ GroupingSetData *gs = lfirst(lc2);
+ double numGroups = estimate_num_groups(root,
+ groupExprs,
+ path_rows,
+ &gset);
+
+ gs->numGroups = numGroups;
+ rollup->numGroups += numGroups;
+ }
- dNumGroups += estimate_num_groups(root,
- groupExprs,
- path_rows,
- &gset);
+ dNumGroups += rollup->numGroups;
+ }
+
+ if (gd->hash_sets_idx)
+ {
+ ListCell *lc;
+
+ gd->dNumHashGroups = 0;
+
+ groupExprs = get_sortgrouplist_exprs(parse->groupClause,
+ parse->targetList);
+
+ forboth(lc, gd->hash_sets_idx, lc2, gd->unsortable_sets)
+ {
+ List *gset = (List *) lfirst(lc);
+ GroupingSetData *gs = lfirst(lc2);
+ double numGroups = estimate_num_groups(root,
+ groupExprs,
+ path_rows,
+ &gset);
+
+ gs->numGroups = numGroups;
+ gd->dNumHashGroups += numGroups;
}
+
+ dNumGroups += gd->dNumHashGroups;
}
}
else
@@ -3486,6 +3684,11 @@ get_number_of_groups(PlannerInfo *root,
* estimate_hashagg_tablesize
* estimate the number of bytes that a hash aggregate hashtable will
* require based on the agg_costs, path width and dNumGroups.
+ *
+ * XXX this may be over-estimating the size now that hashagg knows to omit
+ * unneeded columns from the hashtable. Also for mixed-mode grouping sets,
+ * grouping columns not in the hashed set are counted here even though hashagg
+ * won't store them. Is this a problem?
*/
static Size
estimate_hashagg_tablesize(Path *path, const AggClauseCosts *agg_costs,
@@ -3502,6 +3705,12 @@ estimate_hashagg_tablesize(Path *path, const AggClauseCosts *agg_costs,
/* plus the per-hash-entry overhead */
hashentrysize += hash_agg_entry_size(agg_costs->numAggs);
+ /*
+ * Note that this disregards the effect of fill-factor and growth policy
+ * of the hash-table. That's probably ok, given default the default
+ * fill-factor is relatively high. It'd be hard to meaningfully factor in
+ * "double-in-size" growth policies here.
+ */
return hashentrysize * dNumGroups;
}
@@ -3530,8 +3739,7 @@ create_grouping_paths(PlannerInfo *root,
RelOptInfo *input_rel,
PathTarget *target,
const AggClauseCosts *agg_costs,
- List *rollup_lists,
- List *rollup_groupclauses)
+ grouping_sets_data *gd)
{
Query *parse = root->parse;
Path *cheapest_path = input_rel->cheapest_total_path;
@@ -3558,8 +3766,8 @@ create_grouping_paths(PlannerInfo *root,
* target list and HAVING quals are parallel-safe.
*/
if (input_rel->consider_parallel &&
- !has_parallel_hazard((Node *) target->exprs, false) &&
- !has_parallel_hazard((Node *) parse->havingQual, false))
+ is_parallel_safe(root, (Node *) target->exprs) &&
+ is_parallel_safe(root, (Node *) parse->havingQual))
grouped_rel->consider_parallel = true;
/*
@@ -3615,7 +3823,8 @@ create_grouping_paths(PlannerInfo *root,
create_append_path(grouped_rel,
paths,
NULL,
- 0);
+ 0,
+ NIL);
path->pathtarget = target;
}
else
@@ -3640,8 +3849,7 @@ create_grouping_paths(PlannerInfo *root,
*/
dNumGroups = get_number_of_groups(root,
cheapest_path->rows,
- rollup_lists,
- rollup_groupclauses);
+ gd);
/*
* Determine whether it's possible to perform sort-based implementations
@@ -3649,15 +3857,22 @@ create_grouping_paths(PlannerInfo *root,
* grouping_is_sortable() is trivially true, and all the
* pathkeys_contained_in() tests will succeed too, so that we'll consider
* every surviving input path.)
+ *
+ * If we have grouping sets, we might be able to sort some but not all of
+ * them; in this case, we need can_sort to be true as long as we must
+ * consider any sorted-input plan.
*/
- can_sort = grouping_is_sortable(parse->groupClause);
+ can_sort = (gd && gd->rollups != NIL)
+ || grouping_is_sortable(parse->groupClause);
/*
* Determine whether we should consider hash-based implementations of
* grouping.
*
- * Hashed aggregation only applies if we're grouping. We currently can't
- * hash if there are grouping sets, though.
+ * Hashed aggregation only applies if we're grouping. If we have grouping
+ * sets, some groups might be hashable but others not; in this case we set
+ * can_hash true as long as there is nothing globally preventing us from
+ * hashing (and we should therefore consider plans with hashes).
*
* Executor doesn't support hashed aggregation with DISTINCT or ORDER BY
* aggregates. (Doing so would imply storing *all* the input values in
@@ -3670,9 +3885,8 @@ create_grouping_paths(PlannerInfo *root,
* other gating conditions, so we want to do it last.
*/
can_hash = (parse->groupClause != NIL &&
- parse->groupingSets == NIL &&
agg_costs->numOrderedAggs == 0 &&
- grouping_is_hashable(parse->groupClause));
+ (gd ? gd->any_hashable : grouping_is_hashable(parse->groupClause)));
/*
* If grouped_rel->consider_parallel is true, then paths that we generate
@@ -3770,8 +3984,7 @@ create_grouping_paths(PlannerInfo *root,
/* Estimate number of partial groups. */
dNumPartialGroups = get_number_of_groups(root,
cheapest_partial_path->rows,
- NIL,
- NIL);
+ gd);
/*
* Collect statistics about aggregates for estimating costs of
@@ -3949,20 +4162,9 @@ create_grouping_paths(PlannerInfo *root,
/* Now decide what to stick atop it */
if (parse->groupingSets)
{
- /*
- * We have grouping sets, possibly with aggregation. Make
- * a GroupingSetsPath.
- */
- add_path(grouped_rel, (Path *)
- create_groupingsets_path(root,
- grouped_rel,
- path,
- target,
- (List *) parse->havingQual,
- rollup_lists,
- rollup_groupclauses,
- agg_costs,
- dNumGroups));
+ consider_groupingsets_paths(root, grouped_rel,
+ path, true, can_hash, target,
+ gd, agg_costs, dNumGroups);
}
else if (parse->hasAggs)
{
@@ -4007,8 +4209,7 @@ create_grouping_paths(PlannerInfo *root,
/*
* Now generate a complete GroupAgg Path atop of the cheapest partial
- * path. We need only bother with the cheapest path here, as the
- * output of Gather is never sorted.
+ * path. We can do this using either Gather or Gather Merge.
*/
if (grouped_rel->partial_pathlist)
{
@@ -4023,11 +4224,11 @@ create_grouping_paths(PlannerInfo *root,
&total_groups);
/*
- * Gather is always unsorted, so we'll need to sort, unless
- * there's no GROUP BY clause, in which case there will only be a
- * single group.
+ * Since Gather's output is always unsorted, we'll need to sort,
+ * unless there's no GROUP BY clause or a degenerate (constant)
+ * one, in which case there will only be a single group.
*/
- if (parse->groupClause)
+ if (root->group_pathkeys)
path = (Path *) create_sort_path(root,
grouped_rel,
path,
@@ -4070,54 +4271,130 @@ create_grouping_paths(PlannerInfo *root,
parse->groupClause,
(List *) parse->havingQual,
dNumGroups));
+
+ /*
+ * The point of using Gather Merge rather than Gather is that it
+ * can preserve the ordering of the input path, so there's no
+ * reason to try it unless (1) it's possible to produce more than
+ * one output row and (2) we want the output path to be ordered.
+ */
+ if (parse->groupClause != NIL && root->group_pathkeys != NIL)
+ {
+ foreach(lc, grouped_rel->partial_pathlist)
+ {
+ Path *subpath = (Path *) lfirst(lc);
+ Path *gmpath;
+ double total_groups;
+
+ /*
+ * It's useful to consider paths that are already properly
+ * ordered for Gather Merge, because those don't need a
+ * sort. It's also useful to consider the cheapest path,
+ * because sorting it in parallel and then doing Gather
+ * Merge may be better than doing an unordered Gather
+ * followed by a sort. But there's no point in
+ * considering non-cheapest paths that aren't already
+ * sorted correctly.
+ */
+ if (path != subpath &&
+ !pathkeys_contained_in(root->group_pathkeys,
+ subpath->pathkeys))
+ continue;
+
+ total_groups = subpath->rows * subpath->parallel_workers;
+
+ gmpath = (Path *)
+ create_gather_merge_path(root,
+ grouped_rel,
+ subpath,
+ partial_grouping_target,
+ root->group_pathkeys,
+ NULL,
+ &total_groups);
+
+ if (parse->hasAggs)
+ add_path(grouped_rel, (Path *)
+ create_agg_path(root,
+ grouped_rel,
+ gmpath,
+ target,
+ parse->groupClause ? AGG_SORTED : AGG_PLAIN,
+ AGGSPLIT_FINAL_DESERIAL,
+ parse->groupClause,
+ (List *) parse->havingQual,
+ &agg_final_costs,
+ dNumGroups));
+ else
+ add_path(grouped_rel, (Path *)
+ create_group_path(root,
+ grouped_rel,
+ gmpath,
+ target,
+ parse->groupClause,
+ (List *) parse->havingQual,
+ dNumGroups));
+ }
+ }
}
}
if (can_hash)
{
- hashaggtablesize = estimate_hashagg_tablesize(cheapest_path,
- agg_costs,
- dNumGroups);
-
- /*
- * Provided that the estimated size of the hashtable does not exceed
- * work_mem, we'll generate a HashAgg Path, although if we were unable
- * to sort above, then we'd better generate a Path, so that we at
- * least have one.
- */
- if (hashaggtablesize < work_mem * 1024L ||
- grouped_rel->pathlist == NIL)
+ if (parse->groupingSets)
{
- /* Don't mess with the cheapest path directly. */
- Path *path = cheapest_path;
-
/*
- * If the grouping can't be fully pushed down, we'll push down the
- * first phase of the aggregate, and redistribute only the partial
- * results.
- *
- * If if can be pushed down, disable construction of complex
- * distributed paths.
+ * Try for a hash-only groupingsets path over unsorted input.
*/
- if (! can_push_down_grouping(root, parse, path))
- path = create_remotesubplan_path(root, path, NULL);
- else
- try_distributed_aggregation = false;
+ consider_groupingsets_paths(root, grouped_rel,
+ cheapest_path, false, true, target,
+ gd, agg_costs, dNumGroups);
+ }
+ else
+ {
+ hashaggtablesize = estimate_hashagg_tablesize(cheapest_path,
+ agg_costs,
+ dNumGroups);
/*
- * We just need an Agg over the cheapest-total input path, since
- * input order won't matter.
+ * Provided that the estimated size of the hashtable does not
+ * exceed work_mem, we'll generate a HashAgg Path, although if we
+ * were unable to sort above, then we'd better generate a Path, so
+ * that we at least have one.
*/
- add_path(grouped_rel, (Path *)
- create_agg_path(root, grouped_rel,
- path,
- target,
- AGG_HASHED,
- AGGSPLIT_SIMPLE,
- parse->groupClause,
- (List *) parse->havingQual,
- agg_costs,
- dNumGroups));
+ if (hashaggtablesize < work_mem * 1024L ||
+ grouped_rel->pathlist == NIL)
+ {
+ /* Don't mess with the cheapest path directly. */
+ Path *path = cheapest_path;
+
+ /*
+ * If the grouping can't be fully pushed down, we'll push down the
+ * first phase of the aggregate, and redistribute only the partial
+ * results.
+ *
+ * If if can be pushed down, disable construction of complex
+ * distributed paths.
+ */
+ if (! can_push_down_grouping(root, parse, path))
+ path = create_remotesubplan_path(root, path, NULL);
+ else
+ try_distributed_aggregation = false;
+
+ /*
+ * We just need an Agg over the cheapest-total input path,
+ * since input order won't matter.
+ */
+ add_path(grouped_rel, (Path *)
+ create_agg_path(root, grouped_rel,
+ path,
+ target,
+ AGG_HASHED,
+ AGGSPLIT_SIMPLE,
+ parse->groupClause,
+ (List *) parse->havingQual,
+ agg_costs,
+ dNumGroups));
+ }
}
/*
@@ -4203,8 +4480,7 @@ create_grouping_paths(PlannerInfo *root,
/* Estimate number of partial groups. */
dNumPartialGroups = get_number_of_groups(root,
cheapest_path->rows,
- NIL,
- NIL);
+ gd);
/*
* Collect statistics about aggregates for estimating costs of
@@ -4242,7 +4518,7 @@ create_grouping_paths(PlannerInfo *root,
bool is_sorted;
is_sorted = pathkeys_contained_in(root->group_pathkeys,
- path->pathkeys);
+ path->pathkeys);
/*
* XL: Can it happen that the cheapest path can't be pushed down,
@@ -4640,10 +4916,357 @@ create_grouping_paths(PlannerInfo *root,
/* Now choose the best path(s) */
set_cheapest(grouped_rel);
+ /*
+ * We've been using the partial pathlist for the grouped relation to hold
+ * partially aggregated paths, but that's actually a little bit bogus
+ * because it's unsafe for later planning stages -- like ordered_rel ---
+ * to get the idea that they can use these partial paths as if they didn't
+ * need a FinalizeAggregate step. Zap the partial pathlist at this stage
+ * so we don't get confused.
+ */
+ grouped_rel->partial_pathlist = NIL;
return grouped_rel;
}
+
+/*
+ * For a given input path, consider the possible ways of doing grouping sets on
+ * it, by combinations of hashing and sorting. This can be called multiple
+ * times, so it's important that it not scribble on input. No result is
+ * returned, but any generated paths are added to grouped_rel.
+ */
+static void
+consider_groupingsets_paths(PlannerInfo *root,
+ RelOptInfo *grouped_rel,
+ Path *path,
+ bool is_sorted,
+ bool can_hash,
+ PathTarget *target,
+ grouping_sets_data *gd,
+ const AggClauseCosts *agg_costs,
+ double dNumGroups)
+{
+ Query *parse = root->parse;
+
+ /*
+ * If we're not being offered sorted input, then only consider plans that
+ * can be done entirely by hashing.
+ *
+ * We can hash everything if it looks like it'll fit in work_mem. But if
+ * the input is actually sorted despite not being advertised as such, we
+ * prefer to make use of that in order to use less memory.
+ *
+ * If none of the grouping sets are sortable, then ignore the work_mem
+ * limit and generate a path anyway, since otherwise we'll just fail.
+ */
+ if (!is_sorted)
+ {
+ List *new_rollups = NIL;
+ RollupData *unhashed_rollup = NULL;
+ List *sets_data;
+ List *empty_sets_data = NIL;
+ List *empty_sets = NIL;
+ ListCell *lc;
+ ListCell *l_start = list_head(gd->rollups);
+ AggStrategy strat = AGG_HASHED;
+ Size hashsize;
+ double exclude_groups = 0.0;
+
+ Assert(can_hash);
+
+ if (pathkeys_contained_in(root->group_pathkeys, path->pathkeys))
+ {
+ unhashed_rollup = lfirst(l_start);
+ exclude_groups = unhashed_rollup->numGroups;
+ l_start = lnext(l_start);
+ }
+
+ hashsize = estimate_hashagg_tablesize(path,
+ agg_costs,
+ dNumGroups - exclude_groups);
+
+ /*
+ * gd->rollups is empty if we have only unsortable columns to work
+ * with. Override work_mem in that case; otherwise, we'll rely on the
+ * sorted-input case to generate usable mixed paths.
+ */
+ if (hashsize > work_mem * 1024L && gd->rollups)
+ return; /* nope, won't fit */
+
+ /*
+ * We need to burst the existing rollups list into individual grouping
+ * sets and recompute a groupClause for each set.
+ */
+ sets_data = list_copy(gd->unsortable_sets);
+
+ for_each_cell(lc, l_start)
+ {
+ RollupData *rollup = lfirst(lc);
+
+ /*
+ * If we find an unhashable rollup that's not been skipped by the
+ * "actually sorted" check above, we can't cope; we'd need sorted
+ * input (with a different sort order) but we can't get that here.
+ * So bail out; we'll get a valid path from the is_sorted case
+ * instead.
+ *
+ * The mere presence of empty grouping sets doesn't make a rollup
+ * unhashable (see preprocess_grouping_sets), we handle those
+ * specially below.
+ */
+ if (!rollup->hashable)
+ return;
+ else
+ sets_data = list_concat(sets_data, list_copy(rollup->gsets_data));
+ }
+ foreach(lc, sets_data)
+ {
+ GroupingSetData *gs = lfirst(lc);
+ List *gset = gs->set;
+ RollupData *rollup;
+
+ if (gset == NIL)
+ {
+ /* Empty grouping sets can't be hashed. */
+ empty_sets_data = lappend(empty_sets_data, gs);
+ empty_sets = lappend(empty_sets, NIL);
+ }
+ else
+ {
+ rollup = makeNode(RollupData);
+
+ rollup->groupClause = preprocess_groupclause(root, gset);
+ rollup->gsets_data = list_make1(gs);
+ rollup->gsets = remap_to_groupclause_idx(rollup->groupClause,
+ rollup->gsets_data,
+ gd->tleref_to_colnum_map);
+ rollup->numGroups = gs->numGroups;
+ rollup->hashable = true;
+ rollup->is_hashed = true;
+ new_rollups = lappend(new_rollups, rollup);
+ }
+ }
+
+ /*
+ * If we didn't find anything nonempty to hash, then bail. We'll
+ * generate a path from the is_sorted case.
+ */
+ if (new_rollups == NIL)
+ return;
+
+ /*
+ * If there were empty grouping sets they should have been in the
+ * first rollup.
+ */
+ Assert(!unhashed_rollup || !empty_sets);
+
+ if (unhashed_rollup)
+ {
+ new_rollups = lappend(new_rollups, unhashed_rollup);
+ strat = AGG_MIXED;
+ }
+ else if (empty_sets)
+ {
+ RollupData *rollup = makeNode(RollupData);
+
+ rollup->groupClause = NIL;
+ rollup->gsets_data = empty_sets_data;
+ rollup->gsets = empty_sets;
+ rollup->numGroups = list_length(empty_sets);
+ rollup->hashable = false;
+ rollup->is_hashed = false;
+ new_rollups = lappend(new_rollups, rollup);
+ strat = AGG_MIXED;
+ }
+
+ add_path(grouped_rel, (Path *)
+ create_groupingsets_path(root,
+ grouped_rel,
+ path,
+ target,
+ (List *) parse->havingQual,
+ strat,
+ new_rollups,
+ agg_costs,
+ dNumGroups));
+ return;
+ }
+
+ /*
+ * If we have sorted input but nothing we can do with it, bail.
+ */
+ if (list_length(gd->rollups) == 0)
+ return;
+
+ /*
+ * Given sorted input, we try and make two paths: one sorted and one mixed
+ * sort/hash. (We need to try both because hashagg might be disabled, or
+ * some columns might not be sortable.)
+ *
+ * can_hash is passed in as false if some obstacle elsewhere (such as
+ * ordered aggs) means that we shouldn't consider hashing at all.
+ */
+ if (can_hash && gd->any_hashable)
+ {
+ List *rollups = NIL;
+ List *hash_sets = list_copy(gd->unsortable_sets);
+ double availspace = (work_mem * 1024.0);
+ ListCell *lc;
+
+ /*
+ * Account first for space needed for groups we can't sort at all.
+ */
+ availspace -= (double) estimate_hashagg_tablesize(path,
+ agg_costs,
+ gd->dNumHashGroups);
+
+ if (availspace > 0 && list_length(gd->rollups) > 1)
+ {
+ double scale;
+ int num_rollups = list_length(gd->rollups);
+ int k_capacity;
+ int *k_weights = palloc(num_rollups * sizeof(int));
+ Bitmapset *hash_items = NULL;
+ int i;
+
+ /*
+ * We treat this as a knapsack problem: the knapsack capacity
+ * represents work_mem, the item weights are the estimated memory
+ * usage of the hashtables needed to implement a single rollup,
+ * and we really ought to use the cost saving as the item value;
+ * however, currently the costs assigned to sort nodes don't
+ * reflect the comparison costs well, and so we treat all items as
+ * of equal value (each rollup we hash instead saves us one sort).
+ *
+ * To use the discrete knapsack, we need to scale the values to a
+ * reasonably small bounded range. We choose to allow a 5% error
+ * margin; we have no more than 4096 rollups in the worst possible
+ * case, which with a 5% error margin will require a bit over 42MB
+ * of workspace. (Anyone wanting to plan queries that complex had
+ * better have the memory for it. In more reasonable cases, with
+ * no more than a couple of dozen rollups, the memory usage will
+ * be negligible.)
+ *
+ * k_capacity is naturally bounded, but we clamp the values for
+ * scale and weight (below) to avoid overflows or underflows (or
+ * uselessly trying to use a scale factor less than 1 byte).
+ */
+ scale = Max(availspace / (20.0 * num_rollups), 1.0);
+ k_capacity = (int) floor(availspace / scale);
+
+ /*
+ * We leave the first rollup out of consideration since it's the
+ * one that matches the input sort order. We assign indexes "i"
+ * to only those entries considered for hashing; the second loop,
+ * below, must use the same condition.
+ */
+ i = 0;
+ for_each_cell(lc, lnext(list_head(gd->rollups)))
+ {
+ RollupData *rollup = lfirst(lc);
+
+ if (rollup->hashable)
+ {
+ double sz = estimate_hashagg_tablesize(path,
+ agg_costs,
+ rollup->numGroups);
+
+ /*
+ * If sz is enormous, but work_mem (and hence scale) is
+ * small, avoid integer overflow here.
+ */
+ k_weights[i] = (int) Min(floor(sz / scale),
+ k_capacity + 1.0);
+ ++i;
+ }
+ }
+
+ /*
+ * Apply knapsack algorithm; compute the set of items which
+ * maximizes the value stored (in this case the number of sorts
+ * saved) while keeping the total size (approximately) within
+ * capacity.
+ */
+ if (i > 0)
+ hash_items = DiscreteKnapsack(k_capacity, i, k_weights, NULL);
+
+ if (!bms_is_empty(hash_items))
+ {
+ rollups = list_make1(linitial(gd->rollups));
+
+ i = 0;
+ for_each_cell(lc, lnext(list_head(gd->rollups)))
+ {
+ RollupData *rollup = lfirst(lc);
+
+ if (rollup->hashable)
+ {
+ if (bms_is_member(i, hash_items))
+ hash_sets = list_concat(hash_sets,
+ list_copy(rollup->gsets_data));
+ else
+ rollups = lappend(rollups, rollup);
+ ++i;
+ }
+ else
+ rollups = lappend(rollups, rollup);
+ }
+ }
+ }
+
+ if (!rollups && hash_sets)
+ rollups = list_copy(gd->rollups);
+
+ foreach(lc, hash_sets)
+ {
+ GroupingSetData *gs = lfirst(lc);
+ RollupData *rollup = makeNode(RollupData);
+
+ Assert(gs->set != NIL);
+
+ rollup->groupClause = preprocess_groupclause(root, gs->set);
+ rollup->gsets_data = list_make1(gs);
+ rollup->gsets = remap_to_groupclause_idx(rollup->groupClause,
+ rollup->gsets_data,
+ gd->tleref_to_colnum_map);
+ rollup->numGroups = gs->numGroups;
+ rollup->hashable = true;
+ rollup->is_hashed = true;
+ rollups = lcons(rollup, rollups);
+ }
+
+ if (rollups)
+ {
+ add_path(grouped_rel, (Path *)
+ create_groupingsets_path(root,
+ grouped_rel,
+ path,
+ target,
+ (List *) parse->havingQual,
+ AGG_MIXED,
+ rollups,
+ agg_costs,
+ dNumGroups));
+ }
+ }
+
+ /*
+ * Now try the simple sorted case.
+ */
+ if (!gd->unsortable_sets)
+ add_path(grouped_rel, (Path *)
+ create_groupingsets_path(root,
+ grouped_rel,
+ path,
+ target,
+ (List *) parse->havingQual,
+ AGG_SORTED,
+ gd->rollups,
+ agg_costs,
+ dNumGroups));
+}
+
/*
* create_window_paths
*
@@ -4679,8 +5302,8 @@ create_window_paths(PlannerInfo *root,
* target list and active windows for non-parallel-safe constructs.
*/
if (input_rel->consider_parallel &&
- !has_parallel_hazard((Node *) output_target->exprs, false) &&
- !has_parallel_hazard((Node *) activeWindows, false))
+ is_parallel_safe(root, (Node *) output_target->exprs) &&
+ is_parallel_safe(root, (Node *) activeWindows))
window_rel->consider_parallel = true;
/*
@@ -4807,9 +5430,8 @@ create_one_window_path(PlannerInfo *root,
window_target = copy_pathtarget(window_target);
foreach(lc2, wflists->windowFuncs[wc->winref])
{
- WindowFunc *wfunc = (WindowFunc *) lfirst(lc2);
+ WindowFunc *wfunc = lfirst_node(WindowFunc, lc2);
- Assert(IsA(wfunc, WindowFunc));
add_column_to_pathtarget(window_target, (Expr *) wfunc, 0);
window_target->width += get_typavgwidth(wfunc->wintype, -1);
}
@@ -5096,7 +5718,7 @@ create_ordered_paths(PlannerInfo *root,
* target list is parallel-safe.
*/
if (input_rel->consider_parallel &&
- !has_parallel_hazard((Node *) target->exprs, false))
+ is_parallel_safe(root, (Node *) target->exprs))
ordered_rel->consider_parallel = true;
/*
@@ -5136,6 +5758,56 @@ create_ordered_paths(PlannerInfo *root,
}
/*
+ * generate_gather_paths() will have already generated a simple Gather
+ * path for the best parallel path, if any, and the loop above will have
+ * considered sorting it. Similarly, generate_gather_paths() will also
+ * have generated order-preserving Gather Merge plans which can be used
+ * without sorting if they happen to match the sort_pathkeys, and the loop
+ * above will have handled those as well. However, there's one more
+ * possibility: it may make sense to sort the cheapest partial path
+ * according to the required output order and then use Gather Merge.
+ */
+ if (ordered_rel->consider_parallel && root->sort_pathkeys != NIL &&
+ input_rel->partial_pathlist != NIL)
+ {
+ Path *cheapest_partial_path;
+
+ cheapest_partial_path = linitial(input_rel->partial_pathlist);
+
+ /*
+ * If cheapest partial path doesn't need a sort, this is redundant
+ * with what's already been tried.
+ */
+ if (!pathkeys_contained_in(root->sort_pathkeys,
+ cheapest_partial_path->pathkeys))
+ {
+ Path *path;
+ double total_groups;
+
+ path = (Path *) create_sort_path(root,
+ ordered_rel,
+ cheapest_partial_path,
+ root->sort_pathkeys,
+ -1.0);
+
+ total_groups = cheapest_partial_path->rows *
+ cheapest_partial_path->parallel_workers;
+ path = (Path *)
+ create_gather_merge_path(root, ordered_rel,
+ path,
+ target, root->sort_pathkeys, NULL,
+ &total_groups);
+
+ /* Add projection step if needed */
+ if (path->pathtarget != target)
+ path = apply_projection_to_path(root, ordered_rel,
+ path, target);
+
+ add_path(ordered_rel, path);
+ }
+ }
+
+ /*
* If there is an FDW that's responsible for all baserels of the query,
* let it consider adding ForeignPaths.
*/
@@ -5713,7 +6385,7 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
* bloat the sort dataset, and because it might cause unexpected output order
* if the sort isn't stable. However there's a constraint on that: all SRFs
* in the tlist should be evaluated at the same plan step, so that they can
- * run in sync in ExecTargetList. So if any SRFs are in sort columns, we
+ * run in sync in nodeProjectSet. So if any SRFs are in sort columns, we
* mustn't postpone any SRFs. (Note that in principle that policy should
* probably get applied to the group/window input targetlists too, but we
* have not done that historically.) Lastly, expensive expressions are
@@ -5804,7 +6476,8 @@ make_sort_input_target(PlannerInfo *root,
* Check for SRF or volatile functions. Check the SRF case first
* because we must know whether we have any postponed SRFs.
*/
- if (expression_returns_set((Node *) expr))
+ if (parse->hasTargetSRFs &&
+ expression_returns_set((Node *) expr))
{
/* We'll decide below whether these are postponable */
col_is_srf[i] = true;
@@ -5843,6 +6516,7 @@ make_sort_input_target(PlannerInfo *root,
{
/* For sortgroupref cols, just check if any contain SRFs */
if (!have_srf_sortcols &&
+ parse->hasTargetSRFs &&
expression_returns_set((Node *) expr))
have_srf_sortcols = true;
}
@@ -5952,6 +6626,109 @@ get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
}
/*
+ * adjust_paths_for_srfs
+ * Fix up the Paths of the given upperrel to handle tSRFs properly.
+ *
+ * The executor can only handle set-returning functions that appear at the
+ * top level of the targetlist of a ProjectSet plan node. If we have any SRFs
+ * that are not at top level, we need to split up the evaluation into multiple
+ * plan levels in which each level satisfies this constraint. This function
+ * modifies each Path of an upperrel that (might) compute any SRFs in its
+ * output tlist to insert appropriate projection steps.
+ *
+ * The given targets and targets_contain_srfs lists are from
+ * split_pathtarget_at_srfs(). We assume the existing Paths emit the first
+ * target in targets.
+ */
+static void
+adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel,
+ List *targets, List *targets_contain_srfs)
+{
+ ListCell *lc;
+
+ Assert(list_length(targets) == list_length(targets_contain_srfs));
+ Assert(!linitial_int(targets_contain_srfs));
+
+ /* If no SRFs appear at this plan level, nothing to do */
+ if (list_length(targets) == 1)
+ return;
+
+ /*
+ * Stack SRF-evaluation nodes atop each path for the rel.
+ *
+ * In principle we should re-run set_cheapest() here to identify the
+ * cheapest path, but it seems unlikely that adding the same tlist eval
+ * costs to all the paths would change that, so we don't bother. Instead,
+ * just assume that the cheapest-startup and cheapest-total paths remain
+ * so. (There should be no parameterized paths anymore, so we needn't
+ * worry about updating cheapest_parameterized_paths.)
+ */
+ foreach(lc, rel->pathlist)
+ {
+ Path *subpath = (Path *) lfirst(lc);
+ Path *newpath = subpath;
+ ListCell *lc1,
+ *lc2;
+
+ Assert(subpath->param_info == NULL);
+ forboth(lc1, targets, lc2, targets_contain_srfs)
+ {
+ PathTarget *thistarget = (PathTarget *) lfirst(lc1);
+ bool contains_srfs = (bool) lfirst_int(lc2);
+
+ /* If this level doesn't contain SRFs, do regular projection */
+ if (contains_srfs)
+ newpath = (Path *) create_set_projection_path(root,
+ rel,
+ newpath,
+ thistarget);
+ else
+ newpath = (Path *) apply_projection_to_path(root,
+ rel,
+ newpath,
+ thistarget);
+ }
+ lfirst(lc) = newpath;
+ if (subpath == rel->cheapest_startup_path)
+ rel->cheapest_startup_path = newpath;
+ if (subpath == rel->cheapest_total_path)
+ rel->cheapest_total_path = newpath;
+ }
+
+ /* Likewise for partial paths, if any */
+ foreach(lc, rel->partial_pathlist)
+ {
+ Path *subpath = (Path *) lfirst(lc);
+ Path *newpath = subpath;
+ ListCell *lc1,
+ *lc2;
+
+ Assert(subpath->param_info == NULL);
+ forboth(lc1, targets, lc2, targets_contain_srfs)
+ {
+ PathTarget *thistarget = (PathTarget *) lfirst(lc1);
+ bool contains_srfs = (bool) lfirst_int(lc2);
+
+ /* If this level doesn't contain SRFs, do regular projection */
+ if (contains_srfs)
+ newpath = (Path *) create_set_projection_path(root,
+ rel,
+ newpath,
+ thistarget);
+ else
+ {
+ /* avoid apply_projection_to_path, in case of multiple refs */
+ newpath = (Path *) create_projection_path(root,
+ rel,
+ newpath,
+ thistarget);
+ }
+ }
+ lfirst(lc) = newpath;
+ }
+}
+
+/*
* expression_planner
* Perform planner's transformations on a standalone expression.
*
@@ -6050,7 +6827,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
setup_simple_rel_arrays(root);
/* Build RelOptInfo */
- rel = build_simple_rel(root, 1, RELOPT_BASEREL);
+ rel = build_simple_rel(root, 1, NULL);
/* Locate IndexOptInfo for the target index */
indexInfo = NULL;
@@ -6099,7 +6876,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
indexScanPath = create_index_path(root, indexInfo,
NIL, NIL, NIL, NIL, NIL,
ForwardScanDirection, false,
- NULL, 1.0);
+ NULL, 1.0, false);
return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
}
@@ -6167,6 +6944,37 @@ grouping_distribution_match(PlannerInfo *root, Query *parse, Path *path,
return matches_key;
}
+/*
+ * get_partitioned_child_rels
+ * Returns a list of the RT indexes of the partitioned child relations
+ * with rti as the root parent RT index.
+ *
+ * Note: Only call this function on RTEs known to be partitioned tables.
+ */
+List *
+get_partitioned_child_rels(PlannerInfo *root, Index rti)
+{
+ List *result = NIL;
+ ListCell *l;
+
+ foreach(l, root->pcinfo_list)
+ {
+ PartitionedChildRelInfo *pc = lfirst(l);
+
+ if (pc->parent_relid == rti)
+ {
+ result = pc->child_rels;
+ break;
+ }
+ }
+
+ /* The root partitioned table is included as a child rel */
+ Assert(list_length(result) >= 1);
+
+ return result;
+}
+
+
static bool
groupingsets_distribution_match(PlannerInfo *root, Query *parse, Path *path)
{
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index d5bc9e0760..398586e98a 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -5,7 +5,7 @@
* vars, compute regproc values for operators, etc
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -123,10 +123,10 @@ static Var *search_indexed_tlist_for_var(Var *var,
indexed_tlist *itlist,
Index newvarno,
int rtoffset);
-static Var *search_indexed_tlist_for_non_var(Node *node,
+static Var *search_indexed_tlist_for_non_var(Expr *node,
indexed_tlist *itlist,
Index newvarno);
-static Var *search_indexed_tlist_for_sortgroupref(Node *node,
+static Var *search_indexed_tlist_for_sortgroupref(Expr *node,
Index sortgroupref,
indexed_tlist *itlist,
Index newvarno);
@@ -240,11 +240,9 @@ set_plan_references(PlannerInfo *root, Plan *plan)
*/
foreach(lc, root->rowMarks)
{
- PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
+ PlanRowMark *rc = lfirst_node(PlanRowMark, lc);
PlanRowMark *newrc;
- Assert(IsA(rc, PlanRowMark));
-
/* flat copy is enough since all fields are scalars */
newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
memcpy(newrc, rc, sizeof(PlanRowMark));
@@ -411,11 +409,11 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
newrte->subquery = NULL;
newrte->joinaliasvars = NIL;
newrte->functions = NIL;
+ newrte->tablefunc = NULL;
newrte->values_lists = NIL;
- newrte->values_collations = NIL;
- newrte->ctecoltypes = NIL;
- newrte->ctecoltypmods = NIL;
- newrte->ctecolcollations = NIL;
+ newrte->coltypes = NIL;
+ newrte->coltypmods = NIL;
+ newrte->colcollations = NIL;
newrte->securityQuals = NIL;
glob->finalrtable = lappend(glob->finalrtable, newrte);
@@ -572,6 +570,19 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
fix_scan_list(root, splan->functions, rtoffset);
}
break;
+ case T_TableFuncScan:
+ {
+ TableFuncScan *splan = (TableFuncScan *) plan;
+
+ splan->scan.scanrelid += rtoffset;
+ splan->scan.plan.targetlist =
+ fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
+ splan->scan.plan.qual =
+ fix_scan_list(root, splan->scan.plan.qual, rtoffset);
+ splan->tablefunc = (TableFunc *)
+ fix_scan_expr(root, (Node *) splan->tablefunc, rtoffset);
+ }
+ break;
case T_ValuesScan:
{
ValuesScan *splan = (ValuesScan *) plan;
@@ -596,6 +607,17 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
fix_scan_list(root, splan->scan.plan.qual, rtoffset);
}
break;
+ case T_NamedTuplestoreScan:
+ {
+ NamedTuplestoreScan *splan = (NamedTuplestoreScan *) plan;
+
+ splan->scan.scanrelid += rtoffset;
+ splan->scan.plan.targetlist =
+ fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
+ splan->scan.plan.qual =
+ fix_scan_list(root, splan->scan.plan.qual, rtoffset);
+ }
+ break;
case T_WorkTableScan:
{
WorkTableScan *splan = (WorkTableScan *) plan;
@@ -650,6 +672,7 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
break;
case T_Gather:
+ case T_GatherMerge:
set_upper_references(root, plan, rtoffset);
break;
@@ -779,6 +802,9 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
fix_scan_expr(root, splan->resconstantqual, rtoffset);
}
break;
+ case T_ProjectSet:
+ set_upper_references(root, plan, rtoffset);
+ break;
case T_ModifyTable:
{
ModifyTable *splan = (ModifyTable *) plan;
@@ -865,6 +891,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
splan->nominalRelation += rtoffset;
splan->exclRelRTI += rtoffset;
+ foreach(l, splan->partitioned_rels)
+ {
+ lfirst_int(l) += rtoffset;
+ }
foreach(l, splan->resultRelations)
{
lfirst_int(l) += rtoffset;
@@ -893,6 +923,27 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
root->glob->resultRelations =
list_concat(root->glob->resultRelations,
list_copy(splan->resultRelations));
+
+ /*
+ * If the main target relation is a partitioned table, the
+ * following list contains the RT indexes of partitioned child
+ * relations including the root, which are not included in the
+ * above list. We also keep RT indexes of the roots
+ * separately to be identitied as such during the executor
+ * initialization.
+ */
+ if (splan->partitioned_rels != NIL)
+ {
+ root->glob->nonleafResultRelations =
+ list_concat(root->glob->nonleafResultRelations,
+ list_copy(splan->partitioned_rels));
+ /* Remember where this root will be in the global list. */
+ splan->rootResultRelIndex =
+ list_length(root->glob->rootResultRelations);
+ root->glob->rootResultRelations =
+ lappend_int(root->glob->rootResultRelations,
+ linitial_int(splan->partitioned_rels));
+ }
}
break;
case T_Append:
@@ -905,6 +956,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
*/
set_dummy_tlist_references(plan, rtoffset);
Assert(splan->plan.qual == NIL);
+ foreach(l, splan->partitioned_rels)
+ {
+ lfirst_int(l) += rtoffset;
+ }
foreach(l, splan->appendplans)
{
lfirst(l) = set_plan_refs(root,
@@ -923,6 +978,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
*/
set_dummy_tlist_references(plan, rtoffset);
Assert(splan->plan.qual == NIL);
+ foreach(l, splan->partitioned_rels)
+ {
+ lfirst_int(l) += rtoffset;
+ }
foreach(l, splan->mergeplans)
{
lfirst(l) = set_plan_refs(root,
@@ -1452,7 +1511,7 @@ fix_param_node(PlannerInfo *root, Param *p)
elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
return copyObject(list_nth(params, colno - 1));
}
- return copyObject(p);
+ return (Node *) copyObject(p);
}
/*
@@ -1740,7 +1799,7 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
if (tle->ressortgroupref != 0 && !IsA(tle->expr, Var))
{
newexpr = (Node *)
- search_indexed_tlist_for_sortgroupref((Node *) tle->expr,
+ search_indexed_tlist_for_sortgroupref(tle->expr,
tle->ressortgroupref,
subplan_itlist,
OUTER_VAR);
@@ -1823,7 +1882,7 @@ convert_combining_aggrefs(Node *node, void *context)
*/
child_agg->args = NIL;
child_agg->aggfilter = NULL;
- parent_agg = (Aggref *) copyObject(child_agg);
+ parent_agg = copyObject(child_agg);
child_agg->args = orig_agg->args;
child_agg->aggfilter = orig_agg->aggfilter;
@@ -1872,6 +1931,19 @@ set_dummy_tlist_references(Plan *plan, int rtoffset)
Var *oldvar = (Var *) tle->expr;
Var *newvar;
+ /*
+ * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
+ * as Consts, not Vars referencing Consts. Here, there's no speed
+ * advantage to be had, but it makes EXPLAIN output look cleaner, and
+ * again it avoids confusing the executor.
+ */
+ if (IsA(oldvar, Const))
+ {
+ /* just reuse the existing TLE node */
+ output_targetlist = lappend(output_targetlist, tle);
+ continue;
+ }
+
newvar = makeVar(OUTER_VAR,
tle->resno,
exprType((Node *) oldvar),
@@ -2054,11 +2126,21 @@ search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
* so there's a correctness reason not to call it unless that's set.
*/
static Var *
-search_indexed_tlist_for_non_var(Node *node,
+search_indexed_tlist_for_non_var(Expr *node,
indexed_tlist *itlist, Index newvarno)
{
TargetEntry *tle;
+ /*
+ * If it's a simple Const, replacing it with a Var is silly, even if there
+ * happens to be an identical Const below; a Var is more expensive to
+ * execute than a Const. What's more, replacing it could confuse some
+ * places in the executor that expect to see simple Consts for, eg,
+ * dropped columns.
+ */
+ if (IsA(node, Const))
+ return NULL;
+
tle = tlist_member(node, itlist->tlist);
if (tle)
{
@@ -2085,7 +2167,7 @@ search_indexed_tlist_for_non_var(Node *node,
* And it's also faster than search_indexed_tlist_for_non_var.
*/
static Var *
-search_indexed_tlist_for_sortgroupref(Node *node,
+search_indexed_tlist_for_sortgroupref(Expr *node,
Index sortgroupref,
indexed_tlist *itlist,
Index newvarno)
@@ -2219,7 +2301,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
/* See if the PlaceHolderVar has bubbled up from a lower plan node */
if (context->outer_itlist && context->outer_itlist->has_ph_vars)
{
- newvar = search_indexed_tlist_for_non_var((Node *) phv,
+ newvar = search_indexed_tlist_for_non_var((Expr *) phv,
context->outer_itlist,
OUTER_VAR);
if (newvar)
@@ -2227,7 +2309,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
}
if (context->inner_itlist && context->inner_itlist->has_ph_vars)
{
- newvar = search_indexed_tlist_for_non_var((Node *) phv,
+ newvar = search_indexed_tlist_for_non_var((Expr *) phv,
context->inner_itlist,
INNER_VAR);
if (newvar)
@@ -2242,7 +2324,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
/* Try matching more complex expressions too, if tlists have any */
if (context->outer_itlist && context->outer_itlist->has_non_vars)
{
- newvar = search_indexed_tlist_for_non_var(node,
+ newvar = search_indexed_tlist_for_non_var((Expr *) node,
context->outer_itlist,
OUTER_VAR);
if (newvar)
@@ -2250,7 +2332,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
}
if (context->inner_itlist && context->inner_itlist->has_non_vars)
{
- newvar = search_indexed_tlist_for_non_var(node,
+ newvar = search_indexed_tlist_for_non_var((Expr *) node,
context->inner_itlist,
INNER_VAR);
if (newvar)
@@ -2334,7 +2416,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
/* See if the PlaceHolderVar has bubbled up from a lower plan node */
if (context->subplan_itlist->has_ph_vars)
{
- newvar = search_indexed_tlist_for_non_var((Node *) phv,
+ newvar = search_indexed_tlist_for_non_var((Expr *) phv,
context->subplan_itlist,
context->newvarno);
if (newvar)
@@ -2370,7 +2452,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
/* Try matching more complex expressions too, if tlist has any */
if (context->subplan_itlist->has_non_vars)
{
- newvar = search_indexed_tlist_for_non_var(node,
+ newvar = search_indexed_tlist_for_non_var((Expr *) node,
context->subplan_itlist,
context->newvarno);
if (newvar)
@@ -2561,6 +2643,11 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
if (rte->rtekind == RTE_RELATION)
context->glob->relationOids =
lappend_oid(context->glob->relationOids, rte->relid);
+ else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
+ OidIsValid(rte->relid))
+ context->glob->relationOids =
+ lappend_oid(context->glob->relationOids,
+ rte->relid);
}
/* And recurse into the query's subexpressions */
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index bc2cbcee6b..d8545f2bdd 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -4,7 +4,7 @@
* Planning routines for subselects and parameters.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -85,6 +85,7 @@ static Bitmapset *finalize_plan(PlannerInfo *root,
Bitmapset *valid_params,
Bitmapset *scan_params);
static bool finalize_primnode(Node *node, finalize_primnode_context *context);
+static bool finalize_agg_primnode(Node *node, finalize_primnode_context *context);
/*
@@ -127,7 +128,7 @@ assign_param_for_var(PlannerInfo *root, Var *var)
}
/* Nope, so make a new one */
- var = (Var *) copyObject(var);
+ var = copyObject(var);
var->varlevelsup = 0;
pitem = makeNode(PlannerParamItem);
@@ -226,7 +227,7 @@ assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
}
/* Nope, so make a new one */
- phv = (PlaceHolderVar *) copyObject(phv);
+ phv = copyObject(phv);
if (phv->phlevelsup != 0)
{
IncrementVarSublevelsUp((Node *) phv, -((int) phv->phlevelsup), 0);
@@ -318,7 +319,7 @@ replace_outer_agg(PlannerInfo *root, Aggref *agg)
* It does not seem worthwhile to try to match duplicate outer aggs. Just
* make a new slot every time.
*/
- agg = (Aggref *) copyObject(agg);
+ agg = copyObject(agg);
IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
Assert(agg->agglevelsup == 0);
@@ -360,7 +361,7 @@ replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
* It does not seem worthwhile to try to match duplicate outer aggs. Just
* make a new slot every time.
*/
- grp = (GroupingFunc *) copyObject(grp);
+ grp = copyObject(grp);
IncrementVarSublevelsUp((Node *) grp, -((int) grp->agglevelsup), 0);
Assert(grp->agglevelsup == 0);
@@ -435,9 +436,8 @@ get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod,
/* In cases such as EXISTS, tlist might be empty; arbitrarily use VOID */
if (plan->targetlist)
{
- TargetEntry *tent = (TargetEntry *) linitial(plan->targetlist);
+ TargetEntry *tent = linitial_node(TargetEntry, plan->targetlist);
- Assert(IsA(tent, TargetEntry));
if (!tent->resjunk)
{
*coltype = exprType((Node *) tent->expr);
@@ -494,7 +494,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
* same sub-Query node, but the planner wants to scribble on the Query.
* Try to clean this up when we do querytree redesign...
*/
- subquery = (Query *) copyObject(orig_subquery);
+ subquery = copyObject(orig_subquery);
/*
* If it's an EXISTS subplan, we might be able to simplify it.
@@ -593,7 +593,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
List *paramIds;
/* Make a second copy of the original subquery */
- subquery = (Query *) copyObject(orig_subquery);
+ subquery = copyObject(orig_subquery);
/* and re-simplify */
simple_exists = simplify_EXISTS_query(root, subquery);
Assert(simple_exists);
@@ -625,13 +625,13 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
AlternativeSubPlan *asplan;
/* OK, convert to SubPlan format. */
- hashplan = (SubPlan *) build_subplan(root, plan, subroot,
- plan_params,
- ANY_SUBLINK, 0,
- newtestexpr,
- false, true);
+ hashplan = castNode(SubPlan,
+ build_subplan(root, plan, subroot,
+ plan_params,
+ ANY_SUBLINK, 0,
+ newtestexpr,
+ false, true));
/* Check we got what we expected */
- Assert(IsA(hashplan, SubPlan));
Assert(hashplan->parParam == NIL);
Assert(hashplan->useHashTable);
/* build_subplan won't have filled in paramIds */
@@ -678,6 +678,7 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
&splan->firstColCollation);
splan->useHashTable = false;
splan->unknownEqFalse = unknownEqFalse;
+ splan->parallel_safe = plan->parallel_safe;
splan->setParam = NIL;
splan->parParam = NIL;
splan->args = NIL;
@@ -1256,6 +1257,13 @@ SS_process_ctes(PlannerInfo *root)
&splan->firstColCollation);
splan->useHashTable = false;
splan->unknownEqFalse = false;
+
+ /*
+ * CTE scans are not considered for parallelism (cf
+ * set_rel_consider_parallel), and even if they were, initPlans aren't
+ * parallel-safe.
+ */
+ splan->parallel_safe = false;
splan->setParam = NIL;
splan->parParam = NIL;
splan->args = NIL;
@@ -1466,7 +1474,7 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
* Copy the subquery so we can modify it safely (see comments in
* make_subplan).
*/
- subselect = (Query *) copyObject(subselect);
+ subselect = copyObject(subselect);
/*
* See if the subquery can be simplified based on the knowledge that it's
@@ -1605,7 +1613,7 @@ simplify_EXISTS_query(PlannerInfo *root, Query *query)
{
/*
* We don't try to simplify at all if the query uses set operations,
- * aggregates, grouping sets, modifying CTEs, HAVING, OFFSET, or FOR
+ * aggregates, grouping sets, SRFs, modifying CTEs, HAVING, OFFSET, or FOR
* UPDATE/SHARE; none of these seem likely in normal usage and their
* possible effects are complex. (Note: we could ignore an "OFFSET 0"
* clause, but that traditionally is used as an optimization fence, so we
@@ -1616,6 +1624,7 @@ simplify_EXISTS_query(PlannerInfo *root, Query *query)
query->hasAggs ||
query->groupingSets ||
query->hasWindowFuncs ||
+ query->hasTargetSRFs ||
query->hasModifyingCTE ||
query->havingQual ||
query->limitOffset ||
@@ -1657,13 +1666,6 @@ simplify_EXISTS_query(PlannerInfo *root, Query *query)
}
/*
- * Mustn't throw away the targetlist if it contains set-returning
- * functions; those could affect whether zero rows are returned!
- */
- if (expression_returns_set((Node *) query->targetList))
- return false;
-
- /*
* Otherwise, we can throw away the targetlist, as well as any GROUP,
* WINDOW, DISTINCT, and ORDER BY clauses; none of those clauses will
* change a nonzero-rows result to zero rows or vice versa. (Furthermore,
@@ -2177,11 +2179,13 @@ SS_identify_outer_params(PlannerInfo *root)
}
/*
- * SS_charge_for_initplans - account for cost of initplans in Path costs
+ * SS_charge_for_initplans - account for initplans in Path costs & parallelism
*
* If any initPlans have been created in the current query level, they will
* get attached to the Plan tree created from whichever Path we select from
- * the given rel; so increment all the rel's Paths' costs to account for them.
+ * the given rel. Increment all that rel's Paths' costs to account for them,
+ * and make sure the paths get marked as parallel-unsafe, since we can't
+ * currently transmit initPlans to parallel workers.
*
* This is separate from SS_attach_initplans because we might conditionally
* create more initPlans during create_plan(), depending on which Path we
@@ -2213,7 +2217,7 @@ SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
}
/*
- * Now adjust the costs.
+ * Now adjust the costs and parallel_safe flags.
*/
foreach(lc, final_rel->pathlist)
{
@@ -2221,6 +2225,7 @@ SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
path->startup_cost += initplan_cost;
path->total_cost += initplan_cost;
+ path->parallel_safe = false;
}
/* We needn't do set_cheapest() here, caller will do it */
@@ -2471,6 +2476,12 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
}
break;
+ case T_TableFuncScan:
+ finalize_primnode((Node *) ((TableFuncScan *) plan)->tablefunc,
+ &context);
+ context.paramids = bms_add_members(context.paramids, scan_params);
+ break;
+
case T_ValuesScan:
finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
&context);
@@ -2520,6 +2531,10 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
context.paramids = bms_add_members(context.paramids, scan_params);
break;
+ case T_NamedTuplestoreScan:
+ context.paramids = bms_add_members(context.paramids, scan_params);
+ break;
+
case T_ForeignScan:
{
ForeignScan *fscan = (ForeignScan *) plan;
@@ -2719,6 +2734,29 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
locally_added_param);
break;
+ case T_Agg:
+ {
+ Agg *agg = (Agg *) plan;
+
+ /*
+ * AGG_HASHED plans need to know which Params are referenced
+ * in aggregate calls. Do a separate scan to identify them.
+ */
+ if (agg->aggstrategy == AGG_HASHED)
+ {
+ finalize_primnode_context aggcontext;
+
+ aggcontext.root = root;
+ aggcontext.paramids = NULL;
+ finalize_agg_primnode((Node *) agg->plan.targetlist,
+ &aggcontext);
+ finalize_agg_primnode((Node *) agg->plan.qual,
+ &aggcontext);
+ agg->aggParams = aggcontext.paramids;
+ }
+ }
+ break;
+
case T_WindowAgg:
finalize_primnode(((WindowAgg *) plan)->startOffset,
&context);
@@ -2726,14 +2764,16 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
&context);
break;
+ case T_ProjectSet:
case T_Hash:
- case T_Agg:
case T_Material:
case T_Sort:
case T_Unique:
case T_Gather:
+ case T_GatherMerge:
case T_SetOp:
case T_Group:
+ /* no node-type-specific fields need fixing */
break;
default:
@@ -2879,6 +2919,29 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
}
/*
+ * finalize_agg_primnode: find all Aggref nodes in the given expression tree,
+ * and add IDs of all PARAM_EXEC params appearing within their aggregated
+ * arguments to the result set.
+ */
+static bool
+finalize_agg_primnode(Node *node, finalize_primnode_context *context)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Aggref))
+ {
+ Aggref *agg = (Aggref *) node;
+
+ /* we should not consider the direct arguments, if any */
+ finalize_primnode((Node *) agg->args, context);
+ finalize_primnode((Node *) agg->aggfilter, context);
+ return false; /* there can't be any Aggrefs below here */
+ }
+ return expression_tree_walker(node, finalize_agg_primnode,
+ (void *) context);
+}
+
+/*
* SS_make_initplan_output_param - make a Param for an initPlan's output
*
* The plan is expected to return a scalar value of the given type/collation.
diff --git a/src/backend/optimizer/prep/Makefile b/src/backend/optimizer/prep/Makefile
index 5195d9b0ba..86301bfbd3 100644
--- a/src/backend/optimizer/prep/Makefile
+++ b/src/backend/optimizer/prep/Makefile
@@ -12,6 +12,6 @@ subdir = src/backend/optimizer/prep
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = prepjointree.o prepqual.o prepsecurity.o preptlist.o prepunion.o
+OBJS = prepjointree.o prepqual.o preptlist.o prepunion.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 5fa672d02c..41a930428f 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -12,7 +12,7 @@
* reduce_outer_joins
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -916,6 +916,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
subroot->processed_tlist = NIL;
subroot->grouping_map = NULL;
subroot->minmax_aggs = NIL;
+ subroot->qual_security_level = 0;
subroot->hasInheritedTarget = false;
subroot->hasRecursion = false;
subroot->wt_param_id = -1;
@@ -1121,6 +1122,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
case RTE_SUBQUERY:
case RTE_FUNCTION:
case RTE_VALUES:
+ case RTE_TABLEFUNC:
child_rte->lateral = true;
break;
case RTE_JOIN:
@@ -1128,6 +1130,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
#ifdef XCP
case RTE_REMOTE_DUMMY:
#endif
+ case RTE_NAMEDTUPLESTORE:
/* these can't contain any lateral references */
break;
}
@@ -1194,9 +1197,12 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
*/
parse->hasSubLinks |= subquery->hasSubLinks;
+ /* If subquery had any RLS conditions, now main query does too */
+ parse->hasRowSecurity |= subquery->hasRowSecurity;
+
/*
- * subquery won't be pulled up if it hasAggs or hasWindowFuncs, so no work
- * needed on those flags
+ * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
+ * hasTargetSRFs, so no work needed on those flags
*/
/*
@@ -1413,8 +1419,7 @@ is_simple_subquery(Query *subquery, RangeTblEntry *rte,
* Let's just make sure it's a valid subselect ...
*/
if (!IsA(subquery, Query) ||
- subquery->commandType != CMD_SELECT ||
- subquery->utilityStmt != NULL)
+ subquery->commandType != CMD_SELECT)
elog(ERROR, "subquery is bogus");
/*
@@ -1426,8 +1431,8 @@ is_simple_subquery(Query *subquery, RangeTblEntry *rte,
return false;
/*
- * Can't pull up a subquery involving grouping, aggregation, sorting,
- * limiting, or WITH. (XXX WITH could possibly be allowed later)
+ * Can't pull up a subquery involving grouping, aggregation, SRFs,
+ * sorting, limiting, or WITH. (XXX WITH could possibly be allowed later)
*
* We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
* clauses, because pullup would cause the locking to occur semantically
@@ -1437,6 +1442,7 @@ is_simple_subquery(Query *subquery, RangeTblEntry *rte,
*/
if (subquery->hasAggs ||
subquery->hasWindowFuncs ||
+ subquery->hasTargetSRFs ||
subquery->groupClause ||
subquery->groupingSets ||
subquery->havingQual ||
@@ -1550,15 +1556,6 @@ is_simple_subquery(Query *subquery, RangeTblEntry *rte,
}
/*
- * Don't pull up a subquery that has any set-returning functions in its
- * targetlist. Otherwise we might well wind up inserting set-returning
- * functions into places where they mustn't go, such as quals of higher
- * queries. This also ensures deletion of an empty jointree is valid.
- */
- if (expression_returns_set((Node *) subquery->targetList))
- return false;
-
- /*
* Don't pull up a subquery that has any volatile functions in its
* targetlist. Otherwise we might introduce multiple evaluations of these
* functions, if they get copied to multiple places in the upper query,
@@ -1603,7 +1600,7 @@ pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
* Need a modifiable copy of the VALUES list to hack on, just in case it's
* multiply referenced.
*/
- values_list = (List *) copyObject(linitial(rte->values_lists));
+ values_list = copyObject(linitial(rte->values_lists));
/*
* The VALUES RTE can't contain any Vars of level zero, let alone any that
@@ -1756,15 +1753,13 @@ is_simple_union_all(Query *subquery)
/* Let's just make sure it's a valid subselect ... */
if (!IsA(subquery, Query) ||
- subquery->commandType != CMD_SELECT ||
- subquery->utilityStmt != NULL)
+ subquery->commandType != CMD_SELECT)
elog(ERROR, "subquery is bogus");
/* Is it a set-operation query at all? */
- topop = (SetOperationStmt *) subquery->setOperations;
+ topop = castNode(SetOperationStmt, subquery->setOperations);
if (!topop)
return false;
- Assert(IsA(topop, SetOperationStmt));
/* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
if (subquery->sortClause ||
@@ -1978,6 +1973,11 @@ replace_vars_in_jointree(Node *jtnode,
pullup_replace_vars((Node *) rte->functions,
context);
break;
+ case RTE_TABLEFUNC:
+ rte->tablefunc = (TableFunc *)
+ pullup_replace_vars((Node *) rte->tablefunc,
+ context);
+ break;
case RTE_VALUES:
rte->values_lists = (List *)
pullup_replace_vars((Node *) rte->values_lists,
@@ -1988,6 +1988,7 @@ replace_vars_in_jointree(Node *jtnode,
#ifdef XCP
case RTE_REMOTE_DUMMY:
#endif
+ case RTE_NAMEDTUPLESTORE:
/* these shouldn't be marked LATERAL */
Assert(false);
break;
@@ -2146,7 +2147,7 @@ pullup_replace_vars_callback(Var *var,
varattno);
/* Make a copy of the tlist item to return */
- newnode = copyObject(tle->expr);
+ newnode = (Node *) copyObject(tle->expr);
/* Insert PlaceHolderVar if needed */
if (rcon->need_phvs)
@@ -2346,8 +2347,8 @@ flatten_simple_union_all(PlannerInfo *root)
RangeTblRef *rtr;
/* Shouldn't be called unless query has setops */
- topop = (SetOperationStmt *) parse->setOperations;
- Assert(topop && IsA(topop, SetOperationStmt));
+ topop = castNode(SetOperationStmt, parse->setOperations);
+ Assert(topop);
/* Can't optimize away a recursive UNION */
if (root->hasRecursion)
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index 0cc8856732..f75b3274ad 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -19,7 +19,7 @@
* tree after local transformations that might introduce nested AND/ORs.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/optimizer/prep/prepsecurity.c b/src/backend/optimizer/prep/prepsecurity.c
deleted file mode 100644
index 01eddf0fbf..0000000000
--- a/src/backend/optimizer/prep/prepsecurity.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * prepsecurity.c
- * Routines for preprocessing security barrier quals.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/backend/optimizer/prep/prepsecurity.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "access/sysattr.h"
-#include "catalog/heap.h"
-#include "nodes/makefuncs.h"
-#include "nodes/nodeFuncs.h"
-#include "optimizer/prep.h"
-#include "parser/analyze.h"
-#include "parser/parsetree.h"
-#include "rewrite/rewriteManip.h"
-#include "utils/rel.h"
-
-
-typedef struct
-{
- int rt_index; /* Index of security barrier RTE */
- int sublevels_up; /* Current nesting depth */
- Relation rel; /* RTE relation at rt_index */
- List *targetlist; /* Targetlist for new subquery RTE */
- List *colnames; /* Column names in subquery RTE */
- List *vars_processed; /* List of Vars already processed */
-} security_barrier_replace_vars_context;
-
-static void expand_security_qual(PlannerInfo *root, List *tlist, int rt_index,
- RangeTblEntry *rte, Node *qual, bool targetRelation);
-
-static void security_barrier_replace_vars(Node *node,
- security_barrier_replace_vars_context *context);
-
-static bool security_barrier_replace_vars_walker(Node *node,
- security_barrier_replace_vars_context *context);
-
-
-/*
- * expand_security_quals -
- * expands any security barrier quals on RTEs in the query rtable, turning
- * them into security barrier subqueries.
- *
- * Any given RTE may have multiple security barrier quals in a list, from which
- * we create a set of nested subqueries to isolate each security barrier from
- * the others, providing protection against malicious user-defined security
- * barriers. The first security barrier qual in the list will be used in the
- * innermost subquery.
- *
- * In practice, the only RTEs that will have security barrier quals are those
- * that refer to tables with row-level security, or which are the target
- * relation of an update to an auto-updatable security barrier view. RTEs
- * that read from a security barrier view will have already been expanded by
- * the rewriter.
- */
-void
-expand_security_quals(PlannerInfo *root, List *tlist)
-{
- Query *parse = root->parse;
- int rt_index;
- ListCell *cell;
-
- /*
- * Process each RTE in the rtable list.
- *
- * We only ever modify entries in place and append to the rtable, so it is
- * safe to use a foreach loop here.
- */
- rt_index = 0;
- foreach(cell, parse->rtable)
- {
- bool targetRelation = false;
- RangeTblEntry *rte = (RangeTblEntry *) lfirst(cell);
-
- rt_index++;
-
- if (rte->securityQuals == NIL)
- continue;
-
- /*
- * Ignore any RTEs that aren't used in the query (such RTEs may be
- * present for permissions checks).
- */
- if (rt_index != parse->resultRelation &&
- !rangeTableEntry_used((Node *) parse, rt_index, 0))
- continue;
-
- /*
- * If this RTE is the target then we need to make a copy of it before
- * expanding it. The unexpanded copy will become the new target, and
- * the original RTE will be expanded to become the source of rows to
- * update/delete.
- */
- if (rt_index == parse->resultRelation)
- {
- RangeTblEntry *newrte = copyObject(rte);
-
- /*
- * We need to let expand_security_qual know if this is the target
- * relation, as it has additional work to do in that case.
- *
- * Capture that information here as we're about to replace
- * parse->resultRelation.
- */
- targetRelation = true;
-
- parse->rtable = lappend(parse->rtable, newrte);
- parse->resultRelation = list_length(parse->rtable);
-
- /*
- * Wipe out any copied security barrier quals on the new target to
- * prevent infinite recursion.
- */
- newrte->securityQuals = NIL;
-
- /*
- * There's no need to do permissions checks twice, so wipe out the
- * permissions info for the original RTE (we prefer to keep the
- * bits set on the result RTE).
- */
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
-
- /*
- * For the most part, Vars referencing the original relation
- * should remain as they are, meaning that they pull OLD values
- * from the expanded RTE. But in the RETURNING list and in any
- * WITH CHECK OPTION quals, we want such Vars to represent NEW
- * values, so change them to reference the new RTE.
- */
- ChangeVarNodes((Node *) parse->returningList, rt_index,
- parse->resultRelation, 0);
-
- ChangeVarNodes((Node *) parse->withCheckOptions, rt_index,
- parse->resultRelation, 0);
- }
-
- /*
- * Process each security barrier qual in turn, starting with the
- * innermost one (the first in the list) and working outwards.
- *
- * We remove each qual from the list before processing it, so that its
- * variables aren't modified by expand_security_qual. Also we don't
- * necessarily want the attributes referred to by the qual to be
- * exposed by the newly built subquery.
- */
- while (rte->securityQuals != NIL)
- {
- Node *qual = (Node *) linitial(rte->securityQuals);
-
- rte->securityQuals = list_delete_first(rte->securityQuals);
-
- ChangeVarNodes(qual, rt_index, 1, 0);
- expand_security_qual(root, tlist, rt_index, rte, qual,
- targetRelation);
- }
- }
-}
-
-
-/*
- * expand_security_qual -
- * expand the specified security barrier qual on a query RTE, turning the
- * RTE into a security barrier subquery.
- */
-static void
-expand_security_qual(PlannerInfo *root, List *tlist, int rt_index,
- RangeTblEntry *rte, Node *qual, bool targetRelation)
-{
- Query *parse = root->parse;
- Oid relid = rte->relid;
- Query *subquery;
- RangeTblEntry *subrte;
- RangeTblRef *subrtr;
- PlanRowMark *rc;
- security_barrier_replace_vars_context context;
- ListCell *cell;
-
- /*
- * There should only be 2 possible cases:
- *
- * 1. A relation RTE, which we turn into a subquery RTE containing all
- * referenced columns.
- *
- * 2. A subquery RTE (either from a prior call to this function or from an
- * expanded view). In this case we build a new subquery on top of it to
- * isolate this security barrier qual from any other quals.
- */
- switch (rte->rtekind)
- {
- case RTE_RELATION:
-
- /*
- * Turn the relation RTE into a security barrier subquery RTE,
- * moving all permissions checks down into the subquery.
- */
- subquery = makeNode(Query);
- subquery->commandType = CMD_SELECT;
- subquery->querySource = QSRC_INSTEAD_RULE;
-
- subrte = copyObject(rte);
- subrte->inFromCl = true;
- subrte->securityQuals = NIL;
- subquery->rtable = list_make1(subrte);
-
- subrtr = makeNode(RangeTblRef);
- subrtr->rtindex = 1;
- subquery->jointree = makeFromExpr(list_make1(subrtr), qual);
- subquery->hasSubLinks = checkExprHasSubLink(qual);
-
- rte->rtekind = RTE_SUBQUERY;
- rte->relid = InvalidOid;
- rte->subquery = subquery;
- rte->security_barrier = true;
- rte->inh = false; /* must not be set for a subquery */
-
- /* the permissions checks have now been moved down */
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
-
- /*
- * Now deal with any PlanRowMark on this RTE by requesting a lock
- * of the same strength on the RTE copied down to the subquery.
- *
- * Note that we can only push down user-defined quals if they are
- * only using leakproof (and therefore trusted) functions and
- * operators. As a result, we may end up locking more rows than
- * strictly necessary (and, in the worst case, we could end up
- * locking all rows which pass the securityQuals). This is
- * currently documented behavior, but it'd be nice to come up with
- * a better solution some day.
- */
- rc = get_plan_rowmark(root->rowMarks, rt_index);
- if (rc != NULL)
- {
- if (rc->strength != LCS_NONE)
- applyLockingClause(subquery, 1, rc->strength,
- rc->waitPolicy, false);
- root->rowMarks = list_delete_ptr(root->rowMarks, rc);
- }
-
- /*
- * When we are replacing the target relation with a subquery, we
- * need to make sure to add a locking clause explicitly to the
- * generated subquery since there won't be any row marks against
- * the target relation itself.
- */
- if (targetRelation)
- applyLockingClause(subquery, 1, LCS_FORUPDATE,
- LockWaitBlock, false);
-
- /*
- * Replace any variables in the outer query that refer to the
- * original relation RTE with references to columns that we will
- * expose in the new subquery, building the subquery's targetlist
- * as we go. Also replace any references in the translated_vars
- * lists of any appendrels.
- */
- context.rt_index = rt_index;
- context.sublevels_up = 0;
- context.rel = heap_open(relid, NoLock);
- context.targetlist = NIL;
- context.colnames = NIL;
- context.vars_processed = NIL;
-
- security_barrier_replace_vars((Node *) parse, &context);
- security_barrier_replace_vars((Node *) tlist, &context);
- security_barrier_replace_vars((Node *) root->append_rel_list,
- &context);
-
- heap_close(context.rel, NoLock);
-
- /* Now we know what columns the subquery needs to expose */
- rte->subquery->targetList = context.targetlist;
- rte->eref = makeAlias(rte->eref->aliasname, context.colnames);
-
- break;
-
- case RTE_SUBQUERY:
-
- /*
- * Build a new subquery that includes all the same columns as the
- * original subquery.
- */
- subquery = makeNode(Query);
- subquery->commandType = CMD_SELECT;
- subquery->querySource = QSRC_INSTEAD_RULE;
- subquery->targetList = NIL;
-
- foreach(cell, rte->subquery->targetList)
- {
- TargetEntry *tle;
- Var *var;
-
- tle = (TargetEntry *) lfirst(cell);
- var = makeVarFromTargetEntry(1, tle);
-
- tle = makeTargetEntry((Expr *) var,
- list_length(subquery->targetList) + 1,
- pstrdup(tle->resname),
- tle->resjunk);
- subquery->targetList = lappend(subquery->targetList, tle);
- }
-
- subrte = makeNode(RangeTblEntry);
- subrte->rtekind = RTE_SUBQUERY;
- subrte->subquery = rte->subquery;
- subrte->security_barrier = rte->security_barrier;
- subrte->eref = copyObject(rte->eref);
- subrte->inFromCl = true;
- subquery->rtable = list_make1(subrte);
-
- subrtr = makeNode(RangeTblRef);
- subrtr->rtindex = 1;
- subquery->jointree = makeFromExpr(list_make1(subrtr), qual);
- subquery->hasSubLinks = checkExprHasSubLink(qual);
-
- rte->subquery = subquery;
- rte->security_barrier = true;
-
- break;
-
- default:
- elog(ERROR, "invalid range table entry for security barrier qual");
- }
-}
-
-
-/*
- * security_barrier_replace_vars -
- * Apply security barrier variable replacement to an expression tree.
- *
- * This also builds/updates a targetlist with entries for each replacement
- * variable that needs to be exposed by the security barrier subquery RTE.
- *
- * NOTE: although this has the form of a walker, we cheat and modify the
- * nodes in-place. The given expression tree should have been copied
- * earlier to ensure that no unwanted side-effects occur!
- */
-static void
-security_barrier_replace_vars(Node *node,
- security_barrier_replace_vars_context *context)
-{
- /*
- * Must be prepared to start with a Query or a bare expression tree; if
- * it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
- */
- if (node && IsA(node, Query))
- query_tree_walker((Query *) node,
- security_barrier_replace_vars_walker,
- (void *) context, 0);
- else
- security_barrier_replace_vars_walker(node, context);
-}
-
-static bool
-security_barrier_replace_vars_walker(Node *node,
- security_barrier_replace_vars_context *context)
-{
- if (node == NULL)
- return false;
-
- if (IsA(node, Var))
- {
- Var *var = (Var *) node;
-
- /*
- * Note that the same Var may be present in different lists, so we
- * need to take care not to process it multiple times.
- */
- if (var->varno == context->rt_index &&
- var->varlevelsup == context->sublevels_up &&
- !list_member_ptr(context->vars_processed, var))
- {
- /*
- * Found a matching variable. Make sure that it is in the subquery
- * targetlist and map its attno accordingly.
- */
- AttrNumber attno;
- ListCell *l;
- TargetEntry *tle;
- char *attname;
- Var *newvar;
-
- /* Search for the base attribute in the subquery targetlist */
- attno = InvalidAttrNumber;
- foreach(l, context->targetlist)
- {
- tle = (TargetEntry *) lfirst(l);
- attno++;
-
- Assert(IsA(tle->expr, Var));
- if (((Var *) tle->expr)->varattno == var->varattno &&
- ((Var *) tle->expr)->varcollid == var->varcollid)
- {
- /* Map the variable onto this subquery targetlist entry */
- var->varattno = var->varoattno = attno;
- /* Mark this var as having been processed */
- context->vars_processed = lappend(context->vars_processed, var);
- return false;
- }
- }
-
- /* Not in the subquery targetlist, so add it. Get its name. */
- if (var->varattno < 0)
- {
- Form_pg_attribute att_tup;
-
- att_tup = SystemAttributeDefinition(var->varattno,
- context->rel->rd_rel->relhasoids);
- attname = NameStr(att_tup->attname);
- }
- else if (var->varattno == InvalidAttrNumber)
- {
- attname = "wholerow";
- }
- else if (var->varattno <= context->rel->rd_att->natts)
- {
- Form_pg_attribute att_tup;
-
- att_tup = context->rel->rd_att->attrs[var->varattno - 1];
- attname = NameStr(att_tup->attname);
- }
- else
- {
- elog(ERROR, "invalid attribute number %d in security_barrier_replace_vars", var->varattno);
- }
-
- /* New variable for subquery targetlist */
- newvar = copyObject(var);
- newvar->varno = newvar->varnoold = 1;
- newvar->varlevelsup = 0;
-
- attno = list_length(context->targetlist) + 1;
- tle = makeTargetEntry((Expr *) newvar,
- attno,
- pstrdup(attname),
- false);
-
- context->targetlist = lappend(context->targetlist, tle);
-
- context->colnames = lappend(context->colnames,
- makeString(pstrdup(attname)));
-
- /* Update the outer query's variable */
- var->varattno = var->varoattno = attno;
-
- /* Remember this Var so that we don't process it again */
- context->vars_processed = lappend(context->vars_processed, var);
- }
- return false;
- }
-
- if (IsA(node, Query))
- {
- /* Recurse into subselects */
- bool result;
-
- context->sublevels_up++;
- result = query_tree_walker((Query *) node,
- security_barrier_replace_vars_walker,
- (void *) context, 0);
- context->sublevels_up--;
- return result;
- }
-
- return expression_tree_walker(node, security_barrier_replace_vars_walker,
- (void *) context);
-}
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 64cd7262d0..4d47272781 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -27,7 +27,7 @@
* that because it's faster in typical non-inherited cases.
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -301,7 +301,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
var->varno == result_relation)
continue; /* don't need it */
- if (tlist_member((Node *) var, tlist))
+ if (tlist_member((Expr *) var, tlist))
continue; /* already got it */
tle = makeTargetEntry((Expr *) var,
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 2522636392..66c684c065 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -18,7 +18,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -57,7 +57,6 @@ typedef struct
{
PlannerInfo *root;
AppendRelInfo *appinfo;
- int sublevels_up;
} adjust_appendrel_attrs_context;
static Path *recurse_set_operations(Node *setOp, PlannerInfo *root,
@@ -131,7 +130,7 @@ RelOptInfo *
plan_set_operations(PlannerInfo *root)
{
Query *parse = root->parse;
- SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
+ SetOperationStmt *topop = castNode(SetOperationStmt, parse->setOperations);
Node *node;
RangeTblEntry *leftmostRTE;
Query *leftmostQuery;
@@ -139,7 +138,7 @@ plan_set_operations(PlannerInfo *root)
Path *path;
List *top_tlist;
- Assert(topop && IsA(topop, SetOperationStmt));
+ Assert(topop);
/* check for unsupported stuff */
Assert(parse->jointree->fromlist == NIL);
@@ -273,7 +272,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
* used for much here, but it carries the subroot data structures
* forward to setrefs.c processing.
*/
- rel = build_simple_rel(root, rtr->rtindex, RELOPT_BASEREL);
+ rel = build_simple_rel(root, rtr->rtindex, NULL);
/* plan_params should not be in use in current query level */
Assert(root->plan_params == NIL);
@@ -345,6 +344,16 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
* Estimate number of groups if caller wants it. If the subquery used
* grouping or aggregation, its output is probably mostly unique
* anyway; otherwise do statistical estimation.
+ *
+ * XXX you don't really want to know about this: we do the estimation
+ * using the subquery's original targetlist expressions, not the
+ * subroot->processed_tlist which might seem more appropriate. The
+ * reason is that if the subquery is itself a setop, it may return a
+ * processed_tlist containing "varno 0" Vars generated by
+ * generate_append_tlist, and those would confuse estimate_num_groups
+ * mightily. We ought to get rid of the "varno 0" hack, but that
+ * requires a redesign of the parsetree representation of setops, so
+ * that there can be an RTE corresponding to each setop's output.
*/
if (pNumGroups)
{
@@ -354,7 +363,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
*pNumGroups = subpath->rows;
else
*pNumGroups = estimate_num_groups(subroot,
- get_tlist_exprs(subroot->processed_tlist, false),
+ get_tlist_exprs(subquery->targetList, false),
subpath->rows,
NULL);
}
@@ -635,7 +644,7 @@ generate_union_path(SetOperationStmt *op, PlannerInfo *root,
/*
* Append the child results together.
*/
- path = (Path *) create_append_path(result_rel, pathlist, NULL, 0);
+ path = (Path *) create_append_path(result_rel, pathlist, NULL, 0, NIL);
/* We have to manually jam the right tlist into the path; ick */
path->pathtarget = create_pathtarget(root, tlist);
@@ -747,7 +756,7 @@ generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
/*
* Append the child results together.
*/
- path = (Path *) create_append_path(result_rel, pathlist, NULL, 0);
+ path = (Path *) create_append_path(result_rel, pathlist, NULL, 0, NIL);
/* We have to manually jam the right tlist into the path; ick */
path->pathtarget = create_pathtarget(root, tlist);
@@ -1343,7 +1352,7 @@ generate_append_tlist(List *colTypes, List *colCollations,
static List *
generate_setop_grouplist(SetOperationStmt *op, List *targetlist)
{
- List *grouplist = (List *) copyObject(op->groupClauses);
+ List *grouplist = copyObject(op->groupClauses);
ListCell *lg;
ListCell *lt;
@@ -1433,6 +1442,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
List *inhOIDs;
List *appinfos;
ListCell *l;
+ bool need_append;
+ PartitionedChildRelInfo *pcinfo;
+ List *partitioned_child_rels = NIL;
/* Does RT entry allow inheritance? */
if (!rte->inh)
@@ -1504,6 +1516,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
/* Scan the inheritance set and expand it */
appinfos = NIL;
+ need_append = false;
foreach(l, inhOIDs)
{
Oid childOID = lfirst_oid(l);
@@ -1535,46 +1548,63 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
* We copy most fields of the parent's RTE, but replace relation OID
* and relkind, and set inh = false. Also, set requiredPerms to zero
* since all required permissions checks are done on the original RTE.
+ * Likewise, set the child's securityQuals to empty, because we only
+ * want to apply the parent's RLS conditions regardless of what RLS
+ * properties individual children may have. (This is an intentional
+ * choice to make inherited RLS work like regular permissions checks.)
+ * The parent securityQuals will be propagated to children along with
+ * other base restriction clauses, so we don't need to do it here.
*/
childrte = copyObject(rte);
childrte->relid = childOID;
childrte->relkind = newrelation->rd_rel->relkind;
childrte->inh = false;
childrte->requiredPerms = 0;
+ childrte->securityQuals = NIL;
parse->rtable = lappend(parse->rtable, childrte);
childRTindex = list_length(parse->rtable);
/*
- * Build an AppendRelInfo for this parent and child.
- */
- appinfo = makeNode(AppendRelInfo);
- appinfo->parent_relid = rti;
- appinfo->child_relid = childRTindex;
- appinfo->parent_reltype = oldrelation->rd_rel->reltype;
- appinfo->child_reltype = newrelation->rd_rel->reltype;
- make_inh_translation_list(oldrelation, newrelation, childRTindex,
- &appinfo->translated_vars);
- appinfo->parent_reloid = parentOID;
- appinfos = lappend(appinfos, appinfo);
-
- /*
- * Translate the column permissions bitmaps to the child's attnums (we
- * have to build the translated_vars list before we can do this). But
- * if this is the parent table, leave copyObject's result alone.
- *
- * Note: we need to do this even though the executor won't run any
- * permissions checks on the child RTE. The insertedCols/updatedCols
- * bitmaps may be examined for trigger-firing purposes.
+ * Build an AppendRelInfo for this parent and child, unless the child
+ * is a partitioned table.
*/
- if (childOID != parentOID)
+ if (childrte->relkind != RELKIND_PARTITIONED_TABLE)
{
- childrte->selectedCols = translate_col_privs(rte->selectedCols,
+ need_append = true;
+ appinfo = makeNode(AppendRelInfo);
+ appinfo->parent_relid = rti;
+ appinfo->child_relid = childRTindex;
+ appinfo->parent_reltype = oldrelation->rd_rel->reltype;
+ appinfo->child_reltype = newrelation->rd_rel->reltype;
+ make_inh_translation_list(oldrelation, newrelation, childRTindex,
+ &appinfo->translated_vars);
+ appinfo->parent_reloid = parentOID;
+ appinfos = lappend(appinfos, appinfo);
+
+ /*
+ * Translate the column permissions bitmaps to the child's attnums
+ * (we have to build the translated_vars list before we can do
+ * this). But if this is the parent table, leave copyObject's
+ * result alone.
+ *
+ * Note: we need to do this even though the executor won't run any
+ * permissions checks on the child RTE. The
+ * insertedCols/updatedCols bitmaps may be examined for
+ * trigger-firing purposes.
+ */
+ if (childOID != parentOID)
+ {
+ childrte->selectedCols = translate_col_privs(rte->selectedCols,
appinfo->translated_vars);
- childrte->insertedCols = translate_col_privs(rte->insertedCols,
+ childrte->insertedCols = translate_col_privs(rte->insertedCols,
appinfo->translated_vars);
- childrte->updatedCols = translate_col_privs(rte->updatedCols,
+ childrte->updatedCols = translate_col_privs(rte->updatedCols,
appinfo->translated_vars);
+ }
}
+ else
+ partitioned_child_rels = lappend_int(partitioned_child_rels,
+ childRTindex);
/*
* Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
@@ -1591,7 +1621,14 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
newrc->allMarkTypes = (1 << newrc->markType);
newrc->strength = oldrc->strength;
newrc->waitPolicy = oldrc->waitPolicy;
- newrc->isParent = false;
+
+ /*
+ * We mark RowMarks for partitioned child tables as parent
+ * RowMarks so that the executor ignores them (except their
+ * existence means that the child tables be locked using
+ * appropriate mode).
+ */
+ newrc->isParent = (childrte->relkind == RELKIND_PARTITIONED_TABLE);
/* Include child's rowmark type in parent's allMarkTypes */
oldrc->allMarkTypes |= newrc->allMarkTypes;
@@ -1607,17 +1644,37 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
heap_close(oldrelation, NoLock);
/*
- * If all the children were temp tables, pretend it's a non-inheritance
- * situation. The duplicate RTE we added for the parent table is
- * harmless, so we don't bother to get rid of it.
+ * If all the children were temp tables or a partitioned parent did not
+ * have any leaf partitions, pretend it's a non-inheritance situation; we
+ * don't need Append node in that case. The duplicate RTE we added for
+ * the parent table is harmless, so we don't bother to get rid of it;
+ * ditto for the useless PlanRowMark node.
*/
- if (list_length(appinfos) < 2)
+ if (!need_append)
{
/* Clear flag before returning */
rte->inh = false;
return;
}
+ /*
+ * We keep a list of objects in root, each of which maps a partitioned
+ * parent RT index to the list of RT indexes of its partitioned child
+ * tables. When creating an Append or a ModifyTable path for the parent,
+ * we copy the child RT index list verbatim to the path so that it could
+ * be carried over to the executor so that the latter could identify the
+ * partitioned child tables.
+ */
+ if (partitioned_child_rels != NIL)
+ {
+ pcinfo = makeNode(PartitionedChildRelInfo);
+
+ Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
+ pcinfo->parent_relid = rti;
+ pcinfo->child_rels = partitioned_child_rels;
+ root->pcinfo_list = lappend(root->pcinfo_list, pcinfo);
+ }
+
/* Otherwise, OK to add to root->append_rel_list */
root->append_rel_list = list_concat(root->append_rel_list, appinfos);
}
@@ -1762,12 +1819,11 @@ translate_col_privs(const Bitmapset *parent_privs,
attno = InvalidAttrNumber;
foreach(lc, translated_vars)
{
- Var *var = (Var *) lfirst(lc);
+ Var *var = lfirst_node(Var, lc);
attno++;
if (var == NULL) /* ignore dropped columns */
continue;
- Assert(IsA(var, Var));
if (whole_row ||
bms_is_member(attno - FirstLowInvalidHeapAttributeNumber,
parent_privs))
@@ -1785,9 +1841,8 @@ translate_col_privs(const Bitmapset *parent_privs,
* child rel instead. We also update rtindexes appearing outside Vars,
* such as resultRelation and jointree relids.
*
- * Note: this is applied after conversion of sublinks to subplans in the
- * query jointree, but there may still be sublinks in the security barrier
- * quals of RTEs, so we do need to cope with recursion into sub-queries.
+ * Note: this is only applied after conversion of sublinks to subplans,
+ * so we don't need to cope with recursion into sub-queries.
*
* Note: this is not hugely different from what pullup_replace_vars() does;
* maybe we should try to fold the two routines together.
@@ -1800,12 +1855,9 @@ adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
context.root = root;
context.appinfo = appinfo;
- context.sublevels_up = 0;
/*
- * Must be prepared to start with a Query or a bare expression tree; if
- * it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
+ * Must be prepared to start with a Query or a bare expression tree.
*/
if (node && IsA(node, Query))
{
@@ -1844,7 +1896,7 @@ adjust_appendrel_attrs_mutator(Node *node,
{
Var *var = (Var *) copyObject(node);
- if (var->varlevelsup == context->sublevels_up &&
+ if (var->varlevelsup == 0 &&
var->varno == appinfo->parent_relid)
{
var->varno = appinfo->child_relid;
@@ -1861,7 +1913,6 @@ adjust_appendrel_attrs_mutator(Node *node,
if (newnode == NULL)
elog(ERROR, "attribute %d of relation \"%s\" does not exist",
var->varattno, get_rel_name(appinfo->parent_reloid));
- ((Var *) newnode)->varlevelsup += context->sublevels_up;
return newnode;
}
else if (var->varattno == 0)
@@ -1904,17 +1955,10 @@ adjust_appendrel_attrs_mutator(Node *node,
RowExpr *rowexpr;
List *fields;
RangeTblEntry *rte;
- ListCell *lc;
rte = rt_fetch(appinfo->parent_relid,
context->root->parse->rtable);
- fields = (List *) copyObject(appinfo->translated_vars);
- foreach(lc, fields)
- {
- Var *field = (Var *) lfirst(lc);
-
- field->varlevelsup += context->sublevels_up;
- }
+ fields = copyObject(appinfo->translated_vars);
rowexpr = makeNode(RowExpr);
rowexpr->args = fields;
rowexpr->row_typeid = var->vartype;
@@ -1933,8 +1977,7 @@ adjust_appendrel_attrs_mutator(Node *node,
{
CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
- if (context->sublevels_up == 0 &&
- cexpr->cvarno == appinfo->parent_relid)
+ if (cexpr->cvarno == appinfo->parent_relid)
cexpr->cvarno = appinfo->child_relid;
return (Node *) cexpr;
}
@@ -1942,8 +1985,7 @@ adjust_appendrel_attrs_mutator(Node *node,
{
RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
- if (context->sublevels_up == 0 &&
- rtr->rtindex == appinfo->parent_relid)
+ if (rtr->rtindex == appinfo->parent_relid)
rtr->rtindex = appinfo->child_relid;
return (Node *) rtr;
}
@@ -1956,8 +1998,7 @@ adjust_appendrel_attrs_mutator(Node *node,
adjust_appendrel_attrs_mutator,
(void *) context);
/* now fix JoinExpr's rtindex (probably never happens) */
- if (context->sublevels_up == 0 &&
- j->rtindex == appinfo->parent_relid)
+ if (j->rtindex == appinfo->parent_relid)
j->rtindex = appinfo->child_relid;
return (Node *) j;
}
@@ -1970,7 +2011,7 @@ adjust_appendrel_attrs_mutator(Node *node,
adjust_appendrel_attrs_mutator,
(void *) context);
/* now fix PlaceHolderVar's relid sets */
- if (phv->phlevelsup == context->sublevels_up)
+ if (phv->phlevelsup == 0)
phv->phrels = adjust_relid_set(phv->phrels,
appinfo->parent_relid,
appinfo->child_relid);
@@ -2041,29 +2082,12 @@ adjust_appendrel_attrs_mutator(Node *node,
return (Node *) newinfo;
}
- if (IsA(node, Query))
- {
- /*
- * Recurse into sublink subqueries. This should only be possible in
- * security barrier quals of top-level RTEs. All other sublinks should
- * have already been converted to subplans during expression
- * preprocessing, but this doesn't happen for security barrier quals,
- * since they are destined to become quals of a subquery RTE, which
- * will be recursively planned, and so should not be preprocessed at
- * this stage.
- *
- * We don't explicitly Assert() for securityQuals here simply because
- * it's not trivial to do so.
- */
- Query *newnode;
-
- context->sublevels_up++;
- newnode = query_tree_mutator((Query *) node,
- adjust_appendrel_attrs_mutator,
- (void *) context, 0);
- context->sublevels_up--;
- return (Node *) newnode;
- }
+ /*
+ * NOTE: we do not need to recurse into sublinks, because they should
+ * already have been converted to subplans before we see them.
+ */
+ Assert(!IsA(node, SubLink));
+ Assert(!IsA(node, Query));
return expression_tree_mutator(node, adjust_appendrel_attrs_mutator,
(void *) context);
@@ -2198,7 +2222,7 @@ adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid);
/* If parent is also a child, first recurse to apply its translations */
- if (parent_rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
+ if (IS_OTHER_REL(parent_rel))
node = adjust_appendrel_attrs_multilevel(root, node, parent_rel);
else
Assert(parent_rel->reloptkind == RELOPT_BASEREL);
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 4e23898ff9..a1dafc8e0f 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -3,7 +3,7 @@
* clauses.c
* routines to manipulate qualification clauses
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -91,20 +91,21 @@ typedef struct
typedef struct
{
- bool allow_restricted;
-} has_parallel_hazard_arg;
+ char max_hazard; /* worst proparallel hazard found so far */
+ char max_interesting; /* worst proparallel hazard of interest */
+ List *safe_param_ids; /* PARAM_EXEC Param IDs to treat as safe */
+} max_parallel_hazard_context;
static bool contain_agg_clause_walker(Node *node, void *context);
static bool get_agg_clause_costs_walker(Node *node,
get_agg_clause_costs_context *context);
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists);
-static bool expression_returns_set_rows_walker(Node *node, double *count);
static bool contain_subplans_walker(Node *node, void *context);
static bool contain_mutable_functions_walker(Node *node, void *context);
static bool contain_volatile_functions_walker(Node *node, void *context);
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context);
-static bool has_parallel_hazard_walker(Node *node,
- has_parallel_hazard_arg *context);
+static bool max_parallel_hazard_walker(Node *node,
+ max_parallel_hazard_context *context);
static bool contain_nonstrict_functions_walker(Node *node, void *context);
static bool contain_context_dependent_node(Node *clause);
static bool contain_context_dependent_node_walker(Node *node, int *flags);
@@ -354,8 +355,8 @@ make_and_qual(Node *qual1, Node *qual2)
}
/*
- * Sometimes (such as in the input of ExecQual), we use lists of expression
- * nodes with implicit AND semantics.
+ * The planner frequently prefers to represent qualification expressions
+ * as lists of boolean expressions with implicit AND semantics.
*
* These functions convert between an AND-semantics expression list and the
* ordinary representation of a boolean expression.
@@ -646,6 +647,16 @@ get_agg_clause_costs_walker(Node *node, get_agg_clause_costs_context *context)
/* Use average width if aggregate definition gave one */
if (aggtransspace > 0)
avgwidth = aggtransspace;
+ else if (aggtransfn == F_ARRAY_APPEND)
+ {
+ /*
+ * If the transition function is array_append(), it'll use an
+ * expanded array as transvalue, which will occupy at least
+ * ALLOCSET_SMALL_INITSIZE and possibly more. Use that as the
+ * estimate for lack of a better idea.
+ */
+ avgwidth = ALLOCSET_SMALL_INITSIZE;
+ }
else
{
/*
@@ -779,114 +790,37 @@ find_window_functions_walker(Node *node, WindowFuncLists *lists)
/*
* expression_returns_set_rows
* Estimate the number of rows returned by a set-returning expression.
- * The result is 1 if there are no set-returning functions.
+ * The result is 1 if it's not a set-returning expression.
*
- * We use the product of the rowcount estimates of all the functions in
- * the given tree (this corresponds to the behavior of ExecMakeFunctionResult
- * for nested set-returning functions).
+ * We should only examine the top-level function or operator; it used to be
+ * appropriate to recurse, but not anymore. (Even if there are more SRFs in
+ * the function's inputs, their multipliers are accounted for separately.)
*
* Note: keep this in sync with expression_returns_set() in nodes/nodeFuncs.c.
*/
double
expression_returns_set_rows(Node *clause)
{
- double result = 1;
-
- (void) expression_returns_set_rows_walker(clause, &result);
- return clamp_row_est(result);
-}
-
-static bool
-expression_returns_set_rows_walker(Node *node, double *count)
-{
- if (node == NULL)
- return false;
- if (IsA(node, FuncExpr))
+ if (clause == NULL)
+ return 1.0;
+ if (IsA(clause, FuncExpr))
{
- FuncExpr *expr = (FuncExpr *) node;
+ FuncExpr *expr = (FuncExpr *) clause;
if (expr->funcretset)
- *count *= get_func_rows(expr->funcid);
+ return clamp_row_est(get_func_rows(expr->funcid));
}
- if (IsA(node, OpExpr))
+ if (IsA(clause, OpExpr))
{
- OpExpr *expr = (OpExpr *) node;
+ OpExpr *expr = (OpExpr *) clause;
if (expr->opretset)
{
set_opfuncid(expr);
- *count *= get_func_rows(expr->opfuncid);
+ return clamp_row_est(get_func_rows(expr->opfuncid));
}
}
-
- /* Avoid recursion for some cases that can't return a set */
- if (IsA(node, Aggref))
- return false;
- if (IsA(node, WindowFunc))
- return false;
- if (IsA(node, DistinctExpr))
- return false;
- if (IsA(node, NullIfExpr))
- return false;
- if (IsA(node, ScalarArrayOpExpr))
- return false;
- if (IsA(node, BoolExpr))
- return false;
- if (IsA(node, SubLink))
- return false;
- if (IsA(node, SubPlan))
- return false;
- if (IsA(node, AlternativeSubPlan))
- return false;
- if (IsA(node, ArrayExpr))
- return false;
- if (IsA(node, RowExpr))
- return false;
- if (IsA(node, RowCompareExpr))
- return false;
- if (IsA(node, CoalesceExpr))
- return false;
- if (IsA(node, MinMaxExpr))
- return false;
- if (IsA(node, XmlExpr))
- return false;
-
- return expression_tree_walker(node, expression_returns_set_rows_walker,
- (void *) count);
-}
-
-/*
- * tlist_returns_set_rows
- * Estimate the number of rows returned by a set-returning targetlist.
- * The result is 1 if there are no set-returning functions.
- *
- * Here, the result is the largest rowcount estimate of any of the tlist's
- * expressions, not the product as you would get from naively applying
- * expression_returns_set_rows() to the whole tlist. The behavior actually
- * implemented by ExecTargetList produces a number of rows equal to the least
- * common multiple of the expression rowcounts, so that the product would be
- * a worst-case estimate that is typically not realistic. Taking the max as
- * we do here is a best-case estimate that might not be realistic either,
- * but it's probably closer for typical usages. We don't try to compute the
- * actual LCM because we're working with very approximate estimates, so their
- * LCM would be unduly noisy.
- */
-double
-tlist_returns_set_rows(List *tlist)
-{
- double result = 1;
- ListCell *lc;
-
- foreach(lc, tlist)
- {
- TargetEntry *tle = (TargetEntry *) lfirst(lc);
- double colresult;
-
- colresult = expression_returns_set_rows((Node *) tle->expr);
- if (result < colresult)
- result = colresult;
- }
- return result;
+ return 1.0;
}
@@ -962,6 +896,12 @@ contain_mutable_functions_walker(Node *node, void *context)
context))
return true;
+ if (IsA(node, SQLValueFunction))
+ {
+ /* all variants of SQLValueFunction are stable */
+ return true;
+ }
+
/*
* It should be safe to treat MinMaxExpr as immutable, because it will
* depend on a non-cross-type btree comparison function, and those should
@@ -1031,7 +971,8 @@ contain_volatile_functions_walker(Node *node, void *context)
/*
* See notes in contain_mutable_functions_walker about why we treat
- * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable.
+ * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
+ * SQLValueFunction is stable. Hence, none of them are of interest here.
*/
/* Recurse to check arguments */
@@ -1076,7 +1017,8 @@ contain_volatile_functions_not_nextval_walker(Node *node, void *context)
/*
* See notes in contain_mutable_functions_walker about why we treat
- * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable.
+ * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
+ * SQLValueFunction is stable. Hence, none of them are of interest here.
*/
/* Recurse to check arguments */
@@ -1092,46 +1034,106 @@ contain_volatile_functions_not_nextval_walker(Node *node, void *context)
context);
}
+
/*****************************************************************************
* Check queries for parallel unsafe and/or restricted constructs
*****************************************************************************/
/*
- * Check whether a node tree contains parallel hazards. This is used both on
- * the entire query tree, to see whether the query can be parallelized at all
- * (with allow_restricted = true), and also to evaluate whether a particular
- * expression is safe to run within a parallel worker (with allow_restricted =
- * false). We could separate these concerns into two different functions, but
- * there's enough overlap that it doesn't seem worthwhile.
+ * max_parallel_hazard
+ * Find the worst parallel-hazard level in the given query
+ *
+ * Returns the worst function hazard property (the earliest in this list:
+ * PROPARALLEL_UNSAFE, PROPARALLEL_RESTRICTED, PROPARALLEL_SAFE) that can
+ * be found in the given parsetree. We use this to find out whether the query
+ * can be parallelized at all. The caller will also save the result in
+ * PlannerGlobal so as to short-circuit checks of portions of the querytree
+ * later, in the common case where everything is SAFE.
+ */
+char
+max_parallel_hazard(Query *parse)
+{
+ max_parallel_hazard_context context;
+
+ context.max_hazard = PROPARALLEL_SAFE;
+ context.max_interesting = PROPARALLEL_UNSAFE;
+ context.safe_param_ids = NIL;
+ (void) max_parallel_hazard_walker((Node *) parse, &context);
+ return context.max_hazard;
+}
+
+/*
+ * is_parallel_safe
+ * Detect whether the given expr contains only parallel-safe functions
+ *
+ * root->glob->maxParallelHazard must previously have been set to the
+ * result of max_parallel_hazard() on the whole query.
*/
bool
-has_parallel_hazard(Node *node, bool allow_restricted)
+is_parallel_safe(PlannerInfo *root, Node *node)
{
- has_parallel_hazard_arg context;
+ max_parallel_hazard_context context;
- context.allow_restricted = allow_restricted;
- return has_parallel_hazard_walker(node, &context);
+ /*
+ * Even if the original querytree contained nothing unsafe, we need to
+ * search the expression if we have generated any PARAM_EXEC Params while
+ * planning, because those are parallel-restricted and there might be one
+ * in this expression. But otherwise we don't need to look.
+ */
+ if (root->glob->maxParallelHazard == PROPARALLEL_SAFE &&
+ root->glob->nParamExec == 0)
+ return true;
+ /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */
+ context.max_hazard = PROPARALLEL_SAFE;
+ context.max_interesting = PROPARALLEL_RESTRICTED;
+ context.safe_param_ids = NIL;
+ return !max_parallel_hazard_walker(node, &context);
}
+/* core logic for all parallel-hazard checks */
static bool
-has_parallel_hazard_checker(Oid func_id, void *context)
+max_parallel_hazard_test(char proparallel, max_parallel_hazard_context *context)
{
- char proparallel = func_parallel(func_id);
+ switch (proparallel)
+ {
+ case PROPARALLEL_SAFE:
+ /* nothing to see here, move along */
+ break;
+ case PROPARALLEL_RESTRICTED:
+ /* increase max_hazard to RESTRICTED */
+ Assert(context->max_hazard != PROPARALLEL_UNSAFE);
+ context->max_hazard = proparallel;
+ /* done if we are not expecting any unsafe functions */
+ if (context->max_interesting == proparallel)
+ return true;
+ break;
+ case PROPARALLEL_UNSAFE:
+ context->max_hazard = proparallel;
+ /* we're always done at the first unsafe construct */
+ return true;
+ default:
+ elog(ERROR, "unrecognized proparallel value \"%c\"", proparallel);
+ break;
+ }
+ return false;
+}
- if (((has_parallel_hazard_arg *) context)->allow_restricted)
- return (proparallel == PROPARALLEL_UNSAFE);
- else
- return (proparallel != PROPARALLEL_SAFE);
+/* check_functions_in_node callback */
+static bool
+max_parallel_hazard_checker(Oid func_id, void *context)
+{
+ return max_parallel_hazard_test(func_parallel(func_id),
+ (max_parallel_hazard_context *) context);
}
static bool
-has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
+max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
{
if (node == NULL)
return false;
/* Check for hazardous functions in node itself */
- if (check_functions_in_node(node, has_parallel_hazard_checker,
+ if (check_functions_in_node(node, max_parallel_hazard_checker,
context))
return true;
@@ -1143,11 +1145,12 @@ has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
* (Note: in principle that's wrong because a domain constraint could
* contain a parallel-unsafe function; but useful constraints probably
* never would have such, and assuming they do would cripple use of
- * parallel query in the presence of domain types.)
+ * parallel query in the presence of domain types.) SQLValueFunction
+ * should be safe in all cases.
*/
if (IsA(node, CoerceToDomain))
{
- if (!context->allow_restricted)
+ if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
return true;
}
@@ -1158,33 +1161,62 @@ has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
{
RestrictInfo *rinfo = (RestrictInfo *) node;
- return has_parallel_hazard_walker((Node *) rinfo->clause, context);
+ return max_parallel_hazard_walker((Node *) rinfo->clause, context);
}
/*
- * Since we don't have the ability to push subplans down to workers at
- * present, we treat subplan references as parallel-restricted. We need
- * not worry about examining their contents; if they are unsafe, we would
- * have found that out while examining the whole tree before reduction of
- * sublinks to subplans. (Really we should not see SubLink during a
- * not-allow_restricted scan, but if we do, return true.)
+ * Really we should not see SubLink during a max_interesting == restricted
+ * scan, but if we do, return true.
*/
- else if (IsA(node, SubLink) ||
- IsA(node, SubPlan) ||
- IsA(node, AlternativeSubPlan))
+ else if (IsA(node, SubLink))
{
- if (!context->allow_restricted)
+ if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
return true;
}
/*
+ * Only parallel-safe SubPlans can be sent to workers. Within the
+ * testexpr of the SubPlan, Params representing the output columns of the
+ * subplan can be treated as parallel-safe, so temporarily add their IDs
+ * to the safe_param_ids list while examining the testexpr.
+ */
+ else if (IsA(node, SubPlan))
+ {
+ SubPlan *subplan = (SubPlan *) node;
+ List *save_safe_param_ids;
+
+ if (!subplan->parallel_safe &&
+ max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
+ return true;
+ save_safe_param_ids = context->safe_param_ids;
+ context->safe_param_ids = list_concat(list_copy(subplan->paramIds),
+ context->safe_param_ids);
+ if (max_parallel_hazard_walker(subplan->testexpr, context))
+ return true; /* no need to restore safe_param_ids */
+ context->safe_param_ids = save_safe_param_ids;
+ /* we must also check args, but no special Param treatment there */
+ if (max_parallel_hazard_walker((Node *) subplan->args, context))
+ return true;
+ /* don't want to recurse normally, so we're done */
+ return false;
+ }
+
+ /*
* We can't pass Params to workers at the moment either, so they are also
- * parallel-restricted.
+ * parallel-restricted, unless they are PARAM_EXEC Params listed in
+ * safe_param_ids, meaning they could be generated within the worker.
*/
else if (IsA(node, Param))
{
- if (!context->allow_restricted)
- return true;
+ Param *param = (Param *) node;
+
+ if (param->paramkind != PARAM_EXEC ||
+ !list_member_int(context->safe_param_ids, param->paramid))
+ {
+ if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
+ return true;
+ }
+ return false; /* nothing to recurse to */
}
/*
@@ -1198,20 +1230,24 @@ has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
/* SELECT FOR UPDATE/SHARE must be treated as unsafe */
if (query->rowMarks != NULL)
+ {
+ context->max_hazard = PROPARALLEL_UNSAFE;
return true;
+ }
/* Recurse into subselects */
return query_tree_walker(query,
- has_parallel_hazard_walker,
+ max_parallel_hazard_walker,
context, 0);
}
/* Recurse to check arguments */
return expression_tree_walker(node,
- has_parallel_hazard_walker,
+ max_parallel_hazard_walker,
context);
}
+
/*****************************************************************************
* Check clauses for nonstrict functions
*****************************************************************************/
@@ -1418,10 +1454,8 @@ contain_context_dependent_node_walker(Node *node, int *flags)
*
* Returns true if the clause contains any non-leakproof functions that are
* passed Var nodes of the current query level, and which might therefore leak
- * data. Qualifiers from outside a security_barrier view that might leak data
- * in this way should not be pushed down into the view in case the contents of
- * tuples intended to be filtered out by the view are revealed by the leaky
- * functions.
+ * data. Such clauses must be applied after any lower-level security barrier
+ * clauses.
*/
bool
contain_leaked_vars(Node *clause)
@@ -1458,6 +1492,7 @@ contain_leaked_vars_walker(Node *node, void *context)
case T_CaseTestExpr:
case T_RowExpr:
case T_MinMaxExpr:
+ case T_SQLValueFunction:
case T_NullTest:
case T_BooleanTest:
case T_List:
@@ -1515,10 +1550,10 @@ contain_leaked_vars_walker(Node *node, void *context)
case T_CurrentOfExpr:
/*
- * WHERE CURRENT OF doesn't contain function calls. Moreover, it
- * is important that this can be pushed down into a
- * security_barrier view, since the planner must always generate a
- * TID scan when CURRENT OF is present -- c.f. cost_tidscan.
+ * WHERE CURRENT OF doesn't contain leaky function calls.
+ * Moreover, it is essential that this is considered non-leaky,
+ * since the planner must always generate a TID scan when CURRENT
+ * OF is present -- c.f. cost_tidscan.
*/
return false;
@@ -2699,9 +2734,8 @@ eval_const_expressions_mutator(Node *node,
* Since the underlying operator is "=", must negate
* its result
*/
- Const *csimple = (Const *) simple;
+ Const *csimple = castNode(Const, simple);
- Assert(IsA(csimple, Const));
csimple->constvalue =
BoolGetDatum(!DatumGetBool(csimple->constvalue));
return (Node *) csimple;
@@ -3090,12 +3124,10 @@ eval_const_expressions_mutator(Node *node,
const_true_cond = false;
foreach(arg, caseexpr->args)
{
- CaseWhen *oldcasewhen = (CaseWhen *) lfirst(arg);
+ CaseWhen *oldcasewhen = lfirst_node(CaseWhen, arg);
Node *casecond;
Node *caseresult;
- Assert(IsA(oldcasewhen, CaseWhen));
-
/* Simplify this alternative's test condition */
casecond = eval_const_expressions_mutator((Node *) oldcasewhen->expr,
context);
@@ -3263,6 +3295,23 @@ eval_const_expressions_mutator(Node *node,
newcoalesce->location = coalesceexpr->location;
return (Node *) newcoalesce;
}
+ case T_SQLValueFunction:
+ {
+ /*
+ * All variants of SQLValueFunction are stable, so if we are
+ * estimating the expression's value, we should evaluate the
+ * current function value. Otherwise just copy.
+ */
+ SQLValueFunction *svf = (SQLValueFunction *) node;
+
+ if (context->estimate)
+ return (Node *) evaluate_expr((Expr *) svf,
+ svf->type,
+ svf->typmod,
+ InvalidOid);
+ else
+ return copyObject((Node *) svf);
+ }
case T_FieldSelect:
{
/*
@@ -3380,7 +3429,7 @@ eval_const_expressions_mutator(Node *node,
* Else, make a scalar (argisrow == false) NullTest
* for this field. Scalar semantics are required
* because IS [NOT] NULL doesn't recurse; see comments
- * in ExecEvalNullTest().
+ * in ExecEvalRowNullInt().
*/
newntest = makeNode(NullTest);
newntest->arg = (Expr *) relem;
@@ -3524,8 +3573,8 @@ eval_const_expressions_mutator(Node *node,
* FALSE: drop (does not affect result)
* TRUE: force result to TRUE
* NULL: keep only one
- * We must keep one NULL input because ExecEvalOr returns NULL when no input
- * is TRUE and at least one is NULL. We don't actually include the NULL
+ * We must keep one NULL input because OR expressions evaluate to NULL when no
+ * input is TRUE and at least one is NULL. We don't actually include the NULL
* here, that's supposed to be done by the caller.
*
* The output arguments *haveNull and *forceTrue must be initialized FALSE
@@ -3636,9 +3685,9 @@ simplify_or_arguments(List *args,
* TRUE: drop (does not affect result)
* FALSE: force result to FALSE
* NULL: keep only one
- * We must keep one NULL input because ExecEvalAnd returns NULL when no input
- * is FALSE and at least one is NULL. We don't actually include the NULL
- * here, that's supposed to be done by the caller.
+ * We must keep one NULL input because AND expressions evaluate to NULL when
+ * no input is FALSE and at least one is NULL. We don't actually include the
+ * NULL here, that's supposed to be done by the caller.
*
* The output arguments *haveNull and *forceFalse must be initialized FALSE
* by the caller. They will be set TRUE if a null constant or false constant,
@@ -4063,8 +4112,7 @@ fetch_function_defaults(HeapTuple func_tuple)
if (isnull)
elog(ERROR, "not enough default arguments");
str = TextDatumGetCString(proargdefaults);
- defaults = (List *) stringToNode(str);
- Assert(IsA(defaults, List));
+ defaults = castNode(List, stringToNode(str));
pfree(str);
return defaults;
}
@@ -4311,9 +4359,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
*/
mycxt = AllocSetContextCreate(CurrentMemoryContext,
"inline_function",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(mycxt);
/* Fetch the function body */
@@ -4381,9 +4427,9 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
*/
if (!IsA(querytree, Query) ||
querytree->commandType != CMD_SELECT ||
- querytree->utilityStmt ||
querytree->hasAggs ||
querytree->hasWindowFuncs ||
+ querytree->hasTargetSRFs ||
querytree->hasSubLinks ||
querytree->cteList ||
querytree->rtable ||
@@ -4424,17 +4470,13 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
Assert(!modifyTargetList);
/*
- * Additional validity checks on the expression. It mustn't return a set,
- * and it mustn't be more volatile than the surrounding function (this is
- * to avoid breaking hacks that involve pretending a function is immutable
- * when it really ain't). If the surrounding function is declared strict,
- * then the expression must contain only strict constructs and must use
- * all of the function parameters (this is overkill, but an exact analysis
- * is hard).
+ * Additional validity checks on the expression. It mustn't be more
+ * volatile than the surrounding function (this is to avoid breaking hacks
+ * that involve pretending a function is immutable when it really ain't).
+ * If the surrounding function is declared strict, then the expression
+ * must contain only strict constructs and must use all of the function
+ * parameters (this is overkill, but an exact analysis is hard).
*/
- if (expression_returns_set(newexpr))
- goto fail;
-
if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
contain_mutable_functions(newexpr))
goto fail;
@@ -4671,7 +4713,7 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
*/
const_val = ExecEvalExprSwitchContext(exprstate,
GetPerTupleExprContext(estate),
- &const_is_null, NULL);
+ &const_is_null);
/* Get info needed about result datatype */
get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
@@ -4829,9 +4871,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
*/
mycxt = AllocSetContextCreate(CurrentMemoryContext,
"inline_set_returning_function",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
+ ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(mycxt);
/*
@@ -4904,7 +4944,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
src,
(ParserSetupHook) sql_fn_parser_setup,
- pinfo);
+ pinfo, NULL);
if (list_length(querytree_list) != 1)
goto fail;
querytree = linitial(querytree_list);
@@ -4913,8 +4953,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
* The single command must be a plain SELECT.
*/
if (!IsA(querytree, Query) ||
- querytree->commandType != CMD_SELECT ||
- querytree->utilityStmt)
+ querytree->commandType != CMD_SELECT)
goto fail;
/*
diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c
index 97d5fba391..62629ee7d8 100644
--- a/src/backend/optimizer/util/joininfo.c
+++ b/src/backend/optimizer/util/joininfo.c
@@ -3,7 +3,7 @@
* joininfo.c
* joininfo list manipulation routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -24,7 +24,7 @@
* Detect whether there is a joinclause that involves
* the two given relations.
*
- * Note: the joinclause does not have to be evaluatable with only these two
+ * Note: the joinclause does not have to be evaluable with only these two
* relations. This is intentional. For example consider
* SELECT * FROM a, b, c WHERE a.x = (b.y + c.z)
* If a is much larger than the other tables, it may be worthwhile to
diff --git a/src/backend/optimizer/util/orclauses.c b/src/backend/optimizer/util/orclauses.c
index 13570f006e..b6867e3001 100644
--- a/src/backend/optimizer/util/orclauses.c
+++ b/src/backend/optimizer/util/orclauses.c
@@ -3,7 +3,7 @@
* orclauses.c
* Routines to extract restriction OR clauses from join OR clauses
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -188,9 +188,8 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
foreach(lc2, andargs)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
- Assert(IsA(rinfo, RestrictInfo));
if (restriction_is_or_clause(rinfo))
{
/*
@@ -211,11 +210,11 @@ extract_or_clause(RestrictInfo *or_rinfo, RelOptInfo *rel)
}
else
{
- Assert(IsA(orarg, RestrictInfo));
- Assert(!restriction_is_or_clause((RestrictInfo *) orarg));
- if (is_safe_restriction_clause_for((RestrictInfo *) orarg, rel))
- subclauses = lappend(subclauses,
- ((RestrictInfo *) orarg)->clause);
+ RestrictInfo *rinfo = castNode(RestrictInfo, orarg);
+
+ Assert(!restriction_is_or_clause(rinfo));
+ if (is_safe_restriction_clause_for(rinfo, rel))
+ subclauses = lappend(subclauses, rinfo->clause);
}
/*
@@ -270,6 +269,7 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel,
true,
false,
false,
+ join_or_rinfo->security_level,
NULL,
NULL,
NULL);
@@ -296,6 +296,8 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel,
* OK, add it to the rel's restriction-clause list.
*/
rel->baserestrictinfo = lappend(rel->baserestrictinfo, or_rinfo);
+ rel->baserestrict_min_security = Min(rel->baserestrict_min_security,
+ or_rinfo->security_level);
/*
* Adjust the original join OR clause's cached selectivity to compensate
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 971ffa8822..0ccf4bd47d 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -4,7 +4,7 @@
* Routines to manipulate pathlists and create path nodes
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -762,10 +762,9 @@ add_path_precheck(RelOptInfo *parent_rel,
* As with add_path, we pfree paths that are found to be dominated by
* another partial path; this requires that there be no other references to
* such paths yet. Hence, GatherPaths must not be created for a rel until
- * we're done creating all partial paths for it. We do not currently build
- * partial indexscan paths, so there is no need for an exception for
- * IndexPaths here; for safety, we instead Assert that a path to be freed
- * isn't an IndexPath.
+ * we're done creating all partial paths for it. Unlike add_path, we don't
+ * take an exception for IndexPaths as partial index paths won't be
+ * referenced by partial BitmapHeapPaths.
*/
void
add_partial_path(RelOptInfo *parent_rel, Path *new_path)
@@ -844,8 +843,6 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
{
parent_rel->partial_pathlist =
list_delete_cell(parent_rel->partial_pathlist, p1, p1_prev);
- /* we should not see IndexPaths here, so always safe to delete */
- Assert(!IsA(old_path, IndexPath));
pfree(old_path);
/* p1_prev does not advance */
}
@@ -878,8 +875,6 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
}
else
{
- /* we should not see IndexPaths here, so always safe to delete */
- Assert(!IsA(new_path, IndexPath));
/* Reject and recycle the new path */
pfree(new_path);
}
@@ -2176,6 +2171,7 @@ create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer
* 'required_outer' is the set of outer relids for a parameterized path.
* 'loop_count' is the number of repetitions of the indexscan to factor into
* estimates of caching behavior.
+ * 'partial_path' is true if constructing a parallel index scan path.
*
* Returns the new path node.
*/
@@ -2190,7 +2186,8 @@ create_index_path(PlannerInfo *root,
ScanDirection indexscandir,
bool indexonly,
Relids required_outer,
- double loop_count)
+ double loop_count,
+ bool partial_path)
{
IndexPath *pathnode = makeNode(IndexPath);
RelOptInfo *rel = index->rel;
@@ -2232,7 +2229,7 @@ create_index_path(PlannerInfo *root,
}
}
#endif
- cost_index(pathnode, root, loop_count);
+ cost_index(pathnode, root, loop_count, partial_path);
return pathnode;
}
@@ -2254,7 +2251,8 @@ create_bitmap_heap_path(PlannerInfo *root,
RelOptInfo *rel,
Path *bitmapqual,
Relids required_outer,
- double loop_count)
+ double loop_count,
+ int parallel_degree)
{
BitmapHeapPath *pathnode = makeNode(BitmapHeapPath);
@@ -2263,9 +2261,9 @@ create_bitmap_heap_path(PlannerInfo *root,
pathnode->path.pathtarget = rel->reltarget;
pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
required_outer);
- pathnode->path.parallel_aware = false;
+ pathnode->path.parallel_aware = parallel_degree > 0 ? true : false;
pathnode->path.parallel_safe = rel->consider_parallel;
- pathnode->path.parallel_workers = 0;
+ pathnode->path.parallel_workers = parallel_degree;
pathnode->path.pathkeys = NIL; /* always unordered */
pathnode->bitmapqual = bitmapqual;
@@ -2414,7 +2412,7 @@ create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals,
*/
AppendPath *
create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer,
- int parallel_workers)
+ int parallel_workers, List *partitioned_rels)
{
AppendPath *pathnode = makeNode(AppendPath);
ListCell *l;
@@ -2502,6 +2500,8 @@ create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer,
pathnode->path.distribution = distribution;
}
#endif
+
+ pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->subpaths = subpaths;
/*
@@ -2544,7 +2544,8 @@ create_merge_append_path(PlannerInfo *root,
RelOptInfo *rel,
List *subpaths,
List *pathkeys,
- Relids required_outer)
+ Relids required_outer,
+ List *partitioned_rels)
{
MergeAppendPath *pathnode = makeNode(MergeAppendPath);
Cost input_startup_cost;
@@ -2632,6 +2633,7 @@ create_merge_append_path(PlannerInfo *root,
pathnode->path.parallel_safe = rel->consider_parallel;
pathnode->path.parallel_workers = 0;
pathnode->path.pathkeys = pathkeys;
+ pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->subpaths = subpaths;
/*
@@ -2689,7 +2691,7 @@ create_merge_append_path(PlannerInfo *root,
cost_merge_append(&pathnode->path, root,
pathkeys, list_length(subpaths),
input_startup_cost, input_total_cost,
- rel->tuples);
+ pathnode->path.rows);
return pathnode;
}
@@ -2995,6 +2997,66 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
}
/*
+ * create_gather_merge_path
+ *
+ * Creates a path corresponding to a gather merge scan, returning
+ * the pathnode.
+ */
+GatherMergePath *
+create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
+ PathTarget *target, List *pathkeys,
+ Relids required_outer, double *rows)
+{
+ GatherMergePath *pathnode = makeNode(GatherMergePath);
+ Cost input_startup_cost = 0;
+ Cost input_total_cost = 0;
+
+ Assert(subpath->parallel_safe);
+ Assert(pathkeys);
+
+ pathnode->path.pathtype = T_GatherMerge;
+ pathnode->path.parent = rel;
+ pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
+ required_outer);
+ pathnode->path.parallel_aware = false;
+
+ pathnode->subpath = subpath;
+ pathnode->num_workers = subpath->parallel_workers;
+ pathnode->path.pathkeys = pathkeys;
+ pathnode->path.pathtarget = target ? target : rel->reltarget;
+ pathnode->path.rows += subpath->rows;
+
+ if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
+ {
+ /* Subpath is adequately ordered, we won't need to sort it */
+ input_startup_cost += subpath->startup_cost;
+ input_total_cost += subpath->total_cost;
+ }
+ else
+ {
+ /* We'll need to insert a Sort node, so include cost for that */
+ Path sort_path; /* dummy for result of cost_sort */
+
+ cost_sort(&sort_path,
+ root,
+ pathkeys,
+ subpath->total_cost,
+ subpath->rows,
+ subpath->pathtarget->width,
+ 0.0,
+ work_mem,
+ -1);
+ input_startup_cost += sort_path.startup_cost;
+ input_total_cost += sort_path.total_cost;
+ }
+
+ cost_gather_merge(pathnode, root, rel, pathnode->path.param_info,
+ input_startup_cost, input_total_cost, rows);
+
+ return pathnode;
+}
+
+/*
* translate_sub_tlist - get subquery column numbers represented by tlist
*
* The given targetlist usually contains only Vars referencing the given relid.
@@ -3046,19 +3108,20 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
required_outer);
pathnode->path.parallel_aware = false;
pathnode->path.parallel_safe = false;
- pathnode->path.parallel_workers = subpath->parallel_workers;
+ pathnode->path.parallel_workers = 0;
pathnode->path.pathkeys = NIL; /* Gather has unordered result */
/* distribution is the same as in the subpath */
pathnode->path.distribution = (Distribution *) copyObject(subpath->distribution);
pathnode->subpath = subpath;
+ pathnode->num_workers = subpath->parallel_workers;
pathnode->single_copy = false;
- if (pathnode->path.parallel_workers == 0)
+ if (pathnode->num_workers == 0)
{
- pathnode->path.parallel_workers = 1;
pathnode->path.pathkeys = subpath->pathkeys;
+ pathnode->num_workers = 1;
pathnode->single_copy = true;
}
@@ -3131,6 +3194,32 @@ create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
}
/*
+ * create_tablefuncscan_path
+ * Creates a path corresponding to a sequential scan of a table function,
+ * returning the pathnode.
+ */
+Path *
+create_tablefuncscan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer)
+{
+ Path *pathnode = makeNode(Path);
+
+ pathnode->pathtype = T_TableFuncScan;
+ pathnode->parent = rel;
+ pathnode->pathtarget = rel->reltarget;
+ pathnode->param_info = get_baserel_parampathinfo(root, rel,
+ required_outer);
+ pathnode->parallel_aware = false;
+ pathnode->parallel_safe = rel->consider_parallel;
+ pathnode->parallel_workers = 0;
+ pathnode->pathkeys = NIL; /* result is always unordered */
+
+ cost_tablefuncscan(pathnode, root, rel, pathnode->param_info);
+
+ return pathnode;
+}
+
+/*
* create_valuesscan_path
* Creates a path corresponding to a scan of a VALUES list,
* returning the pathnode.
@@ -3182,6 +3271,32 @@ create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
}
/*
+ * create_namedtuplestorescan_path
+ * Creates a path corresponding to a scan of a named tuplestore, returning
+ * the pathnode.
+ */
+Path *
+create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer)
+{
+ Path *pathnode = makeNode(Path);
+
+ pathnode->pathtype = T_NamedTuplestoreScan;
+ pathnode->parent = rel;
+ pathnode->pathtarget = rel->reltarget;
+ pathnode->param_info = get_baserel_parampathinfo(root, rel,
+ required_outer);
+ pathnode->parallel_aware = false;
+ pathnode->parallel_safe = rel->consider_parallel;
+ pathnode->parallel_workers = 0;
+ pathnode->pathkeys = NIL; /* result is always unordered */
+
+ cost_namedtuplestorescan(pathnode, root, rel, pathnode->param_info);
+
+ return pathnode;
+}
+
+/*
* create_worktablescan_path
* Creates a path corresponding to a scan of a self-reference CTE,
* returning the pathnode.
@@ -3312,8 +3427,7 @@ calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path)
* 'joinrel' is the join relation.
* 'jointype' is the type of join required
* 'workspace' is the result from initial_cost_nestloop
- * 'sjinfo' is extra info about the join for selectivity estimation
- * 'semifactors' contains valid data if jointype is SEMI or ANTI
+ * 'extra' contains various information about the join
* 'outer_path' is the outer path
* 'inner_path' is the inner path
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
@@ -3327,8 +3441,7 @@ create_nestloop_path(PlannerInfo *root,
RelOptInfo *joinrel,
JoinType jointype,
JoinCostWorkspace *workspace,
- SpecialJoinInfo *sjinfo,
- SemiAntiJoinFactors *semifactors,
+ JoinPathExtraData *extra,
Path *outer_path,
Path *inner_path,
List *restrict_clauses,
@@ -3381,7 +3494,7 @@ create_nestloop_path(PlannerInfo *root,
joinrel,
outer_path,
inner_path,
- sjinfo,
+ extra->sjinfo,
required_outer,
&restrict_clauses);
pathnode->path.parallel_aware = false;
@@ -3391,6 +3504,7 @@ create_nestloop_path(PlannerInfo *root,
pathnode->path.parallel_workers = outer_path->parallel_workers;
pathnode->path.pathkeys = pathkeys;
pathnode->jointype = jointype;
+ pathnode->inner_unique = extra->inner_unique;
pathnode->outerjoinpath = outer_path;
pathnode->innerjoinpath = inner_path;
pathnode->joinrestrictinfo = restrict_clauses;
@@ -3400,7 +3514,7 @@ create_nestloop_path(PlannerInfo *root,
alternate = set_joinpath_distribution(root, pathnode);
#endif
- final_cost_nestloop(root, pathnode, workspace, sjinfo, semifactors);
+ final_cost_nestloop(root, pathnode, workspace, extra);
#ifdef XCP
/*
@@ -3409,7 +3523,7 @@ create_nestloop_path(PlannerInfo *root,
foreach(lc, alternate)
{
NestPath *altpath = (NestPath *) lfirst(lc);
- final_cost_nestloop(root, altpath, workspace, sjinfo, semifactors);
+ final_cost_nestloop(root, altpath, workspace, extra);
if (altpath->path.total_cost < pathnode->path.total_cost)
pathnode = altpath;
}
@@ -3426,7 +3540,7 @@ create_nestloop_path(PlannerInfo *root,
* 'joinrel' is the join relation
* 'jointype' is the type of join required
* 'workspace' is the result from initial_cost_mergejoin
- * 'sjinfo' is extra info about the join for selectivity estimation
+ * 'extra' contains various information about the join
* 'outer_path' is the outer path
* 'inner_path' is the inner path
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
@@ -3442,7 +3556,7 @@ create_mergejoin_path(PlannerInfo *root,
RelOptInfo *joinrel,
JoinType jointype,
JoinCostWorkspace *workspace,
- SpecialJoinInfo *sjinfo,
+ JoinPathExtraData *extra,
Path *outer_path,
Path *inner_path,
List *restrict_clauses,
@@ -3466,7 +3580,7 @@ create_mergejoin_path(PlannerInfo *root,
joinrel,
outer_path,
inner_path,
- sjinfo,
+ extra->sjinfo,
required_outer,
&restrict_clauses);
pathnode->jpath.path.parallel_aware = false;
@@ -3476,6 +3590,7 @@ create_mergejoin_path(PlannerInfo *root,
pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
pathnode->jpath.path.pathkeys = pathkeys;
pathnode->jpath.jointype = jointype;
+ pathnode->jpath.inner_unique = extra->inner_unique;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.joinrestrictinfo = restrict_clauses;
@@ -3485,8 +3600,10 @@ create_mergejoin_path(PlannerInfo *root,
#ifdef XCP
alternate = set_joinpath_distribution(root, (JoinPath *) pathnode);
#endif
+ /* pathnode->skip_mark_restore will be set by final_cost_mergejoin */
/* pathnode->materialize_inner will be set by final_cost_mergejoin */
- final_cost_mergejoin(root, pathnode, workspace, sjinfo);
+
+ final_cost_mergejoin(root, pathnode, workspace, extra);
#ifdef XCP
/*
@@ -3495,7 +3612,7 @@ create_mergejoin_path(PlannerInfo *root,
foreach(lc, alternate)
{
MergePath *altpath = (MergePath *) lfirst(lc);
- final_cost_mergejoin(root, altpath, workspace, sjinfo);
+ final_cost_mergejoin(root, altpath, workspace, extra);
if (altpath->jpath.path.total_cost < pathnode->jpath.path.total_cost)
pathnode = altpath;
}
@@ -3511,8 +3628,7 @@ create_mergejoin_path(PlannerInfo *root,
* 'joinrel' is the join relation
* 'jointype' is the type of join required
* 'workspace' is the result from initial_cost_hashjoin
- * 'sjinfo' is extra info about the join for selectivity estimation
- * 'semifactors' contains valid data if jointype is SEMI or ANTI
+ * 'extra' contains various information about the join
* 'outer_path' is the cheapest outer path
* 'inner_path' is the cheapest inner path
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
@@ -3525,8 +3641,7 @@ create_hashjoin_path(PlannerInfo *root,
RelOptInfo *joinrel,
JoinType jointype,
JoinCostWorkspace *workspace,
- SpecialJoinInfo *sjinfo,
- SemiAntiJoinFactors *semifactors,
+ JoinPathExtraData *extra,
Path *outer_path,
Path *inner_path,
List *restrict_clauses,
@@ -3547,7 +3662,7 @@ create_hashjoin_path(PlannerInfo *root,
joinrel,
outer_path,
inner_path,
- sjinfo,
+ extra->sjinfo,
required_outer,
&restrict_clauses);
pathnode->jpath.path.parallel_aware = false;
@@ -3569,6 +3684,7 @@ create_hashjoin_path(PlannerInfo *root,
*/
pathnode->jpath.path.pathkeys = NIL;
pathnode->jpath.jointype = jointype;
+ pathnode->jpath.inner_unique = extra->inner_unique;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.joinrestrictinfo = restrict_clauses;
@@ -3577,7 +3693,8 @@ create_hashjoin_path(PlannerInfo *root,
alternate = set_joinpath_distribution(root, (JoinPath *) pathnode);
#endif
/* final_cost_hashjoin will fill in pathnode->num_batches */
- final_cost_hashjoin(root, pathnode, workspace, sjinfo, semifactors);
+
+ final_cost_hashjoin(root, pathnode, workspace, extra);
#ifdef XCP
/*
@@ -3586,7 +3703,7 @@ create_hashjoin_path(PlannerInfo *root,
foreach(lc, alternate)
{
HashPath *altpath = (HashPath *) lfirst(lc);
- final_cost_hashjoin(root, altpath, workspace, sjinfo, semifactors);
+ final_cost_hashjoin(root, altpath, workspace, extra);
if (altpath->jpath.path.total_cost < pathnode->jpath.path.total_cost)
pathnode = altpath;
}
@@ -3620,7 +3737,7 @@ create_projection_path(PlannerInfo *root,
pathnode->path.parallel_aware = false;
pathnode->path.parallel_safe = rel->consider_parallel &&
subpath->parallel_safe &&
- !has_parallel_hazard((Node *) target->exprs, false);
+ is_parallel_safe(root, (Node *) target->exprs);
pathnode->path.parallel_workers = subpath->parallel_workers;
/* Projection does not change the sort order */
pathnode->path.pathkeys = subpath->pathkeys;
@@ -3729,7 +3846,7 @@ apply_projection_to_path(PlannerInfo *root,
* target expressions, then we can't.
*/
if (IsA(path, GatherPath) &&
- !has_parallel_hazard((Node *) target->exprs, false))
+ is_parallel_safe(root, (Node *) target->exprs))
{
GatherPath *gpath = (GatherPath *) path;
@@ -3750,7 +3867,7 @@ apply_projection_to_path(PlannerInfo *root,
target);
}
else if (path->parallel_safe &&
- has_parallel_hazard((Node *) target->exprs, false))
+ !is_parallel_safe(root, (Node *) target->exprs))
{
/*
* We're inserting a parallel-restricted target list into a path
@@ -3764,6 +3881,72 @@ apply_projection_to_path(PlannerInfo *root,
}
/*
+ * create_set_projection_path
+ * Creates a pathnode that represents performing a projection that
+ * includes set-returning functions.
+ *
+ * 'rel' is the parent relation associated with the result
+ * 'subpath' is the path representing the source of data
+ * 'target' is the PathTarget to be computed
+ */
+ProjectSetPath *
+create_set_projection_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ PathTarget *target)
+{
+ ProjectSetPath *pathnode = makeNode(ProjectSetPath);
+ double tlist_rows;
+ ListCell *lc;
+
+ pathnode->path.pathtype = T_ProjectSet;
+ pathnode->path.parent = rel;
+ pathnode->path.pathtarget = target;
+ /* For now, assume we are above any joins, so no parameterization */
+ pathnode->path.param_info = NULL;
+ pathnode->path.parallel_aware = false;
+ pathnode->path.parallel_safe = rel->consider_parallel &&
+ subpath->parallel_safe &&
+ is_parallel_safe(root, (Node *) target->exprs);
+ pathnode->path.parallel_workers = subpath->parallel_workers;
+ /* Projection does not change the sort order XXX? */
+ pathnode->path.pathkeys = subpath->pathkeys;
+
+ pathnode->subpath = subpath;
+
+ /*
+ * Estimate number of rows produced by SRFs for each row of input; if
+ * there's more than one in this node, use the maximum.
+ */
+ tlist_rows = 1;
+ foreach(lc, target->exprs)
+ {
+ Node *node = (Node *) lfirst(lc);
+ double itemrows;
+
+ itemrows = expression_returns_set_rows(node);
+ if (tlist_rows < itemrows)
+ tlist_rows = itemrows;
+ }
+
+ /*
+ * In addition to the cost of evaluating the tlist, charge cpu_tuple_cost
+ * per input row, and half of cpu_tuple_cost for each added output row.
+ * This is slightly bizarre maybe, but it's what 9.6 did; we may revisit
+ * this estimate later.
+ */
+ pathnode->path.rows = subpath->rows * tlist_rows;
+ pathnode->path.startup_cost = subpath->startup_cost +
+ target->cost.startup;
+ pathnode->path.total_cost = subpath->total_cost +
+ target->cost.startup +
+ (cpu_tuple_cost + target->cost.per_tuple) * subpath->rows +
+ (pathnode->path.rows - subpath->rows) * cpu_tuple_cost / 2;
+
+ return pathnode;
+}
+
+/*
* create_sort_path
* Creates a pathnode that represents performing an explicit sort.
*
@@ -3999,10 +4182,9 @@ create_agg_path(PlannerInfo *root,
* 'subpath' is the path representing the source of data
* 'target' is the PathTarget to be computed
* 'having_qual' is the HAVING quals if any
- * 'rollup_lists' is a list of grouping sets
- * 'rollup_groupclauses' is a list of grouping clauses for grouping sets
+ * 'rollups' is a list of RollupData nodes
* 'agg_costs' contains cost info about the aggregate functions to be computed
- * 'numGroups' is the estimated number of groups
+ * 'numGroups' is the estimated total number of groups
*/
GroupingSetsPath *
create_groupingsets_path(PlannerInfo *root,
@@ -4010,13 +4192,15 @@ create_groupingsets_path(PlannerInfo *root,
Path *subpath,
PathTarget *target,
List *having_qual,
- List *rollup_lists,
- List *rollup_groupclauses,
+ AggStrategy aggstrategy,
+ List *rollups,
const AggClauseCosts *agg_costs,
double numGroups)
{
GroupingSetsPath *pathnode = makeNode(GroupingSetsPath);
- int numGroupCols;
+ ListCell *lc;
+ bool is_first = true;
+ bool is_first_sort = true;
/* The topmost generated Plan node will be an Agg */
pathnode->path.pathtype = T_Agg;
@@ -4033,74 +4217,109 @@ create_groupingsets_path(PlannerInfo *root,
pathnode->path.distribution = (Distribution *) copyObject(subpath->distribution);
/*
+ * Simplify callers by downgrading AGG_SORTED to AGG_PLAIN, and AGG_MIXED
+ * to AGG_HASHED, here if possible.
+ */
+ if (aggstrategy == AGG_SORTED &&
+ list_length(rollups) == 1 &&
+ ((RollupData *) linitial(rollups))->groupClause == NIL)
+ aggstrategy = AGG_PLAIN;
+
+ if (aggstrategy == AGG_MIXED &&
+ list_length(rollups) == 1)
+ aggstrategy = AGG_HASHED;
+
+ /*
* Output will be in sorted order by group_pathkeys if, and only if, there
* is a single rollup operation on a non-empty list of grouping
* expressions.
*/
- if (list_length(rollup_groupclauses) == 1 &&
- ((List *) linitial(rollup_groupclauses)) != NIL)
+ if (aggstrategy == AGG_SORTED && list_length(rollups) == 1)
pathnode->path.pathkeys = root->group_pathkeys;
else
pathnode->path.pathkeys = NIL;
- pathnode->rollup_groupclauses = rollup_groupclauses;
- pathnode->rollup_lists = rollup_lists;
+ pathnode->aggstrategy = aggstrategy;
+ pathnode->rollups = rollups;
pathnode->qual = having_qual;
- Assert(rollup_lists != NIL);
- Assert(list_length(rollup_lists) == list_length(rollup_groupclauses));
-
- /* Account for cost of the topmost Agg node */
- numGroupCols = list_length((List *) linitial((List *) llast(rollup_lists)));
-
- cost_agg(&pathnode->path, root,
- (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
- agg_costs,
- numGroupCols,
- numGroups,
- subpath->startup_cost,
- subpath->total_cost,
- subpath->rows);
+ Assert(rollups != NIL);
+ Assert(aggstrategy != AGG_PLAIN || list_length(rollups) == 1);
+ Assert(aggstrategy != AGG_MIXED || list_length(rollups) > 1);
- /*
- * Add in the costs and output rows of the additional sorting/aggregation
- * steps, if any. Only total costs count, since the extra sorts aren't
- * run on startup.
- */
- if (list_length(rollup_lists) > 1)
+ foreach(lc, rollups)
{
- ListCell *lc;
+ RollupData *rollup = lfirst(lc);
+ List *gsets = rollup->gsets;
+ int numGroupCols = list_length(linitial(gsets));
- foreach(lc, rollup_lists)
+ /*
+ * In AGG_SORTED or AGG_PLAIN mode, the first rollup takes the
+ * (already-sorted) input, and following ones do their own sort.
+ *
+ * In AGG_HASHED mode, there is one rollup for each grouping set.
+ *
+ * In AGG_MIXED mode, the first rollups are hashed, the first
+ * non-hashed one takes the (already-sorted) input, and following ones
+ * do their own sort.
+ */
+ if (is_first)
+ {
+ cost_agg(&pathnode->path, root,
+ aggstrategy,
+ agg_costs,
+ numGroupCols,
+ rollup->numGroups,
+ subpath->startup_cost,
+ subpath->total_cost,
+ subpath->rows);
+ is_first = false;
+ if (!rollup->is_hashed)
+ is_first_sort = false;
+ }
+ else
{
- List *gsets = (List *) lfirst(lc);
Path sort_path; /* dummy for result of cost_sort */
Path agg_path; /* dummy for result of cost_agg */
- /* We must iterate over all but the last rollup_lists element */
- if (lnext(lc) == NULL)
- break;
-
- /* Account for cost of sort, but don't charge input cost again */
- cost_sort(&sort_path, root, NIL,
- 0.0,
- subpath->rows,
- subpath->pathtarget->width,
- 0.0,
- work_mem,
- -1.0);
-
- /* Account for cost of aggregation */
- numGroupCols = list_length((List *) linitial(gsets));
-
- cost_agg(&agg_path, root,
- AGG_SORTED,
- agg_costs,
- numGroupCols,
- numGroups, /* XXX surely not right for all steps? */
- sort_path.startup_cost,
- sort_path.total_cost,
- sort_path.rows);
+ if (rollup->is_hashed || is_first_sort)
+ {
+ /*
+ * Account for cost of aggregation, but don't charge input
+ * cost again
+ */
+ cost_agg(&agg_path, root,
+ rollup->is_hashed ? AGG_HASHED : AGG_SORTED,
+ agg_costs,
+ numGroupCols,
+ rollup->numGroups,
+ 0.0, 0.0,
+ subpath->rows);
+ if (!rollup->is_hashed)
+ is_first_sort = false;
+ }
+ else
+ {
+ /* Account for cost of sort, but don't charge input cost again */
+ cost_sort(&sort_path, root, NIL,
+ 0.0,
+ subpath->rows,
+ subpath->pathtarget->width,
+ 0.0,
+ work_mem,
+ -1.0);
+
+ /* Account for cost of aggregation */
+
+ cost_agg(&agg_path, root,
+ AGG_SORTED,
+ agg_costs,
+ numGroupCols,
+ rollup->numGroups,
+ sort_path.startup_cost,
+ sort_path.total_cost,
+ sort_path.rows);
+ }
pathnode->path.total_cost += agg_path.total_cost;
pathnode->path.rows += agg_path.rows;
@@ -4430,7 +4649,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
ModifyTablePath *
create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
CmdType operation, bool canSetTag,
- Index nominalRelation,
+ Index nominalRelation, List *partitioned_rels,
List *resultRelations, List *subpaths,
List *subroots,
List *withCheckOptionLists, List *returningLists,
@@ -4497,6 +4716,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->operation = operation;
pathnode->canSetTag = canSetTag;
pathnode->nominalRelation = nominalRelation;
+ pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->resultRelations = resultRelations;
pathnode->subpaths = subpaths;
pathnode->subroots = subroots;
@@ -4658,7 +4878,7 @@ reparameterize_path(PlannerInfo *root, Path *path,
memcpy(newpath, ipath, sizeof(IndexPath));
newpath->path.param_info =
get_baserel_parampathinfo(root, rel, required_outer);
- cost_index(newpath, root, loop_count);
+ cost_index(newpath, root, loop_count, false);
return (Path *) newpath;
}
case T_BitmapHeapScan:
@@ -4669,7 +4889,7 @@ reparameterize_path(PlannerInfo *root, Path *path,
rel,
bpath->bitmapqual,
required_outer,
- loop_count);
+ loop_count, 0);
}
case T_SubqueryScan:
#ifdef XCP
diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c
index b210914b85..698a387ac2 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -4,7 +4,7 @@
* PlaceHolderVar and PlaceHolderInfo manipulation routines
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 2b50919b10..aa8f6cf020 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -5,7 +5,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -28,7 +28,9 @@
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/heap.h"
+#include "catalog/partition.h"
#include "catalog/pg_am.h"
+#include "catalog/pg_statistic_ext.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
@@ -40,8 +42,11 @@
#include "parser/parse_relation.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
+#include "statistics/statistics.h"
#include "storage/bufmgr.h"
+#include "utils/builtins.h"
#include "utils/lsyscache.h"
+#include "utils/syscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#ifdef PGXC
@@ -56,7 +61,7 @@ get_relation_info_hook_type get_relation_info_hook = NULL;
static void get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel,
- Relation relation);
+ Relation relation, bool inhparent);
static bool infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
List *idxExprs);
static int32 get_rel_data_width(Relation rel, int32 *attr_widths);
@@ -65,7 +70,7 @@ static List *get_relation_constraints(PlannerInfo *root,
bool include_notnull);
static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
Relation heapRelation);
-
+static List *get_relation_statistics(RelOptInfo *rel, Relation relation);
/*
* get_relation_info -
@@ -77,10 +82,12 @@ static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
* min_attr lowest valid AttrNumber
* max_attr highest valid AttrNumber
* indexlist list of IndexOptInfos for relation's indexes
+ * statlist list of StatisticExtInfo for relation's statistic objects
* serverid if it's a foreign table, the server OID
* fdwroutine if it's a foreign table, the FDW function pointers
* pages number of pages
* tuples number of tuples
+ * rel_parallel_workers user-defined number of parallel workers
*
* Also, add information about the relation's foreign keys to root->fkey_list.
*
@@ -242,6 +249,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->amoptionalkey = amroutine->amoptionalkey;
info->amsearcharray = amroutine->amsearcharray;
info->amsearchnulls = amroutine->amsearchnulls;
+ info->amcanparallel = amroutine->amcanparallel;
info->amhasgettuple = (amroutine->amgettuple != NULL);
info->amhasgetbitmap = (amroutine->amgetbitmap != NULL);
info->amcostestimate = amroutine->amcostestimate;
@@ -408,6 +416,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
rel->indexlist = indexinfos;
+ rel->statlist = get_relation_statistics(rel, relation);
+
/* Grab foreign-table info using the relcache, while we have it */
if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
{
@@ -421,7 +431,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
}
/* Collect info about relation's foreign keys, if relevant */
- get_relation_foreign_keys(root, rel, relation);
+ get_relation_foreign_keys(root, rel, relation, inhparent);
heap_close(relation, NoLock);
@@ -446,7 +456,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
*/
static void
get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel,
- Relation relation)
+ Relation relation, bool inhparent)
{
List *rtable = root->parse->rtable;
List *cachedfkeys;
@@ -462,6 +472,15 @@ get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel,
return;
/*
+ * If it's the parent of an inheritance tree, ignore its FKs. We could
+ * make useful FK-based deductions if we found that all members of the
+ * inheritance tree have equivalent FK constraints, but detecting that
+ * would require code that hasn't been written.
+ */
+ if (inhparent)
+ return;
+
+ /*
* Extract data about relation's FKs from the relcache. Note that this
* list belongs to the relcache and might disappear in a cache flush, so
* we must not do any further catalog access within this function.
@@ -501,6 +520,9 @@ get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel,
if (rte->rtekind != RTE_RELATION ||
rte->relid != cachedfk->confrelid)
continue;
+ /* Ignore if it's an inheritance parent; doesn't really match */
+ if (rte->inh)
+ continue;
/* Ignore self-referential FKs; we only care about joins */
if (rti == rel->relid)
continue;
@@ -1152,6 +1174,7 @@ get_relation_constraints(PlannerInfo *root,
Index varno = rel->relid;
Relation relation;
TupleConstr *constr;
+ List *pcqual;
/*
* We assume the relation has already been safely locked.
@@ -1237,11 +1260,100 @@ get_relation_constraints(PlannerInfo *root,
}
}
+ /* Append partition predicates, if any */
+ pcqual = RelationGetPartitionQual(relation);
+ if (pcqual)
+ {
+ /*
+ * Run each expression through const-simplification and
+ * canonicalization similar to check constraints.
+ */
+ pcqual = (List *) eval_const_expressions(root, (Node *) pcqual);
+ pcqual = (List *) canonicalize_qual((Expr *) pcqual);
+
+ /* Fix Vars to have the desired varno */
+ if (varno != 1)
+ ChangeVarNodes((Node *) pcqual, 1, varno, 0);
+
+ result = list_concat(result, pcqual);
+ }
+
heap_close(relation, NoLock);
return result;
}
+/*
+ * get_relation_statistics
+ * Retrieve extended statistics defined on the table.
+ *
+ * Returns a List (possibly empty) of StatisticExtInfo objects describing
+ * the statistics. Note that this doesn't load the actual statistics data,
+ * just the identifying metadata. Only stats actually built are considered.
+ */
+static List *
+get_relation_statistics(RelOptInfo *rel, Relation relation)
+{
+ List *statoidlist;
+ List *stainfos = NIL;
+ ListCell *l;
+
+ statoidlist = RelationGetStatExtList(relation);
+
+ foreach(l, statoidlist)
+ {
+ Oid statOid = lfirst_oid(l);
+ Form_pg_statistic_ext staForm;
+ HeapTuple htup;
+ Bitmapset *keys = NULL;
+ int i;
+
+ htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statOid));
+ if (!htup)
+ elog(ERROR, "cache lookup failed for statistics object %u", statOid);
+ staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
+
+ /*
+ * First, build the array of columns covered. This is ultimately
+ * wasted if no stats within the object have actually been built, but
+ * it doesn't seem worth troubling over that case.
+ */
+ for (i = 0; i < staForm->stxkeys.dim1; i++)
+ keys = bms_add_member(keys, staForm->stxkeys.values[i]);
+
+ /* add one StatisticExtInfo for each kind built */
+ if (statext_is_kind_built(htup, STATS_EXT_NDISTINCT))
+ {
+ StatisticExtInfo *info = makeNode(StatisticExtInfo);
+
+ info->statOid = statOid;
+ info->rel = rel;
+ info->kind = STATS_EXT_NDISTINCT;
+ info->keys = bms_copy(keys);
+
+ stainfos = lcons(info, stainfos);
+ }
+
+ if (statext_is_kind_built(htup, STATS_EXT_DEPENDENCIES))
+ {
+ StatisticExtInfo *info = makeNode(StatisticExtInfo);
+
+ info->statOid = statOid;
+ info->rel = rel;
+ info->kind = STATS_EXT_DEPENDENCIES;
+ info->keys = bms_copy(keys);
+
+ stainfos = lcons(info, stainfos);
+ }
+
+ ReleaseSysCache(htup);
+ bms_free(keys);
+ }
+
+ list_free(statoidlist);
+
+ return stainfos;
+}
/*
* relation_excluded_by_constraints
@@ -1263,6 +1375,9 @@ relation_excluded_by_constraints(PlannerInfo *root,
List *safe_constraints;
ListCell *lc;
+ /* As of now, constraint exclusion works only with simple relations. */
+ Assert(IS_SIMPLE_REL(rel));
+
/*
* Regardless of the setting of constraint_exclusion, detect
* constant-FALSE-or-NULL restriction clauses. Because const-folding will
@@ -1372,8 +1487,9 @@ relation_excluded_by_constraints(PlannerInfo *root,
* dropped cols.
*
* We also support building a "physical" tlist for subqueries, functions,
- * values lists, and CTEs, since the same optimization can occur in
- * SubqueryScan, FunctionScan, ValuesScan, CteScan, and WorkTableScan nodes.
+ * values lists, table expressions, and CTEs, since the same optimization can
+ * occur in SubqueryScan, FunctionScan, ValuesScan, CteScan, TableFunc,
+ * NamedTuplestoreScan, and WorkTableScan nodes.
*/
List *
build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
@@ -1445,8 +1561,10 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
break;
case RTE_FUNCTION:
+ case RTE_TABLEFUNC:
case RTE_VALUES:
case RTE_CTE:
+ case RTE_NAMEDTUPLESTORE:
/* Not all of these can have dropped cols, but share code anyway */
expandRTE(rte, varno, 0, -1, true /* include dropped */ ,
NULL, &colvars);
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 2c2efb1576..c4a04cfa95 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -4,7 +4,7 @@
* Routines to attempt to prove logical implications between predicate
* expressions.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -1596,7 +1596,7 @@ operator_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
/* And execute it. */
test_result = ExecEvalExprSwitchContext(test_exprstate,
GetPerTupleExprContext(estate),
- &isNull, NULL);
+ &isNull);
/* Get back to outer memory context */
MemoryContextSwitchTo(oldcontext);
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index bdc8a5134c..3ab5ceb7d3 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -3,7 +3,7 @@
* relnode.c
* Relation-node lookup/construction routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -14,6 +14,8 @@
*/
#include "postgres.h"
+#include <limits.h>
+
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
@@ -50,6 +52,9 @@ static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
List *joininfo_list,
List *new_joininfo);
+static void set_foreign_rel_properties(RelOptInfo *joinrel,
+ RelOptInfo *outer_rel, RelOptInfo *inner_rel);
+static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
/*
@@ -86,7 +91,7 @@ setup_simple_rel_arrays(PlannerInfo *root)
* Construct a new RelOptInfo for a base relation or 'other' relation.
*/
RelOptInfo *
-build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
+build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
{
RelOptInfo *rel;
RangeTblEntry *rte;
@@ -101,7 +106,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
Assert(rte != NULL);
rel = makeNode(RelOptInfo);
- rel->reloptkind = reloptkind;
+ rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL;
rel->relids = bms_make_singleton(relid);
rel->rows = 0;
/* cheap startup cost is interesting iff not all tuples to be retrieved */
@@ -124,23 +129,43 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
rel->lateral_vars = NIL;
rel->lateral_referencers = NULL;
rel->indexlist = NIL;
+ rel->statlist = NIL;
rel->pages = 0;
rel->tuples = 0;
rel->allvisfrac = 0;
rel->subroot = NULL;
rel->subplan_params = NIL;
- rel->rel_parallel_workers = -1; /* set up in GetRelationInfo */
+ rel->rel_parallel_workers = -1; /* set up in get_relation_info */
rel->serverid = InvalidOid;
rel->userid = rte->checkAsUser;
rel->useridiscurrent = false;
rel->fdwroutine = NULL;
rel->fdw_private = NULL;
+ rel->unique_for_rels = NIL;
+ rel->non_unique_for_rels = NIL;
rel->baserestrictinfo = NIL;
rel->baserestrictcost.startup = 0;
rel->baserestrictcost.per_tuple = 0;
+ rel->baserestrict_min_security = UINT_MAX;
rel->joininfo = NIL;
rel->has_eclass_joins = false;
+ /*
+ * Pass top parent's relids down the inheritance hierarchy. If the parent
+ * has top_parent_relids set, it's a direct or an indirect child of the
+ * top parent indicated by top_parent_relids. By extension this child is
+ * also an indirect child of that parent.
+ */
+ if (parent)
+ {
+ if (parent->top_parent_relids)
+ rel->top_parent_relids = parent->top_parent_relids;
+ else
+ rel->top_parent_relids = bms_copy(parent->relids);
+ }
+ else
+ rel->top_parent_relids = NULL;
+
/* Check type of rtable entry */
switch (rte->rtekind)
{
@@ -150,12 +175,14 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
break;
case RTE_SUBQUERY:
case RTE_FUNCTION:
+ case RTE_TABLEFUNC:
case RTE_VALUES:
case RTE_CTE:
+ case RTE_NAMEDTUPLESTORE:
/*
- * Subquery, function, or values list --- set up attr range and
- * arrays
+ * Subquery, function, tablefunc, or values list --- set up attr
+ * range and arrays
*
* Note: 0 is included in range to support whole-row Vars
*/
@@ -176,6 +203,16 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
root->simple_rel_array[relid] = rel;
/*
+ * This is a convenient spot at which to note whether rels participating
+ * in the query have any securityQuals attached. If so, increase
+ * root->qual_security_level to ensure it's larger than the maximum
+ * security level needed for securityQuals.
+ */
+ if (rte->securityQuals)
+ root->qual_security_level = Max(root->qual_security_level,
+ list_length(rte->securityQuals));
+
+ /*
* If this rel is an appendrel parent, recurse to build "other rel"
* RelOptInfos for its children. They are "other rels" because they are
* not in the main join tree, but we will need RelOptInfos to plan access
@@ -194,7 +231,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
continue;
(void) build_simple_rel(root, appinfo->child_relid,
- RELOPT_OTHER_MEMBER_REL);
+ rel);
}
}
@@ -317,6 +354,82 @@ find_join_rel(PlannerInfo *root, Relids relids)
}
/*
+ * set_foreign_rel_properties
+ * Set up foreign-join fields if outer and inner relation are foreign
+ * tables (or joins) belonging to the same server and assigned to the same
+ * user to check access permissions as.
+ *
+ * In addition to an exact match of userid, we allow the case where one side
+ * has zero userid (implying current user) and the other side has explicit
+ * userid that happens to equal the current user; but in that case, pushdown of
+ * the join is only valid for the current user. The useridiscurrent field
+ * records whether we had to make such an assumption for this join or any
+ * sub-join.
+ *
+ * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
+ * called for the join relation.
+ *
+ */
+static void
+set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel)
+{
+ if (OidIsValid(outer_rel->serverid) &&
+ inner_rel->serverid == outer_rel->serverid)
+ {
+ if (inner_rel->userid == outer_rel->userid)
+ {
+ joinrel->serverid = outer_rel->serverid;
+ joinrel->userid = outer_rel->userid;
+ joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
+ joinrel->fdwroutine = outer_rel->fdwroutine;
+ }
+ else if (!OidIsValid(inner_rel->userid) &&
+ outer_rel->userid == GetUserId())
+ {
+ joinrel->serverid = outer_rel->serverid;
+ joinrel->userid = outer_rel->userid;
+ joinrel->useridiscurrent = true;
+ joinrel->fdwroutine = outer_rel->fdwroutine;
+ }
+ else if (!OidIsValid(outer_rel->userid) &&
+ inner_rel->userid == GetUserId())
+ {
+ joinrel->serverid = outer_rel->serverid;
+ joinrel->userid = inner_rel->userid;
+ joinrel->useridiscurrent = true;
+ joinrel->fdwroutine = outer_rel->fdwroutine;
+ }
+ }
+}
+
+/*
+ * add_join_rel
+ * Add given join relation to the list of join relations in the given
+ * PlannerInfo. Also add it to the auxiliary hashtable if there is one.
+ */
+static void
+add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
+{
+ /* GEQO requires us to append the new joinrel to the end of the list! */
+ root->join_rel_list = lappend(root->join_rel_list, joinrel);
+
+ /* store it into the auxiliary hashtable if there is one. */
+ if (root->join_rel_hash)
+ {
+ JoinHashEntry *hentry;
+ bool found;
+
+ hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
+ &(joinrel->relids),
+ HASH_ENTER,
+ &found);
+ Assert(!found);
+ hentry->join_rel = joinrel;
+ }
+}
+
+/*
* build_join_rel
* Returns relation entry corresponding to the union of two given rels,
* creating a new relation entry if none already exists.
@@ -396,6 +509,7 @@ build_join_rel(PlannerInfo *root,
joinrel->lateral_vars = NIL;
joinrel->lateral_referencers = NULL;
joinrel->indexlist = NIL;
+ joinrel->statlist = NIL;
joinrel->pages = 0;
joinrel->tuples = 0;
joinrel->allvisfrac = 0;
@@ -407,52 +521,18 @@ build_join_rel(PlannerInfo *root,
joinrel->useridiscurrent = false;
joinrel->fdwroutine = NULL;
joinrel->fdw_private = NULL;
+ joinrel->unique_for_rels = NIL;
+ joinrel->non_unique_for_rels = NIL;
joinrel->baserestrictinfo = NIL;
joinrel->baserestrictcost.startup = 0;
joinrel->baserestrictcost.per_tuple = 0;
+ joinrel->baserestrict_min_security = UINT_MAX;
joinrel->joininfo = NIL;
joinrel->has_eclass_joins = false;
+ joinrel->top_parent_relids = NULL;
- /*
- * Set up foreign-join fields if outer and inner relation are foreign
- * tables (or joins) belonging to the same server and assigned to the same
- * user to check access permissions as. In addition to an exact match of
- * userid, we allow the case where one side has zero userid (implying
- * current user) and the other side has explicit userid that happens to
- * equal the current user; but in that case, pushdown of the join is only
- * valid for the current user. The useridiscurrent field records whether
- * we had to make such an assumption for this join or any sub-join.
- *
- * Otherwise these fields are left invalid, so GetForeignJoinPaths will
- * not be called for the join relation.
- */
- if (OidIsValid(outer_rel->serverid) &&
- inner_rel->serverid == outer_rel->serverid)
- {
- if (inner_rel->userid == outer_rel->userid)
- {
- joinrel->serverid = outer_rel->serverid;
- joinrel->userid = outer_rel->userid;
- joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
- joinrel->fdwroutine = outer_rel->fdwroutine;
- }
- else if (!OidIsValid(inner_rel->userid) &&
- outer_rel->userid == GetUserId())
- {
- joinrel->serverid = outer_rel->serverid;
- joinrel->userid = outer_rel->userid;
- joinrel->useridiscurrent = true;
- joinrel->fdwroutine = outer_rel->fdwroutine;
- }
- else if (!OidIsValid(outer_rel->userid) &&
- inner_rel->userid == GetUserId())
- {
- joinrel->serverid = outer_rel->serverid;
- joinrel->userid = inner_rel->userid;
- joinrel->useridiscurrent = true;
- joinrel->fdwroutine = outer_rel->fdwroutine;
- }
- }
+ /* Compute information relevant to the foreign relations. */
+ set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
/*
* Create a new tlist containing just the vars that need to be output from
@@ -516,29 +596,12 @@ build_join_rel(PlannerInfo *root,
* here.
*/
if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
- !has_parallel_hazard((Node *) restrictlist, false) &&
- !has_parallel_hazard((Node *) joinrel->reltarget->exprs, false))
+ is_parallel_safe(root, (Node *) restrictlist) &&
+ is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
joinrel->consider_parallel = true;
- /*
- * Add the joinrel to the query's joinrel list, and store it into the
- * auxiliary hashtable if there is one. NB: GEQO requires us to append
- * the new joinrel to the end of the list!
- */
- root->join_rel_list = lappend(root->join_rel_list, joinrel);
-
- if (root->join_rel_hash)
- {
- JoinHashEntry *hentry;
- bool found;
-
- hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
- &(joinrel->relids),
- HASH_ENTER,
- &found);
- Assert(!found);
- hentry->join_rel = joinrel;
- }
+ /* Add the joinrel to the PlannerInfo. */
+ add_join_rel(root, joinrel);
/*
* Also, if dynamic-programming join search is active, add the new joinrel
@@ -929,32 +992,6 @@ find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
/*
- * find_childrel_top_parent
- * Fetch the topmost appendrel parent rel of an appendrel child rel.
- *
- * Since appendrels can be nested, a child could have multiple levels of
- * appendrel ancestors. This function locates the topmost ancestor,
- * which will be a regular baserel not an otherrel.
- */
-RelOptInfo *
-find_childrel_top_parent(PlannerInfo *root, RelOptInfo *rel)
-{
- do
- {
- AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
- Index prelid = appinfo->parent_relid;
-
- /* traverse up to the parent rel, loop if it's also a child rel */
- rel = find_base_rel(root, prelid);
- } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
-
- Assert(rel->reloptkind == RELOPT_BASEREL);
-
- return rel;
-}
-
-
-/*
* find_childrel_parents
* Compute the set of parent relids of an appendrel child rel.
*
@@ -967,6 +1004,8 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
{
Relids result = NULL;
+ Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
+
do
{
AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index 7fc81e7aa3..e946290af5 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -3,7 +3,7 @@
* restrictinfo.c
* RestrictInfo node manipulation routines.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -24,6 +24,7 @@ static RestrictInfo *make_restrictinfo_internal(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
bool pseudoconstant,
+ Index security_level,
Relids required_relids,
Relids outer_relids,
Relids nullable_relids);
@@ -31,6 +32,7 @@ static Expr *make_sub_restrictinfos(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
bool pseudoconstant,
+ Index security_level,
Relids required_relids,
Relids outer_relids,
Relids nullable_relids);
@@ -43,7 +45,7 @@ static Expr *make_sub_restrictinfos(Expr *clause,
*
* The is_pushed_down, outerjoin_delayed, and pseudoconstant flags for the
* RestrictInfo must be supplied by the caller, as well as the correct values
- * for outer_relids and nullable_relids.
+ * for security_level, outer_relids, and nullable_relids.
* required_relids can be NULL, in which case it defaults to the actual clause
* contents (i.e., clause_relids).
*
@@ -56,6 +58,7 @@ make_restrictinfo(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
bool pseudoconstant,
+ Index security_level,
Relids required_relids,
Relids outer_relids,
Relids nullable_relids)
@@ -69,6 +72,7 @@ make_restrictinfo(Expr *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
required_relids,
outer_relids,
nullable_relids);
@@ -81,65 +85,13 @@ make_restrictinfo(Expr *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
required_relids,
outer_relids,
nullable_relids);
}
/*
- * make_restrictinfos_from_actual_clauses
- *
- * Given a list of implicitly-ANDed restriction clauses, produce a list
- * of RestrictInfo nodes. This is used to reconstitute the RestrictInfo
- * representation after doing transformations of a list of clauses.
- *
- * We assume that the clauses are relation-level restrictions and therefore
- * we don't have to worry about is_pushed_down, outerjoin_delayed,
- * outer_relids, and nullable_relids (these can be assumed true, false,
- * NULL, and NULL, respectively).
- * We do take care to recognize pseudoconstant clauses properly.
- */
-List *
-make_restrictinfos_from_actual_clauses(PlannerInfo *root,
- List *clause_list)
-{
- List *result = NIL;
- ListCell *l;
-
- foreach(l, clause_list)
- {
- Expr *clause = (Expr *) lfirst(l);
- bool pseudoconstant;
- RestrictInfo *rinfo;
-
- /*
- * It's pseudoconstant if it contains no Vars and no volatile
- * functions. We probably can't see any sublinks here, so
- * contain_var_clause() would likely be enough, but for safety use
- * contain_vars_of_level() instead.
- */
- pseudoconstant =
- !contain_vars_of_level((Node *) clause, 0) &&
- !contain_volatile_functions((Node *) clause);
- if (pseudoconstant)
- {
- /* tell createplan.c to check for gating quals */
- root->hasPseudoConstantQuals = true;
- }
-
- rinfo = make_restrictinfo(clause,
- true,
- false,
- pseudoconstant,
- NULL,
- NULL,
- NULL);
- result = lappend(result, rinfo);
- }
- return result;
-}
-
-/*
* make_restrictinfo_internal
*
* Common code for the main entry points and the recursive cases.
@@ -150,6 +102,7 @@ make_restrictinfo_internal(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
bool pseudoconstant,
+ Index security_level,
Relids required_relids,
Relids outer_relids,
Relids nullable_relids)
@@ -162,10 +115,21 @@ make_restrictinfo_internal(Expr *clause,
restrictinfo->outerjoin_delayed = outerjoin_delayed;
restrictinfo->pseudoconstant = pseudoconstant;
restrictinfo->can_join = false; /* may get set below */
+ restrictinfo->security_level = security_level;
restrictinfo->outer_relids = outer_relids;
restrictinfo->nullable_relids = nullable_relids;
/*
+ * If it's potentially delayable by lower-level security quals, figure out
+ * whether it's leakproof. We can skip testing this for level-zero quals,
+ * since they would never get delayed on security grounds anyway.
+ */
+ if (security_level > 0)
+ restrictinfo->leakproof = !contain_leaked_vars((Node *) clause);
+ else
+ restrictinfo->leakproof = false; /* really, "don't know" */
+
+ /*
* If it's a binary opclause, set up left/right relids info. In any case
* set up the total clause relids info.
*/
@@ -250,7 +214,7 @@ make_restrictinfo_internal(Expr *clause,
*
* The same is_pushed_down, outerjoin_delayed, and pseudoconstant flag
* values can be applied to all RestrictInfo nodes in the result. Likewise
- * for outer_relids and nullable_relids.
+ * for security_level, outer_relids, and nullable_relids.
*
* The given required_relids are attached to our top-level output,
* but any OR-clause constituents are allowed to default to just the
@@ -261,6 +225,7 @@ make_sub_restrictinfos(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
bool pseudoconstant,
+ Index security_level,
Relids required_relids,
Relids outer_relids,
Relids nullable_relids)
@@ -276,6 +241,7 @@ make_sub_restrictinfos(Expr *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
NULL,
outer_relids,
nullable_relids));
@@ -284,6 +250,7 @@ make_sub_restrictinfos(Expr *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
required_relids,
outer_relids,
nullable_relids);
@@ -299,6 +266,7 @@ make_sub_restrictinfos(Expr *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
required_relids,
outer_relids,
nullable_relids));
@@ -310,6 +278,7 @@ make_sub_restrictinfos(Expr *clause,
is_pushed_down,
outerjoin_delayed,
pseudoconstant,
+ security_level,
required_relids,
outer_relids,
nullable_relids);
@@ -330,51 +299,45 @@ restriction_is_or_clause(RestrictInfo *restrictinfo)
}
/*
- * get_actual_clauses
+ * restriction_is_securely_promotable
*
- * Returns a list containing the bare clauses from 'restrictinfo_list'.
- *
- * This is only to be used in cases where none of the RestrictInfos can
- * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
+ * Returns true if it's okay to evaluate this clause "early", that is before
+ * other restriction clauses attached to the specified relation.
*/
-List *
-get_actual_clauses(List *restrictinfo_list)
+bool
+restriction_is_securely_promotable(RestrictInfo *restrictinfo,
+ RelOptInfo *rel)
{
- List *result = NIL;
- ListCell *l;
-
- foreach(l, restrictinfo_list)
- {
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
-
- Assert(IsA(rinfo, RestrictInfo));
-
- Assert(!rinfo->pseudoconstant);
-
- result = lappend(result, rinfo->clause);
- }
- return result;
+ /*
+ * It's okay if there are no baserestrictinfo clauses for the rel that
+ * would need to go before this one, *or* if this one is leakproof.
+ */
+ if (restrictinfo->security_level <= rel->baserestrict_min_security ||
+ restrictinfo->leakproof)
+ return true;
+ else
+ return false;
}
/*
- * get_all_actual_clauses
+ * get_actual_clauses
*
* Returns a list containing the bare clauses from 'restrictinfo_list'.
*
- * This loses the distinction between regular and pseudoconstant clauses,
- * so be careful what you use it for.
+ * This is only to be used in cases where none of the RestrictInfos can
+ * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
*/
List *
-get_all_actual_clauses(List *restrictinfo_list)
+get_actual_clauses(List *restrictinfo_list)
{
List *result = NIL;
ListCell *l;
foreach(l, restrictinfo_list)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
- Assert(IsA(rinfo, RestrictInfo));
+ Assert(!rinfo->pseudoconstant);
result = lappend(result, rinfo->clause);
}
@@ -396,9 +359,7 @@ extract_actual_clauses(List *restrictinfo_list,
foreach(l, restrictinfo_list)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
-
- Assert(IsA(rinfo, RestrictInfo));
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
if (rinfo->pseudoconstant == pseudoconstant)
result = lappend(result, rinfo->clause);
@@ -428,9 +389,7 @@ extract_actual_join_clauses(List *restrictinfo_list,
foreach(l, restrictinfo_list)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
-
- Assert(IsA(rinfo, RestrictInfo));
+ RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
if (rinfo->is_pushed_down)
{
@@ -550,7 +509,7 @@ join_clause_is_movable_into(RestrictInfo *rinfo,
Relids currentrelids,
Relids current_and_outer)
{
- /* Clause must be evaluatable given available context */
+ /* Clause must be evaluable given available context */
if (!bms_is_subset(rinfo->clause_relids, current_and_outer))
return false;
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 68096b309c..09523853d0 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -3,7 +3,7 @@
* tlist.c
* Target list manipulation routines
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -16,9 +16,31 @@
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
+#include "optimizer/cost.h"
#include "optimizer/tlist.h"
+/* Test if an expression node represents a SRF call. Beware multiple eval! */
+#define IS_SRF_CALL(node) \
+ ((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
+ (IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
+
+/* Workspace for split_pathtarget_walker */
+typedef struct
+{
+ List *input_target_exprs; /* exprs available from input */
+ List *level_srfs; /* list of lists of SRF exprs */
+ List *level_input_vars; /* vars needed by SRFs of each level */
+ List *level_input_srfs; /* SRFs needed by SRFs of each level */
+ List *current_input_vars; /* vars needed in current subexpr */
+ List *current_input_srfs; /* SRFs needed in current subexpr */
+ int current_depth; /* max SRF depth in current subexpr */
+} split_pathtarget_context;
+
+static bool split_pathtarget_walker(Node *node,
+ split_pathtarget_context *context);
+
+
/*****************************************************************************
* Target list creation and searching utilities
*****************************************************************************/
@@ -29,7 +51,7 @@
* equal() to the given expression. Result is NULL if no such member.
*/
TargetEntry *
-tlist_member(Node *node, List *targetlist)
+tlist_member(Expr *node, List *targetlist)
{
ListCell *temp;
@@ -50,12 +72,12 @@ tlist_member(Node *node, List *targetlist)
* involving binary-compatible sort operations.
*/
TargetEntry *
-tlist_member_ignore_relabel(Node *node, List *targetlist)
+tlist_member_ignore_relabel(Expr *node, List *targetlist)
{
ListCell *temp;
while (node && IsA(node, RelabelType))
- node = (Node *) ((RelabelType *) node)->arg;
+ node = ((RelabelType *) node)->arg;
foreach(temp, targetlist)
{
@@ -117,7 +139,7 @@ add_to_flat_tlist(List *tlist, List *exprs)
foreach(lc, exprs)
{
- Node *expr = (Node *) lfirst(lc);
+ Expr *expr = (Expr *) lfirst(lc);
if (!tlist_member(expr, tlist))
{
@@ -740,7 +762,7 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
if (expr && IsA(expr, Var))
tle = tlist_member_match_var((Var *) expr, tlist);
else
- tle = tlist_member((Node *) expr, tlist);
+ tle = tlist_member(expr, tlist);
/*
* Complain if noplace for the sortgrouprefs label, or if we'd
@@ -759,3 +781,344 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
i++;
}
}
+
+/*
+ * split_pathtarget_at_srfs
+ * Split given PathTarget into multiple levels to position SRFs safely
+ *
+ * The executor can only handle set-returning functions that appear at the
+ * top level of the targetlist of a ProjectSet plan node. If we have any SRFs
+ * that are not at top level, we need to split up the evaluation into multiple
+ * plan levels in which each level satisfies this constraint. This function
+ * creates appropriate PathTarget(s) for each level.
+ *
+ * As an example, consider the tlist expression
+ * x + srf1(srf2(y + z))
+ * This expression should appear as-is in the top PathTarget, but below that
+ * we must have a PathTarget containing
+ * x, srf1(srf2(y + z))
+ * and below that, another PathTarget containing
+ * x, srf2(y + z)
+ * and below that, another PathTarget containing
+ * x, y, z
+ * When these tlists are processed by setrefs.c, subexpressions that match
+ * output expressions of the next lower tlist will be replaced by Vars,
+ * so that what the executor gets are tlists looking like
+ * Var1 + Var2
+ * Var1, srf1(Var2)
+ * Var1, srf2(Var2 + Var3)
+ * x, y, z
+ * which satisfy the desired property.
+ *
+ * Another example is
+ * srf1(x), srf2(srf3(y))
+ * That must appear as-is in the top PathTarget, but below that we need
+ * srf1(x), srf3(y)
+ * That is, each SRF must be computed at a level corresponding to the nesting
+ * depth of SRFs within its arguments.
+ *
+ * In some cases, a SRF has already been evaluated in some previous plan level
+ * and we shouldn't expand it again (that is, what we see in the target is
+ * already meant as a reference to a lower subexpression). So, don't expand
+ * any tlist expressions that appear in input_target, if that's not NULL.
+ *
+ * The outputs of this function are two parallel lists, one a list of
+ * PathTargets and the other an integer list of bool flags indicating
+ * whether the corresponding PathTarget contains any evaluatable SRFs.
+ * The lists are given in the order they'd need to be evaluated in, with
+ * the "lowest" PathTarget first. So the last list entry is always the
+ * originally given PathTarget, and any entries before it indicate evaluation
+ * levels that must be inserted below it. The first list entry must not
+ * contain any SRFs (other than ones duplicating input_target entries), since
+ * it will typically be attached to a plan node that cannot evaluate SRFs.
+ *
+ * Note: using a list for the flags may seem like overkill, since there
+ * are only a few possible patterns for which levels contain SRFs.
+ * But this representation decouples callers from that knowledge.
+ */
+void
+split_pathtarget_at_srfs(PlannerInfo *root,
+ PathTarget *target, PathTarget *input_target,
+ List **targets, List **targets_contain_srfs)
+{
+ split_pathtarget_context context;
+ int max_depth;
+ bool need_extra_projection;
+ List *prev_level_tlist;
+ ListCell *lc,
+ *lc1,
+ *lc2,
+ *lc3;
+
+ /*
+ * It's not unusual for planner.c to pass us two physically identical
+ * targets, in which case we can conclude without further ado that all
+ * expressions are available from the input. (The logic below would
+ * arrive at the same conclusion, but much more tediously.)
+ */
+ if (target == input_target)
+ {
+ *targets = list_make1(target);
+ *targets_contain_srfs = list_make1_int(false);
+ return;
+ }
+
+ /* Pass any input_target exprs down to split_pathtarget_walker() */
+ context.input_target_exprs = input_target ? input_target->exprs : NIL;
+
+ /*
+ * Initialize with empty level-zero lists, and no levels after that.
+ * (Note: we could dispense with representing level zero explicitly, since
+ * it will never receive any SRFs, but then we'd have to special-case that
+ * level when we get to building result PathTargets. Level zero describes
+ * the SRF-free PathTarget that will be given to the input plan node.)
+ */
+ context.level_srfs = list_make1(NIL);
+ context.level_input_vars = list_make1(NIL);
+ context.level_input_srfs = list_make1(NIL);
+
+ /* Initialize data we'll accumulate across all the target expressions */
+ context.current_input_vars = NIL;
+ context.current_input_srfs = NIL;
+ max_depth = 0;
+ need_extra_projection = false;
+
+ /* Scan each expression in the PathTarget looking for SRFs */
+ foreach(lc, target->exprs)
+ {
+ Node *node = (Node *) lfirst(lc);
+
+ /*
+ * Find all SRFs and Vars (and Var-like nodes) in this expression, and
+ * enter them into appropriate lists within the context struct.
+ */
+ context.current_depth = 0;
+ split_pathtarget_walker(node, &context);
+
+ /* An expression containing no SRFs is of no further interest */
+ if (context.current_depth == 0)
+ continue;
+
+ /*
+ * Track max SRF nesting depth over the whole PathTarget. Also, if
+ * this expression establishes a new max depth, we no longer care
+ * whether previous expressions contained nested SRFs; we can handle
+ * any required projection for them in the final ProjectSet node.
+ */
+ if (max_depth < context.current_depth)
+ {
+ max_depth = context.current_depth;
+ need_extra_projection = false;
+ }
+
+ /*
+ * If any maximum-depth SRF is not at the top level of its expression,
+ * we'll need an extra Result node to compute the top-level scalar
+ * expression.
+ */
+ if (max_depth == context.current_depth && !IS_SRF_CALL(node))
+ need_extra_projection = true;
+ }
+
+ /*
+ * If we found no SRFs needing evaluation (maybe they were all present in
+ * input_target, or maybe they were all removed by const-simplification),
+ * then no ProjectSet is needed; fall out.
+ */
+ if (max_depth == 0)
+ {
+ *targets = list_make1(target);
+ *targets_contain_srfs = list_make1_int(false);
+ return;
+ }
+
+ /*
+ * The Vars and SRF outputs needed at top level can be added to the last
+ * level_input lists if we don't need an extra projection step. If we do
+ * need one, add a SRF-free level to the lists.
+ */
+ if (need_extra_projection)
+ {
+ context.level_srfs = lappend(context.level_srfs, NIL);
+ context.level_input_vars = lappend(context.level_input_vars,
+ context.current_input_vars);
+ context.level_input_srfs = lappend(context.level_input_srfs,
+ context.current_input_srfs);
+ }
+ else
+ {
+ lc = list_nth_cell(context.level_input_vars, max_depth);
+ lfirst(lc) = list_concat(lfirst(lc), context.current_input_vars);
+ lc = list_nth_cell(context.level_input_srfs, max_depth);
+ lfirst(lc) = list_concat(lfirst(lc), context.current_input_srfs);
+ }
+
+ /*
+ * Now construct the output PathTargets. The original target can be used
+ * as-is for the last one, but we need to construct a new SRF-free target
+ * representing what the preceding plan node has to emit, as well as a
+ * target for each intermediate ProjectSet node.
+ */
+ *targets = *targets_contain_srfs = NIL;
+ prev_level_tlist = NIL;
+
+ forthree(lc1, context.level_srfs,
+ lc2, context.level_input_vars,
+ lc3, context.level_input_srfs)
+ {
+ List *level_srfs = (List *) lfirst(lc1);
+ PathTarget *ntarget;
+
+ if (lnext(lc1) == NULL)
+ {
+ ntarget = target;
+ }
+ else
+ {
+ ntarget = create_empty_pathtarget();
+
+ /*
+ * This target should actually evaluate any SRFs of the current
+ * level, and it needs to propagate forward any Vars needed by
+ * later levels, as well as SRFs computed earlier and needed by
+ * later levels. We rely on add_new_columns_to_pathtarget() to
+ * remove duplicate items. Also, for safety, make a separate copy
+ * of each item for each PathTarget.
+ */
+ add_new_columns_to_pathtarget(ntarget, copyObject(level_srfs));
+ for_each_cell(lc, lnext(lc2))
+ {
+ List *input_vars = (List *) lfirst(lc);
+
+ add_new_columns_to_pathtarget(ntarget, copyObject(input_vars));
+ }
+ for_each_cell(lc, lnext(lc3))
+ {
+ List *input_srfs = (List *) lfirst(lc);
+ ListCell *lcx;
+
+ foreach(lcx, input_srfs)
+ {
+ Expr *srf = (Expr *) lfirst(lcx);
+
+ if (list_member(prev_level_tlist, srf))
+ add_new_column_to_pathtarget(ntarget, copyObject(srf));
+ }
+ }
+ set_pathtarget_cost_width(root, ntarget);
+ }
+
+ /*
+ * Add current target and does-it-compute-SRFs flag to output lists.
+ */
+ *targets = lappend(*targets, ntarget);
+ *targets_contain_srfs = lappend_int(*targets_contain_srfs,
+ (level_srfs != NIL));
+
+ /* Remember this level's output for next pass */
+ prev_level_tlist = ntarget->exprs;
+ }
+}
+
+/*
+ * Recursively examine expressions for split_pathtarget_at_srfs.
+ *
+ * Note we make no effort here to prevent duplicate entries in the output
+ * lists. Duplicates will be gotten rid of later.
+ */
+static bool
+split_pathtarget_walker(Node *node, split_pathtarget_context *context)
+{
+ if (node == NULL)
+ return false;
+
+ /*
+ * A subexpression that matches an expression already computed in
+ * input_target can be treated like a Var (which indeed it will be after
+ * setrefs.c gets done with it), even if it's actually a SRF. Record it
+ * as being needed for the current expression, and ignore any
+ * substructure.
+ */
+ if (list_member(context->input_target_exprs, node))
+ {
+ context->current_input_vars = lappend(context->current_input_vars,
+ node);
+ return false;
+ }
+
+ /*
+ * Vars and Var-like constructs are expected to be gotten from the input,
+ * too. We assume that these constructs cannot contain any SRFs (if one
+ * does, there will be an executor failure from a misplaced SRF).
+ */
+ if (IsA(node, Var) ||
+ IsA(node, PlaceHolderVar) ||
+ IsA(node, Aggref) ||
+ IsA(node, GroupingFunc) ||
+ IsA(node, WindowFunc))
+ {
+ context->current_input_vars = lappend(context->current_input_vars,
+ node);
+ return false;
+ }
+
+ /*
+ * If it's a SRF, recursively examine its inputs, determine its level, and
+ * make appropriate entries in the output lists.
+ */
+ if (IS_SRF_CALL(node))
+ {
+ List *save_input_vars = context->current_input_vars;
+ List *save_input_srfs = context->current_input_srfs;
+ int save_current_depth = context->current_depth;
+ int srf_depth;
+ ListCell *lc;
+
+ context->current_input_vars = NIL;
+ context->current_input_srfs = NIL;
+ context->current_depth = 0;
+
+ (void) expression_tree_walker(node, split_pathtarget_walker,
+ (void *) context);
+
+ /* Depth is one more than any SRF below it */
+ srf_depth = context->current_depth + 1;
+
+ /* If new record depth, initialize another level of output lists */
+ if (srf_depth >= list_length(context->level_srfs))
+ {
+ context->level_srfs = lappend(context->level_srfs, NIL);
+ context->level_input_vars = lappend(context->level_input_vars, NIL);
+ context->level_input_srfs = lappend(context->level_input_srfs, NIL);
+ }
+
+ /* Record this SRF as needing to be evaluated at appropriate level */
+ lc = list_nth_cell(context->level_srfs, srf_depth);
+ lfirst(lc) = lappend(lfirst(lc), node);
+
+ /* Record its inputs as being needed at the same level */
+ lc = list_nth_cell(context->level_input_vars, srf_depth);
+ lfirst(lc) = list_concat(lfirst(lc), context->current_input_vars);
+ lc = list_nth_cell(context->level_input_srfs, srf_depth);
+ lfirst(lc) = list_concat(lfirst(lc), context->current_input_srfs);
+
+ /*
+ * Restore caller-level state and update it for presence of this SRF.
+ * Notice we report the SRF itself as being needed for evaluation of
+ * surrounding expression.
+ */
+ context->current_input_vars = save_input_vars;
+ context->current_input_srfs = lappend(save_input_srfs, node);
+ context->current_depth = Max(save_current_depth, srf_depth);
+
+ /* We're done here */
+ return false;
+ }
+
+ /*
+ * Otherwise, the node is a scalar (non-set) expression, so recurse to
+ * examine its inputs.
+ */
+ return expression_tree_walker(node, split_pathtarget_walker,
+ (void *) context);
+}
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 292e1f4aac..cf326ae003 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -9,7 +9,7 @@
* contains variables.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile
index fdd8485cec..4b97f83803 100644
--- a/src/backend/parser/Makefile
+++ b/src/backend/parser/Makefile
@@ -14,18 +14,13 @@ override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
OBJS= analyze.o gram.o scan.o parser.o \
parse_agg.o parse_clause.o parse_coerce.o parse_collate.o parse_cte.o \
- parse_expr.o parse_func.o parse_node.o parse_oper.o parse_param.o \
- parse_relation.o parse_target.o parse_type.o parse_utilcmd.o scansup.o
+ parse_enr.o parse_expr.o parse_func.o parse_node.o parse_oper.o \
+ parse_param.o parse_relation.o parse_target.o parse_type.o \
+ parse_utilcmd.o scansup.o
include $(top_srcdir)/src/backend/common.mk
-# Latest flex causes warnings in this file.
-ifeq ($(GCC),yes)
-scan.o: CFLAGS += -Wno-error
-endif
-
-
# There is no correct way to write a rule that generates two files.
# Rules with two targets don't have that meaning, they are merely
# shorthand for two otherwise separate rules. To be safe for parallel
@@ -41,6 +36,7 @@ gram.c: BISON_CHECK_CMD = $(PERL) $(srcdir)/check_keywords.pl $< $(top_srcdir)/s
scan.c: FLEXFLAGS = -CF -p -p
scan.c: FLEX_NO_BACKUP=yes
+scan.c: FLEX_FIX_WARNING=yes
# Force these dependencies to be known even without dependency info built:
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 90603dd5e5..020d6f74c4 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -15,7 +15,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/parser/analyze.c
@@ -74,6 +74,7 @@
/* Hook for plugins to get control at end of parse analysis */
post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
+static Query *transformOptionalSelectInto(ParseState *pstate, Node *parseTree);
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
static List *transformInsertRow(ParseState *pstate, List *exprlist,
@@ -126,8 +127,9 @@ static void ParseAnalyze_substitute_func(FuncExpr *funcexpr);
* a dummy CMD_UTILITY Query node.
*/
Query *
-parse_analyze(Node *parseTree, const char *sourceText,
- Oid *paramTypes, int numParams)
+parse_analyze(RawStmt *parseTree, const char *sourceText,
+ Oid *paramTypes, int numParams,
+ QueryEnvironment *queryEnv)
{
ParseState *pstate = make_parsestate(NULL);
Query *query;
@@ -139,6 +141,8 @@ parse_analyze(Node *parseTree, const char *sourceText,
if (numParams > 0)
parse_fixed_parameters(pstate, paramTypes, numParams);
+ pstate->p_queryEnv = queryEnv;
+
query = transformTopLevelStmt(pstate, parseTree);
if (post_parse_analyze_hook)
@@ -157,7 +161,7 @@ parse_analyze(Node *parseTree, const char *sourceText,
* be modified or enlarged (via repalloc).
*/
Query *
-parse_analyze_varparams(Node *parseTree, const char *sourceText,
+parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
Oid **paramTypes, int *numParams)
{
ParseState *pstate = make_parsestate(NULL);
@@ -189,13 +193,15 @@ parse_analyze_varparams(Node *parseTree, const char *sourceText,
Query *
parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
CommonTableExpr *parentCTE,
- bool locked_from_parent)
+ bool locked_from_parent,
+ bool resolve_unknowns)
{
ParseState *pstate = make_parsestate(parentParseState);
Query *query;
pstate->p_parent_cte = parentCTE;
pstate->p_locked_from_parent = locked_from_parent;
+ pstate->p_resolve_unknowns = resolve_unknowns;
query = transformStmt(pstate, parseTree);
@@ -208,14 +214,35 @@ parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
* transformTopLevelStmt -
* transform a Parse tree into a Query tree.
*
+ * This function is just responsible for transferring statement location data
+ * from the RawStmt into the finished Query.
+ */
+Query *
+transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
+{
+ Query *result;
+
+ /* We're at top level, so allow SELECT INTO */
+ result = transformOptionalSelectInto(pstate, parseTree->stmt);
+
+ result->stmt_location = parseTree->stmt_location;
+ result->stmt_len = parseTree->stmt_len;
+
+ return result;
+}
+
+/*
+ * transformOptionalSelectInto -
+ * If SELECT has INTO, convert it to CREATE TABLE AS.
+ *
* The only thing we do here that we don't do in transformStmt() is to
* convert SELECT ... INTO into CREATE TABLE AS. Since utility statements
* aren't allowed within larger statements, this is only allowed at the top
* of the parse tree, and so we only try it before entering the recursive
* transformStmt() processing.
*/
-Query *
-transformTopLevelStmt(ParseState *pstate, Node *parseTree)
+static Query *
+transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
{
if (IsA(parseTree, SelectStmt))
{
@@ -359,11 +386,11 @@ transformStmt(ParseState *pstate, Node *parseTree)
* Classification here should match transformStmt().
*/
bool
-analyze_requires_snapshot(Node *parseTree)
+analyze_requires_snapshot(RawStmt *parseTree)
{
bool result;
- switch (nodeTag(parseTree))
+ switch (nodeTag(parseTree->stmt))
{
/*
* Optimizable statements
@@ -379,10 +406,6 @@ analyze_requires_snapshot(Node *parseTree)
* Special cases
*/
case T_DeclareCursorStmt:
- /* yes, because it's analyzed just like SELECT */
- result = true;
- break;
-
case T_ExplainStmt:
case T_CreateTableAsStmt:
/* yes, because we must analyze the contained statement */
@@ -432,7 +455,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
/* set up range table with just the result rel */
qry->resultRelation = setTargetTable(pstate, stmt->relation,
- interpretInhOption(stmt->relation->inhOpt),
+ stmt->relation->inh,
true,
ACL_DELETE);
@@ -469,6 +492,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
qry->hasSubLinks = pstate->p_hasSubLinks;
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
+ qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
qry->hasAggs = pstate->p_hasAggs;
if (pstate->p_hasAggs)
parseCheckAggregates(pstate, qry);
@@ -515,6 +539,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
+ qry->override = stmt->override;
+
isOnConflictUpdate = (stmt->onConflictClause &&
stmt->onConflictClause->action == ONCONFLICT_UPDATE);
@@ -603,10 +629,17 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* otherwise the behavior of SELECT within INSERT might be different
* from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
* bugs of just that nature...)
+ *
+ * The sole exception is that we prevent resolving unknown-type
+ * outputs as TEXT. This does not change the semantics since if the
+ * column type matters semantically, it would have been resolved to
+ * something else anyway. Doing this lets us resolve such outputs as
+ * the target column's type, which we handle below.
*/
sub_pstate->p_rtable = sub_rtable;
sub_pstate->p_joinexprs = NIL; /* sub_rtable has no joins */
sub_pstate->p_namespace = sub_namespace;
+ sub_pstate->p_resolve_unknowns = false;
selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
@@ -614,8 +647,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/* The grammar should have produced a SELECT */
if (!IsA(selectQuery, Query) ||
- selectQuery->commandType != CMD_SELECT ||
- selectQuery->utilityStmt != NULL)
+ selectQuery->commandType != CMD_SELECT)
elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT");
/*
@@ -684,10 +716,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* RTE.
*/
List *exprsLists = NIL;
- List *collations = NIL;
+ List *coltypes = NIL;
+ List *coltypmods = NIL;
+ List *colcollations = NIL;
int sublist_length = -1;
bool lateral = false;
- int i;
Assert(selectStmt->intoClause == NULL);
@@ -695,8 +728,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
{
List *sublist = (List *) lfirst(lc);
- /* Do basic expression transformation (same as a ROW() expr) */
- sublist = transformExpressionList(pstate, sublist, EXPR_KIND_VALUES);
+ /*
+ * Do basic expression transformation (same as a ROW() expr, but
+ * allow SetToDefault at top level)
+ */
+ sublist = transformExpressionList(pstate, sublist,
+ EXPR_KIND_VALUES, true);
/*
* All the sublists must be the same length, *after*
@@ -750,11 +787,20 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
}
/*
- * Although we don't really need collation info, let's just make sure
- * we provide a correctly-sized list in the VALUES RTE.
+ * Construct column type/typmod/collation lists for the VALUES RTE.
+ * Every expression in each column has been coerced to the type/typmod
+ * of the corresponding target column or subfield, so it's sufficient
+ * to look at the exprType/exprTypmod of the first row. We don't care
+ * about the collation labeling, so just fill in InvalidOid for that.
*/
- for (i = 0; i < sublist_length; i++)
- collations = lappend_oid(collations, InvalidOid);
+ foreach(lc, (List *) linitial(exprsLists))
+ {
+ Node *val = (Node *) lfirst(lc);
+
+ coltypes = lappend_oid(coltypes, exprType(val));
+ coltypmods = lappend_int(coltypmods, exprTypmod(val));
+ colcollations = lappend_oid(colcollations, InvalidOid);
+ }
/*
* Ordinarily there can't be any current-level Vars in the expression
@@ -769,7 +815,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/*
* Generate the VALUES RTE
*/
- rte = addRangeTableEntryForValues(pstate, exprsLists, collations,
+ rte = addRangeTableEntryForValues(pstate, exprsLists,
+ coltypes, coltypmods, colcollations,
NULL, lateral, true);
rtr = makeNode(RangeTblRef);
/* assume new rte is at end */
@@ -803,10 +850,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Assert(list_length(valuesLists) == 1);
Assert(selectStmt->intoClause == NULL);
- /* Do basic expression transformation (same as a ROW() expr) */
+ /*
+ * Do basic expression transformation (same as a ROW() expr, but allow
+ * SetToDefault at top level)
+ */
exprList = transformExpressionList(pstate,
(List *) linitial(valuesLists),
- EXPR_KIND_VALUES);
+ EXPR_KIND_VALUES_SINGLE,
+ true);
/* Prepare row for assignment to target table */
exprList = transformInsertRow(pstate, exprList,
@@ -830,8 +881,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
AttrNumber attr_num;
TargetEntry *tle;
- col = (ResTarget *) lfirst(icols);
- Assert(IsA(col, ResTarget));
+ col = lfirst_node(ResTarget, icols);
attr_num = (AttrNumber) lfirst_int(attnos);
tle = makeTargetEntry(expr,
@@ -849,8 +899,16 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/* Process ON CONFLICT, if any. */
if (stmt->onConflictClause)
+ {
+ /* Bail out if target relation is partitioned table */
+ if (pstate->p_target_rangetblentry->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("ON CONFLICT clause is not supported with partitioned tables")));
+
qry->onConflict = transformOnConflictClause(pstate,
stmt->onConflictClause);
+ }
/*
* If we have a RETURNING clause, we need to add the target relation to
@@ -871,6 +929,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
qry->rtable = pstate->p_rtable;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
+ qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
qry->hasSubLinks = pstate->p_hasSubLinks;
assign_query_collations(pstate, qry);
@@ -947,8 +1006,7 @@ transformInsertRow(ParseState *pstate, List *exprlist,
Expr *expr = (Expr *) lfirst(lc);
ResTarget *col;
- col = (ResTarget *) lfirst(icols);
- Assert(IsA(col, ResTarget));
+ col = lfirst_node(ResTarget, icols);
expr = transformAssignedExpr(pstate, expr,
EXPR_KIND_INSERT_TARGET,
@@ -990,7 +1048,7 @@ transformInsertRow(ParseState *pstate, List *exprlist,
}
/*
- * transformSelectStmt -
+ * transformOnConflictClause -
* transforms an OnConflictClause in an INSERT
*/
static OnConflictExpr *
@@ -1038,11 +1096,10 @@ transformOnConflictClause(ParseState *pstate,
exclRelIndex = list_length(pstate->p_rtable);
/*
- * Build a targetlist for the EXCLUDED pseudo relation. Have to be
- * careful to use resnos that correspond to attnos of the underlying
- * relation.
+ * Build a targetlist representing the columns of the EXCLUDED pseudo
+ * relation. Have to be careful to use resnos that correspond to
+ * attnos of the underlying relation.
*/
- Assert(pstate->p_next_resno == 1);
for (attno = 0; attno < targetrel->rd_rel->relnatts; attno++)
{
Form_pg_attribute attr = targetrel->rd_att->attrs[attno];
@@ -1063,14 +1120,11 @@ transformOnConflictClause(ParseState *pstate,
attr->atttypid, attr->atttypmod,
attr->attcollation,
0);
- var->location = -1;
-
- name = NameStr(attr->attname);
+ name = pstrdup(NameStr(attr->attname));
}
- Assert(pstate->p_next_resno == attno + 1);
te = makeTargetEntry((Expr *) var,
- pstate->p_next_resno++,
+ attno + 1,
name,
false);
@@ -1079,15 +1133,16 @@ transformOnConflictClause(ParseState *pstate,
}
/*
- * Additionally add a whole row tlist entry for EXCLUDED. That's
- * really only needed for ruleutils' benefit, which expects to find
- * corresponding entries in child tlists. Alternatively we could do
- * this only when required, but that doesn't seem worth the trouble.
+ * Add a whole-row-Var entry to support references to "EXCLUDED.*".
+ * Like the other entries in exclRelTlist, its resno must match the
+ * Var's varattno, else the wrong things happen while resolving
+ * references in setrefs.c. This is against normal conventions for
+ * targetlists, but it's okay since we don't use this as a real tlist.
*/
var = makeVar(exclRelIndex, InvalidAttrNumber,
- RelationGetRelid(targetrel),
+ targetrel->rd_rel->reltype,
-1, InvalidOid, 0);
- te = makeTargetEntry((Expr *) var, 0, NULL, true);
+ te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
exclRelTlist = lappend(exclRelTlist, te);
/*
@@ -1232,7 +1287,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
stmt->sortClause,
&qry->targetList,
EXPR_KIND_ORDER_BY,
- true /* fix unknowns */ ,
false /* allow SQL92 rules */ );
qry->groupClause = transformGroupClause(pstate,
@@ -1278,11 +1332,16 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
pstate->p_windowdefs,
&qry->targetList);
+ /* resolve any still-unresolved output columns as being type text */
+ if (pstate->p_resolve_unknowns)
+ resolveTargetListUnknowns(pstate, qry->targetList);
+
qry->rtable = pstate->p_rtable;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
qry->hasSubLinks = pstate->p_hasSubLinks;
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
+ qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
qry->hasAggs = pstate->p_hasAggs;
if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
parseCheckAggregates(pstate, qry);
@@ -1310,7 +1369,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
{
Query *qry = makeNode(Query);
List *exprsLists;
- List *collations;
+ List *coltypes = NIL;
+ List *coltypmods = NIL;
+ List *colcollations = NIL;
List **colexprs = NULL;
int sublist_length = -1;
bool lateral = false;
@@ -1342,9 +1403,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
}
/*
- * For each row of VALUES, transform the raw expressions. This is also a
- * handy place to reject DEFAULT nodes, which the grammar allows for
- * simplicity.
+ * For each row of VALUES, transform the raw expressions.
*
* Note that the intermediate representation we build is column-organized
* not row-organized. That simplifies the type and collation processing
@@ -1354,8 +1413,12 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
{
List *sublist = (List *) lfirst(lc);
- /* Do basic expression transformation (same as a ROW() expr) */
- sublist = transformExpressionList(pstate, sublist, EXPR_KIND_VALUES);
+ /*
+ * Do basic expression transformation (same as a ROW() expr, but here
+ * we disallow SetToDefault)
+ */
+ sublist = transformExpressionList(pstate, sublist,
+ EXPR_KIND_VALUES, false);
/*
* All the sublists must be the same length, *after* transformation
@@ -1378,17 +1441,12 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
exprLocation((Node *) sublist))));
}
- /* Check for DEFAULT and build per-column expression lists */
+ /* Build per-column expression lists */
i = 0;
foreach(lc2, sublist)
{
Node *col = (Node *) lfirst(lc2);
- if (IsA(col, SetToDefault))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("DEFAULT can only appear in a VALUES list within INSERT"),
- parser_errposition(pstate, exprLocation(col))));
colexprs[i] = lappend(colexprs[i], col);
i++;
}
@@ -1399,8 +1457,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
/*
* Now resolve the common types of the columns, and coerce everything to
- * those types. Then identify the common collation, if any, of each
- * column.
+ * those types. Then identify the common typmod and common collation, if
+ * any, of each column.
*
* We must do collation processing now because (1) assign_query_collations
* doesn't process rangetable entries, and (2) we need to label the VALUES
@@ -1411,11 +1469,12 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
*
* Note we modify the per-column expression lists in-place.
*/
- collations = NIL;
for (i = 0; i < sublist_length; i++)
{
Oid coltype;
+ int32 coltypmod = -1;
Oid colcoll;
+ bool first = true;
coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
@@ -1425,11 +1484,24 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
col = coerce_to_common_type(pstate, col, coltype, "VALUES");
lfirst(lc) = (void *) col;
+ if (first)
+ {
+ coltypmod = exprTypmod(col);
+ first = false;
+ }
+ else
+ {
+ /* As soon as we see a non-matching typmod, fall back to -1 */
+ if (coltypmod >= 0 && coltypmod != exprTypmod(col))
+ coltypmod = -1;
+ }
}
colcoll = select_common_collation(pstate, colexprs[i], true);
- collations = lappend_oid(collations, colcoll);
+ coltypes = lappend_oid(coltypes, coltype);
+ coltypmods = lappend_int(coltypmods, coltypmod);
+ colcollations = lappend_oid(colcollations, colcoll);
}
/*
@@ -1471,7 +1543,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
/*
* Generate the VALUES RTE
*/
- rte = addRangeTableEntryForValues(pstate, exprsLists, collations,
+ rte = addRangeTableEntryForValues(pstate, exprsLists,
+ coltypes, coltypmods, colcollations,
NULL, lateral, true);
addRTEtoQuery(pstate, rte, true, true, true);
@@ -1493,7 +1566,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
stmt->sortClause,
&qry->targetList,
EXPR_KIND_ORDER_BY,
- true /* fix unknowns */ ,
false /* allow SQL92 rules */ );
qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
@@ -1616,10 +1688,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
/*
* Recursively transform the components of the tree.
*/
- sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt,
- true,
- NULL);
- Assert(sostmt && IsA(sostmt, SetOperationStmt));
+ sostmt = castNode(SetOperationStmt,
+ transformSetOperationTree(pstate, stmt, true, NULL));
+ Assert(sostmt);
qry->setOperations = (Node *) sostmt;
/*
@@ -1717,7 +1788,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
sortClause,
&qry->targetList,
EXPR_KIND_ORDER_BY,
- false /* no unknowns expected */ ,
false /* allow SQL92 rules */ );
/* restore namespace, remove jrte from rtable */
@@ -1743,6 +1813,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
qry->hasSubLinks = pstate->p_hasSubLinks;
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
+ qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
qry->hasAggs = pstate->p_hasAggs;
if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
parseCheckAggregates(pstate, qry);
@@ -1836,11 +1907,19 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
/*
* Transform SelectStmt into a Query.
*
+ * This works the same as SELECT transformation normally would, except
+ * that we prevent resolving unknown-type outputs as TEXT. This does
+ * not change the subquery's semantics since if the column type
+ * matters semantically, it would have been resolved to something else
+ * anyway. Doing this lets us resolve such outputs using
+ * select_common_type(), below.
+ *
* Note: previously transformed sub-queries don't affect the parsing
* of this sub-query, because they are not in the toplevel pstate's
* namespace list.
*/
- selectQuery = parse_sub_analyze((Node *) stmt, pstate, NULL, false);
+ selectQuery = parse_sub_analyze((Node *) stmt, pstate,
+ NULL, false, false);
/*
* Check for bogus references to Vars on the current query level (but
@@ -2187,7 +2266,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
}
qry->resultRelation = setTargetTable(pstate, stmt->relation,
- interpretInhOption(stmt->relation->inhOpt),
+ stmt->relation->inh,
true,
ACL_UPDATE);
@@ -2222,6 +2301,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
qry->rtable = pstate->p_rtable;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
+ qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
qry->hasSubLinks = pstate->p_hasSubLinks;
assign_query_collations(pstate, qry);
@@ -2272,8 +2352,7 @@ transformUpdateTargetList(ParseState *pstate, List *origTlist)
}
if (orig_tl == NULL)
elog(ERROR, "UPDATE target count mismatch --- internal error");
- origTarget = (ResTarget *) lfirst(orig_tl);
- Assert(IsA(origTarget, ResTarget));
+ origTarget = lfirst_node(ResTarget, orig_tl);
attrno = attnameAttNum(pstate->p_target_relation,
origTarget->name, true);
@@ -2342,6 +2421,10 @@ transformReturningList(ParseState *pstate, List *returningList)
/* mark column origins */
markTargetListOrigins(pstate, rlist);
+ /* resolve any still-unresolved output columns as being type text */
+ if (pstate->p_resolve_unknowns)
+ resolveTargetListUnknowns(pstate, rlist);
+
/* restore state */
pstate->p_next_resno = save_next_resno;
@@ -2353,17 +2436,17 @@ transformReturningList(ParseState *pstate, List *returningList)
* transformDeclareCursorStmt -
* transform a DECLARE CURSOR Statement
*
- * DECLARE CURSOR is a hybrid case: it's an optimizable statement (in fact not
- * significantly different from a SELECT) as far as parsing/rewriting/planning
- * are concerned, but it's not passed to the executor and so in that sense is
- * a utility statement. We transform it into a Query exactly as if it were
- * a SELECT, then stick the original DeclareCursorStmt into the utilityStmt
- * field to carry the cursor name and options.
+ * DECLARE CURSOR is like other utility statements in that we emit it as a
+ * CMD_UTILITY Query node; however, we must first transform the contained
+ * query. We used to postpone that until execution, but it's really necessary
+ * to do it during the normal parse analysis phase to ensure that side effects
+ * of parser hooks happen at the expected time.
*/
static Query *
transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
{
Query *result;
+ Query *query;
/*
* Don't allow both SCROLL and NO SCROLL to be specified
@@ -2374,12 +2457,13 @@ transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
errmsg("cannot specify both SCROLL and NO SCROLL")));
- result = transformStmt(pstate, stmt->query);
+ /* Transform contained query, not allowing SELECT INTO */
+ query = transformStmt(pstate, stmt->query);
+ stmt->query = (Node *) query;
/* Grammar should not have allowed anything but SELECT */
- if (!IsA(result, Query) ||
- result->commandType != CMD_SELECT ||
- result->utilityStmt != NULL)
+ if (!IsA(query, Query) ||
+ query->commandType != CMD_SELECT)
elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
/*
@@ -2387,47 +2471,47 @@ transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
* allowed, but the semantics of when the updates occur might be
* surprising.)
*/
- if (result->hasModifyingCTE)
+ if (query->hasModifyingCTE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
/* FOR UPDATE and WITH HOLD are not compatible */
- if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
+ if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
LCS_asString(((RowMarkClause *)
- linitial(result->rowMarks))->strength)),
+ linitial(query->rowMarks))->strength)),
errdetail("Holdable cursors must be READ ONLY.")));
/* FOR UPDATE and SCROLL are not compatible */
- if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
+ if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
LCS_asString(((RowMarkClause *)
- linitial(result->rowMarks))->strength)),
+ linitial(query->rowMarks))->strength)),
errdetail("Scrollable cursors must be READ ONLY.")));
/* FOR UPDATE and INSENSITIVE are not compatible */
- if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
+ if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("DECLARE INSENSITIVE CURSOR ... %s is not supported",
LCS_asString(((RowMarkClause *)
- linitial(result->rowMarks))->strength)),
+ linitial(query->rowMarks))->strength)),
errdetail("Insensitive cursors must be READ ONLY.")));
- /* We won't need the raw querytree any more */
- stmt->query = NULL;
-
+ /* represent the command as a utility Query */
+ result = makeNode(Query);
+ result->commandType = CMD_UTILITY;
result->utilityStmt = (Node *) stmt;
return result;
@@ -2450,7 +2534,7 @@ transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Query *result;
/* transform contained query, allowing SELECT INTO */
- stmt->query = (Node *) transformTopLevelStmt(pstate, stmt->query);
+ stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
/* represent the command as a utility Query */
result = makeNode(Query);
@@ -2466,7 +2550,7 @@ transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
* transform a CREATE TABLE AS, SELECT ... INTO, or CREATE MATERIALIZED VIEW
* Statement
*
- * As with EXPLAIN, transform the contained statement now.
+ * As with DECLARE CURSOR and EXPLAIN, transform the contained statement now.
*/
static Query *
transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
@@ -2474,7 +2558,7 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Query *result;
Query *query;
- /* transform contained query */
+ /* transform contained query, not allowing SELECT INTO */
query = transformStmt(pstate, stmt->query);
stmt->query = (Node *) query;
@@ -2529,7 +2613,7 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
* in the IntoClause because that's where intorel_startup() can
* conveniently get it from.
*/
- stmt->into->viewQuery = copyObject(query);
+ stmt->into->viewQuery = (Node *) copyObject(query);
}
/* represent the command as a utility Query */
@@ -2622,8 +2706,9 @@ transformExecDirectStmt(ParseState *pstate, ExecDirectStmt *stmt)
*/
foreach(raw_parsetree_item, raw_parsetree_list)
{
- Node *parsetree = (Node *) lfirst(raw_parsetree_item);
- result = parse_analyze(parsetree, query, NULL, 0);
+ RawStmt *parsetree = lfirst_node(RawStmt, raw_parsetree_item);
+ List *result_list = pg_analyze_and_rewrite(parsetree, query, NULL, 0, NULL);
+ result = linitial_node(Query, result_list);
}
/* Default list of parameters to set */
@@ -2784,8 +2869,7 @@ CheckSelectLocking(Query *qry, LockClauseStrength strength)
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with window functions",
LCS_asString(strength))));
-
- if (expression_returns_set((Node *) qry->targetList))
+ if (qry->hasTargetSRFs)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
@@ -2913,6 +2997,15 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location)));
break;
+ case RTE_TABLEFUNC:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ /*------
+ translator: %s is a SQL row locking clause such as FOR UPDATE */
+ errmsg("%s cannot be applied to a table function",
+ LCS_asString(lc->strength)),
+ parser_errposition(pstate, thisrel->location)));
+ break;
case RTE_VALUES:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -2931,6 +3024,15 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location)));
break;
+ case RTE_NAMEDTUPLESTORE:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ /*------
+ translator: %s is a SQL row locking clause such as FOR UPDATE */
+ errmsg("%s cannot be applied to a named tuplestore",
+ LCS_asString(lc->strength)),
+ parser_errposition(pstate, thisrel->location)));
+ break;
default:
elog(ERROR, "unrecognized RTE type: %d",
(int) rte->rtekind);
diff --git a/src/backend/parser/check_keywords.pl b/src/backend/parser/check_keywords.pl
index 568ef696fd..6eb0aea96b 100644
--- a/src/backend/parser/check_keywords.pl
+++ b/src/backend/parser/check_keywords.pl
@@ -4,7 +4,7 @@
# Usage: check_keywords.pl gram.y kwlist.h
# src/backend/parser/check_keywords.pl
-# Copyright (c) 2009-2016, PostgreSQL Global Development Group
+# Copyright (c) 2009-2017, PostgreSQL Global Development Group
use warnings;
use strict;
@@ -14,7 +14,7 @@ my $kwlist_filename = $ARGV[1];
my $errors = 0;
-sub error(@)
+sub error
{
print STDERR @_;
$errors = 1;
@@ -29,18 +29,18 @@ $keyword_categories{'col_name_keyword'} = 'COL_NAME_KEYWORD';
$keyword_categories{'type_func_name_keyword'} = 'TYPE_FUNC_NAME_KEYWORD';
$keyword_categories{'reserved_keyword'} = 'RESERVED_KEYWORD';
-open(GRAM, $gram_filename) || die("Could not open : $gram_filename");
+open(my $gram, '<', $gram_filename) || die("Could not open : $gram_filename");
-my ($S, $s, $k, $n, $kcat);
+my $kcat;
my $comment;
my @arr;
my %keywords;
-line: while (<GRAM>)
+line: while (my $S = <$gram>)
{
- chomp; # strip record separator
+ chomp $S; # strip record separator
- $S = $_;
+ my $s;
# Make sure any braces are split
$s = '{', $S =~ s/$s/ { /g;
@@ -54,7 +54,7 @@ line: while (<GRAM>)
{
# Is this the beginning of a keyword list?
- foreach $k (keys %keyword_categories)
+ foreach my $k (keys %keyword_categories)
{
if ($S =~ m/^($k):/)
{
@@ -66,7 +66,7 @@ line: while (<GRAM>)
}
# Now split the line into individual fields
- $n = (@arr = split(' ', $S));
+ my $n = (@arr = split(' ', $S));
# Ok, we're in a keyword list. Go through each field in turn
for (my $fieldIndexer = 0; $fieldIndexer < $n; $fieldIndexer++)
@@ -109,15 +109,15 @@ line: while (<GRAM>)
push @{ $keywords{$kcat} }, $arr[$fieldIndexer];
}
}
-close GRAM;
+close $gram;
# Check that each keyword list is in alphabetical order (just for neatnik-ism)
-my ($prevkword, $kword, $bare_kword);
-foreach $kcat (keys %keyword_categories)
+my ($prevkword, $bare_kword);
+foreach my $kcat (keys %keyword_categories)
{
$prevkword = '';
- foreach $kword (@{ $keywords{$kcat} })
+ foreach my $kword (@{ $keywords{$kcat} })
{
# Some keyword have a _P suffix. Remove it for the comparison.
@@ -149,12 +149,13 @@ while (my ($kcat, $kcat_id) = each(%keyword_categories))
# Now read in kwlist.h
-open(KWLIST, $kwlist_filename) || die("Could not open : $kwlist_filename");
+open(my $kwlist, '<', $kwlist_filename)
+ || die("Could not open : $kwlist_filename");
my $prevkwstring = '';
my $bare_kwname;
my %kwhash;
-kwlist_line: while (<KWLIST>)
+kwlist_line: while (<$kwlist>)
{
my ($line) = $_;
@@ -219,7 +220,7 @@ kwlist_line: while (<KWLIST>)
}
}
}
-close KWLIST;
+close $kwlist;
# Check that we've paired up all keywords from gram.y with lines in kwlist.h
while (my ($kwcat, $kwcat_id) = each(%keyword_categories))
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 54af976917..7fa2f21e3f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6,7 +6,7 @@
* gram.y
* POSTGRESQL BISON rules/actions
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -29,12 +29,11 @@
* current transaction and are just parsing commands to find the next
* ROLLBACK or COMMIT. If you make use of SET variables, then you
* will do the wrong thing in multi-query strings like this:
- * SET SQL_inheritance TO off; SELECT * FROM foo;
+ * SET constraint_exclusion TO off; SELECT * FROM foo;
* because the entire string is parsed by gram.y before the SET gets
* executed. Anything that depends on the database or changeable state
* should be handled during parse analysis so that it happens at the
- * right time not the wrong time. The handling of SQL_inheritance is
- * a good example.
+ * right time not the wrong time.
*
* WARNINGS
* If you use a list, make sure the datum is a node so that the printing
@@ -85,7 +84,8 @@
/*
* The above macro assigns -1 (unknown) as the parse location of any
- * nonterminal that was reduced from an empty rule. This is problematic
+ * nonterminal that was reduced from an empty rule, or whose leftmost
+ * component was reduced from an empty rule. This is problematic
* for nonterminals defined like
* OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ;
* because we'll set -1 as the location during the first reduction and then
@@ -96,6 +96,12 @@
* (Although we have many nonterminals that follow this pattern, we only
* bother with fixing @$ like this when the nonterminal's parse location
* is actually referenced in some rule.)
+ *
+ * A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs
+ * locations until it's found one that's not -1. Then we'd get a correct
+ * location for any nonterminal that isn't entirely empty. But this way
+ * would add overhead to every rule reduction, and so far there's not been
+ * a compelling reason to pay that overhead.
*/
/*
@@ -146,6 +152,8 @@ typedef struct StmtMulti
static void base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner,
const char *msg);
+static RawStmt *makeRawStmt(Node *stmt, int stmt_location);
+static void updateRawStmtEnd(RawStmt *rs, int end_location);
static Node *makeColumnRef(char *colname, List *indirection,
int location, core_yyscan_t yyscanner);
static Node *makeTypeCast(Node *arg, TypeName *typename, int location);
@@ -157,7 +165,7 @@ static Node *makeBitStringConst(char *str, int location);
static Node *makeNullAConst(int location);
static Node *makeAConst(Value *v, int location);
static Node *makeBoolAConst(bool state, int location);
-static Node *makeRoleSpec(RoleSpecType type, int location);
+static RoleSpec *makeRoleSpec(RoleSpecType type, int location);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
static List *check_func_name(List *names, core_yyscan_t yyscanner);
static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
@@ -177,6 +185,8 @@ static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location);
static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location);
static Node *makeNotExpr(Node *expr, int location);
static Node *makeAArrayExpr(List *elements, int location);
+static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod,
+ int location);
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
List *args, int location);
static List *mergeTableFuncParameters(List *func_args, List *columns);
@@ -220,7 +230,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
TypeName *typnam;
FunctionParameter *fun_param;
FunctionParameterMode fun_param_mode;
- FuncWithArgs *funwithargs;
+ ObjectWithArgs *objwithargs;
DefElem *defelt;
SortBy *sortby;
WindowDef *windef;
@@ -244,10 +254,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
DistributeBy *distby;
PGXCSubCluster *subclus;
/* PGXC_END */
+ PartitionElem *partelem;
+ PartitionSpec *partspec;
+ PartitionBoundSpec *partboundspec;
+ RoleSpec *rolespec;
}
%type <node> stmt schema_stmt
- AlterEventTrigStmt
+ AlterEventTrigStmt AlterCollationStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt
@@ -260,16 +274,16 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
CreateDomainStmt CreateExtensionStmt CreateGroupStmt CreateOpClassStmt
CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt
- CreateSchemaStmt CreateSeqStmt CreateStmt CreateTableSpaceStmt
+ CreateSchemaStmt CreateSeqStmt CreateStmt CreateStatsStmt CreateTableSpaceStmt
CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt
CreateAssertStmt CreateTransformStmt CreateTrigStmt CreateEventTrigStmt
CreateUserStmt CreateUserMappingStmt CreateRoleStmt CreatePolicyStmt
CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
- DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt DropRoleStmt
- DropPolicyStmt DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
+ DropAssertStmt DropCastStmt DropRoleStmt
+ DropUserStmt DropdbStmt DropTableSpaceStmt
DropTransformStmt
- DropForeignServerStmt DropUserMappingStmt ExplainStmt ExecDirectStmt FetchStmt
+ DropUserMappingStmt ExplainStmt ExecDirectStmt FetchStmt
GrantStmt GrantRoleStmt ImportForeignSchemaStmt IndexStmt InsertStmt
ListenStmt LoadStmt LockStmt NotifyStmt ExplainableStmt PreparableStmt
CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt
@@ -285,6 +299,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
BarrierStmt PauseStmt AlterNodeStmt CreateNodeStmt DropNodeStmt
CreateNodeGroupStmt DropNodeGroupStmt
CreateMatViewStmt RefreshMatViewStmt CreateAmStmt
+ CreatePublicationStmt AlterPublicationStmt
+ CreateSubscriptionStmt AlterSubscriptionStmt DropSubscriptionStmt
%type <node> select_no_parens select_with_parens select_clause
simple_select values_clause
@@ -293,8 +309,10 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <ival> add_drop opt_asc_desc opt_nulls_order
%type <node> alter_table_cmd alter_type_cmd opt_collate_clause
- replica_identity
+ replica_identity partition_cmd
%type <list> alter_table_cmds alter_type_cmds
+%type <list> alter_identity_column_option_list
+%type <defelt> alter_identity_column_option
%type <dbehavior> opt_drop_behavior
@@ -329,6 +347,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
%type <node> TriggerWhen
+%type <str> TransitionRelName
+%type <boolean> TransitionRowOrTable TransitionOldOrNew
+%type <node> TriggerTransition
%type <list> event_trigger_when_list event_trigger_value_list
%type <defelt> event_trigger_when_item
@@ -349,17 +370,18 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <str> all_Op MathOp
%type <str> row_security_cmd RowSecurityDefaultForCmd
+%type <boolean> RowSecurityDefaultPermissive
%type <node> RowSecurityOptionalWithCheck RowSecurityOptionalExpr
%type <list> RowSecurityDefaultToRole RowSecurityOptionalToRole
%type <str> iso_level opt_encoding
-%type <node> grantee
+%type <rolespec> grantee
%type <list> grantee_list
%type <accesspriv> privilege
%type <list> privileges privilege_list
%type <privtarget> privilege_target
-%type <funwithargs> function_with_argtypes
-%type <list> function_with_argtypes_list
+%type <objwithargs> function_with_argtypes aggregate_with_argtypes operator_with_argtypes
+%type <list> function_with_argtypes_list aggregate_with_argtypes_list operator_with_argtypes_list
%type <ival> defacl_privilege_target
%type <defelt> DefACLOption
%type <list> DefACLOptionList
@@ -383,8 +405,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
qualified_name_list any_name any_name_list type_name_list
any_operator expr_list attrs
target_list opt_target_list insert_column_list set_target_list
- set_clause_list set_clause multiple_set_clause
- ctext_expr_list ctext_row def_list operator_def_list indirection opt_indirection
+ set_clause_list set_clause
+ def_list operator_def_list indirection opt_indirection
reloption_list group_clause TriggerFuncArgs select_limit
opt_select_limit opclass_item_list opclass_drop_list
opclass_purpose opt_opfamily transaction_mode_list_or_empty
@@ -395,10 +417,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
create_generic_options alter_generic_options
relation_expr_list dostmt_opt_list
transform_element_list transform_type_list
+ TriggerTransitions TriggerReferencing
+ publication_name_list
%type <list> group_by_list
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause
%type <node> grouping_sets_clause
+%type <node> opt_publication_for_tables publication_for_tables
+%type <value> publication_name_item
%type <list> opt_fdw_options fdw_options
%type <defelt> fdw_option
@@ -441,14 +467,16 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <boolean> copy_from opt_program
%type <ival> opt_column event cursor_options opt_hold opt_set_data
-%type <objtype> drop_type comment_type security_label_type
+%type <objtype> drop_type_any_name drop_type_name drop_type_name_on_any_name
+ comment_type_any_name comment_type_name
+ security_label_type_any_name security_label_type_name
%type <node> fetch_args limit_clause select_limit_value
offset_clause select_offset_value
select_offset_value2 opt_select_fetch_first_value
%type <ival> row_or_rows first_or_next
-%type <list> OptSeqOptList SeqOptList
+%type <list> OptSeqOptList SeqOptList OptParenthesizedSeqOptList
%type <defelt> SeqOptElem
%type <istmt> insert_rest
@@ -463,8 +491,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound
- columnref in_expr having_clause func_table array_expr
- ExclusionWhereClause
+ columnref in_expr having_clause func_table xmltable array_expr
+ ExclusionWhereClause operator_def_arg
%type <list> rowsfrom_item rowsfrom_list opt_col_def_list
%type <boolean> opt_ordinality
%type <list> ExclusionConstraintList ExclusionConstraintElem
@@ -474,7 +502,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <node> case_expr case_arg when_clause case_default
%type <list> when_clause_list
%type <ival> sub_type
-%type <node> ctext_expr
%type <value> NumericOnly
%type <list> NumericOnly_list
%type <alias> alias_clause opt_alias_clause
@@ -486,7 +513,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <range> relation_expr
%type <range> relation_expr_opt_alias
%type <node> tablesample_clause opt_repeatable_clause
-%type <target> target_el single_set_clause set_target insert_column_item
+%type <target> target_el set_target insert_column_item
%type <str> generic_option_name
%type <node> generic_option_arg
@@ -513,7 +540,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
Bit ConstBit BitWithLength BitWithoutLength
%type <str> character
%type <str> extract_arg
-%type <str> opt_charset
%type <boolean> opt_varying opt_timezone opt_no_inherit
%type <ival> Iconst SignedIconst
@@ -524,7 +550,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <str> NonReservedWord NonReservedWord_or_Sconst
%type <str> createdb_opt_name
%type <node> var_value zone_value
-%type <node> auth_ident RoleSpec opt_granted_by
+%type <rolespec> auth_ident RoleSpec opt_granted_by
%type <keyword> unreserved_keyword type_func_name_keyword
%type <keyword> col_name_keyword reserved_keyword
@@ -540,7 +566,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> constraints_set_list
%type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace
-%type <node> OptTableSpaceOwner
+%type <rolespec> OptTableSpaceOwner
%type <ival> opt_check_option
%type <str> opt_provider security_label
@@ -551,6 +577,11 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <node> xmlexists_argument
%type <ival> document_or_content
%type <boolean> xml_whitespace_option
+%type <list> xmltable_column_list xmltable_column_option_list
+%type <node> xmltable_column_el
+%type <defelt> xmltable_column_option_el
+%type <list> xml_namespace_list
+%type <target> xml_namespace_el
%type <node> func_application func_expr_common_subexpr
%type <node> func_expr func_expr_windowless
@@ -570,15 +601,23 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <subclus> OptSubCluster OptSubClusterInternal
/* PGXC_END */
%type <boolean> opt_if_not_exists
+%type <ival> generated_when override_kind
+%type <partspec> PartitionSpec OptPartitionSpec
+%type <str> part_strategy
+%type <partelem> part_elem
+%type <list> part_params
+%type <partboundspec> ForValues
+%type <node> partbound_datum PartitionRangeDatum
+%type <list> partbound_datum_list range_datum_list
/*
* Non-keyword token types. These are hard-wired into the "flex" lexer.
* They must be listed first so that their numeric codes do not depend on
- * the set of keywords. PL/pgsql depends on this so that it can share the
- * same lexer. If you add/change tokens here, fix PL/pgsql to match!
+ * the set of keywords. PL/pgSQL depends on this so that it can share the
+ * same lexer. If you add/change tokens here, fix PL/pgSQL to match!
*
* DOT_DOT is unused in the core SQL grammar, and so will always provoke
- * parse errors. It is needed by PL/pgsql.
+ * parse errors. It is needed by PL/pgSQL.
*/
%token <str> IDENT FCONST SCONST BCONST XCONST Op
%token <ival> ICONST PARAM
@@ -596,27 +635,24 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
/* PGXC - added DISTRIBUTE, DISTRIBUTED, DISTSYLE, DISTKEY, RANDOMLY, DIRECT, COORDINATOR, CLEAN, NODE, BARRIER */
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
- ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION
+ ASSERTION ASSIGNMENT ASYMMETRIC AT ATTACH ATTRIBUTE AUTHORIZATION
BACKWARD BARRIER BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
BOOLEAN_P BOTH BY
CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLEAN CLOSE
- CLUSTER COALESCE COLLATE COLLATION COLUMN COMMENT COMMENTS COMMIT
- COMMITTED CONCURRENTLY CONFIGURATION CONFLICT CONNECTION CONSTRAINT CONSTRAINTS
- CONTENT_P CONTINUE_P CONVERSION_P COORDINATOR COPY COST CREATE
+ CLUSTER COALESCE COLLATE COLLATION COLUMN COLUMNS COMMENT COMMENTS COMMIT
+ COMMITTED CONCURRENTLY CONFIGURATION CONFLICT CONNECTION CONSTRAINT
+ CONSTRAINTS CONTENT_P CONTINUE_P CONVERSION_P COORDINATOR COPY COST CREATE
CROSS CSV CUBE CURRENT_P
CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA
CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DEPENDS DESC
-/* PGXC_BEGIN */
- DICTIONARY DIRECT DISABLE_P DISCARD DISTINCT DISTKEY DISTRIBUTE DISTRIBUTED
- DISTSTYLE DO DOCUMENT_P DOMAIN_P DOUBLE_P
-/* PGXC_END */
- DROP
+ DETACH DICTIONARY DIRECT DISABLE_P DISCARD DISTINCT DISTKEY DISTRIBUTE DISTRIBUTED DISTSTYLE DO DOCUMENT_P DOMAIN_P
+ DOUBLE_P DROP
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT
EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN
@@ -625,7 +661,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
FALSE_P FAMILY FETCH FILTER FIRST_P FLOAT_P FOLLOWING FOR
FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
- GLOBAL GRANT GRANTED GREATEST GROUP_P GROUPING
+ GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P GROUPING
HANDLER HAVING HEADER_P HOLD HOUR_P
@@ -644,29 +680,29 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
- NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NODE NONE
+ NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NODE NONE
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
NULLS_P NUMERIC
- OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
- ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
+ OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
+ ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER
PARALLEL PARSER PARTIAL PARTITION PASSING PASSWORD PAUSE PLACING PLANS POLICY
POSITION PRECEDING PRECISION PREFERRED PRESERVE PREPARE PREPARED PRIMARY
- PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROGRAM
+ PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROGRAM PUBLICATION
QUOTE
- RANDOMLY RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFRESH REINDEX
- RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
+ RANDOMLY RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFERENCING
+ REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
ROW ROWS RULE
- SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
+ SAVEPOINT SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW
- SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P START
- STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING
- SYMMETRIC SYSID SYSTEM_P
+ SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
+ START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P
+ SUBSCRIPTION SUBSTRING SYMMETRIC SYSID SYSTEM_P
TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN
TIME TIMESTAMP TO TRAILING TRANSACTION TRANSFORM TREAT TRIGGER TRIM TRUE_P
@@ -680,8 +716,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE
- XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE
- XMLPI XMLROOT XMLSERIALIZE
+ XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLNAMESPACES
+ XMLPARSE XMLPI XMLROOT XMLSERIALIZE XMLTABLE
YEAR_P YES_P
@@ -720,6 +756,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
* same as if they weren't keywords). We need to do this for PARTITION,
* RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS
* so that they can follow a_expr without creating postfix-operator problems;
+ * for GENERATED so that it can follow b_expr;
* and for NULL so that it can follow b_expr in ColQualList without creating
* postfix-operator problems.
*
@@ -738,7 +775,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
* blame any funny behavior of UNBOUNDED on the SQL standard, though.
*/
%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
-%nonassoc IDENT NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING CUBE ROLLUP
+%nonassoc IDENT GENERATED NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING CUBE ROLLUP
%left Op OPERATOR /* multi-character ops and user-defined operators */
%left '+' '-'
%left '*' '/' '%'
@@ -774,9 +811,32 @@ stmtblock: stmtmulti
}
;
-/* the thrashing around here is to discard "empty" statements... */
+/*
+ * At top level, we wrap each stmt with a RawStmt node carrying start location
+ * and length of the stmt's text. Notice that the start loc/len are driven
+ * entirely from semicolon locations (@2). It would seem natural to use
+ * @1 or @3 to get the true start location of a stmt, but that doesn't work
+ * for statements that can start with empty nonterminals (opt_with_clause is
+ * the main offender here); as noted in the comments for YYLLOC_DEFAULT,
+ * we'd get -1 for the location in such cases.
+ * We also take care to discard empty statements entirely.
+ */
stmtmulti: stmtmulti ';' stmt
{
+ /*
+ * XXX PG10MERGE: Looks like support for obtaining raw
+ * query string for individual commands is added in PG10.
+ * If so, we can make use of the same infrastructure.
+ *
+ * XXX The following gives a compilation WARNING because
+ * stmtmulti is defined as a List in PG10, but we have our
+ * own definition.
+ */
+ if ($1 != NIL)
+ {
+ /* update length of previous stmt */
+ updateRawStmtEnd(llast_node(RawStmt, $1), @2);
+ }
if ($3 != NULL)
{
char *query;
@@ -819,6 +879,8 @@ stmtmulti: stmtmulti ';' stmt
$$ = n;
}
}
+ if ($3 != NULL)
+ $$ = lappend($1, makeRawStmt($3, @2 + 1));
else
$$ = $1;
}
@@ -851,6 +913,8 @@ stmtmulti: stmtmulti ';' stmt
n->queries = list_make1(query);
$$ = n;
}
+ if ($1 != NULL)
+ $$ = list_make1(makeRawStmt($1, 0));
else
$$ = NULL;
}
@@ -858,6 +922,7 @@ stmtmulti: stmtmulti ';' stmt
stmt :
AlterEventTrigStmt
+ | AlterCollationStmt
| AlterDatabaseStmt
| AlterDatabaseSetStmt
| AlterDefaultPrivilegesStmt
@@ -881,8 +946,10 @@ stmt :
| AlterTableStmt
| AlterTblSpcStmt
| AlterCompositeTypeStmt
+ | AlterPublicationStmt
| AlterRoleSetStmt
| AlterRoleStmt
+ | AlterSubscriptionStmt
| AlterTSConfigurationStmt
| AlterTSDictionaryStmt
| AlterUserMappingStmt
@@ -914,12 +981,15 @@ stmt :
| CreateNodeStmt
| CreateOpClassStmt
| CreateOpFamilyStmt
+ | CreatePublicationStmt
| AlterOpFamilyStmt
| CreatePolicyStmt
| CreatePLangStmt
| CreateSchemaStmt
| CreateSeqStmt
| CreateStmt
+ | CreateSubscriptionStmt
+ | CreateStatsStmt
| CreateTableSpaceStmt
| CreateTransformStmt
| CreateTrigStmt
@@ -936,21 +1006,17 @@ stmt :
| DoStmt
| DropAssertStmt
| DropCastStmt
- | DropFdwStmt
- | DropForeignServerStmt
| DropGroupStmt
| DropNodeGroupStmt
| DropNodeStmt
| DropOpClassStmt
| DropOpFamilyStmt
| DropOwnedStmt
- | DropPolicyStmt
| DropPLangStmt
- | DropRuleStmt
| DropStmt
+ | DropSubscriptionStmt
| DropTableSpaceStmt
| DropTransformStmt
- | DropTrigStmt
| DropRoleStmt
| DropUserStmt
| DropUserMappingStmt
@@ -1037,38 +1103,46 @@ AlterOptRoleElem:
PASSWORD Sconst
{
$$ = makeDefElem("password",
- (Node *)makeString($2));
+ (Node *)makeString($2), @1);
}
| PASSWORD NULL_P
{
- $$ = makeDefElem("password", NULL);
+ $$ = makeDefElem("password", NULL, @1);
}
| ENCRYPTED PASSWORD Sconst
{
- $$ = makeDefElem("encryptedPassword",
- (Node *)makeString($3));
+ /*
+ * These days, passwords are always stored in encrypted
+ * form, so there is no difference between PASSWORD and
+ * ENCRYPTED PASSWORD.
+ */
+ $$ = makeDefElem("password",
+ (Node *)makeString($3), @1);
}
| UNENCRYPTED PASSWORD Sconst
{
- $$ = makeDefElem("unencryptedPassword",
- (Node *)makeString($3));
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("UNENCRYPTED PASSWORD is no longer supported"),
+ errhint("Remove UNENCRYPTED to store the password in encrypted form instead."),
+ parser_errposition(@1)));
}
| INHERIT
{
- $$ = makeDefElem("inherit", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("inherit", (Node *)makeInteger(TRUE), @1);
}
| CONNECTION LIMIT SignedIconst
{
- $$ = makeDefElem("connectionlimit", (Node *)makeInteger($3));
+ $$ = makeDefElem("connectionlimit", (Node *)makeInteger($3), @1);
}
| VALID UNTIL Sconst
{
- $$ = makeDefElem("validUntil", (Node *)makeString($3));
+ $$ = makeDefElem("validUntil", (Node *)makeString($3), @1);
}
/* Supported but not documented for roles, for use by ALTER GROUP. */
| USER role_list
{
- $$ = makeDefElem("rolemembers", (Node *)$2);
+ $$ = makeDefElem("rolemembers", (Node *)$2, @1);
}
| IDENT
{
@@ -1078,36 +1152,36 @@ AlterOptRoleElem:
* size of the main parser.
*/
if (strcmp($1, "superuser") == 0)
- $$ = makeDefElem("superuser", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("superuser", (Node *)makeInteger(TRUE), @1);
else if (strcmp($1, "nosuperuser") == 0)
- $$ = makeDefElem("superuser", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("superuser", (Node *)makeInteger(FALSE), @1);
else if (strcmp($1, "createrole") == 0)
- $$ = makeDefElem("createrole", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("createrole", (Node *)makeInteger(TRUE), @1);
else if (strcmp($1, "nocreaterole") == 0)
- $$ = makeDefElem("createrole", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("createrole", (Node *)makeInteger(FALSE), @1);
else if (strcmp($1, "replication") == 0)
- $$ = makeDefElem("isreplication", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("isreplication", (Node *)makeInteger(TRUE), @1);
else if (strcmp($1, "noreplication") == 0)
- $$ = makeDefElem("isreplication", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("isreplication", (Node *)makeInteger(FALSE), @1);
else if (strcmp($1, "createdb") == 0)
- $$ = makeDefElem("createdb", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("createdb", (Node *)makeInteger(TRUE), @1);
else if (strcmp($1, "nocreatedb") == 0)
- $$ = makeDefElem("createdb", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("createdb", (Node *)makeInteger(FALSE), @1);
else if (strcmp($1, "login") == 0)
- $$ = makeDefElem("canlogin", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("canlogin", (Node *)makeInteger(TRUE), @1);
else if (strcmp($1, "nologin") == 0)
- $$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE), @1);
else if (strcmp($1, "bypassrls") == 0)
- $$ = makeDefElem("bypassrls", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("bypassrls", (Node *)makeInteger(TRUE), @1);
else if (strcmp($1, "nobypassrls") == 0)
- $$ = makeDefElem("bypassrls", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("bypassrls", (Node *)makeInteger(FALSE), @1);
else if (strcmp($1, "noinherit") == 0)
{
/*
* Note that INHERIT is a keyword, so it's handled by main parser, but
* NOINHERIT is handled here.
*/
- $$ = makeDefElem("inherit", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("inherit", (Node *)makeInteger(FALSE), @1);
}
else
ereport(ERROR,
@@ -1122,23 +1196,23 @@ CreateOptRoleElem:
/* The following are not supported by ALTER ROLE/USER/GROUP */
| SYSID Iconst
{
- $$ = makeDefElem("sysid", (Node *)makeInteger($2));
+ $$ = makeDefElem("sysid", (Node *)makeInteger($2), @1);
}
| ADMIN role_list
{
- $$ = makeDefElem("adminmembers", (Node *)$2);
+ $$ = makeDefElem("adminmembers", (Node *)$2, @1);
}
| ROLE role_list
{
- $$ = makeDefElem("rolemembers", (Node *)$2);
+ $$ = makeDefElem("rolemembers", (Node *)$2, @1);
}
| IN_P ROLE role_list
{
- $$ = makeDefElem("addroleto", (Node *)$3);
+ $$ = makeDefElem("addroleto", (Node *)$3, @1);
}
| IN_P GROUP_P role_list
{
- $$ = makeDefElem("addroleto", (Node *)$3);
+ $$ = makeDefElem("addroleto", (Node *)$3, @1);
}
;
@@ -1315,7 +1389,7 @@ AlterGroupStmt:
n->role = $3;
n->action = $4;
n->options = list_make1(makeDefElem("rolemembers",
- (Node *)$6));
+ (Node *)$6, @6));
$$ = (Node *)n;
}
;
@@ -1892,6 +1966,24 @@ AlterTableStmt:
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER TABLE relation_expr partition_cmd
+ {
+ AlterTableStmt *n = makeNode(AlterTableStmt);
+ n->relation = $3;
+ n->cmds = list_make1($4);
+ n->relkind = OBJECT_TABLE;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLE IF_P EXISTS relation_expr partition_cmd
+ {
+ AlterTableStmt *n = makeNode(AlterTableStmt);
+ n->relation = $5;
+ n->cmds = list_make1($6);
+ n->relkind = OBJECT_TABLE;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER TABLE ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
@@ -2037,6 +2129,35 @@ alter_table_cmds:
| alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); }
;
+partition_cmd:
+ /* ALTER TABLE <name> ATTACH PARTITION <table_name> FOR VALUES */
+ ATTACH PARTITION qualified_name ForValues
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ PartitionCmd *cmd = makeNode(PartitionCmd);
+
+ n->subtype = AT_AttachPartition;
+ cmd->name = $3;
+ cmd->bound = $4;
+ n->def = (Node *) cmd;
+
+ $$ = (Node *) n;
+ }
+ /* ALTER TABLE <name> DETACH PARTITION <partition_name> */
+ | DETACH PARTITION qualified_name
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ PartitionCmd *cmd = makeNode(PartitionCmd);
+
+ n->subtype = AT_DetachPartition;
+ cmd->name = $3;
+ cmd->bound = NULL;
+ n->def = (Node *) cmd;
+
+ $$ = (Node *) n;
+ }
+ ;
+
alter_table_cmd:
/* ALTER TABLE <name> ADD <coldef> */
ADD_P columnDef
@@ -2135,6 +2256,50 @@ alter_table_cmd:
n->def = (Node *) makeString($6);
$$ = (Node *)n;
}
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> ADD GENERATED ... AS IDENTITY ... */
+ | ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ Constraint *c = makeNode(Constraint);
+
+ c->contype = CONSTR_IDENTITY;
+ c->generated_when = $6;
+ c->options = $9;
+ c->location = @5;
+
+ n->subtype = AT_AddIdentity;
+ n->name = $3;
+ n->def = (Node *) c;
+
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET <sequence options>/RESET */
+ | ALTER opt_column ColId alter_identity_column_option_list
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetIdentity;
+ n->name = $3;
+ n->def = (Node *) $4;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP IDENTITY */
+ | ALTER opt_column ColId DROP IDENTITY_P
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropIdentity;
+ n->name = $3;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP IDENTITY IF EXISTS */
+ | ALTER opt_column ColId DROP IDENTITY_P IF_P EXISTS
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropIdentity;
+ n->name = $3;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
/* ALTER TABLE <name> DROP [COLUMN] IF EXISTS <colname> [RESTRICT|CASCADE] */
| DROP opt_column IF_P EXISTS ColId opt_drop_behavior
{
@@ -2589,23 +2754,123 @@ reloption_list:
reloption_elem:
ColLabel '=' def_arg
{
- $$ = makeDefElem($1, (Node *) $3);
+ $$ = makeDefElem($1, (Node *) $3, @1);
}
| ColLabel
{
- $$ = makeDefElem($1, NULL);
+ $$ = makeDefElem($1, NULL, @1);
}
| ColLabel '.' ColLabel '=' def_arg
{
$$ = makeDefElemExtended($1, $3, (Node *) $5,
- DEFELEM_UNSPEC);
+ DEFELEM_UNSPEC, @1);
}
| ColLabel '.' ColLabel
{
- $$ = makeDefElemExtended($1, $3, NULL, DEFELEM_UNSPEC);
+ $$ = makeDefElemExtended($1, $3, NULL, DEFELEM_UNSPEC, @1);
}
;
+alter_identity_column_option_list:
+ alter_identity_column_option
+ { $$ = list_make1($1); }
+ | alter_identity_column_option_list alter_identity_column_option
+ { $$ = lappend($1, $2); }
+ ;
+
+alter_identity_column_option:
+ RESTART
+ {
+ $$ = makeDefElem("restart", NULL, @1);
+ }
+ | RESTART opt_with NumericOnly
+ {
+ $$ = makeDefElem("restart", (Node *)$3, @1);
+ }
+ | SET SeqOptElem
+ {
+ if (strcmp($2->defname, "as") == 0 ||
+ strcmp($2->defname, "restart") == 0 ||
+ strcmp($2->defname, "owned_by") == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("sequence option \"%s\" not supported here", $2->defname),
+ parser_errposition(@2)));
+ $$ = $2;
+ }
+ | SET GENERATED generated_when
+ {
+ $$ = makeDefElem("generated", (Node *) makeInteger($3), @1);
+ }
+ ;
+
+ForValues:
+ /* a LIST partition */
+ FOR VALUES IN_P '(' partbound_datum_list ')'
+ {
+ PartitionBoundSpec *n = makeNode(PartitionBoundSpec);
+
+ n->strategy = PARTITION_STRATEGY_LIST;
+ n->listdatums = $5;
+ n->location = @3;
+
+ $$ = n;
+ }
+
+ /* a RANGE partition */
+ | FOR VALUES FROM '(' range_datum_list ')' TO '(' range_datum_list ')'
+ {
+ PartitionBoundSpec *n = makeNode(PartitionBoundSpec);
+
+ n->strategy = PARTITION_STRATEGY_RANGE;
+ n->lowerdatums = $5;
+ n->upperdatums = $9;
+ n->location = @3;
+
+ $$ = n;
+ }
+ ;
+
+partbound_datum:
+ Sconst { $$ = makeStringConst($1, @1); }
+ | NumericOnly { $$ = makeAConst($1, @1); }
+ | NULL_P { $$ = makeNullAConst(@1); }
+ ;
+
+partbound_datum_list:
+ partbound_datum { $$ = list_make1($1); }
+ | partbound_datum_list ',' partbound_datum
+ { $$ = lappend($1, $3); }
+ ;
+
+range_datum_list:
+ PartitionRangeDatum { $$ = list_make1($1); }
+ | range_datum_list ',' PartitionRangeDatum
+ { $$ = lappend($1, $3); }
+ ;
+
+PartitionRangeDatum:
+ UNBOUNDED
+ {
+ PartitionRangeDatum *n = makeNode(PartitionRangeDatum);
+
+ n->infinite = true;
+ n->value = NULL;
+ n->location = @1;
+
+ $$ = (Node *) n;
+ }
+ | partbound_datum
+ {
+ PartitionRangeDatum *n = makeNode(PartitionRangeDatum);
+
+ n->infinite = false;
+ n->value = $1;
+ n->location = @1;
+
+ $$ = (Node *) n;
+ }
+ ;
/*****************************************************************************
*
@@ -2812,59 +3077,59 @@ copy_opt_list:
copy_opt_item:
BINARY
{
- $$ = makeDefElem("format", (Node *)makeString("binary"));
+ $$ = makeDefElem("format", (Node *)makeString("binary"), @1);
}
| OIDS
{
- $$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("oids", (Node *)makeInteger(TRUE), @1);
}
| FREEZE
{
- $$ = makeDefElem("freeze", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("freeze", (Node *)makeInteger(TRUE), @1);
}
| DELIMITER opt_as Sconst
{
- $$ = makeDefElem("delimiter", (Node *)makeString($3));
+ $$ = makeDefElem("delimiter", (Node *)makeString($3), @1);
}
| NULL_P opt_as Sconst
{
- $$ = makeDefElem("null", (Node *)makeString($3));
+ $$ = makeDefElem("null", (Node *)makeString($3), @1);
}
| CSV
{
- $$ = makeDefElem("format", (Node *)makeString("csv"));
+ $$ = makeDefElem("format", (Node *)makeString("csv"), @1);
}
| HEADER_P
{
- $$ = makeDefElem("header", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("header", (Node *)makeInteger(TRUE), @1);
}
| QUOTE opt_as Sconst
{
- $$ = makeDefElem("quote", (Node *)makeString($3));
+ $$ = makeDefElem("quote", (Node *)makeString($3), @1);
}
| ESCAPE opt_as Sconst
{
- $$ = makeDefElem("escape", (Node *)makeString($3));
+ $$ = makeDefElem("escape", (Node *)makeString($3), @1);
}
| FORCE QUOTE columnList
{
- $$ = makeDefElem("force_quote", (Node *)$3);
+ $$ = makeDefElem("force_quote", (Node *)$3, @1);
}
| FORCE QUOTE '*'
{
- $$ = makeDefElem("force_quote", (Node *)makeNode(A_Star));
+ $$ = makeDefElem("force_quote", (Node *)makeNode(A_Star), @1);
}
| FORCE NOT NULL_P columnList
{
- $$ = makeDefElem("force_not_null", (Node *)$4);
+ $$ = makeDefElem("force_not_null", (Node *)$4, @1);
}
| FORCE NULL_P columnList
{
- $$ = makeDefElem("force_null", (Node *)$3);
+ $$ = makeDefElem("force_null", (Node *)$3, @1);
}
| ENCODING Sconst
{
- $$ = makeDefElem("encoding", (Node *)makeString($2));
+ $$ = makeDefElem("encoding", (Node *)makeString($2), @1);
}
;
@@ -2873,7 +3138,7 @@ copy_opt_item:
opt_binary:
BINARY
{
- $$ = makeDefElem("format", (Node *)makeString("binary"));
+ $$ = makeDefElem("format", (Node *)makeString("binary"), @1);
}
| /*EMPTY*/ { $$ = NULL; }
;
@@ -2881,7 +3146,7 @@ opt_binary:
opt_oids:
WITH OIDS
{
- $$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("oids", (Node *)makeInteger(TRUE), @1);
}
| /*EMPTY*/ { $$ = NULL; }
;
@@ -2889,7 +3154,7 @@ opt_oids:
copy_delimiter:
opt_using DELIMITERS Sconst
{
- $$ = makeDefElem("delimiter", (Node *)makeString($3));
+ $$ = makeDefElem("delimiter", (Node *)makeString($3), @2);
}
| /*EMPTY*/ { $$ = NULL; }
;
@@ -2914,7 +3179,7 @@ copy_generic_opt_list:
copy_generic_opt_elem:
ColLabel copy_generic_opt_arg
{
- $$ = makeDefElem($1, $2);
+ $$ = makeDefElem($1, $2, @1);
}
;
@@ -2958,7 +3223,7 @@ copy_generic_opt_arg_list_item:
*****************************************************************************/
CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
- OptInherit OptWith OnCommitOption OptTableSpace
+ OptInherit OptPartitionSpec OptWith OnCommitOption OptTableSpace
/* PGXC_BEGIN */
OptDistributeBy OptSubCluster
/* PGXC_END */
@@ -2968,11 +3233,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->relation = $4;
n->tableElts = $6;
n->inhRelations = $8;
+ n->partspec = $9;
n->ofTypename = NULL;
n->constraints = NIL;
- n->options = $9;
- n->oncommit = $10;
- n->tablespacename = $11;
+ n->options = $10;
+ n->oncommit = $11;
+ n->tablespacename = $12;
n->if_not_exists = false;
/* PGXC_BEGIN */
if ($2 == RELPERSISTENCE_LOCAL_TEMP)
@@ -2981,14 +3247,14 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->islocal = true;
}
n->relkind = RELKIND_RELATION;
- n->distributeby = $12;
- n->subcluster = $13;
+ n->distributeby = $13;
+ n->subcluster = $14;
/* PGXC_END */
$$ = (Node *)n;
}
| CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '('
- OptTableElementList ')' OptInherit OptWith OnCommitOption
- OptTableSpace
+ OptTableElementList ')' OptInherit OptPartitionSpec OptWith
+ OnCommitOption OptTableSpace
/* PGXC_BEGIN */
OptDistributeBy OptSubCluster
/* PGXC_END */
@@ -2998,11 +3264,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->relation = $7;
n->tableElts = $9;
n->inhRelations = $11;
+ n->partspec = $12;
n->ofTypename = NULL;
n->constraints = NIL;
- n->options = $12;
- n->oncommit = $13;
- n->tablespacename = $14;
+ n->options = $13;
+ n->oncommit = $14;
+ n->tablespacename = $15;
n->if_not_exists = true;
/* PGXC_BEGIN */
if ($2 == RELPERSISTENCE_LOCAL_TEMP)
@@ -3011,8 +3278,8 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->islocal = true;
}
n->relkind = RELKIND_RELATION;
- n->distributeby = $15;
- n->subcluster = $16;
+ n->distributeby = $16;
+ n->subcluster = $17;
if (n->inhRelations != NULL && n->distributeby != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -3022,7 +3289,8 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$$ = (Node *)n;
}
| CREATE OptTemp TABLE qualified_name OF any_name
- OptTypedTableElementList OptWith OnCommitOption OptTableSpace
+ OptTypedTableElementList OptPartitionSpec OptWith OnCommitOption
+ OptTableSpace
/* PGXC_BEGIN */
OptDistributeBy OptSubCluster
/* PGXC_END */
@@ -3032,12 +3300,13 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->relation = $4;
n->tableElts = $7;
n->inhRelations = NIL;
+ n->partspec = $8;
n->ofTypename = makeTypeNameFromNameList($6);
n->ofTypename->location = @6;
n->constraints = NIL;
- n->options = $8;
- n->oncommit = $9;
- n->tablespacename = $10;
+ n->options = $9;
+ n->oncommit = $10;
+ n->tablespacename = $11;
n->if_not_exists = false;
/* PGXC_BEGIN */
if ($2 == RELPERSISTENCE_LOCAL_TEMP)
@@ -3046,8 +3315,8 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->islocal = true;
}
n->relkind = RELKIND_RELATION;
- n->distributeby = $11;
- n->subcluster = $12;
+ n->distributeby = $12;
+ n->subcluster = $13;
if (n->inhRelations != NULL && n->distributeby != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -3057,7 +3326,8 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$$ = (Node *)n;
}
| CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name
- OptTypedTableElementList OptWith OnCommitOption OptTableSpace
+ OptTypedTableElementList OptPartitionSpec OptWith OnCommitOption
+ OptTableSpace
/* PGXC_BEGIN */
OptDistributeBy OptSubCluster
/* PGXC_END */
@@ -3067,12 +3337,13 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->relation = $7;
n->tableElts = $10;
n->inhRelations = NIL;
+ n->partspec = $11;
n->ofTypename = makeTypeNameFromNameList($9);
n->ofTypename->location = @9;
n->constraints = NIL;
- n->options = $11;
- n->oncommit = $12;
- n->tablespacename = $13;
+ n->options = $12;
+ n->oncommit = $13;
+ n->tablespacename = $14;
n->if_not_exists = true;
/* PGXC_BEGIN */
if ($2 == RELPERSISTENCE_LOCAL_TEMP)
@@ -3081,8 +3352,8 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->islocal = true;
}
n->relkind = RELKIND_RELATION;
- n->distributeby = $14;
- n->subcluster = $15;
+ n->distributeby = $15;
+ n->subcluster = $16;
if (n->inhRelations != NULL && n->distributeby != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -3091,6 +3362,44 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
/* PGXC_END */
$$ = (Node *)n;
}
+ | CREATE OptTemp TABLE qualified_name PARTITION OF qualified_name
+ OptTypedTableElementList ForValues OptPartitionSpec OptWith
+ OnCommitOption OptTableSpace
+ {
+ CreateStmt *n = makeNode(CreateStmt);
+ $4->relpersistence = $2;
+ n->relation = $4;
+ n->tableElts = $8;
+ n->inhRelations = list_make1($7);
+ n->partbound = $9;
+ n->partspec = $10;
+ n->ofTypename = NULL;
+ n->constraints = NIL;
+ n->options = $11;
+ n->oncommit = $12;
+ n->tablespacename = $13;
+ n->if_not_exists = false;
+ $$ = (Node *)n;
+ }
+ | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name PARTITION OF
+ qualified_name OptTypedTableElementList ForValues OptPartitionSpec
+ OptWith OnCommitOption OptTableSpace
+ {
+ CreateStmt *n = makeNode(CreateStmt);
+ $7->relpersistence = $2;
+ n->relation = $7;
+ n->tableElts = $11;
+ n->inhRelations = list_make1($10);
+ n->partbound = $12;
+ n->partspec = $13;
+ n->ofTypename = NULL;
+ n->constraints = NIL;
+ n->options = $14;
+ n->oncommit = $15;
+ n->tablespacename = $16;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
;
/*
@@ -3178,6 +3487,7 @@ columnDef: ColId Typename create_generic_options ColQualList
n->is_local = true;
n->is_not_null = false;
n->is_from_type = false;
+ n->is_from_parent = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
@@ -3190,7 +3500,26 @@ columnDef: ColId Typename create_generic_options ColQualList
}
;
-columnOptions: ColId WITH OPTIONS ColQualList
+columnOptions: ColId ColQualList
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->typeName = NULL;
+ n->inhcount = 0;
+ n->is_local = true;
+ n->is_not_null = false;
+ n->is_from_type = false;
+ n->is_from_parent = false;
+ n->storage = 0;
+ n->raw_default = NULL;
+ n->cooked_default = NULL;
+ n->collOid = InvalidOid;
+ SplitColQualList($2, &n->constraints, &n->collClause,
+ yyscanner);
+ n->location = @1;
+ $$ = (Node *)n;
+ }
+ | ColId WITH OPTIONS ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
@@ -3199,6 +3528,7 @@ columnOptions: ColId WITH OPTIONS ColQualList
n->is_local = true;
n->is_not_null = false;
n->is_from_type = false;
+ n->is_from_parent = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
@@ -3218,8 +3548,7 @@ ColQualList:
ColConstraint:
CONSTRAINT name ColConstraintElem
{
- Constraint *n = (Constraint *) $3;
- Assert(IsA(n, Constraint));
+ Constraint *n = castNode(Constraint, $3);
n->conname = $2;
n->location = @1;
$$ = (Node *) n;
@@ -3314,6 +3643,15 @@ ColConstraintElem:
n->cooked_expr = NULL;
$$ = (Node *)n;
}
+ | GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_IDENTITY;
+ n->generated_when = $2;
+ n->options = $5;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
| REFERENCES qualified_name opt_column_list key_match key_actions
{
Constraint *n = makeNode(Constraint);
@@ -3331,6 +3669,11 @@ ColConstraintElem:
}
;
+generated_when:
+ ALWAYS { $$ = ATTRIBUTE_IDENTITY_ALWAYS; }
+ | BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; }
+ ;
+
/*
* ConstraintAttr represents constraint attributes, which we parse as if
* they were independent constraint clauses, in order to avoid shift/reduce
@@ -3397,6 +3740,7 @@ TableLikeOptionList:
TableLikeOption:
DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
| CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
+ | IDENTITY_P { $$ = CREATE_TABLE_LIKE_IDENTITY; }
| INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; }
| STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
| COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
@@ -3411,8 +3755,7 @@ TableLikeOption:
TableConstraint:
CONSTRAINT name ConstraintElem
{
- Constraint *n = (Constraint *) $3;
- Assert(IsA(n, Constraint));
+ Constraint *n = castNode(Constraint, $3);
n->conname = $2;
n->location = @1;
$$ = (Node *) n;
@@ -3632,11 +3975,70 @@ OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
+/* Optional partition key specification */
+OptPartitionSpec: PartitionSpec { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+PartitionSpec: PARTITION BY part_strategy '(' part_params ')'
+ {
+ PartitionSpec *n = makeNode(PartitionSpec);
+
+ n->strategy = $3;
+ n->partParams = $5;
+ n->location = @1;
+
+ $$ = n;
+ }
+ ;
+
+part_strategy: IDENT { $$ = $1; }
+ | unreserved_keyword { $$ = pstrdup($1); }
+ ;
+
+part_params: part_elem { $$ = list_make1($1); }
+ | part_params ',' part_elem { $$ = lappend($1, $3); }
+ ;
+
+part_elem: ColId opt_collate opt_class
+ {
+ PartitionElem *n = makeNode(PartitionElem);
+
+ n->name = $1;
+ n->expr = NULL;
+ n->collation = $2;
+ n->opclass = $3;
+ n->location = @1;
+ $$ = n;
+ }
+ | func_expr_windowless opt_collate opt_class
+ {
+ PartitionElem *n = makeNode(PartitionElem);
+
+ n->name = NULL;
+ n->expr = $1;
+ n->collation = $2;
+ n->opclass = $3;
+ n->location = @1;
+ $$ = n;
+ }
+ | '(' a_expr ')' opt_collate opt_class
+ {
+ PartitionElem *n = makeNode(PartitionElem);
+
+ n->name = NULL;
+ n->expr = $2;
+ n->collation = $4;
+ n->opclass = $5;
+ n->location = @1;
+ $$ = n;
+ }
+ ;
/* WITH (options) is preferred, WITH OIDS and WITHOUT OIDS are legacy forms */
OptWith:
WITH reloptions { $$ = $2; }
- | WITH OIDS { $$ = list_make1(defWithOids(true)); }
- | WITHOUT OIDS { $$ = list_make1(defWithOids(false)); }
+ | WITH OIDS { $$ = list_make1(makeDefElem("oids", (Node *) makeInteger(true), @1)); }
+ | WITHOUT OIDS { $$ = list_make1(makeDefElem("oids", (Node *) makeInteger(false), @1)); }
| /*EMPTY*/ { $$ = NIL; }
;
@@ -3780,6 +4182,33 @@ OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; }
ExistingIndex: USING INDEX index_name { $$ = $3; }
;
+/*****************************************************************************
+ *
+ * QUERY :
+ * CREATE STATISTICS stats_name [(stat types)]
+ * ON expression-list FROM from_list
+ *
+ * Note: the expectation here is that the clauses after ON are a subset of
+ * SELECT syntax, allowing for expressions and joined tables, and probably
+ * someday a WHERE clause. Much less than that is currently implemented,
+ * but the grammar accepts it and then we'll throw FEATURE_NOT_SUPPORTED
+ * errors as necessary at execution.
+ *
+ *****************************************************************************/
+
+CreateStatsStmt:
+ CREATE opt_if_not_exists STATISTICS any_name
+ opt_name_list ON expr_list FROM from_list
+ {
+ CreateStatsStmt *n = makeNode(CreateStatsStmt);
+ n->defnames = $4;
+ n->stat_types = $5;
+ n->exprs = $7;
+ n->relations = $9;
+ n->if_not_exists = $2;
+ $$ = (Node *)n;
+ }
+ ;
/*****************************************************************************
*
@@ -3992,57 +4421,70 @@ OptSeqOptList: SeqOptList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
+OptParenthesizedSeqOptList: '(' SeqOptList ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
SeqOptList: SeqOptElem { $$ = list_make1($1); }
| SeqOptList SeqOptElem { $$ = lappend($1, $2); }
;
-SeqOptElem: CACHE NumericOnly
+SeqOptElem: AS SimpleTypename
+ {
+ $$ = makeDefElem("as", (Node *)$2, @1);
+ }
+ | CACHE NumericOnly
{
- $$ = makeDefElem("cache", (Node *)$2);
+ $$ = makeDefElem("cache", (Node *)$2, @1);
}
| CYCLE
{
- $$ = makeDefElem("cycle", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("cycle", (Node *)makeInteger(TRUE), @1);
}
| NO CYCLE
{
- $$ = makeDefElem("cycle", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("cycle", (Node *)makeInteger(FALSE), @1);
}
| INCREMENT opt_by NumericOnly
{
- $$ = makeDefElem("increment", (Node *)$3);
+ $$ = makeDefElem("increment", (Node *)$3, @1);
}
| MAXVALUE NumericOnly
{
- $$ = makeDefElem("maxvalue", (Node *)$2);
+ $$ = makeDefElem("maxvalue", (Node *)$2, @1);
}
| MINVALUE NumericOnly
{
- $$ = makeDefElem("minvalue", (Node *)$2);
+ $$ = makeDefElem("minvalue", (Node *)$2, @1);
}
| NO MAXVALUE
{
- $$ = makeDefElem("maxvalue", NULL);
+ $$ = makeDefElem("maxvalue", NULL, @1);
}
| NO MINVALUE
{
- $$ = makeDefElem("minvalue", NULL);
+ $$ = makeDefElem("minvalue", NULL, @1);
}
| OWNED BY any_name
{
- $$ = makeDefElem("owned_by", (Node *)$3);
+ $$ = makeDefElem("owned_by", (Node *)$3, @1);
+ }
+ | SEQUENCE NAME_P any_name
+ {
+ /* not documented, only used by pg_dump */
+ $$ = makeDefElem("sequence_name", (Node *)$3, @1);
}
| START opt_with NumericOnly
{
- $$ = makeDefElem("start", (Node *)$3);
+ $$ = makeDefElem("start", (Node *)$3, @1);
}
| RESTART
{
- $$ = makeDefElem("restart", NULL);
+ $$ = makeDefElem("restart", NULL, @1);
}
| RESTART opt_with NumericOnly
{
- $$ = makeDefElem("restart", (Node *)$3);
+ $$ = makeDefElem("restart", (Node *)$3, @1);
}
;
@@ -4052,6 +4494,7 @@ opt_by: BY {}
NumericOnly:
FCONST { $$ = makeFloat($1); }
+ | '+' FCONST { $$ = makeFloat($2); }
| '-' FCONST
{
$$ = makeFloat($2);
@@ -4133,8 +4576,7 @@ DropPLangStmt:
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_LANGUAGE;
- n->objects = list_make1(list_make1(makeString($4)));
- n->arguments = NIL;
+ n->objects = list_make1(makeString($4));
n->behavior = $5;
n->missing_ok = false;
n->concurrent = false;
@@ -4144,7 +4586,7 @@ DropPLangStmt:
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_LANGUAGE;
- n->objects = list_make1(list_make1(makeString($6)));
+ n->objects = list_make1(makeString($6));
n->behavior = $7;
n->missing_ok = true;
n->concurrent = false;
@@ -4241,19 +4683,19 @@ create_extension_opt_list:
create_extension_opt_item:
SCHEMA name
{
- $$ = makeDefElem("schema", (Node *)makeString($2));
+ $$ = makeDefElem("schema", (Node *)makeString($2), @1);
}
| VERSION_P NonReservedWord_or_Sconst
{
- $$ = makeDefElem("new_version", (Node *)makeString($2));
+ $$ = makeDefElem("new_version", (Node *)makeString($2), @1);
}
| FROM NonReservedWord_or_Sconst
{
- $$ = makeDefElem("old_version", (Node *)makeString($2));
+ $$ = makeDefElem("old_version", (Node *)makeString($2), @1);
}
| CASCADE
{
- $$ = makeDefElem("cascade", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("cascade", (Node *)makeInteger(TRUE), @1);
}
;
@@ -4282,7 +4724,7 @@ alter_extension_opt_list:
alter_extension_opt_item:
TO NonReservedWord_or_Sconst
{
- $$ = makeDefElem("new_version", (Node *)makeString($2));
+ $$ = makeDefElem("new_version", (Node *)makeString($2), @1);
}
;
@@ -4293,14 +4735,22 @@ alter_extension_opt_item:
*****************************************************************************/
AlterExtensionContentsStmt:
- ALTER EXTENSION name add_drop AGGREGATE func_name aggr_args
+ ALTER EXTENSION name add_drop ACCESS METHOD name
+ {
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
+ n->extname = $3;
+ n->action = $4;
+ n->objtype = OBJECT_ACCESS_METHOD;
+ n->object = (Node *) makeString($7);
+ $$ = (Node *)n;
+ }
+ | ALTER EXTENSION name add_drop AGGREGATE aggregate_with_argtypes
{
AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_AGGREGATE;
- n->objname = $6;
- n->objargs = extractAggrArgTypes($7);
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop CAST '(' Typename AS Typename ')'
@@ -4309,8 +4759,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_CAST;
- n->objname = list_make1($7);
- n->objargs = list_make1($9);
+ n->object = (Node *) list_make2($7, $9);
$$ = (Node *) n;
}
| ALTER EXTENSION name add_drop COLLATION any_name
@@ -4319,7 +4768,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_COLLATION;
- n->objname = $6;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop CONVERSION_P any_name
@@ -4328,7 +4777,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_CONVERSION;
- n->objname = $6;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop DOMAIN_P Typename
@@ -4337,7 +4786,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_DOMAIN;
- n->objname = list_make1($6);
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop FUNCTION function_with_argtypes
@@ -4346,8 +4795,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_FUNCTION;
- n->objname = $6->funcname;
- n->objargs = $6->funcargs;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop opt_procedural LANGUAGE name
@@ -4356,17 +4804,16 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_LANGUAGE;
- n->objname = list_make1(makeString($7));
+ n->object = (Node *) makeString($7);
$$ = (Node *)n;
}
- | ALTER EXTENSION name add_drop OPERATOR any_operator oper_argtypes
+ | ALTER EXTENSION name add_drop OPERATOR operator_with_argtypes
{
AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_OPERATOR;
- n->objname = $6;
- n->objargs = $7;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING access_method
@@ -4375,7 +4822,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_OPCLASS;
- n->objname = lcons(makeString($9), $7);
+ n->object = (Node *) lcons(makeString($9), $7);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING access_method
@@ -4384,7 +4831,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_OPFAMILY;
- n->objname = lcons(makeString($9), $7);
+ n->object = (Node *) lcons(makeString($9), $7);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop SCHEMA name
@@ -4393,7 +4840,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_SCHEMA;
- n->objname = list_make1(makeString($6));
+ n->object = (Node *) makeString($6);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop EVENT TRIGGER name
@@ -4402,7 +4849,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_EVENT_TRIGGER;
- n->objname = list_make1(makeString($7));
+ n->object = (Node *) makeString($7);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TABLE any_name
@@ -4411,7 +4858,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TABLE;
- n->objname = $6;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TEXT_P SEARCH PARSER any_name
@@ -4420,7 +4867,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSPARSER;
- n->objname = $8;
+ n->object = (Node *) $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TEXT_P SEARCH DICTIONARY any_name
@@ -4429,7 +4876,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSDICTIONARY;
- n->objname = $8;
+ n->object = (Node *) $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TEXT_P SEARCH TEMPLATE any_name
@@ -4438,7 +4885,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSTEMPLATE;
- n->objname = $8;
+ n->object = (Node *) $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TEXT_P SEARCH CONFIGURATION any_name
@@ -4447,7 +4894,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSCONFIGURATION;
- n->objname = $8;
+ n->object = (Node *) $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop SEQUENCE any_name
@@ -4456,7 +4903,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_SEQUENCE;
- n->objname = $6;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop VIEW any_name
@@ -4465,7 +4912,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_VIEW;
- n->objname = $6;
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop MATERIALIZED VIEW any_name
@@ -4474,7 +4921,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_MATVIEW;
- n->objname = $7;
+ n->object = (Node *) $7;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop FOREIGN TABLE any_name
@@ -4483,7 +4930,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_FOREIGN_TABLE;
- n->objname = $7;
+ n->object = (Node *) $7;
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop FOREIGN DATA_P WRAPPER name
@@ -4492,7 +4939,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_FDW;
- n->objname = list_make1(makeString($8));
+ n->object = (Node *) makeString($8);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop SERVER name
@@ -4501,7 +4948,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_FOREIGN_SERVER;
- n->objname = list_make1(makeString($6));
+ n->object = (Node *) makeString($6);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TRANSFORM FOR Typename LANGUAGE name
@@ -4510,8 +4957,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TRANSFORM;
- n->objname = list_make1($7);
- n->objargs = list_make1(makeString($9));
+ n->object = (Node *) list_make2($7, makeString($9));
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop TYPE_P Typename
@@ -4520,7 +4966,7 @@ AlterExtensionContentsStmt:
n->extname = $3;
n->action = $4;
n->objtype = OBJECT_TYPE;
- n->objname = list_make1($6);
+ n->object = (Node *) $6;
$$ = (Node *)n;
}
;
@@ -4543,10 +4989,10 @@ CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic
;
fdw_option:
- HANDLER handler_name { $$ = makeDefElem("handler", (Node *)$2); }
- | NO HANDLER { $$ = makeDefElem("handler", NULL); }
- | VALIDATOR handler_name { $$ = makeDefElem("validator", (Node *)$2); }
- | NO VALIDATOR { $$ = makeDefElem("validator", NULL); }
+ HANDLER handler_name { $$ = makeDefElem("handler", (Node *)$2, @1); }
+ | NO HANDLER { $$ = makeDefElem("handler", NULL, @1); }
+ | VALIDATOR handler_name { $$ = makeDefElem("validator", (Node *)$2, @1); }
+ | NO VALIDATOR { $$ = makeDefElem("validator", NULL, @1); }
;
fdw_options:
@@ -4562,37 +5008,6 @@ opt_fdw_options:
/*****************************************************************************
*
* QUERY :
- * DROP FOREIGN DATA WRAPPER name
- *
- ****************************************************************************/
-
-DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_FDW;
- n->objects = list_make1(list_make1(makeString($5)));
- n->arguments = NIL;
- n->missing_ok = false;
- n->behavior = $6;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- | DROP FOREIGN DATA_P WRAPPER IF_P EXISTS name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_FDW;
- n->objects = list_make1(list_make1(makeString($7)));
- n->arguments = NIL;
- n->missing_ok = true;
- n->behavior = $8;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- ;
-
-/*****************************************************************************
- *
- * QUERY :
* ALTER FOREIGN DATA WRAPPER name options
*
****************************************************************************/
@@ -4665,14 +5080,14 @@ alter_generic_option_elem:
}
| DROP generic_option_name
{
- $$ = makeDefElemExtended(NULL, $2, NULL, DEFELEM_DROP);
+ $$ = makeDefElemExtended(NULL, $2, NULL, DEFELEM_DROP, @2);
}
;
generic_option_elem:
generic_option_name generic_option_arg
{
- $$ = makeDefElem($1, $2);
+ $$ = makeDefElem($1, $2, @1);
}
;
@@ -4701,6 +5116,19 @@ CreateForeignServerStmt: CREATE SERVER name opt_type opt_foreign_server_version
n->version = $5;
n->fdwname = $9;
n->options = $10;
+ n->if_not_exists = false;
+ $$ = (Node *) n;
+ }
+ | CREATE SERVER IF_P NOT EXISTS name opt_type opt_foreign_server_version
+ FOREIGN DATA_P WRAPPER name create_generic_options
+ {
+ CreateForeignServerStmt *n = makeNode(CreateForeignServerStmt);
+ n->servername = $6;
+ n->servertype = $7;
+ n->version = $8;
+ n->fdwname = $12;
+ n->options = $13;
+ n->if_not_exists = true;
$$ = (Node *) n;
}
;
@@ -4724,37 +5152,6 @@ opt_foreign_server_version:
/*****************************************************************************
*
* QUERY :
- * DROP SERVER name
- *
- ****************************************************************************/
-
-DropForeignServerStmt: DROP SERVER name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_FOREIGN_SERVER;
- n->objects = list_make1(list_make1(makeString($3)));
- n->arguments = NIL;
- n->missing_ok = false;
- n->behavior = $4;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- | DROP SERVER IF_P EXISTS name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_FOREIGN_SERVER;
- n->objects = list_make1(list_make1(makeString($5)));
- n->arguments = NIL;
- n->missing_ok = true;
- n->behavior = $6;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- ;
-
-/*****************************************************************************
- *
- * QUERY :
* ALTER SERVER name [VERSION] [OPTIONS]
*
****************************************************************************/
@@ -4833,6 +5230,48 @@ CreateForeignTableStmt:
n->options = $14;
$$ = (Node *) n;
}
+ | CREATE FOREIGN TABLE qualified_name
+ PARTITION OF qualified_name OptTypedTableElementList ForValues
+ SERVER name create_generic_options
+ {
+ CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
+ $4->relpersistence = RELPERSISTENCE_PERMANENT;
+ n->base.relation = $4;
+ n->base.inhRelations = list_make1($7);
+ n->base.tableElts = $8;
+ n->base.partbound = $9;
+ n->base.ofTypename = NULL;
+ n->base.constraints = NIL;
+ n->base.options = NIL;
+ n->base.oncommit = ONCOMMIT_NOOP;
+ n->base.tablespacename = NULL;
+ n->base.if_not_exists = false;
+ /* FDW-specific data */
+ n->servername = $11;
+ n->options = $12;
+ $$ = (Node *) n;
+ }
+ | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name
+ PARTITION OF qualified_name OptTypedTableElementList ForValues
+ SERVER name create_generic_options
+ {
+ CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
+ $7->relpersistence = RELPERSISTENCE_PERMANENT;
+ n->base.relation = $7;
+ n->base.inhRelations = list_make1($10);
+ n->base.tableElts = $11;
+ n->base.partbound = $12;
+ n->base.ofTypename = NULL;
+ n->base.constraints = NIL;
+ n->base.options = NIL;
+ n->base.oncommit = ONCOMMIT_NOOP;
+ n->base.tablespacename = NULL;
+ n->base.if_not_exists = true;
+ /* FDW-specific data */
+ n->servername = $14;
+ n->options = $15;
+ $$ = (Node *) n;
+ }
;
/*****************************************************************************
@@ -4922,6 +5361,16 @@ CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_gen
n->user = $5;
n->servername = $7;
n->options = $8;
+ n->if_not_exists = false;
+ $$ = (Node *) n;
+ }
+ | CREATE USER MAPPING IF_P NOT EXISTS FOR auth_ident SERVER name create_generic_options
+ {
+ CreateUserMappingStmt *n = makeNode(CreateUserMappingStmt);
+ n->user = $8;
+ n->servername = $10;
+ n->options = $11;
+ n->if_not_exists = true;
$$ = (Node *) n;
}
;
@@ -4978,26 +5427,29 @@ AlterUserMappingStmt: ALTER USER MAPPING FOR auth_ident SERVER name alter_generi
/*****************************************************************************
*
* QUERIES:
- * CREATE POLICY name ON table [FOR cmd] [TO role, ...]
- * [USING (qual)] [WITH CHECK (with_check)]
+ * CREATE POLICY name ON table
+ * [AS { PERMISSIVE | RESTRICTIVE } ]
+ * [FOR { SELECT | INSERT | UPDATE | DELETE } ]
+ * [TO role, ...]
+ * [USING (qual)] [WITH CHECK (with check qual)]
* ALTER POLICY name ON table [TO role, ...]
- * [USING (qual)] [WITH CHECK (with_check)]
- * DROP POLICY name ON table
+ * [USING (qual)] [WITH CHECK (with check qual)]
*
*****************************************************************************/
CreatePolicyStmt:
- CREATE POLICY name ON qualified_name RowSecurityDefaultForCmd
- RowSecurityDefaultToRole RowSecurityOptionalExpr
- RowSecurityOptionalWithCheck
+ CREATE POLICY name ON qualified_name RowSecurityDefaultPermissive
+ RowSecurityDefaultForCmd RowSecurityDefaultToRole
+ RowSecurityOptionalExpr RowSecurityOptionalWithCheck
{
CreatePolicyStmt *n = makeNode(CreatePolicyStmt);
n->policy_name = $3;
n->table = $5;
- n->cmd_name = $6;
- n->roles = $7;
- n->qual = $8;
- n->with_check = $9;
+ n->permissive = $6;
+ n->cmd_name = $7;
+ n->roles = $8;
+ n->qual = $9;
+ n->with_check = $10;
$$ = (Node *) n;
}
;
@@ -5016,31 +5468,6 @@ AlterPolicyStmt:
}
;
-DropPolicyStmt:
- DROP POLICY name ON any_name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_POLICY;
- n->objects = list_make1(lappend($5, makeString($3)));
- n->arguments = NIL;
- n->behavior = $6;
- n->missing_ok = false;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- | DROP POLICY IF_P EXISTS name ON any_name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_POLICY;
- n->objects = list_make1(lappend($7, makeString($5)));
- n->arguments = NIL;
- n->behavior = $8;
- n->missing_ok = true;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- ;
-
RowSecurityOptionalExpr:
USING '(' a_expr ')' { $$ = $3; }
| /* EMPTY */ { $$ = NULL; }
@@ -5061,6 +5488,24 @@ RowSecurityOptionalToRole:
| /* EMPTY */ { $$ = NULL; }
;
+RowSecurityDefaultPermissive:
+ AS IDENT
+ {
+ if (strcmp($2, "permissive") == 0)
+ $$ = true;
+ else if (strcmp($2, "restrictive") == 0)
+ $$ = false;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized row security option \"%s\"", $2),
+ errhint("Only PERMISSIVE or RESTRICTIVE policies are supported currently."),
+ parser_errposition(@2)));
+
+ }
+ | /* EMPTY */ { $$ = true; }
+ ;
+
RowSecurityDefaultForCmd:
FOR row_security_cmd { $$ = $2; }
| /* EMPTY */ { $$ = "all"; }
@@ -5095,25 +5540,25 @@ CreateAmStmt: CREATE ACCESS METHOD name TYPE_P INDEX HANDLER handler_name
*
* QUERIES :
* CREATE TRIGGER ...
- * DROP TRIGGER ...
*
*****************************************************************************/
CreateTrigStmt:
CREATE TRIGGER name TriggerActionTime TriggerEvents ON
- qualified_name TriggerForSpec TriggerWhen
+ qualified_name TriggerReferencing TriggerForSpec TriggerWhen
EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $3;
n->relation = $7;
- n->funcname = $12;
- n->args = $14;
- n->row = $8;
+ n->funcname = $13;
+ n->args = $15;
+ n->row = $9;
n->timing = $4;
n->events = intVal(linitial($5));
n->columns = (List *) lsecond($5);
- n->whenClause = $9;
+ n->whenClause = $10;
+ n->transitionRels = $8;
n->isconstraint = FALSE;
n->deferrable = FALSE;
n->initdeferred = FALSE;
@@ -5135,6 +5580,7 @@ CreateTrigStmt:
n->events = intVal(linitial($6));
n->columns = (List *) lsecond($6);
n->whenClause = $14;
+ n->transitionRels = NIL;
n->isconstraint = TRUE;
processCASbits($10, @10, "TRIGGER",
&n->deferrable, &n->initdeferred, NULL,
@@ -5187,6 +5633,49 @@ TriggerOneEvent:
{ $$ = list_make2(makeInteger(TRIGGER_TYPE_TRUNCATE), NIL); }
;
+TriggerReferencing:
+ REFERENCING TriggerTransitions { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+TriggerTransitions:
+ TriggerTransition { $$ = list_make1($1); }
+ | TriggerTransitions TriggerTransition { $$ = lappend($1, $2); }
+ ;
+
+TriggerTransition:
+ TransitionOldOrNew TransitionRowOrTable opt_as TransitionRelName
+ {
+ TriggerTransition *n = makeNode(TriggerTransition);
+ n->name = $4;
+ n->isNew = $1;
+ n->isTable = $2;
+ $$ = (Node *)n;
+ }
+ ;
+
+TransitionOldOrNew:
+ NEW { $$ = TRUE; }
+ | OLD { $$ = FALSE; }
+ ;
+
+TransitionRowOrTable:
+ TABLE { $$ = TRUE; }
+ /*
+ * According to the standard, lack of a keyword here implies ROW.
+ * Support for that would require prohibiting ROW entirely here,
+ * reserving the keyword ROW, and/or requiring AS (instead of
+ * allowing it to be optional, as the standard specifies) as the
+ * next token. Requiring ROW seems cleanest and easiest to
+ * explain.
+ */
+ | ROW { $$ = FALSE; }
+ ;
+
+TransitionRelName:
+ ColId { $$ = $1; }
+ ;
+
TriggerForSpec:
FOR TriggerForOptEach TriggerForType
{
@@ -5277,32 +5766,6 @@ ConstraintAttributeElem:
;
-DropTrigStmt:
- DROP TRIGGER name ON any_name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_TRIGGER;
- n->objects = list_make1(lappend($5, makeString($3)));
- n->arguments = NIL;
- n->behavior = $6;
- n->missing_ok = false;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- | DROP TRIGGER IF_P EXISTS name ON any_name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_TRIGGER;
- n->objects = list_make1(lappend($7, makeString($5)));
- n->arguments = NIL;
- n->behavior = $8;
- n->missing_ok = true;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- ;
-
-
/*****************************************************************************
*
* QUERIES :
@@ -5344,7 +5807,7 @@ event_trigger_when_list:
event_trigger_when_item:
ColId IN_P '(' event_trigger_value_list ')'
- { $$ = makeDefElem($1, (Node *) $4); }
+ { $$ = makeDefElem($1, (Node *) $4, @1); }
;
event_trigger_value_list:
@@ -5404,7 +5867,6 @@ DropAssertStmt:
{
DropStmt *n = makeNode(DropStmt);
n->objects = NIL;
- n->arguments = NIL;
n->behavior = $4;
n->removeType = OBJECT_TRIGGER; /* XXX */
ereport(ERROR,
@@ -5543,13 +6005,33 @@ DefineStmt:
n->definition = $4;
$$ = (Node *)n;
}
+ | CREATE COLLATION IF_P NOT EXISTS any_name definition
+ {
+ DefineStmt *n = makeNode(DefineStmt);
+ n->kind = OBJECT_COLLATION;
+ n->args = NIL;
+ n->defnames = $6;
+ n->definition = $7;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
| CREATE COLLATION any_name FROM any_name
{
DefineStmt *n = makeNode(DefineStmt);
n->kind = OBJECT_COLLATION;
n->args = NIL;
n->defnames = $3;
- n->definition = list_make1(makeDefElem("from", (Node *) $5));
+ n->definition = list_make1(makeDefElem("from", (Node *) $5, @5));
+ $$ = (Node *)n;
+ }
+ | CREATE COLLATION IF_P NOT EXISTS any_name FROM any_name
+ {
+ DefineStmt *n = makeNode(DefineStmt);
+ n->kind = OBJECT_COLLATION;
+ n->args = NIL;
+ n->defnames = $6;
+ n->definition = list_make1(makeDefElem("from", (Node *) $8, @8));
+ n->if_not_exists = true;
$$ = (Node *)n;
}
;
@@ -5563,11 +6045,11 @@ def_list: def_elem { $$ = list_make1($1); }
def_elem: ColLabel '=' def_arg
{
- $$ = makeDefElem($1, (Node *) $3);
+ $$ = makeDefElem($1, (Node *) $3, @1);
}
| ColLabel
{
- $$ = makeDefElem($1, NULL);
+ $$ = makeDefElem($1, NULL, @1);
}
;
@@ -5577,6 +6059,7 @@ def_arg: func_type { $$ = (Node *)$1; }
| qual_all_Op { $$ = (Node *)$1; }
| NumericOnly { $$ = (Node *)$1; }
| Sconst { $$ = (Node *)makeString($1); }
+ | NONE { $$ = (Node *)makeString(pstrdup($1)); }
;
old_aggr_definition: '(' old_aggr_list ')' { $$ = $2; }
@@ -5593,7 +6076,7 @@ old_aggr_list: old_aggr_elem { $$ = list_make1($1); }
*/
old_aggr_elem: IDENT '=' def_arg
{
- $$ = makeDefElem($1, (Node *)$3);
+ $$ = makeDefElem($1, (Node *)$3, @1);
}
;
@@ -5619,30 +6102,44 @@ AlterEnumStmt:
{
AlterEnumStmt *n = makeNode(AlterEnumStmt);
n->typeName = $3;
+ n->oldVal = NULL;
n->newVal = $7;
n->newValNeighbor = NULL;
n->newValIsAfter = true;
- n->skipIfExists = $6;
+ n->skipIfNewValExists = $6;
$$ = (Node *) n;
}
| ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst BEFORE Sconst
{
AlterEnumStmt *n = makeNode(AlterEnumStmt);
n->typeName = $3;
+ n->oldVal = NULL;
n->newVal = $7;
n->newValNeighbor = $9;
n->newValIsAfter = false;
- n->skipIfExists = $6;
+ n->skipIfNewValExists = $6;
$$ = (Node *) n;
}
| ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst AFTER Sconst
{
AlterEnumStmt *n = makeNode(AlterEnumStmt);
n->typeName = $3;
+ n->oldVal = NULL;
n->newVal = $7;
n->newValNeighbor = $9;
n->newValIsAfter = true;
- n->skipIfExists = $6;
+ n->skipIfNewValExists = $6;
+ $$ = (Node *) n;
+ }
+ | ALTER TYPE_P any_name RENAME VALUE_P Sconst TO Sconst
+ {
+ AlterEnumStmt *n = makeNode(AlterEnumStmt);
+ n->typeName = $3;
+ n->oldVal = $6;
+ n->newVal = $8;
+ n->newValNeighbor = NULL;
+ n->newValIsAfter = false;
+ n->skipIfNewValExists = false;
$$ = (Node *) n;
}
;
@@ -5687,39 +6184,38 @@ opclass_item:
OPERATOR Iconst any_operator opclass_purpose opt_recheck
{
CreateOpClassItem *n = makeNode(CreateOpClassItem);
+ ObjectWithArgs *owa = makeNode(ObjectWithArgs);
+ owa->objname = $3;
+ owa->objargs = NIL;
n->itemtype = OPCLASS_ITEM_OPERATOR;
- n->name = $3;
- n->args = NIL;
+ n->name = owa;
n->number = $2;
n->order_family = $4;
$$ = (Node *) n;
}
- | OPERATOR Iconst any_operator oper_argtypes opclass_purpose
+ | OPERATOR Iconst operator_with_argtypes opclass_purpose
opt_recheck
{
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_OPERATOR;
n->name = $3;
- n->args = $4;
n->number = $2;
- n->order_family = $5;
+ n->order_family = $4;
$$ = (Node *) n;
}
- | FUNCTION Iconst func_name func_args
+ | FUNCTION Iconst function_with_argtypes
{
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_FUNCTION;
n->name = $3;
- n->args = extractArgTypes($4);
n->number = $2;
$$ = (Node *) n;
}
- | FUNCTION Iconst '(' type_list ')' func_name func_args
+ | FUNCTION Iconst '(' type_list ')' function_with_argtypes
{
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_FUNCTION;
n->name = $6;
- n->args = extractArgTypes($7);
n->number = $2;
n->class_args = $4;
$$ = (Node *) n;
@@ -5806,7 +6302,7 @@ opclass_drop:
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_OPERATOR;
n->number = $2;
- n->args = $4;
+ n->class_args = $4;
$$ = (Node *) n;
}
| FUNCTION Iconst '(' type_list ')'
@@ -5814,7 +6310,7 @@ opclass_drop:
CreateOpClassItem *n = makeNode(CreateOpClassItem);
n->itemtype = OPCLASS_ITEM_FUNCTION;
n->number = $2;
- n->args = $4;
+ n->class_args = $4;
$$ = (Node *) n;
}
;
@@ -5904,28 +6400,66 @@ ReassignOwnedStmt:
*
*****************************************************************************/
-DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
+DropStmt: DROP drop_type_any_name IF_P EXISTS any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->missing_ok = TRUE;
n->objects = $5;
- n->arguments = NIL;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *)n;
}
- | DROP drop_type any_name_list opt_drop_behavior
+ | DROP drop_type_any_name any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->missing_ok = FALSE;
n->objects = $3;
- n->arguments = NIL;
n->behavior = $4;
n->concurrent = false;
$$ = (Node *)n;
}
+ | DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = $2;
+ n->missing_ok = TRUE;
+ n->objects = $5;
+ n->behavior = $6;
+ n->concurrent = false;
+ $$ = (Node *)n;
+ }
+ | DROP drop_type_name name_list opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = $2;
+ n->missing_ok = FALSE;
+ n->objects = $3;
+ n->behavior = $4;
+ n->concurrent = false;
+ $$ = (Node *)n;
+ }
+ | DROP drop_type_name_on_any_name name ON any_name opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = $2;
+ n->objects = list_make1(lappend($5, makeString($3)));
+ n->behavior = $6;
+ n->missing_ok = false;
+ n->concurrent = false;
+ $$ = (Node *) n;
+ }
+ | DROP drop_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = $2;
+ n->objects = list_make1(lappend($7, makeString($5)));
+ n->behavior = $8;
+ n->missing_ok = true;
+ n->concurrent = false;
+ $$ = (Node *) n;
+ }
| DROP TYPE_P type_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
@@ -5972,7 +6506,6 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->removeType = OBJECT_INDEX;
n->missing_ok = FALSE;
n->objects = $4;
- n->arguments = NIL;
n->behavior = $5;
n->concurrent = true;
$$ = (Node *)n;
@@ -5983,32 +6516,47 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->removeType = OBJECT_INDEX;
n->missing_ok = TRUE;
n->objects = $6;
- n->arguments = NIL;
n->behavior = $7;
n->concurrent = true;
$$ = (Node *)n;
}
;
-
-drop_type: TABLE { $$ = OBJECT_TABLE; }
+/* object types taking any_name_list */
+drop_type_any_name:
+ TABLE { $$ = OBJECT_TABLE; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
| VIEW { $$ = OBJECT_VIEW; }
| MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; }
| INDEX { $$ = OBJECT_INDEX; }
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
- | ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; }
- | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
| COLLATION { $$ = OBJECT_COLLATION; }
| CONVERSION_P { $$ = OBJECT_CONVERSION; }
- | SCHEMA { $$ = OBJECT_SCHEMA; }
- | EXTENSION { $$ = OBJECT_EXTENSION; }
+ | STATISTICS { $$ = OBJECT_STATISTIC_EXT; }
| TEXT_P SEARCH PARSER { $$ = OBJECT_TSPARSER; }
| TEXT_P SEARCH DICTIONARY { $$ = OBJECT_TSDICTIONARY; }
| TEXT_P SEARCH TEMPLATE { $$ = OBJECT_TSTEMPLATE; }
| TEXT_P SEARCH CONFIGURATION { $$ = OBJECT_TSCONFIGURATION; }
;
+/* object types taking name_list */
+drop_type_name:
+ ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
+ | EXTENSION { $$ = OBJECT_EXTENSION; }
+ | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; }
+ | PUBLICATION { $$ = OBJECT_PUBLICATION; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
+ | SERVER { $$ = OBJECT_FOREIGN_SERVER; }
+ ;
+
+/* object types attached to a table */
+drop_type_name_on_any_name:
+ POLICY { $$ = OBJECT_POLICY; }
+ | RULE { $$ = OBJECT_RULE; }
+ | TRIGGER { $$ = OBJECT_TRIGGER; }
+ ;
+
any_name_list:
any_name { $$ = list_make1($1); }
| any_name_list ',' any_name { $$ = lappend($1, $3); }
@@ -6025,8 +6573,8 @@ attrs: '.' attr_name
;
type_name_list:
- Typename { $$ = list_make1(list_make1($1)); }
- | type_name_list ',' Typename { $$ = lappend($1, list_make1($3)); }
+ Typename { $$ = list_make1($1); }
+ | type_name_list ',' Typename { $$ = lappend($1, $3); }
/*****************************************************************************
*
@@ -6062,7 +6610,7 @@ opt_restart_seqs:
* EXTENSION | EVENT TRIGGER | FOREIGN DATA WRAPPER |
* FOREIGN TABLE | INDEX | [PROCEDURAL] LANGUAGE |
* MATERIALIZED VIEW | POLICY | ROLE | SCHEMA | SEQUENCE |
- * SERVER | TABLE | TABLESPACE |
+ * SERVER | STATISTICS | TABLE | TABLESPACE |
* TEXT SEARCH CONFIGURATION | TEXT SEARCH DICTIONARY |
* TEXT SEARCH PARSER | TEXT SEARCH TEMPLATE | TYPE |
* VIEW] <objname> |
@@ -6083,12 +6631,19 @@ opt_restart_seqs:
*****************************************************************************/
CommentStmt:
- COMMENT ON comment_type any_name IS comment_text
+ COMMENT ON comment_type_any_name any_name IS comment_text
+ {
+ CommentStmt *n = makeNode(CommentStmt);
+ n->objtype = $3;
+ n->object = (Node *) $4;
+ n->comment = $6;
+ $$ = (Node *) n;
+ }
+ | COMMENT ON comment_type_name name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = $3;
- n->objname = $4;
- n->objargs = NIL;
+ n->object = (Node *) makeString($4);
n->comment = $6;
$$ = (Node *) n;
}
@@ -6096,8 +6651,7 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_TYPE;
- n->objname = list_make1($4);
- n->objargs = NIL;
+ n->object = (Node *) $4;
n->comment = $6;
$$ = (Node *) n;
}
@@ -6105,44 +6659,39 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_DOMAIN;
- n->objname = list_make1($4);
- n->objargs = NIL;
+ n->object = (Node *) $4;
n->comment = $6;
$$ = (Node *) n;
}
- | COMMENT ON AGGREGATE func_name aggr_args IS comment_text
+ | COMMENT ON AGGREGATE aggregate_with_argtypes IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_AGGREGATE;
- n->objname = $4;
- n->objargs = extractAggrArgTypes($5);
- n->comment = $7;
+ n->object = (Node *) $4;
+ n->comment = $6;
$$ = (Node *) n;
}
- | COMMENT ON FUNCTION func_name func_args IS comment_text
+ | COMMENT ON FUNCTION function_with_argtypes IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_FUNCTION;
- n->objname = $4;
- n->objargs = extractArgTypes($5);
- n->comment = $7;
+ n->object = (Node *) $4;
+ n->comment = $6;
$$ = (Node *) n;
}
- | COMMENT ON OPERATOR any_operator oper_argtypes IS comment_text
+ | COMMENT ON OPERATOR operator_with_argtypes IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_OPERATOR;
- n->objname = $4;
- n->objargs = $5;
- n->comment = $7;
+ n->object = (Node *) $4;
+ n->comment = $6;
$$ = (Node *) n;
}
| COMMENT ON CONSTRAINT name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_TABCONSTRAINT;
- n->objname = lappend($6, makeString($4));
- n->objargs = NIL;
+ n->object = (Node *) lappend($6, makeString($4));
n->comment = $8;
$$ = (Node *) n;
}
@@ -6155,8 +6704,7 @@ CommentStmt:
* there's a shift/reduce conflict if we do that, so fix it
* up here.
*/
- n->objname = list_make1(makeTypeNameFromNameList($7));
- n->objargs = list_make1(makeString($4));
+ n->object = (Node *) list_make2(makeTypeNameFromNameList($7), makeString($4));
n->comment = $9;
$$ = (Node *) n;
}
@@ -6164,8 +6712,7 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_POLICY;
- n->objname = lappend($6, makeString($4));
- n->objargs = NIL;
+ n->object = (Node *) lappend($6, makeString($4));
n->comment = $8;
$$ = (Node *) n;
}
@@ -6173,27 +6720,15 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_RULE;
- n->objname = lappend($6, makeString($4));
- n->objargs = NIL;
+ n->object = (Node *) lappend($6, makeString($4));
n->comment = $8;
$$ = (Node *) n;
}
- | COMMENT ON RULE name IS comment_text
- {
- /* Obsolete syntax supported for awhile for compatibility */
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = OBJECT_RULE;
- n->objname = list_make1(makeString($4));
- n->objargs = NIL;
- n->comment = $6;
- $$ = (Node *) n;
- }
| COMMENT ON TRANSFORM FOR Typename LANGUAGE name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_TRANSFORM;
- n->objname = list_make1($5);
- n->objargs = list_make1(makeString($7));
+ n->object = (Node *) list_make2($5, makeString($7));
n->comment = $9;
$$ = (Node *) n;
}
@@ -6201,8 +6736,7 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_TRIGGER;
- n->objname = lappend($6, makeString($4));
- n->objargs = NIL;
+ n->object = (Node *) lappend($6, makeString($4));
n->comment = $8;
$$ = (Node *) n;
}
@@ -6210,7 +6744,7 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_OPCLASS;
- n->objname = lcons(makeString($7), $5);
+ n->object = (Node *) lcons(makeString($7), $5);
n->comment = $9;
$$ = (Node *) n;
}
@@ -6218,8 +6752,7 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_OPFAMILY;
- n->objname = lcons(makeString($7), $5);
- n->objargs = NIL;
+ n->object = (Node *) lcons(makeString($7), $5);
n->comment = $9;
$$ = (Node *) n;
}
@@ -6227,8 +6760,7 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_LARGEOBJECT;
- n->objname = list_make1($5);
- n->objargs = NIL;
+ n->object = (Node *) $5;
n->comment = $7;
$$ = (Node *) n;
}
@@ -6236,47 +6768,46 @@ CommentStmt:
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_CAST;
- n->objname = list_make1($5);
- n->objargs = list_make1($7);
+ n->object = (Node *) list_make2($5, $7);
n->comment = $10;
$$ = (Node *) n;
}
- | COMMENT ON opt_procedural LANGUAGE any_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = OBJECT_LANGUAGE;
- n->objname = $5;
- n->objargs = NIL;
- n->comment = $7;
- $$ = (Node *) n;
- }
;
-comment_type:
- ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; }
- | COLUMN { $$ = OBJECT_COLUMN; }
- | DATABASE { $$ = OBJECT_DATABASE; }
- | SCHEMA { $$ = OBJECT_SCHEMA; }
+/* object types taking any_name */
+comment_type_any_name:
+ COLUMN { $$ = OBJECT_COLUMN; }
| INDEX { $$ = OBJECT_INDEX; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
+ | STATISTICS { $$ = OBJECT_STATISTIC_EXT; }
| TABLE { $$ = OBJECT_TABLE; }
| VIEW { $$ = OBJECT_VIEW; }
| MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; }
| COLLATION { $$ = OBJECT_COLLATION; }
| CONVERSION_P { $$ = OBJECT_CONVERSION; }
- | TABLESPACE { $$ = OBJECT_TABLESPACE; }
- | EXTENSION { $$ = OBJECT_EXTENSION; }
- | ROLE { $$ = OBJECT_ROLE; }
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
- | SERVER { $$ = OBJECT_FOREIGN_SERVER; }
- | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; }
- | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
| TEXT_P SEARCH CONFIGURATION { $$ = OBJECT_TSCONFIGURATION; }
| TEXT_P SEARCH DICTIONARY { $$ = OBJECT_TSDICTIONARY; }
| TEXT_P SEARCH PARSER { $$ = OBJECT_TSPARSER; }
| TEXT_P SEARCH TEMPLATE { $$ = OBJECT_TSTEMPLATE; }
;
+/* object types taking name */
+comment_type_name:
+ ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; }
+ | DATABASE { $$ = OBJECT_DATABASE; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
+ | EXTENSION { $$ = OBJECT_EXTENSION; }
+ | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; }
+ | opt_procedural LANGUAGE { $$ = OBJECT_LANGUAGE; }
+ | PUBLICATION { $$ = OBJECT_PUBLICATION; }
+ | ROLE { $$ = OBJECT_ROLE; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
+ | SERVER { $$ = OBJECT_FOREIGN_SERVER; }
+ | SUBSCRIPTION { $$ = OBJECT_SUBSCRIPTION; }
+ | TABLESPACE { $$ = OBJECT_TABLESPACE; }
+ ;
+
comment_text:
Sconst { $$ = $1; }
| NULL_P { $$ = NULL; }
@@ -6293,14 +6824,23 @@ comment_text:
*****************************************************************************/
SecLabelStmt:
- SECURITY LABEL opt_provider ON security_label_type any_name
+ SECURITY LABEL opt_provider ON security_label_type_any_name any_name
IS security_label
{
SecLabelStmt *n = makeNode(SecLabelStmt);
n->provider = $3;
n->objtype = $5;
- n->objname = $6;
- n->objargs = NIL;
+ n->object = (Node *) $6;
+ n->label = $8;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON security_label_type_name name
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = $5;
+ n->object = (Node *) makeString($6);
n->label = $8;
$$ = (Node *) n;
}
@@ -6310,8 +6850,7 @@ SecLabelStmt:
SecLabelStmt *n = makeNode(SecLabelStmt);
n->provider = $3;
n->objtype = OBJECT_TYPE;
- n->objname = list_make1($6);
- n->objargs = NIL;
+ n->object = (Node *) $6;
n->label = $8;
$$ = (Node *) n;
}
@@ -6321,31 +6860,28 @@ SecLabelStmt:
SecLabelStmt *n = makeNode(SecLabelStmt);
n->provider = $3;
n->objtype = OBJECT_TYPE;
- n->objname = list_make1($6);
- n->objargs = NIL;
+ n->object = (Node *) $6;
n->label = $8;
$$ = (Node *) n;
}
- | SECURITY LABEL opt_provider ON AGGREGATE func_name aggr_args
+ | SECURITY LABEL opt_provider ON AGGREGATE aggregate_with_argtypes
IS security_label
{
SecLabelStmt *n = makeNode(SecLabelStmt);
n->provider = $3;
n->objtype = OBJECT_AGGREGATE;
- n->objname = $6;
- n->objargs = extractAggrArgTypes($7);
- n->label = $9;
+ n->object = (Node *) $6;
+ n->label = $8;
$$ = (Node *) n;
}
- | SECURITY LABEL opt_provider ON FUNCTION func_name func_args
+ | SECURITY LABEL opt_provider ON FUNCTION function_with_argtypes
IS security_label
{
SecLabelStmt *n = makeNode(SecLabelStmt);
n->provider = $3;
n->objtype = OBJECT_FUNCTION;
- n->objname = $6;
- n->objargs = extractArgTypes($7);
- n->label = $9;
+ n->object = (Node *) $6;
+ n->label = $8;
$$ = (Node *) n;
}
| SECURITY LABEL opt_provider ON LARGE_P OBJECT_P NumericOnly
@@ -6354,19 +6890,7 @@ SecLabelStmt:
SecLabelStmt *n = makeNode(SecLabelStmt);
n->provider = $3;
n->objtype = OBJECT_LARGEOBJECT;
- n->objname = list_make1($7);
- n->objargs = NIL;
- n->label = $9;
- $$ = (Node *) n;
- }
- | SECURITY LABEL opt_provider ON opt_procedural LANGUAGE any_name
- IS security_label
- {
- SecLabelStmt *n = makeNode(SecLabelStmt);
- n->provider = $3;
- n->objtype = OBJECT_LANGUAGE;
- n->objname = $7;
- n->objargs = NIL;
+ n->object = (Node *) $7;
n->label = $9;
$$ = (Node *) n;
}
@@ -6376,20 +6900,28 @@ opt_provider: FOR NonReservedWord_or_Sconst { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
-security_label_type:
+/* object types taking any_name */
+security_label_type_any_name:
COLUMN { $$ = OBJECT_COLUMN; }
- | DATABASE { $$ = OBJECT_DATABASE; }
- | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
- | SCHEMA { $$ = OBJECT_SCHEMA; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
| TABLE { $$ = OBJECT_TABLE; }
- | ROLE { $$ = OBJECT_ROLE; }
- | TABLESPACE { $$ = OBJECT_TABLESPACE; }
| VIEW { $$ = OBJECT_VIEW; }
| MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; }
;
+/* object types taking name */
+security_label_type_name:
+ DATABASE { $$ = OBJECT_DATABASE; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
+ | opt_procedural LANGUAGE { $$ = OBJECT_LANGUAGE; }
+ | PUBLICATION { $$ = OBJECT_PUBLICATION; }
+ | ROLE { $$ = OBJECT_ROLE; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
+ | SUBSCRIPTION { $$ = OBJECT_SUBSCRIPTION; }
+ | TABLESPACE { $$ = OBJECT_TABLESPACE; }
+ ;
+
security_label: Sconst { $$ = $1; }
| NULL_P { $$ = NULL; }
;
@@ -6824,22 +7356,6 @@ opt_grant_grant_option:
| /*EMPTY*/ { $$ = FALSE; }
;
-function_with_argtypes_list:
- function_with_argtypes { $$ = list_make1($1); }
- | function_with_argtypes_list ',' function_with_argtypes
- { $$ = lappend($1, $3); }
- ;
-
-function_with_argtypes:
- func_name func_args
- {
- FuncWithArgs *n = makeNode(FuncWithArgs);
- n->funcname = $1;
- n->funcargs = extractArgTypes($2);
- $$ = n;
- }
- ;
-
/*****************************************************************************
*
* GRANT and REVOKE ROLE statements
@@ -6914,15 +7430,15 @@ DefACLOptionList:
DefACLOption:
IN_P SCHEMA name_list
{
- $$ = makeDefElem("schemas", (Node *)$3);
+ $$ = makeDefElem("schemas", (Node *)$3, @1);
}
| FOR ROLE role_list
{
- $$ = makeDefElem("roles", (Node *)$3);
+ $$ = makeDefElem("roles", (Node *)$3, @1);
}
| FOR USER role_list
{
- $$ = makeDefElem("roles", (Node *)$3);
+ $$ = makeDefElem("roles", (Node *)$3, @1);
}
;
@@ -6979,6 +7495,7 @@ defacl_privilege_target:
| FUNCTIONS { $$ = ACL_OBJECT_FUNCTION; }
| SEQUENCES { $$ = ACL_OBJECT_SEQUENCE; }
| TYPES_P { $$ = ACL_OBJECT_TYPE; }
+ | SCHEMAS { $$ = ACL_OBJECT_NAMESPACE; }
;
@@ -7192,6 +7709,49 @@ func_args_list:
| func_args_list ',' func_arg { $$ = lappend($1, $3); }
;
+function_with_argtypes_list:
+ function_with_argtypes { $$ = list_make1($1); }
+ | function_with_argtypes_list ',' function_with_argtypes
+ { $$ = lappend($1, $3); }
+ ;
+
+function_with_argtypes:
+ func_name func_args
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = $1;
+ n->objargs = extractArgTypes($2);
+ $$ = n;
+ }
+ /*
+ * Because of reduce/reduce conflicts, we can't use func_name
+ * below, but we can write it out the long way, which actually
+ * allows more cases.
+ */
+ | type_func_name_keyword
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = list_make1(makeString(pstrdup($1)));
+ n->args_unspecified = true;
+ $$ = n;
+ }
+ | ColId
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = list_make1(makeString($1));
+ n->args_unspecified = true;
+ $$ = n;
+ }
+ | ColId indirection
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = check_func_name(lcons(makeString($1), $2),
+ yyscanner);
+ n->args_unspecified = true;
+ $$ = n;
+ }
+ ;
+
/*
* func_args_with_defaults is separate because we only want to accept
* defaults in CREATE FUNCTION, not in ALTER etc.
@@ -7394,6 +7954,22 @@ aggr_args_list:
| aggr_args_list ',' aggr_arg { $$ = lappend($1, $3); }
;
+aggregate_with_argtypes:
+ func_name aggr_args
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = $1;
+ n->objargs = extractAggrArgTypes($2);
+ $$ = n;
+ }
+ ;
+
+aggregate_with_argtypes_list:
+ aggregate_with_argtypes { $$ = list_make1($1); }
+ | aggregate_with_argtypes_list ',' aggregate_with_argtypes
+ { $$ = lappend($1, $3); }
+ ;
+
createfunc_opt_list:
/* Must be at least one to prevent conflict */
createfunc_opt_item { $$ = list_make1($1); }
@@ -7406,87 +7982,87 @@ createfunc_opt_list:
common_func_opt_item:
CALLED ON NULL_P INPUT_P
{
- $$ = makeDefElem("strict", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("strict", (Node *)makeInteger(FALSE), @1);
}
| RETURNS NULL_P ON NULL_P INPUT_P
{
- $$ = makeDefElem("strict", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("strict", (Node *)makeInteger(TRUE), @1);
}
| STRICT_P
{
- $$ = makeDefElem("strict", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("strict", (Node *)makeInteger(TRUE), @1);
}
| IMMUTABLE
{
- $$ = makeDefElem("volatility", (Node *)makeString("immutable"));
+ $$ = makeDefElem("volatility", (Node *)makeString("immutable"), @1);
}
| STABLE
{
- $$ = makeDefElem("volatility", (Node *)makeString("stable"));
+ $$ = makeDefElem("volatility", (Node *)makeString("stable"), @1);
}
| VOLATILE
{
- $$ = makeDefElem("volatility", (Node *)makeString("volatile"));
+ $$ = makeDefElem("volatility", (Node *)makeString("volatile"), @1);
}
| EXTERNAL SECURITY DEFINER
{
- $$ = makeDefElem("security", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("security", (Node *)makeInteger(TRUE), @1);
}
| EXTERNAL SECURITY INVOKER
{
- $$ = makeDefElem("security", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("security", (Node *)makeInteger(FALSE), @1);
}
| SECURITY DEFINER
{
- $$ = makeDefElem("security", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("security", (Node *)makeInteger(TRUE), @1);
}
| SECURITY INVOKER
{
- $$ = makeDefElem("security", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("security", (Node *)makeInteger(FALSE), @1);
}
| LEAKPROOF
{
- $$ = makeDefElem("leakproof", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("leakproof", (Node *)makeInteger(TRUE), @1);
}
| NOT LEAKPROOF
{
- $$ = makeDefElem("leakproof", (Node *)makeInteger(FALSE));
+ $$ = makeDefElem("leakproof", (Node *)makeInteger(FALSE), @1);
}
| COST NumericOnly
{
- $$ = makeDefElem("cost", (Node *)$2);
+ $$ = makeDefElem("cost", (Node *)$2, @1);
}
| ROWS NumericOnly
{
- $$ = makeDefElem("rows", (Node *)$2);
+ $$ = makeDefElem("rows", (Node *)$2, @1);
}
| FunctionSetResetClause
{
/* we abuse the normal content of a DefElem here */
- $$ = makeDefElem("set", (Node *)$1);
+ $$ = makeDefElem("set", (Node *)$1, @1);
}
| PARALLEL ColId
{
- $$ = makeDefElem("parallel", (Node *)makeString($2));
+ $$ = makeDefElem("parallel", (Node *)makeString($2), @1);
}
;
createfunc_opt_item:
AS func_as
{
- $$ = makeDefElem("as", (Node *)$2);
+ $$ = makeDefElem("as", (Node *)$2, @1);
}
| LANGUAGE NonReservedWord_or_Sconst
{
- $$ = makeDefElem("language", (Node *)makeString($2));
+ $$ = makeDefElem("language", (Node *)makeString($2), @1);
}
| TRANSFORM transform_type_list
{
- $$ = makeDefElem("transform", (Node *)$2);
+ $$ = makeDefElem("transform", (Node *)$2, @1);
}
| WINDOW
{
- $$ = makeDefElem("window", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("window", (Node *)makeInteger(TRUE), @1);
}
| common_func_opt_item
{
@@ -7575,24 +8151,22 @@ opt_restrict:
*****************************************************************************/
RemoveFuncStmt:
- DROP FUNCTION func_name func_args opt_drop_behavior
+ DROP FUNCTION function_with_argtypes_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_FUNCTION;
- n->objects = list_make1($3);
- n->arguments = list_make1(extractArgTypes($4));
- n->behavior = $5;
+ n->objects = $3;
+ n->behavior = $4;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
- | DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior
+ | DROP FUNCTION IF_P EXISTS function_with_argtypes_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_FUNCTION;
- n->objects = list_make1($5);
- n->arguments = list_make1(extractArgTypes($6));
- n->behavior = $7;
+ n->objects = $5;
+ n->behavior = $6;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
@@ -7600,24 +8174,22 @@ RemoveFuncStmt:
;
RemoveAggrStmt:
- DROP AGGREGATE func_name aggr_args opt_drop_behavior
+ DROP AGGREGATE aggregate_with_argtypes_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_AGGREGATE;
- n->objects = list_make1($3);
- n->arguments = list_make1(extractAggrArgTypes($4));
- n->behavior = $5;
+ n->objects = $3;
+ n->behavior = $4;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
- | DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior
+ | DROP AGGREGATE IF_P EXISTS aggregate_with_argtypes_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_AGGREGATE;
- n->objects = list_make1($5);
- n->arguments = list_make1(extractAggrArgTypes($6));
- n->behavior = $7;
+ n->objects = $5;
+ n->behavior = $6;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
@@ -7625,24 +8197,22 @@ RemoveAggrStmt:
;
RemoveOperStmt:
- DROP OPERATOR any_operator oper_argtypes opt_drop_behavior
+ DROP OPERATOR operator_with_argtypes_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_OPERATOR;
- n->objects = list_make1($3);
- n->arguments = list_make1($4);
- n->behavior = $5;
+ n->objects = $3;
+ n->behavior = $4;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
- | DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior
+ | DROP OPERATOR IF_P EXISTS operator_with_argtypes_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_OPERATOR;
- n->objects = list_make1($5);
- n->arguments = list_make1($6);
- n->behavior = $7;
+ n->objects = $5;
+ n->behavior = $6;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
@@ -7673,6 +8243,22 @@ any_operator:
{ $$ = lcons(makeString($1), $3); }
;
+operator_with_argtypes_list:
+ operator_with_argtypes { $$ = list_make1($1); }
+ | operator_with_argtypes_list ',' operator_with_argtypes
+ { $$ = lappend($1, $3); }
+ ;
+
+operator_with_argtypes:
+ any_operator oper_argtypes
+ {
+ ObjectWithArgs *n = makeNode(ObjectWithArgs);
+ n->objname = $1;
+ n->objargs = $2;
+ $$ = n;
+ }
+ ;
+
/*****************************************************************************
*
* DO <anonymous code block> [ LANGUAGE language ]
@@ -7698,11 +8284,11 @@ dostmt_opt_list:
dostmt_opt_item:
Sconst
{
- $$ = makeDefElem("as", (Node *)makeString($1));
+ $$ = makeDefElem("as", (Node *)makeString($1), @1);
}
| LANGUAGE NonReservedWord_or_Sconst
{
- $$ = makeDefElem("language", (Node *)makeString($2));
+ $$ = makeDefElem("language", (Node *)makeString($2), @1);
}
;
@@ -7757,8 +8343,7 @@ DropCastStmt: DROP CAST opt_if_exists '(' Typename AS Typename ')' opt_drop_beha
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_CAST;
- n->objects = list_make1(list_make1($5));
- n->arguments = list_make1(list_make1($7));
+ n->objects = list_make1(list_make2($5, $7));
n->behavior = $9;
n->missing_ok = $3;
n->concurrent = false;
@@ -7812,8 +8397,7 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_TRANSFORM;
- n->objects = list_make1(list_make1($5));
- n->arguments = list_make1(list_make1(makeString($7)));
+ n->objects = list_make1(list_make2($5, makeString($7)));
n->behavior = $8;
n->missing_ok = $3;
$$ = (Node *)n;
@@ -7916,13 +8500,12 @@ AlterTblSpcStmt:
*
*****************************************************************************/
-RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
+RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_AGGREGATE;
- n->object = $3;
- n->objarg = extractAggrArgTypes($4);
- n->newname = $7;
+ n->object = (Node *) $3;
+ n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
}
@@ -7930,7 +8513,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_COLLATION;
- n->object = $3;
+ n->object = (Node *) $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7939,7 +8522,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_CONVERSION;
- n->object = $3;
+ n->object = (Node *) $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7957,7 +8540,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_DOMAIN;
- n->object = $3;
+ n->object = (Node *) $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7966,7 +8549,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_DOMCONSTRAINT;
- n->object = $3;
+ n->object = (Node *) $3;
n->subname = $6;
n->newname = $8;
$$ = (Node *)n;
@@ -7975,7 +8558,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FDW;
- n->object = list_make1(makeString($5));
+ n->object = (Node *) makeString($5);
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7984,8 +8567,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FUNCTION;
- n->object = $3->funcname;
- n->objarg = $3->funcargs;
+ n->object = (Node *) $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8003,7 +8585,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_LANGUAGE;
- n->object = list_make1(makeString($4));
+ n->object = (Node *) makeString($4);
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8012,7 +8594,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_OPCLASS;
- n->object = lcons(makeString($6), $4);
+ n->object = (Node *) lcons(makeString($6), $4);
n->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8021,7 +8603,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_OPFAMILY;
- n->object = lcons(makeString($6), $4);
+ n->object = (Node *) lcons(makeString($6), $4);
n->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8046,6 +8628,15 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER PUBLICATION name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_PUBLICATION;
+ n->object = (Node *) makeString($3);
+ n->newname = $6;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
| ALTER SCHEMA name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8059,7 +8650,16 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FOREIGN_SERVER;
- n->object = list_make1(makeString($3));
+ n->object = (Node *) makeString($3);
+ n->newname = $6;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_SUBSCRIPTION;
+ n->object = (Node *) makeString($3);
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8294,7 +8894,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_EVENT_TRIGGER;
- n->object = list_make1(makeString($4));
+ n->object = (Node *) makeString($4);
n->newname = $7;
$$ = (Node *)n;
}
@@ -8325,11 +8925,20 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER STATISTICS any_name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_STATISTIC_EXT;
+ n->object = (Node *) $3;
+ n->newname = $6;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
| ALTER TEXT_P SEARCH PARSER any_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_TSPARSER;
- n->object = $5;
+ n->object = (Node *) $5;
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8338,7 +8947,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_TSDICTIONARY;
- n->object = $5;
+ n->object = (Node *) $5;
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8347,7 +8956,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_TSTEMPLATE;
- n->object = $5;
+ n->object = (Node *) $5;
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8356,7 +8965,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_TSCONFIGURATION;
- n->object = $5;
+ n->object = (Node *) $5;
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8365,7 +8974,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_TYPE;
- n->object = $3;
+ n->object = (Node *) $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8403,9 +9012,7 @@ AlterObjectDependsStmt:
{
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
n->objectType = OBJECT_FUNCTION;
- n->relation = NULL;
- n->objname = $3->funcname;
- n->objargs = $3->funcargs;
+ n->object = (Node *) $3;
n->extname = makeString($7);
$$ = (Node *)n;
}
@@ -8414,8 +9021,7 @@ AlterObjectDependsStmt:
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
n->objectType = OBJECT_TRIGGER;
n->relation = $5;
- n->objname = list_make1(makeString($3));
- n->objargs = NIL;
+ n->object = (Node *) list_make1(makeString($3));
n->extname = makeString($9);
$$ = (Node *)n;
}
@@ -8424,8 +9030,6 @@ AlterObjectDependsStmt:
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
n->objectType = OBJECT_MATVIEW;
n->relation = $4;
- n->objname = NIL;
- n->objargs = NIL;
n->extname = makeString($8);
$$ = (Node *)n;
}
@@ -8434,8 +9038,6 @@ AlterObjectDependsStmt:
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
n->objectType = OBJECT_INDEX;
n->relation = $3;
- n->objname = NIL;
- n->objargs = NIL;
n->extname = makeString($7);
$$ = (Node *)n;
}
@@ -8448,13 +9050,12 @@ AlterObjectDependsStmt:
*****************************************************************************/
AlterObjectSchemaStmt:
- ALTER AGGREGATE func_name aggr_args SET SCHEMA name
+ ALTER AGGREGATE aggregate_with_argtypes SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_AGGREGATE;
- n->object = $3;
- n->objarg = extractAggrArgTypes($4);
- n->newschema = $7;
+ n->object = (Node *) $3;
+ n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
}
@@ -8462,7 +9063,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_COLLATION;
- n->object = $3;
+ n->object = (Node *) $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8471,7 +9072,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_CONVERSION;
- n->object = $3;
+ n->object = (Node *) $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8480,16 +9081,16 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_DOMAIN;
- n->object = $3;
+ n->object = (Node *) $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
}
- | ALTER EXTENSION any_name SET SCHEMA name
+ | ALTER EXTENSION name SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_EXTENSION;
- n->object = $3;
+ n->object = (Node *) makeString($3);
n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8498,19 +9099,17 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_FUNCTION;
- n->object = $3->funcname;
- n->objarg = $3->funcargs;
+ n->object = (Node *) $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
}
- | ALTER OPERATOR any_operator oper_argtypes SET SCHEMA name
+ | ALTER OPERATOR operator_with_argtypes SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPERATOR;
- n->object = $3;
- n->objarg = $4;
- n->newschema = $7;
+ n->object = (Node *) $3;
+ n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
}
@@ -8518,7 +9117,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPCLASS;
- n->object = lcons(makeString($6), $4);
+ n->object = (Node *) lcons(makeString($6), $4);
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8527,7 +9126,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPFAMILY;
- n->object = lcons(makeString($6), $4);
+ n->object = (Node *) lcons(makeString($6), $4);
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8550,11 +9149,20 @@ AlterObjectSchemaStmt:
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER STATISTICS any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_STATISTIC_EXT;
+ n->object = (Node *) $3;
+ n->newschema = $6;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
| ALTER TEXT_P SEARCH PARSER any_name SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TSPARSER;
- n->object = $5;
+ n->object = (Node *) $5;
n->newschema = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8563,7 +9171,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TSDICTIONARY;
- n->object = $5;
+ n->object = (Node *) $5;
n->newschema = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8572,7 +9180,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TSTEMPLATE;
- n->object = $5;
+ n->object = (Node *) $5;
n->newschema = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8581,7 +9189,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TSCONFIGURATION;
- n->object = $5;
+ n->object = (Node *) $5;
n->newschema = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8662,7 +9270,7 @@ AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TYPE;
- n->object = $3;
+ n->object = (Node *) $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -8676,12 +9284,11 @@ AlterObjectSchemaStmt:
*****************************************************************************/
AlterOperatorStmt:
- ALTER OPERATOR any_operator oper_argtypes SET '(' operator_def_list ')'
+ ALTER OPERATOR operator_with_argtypes SET '(' operator_def_list ')'
{
AlterOperatorStmt *n = makeNode(AlterOperatorStmt);
n->opername = $3;
- n->operargs = $4;
- n->options = $7;
+ n->options = $6;
$$ = (Node *)n;
}
;
@@ -8691,9 +9298,18 @@ operator_def_list: operator_def_elem { $$ = list_make1($1); }
;
operator_def_elem: ColLabel '=' NONE
- { $$ = makeDefElem($1, NULL); }
- | ColLabel '=' def_arg
- { $$ = makeDefElem($1, (Node *) $3); }
+ { $$ = makeDefElem($1, NULL, @1); }
+ | ColLabel '=' operator_def_arg
+ { $$ = makeDefElem($1, (Node *) $3, @1); }
+ ;
+
+/* must be similar enough to def_arg to avoid reduce/reduce conflicts */
+operator_def_arg:
+ func_type { $$ = (Node *)$1; }
+ | reserved_keyword { $$ = (Node *)makeString(pstrdup($1)); }
+ | qual_all_Op { $$ = (Node *)$1; }
+ | NumericOnly { $$ = (Node *)$1; }
+ | Sconst { $$ = (Node *)makeString($1); }
;
/*****************************************************************************
@@ -8702,20 +9318,19 @@ operator_def_elem: ColLabel '=' NONE
*
*****************************************************************************/
-AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
+AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_AGGREGATE;
- n->object = $3;
- n->objarg = extractAggrArgTypes($4);
- n->newowner = $7;
+ n->object = (Node *) $3;
+ n->newowner = $6;
$$ = (Node *)n;
}
| ALTER COLLATION any_name OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_COLLATION;
- n->object = $3;
+ n->object = (Node *) $3;
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8723,7 +9338,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_CONVERSION;
- n->object = $3;
+ n->object = (Node *) $3;
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8731,7 +9346,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_DATABASE;
- n->object = list_make1(makeString($3));
+ n->object = (Node *) makeString($3);
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8739,7 +9354,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_DOMAIN;
- n->object = $3;
+ n->object = (Node *) $3;
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8747,8 +9362,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_FUNCTION;
- n->object = $3->funcname;
- n->objarg = $3->funcargs;
+ n->object = (Node *) $3;
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8756,7 +9370,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_LANGUAGE;
- n->object = list_make1(makeString($4));
+ n->object = (Node *) makeString($4);
n->newowner = $7;
$$ = (Node *)n;
}
@@ -8764,24 +9378,23 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_LARGEOBJECT;
- n->object = list_make1($4);
+ n->object = (Node *) $4;
n->newowner = $7;
$$ = (Node *)n;
}
- | ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleSpec
+ | ALTER OPERATOR operator_with_argtypes OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_OPERATOR;
- n->object = $3;
- n->objarg = $4;
- n->newowner = $7;
+ n->object = (Node *) $3;
+ n->newowner = $6;
$$ = (Node *)n;
}
| ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_OPCLASS;
- n->object = lcons(makeString($6), $4);
+ n->object = (Node *) lcons(makeString($6), $4);
n->newowner = $9;
$$ = (Node *)n;
}
@@ -8789,7 +9402,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_OPFAMILY;
- n->object = lcons(makeString($6), $4);
+ n->object = (Node *) lcons(makeString($6), $4);
n->newowner = $9;
$$ = (Node *)n;
}
@@ -8797,7 +9410,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_SCHEMA;
- n->object = list_make1(makeString($3));
+ n->object = (Node *) makeString($3);
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8805,7 +9418,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_TYPE;
- n->object = $3;
+ n->object = (Node *) $3;
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8813,7 +9426,15 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_TABLESPACE;
- n->object = list_make1(makeString($3));
+ n->object = (Node *) makeString($3);
+ n->newowner = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER STATISTICS any_name OWNER TO RoleSpec
+ {
+ AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_STATISTIC_EXT;
+ n->object = (Node *) $3;
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8821,7 +9442,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_TSDICTIONARY;
- n->object = $5;
+ n->object = (Node *) $5;
n->newowner = $8;
$$ = (Node *)n;
}
@@ -8829,7 +9450,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_TSCONFIGURATION;
- n->object = $5;
+ n->object = (Node *) $5;
n->newowner = $8;
$$ = (Node *)n;
}
@@ -8837,7 +9458,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_FDW;
- n->object = list_make1(makeString($5));
+ n->object = (Node *) makeString($5);
n->newowner = $8;
$$ = (Node *)n;
}
@@ -8845,7 +9466,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_FOREIGN_SERVER;
- n->object = list_make1(makeString($3));
+ n->object = (Node *) makeString($3);
n->newowner = $6;
$$ = (Node *)n;
}
@@ -8853,15 +9474,252 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_EVENT_TRIGGER;
- n->object = list_make1(makeString($4));
+ n->object = (Node *) makeString($4);
n->newowner = $7;
$$ = (Node *)n;
}
+ | ALTER PUBLICATION name OWNER TO RoleSpec
+ {
+ AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_PUBLICATION;
+ n->object = (Node *) makeString($3);
+ n->newowner = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name OWNER TO RoleSpec
+ {
+ AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_SUBSCRIPTION;
+ n->object = (Node *) makeString($3);
+ n->newowner = $6;
+ $$ = (Node *)n;
+ }
;
/*****************************************************************************
*
+ * CREATE PUBLICATION name [ FOR TABLE ] [ WITH options ]
+ *
+ *****************************************************************************/
+
+CreatePublicationStmt:
+ CREATE PUBLICATION name opt_publication_for_tables opt_definition
+ {
+ CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
+ n->pubname = $3;
+ n->options = $5;
+ if ($4 != NULL)
+ {
+ /* FOR TABLE */
+ if (IsA($4, List))
+ n->tables = (List *)$4;
+ /* FOR ALL TABLES */
+ else
+ n->for_all_tables = TRUE;
+ }
+ $$ = (Node *)n;
+ }
+ ;
+
+opt_publication_for_tables:
+ publication_for_tables { $$ = $1; }
+ | /* EMPTY */ { $$ = NULL; }
+ ;
+
+publication_for_tables:
+ FOR TABLE relation_expr_list
+ {
+ $$ = (Node *) $3;
+ }
+ | FOR ALL TABLES
+ {
+ $$ = (Node *) makeInteger(TRUE);
+ }
+ ;
+
+
+/*****************************************************************************
+ *
+ * ALTER PUBLICATION name SET ( options )
+ *
+ * ALTER PUBLICATION name ADD TABLE table [, table2]
+ *
+ * ALTER PUBLICATION name DROP TABLE table [, table2]
+ *
+ * ALTER PUBLICATION name SET TABLE table [, table2]
+ *
+ *****************************************************************************/
+
+AlterPublicationStmt:
+ ALTER PUBLICATION name SET definition
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->options = $5;
+ $$ = (Node *)n;
+ }
+ | ALTER PUBLICATION name ADD_P TABLE relation_expr_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->tables = $6;
+ n->tableAction = DEFELEM_ADD;
+ $$ = (Node *)n;
+ }
+ | ALTER PUBLICATION name SET TABLE relation_expr_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->tables = $6;
+ n->tableAction = DEFELEM_SET;
+ $$ = (Node *)n;
+ }
+ | ALTER PUBLICATION name DROP TABLE relation_expr_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->tables = $6;
+ n->tableAction = DEFELEM_DROP;
+ $$ = (Node *)n;
+ }
+ ;
+
+/*****************************************************************************
+ *
+ * CREATE SUBSCRIPTION name ...
+ *
+ *****************************************************************************/
+
+CreateSubscriptionStmt:
+ CREATE SUBSCRIPTION name CONNECTION Sconst PUBLICATION publication_name_list opt_definition
+ {
+ CreateSubscriptionStmt *n =
+ makeNode(CreateSubscriptionStmt);
+ n->subname = $3;
+ n->conninfo = $5;
+ n->publication = $7;
+ n->options = $8;
+ $$ = (Node *)n;
+ }
+ ;
+
+publication_name_list:
+ publication_name_item
+ {
+ $$ = list_make1($1);
+ }
+ | publication_name_list ',' publication_name_item
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+publication_name_item:
+ ColLabel { $$ = makeString($1); };
+
+/*****************************************************************************
+ *
+ * ALTER SUBSCRIPTION name ...
+ *
+ *****************************************************************************/
+
+AlterSubscriptionStmt:
+ ALTER SUBSCRIPTION name SET definition
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_OPTIONS;
+ n->subname = $3;
+ n->options = $5;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name CONNECTION Sconst
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_CONNECTION;
+ n->subname = $3;
+ n->conninfo = $5;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name REFRESH PUBLICATION opt_definition
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_REFRESH;
+ n->subname = $3;
+ n->options = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list REFRESH opt_definition
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_PUBLICATION_REFRESH;
+ n->subname = $3;
+ n->publication = $6;
+ n->options = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list SKIP REFRESH
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_PUBLICATION;
+ n->subname = $3;
+ n->publication = $6;
+ n->options = NIL;
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name ENABLE_P
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_ENABLED;
+ n->subname = $3;
+ n->options = list_make1(makeDefElem("enabled",
+ (Node *)makeInteger(TRUE), @1));
+ $$ = (Node *)n;
+ }
+ | ALTER SUBSCRIPTION name DISABLE_P
+ {
+ AlterSubscriptionStmt *n =
+ makeNode(AlterSubscriptionStmt);
+ n->kind = ALTER_SUBSCRIPTION_ENABLED;
+ n->subname = $3;
+ n->options = list_make1(makeDefElem("enabled",
+ (Node *)makeInteger(FALSE), @1));
+ $$ = (Node *)n;
+ }
+ ;
+
+/*****************************************************************************
+ *
+ * DROP SUBSCRIPTION [ IF EXISTS ] name
+ *
+ *****************************************************************************/
+
+DropSubscriptionStmt: DROP SUBSCRIPTION name opt_drop_behavior
+ {
+ DropSubscriptionStmt *n = makeNode(DropSubscriptionStmt);
+ n->subname = $3;
+ n->missing_ok = false;
+ n->behavior = $4;
+ $$ = (Node *) n;
+ }
+ | DROP SUBSCRIPTION IF_P EXISTS name opt_drop_behavior
+ {
+ DropSubscriptionStmt *n = makeNode(DropSubscriptionStmt);
+ n->subname = $5;
+ n->missing_ok = true;
+ n->behavior = $6;
+ $$ = (Node *) n;
+ }
+ ;
+
+/*****************************************************************************
+ *
* QUERY: Define Rewrite Rule
*
*****************************************************************************/
@@ -8930,32 +9788,6 @@ opt_instead:
;
-DropRuleStmt:
- DROP RULE name ON any_name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_RULE;
- n->objects = list_make1(lappend($5, makeString($3)));
- n->arguments = NIL;
- n->behavior = $6;
- n->missing_ok = false;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- | DROP RULE IF_P EXISTS name ON any_name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_RULE;
- n->objects = list_make1(lappend($7, makeString($5)));
- n->arguments = NIL;
- n->behavior = $8;
- n->missing_ok = true;
- n->concurrent = false;
- $$ = (Node *) n;
- }
- ;
-
-
/*****************************************************************************
*
* QUERY:
@@ -9059,7 +9891,7 @@ TransactionStmt:
TransactionStmt *n = makeNode(TransactionStmt);
n->kind = TRANS_STMT_SAVEPOINT;
n->options = list_make1(makeDefElem("savepoint_name",
- (Node *)makeString($2)));
+ (Node *)makeString($2), @1));
$$ = (Node *)n;
}
| RELEASE SAVEPOINT ColId
@@ -9067,7 +9899,7 @@ TransactionStmt:
TransactionStmt *n = makeNode(TransactionStmt);
n->kind = TRANS_STMT_RELEASE;
n->options = list_make1(makeDefElem("savepoint_name",
- (Node *)makeString($3)));
+ (Node *)makeString($3), @1));
$$ = (Node *)n;
}
| RELEASE ColId
@@ -9075,7 +9907,7 @@ TransactionStmt:
TransactionStmt *n = makeNode(TransactionStmt);
n->kind = TRANS_STMT_RELEASE;
n->options = list_make1(makeDefElem("savepoint_name",
- (Node *)makeString($2)));
+ (Node *)makeString($2), @1));
$$ = (Node *)n;
}
| ROLLBACK opt_transaction TO SAVEPOINT ColId
@@ -9083,7 +9915,7 @@ TransactionStmt:
TransactionStmt *n = makeNode(TransactionStmt);
n->kind = TRANS_STMT_ROLLBACK_TO;
n->options = list_make1(makeDefElem("savepoint_name",
- (Node *)makeString($5)));
+ (Node *)makeString($5), @1));
$$ = (Node *)n;
}
| ROLLBACK opt_transaction TO ColId
@@ -9091,7 +9923,7 @@ TransactionStmt:
TransactionStmt *n = makeNode(TransactionStmt);
n->kind = TRANS_STMT_ROLLBACK_TO;
n->options = list_make1(makeDefElem("savepoint_name",
- (Node *)makeString($4)));
+ (Node *)makeString($4), @1));
$$ = (Node *)n;
}
| PREPARE TRANSACTION Sconst
@@ -9125,19 +9957,19 @@ opt_transaction: WORK {}
transaction_mode_item:
ISOLATION LEVEL iso_level
{ $$ = makeDefElem("transaction_isolation",
- makeStringConst($3, @3)); }
+ makeStringConst($3, @3), @1); }
| READ ONLY
{ $$ = makeDefElem("transaction_read_only",
- makeIntConst(TRUE, @1)); }
+ makeIntConst(TRUE, @1), @1); }
| READ WRITE
{ $$ = makeDefElem("transaction_read_only",
- makeIntConst(FALSE, @1)); }
+ makeIntConst(FALSE, @1), @1); }
| DEFERRABLE
{ $$ = makeDefElem("transaction_deferrable",
- makeIntConst(TRUE, @1)); }
+ makeIntConst(TRUE, @1), @1); }
| NOT DEFERRABLE
{ $$ = makeDefElem("transaction_deferrable",
- makeIntConst(FALSE, @1)); }
+ makeIntConst(FALSE, @1), @1); }
;
/* Syntax with commas is SQL-spec, without commas is Postgres historical */
@@ -9281,15 +10113,15 @@ createdb_opt_items:
createdb_opt_item:
createdb_opt_name opt_equal SignedIconst
{
- $$ = makeDefElem($1, (Node *)makeInteger($3));
+ $$ = makeDefElem($1, (Node *)makeInteger($3), @1);
}
| createdb_opt_name opt_equal opt_boolean_or_string
{
- $$ = makeDefElem($1, (Node *)makeString($3));
+ $$ = makeDefElem($1, (Node *)makeString($3), @1);
}
| createdb_opt_name opt_equal DEFAULT
{
- $$ = makeDefElem($1, NULL);
+ $$ = makeDefElem($1, NULL, @1);
}
;
@@ -9349,7 +10181,7 @@ AlterDatabaseStmt:
AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt);
n->dbname = $3;
n->options = list_make1(makeDefElem("tablespace",
- (Node *)makeString($6)));
+ (Node *)makeString($6), @6));
$$ = (Node *)n;
}
;
@@ -9391,6 +10223,21 @@ DropdbStmt: DROP DATABASE database_name
/*****************************************************************************
*
+ * ALTER COLLATION
+ *
+ *****************************************************************************/
+
+AlterCollationStmt: ALTER COLLATION any_name REFRESH VERSION_P
+ {
+ AlterCollationStmt *n = makeNode(AlterCollationStmt);
+ n->collname = $3;
+ $$ = (Node *)n;
+ }
+ ;
+
+
+/*****************************************************************************
+ *
* ALTER SYSTEM
*
* This is used to change configuration parameters persistently.
@@ -9992,17 +10839,17 @@ ExplainStmt:
{
ExplainStmt *n = makeNode(ExplainStmt);
n->query = $4;
- n->options = list_make1(makeDefElem("analyze", NULL));
+ n->options = list_make1(makeDefElem("analyze", NULL, @2));
if ($3)
n->options = lappend(n->options,
- makeDefElem("verbose", NULL));
+ makeDefElem("verbose", NULL, @3));
$$ = (Node *) n;
}
| EXPLAIN VERBOSE ExplainableStmt
{
ExplainStmt *n = makeNode(ExplainStmt);
n->query = $3;
- n->options = list_make1(makeDefElem("verbose", NULL));
+ n->options = list_make1(makeDefElem("verbose", NULL, @2));
$$ = (Node *) n;
}
| EXPLAIN '(' explain_option_list ')' ExplainableStmt
@@ -10040,7 +10887,7 @@ explain_option_list:
explain_option_elem:
explain_option_name explain_option_arg
{
- $$ = makeDefElem($1, $2);
+ $$ = makeDefElem($1, $2, @1);
}
;
@@ -10284,12 +11131,26 @@ insert_rest:
$$->cols = NIL;
$$->selectStmt = $1;
}
+ | OVERRIDING override_kind VALUE_P SelectStmt
+ {
+ $$ = makeNode(InsertStmt);
+ $$->cols = NIL;
+ $$->override = $2;
+ $$->selectStmt = $4;
+ }
| '(' insert_column_list ')' SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
$$->selectStmt = $4;
}
+ | '(' insert_column_list ')' OVERRIDING override_kind VALUE_P SelectStmt
+ {
+ $$ = makeNode(InsertStmt);
+ $$->cols = $2;
+ $$->override = $5;
+ $$->selectStmt = $7;
+ }
| DEFAULT VALUES
{
$$ = makeNode(InsertStmt);
@@ -10298,6 +11159,11 @@ insert_rest:
}
;
+override_kind:
+ USER { $$ = OVERRIDING_USER_VALUE; }
+ | SYSTEM_P { $$ = OVERRIDING_SYSTEM_VALUE; }
+ ;
+
insert_column_list:
insert_column_item
{ $$ = list_make1($1); }
@@ -10471,75 +11337,24 @@ set_clause_list:
;
set_clause:
- single_set_clause { $$ = list_make1($1); }
- | multiple_set_clause { $$ = $1; }
- ;
-
-single_set_clause:
- set_target '=' ctext_expr
- {
- $$ = $1;
- $$->val = (Node *) $3;
- }
- ;
-
-/*
- * Ideally, we'd accept any row-valued a_expr as RHS of a multiple_set_clause.
- * However, per SQL spec the row-constructor case must allow DEFAULT as a row
- * member, and it's pretty unclear how to do that (unless perhaps we allow
- * DEFAULT in any a_expr and let parse analysis sort it out later?). For the
- * moment, the planner/executor only support a subquery as a multiassignment
- * source anyhow, so we need only accept ctext_row and subqueries here.
- */
-multiple_set_clause:
- '(' set_target_list ')' '=' ctext_row
+ set_target '=' a_expr
{
- ListCell *col_cell;
- ListCell *val_cell;
-
- /*
- * Break the ctext_row apart, merge individual expressions
- * into the destination ResTargets. This is semantically
- * equivalent to, and much cheaper to process than, the
- * general case.
- */
- if (list_length($2) != list_length($5))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("number of columns does not match number of values"),
- parser_errposition(@5)));
- forboth(col_cell, $2, val_cell, $5)
- {
- ResTarget *res_col = (ResTarget *) lfirst(col_cell);
- Node *res_val = (Node *) lfirst(val_cell);
-
- res_col->val = res_val;
- }
-
- $$ = $2;
+ $1->val = (Node *) $3;
+ $$ = list_make1($1);
}
- | '(' set_target_list ')' '=' select_with_parens
+ | '(' set_target_list ')' '=' a_expr
{
- SubLink *sl = makeNode(SubLink);
int ncolumns = list_length($2);
int i = 1;
ListCell *col_cell;
- /* First, convert bare SelectStmt into a SubLink */
- sl->subLinkType = MULTIEXPR_SUBLINK;
- sl->subLinkId = 0; /* will be assigned later */
- sl->testexpr = NULL;
- sl->operName = NIL;
- sl->subselect = $5;
- sl->location = @5;
-
/* Create a MultiAssignRef source for each target */
foreach(col_cell, $2)
{
ResTarget *res_col = (ResTarget *) lfirst(col_cell);
MultiAssignRef *r = makeNode(MultiAssignRef);
- r->source = (Node *) sl;
+ r->source = (Node *) $5;
r->colno = i;
r->ncolumns = ncolumns;
res_col->val = (Node *) r;
@@ -11198,17 +12013,22 @@ locked_rels_list:
;
+/*
+ * We should allow ROW '(' expr_list ')' too, but that seems to require
+ * making VALUES a fully reserved word, which will probably break more apps
+ * than allowing the noise-word is worth.
+ */
values_clause:
- VALUES ctext_row
+ VALUES '(' expr_list ')'
{
SelectStmt *n = makeNode(SelectStmt);
- n->valuesLists = list_make1($2);
+ n->valuesLists = list_make1($3);
$$ = (Node *) n;
}
- | values_clause ',' ctext_row
+ | values_clause ',' '(' expr_list ')'
{
SelectStmt *n = (SelectStmt *) $1;
- n->valuesLists = lappend(n->valuesLists, $3);
+ n->valuesLists = lappend(n->valuesLists, $4);
$$ = (Node *) n;
}
;
@@ -11263,6 +12083,19 @@ table_ref: relation_expr opt_alias_clause
n->coldeflist = lsecond($3);
$$ = (Node *) n;
}
+ | xmltable opt_alias_clause
+ {
+ RangeTableFunc *n = (RangeTableFunc *) $1;
+ n->alias = $2;
+ $$ = (Node *) n;
+ }
+ | LATERAL_P xmltable opt_alias_clause
+ {
+ RangeTableFunc *n = (RangeTableFunc *) $2;
+ n->lateral = true;
+ n->alias = $3;
+ $$ = (Node *) n;
+ }
| select_with_parens opt_alias_clause
{
RangeSubselect *n = makeNode(RangeSubselect);
@@ -11304,7 +12137,7 @@ table_ref: relation_expr opt_alias_clause
n->lateral = true;
n->subquery = $2;
n->alias = $3;
- /* same coment as above */
+ /* same comment as above */
if ($3 == NULL)
{
if (IsA($2, SelectStmt) &&
@@ -11509,30 +12342,30 @@ join_qual: USING '(' name_list ')' { $$ = (Node *) $3; }
relation_expr:
qualified_name
{
- /* default inheritance */
+ /* inheritance query, implicitly */
$$ = $1;
- $$->inhOpt = INH_DEFAULT;
+ $$->inh = true;
$$->alias = NULL;
}
| qualified_name '*'
{
- /* inheritance query */
+ /* inheritance query, explicitly */
$$ = $1;
- $$->inhOpt = INH_YES;
+ $$->inh = true;
$$->alias = NULL;
}
| ONLY qualified_name
{
/* no inheritance */
$$ = $2;
- $$->inhOpt = INH_NO;
+ $$->inh = false;
$$->alias = NULL;
}
| ONLY '(' qualified_name ')'
{
/* no inheritance, SQL99-style syntax */
$$ = $3;
- $$->inhOpt = INH_NO;
+ $$->inh = false;
$$->alias = NULL;
}
;
@@ -11691,6 +12524,7 @@ TableFuncElement: ColId Typename opt_collate_clause
n->is_local = true;
n->is_not_null = false;
n->is_from_type = false;
+ n->is_from_parent = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
@@ -11702,6 +12536,166 @@ TableFuncElement: ColId Typename opt_collate_clause
}
;
+/*
+ * XMLTABLE
+ */
+xmltable:
+ XMLTABLE '(' c_expr xmlexists_argument COLUMNS xmltable_column_list ')'
+ {
+ RangeTableFunc *n = makeNode(RangeTableFunc);
+ n->rowexpr = $3;
+ n->docexpr = $4;
+ n->columns = $6;
+ n->namespaces = NIL;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
+ | XMLTABLE '(' XMLNAMESPACES '(' xml_namespace_list ')' ','
+ c_expr xmlexists_argument COLUMNS xmltable_column_list ')'
+ {
+ RangeTableFunc *n = makeNode(RangeTableFunc);
+ n->rowexpr = $8;
+ n->docexpr = $9;
+ n->columns = $11;
+ n->namespaces = $5;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
+ ;
+
+xmltable_column_list: xmltable_column_el { $$ = list_make1($1); }
+ | xmltable_column_list ',' xmltable_column_el { $$ = lappend($1, $3); }
+ ;
+
+xmltable_column_el:
+ ColId Typename
+ {
+ RangeTableFuncCol *fc = makeNode(RangeTableFuncCol);
+
+ fc->colname = $1;
+ fc->for_ordinality = false;
+ fc->typeName = $2;
+ fc->is_not_null = false;
+ fc->colexpr = NULL;
+ fc->coldefexpr = NULL;
+ fc->location = @1;
+
+ $$ = (Node *) fc;
+ }
+ | ColId Typename xmltable_column_option_list
+ {
+ RangeTableFuncCol *fc = makeNode(RangeTableFuncCol);
+ ListCell *option;
+ bool nullability_seen = false;
+
+ fc->colname = $1;
+ fc->typeName = $2;
+ fc->for_ordinality = false;
+ fc->is_not_null = false;
+ fc->colexpr = NULL;
+ fc->coldefexpr = NULL;
+ fc->location = @1;
+
+ foreach(option, $3)
+ {
+ DefElem *defel = (DefElem *) lfirst(option);
+
+ if (strcmp(defel->defname, "default") == 0)
+ {
+ if (fc->coldefexpr != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("only one DEFAULT value is allowed"),
+ parser_errposition(defel->location)));
+ fc->coldefexpr = defel->arg;
+ }
+ else if (strcmp(defel->defname, "path") == 0)
+ {
+ if (fc->colexpr != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("only one PATH value per column is allowed"),
+ parser_errposition(defel->location)));
+ fc->colexpr = defel->arg;
+ }
+ else if (strcmp(defel->defname, "is_not_null") == 0)
+ {
+ if (nullability_seen)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant NULL / NOT NULL declarations for column \"%s\"", fc->colname),
+ parser_errposition(defel->location)));
+ fc->is_not_null = intVal(defel->arg);
+ nullability_seen = true;
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized column option \"%s\"",
+ defel->defname),
+ parser_errposition(defel->location)));
+ }
+ }
+ $$ = (Node *) fc;
+ }
+ | ColId FOR ORDINALITY
+ {
+ RangeTableFuncCol *fc = makeNode(RangeTableFuncCol);
+
+ fc->colname = $1;
+ fc->for_ordinality = true;
+ /* other fields are ignored, initialized by makeNode */
+ fc->location = @1;
+
+ $$ = (Node *) fc;
+ }
+ ;
+
+xmltable_column_option_list:
+ xmltable_column_option_el
+ { $$ = list_make1($1); }
+ | xmltable_column_option_list xmltable_column_option_el
+ { $$ = lappend($1, $2); }
+ ;
+
+xmltable_column_option_el:
+ IDENT b_expr
+ { $$ = makeDefElem($1, $2, @1); }
+ | DEFAULT b_expr
+ { $$ = makeDefElem("default", $2, @1); }
+ | NOT NULL_P
+ { $$ = makeDefElem("is_not_null", (Node *) makeInteger(true), @1); }
+ | NULL_P
+ { $$ = makeDefElem("is_not_null", (Node *) makeInteger(false), @1); }
+ ;
+
+xml_namespace_list:
+ xml_namespace_el
+ { $$ = list_make1($1); }
+ | xml_namespace_list ',' xml_namespace_el
+ { $$ = lappend($1, $3); }
+ ;
+
+xml_namespace_el:
+ b_expr AS ColLabel
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = $3;
+ $$->indirection = NIL;
+ $$->val = $1;
+ $$->location = @1;
+ }
+ | DEFAULT b_expr
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = NULL;
+ $$->indirection = NIL;
+ $$->val = $2;
+ $$->location = @1;
+ }
+ ;
+
/*****************************************************************************
*
* Type syntax
@@ -11998,28 +12992,20 @@ ConstCharacter: CharacterWithLength
}
;
-CharacterWithLength: character '(' Iconst ')' opt_charset
+CharacterWithLength: character '(' Iconst ')'
{
- if (($5 != NULL) && (strcmp($5, "sql_text") != 0))
- $1 = psprintf("%s_%s", $1, $5);
-
$$ = SystemTypeName($1);
$$->typmods = list_make1(makeIntConst($3, @3));
$$->location = @1;
}
;
-CharacterWithoutLength: character opt_charset
+CharacterWithoutLength: character
{
- if (($2 != NULL) && (strcmp($2, "sql_text") != 0))
- $1 = psprintf("%s_%s", $1, $2);
-
$$ = SystemTypeName($1);
-
/* char defaults to char(1), varchar to no limit */
if (strcmp($1, "bpchar") == 0)
$$->typmods = list_make1(makeIntConst(1, -1));
-
$$->location = @1;
}
;
@@ -12043,11 +13029,6 @@ opt_varying:
| /*EMPTY*/ { $$ = FALSE; }
;
-opt_charset:
- CHARACTER SET ColId { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
/*
* SQL date/time types
*/
@@ -12599,6 +13580,20 @@ a_expr: c_expr { $$ = $1; }
list_make1($1), @2),
@2);
}
+ | DEFAULT
+ {
+ /*
+ * The SQL spec only allows DEFAULT in "contextually typed
+ * expressions", but for us, it's easier to allow it in
+ * any a_expr and then throw error during parse analysis
+ * if it's in an inappropriate context. This way also
+ * lets us say something smarter than "syntax error".
+ */
+ SetToDefault *n = makeNode(SetToDefault);
+ /* parse analysis will fill in the rest */
+ n->location = @1;
+ $$ = (Node *)n;
+ }
;
/*
@@ -12718,7 +13713,10 @@ c_expr: columnref { $$ = $1; }
* AEXPR_PAREN nodes wrapping all explicitly
* parenthesized subexpressions; this prevents bogus
* warnings from being issued when the ordering has
- * been forced by parentheses.
+ * been forced by parentheses. Take care that an
+ * AEXPR_PAREN node has the same exprLocation as its
+ * child, so as not to cause surprising changes in
+ * error cursor positioning.
*
* In principle we should not be relying on a GUC to
* decide whether to insert AEXPR_PAREN nodes.
@@ -12727,7 +13725,8 @@ c_expr: columnref { $$ = $1; }
* we'd just as soon not waste cycles on dummy parse
* nodes if we don't have to.
*/
- $$ = (Node *) makeA_Expr(AEXPR_PAREN, NIL, $2, NULL, @1);
+ $$ = (Node *) makeA_Expr(AEXPR_PAREN, NIL, $2, NULL,
+ exprLocation($2));
}
else
$$ = $2;
@@ -12795,8 +13794,7 @@ c_expr: columnref { $$ = $1; }
}
| ARRAY array_expr
{
- A_ArrayExpr *n = (A_ArrayExpr *) $2;
- Assert(IsA(n, A_ArrayExpr));
+ A_ArrayExpr *n = castNode(A_ArrayExpr, $2);
/* point outermost A_ArrayExpr to the ARRAY keyword */
n->location = @1;
$$ = (Node *)n;
@@ -12961,143 +13959,63 @@ func_expr_common_subexpr:
}
| CURRENT_DATE
{
- /*
- * Translate as "'now'::text::date".
- *
- * We cannot use "'now'::date" because coerce_type() will
- * immediately reduce that to a constant representing
- * today's date. We need to delay the conversion until
- * runtime, else the wrong things will happen when
- * CURRENT_DATE is used in a column default value or rule.
- *
- * This could be simplified if we had a way to generate
- * an expression tree representing runtime application
- * of type-input conversion functions. (As of PG 7.3
- * that is actually possible, but not clear that we want
- * to rely on it.)
- *
- * The token location is attached to the run-time
- * typecast, not to the Const, for the convenience of
- * pg_stat_statements (which doesn't want these constructs
- * to appear to be replaceable constants).
- */
- Node *n;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- $$ = makeTypeCast(n, SystemTypeName("date"), @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_DATE, -1, @1);
}
| CURRENT_TIME
{
- /*
- * Translate as "'now'::text::timetz".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- $$ = makeTypeCast(n, SystemTypeName("timetz"), @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_TIME, -1, @1);
}
| CURRENT_TIME '(' Iconst ')'
{
- /*
- * Translate as "'now'::text::timetz(n)".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- TypeName *d;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- d = SystemTypeName("timetz");
- d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast(n, d, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_TIME_N, $3, @1);
}
| CURRENT_TIMESTAMP
{
- /*
- * Translate as "now()", since we have a function that
- * does exactly what is needed.
- */
- $$ = (Node *) makeFuncCall(SystemFuncName("now"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_TIMESTAMP, -1, @1);
}
| CURRENT_TIMESTAMP '(' Iconst ')'
{
- /*
- * Translate as "'now'::text::timestamptz(n)".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- TypeName *d;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- d = SystemTypeName("timestamptz");
- d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast(n, d, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_TIMESTAMP_N, $3, @1);
}
| LOCALTIME
{
- /*
- * Translate as "'now'::text::time".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- $$ = makeTypeCast((Node *)n, SystemTypeName("time"), @1);
+ $$ = makeSQLValueFunction(SVFOP_LOCALTIME, -1, @1);
}
| LOCALTIME '(' Iconst ')'
{
- /*
- * Translate as "'now'::text::time(n)".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- TypeName *d;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- d = SystemTypeName("time");
- d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast((Node *)n, d, @1);
+ $$ = makeSQLValueFunction(SVFOP_LOCALTIME_N, $3, @1);
}
| LOCALTIMESTAMP
{
- /*
- * Translate as "'now'::text::timestamp".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- $$ = makeTypeCast(n, SystemTypeName("timestamp"), @1);
+ $$ = makeSQLValueFunction(SVFOP_LOCALTIMESTAMP, -1, @1);
}
| LOCALTIMESTAMP '(' Iconst ')'
{
- /*
- * Translate as "'now'::text::timestamp(n)".
- * See comments for CURRENT_DATE.
- */
- Node *n;
- TypeName *d;
- n = makeStringConstCast("now", -1, SystemTypeName("text"));
- d = SystemTypeName("timestamp");
- d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast(n, d, @1);
+ $$ = makeSQLValueFunction(SVFOP_LOCALTIMESTAMP_N, $3, @1);
}
| CURRENT_ROLE
{
- $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_ROLE, -1, @1);
}
| CURRENT_USER
{
- $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_USER, -1, @1);
}
| SESSION_USER
{
- $$ = (Node *) makeFuncCall(SystemFuncName("session_user"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_SESSION_USER, -1, @1);
}
| USER
{
- $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_USER, -1, @1);
}
| CURRENT_CATALOG
{
- $$ = (Node *) makeFuncCall(SystemFuncName("current_database"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_CATALOG, -1, @1);
}
| CURRENT_SCHEMA
{
- $$ = (Node *) makeFuncCall(SystemFuncName("current_schema"), NIL, @1);
+ $$ = makeSQLValueFunction(SVFOP_CURRENT_SCHEMA, -1, @1);
}
| CAST '(' a_expr AS Typename ')'
{ $$ = makeTypeCast($3, $5, @1); }
@@ -13934,36 +14852,6 @@ opt_asymmetric: ASYMMETRIC
| /*EMPTY*/
;
-/*
- * The SQL spec defines "contextually typed value expressions" and
- * "contextually typed row value constructors", which for our purposes
- * are the same as "a_expr" and "row" except that DEFAULT can appear at
- * the top level.
- */
-
-ctext_expr:
- a_expr { $$ = (Node *) $1; }
- | DEFAULT
- {
- SetToDefault *n = makeNode(SetToDefault);
- n->location = @1;
- $$ = (Node *) n;
- }
- ;
-
-ctext_expr_list:
- ctext_expr { $$ = list_make1($1); }
- | ctext_expr_list ',' ctext_expr { $$ = lappend($1, $3); }
- ;
-
-/*
- * We should allow ROW '(' ctext_expr_list ')' too, but that seems to require
- * making VALUES a fully reserved word, which will probably break more apps
- * than allowing the noise-word is worth.
- */
-ctext_row: '(' ctext_expr_list ')' { $$ = $2; }
- ;
-
/*****************************************************************************
*
@@ -14275,10 +15163,10 @@ RoleSpec: NonReservedWord
}
else
{
- n = (RoleSpec *) makeRoleSpec(ROLESPEC_CSTRING, @1);
+ n = makeRoleSpec(ROLESPEC_CSTRING, @1);
n->rolename = pstrdup($1);
}
- $$ = (Node *) n;
+ $$ = n;
}
| CURRENT_USER
{
@@ -14371,6 +15259,7 @@ unreserved_keyword:
| ASSERTION
| ASSIGNMENT
| AT
+ | ATTACH
| ATTRIBUTE
| BACKWARD
/* PGXC_BEGIN */
@@ -14391,6 +15280,7 @@ unreserved_keyword:
| CLEAN
| CLOSE
| CLUSTER
+ | COLUMNS
| COMMENT
| COMMENTS
| COMMIT
@@ -14422,6 +15312,7 @@ unreserved_keyword:
| DELIMITER
| DELIMITERS
| DEPENDS
+ | DETACH
| DICTIONARY
| DIRECT
| DISABLE_P
@@ -14458,6 +15349,7 @@ unreserved_keyword:
| FORWARD
| FUNCTION
| FUNCTIONS
+ | GENERATED
| GLOBAL
| GRANTED
| HANDLER
@@ -14509,6 +15401,7 @@ unreserved_keyword:
| MOVE
| NAME_P
| NAMES
+ | NEW
| NEXT
| NO
| NODE
@@ -14520,11 +15413,13 @@ unreserved_keyword:
| OF
| OFF
| OIDS
+ | OLD
| OPERATOR
| OPTION
| OPTIONS
| ORDINALITY
| OVER
+ | OVERRIDING
| OWNED
| OWNER
| PARALLEL
@@ -14550,6 +15445,7 @@ unreserved_keyword:
| PROCEDURAL
| PROCEDURE
| PROGRAM
+ | PUBLICATION
| QUOTE
/* PGXC_BEGIN */
| RANDOMLY
@@ -14560,6 +15456,7 @@ unreserved_keyword:
| RECHECK
| RECURSIVE
| REF
+ | REFERENCING
| REFRESH
| REINDEX
| RELATIVE_P
@@ -14580,6 +15477,7 @@ unreserved_keyword:
| RULE
| SAVEPOINT
| SCHEMA
+ | SCHEMAS
| SCROLL
| SEARCH
| SECOND_P
@@ -14607,6 +15505,7 @@ unreserved_keyword:
| STORAGE
| STRICT_P
| STRIP_P
+ | SUBSCRIPTION
| SYSID
| SYSTEM_P
| TABLES
@@ -14710,10 +15609,12 @@ col_name_keyword:
| XMLELEMENT
| XMLEXISTS
| XMLFOREST
+ | XMLNAMESPACES
| XMLPARSE
| XMLPI
| XMLROOT
| XMLSERIALIZE
+ | XMLTABLE
;
/* Type/function identifier --- keywords that can be type or function names.
@@ -14851,6 +15752,33 @@ base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg)
parser_yyerror(msg);
}
+static RawStmt *
+makeRawStmt(Node *stmt, int stmt_location)
+{
+ RawStmt *rs = makeNode(RawStmt);
+
+ rs->stmt = stmt;
+ rs->stmt_location = stmt_location;
+ rs->stmt_len = 0; /* might get changed later */
+ return rs;
+}
+
+/* Adjust a RawStmt to reflect that it doesn't run to the end of the string */
+static void
+updateRawStmtEnd(RawStmt *rs, int end_location)
+{
+ /*
+ * If we already set the length, don't change it. This is for situations
+ * like "select foo ;; select bar" where the same statement will be last
+ * in the string for more than one semicolon.
+ */
+ if (rs->stmt_len > 0)
+ return;
+
+ /* OK, update length of RawStmt */
+ rs->stmt_len = end_location - rs->stmt_location;
+}
+
static Node *
makeColumnRef(char *colname, List *indirection,
int location, core_yyscan_t yyscanner)
@@ -15022,7 +15950,7 @@ makeBoolAConst(bool state, int location)
/* makeRoleSpec
* Create a RoleSpec with the given type
*/
-static Node *
+static RoleSpec *
makeRoleSpec(RoleSpecType type, int location)
{
RoleSpec *spec = makeNode(RoleSpec);
@@ -15030,7 +15958,7 @@ makeRoleSpec(RoleSpecType type, int location)
spec->roletype = type;
spec->location = location;
- return (Node *) spec;
+ return spec;
}
/* check_qualified_name --- check the result of qualified_name production
@@ -15368,6 +16296,18 @@ makeAArrayExpr(List *elements, int location)
}
static Node *
+makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location)
+{
+ SQLValueFunction *svf = makeNode(SQLValueFunction);
+
+ svf->op = op;
+ /* svf->type will be filled during parse analysis */
+ svf->typmod = typmod;
+ svf->location = location;
+ return (Node *) svf;
+}
+
+static Node *
makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args,
int location)
{
@@ -15424,7 +16364,7 @@ TableFuncTypeName(List *columns)
{
FunctionParameter *p = (FunctionParameter *) linitial(columns);
- result = (TypeName *) copyObject(p->argType);
+ result = copyObject(p->argType);
}
else
result = SystemTypeName("record");
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 6876f2a3d4..9fc0371cb3 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -4,7 +4,7 @@
* handle aggregates and window functions in parser
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -162,8 +162,7 @@ transformAggregateCall(ParseState *pstate, Aggref *agg,
tlist = lappend(tlist, tle);
torder = addTargetToSortList(pstate, tle,
- torder, tlist, sortby,
- true /* fix unknowns */ );
+ torder, tlist, sortby);
}
/* Never any DISTINCT in an ordered-set agg */
@@ -203,7 +202,6 @@ transformAggregateCall(ParseState *pstate, Aggref *agg,
aggorder,
&tlist,
EXPR_KIND_ORDER_BY,
- true /* fix unknowns */ ,
true /* force SQL99 rules */ );
/*
@@ -454,6 +452,7 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr)
errkind = true;
break;
case EXPR_KIND_VALUES:
+ case EXPR_KIND_VALUES_SINGLE:
errkind = true;
break;
case EXPR_KIND_CHECK_CONSTRAINT:
@@ -508,6 +507,13 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr)
err = _("grouping operations are not allowed in trigger WHEN conditions");
break;
+ case EXPR_KIND_PARTITION_EXPRESSION:
+ if (isAgg)
+ err = _("aggregate functions are not allowed in partition key expression");
+ else
+ err = _("grouping operations are not allowed in partition key expression");
+
+ break;
/*
* There is intentionally no default: case here, so that the
@@ -840,6 +846,7 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
errkind = true;
break;
case EXPR_KIND_VALUES:
+ case EXPR_KIND_VALUES_SINGLE:
errkind = true;
break;
case EXPR_KIND_CHECK_CONSTRAINT:
@@ -865,6 +872,9 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
case EXPR_KIND_TRIGGER_WHEN:
err = _("window functions are not allowed in trigger WHEN conditions");
break;
+ case EXPR_KIND_PARTITION_EXPRESSION:
+ err = _("window functions are not allowed in partition key expression");
+ break;
/*
* There is intentionally no default: case here, so that the
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 751de4bddb..27dd49d301 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -3,7 +3,7 @@
* parse_clause.c
* handle clauses in parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,6 +22,7 @@
#include "catalog/catalog.h"
#include "catalog/heap.h"
#include "catalog/pg_am.h"
+#include "catalog/pg_collation.h"
#include "catalog/pg_constraint_fn.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
@@ -58,13 +59,18 @@ static Node *transformJoinUsingClause(ParseState *pstate,
List *leftVars, List *rightVars);
static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j,
List *namespace);
+static RangeTblEntry *getRTEForSpecialRelationTypes(ParseState *pstate,
+ RangeVar *rv);
static RangeTblEntry *transformTableEntry(ParseState *pstate, RangeVar *r);
static RangeTblEntry *transformCTEReference(ParseState *pstate, RangeVar *r,
CommonTableExpr *cte, Index levelsup);
+static RangeTblEntry *transformENRReference(ParseState *pstate, RangeVar *r);
static RangeTblEntry *transformRangeSubselect(ParseState *pstate,
RangeSubselect *r);
static RangeTblEntry *transformRangeFunction(ParseState *pstate,
RangeFunction *r);
+static RangeTblEntry *transformRangeTableFunc(ParseState *pstate,
+ RangeTableFunc *t);
static TableSampleClause *transformRangeTableSample(ParseState *pstate,
RangeTableSample *rts);
static Node *transformFromClauseItem(ParseState *pstate, Node *n,
@@ -89,8 +95,7 @@ static int get_matching_location(int sortgroupref,
static List *resolve_unique_index_expr(ParseState *pstate, InferClause *infer,
Relation heapRel);
static List *addTargetToGroupList(ParseState *pstate, TargetEntry *tle,
- List *grouplist, List *targetlist, int location,
- bool resolveUnknown);
+ List *grouplist, List *targetlist, int location);
static WindowClause *findWindowClause(List *wclist, const char *name);
static Node *transformFrameOffset(ParseState *pstate, int frameOptions,
Node *clause);
@@ -179,6 +184,14 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
RangeTblEntry *rte;
int rtindex;
+ /* So far special relations are immutable; so they cannot be targets. */
+ rte = getRTEForSpecialRelationTypes(pstate, relation);
+ if (rte != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("relation \"%s\" cannot be the target of a modifying statement",
+ relation->relname)));
+
/* Close old target; this could only happen for multi-action rules */
if (pstate->p_target_relation != NULL)
heap_close(pstate->p_target_relation, NoLock);
@@ -229,30 +242,6 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
}
/*
- * Simplify InhOption (yes/no/default) into boolean yes/no.
- *
- * The reason we do things this way is that we don't want to examine the
- * SQL_inheritance option flag until parse_analyze() is run. Otherwise,
- * we'd do the wrong thing with query strings that intermix SET commands
- * with queries.
- */
-bool
-interpretInhOption(InhOption inhOpt)
-{
- switch (inhOpt)
- {
- case INH_NO:
- return false;
- case INH_YES:
- return true;
- case INH_DEFAULT:
- return SQL_inheritance;
- }
- elog(ERROR, "bogus InhOption value: %d", inhOpt);
- return false; /* keep compiler quiet */
-}
-
-/*
* Given a relation-options list (of DefElems), return true iff the specified
* table/result set should be created with OIDs. This needs to be done after
* parsing the query string because the return value can depend upon the
@@ -370,7 +359,7 @@ transformJoinUsingClause(ParseState *pstate,
/* Now create the lvar = rvar join condition */
e = makeSimpleA_Expr(AEXPR_OP, "=",
- copyObject(lvar), copyObject(rvar),
+ (Node *) copyObject(lvar), (Node *) copyObject(rvar),
-1);
/* Prepare to combine into an AND clause, if multiple join columns */
@@ -436,8 +425,7 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
RangeTblEntry *rte;
/* We need only build a range table entry */
- rte = addRangeTableEntry(pstate, r, r->alias,
- interpretInhOption(r->inhOpt), true);
+ rte = addRangeTableEntry(pstate, r, r->alias, r->inh, true);
return rte;
}
@@ -458,6 +446,20 @@ transformCTEReference(ParseState *pstate, RangeVar *r,
}
/*
+ * transformENRReference --- transform a RangeVar that references an ephemeral
+ * named relation
+ */
+static RangeTblEntry *
+transformENRReference(ParseState *pstate, RangeVar *r)
+{
+ RangeTblEntry *rte;
+
+ rte = addRangeTableEntryForENR(pstate, r, true);
+
+ return rte;
+}
+
+/*
* transformRangeSubselect --- transform a sub-SELECT appearing in FROM
*/
static RangeTblEntry *
@@ -496,19 +498,19 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
* Analyze and transform the subquery.
*/
query = parse_sub_analyze(r->subquery, pstate, NULL,
- isLockedRefname(pstate, r->alias->aliasname));
+ isLockedRefname(pstate, r->alias->aliasname),
+ true);
/* Restore state */
pstate->p_lateral_active = false;
pstate->p_expr_kind = EXPR_KIND_NONE;
/*
- * Check that we got something reasonable. Many of these conditions are
- * impossible given restrictions of the grammar, but check 'em anyway.
+ * Check that we got a SELECT. Anything else should be impossible given
+ * restrictions of the grammar, but check anyway.
*/
if (!IsA(query, Query) ||
- query->commandType != CMD_SELECT ||
- query->utilityStmt != NULL)
+ query->commandType != CMD_SELECT)
elog(ERROR, "unexpected non-SELECT command in subquery in FROM");
/*
@@ -719,6 +721,228 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
}
/*
+ * transformRangeTableFunc -
+ * Transform a raw RangeTableFunc into TableFunc.
+ *
+ * Transform the namespace clauses, the document-generating expression, the
+ * row-generating expression, the column-generating expressions, and the
+ * default value expressions.
+ */
+static RangeTblEntry *
+transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
+{
+ TableFunc *tf = makeNode(TableFunc);
+ const char *constructName;
+ Oid docType;
+ RangeTblEntry *rte;
+ bool is_lateral;
+ ListCell *col;
+ char **names;
+ int colno;
+
+ /* Currently only XMLTABLE is supported */
+ constructName = "XMLTABLE";
+ docType = XMLOID;
+
+ /*
+ * We make lateral_only names of this level visible, whether or not the
+ * RangeTableFunc is explicitly marked LATERAL. This is needed for SQL
+ * spec compliance and seems useful on convenience grounds for all
+ * functions in FROM.
+ *
+ * (LATERAL can't nest within a single pstate level, so we don't need
+ * save/restore logic here.)
+ */
+ Assert(!pstate->p_lateral_active);
+ pstate->p_lateral_active = true;
+
+ /* Transform and apply typecast to the row-generating expression ... */
+ Assert(rtf->rowexpr != NULL);
+ tf->rowexpr = coerce_to_specific_type(pstate,
+ transformExpr(pstate, rtf->rowexpr, EXPR_KIND_FROM_FUNCTION),
+ TEXTOID,
+ constructName);
+ assign_expr_collations(pstate, tf->rowexpr);
+
+ /* ... and to the document itself */
+ Assert(rtf->docexpr != NULL);
+ tf->docexpr = coerce_to_specific_type(pstate,
+ transformExpr(pstate, rtf->docexpr, EXPR_KIND_FROM_FUNCTION),
+ docType,
+ constructName);
+ assign_expr_collations(pstate, tf->docexpr);
+
+ /* undef ordinality column number */
+ tf->ordinalitycol = -1;
+
+
+ names = palloc(sizeof(char *) * list_length(rtf->columns));
+
+ colno = 0;
+ foreach(col, rtf->columns)
+ {
+ RangeTableFuncCol *rawc = (RangeTableFuncCol *) lfirst(col);
+ Oid typid;
+ int32 typmod;
+ Node *colexpr;
+ Node *coldefexpr;
+ int j;
+
+ tf->colnames = lappend(tf->colnames,
+ makeString(pstrdup(rawc->colname)));
+
+ /*
+ * Determine the type and typmod for the new column. FOR ORDINALITY
+ * columns are INTEGER per spec; the others are user-specified.
+ */
+ if (rawc->for_ordinality)
+ {
+ if (tf->ordinalitycol != -1)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("only one FOR ORDINALITY column is allowed"),
+ parser_errposition(pstate, rawc->location)));
+
+ typid = INT4OID;
+ typmod = -1;
+ tf->ordinalitycol = colno;
+ }
+ else
+ {
+ if (rawc->typeName->setof)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("column \"%s\" cannot be declared SETOF",
+ rawc->colname),
+ parser_errposition(pstate, rawc->location)));
+
+ typenameTypeIdAndMod(pstate, rawc->typeName,
+ &typid, &typmod);
+ }
+
+ tf->coltypes = lappend_oid(tf->coltypes, typid);
+ tf->coltypmods = lappend_int(tf->coltypmods, typmod);
+ tf->colcollations = lappend_oid(tf->colcollations,
+ type_is_collatable(typid) ? DEFAULT_COLLATION_OID : InvalidOid);
+
+ /* Transform the PATH and DEFAULT expressions */
+ if (rawc->colexpr)
+ {
+ colexpr = coerce_to_specific_type(pstate,
+ transformExpr(pstate, rawc->colexpr,
+ EXPR_KIND_FROM_FUNCTION),
+ TEXTOID,
+ constructName);
+ assign_expr_collations(pstate, colexpr);
+ }
+ else
+ colexpr = NULL;
+
+ if (rawc->coldefexpr)
+ {
+ coldefexpr = coerce_to_specific_type_typmod(pstate,
+ transformExpr(pstate, rawc->coldefexpr,
+ EXPR_KIND_FROM_FUNCTION),
+ typid, typmod,
+ constructName);
+ assign_expr_collations(pstate, coldefexpr);
+ }
+ else
+ coldefexpr = NULL;
+
+ tf->colexprs = lappend(tf->colexprs, colexpr);
+ tf->coldefexprs = lappend(tf->coldefexprs, coldefexpr);
+
+ if (rawc->is_not_null)
+ tf->notnulls = bms_add_member(tf->notnulls, colno);
+
+ /* make sure column names are unique */
+ for (j = 0; j < colno; j++)
+ if (strcmp(names[j], rawc->colname) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("column name \"%s\" is not unique",
+ rawc->colname),
+ parser_errposition(pstate, rawc->location)));
+ names[colno] = rawc->colname;
+
+ colno++;
+ }
+ pfree(names);
+
+ /* Namespaces, if any, also need to be transformed */
+ if (rtf->namespaces != NIL)
+ {
+ ListCell *ns;
+ ListCell *lc2;
+ List *ns_uris = NIL;
+ List *ns_names = NIL;
+ bool default_ns_seen = false;
+
+ foreach(ns, rtf->namespaces)
+ {
+ ResTarget *r = (ResTarget *) lfirst(ns);
+ Node *ns_uri;
+
+ Assert(IsA(r, ResTarget));
+ ns_uri = transformExpr(pstate, r->val, EXPR_KIND_FROM_FUNCTION);
+ ns_uri = coerce_to_specific_type(pstate, ns_uri,
+ TEXTOID, constructName);
+ assign_expr_collations(pstate, ns_uri);
+ ns_uris = lappend(ns_uris, ns_uri);
+
+ /* Verify consistency of name list: no dupes, only one DEFAULT */
+ if (r->name != NULL)
+ {
+ foreach(lc2, ns_names)
+ {
+ char *name = strVal(lfirst(lc2));
+
+ if (name == NULL)
+ continue;
+ if (strcmp(name, r->name) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("namespace name \"%s\" is not unique",
+ name),
+ parser_errposition(pstate, r->location)));
+ }
+ }
+ else
+ {
+ if (default_ns_seen)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("only one default namespace is allowed"),
+ parser_errposition(pstate, r->location)));
+ default_ns_seen = true;
+ }
+
+ /* Note the string may be NULL */
+ ns_names = lappend(ns_names, makeString(r->name));
+ }
+
+ tf->ns_uris = ns_uris;
+ tf->ns_names = ns_names;
+ }
+
+ tf->location = rtf->location;
+
+ pstate->p_lateral_active = false;
+
+ /*
+ * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
+ * there are any lateral cross-references in it.
+ */
+ is_lateral = rtf->lateral || contain_vars_of_level((Node *) tf, 0);
+
+ rte = addRangeTableEntryForTableFunc(pstate,
+ tf, rtf->alias, is_lateral, true);
+
+ return rte;
+}
+
+/*
* transformRangeTableSample --- transform a TABLESAMPLE clause
*
* Caller has already transformed rts->relation, we just have to validate
@@ -822,6 +1046,22 @@ transformRangeTableSample(ParseState *pstate, RangeTableSample *rts)
}
+static RangeTblEntry *
+getRTEForSpecialRelationTypes(ParseState *pstate, RangeVar *rv)
+{
+ CommonTableExpr *cte;
+ Index levelsup;
+ RangeTblEntry *rte = NULL;
+
+ cte = scanNameSpaceForCTE(pstate, rv->relname, &levelsup);
+ if (cte)
+ rte = transformCTEReference(pstate, rv, cte, levelsup);
+ if (!rte && scanNameSpaceForENR(pstate, rv->relname))
+ rte = transformENRReference(pstate, rv);
+
+ return rte;
+}
+
/*
* transformFromClauseItem -
* Transform a FROM-clause item, adding any required entries to the
@@ -856,18 +1096,14 @@ transformFromClauseItem(ParseState *pstate, Node *n,
RangeTblEntry *rte = NULL;
int rtindex;
- /* if it is an unqualified name, it might be a CTE reference */
+ /*
+ * if it is an unqualified name, it might be a CTE or tuplestore
+ * reference
+ */
if (!rv->schemaname)
- {
- CommonTableExpr *cte;
- Index levelsup;
-
- cte = scanNameSpaceForCTE(pstate, rv->relname, &levelsup);
- if (cte)
- rte = transformCTEReference(pstate, rv, cte, levelsup);
- }
+ rte = getRTEForSpecialRelationTypes(pstate, rv);
- /* if not found as a CTE, must be a table reference */
+ /* if not found above, must be a table reference */
if (!rte)
rte = transformTableEntry(pstate, rv);
@@ -917,6 +1153,24 @@ transformFromClauseItem(ParseState *pstate, Node *n,
rtr->rtindex = rtindex;
return (Node *) rtr;
}
+ else if (IsA(n, RangeTableFunc))
+ {
+ /* table function is like a plain relation */
+ RangeTblRef *rtr;
+ RangeTblEntry *rte;
+ int rtindex;
+
+ rte = transformRangeTableFunc(pstate, (RangeTableFunc *) n);
+ /* assume new rte is at end */
+ rtindex = list_length(pstate->p_rtable);
+ Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
+ *top_rte = rte;
+ *top_rti = rtindex;
+ *namespace = list_make1(makeDefaultNSItem(rte));
+ rtr = makeNode(RangeTblRef);
+ rtr->rtindex = rtindex;
+ return (Node *) rtr;
+ }
else if (IsA(n, RangeTableSample))
{
/* TABLESAMPLE clause (wrapping some other valid FROM node) */
@@ -929,12 +1183,12 @@ transformFromClauseItem(ParseState *pstate, Node *n,
rel = transformFromClauseItem(pstate, rts->relation,
top_rte, top_rti, namespace);
/* Currently, grammar could only return a RangeVar as contained rel */
- Assert(IsA(rel, RangeTblRef));
- rtr = (RangeTblRef *) rel;
+ rtr = castNode(RangeTblRef, rel);
rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
/* We only support this on plain relations and matviews */
if (rte->relkind != RELKIND_RELATION &&
- rte->relkind != RELKIND_MATVIEW)
+ rte->relkind != RELKIND_MATVIEW &&
+ rte->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("TABLESAMPLE clause can only be applied to tables and materialized views"),
@@ -2036,8 +2290,7 @@ transformGroupClauseExpr(List **flatresult, Bitmapset *seen_local,
if (!found)
*flatresult = addTargetToGroupList(pstate, tle,
*flatresult, *targetlist,
- exprLocation(gexpr),
- true);
+ exprLocation(gexpr));
/*
* _something_ must have assigned us a sortgroupref by now...
@@ -2325,7 +2578,6 @@ transformSortClause(ParseState *pstate,
List *orderlist,
List **targetlist,
ParseExprKind exprKind,
- bool resolveUnknown,
bool useSQL99)
{
List *sortlist = NIL;
@@ -2344,8 +2596,7 @@ transformSortClause(ParseState *pstate,
targetlist, exprKind);
sortlist = addTargetToSortList(pstate, tle,
- sortlist, *targetlist, sortby,
- resolveUnknown);
+ sortlist, *targetlist, sortby);
}
return sortlist;
@@ -2407,7 +2658,6 @@ transformWindowDefinitions(ParseState *pstate,
windef->orderClause,
targetlist,
EXPR_KIND_WINDOW_ORDER,
- true /* fix unknowns */ ,
true /* force SQL99 rules */ );
partitionClause = transformGroupClause(pstate,
windef->partitionClause,
@@ -2578,8 +2828,7 @@ transformDistinctClause(ParseState *pstate,
continue; /* ignore junk */
result = addTargetToGroupList(pstate, tle,
result, *targetlist,
- exprLocation((Node *) tle->expr),
- true);
+ exprLocation((Node *) tle->expr));
}
/*
@@ -2696,8 +2945,7 @@ transformDistinctOnClause(ParseState *pstate, List *distinctlist,
parser_errposition(pstate, exprLocation(dexpr))));
result = addTargetToGroupList(pstate, tle,
result, *targetlist,
- exprLocation(dexpr),
- true);
+ exprLocation(dexpr));
}
/*
@@ -2931,17 +3179,11 @@ transformOnConflictArbiter(ParseState *pstate,
* list, add it to the end of the list, using the given sort ordering
* info.
*
- * If resolveUnknown is TRUE, convert TLEs of type UNKNOWN to TEXT. If not,
- * do nothing (which implies the search for a sort operator will fail).
- * pstate should be provided if resolveUnknown is TRUE, but can be NULL
- * otherwise.
- *
* Returns the updated SortGroupClause list.
*/
List *
addTargetToSortList(ParseState *pstate, TargetEntry *tle,
- List *sortlist, List *targetlist, SortBy *sortby,
- bool resolveUnknown)
+ List *sortlist, List *targetlist, SortBy *sortby)
{
Oid restype = exprType((Node *) tle->expr);
Oid sortop;
@@ -2952,7 +3194,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
ParseCallbackState pcbstate;
/* if tlist item is an UNKNOWN literal, change it to TEXT */
- if (restype == UNKNOWNOID && resolveUnknown)
+ if (restype == UNKNOWNOID)
{
tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
restype, TEXTOID, -1,
@@ -3080,22 +3322,16 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
* to a SELECT item that matches the GROUP BY item; it'd be pretty confusing
* to report such a location.
*
- * If resolveUnknown is TRUE, convert TLEs of type UNKNOWN to TEXT. If not,
- * do nothing (which implies the search for an equality operator will fail).
- * pstate should be provided if resolveUnknown is TRUE, but can be NULL
- * otherwise.
- *
* Returns the updated SortGroupClause list.
*/
static List *
addTargetToGroupList(ParseState *pstate, TargetEntry *tle,
- List *grouplist, List *targetlist, int location,
- bool resolveUnknown)
+ List *grouplist, List *targetlist, int location)
{
Oid restype = exprType((Node *) tle->expr);
/* if tlist item is an UNKNOWN literal, change it to TEXT */
- if (restype == UNKNOWNOID && resolveUnknown)
+ if (restype == UNKNOWNOID)
{
tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
restype, TEXTOID, -1,
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 633697c8b9..cd05eac159 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -3,7 +3,7 @@
* parse_coerce.c
* handle type coercions/conversions for parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -1084,8 +1084,9 @@ coerce_to_boolean(ParseState *pstate, Node *node,
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
/* translator: first %s is name of a SQL construct, eg WHERE */
- errmsg("argument of %s must be type boolean, not type %s",
- constructName, format_type_be(inputTypeId)),
+ errmsg("argument of %s must be type %s, not type %s",
+ constructName, "boolean",
+ format_type_be(inputTypeId)),
parser_errposition(pstate, exprLocation(node))));
node = newnode;
}
@@ -1102,9 +1103,9 @@ coerce_to_boolean(ParseState *pstate, Node *node,
}
/*
- * coerce_to_specific_type()
- * Coerce an argument of a construct that requires a specific data type.
- * Also check that input is not a set.
+ * coerce_to_specific_type_typmod()
+ * Coerce an argument of a construct that requires a specific data type,
+ * with a specific typmod. Also check that input is not a set.
*
* Returns the possibly-transformed node tree.
*
@@ -1112,9 +1113,9 @@ coerce_to_boolean(ParseState *pstate, Node *node,
* processing is wanted.
*/
Node *
-coerce_to_specific_type(ParseState *pstate, Node *node,
- Oid targetTypeId,
- const char *constructName)
+coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
+ Oid targetTypeId, int32 targetTypmod,
+ const char *constructName)
{
Oid inputTypeId = exprType(node);
@@ -1123,7 +1124,7 @@ coerce_to_specific_type(ParseState *pstate, Node *node,
Node *newnode;
newnode = coerce_to_target_type(pstate, node, inputTypeId,
- targetTypeId, -1,
+ targetTypeId, targetTypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
-1);
@@ -1150,6 +1151,25 @@ coerce_to_specific_type(ParseState *pstate, Node *node,
return node;
}
+/*
+ * coerce_to_specific_type()
+ * Coerce an argument of a construct that requires a specific data type.
+ * Also check that input is not a set.
+ *
+ * Returns the possibly-transformed node tree.
+ *
+ * As with coerce_type, pstate may be NULL if no special unknown-Param
+ * processing is wanted.
+ */
+Node *
+coerce_to_specific_type(ParseState *pstate, Node *node,
+ Oid targetTypeId,
+ const char *constructName)
+{
+ return coerce_to_specific_type_typmod(pstate, node,
+ targetTypeId, -1,
+ constructName);
+}
/*
* parser_coercion_errposition - report coercion error location, if possible
@@ -1702,8 +1722,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (!OidIsValid(array_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyarray\" is not an array but type %s",
- format_type_be(array_typeid))));
+ errmsg("argument declared %s is not an array but type %s",
+ "anyarray", format_type_be(array_typeid))));
}
if (!OidIsValid(elem_typeid))
@@ -1718,7 +1738,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
/* otherwise, they better match */
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""),
+ errmsg("argument declared %s is not consistent with argument declared %s",
+ "anyarray", "anyelement"),
errdetail("%s versus %s",
format_type_be(array_typeid),
format_type_be(elem_typeid))));
@@ -1739,8 +1760,9 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (!OidIsValid(range_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyrange\" is not a range type but type %s",
- format_type_be(range_typeid))));
+ errmsg("argument declared %s is not a range type but type %s",
+ "anyrange",
+ format_type_be(range_typeid))));
}
if (!OidIsValid(elem_typeid))
@@ -1755,7 +1777,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
/* otherwise, they better match */
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyrange\" is not consistent with argument declared \"anyelement\""),
+ errmsg("argument declared %s is not consistent with argument declared %s",
+ "anyrange", "anyelement"),
errdetail("%s versus %s",
format_type_be(range_typeid),
format_type_be(elem_typeid))));
@@ -1775,7 +1798,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
/* Only way to get here is if all the generic args are UNKNOWN */
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("could not determine polymorphic type because input has type \"unknown\"")));
+ errmsg("could not determine polymorphic type because input has type %s",
+ "unknown")));
}
}
@@ -1913,8 +1937,8 @@ resolve_generic_type(Oid declared_type,
if (!OidIsValid(array_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyarray\" is not an array but type %s",
- format_type_be(context_base_type))));
+ errmsg("argument declared %s is not an array but type %s",
+ "anyarray", format_type_be(context_base_type))));
return context_base_type;
}
else if (context_declared_type == ANYELEMENTOID ||
@@ -1947,8 +1971,8 @@ resolve_generic_type(Oid declared_type,
if (!OidIsValid(array_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyarray\" is not an array but type %s",
- format_type_be(context_base_type))));
+ errmsg("argument declared %s is not an array but type %s",
+ "anyarray", format_type_be(context_base_type))));
return array_typelem;
}
else if (context_declared_type == ANYRANGEOID)
@@ -1960,8 +1984,8 @@ resolve_generic_type(Oid declared_type,
if (!OidIsValid(range_typelem))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("argument declared \"anyrange\" is not a range type but type %s",
- format_type_be(context_base_type))));
+ errmsg("argument declared %s is not a range type but type %s",
+ "anyrange", format_type_be(context_base_type))));
return range_typelem;
}
else if (context_declared_type == ANYELEMENTOID ||
diff --git a/src/backend/parser/parse_collate.c b/src/backend/parser/parse_collate.c
index a19e8dd075..aa443f23ad 100644
--- a/src/backend/parser/parse_collate.c
+++ b/src/backend/parser/parse_collate.c
@@ -29,7 +29,7 @@
* at runtime. If we knew exactly which functions require collation
* information, we could throw those errors at parse time instead.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -514,8 +514,7 @@ assign_collations_walker(Node *node, assign_collations_context *context)
if (qtree->targetList == NIL)
return false;
- tent = (TargetEntry *) linitial(qtree->targetList);
- Assert(IsA(tent, TargetEntry));
+ tent = linitial_node(TargetEntry, qtree->targetList);
if (tent->resjunk)
return false;
@@ -650,9 +649,7 @@ assign_collations_walker(Node *node, assign_collations_context *context)
foreach(lc, expr->args)
{
- CaseWhen *when = (CaseWhen *) lfirst(lc);
-
- Assert(IsA(when, CaseWhen));
+ CaseWhen *when = lfirst_node(CaseWhen, lc);
/*
* The condition expressions mustn't affect
@@ -805,7 +802,7 @@ merge_collation_state(Oid collation,
else if (collation != DEFAULT_COLLATION_OID)
{
/*
- * Ooops, we have a conflict. We cannot throw error
+ * Oops, we have a conflict. We cannot throw error
* here, since the conflict could be resolved by a
* later sibling CollateExpr, or the parent might not
* care about collation anyway. Return enough info to
@@ -824,7 +821,7 @@ merge_collation_state(Oid collation,
if (collation != context->collation)
{
/*
- * Ooops, we have a conflict of explicit COLLATE clauses.
+ * Oops, we have a conflict of explicit COLLATE clauses.
* Here we choose to throw error immediately; that is what
* the SQL standard says to do, and there's no good reason
* to be less strict.
@@ -868,9 +865,8 @@ assign_aggregate_collations(Aggref *aggref,
/* Process aggregated args, holding resjunk ones at arm's length */
foreach(lc, aggref->args)
{
- TargetEntry *tle = (TargetEntry *) lfirst(lc);
+ TargetEntry *tle = lfirst_node(TargetEntry, lc);
- Assert(IsA(tle, TargetEntry));
if (tle->resjunk)
assign_expr_collations(loccontext->pstate, (Node *) tle);
else
@@ -913,9 +909,8 @@ assign_ordered_set_collations(Aggref *aggref,
/* Process aggregated args appropriately */
foreach(lc, aggref->args)
{
- TargetEntry *tle = (TargetEntry *) lfirst(lc);
+ TargetEntry *tle = lfirst_node(TargetEntry, lc);
- Assert(IsA(tle, TargetEntry));
if (merge_sort_collations)
(void) assign_collations_walker((Node *) tle, loccontext);
else
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index 5e8bcd40d5..dfbcaa2cdc 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -3,7 +3,7 @@
* parse_cte.c
* handle CTEs (common table expressions) in parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -241,7 +241,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
/* Analysis not done already */
Assert(!IsA(cte->ctequery, Query));
- query = parse_sub_analyze(cte->ctequery, pstate, cte, false);
+ query = parse_sub_analyze(cte->ctequery, pstate, cte, false, true);
cte->ctequery = (Node *) query;
/*
@@ -393,11 +393,10 @@ analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
/*
* If the CTE is recursive, force the exposed column type of any
- * "unknown" column to "text". This corresponds to the fact that
- * SELECT 'foo' UNION SELECT 'bar' will ultimately produce text. We
- * might see "unknown" as a result of an untyped literal in the
- * non-recursive term's select list, and if we don't convert to text
- * then we'll have a mismatch against the UNION result.
+ * "unknown" column to "text". We must deal with this here because
+ * we're called on the non-recursive term before there's been any
+ * attempt to force unknown output columns to some other type. We
+ * have to resolve unknowns before looking at the recursive term.
*
* The column might contain 'foo' COLLATE "bar", so don't override
* collation if it's already set.
diff --git a/src/backend/parser/parse_enr.c b/src/backend/parser/parse_enr.c
new file mode 100644
index 0000000000..1cfcf65a51
--- /dev/null
+++ b/src/backend/parser/parse_enr.c
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_enr.c
+ * parser support routines dealing with ephemeral named relations
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/parser/parse_enr.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "parser/parse_enr.h"
+
+bool
+name_matches_visible_ENR(ParseState *pstate, const char *refname)
+{
+ return (get_visible_ENR_metadata(pstate->p_queryEnv, refname) != NULL);
+}
+
+EphemeralNamedRelationMetadata
+get_visible_ENR(ParseState *pstate, const char *refname)
+{
+ return get_visible_ENR_metadata(pstate->p_queryEnv, refname);
+}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index e54738bbff..8e2ae0e11c 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -3,7 +3,7 @@
* parse_expr.c
* handle expressions in parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -34,7 +34,9 @@
#include "parser/parse_type.h"
#include "parser/parse_agg.h"
#include "utils/builtins.h"
+#include "utils/date.h"
#include "utils/lsyscache.h"
+#include "utils/timestamp.h"
#include "utils/xml.h"
@@ -104,9 +106,11 @@ static Node *transformCaseExpr(ParseState *pstate, CaseExpr *c);
static Node *transformSubLink(ParseState *pstate, SubLink *sublink);
static Node *transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
Oid array_type, Oid element_type, int32 typmod);
-static Node *transformRowExpr(ParseState *pstate, RowExpr *r);
+static Node *transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault);
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
+static Node *transformSQLValueFunction(ParseState *pstate,
+ SQLValueFunction *svf);
static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x);
static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
@@ -295,7 +299,7 @@ transformExprRecurse(ParseState *pstate, Node *expr)
break;
case T_RowExpr:
- result = transformRowExpr(pstate, (RowExpr *) expr);
+ result = transformRowExpr(pstate, (RowExpr *) expr, false);
break;
case T_CoalesceExpr:
@@ -306,6 +310,11 @@ transformExprRecurse(ParseState *pstate, Node *expr)
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break;
+ case T_SQLValueFunction:
+ result = transformSQLValueFunction(pstate,
+ (SQLValueFunction *) expr);
+ break;
+
case T_XmlExpr:
result = transformXmlExpr(pstate, (XmlExpr *) expr);
break;
@@ -339,8 +348,20 @@ transformExprRecurse(ParseState *pstate, Node *expr)
break;
/*
- * CaseTestExpr and SetToDefault don't require any processing;
- * they are only injected into parse trees in fully-formed state.
+ * In all places where DEFAULT is legal, the caller should have
+ * processed it rather than passing it to transformExpr().
+ */
+ case T_SetToDefault:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("DEFAULT is not allowed in this context"),
+ parser_errposition(pstate,
+ ((SetToDefault *) expr)->location)));
+ break;
+
+ /*
+ * CaseTestExpr doesn't require any processing; it is only
+ * injected into parse trees in a fully-formed state.
*
* Ordinarily we should not see a Var here, but it is convenient
* for transformJoinUsingClause() to create untransformed operator
@@ -349,7 +370,6 @@ transformExprRecurse(ParseState *pstate, Node *expr)
* references, which seems expensively pointless. So allow it.
*/
case T_CaseTestExpr:
- case T_SetToDefault:
case T_Var:
{
result = (Node *) expr;
@@ -557,27 +577,6 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/*
* Not known as a column of any range-table entry.
*
- * Consider the possibility that it's VALUE in a domain
- * check expression. (We handle VALUE as a name, not a
- * keyword, to avoid breaking a lot of applications that
- * have used VALUE as a column name in the past.)
- */
- if (pstate->p_value_substitute != NULL &&
- strcmp(colname, "value") == 0)
- {
- node = (Node *) copyObject(pstate->p_value_substitute);
-
- /*
- * Try to propagate location knowledge. This should
- * be extended if p_value_substitute can ever take on
- * other node types.
- */
- if (IsA(node, CoerceToDomainValue))
- ((CoerceToDomainValue *) node)->location = cref->location;
- break;
- }
-
- /*
* Try to find the name as a relation. Note that only
* relations already entered into the rangetable will be
* recognized.
@@ -918,13 +917,11 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
/* ROW() op ROW() is handled specially */
lexpr = transformExprRecurse(pstate, lexpr);
rexpr = transformExprRecurse(pstate, rexpr);
- Assert(IsA(lexpr, RowExpr));
- Assert(IsA(rexpr, RowExpr));
result = make_row_comparison_op(pstate,
a->name,
- ((RowExpr *) lexpr)->args,
- ((RowExpr *) rexpr)->args,
+ castNode(RowExpr, lexpr)->args,
+ castNode(RowExpr, rexpr)->args,
a->location);
}
else
@@ -1258,7 +1255,7 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
/* ROW() op ROW() is handled specially */
cmp = make_row_comparison_op(pstate,
a->name,
- (List *) copyObject(((RowExpr *) lexpr)->args),
+ copyObject(((RowExpr *) lexpr)->args),
((RowExpr *) rexpr)->args,
a->location);
}
@@ -1297,8 +1294,7 @@ transformAExprBetween(ParseState *pstate, A_Expr *a)
/* Deconstruct A_Expr into three subexprs */
aexpr = a->lexpr;
- Assert(IsA(a->rexpr, List));
- args = (List *) a->rexpr;
+ args = castNode(List, a->rexpr);
Assert(list_length(args) == 2);
bexpr = (Node *) linitial(args);
cexpr = (Node *) lsecond(args);
@@ -1478,9 +1474,9 @@ static Node *
transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
{
SubLink *sublink;
+ RowExpr *rexpr;
Query *qtree;
TargetEntry *tle;
- Param *param;
/* We should only see this in first-stage processing of UPDATE tlists */
Assert(pstate->p_expr_kind == EXPR_KIND_UPDATE_SOURCE);
@@ -1488,64 +1484,137 @@ transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
/* We only need to transform the source if this is the first column */
if (maref->colno == 1)
{
- sublink = (SubLink *) transformExprRecurse(pstate, maref->source);
- /* Currently, the grammar only allows a SubLink as source */
- Assert(IsA(sublink, SubLink));
- Assert(sublink->subLinkType == MULTIEXPR_SUBLINK);
- qtree = (Query *) sublink->subselect;
- Assert(IsA(qtree, Query));
+ /*
+ * For now, we only allow EXPR SubLinks and RowExprs as the source of
+ * an UPDATE multiassignment. This is sufficient to cover interesting
+ * cases; at worst, someone would have to write (SELECT * FROM expr)
+ * to expand a composite-returning expression of another form.
+ */
+ if (IsA(maref->source, SubLink) &&
+ ((SubLink *) maref->source)->subLinkType == EXPR_SUBLINK)
+ {
+ /* Relabel it as a MULTIEXPR_SUBLINK */
+ sublink = (SubLink *) maref->source;
+ sublink->subLinkType = MULTIEXPR_SUBLINK;
+ /* And transform it */
+ sublink = (SubLink *) transformExprRecurse(pstate,
+ (Node *) sublink);
- /* Check subquery returns required number of columns */
- if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
+ qtree = castNode(Query, sublink->subselect);
+
+ /* Check subquery returns required number of columns */
+ if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("number of columns does not match number of values"),
- parser_errposition(pstate, sublink->location)));
+ parser_errposition(pstate, sublink->location)));
- /*
- * Build a resjunk tlist item containing the MULTIEXPR SubLink, and
- * add it to pstate->p_multiassign_exprs, whence it will later get
- * appended to the completed targetlist. We needn't worry about
- * selecting a resno for it; transformUpdateStmt will do that.
- */
- tle = makeTargetEntry((Expr *) sublink, 0, NULL, true);
- pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs, tle);
+ /*
+ * Build a resjunk tlist item containing the MULTIEXPR SubLink,
+ * and add it to pstate->p_multiassign_exprs, whence it will later
+ * get appended to the completed targetlist. We needn't worry
+ * about selecting a resno for it; transformUpdateStmt will do
+ * that.
+ */
+ tle = makeTargetEntry((Expr *) sublink, 0, NULL, true);
+ pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs,
+ tle);
- /*
- * Assign a unique-within-this-targetlist ID to the MULTIEXPR SubLink.
- * We can just use its position in the p_multiassign_exprs list.
- */
- sublink->subLinkId = list_length(pstate->p_multiassign_exprs);
+ /*
+ * Assign a unique-within-this-targetlist ID to the MULTIEXPR
+ * SubLink. We can just use its position in the
+ * p_multiassign_exprs list.
+ */
+ sublink->subLinkId = list_length(pstate->p_multiassign_exprs);
+ }
+ else if (IsA(maref->source, RowExpr))
+ {
+ /* Transform the RowExpr, allowing SetToDefault items */
+ rexpr = (RowExpr *) transformRowExpr(pstate,
+ (RowExpr *) maref->source,
+ true);
+
+ /* Check it returns required number of columns */
+ if (list_length(rexpr->args) != maref->ncolumns)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("number of columns does not match number of values"),
+ parser_errposition(pstate, rexpr->location)));
+
+ /*
+ * Temporarily append it to p_multiassign_exprs, so we can get it
+ * back when we come back here for additional columns.
+ */
+ tle = makeTargetEntry((Expr *) rexpr, 0, NULL, true);
+ pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs,
+ tle);
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression"),
+ parser_errposition(pstate, exprLocation(maref->source))));
}
else
{
/*
* Second or later column in a multiassignment. Re-fetch the
- * transformed query, which we assume is still the last entry in
- * p_multiassign_exprs.
+ * transformed SubLink or RowExpr, which we assume is still the last
+ * entry in p_multiassign_exprs.
*/
Assert(pstate->p_multiassign_exprs != NIL);
tle = (TargetEntry *) llast(pstate->p_multiassign_exprs);
+ }
+
+ /*
+ * Emit the appropriate output expression for the current column
+ */
+ if (IsA(tle->expr, SubLink))
+ {
+ Param *param;
+
sublink = (SubLink *) tle->expr;
- Assert(IsA(sublink, SubLink));
Assert(sublink->subLinkType == MULTIEXPR_SUBLINK);
- qtree = (Query *) sublink->subselect;
- Assert(IsA(qtree, Query));
+ qtree = castNode(Query, sublink->subselect);
+
+ /* Build a Param representing the current subquery output column */
+ tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1);
+ Assert(!tle->resjunk);
+
+ param = makeNode(Param);
+ param->paramkind = PARAM_MULTIEXPR;
+ param->paramid = (sublink->subLinkId << 16) | maref->colno;
+ param->paramtype = exprType((Node *) tle->expr);
+ param->paramtypmod = exprTypmod((Node *) tle->expr);
+ param->paramcollid = exprCollation((Node *) tle->expr);
+ param->location = exprLocation((Node *) tle->expr);
+
+ return (Node *) param;
}
- /* Build a Param representing the appropriate subquery output column */
- tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1);
- Assert(!tle->resjunk);
+ if (IsA(tle->expr, RowExpr))
+ {
+ Node *result;
+
+ rexpr = (RowExpr *) tle->expr;
+
+ /* Just extract and return the next element of the RowExpr */
+ result = (Node *) list_nth(rexpr->args, maref->colno - 1);
+
+ /*
+ * If we're at the last column, delete the RowExpr from
+ * p_multiassign_exprs; we don't need it anymore, and don't want it in
+ * the finished UPDATE tlist.
+ */
+ if (maref->colno == maref->ncolumns)
+ pstate->p_multiassign_exprs =
+ list_delete_ptr(pstate->p_multiassign_exprs, tle);
- param = makeNode(Param);
- param->paramkind = PARAM_MULTIEXPR;
- param->paramid = (sublink->subLinkId << 16) | maref->colno;
- param->paramtype = exprType((Node *) tle->expr);
- param->paramtypmod = exprTypmod((Node *) tle->expr);
- param->paramcollid = exprCollation((Node *) tle->expr);
- param->location = exprLocation((Node *) tle->expr);
+ return result;
+ }
- return (Node *) param;
+ elog(ERROR, "unexpected expr type in multiassign list");
+ return NULL; /* keep compiler quiet */
}
static Node *
@@ -1601,12 +1670,10 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
resultexprs = NIL;
foreach(l, c->args)
{
- CaseWhen *w = (CaseWhen *) lfirst(l);
+ CaseWhen *w = lfirst_node(CaseWhen, l);
CaseWhen *neww = makeNode(CaseWhen);
Node *warg;
- Assert(IsA(w, CaseWhen));
-
warg = (Node *) w->expr;
if (placeholder)
{
@@ -1724,6 +1791,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
case EXPR_KIND_OFFSET:
case EXPR_KIND_RETURNING:
case EXPR_KIND_VALUES:
+ case EXPR_KIND_VALUES_SINGLE:
/* okay */
break;
case EXPR_KIND_CHECK_CONSTRAINT:
@@ -1749,6 +1817,9 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
case EXPR_KIND_TRIGGER_WHEN:
err = _("cannot use subquery in trigger WHEN condition");
break;
+ case EXPR_KIND_PARTITION_EXPRESSION:
+ err = _("cannot use subquery in partition key expression");
+ break;
/*
* There is intentionally no default: case here, so that the
@@ -1769,15 +1840,14 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
/*
* OK, let's transform the sub-SELECT.
*/
- qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false);
+ qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true);
/*
- * Check that we got something reasonable. Many of these conditions are
- * impossible given restrictions of the grammar, but check 'em anyway.
+ * Check that we got a SELECT. Anything else should be impossible given
+ * restrictions of the grammar, but check anyway.
*/
if (!IsA(qtree, Query) ||
- qtree->commandType != CMD_SELECT ||
- qtree->utilityStmt != NULL)
+ qtree->commandType != CMD_SELECT)
elog(ERROR, "unexpected non-SELECT command in SubLink");
sublink->subselect = (Node *) qtree;
@@ -2073,7 +2143,7 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
}
static Node *
-transformRowExpr(ParseState *pstate, RowExpr *r)
+transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault)
{
RowExpr *newr;
char fname[16];
@@ -2083,7 +2153,8 @@ transformRowExpr(ParseState *pstate, RowExpr *r)
newr = makeNode(RowExpr);
/* Transform the field expressions */
- newr->args = transformExpressionList(pstate, r->args, pstate->p_expr_kind);
+ newr->args = transformExpressionList(pstate, r->args,
+ pstate->p_expr_kind, allowDefault);
/* Barring later casting, we consider the type RECORD */
newr->row_typeid = RECORDOID;
@@ -2180,6 +2251,59 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
}
static Node *
+transformSQLValueFunction(ParseState *pstate, SQLValueFunction *svf)
+{
+ /*
+ * All we need to do is insert the correct result type and (where needed)
+ * validate the typmod, so we just modify the node in-place.
+ */
+ switch (svf->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ svf->type = DATEOID;
+ break;
+ case SVFOP_CURRENT_TIME:
+ svf->type = TIMETZOID;
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ svf->type = TIMETZOID;
+ svf->typmod = anytime_typmod_check(true, svf->typmod);
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ svf->type = TIMESTAMPTZOID;
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ svf->type = TIMESTAMPTZOID;
+ svf->typmod = anytimestamp_typmod_check(true, svf->typmod);
+ break;
+ case SVFOP_LOCALTIME:
+ svf->type = TIMEOID;
+ break;
+ case SVFOP_LOCALTIME_N:
+ svf->type = TIMEOID;
+ svf->typmod = anytime_typmod_check(false, svf->typmod);
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ svf->type = TIMESTAMPOID;
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ svf->type = TIMESTAMPOID;
+ svf->typmod = anytimestamp_typmod_check(false, svf->typmod);
+ break;
+ case SVFOP_CURRENT_ROLE:
+ case SVFOP_CURRENT_USER:
+ case SVFOP_USER:
+ case SVFOP_SESSION_USER:
+ case SVFOP_CURRENT_CATALOG:
+ case SVFOP_CURRENT_SCHEMA:
+ svf->type = NAMEOID;
+ break;
+ }
+
+ return (Node *) svf;
+}
+
+static Node *
transformXmlExpr(ParseState *pstate, XmlExpr *x)
{
XmlExpr *newx;
@@ -2211,12 +2335,10 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
foreach(lc, x->named_args)
{
- ResTarget *r = (ResTarget *) lfirst(lc);
+ ResTarget *r = lfirst_node(ResTarget, lc);
Node *expr;
char *argname;
- Assert(IsA(r, ResTarget));
-
expr = transformExprRecurse(pstate, r->val);
if (r->name)
@@ -2678,8 +2800,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
Node *rarg = (Node *) lfirst(r);
OpExpr *cmp;
- cmp = (OpExpr *) make_op(pstate, opname, larg, rarg, location);
- Assert(IsA(cmp, OpExpr));
+ cmp = castNode(OpExpr, make_op(pstate, opname, larg, rarg, location));
/*
* We don't use coerce_to_boolean here because we insist on the
@@ -3287,6 +3408,7 @@ ParseExprKindName(ParseExprKind exprKind)
case EXPR_KIND_RETURNING:
return "RETURNING";
case EXPR_KIND_VALUES:
+ case EXPR_KIND_VALUES_SINGLE:
return "VALUES";
case EXPR_KIND_CHECK_CONSTRAINT:
case EXPR_KIND_DOMAIN_CHECK:
@@ -3304,6 +3426,8 @@ ParseExprKindName(ParseExprKind exprKind)
return "EXECUTE";
case EXPR_KIND_TRIGGER_WHEN:
return "WHEN";
+ case EXPR_KIND_PARTITION_EXPRESSION:
+ return "PARTITION BY";
/*
* There is intentionally no default: case here, so that the
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 61af484fee..55853c20bb 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -3,7 +3,7 @@
* parse_func.c
* handle function calls in parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -25,6 +25,7 @@
#include "parser/parse_agg.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
+#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
@@ -625,6 +626,10 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
exprLocation((Node *) llast(fargs)))));
}
+ /* if it returns a set, check that's OK */
+ if (retset)
+ check_srf_call_placement(pstate, location);
+
/* build the appropriate output structure */
if (fdresult == FUNCDETAIL_NORMAL)
{
@@ -1510,8 +1515,7 @@ func_get_detail(List *funcname,
&isnull);
Assert(!isnull);
str = TextDatumGetCString(proargdefaults);
- defaults = (List *) stringToNode(str);
- Assert(IsA(defaults, List));
+ defaults = castNode(List, stringToNode(str));
pfree(str);
/* Delete any unused defaults from the returned list */
@@ -1891,8 +1895,10 @@ func_signature_string(List *funcname, int nargs,
/*
* LookupFuncName
- * Given a possibly-qualified function name and a set of argument types,
- * look up the function.
+ *
+ * Given a possibly-qualified function name and optionally a set of argument
+ * types, look up the function. Pass nargs == -1 to indicate that no argument
+ * types are specified.
*
* If the function name is not schema-qualified, it is sought in the current
* namespace search path.
@@ -1910,6 +1916,35 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError);
+ /*
+ * If no arguments were specified, the name must yield a unique candidate.
+ */
+ if (nargs == -1)
+ {
+ if (clist)
+ {
+ if (clist->next)
+ {
+ if (!noError)
+ ereport(ERROR,
+ (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
+ errmsg("function name \"%s\" is not unique",
+ NameListToString(funcname)),
+ errhint("Specify the argument list to select the function unambiguously.")));
+ }
+ else
+ return clist->oid;
+ }
+ else
+ {
+ if (!noError)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not find a function named \"%s\"",
+ NameListToString(funcname))));
+ }
+ }
+
while (clist)
{
if (memcmp(argtypes, clist->args, nargs * sizeof(Oid)) == 0)
@@ -1928,19 +1963,19 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
}
/*
- * LookupFuncNameTypeNames
+ * LookupFuncWithArgs
* Like LookupFuncName, but the argument types are specified by a
- * list of TypeName nodes.
+ * ObjectWithArgs node.
*/
Oid
-LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
+LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
{
Oid argoids[FUNC_MAX_ARGS];
int argcount;
int i;
ListCell *args_item;
- argcount = list_length(argtypes);
+ argcount = list_length(func->objargs);
if (argcount > FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
@@ -1949,7 +1984,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
FUNC_MAX_ARGS,
FUNC_MAX_ARGS)));
- args_item = list_head(argtypes);
+ args_item = list_head(func->objargs);
for (i = 0; i < argcount; i++)
{
TypeName *t = (TypeName *) lfirst(args_item);
@@ -1958,19 +1993,19 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
args_item = lnext(args_item);
}
- return LookupFuncName(funcname, argcount, argoids, noError);
+ return LookupFuncName(func->objname, func->args_unspecified ? -1 : argcount, argoids, noError);
}
/*
- * LookupAggNameTypeNames
- * Find an aggregate function given a name and list of TypeName nodes.
+ * LookupAggWithArgs
+ * Find an aggregate function from a given ObjectWithArgs node.
*
- * This is almost like LookupFuncNameTypeNames, but the error messages refer
+ * This is almost like LookupFuncWithArgs, but the error messages refer
* to aggregates rather than plain functions, and we verify that the found
* function really is an aggregate.
*/
Oid
-LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
+LookupAggWithArgs(ObjectWithArgs *agg, bool noError)
{
Oid argoids[FUNC_MAX_ARGS];
int argcount;
@@ -1980,7 +2015,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
HeapTuple ftup;
Form_pg_proc pform;
- argcount = list_length(argtypes);
+ argcount = list_length(agg->objargs);
if (argcount > FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
@@ -1990,7 +2025,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
FUNC_MAX_ARGS)));
i = 0;
- foreach(lc, argtypes)
+ foreach(lc, agg->objargs)
{
TypeName *t = (TypeName *) lfirst(lc);
@@ -1998,7 +2033,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
i++;
}
- oid = LookupFuncName(aggname, argcount, argoids, true);
+ oid = LookupFuncName(agg->objname, argcount, argoids, true);
if (!OidIsValid(oid))
{
@@ -2008,12 +2043,12 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("aggregate %s(*) does not exist",
- NameListToString(aggname))));
+ NameListToString(agg->objname))));
else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("aggregate %s does not exist",
- func_signature_string(aggname, argcount,
+ func_signature_string(agg->objname, argcount,
NIL, argoids))));
}
@@ -2032,7 +2067,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("function %s is not an aggregate",
- func_signature_string(aggname, argcount,
+ func_signature_string(agg->objname, argcount,
NIL, argoids))));
}
@@ -2040,3 +2075,154 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
return oid;
}
+
+
+/*
+ * check_srf_call_placement
+ * Verify that a set-returning function is called in a valid place,
+ * and throw a nice error if not.
+ *
+ * A side-effect is to set pstate->p_hasTargetSRFs true if appropriate.
+ */
+void
+check_srf_call_placement(ParseState *pstate, int location)
+{
+ const char *err;
+ bool errkind;
+
+ /*
+ * Check to see if the set-returning function is in an invalid place
+ * within the query. Basically, we don't allow SRFs anywhere except in
+ * the targetlist (which includes GROUP BY/ORDER BY expressions), VALUES,
+ * and functions in FROM.
+ *
+ * For brevity we support two schemes for reporting an error here: set
+ * "err" to a custom message, or set "errkind" true if the error context
+ * is sufficiently identified by what ParseExprKindName will return, *and*
+ * what it will return is just a SQL keyword. (Otherwise, use a custom
+ * message to avoid creating translation problems.)
+ */
+ err = NULL;
+ errkind = false;
+ switch (pstate->p_expr_kind)
+ {
+ case EXPR_KIND_NONE:
+ Assert(false); /* can't happen */
+ break;
+ case EXPR_KIND_OTHER:
+ /* Accept SRF here; caller must throw error if wanted */
+ break;
+ case EXPR_KIND_JOIN_ON:
+ case EXPR_KIND_JOIN_USING:
+ err = _("set-returning functions are not allowed in JOIN conditions");
+ break;
+ case EXPR_KIND_FROM_SUBSELECT:
+ /* can't get here, but just in case, throw an error */
+ errkind = true;
+ break;
+ case EXPR_KIND_FROM_FUNCTION:
+ /* okay ... but we can't check nesting here */
+ break;
+ case EXPR_KIND_WHERE:
+ errkind = true;
+ break;
+ case EXPR_KIND_POLICY:
+ err = _("set-returning functions are not allowed in policy expressions");
+ break;
+ case EXPR_KIND_HAVING:
+ errkind = true;
+ break;
+ case EXPR_KIND_FILTER:
+ errkind = true;
+ break;
+ case EXPR_KIND_WINDOW_PARTITION:
+ case EXPR_KIND_WINDOW_ORDER:
+ /* okay, these are effectively GROUP BY/ORDER BY */
+ pstate->p_hasTargetSRFs = true;
+ break;
+ case EXPR_KIND_WINDOW_FRAME_RANGE:
+ case EXPR_KIND_WINDOW_FRAME_ROWS:
+ err = _("set-returning functions are not allowed in window definitions");
+ break;
+ case EXPR_KIND_SELECT_TARGET:
+ case EXPR_KIND_INSERT_TARGET:
+ /* okay */
+ pstate->p_hasTargetSRFs = true;
+ break;
+ case EXPR_KIND_UPDATE_SOURCE:
+ case EXPR_KIND_UPDATE_TARGET:
+ /* disallowed because it would be ambiguous what to do */
+ errkind = true;
+ break;
+ case EXPR_KIND_GROUP_BY:
+ case EXPR_KIND_ORDER_BY:
+ /* okay */
+ pstate->p_hasTargetSRFs = true;
+ break;
+ case EXPR_KIND_DISTINCT_ON:
+ /* okay */
+ pstate->p_hasTargetSRFs = true;
+ break;
+ case EXPR_KIND_LIMIT:
+ case EXPR_KIND_OFFSET:
+ errkind = true;
+ break;
+ case EXPR_KIND_RETURNING:
+ errkind = true;
+ break;
+ case EXPR_KIND_VALUES:
+ /* SRFs are presently not supported by nodeValuesscan.c */
+ errkind = true;
+ break;
+ case EXPR_KIND_VALUES_SINGLE:
+ /* okay, since we process this like a SELECT tlist */
+ pstate->p_hasTargetSRFs = true;
+ break;
+ case EXPR_KIND_CHECK_CONSTRAINT:
+ case EXPR_KIND_DOMAIN_CHECK:
+ err = _("set-returning functions are not allowed in check constraints");
+ break;
+ case EXPR_KIND_COLUMN_DEFAULT:
+ case EXPR_KIND_FUNCTION_DEFAULT:
+ err = _("set-returning functions are not allowed in DEFAULT expressions");
+ break;
+ case EXPR_KIND_INDEX_EXPRESSION:
+ err = _("set-returning functions are not allowed in index expressions");
+ break;
+ case EXPR_KIND_INDEX_PREDICATE:
+ err = _("set-returning functions are not allowed in index predicates");
+ break;
+ case EXPR_KIND_ALTER_COL_TRANSFORM:
+ err = _("set-returning functions are not allowed in transform expressions");
+ break;
+ case EXPR_KIND_EXECUTE_PARAMETER:
+ err = _("set-returning functions are not allowed in EXECUTE parameters");
+ break;
+ case EXPR_KIND_TRIGGER_WHEN:
+ err = _("set-returning functions are not allowed in trigger WHEN conditions");
+ break;
+ case EXPR_KIND_PARTITION_EXPRESSION:
+ err = _("set-returning functions are not allowed in partition key expression");
+ break;
+
+ /*
+ * There is intentionally no default: case here, so that the
+ * compiler will warn if we add a new ParseExprKind without
+ * extending this switch. If we do see an unrecognized value at
+ * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
+ * which is sane anyway.
+ */
+ }
+ if (err)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg_internal("%s", err),
+ parser_errposition(pstate, location)));
+ if (errkind)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ /* translator: %s is name of a SQL construct, eg GROUP BY */
+ errmsg("set-returning functions are not allowed in %s",
+ ParseExprKindName(pstate->p_expr_kind)),
+ parser_errposition(pstate, location)));
+}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 62d2f7105f..fb3d117a7d 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -3,7 +3,7 @@
* parse_node.c
* various routines that make nodes for querytrees
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -51,6 +51,7 @@ make_parsestate(ParseState *parentParseState)
/* Fill in fields that don't start at null/false/zero */
pstate->p_next_resno = 1;
+ pstate->p_resolve_unknowns = true;
if (parentParseState)
{
@@ -61,6 +62,8 @@ make_parsestate(ParseState *parentParseState)
pstate->p_paramref_hook = parentParseState->p_paramref_hook;
pstate->p_coerce_param_hook = parentParseState->p_coerce_param_hook;
pstate->p_ref_hook_state = parentParseState->p_ref_hook_state;
+ /* query environment stays in context for the whole parse analysis */
+ pstate->p_queryEnv = parentParseState->p_queryEnv;
}
return pstate;
@@ -334,10 +337,9 @@ transformArraySubscripts(ParseState *pstate,
*/
foreach(idx, indirection)
{
- A_Indices *ai = (A_Indices *) lfirst(idx);
+ A_Indices *ai = lfirst_node(A_Indices, idx);
Node *subexpr;
- Assert(IsA(ai, A_Indices));
if (isSlice)
{
if (ai->lidx)
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index e913d05a79..e40b10d4f6 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -3,7 +3,7 @@
* parse_oper.c
* handle operator things for parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -132,32 +132,34 @@ LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
}
/*
- * LookupOperNameTypeNames
+ * LookupOperWithArgs
* Like LookupOperName, but the argument types are specified by
- * TypeName nodes.
- *
- * Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op.
+ * a ObjectWithArg node.
*/
Oid
-LookupOperNameTypeNames(ParseState *pstate, List *opername,
- TypeName *oprleft, TypeName *oprright,
- bool noError, int location)
+LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
{
+ TypeName *oprleft,
+ *oprright;
Oid leftoid,
rightoid;
+ Assert(list_length(oper->objargs) == 2);
+ oprleft = linitial(oper->objargs);
+ oprright = lsecond(oper->objargs);
+
if (oprleft == NULL)
leftoid = InvalidOid;
else
- leftoid = LookupTypeNameOid(pstate, oprleft, noError);
+ leftoid = LookupTypeNameOid(NULL, oprleft, noError);
if (oprright == NULL)
rightoid = InvalidOid;
else
- rightoid = LookupTypeNameOid(pstate, oprright, noError);
+ rightoid = LookupTypeNameOid(NULL, oprright, noError);
- return LookupOperName(pstate, opername, leftoid, rightoid,
- noError, location);
+ return LookupOperName(NULL, oper->objname, leftoid, rightoid,
+ noError, -1);
}
/*
@@ -839,6 +841,10 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
result->args = args;
result->location = location;
+ /* if it returns a set, check that's OK */
+ if (result->opretset)
+ check_srf_call_placement(pstate, location);
+
ReleaseSysCache(tup);
return (Expr *) result;
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index b402843680..20fd83f095 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -12,7 +12,7 @@
* Note that other approaches to parameters are possible using the parser
* hooks defined in ParseState.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -210,7 +210,7 @@ variable_coerce_param_hook(ParseState *pstate, Param *param,
}
else
{
- /* Ooops */
+ /* Oops */
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
errmsg("inconsistent types deduced for parameter $%d",
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index c10e272d72..8ae8b00236 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -4,7 +4,7 @@
* parser support routines dealing with relations
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -26,6 +26,7 @@
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
+#include "parser/parse_enr.h"
#include "parser/parse_relation.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
@@ -39,6 +40,7 @@
#include "pgxc/pgxc.h"
#include "miscadmin.h"
#endif
+#include "utils/varlena.h"
#define MAX_FUZZY_DISTANCE 3
@@ -291,6 +293,16 @@ isFutureCTE(ParseState *pstate, const char *refname)
}
/*
+ * Search the query's ephemeral named relation namespace for a relation
+ * matching the given unqualified refname.
+ */
+bool
+scanNameSpaceForENR(ParseState *pstate, const char *refname)
+{
+ return name_matches_visible_ENR(pstate, refname);
+}
+
+/*
* searchRangeTableForRel
* See if any RangeTblEntry could possibly match the RangeVar.
* If so, return a pointer to the RangeTblEntry; else return NULL.
@@ -311,6 +323,7 @@ searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
const char *refname = relation->relname;
Oid relId = InvalidOid;
CommonTableExpr *cte = NULL;
+ bool isenr = false;
Index ctelevelsup = 0;
Index levelsup;
@@ -327,11 +340,16 @@ searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
* unlocked.
*/
if (!relation->schemaname)
+ {
cte = scanNameSpaceForCTE(pstate, refname, &ctelevelsup);
- if (!cte)
+ if (!cte)
+ isenr = scanNameSpaceForENR(pstate, refname);
+ }
+
+ if (!cte && !isenr)
relId = RangeVarGetRelid(relation, NoLock, true);
- /* Now look for RTEs matching either the relation/CTE or the alias */
+ /* Now look for RTEs matching either the relation/CTE/ENR or the alias */
for (levelsup = 0;
pstate != NULL;
pstate = pstate->parentParseState, levelsup++)
@@ -351,6 +369,10 @@ searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
rte->ctelevelsup + levelsup == ctelevelsup &&
strcmp(rte->ctename, refname) == 0)
return rte;
+ if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
+ isenr &&
+ strcmp(rte->enrname, refname) == 0)
+ return rte;
if (strcmp(rte->eref->aliasname, refname) == 0)
return rte;
}
@@ -938,12 +960,11 @@ markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
JoinExpr *j;
if (rtindex > 0 && rtindex <= list_length(pstate->p_joinexprs))
- j = (JoinExpr *) list_nth(pstate->p_joinexprs, rtindex - 1);
+ j = list_nth_node(JoinExpr, pstate->p_joinexprs, rtindex - 1);
else
j = NULL;
if (j == NULL)
elog(ERROR, "could not find JoinExpr for whole-row reference");
- Assert(IsA(j, JoinExpr));
/* Note: we can't see FromExpr here */
if (IsA(j->larg, RangeTblRef))
@@ -1168,12 +1189,18 @@ parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode)
else
{
/*
+ * An unqualified name might be a named ephemeral relation.
+ */
+ if (get_visible_ENR_metadata(pstate->p_queryEnv, relation->relname))
+ rel = NULL;
+
+ /*
* An unqualified name might have been meant as a reference to
* some not-yet-in-scope CTE. The bare "does not exist" message
* has proven remarkably unhelpful for figuring out such problems,
* so we take pains to offer a specific hint.
*/
- if (isFutureCTE(pstate, relation->relname))
+ else if (isFutureCTE(pstate, relation->relname))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation \"%s\" does not exist",
@@ -1719,6 +1746,69 @@ addRangeTableEntryForFunction(ParseState *pstate,
}
/*
+ * Add an entry for a table function to the pstate's range table (p_rtable).
+ *
+ * This is much like addRangeTableEntry() except that it makes a tablefunc RTE.
+ */
+RangeTblEntry *
+addRangeTableEntryForTableFunc(ParseState *pstate,
+ TableFunc *tf,
+ Alias *alias,
+ bool lateral,
+ bool inFromCl)
+{
+ RangeTblEntry *rte = makeNode(RangeTblEntry);
+ char *refname = alias ? alias->aliasname : pstrdup("xmltable");
+ Alias *eref;
+ int numaliases;
+
+ Assert(pstate != NULL);
+
+ rte->rtekind = RTE_TABLEFUNC;
+ rte->relid = InvalidOid;
+ rte->subquery = NULL;
+ rte->tablefunc = tf;
+ rte->coltypes = tf->coltypes;
+ rte->coltypmods = tf->coltypmods;
+ rte->colcollations = tf->colcollations;
+ rte->alias = alias;
+
+ eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
+ numaliases = list_length(eref->colnames);
+
+ /* fill in any unspecified alias columns */
+ if (numaliases < list_length(tf->colnames))
+ eref->colnames = list_concat(eref->colnames,
+ list_copy_tail(tf->colnames, numaliases));
+
+ rte->eref = eref;
+
+ /*
+ * Set flags and access permissions.
+ *
+ * Tablefuncs are never checked for access rights (at least, not by the
+ * RTE permissions mechanism).
+ */
+ rte->lateral = lateral;
+ rte->inh = false; /* never true for tablefunc RTEs */
+ rte->inFromCl = inFromCl;
+
+ rte->requiredPerms = 0;
+ rte->checkAsUser = InvalidOid;
+ rte->selectedCols = NULL;
+ rte->insertedCols = NULL;
+ rte->updatedCols = NULL;
+
+ /*
+ * Add completed RTE to pstate's range table list, but not to join list
+ * nor namespace --- caller must do that if appropriate.
+ */
+ pstate->p_rtable = lappend(pstate->p_rtable, rte);
+
+ return rte;
+}
+
+/*
* Add an entry for a VALUES list to the pstate's range table (p_rtable).
*
* This is much like addRangeTableEntry() except that it makes a values RTE.
@@ -1726,7 +1816,9 @@ addRangeTableEntryForFunction(ParseState *pstate,
RangeTblEntry *
addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
- List *collations,
+ List *coltypes,
+ List *coltypmods,
+ List *colcollations,
Alias *alias,
bool lateral,
bool inFromCl)
@@ -1743,7 +1835,9 @@ addRangeTableEntryForValues(ParseState *pstate,
rte->relid = InvalidOid;
rte->subquery = NULL;
rte->values_lists = exprs;
- rte->values_collations = collations;
+ rte->coltypes = coltypes;
+ rte->coltypmods = coltypmods;
+ rte->colcollations = colcollations;
rte->alias = alias;
eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
@@ -1828,7 +1922,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
rte->joinaliasvars = aliasvars;
rte->alias = alias;
- eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL);
+ eref = alias ? copyObject(alias) : makeAlias("unnamed_join", NIL);
numaliases = list_length(eref->colnames);
/* fill in any unspecified alias columns */
@@ -1913,9 +2007,9 @@ addRangeTableEntryForCTE(ParseState *pstate,
parser_errposition(pstate, rv->location)));
}
- rte->ctecoltypes = cte->ctecoltypes;
- rte->ctecoltypmods = cte->ctecoltypmods;
- rte->ctecolcollations = cte->ctecolcollations;
+ rte->coltypes = cte->ctecoltypes;
+ rte->coltypmods = cte->ctecoltypmods;
+ rte->colcollations = cte->ctecolcollations;
rte->alias = alias;
if (alias)
@@ -1964,6 +2058,102 @@ addRangeTableEntryForCTE(ParseState *pstate,
return rte;
}
+/*
+ * Add an entry for an ephemeral named relation reference to the pstate's
+ * range table (p_rtable).
+ *
+ * It is expected that the RangeVar, which up until now is only known to be an
+ * ephemeral named relation, will (in conjunction with the QueryEnvironment in
+ * the ParseState), create a RangeTblEntry for a specific *kind* of ephemeral
+ * named relation, based on enrtype.
+ *
+ * This is much like addRangeTableEntry() except that it makes an RTE for an
+ * ephemeral named relation.
+ */
+RangeTblEntry *
+addRangeTableEntryForENR(ParseState *pstate,
+ RangeVar *rv,
+ bool inFromCl)
+{
+ RangeTblEntry *rte = makeNode(RangeTblEntry);
+ Alias *alias = rv->alias;
+ char *refname = alias ? alias->aliasname : rv->relname;
+ EphemeralNamedRelationMetadata enrmd;
+ TupleDesc tupdesc;
+ int attno;
+
+ Assert(pstate != NULL);
+ enrmd = get_visible_ENR(pstate, rv->relname);
+ Assert(enrmd != NULL);
+
+ switch (enrmd->enrtype)
+ {
+ case ENR_NAMED_TUPLESTORE:
+ rte->rtekind = RTE_NAMEDTUPLESTORE;
+ break;
+
+ default:
+ elog(ERROR, "unexpected enrtype: %d", enrmd->enrtype);
+ return NULL; /* for fussy compilers */
+ }
+
+ /*
+ * Record dependency on a relation. This allows plans to be invalidated
+ * if they access transition tables linked to a table that is altered.
+ */
+ rte->relid = enrmd->reliddesc;
+
+ /*
+ * Build the list of effective column names using user-supplied aliases
+ * and/or actual column names. Also build the cannibalized fields.
+ */
+ tupdesc = ENRMetadataGetTupDesc(enrmd);
+ rte->eref = makeAlias(refname, NIL);
+ buildRelationAliases(tupdesc, alias, rte->eref);
+ rte->enrname = enrmd->name;
+ rte->enrtuples = enrmd->enrtuples;
+ rte->coltypes = NIL;
+ rte->coltypmods = NIL;
+ rte->colcollations = NIL;
+ for (attno = 1; attno <= tupdesc->natts; ++attno)
+ {
+ if (tupdesc->attrs[attno - 1]->atttypid == InvalidOid &&
+ !(tupdesc->attrs[attno - 1]->attisdropped))
+ elog(ERROR, "atttypid was invalid for column which has not been dropped from \"%s\"",
+ rv->relname);
+ rte->coltypes =
+ lappend_oid(rte->coltypes,
+ tupdesc->attrs[attno - 1]->atttypid);
+ rte->coltypmods =
+ lappend_int(rte->coltypmods,
+ tupdesc->attrs[attno - 1]->atttypmod);
+ rte->colcollations =
+ lappend_oid(rte->colcollations,
+ tupdesc->attrs[attno - 1]->attcollation);
+ }
+
+ /*
+ * Set flags and access permissions.
+ *
+ * ENRs are never checked for access rights.
+ */
+ rte->lateral = false;
+ rte->inh = false; /* never true for ENRs */
+ rte->inFromCl = inFromCl;
+
+ rte->requiredPerms = 0;
+ rte->checkAsUser = InvalidOid;
+ rte->selectedCols = NULL;
+
+ /*
+ * Add completed RTE to pstate's range table list, but not to join list
+ * nor namespace --- caller must do that if appropriate.
+ */
+ pstate->p_rtable = lappend(pstate->p_rtable, rte);
+
+ return rte;
+}
+
/*
* Has the specified refname been selected FOR UPDATE/FOR SHARE?
@@ -2244,46 +2434,6 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
}
}
break;
- case RTE_VALUES:
- {
- /* Values RTE */
- ListCell *aliasp_item = list_head(rte->eref->colnames);
- ListCell *lcv;
- ListCell *lcc;
-
- varattno = 0;
- forboth(lcv, (List *) linitial(rte->values_lists),
- lcc, rte->values_collations)
- {
- Node *col = (Node *) lfirst(lcv);
- Oid colcollation = lfirst_oid(lcc);
-
- varattno++;
- if (colnames)
- {
- /* Assume there is one alias per column */
- char *label = strVal(lfirst(aliasp_item));
-
- *colnames = lappend(*colnames,
- makeString(pstrdup(label)));
- aliasp_item = lnext(aliasp_item);
- }
-
- if (colvars)
- {
- Var *varnode;
-
- varnode = makeVar(rtindex, varattno,
- exprType(col),
- exprTypmod(col),
- colcollation,
- sublevels_up);
- varnode->location = location;
- *colvars = lappend(*colvars, varnode);
- }
- }
- }
- break;
case RTE_JOIN:
{
/* Join RTE */
@@ -2353,17 +2503,21 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
}
}
break;
+ case RTE_TABLEFUNC:
+ case RTE_VALUES:
case RTE_CTE:
+ case RTE_NAMEDTUPLESTORE:
{
+ /* Tablefunc, Values or CTE RTE */
ListCell *aliasp_item = list_head(rte->eref->colnames);
ListCell *lct;
ListCell *lcm;
ListCell *lcc;
varattno = 0;
- forthree(lct, rte->ctecoltypes,
- lcm, rte->ctecoltypmods,
- lcc, rte->ctecolcollations)
+ forthree(lct, rte->coltypes,
+ lcm, rte->coltypmods,
+ lcc, rte->colcollations)
{
Oid coltype = lfirst_oid(lct);
int32 coltypmod = lfirst_int(lcm);
@@ -2376,7 +2530,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
/* Assume there is one alias per output column */
char *label = strVal(lfirst(aliasp_item));
- *colnames = lappend(*colnames, makeString(pstrdup(label)));
+ *colnames = lappend(*colnames,
+ makeString(pstrdup(label)));
aliasp_item = lnext(aliasp_item);
}
@@ -2387,6 +2542,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
varnode = makeVar(rtindex, varattno,
coltype, coltypmod, colcoll,
sublevels_up);
+ varnode->location = location;
+
*colvars = lappend(*colvars, varnode);
}
}
@@ -2745,22 +2902,6 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
rte->eref->aliasname)));
}
break;
- case RTE_VALUES:
- {
- /* Values RTE --- get type info from first sublist */
- /* collation is stored separately, though */
- List *collist = (List *) linitial(rte->values_lists);
- Node *col;
-
- if (attnum < 1 || attnum > list_length(collist))
- elog(ERROR, "values list %s does not have attribute %d",
- rte->eref->aliasname, attnum);
- col = (Node *) list_nth(collist, attnum - 1);
- *vartype = exprType(col);
- *vartypmod = exprTypmod(col);
- *varcollid = list_nth_oid(rte->values_collations, attnum - 1);
- }
- break;
case RTE_JOIN:
{
/*
@@ -2776,13 +2917,19 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
*varcollid = exprCollation(aliasvar);
}
break;
+ case RTE_TABLEFUNC:
+ case RTE_VALUES:
case RTE_CTE:
+ case RTE_NAMEDTUPLESTORE:
{
- /* CTE RTE --- get type info from lists in the RTE */
- Assert(attnum > 0 && attnum <= list_length(rte->ctecoltypes));
- *vartype = list_nth_oid(rte->ctecoltypes, attnum - 1);
- *vartypmod = list_nth_int(rte->ctecoltypmods, attnum - 1);
- *varcollid = list_nth_oid(rte->ctecolcollations, attnum - 1);
+ /*
+ * tablefunc, VALUES or CTE RTE --- get type info from lists
+ * in the RTE
+ */
+ Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
+ *vartype = list_nth_oid(rte->coltypes, attnum - 1);
+ *vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
+ *varcollid = list_nth_oid(rte->colcollations, attnum - 1);
}
break;
default:
@@ -2821,11 +2968,29 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
}
break;
case RTE_SUBQUERY:
+ case RTE_TABLEFUNC:
case RTE_VALUES:
case RTE_CTE:
- /* Subselect, Values, CTE RTEs never have dropped columns */
+
+ /*
+ * Subselect, Table Functions, Values, CTE RTEs never have dropped
+ * columns
+ */
result = false;
break;
+ case RTE_NAMEDTUPLESTORE:
+ {
+ Assert(rte->enrname);
+
+ /*
+ * We checked when we loaded coltypes for the tuplestore that
+ * InvalidOid was only used for dropped columns, so it is safe
+ * to count on that here.
+ */
+ result =
+ ((list_nth_oid(rte->coltypes, attnum - 1) == InvalidOid));
+ }
+ break;
case RTE_JOIN:
{
/*
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index bb78974532..f2ca840ef2 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -3,7 +3,7 @@
* parse_target.c
* handle target lists
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -91,7 +91,17 @@ transformTargetEntry(ParseState *pstate,
{
/* Transform the node if caller didn't do it already */
if (expr == NULL)
- expr = transformExpr(pstate, node, exprKind);
+ {
+ /*
+ * If it's a SetToDefault node and we should allow that, pass it
+ * through unmodified. (transformExpr will throw the appropriate
+ * error if we're disallowing it.)
+ */
+ if (exprKind == EXPR_KIND_UPDATE_SOURCE && IsA(node, SetToDefault))
+ expr = node;
+ else
+ expr = transformExpr(pstate, node, exprKind);
+ }
if (colname == NULL && !resjunk)
{
@@ -122,11 +132,15 @@ transformTargetList(ParseState *pstate, List *targetlist,
ParseExprKind exprKind)
{
List *p_target = NIL;
+ bool expand_star;
ListCell *o_target;
/* Shouldn't have any leftover multiassign items at start */
Assert(pstate->p_multiassign_exprs == NIL);
+ /* Expand "something.*" in SELECT and RETURNING, but not UPDATE */
+ expand_star = (exprKind != EXPR_KIND_UPDATE_SOURCE);
+
foreach(o_target, targetlist)
{
ResTarget *res = (ResTarget *) lfirst(o_target);
@@ -136,35 +150,42 @@ transformTargetList(ParseState *pstate, List *targetlist,
* "something", the star could appear as the last field in ColumnRef,
* or as the last indirection item in A_Indirection.
*/
- if (IsA(res->val, ColumnRef))
+ if (expand_star)
{
- ColumnRef *cref = (ColumnRef *) res->val;
-
- if (IsA(llast(cref->fields), A_Star))
+ if (IsA(res->val, ColumnRef))
{
- /* It is something.*, expand into multiple items */
- p_target = list_concat(p_target,
- ExpandColumnRefStar(pstate, cref,
- true));
- continue;
- }
- }
- else if (IsA(res->val, A_Indirection))
- {
- A_Indirection *ind = (A_Indirection *) res->val;
+ ColumnRef *cref = (ColumnRef *) res->val;
- if (IsA(llast(ind->indirection), A_Star))
+ if (IsA(llast(cref->fields), A_Star))
+ {
+ /* It is something.*, expand into multiple items */
+ p_target = list_concat(p_target,
+ ExpandColumnRefStar(pstate,
+ cref,
+ true));
+ continue;
+ }
+ }
+ else if (IsA(res->val, A_Indirection))
{
- /* It is something.*, expand into multiple items */
- p_target = list_concat(p_target,
- ExpandIndirectionStar(pstate, ind,
- true, exprKind));
- continue;
+ A_Indirection *ind = (A_Indirection *) res->val;
+
+ if (IsA(llast(ind->indirection), A_Star))
+ {
+ /* It is something.*, expand into multiple items */
+ p_target = list_concat(p_target,
+ ExpandIndirectionStar(pstate,
+ ind,
+ true,
+ exprKind));
+ continue;
+ }
}
}
/*
- * Not "something.*", so transform as a single expression
+ * Not "something.*", or we want to treat that as a plain whole-row
+ * variable, so transform as a single expression
*/
p_target = lappend(p_target,
transformTargetEntry(pstate,
@@ -199,10 +220,13 @@ transformTargetList(ParseState *pstate, List *targetlist,
* the input list elements are bare expressions without ResTarget decoration,
* and the output elements are likewise just expressions without TargetEntry
* decoration. We use this for ROW() and VALUES() constructs.
+ *
+ * exprKind is not enough to tell us whether to allow SetToDefault, so
+ * an additional flag is needed for that.
*/
List *
transformExpressionList(ParseState *pstate, List *exprlist,
- ParseExprKind exprKind)
+ ParseExprKind exprKind, bool allowDefault)
{
List *result = NIL;
ListCell *lc;
@@ -244,10 +268,17 @@ transformExpressionList(ParseState *pstate, List *exprlist,
}
/*
- * Not "something.*", so transform as a single expression
+ * Not "something.*", so transform as a single expression. If it's a
+ * SetToDefault node and we should allow that, pass it through
+ * unmodified. (transformExpr will throw the appropriate error if
+ * we're disallowing it.)
*/
- result = lappend(result,
- transformExpr(pstate, e, exprKind));
+ if (allowDefault && IsA(e, SetToDefault))
+ /* do nothing */ ;
+ else
+ e = transformExpr(pstate, e, exprKind);
+
+ result = lappend(result, e);
}
/* Shouldn't have any multiassign items here */
@@ -258,12 +289,41 @@ transformExpressionList(ParseState *pstate, List *exprlist,
/*
+ * resolveTargetListUnknowns()
+ * Convert any unknown-type targetlist entries to type TEXT.
+ *
+ * We do this after we've exhausted all other ways of identifying the output
+ * column types of a query.
+ */
+void
+resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
+{
+ ListCell *l;
+
+ foreach(l, targetlist)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+ Oid restype = exprType((Node *) tle->expr);
+
+ if (restype == UNKNOWNOID)
+ {
+ tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
+ restype, TEXTOID, -1,
+ COERCION_IMPLICIT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+ }
+ }
+}
+
+
+/*
* markTargetListOrigins()
* Mark targetlist columns that are simple Vars with the source
* table's OID and column number.
*
- * Currently, this is done only for SELECT targetlists, since we only
- * need the info if we are going to send it to the frontend.
+ * Currently, this is done only for SELECT targetlists and RETURNING lists,
+ * since we only need the info if we are going to send it to the frontend.
*/
void
markTargetListOrigins(ParseState *pstate, List *targetlist)
@@ -336,6 +396,8 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
break;
case RTE_FUNCTION:
case RTE_VALUES:
+ case RTE_TABLEFUNC:
+ case RTE_NAMEDTUPLESTORE:
/* not a simple relation, leave it unmarked */
break;
case RTE_CTE:
@@ -1449,6 +1511,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
{
case RTE_RELATION:
case RTE_VALUES:
+ case RTE_NAMEDTUPLESTORE:
/*
* This case should not occur: a column of a table or values list
@@ -1502,6 +1565,12 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
* its result columns as RECORD, which is not allowed.
*/
break;
+ case RTE_TABLEFUNC:
+
+ /*
+ * Table function cannot have columns with RECORD type.
+ */
+ break;
case RTE_CTE:
/* CTE reference: examine subquery's output expr */
if (!rte->self_reference)
@@ -1771,6 +1840,49 @@ FigureColnameInternal(Node *node, char **name)
return 2;
}
break;
+ case T_SQLValueFunction:
+ /* make these act like a function or variable */
+ switch (((SQLValueFunction *) node)->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ *name = "current_date";
+ return 2;
+ case SVFOP_CURRENT_TIME:
+ case SVFOP_CURRENT_TIME_N:
+ *name = "current_time";
+ return 2;
+ case SVFOP_CURRENT_TIMESTAMP:
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ *name = "current_timestamp";
+ return 2;
+ case SVFOP_LOCALTIME:
+ case SVFOP_LOCALTIME_N:
+ *name = "localtime";
+ return 2;
+ case SVFOP_LOCALTIMESTAMP:
+ case SVFOP_LOCALTIMESTAMP_N:
+ *name = "localtimestamp";
+ return 2;
+ case SVFOP_CURRENT_ROLE:
+ *name = "current_role";
+ return 2;
+ case SVFOP_CURRENT_USER:
+ *name = "current_user";
+ return 2;
+ case SVFOP_USER:
+ *name = "user";
+ return 2;
+ case SVFOP_SESSION_USER:
+ *name = "session_user";
+ return 2;
+ case SVFOP_CURRENT_CATALOG:
+ *name = "current_catalog";
+ return 2;
+ case SVFOP_CURRENT_SCHEMA:
+ *name = "current_schema";
+ return 2;
+ }
+ break;
case T_XmlExpr:
/* make SQL/XML functions act like a regular function */
switch (((XmlExpr *) node)->op)
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index d39f06e831..a723ea15ad 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -3,7 +3,7 @@
* parse_type.c
* handle type operations for parser
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -478,9 +478,8 @@ TypeNameListToString(List *typenames)
initStringInfo(&string);
foreach(l, typenames)
{
- TypeName *typeName = (TypeName *) lfirst(l);
+ TypeName *typeName = lfirst_node(TypeName, l);
- Assert(IsA(typeName, TypeName));
if (l != list_head(typenames))
appendStringInfoChar(&string, ',');
appendTypeNameToBuffer(typeName, &string);
@@ -720,7 +719,7 @@ typeStringToTypeName(const char *str)
*/
if (list_length(raw_parsetree_list) != 1)
goto fail;
- stmt = (SelectStmt *) linitial(raw_parsetree_list);
+ stmt = (SelectStmt *) linitial_node(RawStmt, raw_parsetree_list)->stmt;
if (stmt == NULL ||
!IsA(stmt, SelectStmt) ||
stmt->distinctClause != NIL ||
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index bd0a620285..c04e77775e 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -17,7 +17,7 @@
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
@@ -47,13 +47,16 @@
#endif
#include "commands/comment.h"
#include "commands/defrem.h"
+#include "commands/sequence.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
+#include "optimizer/planner.h"
#include "parser/analyze.h"
#include "parser/parse_clause.h"
+#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
@@ -70,9 +73,9 @@
#include "rewrite/rewriteManip.h"
#include "utils/acl.h"
#include "utils/builtins.h"
-#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
+#include "utils/ruleutils.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
@@ -117,6 +120,8 @@ typedef struct
DistributeBy *distributeby; /* original distribute by column of CREATE TABLE */
PGXCSubCluster *subcluster; /* original subcluster option of CREATE TABLE */
#endif
+ bool ispartitioned; /* true if table is partitioned */
+ PartitionBoundSpec *partbound; /* transformed FOR VALUES */
} CreateStmtContext;
/* State shared by transformCreateSchemaStmt and its subroutines */
@@ -169,6 +174,10 @@ static void checkLocalFKConstraints(CreateStmtContext *cxt);
static List *transformSubclusterNodes(PGXCSubCluster *subcluster);
static PGXCSubCluster *makeSubCluster(List *nodelist);
#endif
+static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
+static Const *transformPartitionBoundValue(ParseState *pstate, A_Const *con,
+ const char *colName, Oid colType, int32 colTypmod);
+
/*
* transformCreateStmt -
@@ -207,7 +216,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
* We must not scribble on the passed-in CreateStmt, so copy it. (This is
* overkill, but easy.)
*/
- stmt = (CreateStmt *) copyObject(stmt);
+ stmt = copyObject(stmt);
/* Set up pstate */
pstate = make_parsestate(NULL);
@@ -280,6 +289,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
cxt.distributeby = stmt->distributeby;
cxt.subcluster = stmt->subcluster;
#endif
+ cxt.ispartitioned = stmt->partspec != NULL;
/*
* Notice that we allow OIDs here only for plain tables, even though
@@ -298,12 +308,17 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
if (stmt->ofTypename)
transformOfType(&cxt, stmt->ofTypename);
+ if (stmt->partspec)
+ {
+ if (stmt->inhRelations && !stmt->partbound)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot create partitioned table as inheritance child")));
+ }
+
/*
* Run through each primary element in the table creation clause. Separate
- * column defs from constraints, and do preliminary analysis. We have to
- * process column-defining clauses first because it can control the
- * presence of columns which are referenced by columns referenced by
- * constraints.
+ * column defs from constraints, and do preliminary analysis.
*/
foreach(elements, stmt->tableElts)
{
@@ -315,17 +330,13 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
transformColumnDefinition(&cxt, (ColumnDef *) element);
break;
- case T_TableLikeClause:
- if (!like_found)
- {
- cxt.hasoids = false;
- like_found = true;
- }
- transformTableLikeClause(&cxt, (TableLikeClause *) element);
+ case T_Constraint:
+ transformTableConstraint(&cxt, (Constraint *) element);
break;
- case T_Constraint:
- /* process later */
+ case T_TableLikeClause:
+ like_found = true;
+ transformTableLikeClause(&cxt, (TableLikeClause *) element);
break;
default:
@@ -335,26 +346,19 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
}
}
- if (like_found)
- {
- /*
- * To match INHERITS, the existence of any LIKE table with OIDs causes
- * the new table to have oids. For the same reason, WITH/WITHOUT OIDs
- * is also ignored with LIKE. We prepend because the first oid option
- * list entry is honored. Our prepended WITHOUT OIDS clause will be
- * overridden if an inherited table has oids.
- */
+ /*
+ * If we had any LIKE tables, they may require creation of an OID column
+ * even though the command's own WITH clause didn't ask for one (or,
+ * perhaps, even specifically rejected having one). Insert a WITH option
+ * to ensure that happens. We prepend to the list because the first oid
+ * option will be honored, and we want to override anything already there.
+ * (But note that DefineRelation will override this again to add an OID
+ * column if one appears in an inheritance parent table.)
+ */
+ if (like_found && cxt.hasoids)
stmt->options = lcons(makeDefElem("oids",
- (Node *) makeInteger(cxt.hasoids)), stmt->options);
- }
-
- foreach(elements, stmt->tableElts)
- {
- Node *element = lfirst(elements);
-
- if (nodeTag(element) == T_Constraint)
- transformTableConstraint(&cxt, (Constraint *) element);
- }
+ (Node *) makeInteger(true), -1),
+ stmt->options);
/*
* transformIndexConstraints wants cxt.alist to contain only index
@@ -482,6 +486,133 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
return result;
}
+static void
+generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
+ Oid seqtypid, List *seqoptions, bool for_identity,
+ char **snamespace_p, char **sname_p)
+{
+ ListCell *option;
+ DefElem *nameEl = NULL;
+ Oid snamespaceid;
+ char *snamespace;
+ char *sname;
+ CreateSeqStmt *seqstmt;
+ AlterSeqStmt *altseqstmt;
+ List *attnamelist;
+
+ /*
+ * Determine namespace and name to use for the sequence.
+ *
+ * First, check if a sequence name was passed in as an option. This is
+ * used by pg_dump. Else, generate a name.
+ *
+ * Although we use ChooseRelationName, it's not guaranteed that the
+ * selected sequence name won't conflict; given sufficiently long field
+ * names, two different serial columns in the same table could be assigned
+ * the same sequence name, and we'd not notice since we aren't creating
+ * the sequence quite yet. In practice this seems quite unlikely to be a
+ * problem, especially since few people would need two serial columns in
+ * one table.
+ */
+
+ foreach(option, seqoptions)
+ {
+ DefElem *defel = lfirst_node(DefElem, option);
+
+ if (strcmp(defel->defname, "sequence_name") == 0)
+ {
+ if (nameEl)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ nameEl = defel;
+ }
+ }
+
+ if (nameEl)
+ {
+ RangeVar *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg));
+
+ snamespace = rv->schemaname;
+ sname = rv->relname;
+ seqoptions = list_delete_ptr(seqoptions, nameEl);
+ }
+ else
+ {
+ if (cxt->rel)
+ snamespaceid = RelationGetNamespace(cxt->rel);
+ else
+ {
+ snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
+ RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
+ }
+ snamespace = get_namespace_name(snamespaceid);
+ sname = ChooseRelationName(cxt->relation->relname,
+ column->colname,
+ "seq",
+ snamespaceid);
+ }
+
+ ereport(DEBUG1,
+ (errmsg("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
+ cxt->stmtType, sname,
+ cxt->relation->relname, column->colname)));
+
+ /*
+ * Build a CREATE SEQUENCE command to create the sequence object, and add
+ * it to the list of things to be done before this CREATE/ALTER TABLE.
+ */
+ seqstmt = makeNode(CreateSeqStmt);
+ seqstmt->for_identity = for_identity;
+ seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
+ seqstmt->options = seqoptions;
+
+ /*
+ * If a sequence data type was specified, add it to the options. Prepend
+ * to the list rather than append; in case a user supplied their own AS
+ * clause, the "redundant options" error will point to their occurrence,
+ * not our synthetic one.
+ */
+ if (seqtypid)
+ seqstmt->options = lcons(makeDefElem("as", (Node *) makeTypeNameFromOid(seqtypid, -1), -1),
+ seqstmt->options);
+
+ /*
+ * If this is ALTER ADD COLUMN, make sure the sequence will be owned by
+ * the table's owner. The current user might be someone else (perhaps a
+ * superuser, or someone who's only a member of the owning role), but the
+ * SEQUENCE OWNED BY mechanisms will bleat unless table and sequence have
+ * exactly the same owning role.
+ */
+ if (cxt->rel)
+ seqstmt->ownerId = cxt->rel->rd_rel->relowner;
+ else
+ seqstmt->ownerId = InvalidOid;
+
+ cxt->blist = lappend(cxt->blist, seqstmt);
+
+ /*
+ * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence as
+ * owned by this column, and add it to the list of things to be done after
+ * this CREATE/ALTER TABLE.
+ */
+ altseqstmt = makeNode(AlterSeqStmt);
+ altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
+ attnamelist = list_make3(makeString(snamespace),
+ makeString(cxt->relation->relname),
+ makeString(column->colname));
+ altseqstmt->options = list_make1(makeDefElem("owned_by",
+ (Node *) attnamelist, -1));
+ altseqstmt->for_identity = for_identity;
+
+ cxt->alist = lappend(cxt->alist, altseqstmt);
+
+ if (snamespace_p)
+ *snamespace_p = snamespace;
+ if (sname_p)
+ *sname_p = sname;
+}
+
/*
* transformColumnDefinition -
* transform a single ColumnDef within CREATE TABLE
@@ -493,7 +624,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
bool is_serial;
bool saw_nullable;
bool saw_default;
- Constraint *constraint;
+ bool saw_identity;
ListCell *clist;
cxt->columns = lappend(cxt->columns, column);
@@ -548,89 +679,18 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
/* Special actions for SERIAL pseudo-types */
if (is_serial)
{
- Oid snamespaceid;
char *snamespace;
char *sname;
char *qstring;
A_Const *snamenode;
TypeCast *castnode;
FuncCall *funccallnode;
- CreateSeqStmt *seqstmt;
- AlterSeqStmt *altseqstmt;
- List *attnamelist;
-
- /*
- * Determine namespace and name to use for the sequence.
- *
- * Although we use ChooseRelationName, it's not guaranteed that the
- * selected sequence name won't conflict; given sufficiently long
- * field names, two different serial columns in the same table could
- * be assigned the same sequence name, and we'd not notice since we
- * aren't creating the sequence quite yet. In practice this seems
- * quite unlikely to be a problem, especially since few people would
- * need two serial columns in one table.
- */
- if (cxt->rel)
- snamespaceid = RelationGetNamespace(cxt->rel);
- else
- {
- snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
- RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
- }
- snamespace = get_namespace_name(snamespaceid);
- sname = ChooseRelationName(cxt->relation->relname,
- column->colname,
- "seq",
- snamespaceid);
-
- ereport(DEBUG1,
- (errmsg("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
- cxt->stmtType, sname,
- cxt->relation->relname, column->colname)));
-
- /*
- * Build a CREATE SEQUENCE command to create the sequence object, and
- * add it to the list of things to be done before this CREATE/ALTER
- * TABLE.
- */
- seqstmt = makeNode(CreateSeqStmt);
- seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
- seqstmt->options = NIL;
-#ifdef PGXC
- seqstmt->is_serial = true;
-#endif
-
- /*
- * If this is ALTER ADD COLUMN, make sure the sequence will be owned
- * by the table's owner. The current user might be someone else
- * (perhaps a superuser, or someone who's only a member of the owning
- * role), but the SEQUENCE OWNED BY mechanisms will bleat unless table
- * and sequence have exactly the same owning role.
- */
- if (cxt->rel)
- seqstmt->ownerId = cxt->rel->rd_rel->relowner;
- else
- seqstmt->ownerId = InvalidOid;
-
- cxt->blist = lappend(cxt->blist, seqstmt);
-
- /*
- * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence
- * as owned by this column, and add it to the list of things to be
- * done after this CREATE/ALTER TABLE.
- */
- altseqstmt = makeNode(AlterSeqStmt);
- altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
-#ifdef PGXC
- altseqstmt->is_serial = true;
-#endif
- attnamelist = list_make3(makeString(snamespace),
- makeString(cxt->relation->relname),
- makeString(column->colname));
- altseqstmt->options = list_make1(makeDefElem("owned_by",
- (Node *) attnamelist));
+ Constraint *constraint;
- cxt->alist = lappend(cxt->alist, altseqstmt);
+ /* XXX XL 9.6 was setting stmt->is_serial. CHECK */
+ generateSerialExtraStmts(cxt, column,
+ column->typeName->typeOid, NIL, false,
+ &snamespace, &sname);
/*
* Create appropriate constraints for SERIAL. We do this in full,
@@ -672,11 +732,11 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
saw_nullable = false;
saw_default = false;
+ saw_identity = false;
foreach(clist, column->constraints)
{
- constraint = lfirst(clist);
- Assert(IsA(constraint, Constraint));
+ Constraint *constraint = lfirst_node(Constraint, clist);
switch (constraint->contype)
{
@@ -717,6 +777,33 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
saw_default = true;
break;
+ case CONSTR_IDENTITY:
+ {
+ Type ctype;
+ Oid typeOid;
+
+ ctype = typenameType(cxt->pstate, column->typeName, NULL);
+ typeOid = HeapTupleGetOid(ctype);
+ ReleaseSysCache(ctype);
+
+ if (saw_identity)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("multiple identity specifications for column \"%s\" of table \"%s\"",
+ column->colname, cxt->relation->relname),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
+
+ generateSerialExtraStmts(cxt, column,
+ typeOid, constraint->options, true,
+ NULL, NULL);
+
+ column->identity = constraint->generated_when;
+ saw_identity = true;
+ column->is_not_null = TRUE;
+ break;
+ }
+
case CONSTR_CHECK:
cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
break;
@@ -728,6 +815,12 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
errmsg("primary key constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("primary key constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
/* FALL THRU */
case CONSTR_UNIQUE:
@@ -737,6 +830,12 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
errmsg("unique constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unique constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
if (constraint->keys == NIL)
constraint->keys = list_make1(makeString(column->colname));
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
@@ -754,6 +853,12 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
errmsg("foreign key constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("foreign key constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
/*
* Fill in the current attribute's name and throw it into the
@@ -775,6 +880,14 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
constraint->contype);
break;
}
+
+ if (saw_default && saw_identity)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("both default and identity specified for column \"%s\" of table \"%s\"",
+ column->colname, cxt->relation->relname),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
}
/*
@@ -819,6 +932,12 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
errmsg("primary key constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("primary key constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
break;
@@ -829,6 +948,12 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
errmsg("unique constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unique constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
break;
@@ -839,6 +964,12 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
errmsg("exclusion constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("exclusion constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
break;
@@ -853,6 +984,12 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
errmsg("foreign key constraints are not supported on foreign tables"),
parser_errposition(cxt->pstate,
constraint->location)));
+ if (cxt->ispartitioned)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("foreign key constraints are not supported on partitioned tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
break;
@@ -908,7 +1045,8 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
relation->rd_rel->relkind != RELKIND_VIEW &&
relation->rd_rel->relkind != RELKIND_MATVIEW &&
relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
- relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
@@ -994,6 +1132,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
def->is_local = true;
def->is_not_null = attribute->attnotnull;
def->is_from_type = false;
+ def->is_from_parent = false;
def->storage = 0;
def->raw_default = NULL;
def->cooked_default = NULL;
@@ -1054,6 +1193,27 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
def->cooked_default = this_default;
}
+ /*
+ * Copy identity if requested
+ */
+ if (attribute->attidentity &&
+ (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY))
+ {
+ Oid seq_relid;
+ List *seq_options;
+
+ /*
+ * find sequence owned by old column; extract sequence parameters;
+ * build new create sequence command
+ */
+ seq_relid = getOwnedSequence(RelationGetRelid(relation), attribute->attnum);
+ seq_options = sequence_options(seq_relid);
+ generateSerialExtraStmts(cxt, def,
+ InvalidOid, seq_options, true,
+ NULL, NULL);
+ def->identity = attribute->attidentity;
+ }
+
/* Likewise, copy storage if requested */
if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
def->storage = attribute->attstorage;
@@ -1069,10 +1229,9 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
CommentStmt *stmt = makeNode(CommentStmt);
stmt->objtype = OBJECT_COLUMN;
- stmt->objname = list_make3(makeString(cxt->relation->schemaname),
- makeString(cxt->relation->relname),
- makeString(def->colname));
- stmt->objargs = NIL;
+ stmt->object = (Node *) list_make3(makeString(cxt->relation->schemaname),
+ makeString(cxt->relation->relname),
+ makeString(def->colname));
stmt->comment = comment;
cxt->alist = lappend(cxt->alist, stmt);
@@ -1080,7 +1239,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
}
/* We use oids if at least one LIKE'ed table has oids. */
- cxt->hasoids = cxt->hasoids || relation->rd_rel->relhasoids;
+ cxt->hasoids |= relation->rd_rel->relhasoids;
/*
* Copy CHECK constraints if requested, being careful to adjust attribute
@@ -1135,10 +1294,9 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
CommentStmt *stmt = makeNode(CommentStmt);
stmt->objtype = OBJECT_TABCONSTRAINT;
- stmt->objname = list_make3(makeString(cxt->relation->schemaname),
- makeString(cxt->relation->relname),
- makeString(n->conname));
- stmt->objargs = NIL;
+ stmt->object = (Node *) list_make3(makeString(cxt->relation->schemaname),
+ makeString(cxt->relation->relname),
+ makeString(n->conname));
stmt->comment = comment;
cxt->alist = lappend(cxt->alist, stmt);
@@ -1227,6 +1385,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
n->is_local = true;
n->is_not_null = false;
n->is_from_type = true;
+ n->is_from_parent = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
@@ -1641,9 +1800,8 @@ transformIndexConstraints(CreateStmtContext *cxt)
*/
foreach(lc, cxt->ixconstraints)
{
- Constraint *constraint = (Constraint *) lfirst(lc);
+ Constraint *constraint = lfirst_node(Constraint, lc);
- Assert(IsA(constraint, Constraint));
Assert(constraint->contype == CONSTR_PRIMARY ||
constraint->contype == CONSTR_UNIQUE ||
constraint->contype == CONSTR_EXCLUSION);
@@ -1970,10 +2128,8 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
List *opname;
Assert(list_length(pair) == 2);
- elem = (IndexElem *) linitial(pair);
- Assert(IsA(elem, IndexElem));
- opname = (List *) lsecond(pair);
- Assert(IsA(opname, List));
+ elem = linitial_node(IndexElem, pair);
+ opname = lsecond_node(List, pair);
index->indexParams = lappend(index->indexParams, elem);
index->excludeOpNames = lappend(index->excludeOpNames, opname);
@@ -2000,8 +2156,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
foreach(columns, cxt->columns)
{
- column = (ColumnDef *) lfirst(columns);
- Assert(IsA(column, ColumnDef));
+ column = lfirst_node(ColumnDef, columns);
if (strcmp(column->colname, key) == 0)
{
found = true;
@@ -2030,15 +2185,15 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
foreach(inher, cxt->inhRelations)
{
- RangeVar *inh = (RangeVar *) lfirst(inher);
+ RangeVar *inh = lfirst_node(RangeVar, inher);
Relation rel;
int count;
- Assert(IsA(inh, RangeVar));
rel = heap_openrv(inh, AccessShareLock);
/* check user requested inheritance from valid relkind */
if (rel->rd_rel->relkind != RELKIND_RELATION &&
- rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("inherited relation \"%s\" is not a table or foreign table",
@@ -2358,7 +2513,7 @@ transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
* We must not scribble on the passed-in IndexStmt, so copy it. (This is
* overkill, but easy.)
*/
- stmt = (IndexStmt *) copyObject(stmt);
+ stmt = copyObject(stmt);
/* Set up pstate */
pstate = make_parsestate(NULL);
@@ -2406,17 +2561,11 @@ transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
/*
* transformExpr() should have already rejected subqueries,
- * aggregates, and window functions, based on the EXPR_KIND_ for
- * an index expression.
+ * aggregates, window functions, and SRFs, based on the EXPR_KIND_
+ * for an index expression.
*
- * Also reject expressions returning sets; this is for consistency
- * with what transformWhereClause() checks for the predicate.
* DefineIndex() will make more checks.
*/
- if (expression_returns_set(ielem->expr))
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("index expression cannot return a set")));
}
}
@@ -2784,7 +2933,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
* We must not scribble on the passed-in AlterTableStmt, so copy it. (This
* is overkill, but easy.)
*/
- stmt = (AlterTableStmt *) copyObject(stmt);
+ stmt = copyObject(stmt);
/* Caller is responsible for locking the relation */
rel = relation_open(relid, NoLock);
@@ -2830,6 +2979,8 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
cxt.distributeby = NULL;
cxt.subcluster = NULL;
#endif
+ cxt.ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+ cxt.partbound = NULL;
/*
* The only subtypes that currently require parse transformation handling
@@ -2845,9 +2996,8 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
case AT_AddColumn:
case AT_AddColumnToView:
{
- ColumnDef *def = (ColumnDef *) cmd->def;
+ ColumnDef *def = castNode(ColumnDef, cmd->def);
- Assert(IsA(def, ColumnDef));
transformColumnDefinition(&cxt, def);
/*
@@ -2898,6 +3048,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
case AT_AlterColumnType:
{
ColumnDef *def = (ColumnDef *) cmd->def;
+ AttrNumber attnum;
/*
* For ALTER COLUMN TYPE, transform the USING clause if
@@ -2908,18 +3059,133 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
def->cooked_default =
transformExpr(pstate, def->raw_default,
EXPR_KIND_ALTER_COL_TRANSFORM);
+ }
- /* it can't return a set */
- if (expression_returns_set(def->cooked_default))
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("transform expression must not return a set")));
+ /*
+ * For identity column, create ALTER SEQUENCE command to
+ * change the data type of the sequence.
+ */
+ attnum = get_attnum(relid, cmd->name);
+
+ /*
+ * if attribute not found, something will error about it
+ * later
+ */
+ if (attnum != InvalidAttrNumber && get_attidentity(relid, attnum))
+ {
+ Oid seq_relid = getOwnedSequence(relid, attnum);
+ Oid typeOid = typenameTypeId(pstate, def->typeName);
+ AlterSeqStmt *altseqstmt = makeNode(AlterSeqStmt);
+
+ altseqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
+ get_rel_name(seq_relid),
+ -1);
+ altseqstmt->options = list_make1(makeDefElem("as", (Node *) makeTypeNameFromOid(typeOid, -1), -1));
+ altseqstmt->for_identity = true;
+ cxt.blist = lappend(cxt.blist, altseqstmt);
+ }
+
+ newcmds = lappend(newcmds, cmd);
+ break;
+ }
+
+ case AT_AddIdentity:
+ {
+ Constraint *def = castNode(Constraint, cmd->def);
+ ColumnDef *newdef = makeNode(ColumnDef);
+ AttrNumber attnum;
+
+ newdef->colname = cmd->name;
+ newdef->identity = def->generated_when;
+ cmd->def = (Node *) newdef;
+
+ attnum = get_attnum(relid, cmd->name);
+
+ /*
+ * if attribute not found, something will error about it
+ * later
+ */
+ if (attnum != InvalidAttrNumber)
+ generateSerialExtraStmts(&cxt, newdef,
+ get_atttype(relid, attnum),
+ def->options, true,
+ NULL, NULL);
+
+ newcmds = lappend(newcmds, cmd);
+ break;
+ }
+
+ case AT_SetIdentity:
+ {
+ /*
+ * Create an ALTER SEQUENCE statement for the internal
+ * sequence of the identity column.
+ */
+ ListCell *lc;
+ List *newseqopts = NIL;
+ List *newdef = NIL;
+ List *seqlist;
+ AttrNumber attnum;
+
+ /*
+ * Split options into those handled by ALTER SEQUENCE and
+ * those for ALTER TABLE proper.
+ */
+ foreach(lc, castNode(List, cmd->def))
+ {
+ DefElem *def = lfirst_node(DefElem, lc);
+
+ if (strcmp(def->defname, "generated") == 0)
+ newdef = lappend(newdef, def);
+ else
+ newseqopts = lappend(newseqopts, def);
}
+ attnum = get_attnum(relid, cmd->name);
+
+ if (attnum)
+ {
+ seqlist = getOwnedSequences(relid, attnum);
+ if (seqlist)
+ {
+ AlterSeqStmt *seqstmt;
+ Oid seq_relid;
+
+ seqstmt = makeNode(AlterSeqStmt);
+ seq_relid = linitial_oid(seqlist);
+ seqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
+ get_rel_name(seq_relid), -1);
+ seqstmt->options = newseqopts;
+ seqstmt->for_identity = true;
+ seqstmt->missing_ok = false;
+
+ cxt.alist = lappend(cxt.alist, seqstmt);
+ }
+ }
+
+ /*
+ * If column was not found or was not an identity column,
+ * we just let the ALTER TABLE command error out later.
+ */
+
+ cmd->def = (Node *) newdef;
newcmds = lappend(newcmds, cmd);
break;
}
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ {
+ PartitionCmd *partcmd = (PartitionCmd *) cmd->def;
+
+ transformPartitionCmd(&cxt, partcmd);
+ /* assign transformed value of the partition bound */
+ partcmd->bound = cxt.partbound;
+ }
+
+ newcmds = lappend(newcmds, cmd);
+ break;
+
default:
newcmds = lappend(newcmds, cmd);
break;
@@ -2947,9 +3213,8 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
*/
foreach(l, cxt.alist)
{
- IndexStmt *idxstmt = (IndexStmt *) lfirst(l);
+ IndexStmt *idxstmt = lfirst_node(IndexStmt, l);
- Assert(IsA(idxstmt, IndexStmt));
idxstmt = transformIndexStmt(relid, idxstmt, queryString);
newcmd = makeNode(AlterTableCmd);
newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
@@ -3791,3 +4056,275 @@ makeSubCluster(List *nodelist)
return result;
}
#endif
+
+/*
+ * transformPartitionCmd
+ * Analyze the ATTACH/DETACH PARTITION command
+ *
+ * In case of the ATTACH PARTITION command, cxt->partbound is set to the
+ * transformed value of cmd->bound.
+ */
+static void
+transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
+{
+ Relation parentRel = cxt->rel;
+
+ /* the table must be partitioned */
+ if (parentRel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("\"%s\" is not partitioned",
+ RelationGetRelationName(parentRel))));
+
+ /* transform the partition bound, if any */
+ Assert(RelationGetPartitionKey(parentRel) != NULL);
+ if (cmd->bound != NULL)
+ cxt->partbound = transformPartitionBound(cxt->pstate, parentRel,
+ cmd->bound);
+}
+
+/*
+ * transformPartitionBound
+ *
+ * Transform a partition bound specification
+ */
+PartitionBoundSpec *
+transformPartitionBound(ParseState *pstate, Relation parent,
+ PartitionBoundSpec *spec)
+{
+ PartitionBoundSpec *result_spec;
+ PartitionKey key = RelationGetPartitionKey(parent);
+ char strategy = get_partition_strategy(key);
+ int partnatts = get_partition_natts(key);
+ List *partexprs = get_partition_exprs(key);
+
+ /* Avoid scribbling on input */
+ result_spec = copyObject(spec);
+
+ if (strategy == PARTITION_STRATEGY_LIST)
+ {
+ ListCell *cell;
+ char *colname;
+ Oid coltype;
+ int32 coltypmod;
+
+ if (spec->strategy != PARTITION_STRATEGY_LIST)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("invalid bound specification for a list partition"),
+ parser_errposition(pstate, exprLocation((Node *) spec))));
+
+ /* Get the only column's name in case we need to output an error */
+ if (key->partattrs[0] != 0)
+ colname = get_relid_attribute_name(RelationGetRelid(parent),
+ key->partattrs[0]);
+ else
+ colname = deparse_expression((Node *) linitial(partexprs),
+ deparse_context_for(RelationGetRelationName(parent),
+ RelationGetRelid(parent)),
+ false, false);
+ /* Need its type data too */
+ coltype = get_partition_col_typid(key, 0);
+ coltypmod = get_partition_col_typmod(key, 0);
+
+ result_spec->listdatums = NIL;
+ foreach(cell, spec->listdatums)
+ {
+ A_Const *con = castNode(A_Const, lfirst(cell));
+ Const *value;
+ ListCell *cell2;
+ bool duplicate;
+
+ value = transformPartitionBoundValue(pstate, con,
+ colname, coltype, coltypmod);
+
+ /* Don't add to the result if the value is a duplicate */
+ duplicate = false;
+ foreach(cell2, result_spec->listdatums)
+ {
+ Const *value2 = castNode(Const, lfirst(cell2));
+
+ if (equal(value, value2))
+ {
+ duplicate = true;
+ break;
+ }
+ }
+ if (duplicate)
+ continue;
+
+ result_spec->listdatums = lappend(result_spec->listdatums,
+ value);
+ }
+ }
+ else if (strategy == PARTITION_STRATEGY_RANGE)
+ {
+ ListCell *cell1,
+ *cell2;
+ int i,
+ j;
+ bool seen_unbounded;
+
+ if (spec->strategy != PARTITION_STRATEGY_RANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("invalid bound specification for a range partition"),
+ parser_errposition(pstate, exprLocation((Node *) spec))));
+
+ if (list_length(spec->lowerdatums) != partnatts)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("FROM must specify exactly one value per partitioning column")));
+ if (list_length(spec->upperdatums) != partnatts)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("TO must specify exactly one value per partitioning column")));
+
+ /*
+ * Check that no finite value follows an UNBOUNDED item in either of
+ * lower and upper bound lists.
+ */
+ seen_unbounded = false;
+ foreach(cell1, spec->lowerdatums)
+ {
+ PartitionRangeDatum *ldatum = castNode(PartitionRangeDatum,
+ lfirst(cell1));
+
+ if (ldatum->infinite)
+ seen_unbounded = true;
+ else if (seen_unbounded)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot specify finite value after UNBOUNDED"),
+ parser_errposition(pstate, exprLocation((Node *) ldatum))));
+ }
+ seen_unbounded = false;
+ foreach(cell1, spec->upperdatums)
+ {
+ PartitionRangeDatum *rdatum = castNode(PartitionRangeDatum,
+ lfirst(cell1));
+
+ if (rdatum->infinite)
+ seen_unbounded = true;
+ else if (seen_unbounded)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot specify finite value after UNBOUNDED"),
+ parser_errposition(pstate, exprLocation((Node *) rdatum))));
+ }
+
+ /* Transform all the constants */
+ i = j = 0;
+ result_spec->lowerdatums = result_spec->upperdatums = NIL;
+ forboth(cell1, spec->lowerdatums, cell2, spec->upperdatums)
+ {
+ PartitionRangeDatum *ldatum = (PartitionRangeDatum *) lfirst(cell1);
+ PartitionRangeDatum *rdatum = (PartitionRangeDatum *) lfirst(cell2);
+ char *colname;
+ Oid coltype;
+ int32 coltypmod;
+ A_Const *con;
+ Const *value;
+
+ /* Get the column's name in case we need to output an error */
+ if (key->partattrs[i] != 0)
+ colname = get_relid_attribute_name(RelationGetRelid(parent),
+ key->partattrs[i]);
+ else
+ {
+ colname = deparse_expression((Node *) list_nth(partexprs, j),
+ deparse_context_for(RelationGetRelationName(parent),
+ RelationGetRelid(parent)),
+ false, false);
+ ++j;
+ }
+ /* Need its type data too */
+ coltype = get_partition_col_typid(key, i);
+ coltypmod = get_partition_col_typmod(key, i);
+
+ if (ldatum->value)
+ {
+ con = castNode(A_Const, ldatum->value);
+ value = transformPartitionBoundValue(pstate, con,
+ colname,
+ coltype, coltypmod);
+ if (value->constisnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot specify NULL in range bound")));
+ ldatum = copyObject(ldatum); /* don't scribble on input */
+ ldatum->value = (Node *) value;
+ }
+
+ if (rdatum->value)
+ {
+ con = castNode(A_Const, rdatum->value);
+ value = transformPartitionBoundValue(pstate, con,
+ colname,
+ coltype, coltypmod);
+ if (value->constisnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot specify NULL in range bound")));
+ rdatum = copyObject(rdatum); /* don't scribble on input */
+ rdatum->value = (Node *) value;
+ }
+
+ result_spec->lowerdatums = lappend(result_spec->lowerdatums,
+ ldatum);
+ result_spec->upperdatums = lappend(result_spec->upperdatums,
+ rdatum);
+
+ ++i;
+ }
+ }
+ else
+ elog(ERROR, "unexpected partition strategy: %d", (int) strategy);
+
+ return result_spec;
+}
+
+/*
+ * Transform one constant in a partition bound spec
+ */
+static Const *
+transformPartitionBoundValue(ParseState *pstate, A_Const *con,
+ const char *colName, Oid colType, int32 colTypmod)
+{
+ Node *value;
+
+ /* Make it into a Const */
+ value = (Node *) make_const(pstate, &con->val, con->location);
+
+ /* Coerce to correct type */
+ value = coerce_to_target_type(pstate,
+ value, exprType(value),
+ colType,
+ colTypmod,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+
+ if (value == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("specified value cannot be cast to type %s for column \"%s\"",
+ format_type_be(colType), colName),
+ parser_errposition(pstate, con->location)));
+
+ /* Simplify the expression, in case we had a coercion */
+ if (!IsA(value, Const))
+ value = (Node *) expression_planner((Expr *) value);
+
+ /* Fail if we don't have a constant (i.e., non-immutable coercion) */
+ if (!IsA(value, Const))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("specified value cannot be cast to type %s for column \"%s\"",
+ format_type_be(colType), colName),
+ errdetail("The cast requires a non-immutable conversion."),
+ errhint("Try putting the literal value in single quotes."),
+ parser_errposition(pstate, con->location)));
+
+ return (Const *) value;
+}
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 2cc9b54dd5..522d7ec203 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -10,7 +10,7 @@
* analyze.c and related files.
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -29,7 +29,8 @@
* raw_parser
* Given a query in string form, do lexical and grammatical analysis.
*
- * Returns a list of raw (un-analyzed) parse trees.
+ * Returns a list of raw (un-analyzed) parse trees. The immediate elements
+ * of the list are always RawStmt nodes.
*/
List *
raw_parser(const char *str, List **queries)
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index e693293c59..83a73410b8 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -21,7 +21,7 @@
* Postgres 9.2, this check is made automatically by the Makefile.)
*
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -1439,6 +1439,13 @@ litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner)
}
}
+ /* unfinished surrogate pair? */
+ if (pair_first)
+ {
+ ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */
+ yyerror("invalid Unicode surrogate pair");
+ }
+
*out = '\0';
/*
diff --git a/src/backend/parser/scansup.c b/src/backend/parser/scansup.c
index 7aa5b76841..c3d2805803 100644
--- a/src/backend/parser/scansup.c
+++ b/src/backend/parser/scansup.c
@@ -4,7 +4,7 @@
* support routines for the lex/flex scanner, used by both the normal
* backend as well as the bootstrap backend
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
diff --git a/src/backend/pgxc/cluster/pause.c b/src/backend/pgxc/cluster/pause.c
index 164dafa0e8..65769e94c3 100644
--- a/src/backend/pgxc/cluster/pause.c
+++ b/src/backend/pgxc/cluster/pause.c
@@ -15,6 +15,7 @@
#include "pgxc/execRemote.h"
#include "pgxc/pause.h"
#include "pgxc/pgxc.h"
+#include "storage/shmem.h"
#include "storage/spin.h"
#include "miscadmin.h"
diff --git a/src/backend/pgxc/locator/locator.c b/src/backend/pgxc/locator/locator.c
index c45d7e7d14..1c6d98c8a2 100644
--- a/src/backend/pgxc/locator/locator.c
+++ b/src/backend/pgxc/locator/locator.c
@@ -889,8 +889,6 @@ hash_func_ptr(Oid dataType)
return hashchar;
case NAMEOID:
return hashname;
- case INT2VECTOROID:
- return hashint2vector;
case VARCHAROID:
case TEXTOID:
return hashtext;
diff --git a/src/backend/pgxc/nodemgr/groupmgr.c b/src/backend/pgxc/nodemgr/groupmgr.c
index b63b8cf44f..8104e5ba4c 100644
--- a/src/backend/pgxc/nodemgr/groupmgr.c
+++ b/src/backend/pgxc/nodemgr/groupmgr.c
@@ -106,10 +106,7 @@ PgxcGroupCreate(CreateGroupStmt *stmt)
rel = heap_open(PgxcGroupRelationId, RowExclusiveLock);
tup = heap_form_tuple(rel->rd_att, values, nulls);
- /* Do the insertion */
- (void) simple_heap_insert(rel, tup);
-
- CatalogUpdateIndexes(rel, tup);
+ CatalogTupleInsert(rel, tup);
heap_close(rel, RowExclusiveLock);
}
diff --git a/src/backend/pgxc/nodemgr/nodemgr.c b/src/backend/pgxc/nodemgr/nodemgr.c
index 5ae6fe5f05..e6cc9af14b 100644
--- a/src/backend/pgxc/nodemgr/nodemgr.c
+++ b/src/backend/pgxc/nodemgr/nodemgr.c
@@ -28,6 +28,8 @@
#include "pgxc/locator.h"
#include "pgxc/nodemgr.h"
#include "pgxc/pgxc.h"
+#include "storage/lwlock.h"
+#include "storage/shmem.h"
/*
* How many times should we try to find a unique indetifier
@@ -838,10 +840,7 @@ PgxcNodeCreate(CreateNodeStmt *stmt)
htup = heap_form_tuple(pgxcnodesrel->rd_att, values, nulls);
- /* Insert tuple in catalog */
- simple_heap_insert(pgxcnodesrel, htup);
-
- CatalogUpdateIndexes(pgxcnodesrel, htup);
+ CatalogTupleInsert(pgxcnodesrel, htup);
heap_close(pgxcnodesrel, AccessExclusiveLock);
}
@@ -964,10 +963,7 @@ PgxcNodeAlter(AlterNodeStmt *stmt)
newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(rel, &oldtup->t_self, newtup);
-
- /* Update indexes */
- CatalogUpdateIndexes(rel, newtup);
+ CatalogTupleUpdate(rel, &oldtup->t_self, newtup);
/* Release lock at Commit */
heap_close(rel, NoLock);
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c
index 21f155f5f7..59c5d8e7c0 100644
--- a/src/backend/pgxc/pool/execRemote.c
+++ b/src/backend/pgxc/pool/execRemote.c
@@ -3142,8 +3142,7 @@ get_exec_connections(RemoteQueryState *planstate,
(PlanState *) planstate);
Datum partvalue = ExecEvalExpr(estate,
planstate->combiner.ss.ps.ps_ExprContext,
- &isnull,
- NULL);
+ &isnull);
RelationLocInfo *rel_loc_info = GetRelationLocInfo(exec_nodes->en_relid);
/* PGXCTODO what is the type of partvalue here */
ExecNodes *nodes = GetRelationNodes(rel_loc_info,
@@ -3922,7 +3921,8 @@ PreCommit_Remote(char *prepareGID, char *nodestring, bool preparedLocalNode)
* table finally aborts - remote connections are not holding temporary
* objects in this case.
*/
- if (IS_PGXC_LOCAL_COORDINATOR && MyXactAccessedTempRel)
+ if (IS_PGXC_LOCAL_COORDINATOR &&
+ (MyXactFlags & XACT_FLAGS_ACCESSEDTEMPREL))
temp_object_included = true;
@@ -4194,7 +4194,7 @@ IsTwoPhaseCommitRequired(bool localWrite)
if (IS_PGXC_DATANODE)
return false;
- if (MyXactAccessedTempRel)
+ if (MyXactFlags & XACT_FLAGS_ACCESSEDTEMPREL)
{
elog(DEBUG1, "Transaction accessed temporary objects - "
"2PC will not be used and that can lead to data inconsistencies "
@@ -4492,7 +4492,7 @@ ExecInitRemoteQuery(RemoteQuery *node, EState *estate, int eflags)
combiner->ss.ps.plan = (Plan *) node;
combiner->ss.ps.state = estate;
- combiner->ss.ps.qual = NIL;
+ combiner->ss.ps.qual = NULL;
combiner->request_type = REQUEST_TYPE_QUERY;
@@ -4713,7 +4713,7 @@ ExecRemoteQuery(RemoteQueryState *node)
if (combiner->tuplesortstate)
{
if (tuplesort_gettupleslot((Tuplesortstate *) combiner->tuplesortstate,
- true, resultslot, NULL))
+ true, true, resultslot, NULL))
return resultslot;
else
ExecClearTuple(resultslot);
@@ -5244,7 +5244,7 @@ ExecInitRemoteSubplan(RemoteSubplan *node, EState *estate, int eflags)
combiner->ss.ps.plan = (Plan *) node;
combiner->ss.ps.state = estate;
- combiner->ss.ps.qual = NIL;
+ combiner->ss.ps.qual = NULL;
combiner->request_type = REQUEST_TYPE_QUERY;
@@ -6049,7 +6049,7 @@ primary_mode_phase_two:
if (combiner->tuplesortstate)
{
if (tuplesort_gettupleslot((Tuplesortstate *) combiner->tuplesortstate,
- true, resultslot, NULL))
+ true, true, resultslot, NULL))
{
if (log_remotesubplan_stats)
ShowUsageCommon("ExecRemoteSubplan", &start_r, &start_t);
diff --git a/src/backend/pgxc/pool/pgxcnode.c b/src/backend/pgxc/pool/pgxcnode.c
index eafd9cbbe0..809da4f1d2 100644
--- a/src/backend/pgxc/pool/pgxcnode.c
+++ b/src/backend/pgxc/pool/pgxcnode.c
@@ -48,6 +48,7 @@
#include "pgxc/pgxc.h"
#include "pgxc/poolmgr.h"
#include "tcop/dest.h"
+#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/elog.h"
#include "utils/memutils.h"
@@ -2509,7 +2510,7 @@ PGXCNodeGetNodeOid(int nodeid, char node_type)
Datum
pgxc_node_str(PG_FUNCTION_ARGS)
{
- PG_RETURN_NAME(PGXCNodeName);
+ PG_RETURN_TEXT_P(cstring_to_text(PGXCNodeName));
}
/*
diff --git a/src/backend/pgxc/pool/poolmgr.c b/src/backend/pgxc/pool/poolmgr.c
index 336101419e..140907d872 100644
--- a/src/backend/pgxc/pool/poolmgr.c
+++ b/src/backend/pgxc/pool/poolmgr.c
@@ -39,6 +39,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
+#include <math.h>
#include "postgres.h"
@@ -63,10 +64,12 @@
#include "pgxc/poolutils.h"
#include "postmaster/postmaster.h" /* For UnixSocketDir */
#include "storage/procarray.h"
+#include "utils/varlena.h"
#include "../interfaces/libpq/libpq-fe.h"
#include "../interfaces/libpq/libpq-int.h"
+
/* Configuration options */
int PoolConnKeepAlive = 600;
int PoolMaintenanceTimeout = 30;
diff --git a/src/backend/pgxc/squeue/squeue.c b/src/backend/pgxc/squeue/squeue.c
index 4fbae5b31b..a9741f33f6 100644
--- a/src/backend/pgxc/squeue/squeue.c
+++ b/src/backend/pgxc/squeue/squeue.c
@@ -36,6 +36,7 @@
#include "storage/shmem.h"
#include "utils/hsearch.h"
#include "utils/resowner.h"
+#include "pgstat.h"
int NSQueues = 64;
@@ -120,7 +121,6 @@ typedef struct SQueueHeader
*/
static HTAB *SharedQueues = NULL;
static LWLockPadded *SQueueLocks = NULL;
-static LWLockTranche SharedQueueLocksTranche;
/*
* Pool of synchronization items
@@ -234,12 +234,8 @@ SharedQueuesInit(void)
/* either both syncs and locks, or none of them */
Assert(! foundLocks);
- SharedQueueLocksTranche.name = "Shared Queue Locks";
- SharedQueueLocksTranche.array_base = SQueueLocks;
- SharedQueueLocksTranche.array_stride = sizeof(LWLockPadded);
-
/* Register the trannche tranche in the main tranches array */
- LWLockRegisterTranche(LWTRANCHE_SHARED_QUEUES, &SharedQueueLocksTranche);
+ LWLockRegisterTranche(LWTRANCHE_SHARED_QUEUES, "Shared Queue Locks");
l = 0;
for (i = 0; i < NUM_SQUEUES; i++)
@@ -1020,7 +1016,9 @@ SharedQueueRead(SharedQueue squeue, int consumerIdx,
cstate->cs_node, cstate->cs_pid, cstate->cs_status);
/* Wait for notification about available info */
- WaitLatch(&sqsync->sqs_consumer_sync[consumerIdx].cs_latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1);
+ WaitLatch(&sqsync->sqs_consumer_sync[consumerIdx].cs_latch,
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, -1,
+ WAIT_EVENT_MQ_INTERNAL);
/* got the notification, restore lock and try again */
LWLockAcquire(sqsync->sqs_consumer_sync[consumerIdx].cs_lwlock, LW_EXCLUSIVE);
}
@@ -1421,7 +1419,7 @@ CHECK:
/* wait for a notification */
wait_result = WaitLatch(&sqsync->sqs_producer_latch,
WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT,
- 10000L);
+ 10000L, WAIT_EVENT_MQ_INTERNAL);
if (wait_result & WL_TIMEOUT)
{
elog(WARNING, "SQueue %s, timeout while waiting for Consumers "
@@ -1776,7 +1774,8 @@ sq_pull_long_tuple(ConsState *cstate, RemoteDataRow datarow,
ResetLatch(&sync->cs_latch);
LWLockRelease(sync->cs_lwlock);
/* Wait for notification about available info */
- WaitLatch(&sync->cs_latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1);
+ WaitLatch(&sync->cs_latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1,
+ WAIT_EVENT_MQ_INTERNAL);
/* got the notification, restore lock and try again */
LWLockAcquire(sync->cs_lwlock, LW_EXCLUSIVE);
}
diff --git a/src/backend/po/de.po b/src/backend/po/de.po
index 9ac21992a9..09622423fb 100644
--- a/src/backend/po/de.po
+++ b/src/backend/po/de.po
@@ -1,14 +1,14 @@
# German message translation file for PostgreSQL server
-# Peter Eisentraut <[email protected]>, 2001 - 2016.
+# Peter Eisentraut <[email protected]>, 2001 - 2017.
#
# Use these quotes: »%s«
#
msgid ""
msgstr ""
-"Project-Id-Version: PostgreSQL 9.6\n"
+"Project-Id-Version: PostgreSQL 10\n"
"Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2016-08-07 23:08+0000\n"
-"PO-Revision-Date: 2016-08-08 08:06-0400\n"
+"POT-Creation-Date: 2017-03-13 20:08+0000\n"
+"PO-Revision-Date: 2017-03-13 17:04-0400\n"
"Last-Translator: Peter Eisentraut <[email protected]>\n"
"Language-Team: German <[email protected]>\n"
"Language: de\n"
@@ -25,58 +25,40 @@ msgstr ""
msgid "not recorded"
msgstr "nicht aufgezeichnet"
-#: ../common/controldata_utils.c:52 commands/copy.c:2798
-#: commands/extension.c:3120 utils/adt/genfile.c:134
+#: ../common/controldata_utils.c:57 commands/copy.c:3028
+#: commands/extension.c:3323 utils/adt/genfile.c:134
#, c-format
msgid "could not open file \"%s\" for reading: %m"
msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m"
-#: ../common/controldata_utils.c:56
+#: ../common/controldata_utils.c:61
#, c-format
msgid "%s: could not open file \"%s\" for reading: %s\n"
msgstr "%s: konnte Datei »%s« nicht zum Lesen öffnen: %s\n"
-#: ../common/controldata_utils.c:66 access/transam/timeline.c:346
-#: access/transam/xlog.c:3191 access/transam/xlog.c:10336
-#: access/transam/xlog.c:10349 access/transam/xlog.c:10712
-#: access/transam/xlog.c:10755 access/transam/xlog.c:10794
-#: access/transam/xlog.c:10837 access/transam/xlogfuncs.c:665
-#: access/transam/xlogfuncs.c:684 commands/extension.c:3130
-#: replication/logical/origin.c:665 replication/logical/origin.c:695
-#: replication/logical/reorderbuffer.c:3091 replication/walsender.c:499
-#: storage/file/copydir.c:176 utils/adt/genfile.c:151
+#: ../common/controldata_utils.c:71 access/transam/timeline.c:345
+#: access/transam/xlog.c:3368 access/transam/xlog.c:10701
+#: access/transam/xlog.c:10714 access/transam/xlog.c:11106
+#: access/transam/xlog.c:11149 access/transam/xlog.c:11188
+#: access/transam/xlog.c:11231 access/transam/xlogfuncs.c:664
+#: access/transam/xlogfuncs.c:683 commands/extension.c:3333 libpq/hba.c:496
+#: replication/logical/origin.c:658 replication/logical/origin.c:688
+#: replication/logical/reorderbuffer.c:3055 replication/walsender.c:469
+#: storage/file/copydir.c:176 utils/adt/genfile.c:151 utils/adt/misc.c:924
#, c-format
msgid "could not read file \"%s\": %m"
msgstr "konnte Datei »%s« nicht lesen: %m"
-#: ../common/controldata_utils.c:69
+#: ../common/controldata_utils.c:74
#, c-format
msgid "%s: could not read file \"%s\": %s\n"
msgstr "%s: konnte Datei »%s« nicht lesen: %s\n"
-#: ../common/controldata_utils.c:86
-msgid "calculated CRC checksum does not match value stored in file"
-msgstr "berechnete CRC-Prüfsumme stimmt nicht mit dem Wert in der Datei überein"
-
-#: ../common/controldata_utils.c:88
-#, c-format
-msgid ""
-"WARNING: Calculated CRC checksum does not match value stored in file.\n"
-"Either the file is corrupt, or it has a different layout than this program\n"
-"is expecting. The results below are untrustworthy.\n"
-"\n"
-msgstr ""
-"WARNUNG: Berechnete CRC-Prüfsumme stimmt nicht mit dem Wert in der Datei\n"
-"überein. Entweder ist die Datei kaputt oder sie hat ein anderes Layout\n"
-"als von diesem Programm erwartet. Die Ergebnisse unten sind nicht\n"
-"verlässlich.\n"
-"\n"
-
-#: ../common/controldata_utils.c:97
+#: ../common/controldata_utils.c:95
msgid "byte ordering mismatch"
msgstr "falsche Byte-Reihenfolge"
-#: ../common/controldata_utils.c:99
+#: ../common/controldata_utils.c:97
#, c-format
msgid ""
"WARNING: possible byte ordering mismatch\n"
@@ -127,7 +109,9 @@ msgstr "pclose fehlgeschlagen: %s"
#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75
#: ../common/fe_memutils.c:98 ../common/psprintf.c:181 ../port/path.c:632
-#: ../port/path.c:670 ../port/path.c:687
+#: ../port/path.c:670 ../port/path.c:687 utils/misc/ps_status.c:171
+#: utils/misc/ps_status.c:179 utils/misc/ps_status.c:209
+#: utils/misc/ps_status.c:217
#, c-format
msgid "out of memory\n"
msgstr "Speicher aufgebraucht\n"
@@ -137,6 +121,37 @@ msgstr "Speicher aufgebraucht\n"
msgid "cannot duplicate null pointer (internal error)\n"
msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n"
+#: ../common/file_utils.c:82 ../common/file_utils.c:167
+#, c-format
+msgid "%s: could not stat file \"%s\": %s\n"
+msgstr "%s: konnte »stat« für Datei »%s« nicht ausführen: %s\n"
+
+#: ../common/file_utils.c:143
+#, c-format
+msgid "%s: could not open directory \"%s\": %s\n"
+msgstr "%s: konnte Verzeichnis »%s« nicht öffnen: %s\n"
+
+#: ../common/file_utils.c:179
+#, c-format
+msgid "%s: could not read directory \"%s\": %s\n"
+msgstr "%s: konnte Verzeichnis »%s« nicht lesen: %s\n"
+
+#: ../common/file_utils.c:212 ../common/file_utils.c:272
+#: ../common/file_utils.c:348
+#, c-format
+msgid "%s: could not open file \"%s\": %s\n"
+msgstr "%s: konnte Datei »%s« nicht öffnen: %s\n"
+
+#: ../common/file_utils.c:285 ../common/file_utils.c:357
+#, c-format
+msgid "%s: could not fsync file \"%s\": %s\n"
+msgstr "%s: konnte Datei »%s« nicht fsyncen: %s\n"
+
+#: ../common/file_utils.c:368
+#, c-format
+msgid "%s: could not rename file \"%s\" to \"%s\": %s\n"
+msgstr "%s: konnte Datei »%s« nicht in »%s« umbenennen: %s\n"
+
#: ../common/pgfnames.c:45
#, c-format
msgid "could not open directory \"%s\": %s\n"
@@ -154,29 +169,31 @@ msgstr "konnte Verzeichnis »%s« nicht schließen: %s\n"
#: ../common/psprintf.c:179 ../port/path.c:630 ../port/path.c:668
#: ../port/path.c:685 access/transam/twophase.c:1261
-#: access/transam/xlog.c:6067 lib/stringinfo.c:258 libpq/auth.c:847
-#: libpq/auth.c:1210 libpq/auth.c:1278 libpq/auth.c:1794
-#: postmaster/bgworker.c:289 postmaster/bgworker.c:797
-#: postmaster/postmaster.c:2326 postmaster/postmaster.c:2357
-#: postmaster/postmaster.c:3890 postmaster/postmaster.c:4580
-#: postmaster/postmaster.c:4648 postmaster/postmaster.c:5347
-#: postmaster/postmaster.c:5611
-#: replication/libpqwalreceiver/libpqwalreceiver.c:143
-#: replication/logical/logical.c:170 storage/buffer/localbuf.c:436
-#: storage/file/fd.c:729 storage/file/fd.c:1126 storage/file/fd.c:1244
-#: storage/file/fd.c:1916 storage/ipc/procarray.c:1060
-#: storage/ipc/procarray.c:1546 storage/ipc/procarray.c:1553
-#: storage/ipc/procarray.c:1967 storage/ipc/procarray.c:2570
-#: utils/adt/formatting.c:1522 utils/adt/formatting.c:1642
-#: utils/adt/formatting.c:1763 utils/adt/regexp.c:219 utils/adt/varlena.c:4440
-#: utils/adt/varlena.c:4461 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:431
-#: utils/hash/dynahash.c:537 utils/hash/dynahash.c:1049 utils/mb/mbutils.c:376
-#: utils/mb/mbutils.c:709 utils/misc/guc.c:3886 utils/misc/guc.c:3902
-#: utils/misc/guc.c:3915 utils/misc/guc.c:6861 utils/misc/tzparser.c:470
-#: utils/mmgr/aset.c:505 utils/mmgr/mcxt.c:770 utils/mmgr/mcxt.c:805
-#: utils/mmgr/mcxt.c:842 utils/mmgr/mcxt.c:879 utils/mmgr/mcxt.c:913
-#: utils/mmgr/mcxt.c:942 utils/mmgr/mcxt.c:976 utils/mmgr/mcxt.c:1058
-#: utils/mmgr/mcxt.c:1092 utils/mmgr/mcxt.c:1141
+#: access/transam/xlog.c:6317 lib/stringinfo.c:300 libpq/auth.c:1011
+#: libpq/auth.c:1376 libpq/auth.c:1444 libpq/auth.c:1960
+#: postmaster/bgworker.c:318 postmaster/bgworker.c:874
+#: postmaster/postmaster.c:2363 postmaster/postmaster.c:2385
+#: postmaster/postmaster.c:3935 postmaster/postmaster.c:4635
+#: postmaster/postmaster.c:4710 postmaster/postmaster.c:5379
+#: postmaster/postmaster.c:5660
+#: replication/libpqwalreceiver/libpqwalreceiver.c:246
+#: replication/logical/logical.c:168 storage/buffer/localbuf.c:436
+#: storage/file/fd.c:736 storage/file/fd.c:1164 storage/file/fd.c:1282
+#: storage/file/fd.c:1993 storage/ipc/procarray.c:1054
+#: storage/ipc/procarray.c:1540 storage/ipc/procarray.c:1547
+#: storage/ipc/procarray.c:1961 storage/ipc/procarray.c:2564
+#: utils/adt/formatting.c:1509 utils/adt/formatting.c:1629
+#: utils/adt/formatting.c:1750 utils/adt/pg_locale.c:462
+#: utils/adt/pg_locale.c:646 utils/adt/regexp.c:219 utils/adt/varlena.c:4427
+#: utils/adt/varlena.c:4448 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:429
+#: utils/hash/dynahash.c:535 utils/hash/dynahash.c:1047 utils/mb/mbutils.c:376
+#: utils/mb/mbutils.c:709 utils/misc/guc.c:3954 utils/misc/guc.c:3970
+#: utils/misc/guc.c:3983 utils/misc/guc.c:6929 utils/misc/tzparser.c:468
+#: utils/mmgr/aset.c:404 utils/mmgr/dsa.c:713 utils/mmgr/dsa.c:795
+#: utils/mmgr/mcxt.c:725 utils/mmgr/mcxt.c:760 utils/mmgr/mcxt.c:797
+#: utils/mmgr/mcxt.c:834 utils/mmgr/mcxt.c:868 utils/mmgr/mcxt.c:897
+#: utils/mmgr/mcxt.c:931 utils/mmgr/mcxt.c:982 utils/mmgr/mcxt.c:1016
+#: utils/mmgr/mcxt.c:1050
#, c-format
msgid "out of memory"
msgstr "Speicher aufgebraucht"
@@ -236,67 +253,61 @@ msgstr "konnte »stat« für Datei oder Verzeichnis »%s« nicht ausführen: %s\
msgid "could not remove file or directory \"%s\": %s\n"
msgstr "konnte Datei oder Verzeichnis »%s« nicht entfernen: %s\n"
-#: ../common/username.c:45
+#: ../common/username.c:43
#, c-format
msgid "could not look up effective user ID %ld: %s"
msgstr "konnte effektive Benutzer-ID %ld nicht nachschlagen: %s"
-#: ../common/username.c:47 libpq/auth.c:1741
+#: ../common/username.c:45 libpq/auth.c:1907
msgid "user does not exist"
msgstr "Benutzer existiert nicht"
-#: ../common/username.c:62
+#: ../common/username.c:60
#, c-format
msgid "user name lookup failure: error code %lu"
msgstr "Fehler beim Nachschlagen des Benutzernamens: Fehlercode %lu"
-#: ../common/wait_error.c:47
+#: ../common/wait_error.c:45
#, c-format
msgid "command not executable"
msgstr "Befehl ist nicht ausführbar"
-#: ../common/wait_error.c:51
+#: ../common/wait_error.c:49
#, c-format
msgid "command not found"
msgstr "Befehl nicht gefunden"
-#: ../common/wait_error.c:56
+#: ../common/wait_error.c:54
#, c-format
msgid "child process exited with exit code %d"
msgstr "Kindprozess hat mit Code %d beendet"
-#: ../common/wait_error.c:63
+#: ../common/wait_error.c:61
#, c-format
msgid "child process was terminated by exception 0x%X"
msgstr "Kindprozess wurde durch Ausnahme 0x%X beendet"
-#: ../common/wait_error.c:73
+#: ../common/wait_error.c:71
#, c-format
msgid "child process was terminated by signal %s"
msgstr "Kindprozess wurde von Signal %s beendet"
-#: ../common/wait_error.c:77
+#: ../common/wait_error.c:75
#, c-format
msgid "child process was terminated by signal %d"
msgstr "Kindprozess wurde von Signal %d beendet"
-#: ../common/wait_error.c:82
+#: ../common/wait_error.c:80
#, c-format
msgid "child process exited with unrecognized status %d"
msgstr "Kindprozess hat mit unbekanntem Status %d beendet"
-#: ../port/chklocale.c:293
+#: ../port/chklocale.c:288
#, c-format
msgid "could not determine encoding for codeset \"%s\""
msgstr "konnte Kodierung für Codeset »%s« nicht bestimmen"
-#: ../port/chklocale.c:294 ../port/chklocale.c:423
-#: postmaster/postmaster.c:4880
-#, c-format
-msgid "Please report this to <[email protected]>."
-msgstr "Bitte berichten Sie das an <[email protected]>."
-
-#: ../port/chklocale.c:415 ../port/chklocale.c:421
+#: ../port/chklocale.c:409 ../port/chklocale.c:415
#, c-format
msgid "could not determine encoding for locale \"%s\": codeset is \"%s\""
msgstr "konnte Kodierung für Locale »%s« nicht bestimmen: Codeset ist »%s«"
@@ -321,25 +332,25 @@ msgstr "konnte Junction für »%s« nicht ermitteln: %s"
msgid "could not get junction for \"%s\": %s\n"
msgstr "konnte Junction für »%s« nicht ermitteln: %s\n"
-#: ../port/open.c:112
+#: ../port/open.c:111
#, c-format
msgid "could not open file \"%s\": %s"
msgstr "konnte Datei »%s« nicht öffnen: %s"
-#: ../port/open.c:113
+#: ../port/open.c:112
msgid "lock violation"
msgstr "Sperrverletzung"
-#: ../port/open.c:113
+#: ../port/open.c:112
msgid "sharing violation"
msgstr "Zugriffsverletzung (Sharing Violation)"
-#: ../port/open.c:114
+#: ../port/open.c:113
#, c-format
msgid "Continuing to retry for 30 seconds."
msgstr "Versuche werden für 30 Sekunden wiederholt."
-#: ../port/open.c:115
+#: ../port/open.c:114
#, c-format
msgid "You might have antivirus, backup, or similar software interfering with the database system."
msgstr "Möglicherweise stört eine Antivirus-, Datensicherungs- oder ähnliche Software das Datenbanksystem."
@@ -354,18 +365,33 @@ msgstr "konnte aktuelles Arbeitsverzeichnis nicht ermitteln: %s\n"
msgid "unrecognized error %d"
msgstr "unbekannter Fehler %d"
-#: access/brin/brin.c:813
+#: ../port/win32security.c:68
+#, c-format
+msgid "could not open process token: error code %lu\n"
+msgstr "konnte Prozess-Token nicht öffnen: Fehlercode %lu\n"
+
+#: ../port/win32security.c:89
+#, c-format
+msgid "could not get SID for Administrators group: error code %lu\n"
+msgstr "konnte SID der Administrators-Gruppe nicht ermitteln: Fehlercode %lu\n"
+
+#: ../port/win32security.c:99
+#, c-format
+msgid "could not get SID for PowerUsers group: error code %lu\n"
+msgstr "konnte SID der PowerUsers-Gruppe nicht ermitteln: Fehlercode %lu\n"
+
+#: access/brin/brin.c:820
#, c-format
msgid "\"%s\" is not a BRIN index"
msgstr "»%s« ist kein BRIN-Index"
-#: access/brin/brin.c:829
+#: access/brin/brin.c:836
#, c-format
msgid "could not open parent table of index %s"
msgstr "konnte Basistabelle von Index %s nicht öffnen"
-#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362
-#: access/brin/brin_pageops.c:828
+#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:360
+#: access/brin/brin_pageops.c:826
#, c-format
msgid "index row size %lu exceeds maximum %lu for index \"%s\""
msgstr "Größe %lu der Indexzeile überschreitet Maximum %lu für Index »%s«"
@@ -375,52 +401,52 @@ msgstr "Größe %lu der Indexzeile überschreitet Maximum %lu für Index »%s«"
msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u"
msgstr "unerwarteter Seitentyp 0x%04X in BRIN-Index »%s« Block %u"
-#: access/brin/brin_validate.c:115
+#: access/brin/brin_validate.c:116
#, c-format
msgid "brin operator family \"%s\" contains function %s with invalid support number %d"
msgstr "BRIN-Operatorfamilie »%s« enthält Funktion %s mit ungültiger Support-Nummer %d"
-#: access/brin/brin_validate.c:131
+#: access/brin/brin_validate.c:132
#, c-format
msgid "brin operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr "BRIN-Operatorfamilie »%s« enthält Funktion %s mit falscher Signatur für Support-Nummer %d"
-#: access/brin/brin_validate.c:153
+#: access/brin/brin_validate.c:154
#, c-format
msgid "brin operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr "BRIN-Operatorfamilie »%s« enthält Operator %s mit ungültiger Strategienummer %d"
-#: access/brin/brin_validate.c:182
+#: access/brin/brin_validate.c:183
#, c-format
msgid "brin operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr "BRIN-Operatorfamilie »%s« enthält ungültige ORDER-BY-Angabe für Operator %s"
-#: access/brin/brin_validate.c:195
+#: access/brin/brin_validate.c:196
#, c-format
msgid "brin operator family \"%s\" contains operator %s with wrong signature"
msgstr "BRIN-Operatorfamilie »%s« enthält Operator %s mit falscher Signatur"
-#: access/brin/brin_validate.c:233
+#: access/brin/brin_validate.c:234
#, c-format
msgid "brin operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr "in BRIN-Operatorfamilie »%s« fehlen Operatoren für Typen %s und %s"
-#: access/brin/brin_validate.c:243
+#: access/brin/brin_validate.c:244
#, c-format
msgid "brin operator family \"%s\" is missing support function(s) for types %s and %s"
msgstr "in BRIN-Operatorfamilie »%s« fehlen Support-Funktionen für Typen %s und %s"
-#: access/brin/brin_validate.c:256
+#: access/brin/brin_validate.c:257
#, c-format
msgid "brin operator class \"%s\" is missing operator(s)"
msgstr "in BRIN-Operatorklasse »%s« fehlen Operatoren"
-#: access/brin/brin_validate.c:267
+#: access/brin/brin_validate.c:268
#, c-format
msgid "brin operator class \"%s\" is missing support function %d"
msgstr "in BRIN-Operatorklasse »%s« fehlt Support-Funktion %d"
-#: access/common/heaptuple.c:708 access/common/heaptuple.c:1339
+#: access/common/heaptuple.c:708 access/common/heaptuple.c:1407
#, c-format
msgid "number of columns (%d) exceeds limit (%d)"
msgstr "Anzahl der Spalten (%d) überschreitet Maximum (%d)"
@@ -430,68 +456,68 @@ msgstr "Anzahl der Spalten (%d) überschreitet Maximum (%d)"
msgid "number of index columns (%d) exceeds limit (%d)"
msgstr "Anzahl der Indexspalten (%d) überschreitet Maximum (%d)"
-#: access/common/indextuple.c:176 access/spgist/spgutils.c:641
+#: access/common/indextuple.c:176 access/spgist/spgutils.c:647
#, c-format
msgid "index row requires %zu bytes, maximum size is %zu"
msgstr "Indexzeile benötigt %zu Bytes, Maximalgröße ist %zu"
-#: access/common/printtup.c:294 tcop/fastpath.c:182 tcop/fastpath.c:544
-#: tcop/postgres.c:1721
+#: access/common/printtup.c:290 tcop/fastpath.c:182 tcop/fastpath.c:544
+#: tcop/postgres.c:1727
#, c-format
msgid "unsupported format code: %d"
msgstr "nicht unterstützter Formatcode: %d"
-#: access/common/reloptions.c:493
+#: access/common/reloptions.c:531
#, c-format
msgid "user-defined relation parameter types limit exceeded"
msgstr "Wertebereich des Typs für benutzerdefinierte Relationsparameter überschritten"
-#: access/common/reloptions.c:775
+#: access/common/reloptions.c:812
#, c-format
msgid "RESET must not include values for parameters"
msgstr "RESET darf keinen Parameterwert enthalten"
-#: access/common/reloptions.c:808
+#: access/common/reloptions.c:845
#, c-format
msgid "unrecognized parameter namespace \"%s\""
msgstr "unbekannter Parameter-Namensraum »%s«"
-#: access/common/reloptions.c:1050 parser/parse_clause.c:281
+#: access/common/reloptions.c:1087 parser/parse_clause.c:259
#, c-format
msgid "unrecognized parameter \"%s\""
msgstr "unbekannter Parameter »%s«"
-#: access/common/reloptions.c:1080
+#: access/common/reloptions.c:1117
#, c-format
msgid "parameter \"%s\" specified more than once"
msgstr "Parameter »%s« mehrmals angegeben"
-#: access/common/reloptions.c:1096
+#: access/common/reloptions.c:1133
#, c-format
msgid "invalid value for boolean option \"%s\": %s"
msgstr "ungültiger Wert für Boole’sche Option »%s«: »%s«"
-#: access/common/reloptions.c:1108
+#: access/common/reloptions.c:1145
#, c-format
msgid "invalid value for integer option \"%s\": %s"
msgstr "ungültiger Wert für ganzzahlige Option »%s«: »%s«"
-#: access/common/reloptions.c:1114 access/common/reloptions.c:1134
+#: access/common/reloptions.c:1151 access/common/reloptions.c:1171
#, c-format
msgid "value %s out of bounds for option \"%s\""
msgstr "Wert %s ist außerhalb des gültigen Bereichs für Option »%s«"
-#: access/common/reloptions.c:1116
+#: access/common/reloptions.c:1153
#, c-format
msgid "Valid values are between \"%d\" and \"%d\"."
msgstr "Gültige Werte sind zwischen »%d« und »%d«."
-#: access/common/reloptions.c:1128
+#: access/common/reloptions.c:1165
#, c-format
msgid "invalid value for floating point option \"%s\": %s"
msgstr "ungültiger Wert für Gleitkommaoption »%s«: »%s«"
-#: access/common/reloptions.c:1136
+#: access/common/reloptions.c:1173
#, c-format
msgid "Valid values are between \"%f\" and \"%f\"."
msgstr "Gültige Werte sind zwischen »%f« und »%f«."
@@ -506,17 +532,18 @@ msgstr "Zurückgegebener Typ %1$s stimmt in Spalte %3$d nicht mit erwartetem Typ
msgid "Number of returned columns (%d) does not match expected column count (%d)."
msgstr "Anzahl der zurückgegebenen Spalten (%d) entspricht nicht der erwarteten Spaltenanzahl (%d)."
-#: access/common/tupconvert.c:241
+#: access/common/tupconvert.c:316
#, c-format
msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s."
msgstr "Attribut »%s« von Typ %s stimmt nicht mit dem entsprechenden Attribut von Typ %s überein."
-#: access/common/tupconvert.c:253
+#: access/common/tupconvert.c:328
#, c-format
msgid "Attribute \"%s\" of type %s does not exist in type %s."
msgstr "Attribut »%s« von Typ %s existiert nicht in Typ %s."
-#: access/common/tupdesc.c:635 parser/parse_relation.c:1517
+#: access/common/tupdesc.c:722 parser/parse_clause.c:791
+#: parser/parse_relation.c:1517
#, c-format
msgid "column \"%s\" cannot be declared SETOF"
msgstr "Spalte »%s« kann nicht als SETOF deklariert werden"
@@ -531,18 +558,18 @@ msgstr "Posting-Liste ist zu lang"
msgid "Reduce maintenance_work_mem."
msgstr "Reduzieren Sie maintenance_work_mem."
-#: access/gin/ginentrypage.c:109 access/gist/gist.c:1338
-#: access/nbtree/nbtinsert.c:576 access/nbtree/nbtsort.c:488
-#: access/spgist/spgdoinsert.c:1907
+#: access/gin/ginentrypage.c:110 access/gist/gist.c:1363
+#: access/nbtree/nbtinsert.c:577 access/nbtree/nbtsort.c:488
+#: access/spgist/spgdoinsert.c:1933
#, c-format
msgid "index row size %zu exceeds maximum %zu for index \"%s\""
msgstr "Größe %zu der Indexzeile überschreitet Maximum %zu für Index »%s«"
-#: access/gin/ginfast.c:991 access/transam/xlog.c:9793
-#: access/transam/xlog.c:10264 access/transam/xlogfuncs.c:293
-#: access/transam/xlogfuncs.c:320 access/transam/xlogfuncs.c:359
-#: access/transam/xlogfuncs.c:380 access/transam/xlogfuncs.c:401
-#: access/transam/xlogfuncs.c:471 access/transam/xlogfuncs.c:527
+#: access/gin/ginfast.c:991 access/transam/xlog.c:10136
+#: access/transam/xlog.c:10640 access/transam/xlogfuncs.c:292
+#: access/transam/xlogfuncs.c:319 access/transam/xlogfuncs.c:358
+#: access/transam/xlogfuncs.c:379 access/transam/xlogfuncs.c:400
+#: access/transam/xlogfuncs.c:470 access/transam/xlogfuncs.c:526
#, c-format
msgid "recovery is in progress"
msgstr "Wiederherstellung läuft"
@@ -562,86 +589,93 @@ msgstr "»%s« ist kein GIN-Index"
msgid "cannot access temporary indexes of other sessions"
msgstr "auf temporäre Indexe anderer Sitzungen kann nicht zugegriffen werden"
-#: access/gin/ginscan.c:409
+#: access/gin/ginscan.c:405
#, c-format
msgid "old GIN indexes do not support whole-index scans nor searches for nulls"
msgstr "alte GIN-Indexe unterstützen keine Scans des ganzen Index oder Suchen nach NULL-Werten"
-#: access/gin/ginscan.c:410
+#: access/gin/ginscan.c:406
#, c-format
msgid "To fix this, do REINDEX INDEX \"%s\"."
msgstr "Um das zu reparieren, führen Sie REINDEX INDEX \"%s\" aus."
-#: access/gin/ginvalidate.c:92
+#: access/gin/ginutil.c:134 executor/execQual.c:4865
+#: utils/adt/arrayfuncs.c:3803 utils/adt/arrayfuncs.c:6325
+#: utils/adt/rowtypes.c:927
+#, c-format
+msgid "could not identify a comparison function for type %s"
+msgstr "konnte keine Vergleichsfunktion für Typ %s ermitteln"
+
+#: access/gin/ginvalidate.c:93
#, c-format
msgid "gin operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr "GIN-Operatorfamilie »%s« enthält Support-Prozedur %s mit typübergreifender Registrierung"
-#: access/gin/ginvalidate.c:148
+#: access/gin/ginvalidate.c:149
#, c-format
msgid "gin operator family \"%s\" contains function %s with invalid support number %d"
msgstr "GIN-Operatorfamilie »%s« enthält Funktion %s mit ungültiger Support-Nummer %d"
-#: access/gin/ginvalidate.c:160
+#: access/gin/ginvalidate.c:161
#, c-format
msgid "gin operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr "GIN-Operatorfamilie »%s« enthält Funktion %s mit falscher Signatur für Support-Nummer %d"
-#: access/gin/ginvalidate.c:179
+#: access/gin/ginvalidate.c:180
#, c-format
msgid "gin operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr "GIN-Operatorfamilie »%s« enthält Operator %s mit ungültiger Strategienummer %d"
-#: access/gin/ginvalidate.c:192
+#: access/gin/ginvalidate.c:193
#, c-format
msgid "gin operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr "GIN-Operatorfamilie »%s« enthält ungültige ORDER-BY-Angabe für Operator %s"
-#: access/gin/ginvalidate.c:205
+#: access/gin/ginvalidate.c:206
#, c-format
msgid "gin operator family \"%s\" contains operator %s with wrong signature"
msgstr "GIN-Operatorfamilie »%s« enthält Operator %s mit falscher Signatur"
-#: access/gin/ginvalidate.c:246
+#: access/gin/ginvalidate.c:247
#, c-format
msgid "gin operator class \"%s\" is missing support function %d"
msgstr "in GIN-Operatorklasse »%s« fehlt Support-Funktion %d"
-#: access/gin/ginvalidate.c:256
+#: access/gin/ginvalidate.c:257
#, c-format
msgid "gin operator class \"%s\" is missing support function %d or %d"
msgstr "in GIN-Operatorklasse »%s« fehlt Support-Funktion %d oder %d"
-#: access/gist/gist.c:681 access/gist/gistvacuum.c:258
+#: access/gist/gist.c:706 access/gist/gistvacuum.c:258
#, c-format
msgid "index \"%s\" contains an inner tuple marked as invalid"
msgstr "Index »%s« enthält ein inneres Tupel, das als ungültig markiert ist"
-#: access/gist/gist.c:683 access/gist/gistvacuum.c:260
+#: access/gist/gist.c:708 access/gist/gistvacuum.c:260
#, c-format
msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1."
msgstr "Das kommt von einem unvollständigen Page-Split bei der Crash-Recovery vor dem Upgrade auf PostgreSQL 9.1."
-#: access/gist/gist.c:684 access/gist/gistutil.c:735
-#: access/gist/gistutil.c:746 access/gist/gistvacuum.c:261
-#: access/hash/hashutil.c:172 access/hash/hashutil.c:183
-#: access/hash/hashutil.c:195 access/hash/hashutil.c:216
-#: access/nbtree/nbtpage.c:518 access/nbtree/nbtpage.c:529
+#: access/gist/gist.c:709 access/gist/gistutil.c:739
+#: access/gist/gistutil.c:750 access/gist/gistvacuum.c:261
+#: access/hash/hashutil.c:174 access/hash/hashutil.c:185
+#: access/hash/hashutil.c:197 access/hash/hashutil.c:218
+#: access/nbtree/nbtpage.c:519 access/nbtree/nbtpage.c:530
#, c-format
msgid "Please REINDEX it."
msgstr "Bitte führen Sie REINDEX für den Index aus."
-#: access/gist/gistbuild.c:249
+#: access/gist/gistbuild.c:250
#, c-format
msgid "invalid value for \"buffering\" option"
msgstr "ungültiger Wert für Option »buffering«"
-#: access/gist/gistbuild.c:250
+#: access/gist/gistbuild.c:251
#, c-format
msgid "Valid values are \"on\", \"off\", and \"auto\"."
msgstr "Gültige Werte sind »on«, »off« und »auto«."
-#: access/gist/gistbuildbuffers.c:778 utils/sort/logtape.c:209
+#: access/gist/gistbuildbuffers.c:778 utils/sort/logtape.c:231
#, c-format
msgid "could not write block %ld of temporary file: %m"
msgstr "konnte Block %ld von temporärer Datei nicht schreiben: %m"
@@ -656,310 +690,318 @@ msgstr "Picksplit-Methode für Spalte %d von Index »%s« fehlgeschlagen"
msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command."
msgstr "Der Index ist nicht optimal. Um ihn zu optimieren, kontaktieren Sie einen Entwickler oder versuchen Sie, die Spalte als die zweite im CREATE-INDEX-Befehl zu verwenden."
-#: access/gist/gistutil.c:732 access/hash/hashutil.c:169
-#: access/nbtree/nbtpage.c:515
+#: access/gist/gistutil.c:736 access/hash/hashutil.c:171
+#: access/nbtree/nbtpage.c:516
#, c-format
msgid "index \"%s\" contains unexpected zero page at block %u"
msgstr "Index »%s« enthält unerwartete Nullseite bei Block %u"
-#: access/gist/gistutil.c:743 access/hash/hashutil.c:180
-#: access/hash/hashutil.c:192 access/nbtree/nbtpage.c:526
+#: access/gist/gistutil.c:747 access/hash/hashutil.c:182
+#: access/hash/hashutil.c:194 access/nbtree/nbtpage.c:527
#, c-format
msgid "index \"%s\" contains corrupted page at block %u"
msgstr "Index »%s« enthält korrupte Seite bei Block %u"
-#: access/gist/gistvalidate.c:92
+#: access/gist/gistvalidate.c:93
#, c-format
msgid "gist operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr "GiST-Operatorfamilie »%s« enthält Support-Prozedur %s mit typübergreifender Registrierung"
-#: access/gist/gistvalidate.c:145
+#: access/gist/gistvalidate.c:146
#, c-format
msgid "gist operator family \"%s\" contains function %s with invalid support number %d"
msgstr "GiST-Operatorfamilie »%s« enthält Funktion %s mit ungültiger Support-Nummer %d"
-#: access/gist/gistvalidate.c:157
+#: access/gist/gistvalidate.c:158
#, c-format
msgid "gist operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr "GiST-Operatorfamilie »%s« enthält Funktion %s mit falscher Signatur für Support-Nummer %d"
-#: access/gist/gistvalidate.c:177
+#: access/gist/gistvalidate.c:178
#, c-format
msgid "gist operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr "GiST-Operatorfamilie »%s« enthält Operator %s mit ungültiger Strategienummer %d"
-#: access/gist/gistvalidate.c:195
+#: access/gist/gistvalidate.c:196
#, c-format
msgid "gist operator family \"%s\" contains unsupported ORDER BY specification for operator %s"
msgstr "GiST-Operatorfamilie »%s« enthält nicht unterstützte ORDER-BY-Angabe für Operator %s"
-#: access/gist/gistvalidate.c:206
+#: access/gist/gistvalidate.c:207
#, c-format
msgid "gist operator family \"%s\" contains incorrect ORDER BY opfamily specification for operator %s"
msgstr "GiST-Operatorfamilie »%s« enthält ungültige ORDER-BY-Operatorfamilienangabe für Operator %s"
-#: access/gist/gistvalidate.c:225
+#: access/gist/gistvalidate.c:226
#, c-format
msgid "gist operator family \"%s\" contains operator %s with wrong signature"
msgstr "GiST-Operatorfamilie »%s« enthält Operator %s mit falscher Signatur"
-#: access/gist/gistvalidate.c:264
+#: access/gist/gistvalidate.c:265
#, c-format
msgid "gist operator class \"%s\" is missing support function %d"
msgstr "in GiST-Operatorklasse »%s« fehlt Support-Funktion %d"
-#: access/hash/hashinsert.c:68
+#: access/hash/hashinsert.c:74
#, c-format
msgid "index row size %zu exceeds hash maximum %zu"
msgstr "Größe der Indexzeile %zu überschreitet Maximum für Hash-Index %zu"
-#: access/hash/hashinsert.c:70 access/spgist/spgdoinsert.c:1911
-#: access/spgist/spgutils.c:702
+#: access/hash/hashinsert.c:76 access/spgist/spgdoinsert.c:1937
+#: access/spgist/spgutils.c:708
#, c-format
msgid "Values larger than a buffer page cannot be indexed."
msgstr "Werte, die größer sind als eine Pufferseite, können nicht indiziert werden."
-#: access/hash/hashovfl.c:546
+#: access/hash/hashovfl.c:84
+#, fuzzy, c-format
+#| msgid "invalid port number: \"%s\"\n"
+msgid "invalid overflow block number %u"
+msgstr "ungültige Portnummer: »%s«\n"
+
+#: access/hash/hashovfl.c:273 access/hash/hashpage.c:426
#, c-format
msgid "out of overflow pages in hash index \"%s\""
msgstr "keine Überlaufseiten in Hash-Index »%s« mehr"
-#: access/hash/hashsearch.c:153
+#: access/hash/hashsearch.c:248
#, c-format
msgid "hash indexes do not support whole-index scans"
msgstr "Hash-Indexe unterstützen keine Scans des ganzen Index"
-#: access/hash/hashutil.c:208
+#: access/hash/hashutil.c:210
#, c-format
msgid "index \"%s\" is not a hash index"
msgstr "Index »%s« ist kein Hash-Index"
-#: access/hash/hashutil.c:214
+#: access/hash/hashutil.c:216
#, c-format
msgid "index \"%s\" has wrong hash version"
msgstr "Index »%s« hat falsche Hash-Version"
-#: access/hash/hashvalidate.c:98
+#: access/hash/hashvalidate.c:99
#, c-format
msgid "hash operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr "Hash-Operatorfamilie »%s« enthält Support-Prozedur %s mit typübergreifender Registrierung"
-#: access/hash/hashvalidate.c:113
+#: access/hash/hashvalidate.c:114
#, c-format
msgid "hash operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr "Hash-Operatorfamilie »%s« enthält Funktion %s mit falscher Signatur für Support-Nummer %d"
-#: access/hash/hashvalidate.c:130
+#: access/hash/hashvalidate.c:131
#, c-format
msgid "hash operator family \"%s\" contains function %s with invalid support number %d"
msgstr "Hash-Operatorfamilie »%s« enthält Funktion %s mit ungültiger Support-Nummer %d"
-#: access/hash/hashvalidate.c:151
+#: access/hash/hashvalidate.c:152
#, c-format
msgid "hash operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr "Hash-Operatorfamilie »%s« enthält Operator %s mit ungültiger Strategienummer %d"
-#: access/hash/hashvalidate.c:164
+#: access/hash/hashvalidate.c:165
#, c-format
msgid "hash operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr "Hash-Operatorfamilie »%s« enthält ungültige ORDER-BY-Angabe für Operator %s"
-#: access/hash/hashvalidate.c:177
+#: access/hash/hashvalidate.c:178
#, c-format
msgid "hash operator family \"%s\" contains operator %s with wrong signature"
msgstr "Hash-Operatorfamilie »%s« enthält Operator %s mit falscher Signatur"
-#: access/hash/hashvalidate.c:189
+#: access/hash/hashvalidate.c:190
#, c-format
msgid "hash operator family \"%s\" lacks support function for operator %s"
msgstr "in Hash-Operatorfamilie »%s« fehlt Support-Funktion für Operator %s"
-#: access/hash/hashvalidate.c:217
+#: access/hash/hashvalidate.c:218
#, c-format
msgid "hash operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr "in Hash-Operatorfamilie »%s« fehlen Operatoren für Typen %s und %s"
-#: access/hash/hashvalidate.c:231
+#: access/hash/hashvalidate.c:232
#, c-format
msgid "hash operator class \"%s\" is missing operator(s)"
msgstr "in Hash-Operatorklasse »%s« fehlen Operatoren"
-#: access/hash/hashvalidate.c:247
+#: access/hash/hashvalidate.c:248
#, c-format
msgid "hash operator family \"%s\" is missing cross-type operator(s)"
msgstr "in Hash-Operatorfamilie »%s« fehlen typübergreifende Operatoren"
-#: access/heap/heapam.c:1295 access/heap/heapam.c:1323
-#: access/heap/heapam.c:1355 catalog/aclchk.c:1748
+#: access/heap/heapam.c:1296 access/heap/heapam.c:1324
+#: access/heap/heapam.c:1356 catalog/aclchk.c:1754
#, c-format
msgid "\"%s\" is an index"
msgstr "»%s« ist ein Index"
-#: access/heap/heapam.c:1300 access/heap/heapam.c:1328
-#: access/heap/heapam.c:1360 catalog/aclchk.c:1755 commands/tablecmds.c:8984
-#: commands/tablecmds.c:12042
+#: access/heap/heapam.c:1301 access/heap/heapam.c:1329
+#: access/heap/heapam.c:1361 catalog/aclchk.c:1761 commands/tablecmds.c:9558
+#: commands/tablecmds.c:12769
#, c-format
msgid "\"%s\" is a composite type"
msgstr "»%s« ist ein zusammengesetzter Typ"
-#: access/heap/heapam.c:2567
+#: access/heap/heapam.c:2595
#, c-format
msgid "cannot insert tuples during a parallel operation"
msgstr "während einer parallelen Operation können keine Tupel eingefügt werden"
-#: access/heap/heapam.c:3017
+#: access/heap/heapam.c:3045
#, c-format
msgid "cannot delete tuples during a parallel operation"
msgstr "während einer parallelen Operation können keine Tupel gelöscht werden"
-#: access/heap/heapam.c:3063
+#: access/heap/heapam.c:3091
#, c-format
msgid "attempted to delete invisible tuple"
msgstr "Versuch ein unsichtbares Tupel zu löschen"
-#: access/heap/heapam.c:3489 access/heap/heapam.c:6223
+#: access/heap/heapam.c:3517 access/heap/heapam.c:6268
#, c-format
msgid "cannot update tuples during a parallel operation"
msgstr "während einer parallelen Operation können keine Tupel aktualisiert werden"
-#: access/heap/heapam.c:3611
+#: access/heap/heapam.c:3639
#, c-format
msgid "attempted to update invisible tuple"
msgstr "Versuch ein unsichtbares Tupel zu aktualisieren"
-#: access/heap/heapam.c:4961 access/heap/heapam.c:4999
-#: access/heap/heapam.c:5251 executor/execMain.c:2312
+#: access/heap/heapam.c:4991 access/heap/heapam.c:5029
+#: access/heap/heapam.c:5281 executor/execMain.c:2461
#, c-format
msgid "could not obtain lock on row in relation \"%s\""
msgstr "konnte Sperre für Zeile in Relation »%s« nicht setzen"
-#: access/heap/hio.c:322 access/heap/rewriteheap.c:666
+#: access/heap/hio.c:322 access/heap/rewriteheap.c:664
#, c-format
msgid "row is too big: size %zu, maximum size %zu"
msgstr "Zeile ist zu groß: Größe ist %zu, Maximalgröße ist %zu"
-#: access/heap/rewriteheap.c:925
+#: access/heap/rewriteheap.c:923
#, c-format
msgid "could not write to file \"%s\", wrote %d of %d: %m"
msgstr "konnte nicht in Datei »%s« schreiben, %d von %d geschrieben: %m"
-#: access/heap/rewriteheap.c:965 access/heap/rewriteheap.c:1177
-#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:407
-#: access/transam/timeline.c:483 access/transam/xlog.c:3058
-#: access/transam/xlog.c:3220 replication/logical/snapbuild.c:1607
-#: replication/slot.c:1078 replication/slot.c:1163 storage/file/fd.c:624
-#: storage/file/fd.c:3052 storage/smgr/md.c:1044 storage/smgr/md.c:1277
-#: storage/smgr/md.c:1450 utils/misc/guc.c:6883
+#: access/heap/rewriteheap.c:963 access/heap/rewriteheap.c:1175
+#: access/heap/rewriteheap.c:1272 access/transam/timeline.c:406
+#: access/transam/timeline.c:482 access/transam/xlog.c:3235
+#: access/transam/xlog.c:3397 replication/logical/snapbuild.c:1604
+#: replication/slot.c:1125 replication/slot.c:1210 storage/file/fd.c:631
+#: storage/file/fd.c:3129 storage/smgr/md.c:1043 storage/smgr/md.c:1276
+#: storage/smgr/md.c:1449 utils/misc/guc.c:6951
#, c-format
msgid "could not fsync file \"%s\": %m"
msgstr "konnte Datei »%s« nicht fsyncen: %m"
-#: access/heap/rewriteheap.c:1020 access/heap/rewriteheap.c:1140
-#: access/transam/timeline.c:315 access/transam/timeline.c:461
-#: access/transam/xlog.c:3014 access/transam/xlog.c:3163
-#: access/transam/xlog.c:10122 access/transam/xlog.c:10160
-#: access/transam/xlog.c:10487 postmaster/postmaster.c:4355
-#: replication/logical/origin.c:542 replication/slot.c:1035
-#: storage/file/copydir.c:162 storage/smgr/md.c:331 utils/time/snapmgr.c:1223
+#: access/heap/rewriteheap.c:1018 access/heap/rewriteheap.c:1138
+#: access/transam/timeline.c:314 access/transam/timeline.c:460
+#: access/transam/xlog.c:3191 access/transam/xlog.c:3340
+#: access/transam/xlog.c:10470 access/transam/xlog.c:10508
+#: access/transam/xlog.c:10881 postmaster/postmaster.c:4410
+#: replication/logical/origin.c:535 replication/slot.c:1082
+#: storage/file/copydir.c:162 storage/smgr/md.c:326 utils/time/snapmgr.c:1275
#, c-format
msgid "could not create file \"%s\": %m"
msgstr "konnte Datei »%s« nicht erstellen: %m"
-#: access/heap/rewriteheap.c:1149
+#: access/heap/rewriteheap.c:1147
#, c-format
msgid "could not truncate file \"%s\" to %u: %m"
msgstr "konnte Datei »%s« nicht auf %u kürzen: %m"
-#: access/heap/rewriteheap.c:1156 replication/walsender.c:481
-#: storage/smgr/md.c:1902
+#: access/heap/rewriteheap.c:1154 replication/walsender.c:451
+#: storage/smgr/md.c:1948
#, c-format
msgid "could not seek to end of file \"%s\": %m"
msgstr "konnte Positionszeiger nicht ans Ende der Datei »%s« setzen: %m"
-#: access/heap/rewriteheap.c:1167 access/transam/timeline.c:367
-#: access/transam/timeline.c:401 access/transam/timeline.c:477
-#: access/transam/xlog.c:3049 access/transam/xlog.c:3213
-#: postmaster/postmaster.c:4365 postmaster/postmaster.c:4375
-#: replication/logical/origin.c:551 replication/logical/origin.c:587
-#: replication/logical/origin.c:603 replication/logical/snapbuild.c:1591
-#: replication/slot.c:1064 storage/file/copydir.c:187
+#: access/heap/rewriteheap.c:1165 access/transam/timeline.c:366
+#: access/transam/timeline.c:400 access/transam/timeline.c:476
+#: access/transam/xlog.c:3226 access/transam/xlog.c:3390
+#: postmaster/postmaster.c:4420 postmaster/postmaster.c:4430
+#: replication/logical/origin.c:544 replication/logical/origin.c:580
+#: replication/logical/origin.c:596 replication/logical/snapbuild.c:1588
+#: replication/slot.c:1111 storage/file/copydir.c:187
#: utils/init/miscinit.c:1228 utils/init/miscinit.c:1237
-#: utils/init/miscinit.c:1244 utils/misc/guc.c:6844 utils/misc/guc.c:6875
-#: utils/misc/guc.c:8717 utils/misc/guc.c:8731 utils/time/snapmgr.c:1228
-#: utils/time/snapmgr.c:1235
+#: utils/init/miscinit.c:1244 utils/misc/guc.c:6912 utils/misc/guc.c:6943
+#: utils/misc/guc.c:8792 utils/misc/guc.c:8806 utils/time/snapmgr.c:1280
+#: utils/time/snapmgr.c:1287
#, c-format
msgid "could not write to file \"%s\": %m"
msgstr "konnte nicht in Datei »%s« schreiben: %m"
-#: access/heap/rewriteheap.c:1250 access/transam/xlog.c:10354
-#: access/transam/xlogarchive.c:114 access/transam/xlogarchive.c:468
-#: replication/logical/origin.c:529 replication/logical/reorderbuffer.c:2625
-#: replication/logical/reorderbuffer.c:2682
-#: replication/logical/snapbuild.c:1535 replication/logical/snapbuild.c:1910
-#: replication/slot.c:1137 storage/ipc/dsm.c:326 storage/smgr/md.c:431
-#: storage/smgr/md.c:480 storage/smgr/md.c:1397
+#: access/heap/rewriteheap.c:1248 access/transam/xlog.c:10719
+#: access/transam/xlogarchive.c:113 access/transam/xlogarchive.c:467
+#: postmaster/postmaster.c:1239 postmaster/syslogger.c:1371
+#: replication/logical/origin.c:522 replication/logical/reorderbuffer.c:2588
+#: replication/logical/reorderbuffer.c:2645
+#: replication/logical/snapbuild.c:1532 replication/logical/snapbuild.c:1907
+#: replication/slot.c:1184 storage/ipc/dsm.c:327 storage/smgr/md.c:425
+#: storage/smgr/md.c:474 storage/smgr/md.c:1396
#, c-format
msgid "could not remove file \"%s\": %m"
msgstr "konnte Datei »%s« nicht löschen: %m"
-#: access/heap/rewriteheap.c:1264 access/transam/timeline.c:111
-#: access/transam/timeline.c:236 access/transam/timeline.c:334
-#: access/transam/xlog.c:2990 access/transam/xlog.c:3107
-#: access/transam/xlog.c:3148 access/transam/xlog.c:3421
-#: access/transam/xlog.c:3499 access/transam/xlogutils.c:701
-#: replication/basebackup.c:401 replication/basebackup.c:1162
-#: replication/logical/origin.c:658 replication/logical/reorderbuffer.c:2155
-#: replication/logical/reorderbuffer.c:2395
-#: replication/logical/reorderbuffer.c:3073
-#: replication/logical/snapbuild.c:1584 replication/logical/snapbuild.c:1668
-#: replication/slot.c:1152 replication/walsender.c:474
-#: replication/walsender.c:2104 storage/file/copydir.c:155
-#: storage/file/fd.c:607 storage/file/fd.c:2964 storage/file/fd.c:3031
-#: storage/smgr/md.c:613 utils/error/elog.c:1870 utils/init/miscinit.c:1163
-#: utils/init/miscinit.c:1284 utils/init/miscinit.c:1362 utils/misc/guc.c:7103
-#: utils/misc/guc.c:7136
+#: access/heap/rewriteheap.c:1262 access/transam/timeline.c:110
+#: access/transam/timeline.c:235 access/transam/timeline.c:333
+#: access/transam/xlog.c:3167 access/transam/xlog.c:3284
+#: access/transam/xlog.c:3325 access/transam/xlog.c:3598
+#: access/transam/xlog.c:3676 access/transam/xlogutils.c:702
+#: postmaster/syslogger.c:1380 replication/basebackup.c:474
+#: replication/basebackup.c:1218 replication/logical/origin.c:651
+#: replication/logical/reorderbuffer.c:2112
+#: replication/logical/reorderbuffer.c:2358
+#: replication/logical/reorderbuffer.c:3037
+#: replication/logical/snapbuild.c:1581 replication/logical/snapbuild.c:1665
+#: replication/slot.c:1199 replication/walsender.c:444
+#: replication/walsender.c:2055 storage/file/copydir.c:155
+#: storage/file/fd.c:614 storage/file/fd.c:3041 storage/file/fd.c:3108
+#: storage/smgr/md.c:607 utils/error/elog.c:1879 utils/init/miscinit.c:1163
+#: utils/init/miscinit.c:1284 utils/init/miscinit.c:1359 utils/misc/guc.c:7171
+#: utils/misc/guc.c:7204
#, c-format
msgid "could not open file \"%s\": %m"
msgstr "konnte Datei »%s« nicht öffnen: %m"
-#: access/index/amapi.c:69 commands/amcmds.c:164
+#: access/index/amapi.c:83 commands/amcmds.c:163
#, c-format
msgid "access method \"%s\" is not of type %s"
msgstr "Zugriffsmethode »%s« ist nicht vom Typ %s"
-#: access/index/amapi.c:78
+#: access/index/amapi.c:99
#, c-format
msgid "index access method \"%s\" does not have a handler"
msgstr "Indexzugriffsmethode »%s« hat keinen Handler"
-#: access/index/indexam.c:155 catalog/objectaddress.c:1196
-#: commands/indexcmds.c:1799 commands/tablecmds.c:241
-#: commands/tablecmds.c:12033
+#: access/index/indexam.c:160 catalog/objectaddress.c:1200
+#: commands/indexcmds.c:1811 commands/tablecmds.c:247
+#: commands/tablecmds.c:12760
#, c-format
msgid "\"%s\" is not an index"
msgstr "»%s« ist kein Index"
-#: access/nbtree/nbtinsert.c:428
+#: access/nbtree/nbtinsert.c:429
#, c-format
msgid "duplicate key value violates unique constraint \"%s\""
msgstr "doppelter Schlüsselwert verletzt Unique-Constraint »%s«"
-#: access/nbtree/nbtinsert.c:430
+#: access/nbtree/nbtinsert.c:431
#, c-format
msgid "Key %s already exists."
msgstr "Schlüssel »%s« existiert bereits."
-#: access/nbtree/nbtinsert.c:497
+#: access/nbtree/nbtinsert.c:498
#, c-format
msgid "failed to re-find tuple within index \"%s\""
msgstr "konnte Tupel mit Index »%s« nicht erneut finden"
-#: access/nbtree/nbtinsert.c:499
+#: access/nbtree/nbtinsert.c:500
#, c-format
msgid "This may be because of a non-immutable index expression."
msgstr "Das kann daran liegen, dass der Indexausdruck nicht »immutable« ist."
-#: access/nbtree/nbtinsert.c:579 access/nbtree/nbtsort.c:491
+#: access/nbtree/nbtinsert.c:580 access/nbtree/nbtsort.c:491
#, c-format
msgid ""
"Values larger than 1/3 of a buffer page cannot be indexed.\n"
@@ -968,119 +1010,119 @@ msgstr ""
"Werte, die größer sind als 1/3 einer Pufferseite, können nicht indiziert werden.\n"
"Erstellen Sie eventuell einen Funktionsindex auf einen MD5-Hash oder verwenden Sie Volltextindizierung."
-#: access/nbtree/nbtpage.c:168 access/nbtree/nbtpage.c:371
-#: access/nbtree/nbtpage.c:458 parser/parse_utilcmd.c:1717
+#: access/nbtree/nbtpage.c:169 access/nbtree/nbtpage.c:372
+#: access/nbtree/nbtpage.c:459 parser/parse_utilcmd.c:1770
#, c-format
msgid "index \"%s\" is not a btree"
msgstr "Index »%s« ist kein B-Tree"
-#: access/nbtree/nbtpage.c:174 access/nbtree/nbtpage.c:377
-#: access/nbtree/nbtpage.c:464
+#: access/nbtree/nbtpage.c:175 access/nbtree/nbtpage.c:378
+#: access/nbtree/nbtpage.c:465
#, c-format
msgid "version mismatch in index \"%s\": file version %d, code version %d"
msgstr "keine Versionsübereinstimmung in Index »%s«: Dateiversion %d, Code-Version %d"
-#: access/nbtree/nbtpage.c:1152
+#: access/nbtree/nbtpage.c:1153
#, c-format
msgid "index \"%s\" contains a half-dead internal page"
msgstr "Index »%s« enthält eine halbtote interne Seite"
-#: access/nbtree/nbtpage.c:1154
+#: access/nbtree/nbtpage.c:1155
#, c-format
msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it."
msgstr "Die Ursache kann ein unterbrochenes VACUUM in Version 9.3 oder älter vor dem Upgrade sein. Bitte REINDEX durchführen."
-#: access/nbtree/nbtvalidate.c:100
+#: access/nbtree/nbtvalidate.c:101
#, c-format
msgid "btree operator family \"%s\" contains function %s with invalid support number %d"
msgstr "B-Tree-Operatorfamilie »%s« enthält Funktion %s mit ungültiger Support-Nummer %d"
-#: access/nbtree/nbtvalidate.c:112
+#: access/nbtree/nbtvalidate.c:113
#, c-format
msgid "btree operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr "B-Tree-Operatorfamilie »%s« enthält Funktion %s mit falscher Signatur für Support-Nummer %d"
-#: access/nbtree/nbtvalidate.c:132
+#: access/nbtree/nbtvalidate.c:133
#, c-format
msgid "btree operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr "B-Tree-Operatorfamilie »%s« enthält Operator %s mit ungültiger Strategienummer %d"
-#: access/nbtree/nbtvalidate.c:145
+#: access/nbtree/nbtvalidate.c:146
#, c-format
msgid "btree operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr "B-Tree-Operatorfamilie »%s« enthält ungültige ORDER-BY-Angabe für Operator %s"
-#: access/nbtree/nbtvalidate.c:158
+#: access/nbtree/nbtvalidate.c:159
#, c-format
msgid "btree operator family \"%s\" contains operator %s with wrong signature"
msgstr "B-Tree-Operatorfamilie »%s« enthält Operator %s mit falscher Signatur"
-#: access/nbtree/nbtvalidate.c:200
+#: access/nbtree/nbtvalidate.c:201
#, c-format
msgid "btree operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr "in B-Tree-Operatorfamilie »%s« fehlen Operatoren für Typen %s und %s"
-#: access/nbtree/nbtvalidate.c:210
+#: access/nbtree/nbtvalidate.c:211
#, c-format
msgid "btree operator family \"%s\" is missing support function for types %s and %s"
msgstr "in B-Tree-Operatorfamilie »%s« fehlen Support-Funktionen für Typen %s und %s"
-#: access/nbtree/nbtvalidate.c:224
+#: access/nbtree/nbtvalidate.c:225
#, c-format
msgid "btree operator class \"%s\" is missing operator(s)"
msgstr "in B-Tree-Operatorklasse »%s« fehlen Operatoren"
-#: access/nbtree/nbtvalidate.c:241
+#: access/nbtree/nbtvalidate.c:242
#, c-format
msgid "btree operator family \"%s\" is missing cross-type operator(s)"
msgstr "in B-Tree-Operatorfamilie »%s« fehlen typübergreifende Operatoren"
-#: access/spgist/spgutils.c:699
+#: access/spgist/spgutils.c:705
#, c-format
msgid "SP-GiST inner tuple size %zu exceeds maximum %zu"
msgstr "innere Tupelgröße %zu überschreitet SP-GiST-Maximum %zu"
-#: access/spgist/spgvalidate.c:92
+#: access/spgist/spgvalidate.c:93
#, c-format
msgid "spgist operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr "SPGiST-Operatorfamilie »%s« enthält Support-Prozedur %s mit typübergreifender Registrierung"
-#: access/spgist/spgvalidate.c:115
+#: access/spgist/spgvalidate.c:116
#, c-format
msgid "spgist operator family \"%s\" contains function %s with invalid support number %d"
msgstr "SPGiST-Operatorfamilie »%s« enthält Funktion %s mit ungültiger Support-Nummer %d"
-#: access/spgist/spgvalidate.c:127
+#: access/spgist/spgvalidate.c:128
#, c-format
msgid "spgist operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr "SPGiST-Operatorfamilie »%s« enthält Funktion %s mit falscher Signatur für Support-Nummer %d"
-#: access/spgist/spgvalidate.c:146
+#: access/spgist/spgvalidate.c:147
#, c-format
msgid "spgist operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr "SPGiST-Operatorfamilie »%s« enthält Operator %s mit ungültiger Strategienummer %d"
-#: access/spgist/spgvalidate.c:159
+#: access/spgist/spgvalidate.c:160
#, c-format
msgid "spgist operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr "SPGiST-Operatorfamilie »%s« enthält ungültige ORDER-BY-Angabe für Operator %s"
-#: access/spgist/spgvalidate.c:172
+#: access/spgist/spgvalidate.c:173
#, c-format
msgid "spgist operator family \"%s\" contains operator %s with wrong signature"
msgstr "SPGiST-Operatorfamilie »%s« enthält Operator %s mit falscher Signatur"
-#: access/spgist/spgvalidate.c:200
+#: access/spgist/spgvalidate.c:201
#, c-format
msgid "spgist operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr "in SPGiST-Operatorfamilie »%s« fehlen Operatoren für Typen %s und %s"
-#: access/spgist/spgvalidate.c:220
+#: access/spgist/spgvalidate.c:221
#, c-format
msgid "spgist operator family \"%s\" is missing support function %d for type %s"
msgstr "in SPGiST-Operatorfamilie »%s« fehlt Support-Funktion %d für Typ %s"
-#: access/spgist/spgvalidate.c:233
+#: access/spgist/spgvalidate.c:234
#, c-format
msgid "spgist operator class \"%s\" is missing operator(s)"
msgstr "in SPGiST-Operatorklasse »%s« fehlen Operatoren"
@@ -1095,17 +1137,17 @@ msgstr "Stichprobenprozentsatz muss zwischen 0 und 100 sein"
msgid "cannot retrieve commit timestamp for transaction %u"
msgstr "Commit-Timestamp von Transaktion %u kann nicht abgefragt werden"
-#: access/transam/commit_ts.c:385
+#: access/transam/commit_ts.c:393
#, c-format
msgid "could not get commit timestamp data"
msgstr "konnte Commit-Timestamp-Daten nicht auslesen"
-#: access/transam/commit_ts.c:387
+#: access/transam/commit_ts.c:395
#, c-format
msgid "Make sure the configuration parameter \"%s\" is set on the master server."
msgstr "Stellen Sie sicher, dass der Konfigurationsparameter »%s« auf dem Masterserver gesetzt ist."
-#: access/transam/commit_ts.c:389 libpq/hba.c:1441
+#: access/transam/commit_ts.c:397
#, c-format
msgid "Make sure the configuration parameter \"%s\" is set."
msgstr "Stellen Sie sicher, dass der Konfigurationsparameter »%s« gesetzt ist."
@@ -1130,14 +1172,14 @@ msgstr ""
msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u"
msgstr "Datenbank nimmt keine Befehle an, die neue MultiXactIds erzeugen, um Datenverlust wegen Transaktionsnummernüberlauf in Datenbank mit OID %u zu vermeiden"
-#: access/transam/multixact.c:1028 access/transam/multixact.c:2316
+#: access/transam/multixact.c:1028 access/transam/multixact.c:2314
#, c-format
msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used"
msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used"
msgstr[0] "Datenbank »%s« muss gevacuumt werden, bevor %u weitere MultiXactId aufgebraucht ist"
msgstr[1] "Datenbank »%s« muss gevacuumt werden, bevor %u weitere MultiXactIds aufgebraucht sind"
-#: access/transam/multixact.c:1037 access/transam/multixact.c:2325
+#: access/transam/multixact.c:1037 access/transam/multixact.c:2323
#, c-format
msgid "database with OID %u must be vacuumed before %u more MultiXactId is used"
msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used"
@@ -1183,12 +1225,12 @@ msgstr "MultiXactId %u existiert nicht mehr -- anscheinender Überlauf"
msgid "MultiXactId %u has not been created yet -- apparent wraparound"
msgstr "MultiXactId %u wurde noch nicht erzeugt -- anscheinender Überlauf"
-#: access/transam/multixact.c:2266
+#: access/transam/multixact.c:2264
#, c-format
msgid "MultiXactId wrap limit is %u, limited by database with OID %u"
msgstr "Grenze für MultiXactId-Überlauf ist %u, begrenzt durch Datenbank mit OID %u"
-#: access/transam/multixact.c:2321 access/transam/multixact.c:2330
+#: access/transam/multixact.c:2319 access/transam/multixact.c:2328
#: access/transam/varsup.c:146 access/transam/varsup.c:153
#: access/transam/varsup.c:384 access/transam/varsup.c:391
#, c-format
@@ -1199,192 +1241,191 @@ msgstr ""
"Um ein Abschalten der Datenbank zu vermeiden, führen Sie ein komplettes VACUUM über diese Datenbank aus.\n"
"Eventuell müssen Sie auch alte vorbereitete Transaktionen committen oder zurückrollen."
-#: access/transam/multixact.c:2600
+#: access/transam/multixact.c:2598
#, c-format
msgid "oldest MultiXactId member is at offset %u"
msgstr "ältestes MultiXactId-Mitglied ist bei Offset %u"
-#: access/transam/multixact.c:2604
+#: access/transam/multixact.c:2602
#, c-format
msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk"
msgstr "MultiXact-Member-Wraparound-Schutz ist deaktiviert, weil die älteste gecheckpointete MultiXact %u nicht auf der Festplatte existiert"
-#: access/transam/multixact.c:2626
+#: access/transam/multixact.c:2624
#, c-format
msgid "MultiXact member wraparound protections are now enabled"
msgstr "MultiXact-Member-Wraparound-Schutz ist jetzt aktiviert"
-#: access/transam/multixact.c:2628
+#: access/transam/multixact.c:2626
#, c-format
msgid "MultiXact member stop limit is now %u based on MultiXact %u"
msgstr "MultiXact-Member-Stopp-Limit ist jetzt %u, basierend auf MultiXact %u"
-#: access/transam/multixact.c:3008
+#: access/transam/multixact.c:3006
#, c-format
msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation"
msgstr "älteste MultiXact %u nicht gefunden, älteste ist MultiXact %u, Truncate wird ausgelassen"
-#: access/transam/multixact.c:3026
+#: access/transam/multixact.c:3024
#, c-format
msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation"
msgstr "kann nicht bis MultiXact %u trunkieren, weil sie nicht auf der Festplatte existiert, Trunkierung wird ausgelassen"
-#: access/transam/multixact.c:3352
+#: access/transam/multixact.c:3350
#, c-format
msgid "invalid MultiXactId: %u"
msgstr "ungültige MultiXactId: %u"
-#: access/transam/parallel.c:590
+#: access/transam/parallel.c:592
#, c-format
msgid "postmaster exited during a parallel transaction"
msgstr "Postmaster beendete während einer parallelen Transaktion"
-#: access/transam/parallel.c:757
+#: access/transam/parallel.c:777
#, c-format
msgid "lost connection to parallel worker"
msgstr "Verbindung mit parallelem Arbeitsprozess verloren"
-#: access/transam/parallel.c:941
+#: access/transam/parallel.c:836 access/transam/parallel.c:838
+msgid "parallel worker"
+msgstr "paralleler Arbeitsprozess"
+
+#: access/transam/parallel.c:977
#, c-format
msgid "could not map dynamic shared memory segment"
msgstr "konnte dynamisches Shared-Memory-Segment nicht mappen"
-#: access/transam/parallel.c:946
+#: access/transam/parallel.c:982
#, c-format
msgid "invalid magic number in dynamic shared memory segment"
msgstr "ungültige magische Zahl in dynamischem Shared-Memory-Segment"
-#: access/transam/parallel.c:1124
-#, c-format
-msgid "parallel worker"
-msgstr "paralleler Arbeitsprozess"
-
-#: access/transam/slru.c:665
+#: access/transam/slru.c:663
#, c-format
msgid "file \"%s\" doesn't exist, reading as zeroes"
msgstr "Datei »%s« existiert nicht, wird als Nullen eingelesen"
-#: access/transam/slru.c:895 access/transam/slru.c:901
-#: access/transam/slru.c:908 access/transam/slru.c:915
-#: access/transam/slru.c:922 access/transam/slru.c:929
+#: access/transam/slru.c:893 access/transam/slru.c:899
+#: access/transam/slru.c:906 access/transam/slru.c:913
+#: access/transam/slru.c:920 access/transam/slru.c:927
#, c-format
msgid "could not access status of transaction %u"
msgstr "konnte auf den Status von Transaktion %u nicht zugreifen"
-#: access/transam/slru.c:896
+#: access/transam/slru.c:894
#, c-format
msgid "Could not open file \"%s\": %m."
msgstr "Konnte Datei »%s« nicht öffnen: %m."
-#: access/transam/slru.c:902
+#: access/transam/slru.c:900
#, c-format
msgid "Could not seek in file \"%s\" to offset %u: %m."
msgstr "Konnte Positionszeiger in Datei »%s« nicht auf %u setzen: %m."
-#: access/transam/slru.c:909
+#: access/transam/slru.c:907
#, c-format
msgid "Could not read from file \"%s\" at offset %u: %m."
msgstr "Konnte nicht aus Datei »%s« bei Position %u lesen: %m."
-#: access/transam/slru.c:916
+#: access/transam/slru.c:914
#, c-format
msgid "Could not write to file \"%s\" at offset %u: %m."
msgstr "Konnte nicht in Datei »%s« bei Position %u schreiben: %m."
-#: access/transam/slru.c:923
+#: access/transam/slru.c:921
#, c-format
msgid "Could not fsync file \"%s\": %m."
msgstr "Konnte Datei »%s« nicht fsyncen: %m."
-#: access/transam/slru.c:930
+#: access/transam/slru.c:928
#, c-format
msgid "Could not close file \"%s\": %m."
msgstr "Konnte Datei »%s« nicht schließen: %m."
-#: access/transam/slru.c:1185
+#: access/transam/slru.c:1183
#, c-format
msgid "could not truncate directory \"%s\": apparent wraparound"
msgstr "konnte Verzeichnis »%s« nicht leeren: anscheinender Überlauf"
-#: access/transam/slru.c:1240 access/transam/slru.c:1296
+#: access/transam/slru.c:1238 access/transam/slru.c:1294
#, c-format
msgid "removing file \"%s\""
msgstr "entferne Datei »%s«"
-#: access/transam/timeline.c:148 access/transam/timeline.c:153
+#: access/transam/timeline.c:147 access/transam/timeline.c:152
#, c-format
msgid "syntax error in history file: %s"
msgstr "Syntaxfehler in History-Datei: %s"
-#: access/transam/timeline.c:149
+#: access/transam/timeline.c:148
#, c-format
msgid "Expected a numeric timeline ID."
msgstr "Eine numerische Zeitleisten-ID wurde erwartet."
-#: access/transam/timeline.c:154
+#: access/transam/timeline.c:153
#, c-format
msgid "Expected a transaction log switchpoint location."
msgstr "Eine Transaktionslog-Switchpoint-Position wurde erwartet."
-#: access/transam/timeline.c:158
+#: access/transam/timeline.c:157
#, c-format
msgid "invalid data in history file: %s"
msgstr "ungültige Daten in History-Datei: %s"
-#: access/transam/timeline.c:159
+#: access/transam/timeline.c:158
#, c-format
msgid "Timeline IDs must be in increasing sequence."
msgstr "Zeitleisten-IDs müssen in aufsteigender Folge sein."
-#: access/transam/timeline.c:179
+#: access/transam/timeline.c:178
#, c-format
msgid "invalid data in history file \"%s\""
msgstr "ungültige Daten in History-Datei »%s«"
-#: access/transam/timeline.c:180
+#: access/transam/timeline.c:179
#, c-format
msgid "Timeline IDs must be less than child timeline's ID."
msgstr "Zeitleisten-IDs müssen kleiner als die Zeitleisten-ID des Kindes sein."
-#: access/transam/timeline.c:412 access/transam/timeline.c:488
-#: access/transam/xlog.c:3064 access/transam/xlog.c:3225
-#: access/transam/xlogfuncs.c:690 commands/copy.c:1671
+#: access/transam/timeline.c:411 access/transam/timeline.c:487
+#: access/transam/xlog.c:3241 access/transam/xlog.c:3402
+#: access/transam/xlogfuncs.c:689 commands/copy.c:1743
#: storage/file/copydir.c:201
#, c-format
msgid "could not close file \"%s\": %m"
msgstr "konnte Datei »%s« nicht schließen: %m"
-#: access/transam/timeline.c:570
+#: access/transam/timeline.c:569
#, c-format
msgid "requested timeline %u is not in this server's history"
msgstr "angeforderte Zeitleiste %u ist nicht in der History dieses Servers"
-#: access/transam/twophase.c:363
+#: access/transam/twophase.c:362
#, c-format
msgid "transaction identifier \"%s\" is too long"
msgstr "Transaktionsbezeichner »%s« ist zu lang"
-#: access/transam/twophase.c:370
+#: access/transam/twophase.c:369
#, c-format
msgid "prepared transactions are disabled"
msgstr "vorbereitete Transaktionen sind abgeschaltet"
-#: access/transam/twophase.c:371
+#: access/transam/twophase.c:370
#, c-format
msgid "Set max_prepared_transactions to a nonzero value."
msgstr "Setzen Sie max_prepared_transactions auf einen Wert höher als null."
-#: access/transam/twophase.c:390
+#: access/transam/twophase.c:389
#, c-format
msgid "transaction identifier \"%s\" is already in use"
msgstr "Transaktionsbezeichner »%s« wird bereits verwendet"
-#: access/transam/twophase.c:399
+#: access/transam/twophase.c:398
#, c-format
msgid "maximum number of prepared transactions reached"
msgstr "maximale Anzahl vorbereiteter Transaktionen erreicht"
-#: access/transam/twophase.c:400
+#: access/transam/twophase.c:399
#, c-format
msgid "Increase max_prepared_transactions (currently %d)."
msgstr "Erhöhen Sie max_prepared_transactions (aktuell %d)."
@@ -1439,20 +1480,20 @@ msgstr "konnte »stat« für Zweiphasen-Statusdatei »%s« nicht ausführen: %m"
msgid "could not read two-phase state file \"%s\": %m"
msgstr "konnte Zweiphasen-Statusdatei »%s« nicht lesen: %m"
-#: access/transam/twophase.c:1262 access/transam/xlog.c:6068
+#: access/transam/twophase.c:1262 access/transam/xlog.c:6318
#, c-format
-msgid "Failed while allocating an XLog reading processor."
-msgstr "Fehlgeschlagen beim Anlegen eines XLog-Leseprozessors."
+msgid "Failed while allocating a WAL reading processor."
+msgstr "Fehlgeschlagen beim Anlegen eines WAL-Leseprozessors."
#: access/transam/twophase.c:1268
#, c-format
-msgid "could not read two-phase state from xlog at %X/%X"
-msgstr "konnte Zweiphasen-Status nicht aus dem Xlog bei %X/%X lesen"
+msgid "could not read two-phase state from WAL at %X/%X"
+msgstr "konnte Zweiphasen-Status nicht aus dem WAL bei %X/%X lesen"
#: access/transam/twophase.c:1276
#, c-format
-msgid "expected two-phase state data is not present in xlog at %X/%X"
-msgstr "erwartete Zweiphasen-Status-Daten sind nicht im Xlog bei %X/%X vorhanden"
+msgid "expected two-phase state data is not present in WAL at %X/%X"
+msgstr "erwartete Zweiphasen-Status-Daten sind nicht im WAL bei %X/%X vorhanden"
#: access/transam/twophase.c:1511
#, c-format
@@ -1480,8 +1521,10 @@ msgid "could not close two-phase state file: %m"
msgstr "konnte Zweiphasen-Statusdatei nicht schließen: %m"
#: access/transam/twophase.c:1648
-#, c-format
-msgid "%u two-phase state file was written for long-running prepared transactions"
+#, fuzzy, c-format
+#| msgid "%u two-phase state file was written for long-running prepared transactions"
+#| msgid_plural "%u two-phase state files were written for long-running prepared transactions"
+msgid "%u two-phase state file was written for a long-running prepared transaction"
msgid_plural "%u two-phase state files were written for long-running prepared transactions"
msgstr[0] "%u Zweiphasen-Statusdatei wurde für lange laufende vorbereitete Transaktionen geschrieben"
msgstr[1] "%u Zweiphasen-Statusdateien wurden für lange laufende vorbereitete Transaktionen geschrieben"
@@ -1492,18 +1535,18 @@ msgid "removing future two-phase state file \"%s\""
msgstr "entferne Zweiphasen-Statusdatei aus der Zukunft »%s«"
#: access/transam/twophase.c:1728 access/transam/twophase.c:1739
-#: access/transam/twophase.c:1858 access/transam/twophase.c:1869
-#: access/transam/twophase.c:1943
+#: access/transam/twophase.c:1859 access/transam/twophase.c:1870
+#: access/transam/twophase.c:1947
#, c-format
msgid "removing corrupt two-phase state file \"%s\""
msgstr "entferne verfälschte Zweiphasen-Statusdatei »%s«"
-#: access/transam/twophase.c:1847 access/transam/twophase.c:1932
+#: access/transam/twophase.c:1848 access/transam/twophase.c:1936
#, c-format
msgid "removing stale two-phase state file \"%s\""
msgstr "entferne abgelaufene Zweiphasen-Statusdatei »%s«"
-#: access/transam/twophase.c:1950
+#: access/transam/twophase.c:1954
#, c-format
msgid "recovering prepared transaction %u"
msgstr "Wiederherstellung der vorbereiteten Transaktion %u"
@@ -1542,1144 +1585,1164 @@ msgstr "Datenbank mit OID %u muss innerhalb von %u Transaktionen gevacuumt werde
msgid "transaction ID wrap limit is %u, limited by database with OID %u"
msgstr "Grenze für Transaktionsnummernüberlauf ist %u, begrenzt durch Datenbank mit OID %u"
-#: access/transam/xact.c:943
+#: access/transam/xact.c:945
#, c-format
msgid "cannot have more than 2^32-2 commands in a transaction"
msgstr "kann nicht mehr als 2^32-2 Befehle in einer Transaktion ausführen"
-#: access/transam/xact.c:1471
+#: access/transam/xact.c:1469
#, c-format
msgid "maximum number of committed subtransactions (%d) exceeded"
msgstr "maximale Anzahl committeter Subtransaktionen (%d) überschritten"
-#: access/transam/xact.c:2267
+#: access/transam/xact.c:2266
#, c-format
msgid "cannot PREPARE a transaction that has operated on temporary tables"
msgstr "PREPARE kann nicht für eine Transaktion ausgeführt werden, die temporäre Tabellen bearbeitet hat"
-#: access/transam/xact.c:2277
+#: access/transam/xact.c:2276
#, c-format
msgid "cannot PREPARE a transaction that has exported snapshots"
msgstr "PREPARE kann nicht für eine Transaktion ausgeführt werden, die Snapshots exportiert hat"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3159
+#: access/transam/xact.c:3161
#, c-format
msgid "%s cannot run inside a transaction block"
msgstr "%s kann nicht in einem Transaktionsblock laufen"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3169
+#: access/transam/xact.c:3171
#, c-format
msgid "%s cannot run inside a subtransaction"
msgstr "%s kann nicht in einer Subtransaktion laufen"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3179
+#: access/transam/xact.c:3181
#, c-format
msgid "%s cannot be executed from a function or multi-command string"
msgstr "%s kann nicht aus einer Funktion oder einer mehrbefehligen Zeichenkette heraus ausgeführt werden"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3250
+#: access/transam/xact.c:3252
#, c-format
msgid "%s can only be used in transaction blocks"
msgstr "%s kann nur in Transaktionsblöcken verwendet werden"
-#: access/transam/xact.c:3434
+#: access/transam/xact.c:3436
#, c-format
msgid "there is already a transaction in progress"
msgstr "eine Transaktion ist bereits begonnen"
-#: access/transam/xact.c:3602 access/transam/xact.c:3705
+#: access/transam/xact.c:3604 access/transam/xact.c:3707
#, c-format
msgid "there is no transaction in progress"
msgstr "keine Transaktion offen"
-#: access/transam/xact.c:3613
+#: access/transam/xact.c:3615
#, c-format
msgid "cannot commit during a parallel operation"
msgstr "während einer parallelen Operation kann nicht committet werden"
-#: access/transam/xact.c:3716
+#: access/transam/xact.c:3718
#, c-format
msgid "cannot abort during a parallel operation"
msgstr "während einer parallelen Operation kann nicht abgebrochen werden"
-#: access/transam/xact.c:3758
+#: access/transam/xact.c:3760
#, c-format
msgid "cannot define savepoints during a parallel operation"
msgstr "während einer parallelen Operation können keine Sicherungspunkte definiert werden"
-#: access/transam/xact.c:3825
+#: access/transam/xact.c:3827
#, c-format
msgid "cannot release savepoints during a parallel operation"
msgstr "während einer parallelen Operation können keine Sicherungspunkte freigegeben werden"
-#: access/transam/xact.c:3836 access/transam/xact.c:3888
-#: access/transam/xact.c:3894 access/transam/xact.c:3950
-#: access/transam/xact.c:4000 access/transam/xact.c:4006
+#: access/transam/xact.c:3838 access/transam/xact.c:3890
+#: access/transam/xact.c:3896 access/transam/xact.c:3952
+#: access/transam/xact.c:4002 access/transam/xact.c:4008
#, c-format
msgid "no such savepoint"
msgstr "Sicherungspunkt existiert nicht"
-#: access/transam/xact.c:3938
+#: access/transam/xact.c:3940
#, c-format
msgid "cannot rollback to savepoints during a parallel operation"
msgstr "während einer parallelen Operation kann nicht auf einen Sicherungspunkt zurückgerollt werden"
-#: access/transam/xact.c:4066
+#: access/transam/xact.c:4068
#, c-format
msgid "cannot start subtransactions during a parallel operation"
msgstr "während einer parallelen Operation können keine Subtransaktionen gestartet werden"
-#: access/transam/xact.c:4133
+#: access/transam/xact.c:4135
#, c-format
msgid "cannot commit subtransactions during a parallel operation"
msgstr "während einer parallelen Operation können keine Subtransaktionen committet werden"
-#: access/transam/xact.c:4741
+#: access/transam/xact.c:4743
#, c-format
msgid "cannot have more than 2^32-1 subtransactions in a transaction"
msgstr "kann nicht mehr als 2^32-1 Subtransaktionen in einer Transaktion haben"
-#: access/transam/xlog.c:2270
+#: access/transam/xlog.c:2446
#, c-format
msgid "could not seek in log file %s to offset %u: %m"
msgstr "konnte Positionszeiger in Logdatei %s nicht auf %u setzen: %m"
-#: access/transam/xlog.c:2290
+#: access/transam/xlog.c:2466
#, c-format
msgid "could not write to log file %s at offset %u, length %zu: %m"
msgstr "konnte nicht in Logdatei %s bei Position %u, Länge %zu schreiben: %m"
-#: access/transam/xlog.c:2553
+#: access/transam/xlog.c:2730
#, c-format
msgid "updated min recovery point to %X/%X on timeline %u"
msgstr "minimaler Recovery-Punkt auf %X/%X auf Zeitleiste %u aktualisiert"
-#: access/transam/xlog.c:3195
+#: access/transam/xlog.c:3372
#, c-format
msgid "not enough data in file \"%s\""
msgstr "nicht genug Daten in Datei »%s«"
-#: access/transam/xlog.c:3336
+#: access/transam/xlog.c:3513
#, c-format
msgid "could not open transaction log file \"%s\": %m"
msgstr "konnte Transaktionslogdatei »%s« nicht öffnen: %m"
-#: access/transam/xlog.c:3525 access/transam/xlog.c:5298
+#: access/transam/xlog.c:3702 access/transam/xlog.c:5503
#, c-format
msgid "could not close log file %s: %m"
msgstr "konnte Logdatei %s nicht schließen: %m"
-#: access/transam/xlog.c:3582 access/transam/xlogutils.c:696
-#: replication/walsender.c:2099
+#: access/transam/xlog.c:3759 access/transam/xlogutils.c:697
+#: replication/walsender.c:2050
#, c-format
msgid "requested WAL segment %s has already been removed"
msgstr "das angeforderte WAL-Segment %s wurde schon entfernt"
-#: access/transam/xlog.c:3642 access/transam/xlog.c:3717
-#: access/transam/xlog.c:3915
+#: access/transam/xlog.c:3819 access/transam/xlog.c:3894
+#: access/transam/xlog.c:4092
#, c-format
msgid "could not open transaction log directory \"%s\": %m"
msgstr "konnte Transaktionslog-Verzeichnis »%s« nicht öffnen: %m"
-#: access/transam/xlog.c:3798
+#: access/transam/xlog.c:3975
#, c-format
msgid "recycled transaction log file \"%s\""
msgstr "Transaktionslogdatei »%s« wird wiederverwendet"
-#: access/transam/xlog.c:3810
+#: access/transam/xlog.c:3987
#, c-format
msgid "removing transaction log file \"%s\""
msgstr "entferne Transaktionslogdatei »%s«"
-#: access/transam/xlog.c:3830
+#: access/transam/xlog.c:4007
#, c-format
msgid "could not rename old transaction log file \"%s\": %m"
msgstr "konnte alte Transaktionslogdatei »%s« nicht umbenennen: %m"
-#: access/transam/xlog.c:3842
+#: access/transam/xlog.c:4019
#, c-format
msgid "could not remove old transaction log file \"%s\": %m"
msgstr "konnte alte Transaktionslogdatei »%s« nicht löschen: %m"
-#: access/transam/xlog.c:3875 access/transam/xlog.c:3885
+#: access/transam/xlog.c:4052 access/transam/xlog.c:4062
#, c-format
msgid "required WAL directory \"%s\" does not exist"
msgstr "benötigtes WAL-Verzeichnis »%s« existiert nicht"
-#: access/transam/xlog.c:3891
+#: access/transam/xlog.c:4068
#, c-format
msgid "creating missing WAL directory \"%s\""
msgstr "erzeuge fehlendes WAL-Verzeichnis »%s«"
-#: access/transam/xlog.c:3894
+#: access/transam/xlog.c:4071
#, c-format
msgid "could not create missing directory \"%s\": %m"
msgstr "konnte fehlendes Verzeichnis »%s« nicht erzeugen: %m"
-#: access/transam/xlog.c:3925
+#: access/transam/xlog.c:4102
#, c-format
msgid "removing transaction log backup history file \"%s\""
msgstr "entferne Transaktionslog-Backup-History-Datei »%s«"
-#: access/transam/xlog.c:4006
+#: access/transam/xlog.c:4183
#, c-format
msgid "unexpected timeline ID %u in log segment %s, offset %u"
msgstr "unerwartete Zeitleisten-ID %u in Logsegment %s, Offset %u"
-#: access/transam/xlog.c:4128
+#: access/transam/xlog.c:4305
#, c-format
msgid "new timeline %u is not a child of database system timeline %u"
msgstr "neue Zeitleiste %u ist kein Kind der Datenbanksystemzeitleiste %u"
-#: access/transam/xlog.c:4142
+#: access/transam/xlog.c:4319
#, c-format
msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X"
msgstr "neue Zeitleiste %u zweigte von der aktuellen Datenbanksystemzeitleiste %u vor dem aktuellen Wiederherstellungspunkt %X/%X ab"
-#: access/transam/xlog.c:4161
+#: access/transam/xlog.c:4338
#, c-format
msgid "new target timeline is %u"
msgstr "neue Zielzeitleiste ist %u"
-#: access/transam/xlog.c:4241
+#: access/transam/xlog.c:4413
#, c-format
msgid "could not create control file \"%s\": %m"
msgstr "konnte Kontrolldatei »%s« nicht erzeugen: %m"
-#: access/transam/xlog.c:4252 access/transam/xlog.c:4488
+#: access/transam/xlog.c:4424 access/transam/xlog.c:4644
#, c-format
msgid "could not write to control file: %m"
msgstr "konnte nicht in Kontrolldatei schreiben: %m"
-#: access/transam/xlog.c:4258 access/transam/xlog.c:4494
+#: access/transam/xlog.c:4430 access/transam/xlog.c:4650
#, c-format
msgid "could not fsync control file: %m"
msgstr "konnte Kontrolldatei nicht fsyncen: %m"
-#: access/transam/xlog.c:4263 access/transam/xlog.c:4499
+#: access/transam/xlog.c:4435 access/transam/xlog.c:4655
#, c-format
msgid "could not close control file: %m"
msgstr "konnte Kontrolldatei nicht schließen: %m"
-#: access/transam/xlog.c:4281 access/transam/xlog.c:4477
+#: access/transam/xlog.c:4453 access/transam/xlog.c:4633
#, c-format
msgid "could not open control file \"%s\": %m"
msgstr "konnte Kontrolldatei »%s« nicht öffnen: %m"
-#: access/transam/xlog.c:4287
+#: access/transam/xlog.c:4459
#, c-format
msgid "could not read from control file: %m"
msgstr "konnte nicht aus Kontrolldatei lesen: %m"
-#: access/transam/xlog.c:4300 access/transam/xlog.c:4309
-#: access/transam/xlog.c:4333 access/transam/xlog.c:4340
-#: access/transam/xlog.c:4347 access/transam/xlog.c:4352
-#: access/transam/xlog.c:4359 access/transam/xlog.c:4366
-#: access/transam/xlog.c:4373 access/transam/xlog.c:4380
-#: access/transam/xlog.c:4387 access/transam/xlog.c:4394
-#: access/transam/xlog.c:4401 access/transam/xlog.c:4410
-#: access/transam/xlog.c:4417 access/transam/xlog.c:4426
-#: access/transam/xlog.c:4433 access/transam/xlog.c:4442
-#: access/transam/xlog.c:4449 utils/init/miscinit.c:1380
+#: access/transam/xlog.c:4472 access/transam/xlog.c:4481
+#: access/transam/xlog.c:4505 access/transam/xlog.c:4512
+#: access/transam/xlog.c:4519 access/transam/xlog.c:4524
+#: access/transam/xlog.c:4531 access/transam/xlog.c:4538
+#: access/transam/xlog.c:4545 access/transam/xlog.c:4552
+#: access/transam/xlog.c:4559 access/transam/xlog.c:4566
+#: access/transam/xlog.c:4573 access/transam/xlog.c:4582
+#: access/transam/xlog.c:4589 access/transam/xlog.c:4598
+#: access/transam/xlog.c:4605 utils/init/miscinit.c:1380
#, c-format
msgid "database files are incompatible with server"
msgstr "Datenbankdateien sind inkompatibel mit Server"
-#: access/transam/xlog.c:4301
+#: access/transam/xlog.c:4473
#, c-format
msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)."
msgstr "Der Datenbank-Cluster wurde mit PG_CONTROL_VERSION %d (0x%08x) initialisiert, aber der Server wurde mit PG_CONTROL_VERSION %d (0x%08x) kompiliert."
-#: access/transam/xlog.c:4305
+#: access/transam/xlog.c:4477
#, c-format
msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb."
msgstr "Das Problem könnte eine falsche Byte-Reihenfolge sein. Es sieht so aus, dass Sie initdb ausführen müssen."
-#: access/transam/xlog.c:4310
+#: access/transam/xlog.c:4482
#, c-format
msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d."
msgstr "Der Datenbank-Cluster wurde mit PG_CONTROL_VERSION %d initialisiert, aber der Server wurde mit PG_CONTROL_VERSION %d kompiliert."
-#: access/transam/xlog.c:4313 access/transam/xlog.c:4337
-#: access/transam/xlog.c:4344 access/transam/xlog.c:4349
+#: access/transam/xlog.c:4485 access/transam/xlog.c:4509
+#: access/transam/xlog.c:4516 access/transam/xlog.c:4521
#, c-format
msgid "It looks like you need to initdb."
msgstr "Es sieht so aus, dass Sie initdb ausführen müssen."
-#: access/transam/xlog.c:4324
+#: access/transam/xlog.c:4496
#, c-format
msgid "incorrect checksum in control file"
msgstr "falsche Prüfsumme in Kontrolldatei"
-#: access/transam/xlog.c:4334
+#: access/transam/xlog.c:4506
#, c-format
msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d."
msgstr "Der Datenbank-Cluster wurde mit CATALOG_VERSION_NO %d initialisiert, aber der Server wurde mit CATALOG_VERSION_NO %d kompiliert."
-#: access/transam/xlog.c:4341
+#: access/transam/xlog.c:4513
#, c-format
msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d."
msgstr "Der Datenbank-Cluster wurde mit MAXALIGN %d initialisiert, aber der Server wurde mit MAXALIGN %d kompiliert."
-#: access/transam/xlog.c:4348
+#: access/transam/xlog.c:4520
#, c-format
msgid "The database cluster appears to use a different floating-point number format than the server executable."
msgstr "Der Datenbank-Cluster verwendet anscheinend ein anderes Fließkommazahlenformat als das Serverprogramm."
-#: access/transam/xlog.c:4353
+#: access/transam/xlog.c:4525
#, c-format
msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d."
msgstr "Der Datenbank-Cluster wurde mit BLCKSZ %d initialisiert, aber der Server wurde mit BLCKSZ %d kompiliert."
-#: access/transam/xlog.c:4356 access/transam/xlog.c:4363
-#: access/transam/xlog.c:4370 access/transam/xlog.c:4377
-#: access/transam/xlog.c:4384 access/transam/xlog.c:4391
-#: access/transam/xlog.c:4398 access/transam/xlog.c:4405
-#: access/transam/xlog.c:4413 access/transam/xlog.c:4420
-#: access/transam/xlog.c:4429 access/transam/xlog.c:4436
-#: access/transam/xlog.c:4445 access/transam/xlog.c:4452
+#: access/transam/xlog.c:4528 access/transam/xlog.c:4535
+#: access/transam/xlog.c:4542 access/transam/xlog.c:4549
+#: access/transam/xlog.c:4556 access/transam/xlog.c:4563
+#: access/transam/xlog.c:4570 access/transam/xlog.c:4577
+#: access/transam/xlog.c:4585 access/transam/xlog.c:4592
+#: access/transam/xlog.c:4601 access/transam/xlog.c:4608
#, c-format
msgid "It looks like you need to recompile or initdb."
msgstr "Es sieht so aus, dass Sie neu kompilieren oder initdb ausführen müssen."
-#: access/transam/xlog.c:4360
+#: access/transam/xlog.c:4532
#, c-format
msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d."
msgstr "Der Datenbank-Cluster wurde mit RELSEG_SIZE %d initialisiert, aber der Server wurde mit RELSEGSIZE %d kompiliert."
-#: access/transam/xlog.c:4367
+#: access/transam/xlog.c:4539
#, c-format
msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d."
msgstr "Der Datenbank-Cluster wurde mit XLOG_BLCKSZ %d initialisiert, aber der Server wurde mit XLOG_BLCKSZ %d kompiliert."
-#: access/transam/xlog.c:4374
+#: access/transam/xlog.c:4546
#, c-format
msgid "The database cluster was initialized with XLOG_SEG_SIZE %d, but the server was compiled with XLOG_SEG_SIZE %d."
msgstr "Der Datenbank-Cluster wurde mit XLOG_SEG_SIZE %d initialisiert, aber der Server wurde mit XLOG_SEG_SIZE %d kompiliert."
-#: access/transam/xlog.c:4381
+#: access/transam/xlog.c:4553
#, c-format
msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d."
msgstr "Der Datenbank-Cluster wurde mit NAMEDATALEN %d initialisiert, aber der Server wurde mit NAMEDATALEN %d kompiliert."
-#: access/transam/xlog.c:4388
+#: access/transam/xlog.c:4560
#, c-format
msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d."
msgstr "Der Datenbank-Cluster wurde mit INDEX_MAX_KEYS %d initialisiert, aber der Server wurde mit INDEX_MAX_KEYS %d kompiliert."
-#: access/transam/xlog.c:4395
+#: access/transam/xlog.c:4567
#, c-format
msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d."
msgstr "Der Datenbank-Cluster wurde mit TOAST_MAX_CHUNK_SIZE %d initialisiert, aber der Server wurde mit TOAST_MAX_CHUNK_SIZE %d kompiliert."
-#: access/transam/xlog.c:4402
+#: access/transam/xlog.c:4574
#, c-format
msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d."
msgstr "Der Datenbank-Cluster wurde mit LOBLKSIZE %d initialisiert, aber der Server wurde mit LOBLKSIZE %d kompiliert."
-#: access/transam/xlog.c:4411
-#, c-format
-msgid "The database cluster was initialized without HAVE_INT64_TIMESTAMP but the server was compiled with HAVE_INT64_TIMESTAMP."
-msgstr "Der Datenbank-Cluster wurde ohne HAVE_INT64_TIMESTAMP initialisiert, aber der Server wurde mit HAE_INT64_TIMESTAMP kompiliert."
-
-#: access/transam/xlog.c:4418
-#, c-format
-msgid "The database cluster was initialized with HAVE_INT64_TIMESTAMP but the server was compiled without HAVE_INT64_TIMESTAMP."
-msgstr "Der Datenbank-Cluster wurde mit HAVE_INT64_TIMESTAMP initialisiert, aber der Server wurde ohne HAE_INT64_TIMESTAMP kompiliert."
-
-#: access/transam/xlog.c:4427
+#: access/transam/xlog.c:4583
#, c-format
msgid "The database cluster was initialized without USE_FLOAT4_BYVAL but the server was compiled with USE_FLOAT4_BYVAL."
msgstr "Der Datenbank-Cluster wurde ohne USE_FLOAT4_BYVAL initialisiert, aber der Server wurde mit USE_FLOAT4_BYVAL kompiliert."
-#: access/transam/xlog.c:4434
+#: access/transam/xlog.c:4590
#, c-format
msgid "The database cluster was initialized with USE_FLOAT4_BYVAL but the server was compiled without USE_FLOAT4_BYVAL."
msgstr "Der Datenbank-Cluster wurde mit USE_FLOAT4_BYVAL initialisiert, aber der Server wurde ohne USE_FLOAT4_BYVAL kompiliert."
-#: access/transam/xlog.c:4443
+#: access/transam/xlog.c:4599
#, c-format
msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL."
msgstr "Der Datenbank-Cluster wurde ohne USE_FLOAT8_BYVAL initialisiert, aber der Server wurde mit USE_FLOAT8_BYVAL kompiliert."
-#: access/transam/xlog.c:4450
+#: access/transam/xlog.c:4606
#, c-format
msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL."
msgstr "Der Datenbank-Cluster wurde mit USE_FLOAT8_BYVAL initialisiert, aber der Server wurde ohne USE_FLOAT8_BYVAL kompiliert."
-#: access/transam/xlog.c:4873
+#: access/transam/xlog.c:4958
+#, fuzzy, c-format
+#| msgid "could not generate random encryption vector"
+msgid "could not generation secret authorization token"
+msgstr "konnte zufälligen Verschlüsselungsvektor nicht erzeugen"
+
+#: access/transam/xlog.c:5046
#, c-format
msgid "could not write bootstrap transaction log file: %m"
msgstr "konnte Bootstrap-Transaktionslogdatei nicht schreiben: %m"
-#: access/transam/xlog.c:4879
+#: access/transam/xlog.c:5052
#, c-format
msgid "could not fsync bootstrap transaction log file: %m"
msgstr "konnte Bootstrap-Transaktionslogdatei nicht fsyncen: %m"
-#: access/transam/xlog.c:4884
+#: access/transam/xlog.c:5057
#, c-format
msgid "could not close bootstrap transaction log file: %m"
msgstr "konnte Bootstrap-Transaktionslogdatei nicht schließen: %m"
-#: access/transam/xlog.c:4959
+#: access/transam/xlog.c:5133
#, c-format
msgid "could not open recovery command file \"%s\": %m"
msgstr "konnte Recovery-Kommandodatei »%s« nicht öffnen: %m"
-#: access/transam/xlog.c:5005 access/transam/xlog.c:5088
+#: access/transam/xlog.c:5179 access/transam/xlog.c:5281
#, c-format
msgid "invalid value for recovery parameter \"%s\": \"%s\""
msgstr "ungültiger Wert für Recovery-Parameter »%s«: »%s«"
-#: access/transam/xlog.c:5008
+#: access/transam/xlog.c:5182
#, c-format
msgid "Valid values are \"pause\", \"promote\", and \"shutdown\"."
msgstr "Gültige Werte sind »pause«, »promote« und »shutdown«."
-#: access/transam/xlog.c:5027
+#: access/transam/xlog.c:5202
#, c-format
msgid "recovery_target_timeline is not a valid number: \"%s\""
msgstr "recovery_target_timeline ist keine gültige Zahl: »%s«"
-#: access/transam/xlog.c:5043
+#: access/transam/xlog.c:5219
#, c-format
msgid "recovery_target_xid is not a valid number: \"%s\""
msgstr "recovery_target_xid ist keine gültige Zahl: »%s«"
-#: access/transam/xlog.c:5074
+#: access/transam/xlog.c:5250
#, c-format
msgid "recovery_target_name is too long (maximum %d characters)"
msgstr "recovery_target_name ist zu lang (maximal %d Zeichen)"
-#: access/transam/xlog.c:5091
+#: access/transam/xlog.c:5284
#, c-format
msgid "The only allowed value is \"immediate\"."
msgstr "Der einzige erlaubte Wert ist »immediate«."
-#: access/transam/xlog.c:5104 access/transam/xlog.c:5115
-#: commands/extension.c:533 commands/extension.c:541 utils/misc/guc.c:5638
+#: access/transam/xlog.c:5297 access/transam/xlog.c:5308
+#: commands/extension.c:546 commands/extension.c:554 utils/misc/guc.c:5706
#, c-format
msgid "parameter \"%s\" requires a Boolean value"
msgstr "Parameter »%s« erfordert einen Boole’schen Wert"
-#: access/transam/xlog.c:5150
+#: access/transam/xlog.c:5343
#, c-format
msgid "parameter \"%s\" requires a temporal value"
msgstr "Parameter »%s« erfordert einen Zeitwert"
-#: access/transam/xlog.c:5152 catalog/dependency.c:991
-#: catalog/dependency.c:992 catalog/dependency.c:998 catalog/dependency.c:999
-#: catalog/dependency.c:1010 catalog/dependency.c:1011
-#: catalog/objectaddress.c:1100 commands/tablecmds.c:795
-#: commands/tablecmds.c:9445 commands/user.c:1045 commands/view.c:470
-#: libpq/auth.c:304 replication/syncrep.c:926 storage/lmgr/deadlock.c:1139
-#: storage/lmgr/proc.c:1276 utils/adt/acl.c:5281 utils/misc/guc.c:5660
-#: utils/misc/guc.c:5753 utils/misc/guc.c:9688 utils/misc/guc.c:9722
-#: utils/misc/guc.c:9756 utils/misc/guc.c:9790 utils/misc/guc.c:9825
+#: access/transam/xlog.c:5345 catalog/dependency.c:959
+#: catalog/dependency.c:960 catalog/dependency.c:966 catalog/dependency.c:967
+#: catalog/dependency.c:978 catalog/dependency.c:979 commands/tablecmds.c:946
+#: commands/tablecmds.c:10018 commands/user.c:1052 commands/view.c:505
+#: libpq/auth.c:334 replication/syncrep.c:1118 storage/lmgr/deadlock.c:1139
+#: storage/lmgr/proc.c:1286 utils/adt/acl.c:5248 utils/misc/guc.c:5728
+#: utils/misc/guc.c:5821 utils/misc/guc.c:9773 utils/misc/guc.c:9807
+#: utils/misc/guc.c:9841 utils/misc/guc.c:9875 utils/misc/guc.c:9910
#, c-format
msgid "%s"
msgstr "%s"
-#: access/transam/xlog.c:5158
+#: access/transam/xlog.c:5352
#, c-format
msgid "unrecognized recovery parameter \"%s\""
msgstr "unbekannter Recovery-Parameter »%s«"
-#: access/transam/xlog.c:5169
+#: access/transam/xlog.c:5363
#, c-format
msgid "recovery command file \"%s\" specified neither primary_conninfo nor restore_command"
msgstr "Recovery-Kommandodatei »%s« hat weder primary_conninfo noch restore_command angegeben"
-#: access/transam/xlog.c:5171
+#: access/transam/xlog.c:5365
#, c-format
-msgid "The database server will regularly poll the pg_xlog subdirectory to check for files placed there."
-msgstr "Der Datenbankserver prüft das Unterverzeichnis pg_xlog regelmäßig auf dort abgelegte Dateien."
+msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there."
+msgstr "Der Datenbankserver prüft das Unterverzeichnis pg_wal regelmäßig auf dort abgelegte Dateien."
-#: access/transam/xlog.c:5177
+#: access/transam/xlog.c:5372
#, c-format
msgid "recovery command file \"%s\" must specify restore_command when standby mode is not enabled"
msgstr "Recovery-Kommandodatei »%s« muss restore_command angeben, wenn der Standby-Modus nicht eingeschaltet ist"
-#: access/transam/xlog.c:5207
+#: access/transam/xlog.c:5393
+#, c-format
+msgid "standby mode is not supported by single-user servers"
+msgstr "Standby-Modus wird von Servern im Einzelbenutzermodus nicht unterstützt"
+
+#: access/transam/xlog.c:5412
#, c-format
msgid "recovery target timeline %u does not exist"
msgstr "recovery_target_timeline %u existiert nicht"
-#: access/transam/xlog.c:5328
+#: access/transam/xlog.c:5533
#, c-format
msgid "archive recovery complete"
msgstr "Wiederherstellung aus Archiv abgeschlossen"
-#: access/transam/xlog.c:5387 access/transam/xlog.c:5615
+#: access/transam/xlog.c:5592 access/transam/xlog.c:5858
#, c-format
msgid "recovery stopping after reaching consistency"
msgstr "Wiederherstellung beendet nachdem Konsistenz erreicht wurde"
-#: access/transam/xlog.c:5475
+#: access/transam/xlog.c:5613
+#, c-format
+msgid "recovery stopping before WAL position (LSN) \"%X/%X\""
+msgstr "Wiederherstellung beendet vor WAL-Position (LSN) »%X/%X«"
+
+#: access/transam/xlog.c:5699
#, c-format
msgid "recovery stopping before commit of transaction %u, time %s"
msgstr "Wiederherstellung beendet vor Commit der Transaktion %u, Zeit %s"
-#: access/transam/xlog.c:5482
+#: access/transam/xlog.c:5706
#, c-format
msgid "recovery stopping before abort of transaction %u, time %s"
msgstr "Wiederherstellung beendet vor Abbruch der Transaktion %u, Zeit %s"
-#: access/transam/xlog.c:5527
+#: access/transam/xlog.c:5752
#, c-format
msgid "recovery stopping at restore point \"%s\", time %s"
msgstr "Wiederherstellung beendet bei Restore-Punkt »%s«, Zeit %s"
-#: access/transam/xlog.c:5595
+#: access/transam/xlog.c:5770
+#, c-format
+msgid "recovery stopping after WAL position (LSN) \"%X/%X\""
+msgstr "Wiederherstellung beendet nach WAL-Position (LSN) »%X/%X«"
+
+#: access/transam/xlog.c:5838
#, c-format
msgid "recovery stopping after commit of transaction %u, time %s"
msgstr "Wiederherstellung beendet nach Commit der Transaktion %u, Zeit %s"
-#: access/transam/xlog.c:5603
+#: access/transam/xlog.c:5846
#, c-format
msgid "recovery stopping after abort of transaction %u, time %s"
msgstr "Wiederherstellung beendet nach Abbruch der Transaktion %u, Zeit %s"
-#: access/transam/xlog.c:5642
+#: access/transam/xlog.c:5886
#, c-format
msgid "recovery has paused"
msgstr "Wiederherstellung wurde pausiert"
-#: access/transam/xlog.c:5643
+#: access/transam/xlog.c:5887
#, c-format
-msgid "Execute pg_xlog_replay_resume() to continue."
-msgstr "Führen Sie pg_xlog_replay_resume() aus um fortzusetzen."
+msgid "Execute pg_wal_replay_resume() to continue."
+msgstr "Führen Sie pg_wal_replay_resume() aus um fortzusetzen."
-#: access/transam/xlog.c:5850
+#: access/transam/xlog.c:6095
#, c-format
msgid "hot standby is not possible because %s = %d is a lower setting than on the master server (its value was %d)"
msgstr "Hot Standby ist nicht möglich, weil %s = %d eine niedrigere Einstellung als auf dem Masterserver ist (Wert dort war %d)"
-#: access/transam/xlog.c:5876
+#: access/transam/xlog.c:6121
#, c-format
msgid "WAL was generated with wal_level=minimal, data may be missing"
msgstr "WAL wurde mit wal_level=minimal erzeugt, eventuell fehlen Daten"
-#: access/transam/xlog.c:5877
+#: access/transam/xlog.c:6122
#, c-format
msgid "This happens if you temporarily set wal_level=minimal without taking a new base backup."
msgstr "Das passiert, wenn vorübergehend wal_level=minimal gesetzt wurde, ohne ein neues Base-Backup zu erzeugen."
-#: access/transam/xlog.c:5888
+#: access/transam/xlog.c:6133
#, c-format
msgid "hot standby is not possible because wal_level was not set to \"replica\" or higher on the master server"
msgstr "Hot Standby ist nicht möglich, weil wal_level auf dem Masterserver nicht auf »replica« oder höher gesetzt wurde"
-#: access/transam/xlog.c:5889
+#: access/transam/xlog.c:6134
#, c-format
msgid "Either set wal_level to \"replica\" on the master, or turn off hot_standby here."
msgstr "Setzen Sie entweder wal_level auf »replica« auf dem Master oder schalten Sie hot_standby hier aus."
-#: access/transam/xlog.c:5946
+#: access/transam/xlog.c:6191
#, c-format
msgid "control file contains invalid data"
msgstr "Kontrolldatei enthält ungültige Daten"
-#: access/transam/xlog.c:5952
+#: access/transam/xlog.c:6197
#, c-format
msgid "database system was shut down at %s"
msgstr "Datenbanksystem wurde am %s heruntergefahren"
-#: access/transam/xlog.c:5957
+#: access/transam/xlog.c:6202
#, c-format
msgid "database system was shut down in recovery at %s"
msgstr "Datenbanksystem wurde während der Wiederherstellung am %s heruntergefahren"
-#: access/transam/xlog.c:5961
+#: access/transam/xlog.c:6206
#, c-format
msgid "database system shutdown was interrupted; last known up at %s"
msgstr "Datenbanksystem wurde beim Herunterfahren unterbrochen; letzte bekannte Aktion am %s"
-#: access/transam/xlog.c:5965
+#: access/transam/xlog.c:6210
#, c-format
msgid "database system was interrupted while in recovery at %s"
msgstr "Datenbanksystem wurde während der Wiederherstellung am %s unterbrochen"
-#: access/transam/xlog.c:5967
+#: access/transam/xlog.c:6212
#, c-format
msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery."
msgstr "Das bedeutet wahrscheinlich, dass einige Daten verfälscht sind und Sie die letzte Datensicherung zur Wiederherstellung verwenden müssen."
-#: access/transam/xlog.c:5971
+#: access/transam/xlog.c:6216
#, c-format
msgid "database system was interrupted while in recovery at log time %s"
msgstr "Datenbanksystem wurde während der Wiederherstellung bei Logzeit %s unterbrochen"
-#: access/transam/xlog.c:5973
+#: access/transam/xlog.c:6218
#, c-format
msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target."
msgstr "Wenn dies mehr als einmal vorgekommen ist, dann sind einige Daten möglicherweise verfälscht und Sie müssen ein früheres Wiederherstellungsziel wählen."
-#: access/transam/xlog.c:5977
+#: access/transam/xlog.c:6222
#, c-format
msgid "database system was interrupted; last known up at %s"
msgstr "Datenbanksystem wurde unterbrochen; letzte bekannte Aktion am %s"
-#: access/transam/xlog.c:6033
+#: access/transam/xlog.c:6278
#, c-format
msgid "entering standby mode"
msgstr "Standby-Modus eingeschaltet"
-#: access/transam/xlog.c:6036
+#: access/transam/xlog.c:6281
#, c-format
msgid "starting point-in-time recovery to XID %u"
msgstr "starte Point-in-Time-Recovery bis XID %u"
-#: access/transam/xlog.c:6040
+#: access/transam/xlog.c:6285
#, c-format
msgid "starting point-in-time recovery to %s"
msgstr "starte Point-in-Time-Recovery bis %s"
-#: access/transam/xlog.c:6044
+#: access/transam/xlog.c:6289
#, c-format
msgid "starting point-in-time recovery to \"%s\""
msgstr "starte Point-in-Time-Recovery bis »%s«"
-#: access/transam/xlog.c:6048
+#: access/transam/xlog.c:6293
+#, c-format
+msgid "starting point-in-time recovery to WAL position (LSN) \"%X/%X\""
+msgstr "starte Point-in-Time-Recovery bis WAL-Position (LSN) »%X/%X«"
+
+#: access/transam/xlog.c:6298
#, c-format
msgid "starting point-in-time recovery to earliest consistent point"
msgstr "starte Point-in-Time-Recovery bis zum frühesten konsistenten Punkt"
-#: access/transam/xlog.c:6051
+#: access/transam/xlog.c:6301
#, c-format
msgid "starting archive recovery"
msgstr "starte Wiederherstellung aus Archiv"
-#: access/transam/xlog.c:6095 access/transam/xlog.c:6223
+#: access/transam/xlog.c:6352 access/transam/xlog.c:6480
#, c-format
msgid "checkpoint record is at %X/%X"
msgstr "Checkpoint-Eintrag ist bei %X/%X"
-#: access/transam/xlog.c:6109
+#: access/transam/xlog.c:6366
#, c-format
msgid "could not find redo location referenced by checkpoint record"
msgstr "konnte die vom Checkpoint-Datensatz referenzierte Redo-Position nicht finden"
-#: access/transam/xlog.c:6110 access/transam/xlog.c:6117
+#: access/transam/xlog.c:6367 access/transam/xlog.c:6374
#, c-format
msgid "If you are not restoring from a backup, try removing the file \"%s/backup_label\"."
msgstr "Wenn Sie gerade keine Sicherung wiederherstellen, versuchen Sie, die Datei »%s/backup_label« zu löschen."
-#: access/transam/xlog.c:6116
+#: access/transam/xlog.c:6373
#, c-format
msgid "could not locate required checkpoint record"
msgstr "konnte den nötigen Checkpoint-Datensatz nicht finden"
-#: access/transam/xlog.c:6142 commands/tablespace.c:641
+#: access/transam/xlog.c:6399 commands/tablespace.c:639
#, c-format
msgid "could not create symbolic link \"%s\": %m"
msgstr "konnte symbolische Verknüpfung »%s« nicht erstellen: %m"
-#: access/transam/xlog.c:6174 access/transam/xlog.c:6180
+#: access/transam/xlog.c:6431 access/transam/xlog.c:6437
#, c-format
msgid "ignoring file \"%s\" because no file \"%s\" exists"
msgstr "ignoriere Datei »%s«, weil keine Datei »%s« existiert"
-#: access/transam/xlog.c:6176 access/transam/xlog.c:10916
+#: access/transam/xlog.c:6433 access/transam/xlog.c:11310
#, c-format
msgid "File \"%s\" was renamed to \"%s\"."
msgstr "Datei »%s« wurde in »%s« umbenannt."
-#: access/transam/xlog.c:6182
+#: access/transam/xlog.c:6439
#, c-format
msgid "Could not rename file \"%s\" to \"%s\": %m."
msgstr "Konnte Datei »%s« nicht in »%s« umbenennen: %m."
-#: access/transam/xlog.c:6233 access/transam/xlog.c:6248
+#: access/transam/xlog.c:6490 access/transam/xlog.c:6505
#, c-format
msgid "could not locate a valid checkpoint record"
msgstr "konnte keinen gültigen Checkpoint-Datensatz finden"
-#: access/transam/xlog.c:6242
+#: access/transam/xlog.c:6499
#, c-format
msgid "using previous checkpoint record at %X/%X"
msgstr "verwende vorherigen Checkpoint-Eintrag bei %X/%X"
-#: access/transam/xlog.c:6286
+#: access/transam/xlog.c:6543
#, c-format
msgid "requested timeline %u is not a child of this server's history"
msgstr "angeforderte Zeitleiste %u ist kein Kind der History dieses Servers"
-#: access/transam/xlog.c:6288
+#: access/transam/xlog.c:6545
#, c-format
msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X."
msgstr "Neuester Checkpoint ist bei %X/%X auf Zeitleiste %u, aber in der History der angeforderten Zeitleiste zweigte der Server von dieser Zeitleiste bei %X/%X ab."
-#: access/transam/xlog.c:6304
+#: access/transam/xlog.c:6561
#, c-format
msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u"
msgstr "angeforderte Zeitleiste %u enthält nicht den minimalen Wiederherstellungspunkt %X/%X auf Zeitleiste %u"
-#: access/transam/xlog.c:6335
+#: access/transam/xlog.c:6592
#, c-format
msgid "invalid next transaction ID"
msgstr "ungültige nächste Transaktions-ID"
-#: access/transam/xlog.c:6418
+#: access/transam/xlog.c:6675
#, c-format
msgid "invalid redo in checkpoint record"
msgstr "ungültiges Redo im Checkpoint-Datensatz"
-#: access/transam/xlog.c:6429
+#: access/transam/xlog.c:6686
#, c-format
msgid "invalid redo record in shutdown checkpoint"
msgstr "ungültiger Redo-Datensatz im Shutdown-Checkpoint"
-#: access/transam/xlog.c:6457
+#: access/transam/xlog.c:6714
#, c-format
msgid "database system was not properly shut down; automatic recovery in progress"
msgstr "Datenbanksystem wurde nicht richtig heruntergefahren; automatische Wiederherstellung läuft"
-#: access/transam/xlog.c:6461
+#: access/transam/xlog.c:6718
#, c-format
msgid "crash recovery starts in timeline %u and has target timeline %u"
msgstr "Wiederherstellung nach Absturz beginnt in Zeitleiste %u und hat Zielzeitleiste %u"
-#: access/transam/xlog.c:6505
+#: access/transam/xlog.c:6762
#, c-format
msgid "backup_label contains data inconsistent with control file"
msgstr "Daten in backup_label stimmen nicht mit Kontrolldatei überein"
-#: access/transam/xlog.c:6506
+#: access/transam/xlog.c:6763
#, c-format
msgid "This means that the backup is corrupted and you will have to use another backup for recovery."
msgstr "Das bedeutet, dass die Datensicherung verfälscht ist und Sie eine andere Datensicherung zur Wiederherstellung verwenden werden müssen."
-#: access/transam/xlog.c:6580
+#: access/transam/xlog.c:6837
#, c-format
msgid "initializing for hot standby"
msgstr "initialisiere für Hot Standby"
-#: access/transam/xlog.c:6712
+#: access/transam/xlog.c:6969
#, c-format
msgid "redo starts at %X/%X"
msgstr "Redo beginnt bei %X/%X"
-#: access/transam/xlog.c:6937
+#: access/transam/xlog.c:7203
#, c-format
msgid "requested recovery stop point is before consistent recovery point"
msgstr "angeforderter Recovery-Endpunkt ist vor konsistentem Recovery-Punkt"
-#: access/transam/xlog.c:6975
+#: access/transam/xlog.c:7241
#, c-format
msgid "redo done at %X/%X"
msgstr "Redo fertig bei %X/%X"
-#: access/transam/xlog.c:6980 access/transam/xlog.c:8904
+#: access/transam/xlog.c:7246 access/transam/xlog.c:9244
#, c-format
msgid "last completed transaction was at log time %s"
msgstr "letzte vollständige Transaktion war bei Logzeit %s"
-#: access/transam/xlog.c:6989
+#: access/transam/xlog.c:7255
#, c-format
msgid "redo is not required"
msgstr "Redo nicht nötig"
-#: access/transam/xlog.c:7064 access/transam/xlog.c:7068
+#: access/transam/xlog.c:7330 access/transam/xlog.c:7334
#, c-format
msgid "WAL ends before end of online backup"
msgstr "WAL endet vor dem Ende der Online-Sicherung"
-#: access/transam/xlog.c:7065
+#: access/transam/xlog.c:7331
#, c-format
msgid "All WAL generated while online backup was taken must be available at recovery."
msgstr "Der komplette WAL, der während der Online-Sicherung erzeugt wurde, muss bei der Wiederherstellung verfügbar sein."
-#: access/transam/xlog.c:7069
+#: access/transam/xlog.c:7335
#, c-format
msgid "Online backup started with pg_start_backup() must be ended with pg_stop_backup(), and all WAL up to that point must be available at recovery."
msgstr "Die mit pg_start_backup() begonnene Online-Sicherung muss mit pg_stop_backup() beendet werden und der ganze WAL bis zu diesem Punkt muss bei der Wiederherstellung verfügbar sein."
-#: access/transam/xlog.c:7072
+#: access/transam/xlog.c:7338
#, c-format
msgid "WAL ends before consistent recovery point"
msgstr "WAL endet vor einem konsistenten Wiederherstellungspunkt"
-#: access/transam/xlog.c:7099
+#: access/transam/xlog.c:7365
#, c-format
msgid "selected new timeline ID: %u"
msgstr "gewählte neue Zeitleisten-ID: %u"
-#: access/transam/xlog.c:7510
+#: access/transam/xlog.c:7794
#, c-format
msgid "consistent recovery state reached at %X/%X"
msgstr "konsistenter Wiederherstellungszustand erreicht bei %X/%X"
-#: access/transam/xlog.c:7701
+#: access/transam/xlog.c:7986
#, c-format
msgid "invalid primary checkpoint link in control file"
msgstr "ungültige primäre Checkpoint-Verknüpfung in Kontrolldatei"
-#: access/transam/xlog.c:7705
+#: access/transam/xlog.c:7990
#, c-format
msgid "invalid secondary checkpoint link in control file"
msgstr "ungültige sekundäre Checkpoint-Verknüpfung in Kontrolldatei"
-#: access/transam/xlog.c:7709
+#: access/transam/xlog.c:7994
#, c-format
msgid "invalid checkpoint link in backup_label file"
msgstr "ungültige Checkpoint-Verknüpfung in backup_label-Datei"
-#: access/transam/xlog.c:7726
+#: access/transam/xlog.c:8011
#, c-format
msgid "invalid primary checkpoint record"
msgstr "ungültiger primärer Checkpoint-Datensatz"
-#: access/transam/xlog.c:7730
+#: access/transam/xlog.c:8015
#, c-format
msgid "invalid secondary checkpoint record"
msgstr "ungültiger sekundärer Checkpoint-Datensatz"
-#: access/transam/xlog.c:7734
+#: access/transam/xlog.c:8019
#, c-format
msgid "invalid checkpoint record"
msgstr "ungültiger Checkpoint-Datensatz"
-#: access/transam/xlog.c:7745
+#: access/transam/xlog.c:8030
#, c-format
msgid "invalid resource manager ID in primary checkpoint record"
msgstr "ungültige Resource-Manager-ID im primären Checkpoint-Datensatz"
-#: access/transam/xlog.c:7749
+#: access/transam/xlog.c:8034
#, c-format
msgid "invalid resource manager ID in secondary checkpoint record"
msgstr "ungültige Resource-Manager-ID im sekundären Checkpoint-Datensatz"
-#: access/transam/xlog.c:7753
+#: access/transam/xlog.c:8038
#, c-format
msgid "invalid resource manager ID in checkpoint record"
msgstr "ungültige Resource-Manager-ID im Checkpoint-Datensatz"
-#: access/transam/xlog.c:7765
+#: access/transam/xlog.c:8051
#, c-format
msgid "invalid xl_info in primary checkpoint record"
msgstr "ungültige xl_info im primären Checkpoint-Datensatz"
-#: access/transam/xlog.c:7769
+#: access/transam/xlog.c:8055
#, c-format
msgid "invalid xl_info in secondary checkpoint record"
msgstr "ungültige xl_info im sekundären Checkpoint-Datensatz"
-#: access/transam/xlog.c:7773
+#: access/transam/xlog.c:8059
#, c-format
msgid "invalid xl_info in checkpoint record"
msgstr "ungültige xl_info im Checkpoint-Datensatz"
-#: access/transam/xlog.c:7784
+#: access/transam/xlog.c:8070
#, c-format
msgid "invalid length of primary checkpoint record"
msgstr "ungültige Länge des primären Checkpoint-Datensatzes"
-#: access/transam/xlog.c:7788
+#: access/transam/xlog.c:8074
#, c-format
msgid "invalid length of secondary checkpoint record"
msgstr "ungültige Länge des sekundären Checkpoint-Datensatzes"
-#: access/transam/xlog.c:7792
+#: access/transam/xlog.c:8078
#, c-format
msgid "invalid length of checkpoint record"
msgstr "ungültige Länge des Checkpoint-Datensatzes"
-#: access/transam/xlog.c:7960
+#: access/transam/xlog.c:8281
#, c-format
msgid "shutting down"
msgstr "fahre herunter"
-#: access/transam/xlog.c:8473
+#: access/transam/xlog.c:8589
+#, fuzzy, c-format
+#| msgid "checkpoint request failed"
+msgid "checkpoint skipped due to an idle system"
+msgstr "Checkpoint-Anforderung fehlgeschlagen"
+
+#: access/transam/xlog.c:8789
#, c-format
msgid "concurrent transaction log activity while database system is shutting down"
msgstr "gleichzeitige Transaktionslog-Aktivität während das Datenbanksystem herunterfährt"
-#: access/transam/xlog.c:8724
+#: access/transam/xlog.c:9043
#, c-format
msgid "skipping restartpoint, recovery has already ended"
msgstr "Restart-Punkt übersprungen, Wiederherstellung ist bereits beendet"
-#: access/transam/xlog.c:8747
+#: access/transam/xlog.c:9066
#, c-format
msgid "skipping restartpoint, already performed at %X/%X"
msgstr "Restart-Punkt wird übersprungen, schon bei %X/%X erledigt"
-#: access/transam/xlog.c:8902
+#: access/transam/xlog.c:9242
#, c-format
msgid "recovery restart point at %X/%X"
msgstr "Recovery-Restart-Punkt bei %X/%X"
-#: access/transam/xlog.c:9035
+#: access/transam/xlog.c:9378
#, c-format
msgid "restore point \"%s\" created at %X/%X"
msgstr "Restore-Punkt »%s« erzeugt bei %X/%X"
-#: access/transam/xlog.c:9165
+#: access/transam/xlog.c:9508
#, c-format
msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record"
msgstr "unerwartete vorherige Zeitleisten-ID %u (aktuelle Zeitleisten-ID %u) im Checkpoint-Datensatz"
-#: access/transam/xlog.c:9174
+#: access/transam/xlog.c:9517
#, c-format
msgid "unexpected timeline ID %u (after %u) in checkpoint record"
msgstr "unerwartete Zeitleisten-ID %u (nach %u) im Checkpoint-Datensatz"
-#: access/transam/xlog.c:9190
+#: access/transam/xlog.c:9533
#, c-format
msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u"
msgstr "unerwartete Zeitleisten-ID %u in Checkpoint-Datensatz, bevor der minimale Wiederherstellungspunkt %X/%X auf Zeitleiste %u erreicht wurde"
-#: access/transam/xlog.c:9261
+#: access/transam/xlog.c:9604
#, c-format
msgid "online backup was canceled, recovery cannot continue"
msgstr "Online-Sicherung wurde storniert, Wiederherstellung kann nicht fortgesetzt werden"
-#: access/transam/xlog.c:9317 access/transam/xlog.c:9364
-#: access/transam/xlog.c:9387
+#: access/transam/xlog.c:9660 access/transam/xlog.c:9707
+#: access/transam/xlog.c:9730
#, c-format
msgid "unexpected timeline ID %u (should be %u) in checkpoint record"
msgstr "unerwartete Zeitleisten-ID %u (sollte %u sein) im Checkpoint-Datensatz"
-#: access/transam/xlog.c:9662
+#: access/transam/xlog.c:10005
#, c-format
msgid "could not fsync log segment %s: %m"
msgstr "konnte Logsegment %s nicht fsyncen: %m"
-#: access/transam/xlog.c:9686
+#: access/transam/xlog.c:10029
#, c-format
msgid "could not fsync log file %s: %m"
msgstr "konnte Logdatei %s nicht fsyncen: %m"
-#: access/transam/xlog.c:9694
+#: access/transam/xlog.c:10037
#, c-format
msgid "could not fsync write-through log file %s: %m"
msgstr "konnte Write-Through-Logdatei %s nicht fsyncen: %m"
-#: access/transam/xlog.c:9703
+#: access/transam/xlog.c:10046
#, c-format
msgid "could not fdatasync log file %s: %m"
msgstr "konnte Logdatei %s nicht fdatasyncen: %m"
-#: access/transam/xlog.c:9794 access/transam/xlog.c:10265
-#: access/transam/xlogfuncs.c:294 access/transam/xlogfuncs.c:321
-#: access/transam/xlogfuncs.c:360 access/transam/xlogfuncs.c:381
-#: access/transam/xlogfuncs.c:402
+#: access/transam/xlog.c:10137 access/transam/xlog.c:10641
+#: access/transam/xlogfuncs.c:293 access/transam/xlogfuncs.c:320
+#: access/transam/xlogfuncs.c:359 access/transam/xlogfuncs.c:380
+#: access/transam/xlogfuncs.c:401
#, c-format
msgid "WAL control functions cannot be executed during recovery."
msgstr "Während der Wiederherstellung können keine WAL-Kontrollfunktionen ausgeführt werden."
-#: access/transam/xlog.c:9803 access/transam/xlog.c:10274
+#: access/transam/xlog.c:10146 access/transam/xlog.c:10650
#, c-format
msgid "WAL level not sufficient for making an online backup"
msgstr "WAL-Level nicht ausreichend, um Online-Sicherung durchzuführen"
-#: access/transam/xlog.c:9804 access/transam/xlog.c:10275
-#: access/transam/xlogfuncs.c:327
+#: access/transam/xlog.c:10147 access/transam/xlog.c:10651
+#: access/transam/xlogfuncs.c:326
#, c-format
msgid "wal_level must be set to \"replica\" or \"logical\" at server start."
msgstr "wal_level muss beim Serverstart auf »replica« oder »logical« gesetzt werden."
-#: access/transam/xlog.c:9809
+#: access/transam/xlog.c:10152
#, c-format
msgid "backup label too long (max %d bytes)"
msgstr "Backup-Label zu lang (maximal %d Bytes)"
-#: access/transam/xlog.c:9841 access/transam/xlog.c:10113
-#: access/transam/xlog.c:10151
+#: access/transam/xlog.c:10189 access/transam/xlog.c:10461
+#: access/transam/xlog.c:10499
#, c-format
msgid "a backup is already in progress"
msgstr "ein Backup läuft bereits"
-#: access/transam/xlog.c:9842
+#: access/transam/xlog.c:10190
#, c-format
msgid "Run pg_stop_backup() and try again."
msgstr "Führen Sie pg_stop_backup() aus und versuchen Sie es nochmal."
-#: access/transam/xlog.c:9937
+#: access/transam/xlog.c:10285
#, c-format
msgid "WAL generated with full_page_writes=off was replayed since last restartpoint"
msgstr "mit full_page_writes=off erzeugtes WAL wurde seit dem letzten Restart-Punkt zurückgespielt"
-#: access/transam/xlog.c:9939 access/transam/xlog.c:10438
+#: access/transam/xlog.c:10287 access/transam/xlog.c:10832
#, c-format
msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable full_page_writes and run CHECKPOINT on the master, and then try an online backup again."
msgstr "Das bedeutet, dass die aktuelle Datensicherung auf dem Standby-Server verfälscht ist und nicht verwendet werden sollte. Schalten Sie full_page_writes ein, führen Sie CHECKPOINT aus und versuchen Sie dann die Online-Sicherung erneut."
-#: access/transam/xlog.c:10006 replication/basebackup.c:1038
-#: utils/adt/misc.c:498
+#: access/transam/xlog.c:10354 replication/basebackup.c:1096
+#: utils/adt/misc.c:497
#, c-format
msgid "could not read symbolic link \"%s\": %m"
msgstr "konnte symbolische Verknüpfung »%s« nicht lesen: %m"
-#: access/transam/xlog.c:10013 replication/basebackup.c:1043
-#: utils/adt/misc.c:503
+#: access/transam/xlog.c:10361 replication/basebackup.c:1101
+#: utils/adt/misc.c:502
#, c-format
msgid "symbolic link \"%s\" target is too long"
msgstr "Ziel für symbolische Verknüpfung »%s« ist zu lang"
-#: access/transam/xlog.c:10066 commands/tablespace.c:391
-#: commands/tablespace.c:553 replication/basebackup.c:1059
-#: utils/adt/misc.c:511
+#: access/transam/xlog.c:10414 commands/tablespace.c:389
+#: commands/tablespace.c:551 replication/basebackup.c:1116
+#: utils/adt/misc.c:510
#, c-format
msgid "tablespaces are not supported on this platform"
msgstr "Tablespaces werden auf dieser Plattform nicht unterstützt"
-#: access/transam/xlog.c:10107 access/transam/xlog.c:10145
-#: access/transam/xlog.c:10324 access/transam/xlogarchive.c:106
-#: access/transam/xlogarchive.c:265 commands/copy.c:1778 commands/copy.c:2804
-#: commands/extension.c:3109 commands/tablespace.c:782
-#: commands/tablespace.c:873 guc-file.l:1003 replication/basebackup.c:407
-#: replication/basebackup.c:475 replication/logical/snapbuild.c:1493
-#: storage/file/copydir.c:72 storage/file/copydir.c:115 storage/file/fd.c:2826
-#: storage/file/fd.c:2918 utils/adt/dbsize.c:70 utils/adt/dbsize.c:220
-#: utils/adt/dbsize.c:300 utils/adt/genfile.c:114 utils/adt/genfile.c:333
+#: access/transam/xlog.c:10455 access/transam/xlog.c:10493
+#: access/transam/xlog.c:10689 access/transam/xlogarchive.c:105
+#: access/transam/xlogarchive.c:264 commands/copy.c:1864 commands/copy.c:3038
+#: commands/extension.c:3312 commands/tablespace.c:780
+#: commands/tablespace.c:871 guc-file.l:1001 replication/basebackup.c:480
+#: replication/basebackup.c:548 replication/logical/snapbuild.c:1490
+#: storage/file/copydir.c:72 storage/file/copydir.c:115 storage/file/fd.c:2903
+#: storage/file/fd.c:2995 utils/adt/dbsize.c:69 utils/adt/dbsize.c:219
+#: utils/adt/dbsize.c:299 utils/adt/genfile.c:114 utils/adt/genfile.c:333
#, c-format
msgid "could not stat file \"%s\": %m"
msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m"
-#: access/transam/xlog.c:10114 access/transam/xlog.c:10152
+#: access/transam/xlog.c:10462 access/transam/xlog.c:10500
#, c-format
msgid "If you're sure there is no backup in progress, remove file \"%s\" and try again."
msgstr "Wenn Sie sicher sind, dass noch kein Backup läuft, entfernen Sie die Datei »%s« und versuchen Sie es noch einmal."
-#: access/transam/xlog.c:10131 access/transam/xlog.c:10169
-#: access/transam/xlog.c:10499
+#: access/transam/xlog.c:10479 access/transam/xlog.c:10517
+#: access/transam/xlog.c:10893 postmaster/syslogger.c:1391
+#: postmaster/syslogger.c:1404
#, c-format
msgid "could not write file \"%s\": %m"
msgstr "konnte Datei »%s« nicht schreiben: %m"
-#: access/transam/xlog.c:10288
+#: access/transam/xlog.c:10666
#, c-format
msgid "exclusive backup not in progress"
msgstr "es läuft kein exklusives Backup"
-#: access/transam/xlog.c:10328
+#: access/transam/xlog.c:10693
#, c-format
msgid "a backup is not in progress"
msgstr "es läuft kein Backup"
-#: access/transam/xlog.c:10373 access/transam/xlog.c:10386
-#: access/transam/xlog.c:10726 access/transam/xlog.c:10732
-#: access/transam/xlog.c:10816 access/transam/xlogfuncs.c:695
+#: access/transam/xlog.c:10767 access/transam/xlog.c:10780
+#: access/transam/xlog.c:11120 access/transam/xlog.c:11126
+#: access/transam/xlog.c:11210 access/transam/xlogfuncs.c:694
#, c-format
msgid "invalid data in file \"%s\""
msgstr "ungültige Daten in Datei »%s«"
-#: access/transam/xlog.c:10390 replication/basebackup.c:936
+#: access/transam/xlog.c:10784 replication/basebackup.c:994
#, c-format
msgid "the standby was promoted during online backup"
msgstr "der Standby-Server wurde während der Online-Sicherung zum Primärserver befördert"
-#: access/transam/xlog.c:10391 replication/basebackup.c:937
+#: access/transam/xlog.c:10785 replication/basebackup.c:995
#, c-format
msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup."
msgstr "Das bedeutet, dass die aktuelle Online-Sicherung verfälscht ist und nicht verwendet werden sollte. Versuchen Sie, eine neue Online-Sicherung durchzuführen."
-#: access/transam/xlog.c:10436
+#: access/transam/xlog.c:10830
#, c-format
msgid "WAL generated with full_page_writes=off was replayed during online backup"
msgstr "mit full_page_writes=off erzeugtes WAL wurde während der Online-Sicherung zurückgespielt"
-#: access/transam/xlog.c:10548
+#: access/transam/xlog.c:10942
#, c-format
msgid "pg_stop_backup cleanup done, waiting for required WAL segments to be archived"
msgstr "Aufräumen nach pg_stop_backup beendet, warte bis die benötigten WAL-Segmente archiviert sind"
-#: access/transam/xlog.c:10558
+#: access/transam/xlog.c:10952
#, c-format
msgid "pg_stop_backup still waiting for all required WAL segments to be archived (%d seconds elapsed)"
msgstr "pg_stop_backup wartet immer noch, bis alle benötigten WAL-Segmente archiviert sind (%d Sekunden abgelaufen)"
-#: access/transam/xlog.c:10560
+#: access/transam/xlog.c:10954
#, c-format
msgid "Check that your archive_command is executing properly. pg_stop_backup can be canceled safely, but the database backup will not be usable without all the WAL segments."
msgstr "Prüfen Sie, ob das archive_command korrekt ausgeführt wird. pg_stop_backup kann gefahrlos abgebrochen werden, aber die Datenbanksicherung wird ohne die fehlenden WAL-Segmente nicht benutzbar sein."
-#: access/transam/xlog.c:10567
+#: access/transam/xlog.c:10961
#, c-format
msgid "pg_stop_backup complete, all required WAL segments have been archived"
msgstr "pg_stop_backup abgeschlossen, alle benötigten WAL-Segmente wurden archiviert"
-#: access/transam/xlog.c:10571
+#: access/transam/xlog.c:10965
#, c-format
msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup"
msgstr "WAL-Archivierung ist nicht eingeschaltet; Sie müssen dafür sorgen, dass alle benötigten WAL-Segmente auf andere Art kopiert werden, um die Sicherung abzuschließen"
-#. translator: %s is an XLog record description
-#: access/transam/xlog.c:10856
+#. translator: %s is a WAL record description
+#: access/transam/xlog.c:11250
#, c-format
-msgid "xlog redo at %X/%X for %s"
-msgstr "xlog redo bei %X/%X für %s"
+msgid "WAL redo at %X/%X for %s"
+msgstr "WAL-Redo bei %X/%X für %s"
-#: access/transam/xlog.c:10905
+#: access/transam/xlog.c:11299
#, c-format
msgid "online backup mode was not canceled"
msgstr "Online-Sicherungsmodus wurde nicht storniert"
-#: access/transam/xlog.c:10906
+#: access/transam/xlog.c:11300
#, c-format
msgid "File \"%s\" could not be renamed to \"%s\": %m."
msgstr "Konnte Datei »%s« nicht in »%s« umbenennen: %m."
-#: access/transam/xlog.c:10915 access/transam/xlog.c:10927
-#: access/transam/xlog.c:10937
+#: access/transam/xlog.c:11309 access/transam/xlog.c:11321
+#: access/transam/xlog.c:11331
#, c-format
msgid "online backup mode canceled"
msgstr "Online-Sicherungsmodus storniert"
-#: access/transam/xlog.c:10928
+#: access/transam/xlog.c:11322
#, c-format
msgid "Files \"%s\" and \"%s\" were renamed to \"%s\" and \"%s\", respectively."
msgstr "Dateien »%s« und »%s« wurden in »%s« und »%s« umbenannt."
-#: access/transam/xlog.c:10938
+#: access/transam/xlog.c:11332
#, c-format
msgid "File \"%s\" was renamed to \"%s\", but file \"%s\" could not be renamed to \"%s\": %m."
msgstr "Datei »%s« wurde in »%s« umbenannt, aber Datei »%s« konnte nicht in »%s« umbenannt werden: %m."
-#: access/transam/xlog.c:11060 access/transam/xlogutils.c:718
-#: replication/walreceiver.c:994 replication/walsender.c:2116
+#: access/transam/xlog.c:11454 access/transam/xlogutils.c:719
+#: replication/walreceiver.c:1005 replication/walsender.c:2067
#, c-format
msgid "could not seek in log segment %s to offset %u: %m"
msgstr "konnte Positionszeiger von Logsegment %s nicht auf %u setzen: %m"
-#: access/transam/xlog.c:11072
+#: access/transam/xlog.c:11466
#, c-format
msgid "could not read from log segment %s, offset %u: %m"
msgstr "konnte nicht aus Logsegment %s, Position %u lesen: %m"
-#: access/transam/xlog.c:11546
+#: access/transam/xlog.c:11940
#, c-format
msgid "received promote request"
msgstr "Anforderung zum Befördern empfangen"
-#: access/transam/xlog.c:11559
+#: access/transam/xlog.c:11953
#, c-format
msgid "trigger file found: %s"
msgstr "Triggerdatei gefunden: %s"
-#: access/transam/xlog.c:11568
+#: access/transam/xlog.c:11962
#, c-format
msgid "could not stat trigger file \"%s\": %m"
msgstr "konnte »stat« für Trigger-Datei »%s« nicht ausführen: %m"
-#: access/transam/xlogarchive.c:244
+#: access/transam/xlogarchive.c:243
#, c-format
msgid "archive file \"%s\" has wrong size: %lu instead of %lu"
msgstr "Archivdatei »%s« hat falsche Größe: %lu statt %lu"
-#: access/transam/xlogarchive.c:253
+#: access/transam/xlogarchive.c:252
#, c-format
msgid "restored log file \"%s\" from archive"
msgstr "Logdatei »%s« aus Archiv wiederhergestellt"
-#: access/transam/xlogarchive.c:303
+#: access/transam/xlogarchive.c:302
#, c-format
msgid "could not restore file \"%s\" from archive: %s"
msgstr "konnte Datei »%s« nicht aus Archiv wiederherstellen: %s"
@@ -2687,124 +2750,125 @@ msgstr "konnte Datei »%s« nicht aus Archiv wiederherstellen: %s"
#. translator: First %s represents a recovery.conf parameter name like
#. "recovery_end_command", the 2nd is the value of that parameter, the
#. third an already translated error message.
-#: access/transam/xlogarchive.c:415
+#: access/transam/xlogarchive.c:414
#, c-format
msgid "%s \"%s\": %s"
msgstr "%s »%s«: %s"
-#: access/transam/xlogarchive.c:458 replication/logical/snapbuild.c:1621
-#: replication/slot.c:470 replication/slot.c:982 replication/slot.c:1090
-#: storage/file/fd.c:635 storage/file/fd.c:693 utils/time/snapmgr.c:1246
+#: access/transam/xlogarchive.c:457 postmaster/syslogger.c:1415
+#: replication/logical/snapbuild.c:1618 replication/slot.c:517
+#: replication/slot.c:1029 replication/slot.c:1137 storage/file/fd.c:642
+#: storage/file/fd.c:700 utils/time/snapmgr.c:1298
#, c-format
msgid "could not rename file \"%s\" to \"%s\": %m"
msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m"
-#: access/transam/xlogarchive.c:525 access/transam/xlogarchive.c:589
+#: access/transam/xlogarchive.c:524 access/transam/xlogarchive.c:588
#, c-format
msgid "could not create archive status file \"%s\": %m"
msgstr "konnte Archivstatusdatei »%s« nicht erstellen: %m"
-#: access/transam/xlogarchive.c:533 access/transam/xlogarchive.c:597
+#: access/transam/xlogarchive.c:532 access/transam/xlogarchive.c:596
#, c-format
msgid "could not write archive status file \"%s\": %m"
msgstr "konnte Archivstatusdatei »%s« nicht schreiben: %m"
-#: access/transam/xlogfuncs.c:58
+#: access/transam/xlogfuncs.c:57
#, c-format
msgid "aborting backup due to backend exiting before pg_stop_backup was called"
msgstr "Backup wird abgebrochen, weil Backend-Prozess beendete, bevor pg_stop_backup aufgerufen wurde"
-#: access/transam/xlogfuncs.c:88
+#: access/transam/xlogfuncs.c:87
#, c-format
msgid "a backup is already in progress in this session"
msgstr "ein Backup läuft bereits in dieser Sitzung"
-#: access/transam/xlogfuncs.c:94 commands/tablespace.c:705
-#: commands/tablespace.c:715 postmaster/postmaster.c:1398
-#: replication/basebackup.c:295 replication/basebackup.c:635
-#: storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2292
-#: storage/file/fd.c:2891 storage/ipc/dsm.c:300 utils/adt/genfile.c:439
-#: utils/adt/misc.c:411 utils/misc/tzparser.c:339
+#: access/transam/xlogfuncs.c:93 commands/tablespace.c:703
+#: commands/tablespace.c:713 postmaster/postmaster.c:1434
+#: replication/basebackup.c:368 replication/basebackup.c:708
+#: storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2369
+#: storage/file/fd.c:2968 storage/ipc/dsm.c:301 utils/adt/genfile.c:439
+#: utils/adt/misc.c:410 utils/misc/tzparser.c:339
#, c-format
msgid "could not open directory \"%s\": %m"
msgstr "konnte Verzeichnis »%s« nicht öffnen: %m"
-#: access/transam/xlogfuncs.c:155 access/transam/xlogfuncs.c:229
+#: access/transam/xlogfuncs.c:154 access/transam/xlogfuncs.c:228
#, c-format
msgid "non-exclusive backup in progress"
msgstr "es läuft ein nicht-exklusives Backup"
-#: access/transam/xlogfuncs.c:156 access/transam/xlogfuncs.c:230
+#: access/transam/xlogfuncs.c:155 access/transam/xlogfuncs.c:229
#, c-format
msgid "Did you mean to use pg_stop_backup('f')?"
msgstr "Meinten Sie pg_stop_backup('f')?"
-#: access/transam/xlogfuncs.c:200 commands/event_trigger.c:1449
-#: commands/event_trigger.c:2000 commands/extension.c:1728
-#: commands/extension.c:1837 commands/extension.c:2030 commands/prepare.c:702
-#: executor/execQual.c:1757 executor/execQual.c:1782 executor/execQual.c:2157
-#: executor/execQual.c:5411 executor/functions.c:1024 foreign/foreign.c:492
-#: replication/logical/logicalfuncs.c:175 replication/logical/origin.c:1391
-#: replication/slotfuncs.c:189 replication/walsender.c:2765
-#: utils/adt/jsonfuncs.c:1483 utils/adt/jsonfuncs.c:1615
-#: utils/adt/jsonfuncs.c:1805 utils/adt/jsonfuncs.c:1934
-#: utils/adt/jsonfuncs.c:2702 utils/adt/pgstatfuncs.c:554
-#: utils/adt/pgstatfuncs.c:655 utils/fmgr/funcapi.c:61 utils/misc/guc.c:8426
-#: utils/mmgr/portalmem.c:1080
+#: access/transam/xlogfuncs.c:199 commands/event_trigger.c:1450
+#: commands/event_trigger.c:2001 commands/extension.c:1889
+#: commands/extension.c:1998 commands/extension.c:2222 commands/prepare.c:718
+#: executor/execQual.c:1312 executor/functions.c:1024 foreign/foreign.c:488
+#: libpq/hba.c:2414 replication/logical/launcher.c:680
+#: replication/logical/logicalfuncs.c:176 replication/logical/origin.c:1384
+#: replication/slotfuncs.c:196 replication/walsender.c:2716
+#: utils/adt/jsonfuncs.c:1484 utils/adt/jsonfuncs.c:1614
+#: utils/adt/jsonfuncs.c:1802 utils/adt/jsonfuncs.c:1929
+#: utils/adt/jsonfuncs.c:2695 utils/adt/pgstatfuncs.c:454
+#: utils/adt/pgstatfuncs.c:555 utils/fmgr/funcapi.c:62 utils/misc/guc.c:8501
+#: utils/mmgr/portalmem.c:1053
#, c-format
msgid "set-valued function called in context that cannot accept a set"
msgstr "Funktion mit Mengenergebnis in einem Zusammenhang aufgerufen, der keine Mengenergebnisse verarbeiten kann"
-#: access/transam/xlogfuncs.c:204 commands/event_trigger.c:1453
-#: commands/event_trigger.c:2004 commands/extension.c:1732
-#: commands/extension.c:1841 commands/extension.c:2034 commands/prepare.c:706
-#: foreign/foreign.c:497 replication/logical/logicalfuncs.c:179
-#: replication/logical/origin.c:1395 replication/slotfuncs.c:193
-#: replication/walsender.c:2769 utils/adt/pgstatfuncs.c:558
-#: utils/adt/pgstatfuncs.c:659 utils/misc/guc.c:8430 utils/misc/pg_config.c:44
-#: utils/mmgr/portalmem.c:1084
+#: access/transam/xlogfuncs.c:203 commands/event_trigger.c:1454
+#: commands/event_trigger.c:2005 commands/extension.c:1893
+#: commands/extension.c:2002 commands/extension.c:2226 commands/prepare.c:722
+#: foreign/foreign.c:493 libpq/hba.c:2418 replication/logical/launcher.c:684
+#: replication/logical/logicalfuncs.c:180 replication/logical/origin.c:1388
+#: replication/slotfuncs.c:200 replication/walsender.c:2720
+#: utils/adt/pgstatfuncs.c:458 utils/adt/pgstatfuncs.c:559
+#: utils/misc/guc.c:8505 utils/misc/pg_config.c:44 utils/mmgr/portalmem.c:1057
#, c-format
msgid "materialize mode required, but it is not allowed in this context"
msgstr "Materialisierungsmodus wird benötigt, ist aber in diesem Zusammenhang nicht erlaubt"
-#: access/transam/xlogfuncs.c:247
+#: access/transam/xlogfuncs.c:246
#, c-format
msgid "non-exclusive backup is not in progress"
msgstr "es läuft kein nicht-exklusives Backup"
-#: access/transam/xlogfuncs.c:248
+#: access/transam/xlogfuncs.c:247
#, c-format
msgid "Did you mean to use pg_stop_backup('t')?"
msgstr "Meinten Sie pg_stop_backup('t')?"
-#: access/transam/xlogfuncs.c:326
+#: access/transam/xlogfuncs.c:325
#, c-format
msgid "WAL level not sufficient for creating a restore point"
msgstr "WAL-Level nicht ausreichend, um Restore-Punkt anzulegen"
-#: access/transam/xlogfuncs.c:334
+#: access/transam/xlogfuncs.c:333
#, c-format
msgid "value too long for restore point (maximum %d characters)"
msgstr "Wert zu lang für Restore-Punkt (maximal %d Zeichen)"
-#: access/transam/xlogfuncs.c:472
+#: access/transam/xlogfuncs.c:471
#, c-format
-msgid "pg_xlogfile_name_offset() cannot be executed during recovery."
-msgstr "pg_xlogfile_name_offset() kann nicht während der Wiederherstellung ausgeführt werden."
+msgid "pg_walfile_name_offset() cannot be executed during recovery."
+msgstr "pg_walfile_name_offset() kann nicht während der Wiederherstellung ausgeführt werden."
-#: access/transam/xlogfuncs.c:528
+#: access/transam/xlogfuncs.c:527
#, c-format
-msgid "pg_xlogfile_name() cannot be executed during recovery."
-msgstr "pg_xlogfile_name() kann nicht während der Wiederherstellung ausgeführt werden."
+msgid "pg_walfile_name() cannot be executed during recovery."
+msgstr "pg_walfile_name() kann nicht während der Wiederherstellung ausgeführt werden."
-#: access/transam/xlogfuncs.c:548 access/transam/xlogfuncs.c:568
-#: access/transam/xlogfuncs.c:585
+#: access/transam/xlogfuncs.c:547 access/transam/xlogfuncs.c:567
+#: access/transam/xlogfuncs.c:584
#, c-format
msgid "recovery is not in progress"
msgstr "Wiederherstellung läuft nicht"
-#: access/transam/xlogfuncs.c:549 access/transam/xlogfuncs.c:569
-#: access/transam/xlogfuncs.c:586
+#: access/transam/xlogfuncs.c:548 access/transam/xlogfuncs.c:568
+#: access/transam/xlogfuncs.c:585
#, c-format
msgid "Recovery control functions can only be executed during recovery."
msgstr "Wiederherstellungskontrollfunktionen können nur während der Wiederherstellung ausgeführt werden."
@@ -2819,7 +2883,7 @@ msgstr "ungültiger Datensatz-Offset bei %X/%X"
msgid "contrecord is requested by %X/%X"
msgstr "Contrecord angefordert von %X/%X"
-#: access/transam/xlogreader.c:325 access/transam/xlogreader.c:624
+#: access/transam/xlogreader.c:325 access/transam/xlogreader.c:625
#, c-format
msgid "invalid record length at %X/%X: wanted %u, got %u"
msgstr "ungültige Datensatzlänge bei %X/%X: %u erwartet, %u erhalten"
@@ -2839,704 +2903,744 @@ msgstr "keine Contrecord-Flag bei %X/%X"
msgid "invalid contrecord length %u at %X/%X"
msgstr "ungültige Contrecord-Länge %u bei %X/%X"
-#: access/transam/xlogreader.c:632
+#: access/transam/xlogreader.c:633
#, c-format
msgid "invalid resource manager ID %u at %X/%X"
msgstr "ungültige Resource-Manager-ID %u bei %X/%X"
-#: access/transam/xlogreader.c:646 access/transam/xlogreader.c:663
+#: access/transam/xlogreader.c:647 access/transam/xlogreader.c:664
#, c-format
msgid "record with incorrect prev-link %X/%X at %X/%X"
msgstr "Datensatz mit falschem Prev-Link %X/%X bei %X/%X"
-#: access/transam/xlogreader.c:700
+#: access/transam/xlogreader.c:701
#, c-format
msgid "incorrect resource manager data checksum in record at %X/%X"
msgstr "ungültige Resource-Manager-Datenprüfsumme in Datensatz bei %X/%X"
-#: access/transam/xlogreader.c:733
+#: access/transam/xlogreader.c:734
#, c-format
msgid "invalid magic number %04X in log segment %s, offset %u"
msgstr "ungültige magische Zahl %04X in Logsegment %s, Offset %u"
-#: access/transam/xlogreader.c:747 access/transam/xlogreader.c:798
+#: access/transam/xlogreader.c:748 access/transam/xlogreader.c:799
#, c-format
msgid "invalid info bits %04X in log segment %s, offset %u"
msgstr "ungültige Info-Bits %04X in Logsegment %s, Offset %u"
-#: access/transam/xlogreader.c:773
+#: access/transam/xlogreader.c:774
#, c-format
msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s"
msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Datenbanksystemidentifikator in WAL-Datei ist %s, Datenbanksystemidentifikator in pg_control ist %s"
-#: access/transam/xlogreader.c:780
+#: access/transam/xlogreader.c:781
#, c-format
msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header"
msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Falsche XLOG_SEG_SIZE im Seitenkopf"
-#: access/transam/xlogreader.c:786
+#: access/transam/xlogreader.c:787
#, c-format
msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Falsche XLOG_BLCKSZ im Seitenkopf"
-#: access/transam/xlogreader.c:812
+#: access/transam/xlogreader.c:813
#, c-format
msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
msgstr "unerwartete Pageaddr %X/%X in Logsegment %s, Offset %u"
-#: access/transam/xlogreader.c:837
+#: access/transam/xlogreader.c:838
#, c-format
msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
msgstr "Zeitleisten-ID %u außer der Reihe (nach %u) in Logsegment %s, Offset %u"
-#: access/transam/xlogreader.c:1044
+#: access/transam/xlogreader.c:1083
#, c-format
msgid "out-of-order block_id %u at %X/%X"
msgstr "block_id %u außer der Reihe bei %X/%X"
-#: access/transam/xlogreader.c:1066
+#: access/transam/xlogreader.c:1106
#, c-format
msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
msgstr "BKPBLOCK_HAS_DATA gesetzt, aber keine Daten enthalten bei %X/%X"
-#: access/transam/xlogreader.c:1073
+#: access/transam/xlogreader.c:1113
#, c-format
msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
msgstr "BKPBLOCK_HAS_DATA nicht gesetzt, aber Datenlänge ist %u bei %X/%X"
-#: access/transam/xlogreader.c:1106
+#: access/transam/xlogreader.c:1149
#, c-format
msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
msgstr "BKPIMAGE_HAS_HOLE gesetzt, aber Loch Offset %u Länge %u Block-Abbild-Länge %u bei %X/%X"
-#: access/transam/xlogreader.c:1122
+#: access/transam/xlogreader.c:1165
#, c-format
msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
msgstr "BKPIMAGE_HAS_HOLE nicht gesetzt, aber Loch Offset %u Länge %u bei %X/%X"
-#: access/transam/xlogreader.c:1137
+#: access/transam/xlogreader.c:1180
#, c-format
msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
msgstr "BKPIMAGE_IS_COMPRESSED gesetzt, aber Block-Abbild-Länge %u bei %X/%X"
-#: access/transam/xlogreader.c:1152
+#: access/transam/xlogreader.c:1195
#, c-format
msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
msgstr "weder BKPIMAGE_HAS_HOLE noch BKPIMAGE_IS_COMPRESSED gesetzt, aber Block-Abbild-Länge ist %u bei %X/%X"
-#: access/transam/xlogreader.c:1168
+#: access/transam/xlogreader.c:1211
#, c-format
msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
msgstr "BKPBLOCK_SAME_REL gesetzt, aber keine vorangehende Relation bei %X/%X"
-#: access/transam/xlogreader.c:1180
+#: access/transam/xlogreader.c:1223
#, c-format
msgid "invalid block_id %u at %X/%X"
msgstr "ungültige block_id %u bei %X/%X"
-#: access/transam/xlogreader.c:1245
+#: access/transam/xlogreader.c:1291
#, c-format
msgid "record with invalid length at %X/%X"
msgstr "Datensatz mit ungültiger Länge bei %X/%X"
-#: access/transam/xlogreader.c:1334
+#: access/transam/xlogreader.c:1380
#, c-format
msgid "invalid compressed image at %X/%X, block %d"
msgstr "ungültiges komprimiertes Abbild bei %X/%X, Block %d"
-#: access/transam/xlogutils.c:739 replication/walsender.c:2133
+#: access/transam/xlogutils.c:740 replication/walsender.c:2084
#, c-format
msgid "could not read from log segment %s, offset %u, length %lu: %m"
msgstr "konnte nicht aus Logsegment %s bei Position %u, Länge %lu lesen: %m"
-#: bootstrap/bootstrap.c:269 postmaster/postmaster.c:785 tcop/postgres.c:3503
+#: bootstrap/bootstrap.c:271 postmaster/postmaster.c:801 tcop/postgres.c:3489
#, c-format
msgid "--%s requires a value"
msgstr "--%s benötigt einen Wert"
-#: bootstrap/bootstrap.c:274 postmaster/postmaster.c:790 tcop/postgres.c:3508
+#: bootstrap/bootstrap.c:276 postmaster/postmaster.c:806 tcop/postgres.c:3494
#, c-format
msgid "-c %s requires a value"
msgstr "-c %s benötigt einen Wert"
-#: bootstrap/bootstrap.c:285 postmaster/postmaster.c:802
-#: postmaster/postmaster.c:815
+#: bootstrap/bootstrap.c:287 postmaster/postmaster.c:818
+#: postmaster/postmaster.c:831
#, c-format
msgid "Try \"%s --help\" for more information.\n"
msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n"
-#: bootstrap/bootstrap.c:294
+#: bootstrap/bootstrap.c:296
#, c-format
msgid "%s: invalid command-line arguments\n"
msgstr "%s: ungültige Kommandozeilenargumente\n"
-#: catalog/aclchk.c:193
+#: catalog/aclchk.c:202
#, c-format
msgid "grant options can only be granted to roles"
msgstr "Grant-Optionen können nur Rollen gewährt werden"
-#: catalog/aclchk.c:316
+#: catalog/aclchk.c:325
#, c-format
msgid "no privileges were granted for column \"%s\" of relation \"%s\""
msgstr "es wurden keine Privilegien für Spalte »%s« von Relation »%s« gewährt"
-#: catalog/aclchk.c:321
+#: catalog/aclchk.c:330
#, c-format
msgid "no privileges were granted for \"%s\""
msgstr "es wurden keine Privilegien für »%s« gewährt"
-#: catalog/aclchk.c:329
+#: catalog/aclchk.c:338
#, c-format
msgid "not all privileges were granted for column \"%s\" of relation \"%s\""
msgstr "es wurden nicht alle Priviligien für Spalte »%s« von Relation »%s« gewährt"
-#: catalog/aclchk.c:334
+#: catalog/aclchk.c:343
#, c-format
msgid "not all privileges were granted for \"%s\""
msgstr "es wurden nicht alle Priviligien für »%s« gewährt"
-#: catalog/aclchk.c:345
+#: catalog/aclchk.c:354
#, c-format
msgid "no privileges could be revoked for column \"%s\" of relation \"%s\""
msgstr "es konnten keine Privilegien für Spalte »%s« von Relation »%s« entzogen werden"
-#: catalog/aclchk.c:350
+#: catalog/aclchk.c:359
#, c-format
msgid "no privileges could be revoked for \"%s\""
msgstr "es konnten keine Privilegien für »%s« entzogen werden"
-#: catalog/aclchk.c:358
+#: catalog/aclchk.c:367
#, c-format
msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\""
msgstr "es konnten nicht alle Privilegien für Spalte »%s« von Relation »%s« entzogen werden"
-#: catalog/aclchk.c:363
+#: catalog/aclchk.c:372
#, c-format
msgid "not all privileges could be revoked for \"%s\""
msgstr "es konnten nicht alle Privilegien für »%s« entzogen werden"
-#: catalog/aclchk.c:445 catalog/aclchk.c:935
+#: catalog/aclchk.c:454 catalog/aclchk.c:947
#, c-format
msgid "invalid privilege type %s for relation"
msgstr "ungültiger Privilegtyp %s für Relation"
-#: catalog/aclchk.c:449 catalog/aclchk.c:939
+#: catalog/aclchk.c:458 catalog/aclchk.c:951
#, c-format
msgid "invalid privilege type %s for sequence"
msgstr "ungültiger Privilegtyp %s für Sequenz"
-#: catalog/aclchk.c:453
+#: catalog/aclchk.c:462
#, c-format
msgid "invalid privilege type %s for database"
msgstr "ungültiger Privilegtyp %s für Datenbank"
-#: catalog/aclchk.c:457
+#: catalog/aclchk.c:466
#, c-format
msgid "invalid privilege type %s for domain"
msgstr "ungültiger Privilegtyp %s für Domäne"
-#: catalog/aclchk.c:461 catalog/aclchk.c:943
+#: catalog/aclchk.c:470 catalog/aclchk.c:955
#, c-format
msgid "invalid privilege type %s for function"
msgstr "ungültiger Privilegtyp %s für Funktion"
-#: catalog/aclchk.c:465
+#: catalog/aclchk.c:474
#, c-format
msgid "invalid privilege type %s for language"
msgstr "ungültiger Privilegtyp %s für Sprache"
-#: catalog/aclchk.c:469
+#: catalog/aclchk.c:478
#, c-format
msgid "invalid privilege type %s for large object"
msgstr "ungültiger Privilegtyp %s für Large Object"
-#: catalog/aclchk.c:473
+#: catalog/aclchk.c:482
#, c-format
msgid "invalid privilege type %s for schema"
msgstr "ungültiger Privilegtyp %s für Schema"
-#: catalog/aclchk.c:477
+#: catalog/aclchk.c:486
#, c-format
msgid "invalid privilege type %s for tablespace"
msgstr "ungültiger Privilegtyp %s für Tablespace"
-#: catalog/aclchk.c:481 catalog/aclchk.c:947
+#: catalog/aclchk.c:490 catalog/aclchk.c:959
#, c-format
msgid "invalid privilege type %s for type"
msgstr "ungültiger Privilegtyp %s für Typ"
-#: catalog/aclchk.c:485
+#: catalog/aclchk.c:494
#, c-format
msgid "invalid privilege type %s for foreign-data wrapper"
msgstr "ungültiger Privilegtyp %s für Fremddaten-Wrapper"
-#: catalog/aclchk.c:489
+#: catalog/aclchk.c:498
#, c-format
msgid "invalid privilege type %s for foreign server"
msgstr "ungültiger Privilegtyp %s für Fremdserver"
-#: catalog/aclchk.c:528
+#: catalog/aclchk.c:537
#, c-format
msgid "column privileges are only valid for relations"
msgstr "Spaltenprivilegien sind nur für Relation gültig"
-#: catalog/aclchk.c:687 catalog/aclchk.c:3915 catalog/aclchk.c:4697
-#: catalog/objectaddress.c:873 catalog/pg_largeobject.c:113
+#: catalog/aclchk.c:695 catalog/aclchk.c:3900 catalog/aclchk.c:4682
+#: catalog/objectaddress.c:912 catalog/pg_largeobject.c:111
#: storage/large_object/inv_api.c:291
#, c-format
msgid "large object %u does not exist"
msgstr "Large Object %u existiert nicht"
-#: catalog/aclchk.c:874 catalog/aclchk.c:882 commands/collationcmds.c:92
-#: commands/copy.c:1008 commands/copy.c:1026 commands/copy.c:1034
-#: commands/copy.c:1042 commands/copy.c:1050 commands/copy.c:1058
-#: commands/copy.c:1066 commands/copy.c:1074 commands/copy.c:1082
-#: commands/copy.c:1098 commands/copy.c:1112 commands/copy.c:1131
-#: commands/copy.c:1146 commands/dbcommands.c:155 commands/dbcommands.c:163
-#: commands/dbcommands.c:171 commands/dbcommands.c:179
-#: commands/dbcommands.c:187 commands/dbcommands.c:195
-#: commands/dbcommands.c:203 commands/dbcommands.c:211
-#: commands/dbcommands.c:219 commands/dbcommands.c:1397
-#: commands/dbcommands.c:1405 commands/dbcommands.c:1413
-#: commands/dbcommands.c:1421 commands/extension.c:1218
-#: commands/extension.c:1226 commands/extension.c:1234
-#: commands/extension.c:1242 commands/extension.c:2760
-#: commands/foreigncmds.c:539 commands/foreigncmds.c:548
-#: commands/functioncmds.c:533 commands/functioncmds.c:649
-#: commands/functioncmds.c:657 commands/functioncmds.c:665
-#: commands/functioncmds.c:673 commands/functioncmds.c:2085
-#: commands/functioncmds.c:2093 commands/sequence.c:1189
-#: commands/sequence.c:1197 commands/sequence.c:1205 commands/sequence.c:1213
-#: commands/sequence.c:1221 commands/sequence.c:1229 commands/sequence.c:1237
-#: commands/sequence.c:1245 commands/typecmds.c:295 commands/typecmds.c:1382
-#: commands/typecmds.c:1391 commands/typecmds.c:1399 commands/typecmds.c:1407
-#: commands/typecmds.c:1415 commands/user.c:139 commands/user.c:156
-#: commands/user.c:164 commands/user.c:172 commands/user.c:180
-#: commands/user.c:188 commands/user.c:196 commands/user.c:204
-#: commands/user.c:212 commands/user.c:220 commands/user.c:228
-#: commands/user.c:236 commands/user.c:244 commands/user.c:537
-#: commands/user.c:549 commands/user.c:557 commands/user.c:565
-#: commands/user.c:573 commands/user.c:581 commands/user.c:589
-#: commands/user.c:597 commands/user.c:606 commands/user.c:614
-#: commands/user.c:622
+#: catalog/aclchk.c:884 catalog/aclchk.c:893 commands/collationcmds.c:92
+#: commands/copy.c:1039 commands/copy.c:1059 commands/copy.c:1068
+#: commands/copy.c:1077 commands/copy.c:1086 commands/copy.c:1095
+#: commands/copy.c:1104 commands/copy.c:1113 commands/copy.c:1122
+#: commands/copy.c:1140 commands/copy.c:1156 commands/copy.c:1176
+#: commands/copy.c:1193 commands/dbcommands.c:155 commands/dbcommands.c:164
+#: commands/dbcommands.c:173 commands/dbcommands.c:182
+#: commands/dbcommands.c:191 commands/dbcommands.c:200
+#: commands/dbcommands.c:209 commands/dbcommands.c:218
+#: commands/dbcommands.c:227 commands/dbcommands.c:1419
+#: commands/dbcommands.c:1428 commands/dbcommands.c:1437
+#: commands/dbcommands.c:1446 commands/extension.c:1672
+#: commands/extension.c:1682 commands/extension.c:1692
+#: commands/extension.c:1702 commands/extension.c:2942
+#: commands/foreigncmds.c:537 commands/foreigncmds.c:546
+#: commands/functioncmds.c:526 commands/functioncmds.c:643
+#: commands/functioncmds.c:652 commands/functioncmds.c:661
+#: commands/functioncmds.c:670 commands/functioncmds.c:2076
+#: commands/functioncmds.c:2084 commands/publicationcmds.c:89
+#: commands/publicationcmds.c:99 commands/publicationcmds.c:109
+#: commands/publicationcmds.c:119 commands/publicationcmds.c:129
+#: commands/publicationcmds.c:139 commands/sequence.c:1247
+#: commands/sequence.c:1256 commands/sequence.c:1265 commands/sequence.c:1274
+#: commands/sequence.c:1283 commands/sequence.c:1292 commands/sequence.c:1301
+#: commands/sequence.c:1310 commands/sequence.c:1319
+#: commands/subscriptioncmds.c:83 commands/subscriptioncmds.c:92
+#: commands/subscriptioncmds.c:101 commands/subscriptioncmds.c:111
+#: commands/subscriptioncmds.c:121 commands/subscriptioncmds.c:131
+#: commands/subscriptioncmds.c:141 commands/typecmds.c:298
+#: commands/typecmds.c:1375 commands/typecmds.c:1384 commands/typecmds.c:1392
+#: commands/typecmds.c:1400 commands/typecmds.c:1408 commands/user.c:138
+#: commands/user.c:161 commands/user.c:170 commands/user.c:179
+#: commands/user.c:188 commands/user.c:197 commands/user.c:206
+#: commands/user.c:215 commands/user.c:224 commands/user.c:233
+#: commands/user.c:242 commands/user.c:251 commands/user.c:260
+#: commands/user.c:547 commands/user.c:564 commands/user.c:572
+#: commands/user.c:580 commands/user.c:588 commands/user.c:596
+#: commands/user.c:604 commands/user.c:612 commands/user.c:621
+#: commands/user.c:629 commands/user.c:637 replication/pgoutput/pgoutput.c:107
+#: replication/pgoutput/pgoutput.c:128
#, c-format
msgid "conflicting or redundant options"
msgstr "widersprüchliche oder überflüssige Optionen"
-#: catalog/aclchk.c:980
+#: catalog/aclchk.c:992
#, c-format
msgid "default privileges cannot be set for columns"
msgstr "Vorgabeprivilegien können nicht für Spalten gesetzt werden"
-#: catalog/aclchk.c:1494 catalog/objectaddress.c:1390 commands/analyze.c:378
-#: commands/copy.c:4423 commands/sequence.c:1491 commands/tablecmds.c:5197
-#: commands/tablecmds.c:5303 commands/tablecmds.c:5363
-#: commands/tablecmds.c:5476 commands/tablecmds.c:5533
-#: commands/tablecmds.c:5627 commands/tablecmds.c:5723
-#: commands/tablecmds.c:7875 commands/tablecmds.c:8080
-#: commands/tablecmds.c:8500 commands/trigger.c:642 parser/analyze.c:2231
-#: parser/parse_relation.c:2542 parser/parse_relation.c:2604
-#: parser/parse_target.c:940 parser/parse_type.c:127 utils/adt/acl.c:2840
-#: utils/adt/ruleutils.c:1981
+#: catalog/aclchk.c:1503 catalog/objectaddress.c:1367 commands/analyze.c:384
+#: commands/copy.c:4657 commands/sequence.c:1625 commands/tablecmds.c:5533
+#: commands/tablecmds.c:5694 commands/tablecmds.c:5751
+#: commands/tablecmds.c:5865 commands/tablecmds.c:5919
+#: commands/tablecmds.c:6011 commands/tablecmds.c:6167
+#: commands/tablecmds.c:8386 commands/tablecmds.c:8662
+#: commands/tablecmds.c:9079 commands/trigger.c:732 parser/analyze.c:2305
+#: parser/parse_relation.c:2575 parser/parse_relation.c:2637
+#: parser/parse_target.c:1001 parser/parse_type.c:127 utils/adt/acl.c:2823
+#: utils/adt/ruleutils.c:2188
#, c-format
msgid "column \"%s\" of relation \"%s\" does not exist"
msgstr "Spalte »%s« von Relation »%s« existiert nicht"
-#: catalog/aclchk.c:1763 catalog/objectaddress.c:1203 commands/sequence.c:1078
-#: commands/tablecmds.c:223 commands/tablecmds.c:12007 utils/adt/acl.c:2076
-#: utils/adt/acl.c:2106 utils/adt/acl.c:2138 utils/adt/acl.c:2170
-#: utils/adt/acl.c:2198 utils/adt/acl.c:2228
+#: catalog/aclchk.c:1769 catalog/objectaddress.c:1207 commands/sequence.c:1137
+#: commands/tablecmds.c:229 commands/tablecmds.c:12734 utils/adt/acl.c:2059
+#: utils/adt/acl.c:2089 utils/adt/acl.c:2121 utils/adt/acl.c:2153
+#: utils/adt/acl.c:2181 utils/adt/acl.c:2211
#, c-format
msgid "\"%s\" is not a sequence"
msgstr "»%s« ist keine Sequenz"
-#: catalog/aclchk.c:1801
+#: catalog/aclchk.c:1807
#, c-format
msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges"
msgstr "Sequenz »%s« unterstützt nur die Privilegien USAGE, SELECT und UPDATE"
-#: catalog/aclchk.c:1818
+#: catalog/aclchk.c:1824
#, c-format
-msgid "invalid privilege type USAGE for table"
-msgstr "ungültiger Privilegtyp USAGE für Tabelle"
+msgid "invalid privilege type %s for table"
+msgstr "ungültiger Privilegtyp %s für Tabelle"
-#: catalog/aclchk.c:1986
+#: catalog/aclchk.c:1990
#, c-format
msgid "invalid privilege type %s for column"
msgstr "ungültiger Privilegtyp %s für Spalte"
-#: catalog/aclchk.c:1999
+#: catalog/aclchk.c:2003
#, c-format
msgid "sequence \"%s\" only supports SELECT column privileges"
msgstr "Sequenz »%s« unterstützt nur den Spaltenprivilegientyp SELECT"
-#: catalog/aclchk.c:2593
+#: catalog/aclchk.c:2585
#, c-format
msgid "language \"%s\" is not trusted"
msgstr "Sprache »%s« ist nicht »trusted«"
-#: catalog/aclchk.c:2595
+#: catalog/aclchk.c:2587
#, c-format
msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages."
msgstr "GRANT und REVOKE sind für nicht vertrauenswürdige Sprachen nicht erlaubt, weil nur Superuser nicht vertrauenswürdige Sprachen verwenden können."
-#: catalog/aclchk.c:3121
+#: catalog/aclchk.c:3101
#, c-format
msgid "cannot set privileges of array types"
msgstr "für Array-Typen können keine Privilegien gesetzt werden"
-#: catalog/aclchk.c:3122
+#: catalog/aclchk.c:3102
#, c-format
msgid "Set the privileges of the element type instead."
msgstr "Setzen Sie stattdessen die Privilegien des Elementtyps."
-#: catalog/aclchk.c:3129 catalog/objectaddress.c:1523 commands/typecmds.c:3146
+#: catalog/aclchk.c:3109 catalog/objectaddress.c:1497 commands/typecmds.c:3165
#, c-format
msgid "\"%s\" is not a domain"
msgstr "»%s« ist keine Domäne"
-#: catalog/aclchk.c:3252
+#: catalog/aclchk.c:3229
#, c-format
msgid "unrecognized privilege type \"%s\""
msgstr "unbekannter Privilegtyp »%s«"
-#: catalog/aclchk.c:3301
+#: catalog/aclchk.c:3278
#, c-format
msgid "permission denied for column %s"
msgstr "keine Berechtigung für Spalte %s"
-#: catalog/aclchk.c:3303
+#: catalog/aclchk.c:3280
#, c-format
msgid "permission denied for relation %s"
msgstr "keine Berechtigung für Relation %s"
-#: catalog/aclchk.c:3305 commands/sequence.c:561 commands/sequence.c:786
-#: commands/sequence.c:828 commands/sequence.c:865 commands/sequence.c:1543
+#: catalog/aclchk.c:3282 commands/sequence.c:599 commands/sequence.c:833
+#: commands/sequence.c:875 commands/sequence.c:916 commands/sequence.c:1671
+#: commands/sequence.c:1735
#, c-format
msgid "permission denied for sequence %s"
msgstr "keine Berechtigung für Sequenz %s"
-#: catalog/aclchk.c:3307
+#: catalog/aclchk.c:3284
#, c-format
msgid "permission denied for database %s"
msgstr "keine Berechtigung für Datenbank %s"
-#: catalog/aclchk.c:3309
+#: catalog/aclchk.c:3286
#, c-format
msgid "permission denied for function %s"
msgstr "keine Berechtigung für Funktion %s"
-#: catalog/aclchk.c:3311
+#: catalog/aclchk.c:3288
#, c-format
msgid "permission denied for operator %s"
msgstr "keine Berechtigung für Operator %s"
-#: catalog/aclchk.c:3313
+#: catalog/aclchk.c:3290
#, c-format
msgid "permission denied for type %s"
msgstr "keine Berechtigung für Typ %s"
-#: catalog/aclchk.c:3315
+#: catalog/aclchk.c:3292
#, c-format
msgid "permission denied for language %s"
msgstr "keine Berechtigung für Sprache %s"
-#: catalog/aclchk.c:3317
+#: catalog/aclchk.c:3294
#, c-format
msgid "permission denied for large object %s"
msgstr "keine Berechtigung für Large Object %s"
-#: catalog/aclchk.c:3319
+#: catalog/aclchk.c:3296
#, c-format
msgid "permission denied for schema %s"
msgstr "keine Berechtigung für Schema %s"
-#: catalog/aclchk.c:3321
+#: catalog/aclchk.c:3298
#, c-format
msgid "permission denied for operator class %s"
msgstr "keine Berechtigung für Operatorklasse %s"
-#: catalog/aclchk.c:3323
+#: catalog/aclchk.c:3300
#, c-format
msgid "permission denied for operator family %s"
msgstr "keine Berechtigung für Operatorfamilie %s"
-#: catalog/aclchk.c:3325
+#: catalog/aclchk.c:3302
#, c-format
msgid "permission denied for collation %s"
msgstr "keine Berechtigung für Sortierfolge %s"
-#: catalog/aclchk.c:3327
+#: catalog/aclchk.c:3304
#, c-format
msgid "permission denied for conversion %s"
msgstr "keine Berechtigung für Konversion %s"
-#: catalog/aclchk.c:3329
+#: catalog/aclchk.c:3306
#, c-format
msgid "permission denied for tablespace %s"
msgstr "keine Berechtigung für Tablespace %s"
-#: catalog/aclchk.c:3331
+#: catalog/aclchk.c:3308
#, c-format
msgid "permission denied for text search dictionary %s"
msgstr "keine Berechtigung für Textsuchewörterbuch %s"
-#: catalog/aclchk.c:3333
+#: catalog/aclchk.c:3310
#, c-format
msgid "permission denied for text search configuration %s"
msgstr "keine Berechtigung für Textsuchekonfiguration %s"
-#: catalog/aclchk.c:3335
+#: catalog/aclchk.c:3312
#, c-format
msgid "permission denied for foreign-data wrapper %s"
msgstr "keine Berechtigung für Fremddaten-Wrapper %s"
-#: catalog/aclchk.c:3337
+#: catalog/aclchk.c:3314
#, c-format
msgid "permission denied for foreign server %s"
msgstr "keine Berechtigung für Fremdserver %s"
-#: catalog/aclchk.c:3339
+#: catalog/aclchk.c:3316
#, c-format
msgid "permission denied for event trigger %s"
msgstr "keine Berechtigung für Ereignistrigger %s"
-#: catalog/aclchk.c:3341
+#: catalog/aclchk.c:3318
#, c-format
msgid "permission denied for extension %s"
msgstr "keine Berechtigung für Erweiterung %s"
-#: catalog/aclchk.c:3347 catalog/aclchk.c:3349
+#: catalog/aclchk.c:3320
+#, c-format
+msgid "permission denied for publication %s"
+msgstr "keine Berechtigung für Publikation %s"
+
+#: catalog/aclchk.c:3322
+#, c-format
+msgid "permission denied for subscription %s"
+msgstr "keine Berechtigung für Subskription %s"
+
+#: catalog/aclchk.c:3328 catalog/aclchk.c:3330
#, c-format
msgid "must be owner of relation %s"
msgstr "Berechtigung nur für Eigentümer der Relation %s"
-#: catalog/aclchk.c:3351
+#: catalog/aclchk.c:3332
#, c-format
msgid "must be owner of sequence %s"
msgstr "Berechtigung nur für Eigentümer der Sequenz %s"
-#: catalog/aclchk.c:3353
+#: catalog/aclchk.c:3334
#, c-format
msgid "must be owner of database %s"
msgstr "Berechtigung nur für Eigentümer der Datenbank %s"
-#: catalog/aclchk.c:3355
+#: catalog/aclchk.c:3336
#, c-format
msgid "must be owner of function %s"
msgstr "Berechtigung nur für Eigentümer der Funktion %s"
-#: catalog/aclchk.c:3357
+#: catalog/aclchk.c:3338
#, c-format
msgid "must be owner of operator %s"
msgstr "Berechtigung nur für Eigentümer des Operators %s"
-#: catalog/aclchk.c:3359
+#: catalog/aclchk.c:3340
#, c-format
msgid "must be owner of type %s"
msgstr "Berechtigung nur für Eigentümer des Typs %s"
-#: catalog/aclchk.c:3361
+#: catalog/aclchk.c:3342
#, c-format
msgid "must be owner of language %s"
msgstr "Berechtigung nur für Eigentümer der Sprache %s"
-#: catalog/aclchk.c:3363
+#: catalog/aclchk.c:3344
#, c-format
msgid "must be owner of large object %s"
msgstr "Berechtigung nur für Eigentümer des Large Object %s"
-#: catalog/aclchk.c:3365
+#: catalog/aclchk.c:3346
#, c-format
msgid "must be owner of schema %s"
msgstr "Berechtigung nur für Eigentümer des Schemas %s"
-#: catalog/aclchk.c:3367
+#: catalog/aclchk.c:3348
#, c-format
msgid "must be owner of operator class %s"
msgstr "Berechtigung nur für Eigentümer der Operatorklasse %s"
-#: catalog/aclchk.c:3369
+#: catalog/aclchk.c:3350
#, c-format
msgid "must be owner of operator family %s"
msgstr "Berechtigung nur für Eigentümer der Operatorfamilie %s"
-#: catalog/aclchk.c:3371
+#: catalog/aclchk.c:3352
#, c-format
msgid "must be owner of collation %s"
msgstr "Berechtigung nur für Eigentümer der Sortierfolge %s"
-#: catalog/aclchk.c:3373
+#: catalog/aclchk.c:3354
#, c-format
msgid "must be owner of conversion %s"
msgstr "Berechtigung nur für Eigentümer der Konversion %s"
-#: catalog/aclchk.c:3375
+#: catalog/aclchk.c:3356
#, c-format
msgid "must be owner of tablespace %s"
msgstr "Berechtigung nur für Eigentümer des Tablespace %s"
-#: catalog/aclchk.c:3377
+#: catalog/aclchk.c:3358
#, c-format
msgid "must be owner of text search dictionary %s"
msgstr "Berechtigung nur für Eigentümer des Textsuchewörterbuches %s"
-#: catalog/aclchk.c:3379
+#: catalog/aclchk.c:3360
#, c-format
msgid "must be owner of text search configuration %s"
msgstr "Berechtigung nur für Eigentümer der Textsuchekonfiguration %s"
-#: catalog/aclchk.c:3381
+#: catalog/aclchk.c:3362
#, c-format
msgid "must be owner of foreign-data wrapper %s"
msgstr "Berechtigung nur für Eigentümer des Fremddaten-Wrappers %s"
-#: catalog/aclchk.c:3383
+#: catalog/aclchk.c:3364
#, c-format
msgid "must be owner of foreign server %s"
msgstr "Berechtigung nur für Eigentümer des Fremdservers %s"
-#: catalog/aclchk.c:3385
+#: catalog/aclchk.c:3366
#, c-format
msgid "must be owner of event trigger %s"
msgstr "Berechtigung nur für Eigentümer des Ereignistriggers %s"
-#: catalog/aclchk.c:3387
+#: catalog/aclchk.c:3368
#, c-format
msgid "must be owner of extension %s"
msgstr "Berechtigung nur für Eigentümer der Erweiterung %s"
-#: catalog/aclchk.c:3429
+#: catalog/aclchk.c:3370
+#, c-format
+msgid "must be owner of publication %s"
+msgstr "Berechtigung nur für Eigentümer der Publikation %s"
+
+#: catalog/aclchk.c:3372
+#, c-format
+msgid "must be owner of subscription %s"
+msgstr "Berechtigung nur für Eigentümer der Subskription %s"
+
+#: catalog/aclchk.c:3414
#, c-format
msgid "permission denied for column \"%s\" of relation \"%s\""
msgstr "keine Berechtigung für Spalte »%s« von Relation »%s«"
-#: catalog/aclchk.c:3548 catalog/aclchk.c:3556
+#: catalog/aclchk.c:3533 catalog/aclchk.c:3541
#, c-format
msgid "attribute %d of relation with OID %u does not exist"
msgstr "Attribut %d der Relation mit OID %u existiert nicht"
-#: catalog/aclchk.c:3629 catalog/aclchk.c:4548
+#: catalog/aclchk.c:3614 catalog/aclchk.c:4533
#, c-format
msgid "relation with OID %u does not exist"
msgstr "Relation mit OID %u existiert nicht"
-#: catalog/aclchk.c:3728 catalog/aclchk.c:4966
+#: catalog/aclchk.c:3713 catalog/aclchk.c:4951
#, c-format
msgid "database with OID %u does not exist"
msgstr "Datenbank mit OID %u existiert nicht"
-#: catalog/aclchk.c:3782 catalog/aclchk.c:4626 tcop/fastpath.c:223
+#: catalog/aclchk.c:3767 catalog/aclchk.c:4611 tcop/fastpath.c:223
+#: utils/fmgr/fmgr.c:2428
#, c-format
msgid "function with OID %u does not exist"
msgstr "Funktion mit OID %u existiert nicht"
-#: catalog/aclchk.c:3836 catalog/aclchk.c:4652
+#: catalog/aclchk.c:3821 catalog/aclchk.c:4637
#, c-format
msgid "language with OID %u does not exist"
msgstr "Sprache mit OID %u existiert nicht"
-#: catalog/aclchk.c:4000 catalog/aclchk.c:4724
+#: catalog/aclchk.c:3985 catalog/aclchk.c:4709
#, c-format
msgid "schema with OID %u does not exist"
msgstr "Schema mit OID %u existiert nicht"
-#: catalog/aclchk.c:4054 catalog/aclchk.c:4751
+#: catalog/aclchk.c:4039 catalog/aclchk.c:4736
#, c-format
msgid "tablespace with OID %u does not exist"
msgstr "Tablespace mit OID %u existiert nicht"
-#: catalog/aclchk.c:4113 catalog/aclchk.c:4885 commands/foreigncmds.c:325
+#: catalog/aclchk.c:4098 catalog/aclchk.c:4870 commands/foreigncmds.c:324
#, c-format
msgid "foreign-data wrapper with OID %u does not exist"
msgstr "Fremddaten-Wrapper mit OID %u existiert nicht"
-#: catalog/aclchk.c:4175 catalog/aclchk.c:4912 commands/foreigncmds.c:461
+#: catalog/aclchk.c:4160 catalog/aclchk.c:4897 commands/foreigncmds.c:459
#, c-format
msgid "foreign server with OID %u does not exist"
msgstr "Fremdserver mit OID %u existiert nicht"
-#: catalog/aclchk.c:4235 catalog/aclchk.c:4574
+#: catalog/aclchk.c:4220 catalog/aclchk.c:4559 utils/cache/typcache.c:238
#, c-format
msgid "type with OID %u does not exist"
msgstr "Typ mit OID %u existiert nicht"
-#: catalog/aclchk.c:4600
+#: catalog/aclchk.c:4585
#, c-format
msgid "operator with OID %u does not exist"
msgstr "Operator mit OID %u existiert nicht"
-#: catalog/aclchk.c:4777
+#: catalog/aclchk.c:4762
#, c-format
msgid "operator class with OID %u does not exist"
msgstr "Operatorklasse mit OID %u existiert nicht"
-#: catalog/aclchk.c:4804
+#: catalog/aclchk.c:4789
#, c-format
msgid "operator family with OID %u does not exist"
msgstr "Operatorfamilie mit OID %u existiert nicht"
-#: catalog/aclchk.c:4831
+#: catalog/aclchk.c:4816
#, c-format
msgid "text search dictionary with OID %u does not exist"
msgstr "Textsuchewörterbuch mit OID %u existiert nicht"
-#: catalog/aclchk.c:4858
+#: catalog/aclchk.c:4843
#, c-format
msgid "text search configuration with OID %u does not exist"
msgstr "Textsuchekonfiguration mit OID %u existiert nicht"
-#: catalog/aclchk.c:4939 commands/event_trigger.c:587
+#: catalog/aclchk.c:4924 commands/event_trigger.c:587
#, c-format
msgid "event trigger with OID %u does not exist"
msgstr "Ereignistrigger mit OID %u existiert nicht"
-#: catalog/aclchk.c:4992
+#: catalog/aclchk.c:4977
#, c-format
msgid "collation with OID %u does not exist"
msgstr "Sortierfolge mit OID %u existiert nicht"
-#: catalog/aclchk.c:5018
+#: catalog/aclchk.c:5003
#, c-format
msgid "conversion with OID %u does not exist"
msgstr "Konversion mit OID %u existiert nicht"
-#: catalog/aclchk.c:5059
+#: catalog/aclchk.c:5044
#, c-format
msgid "extension with OID %u does not exist"
msgstr "Erweiterung mit OID %u existiert nicht"
-#: catalog/dependency.c:646
+#: catalog/aclchk.c:5071 commands/publicationcmds.c:746
+#, c-format
+msgid "publication with OID %u does not exist"
+msgstr "Publikation mit OID %u existiert nicht"
+
+#: catalog/aclchk.c:5097 commands/subscriptioncmds.c:682
+#, c-format
+msgid "subscription with OID %u does not exist"
+msgstr "Subskription mit OID %u existiert nicht"
+
+#: catalog/dependency.c:611
#, c-format
msgid "cannot drop %s because %s requires it"
msgstr "kann %s nicht löschen, wird von %s benötigt"
-#: catalog/dependency.c:649
+#: catalog/dependency.c:614
#, c-format
msgid "You can drop %s instead."
msgstr "Sie können stattdessen %s löschen."
-#: catalog/dependency.c:811 catalog/pg_shdepend.c:576
+#: catalog/dependency.c:777 catalog/pg_shdepend.c:573
#, c-format
msgid "cannot drop %s because it is required by the database system"
msgstr "kann %s nicht löschen, wird vom Datenbanksystem benötigt"
-#: catalog/dependency.c:927
+#: catalog/dependency.c:895
#, c-format
msgid "drop auto-cascades to %s"
msgstr "Löschvorgang löscht automatisch %s"
-#: catalog/dependency.c:939 catalog/dependency.c:948
+#: catalog/dependency.c:907 catalog/dependency.c:916
#, c-format
msgid "%s depends on %s"
msgstr "%s hängt von %s ab"
-#: catalog/dependency.c:960 catalog/dependency.c:969
+#: catalog/dependency.c:928 catalog/dependency.c:937
#, c-format
msgid "drop cascades to %s"
msgstr "Löschvorgang löscht ebenfalls %s"
-#: catalog/dependency.c:977 catalog/pg_shdepend.c:687
+#: catalog/dependency.c:945 catalog/pg_shdepend.c:684
#, c-format
msgid ""
"\n"
@@ -3551,191 +3655,193 @@ msgstr[1] ""
"\n"
"und %d weitere Objekte (Liste im Serverlog)"
-#: catalog/dependency.c:989
+#: catalog/dependency.c:957
#, c-format
msgid "cannot drop %s because other objects depend on it"
msgstr "kann %s nicht löschen, weil andere Objekte davon abhängen"
-#: catalog/dependency.c:993 catalog/dependency.c:1000
+#: catalog/dependency.c:961 catalog/dependency.c:968
#, c-format
msgid "Use DROP ... CASCADE to drop the dependent objects too."
msgstr "Verwenden Sie DROP ... CASCADE, um die abhängigen Objekte ebenfalls zu löschen."
-#: catalog/dependency.c:997
+#: catalog/dependency.c:965
#, c-format
msgid "cannot drop desired object(s) because other objects depend on them"
msgstr "kann gewünschte Objekte nicht löschen, weil andere Objekte davon abhängen"
#. translator: %d always has a value larger than 1
-#: catalog/dependency.c:1006
+#: catalog/dependency.c:974
#, c-format
msgid "drop cascades to %d other object"
msgid_plural "drop cascades to %d other objects"
msgstr[0] "Löschvorgang löscht ebenfalls %d weiteres Objekt"
msgstr[1] "Löschvorgang löscht ebenfalls %d weitere Objekte"
-#: catalog/dependency.c:1634
-#, c-format
-msgid "constant of the type \"regrole\" cannot be used here"
+#: catalog/dependency.c:1616
+#, fuzzy, c-format
+#| msgid "constant of the type \"regrole\" cannot be used here"
+msgid "constant of the type %s cannot be used here"
msgstr "Konstante vom Typ »regrole« kann hier nicht verwendet werden"
-#: catalog/heap.c:277
+#: catalog/heap.c:281
#, c-format
msgid "permission denied to create \"%s.%s\""
msgstr "keine Berechtigung, um »%s.%s« zu erzeugen"
-#: catalog/heap.c:279
+#: catalog/heap.c:283
#, c-format
msgid "System catalog modifications are currently disallowed."
msgstr "Änderungen an Systemkatalogen sind gegenwärtig nicht erlaubt."
-#: catalog/heap.c:414 commands/tablecmds.c:1438 commands/tablecmds.c:1895
-#: commands/tablecmds.c:4819
+#: catalog/heap.c:418 commands/tablecmds.c:1619 commands/tablecmds.c:2122
+#: commands/tablecmds.c:5144
#, c-format
msgid "tables can have at most %d columns"
msgstr "Tabellen können höchstens %d Spalten haben"
-#: catalog/heap.c:431 commands/tablecmds.c:5080
+#: catalog/heap.c:435 commands/tablecmds.c:5402
#, c-format
msgid "column name \"%s\" conflicts with a system column name"
msgstr "Spaltenname »%s« steht im Konflikt mit dem Namen einer Systemspalte"
-#: catalog/heap.c:447
+#: catalog/heap.c:451
#, c-format
msgid "column name \"%s\" specified more than once"
msgstr "Spaltenname »%s« mehrmals angegeben"
-#: catalog/heap.c:497
-#, c-format
-msgid "column \"%s\" has type \"unknown\""
-msgstr "Spalte »%s« hat Typ »unknown«"
-
-#: catalog/heap.c:498
-#, c-format
-msgid "Proceeding with relation creation anyway."
-msgstr "Relation wird trotzdem erzeugt."
-
-#: catalog/heap.c:511
+#: catalog/heap.c:504
#, c-format
msgid "column \"%s\" has pseudo-type %s"
msgstr "Spalte »%s« hat Pseudotyp %s"
-#: catalog/heap.c:541
+#: catalog/heap.c:534
#, c-format
msgid "composite type %s cannot be made a member of itself"
msgstr "zusammengesetzter Typ %s kann nicht Teil von sich selbst werden"
-#: catalog/heap.c:583 commands/createas.c:201 commands/createas.c:498
+#: catalog/heap.c:576 commands/createas.c:201 commands/createas.c:497
#, c-format
msgid "no collation was derived for column \"%s\" with collatable type %s"
msgstr "für Spalte »%s« mit sortierbarem Typ %s wurde keine Sortierfolge abgeleitet"
-#: catalog/heap.c:585 commands/createas.c:204 commands/createas.c:501
-#: commands/indexcmds.c:1132 commands/view.c:105 regex/regc_pg_locale.c:262
-#: utils/adt/formatting.c:1513 utils/adt/formatting.c:1565
-#: utils/adt/formatting.c:1633 utils/adt/formatting.c:1685
-#: utils/adt/formatting.c:1754 utils/adt/formatting.c:1818
-#: utils/adt/like.c:213 utils/adt/selfuncs.c:5334 utils/adt/varlena.c:1421
-#: utils/adt/varlena.c:1826
+#: catalog/heap.c:578 commands/createas.c:204 commands/createas.c:500
+#: commands/indexcmds.c:1141 commands/tablecmds.c:13000 commands/view.c:103
+#: regex/regc_pg_locale.c:262 utils/adt/formatting.c:1500
+#: utils/adt/formatting.c:1552 utils/adt/formatting.c:1620
+#: utils/adt/formatting.c:1672 utils/adt/formatting.c:1741
+#: utils/adt/formatting.c:1805 utils/adt/like.c:213 utils/adt/selfuncs.c:5332
+#: utils/adt/varlena.c:1422 utils/adt/varlena.c:1827
#, c-format
msgid "Use the COLLATE clause to set the collation explicitly."
msgstr "Verwenden Sie die COLLATE-Klausel, um die Sortierfolge explizit zu setzen."
-#: catalog/heap.c:1066 catalog/index.c:792 commands/tablecmds.c:2622
+#: catalog/heap.c:1063 catalog/index.c:806 commands/tablecmds.c:2903
#, c-format
msgid "relation \"%s\" already exists"
msgstr "Relation »%s« existiert bereits"
-#: catalog/heap.c:1082 catalog/pg_type.c:412 catalog/pg_type.c:722
-#: commands/typecmds.c:237 commands/typecmds.c:784 commands/typecmds.c:1135
-#: commands/typecmds.c:1357 commands/typecmds.c:2113
+#: catalog/heap.c:1079 catalog/pg_type.c:410 catalog/pg_type.c:717
+#: commands/typecmds.c:239 commands/typecmds.c:788 commands/typecmds.c:1139
+#: commands/typecmds.c:1350 commands/typecmds.c:2106
#, c-format
msgid "type \"%s\" already exists"
msgstr "Typ »%s« existiert bereits"
-#: catalog/heap.c:1083
+#: catalog/heap.c:1080
#, c-format
msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type."
msgstr "Eine Relation hat einen zugehörigen Typ mit dem selben Namen, daher müssen Sie einen Namen wählen, der nicht mit einem bestehenden Typ kollidiert."
-#: catalog/heap.c:1111
+#: catalog/heap.c:1109
#, c-format
msgid "pg_class heap OID value not set when in binary upgrade mode"
msgstr "Heap-OID-Wert für pg_class ist im Binary-Upgrade-Modus nicht gesetzt"
-#: catalog/heap.c:2289
+#: catalog/heap.c:2063
+#, fuzzy, c-format
+#| msgid "cannot use a deferrable unique constraint for referenced table \"%s\""
+msgid "cannot add NO INHERIT constraint to partitioned table \"%s\""
+msgstr "aufschiebbarer Unique-Constraint kann nicht für Tabelle »%s«, auf die verwiesen wird, verwendet werden"
+
+#: catalog/heap.c:2321
#, c-format
msgid "check constraint \"%s\" already exists"
msgstr "Check-Constraint »%s« existiert bereits"
-#: catalog/heap.c:2442 catalog/pg_constraint.c:654 commands/tablecmds.c:6068
+#: catalog/heap.c:2489 catalog/pg_constraint.c:649 commands/tablecmds.c:6525
#, c-format
msgid "constraint \"%s\" for relation \"%s\" already exists"
msgstr "Constraint »%s« existiert bereits für Relation »%s«"
-#: catalog/heap.c:2452
+#: catalog/heap.c:2496
#, c-format
msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\""
msgstr "Constraint »%s« kollidiert mit nicht vererbtem Constraint für Relation »%s«"
-#: catalog/heap.c:2466
+#: catalog/heap.c:2507
+#, c-format
+msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\""
+msgstr "Constraint »%s« kollidiert mit vererbtem Constraint für Relation »%s«"
+
+#: catalog/heap.c:2517
+#, c-format
+msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\""
+msgstr "Constraint »%s« kollidiert mit NOT-VALID-Constraint für Relation »%s«"
+
+#: catalog/heap.c:2522
#, c-format
msgid "merging constraint \"%s\" with inherited definition"
msgstr "Constraint »%s« wird mit geerbter Definition zusammengeführt"
-#: catalog/heap.c:2559
+#: catalog/heap.c:2638
#, c-format
msgid "cannot use column references in default expression"
msgstr "Spaltenverweise können nicht in Vorgabeausdrücken verwendet werden"
-#: catalog/heap.c:2570
-#, c-format
-msgid "default expression must not return a set"
-msgstr "Vorgabeausdruck kann keine Ergebnismenge zurückgeben"
-
-#: catalog/heap.c:2589 rewrite/rewriteHandler.c:1084
+#: catalog/heap.c:2663 rewrite/rewriteHandler.c:1097
#, c-format
msgid "column \"%s\" is of type %s but default expression is of type %s"
msgstr "Spalte »%s« hat Typ %s, aber der Vorgabeausdruck hat Typ %s"
-#: catalog/heap.c:2594 commands/prepare.c:374 parser/parse_node.c:428
-#: parser/parse_target.c:528 parser/parse_target.c:778
-#: parser/parse_target.c:788 rewrite/rewriteHandler.c:1089
+#: catalog/heap.c:2668 commands/prepare.c:384 parser/parse_node.c:428
+#: parser/parse_target.c:589 parser/parse_target.c:839
+#: parser/parse_target.c:849 rewrite/rewriteHandler.c:1102
#, c-format
msgid "You will need to rewrite or cast the expression."
msgstr "Sie müssen den Ausdruck umschreiben oder eine Typumwandlung vornehmen."
-#: catalog/heap.c:2641
+#: catalog/heap.c:2715
#, c-format
msgid "only table \"%s\" can be referenced in check constraint"
msgstr "nur Verweise auf Tabelle »%s« sind im Check-Constraint zugelassen"
-#: catalog/heap.c:2881
+#: catalog/heap.c:2955
#, c-format
msgid "unsupported ON COMMIT and foreign key combination"
msgstr "nicht unterstützte Kombination aus ON COMMIT und Fremdschlüssel"
-#: catalog/heap.c:2882
+#: catalog/heap.c:2956
#, c-format
msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting."
msgstr "Tabelle »%s« verweist auf »%s«, aber sie haben nicht die gleiche ON-COMMIT-Einstellung."
-#: catalog/heap.c:2887
+#: catalog/heap.c:2961
#, c-format
msgid "cannot truncate a table referenced in a foreign key constraint"
msgstr "kann eine Tabelle, die in einen Fremdschlüssel-Constraint eingebunden ist, nicht leeren"
-#: catalog/heap.c:2888
+#: catalog/heap.c:2962
#, c-format
msgid "Table \"%s\" references \"%s\"."
msgstr "Tabelle »%s« verweist auf »%s«."
-#: catalog/heap.c:2890
+#: catalog/heap.c:2964
#, c-format
msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE."
msgstr "Leeren Sie die Tabelle »%s« gleichzeitig oder verwenden Sie TRUNCATE ... CASCADE."
-#: catalog/index.c:210 parser/parse_utilcmd.c:1488 parser/parse_utilcmd.c:1574
+#: catalog/index.c:210 parser/parse_utilcmd.c:1541 parser/parse_utilcmd.c:1627
#, c-format
msgid "multiple primary keys for table \"%s\" are not allowed"
msgstr "mehrere Primärschlüssel für Tabelle »%s« nicht erlaubt"
@@ -3745,440 +3851,412 @@ msgstr "mehrere Primärschlüssel für Tabelle »%s« nicht erlaubt"
msgid "primary keys cannot be expressions"
msgstr "Primärschlüssel können keine Ausdrücke sein"
-#: catalog/index.c:742 catalog/index.c:1160
+#: catalog/index.c:756 catalog/index.c:1174
#, c-format
msgid "user-defined indexes on system catalog tables are not supported"
msgstr "benutzerdefinierte Indexe für Systemkatalogtabellen werden nicht unterstützt"
-#: catalog/index.c:752
+#: catalog/index.c:766
#, c-format
msgid "concurrent index creation on system catalog tables is not supported"
msgstr "nebenläufige Indexerzeugung für Systemkatalogtabellen wird nicht unterstützt"
-#: catalog/index.c:770
+#: catalog/index.c:784
#, c-format
msgid "shared indexes cannot be created after initdb"
msgstr "Cluster-globale Indexe können nicht nach initdb erzeugt werden"
-#: catalog/index.c:784 commands/createas.c:249 commands/sequence.c:141
-#: parser/parse_utilcmd.c:192
+#: catalog/index.c:798 commands/createas.c:249 commands/sequence.c:149
+#: parser/parse_utilcmd.c:197
#, c-format
msgid "relation \"%s\" already exists, skipping"
msgstr "Relation »%s« existiert bereits, wird übersprungen"
-#: catalog/index.c:820
+#: catalog/index.c:834
#, c-format
msgid "pg_class index OID value not set when in binary upgrade mode"
msgstr "Index-OID-Wert für pg_class ist im Binary-Upgrade-Modus nicht gesetzt"
-#: catalog/index.c:1422
+#: catalog/index.c:1435
#, c-format
msgid "DROP INDEX CONCURRENTLY must be first action in transaction"
msgstr "DROP INDEX CONCURRENTLY muss die erste Aktion in einer Transaktion sein"
-#: catalog/index.c:2004
+#: catalog/index.c:2020
#, c-format
msgid "building index \"%s\" on table \"%s\""
msgstr "baue Index »%s« von Tabelle »%s«"
-#: catalog/index.c:3322
+#: catalog/index.c:3338
#, c-format
msgid "cannot reindex temporary tables of other sessions"
msgstr "kann temporäre Tabellen anderer Sitzungen nicht reindizieren"
-#: catalog/index.c:3454
+#: catalog/index.c:3469
#, c-format
msgid "index \"%s\" was reindexed"
msgstr "Index »%s« wurde neu indiziert"
-#: catalog/index.c:3456 commands/vacuumlazy.c:1338 commands/vacuumlazy.c:1414
-#: commands/vacuumlazy.c:1603 commands/vacuumlazy.c:1813
+#: catalog/index.c:3471 commands/vacuumlazy.c:1345 commands/vacuumlazy.c:1421
+#: commands/vacuumlazy.c:1610 commands/vacuumlazy.c:1820
#, c-format
msgid "%s."
msgstr "%s."
-#: catalog/namespace.c:249 catalog/namespace.c:447 catalog/namespace.c:541
-#: commands/trigger.c:4527
+#: catalog/namespace.c:234 catalog/namespace.c:432 catalog/namespace.c:526
+#: commands/trigger.c:4782
#, c-format
msgid "cross-database references are not implemented: \"%s.%s.%s\""
msgstr "Verweise auf andere Datenbanken sind nicht implementiert: »%s.%s.%s«"
-#: catalog/namespace.c:306
+#: catalog/namespace.c:291
#, c-format
msgid "temporary tables cannot specify a schema name"
msgstr "temporäre Tabellen können keinen Schemanamen angeben"
-#: catalog/namespace.c:385
+#: catalog/namespace.c:370
#, c-format
msgid "could not obtain lock on relation \"%s.%s\""
msgstr "konnte Sperre für Relation »%s.%s« nicht setzen"
-#: catalog/namespace.c:390 commands/lockcmds.c:146
+#: catalog/namespace.c:375 commands/lockcmds.c:145
#, c-format
msgid "could not obtain lock on relation \"%s\""
msgstr "konnte Sperre für Relation »%s« nicht setzen"
-#: catalog/namespace.c:414 parser/parse_relation.c:1137
+#: catalog/namespace.c:399 parser/parse_relation.c:1137
#, c-format
msgid "relation \"%s.%s\" does not exist"
msgstr "Relation »%s.%s« existiert nicht"
-#: catalog/namespace.c:419 parser/parse_relation.c:1150
-#: parser/parse_relation.c:1158 utils/adt/regproc.c:1034
+#: catalog/namespace.c:404 parser/parse_relation.c:1150
+#: parser/parse_relation.c:1158 utils/adt/regproc.c:1036
#, c-format
msgid "relation \"%s\" does not exist"
msgstr "Relation »%s« existiert nicht"
-#: catalog/namespace.c:487 catalog/namespace.c:2841 commands/extension.c:1382
-#: commands/extension.c:1388
+#: catalog/namespace.c:472 catalog/namespace.c:2826 commands/extension.c:1460
+#: commands/extension.c:1466
#, c-format
msgid "no schema has been selected to create in"
msgstr "kein Schema für die Objekterzeugung ausgewählt"
-#: catalog/namespace.c:639 catalog/namespace.c:652
+#: catalog/namespace.c:624 catalog/namespace.c:637
#, c-format
msgid "cannot create relations in temporary schemas of other sessions"
msgstr "kann keine Relationen in temporären Schemas anderer Sitzungen erzeugen"
-#: catalog/namespace.c:643
+#: catalog/namespace.c:628
#, c-format
msgid "cannot create temporary relation in non-temporary schema"
msgstr "kann keine temporäre Relation in einem nicht-temporären Schema erzeugen"
-#: catalog/namespace.c:658
+#: catalog/namespace.c:643
#, c-format
msgid "only temporary relations may be created in temporary schemas"
msgstr "nur temporäre Relationen können in temporären Schemas erzeugt werden"
-#: catalog/namespace.c:2154
+#: catalog/namespace.c:2139
#, c-format
msgid "text search parser \"%s\" does not exist"
msgstr "Textsucheparser »%s« existiert nicht"
-#: catalog/namespace.c:2280
+#: catalog/namespace.c:2265
#, c-format
msgid "text search dictionary \"%s\" does not exist"
msgstr "Textsuchewörterbuch »%s« existiert nicht"
-#: catalog/namespace.c:2407
+#: catalog/namespace.c:2392
#, c-format
msgid "text search template \"%s\" does not exist"
msgstr "Textsuchevorlage »%s« existiert nicht"
-#: catalog/namespace.c:2533 commands/tsearchcmds.c:1197
-#: utils/cache/ts_cache.c:613
+#: catalog/namespace.c:2518 commands/tsearchcmds.c:1185
+#: utils/cache/ts_cache.c:612
#, c-format
msgid "text search configuration \"%s\" does not exist"
msgstr "Textsuchekonfiguration »%s« existiert nicht"
-#: catalog/namespace.c:2646 parser/parse_expr.c:792 parser/parse_target.c:1130
+#: catalog/namespace.c:2631 parser/parse_expr.c:791 parser/parse_target.c:1191
#, c-format
msgid "cross-database references are not implemented: %s"
msgstr "Verweise auf andere Datenbanken sind nicht implementiert: %s"
-#: catalog/namespace.c:2652 gram.y:13441 gram.y:14810 parser/parse_expr.c:799
-#: parser/parse_target.c:1137
+#: catalog/namespace.c:2637 gram.y:14068 gram.y:15487 parser/parse_expr.c:798
+#: parser/parse_target.c:1198
#, c-format
msgid "improper qualified name (too many dotted names): %s"
msgstr "falscher qualifizierter Name (zu viele Namensteile): %s"
-#: catalog/namespace.c:2783
+#: catalog/namespace.c:2768
#, c-format
msgid "cannot move objects into or out of temporary schemas"
msgstr "Objekte können nicht in oder aus temporären Schemas verschoben werden"
-#: catalog/namespace.c:2789
+#: catalog/namespace.c:2774
#, c-format
msgid "cannot move objects into or out of TOAST schema"
msgstr "Objekte können nicht in oder aus TOAST-Schemas verschoben werden"
-#: catalog/namespace.c:2862 commands/schemacmds.c:238
-#: commands/schemacmds.c:317 commands/tablecmds.c:740
+#: catalog/namespace.c:2847 commands/schemacmds.c:255
+#: commands/schemacmds.c:333 commands/tablecmds.c:891
#, c-format
msgid "schema \"%s\" does not exist"
msgstr "Schema »%s« existiert nicht"
-#: catalog/namespace.c:2893
+#: catalog/namespace.c:2878
#, c-format
msgid "improper relation name (too many dotted names): %s"
msgstr "falscher Relationsname (zu viele Namensteile): %s"
-#: catalog/namespace.c:3403
+#: catalog/namespace.c:3388
#, c-format
msgid "collation \"%s\" for encoding \"%s\" does not exist"
msgstr "Sortierfolge »%s« für Kodierung »%s« existiert nicht"
-#: catalog/namespace.c:3458
+#: catalog/namespace.c:3443
#, c-format
msgid "conversion \"%s\" does not exist"
msgstr "Konversion »%s« existiert nicht"
-#: catalog/namespace.c:3666
+#: catalog/namespace.c:3651
#, c-format
msgid "permission denied to create temporary tables in database \"%s\""
msgstr "keine Berechtigung, um temporäre Tabellen in Datenbank »%s« zu erzeugen"
-#: catalog/namespace.c:3682
+#: catalog/namespace.c:3667
#, c-format
msgid "cannot create temporary tables during recovery"
msgstr "während der Wiederherstellung können keine temporären Tabellen erzeugt werden"
-#: catalog/namespace.c:3688
+#: catalog/namespace.c:3673
#, c-format
msgid "cannot create temporary tables in parallel mode"
msgstr "im Parallelmodus können keine temporären Tabellen erzeugt werden"
-#: catalog/namespace.c:3932 commands/tablespace.c:1173 commands/variable.c:63
-#: utils/misc/guc.c:9855
+#: catalog/namespace.c:3922 commands/tablespace.c:1169 commands/variable.c:64
+#: utils/misc/guc.c:9942 utils/misc/guc.c:10020
#, c-format
msgid "List syntax is invalid."
msgstr "Die Listensyntax ist ungültig."
-#: catalog/objectaddress.c:1065
-msgid "access method name cannot be qualified"
-msgstr "Zugriffsmethodenname kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1068
-msgid "database name cannot be qualified"
-msgstr "Datenbankname kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1071 commands/extension.c:2506
-#, c-format
-msgid "extension name cannot be qualified"
-msgstr "Erweiterungsname kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1074
-msgid "tablespace name cannot be qualified"
-msgstr "Tablespace-Name kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1077
-msgid "role name cannot be qualified"
-msgstr "Rollenname kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1080
-msgid "schema name cannot be qualified"
-msgstr "Schemaname kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1083
-msgid "language name cannot be qualified"
-msgstr "Sprachname kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1086
-msgid "foreign-data wrapper name cannot be qualified"
-msgstr "Fremddaten-Wrapper-Name kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1089
-msgid "server name cannot be qualified"
-msgstr "Servername kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1092
-msgid "event trigger name cannot be qualified"
-msgstr "Ereignistriggername kann nicht qualifiziert werden"
-
-#: catalog/objectaddress.c:1210 commands/lockcmds.c:94 commands/policy.c:94
-#: commands/policy.c:384 commands/policy.c:473 commands/tablecmds.c:217
-#: commands/tablecmds.c:1299 commands/tablecmds.c:4346
-#: commands/tablecmds.c:7977
+#: catalog/objectaddress.c:1215 catalog/pg_publication.c:57
+#: commands/lockcmds.c:93 commands/policy.c:94 commands/policy.c:391
+#: commands/policy.c:480 commands/tablecmds.c:223 commands/tablecmds.c:265
+#: commands/tablecmds.c:1477 commands/tablecmds.c:4665
+#: commands/tablecmds.c:8502
#, c-format
msgid "\"%s\" is not a table"
msgstr "»%s« ist keine Tabelle"
-#: catalog/objectaddress.c:1217 commands/tablecmds.c:229
-#: commands/tablecmds.c:4376 commands/tablecmds.c:12012 commands/view.c:143
+#: catalog/objectaddress.c:1222 commands/tablecmds.c:235
+#: commands/tablecmds.c:4695 commands/tablecmds.c:12739 commands/view.c:141
#, c-format
msgid "\"%s\" is not a view"
msgstr "»%s« ist keine Sicht"
-#: catalog/objectaddress.c:1224 commands/matview.c:174
-#: commands/tablecmds.c:235 commands/tablecmds.c:12017
+#: catalog/objectaddress.c:1229 commands/matview.c:172
+#: commands/tablecmds.c:241 commands/tablecmds.c:12744
#, c-format
msgid "\"%s\" is not a materialized view"
msgstr "»%s« ist keine materialisierte Sicht"
-#: catalog/objectaddress.c:1231 commands/tablecmds.c:253
-#: commands/tablecmds.c:4379 commands/tablecmds.c:12022
+#: catalog/objectaddress.c:1236 commands/tablecmds.c:259
+#: commands/tablecmds.c:4698 commands/tablecmds.c:12749
#, c-format
msgid "\"%s\" is not a foreign table"
msgstr "»%s« ist keine Fremdtabelle"
-#: catalog/objectaddress.c:1376 catalog/objectaddress.c:1429
+#: catalog/objectaddress.c:1277
+#, fuzzy, c-format
+#| msgid "%s must specify unqualified relation names"
+msgid "must specify relation and object name"
+msgstr "%s muss unqualifizierte Relationsnamen angeben"
+
+#: catalog/objectaddress.c:1353 catalog/objectaddress.c:1406
#, c-format
msgid "column name must be qualified"
msgstr "Spaltenname muss qualifiziert werden"
-#: catalog/objectaddress.c:1472
+#: catalog/objectaddress.c:1449
#, c-format
msgid "default value for column \"%s\" of relation \"%s\" does not exist"
msgstr "Vorgabewert für Spalte »%s« von Relation »%s« existiert nicht"
-#: catalog/objectaddress.c:1512 commands/functioncmds.c:128
-#: commands/tablecmds.c:245 commands/typecmds.c:3214 parser/parse_type.c:226
-#: parser/parse_type.c:255 parser/parse_type.c:795 utils/adt/acl.c:4374
-#: utils/adt/regproc.c:1225
+#: catalog/objectaddress.c:1486 commands/functioncmds.c:128
+#: commands/tablecmds.c:251 commands/typecmds.c:3233 parser/parse_type.c:226
+#: parser/parse_type.c:255 parser/parse_type.c:794 utils/adt/acl.c:4357
+#: utils/adt/regproc.c:1227
#, c-format
msgid "type \"%s\" does not exist"
msgstr "Typ »%s« existiert nicht"
-#: catalog/objectaddress.c:1629
+#: catalog/objectaddress.c:1603
#, c-format
msgid "operator %d (%s, %s) of %s does not exist"
msgstr "Operator %d (%s, %s) von %s existiert nicht"
-#: catalog/objectaddress.c:1658
+#: catalog/objectaddress.c:1632
#, c-format
msgid "function %d (%s, %s) of %s does not exist"
msgstr "Funktion %d (%s, %s) von %s existiert nicht"
-#: catalog/objectaddress.c:1707 catalog/objectaddress.c:1733
+#: catalog/objectaddress.c:1681 catalog/objectaddress.c:1707
#, c-format
msgid "user mapping for user \"%s\" on server \"%s\" does not exist"
msgstr "Benutzerabbildung für Benutzer »%s« auf Server »%s« existiert nicht"
-#: catalog/objectaddress.c:1722 commands/foreigncmds.c:430
-#: commands/foreigncmds.c:997 commands/foreigncmds.c:1359
-#: foreign/foreign.c:692
+#: catalog/objectaddress.c:1696 commands/foreigncmds.c:428
+#: commands/foreigncmds.c:991 commands/foreigncmds.c:1349
+#: foreign/foreign.c:688
#, c-format
msgid "server \"%s\" does not exist"
msgstr "Server »%s« existiert nicht"
-#: catalog/objectaddress.c:1794
+#: catalog/objectaddress.c:1763
+#, c-format
+msgid "publication relation \"%s\" in publication \"%s\" does not exist"
+msgstr "Publikationsrelation »%s« in Publikation »%s« existiert nicht"
+
+#: catalog/objectaddress.c:1822
#, c-format
msgid "unrecognized default ACL object type %c"
msgstr "unbekannter Standard-ACL-Objekttyp %c"
-#: catalog/objectaddress.c:1795
+#: catalog/objectaddress.c:1823
#, c-format
msgid "Valid object types are \"r\", \"S\", \"f\", and \"T\"."
msgstr "Gültige Objekttypen sind »r«, »S«, »f« und »T«."
-#: catalog/objectaddress.c:1841
+#: catalog/objectaddress.c:1869
#, c-format
msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist"
msgstr "Standard-ACL für Benutzer »%s« in Schema »%s« für %s existiert nicht"
-#: catalog/objectaddress.c:1846
+#: catalog/objectaddress.c:1874
#, c-format
msgid "default ACL for user \"%s\" on %s does not exist"
msgstr "Standard-ACL für Benutzer »%s« für %s existiert nicht"
-#: catalog/objectaddress.c:1873 catalog/objectaddress.c:1929
-#: catalog/objectaddress.c:1984
+#: catalog/objectaddress.c:1901 catalog/objectaddress.c:1959
+#: catalog/objectaddress.c:2014
#, c-format
msgid "name or argument lists may not contain nulls"
msgstr "Namens- oder Argumentlisten dürfen keine NULL-Werte enthalten"
-#: catalog/objectaddress.c:1905
+#: catalog/objectaddress.c:1935
#, c-format
msgid "unsupported object type \"%s\""
msgstr "nicht unterstützter Objekttyp »%s«"
-#: catalog/objectaddress.c:1925 catalog/objectaddress.c:1943
+#: catalog/objectaddress.c:1955 catalog/objectaddress.c:1973
+#: catalog/objectaddress.c:2110
#, c-format
msgid "name list length must be exactly %d"
msgstr "Länge der Namensliste muss genau %d sein"
-#: catalog/objectaddress.c:1947
+#: catalog/objectaddress.c:1977
#, c-format
msgid "large object OID may not be null"
msgstr "Large-Object-OID darf nicht NULL sein"
-#: catalog/objectaddress.c:1956 catalog/objectaddress.c:2016
-#: catalog/objectaddress.c:2023
+#: catalog/objectaddress.c:1986 catalog/objectaddress.c:2047
+#: catalog/objectaddress.c:2054
#, c-format
msgid "name list length must be at least %d"
msgstr "Länge der Namensliste muss mindestens %d sein"
-#: catalog/objectaddress.c:2009 catalog/objectaddress.c:2029
+#: catalog/objectaddress.c:2040 catalog/objectaddress.c:2060
#, c-format
msgid "argument list length must be exactly %d"
msgstr "Länge der Argumentliste muss genau %d sein"
-#: catalog/objectaddress.c:2165 libpq/be-fsstubs.c:352
+#: catalog/objectaddress.c:2285 libpq/be-fsstubs.c:350
#, c-format
msgid "must be owner of large object %u"
msgstr "Berechtigung nur für Eigentümer des Large Object %u"
-#: catalog/objectaddress.c:2180 commands/functioncmds.c:1426
+#: catalog/objectaddress.c:2300 commands/functioncmds.c:1419
#, c-format
msgid "must be owner of type %s or type %s"
msgstr "Berechtigung nur für Eigentümer des Typs %s oder des Typs %s"
-#: catalog/objectaddress.c:2220 catalog/objectaddress.c:2237
+#: catalog/objectaddress.c:2350 catalog/objectaddress.c:2367
#, c-format
msgid "must be superuser"
msgstr "Berechtigung nur für Superuser"
-#: catalog/objectaddress.c:2227
+#: catalog/objectaddress.c:2357
#, c-format
msgid "must have CREATEROLE privilege"
msgstr "Berechtigung nur mit CREATEROLE-Privileg"
-#: catalog/objectaddress.c:2307
+#: catalog/objectaddress.c:2432
#, c-format
msgid "unrecognized object type \"%s\""
msgstr "unbekannter Objekttyp »%s«"
-#: catalog/objectaddress.c:2502
+#: catalog/objectaddress.c:2627
#, c-format
msgid " column %s"
msgstr " Spalte %s"
-#: catalog/objectaddress.c:2508
+#: catalog/objectaddress.c:2633
#, c-format
msgid "function %s"
msgstr "Funktion %s"
-#: catalog/objectaddress.c:2513
+#: catalog/objectaddress.c:2638
#, c-format
msgid "type %s"
msgstr "Typ %s"
-#: catalog/objectaddress.c:2543
+#: catalog/objectaddress.c:2668
#, c-format
msgid "cast from %s to %s"
msgstr "Typumwandlung von %s in %s"
-#: catalog/objectaddress.c:2563
+#: catalog/objectaddress.c:2688
#, c-format
msgid "collation %s"
msgstr "Sortierfolge %s"
-#: catalog/objectaddress.c:2587
+#: catalog/objectaddress.c:2712
#, c-format
msgid "constraint %s on %s"
msgstr "Constraint %s für %s"
-#: catalog/objectaddress.c:2593
+#: catalog/objectaddress.c:2718
#, c-format
msgid "constraint %s"
msgstr "Constraint %s"
-#: catalog/objectaddress.c:2610
+#: catalog/objectaddress.c:2735
#, c-format
msgid "conversion %s"
msgstr "Konversion %s"
-#: catalog/objectaddress.c:2647
+#: catalog/objectaddress.c:2772
#, c-format
msgid "default for %s"
msgstr "Vorgabewert für %s"
-#: catalog/objectaddress.c:2656
+#: catalog/objectaddress.c:2781
#, c-format
msgid "language %s"
msgstr "Sprache %s"
-#: catalog/objectaddress.c:2661
+#: catalog/objectaddress.c:2786
#, c-format
msgid "large object %u"
msgstr "Large Object %u"
-#: catalog/objectaddress.c:2666
+#: catalog/objectaddress.c:2791
#, c-format
msgid "operator %s"
msgstr "Operator %s"
-#: catalog/objectaddress.c:2698
+#: catalog/objectaddress.c:2823
#, c-format
msgid "operator class %s for access method %s"
msgstr "Operatorklasse %s für Zugriffsmethode %s"
@@ -4187,7 +4265,7 @@ msgstr "Operatorklasse %s für Zugriffsmethode %s"
#. first two %s's are data type names, the third %s is the
#. description of the operator family, and the last %s is the
#. textual form of the operator with arguments.
-#: catalog/objectaddress.c:2748
+#: catalog/objectaddress.c:2873
#, c-format
msgid "operator %d (%s, %s) of %s: %s"
msgstr "Operator %d (%s, %s) von %s: %s"
@@ -4196,181 +4274,223 @@ msgstr "Operator %d (%s, %s) von %s: %s"
#. are data type names, the third %s is the description of the
#. operator family, and the last %s is the textual form of the
#. function with arguments.
-#: catalog/objectaddress.c:2798
+#: catalog/objectaddress.c:2923
#, c-format
msgid "function %d (%s, %s) of %s: %s"
msgstr "Funktion %d (%s, %s) von %s: %s"
-#: catalog/objectaddress.c:2838
+#: catalog/objectaddress.c:2963
#, c-format
msgid "rule %s on "
msgstr "Regel %s für "
-#: catalog/objectaddress.c:2860
+#: catalog/objectaddress.c:2985
#, c-format
msgid "transform for %s language %s"
msgstr "Transformation %s für Sprache %s"
-#: catalog/objectaddress.c:2894
+#: catalog/objectaddress.c:3019
#, c-format
msgid "trigger %s on "
msgstr "Trigger %s für "
-#: catalog/objectaddress.c:2911
+#: catalog/objectaddress.c:3036
#, c-format
msgid "schema %s"
msgstr "Schema %s"
-#: catalog/objectaddress.c:2924
+#: catalog/objectaddress.c:3049
#, c-format
msgid "text search parser %s"
msgstr "Textsucheparser %s"
-#: catalog/objectaddress.c:2939
+#: catalog/objectaddress.c:3064
#, c-format
msgid "text search dictionary %s"
msgstr "Textsuchewörterbuch %s"
-#: catalog/objectaddress.c:2954
+#: catalog/objectaddress.c:3079
#, c-format
msgid "text search template %s"
msgstr "Textsuchevorlage %s"
-#: catalog/objectaddress.c:2969
+#: catalog/objectaddress.c:3094
#, c-format
msgid "text search configuration %s"
msgstr "Textsuchekonfiguration %s"
-#: catalog/objectaddress.c:2977
+#: catalog/objectaddress.c:3102
#, c-format
msgid "role %s"
msgstr "Rolle %s"
-#: catalog/objectaddress.c:2990
+#: catalog/objectaddress.c:3115
#, c-format
msgid "database %s"
msgstr "Datenbank %s"
-#: catalog/objectaddress.c:3002
+#: catalog/objectaddress.c:3127
#, c-format
msgid "tablespace %s"
msgstr "Tablespace %s"
-#: catalog/objectaddress.c:3011
+#: catalog/objectaddress.c:3136
#, c-format
msgid "foreign-data wrapper %s"
msgstr "Fremddaten-Wrapper %s"
-#: catalog/objectaddress.c:3020
+#: catalog/objectaddress.c:3145
#, c-format
msgid "server %s"
msgstr "Server %s"
-#: catalog/objectaddress.c:3048
+#: catalog/objectaddress.c:3173
#, c-format
msgid "user mapping for %s on server %s"
msgstr "Benutzerabbildung für %s auf Server %s"
-#: catalog/objectaddress.c:3083
+#: catalog/objectaddress.c:3208
#, c-format
msgid "default privileges on new relations belonging to role %s"
msgstr "Vorgabeprivilegien für neue Relationen von Rolle %s"
-#: catalog/objectaddress.c:3088
+#: catalog/objectaddress.c:3213
#, c-format
msgid "default privileges on new sequences belonging to role %s"
msgstr "Vorgabeprivilegien für neue Sequenzen von Rolle %s"
-#: catalog/objectaddress.c:3093
+#: catalog/objectaddress.c:3218
#, c-format
msgid "default privileges on new functions belonging to role %s"
msgstr "Vorgabeprivilegien für neue Funktionen von Rolle %s"
-#: catalog/objectaddress.c:3098
+#: catalog/objectaddress.c:3223
#, c-format
msgid "default privileges on new types belonging to role %s"
msgstr "Vorgabeprivilegien für neue Typen von Rolle %s"
-#: catalog/objectaddress.c:3104
+#: catalog/objectaddress.c:3229
#, c-format
msgid "default privileges belonging to role %s"
msgstr "Vorgabeprivilegien von Rolle %s"
-#: catalog/objectaddress.c:3112
+#: catalog/objectaddress.c:3237
#, c-format
msgid " in schema %s"
msgstr " in Schema %s"
-#: catalog/objectaddress.c:3129
+#: catalog/objectaddress.c:3254
#, c-format
msgid "extension %s"
msgstr "Erweiterung %s"
-#: catalog/objectaddress.c:3142
+#: catalog/objectaddress.c:3267
#, c-format
msgid "event trigger %s"
msgstr "Ereignistrigger %s"
-#: catalog/objectaddress.c:3174
+#: catalog/objectaddress.c:3299
#, c-format
msgid "policy %s on "
msgstr "Policy %s für "
-#: catalog/objectaddress.c:3192
+#: catalog/objectaddress.c:3317
#, c-format
msgid "access method %s"
msgstr "Zugriffsmethode %s"
-#: catalog/objectaddress.c:3252
+#: catalog/objectaddress.c:3325
+#, c-format
+msgid "publication %s"
+msgstr "Publikation %s"
+
+#: catalog/objectaddress.c:3345
+#, c-format
+msgid "publication table %s in publication %s"
+msgstr "Publikationstabelle %s in Publikation %s"
+
+#: catalog/objectaddress.c:3353
+#, c-format
+msgid "subscription %s"
+msgstr "Subskription %s"
+
+#: catalog/objectaddress.c:3413
#, c-format
msgid "table %s"
msgstr "Tabelle %s"
-#: catalog/objectaddress.c:3256
+#: catalog/objectaddress.c:3417
#, c-format
msgid "index %s"
msgstr "Index %s"
-#: catalog/objectaddress.c:3260
+#: catalog/objectaddress.c:3421
#, c-format
msgid "sequence %s"
msgstr "Sequenz %s"
-#: catalog/objectaddress.c:3264
+#: catalog/objectaddress.c:3425
#, c-format
msgid "toast table %s"
msgstr "TOAST-Tabelle %s"
-#: catalog/objectaddress.c:3268
+#: catalog/objectaddress.c:3429
#, c-format
msgid "view %s"
msgstr "Sicht %s"
-#: catalog/objectaddress.c:3272
+#: catalog/objectaddress.c:3433
#, c-format
msgid "materialized view %s"
msgstr "materialisierte Sicht %s"
-#: catalog/objectaddress.c:3276
+#: catalog/objectaddress.c:3437
#, c-format
msgid "composite type %s"
msgstr "zusammengesetzter Typ %s"
-#: catalog/objectaddress.c:3280
+#: catalog/objectaddress.c:3441
#, c-format
msgid "foreign table %s"
msgstr "Fremdtabelle %s"
-#: catalog/objectaddress.c:3285
+#: catalog/objectaddress.c:3446
#, c-format
msgid "relation %s"
msgstr "Relation %s"
-#: catalog/objectaddress.c:3322
+#: catalog/objectaddress.c:3483
#, c-format
msgid "operator family %s for access method %s"
msgstr "Operatorfamilie %s für Zugriffsmethode %s"
+#: catalog/objectaddress.c:4854
+#, c-format
+msgid "%s in publication %s"
+msgstr "%s in Publikation %s"
+
+#: catalog/partition.c:741
+#, fuzzy, c-format
+#| msgid "cannot determine transition data type"
+msgid "cannot create range partition with empty range"
+msgstr "kann Übergangsdatentyp nicht bestimmen"
+
+#: catalog/partition.c:835
+#, fuzzy, c-format
+#| msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgid "partition \"%s\" would overlap partition \"%s\""
+msgstr "Relation »%s« ist keine Basisrelation von Relation »%s«"
+
+#: catalog/partition.c:939 catalog/partition.c:1088 commands/analyze.c:1438
+#: commands/tablecmds.c:8564 executor/execMain.c:3159 executor/execQual.c:2691
+msgid "could not convert row type"
+msgstr "konnte Zeilentyp nicht umwandeln"
+
+#: catalog/partition.c:1726
+#, c-format
+msgid "range partition key of row contains null"
+msgstr ""
+
#: catalog/pg_aggregate.c:125
#, c-format
msgid "aggregates cannot have more than %d argument"
@@ -4413,7 +4533,7 @@ msgstr "Anfangswert darf nicht ausgelassen werden, wenn Übergangsfunktion strik
msgid "return type of inverse transition function %s is not %s"
msgstr "Rückgabetyp der inversen Übergangsfunktion %s ist nicht %s"
-#: catalog/pg_aggregate.c:351 executor/nodeWindowAgg.c:2305
+#: catalog/pg_aggregate.c:351 executor/nodeWindowAgg.c:2298
#, c-format
msgid "strictness of aggregate's forward and inverse transition functions must match"
msgstr "Striktheit der vorwärtigen und inversen Übergangsfunktionen einer Aggregatfunktion müssen übereinstimmen"
@@ -4443,7 +4563,7 @@ msgstr "Rückgabetyp der Serialisierungsfunktion %s ist nicht %s"
msgid "return type of deserialization function %s is not %s"
msgstr "Rückgabetyp der Deserialisierungsfunktion %s ist nicht %s"
-#: catalog/pg_aggregate.c:491 catalog/pg_proc.c:246 catalog/pg_proc.c:253
+#: catalog/pg_aggregate.c:491 catalog/pg_proc.c:243 catalog/pg_proc.c:250
#, c-format
msgid "cannot determine result data type"
msgstr "kann Ergebnisdatentyp nicht bestimmen"
@@ -4453,12 +4573,12 @@ msgstr "kann Ergebnisdatentyp nicht bestimmen"
msgid "An aggregate returning a polymorphic type must have at least one polymorphic argument."
msgstr "Eine Aggregatfunktion, die einen polymorphischen Typ zurückgibt, muss mindestens ein polymorphisches Argument haben."
-#: catalog/pg_aggregate.c:504 catalog/pg_proc.c:259
+#: catalog/pg_aggregate.c:504 catalog/pg_proc.c:256
#, c-format
msgid "unsafe use of pseudo-type \"internal\""
msgstr "unsichere Verwendung des Pseudotyps »internal«"
-#: catalog/pg_aggregate.c:505 catalog/pg_proc.c:260
+#: catalog/pg_aggregate.c:505 catalog/pg_proc.c:257
#, c-format
msgid "A function returning \"internal\" must have at least one \"internal\" argument."
msgstr "Eine Funktion, die »internal« zurückgibt, muss mindestens ein Argument vom Typ »internal« haben."
@@ -4473,62 +4593,72 @@ msgstr "Moving-Aggregat-Implementierung gibt Typ %s zurück, aber die normale Im
msgid "sort operator can only be specified for single-argument aggregates"
msgstr "Sortieroperator kann nur für Aggregatfunktionen mit einem Argument angegeben werden"
-#: catalog/pg_aggregate.c:812 commands/typecmds.c:1705
-#: commands/typecmds.c:1756 commands/typecmds.c:1787 commands/typecmds.c:1810
-#: commands/typecmds.c:1831 commands/typecmds.c:1858 commands/typecmds.c:1885
-#: commands/typecmds.c:1962 commands/typecmds.c:2004 parser/parse_func.c:364
-#: parser/parse_func.c:393 parser/parse_func.c:418 parser/parse_func.c:432
-#: parser/parse_func.c:507 parser/parse_func.c:518 parser/parse_func.c:1923
+#: catalog/pg_aggregate.c:810 commands/typecmds.c:1698
+#: commands/typecmds.c:1749 commands/typecmds.c:1780 commands/typecmds.c:1803
+#: commands/typecmds.c:1824 commands/typecmds.c:1851 commands/typecmds.c:1878
+#: commands/typecmds.c:1955 commands/typecmds.c:1997 parser/parse_func.c:365
+#: parser/parse_func.c:394 parser/parse_func.c:419 parser/parse_func.c:433
+#: parser/parse_func.c:508 parser/parse_func.c:519 parser/parse_func.c:1927
#, c-format
msgid "function %s does not exist"
msgstr "Funktion %s existiert nicht"
-#: catalog/pg_aggregate.c:818
+#: catalog/pg_aggregate.c:816
#, c-format
msgid "function %s returns a set"
msgstr "Funktion %s gibt eine Ergebnismenge zurück"
-#: catalog/pg_aggregate.c:833
+#: catalog/pg_aggregate.c:831
#, c-format
msgid "function %s must accept VARIADIC ANY to be used in this aggregate"
msgstr "Funktion %s muss VARIADIC ANY akzeptieren, um in dieser Aggregatfunktion verwendet zu werden"
-#: catalog/pg_aggregate.c:857
+#: catalog/pg_aggregate.c:855
#, c-format
msgid "function %s requires run-time type coercion"
msgstr "Funktion %s erfordert Typumwandlung zur Laufzeit"
-#: catalog/pg_collation.c:77
+#: catalog/pg_collation.c:81
+#, c-format
+msgid "collation \"%s\" for encoding \"%s\" already exists, skipping"
+msgstr "Sortierfolge »%s« für Kodierung »%s« existiert bereits, wird übersprungen"
+
+#: catalog/pg_collation.c:88
#, c-format
msgid "collation \"%s\" for encoding \"%s\" already exists"
msgstr "Sortierfolge »%s« für Kodierung »%s« existiert bereits"
-#: catalog/pg_collation.c:91
+#: catalog/pg_collation.c:106
+#, c-format
+msgid "collation \"%s\" already exists, skipping"
+msgstr "Sortierfolge »%s« existiert bereits, wird übersprungen"
+
+#: catalog/pg_collation.c:113
#, c-format
msgid "collation \"%s\" already exists"
msgstr "Sortierfolge »%s« existiert bereits"
-#: catalog/pg_constraint.c:663
+#: catalog/pg_constraint.c:658
#, c-format
msgid "constraint \"%s\" for domain %s already exists"
msgstr "Constraint »%s« für Domäne %s existiert bereits"
-#: catalog/pg_constraint.c:797
+#: catalog/pg_constraint.c:788
#, c-format
msgid "table \"%s\" has multiple constraints named \"%s\""
msgstr "Tabelle »%s« hat mehrere Constraints namens »%s«"
-#: catalog/pg_constraint.c:809
+#: catalog/pg_constraint.c:800
#, c-format
msgid "constraint \"%s\" for table \"%s\" does not exist"
msgstr "Constraint »%s« für Tabelle »%s« existiert nicht"
-#: catalog/pg_constraint.c:855
+#: catalog/pg_constraint.c:846
#, c-format
msgid "domain \"%s\" has multiple constraints named \"%s\""
msgstr "Domäne »%s« hat mehrere Constraints namens »%s«"
-#: catalog/pg_constraint.c:867
+#: catalog/pg_constraint.c:858
#, c-format
msgid "constraint \"%s\" for domain \"%s\" does not exist"
msgstr "Constraint »%s« für Domäne »%s« existiert nicht"
@@ -4543,215 +4673,251 @@ msgstr "Konversion »%s« existiert bereits"
msgid "default conversion for %s to %s already exists"
msgstr "Standardumwandlung von %s nach %s existiert bereits"
-#: catalog/pg_depend.c:165 commands/extension.c:3028
+#: catalog/pg_depend.c:163 commands/extension.c:3211
#, c-format
msgid "%s is already a member of extension \"%s\""
msgstr "%s ist schon Mitglied der Erweiterung »%s«"
-#: catalog/pg_depend.c:324
+#: catalog/pg_depend.c:322
#, c-format
msgid "cannot remove dependency on %s because it is a system object"
msgstr "kann Abhängigkeit von %s nicht entfernen, weil es ein Systemobjekt ist"
-#: catalog/pg_enum.c:115 catalog/pg_enum.c:202
+#: catalog/pg_enum.c:115 catalog/pg_enum.c:201 catalog/pg_enum.c:488
#, c-format
msgid "invalid enum label \"%s\""
msgstr "ungültiges Enum-Label »%s«"
-#: catalog/pg_enum.c:116 catalog/pg_enum.c:203
+#: catalog/pg_enum.c:116 catalog/pg_enum.c:202 catalog/pg_enum.c:489
#, c-format
msgid "Labels must be %d characters or less."
msgstr "Labels müssen %d oder weniger Zeichen haben."
-#: catalog/pg_enum.c:231
+#: catalog/pg_enum.c:230
#, c-format
msgid "enum label \"%s\" already exists, skipping"
msgstr "Enum-Label »%s« existiert bereits, wird übersprungen"
-#: catalog/pg_enum.c:238
+#: catalog/pg_enum.c:237 catalog/pg_enum.c:532
#, c-format
msgid "enum label \"%s\" already exists"
msgstr "Enum-Label »%s« existiert bereits"
-#: catalog/pg_enum.c:293
+#: catalog/pg_enum.c:292 catalog/pg_enum.c:527
#, c-format
msgid "\"%s\" is not an existing enum label"
msgstr "»%s« ist kein existierendes Enum-Label"
-#: catalog/pg_enum.c:349
+#: catalog/pg_enum.c:350
#, c-format
msgid "pg_enum OID value not set when in binary upgrade mode"
msgstr "OID-Wert für pg_enum ist im Binary-Upgrade-Modus nicht gesetzt"
-#: catalog/pg_enum.c:359
+#: catalog/pg_enum.c:360
#, c-format
msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade"
msgstr "ALTER TYPE ADD BEFORE/AFTER ist mit Binary Upgrade inkompatibel"
-#: catalog/pg_namespace.c:61 commands/schemacmds.c:246
+#: catalog/pg_namespace.c:61 commands/schemacmds.c:263
#, c-format
msgid "schema \"%s\" already exists"
msgstr "Schema »%s« existiert bereits"
-#: catalog/pg_operator.c:219 catalog/pg_operator.c:360
+#: catalog/pg_operator.c:219 catalog/pg_operator.c:358
#, c-format
msgid "\"%s\" is not a valid operator name"
msgstr "»%s« ist kein gültiger Operatorname"
-#: catalog/pg_operator.c:369
+#: catalog/pg_operator.c:367
#, c-format
msgid "only binary operators can have commutators"
msgstr "nur binäre Operatoren können Kommutatoren haben"
-#: catalog/pg_operator.c:373 commands/operatorcmds.c:485
+#: catalog/pg_operator.c:371 commands/operatorcmds.c:482
#, c-format
msgid "only binary operators can have join selectivity"
msgstr "nur binäre Operatoren können Join-Selectivity haben"
-#: catalog/pg_operator.c:377
+#: catalog/pg_operator.c:375
#, c-format
msgid "only binary operators can merge join"
msgstr "nur binäre Operatoren können an einem Merge-Verbund teilnehmen"
-#: catalog/pg_operator.c:381
+#: catalog/pg_operator.c:379
#, c-format
msgid "only binary operators can hash"
msgstr "nur binäre Operatoren können eine Hash-Funktion haben"
-#: catalog/pg_operator.c:392
+#: catalog/pg_operator.c:390
#, c-format
msgid "only boolean operators can have negators"
msgstr "nur Boole’sche Operatoren können Negatoren haben"
-#: catalog/pg_operator.c:396 commands/operatorcmds.c:493
+#: catalog/pg_operator.c:394 commands/operatorcmds.c:490
#, c-format
msgid "only boolean operators can have restriction selectivity"
msgstr "nur Boole’sche Operatoren können Restriction-Selectivity haben"
-#: catalog/pg_operator.c:400 commands/operatorcmds.c:497
+#: catalog/pg_operator.c:398 commands/operatorcmds.c:494
#, c-format
msgid "only boolean operators can have join selectivity"
msgstr "nur Boole’sche Operatoren können Join-Selectivity haben"
-#: catalog/pg_operator.c:404
+#: catalog/pg_operator.c:402
#, c-format
msgid "only boolean operators can merge join"
msgstr "nur Boole’sche Operatoren können an einem Merge-Verbund teilnehmen"
-#: catalog/pg_operator.c:408
+#: catalog/pg_operator.c:406
#, c-format
msgid "only boolean operators can hash"
msgstr "nur Boole’sche Operatoren können eine Hash-Funktion haben"
-#: catalog/pg_operator.c:420
+#: catalog/pg_operator.c:418
#, c-format
msgid "operator %s already exists"
msgstr "Operator %s existiert bereits"
-#: catalog/pg_operator.c:617
+#: catalog/pg_operator.c:612
#, c-format
msgid "operator cannot be its own negator or sort operator"
msgstr "Operator kann nicht sein eigener Negator oder Sortierungsoperator sein"
-#: catalog/pg_proc.c:134 parser/parse_func.c:1947 parser/parse_func.c:1987
+#: catalog/pg_proc.c:131 parser/parse_func.c:1951 parser/parse_func.c:1991
#, c-format
msgid "functions cannot have more than %d argument"
msgid_plural "functions cannot have more than %d arguments"
msgstr[0] "Funktionen können nicht mehr als %d Argument haben"
msgstr[1] "Funktionen können nicht mehr als %d Argumente haben"
-#: catalog/pg_proc.c:247
+#: catalog/pg_proc.c:244
#, c-format
msgid "A function returning a polymorphic type must have at least one polymorphic argument."
msgstr "Eine Funktion, die einen polymorphischen Typ zurückgibt, muss mindestens ein polymorphisches Argument haben."
-#: catalog/pg_proc.c:254
+#: catalog/pg_proc.c:251
#, c-format
msgid "A function returning \"anyrange\" must have at least one \"anyrange\" argument."
msgstr "Eine Funktion, die »anyrange« zurückgibt, muss mindestens ein Argument vom Typ »anyrange« haben."
-#: catalog/pg_proc.c:272
+#: catalog/pg_proc.c:269
#, c-format
msgid "\"%s\" is already an attribute of type %s"
msgstr "»%s« ist schon ein Attribut von Typ %s"
-#: catalog/pg_proc.c:403
+#: catalog/pg_proc.c:400
#, c-format
msgid "function \"%s\" already exists with same argument types"
msgstr "Funktion »%s« existiert bereits mit den selben Argumenttypen"
-#: catalog/pg_proc.c:417 catalog/pg_proc.c:440
+#: catalog/pg_proc.c:414 catalog/pg_proc.c:437
#, c-format
msgid "cannot change return type of existing function"
msgstr "kann Rückgabetyp einer bestehenden Funktion nicht ändern"
-#: catalog/pg_proc.c:418 catalog/pg_proc.c:442 catalog/pg_proc.c:485
-#: catalog/pg_proc.c:509 catalog/pg_proc.c:536
+#: catalog/pg_proc.c:415 catalog/pg_proc.c:439 catalog/pg_proc.c:482
+#: catalog/pg_proc.c:506 catalog/pg_proc.c:532
#, c-format
msgid "Use DROP FUNCTION %s first."
msgstr "Verwenden Sie zuerst DROP FUNCTION %s."
-#: catalog/pg_proc.c:441
+#: catalog/pg_proc.c:438
#, c-format
msgid "Row type defined by OUT parameters is different."
msgstr "Der von OUT-Parametern bestimmte Zeilentyp ist verschieden."
-#: catalog/pg_proc.c:483
+#: catalog/pg_proc.c:480
#, c-format
msgid "cannot change name of input parameter \"%s\""
msgstr "kann Name des Eingabeparameters »%s« nicht ändern"
-#: catalog/pg_proc.c:508
+#: catalog/pg_proc.c:505
#, c-format
msgid "cannot remove parameter defaults from existing function"
msgstr "kann Parametervorgabewerte einer bestehenden Funktion nicht entfernen"
-#: catalog/pg_proc.c:535
+#: catalog/pg_proc.c:531
#, c-format
msgid "cannot change data type of existing parameter default value"
msgstr "kann Datentyp eines bestehenden Parametervorgabewerts nicht ändern"
-#: catalog/pg_proc.c:548
+#: catalog/pg_proc.c:544
#, c-format
msgid "function \"%s\" is an aggregate function"
msgstr "Funktion »%s« ist eine Aggregatfunktion"
-#: catalog/pg_proc.c:553
+#: catalog/pg_proc.c:549
#, c-format
msgid "function \"%s\" is not an aggregate function"
msgstr "Funktion »%s« ist keine Aggregatfunktion"
-#: catalog/pg_proc.c:561
+#: catalog/pg_proc.c:557
#, c-format
msgid "function \"%s\" is a window function"
msgstr "Funktion %s ist eine Fensterfunktion"
-#: catalog/pg_proc.c:566
+#: catalog/pg_proc.c:562
#, c-format
msgid "function \"%s\" is not a window function"
msgstr "Funktion »%s« ist keine Fensterfunktion"
-#: catalog/pg_proc.c:774
+#: catalog/pg_proc.c:768
#, c-format
msgid "there is no built-in function named \"%s\""
msgstr "es gibt keine eingebaute Funktion namens %s"
-#: catalog/pg_proc.c:872
+#: catalog/pg_proc.c:866
#, c-format
msgid "SQL functions cannot return type %s"
msgstr "SQL-Funktionen können keinen Rückgabetyp »%s« haben"
-#: catalog/pg_proc.c:887
+#: catalog/pg_proc.c:881
#, c-format
msgid "SQL functions cannot have arguments of type %s"
msgstr "SQL-Funktionen können keine Argumente vom Typ »%s« haben"
-#: catalog/pg_proc.c:973 executor/functions.c:1424
+#: catalog/pg_proc.c:967 executor/functions.c:1424
#, c-format
msgid "SQL function \"%s\""
msgstr "SQL-Funktion »%s«"
-#: catalog/pg_shdepend.c:694
+#: catalog/pg_publication.c:59
+#, c-format
+msgid "Only tables can be added to publications."
+msgstr "Nur Tabellen können Teil einer Publikationen sein."
+
+#: catalog/pg_publication.c:65
+#, c-format
+msgid "\"%s\" is a system table"
+msgstr "»%s« ist eine Systemtabelle"
+
+#: catalog/pg_publication.c:67
+#, c-format
+msgid "System tables cannot be added to publications."
+msgstr "Systemtabellen können nicht Teil einer Publikationen sein."
+
+#: catalog/pg_publication.c:73
+#, c-format
+msgid "table \"%s\" cannot be replicated"
+msgstr "Tabelle »%s« kann nicht repliziert werden"
+
+#: catalog/pg_publication.c:75
+#, c-format
+msgid "Temporary and unlogged relations cannot be replicated."
+msgstr "Temporäre und ungeloggte Tabellen können nicht repliziert werden."
+
+#: catalog/pg_publication.c:134
+#, c-format
+msgid "relation \"%s\" is already member of publication \"%s\""
+msgstr "Relation »%s« ist schon Mitglied der Publikation »%s«"
+
+#: catalog/pg_publication.c:361 catalog/pg_publication.c:382
+#: commands/publicationcmds.c:430 commands/publicationcmds.c:715
+#, c-format
+msgid "publication \"%s\" does not exist"
+msgstr "Publikation »%s« existiert nicht"
+
+#: catalog/pg_shdepend.c:691
#, c-format
msgid ""
"\n"
@@ -4766,92 +4932,98 @@ msgstr[1] ""
"\n"
"und Objekte in %d anderen Datenbanken (Liste im Serverlog)"
-#: catalog/pg_shdepend.c:1006
+#: catalog/pg_shdepend.c:997
#, c-format
msgid "role %u was concurrently dropped"
msgstr "Rolle %u wurde gleichzeitig gelöscht"
-#: catalog/pg_shdepend.c:1025
+#: catalog/pg_shdepend.c:1016
#, c-format
msgid "tablespace %u was concurrently dropped"
msgstr "Tablespace %u wurde gleichzeitig gelöscht"
-#: catalog/pg_shdepend.c:1040
+#: catalog/pg_shdepend.c:1031
#, c-format
msgid "database %u was concurrently dropped"
msgstr "Datenbank %u wurde gleichzeitig gelöscht"
-#: catalog/pg_shdepend.c:1085
+#: catalog/pg_shdepend.c:1076
#, c-format
msgid "owner of %s"
msgstr "Eigentümer von %s"
-#: catalog/pg_shdepend.c:1087
+#: catalog/pg_shdepend.c:1078
#, c-format
msgid "privileges for %s"
msgstr "Privilegien für %s"
-#: catalog/pg_shdepend.c:1089
+#: catalog/pg_shdepend.c:1080
#, c-format
msgid "target of %s"
msgstr "Ziel von %s"
#. translator: %s will always be "database %s"
-#: catalog/pg_shdepend.c:1097
+#: catalog/pg_shdepend.c:1088
#, c-format
msgid "%d object in %s"
msgid_plural "%d objects in %s"
msgstr[0] "%d Objekt in %s"
msgstr[1] "%d Objekte in %s"
-#: catalog/pg_shdepend.c:1208
+#: catalog/pg_shdepend.c:1199
#, c-format
msgid "cannot drop objects owned by %s because they are required by the database system"
msgstr "kann Objekte, die %s gehören, nicht löschen, weil sie vom Datenbanksystem benötigt werden"
-#: catalog/pg_shdepend.c:1323
+#: catalog/pg_shdepend.c:1314
#, c-format
msgid "cannot reassign ownership of objects owned by %s because they are required by the database system"
msgstr "kann den Eigentümer von den Objekten, die %s gehören, nicht ändern, weil die Objekte vom Datenbanksystem benötigt werden"
-#: catalog/pg_type.c:136 catalog/pg_type.c:454
+#: catalog/pg_subscription.c:158 commands/subscriptioncmds.c:373
+#: commands/subscriptioncmds.c:481 commands/subscriptioncmds.c:651
+#, c-format
+msgid "subscription \"%s\" does not exist"
+msgstr "Subskription »%s« existiert nicht"
+
+#: catalog/pg_type.c:136 catalog/pg_type.c:452
#, c-format
msgid "pg_type OID value not set when in binary upgrade mode"
msgstr "OID-Wert für pg_type ist im Binary-Upgrade-Modus nicht gesetzt"
-#: catalog/pg_type.c:253
+#: catalog/pg_type.c:251
#, c-format
msgid "invalid type internal size %d"
msgstr "ungültige interne Typgröße %d"
-#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285
-#: catalog/pg_type.c:294
+#: catalog/pg_type.c:267 catalog/pg_type.c:275 catalog/pg_type.c:283
+#: catalog/pg_type.c:292
#, c-format
msgid "alignment \"%c\" is invalid for passed-by-value type of size %d"
msgstr "Ausrichtung »%c« ist ungültig für Typen mit Wertübergabe mit Größe %d"
-#: catalog/pg_type.c:301
+#: catalog/pg_type.c:299
#, c-format
msgid "internal size %d is invalid for passed-by-value type"
msgstr "interne Größe %d ist ungültig für Typen mit Wertübergabe"
-#: catalog/pg_type.c:310 catalog/pg_type.c:316
+#: catalog/pg_type.c:308 catalog/pg_type.c:314
#, c-format
msgid "alignment \"%c\" is invalid for variable-length type"
msgstr "Ausrichtung »%c« ist ungültig für Typen variabler Länge"
-#: catalog/pg_type.c:324
+#: catalog/pg_type.c:322
#, c-format
msgid "fixed-size types must have storage PLAIN"
msgstr "Typen mit fester Größe müssen Storage-Typ PLAIN haben"
-#: catalog/pg_type.c:789
+#: catalog/pg_type.c:781
#, c-format
msgid "could not form array type name for type \"%s\""
msgstr "konnte keinen Arraytypnamen für Datentyp »%s« erzeugen"
-#: catalog/toasting.c:105 commands/indexcmds.c:389 commands/tablecmds.c:4358
-#: commands/tablecmds.c:11900
+#: catalog/toasting.c:105 commands/indexcmds.c:395 commands/tablecmds.c:4677
+#: commands/tablecmds.c:12627
#, c-format
msgid "\"%s\" is not a table or materialized view"
msgstr "»%s« ist keine Tabelle oder materialisierte Sicht"
@@ -4861,142 +5033,152 @@ msgstr "»%s« ist keine Tabelle oder materialisierte Sicht"
msgid "shared tables cannot be toasted after initdb"
msgstr "Cluster-globale Tabellen können nach initdb nicht mehr getoastet werden"
-#: commands/aggregatecmds.c:159
+#: commands/aggregatecmds.c:157
#, c-format
msgid "only ordered-set aggregates can be hypothetical"
msgstr "nur Ordered-Set-Aggregatfunktionen können Hypothetical-Set-Aggregatfunktionen sein"
-#: commands/aggregatecmds.c:184
+#: commands/aggregatecmds.c:182
#, c-format
msgid "aggregate attribute \"%s\" not recognized"
msgstr "Attribut »%s« für Aggregatfunktion unbekannt"
-#: commands/aggregatecmds.c:194
+#: commands/aggregatecmds.c:192
#, c-format
msgid "aggregate stype must be specified"
msgstr "»stype« für Aggregatfunktion muss angegeben werden"
-#: commands/aggregatecmds.c:198
+#: commands/aggregatecmds.c:196
#, c-format
msgid "aggregate sfunc must be specified"
msgstr "»sfunc« für Aggregatfunktion muss angegeben werden"
-#: commands/aggregatecmds.c:210
+#: commands/aggregatecmds.c:208
#, c-format
msgid "aggregate msfunc must be specified when mstype is specified"
msgstr "»msfunc« für Aggregatfunktion muss angegeben werden, wenn »mstype« angegeben ist"
-#: commands/aggregatecmds.c:214
+#: commands/aggregatecmds.c:212
#, c-format
msgid "aggregate minvfunc must be specified when mstype is specified"
msgstr "»minvfunc« für Aggregatfunktion muss angegeben werden, wenn »mstype« angegeben ist"
-#: commands/aggregatecmds.c:221
+#: commands/aggregatecmds.c:219
#, c-format
msgid "aggregate msfunc must not be specified without mstype"
msgstr "»msfunc« für Aggregatfunktion darf nicht angegeben werden, wenn »mstype« nicht angegeben ist"
-#: commands/aggregatecmds.c:225
+#: commands/aggregatecmds.c:223
#, c-format
msgid "aggregate minvfunc must not be specified without mstype"
msgstr "»minvfunc« für Aggregatfunktion darf nicht angegeben werden, wenn »mstype« nicht angegeben ist"
-#: commands/aggregatecmds.c:229
+#: commands/aggregatecmds.c:227
#, c-format
msgid "aggregate mfinalfunc must not be specified without mstype"
msgstr "»mfinalfunc« für Aggregatfunktion darf nicht angegeben werden, wenn »mstype« nicht angegeben ist"
-#: commands/aggregatecmds.c:233
+#: commands/aggregatecmds.c:231
#, c-format
msgid "aggregate msspace must not be specified without mstype"
msgstr "»msspace« für Aggregatfunktion darf nicht angegeben werden, wenn »mstype« nicht angegeben ist"
-#: commands/aggregatecmds.c:237
+#: commands/aggregatecmds.c:235
#, c-format
msgid "aggregate minitcond must not be specified without mstype"
msgstr "»minitcond« für Aggregatfunktion darf nicht angegeben werden, wenn »mstype« nicht angegeben ist"
-#: commands/aggregatecmds.c:257
+#: commands/aggregatecmds.c:255
#, c-format
msgid "aggregate input type must be specified"
msgstr "Eingabetyp für Aggregatfunktion muss angegeben werden"
-#: commands/aggregatecmds.c:287
+#: commands/aggregatecmds.c:285
#, c-format
msgid "basetype is redundant with aggregate input type specification"
msgstr "Angabe »basetype« ist überflüssig bei Angabe des Eingabetyps der Aggregatfunktion"
-#: commands/aggregatecmds.c:328 commands/aggregatecmds.c:369
+#: commands/aggregatecmds.c:326 commands/aggregatecmds.c:367
#, c-format
msgid "aggregate transition data type cannot be %s"
msgstr "Übergangsdatentyp von Aggregatfunktion kann nicht %s sein"
-#: commands/aggregatecmds.c:340
+#: commands/aggregatecmds.c:338
#, c-format
msgid "serialization functions may be specified only when the aggregate transition data type is %s"
msgstr "Serialisierungsfunktionen dürfen nur angegeben werden, wenn der Übergangsdatentyp der Aggregatfunktion %s ist"
-#: commands/aggregatecmds.c:350
+#: commands/aggregatecmds.c:348
#, c-format
msgid "must specify both or neither of serialization and deserialization functions"
msgstr "Serialisierungs- und Deserialisierungsfunktionen müssen zusammen angegeben werden"
-#: commands/aggregatecmds.c:415 commands/functioncmds.c:570
+#: commands/aggregatecmds.c:413 commands/functioncmds.c:564
#, c-format
msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE"
msgstr "Parameter »parallel« muss SAFE, RESTRICTED oder UNSAFE sein"
-#: commands/alter.c:80 commands/event_trigger.c:231
+#: commands/alter.c:83 commands/event_trigger.c:233
#, c-format
msgid "event trigger \"%s\" already exists"
msgstr "Ereignistrigger »%s« existiert bereits"
-#: commands/alter.c:83 commands/foreigncmds.c:597
+#: commands/alter.c:86 commands/foreigncmds.c:595
#, c-format
msgid "foreign-data wrapper \"%s\" already exists"
msgstr "Fremddaten-Wrapper »%s« existiert bereits"
-#: commands/alter.c:86 commands/foreigncmds.c:890
+#: commands/alter.c:89 commands/foreigncmds.c:886
#, c-format
msgid "server \"%s\" already exists"
msgstr "Server »%s« existiert bereits"
-#: commands/alter.c:89 commands/proclang.c:366
+#: commands/alter.c:92 commands/proclang.c:367
#, c-format
msgid "language \"%s\" already exists"
msgstr "Sprache »%s« existiert bereits"
-#: commands/alter.c:112
+#: commands/alter.c:95 commands/publicationcmds.c:189
+#, c-format
+msgid "publication \"%s\" already exists"
+msgstr "Publikation »%s« existiert bereits"
+
+#: commands/alter.c:98 commands/subscriptioncmds.c:256
+#, c-format
+msgid "subscription \"%s\" already exists"
+msgstr "Subskription »%s« existiert bereits"
+
+#: commands/alter.c:121
#, c-format
msgid "conversion \"%s\" already exists in schema \"%s\""
msgstr "Konversion »%s« existiert bereits in Schema »%s«"
-#: commands/alter.c:116
+#: commands/alter.c:125
#, c-format
msgid "text search parser \"%s\" already exists in schema \"%s\""
msgstr "Textsucheparser »%s« existiert bereits in Schema »%s«"
-#: commands/alter.c:120
+#: commands/alter.c:129
#, c-format
msgid "text search dictionary \"%s\" already exists in schema \"%s\""
msgstr "Textsuchewörterbuch »%s« existiert bereits in Schema »%s«"
-#: commands/alter.c:124
+#: commands/alter.c:133
#, c-format
msgid "text search template \"%s\" already exists in schema \"%s\""
msgstr "Textsuchevorlage »%s« existiert bereits in Schema »%s«"
-#: commands/alter.c:128
+#: commands/alter.c:137
#, c-format
msgid "text search configuration \"%s\" already exists in schema \"%s\""
msgstr "Textsuchekonfiguration »%s« existiert bereits in Schema »%s«"
-#: commands/alter.c:202
+#: commands/alter.c:211
#, c-format
msgid "must be superuser to rename %s"
msgstr "nur Superuser können %s umbenennen"
-#: commands/alter.c:655
+#: commands/alter.c:670
#, c-format
msgid "must be superuser to set schema of %s"
msgstr "nur Superuser können Schema von %s setzen"
@@ -5016,25 +5198,25 @@ msgstr "Nur Superuser können Zugriffsmethoden anlegen."
msgid "access method \"%s\" already exists"
msgstr "Zugriffsmethode »%s« existiert bereits"
-#: commands/amcmds.c:124
+#: commands/amcmds.c:123
#, c-format
msgid "must be superuser to drop access methods"
msgstr "nur Superuser können Zugriffsmethoden löschen"
-#: commands/amcmds.c:175 commands/indexcmds.c:164 commands/indexcmds.c:495
-#: commands/opclasscmds.c:365 commands/opclasscmds.c:790
+#: commands/amcmds.c:174 commands/indexcmds.c:163 commands/indexcmds.c:502
+#: commands/opclasscmds.c:363 commands/opclasscmds.c:777
#, c-format
msgid "access method \"%s\" does not exist"
msgstr "Zugriffsmethode »%s« existiert nicht"
-#: commands/amcmds.c:251
+#: commands/amcmds.c:250
#, c-format
msgid "handler function is not specified"
msgstr "keine Handler-Funktion angegeben"
-#: commands/amcmds.c:263 commands/event_trigger.c:240
-#: commands/foreigncmds.c:489 commands/proclang.c:117 commands/proclang.c:288
-#: commands/trigger.c:441 parser/parse_clause.c:761
+#: commands/amcmds.c:262 commands/event_trigger.c:242
+#: commands/foreigncmds.c:487 commands/proclang.c:117 commands/proclang.c:289
+#: commands/trigger.c:531 parser/parse_clause.c:961
#, c-format
msgid "function %s must return type %s"
msgstr "Function %s muss Rückgabetyp %s haben"
@@ -5064,45 +5246,41 @@ msgstr "überspringe »%s« --- nur Eigentümer der Tabelle oder der Datenbank k
msgid "skipping \"%s\" --- cannot analyze this foreign table"
msgstr "überspringe »%s« --- kann diese Fremdtabelle nicht analysieren"
-#: commands/analyze.c:241
+#: commands/analyze.c:247
#, c-format
msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables"
msgstr "überspringe »%s« --- kann Nicht-Tabellen oder besondere Systemtabellen nicht analysieren"
-#: commands/analyze.c:320
+#: commands/analyze.c:328
#, c-format
msgid "analyzing \"%s.%s\" inheritance tree"
msgstr "analysiere Vererbungsbaum von »%s.%s«"
-#: commands/analyze.c:325
+#: commands/analyze.c:333
#, c-format
msgid "analyzing \"%s.%s\""
msgstr "analysiere »%s.%s«"
-#: commands/analyze.c:654
+#: commands/analyze.c:658
#, c-format
msgid "automatic analyze of table \"%s.%s.%s\" system usage: %s"
msgstr "automatisches Analysieren von Tabelle »%s.%s.%s« Systembenutzung: %s"
-#: commands/analyze.c:1210
+#: commands/analyze.c:1212
#, c-format
msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows"
msgstr "»%s«: %d von %u Seiten gelesen, enthalten %.0f lebende Zeilen und %.0f tote Zeilen; %d Zeilen in Stichprobe, schätzungsweise %.0f Zeilen insgesamt"
-#: commands/analyze.c:1289
+#: commands/analyze.c:1292
#, c-format
msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables"
msgstr "überspringe Analysieren des Vererbungsbaums »%s.%s« --- dieser Vererbungsbaum enthält keine abgeleiteten Tabellen"
-#: commands/analyze.c:1378
+#: commands/analyze.c:1390
#, c-format
msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables"
msgstr "überspringe Analysieren des Vererbungsbaums »%s.%s« --- dieser Vererbungsbaum enthält keine analysierbaren abgeleiteten Tabellen"
-#: commands/analyze.c:1426 executor/execQual.c:2927
-msgid "could not convert row type"
-msgstr "konnte Zeilentyp nicht umwandeln"
-
#: commands/async.c:555
#, c-format
msgid "channel name cannot be empty"
@@ -5143,7 +5321,7 @@ msgstr "Der Serverprozess mit PID %d gehört zu denen mit den ältesten Transakt
msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction."
msgstr "Die NOTIFY-Schlange kann erst geleert werden, wenn dieser Prozess seine aktuelle Transaktion beendet."
-#: commands/cluster.c:129 commands/cluster.c:366
+#: commands/cluster.c:129 commands/cluster.c:364
#, c-format
msgid "cannot cluster temporary tables of other sessions"
msgstr "kann temporäre Tabellen anderer Sitzungen nicht clustern"
@@ -5153,62 +5331,62 @@ msgstr "kann temporäre Tabellen anderer Sitzungen nicht clustern"
msgid "there is no previously clustered index for table \"%s\""
msgstr "es gibt keinen bereits geclusterten Index für Tabelle »%s«"
-#: commands/cluster.c:173 commands/tablecmds.c:9286 commands/tablecmds.c:11002
+#: commands/cluster.c:173 commands/tablecmds.c:9858 commands/tablecmds.c:11721
#, c-format
msgid "index \"%s\" for table \"%s\" does not exist"
msgstr "Index »%s« für Tabelle »%s« existiert nicht"
-#: commands/cluster.c:355
+#: commands/cluster.c:353
#, c-format
msgid "cannot cluster a shared catalog"
msgstr "globaler Katalog kann nicht geclustert werden"
-#: commands/cluster.c:370
+#: commands/cluster.c:368
#, c-format
msgid "cannot vacuum temporary tables of other sessions"
msgstr "temporäre Tabellen anderer Sitzungen können nicht gevacuumt werden"
-#: commands/cluster.c:433 commands/tablecmds.c:11012
+#: commands/cluster.c:431 commands/tablecmds.c:11731
#, c-format
msgid "\"%s\" is not an index for table \"%s\""
msgstr "»%s« ist kein Index für Tabelle »%s«"
-#: commands/cluster.c:441
+#: commands/cluster.c:439
#, c-format
msgid "cannot cluster on index \"%s\" because access method does not support clustering"
msgstr "kann nicht anhand des Index »%s« clustern, weil die Indexmethode Clustern nicht unterstützt"
-#: commands/cluster.c:453
+#: commands/cluster.c:451
#, c-format
msgid "cannot cluster on partial index \"%s\""
msgstr "kann nicht anhand des partiellen Index »%s« clustern"
-#: commands/cluster.c:467
+#: commands/cluster.c:465
#, c-format
msgid "cannot cluster on invalid index \"%s\""
msgstr "kann nicht anhand des ungültigen Index »%s« clustern"
-#: commands/cluster.c:920
+#: commands/cluster.c:918
#, c-format
msgid "clustering \"%s.%s\" using index scan on \"%s\""
msgstr "clustere »%s.%s« durch Index-Scan von »%s«"
-#: commands/cluster.c:926
+#: commands/cluster.c:924
#, c-format
msgid "clustering \"%s.%s\" using sequential scan and sort"
msgstr "clustere »%s.%s« durch sequenziellen Scan und Sortieren"
-#: commands/cluster.c:931 commands/vacuumlazy.c:479
+#: commands/cluster.c:929 commands/vacuumlazy.c:486
#, c-format
msgid "vacuuming \"%s.%s\""
msgstr "vacuume »%s.%s«"
-#: commands/cluster.c:1090
+#: commands/cluster.c:1084
#, c-format
msgid "\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages"
msgstr "»%s«: %.0f entfernbare, %.0f nicht entfernbare Zeilenversionen in %u Seiten gefunden"
-#: commands/cluster.c:1094
+#: commands/cluster.c:1088
#, c-format
msgid ""
"%.0f dead row versions cannot be removed yet.\n"
@@ -5217,7 +5395,7 @@ msgstr ""
"%.0f tote Zeilenversionen können noch nicht entfernt werden.\n"
"%s."
-#: commands/collationcmds.c:80
+#: commands/collationcmds.c:79
#, c-format
msgid "collation attribute \"%s\" not recognized"
msgstr "Attribut »%s« für Sortierfolge unbekannt"
@@ -5232,36 +5410,51 @@ msgstr "Parameter »lc_collate« muss angegeben werden"
msgid "parameter \"lc_ctype\" must be specified"
msgstr "Parameter »lc_ctype« muss angegeben werden"
-#: commands/collationcmds.c:166
+#: commands/collationcmds.c:170
#, c-format
msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\""
msgstr "Sortierfolge »%s« für Kodierung »%s« existiert bereits in Schema »%s«"
-#: commands/collationcmds.c:177
+#: commands/collationcmds.c:181
#, c-format
msgid "collation \"%s\" already exists in schema \"%s\""
msgstr "Sortierfolge »%s« existiert bereits in Schema »%s«"
-#: commands/comment.c:62 commands/dbcommands.c:797 commands/dbcommands.c:962
-#: commands/dbcommands.c:1067 commands/dbcommands.c:1257
-#: commands/dbcommands.c:1477 commands/dbcommands.c:1594
-#: commands/dbcommands.c:2011 utils/init/postinit.c:843
-#: utils/init/postinit.c:945 utils/init/postinit.c:962
+#: commands/collationcmds.c:243
+#, c-format
+msgid "must be superuser to import system collations"
+msgstr "nur Superuser können Systemsortierfolgen importieren"
+
+#: commands/collationcmds.c:250 commands/copy.c:1827 commands/copy.c:3013
+#, c-format
+msgid "could not execute command \"%s\": %m"
+msgstr "konnte Befehl »%s« nicht ausführen: %m"
+
+#: commands/collationcmds.c:343
+#, c-format
+msgid "no usable system locales were found"
+msgstr "keine brauchbaren System-Locales gefunden"
+
+#: commands/comment.c:61 commands/dbcommands.c:808 commands/dbcommands.c:988
+#: commands/dbcommands.c:1092 commands/dbcommands.c:1282
+#: commands/dbcommands.c:1505 commands/dbcommands.c:1619
+#: commands/dbcommands.c:2035 utils/init/postinit.c:841
+#: utils/init/postinit.c:943 utils/init/postinit.c:960
#, c-format
msgid "database \"%s\" does not exist"
msgstr "Datenbank »%s« existiert nicht"
-#: commands/comment.c:101 commands/seclabel.c:116 parser/parse_utilcmd.c:768
+#: commands/comment.c:100 commands/seclabel.c:117 parser/parse_utilcmd.c:824
#, c-format
msgid "\"%s\" is not a table, view, materialized view, composite type, or foreign table"
msgstr "»%s« ist weder Tabelle, Sicht, materialisierte Sicht, zusammengesetzter Typ noch Fremdtabelle"
-#: commands/constraint.c:60 utils/adt/ri_triggers.c:2717
+#: commands/constraint.c:60 utils/adt/ri_triggers.c:2715
#, c-format
msgid "function \"%s\" was not called by trigger manager"
msgstr "Funktion »%s« wurde nicht von Triggermanager aufgerufen"
-#: commands/constraint.c:67 utils/adt/ri_triggers.c:2726
+#: commands/constraint.c:67 utils/adt/ri_triggers.c:2724
#, c-format
msgid "function \"%s\" must be fired AFTER ROW"
msgstr "Funktion »%s« muss AFTER ROW ausgelöst werden"
@@ -5271,756 +5464,791 @@ msgstr "Funktion »%s« muss AFTER ROW ausgelöst werden"
msgid "function \"%s\" must be fired for INSERT or UPDATE"
msgstr "Funktion »%s« muss von INSERT oder UPDATE ausgelöst werden"
-#: commands/conversioncmds.c:67
+#: commands/conversioncmds.c:66
#, c-format
msgid "source encoding \"%s\" does not exist"
msgstr "Quellkodierung »%s« existiert nicht"
-#: commands/conversioncmds.c:74
+#: commands/conversioncmds.c:73
#, c-format
msgid "destination encoding \"%s\" does not exist"
msgstr "Zielkodierung »%s« existiert nicht"
-#: commands/conversioncmds.c:88
+#: commands/conversioncmds.c:87
#, c-format
msgid "encoding conversion function %s must return type %s"
msgstr "Kodierungskonversionsfunktion %s muss Typ %s zurückgeben"
-#: commands/copy.c:362 commands/copy.c:374 commands/copy.c:408
-#: commands/copy.c:420
+#: commands/copy.c:369 commands/copy.c:403
#, c-format
msgid "COPY BINARY is not supported to stdout or from stdin"
msgstr "COPY BINARY mit STDOUT oder STDIN wird nicht unterstützt"
-#: commands/copy.c:520
+#: commands/copy.c:503
#, c-format
msgid "could not write to COPY program: %m"
msgstr "konnte nicht zum COPY-Programm schreiben: %m"
-#: commands/copy.c:525
+#: commands/copy.c:508
#, c-format
msgid "could not write to COPY file: %m"
msgstr "konnte nicht in COPY-Datei schreiben: %m"
-#: commands/copy.c:538
+#: commands/copy.c:521
#, c-format
msgid "connection lost during COPY to stdout"
msgstr "Verbindung während COPY nach STDOUT verloren"
-#: commands/copy.c:579
+#: commands/copy.c:562
#, c-format
msgid "could not read from COPY file: %m"
msgstr "konnte nicht aus COPY-Datei lesen: %m"
-#: commands/copy.c:595 commands/copy.c:616 commands/copy.c:620
+#: commands/copy.c:578 commands/copy.c:599 commands/copy.c:603
#: tcop/postgres.c:341 tcop/postgres.c:377 tcop/postgres.c:404
#, c-format
msgid "unexpected EOF on client connection with an open transaction"
msgstr "unerwartetes EOF auf Client-Verbindung mit einer offenen Transaktion"
-#: commands/copy.c:633
+#: commands/copy.c:616
#, c-format
msgid "COPY from stdin failed: %s"
msgstr "COPY FROM STDIN fehlgeschlagen: %s"
-#: commands/copy.c:649
+#: commands/copy.c:632
#, c-format
msgid "unexpected message type 0x%02X during COPY from stdin"
msgstr "unerwarteter Messagetyp 0x%02X während COPY FROM STDIN"
-#: commands/copy.c:806
+#: commands/copy.c:791
#, c-format
msgid "must be superuser to COPY to or from an external program"
msgstr "nur Superuser können COPY mit externen Programmen verwenden"
-#: commands/copy.c:807 commands/copy.c:813
+#: commands/copy.c:792 commands/copy.c:798
#, c-format
msgid "Anyone can COPY to stdout or from stdin. psql's \\copy command also works for anyone."
msgstr "Jeder kann COPY mit STDOUT oder STDIN verwenden. Der Befehl \\copy in psql funktioniert auch für jeden."
-#: commands/copy.c:812
+#: commands/copy.c:797
#, c-format
msgid "must be superuser to COPY to or from a file"
msgstr "nur Superuser können COPY mit Dateien verwenden"
-#: commands/copy.c:878
+#: commands/copy.c:864
#, c-format
msgid "COPY FROM not supported with row-level security"
msgstr "COPY FROM wird nicht unterstützt mit Sicherheit auf Zeilenebene"
-#: commands/copy.c:879
+#: commands/copy.c:865
#, c-format
msgid "Use INSERT statements instead."
msgstr "Verwenden Sie stattdessen INSERT-Anweisungen."
-#: commands/copy.c:1019
+#: commands/copy.c:1051
#, c-format
msgid "COPY format \"%s\" not recognized"
msgstr "COPY-Format »%s« nicht erkannt"
-#: commands/copy.c:1090 commands/copy.c:1104 commands/copy.c:1118
-#: commands/copy.c:1138
+#: commands/copy.c:1131 commands/copy.c:1147 commands/copy.c:1162
+#: commands/copy.c:1184
#, c-format
msgid "argument to option \"%s\" must be a list of column names"
msgstr "Argument von Option »%s« muss eine Liste aus Spaltennamen sein"
-#: commands/copy.c:1151
+#: commands/copy.c:1199
#, c-format
msgid "argument to option \"%s\" must be a valid encoding name"
msgstr "Argument von Option »%s« muss ein gültiger Kodierungsname sein"
-#: commands/copy.c:1157 commands/dbcommands.c:232 commands/dbcommands.c:1427
+#: commands/copy.c:1206 commands/dbcommands.c:242 commands/dbcommands.c:1453
#, c-format
msgid "option \"%s\" not recognized"
msgstr "Option »%s« nicht erkannt"
-#: commands/copy.c:1168
+#: commands/copy.c:1218
#, c-format
msgid "cannot specify DELIMITER in BINARY mode"
msgstr "DELIMITER kann nicht im BINARY-Modus angegeben werden"
-#: commands/copy.c:1173
+#: commands/copy.c:1223
#, c-format
msgid "cannot specify NULL in BINARY mode"
msgstr "NULL kann nicht im BINARY-Modus angegeben werden"
-#: commands/copy.c:1195
+#: commands/copy.c:1245
#, c-format
msgid "COPY delimiter must be a single one-byte character"
msgstr "DELIMITER für COPY muss ein einzelnes Ein-Byte-Zeichen sein"
-#: commands/copy.c:1202
+#: commands/copy.c:1252
#, c-format
msgid "COPY delimiter cannot be newline or carriage return"
msgstr "COPY-Trennzeichen kann nicht Newline oder Carriage Return sein"
-#: commands/copy.c:1208
+#: commands/copy.c:1258
#, c-format
msgid "COPY null representation cannot use newline or carriage return"
msgstr "COPY NULL-Darstellung kann nicht Newline oder Carriage Return enthalten"
-#: commands/copy.c:1225
+#: commands/copy.c:1275
#, c-format
msgid "COPY delimiter cannot be \"%s\""
msgstr "DELIMITER für COPY darf nicht »%s« sein"
-#: commands/copy.c:1231
+#: commands/copy.c:1281
#, c-format
msgid "COPY HEADER available only in CSV mode"
msgstr "COPY HEADER ist nur im CSV-Modus verfügbar"
-#: commands/copy.c:1237
+#: commands/copy.c:1287
#, c-format
msgid "COPY quote available only in CSV mode"
msgstr "Quote-Zeichen für COPY ist nur im CSV-Modus verfügbar"
-#: commands/copy.c:1242
+#: commands/copy.c:1292
#, c-format
msgid "COPY quote must be a single one-byte character"
msgstr "Quote-Zeichen für COPY muss ein einzelnes Ein-Byte-Zeichen sein"
-#: commands/copy.c:1247
+#: commands/copy.c:1297
#, c-format
msgid "COPY delimiter and quote must be different"
msgstr "DELIMITER und QUOTE für COPY müssen verschieden sein"
-#: commands/copy.c:1253
+#: commands/copy.c:1303
#, c-format
msgid "COPY escape available only in CSV mode"
msgstr "Escape-Zeichen für COPY ist nur im CSV-Modus verfügbar"
-#: commands/copy.c:1258
+#: commands/copy.c:1308
#, c-format
msgid "COPY escape must be a single one-byte character"
msgstr "Escape-Zeichen für COPY muss ein einzelnes Ein-Byte-Zeichen sein"
-#: commands/copy.c:1264
+#: commands/copy.c:1314
#, c-format
msgid "COPY force quote available only in CSV mode"
msgstr "FORCE_QUOTE für COPY ist nur im CSV-Modus verfügbar"
-#: commands/copy.c:1268
+#: commands/copy.c:1318
#, c-format
msgid "COPY force quote only available using COPY TO"
msgstr "FORCE_QUOTE ist nur bei COPY TO verfügbar"
-#: commands/copy.c:1274
+#: commands/copy.c:1324
#, c-format
msgid "COPY force not null available only in CSV mode"
msgstr "FORCE_NOT_NULL für COPY ist nur im CSV-Modus verfügbar"
-#: commands/copy.c:1278
+#: commands/copy.c:1328
#, c-format
msgid "COPY force not null only available using COPY FROM"
msgstr "FORCE_NOT_NULL ist nur bei COPY FROM verfügbar"
-#: commands/copy.c:1284
+#: commands/copy.c:1334
#, c-format
msgid "COPY force null available only in CSV mode"
msgstr "FORCE_NULL für COPY ist nur im CSV-Modus verfügbar"
-#: commands/copy.c:1289
+#: commands/copy.c:1339
#, c-format
msgid "COPY force null only available using COPY FROM"
msgstr "FORCE_NULL ist nur bei COPY FROM verfügbar"
-#: commands/copy.c:1295
+#: commands/copy.c:1345
#, c-format
msgid "COPY delimiter must not appear in the NULL specification"
msgstr "Trennzeichen für COPY darf nicht in der NULL-Darstellung erscheinen"
-#: commands/copy.c:1302
+#: commands/copy.c:1352
#, c-format
msgid "CSV quote character must not appear in the NULL specification"
msgstr "CSV-Quote-Zeichen darf nicht in der NULL-Darstellung erscheinen"
-#: commands/copy.c:1365
+#: commands/copy.c:1413
#, c-format
msgid "table \"%s\" does not have OIDs"
msgstr "Tabelle »%s« hat keine OIDs"
-#: commands/copy.c:1382
+#: commands/copy.c:1454
#, c-format
msgid "COPY (query) WITH OIDS is not supported"
msgstr "COPY (Anfrage) WITH OIDS wird nicht unterstützt"
-#: commands/copy.c:1402
+#: commands/copy.c:1474
#, c-format
msgid "DO INSTEAD NOTHING rules are not supported for COPY"
msgstr "DO INSTEAD NOTHING-Regeln werden für COPY nicht unterstützt"
-#: commands/copy.c:1416
+#: commands/copy.c:1488
#, c-format
msgid "conditional DO INSTEAD rules are not supported for COPY"
msgstr "Do INSTEAD-Regeln mit Bedingung werden für COPY nicht unterstützt"
-#: commands/copy.c:1420
+#: commands/copy.c:1492
#, c-format
msgid "DO ALSO rules are not supported for the COPY"
msgstr "DO ALSO-Regeln werden für COPY nicht unterstützt"
-#: commands/copy.c:1425
+#: commands/copy.c:1497
#, c-format
msgid "multi-statement DO INSTEAD rules are not supported for COPY"
msgstr "DO INSTEAD-Regeln mit mehreren Anweisungen werden für COPY nicht unterstützt"
-#: commands/copy.c:1435
+#: commands/copy.c:1507
#, c-format
msgid "COPY (SELECT INTO) is not supported"
msgstr "COPY (SELECT INTO) wird nicht unterstützt"
-#: commands/copy.c:1452
+#: commands/copy.c:1524
#, c-format
msgid "COPY query must have a RETURNING clause"
msgstr "COPY-Anfrage muss eine RETURNING-Klausel haben"
-#: commands/copy.c:1480
+#: commands/copy.c:1552
#, c-format
msgid "relation referenced by COPY statement has changed"
msgstr "die von der COPY-Anweisung verwendete Relation hat sich geändert"
-#: commands/copy.c:1538
+#: commands/copy.c:1610
#, c-format
msgid "FORCE_QUOTE column \"%s\" not referenced by COPY"
msgstr "FORCE_QUOTE-Spalte »%s« wird von COPY nicht verwendet"
-#: commands/copy.c:1560
+#: commands/copy.c:1632
#, c-format
msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY"
msgstr "Spalte »%s« mit FORCE_NOT_NULL wird von COPY nicht verwendet"
-#: commands/copy.c:1582
+#: commands/copy.c:1654
#, c-format
msgid "FORCE_NULL column \"%s\" not referenced by COPY"
msgstr "Spalte »%s« mit FORCE_NULL wird von COPY nicht verwendet"
-#: commands/copy.c:1647
+#: commands/copy.c:1719
#, c-format
msgid "could not close pipe to external command: %m"
msgstr "konnte Pipe zu externem Programm nicht schließen: %m"
-#: commands/copy.c:1651
+#: commands/copy.c:1723
#, c-format
msgid "program \"%s\" failed"
msgstr "Programm »%s« fehlgeschlagen"
-#: commands/copy.c:1701
+#: commands/copy.c:1773
#, c-format
msgid "cannot copy from view \"%s\""
msgstr "kann nicht aus Sicht »%s« kopieren"
-#: commands/copy.c:1703 commands/copy.c:1709 commands/copy.c:1715
+#: commands/copy.c:1775 commands/copy.c:1781 commands/copy.c:1787
+#: commands/copy.c:1798
#, c-format
msgid "Try the COPY (SELECT ...) TO variant."
msgstr "Versuchen Sie die Variante COPY (SELECT ...) TO."
-#: commands/copy.c:1707
+#: commands/copy.c:1779
#, c-format
msgid "cannot copy from materialized view \"%s\""
msgstr "kann nicht aus materialisierter Sicht »%s« kopieren"
-#: commands/copy.c:1713
+#: commands/copy.c:1785
#, c-format
msgid "cannot copy from foreign table \"%s\""
msgstr "kann nicht aus Fremdtabelle »%s« kopieren"
-#: commands/copy.c:1719
+#: commands/copy.c:1791
#, c-format
msgid "cannot copy from sequence \"%s\""
msgstr "kann nicht aus Sequenz »%s« kopieren"
-#: commands/copy.c:1724
+#: commands/copy.c:1796
#, c-format
-msgid "cannot copy from non-table relation \"%s\""
-msgstr "kann nicht aus Relation »%s«, die keine Tabelle ist, kopieren"
+msgid "cannot copy from partitioned table \"%s\""
+msgstr "kann nicht aus partitionierter Tabelle »%s« kopieren"
-#: commands/copy.c:1749 commands/copy.c:2787
+#: commands/copy.c:1802
#, c-format
-msgid "could not execute command \"%s\": %m"
-msgstr "konnte Befehl »%s« nicht ausführen: %m"
+msgid "cannot copy from non-table relation \"%s\""
+msgstr "kann nicht aus Relation »%s«, die keine Tabelle ist, kopieren"
-#: commands/copy.c:1764
+#: commands/copy.c:1842
#, c-format
msgid "relative path not allowed for COPY to file"
msgstr "relativer Pfad bei COPY in Datei nicht erlaubt"
-#: commands/copy.c:1772
+#: commands/copy.c:1854
#, c-format
msgid "could not open file \"%s\" for writing: %m"
msgstr "konnte Datei »%s« nicht zum Schreiben öffnen: %m"
-#: commands/copy.c:1784 commands/copy.c:2810
+#: commands/copy.c:1857
+#, c-format
+msgid "COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \\copy."
+msgstr ""
+
+#: commands/copy.c:1870 commands/copy.c:3044
#, c-format
msgid "\"%s\" is a directory"
msgstr "»%s« ist ein Verzeichnis"
-#: commands/copy.c:2109
+#: commands/copy.c:2193
#, c-format
msgid "COPY %s, line %d, column %s"
msgstr "COPY %s, Zeile %d, Spalte %s"
-#: commands/copy.c:2113 commands/copy.c:2160
+#: commands/copy.c:2197 commands/copy.c:2244
#, c-format
msgid "COPY %s, line %d"
msgstr "COPY %s, Zeile %d"
-#: commands/copy.c:2124
+#: commands/copy.c:2208
#, c-format
msgid "COPY %s, line %d, column %s: \"%s\""
msgstr "COPY %s, Zeile %d, Spalte %s: »%s«"
-#: commands/copy.c:2132
+#: commands/copy.c:2216
#, c-format
msgid "COPY %s, line %d, column %s: null input"
msgstr "COPY %s, Zeile %d, Spalte %s: NULL Eingabe"
-#: commands/copy.c:2154
+#: commands/copy.c:2238
#, c-format
msgid "COPY %s, line %d: \"%s\""
msgstr "COPY %s, Zeile %d: »%s«"
-#: commands/copy.c:2238
+#: commands/copy.c:2332
#, c-format
msgid "cannot copy to view \"%s\""
msgstr "kann nicht in Sicht »%s« kopieren"
-#: commands/copy.c:2243
+#: commands/copy.c:2334
+#, fuzzy, c-format
+#| msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."
+msgid "To enable copying to a view, provide an INSTEAD OF INSERT trigger."
+msgstr "Um Einfügen in die Sicht zu ermöglichen, richten Sie einen INSTEAD OF INSERT Trigger oder eine ON INSERT DO INSTEAD Regel ohne Bedingung ein."
+
+#: commands/copy.c:2338
#, c-format
msgid "cannot copy to materialized view \"%s\""
msgstr "kann nicht in materialisierte Sicht »%s« kopieren"
-#: commands/copy.c:2248
+#: commands/copy.c:2343
#, c-format
msgid "cannot copy to foreign table \"%s\""
msgstr "kann nicht in Fremdtabelle »%s« kopieren"
-#: commands/copy.c:2253
+#: commands/copy.c:2348
#, c-format
msgid "cannot copy to sequence \"%s\""
msgstr "kann nicht in Sequenz »%s« kopieren"
-#: commands/copy.c:2258
+#: commands/copy.c:2353
#, c-format
msgid "cannot copy to non-table relation \"%s\""
msgstr "kann nicht in Relation »%s« kopieren, die keine Tabelle ist"
-#: commands/copy.c:2321
+#: commands/copy.c:2416
#, c-format
msgid "cannot perform FREEZE because of prior transaction activity"
msgstr "FREEZE kann nicht durchgeführt werden wegen vorheriger Aktivität in dieser Transaktion"
-#: commands/copy.c:2327
+#: commands/copy.c:2422
#, c-format
msgid "cannot perform FREEZE because the table was not created or truncated in the current subtransaction"
msgstr "FREEZE kann nicht durchgeführt werden, weil die Tabelle nicht in der aktuellen Transaktion erzeugt oder geleert wurde"
-#: commands/copy.c:2830
+#: commands/copy.c:2587 executor/nodeModifyTable.c:311
+#, fuzzy, c-format
+#| msgid "cannot insert into foreign table \"%s\""
+msgid "cannot route inserted tuples to a foreign table"
+msgstr "kann nicht in Fremdtabelle »%s« einfügen"
+
+#: commands/copy.c:3031
+#, c-format
+msgid "COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \\copy."
+msgstr ""
+
+#: commands/copy.c:3064
#, c-format
msgid "COPY file signature not recognized"
msgstr "COPY-Datei-Signatur nicht erkannt"
-#: commands/copy.c:2835
+#: commands/copy.c:3069
#, c-format
msgid "invalid COPY file header (missing flags)"
msgstr "ungültiger COPY-Dateikopf (Flags fehlen)"
-#: commands/copy.c:2841
+#: commands/copy.c:3075
#, c-format
msgid "unrecognized critical flags in COPY file header"
msgstr "unbekannte kritische Flags im COPY-Dateikopf"
-#: commands/copy.c:2847
+#: commands/copy.c:3081
#, c-format
msgid "invalid COPY file header (missing length)"
msgstr "ungültiger COPY-Dateikopf (Länge fehlt)"
-#: commands/copy.c:2854
+#: commands/copy.c:3088
#, c-format
msgid "invalid COPY file header (wrong length)"
msgstr "ungültiger COPY-Dateikopf (falsche Länge)"
-#: commands/copy.c:2987 commands/copy.c:3694 commands/copy.c:3924
+#: commands/copy.c:3221 commands/copy.c:3928 commands/copy.c:4158
#, c-format
msgid "extra data after last expected column"
msgstr "zusätzliche Daten nach letzter erwarteter Spalte"
-#: commands/copy.c:2997
+#: commands/copy.c:3231
#, c-format
msgid "missing data for OID column"
msgstr "fehlende Daten für OID-Spalte"
-#: commands/copy.c:3003
+#: commands/copy.c:3237
#, c-format
msgid "null OID in COPY data"
msgstr "OID ist NULL in COPY-Daten"
-#: commands/copy.c:3013 commands/copy.c:3136
+#: commands/copy.c:3247 commands/copy.c:3370
#, c-format
msgid "invalid OID in COPY data"
msgstr "ungültige OID in COPY-Daten"
-#: commands/copy.c:3028
+#: commands/copy.c:3262
#, c-format
msgid "missing data for column \"%s\""
msgstr "fehlende Daten für Spalte »%s«"
-#: commands/copy.c:3111
+#: commands/copy.c:3345
#, c-format
msgid "received copy data after EOF marker"
msgstr "COPY-Daten nach EOF-Markierung empfangen"
-#: commands/copy.c:3118
+#: commands/copy.c:3352
#, c-format
msgid "row field count is %d, expected %d"
msgstr "Feldanzahl in Zeile ist %d, erwartet wurden %d"
-#: commands/copy.c:3458 commands/copy.c:3475
+#: commands/copy.c:3692 commands/copy.c:3709
#, c-format
msgid "literal carriage return found in data"
msgstr "Carriage-Return-Zeichen in Daten gefunden"
-#: commands/copy.c:3459 commands/copy.c:3476
+#: commands/copy.c:3693 commands/copy.c:3710
#, c-format
msgid "unquoted carriage return found in data"
msgstr "ungequotetes Carriage-Return-Zeichen in Daten gefunden"
-#: commands/copy.c:3461 commands/copy.c:3478
+#: commands/copy.c:3695 commands/copy.c:3712
#, c-format
msgid "Use \"\\r\" to represent carriage return."
msgstr "Verwenden Sie »\\r«, um ein Carriage-Return-Zeichen darzustellen."
-#: commands/copy.c:3462 commands/copy.c:3479
+#: commands/copy.c:3696 commands/copy.c:3713
#, c-format
msgid "Use quoted CSV field to represent carriage return."
msgstr "Verwenden Sie ein gequotetes CSV-Feld, um ein Carriage-Return-Zeichen darzustellen."
-#: commands/copy.c:3491
+#: commands/copy.c:3725
#, c-format
msgid "literal newline found in data"
msgstr "Newline-Zeichen in Daten gefunden"
-#: commands/copy.c:3492
+#: commands/copy.c:3726
#, c-format
msgid "unquoted newline found in data"
msgstr "ungequotetes Newline-Zeichen in Daten gefunden"
-#: commands/copy.c:3494
+#: commands/copy.c:3728
#, c-format
msgid "Use \"\\n\" to represent newline."
msgstr "Verwenden Sie »\\n«, um ein Newline-Zeichen darzustellen."
-#: commands/copy.c:3495
+#: commands/copy.c:3729
#, c-format
msgid "Use quoted CSV field to represent newline."
msgstr "Verwenden Sie ein gequotetes CSV-Feld, um ein Newline-Zeichen darzustellen."
-#: commands/copy.c:3541 commands/copy.c:3577
+#: commands/copy.c:3775 commands/copy.c:3811
#, c-format
msgid "end-of-copy marker does not match previous newline style"
msgstr "COPY-Ende-Markierung stimmt nicht mit vorherigem Newline-Stil überein"
-#: commands/copy.c:3550 commands/copy.c:3566
+#: commands/copy.c:3784 commands/copy.c:3800
#, c-format
msgid "end-of-copy marker corrupt"
msgstr "COPY-Ende-Markierung verfälscht"
-#: commands/copy.c:4008
+#: commands/copy.c:4242
#, c-format
msgid "unterminated CSV quoted field"
msgstr "Quotes in CSV-Feld nicht abgeschlossen"
-#: commands/copy.c:4085 commands/copy.c:4104
+#: commands/copy.c:4319 commands/copy.c:4338
#, c-format
msgid "unexpected EOF in COPY data"
msgstr "unerwartetes EOF in COPY-Daten"
-#: commands/copy.c:4094
+#: commands/copy.c:4328
#, c-format
msgid "invalid field size"
msgstr "ungültige Feldgröße"
-#: commands/copy.c:4117
+#: commands/copy.c:4351
#, c-format
msgid "incorrect binary data format"
msgstr "falsches Binärdatenformat"
-#: commands/copy.c:4428 commands/indexcmds.c:1053 commands/tablecmds.c:1463
-#: commands/tablecmds.c:2290 parser/parse_relation.c:3084
-#: parser/parse_relation.c:3104 utils/adt/tsvector_op.c:2307
+#: commands/copy.c:4662 commands/indexcmds.c:1062 commands/tablecmds.c:1655
+#: commands/tablecmds.c:2150 commands/tablecmds.c:2573
+#: parser/parse_relation.c:3111 parser/parse_relation.c:3131
+#: utils/adt/tsvector_op.c:2561
#, c-format
msgid "column \"%s\" does not exist"
msgstr "Spalte »%s« existiert nicht"
-#: commands/copy.c:4435 commands/tablecmds.c:1489 commands/trigger.c:651
-#: parser/parse_target.c:956 parser/parse_target.c:967
+#: commands/copy.c:4669 commands/tablecmds.c:1681 commands/trigger.c:741
+#: parser/parse_target.c:1017 parser/parse_target.c:1028
#, c-format
msgid "column \"%s\" specified more than once"
msgstr "Spalte »%s« mehrmals angegeben"
-#: commands/createas.c:213 commands/createas.c:509
+#: commands/createas.c:213 commands/createas.c:508
#, c-format
msgid "too many column names were specified"
msgstr "zu viele Spaltennamen wurden angegeben"
-#: commands/createas.c:550
+#: commands/createas.c:549
#, c-format
msgid "policies not yet implemented for this command"
msgstr "Policys sind für diesen Befehl noch nicht implementiert"
-#: commands/dbcommands.c:226
+#: commands/dbcommands.c:235
#, c-format
msgid "LOCATION is not supported anymore"
msgstr "LOCATION wird nicht mehr unterstützt"
-#: commands/dbcommands.c:227
+#: commands/dbcommands.c:236
#, c-format
msgid "Consider using tablespaces instead."
msgstr "Verwenden Sie stattdessen Tablespaces."
-#: commands/dbcommands.c:251 utils/adt/ascii.c:144
+#: commands/dbcommands.c:262 utils/adt/ascii.c:145
#, c-format
msgid "%d is not a valid encoding code"
msgstr "%d ist kein gültiger Kodierungscode"
-#: commands/dbcommands.c:261 utils/adt/ascii.c:126
+#: commands/dbcommands.c:273 utils/adt/ascii.c:127
#, c-format
msgid "%s is not a valid encoding name"
msgstr "%s ist kein gültiger Kodierungsname"
-#: commands/dbcommands.c:279 commands/dbcommands.c:1458 commands/user.c:272
-#: commands/user.c:650
+#: commands/dbcommands.c:292 commands/dbcommands.c:1486 commands/user.c:289
+#: commands/user.c:665
#, c-format
msgid "invalid connection limit: %d"
msgstr "ungültige Verbindungshöchstgrenze: %d"
-#: commands/dbcommands.c:298
+#: commands/dbcommands.c:311
#, c-format
msgid "permission denied to create database"
msgstr "keine Berechtigung, um Datenbank zu erzeugen"
-#: commands/dbcommands.c:321
+#: commands/dbcommands.c:334
#, c-format
msgid "template database \"%s\" does not exist"
msgstr "Template-Datenbank »%s« existiert nicht"
-#: commands/dbcommands.c:333
+#: commands/dbcommands.c:346
#, c-format
msgid "permission denied to copy database \"%s\""
msgstr "keine Berechtigung, um Datenbank »%s« zu kopieren"
-#: commands/dbcommands.c:349
+#: commands/dbcommands.c:362
#, c-format
msgid "invalid server encoding %d"
msgstr "ungültige Serverkodierung %d"
-#: commands/dbcommands.c:355 commands/dbcommands.c:360
+#: commands/dbcommands.c:368 commands/dbcommands.c:373
#, c-format
msgid "invalid locale name: \"%s\""
msgstr "ungültiger Locale-Name: »%s«"
-#: commands/dbcommands.c:380
+#: commands/dbcommands.c:393
#, c-format
msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)"
msgstr "neue Kodierung (%s) ist inkompatibel mit der Kodierung der Template-Datenbank (%s)"
-#: commands/dbcommands.c:383
+#: commands/dbcommands.c:396
#, c-format
msgid "Use the same encoding as in the template database, or use template0 as template."
msgstr "Verwenden Sie die gleiche Kodierung wie die Template-Datenbank oder verwenden Sie template0 als Template."
-#: commands/dbcommands.c:388
+#: commands/dbcommands.c:401
#, c-format
msgid "new collation (%s) is incompatible with the collation of the template database (%s)"
msgstr "neue Sortierreihenfolge (%s) ist inkompatibel mit der Sortierreihenfolge der Template-Datenbank (%s)"
-#: commands/dbcommands.c:390
+#: commands/dbcommands.c:403
#, c-format
msgid "Use the same collation as in the template database, or use template0 as template."
msgstr "Verwenden Sie die gleiche Sortierreihenfolge wie die Template-Datenbank oder verwenden Sie template0 als Template."
-#: commands/dbcommands.c:395
+#: commands/dbcommands.c:408
#, c-format
msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)"
msgstr "neues LC_CTYPE (%s) ist inkompatibel mit dem LC_CTYPE der Template-Datenbank (%s)"
-#: commands/dbcommands.c:397
+#: commands/dbcommands.c:410
#, c-format
msgid "Use the same LC_CTYPE as in the template database, or use template0 as template."
msgstr "Verwenden Sie das gleiche LC_CTYPE wie die Template-Datenbank oder verwenden Sie template0 als Template."
-#: commands/dbcommands.c:419 commands/dbcommands.c:1113
+#: commands/dbcommands.c:432 commands/dbcommands.c:1138
#, c-format
msgid "pg_global cannot be used as default tablespace"
msgstr "pg_global kann nicht als Standard-Tablespace verwendet werden"
-#: commands/dbcommands.c:445
+#: commands/dbcommands.c:458
#, c-format
msgid "cannot assign new default tablespace \"%s\""
msgstr "kann neuen Standard-Tablespace »%s« nicht setzen"
-#: commands/dbcommands.c:447
+#: commands/dbcommands.c:460
#, c-format
msgid "There is a conflict because database \"%s\" already has some tables in this tablespace."
msgstr "Es gibt einen Konflikt, weil Datenbank »%s« schon einige Tabellen in diesem Tablespace hat."
-#: commands/dbcommands.c:467 commands/dbcommands.c:982
+#: commands/dbcommands.c:480 commands/dbcommands.c:1008
#, c-format
msgid "database \"%s\" already exists"
msgstr "Datenbank »%s« existiert bereits"
-#: commands/dbcommands.c:481
+#: commands/dbcommands.c:494
#, c-format
msgid "source database \"%s\" is being accessed by other users"
msgstr "auf Quelldatenbank »%s« wird gerade von anderen Benutzern zugegriffen"
-#: commands/dbcommands.c:726 commands/dbcommands.c:741
+#: commands/dbcommands.c:736 commands/dbcommands.c:751
#, c-format
msgid "encoding \"%s\" does not match locale \"%s\""
msgstr "Kodierung »%s« stimmt nicht mit Locale »%s« überein"
-#: commands/dbcommands.c:729
+#: commands/dbcommands.c:739
#, c-format
msgid "The chosen LC_CTYPE setting requires encoding \"%s\"."
msgstr "Die gewählte LC_CTYPE-Einstellung verlangt die Kodierung »%s«."
-#: commands/dbcommands.c:744
+#: commands/dbcommands.c:754
#, c-format
msgid "The chosen LC_COLLATE setting requires encoding \"%s\"."
msgstr "Die gewählte LC_COLLATE-Einstellung verlangt die Kodierung »%s«."
-#: commands/dbcommands.c:804
+#: commands/dbcommands.c:815
#, c-format
msgid "database \"%s\" does not exist, skipping"
msgstr "Datenbank »%s« existiert nicht, wird übersprungen"
-#: commands/dbcommands.c:828
+#: commands/dbcommands.c:839
#, c-format
msgid "cannot drop a template database"
msgstr "Template-Datenbank kann nicht gelöscht werden"
-#: commands/dbcommands.c:834
+#: commands/dbcommands.c:845
#, c-format
msgid "cannot drop the currently open database"
msgstr "kann aktuell geöffnete Datenbank nicht löschen"
-#: commands/dbcommands.c:844
+#: commands/dbcommands.c:855
#, c-format
msgid "database \"%s\" is used by a logical replication slot"
msgstr "Datenbank »%s« wird von einem logischen Replikations-Slot verwendet"
-#: commands/dbcommands.c:846
+#: commands/dbcommands.c:857
#, c-format
msgid "There is %d slot, %d of them active."
msgid_plural "There are %d slots, %d of them active."
msgstr[0] "%d Slot ist vorhanden, %d davon aktiv."
msgstr[1] "%d Slots sind vorhanden, %d davon aktiv."
-#: commands/dbcommands.c:860 commands/dbcommands.c:1004
-#: commands/dbcommands.c:1135
+#: commands/dbcommands.c:871 commands/dbcommands.c:1030
+#: commands/dbcommands.c:1160
#, c-format
msgid "database \"%s\" is being accessed by other users"
msgstr "auf Datenbank »%s« wird von anderen Benutzern zugegriffen"
-#: commands/dbcommands.c:973
+#: commands/dbcommands.c:884
+#, c-format
+msgid "database \"%s\" is being used by logical replication subscription"
+msgstr "Datenbank »%s« wird von einer Subskription für logische Replikation verwendet"
+
+#: commands/dbcommands.c:886
+#, c-format
+msgid "There is %d subscription."
+msgid_plural "There are %d subscriptions."
+msgstr[0] ""
+msgstr[1] ""
+
+#: commands/dbcommands.c:999
#, c-format
msgid "permission denied to rename database"
msgstr "keine Berechtigung, um Datenbank umzubenennen"
-#: commands/dbcommands.c:993
+#: commands/dbcommands.c:1019
#, c-format
msgid "current database cannot be renamed"
msgstr "aktuelle Datenbank kann nicht umbenannt werden"
-#: commands/dbcommands.c:1091
+#: commands/dbcommands.c:1116
#, c-format
msgid "cannot change the tablespace of the currently open database"
msgstr "kann den Tablespace der aktuell geöffneten Datenbank nicht ändern"
-#: commands/dbcommands.c:1194
+#: commands/dbcommands.c:1219
#, c-format
msgid "some relations of database \"%s\" are already in tablespace \"%s\""
msgstr "einige Relationen von Datenbank »%s« ist bereits in Tablespace »%s«"
-#: commands/dbcommands.c:1196
+#: commands/dbcommands.c:1221
#, c-format
msgid "You must move them back to the database's default tablespace before using this command."
msgstr "Sie müssen sie zurück in den Standard-Tablespace der Datenbank verschieben, bevor Sie diesen Befehl verwenden können."
-#: commands/dbcommands.c:1325 commands/dbcommands.c:1868
-#: commands/dbcommands.c:2072 commands/dbcommands.c:2120
-#: commands/tablespace.c:606
+#: commands/dbcommands.c:1347 commands/dbcommands.c:1892
+#: commands/dbcommands.c:2096 commands/dbcommands.c:2144
+#: commands/tablespace.c:604
#, c-format
msgid "some useless files may be left behind in old database directory \"%s\""
msgstr "einige nutzlose Dateien wurde möglicherweise im alten Datenbankverzeichnis »%s« zurückgelassen"
-#: commands/dbcommands.c:1440
+#: commands/dbcommands.c:1467
#, c-format
msgid "option \"%s\" cannot be specified with other options"
msgstr "Option »%s« kann nicht mit anderen Optionen angegeben werden"
-#: commands/dbcommands.c:1494
+#: commands/dbcommands.c:1522
#, c-format
msgid "cannot disallow connections for current database"
msgstr "Verbindungen mit der aktuellen Datenbank können nicht verboten werden"
-#: commands/dbcommands.c:1634
+#: commands/dbcommands.c:1659
#, c-format
msgid "permission denied to change owner of database"
msgstr "keine Berechtigung, um Eigentümer der Datenbank zu ändern"
-#: commands/dbcommands.c:1955
+#: commands/dbcommands.c:1979
#, c-format
msgid "There are %d other session(s) and %d prepared transaction(s) using the database."
msgstr "%d andere Sitzung(en) und %d vorbereitete Transaktion(en) verwenden die Datenbank."
-#: commands/dbcommands.c:1958
+#: commands/dbcommands.c:1982
#, c-format
msgid "There is %d other session using the database."
msgid_plural "There are %d other sessions using the database."
msgstr[0] "%d andere Sitzung verwendet die Datenbank."
msgstr[1] "%d andere Sitzungen verwenden die Datenbank."
-#: commands/dbcommands.c:1963
+#: commands/dbcommands.c:1987
#, c-format
msgid "There is %d prepared transaction using the database."
msgid_plural "There are %d prepared transactions using the database."
@@ -6028,7 +6256,7 @@ msgstr[0] "%d vorbereitete Transaktion verwendet die Datenbank."
msgstr[1] "%d vorbereitete Transaktionen verwenden die Datenbank."
#: commands/define.c:54 commands/define.c:228 commands/define.c:260
-#: commands/define.c:288
+#: commands/define.c:288 commands/define.c:334
#, c-format
msgid "%s requires a parameter"
msgstr "%s erfordert einen Parameter"
@@ -6064,182 +6292,187 @@ msgstr "Argument von %s muss ein Typname sein"
msgid "invalid argument for %s: \"%s\""
msgstr "ungültiges Argument für %s: »%s«"
-#: commands/dropcmds.c:112 commands/functioncmds.c:1203
-#: utils/adt/ruleutils.c:2077
+#: commands/dropcmds.c:104 commands/functioncmds.c:1200
+#: utils/adt/ruleutils.c:2284
#, c-format
msgid "\"%s\" is an aggregate function"
msgstr "»%s« ist eine Aggregatfunktion"
-#: commands/dropcmds.c:114
+#: commands/dropcmds.c:106
#, c-format
msgid "Use DROP AGGREGATE to drop aggregate functions."
msgstr "Verwenden Sie DROP AGGREGATE, um Aggregatfunktionen zu löschen."
-#: commands/dropcmds.c:165 commands/sequence.c:424 commands/tablecmds.c:2377
-#: commands/tablecmds.c:2528 commands/tablecmds.c:2570
-#: commands/tablecmds.c:11377 tcop/utility.c:1119
+#: commands/dropcmds.c:157 commands/sequence.c:430 commands/tablecmds.c:2657
+#: commands/tablecmds.c:2808 commands/tablecmds.c:2851
+#: commands/tablecmds.c:12104 tcop/utility.c:1159
#, c-format
msgid "relation \"%s\" does not exist, skipping"
msgstr "Relation »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:195 commands/dropcmds.c:296 commands/tablecmds.c:745
+#: commands/dropcmds.c:187 commands/dropcmds.c:286 commands/tablecmds.c:896
#, c-format
msgid "schema \"%s\" does not exist, skipping"
msgstr "Schema »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:237 commands/dropcmds.c:276 commands/tablecmds.c:246
+#: commands/dropcmds.c:227 commands/dropcmds.c:266 commands/tablecmds.c:252
#, c-format
msgid "type \"%s\" does not exist, skipping"
msgstr "Typ »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:266
+#: commands/dropcmds.c:256
#, c-format
msgid "access method \"%s\" does not exist, skipping"
msgstr "Zugriffsmethode »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:284
+#: commands/dropcmds.c:274
#, c-format
msgid "collation \"%s\" does not exist, skipping"
msgstr "Sortierfolge »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:291
+#: commands/dropcmds.c:281
#, c-format
msgid "conversion \"%s\" does not exist, skipping"
msgstr "Konversion »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:302
+#: commands/dropcmds.c:292
#, c-format
msgid "text search parser \"%s\" does not exist, skipping"
msgstr "Textsucheparser »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:309
+#: commands/dropcmds.c:299
#, c-format
msgid "text search dictionary \"%s\" does not exist, skipping"
msgstr "Textsuchewörterbuch »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:316
+#: commands/dropcmds.c:306
#, c-format
msgid "text search template \"%s\" does not exist, skipping"
msgstr "Textsuchevorlage »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:323
+#: commands/dropcmds.c:313
#, c-format
msgid "text search configuration \"%s\" does not exist, skipping"
msgstr "Textsuchekonfiguration »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:328
+#: commands/dropcmds.c:318
#, c-format
msgid "extension \"%s\" does not exist, skipping"
msgstr "Erweiterung »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:335
+#: commands/dropcmds.c:327
#, c-format
msgid "function %s(%s) does not exist, skipping"
msgstr "Funktion %s(%s) existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:344
+#: commands/dropcmds.c:339
#, c-format
msgid "aggregate %s(%s) does not exist, skipping"
msgstr "Aggregatfunktion %s(%s) existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:353
+#: commands/dropcmds.c:351
#, c-format
msgid "operator %s does not exist, skipping"
msgstr "Operator %s existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:358
+#: commands/dropcmds.c:357
#, c-format
msgid "language \"%s\" does not exist, skipping"
msgstr "Sprache »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:367
+#: commands/dropcmds.c:366
#, c-format
msgid "cast from type %s to type %s does not exist, skipping"
msgstr "Typumwandlung von Typ %s in Typ %s existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:376
+#: commands/dropcmds.c:375
#, c-format
msgid "transform for type %s language \"%s\" does not exist, skipping"
msgstr "Transformation für Typ %s Sprache »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:384
+#: commands/dropcmds.c:383
#, c-format
msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping"
msgstr "Trigger »%s« für Relation »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:393
+#: commands/dropcmds.c:392
#, c-format
msgid "policy \"%s\" for relation \"%s\" does not exist, skipping"
msgstr "Policy »%s« für Relation »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:400
+#: commands/dropcmds.c:399
#, c-format
msgid "event trigger \"%s\" does not exist, skipping"
msgstr "Ereignistrigger »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:406
+#: commands/dropcmds.c:405
#, c-format
msgid "rule \"%s\" for relation \"%s\" does not exist, skipping"
msgstr "Regel »%s« für Relation »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:413
+#: commands/dropcmds.c:412
#, c-format
msgid "foreign-data wrapper \"%s\" does not exist, skipping"
msgstr "Fremddaten-Wrapper »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:417
+#: commands/dropcmds.c:416
#, c-format
msgid "server \"%s\" does not exist, skipping"
msgstr "Server »%s« existiert nicht, wird übersprungen"
-#: commands/dropcmds.c:426
+#: commands/dropcmds.c:425
#, c-format
msgid "operator class \"%s\" does not exist for access method \"%s\", skipping"
msgstr "Operatorklasse »%s« existiert nicht für Zugriffsmethode »%s«, wird übersprungen"
-#: commands/dropcmds.c:438
+#: commands/dropcmds.c:437
#, c-format
msgid "operator family \"%s\" does not exist for access method \"%s\", skipping"
msgstr "Operatorfamilie »%s« existiert nicht für Zugriffsmethode »%s«, wird übersprungen"
-#: commands/event_trigger.c:182
+#: commands/dropcmds.c:444
+#, c-format
+msgid "publication \"%s\" does not exist, skipping"
+msgstr "Publikation »%s« existiert nicht, wird übersprungen"
+
+#: commands/event_trigger.c:184
#, c-format
msgid "permission denied to create event trigger \"%s\""
msgstr "keine Berechtigung, um Ereignistrigger »%s« zu erzeugen"
-#: commands/event_trigger.c:184
+#: commands/event_trigger.c:186
#, c-format
msgid "Must be superuser to create an event trigger."
msgstr "Nur Superuser können Ereignistrigger anlegen."
-#: commands/event_trigger.c:193
+#: commands/event_trigger.c:195
#, c-format
msgid "unrecognized event name \"%s\""
msgstr "unbekannter Ereignisname »%s«"
-#: commands/event_trigger.c:210
+#: commands/event_trigger.c:212
#, c-format
msgid "unrecognized filter variable \"%s\""
msgstr "unbekannte Filtervariable »%s«"
-#: commands/event_trigger.c:265
+#: commands/event_trigger.c:267
#, c-format
msgid "filter value \"%s\" not recognized for filter variable \"%s\""
msgstr "Filterwert »%s« nicht erkannt für Filtervariable »%s«"
#. translator: %s represents an SQL statement name
-#: commands/event_trigger.c:271 commands/event_trigger.c:341
+#: commands/event_trigger.c:273 commands/event_trigger.c:343
#, c-format
msgid "event triggers are not supported for %s"
msgstr "Ereignistrigger für %s werden nicht unterstützt"
-#: commands/event_trigger.c:364
+#: commands/event_trigger.c:366
#, c-format
msgid "filter variable \"%s\" specified more than once"
msgstr "Filtervariable »%s« mehrmals angegeben"
-#: commands/event_trigger.c:512 commands/event_trigger.c:556
-#: commands/event_trigger.c:649
+#: commands/event_trigger.c:513 commands/event_trigger.c:556
+#: commands/event_trigger.c:648
#, c-format
msgid "event trigger \"%s\" does not exist"
msgstr "Ereignistrigger »%s« existiert nicht"
@@ -6254,264 +6487,270 @@ msgstr "keine Berechtigung, um Eigentümer des Ereignistriggers »%s« zu änder
msgid "The owner of an event trigger must be a superuser."
msgstr "Der Eigentümer eines Ereignistriggers muss ein Superuser sein."
-#: commands/event_trigger.c:1442
+#: commands/event_trigger.c:1443
#, c-format
msgid "%s can only be called in a sql_drop event trigger function"
msgstr "%s kann nur in einer sql_drop-Ereignistriggerfunktion aufgerufen werden"
-#: commands/event_trigger.c:1562 commands/event_trigger.c:1583
+#: commands/event_trigger.c:1563 commands/event_trigger.c:1584
#, c-format
msgid "%s can only be called in a table_rewrite event trigger function"
msgstr "%s kann nur in einer table_rewrite-Ereignistriggerfunktion aufgerufen werden"
-#: commands/event_trigger.c:1993
+#: commands/event_trigger.c:1994
#, c-format
msgid "%s can only be called in an event trigger function"
msgstr "%s kann nur in einer Ereignistriggerfunktion aufgerufen werden"
-#: commands/explain.c:184
+#: commands/explain.c:192
#, c-format
msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\""
msgstr "unbekannter Wert für EXPLAIN-Option »%s«: »%s«"
-#: commands/explain.c:190
+#: commands/explain.c:199
#, c-format
msgid "unrecognized EXPLAIN option \"%s\""
msgstr "unbekannte EXPLAIN-Option »%s«"
-#: commands/explain.c:197
+#: commands/explain.c:207
#, c-format
msgid "EXPLAIN option BUFFERS requires ANALYZE"
msgstr "EXPLAIN-Option BUFFERS erfordert ANALYZE"
-#: commands/explain.c:206
+#: commands/explain.c:216
#, c-format
msgid "EXPLAIN option TIMING requires ANALYZE"
msgstr "EXPLAIN-Option TIMING erfordert ANALYZE"
-#: commands/extension.c:154 commands/extension.c:2718
+#: commands/extension.c:167 commands/extension.c:2900
#, c-format
msgid "extension \"%s\" does not exist"
msgstr "Erweiterung »%s« existiert nicht"
-#: commands/extension.c:253 commands/extension.c:262 commands/extension.c:274
-#: commands/extension.c:284
+#: commands/extension.c:266 commands/extension.c:275 commands/extension.c:287
+#: commands/extension.c:297
#, c-format
msgid "invalid extension name: \"%s\""
msgstr "ungültiger Erweiterungsname: »%s«"
-#: commands/extension.c:254
+#: commands/extension.c:267
#, c-format
msgid "Extension names must not be empty."
msgstr "Erweiterungsnamen dürfen nicht leer sein."
-#: commands/extension.c:263
+#: commands/extension.c:276
#, c-format
msgid "Extension names must not contain \"--\"."
msgstr "Erweiterungsnamen dürfen nicht »--« enthalten."
-#: commands/extension.c:275
+#: commands/extension.c:288
#, c-format
msgid "Extension names must not begin or end with \"-\"."
msgstr "Erweiterungsnamen dürfen nicht mit »-« anfangen oder aufhören."
-#: commands/extension.c:285
+#: commands/extension.c:298
#, c-format
msgid "Extension names must not contain directory separator characters."
msgstr "Erweiterungsnamen dürfen keine Verzeichnistrennzeichen enthalten."
-#: commands/extension.c:300 commands/extension.c:309 commands/extension.c:318
-#: commands/extension.c:328
+#: commands/extension.c:313 commands/extension.c:322 commands/extension.c:331
+#: commands/extension.c:341
#, c-format
msgid "invalid extension version name: \"%s\""
msgstr "ungültiger Erweiterungsversionsname: »%s«"
-#: commands/extension.c:301
+#: commands/extension.c:314
#, c-format
msgid "Version names must not be empty."
msgstr "Versionsnamen dürfen nicht leer sein."
-#: commands/extension.c:310
+#: commands/extension.c:323
#, c-format
msgid "Version names must not contain \"--\"."
msgstr "Versionsnamen dürfen nicht »--« enthalten."
-#: commands/extension.c:319
+#: commands/extension.c:332
#, c-format
msgid "Version names must not begin or end with \"-\"."
msgstr "Versionsnamen dürfen nicht mit »-« anfangen oder aufhören."
-#: commands/extension.c:329
+#: commands/extension.c:342
#, c-format
msgid "Version names must not contain directory separator characters."
msgstr "Versionsnamen dürfen keine Verzeichnistrennzeichen enthalten."
-#: commands/extension.c:479
+#: commands/extension.c:492
#, c-format
msgid "could not open extension control file \"%s\": %m"
msgstr "konnte Erweiterungskontrolldatei »%s« nicht öffnen: %m"
-#: commands/extension.c:501 commands/extension.c:511
+#: commands/extension.c:514 commands/extension.c:524
#, c-format
msgid "parameter \"%s\" cannot be set in a secondary extension control file"
msgstr "Parameter »%s« kann nicht in einer sekundären Erweitungskontrolldatei gesetzt werden"
-#: commands/extension.c:550
+#: commands/extension.c:563
#, c-format
msgid "\"%s\" is not a valid encoding name"
msgstr "»%s« ist kein gültiger Kodierungsname"
-#: commands/extension.c:564
+#: commands/extension.c:577
#, c-format
msgid "parameter \"%s\" must be a list of extension names"
msgstr "Parameter »%s« muss eine Liste von Erweiterungsnamen sein"
-#: commands/extension.c:571
+#: commands/extension.c:584
#, c-format
msgid "unrecognized parameter \"%s\" in file \"%s\""
msgstr "unbekannter Parameter »%s« in Datei »%s«"
-#: commands/extension.c:580
+#: commands/extension.c:593
#, c-format
msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true"
msgstr "Parameter »schema« kann nicht angegeben werden, wenn »relocatable« an ist"
-#: commands/extension.c:721
+#: commands/extension.c:756
#, c-format
msgid "transaction control statements are not allowed within an extension script"
msgstr "Transaktionskontrollanweisungen sind nicht in einem Erweiterungsskript erlaubt"
-#: commands/extension.c:789
+#: commands/extension.c:801
#, c-format
msgid "permission denied to create extension \"%s\""
msgstr "keine Berechtigung, um Erweiterung »%s« zu erzeugen"
-#: commands/extension.c:791
+#: commands/extension.c:803
#, c-format
msgid "Must be superuser to create this extension."
msgstr "Nur Superuser können diese Erweiterung anlegen."
-#: commands/extension.c:795
+#: commands/extension.c:807
#, c-format
msgid "permission denied to update extension \"%s\""
msgstr "keine Berechtigung, um Erweiterung »%s« zu aktualisieren"
-#: commands/extension.c:797
+#: commands/extension.c:809
#, c-format
msgid "Must be superuser to update this extension."
msgstr "Nur Superuser können diese Erweiterung aktualisieren."
-#: commands/extension.c:1079
+#: commands/extension.c:1091
#, c-format
msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\""
msgstr "Erweiterung »%s« hat keinen Aktualisierungspfad von Version »%s« auf Version »%s«"
-#: commands/extension.c:1261 commands/extension.c:2778
+#: commands/extension.c:1298 commands/extension.c:2961
#, c-format
msgid "version to install must be specified"
msgstr "die zu installierende Version muss angegeben werden"
-#: commands/extension.c:1278
+#: commands/extension.c:1320
#, c-format
msgid "FROM version must be different from installation target version \"%s\""
msgstr "FROM-Version muss verschieden von der zu installierenden Version »%s« sein"
-#: commands/extension.c:1343
+#: commands/extension.c:1385
+#, fuzzy, c-format
+#| msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\""
+msgid "extension \"%s\" has no installation script nor update path for version \"%s\""
+msgstr "Erweiterung »%s« hat keinen Aktualisierungspfad von Version »%s« auf Version »%s«"
+
+#: commands/extension.c:1420
#, c-format
msgid "extension \"%s\" must be installed in schema \"%s\""
msgstr "Erweiterung »%s« muss in Schema »%s« installiert werden"
-#: commands/extension.c:1435
+#: commands/extension.c:1573
#, c-format
msgid "cyclic dependency detected between extensions \"%s\" and \"%s\""
msgstr "zyklische Abhängigkeit zwischen Erweiterungen »%s« und »%s« entdeckt"
-#: commands/extension.c:1440
+#: commands/extension.c:1578
#, c-format
msgid "installing required extension \"%s\""
msgstr "installiere benötigte Erweiterung »%s«"
-#: commands/extension.c:1468 commands/extension.c:2923
+#: commands/extension.c:1602
#, c-format
msgid "required extension \"%s\" is not installed"
msgstr "benötigte Erweiterung »%s« ist nicht installiert"
-#: commands/extension.c:1470
+#: commands/extension.c:1605
#, c-format
msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too."
msgstr "Verwenden Sie CREATE EXTENSION ... CASCADE, um die benötigten Erweiterungen ebenfalls zu installieren."
-#: commands/extension.c:1534
+#: commands/extension.c:1642
#, c-format
msgid "extension \"%s\" already exists, skipping"
msgstr "Erweiterung »%s« existiert bereits, wird übersprungen"
-#: commands/extension.c:1541
+#: commands/extension.c:1649
#, c-format
msgid "extension \"%s\" already exists"
msgstr "Erweiterung »%s« existiert bereits"
-#: commands/extension.c:1552
+#: commands/extension.c:1660
#, c-format
msgid "nested CREATE EXTENSION is not supported"
msgstr "geschachteltes CREATE EXTENSION wird nicht unterstützt"
-#: commands/extension.c:1680
+#: commands/extension.c:1841
#, c-format
msgid "cannot drop extension \"%s\" because it is being modified"
msgstr "Erweiterung »%s« kann nicht gelöscht werden, weil sie gerade geändert wird"
-#: commands/extension.c:2151
+#: commands/extension.c:2343
#, c-format
msgid "pg_extension_config_dump() can only be called from an SQL script executed by CREATE EXTENSION"
msgstr "pg_extension_config_dump() kann nur von einem SQL-Skript aufgerufen werden, das von CREATE EXTENSION ausgeführt wird"
-#: commands/extension.c:2163
+#: commands/extension.c:2355
#, c-format
msgid "OID %u does not refer to a table"
msgstr "OID %u bezieht sich nicht auf eine Tabelle"
-#: commands/extension.c:2168
+#: commands/extension.c:2360
#, c-format
msgid "table \"%s\" is not a member of the extension being created"
msgstr "Tabelle »%s« ist kein Mitglied der anzulegenden Erweiterung"
-#: commands/extension.c:2533
+#: commands/extension.c:2716
#, c-format
msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema"
msgstr "kann Erweiterung »%s« nicht in Schema »%s« verschieben, weil die Erweiterung das Schema enthält"
-#: commands/extension.c:2573 commands/extension.c:2636
+#: commands/extension.c:2756 commands/extension.c:2819
#, c-format
msgid "extension \"%s\" does not support SET SCHEMA"
msgstr "Erweiterung »%s« unterstützt SET SCHEMA nicht"
-#: commands/extension.c:2638
+#: commands/extension.c:2821
#, c-format
msgid "%s is not in the extension's schema \"%s\""
msgstr "%s ist nicht im Schema der Erweiterung (»%s«)"
-#: commands/extension.c:2698
+#: commands/extension.c:2880
#, c-format
msgid "nested ALTER EXTENSION is not supported"
msgstr "geschachteltes ALTER EXTENSION wird nicht unterstützt"
-#: commands/extension.c:2789
+#: commands/extension.c:2972
#, c-format
msgid "version \"%s\" of extension \"%s\" is already installed"
msgstr "Version »%s« von Erweiterung »%s« ist bereits installiert"
-#: commands/extension.c:3040
+#: commands/extension.c:3223
#, c-format
msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension"
msgstr "kann Schema »%s« nicht zu Erweiterung »%s« hinzufügen, weil das Schema die Erweiterung enthält"
-#: commands/extension.c:3058
+#: commands/extension.c:3251
#, c-format
msgid "%s is not a member of extension \"%s\""
msgstr "%s ist kein Mitglied der Erweiterung »%s«"
-#: commands/extension.c:3114
+#: commands/extension.c:3317
#, c-format
msgid "file \"%s\" is too large"
msgstr "Datei »%s« ist zu groß"
@@ -6541,72 +6780,72 @@ msgstr "Nur Superuser können den Eigentümer eines Fremddaten-Wrappers ändern.
msgid "The owner of a foreign-data wrapper must be a superuser."
msgstr "Der Eigentümer eines Fremddaten-Wrappers muss ein Superuser sein."
-#: commands/foreigncmds.c:292 commands/foreigncmds.c:709 foreign/foreign.c:671
+#: commands/foreigncmds.c:291 commands/foreigncmds.c:706 foreign/foreign.c:667
#, c-format
msgid "foreign-data wrapper \"%s\" does not exist"
msgstr "Fremddaten-Wrapper »%s« existiert nicht"
-#: commands/foreigncmds.c:584
+#: commands/foreigncmds.c:582
#, c-format
msgid "permission denied to create foreign-data wrapper \"%s\""
msgstr "keine Berechtigung, um Fremddaten-Wrapper »%s« zu erzeugen"
-#: commands/foreigncmds.c:586
+#: commands/foreigncmds.c:584
#, c-format
msgid "Must be superuser to create a foreign-data wrapper."
msgstr "Nur Superuser können Fremddaten-Wrapper anlegen."
-#: commands/foreigncmds.c:699
+#: commands/foreigncmds.c:696
#, c-format
msgid "permission denied to alter foreign-data wrapper \"%s\""
msgstr "keine Berechtigung, um Fremddaten-Wrapper »%s« zu ändern"
-#: commands/foreigncmds.c:701
+#: commands/foreigncmds.c:698
#, c-format
msgid "Must be superuser to alter a foreign-data wrapper."
msgstr "Nur Superuser können Fremddaten-Wrapper ändern."
-#: commands/foreigncmds.c:732
+#: commands/foreigncmds.c:729
#, c-format
msgid "changing the foreign-data wrapper handler can change behavior of existing foreign tables"
msgstr "das Ändern des Handlers des Fremddaten-Wrappers kann das Verhalten von bestehenden Fremdtabellen verändern"
-#: commands/foreigncmds.c:747
+#: commands/foreigncmds.c:744
#, c-format
msgid "changing the foreign-data wrapper validator can cause the options for dependent objects to become invalid"
msgstr "durch Ändern des Validators des Fremddaten-Wrappers können die Optionen von abhängigen Objekten ungültig werden"
-#: commands/foreigncmds.c:1165
+#: commands/foreigncmds.c:1158
#, c-format
msgid "user mapping \"%s\" already exists for server %s"
msgstr "Benutzerabbildung »%s« existiert bereits für Server »%s«"
-#: commands/foreigncmds.c:1259 commands/foreigncmds.c:1375
+#: commands/foreigncmds.c:1250 commands/foreigncmds.c:1365
#, c-format
msgid "user mapping \"%s\" does not exist for the server"
msgstr "Benutzerabbildung »%s« existiert für den Server nicht"
-#: commands/foreigncmds.c:1362
+#: commands/foreigncmds.c:1352
#, c-format
msgid "server does not exist, skipping"
msgstr "Server existiert nicht, wird übersprungen"
-#: commands/foreigncmds.c:1380
+#: commands/foreigncmds.c:1370
#, c-format
msgid "user mapping \"%s\" does not exist for the server, skipping"
msgstr "Benutzerabbildung »%s« existiert nicht für den Server, wird übersprungen"
-#: commands/foreigncmds.c:1532 foreign/foreign.c:361
+#: commands/foreigncmds.c:1521 foreign/foreign.c:357
#, c-format
msgid "foreign-data wrapper \"%s\" has no handler"
msgstr "Fremddaten-Wrapper »%s« hat keinen Handler"
-#: commands/foreigncmds.c:1538
+#: commands/foreigncmds.c:1527
#, c-format
msgid "foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA"
msgstr "Fremddaten-Wrapper »%s« unterstützt IMPORT FOREIGN SCHEMA nicht"
-#: commands/foreigncmds.c:1631
+#: commands/foreigncmds.c:1630
#, c-format
msgid "importing foreign table \"%s\""
msgstr "importiere Fremdtabelle »%s«"
@@ -6636,87 +6875,87 @@ msgstr "Typ »%s« ist noch nicht definiert"
msgid "Creating a shell type definition."
msgstr "Hüllentypdefinition wird erzeugt."
-#: commands/functioncmds.c:239
+#: commands/functioncmds.c:233
#, c-format
msgid "SQL function cannot accept shell type %s"
msgstr "SQL-Funktion kann keinen Hüllentyp %s annehmen"
-#: commands/functioncmds.c:245
+#: commands/functioncmds.c:239
#, c-format
msgid "aggregate cannot accept shell type %s"
msgstr "Aggregatfunktion kann keinen Hüllentyp %s annehmen"
-#: commands/functioncmds.c:250
+#: commands/functioncmds.c:244
#, c-format
msgid "argument type %s is only a shell"
msgstr "Argumenttyp %s ist nur eine Hülle"
-#: commands/functioncmds.c:260
+#: commands/functioncmds.c:254
#, c-format
msgid "type %s does not exist"
msgstr "Typ %s existiert nicht"
-#: commands/functioncmds.c:274
+#: commands/functioncmds.c:268
#, c-format
msgid "aggregates cannot accept set arguments"
msgstr "Aggregatfunktionen können keine SETOF-Argumente haben"
-#: commands/functioncmds.c:278
+#: commands/functioncmds.c:272
#, c-format
msgid "functions cannot accept set arguments"
msgstr "Funktionen können keine SETOF-Argumente haben"
-#: commands/functioncmds.c:288
+#: commands/functioncmds.c:282
#, c-format
msgid "VARIADIC parameter must be the last input parameter"
msgstr "VARIADIC-Parameter muss der letzte Eingabeparameter sein"
-#: commands/functioncmds.c:316
+#: commands/functioncmds.c:310
#, c-format
msgid "VARIADIC parameter must be an array"
msgstr "VARIADIC-Parameter muss ein Array sein"
-#: commands/functioncmds.c:356
+#: commands/functioncmds.c:350
#, c-format
msgid "parameter name \"%s\" used more than once"
msgstr "Parametername »%s« mehrmals angegeben"
-#: commands/functioncmds.c:371
+#: commands/functioncmds.c:365
#, c-format
msgid "only input parameters can have default values"
msgstr "nur Eingabeparameter können Vorgabewerte haben"
-#: commands/functioncmds.c:386
+#: commands/functioncmds.c:380
#, c-format
msgid "cannot use table references in parameter default value"
msgstr "Tabellenverweise können nicht in Parametervorgabewerten verwendet werden"
-#: commands/functioncmds.c:410
+#: commands/functioncmds.c:404
#, c-format
msgid "input parameters after one with a default value must also have defaults"
msgstr "Eingabeparameter hinter einem mit Vorgabewert müssen auch einen Vorgabewert haben"
-#: commands/functioncmds.c:701
+#: commands/functioncmds.c:700
#, c-format
msgid "no function body specified"
msgstr "kein Funktionskörper angegeben"
-#: commands/functioncmds.c:711
+#: commands/functioncmds.c:710
#, c-format
msgid "no language specified"
msgstr "keine Sprache angegeben"
-#: commands/functioncmds.c:736 commands/functioncmds.c:1243
+#: commands/functioncmds.c:735 commands/functioncmds.c:1241
#, c-format
msgid "COST must be positive"
msgstr "COST muss positiv sein"
-#: commands/functioncmds.c:744 commands/functioncmds.c:1251
+#: commands/functioncmds.c:743 commands/functioncmds.c:1249
#, c-format
msgid "ROWS must be positive"
msgstr "ROWS muss positiv sein"
-#: commands/functioncmds.c:785
+#: commands/functioncmds.c:784
#, c-format
msgid "unrecognized function attribute \"%s\" ignored"
msgstr "unbekanntes Funktionsattribut »%s« ignoriert"
@@ -6726,405 +6965,412 @@ msgstr "unbekanntes Funktionsattribut »%s« ignoriert"
msgid "only one AS item needed for language \"%s\""
msgstr "nur ein AS-Element benötigt für Sprache »%s«"
-#: commands/functioncmds.c:929 commands/functioncmds.c:2119
-#: commands/proclang.c:563
+#: commands/functioncmds.c:930 commands/functioncmds.c:2110
+#: commands/proclang.c:561
#, c-format
msgid "language \"%s\" does not exist"
msgstr "Sprache »%s« existiert nicht"
-#: commands/functioncmds.c:931 commands/functioncmds.c:2121
+#: commands/functioncmds.c:932 commands/functioncmds.c:2112
#, c-format
msgid "Use CREATE LANGUAGE to load the language into the database."
msgstr "Sie müssen CREATE LANGUAGE verwenden, um die Sprache in die Datenbank zu laden."
-#: commands/functioncmds.c:966 commands/functioncmds.c:1235
+#: commands/functioncmds.c:967 commands/functioncmds.c:1233
#, c-format
msgid "only superuser can define a leakproof function"
msgstr "nur Superuser können eine »leakproof«-Funktion definieren"
-#: commands/functioncmds.c:1010
+#: commands/functioncmds.c:1009
#, c-format
msgid "function result type must be %s because of OUT parameters"
msgstr "Ergebnistyp der Funktion muss %s sein wegen OUT-Parametern"
-#: commands/functioncmds.c:1023
+#: commands/functioncmds.c:1022
#, c-format
msgid "function result type must be specified"
msgstr "Ergebnistyp der Funktion muss angegeben werden"
-#: commands/functioncmds.c:1077 commands/functioncmds.c:1255
+#: commands/functioncmds.c:1076 commands/functioncmds.c:1253
#, c-format
msgid "ROWS is not applicable when function does not return a set"
msgstr "ROWS ist nicht anwendbar, wenn die Funktion keine Ergebnismenge zurückgibt"
-#: commands/functioncmds.c:1412
+#: commands/functioncmds.c:1405
#, c-format
msgid "source data type %s is a pseudo-type"
msgstr "Quelldatentyp %s ist ein Pseudotyp"
-#: commands/functioncmds.c:1418
+#: commands/functioncmds.c:1411
#, c-format
msgid "target data type %s is a pseudo-type"
msgstr "Zieldatentyp %s ist ein Pseudotyp"
-#: commands/functioncmds.c:1442
+#: commands/functioncmds.c:1435
#, c-format
msgid "cast will be ignored because the source data type is a domain"
msgstr "Typumwandlung wird ignoriert werden, weil der Quelldatentyp eine Domäne ist"
-#: commands/functioncmds.c:1447
+#: commands/functioncmds.c:1440
#, c-format
msgid "cast will be ignored because the target data type is a domain"
msgstr "Typumwandlung wird ignoriert werden, weil der Zieldatentyp eine Domäne ist"
-#: commands/functioncmds.c:1474
+#: commands/functioncmds.c:1465
#, c-format
msgid "cast function must take one to three arguments"
msgstr "Typumwandlungsfunktion muss ein bis drei Argumente haben"
-#: commands/functioncmds.c:1478
+#: commands/functioncmds.c:1469
#, c-format
msgid "argument of cast function must match or be binary-coercible from source data type"
msgstr "Argument der Typumwandlungsfunktion muss mit Quelldatentyp übereinstimmen oder in ihn binär-umwandelbar sein"
-#: commands/functioncmds.c:1482
+#: commands/functioncmds.c:1473
#, c-format
-msgid "second argument of cast function must be type integer"
-msgstr "zweites Argument der Typumwandlungsfunktion muss Typ integer haben"
+msgid "second argument of cast function must be type %s"
+msgstr "zweites Argument der Typumwandlungsfunktion muss Typ %s haben"
-#: commands/functioncmds.c:1486
+#: commands/functioncmds.c:1478
#, c-format
-msgid "third argument of cast function must be type boolean"
-msgstr "drittes Argument der Typumwandlungsfunktion muss Typ boolean haben"
+msgid "third argument of cast function must be type %s"
+msgstr "drittes Argument der Typumwandlungsfunktion muss Typ %s haben"
-#: commands/functioncmds.c:1490
+#: commands/functioncmds.c:1483
#, c-format
msgid "return data type of cast function must match or be binary-coercible to target data type"
msgstr "Rückgabetyp der Typumwandlungsfunktion muss mit Zieldatentyp übereinstimmen oder in ihn binär-umwandelbar sein"
-#: commands/functioncmds.c:1501
+#: commands/functioncmds.c:1494
#, c-format
msgid "cast function must not be volatile"
msgstr "Typumwandlungsfunktion darf nicht VOLATILE sein"
-#: commands/functioncmds.c:1506
+#: commands/functioncmds.c:1499
#, c-format
msgid "cast function must not be an aggregate function"
msgstr "Typumwandlungsfunktion darf keine Aggregatfunktion sein"
-#: commands/functioncmds.c:1510
+#: commands/functioncmds.c:1503
#, c-format
msgid "cast function must not be a window function"
msgstr "Typumwandlungsfunktion darf keine Fensterfunktion sein"
-#: commands/functioncmds.c:1514
+#: commands/functioncmds.c:1507
#, c-format
msgid "cast function must not return a set"
msgstr "Typumwandlungsfunktion darf keine Ergebnismenge zurückgeben"
-#: commands/functioncmds.c:1540
+#: commands/functioncmds.c:1533
#, c-format
msgid "must be superuser to create a cast WITHOUT FUNCTION"
msgstr "nur Superuser können Typumwandlungen mit WITHOUT FUNCTION erzeugen"
-#: commands/functioncmds.c:1555
+#: commands/functioncmds.c:1548
#, c-format
msgid "source and target data types are not physically compatible"
msgstr "Quelldatentyp und Zieldatentyp sind nicht physikalisch kompatibel"
-#: commands/functioncmds.c:1570
+#: commands/functioncmds.c:1563
#, c-format
msgid "composite data types are not binary-compatible"
msgstr "zusammengesetzte Datentypen sind nicht binärkompatibel"
-#: commands/functioncmds.c:1576
+#: commands/functioncmds.c:1569
#, c-format
msgid "enum data types are not binary-compatible"
msgstr "Enum-Datentypen sind nicht binärkompatibel"
-#: commands/functioncmds.c:1582
+#: commands/functioncmds.c:1575
#, c-format
msgid "array data types are not binary-compatible"
msgstr "Array-Datentypen sind nicht binärkompatibel"
-#: commands/functioncmds.c:1599
+#: commands/functioncmds.c:1592
#, c-format
msgid "domain data types must not be marked binary-compatible"
msgstr "Domänendatentypen dürfen nicht als binärkompatibel markiert werden"
-#: commands/functioncmds.c:1609
+#: commands/functioncmds.c:1602
#, c-format
msgid "source data type and target data type are the same"
msgstr "Quelldatentyp und Zieldatentyp sind der selbe"
-#: commands/functioncmds.c:1642
+#: commands/functioncmds.c:1635
#, c-format
msgid "cast from type %s to type %s already exists"
msgstr "Typumwandlung von Typ %s in Typ %s existiert bereits"
-#: commands/functioncmds.c:1717
+#: commands/functioncmds.c:1708
#, c-format
msgid "cast from type %s to type %s does not exist"
msgstr "Typumwandlung von Typ %s in Typ %s existiert nicht"
-#: commands/functioncmds.c:1756
+#: commands/functioncmds.c:1747
#, c-format
msgid "transform function must not be volatile"
msgstr "Transformationsfunktion darf nicht VOLATILE sein"
-#: commands/functioncmds.c:1760
+#: commands/functioncmds.c:1751
#, c-format
msgid "transform function must not be an aggregate function"
msgstr "Transformationsfunktion darf keine Aggregatfunktion sein"
-#: commands/functioncmds.c:1764
+#: commands/functioncmds.c:1755
#, c-format
msgid "transform function must not be a window function"
msgstr "Transformationsfunktion darf keine Fensterfunktion sein"
-#: commands/functioncmds.c:1768
+#: commands/functioncmds.c:1759
#, c-format
msgid "transform function must not return a set"
msgstr "Transformationsfunktion darf keine Ergebnismenge zurückgeben"
-#: commands/functioncmds.c:1772
+#: commands/functioncmds.c:1763
#, c-format
msgid "transform function must take one argument"
msgstr "Transformationsfunktion muss ein Argument haben"
-#: commands/functioncmds.c:1776
+#: commands/functioncmds.c:1767
#, c-format
-msgid "first argument of transform function must be type \"internal\""
-msgstr "erstes Argument der Transformationsfunktion muss Typ »internal« haben"
+msgid "first argument of transform function must be type %s"
+msgstr "erstes Argument der Transformationsfunktion muss Typ %s haben"
-#: commands/functioncmds.c:1813
+#: commands/functioncmds.c:1805
#, c-format
msgid "data type %s is a pseudo-type"
msgstr "Datentyp %s ist ein Pseudotyp"
-#: commands/functioncmds.c:1819
+#: commands/functioncmds.c:1811
#, c-format
msgid "data type %s is a domain"
msgstr "Datentyp %s ist eine Domäne"
-#: commands/functioncmds.c:1859
+#: commands/functioncmds.c:1851
#, c-format
-msgid "return data type of FROM SQL function must be \"internal\""
-msgstr "Rückgabetyp der FROM-SQL-Funktion muss »internal« sein"
+msgid "return data type of FROM SQL function must be %s"
+msgstr "Rückgabetyp der FROM-SQL-Funktion muss %s sein"
-#: commands/functioncmds.c:1884
+#: commands/functioncmds.c:1877
#, c-format
msgid "return data type of TO SQL function must be the transform data type"
msgstr "Rückgabetyp der TO-SQL-Funktion muss der zu transformierende Datentyp sein"
-#: commands/functioncmds.c:1911
+#: commands/functioncmds.c:1904
#, c-format
msgid "transform for type %s language \"%s\" already exists"
msgstr "Transformation für Typ %s Sprache »%s« existiert bereits"
-#: commands/functioncmds.c:2002
+#: commands/functioncmds.c:1993
#, c-format
msgid "transform for type %s language \"%s\" does not exist"
msgstr "Transformation für Typ %s Sprache »%s« existiert nicht"
-#: commands/functioncmds.c:2053
+#: commands/functioncmds.c:2044
#, c-format
msgid "function %s already exists in schema \"%s\""
msgstr "Funktion %s existiert bereits in Schema »%s«"
-#: commands/functioncmds.c:2106
+#: commands/functioncmds.c:2097
#, c-format
msgid "no inline code specified"
msgstr "kein Inline-Code angegeben"
-#: commands/functioncmds.c:2151
+#: commands/functioncmds.c:2142
#, c-format
msgid "language \"%s\" does not support inline code execution"
msgstr "Sprache »%s« unterstützt das Ausführen von Inline-Code nicht"
-#: commands/indexcmds.c:349
+#: commands/indexcmds.c:350
#, c-format
msgid "must specify at least one column"
msgstr "mindestens eine Spalte muss angegeben werden"
-#: commands/indexcmds.c:353
+#: commands/indexcmds.c:354
#, c-format
msgid "cannot use more than %d columns in an index"
msgstr "Index kann nicht mehr als %d Spalten enthalten"
-#: commands/indexcmds.c:384
+#: commands/indexcmds.c:385
#, c-format
msgid "cannot create index on foreign table \"%s\""
msgstr "kann keinen Index für Fremdtabelle »%s« erzeugen"
-#: commands/indexcmds.c:399
+#: commands/indexcmds.c:390
+#, c-format
+msgid "cannot create index on partitioned table \"%s\""
+msgstr "kann keinen Index für partitionierte Tabelle »%s« erzeugen"
+
+#: commands/indexcmds.c:405
#, c-format
msgid "cannot create indexes on temporary tables of other sessions"
msgstr "kann keine Indexe für temporäre Tabellen anderer Sitzungen erzeugen"
-#: commands/indexcmds.c:454 commands/tablecmds.c:545 commands/tablecmds.c:9597
+#: commands/indexcmds.c:461 commands/tablecmds.c:579
+#: commands/tablecmds.c:10166
#, c-format
msgid "only shared relations can be placed in pg_global tablespace"
msgstr "nur geteilte Relationen können in den Tablespace »pg_global« gelegt werden"
-#: commands/indexcmds.c:487
+#: commands/indexcmds.c:494
#, c-format
msgid "substituting access method \"gist\" for obsolete method \"rtree\""
msgstr "ersetze Zugriffsmethode »gist« für obsolete Methode »rtree«"
-#: commands/indexcmds.c:505
+#: commands/indexcmds.c:512
#, c-format
msgid "hash indexes are not WAL-logged and their use is discouraged"
msgstr "Hash-Indexe werden nicht im WAL geloggt und von ihrer Verwendung wird abgeraten."
-#: commands/indexcmds.c:510
+#: commands/indexcmds.c:517
#, c-format
msgid "access method \"%s\" does not support unique indexes"
msgstr "Zugriffsmethode »%s« unterstützt keine Unique Indexe"
-#: commands/indexcmds.c:515
+#: commands/indexcmds.c:522
#, c-format
msgid "access method \"%s\" does not support multicolumn indexes"
msgstr "Zugriffsmethode »%s« unterstützt keine mehrspaltigen Indexe"
-#: commands/indexcmds.c:520
+#: commands/indexcmds.c:527
#, c-format
msgid "access method \"%s\" does not support exclusion constraints"
msgstr "Zugriffsmethode »%s« unterstützt keine Exclusion-Constraints"
-#: commands/indexcmds.c:590 commands/indexcmds.c:610
+#: commands/indexcmds.c:599 commands/indexcmds.c:619
#, c-format
msgid "index creation on system columns is not supported"
msgstr "Indexerzeugung für Systemspalten wird nicht unterstützt"
-#: commands/indexcmds.c:635
+#: commands/indexcmds.c:644
#, c-format
msgid "%s %s will create implicit index \"%s\" for table \"%s\""
msgstr "%s %s erstellt implizit einen Index »%s« für Tabelle »%s«"
-#: commands/indexcmds.c:982
+#: commands/indexcmds.c:991
#, c-format
msgid "functions in index predicate must be marked IMMUTABLE"
msgstr "Funktionen im Indexprädikat müssen als IMMUTABLE markiert sein"
-#: commands/indexcmds.c:1048 parser/parse_utilcmd.c:1896
+#: commands/indexcmds.c:1057 parser/parse_utilcmd.c:1946
#, c-format
msgid "column \"%s\" named in key does not exist"
msgstr "Spalte »%s«, die im Schlüssel verwendet wird, existiert nicht"
-#: commands/indexcmds.c:1108
+#: commands/indexcmds.c:1117
#, c-format
msgid "functions in index expression must be marked IMMUTABLE"
msgstr "Funktionen im Indexausdruck müssen als IMMUTABLE markiert sein"
-#: commands/indexcmds.c:1131
+#: commands/indexcmds.c:1140
#, c-format
msgid "could not determine which collation to use for index expression"
msgstr "konnte die für den Indexausdruck zu verwendende Sortierfolge nicht bestimmen"
-#: commands/indexcmds.c:1139 commands/typecmds.c:827 parser/parse_expr.c:2608
-#: parser/parse_type.c:550 parser/parse_utilcmd.c:2822 utils/adt/misc.c:666
+#: commands/indexcmds.c:1148 commands/tablecmds.c:13007
+#: commands/typecmds.c:831 parser/parse_expr.c:2730 parser/parse_type.c:549
+#: parser/parse_utilcmd.c:2873 utils/adt/misc.c:661
#, c-format
msgid "collations are not supported by type %s"
msgstr "Sortierfolgen werden von Typ %s nicht unterstützt"
-#: commands/indexcmds.c:1177
+#: commands/indexcmds.c:1186
#, c-format
msgid "operator %s is not commutative"
msgstr "Operator %s ist nicht kommutativ"
-#: commands/indexcmds.c:1179
+#: commands/indexcmds.c:1188
#, c-format
msgid "Only commutative operators can be used in exclusion constraints."
msgstr "In Exclusion-Constraints können nur kommutative Operatoren verwendet werden."
-#: commands/indexcmds.c:1205
+#: commands/indexcmds.c:1214
#, c-format
msgid "operator %s is not a member of operator family \"%s\""
msgstr "Operator %s ist kein Mitglied der Operatorfamilie »%s«"
-#: commands/indexcmds.c:1208
+#: commands/indexcmds.c:1217
#, c-format
msgid "The exclusion operator must be related to the index operator class for the constraint."
msgstr "Der Exklusionsoperator muss in Beziehung zur Indexoperatorklasse des Constraints stehen."
-#: commands/indexcmds.c:1243
+#: commands/indexcmds.c:1252
#, c-format
msgid "access method \"%s\" does not support ASC/DESC options"
msgstr "Zugriffsmethode »%s« unterstützt die Optionen ASC/DESC nicht"
-#: commands/indexcmds.c:1248
+#: commands/indexcmds.c:1257
#, c-format
msgid "access method \"%s\" does not support NULLS FIRST/LAST options"
msgstr "Zugriffsmethode »%s« unterstützt die Optionen NULLS FIRST/LAST nicht"
-#: commands/indexcmds.c:1304 commands/typecmds.c:1935
+#: commands/indexcmds.c:1316 commands/typecmds.c:1928
#, c-format
msgid "data type %s has no default operator class for access method \"%s\""
msgstr "Datentyp %s hat keine Standardoperatorklasse für Zugriffsmethode »%s«"
-#: commands/indexcmds.c:1306
+#: commands/indexcmds.c:1318
#, c-format
msgid "You must specify an operator class for the index or define a default operator class for the data type."
msgstr "Sie müssen für den Index eine Operatorklasse angeben oder eine Standardoperatorklasse für den Datentyp definieren."
-#: commands/indexcmds.c:1335 commands/indexcmds.c:1343
+#: commands/indexcmds.c:1347 commands/indexcmds.c:1355
#: commands/opclasscmds.c:205
#, c-format
msgid "operator class \"%s\" does not exist for access method \"%s\""
msgstr "Operatorklasse »%s« existiert nicht für Zugriffsmethode »%s«"
-#: commands/indexcmds.c:1356 commands/typecmds.c:1923
+#: commands/indexcmds.c:1368 commands/typecmds.c:1916
#, c-format
msgid "operator class \"%s\" does not accept data type %s"
msgstr "Operatorklasse »%s« akzeptiert Datentyp %s nicht"
-#: commands/indexcmds.c:1446
+#: commands/indexcmds.c:1458
#, c-format
msgid "there are multiple default operator classes for data type %s"
msgstr "es gibt mehrere Standardoperatorklassen für Datentyp %s"
-#: commands/indexcmds.c:1837
+#: commands/indexcmds.c:1849
#, c-format
msgid "table \"%s\" has no indexes"
msgstr "Tabelle »%s« hat keine Indexe"
-#: commands/indexcmds.c:1892
+#: commands/indexcmds.c:1904
#, c-format
msgid "can only reindex the currently open database"
msgstr "aktuell geöffnete Datenbank kann nicht reindiziert werden"
-#: commands/indexcmds.c:1994
+#: commands/indexcmds.c:2004
#, c-format
msgid "table \"%s.%s\" was reindexed"
msgstr "Tabelle »%s.%s« wurde neu indiziert"
-#: commands/matview.c:181
+#: commands/matview.c:179
#, c-format
msgid "CONCURRENTLY cannot be used when the materialized view is not populated"
msgstr "CONCURRENTLY kann nicht verwendet werden, wenn die materialisierte Sicht nicht befüllt ist"
-#: commands/matview.c:187
+#: commands/matview.c:185
#, c-format
msgid "CONCURRENTLY and WITH NO DATA options cannot be used together"
msgstr "Optionen CONCURRENTLY und WITH NO DATA können nicht zusammen verwendet werden"
-#: commands/matview.c:257
+#: commands/matview.c:255
#, c-format
msgid "cannot refresh materialized view \"%s\" concurrently"
msgstr "kann materialisierte Sicht »%s« nicht nebenläufig auffrischen"
-#: commands/matview.c:260
+#: commands/matview.c:258
#, c-format
msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view."
msgstr "Erzeugen Sie einen Unique Index ohne WHERE-Klausel für eine oder mehrere Spalten der materialisierten Sicht."
-#: commands/matview.c:657
+#: commands/matview.c:654
#, c-format
msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns"
msgstr "neue Daten für materialisierte Sicht »%s« enthalten doppelte Zeilen ohne Spalten mit NULL-Werten"
-#: commands/matview.c:659
+#: commands/matview.c:656
#, c-format
msgid "Row: %s"
msgstr "Zeile: %s"
@@ -7139,159 +7385,159 @@ msgstr "Operatorfamilie »%s« existiert nicht für Zugriffsmethode »%s«"
msgid "operator family \"%s\" for access method \"%s\" already exists"
msgstr "Operatorfamilie »%s« für Zugriffsmethode »%s« existiert bereits"
-#: commands/opclasscmds.c:404
+#: commands/opclasscmds.c:402
#, c-format
msgid "must be superuser to create an operator class"
msgstr "nur Superuser können Operatorklassen erzeugen"
-#: commands/opclasscmds.c:478 commands/opclasscmds.c:863
-#: commands/opclasscmds.c:996
+#: commands/opclasscmds.c:475 commands/opclasscmds.c:849
+#: commands/opclasscmds.c:973
#, c-format
msgid "invalid operator number %d, must be between 1 and %d"
msgstr "ungültige Operatornummer %d, muss zwischen 1 und %d sein"
-#: commands/opclasscmds.c:529 commands/opclasscmds.c:914
-#: commands/opclasscmds.c:1011
+#: commands/opclasscmds.c:519 commands/opclasscmds.c:893
+#: commands/opclasscmds.c:988
#, c-format
msgid "invalid procedure number %d, must be between 1 and %d"
msgstr "ungültige Prozedurnummer %d, muss zwischen 1 und %d sein"
-#: commands/opclasscmds.c:559
+#: commands/opclasscmds.c:548
#, c-format
msgid "storage type specified more than once"
msgstr "Storage-Typ mehrmals angegeben"
-#: commands/opclasscmds.c:586
+#: commands/opclasscmds.c:575
#, c-format
msgid "storage type cannot be different from data type for access method \"%s\""
msgstr "Storage-Typ kann nicht vom Datentyp der Zugriffsmethode »%s« verschieden sein"
-#: commands/opclasscmds.c:602
+#: commands/opclasscmds.c:591
#, c-format
msgid "operator class \"%s\" for access method \"%s\" already exists"
msgstr "Operatorklasse »%s« für Zugriffsmethode »%s« existiert bereits"
-#: commands/opclasscmds.c:630
+#: commands/opclasscmds.c:619
#, c-format
msgid "could not make operator class \"%s\" be default for type %s"
msgstr "konnte Operatorklasse »%s« nicht zum Standard für Typ %s machen"
-#: commands/opclasscmds.c:633
+#: commands/opclasscmds.c:622
#, c-format
msgid "Operator class \"%s\" already is the default."
msgstr "Operatorklasse »%s« ist bereits der Standard."
-#: commands/opclasscmds.c:760
+#: commands/opclasscmds.c:747
#, c-format
msgid "must be superuser to create an operator family"
msgstr "nur Superuser können Operatorfamilien erzeugen"
-#: commands/opclasscmds.c:816
+#: commands/opclasscmds.c:803
#, c-format
msgid "must be superuser to alter an operator family"
msgstr "nur Superuser können Operatorfamilien ändern"
-#: commands/opclasscmds.c:879
+#: commands/opclasscmds.c:858
#, c-format
msgid "operator argument types must be specified in ALTER OPERATOR FAMILY"
msgstr "Operatorargumenttypen müssen in ALTER OPERATOR FAMILY angegeben werden"
-#: commands/opclasscmds.c:943
+#: commands/opclasscmds.c:921
#, c-format
msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY"
msgstr "STORAGE kann in ALTER OPERATOR FAMILY nicht angegeben werden"
-#: commands/opclasscmds.c:1066
+#: commands/opclasscmds.c:1043
#, c-format
msgid "one or two argument types must be specified"
msgstr "ein oder zwei Argumenttypen müssen angegeben werden"
-#: commands/opclasscmds.c:1092
+#: commands/opclasscmds.c:1069
#, c-format
msgid "index operators must be binary"
msgstr "Indexoperatoren müssen binär sein"
-#: commands/opclasscmds.c:1111
+#: commands/opclasscmds.c:1088
#, c-format
msgid "access method \"%s\" does not support ordering operators"
msgstr "Zugriffsmethode »%s« unterstützt keine Sortieroperatoren"
-#: commands/opclasscmds.c:1122
+#: commands/opclasscmds.c:1099
#, c-format
msgid "index search operators must return boolean"
msgstr "Indexsuchoperatoren müssen Typ boolean zurückgeben"
-#: commands/opclasscmds.c:1164
+#: commands/opclasscmds.c:1141
#, c-format
msgid "btree comparison procedures must have two arguments"
msgstr "btree-Vergleichsprozeduren müssen zwei Argumente haben"
-#: commands/opclasscmds.c:1168
+#: commands/opclasscmds.c:1145
#, c-format
msgid "btree comparison procedures must return integer"
msgstr "btree-Vergleichsprozeduren müssen Typ integer zurückgeben"
-#: commands/opclasscmds.c:1185
+#: commands/opclasscmds.c:1162
#, c-format
msgid "btree sort support procedures must accept type \"internal\""
msgstr "btree-Sortierunterstützungsprozeduren müssen Typ »internal« akzeptieren"
-#: commands/opclasscmds.c:1189
+#: commands/opclasscmds.c:1166
#, c-format
msgid "btree sort support procedures must return void"
msgstr "btree-Sortierunterstützungsprozeduren müssen Typ void zurückgeben"
-#: commands/opclasscmds.c:1201
+#: commands/opclasscmds.c:1178
#, c-format
msgid "hash procedures must have one argument"
msgstr "Hash-Prozeduren müssen ein Argument haben"
-#: commands/opclasscmds.c:1205
+#: commands/opclasscmds.c:1182
#, c-format
msgid "hash procedures must return integer"
msgstr "Hash-Prozeduren müssen Typ integer zurückgeben"
-#: commands/opclasscmds.c:1229
+#: commands/opclasscmds.c:1206
#, c-format
msgid "associated data types must be specified for index support procedure"
msgstr "zugehörige Datentypen müssen für Indexunterstützungsprozedur angegeben werden"
-#: commands/opclasscmds.c:1254
+#: commands/opclasscmds.c:1231
#, c-format
msgid "procedure number %d for (%s,%s) appears more than once"
msgstr "Prozedurnummer %d für (%s,%s) einscheint mehrmals"
-#: commands/opclasscmds.c:1261
+#: commands/opclasscmds.c:1238
#, c-format
msgid "operator number %d for (%s,%s) appears more than once"
msgstr "Operatornummer %d für (%s,%s) einscheint mehrmals"
-#: commands/opclasscmds.c:1310
+#: commands/opclasscmds.c:1287
#, c-format
msgid "operator %d(%s,%s) already exists in operator family \"%s\""
msgstr "Operator %d(%s,%s) existiert bereits in Operatorfamilie »%s«"
-#: commands/opclasscmds.c:1426
+#: commands/opclasscmds.c:1401
#, c-format
msgid "function %d(%s,%s) already exists in operator family \"%s\""
msgstr "Funktion %d(%s,%s) existiert bereits in Operatorfamilie »%s«"
-#: commands/opclasscmds.c:1516
+#: commands/opclasscmds.c:1489
#, c-format
msgid "operator %d(%s,%s) does not exist in operator family \"%s\""
msgstr "Operator %d(%s,%s) existiert nicht in Operatorfamilie »%s«"
-#: commands/opclasscmds.c:1556
+#: commands/opclasscmds.c:1529
#, c-format
msgid "function %d(%s,%s) does not exist in operator family \"%s\""
msgstr "Funktion %d(%s,%s) existiert nicht in Operatorfamilie »%s«"
-#: commands/opclasscmds.c:1686
+#: commands/opclasscmds.c:1659
#, c-format
msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\""
msgstr "Operatorklasse »%s« für Zugriffsmethode »%s« existiert bereits in Schema »%s«"
-#: commands/opclasscmds.c:1709
+#: commands/opclasscmds.c:1682
#, c-format
msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\""
msgstr "Operatorfamilie »%s« für Zugriffsmethode »%s« existiert bereits in Schema »%s«"
@@ -7301,7 +7547,7 @@ msgstr "Operatorfamilie »%s« für Zugriffsmethode »%s« existiert bereits in
msgid "SETOF type not allowed for operator argument"
msgstr "SETOF-Typ nicht als Operatorargument erlaubt"
-#: commands/operatorcmds.c:152 commands/operatorcmds.c:457
+#: commands/operatorcmds.c:152 commands/operatorcmds.c:454
#, c-format
msgid "operator attribute \"%s\" not recognized"
msgstr "Operator-Attribut »%s« unbekannt"
@@ -7326,18 +7572,18 @@ msgstr "Restriktionsschätzfunktion %s muss Typ %s zurückgeben"
msgid "join estimator function %s must return type %s"
msgstr "Join-Schätzfunktion %s muss Typ %s zurückgeben"
-#: commands/operatorcmds.c:451
+#: commands/operatorcmds.c:448
#, c-format
msgid "operator attribute \"%s\" cannot be changed"
msgstr "Operator-Attribut »%s« kann nicht geändert werden"
-#: commands/policy.c:87 commands/policy.c:390 commands/policy.c:479
-#: commands/tablecmds.c:970 commands/tablecmds.c:1312
-#: commands/tablecmds.c:2184 commands/tablecmds.c:4328
-#: commands/tablecmds.c:6279 commands/tablecmds.c:11933
-#: commands/tablecmds.c:11968 commands/trigger.c:241 commands/trigger.c:1125
-#: commands/trigger.c:1233 rewrite/rewriteDefine.c:273
-#: rewrite/rewriteDefine.c:917
+#: commands/policy.c:87 commands/policy.c:397 commands/policy.c:486
+#: commands/tablecmds.c:1134 commands/tablecmds.c:1490
+#: commands/tablecmds.c:2467 commands/tablecmds.c:4647
+#: commands/tablecmds.c:6742 commands/tablecmds.c:12660
+#: commands/tablecmds.c:12695 commands/trigger.c:251 commands/trigger.c:1235
+#: commands/trigger.c:1344 rewrite/rewriteDefine.c:272
+#: rewrite/rewriteDefine.c:911
#, c-format
msgid "permission denied: \"%s\" is a system catalog"
msgstr "keine Berechtigung: »%s« ist ein Systemkatalog"
@@ -7352,89 +7598,89 @@ msgstr "angegebene Rollen außer PUBLIC werden ignoriert"
msgid "All roles are members of the PUBLIC role."
msgstr "Alle Rollen sind Mitglieder der Rolle PUBLIC."
-#: commands/policy.c:503
+#: commands/policy.c:510
#, c-format
msgid "role \"%s\" could not be removed from policy \"%s\" on \"%s\""
msgstr "Rolle »%s« konnte nicht aus Policy »%s« für »%s« entfernt werden"
-#: commands/policy.c:712
+#: commands/policy.c:716
#, c-format
msgid "WITH CHECK cannot be applied to SELECT or DELETE"
msgstr "WITH CHECK kann nicht auf SELECT oder DELETE angewendet werden"
-#: commands/policy.c:721 commands/policy.c:1021
+#: commands/policy.c:725 commands/policy.c:1023
#, c-format
msgid "only WITH CHECK expression allowed for INSERT"
msgstr "für INSERT sind nur WITH-CHECK-Ausdrücke erlaubt"
-#: commands/policy.c:794 commands/policy.c:1244
+#: commands/policy.c:798 commands/policy.c:1243
#, c-format
msgid "policy \"%s\" for table \"%s\" already exists"
msgstr "Policy »%s« für Tabelle »%s« existiert bereits"
-#: commands/policy.c:993 commands/policy.c:1272 commands/policy.c:1347
+#: commands/policy.c:995 commands/policy.c:1271 commands/policy.c:1343
#, c-format
msgid "policy \"%s\" for table \"%s\" does not exist"
msgstr "Policy »%s« für Tabelle »%s« existiert nicht"
-#: commands/policy.c:1011
+#: commands/policy.c:1013
#, c-format
msgid "only USING expression allowed for SELECT, DELETE"
msgstr "für SELECT und DELETE sind nur USING-Ausdrücke erlaubt"
-#: commands/portalcmds.c:61 commands/portalcmds.c:160
-#: commands/portalcmds.c:212
+#: commands/portalcmds.c:58 commands/portalcmds.c:182
+#: commands/portalcmds.c:234
#, c-format
msgid "invalid cursor name: must not be empty"
msgstr "ungültiger Cursorname: darf nicht leer sein"
-#: commands/portalcmds.c:168 commands/portalcmds.c:222
-#: executor/execCurrent.c:67 utils/adt/xml.c:2391 utils/adt/xml.c:2558
+#: commands/portalcmds.c:190 commands/portalcmds.c:244
+#: executor/execCurrent.c:67 utils/adt/xml.c:2460 utils/adt/xml.c:2627
#, c-format
msgid "cursor \"%s\" does not exist"
msgstr "Cursor »%s« existiert nicht"
-#: commands/prepare.c:71
+#: commands/prepare.c:75
#, c-format
msgid "invalid statement name: must not be empty"
msgstr "ungültiger Anweisungsname: darf nicht leer sein"
-#: commands/prepare.c:129 parser/parse_param.c:304 tcop/postgres.c:1345
+#: commands/prepare.c:141 parser/parse_param.c:304 tcop/postgres.c:1350
#, c-format
msgid "could not determine data type of parameter $%d"
msgstr "konnte Datentyp von Parameter $%d nicht ermitteln"
-#: commands/prepare.c:147
+#: commands/prepare.c:159
#, c-format
msgid "utility statements cannot be prepared"
msgstr "Utility-Anweisungen können nicht vorbereitet werden"
-#: commands/prepare.c:257 commands/prepare.c:264
+#: commands/prepare.c:269 commands/prepare.c:274
#, c-format
msgid "prepared statement is not a SELECT"
msgstr "vorbereitete Anweisung ist kein SELECT"
-#: commands/prepare.c:332
+#: commands/prepare.c:342
#, c-format
msgid "wrong number of parameters for prepared statement \"%s\""
msgstr "falsche Anzahl Parameter für vorbereitete Anweisung »%s«"
-#: commands/prepare.c:334
+#: commands/prepare.c:344
#, c-format
msgid "Expected %d parameters but got %d."
msgstr "%d Parameter erwartet aber %d erhalten."
-#: commands/prepare.c:370
+#: commands/prepare.c:380
#, c-format
msgid "parameter $%d of type %s cannot be coerced to the expected type %s"
msgstr "Parameter $%d mit Typ %s kann nicht in erwarteten Typ %s umgewandelt werden"
-#: commands/prepare.c:465
+#: commands/prepare.c:474
#, c-format
msgid "prepared statement \"%s\" already exists"
msgstr "vorbereitete Anweisung »%s« existiert bereits"
-#: commands/prepare.c:504
+#: commands/prepare.c:513
#, c-format
msgid "prepared statement \"%s\" does not exist"
msgstr "vorbereitete Anweisung »%s« existiert nicht"
@@ -7464,22 +7710,54 @@ msgstr "Die unterstützten Sprachen stehen im Systemkatalog pg_pltemplate."
msgid "must be superuser to create custom procedural language"
msgstr "nur Superuser können maßgeschneiderte prozedurale Sprachen erzeugen"
-#: commands/proclang.c:281
+#: commands/proclang.c:281 commands/trigger.c:523 commands/typecmds.c:457
+#: commands/typecmds.c:474
+#, c-format
+msgid "changing return type of function %s from %s to %s"
+msgstr "ändere Rückgabetyp von Funktion %s von %s in %s"
+
+#: commands/publicationcmds.c:179
+#, c-format
+msgid "must be superuser to create FOR ALL TABLES publication"
+msgstr "nur Superuser können eine Publikation FOR ALL TABLES erzeugen"
+
+#: commands/publicationcmds.c:351
#, c-format
-msgid "changing return type of function %s from \"opaque\" to \"language_handler\""
-msgstr "ändere Rückgabetyp von Funktion %s von »opaque« in »language_handler«"
+msgid "publication \"%s\" is defined as FOR ALL TABLES"
+msgstr "Publikation »%s« ist als FOR ALL TABLES definiert"
-#: commands/schemacmds.c:99 commands/schemacmds.c:262
+#: commands/publicationcmds.c:353
+#, c-format
+msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications."
+msgstr ""
+
+#: commands/publicationcmds.c:651
+#, fuzzy, c-format
+#| msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgid "relation \"%s\" is not part of the publication"
+msgstr "Relation »%s« ist keine Basisrelation von Relation »%s«"
+
+#: commands/publicationcmds.c:681
+#, c-format
+msgid "permission denied to change owner of publication \"%s\""
+msgstr "keine Berechtigung, um Eigentümer der Publikation »%s« zu ändern"
+
+#: commands/publicationcmds.c:683
+#, c-format
+msgid "The owner of a publication must be a superuser."
+msgstr "Der Eigentümer einer Publikation muss ein Superuser sein."
+
+#: commands/schemacmds.c:106 commands/schemacmds.c:279
#, c-format
msgid "unacceptable schema name \"%s\""
msgstr "inakzeptabler Schemaname »%s«"
-#: commands/schemacmds.c:100 commands/schemacmds.c:263
+#: commands/schemacmds.c:107 commands/schemacmds.c:280
#, c-format
msgid "The prefix \"pg_\" is reserved for system schemas."
msgstr "Der Präfix »pg_« ist für Systemschemas reserviert."
-#: commands/schemacmds.c:114
+#: commands/schemacmds.c:121
#, c-format
msgid "schema \"%s\" already exists, skipping"
msgstr "Schema »%s« existiert bereits, wird übersprungen"
@@ -7499,1008 +7777,1354 @@ msgstr "Provider muss angegeben werden, wenn mehrere Security-Label-Provider gel
msgid "security label provider \"%s\" is not loaded"
msgstr "Security-Label-Provider »%s« ist nicht geladen"
-#: commands/sequence.c:127
+#: commands/sequence.c:135
#, c-format
msgid "unlogged sequences are not supported"
msgstr "ungeloggte Sequenzen werden nicht unterstützt"
-#: commands/sequence.c:651
+#: commands/sequence.c:698
#, c-format
msgid "nextval: reached maximum value of sequence \"%s\" (%s)"
msgstr "nextval: Maximalwert von Sequenz »%s« erreicht (%s)"
-#: commands/sequence.c:674
+#: commands/sequence.c:721
#, c-format
msgid "nextval: reached minimum value of sequence \"%s\" (%s)"
msgstr "nextval: Minimalwert von Sequenz »%s« erreicht (%s)"
-#: commands/sequence.c:792
+#: commands/sequence.c:839
#, c-format
msgid "currval of sequence \"%s\" is not yet defined in this session"
msgstr "currval von Sequenz »%s« ist in dieser Sitzung noch nicht definiert"
-#: commands/sequence.c:811 commands/sequence.c:817
+#: commands/sequence.c:858 commands/sequence.c:864
#, c-format
msgid "lastval is not yet defined in this session"
msgstr "lastval ist in dieser Sitzung noch nicht definiert"
-#: commands/sequence.c:893
+#: commands/sequence.c:952
#, c-format
msgid "setval: value %s is out of bounds for sequence \"%s\" (%s..%s)"
msgstr "setval: Wert %s ist außerhalb des gültigen Bereichs von Sequenz »%s« (%s..%s)"
-#: commands/sequence.c:1267
+#: commands/sequence.c:1344
+#, c-format
+msgid "sequence type must be smallint, integer, or bigint"
+msgstr ""
+
+#: commands/sequence.c:1356
#, c-format
msgid "INCREMENT must not be zero"
msgstr "INCREMENT darf nicht null sein"
-#: commands/sequence.c:1323
+#: commands/sequence.c:1405
+#, fuzzy, c-format
+#| msgid "\"%s\" is out of range for type real"
+msgid "MAXVALUE (%s) is out of range for sequence data type %s"
+msgstr "»%s« ist außerhalb des gültigen Bereichs für Typ real"
+
+#: commands/sequence.c:1442
+#, fuzzy, c-format
+#| msgid "\"%s\" is out of range for type real"
+msgid "MINVALUE (%s) is out of range for sequence data type %s"
+msgstr "»%s« ist außerhalb des gültigen Bereichs für Typ real"
+
+#: commands/sequence.c:1456
#, c-format
msgid "MINVALUE (%s) must be less than MAXVALUE (%s)"
msgstr "MINVALUE (%s) muss kleiner als MAXVALUE (%s) sein"
-#: commands/sequence.c:1348
+#: commands/sequence.c:1481
#, c-format
msgid "START value (%s) cannot be less than MINVALUE (%s)"
msgstr "START-Wert (%s) kann nicht kleiner als MINVALUE (%s) sein"
-#: commands/sequence.c:1360
+#: commands/sequence.c:1493
#, c-format
msgid "START value (%s) cannot be greater than MAXVALUE (%s)"
msgstr "START-Wert (%s) kann nicht größer als MAXVALUE (%s) sein"
-#: commands/sequence.c:1390
+#: commands/sequence.c:1523
#, c-format
msgid "RESTART value (%s) cannot be less than MINVALUE (%s)"
msgstr "RESTART-Wert (%s) kann nicht kleiner als MINVALUE (%s) sein"
-#: commands/sequence.c:1402
+#: commands/sequence.c:1535
#, c-format
msgid "RESTART value (%s) cannot be greater than MAXVALUE (%s)"
msgstr "RESTART-Wert (%s) kann nicht größer als MAXVALUE (%s) sein"
-#: commands/sequence.c:1417
+#: commands/sequence.c:1550
#, c-format
msgid "CACHE (%s) must be greater than zero"
msgstr "CACHE (%s) muss größer als null sein"
-#: commands/sequence.c:1449
+#: commands/sequence.c:1582
#, c-format
msgid "invalid OWNED BY option"
msgstr "ungültige OWNED BY Option"
-#: commands/sequence.c:1450
+#: commands/sequence.c:1583
#, c-format
msgid "Specify OWNED BY table.column or OWNED BY NONE."
msgstr "Geben Sie OWNED BY tabelle.spalte oder OWNED BY NONE an."
-#: commands/sequence.c:1473
+#: commands/sequence.c:1607
#, c-format
msgid "referenced relation \"%s\" is not a table or foreign table"
msgstr "Relation »%s«, auf die verwiesen wird, ist keine Tabelle oder Fremdtabelle"
-#: commands/sequence.c:1480
+#: commands/sequence.c:1614
#, c-format
msgid "sequence must have same owner as table it is linked to"
msgstr "Sequenz muss selben Eigentümer wie die verknüpfte Tabelle haben"
-#: commands/sequence.c:1484
+#: commands/sequence.c:1618
#, c-format
msgid "sequence must be in same schema as table it is linked to"
msgstr "Sequenz muss im selben Schema wie die verknüpfte Tabelle sein"
-#: commands/tablecmds.c:215
+#: commands/subscriptioncmds.c:188
+#, c-format
+msgid "publication name \"%s\" used more than once"
+msgstr "Publikationsname »%s« mehrmals angegeben"
+
+#: commands/subscriptioncmds.c:245
+#, c-format
+msgid "must be superuser to create subscriptions"
+msgstr "nur Superuser können Subskriptionen erzeugen"
+
+#: commands/subscriptioncmds.c:313 replication/logical/worker.c:1427
+#, fuzzy, c-format
+#| msgid "could not connect to the primary server: %s"
+msgid "could not connect to the publisher: %s"
+msgstr "konnte nicht mit dem Primärserver verbinden: %s"
+
+#: commands/subscriptioncmds.c:319
+#, fuzzy, c-format
+#| msgid "%s: creating replication slot \"%s\"\n"
+msgid "created replication slot \"%s\" on publisher"
+msgstr "%s: erzeuge Replikations-Slot »%s«\n"
+
+#: commands/subscriptioncmds.c:485
+#, c-format
+msgid "subscription \"%s\" does not exist, skipping"
+msgstr "Subskription »%s« existiert nicht, wird übersprungen"
+
+#: commands/subscriptioncmds.c:564
+#, c-format
+msgid "could not connect to publisher when attempting to drop the replication slot \"%s\""
+msgstr ""
+
+#: commands/subscriptioncmds.c:566 commands/subscriptioncmds.c:574
+#, c-format
+msgid "The error was: %s"
+msgstr "Der Fehler war: %s"
+
+#: commands/subscriptioncmds.c:572
+#, fuzzy, c-format
+#| msgid "%s: could not send replication command \"%s\": %s"
+msgid "could not drop the replication slot \"%s\" on publisher"
+msgstr "%s: konnte Replikationsbefehl »%s« nicht senden: %s"
+
+#: commands/subscriptioncmds.c:577
+#, fuzzy, c-format
+#| msgid "%s: dropping replication slot \"%s\"\n"
+msgid "dropped replication slot \"%s\" on publisher"
+msgstr "%s: lösche Replikations-Slot »%s«\n"
+
+#: commands/subscriptioncmds.c:616
+#, c-format
+msgid "permission denied to change owner of subscription \"%s\""
+msgstr "keine Berechtigung, um Eigentümer der Subskription »%s« zu ändern"
+
+#: commands/subscriptioncmds.c:618
+#, c-format
+msgid "The owner of an subscription must be a superuser."
+msgstr "Der Eigentümer einer Subskription muss ein Superuser sein."
+
+#: commands/tablecmds.c:221 commands/tablecmds.c:263
#, c-format
msgid "table \"%s\" does not exist"
msgstr "Tabelle »%s« existiert nicht"
-#: commands/tablecmds.c:216
+#: commands/tablecmds.c:222 commands/tablecmds.c:264
#, c-format
msgid "table \"%s\" does not exist, skipping"
msgstr "Tabelle »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:218
+#: commands/tablecmds.c:224 commands/tablecmds.c:266
msgid "Use DROP TABLE to remove a table."
msgstr "Verwenden Sie DROP TABLE, um eine Tabelle zu löschen."
-#: commands/tablecmds.c:221
+#: commands/tablecmds.c:227
#, c-format
msgid "sequence \"%s\" does not exist"
msgstr "Sequenz »%s« existiert nicht"
-#: commands/tablecmds.c:222
+#: commands/tablecmds.c:228
#, c-format
msgid "sequence \"%s\" does not exist, skipping"
msgstr "Sequenz »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:224
+#: commands/tablecmds.c:230
msgid "Use DROP SEQUENCE to remove a sequence."
msgstr "Verwenden Sie DROP SEQUENCE, um eine Sequenz zu löschen."
-#: commands/tablecmds.c:227
+#: commands/tablecmds.c:233
#, c-format
msgid "view \"%s\" does not exist"
msgstr "Sicht »%s« existiert nicht"
-#: commands/tablecmds.c:228
+#: commands/tablecmds.c:234
#, c-format
msgid "view \"%s\" does not exist, skipping"
msgstr "Sicht »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:230
+#: commands/tablecmds.c:236
msgid "Use DROP VIEW to remove a view."
msgstr "Verwenden Sie DROP VIEW, um eine Sicht zu löschen."
-#: commands/tablecmds.c:233
+#: commands/tablecmds.c:239
#, c-format
msgid "materialized view \"%s\" does not exist"
msgstr "materialisierte Sicht »%s« existiert nicht"
-#: commands/tablecmds.c:234
+#: commands/tablecmds.c:240
#, c-format
msgid "materialized view \"%s\" does not exist, skipping"
msgstr "materialisierte Sicht »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:236
+#: commands/tablecmds.c:242
msgid "Use DROP MATERIALIZED VIEW to remove a materialized view."
msgstr "Verwenden Sie DROP MATERIALIZED VIEW, um eine materialisierte Sicht zu löschen."
-#: commands/tablecmds.c:239 parser/parse_utilcmd.c:1645
+#: commands/tablecmds.c:245 parser/parse_utilcmd.c:1698
#, c-format
msgid "index \"%s\" does not exist"
msgstr "Index »%s« existiert nicht"
-#: commands/tablecmds.c:240
+#: commands/tablecmds.c:246
#, c-format
msgid "index \"%s\" does not exist, skipping"
msgstr "Index »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:242
+#: commands/tablecmds.c:248
msgid "Use DROP INDEX to remove an index."
msgstr "Verwenden Sie DROP INDEX, um einen Index zu löschen."
-#: commands/tablecmds.c:247
+#: commands/tablecmds.c:253
#, c-format
msgid "\"%s\" is not a type"
msgstr "»%s« ist kein Typ"
-#: commands/tablecmds.c:248
+#: commands/tablecmds.c:254
msgid "Use DROP TYPE to remove a type."
msgstr "Verwenden Sie DROP TYPE, um einen Typen zu löschen."
-#: commands/tablecmds.c:251 commands/tablecmds.c:8486
-#: commands/tablecmds.c:11194
+#: commands/tablecmds.c:257 commands/tablecmds.c:9065
+#: commands/tablecmds.c:11904
#, c-format
msgid "foreign table \"%s\" does not exist"
msgstr "Fremdtabelle »%s« existiert nicht"
-#: commands/tablecmds.c:252
+#: commands/tablecmds.c:258
#, c-format
msgid "foreign table \"%s\" does not exist, skipping"
msgstr "Fremdtabelle »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:254
+#: commands/tablecmds.c:260
msgid "Use DROP FOREIGN TABLE to remove a foreign table."
msgstr "Verwenden Sie DROP FOREIGN TABLE, um eine Fremdtabelle zu löschen."
-#: commands/tablecmds.c:493
+#: commands/tablecmds.c:519
#, c-format
msgid "ON COMMIT can only be used on temporary tables"
msgstr "ON COMMIT kann nur mit temporären Tabellen verwendet werden"
-#: commands/tablecmds.c:513
+#: commands/tablecmds.c:547
#, c-format
msgid "cannot create temporary table within security-restricted operation"
msgstr "kann temporäre Tabelle nicht in einer sicherheitsbeschränkten Operation erzeugen"
-#: commands/tablecmds.c:821
+#: commands/tablecmds.c:646
+#, fuzzy, c-format
+#| msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgid "cannot create table with OIDs as partition of table without OIDs"
+msgstr "Tabelle »%s« ohne OIDs kann nicht von Tabelle »%s« mit OIDs erben"
+
+#: commands/tablecmds.c:764 parser/parse_utilcmd.c:3040
+#, fuzzy, c-format
+#| msgid "\"%s\" is not an index"
+msgid "\"%s\" is not partitioned"
+msgstr "»%s« ist kein Index"
+
+#: commands/tablecmds.c:972
#, c-format
msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects"
msgstr "DROP INDEX CONCURRENTLY unterstützt das Löschen von mehreren Objekten nicht"
-#: commands/tablecmds.c:825
+#: commands/tablecmds.c:976
#, c-format
msgid "DROP INDEX CONCURRENTLY does not support CASCADE"
msgstr "DROP INDEX CONCURRENTLY unterstützt kein CASCADE"
-#: commands/tablecmds.c:1084
+#: commands/tablecmds.c:1224
+#, fuzzy, c-format
+#| msgid "column must be added to child tables too"
+msgid "must truncate child tables too"
+msgstr "Spalte muss ebenso in den abgeleiteten Tabellen hinzugefügt werden"
+
+#: commands/tablecmds.c:1252
#, c-format
msgid "truncate cascades to table \"%s\""
msgstr "Truncate-Vorgang leert ebenfalls Tabelle »%s«"
-#: commands/tablecmds.c:1322
+#: commands/tablecmds.c:1500
#, c-format
msgid "cannot truncate temporary tables of other sessions"
msgstr "kann temporäre Tabellen anderer Sitzungen nicht leeren"
-#: commands/tablecmds.c:1528 parser/parse_utilcmd.c:1859
+#: commands/tablecmds.c:1731 commands/tablecmds.c:10648
+#, fuzzy, c-format
+#| msgid "cannot insert into foreign table \"%s\""
+msgid "cannot inherit from partitioned table \"%s\""
+msgstr "kann nicht in Fremdtabelle »%s« einfügen"
+
+#: commands/tablecmds.c:1736
+#, fuzzy, c-format
+#| msgid "cannot inherit from temporary relation \"%s\""
+msgid "cannot inherit from partition \"%s\""
+msgstr "von temporärer Relation »%s« kann nicht geerbt werden"
+
+#: commands/tablecmds.c:1744 parser/parse_utilcmd.c:1909
#, c-format
msgid "inherited relation \"%s\" is not a table or foreign table"
msgstr "geerbte Relation »%s« ist keine Tabelle oder Fremdtabelle"
-#: commands/tablecmds.c:1535 commands/tablecmds.c:10053
+#: commands/tablecmds.c:1752 commands/tablecmds.c:10627
#, c-format
msgid "cannot inherit from temporary relation \"%s\""
msgstr "von temporärer Relation »%s« kann nicht geerbt werden"
-#: commands/tablecmds.c:1543 commands/tablecmds.c:10061
+#: commands/tablecmds.c:1762 commands/tablecmds.c:10635
#, c-format
msgid "cannot inherit from temporary relation of another session"
msgstr "von temporärer Relation einer anderen Sitzung kann nicht geerbt werden"
-#: commands/tablecmds.c:1559 commands/tablecmds.c:10095
+#: commands/tablecmds.c:1779 commands/tablecmds.c:10746
#, c-format
msgid "relation \"%s\" would be inherited from more than once"
msgstr "von der Relation »%s« würde mehrmals geerbt werden"
-#: commands/tablecmds.c:1607
+#: commands/tablecmds.c:1827
#, c-format
msgid "merging multiple inherited definitions of column \"%s\""
msgstr "geerbte Definitionen von Spalte »%s« werden zusammengeführt"
-#: commands/tablecmds.c:1615
+#: commands/tablecmds.c:1835
#, c-format
msgid "inherited column \"%s\" has a type conflict"
msgstr "geerbte Spalte »%s« hat Typkonflikt"
-#: commands/tablecmds.c:1617 commands/tablecmds.c:1640
-#: commands/tablecmds.c:1838 commands/tablecmds.c:1862
-#: parser/parse_coerce.c:1630 parser/parse_coerce.c:1650
-#: parser/parse_coerce.c:1670 parser/parse_coerce.c:1715
-#: parser/parse_coerce.c:1752 parser/parse_param.c:218
+#: commands/tablecmds.c:1837 commands/tablecmds.c:1860
+#: commands/tablecmds.c:2065 commands/tablecmds.c:2089
+#: parser/parse_coerce.c:1650 parser/parse_coerce.c:1670
+#: parser/parse_coerce.c:1690 parser/parse_coerce.c:1736
+#: parser/parse_coerce.c:1775 parser/parse_param.c:218
#, c-format
msgid "%s versus %s"
msgstr "%s gegen %s"
-#: commands/tablecmds.c:1626
+#: commands/tablecmds.c:1846
#, c-format
msgid "inherited column \"%s\" has a collation conflict"
msgstr "geerbte Spalte »%s« hat Sortierfolgenkonflikt"
-#: commands/tablecmds.c:1628 commands/tablecmds.c:1850
-#: commands/tablecmds.c:4766
+#: commands/tablecmds.c:1848 commands/tablecmds.c:2077
+#: commands/tablecmds.c:5092
#, c-format
msgid "\"%s\" versus \"%s\""
msgstr "»%s« gegen »%s«"
-#: commands/tablecmds.c:1638
+#: commands/tablecmds.c:1858
#, c-format
msgid "inherited column \"%s\" has a storage parameter conflict"
msgstr "geerbte Spalte »%s« hat einen Konflikt bei einem Storage-Parameter"
-#: commands/tablecmds.c:1751 parser/parse_utilcmd.c:938
-#: parser/parse_utilcmd.c:1289 parser/parse_utilcmd.c:1365
+#: commands/tablecmds.c:1971 commands/tablecmds.c:8573
+#: parser/parse_utilcmd.c:993 parser/parse_utilcmd.c:1343
+#: parser/parse_utilcmd.c:1419
#, c-format
msgid "cannot convert whole-row table reference"
msgstr "kann Verweis auf ganze Zeile der Tabelle nicht umwandeln"
-#: commands/tablecmds.c:1752 parser/parse_utilcmd.c:939
+#: commands/tablecmds.c:1972 parser/parse_utilcmd.c:994
#, c-format
msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"."
msgstr "Constraint »%s« enthält einen Verweis auf die ganze Zeile der Tabelle »%s«."
-#: commands/tablecmds.c:1824
+#: commands/tablecmds.c:2051
#, c-format
msgid "merging column \"%s\" with inherited definition"
msgstr "Spalte »%s« wird mit geerbter Definition zusammengeführt"
-#: commands/tablecmds.c:1828
+#: commands/tablecmds.c:2055
#, c-format
msgid "moving and merging column \"%s\" with inherited definition"
msgstr "Spalte »%s« wird verschoben und mit geerbter Definition zusammengeführt"
-#: commands/tablecmds.c:1829
+#: commands/tablecmds.c:2056
#, c-format
msgid "User-specified column moved to the position of the inherited column."
msgstr "Benutzerdefinierte Spalte wurde auf die Position der geerbten Spalte verschoben."
-#: commands/tablecmds.c:1836
+#: commands/tablecmds.c:2063
#, c-format
msgid "column \"%s\" has a type conflict"
msgstr "für Spalte »%s« besteht ein Typkonflikt"
-#: commands/tablecmds.c:1848
+#: commands/tablecmds.c:2075
#, c-format
msgid "column \"%s\" has a collation conflict"
msgstr "für Spalte »%s« besteht ein Sortierfolgenkonflikt"
-#: commands/tablecmds.c:1860
+#: commands/tablecmds.c:2087
#, c-format
msgid "column \"%s\" has a storage parameter conflict"
msgstr "für Spalte »%s« besteht ein Konflikt bei einem Storage-Parameter"
-#: commands/tablecmds.c:1912
+#: commands/tablecmds.c:2189
#, c-format
msgid "column \"%s\" inherits conflicting default values"
msgstr "Spalte »%s« erbt widersprüchliche Vorgabewerte"
-#: commands/tablecmds.c:1914
+#: commands/tablecmds.c:2191
#, c-format
msgid "To resolve the conflict, specify a default explicitly."
msgstr "Um den Konflikt zu lösen, geben Sie einen Vorgabewert ausdrücklich an."
-#: commands/tablecmds.c:1961
+#: commands/tablecmds.c:2238
#, c-format
msgid "check constraint name \"%s\" appears multiple times but with different expressions"
msgstr "Check-Constraint-Name »%s« erscheint mehrmals, aber mit unterschiedlichen Ausdrücken"
-#: commands/tablecmds.c:2155
+#: commands/tablecmds.c:2437
#, c-format
msgid "cannot rename column of typed table"
msgstr "Spalte einer getypten Tabelle kann nicht umbenannt werden"
-#: commands/tablecmds.c:2172
+#: commands/tablecmds.c:2455
#, c-format
msgid "\"%s\" is not a table, view, materialized view, composite type, index, or foreign table"
msgstr "»%s« ist weder Tabelle, Sicht, materialisierte Sicht, zusammengesetzter Typ, Index noch Fremdtabelle"
-#: commands/tablecmds.c:2266
+#: commands/tablecmds.c:2549
#, c-format
msgid "inherited column \"%s\" must be renamed in child tables too"
msgstr "vererbte Spalte »%s« muss ebenso in den abgeleiteten Tabellen umbenannt werden"
-#: commands/tablecmds.c:2298
+#: commands/tablecmds.c:2581
#, c-format
msgid "cannot rename system column \"%s\""
msgstr "Systemspalte »%s« kann nicht umbenannt werden"
-#: commands/tablecmds.c:2313
+#: commands/tablecmds.c:2596
#, c-format
msgid "cannot rename inherited column \"%s\""
msgstr "kann vererbte Spalte »%s« nicht umbenennen"
-#: commands/tablecmds.c:2468
+#: commands/tablecmds.c:2748
#, c-format
msgid "inherited constraint \"%s\" must be renamed in child tables too"
msgstr "vererbter Constraint »%s« muss ebenso in den abgeleiteten Tabellen umbenannt werden"
-#: commands/tablecmds.c:2475
+#: commands/tablecmds.c:2755
#, c-format
msgid "cannot rename inherited constraint \"%s\""
msgstr "kann vererbten Constraint »%s« nicht umbenennen"
#. translator: first %s is a SQL command, eg ALTER TABLE
-#: commands/tablecmds.c:2701
+#: commands/tablecmds.c:2979
#, c-format
msgid "cannot %s \"%s\" because it is being used by active queries in this session"
msgstr "%s mit Relation »%s« nicht möglich, weil sie von aktiven Anfragen in dieser Sitzung verwendet wird"
#. translator: first %s is a SQL command, eg ALTER TABLE
-#: commands/tablecmds.c:2710
+#: commands/tablecmds.c:2988
#, c-format
msgid "cannot %s \"%s\" because it has pending trigger events"
msgstr "%s mit Relation »%s« nicht möglich, weil es anstehende Trigger-Ereignisse dafür gibt"
-#: commands/tablecmds.c:3784
+#: commands/tablecmds.c:4087
#, c-format
msgid "cannot rewrite system relation \"%s\""
msgstr "Systemrelation »%s« kann nicht neu geschrieben werden"
-#: commands/tablecmds.c:3790
+#: commands/tablecmds.c:4093
#, c-format
msgid "cannot rewrite table \"%s\" used as a catalog table"
msgstr "Tabelle »%s«, die als Katalogtabelle verwendet wird, kann nicht neu geschrieben werden"
-#: commands/tablecmds.c:3800
+#: commands/tablecmds.c:4103
#, c-format
msgid "cannot rewrite temporary tables of other sessions"
msgstr "kann temporäre Tabellen anderer Sitzungen nicht neu schreiben"
-#: commands/tablecmds.c:4068
+#: commands/tablecmds.c:4382
#, c-format
msgid "rewriting table \"%s\""
msgstr "schreibe Tabelle »%s« neu"
-#: commands/tablecmds.c:4072
+#: commands/tablecmds.c:4386
#, c-format
msgid "verifying table \"%s\""
msgstr "überprüfe Tabelle »%s«"
-#: commands/tablecmds.c:4186
+#: commands/tablecmds.c:4499
#, c-format
msgid "column \"%s\" contains null values"
msgstr "Spalte »%s« enthält NULL-Werte"
-#: commands/tablecmds.c:4201 commands/tablecmds.c:7366
+#: commands/tablecmds.c:4514 commands/tablecmds.c:7844
#, c-format
msgid "check constraint \"%s\" is violated by some row"
msgstr "Check-Constraint »%s« wird von irgendeiner Zeile verletzt"
-#: commands/tablecmds.c:4349 commands/trigger.c:235
-#: rewrite/rewriteDefine.c:267 rewrite/rewriteDefine.c:912
+#: commands/tablecmds.c:4530
+#, fuzzy, c-format
+#| msgid "check constraint \"%s\" is violated by some row"
+msgid "partition constraint is violated by some row"
+msgstr "Check-Constraint »%s« wird von irgendeiner Zeile verletzt"
+
+#: commands/tablecmds.c:4668 commands/trigger.c:245
+#: rewrite/rewriteDefine.c:266 rewrite/rewriteDefine.c:906
#, c-format
msgid "\"%s\" is not a table or view"
msgstr "»%s« ist keine Tabelle oder Sicht"
-#: commands/tablecmds.c:4352 commands/trigger.c:1119 commands/trigger.c:1224
+#: commands/tablecmds.c:4671 commands/trigger.c:1229 commands/trigger.c:1335
#, c-format
msgid "\"%s\" is not a table, view, or foreign table"
msgstr "»%s« ist keine Tabelle, Sicht oder Fremdtabelle"
-#: commands/tablecmds.c:4355
+#: commands/tablecmds.c:4674
#, c-format
msgid "\"%s\" is not a table, view, materialized view, or index"
msgstr "»%s« ist weder Tabelle, Sicht, materialisierte Sicht noch Index"
-#: commands/tablecmds.c:4361
+#: commands/tablecmds.c:4680
#, c-format
msgid "\"%s\" is not a table, materialized view, or index"
msgstr "»%s« ist weder Tabelle, materialisierte Sicht noch Index"
-#: commands/tablecmds.c:4364
+#: commands/tablecmds.c:4683
#, c-format
msgid "\"%s\" is not a table, materialized view, or foreign table"
msgstr "»%s« ist weder Tabelle, materialisierte Sicht noch Fremdtabelle"
-#: commands/tablecmds.c:4367
+#: commands/tablecmds.c:4686
#, c-format
msgid "\"%s\" is not a table or foreign table"
msgstr "»%s« ist keine Tabelle oder Fremdtabelle"
-#: commands/tablecmds.c:4370
+#: commands/tablecmds.c:4689
#, c-format
msgid "\"%s\" is not a table, composite type, or foreign table"
msgstr "»%s« ist weder Tabelle, Sicht, zusammengesetzter Typ noch Fremdtabelle"
-#: commands/tablecmds.c:4373 commands/tablecmds.c:5425
+#: commands/tablecmds.c:4692 commands/tablecmds.c:5814
#, c-format
msgid "\"%s\" is not a table, materialized view, index, or foreign table"
msgstr "»%s« ist weder Tabelle, materialisierte Sicht, Index noch Fremdtabelle"
-#: commands/tablecmds.c:4383
+#: commands/tablecmds.c:4702
#, c-format
msgid "\"%s\" is of the wrong type"
msgstr "»%s« hat den falschen Typ"
-#: commands/tablecmds.c:4535 commands/tablecmds.c:4542
+#: commands/tablecmds.c:4856 commands/tablecmds.c:4863
#, c-format
msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it"
msgstr "kann Typ »%s« nicht ändern, weil Spalte »%s.%s« ihn verwendet"
-#: commands/tablecmds.c:4549
+#: commands/tablecmds.c:4870
#, c-format
msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type"
msgstr "kann Fremdtabelle »%s« nicht ändern, weil Spalte »%s.%s« ihren Zeilentyp verwendet"
-#: commands/tablecmds.c:4556
+#: commands/tablecmds.c:4877
#, c-format
msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type"
msgstr "kann Tabelle »%s« nicht ändern, weil Spalte »%s.%s« ihren Zeilentyp verwendet"
-#: commands/tablecmds.c:4618
+#: commands/tablecmds.c:4939
#, c-format
msgid "cannot alter type \"%s\" because it is the type of a typed table"
msgstr "kann Typ »%s« nicht ändern, weil er der Typ einer getypten Tabelle ist"
-#: commands/tablecmds.c:4620
+#: commands/tablecmds.c:4941
#, c-format
msgid "Use ALTER ... CASCADE to alter the typed tables too."
msgstr "Verwenden Sie ALTER ... CASCADE, um die getypten Tabellen ebenfalls zu ändern."
-#: commands/tablecmds.c:4664
+#: commands/tablecmds.c:4985
#, c-format
msgid "type %s is not a composite type"
msgstr "Typ %s ist kein zusammengesetzter Typ"
-#: commands/tablecmds.c:4690
+#: commands/tablecmds.c:5011
#, c-format
msgid "cannot add column to typed table"
msgstr "zu einer getypten Tabelle kann keine Spalte hinzugefügt werden"
-#: commands/tablecmds.c:4758 commands/tablecmds.c:10254
+#: commands/tablecmds.c:5055
+#, fuzzy, c-format
+#| msgid "cannot add column to typed table"
+msgid "cannot add column to a partition"
+msgstr "zu einer getypten Tabelle kann keine Spalte hinzugefügt werden"
+
+#: commands/tablecmds.c:5084 commands/tablecmds.c:10872
#, c-format
msgid "child table \"%s\" has different type for column \"%s\""
msgstr "abgeleitete Tabelle »%s« hat unterschiedlichen Typ für Spalte »%s«"
-#: commands/tablecmds.c:4764 commands/tablecmds.c:10261
+#: commands/tablecmds.c:5090 commands/tablecmds.c:10879
#, c-format
msgid "child table \"%s\" has different collation for column \"%s\""
msgstr "abgeleitete Tabelle »%s« hat unterschiedliche Sortierfolge für Spalte »%s«"
-#: commands/tablecmds.c:4774
+#: commands/tablecmds.c:5100
#, c-format
msgid "child table \"%s\" has a conflicting \"%s\" column"
msgstr "abgeleitete Tabelle »%s« hat eine widersprüchliche Spalte »%s«"
-#: commands/tablecmds.c:4786
+#: commands/tablecmds.c:5111
#, c-format
msgid "merging definition of column \"%s\" for child \"%s\""
msgstr "Definition von Spalte »%s« für abgeleitete Tabelle »%s« wird zusammengeführt"
-#: commands/tablecmds.c:5013
+#: commands/tablecmds.c:5335
#, c-format
msgid "column must be added to child tables too"
msgstr "Spalte muss ebenso in den abgeleiteten Tabellen hinzugefügt werden"
-#: commands/tablecmds.c:5088
+#: commands/tablecmds.c:5410
#, c-format
msgid "column \"%s\" of relation \"%s\" already exists, skipping"
msgstr "Spalte »%s« von Relation »%s« existiert bereits, wird übersprungen"
-#: commands/tablecmds.c:5095
+#: commands/tablecmds.c:5417
#, c-format
msgid "column \"%s\" of relation \"%s\" already exists"
msgstr "Spalte »%s« von Relation »%s« existiert bereits"
-#: commands/tablecmds.c:5206 commands/tablecmds.c:5312
-#: commands/tablecmds.c:5370 commands/tablecmds.c:5484
-#: commands/tablecmds.c:5541 commands/tablecmds.c:5635
-#: commands/tablecmds.c:7884 commands/tablecmds.c:8509
+#: commands/tablecmds.c:5511 commands/tablecmds.c:8246
+#, fuzzy, c-format
+#| msgid "constraint must be added to child tables too"
+msgid "constraint must be dropped from child tables too"
+msgstr "Constraint muss ebenso in den abgeleiteten Tabellen hinzugefügt werden"
+
+#: commands/tablecmds.c:5542 commands/tablecmds.c:5703
+#: commands/tablecmds.c:5758 commands/tablecmds.c:5873
+#: commands/tablecmds.c:5927 commands/tablecmds.c:6019
+#: commands/tablecmds.c:8395 commands/tablecmds.c:9088
#, c-format
msgid "cannot alter system column \"%s\""
msgstr "Systemspalte »%s« kann nicht geändert werden"
-#: commands/tablecmds.c:5242
+#: commands/tablecmds.c:5578
#, c-format
msgid "column \"%s\" is in a primary key"
msgstr "Spalte »%s« ist in einem Primärschlüssel"
-#: commands/tablecmds.c:5457
+#: commands/tablecmds.c:5600
+#, fuzzy, c-format
+#| msgid "column \"%s\" in child table must be marked NOT NULL"
+msgid "column \"%s\" is marked NOT NULL in parent table"
+msgstr "Spalte »%s« in abgeleiteter Tabelle muss als NOT NULL markiert sein"
+
+#: commands/tablecmds.c:5625
+#, fuzzy, c-format
+#| msgid "column \"%s\" is in a primary key"
+msgid "column \"%s\" is in range partition key"
+msgstr "Spalte »%s« ist in einem Primärschlüssel"
+
+#: commands/tablecmds.c:5672 commands/tablecmds.c:6659
+#, c-format
+msgid "constraint must be added to child tables too"
+msgstr "Constraint muss ebenso in den abgeleiteten Tabellen hinzugefügt werden"
+
+#: commands/tablecmds.c:5846
#, c-format
msgid "statistics target %d is too low"
msgstr "Statistikziel %d ist zu niedrig"
-#: commands/tablecmds.c:5465
+#: commands/tablecmds.c:5854
#, c-format
msgid "lowering statistics target to %d"
msgstr "setze Statistikziel auf %d herab"
-#: commands/tablecmds.c:5615
+#: commands/tablecmds.c:5999
#, c-format
msgid "invalid storage type \"%s\""
msgstr "ungültiger Storage-Typ »%s«"
-#: commands/tablecmds.c:5647
+#: commands/tablecmds.c:6031
#, c-format
msgid "column data type %s can only have storage PLAIN"
msgstr "Spaltendatentyp %s kann nur Storage-Typ PLAIN"
-#: commands/tablecmds.c:5685
+#: commands/tablecmds.c:6066
#, c-format
msgid "cannot drop column from typed table"
msgstr "aus einer getypten Tabelle können keine Spalten gelöscht werden"
-#: commands/tablecmds.c:5729
+#: commands/tablecmds.c:6173
#, c-format
msgid "column \"%s\" of relation \"%s\" does not exist, skipping"
msgstr "Spalte »%s« von Relation »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:5742
+#: commands/tablecmds.c:6186
#, c-format
msgid "cannot drop system column \"%s\""
msgstr "Systemspalte »%s« kann nicht gelöscht werden"
-#: commands/tablecmds.c:5749
+#: commands/tablecmds.c:6193
#, c-format
msgid "cannot drop inherited column \"%s\""
msgstr "geerbte Spalte »%s« kann nicht gelöscht werden"
-#: commands/tablecmds.c:5989
+#: commands/tablecmds.c:6202
+#, fuzzy, c-format
+#| msgid "cannot drop column from typed table"
+msgid "cannot drop column named in partition key"
+msgstr "aus einer getypten Tabelle können keine Spalten gelöscht werden"
+
+#: commands/tablecmds.c:6206
+#, fuzzy, c-format
+#| msgid "cannot use column references in default expression"
+msgid "cannot drop column referenced in partition key expression"
+msgstr "Spaltenverweise können nicht in Vorgabeausdrücken verwendet werden"
+
+#: commands/tablecmds.c:6230
+#, fuzzy, c-format
+#| msgid "column must be added to child tables too"
+msgid "column must be dropped from child tables too"
+msgstr "Spalte muss ebenso in den abgeleiteten Tabellen hinzugefügt werden"
+
+#: commands/tablecmds.c:6446
#, c-format
msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\""
msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX benennt Index »%s« um in »%s«"
-#: commands/tablecmds.c:6202
-#, c-format
-msgid "constraint must be added to child tables too"
-msgstr "Constraint muss ebenso in den abgeleiteten Tabellen hinzugefügt werden"
+#: commands/tablecmds.c:6730
+#, fuzzy, c-format
+#| msgid "cannot insert into foreign table \"%s\""
+msgid "cannot reference partitioned table \"%s\""
+msgstr "kann nicht in Fremdtabelle »%s« einfügen"
-#: commands/tablecmds.c:6273
+#: commands/tablecmds.c:6736
#, c-format
msgid "referenced relation \"%s\" is not a table"
msgstr "Relation »%s«, auf die verwiesen wird, ist keine Tabelle"
-#: commands/tablecmds.c:6296
+#: commands/tablecmds.c:6759
#, c-format
msgid "constraints on permanent tables may reference only permanent tables"
msgstr "Constraints für permanente Tabellen dürfen nur auf permanente Tabellen verweisen"
-#: commands/tablecmds.c:6303
+#: commands/tablecmds.c:6766
#, c-format
msgid "constraints on unlogged tables may reference only permanent or unlogged tables"
msgstr "Constraints für ungeloggte Tabellen dürfen nur auf permanente oder ungeloggte Tabellen verweisen"
-#: commands/tablecmds.c:6309
+#: commands/tablecmds.c:6772
#, c-format
msgid "constraints on temporary tables may reference only temporary tables"
msgstr "Constraints für temporäre Tabellen dürfen nur auf temporäre Tabellen verweisen"
-#: commands/tablecmds.c:6313
+#: commands/tablecmds.c:6776
#, c-format
msgid "constraints on temporary tables must involve temporary tables of this session"
msgstr "Constraints für temporäre Tabellen müssen temporäre Tabellen dieser Sitzung beinhalten"
-#: commands/tablecmds.c:6374
+#: commands/tablecmds.c:6837
#, c-format
msgid "number of referencing and referenced columns for foreign key disagree"
msgstr "Anzahl der Quell- und Zielspalten im Fremdschlüssel stimmt nicht überein"
-#: commands/tablecmds.c:6481
+#: commands/tablecmds.c:6944
#, c-format
msgid "foreign key constraint \"%s\" cannot be implemented"
msgstr "Fremdschlüssel-Constraint »%s« kann nicht implementiert werden"
-#: commands/tablecmds.c:6484
+#: commands/tablecmds.c:6947
#, c-format
msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s."
msgstr "Schlüsselspalten »%s« und »%s« haben inkompatible Typen: %s und %s."
-#: commands/tablecmds.c:6691 commands/tablecmds.c:6841
-#: commands/tablecmds.c:7723 commands/tablecmds.c:7779
+#: commands/tablecmds.c:7153 commands/tablecmds.c:7319
+#: commands/tablecmds.c:8225 commands/tablecmds.c:8291
#, c-format
msgid "constraint \"%s\" of relation \"%s\" does not exist"
msgstr "Constraint »%s« von Relation »%s« existiert nicht"
-#: commands/tablecmds.c:6697
+#: commands/tablecmds.c:7159
#, c-format
msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint"
msgstr "Constraint »%s« von Relation »%s« ist kein Fremdschlüssel-Constraint"
-#: commands/tablecmds.c:6848
+#: commands/tablecmds.c:7326
#, c-format
msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint"
msgstr "Constraint »%s« von Relation »%s« ist kein Fremdschlüssel- oder Check-Constraint"
-#: commands/tablecmds.c:6916
+#: commands/tablecmds.c:7395
#, c-format
msgid "constraint must be validated on child tables too"
msgstr "Constraint muss ebenso in den abgeleiteten Tabellen validiert werden"
-#: commands/tablecmds.c:6985
+#: commands/tablecmds.c:7463
#, c-format
msgid "column \"%s\" referenced in foreign key constraint does not exist"
msgstr "Spalte »%s«, die im Fremdschlüssel verwendet wird, existiert nicht"
-#: commands/tablecmds.c:6990
+#: commands/tablecmds.c:7468
#, c-format
msgid "cannot have more than %d keys in a foreign key"
msgstr "Fremdschlüssel kann nicht mehr als %d Schlüssel haben"
-#: commands/tablecmds.c:7055
+#: commands/tablecmds.c:7533
#, c-format
msgid "cannot use a deferrable primary key for referenced table \"%s\""
msgstr "aufschiebbarer Primärschlüssel kann nicht für Tabelle »%s«, auf die verwiesen wird, verwendet werden"
-#: commands/tablecmds.c:7072
+#: commands/tablecmds.c:7550
#, c-format
msgid "there is no primary key for referenced table \"%s\""
msgstr "in Tabelle »%s«, auf die verwiesen wird, gibt es keinen Primärschlüssel"
-#: commands/tablecmds.c:7137
+#: commands/tablecmds.c:7615
#, c-format
msgid "foreign key referenced-columns list must not contain duplicates"
msgstr "die Liste der Spalten, auf die ein Fremdschlüssel verweist, darf keine doppelten Einträge enthalten"
-#: commands/tablecmds.c:7231
+#: commands/tablecmds.c:7709
#, c-format
msgid "cannot use a deferrable unique constraint for referenced table \"%s\""
msgstr "aufschiebbarer Unique-Constraint kann nicht für Tabelle »%s«, auf die verwiesen wird, verwendet werden"
-#: commands/tablecmds.c:7236
+#: commands/tablecmds.c:7714
#, c-format
msgid "there is no unique constraint matching given keys for referenced table \"%s\""
msgstr "in Tabelle »%s«, auf die verwiesen wird, gibt es keinen Unique-Constraint, der auf die angegebenen Schlüssel passt"
-#: commands/tablecmds.c:7399
+#: commands/tablecmds.c:7877
#, c-format
msgid "validating foreign key constraint \"%s\""
msgstr "validiere Fremdschlüssel-Constraint »%s«"
-#: commands/tablecmds.c:7695
+#: commands/tablecmds.c:8179
#, c-format
msgid "cannot drop inherited constraint \"%s\" of relation \"%s\""
msgstr "geerbter Constraint »%s« von Relation »%s« kann nicht gelöscht werden"
-#: commands/tablecmds.c:7729
+#: commands/tablecmds.c:8231
#, c-format
msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping"
msgstr "Constraint »%s« von Relation »%s« existiert nicht, wird übersprungen"
-#: commands/tablecmds.c:7868
+#: commands/tablecmds.c:8379
#, c-format
msgid "cannot alter column type of typed table"
msgstr "Spaltentyp einer getypten Tabelle kann nicht geändert werden"
-#: commands/tablecmds.c:7891
+#: commands/tablecmds.c:8402
#, c-format
msgid "cannot alter inherited column \"%s\""
msgstr "kann vererbte Spalte »%s« nicht ändern"
-#: commands/tablecmds.c:7940
+#: commands/tablecmds.c:8411
+#, fuzzy, c-format
+#| msgid "cannot alter type of a column used in a trigger definition"
+msgid "cannot alter type of column named in partition key"
+msgstr "Typ einer Spalte, die in einer Trigger-Definition verwendet wird, kann nicht geändert werden"
+
+#: commands/tablecmds.c:8415
+#, fuzzy, c-format
+#| msgid "cannot use column references in default expression"
+msgid "cannot alter type of column referenced in partition key expression"
+msgstr "Spaltenverweise können nicht in Vorgabeausdrücken verwendet werden"
+
+#: commands/tablecmds.c:8465
#, c-format
msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s"
msgstr "Ergebnis der USING-Klausel für Spalte »%s« kann nicht automatisch in Typ %s umgewandelt werden"
-#: commands/tablecmds.c:7943
+#: commands/tablecmds.c:8468
#, c-format
msgid "You might need to add an explicit cast."
msgstr "Sie müssen möglicherweise eine ausdrückliche Typumwandlung hinzufügen."
-#: commands/tablecmds.c:7947
+#: commands/tablecmds.c:8472
#, c-format
msgid "column \"%s\" cannot be cast automatically to type %s"
msgstr "Spalte »%s« kann nicht automatisch in Typ %s umgewandelt werden"
#. translator: USING is SQL, don't translate it
-#: commands/tablecmds.c:7950
+#: commands/tablecmds.c:8475
#, c-format
msgid "You might need to specify \"USING %s::%s\"."
msgstr "Sie müssen möglicherweise »USING %s::%s« angeben."
-#: commands/tablecmds.c:8003
+#: commands/tablecmds.c:8574
+#, c-format
+msgid "USING expression contains a whole-row table reference."
+msgstr "USING-Ausdruck enthält einen Verweis auf die ganze Zeile der Tabelle."
+
+#: commands/tablecmds.c:8585
#, c-format
msgid "type of inherited column \"%s\" must be changed in child tables too"
msgstr "Typ der vererbten Spalte »%s« muss ebenso in den abgeleiteten Tabellen geändert werden"
-#: commands/tablecmds.c:8090
+#: commands/tablecmds.c:8672
#, c-format
msgid "cannot alter type of column \"%s\" twice"
msgstr "Typ der Spalte »%s« kann nicht zweimal geändert werden"
-#: commands/tablecmds.c:8126
+#: commands/tablecmds.c:8708
#, c-format
msgid "default for column \"%s\" cannot be cast automatically to type %s"
msgstr "Vorgabewert der Spalte »%s« kann nicht automatisch in Typ %s umgewandelt werden"
-#: commands/tablecmds.c:8252
+#: commands/tablecmds.c:8834
#, c-format
msgid "cannot alter type of a column used by a view or rule"
msgstr "Typ einer Spalte, die von einer Sicht oder Regel verwendet wird, kann nicht geändert werden"
-#: commands/tablecmds.c:8253 commands/tablecmds.c:8272
-#: commands/tablecmds.c:8290
+#: commands/tablecmds.c:8835 commands/tablecmds.c:8854
+#: commands/tablecmds.c:8872
#, c-format
msgid "%s depends on column \"%s\""
msgstr "%s hängt von Spalte »%s« ab"
-#: commands/tablecmds.c:8271
+#: commands/tablecmds.c:8853
#, c-format
msgid "cannot alter type of a column used in a trigger definition"
msgstr "Typ einer Spalte, die in einer Trigger-Definition verwendet wird, kann nicht geändert werden"
-#: commands/tablecmds.c:8289
+#: commands/tablecmds.c:8871
#, c-format
msgid "cannot alter type of a column used in a policy definition"
msgstr "Typ einer Spalte, die in einer Policy-Definition verwendet wird, kann nicht geändert werden"
-#: commands/tablecmds.c:8954
+#: commands/tablecmds.c:9528
#, c-format
msgid "cannot change owner of index \"%s\""
msgstr "kann Eigentümer des Index »%s« nicht ändern"
-#: commands/tablecmds.c:8956
+#: commands/tablecmds.c:9530
#, c-format
msgid "Change the ownership of the index's table, instead."
msgstr "Ändern Sie stattdessen den Eigentümer der Tabelle des Index."
-#: commands/tablecmds.c:8972
+#: commands/tablecmds.c:9546
#, c-format
msgid "cannot change owner of sequence \"%s\""
msgstr "kann Eigentümer der Sequenz »%s« nicht ändern"
-#: commands/tablecmds.c:8974 commands/tablecmds.c:11396
+#: commands/tablecmds.c:9548 commands/tablecmds.c:12123
#, c-format
msgid "Sequence \"%s\" is linked to table \"%s\"."
msgstr "Sequenz »%s« ist mit Tabelle »%s« verknüpft."
-#: commands/tablecmds.c:8986 commands/tablecmds.c:12043
+#: commands/tablecmds.c:9560 commands/tablecmds.c:12770
#, c-format
msgid "Use ALTER TYPE instead."
msgstr "Verwenden Sie stattdessen ALTER TYPE."
-#: commands/tablecmds.c:8995
+#: commands/tablecmds.c:9569
#, c-format
msgid "\"%s\" is not a table, view, sequence, or foreign table"
msgstr "»%s« ist keine Tabelle, Sicht, Sequenz oder Fremdtabelle"
-#: commands/tablecmds.c:9338
+#: commands/tablecmds.c:9910
#, c-format
msgid "cannot have multiple SET TABLESPACE subcommands"
msgstr "mehrere SET TABLESPACE Unterbefehle sind ungültig"
-#: commands/tablecmds.c:9411
+#: commands/tablecmds.c:9984
#, c-format
msgid "\"%s\" is not a table, view, materialized view, index, or TOAST table"
msgstr "»%s« ist weder Tabelle, Sicht, materialisierte Sicht, Index noch TOAST-Tabelle"
-#: commands/tablecmds.c:9444 commands/view.c:469
+#: commands/tablecmds.c:10017 commands/view.c:504
#, c-format
msgid "WITH CHECK OPTION is supported only on automatically updatable views"
msgstr "WITH CHECK OPTION wird nur für automatisch aktualisierbare Sichten unterstützt"
-#: commands/tablecmds.c:9590
+#: commands/tablecmds.c:10159
#, c-format
msgid "cannot move system relation \"%s\""
msgstr "Systemrelation »%s« kann nicht verschoben werden"
-#: commands/tablecmds.c:9606
+#: commands/tablecmds.c:10175
#, c-format
msgid "cannot move temporary tables of other sessions"
msgstr "temporäre Tabellen anderer Sitzungen können nicht verschoben werden"
-#: commands/tablecmds.c:9743
+#: commands/tablecmds.c:10311
#, c-format
msgid "only tables, indexes, and materialized views exist in tablespaces"
msgstr "nur Tabellen, Indexe und materialisierte Sichten existieren in Tablespaces"
-#: commands/tablecmds.c:9755
+#: commands/tablecmds.c:10323
#, c-format
msgid "cannot move relations in to or out of pg_global tablespace"
msgstr "Relationen können nicht in den oder aus dem Tablespace »pg_global« verschoben werden"
-#: commands/tablecmds.c:9846
+#: commands/tablecmds.c:10415
#, c-format
msgid "aborting because lock on relation \"%s.%s\" is not available"
msgstr "Abbruch weil Sperre für Relation »%s.%s« nicht verfügbar ist"
-#: commands/tablecmds.c:9862
+#: commands/tablecmds.c:10431
#, c-format
msgid "no matching relations in tablespace \"%s\" found"
msgstr "keine passenden Relationen in Tablespace »%s« gefunden"
-#: commands/tablecmds.c:9936 storage/buffer/bufmgr.c:915
+#: commands/tablecmds.c:10505 storage/buffer/bufmgr.c:915
#, c-format
msgid "invalid page in block %u of relation %s"
msgstr "ungültige Seite in Block %u von Relation %s"
-#: commands/tablecmds.c:10018
+#: commands/tablecmds.c:10587
#, c-format
msgid "cannot change inheritance of typed table"
msgstr "Vererbung einer getypten Tabelle kann nicht geändert werden"
-#: commands/tablecmds.c:10068
+#: commands/tablecmds.c:10592 commands/tablecmds.c:11120
+#, fuzzy, c-format
+#| msgid "cannot change inheritance of typed table"
+msgid "cannot change inheritance of a partition"
+msgstr "Vererbung einer getypten Tabelle kann nicht geändert werden"
+
+#: commands/tablecmds.c:10597
+#, fuzzy, c-format
+#| msgid "cannot change inheritance of typed table"
+msgid "cannot change inheritance of partitioned table"
+msgstr "Vererbung einer getypten Tabelle kann nicht geändert werden"
+
+#: commands/tablecmds.c:10642
#, c-format
msgid "cannot inherit to temporary relation of another session"
msgstr "an temporäre Relation einer anderen Sitzung kann nicht vererbt werden"
-#: commands/tablecmds.c:10122
+#: commands/tablecmds.c:10655
+#, fuzzy, c-format
+#| msgid "cannot inherit from temporary relation \"%s\""
+msgid "cannot inherit from a partition"
+msgstr "von temporärer Relation »%s« kann nicht geerbt werden"
+
+#: commands/tablecmds.c:10677 commands/tablecmds.c:13122
#, c-format
msgid "circular inheritance not allowed"
msgstr "zirkuläre Vererbung ist nicht erlaubt"
-#: commands/tablecmds.c:10123
+#: commands/tablecmds.c:10678 commands/tablecmds.c:13123
#, c-format
msgid "\"%s\" is already a child of \"%s\"."
msgstr "»%s« ist schon von »%s« abgeleitet."
-#: commands/tablecmds.c:10131
+#: commands/tablecmds.c:10686
#, c-format
msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
msgstr "Tabelle »%s« ohne OIDs kann nicht von Tabelle »%s« mit OIDs erben"
-#: commands/tablecmds.c:10272
+#: commands/tablecmds.c:10890
#, c-format
msgid "column \"%s\" in child table must be marked NOT NULL"
msgstr "Spalte »%s« in abgeleiteter Tabelle muss als NOT NULL markiert sein"
-#: commands/tablecmds.c:10288
+#: commands/tablecmds.c:10917 commands/tablecmds.c:10956
#, c-format
msgid "child table is missing column \"%s\""
msgstr "Spalte »%s« fehlt in abgeleiteter Tabelle"
-#: commands/tablecmds.c:10371
+#: commands/tablecmds.c:11044
#, c-format
msgid "child table \"%s\" has different definition for check constraint \"%s\""
msgstr "abgeleitete Tabelle »%s« hat unterschiedliche Definition für Check-Constraint »%s«"
-#: commands/tablecmds.c:10379
+#: commands/tablecmds.c:11052
#, c-format
msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\""
msgstr "Constraint »%s« kollidiert mit nicht vererbtem Constraint für abgeleitete Tabelle »%s«"
-#: commands/tablecmds.c:10403
+#: commands/tablecmds.c:11063
+#, c-format
+msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\""
+msgstr "Constraint »%s« kollidiert mit NOT-VALID-Constraint für abgeleitete Tabelle »%s«"
+
+#: commands/tablecmds.c:11098
#, c-format
msgid "child table is missing constraint \"%s\""
msgstr "Constraint »%s« fehlt in abgeleiteter Tabelle"
-#: commands/tablecmds.c:10487
+#: commands/tablecmds.c:11214
+#, fuzzy, c-format
+#| msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgid "relation \"%s\" is not a partition of relation \"%s\""
+msgstr "Relation »%s« ist keine Basisrelation von Relation »%s«"
+
+#: commands/tablecmds.c:11220
#, c-format
msgid "relation \"%s\" is not a parent of relation \"%s\""
msgstr "Relation »%s« ist keine Basisrelation von Relation »%s«"
-#: commands/tablecmds.c:10721
+#: commands/tablecmds.c:11444
#, c-format
msgid "typed tables cannot inherit"
msgstr "getypte Tabellen können nicht erben"
-#: commands/tablecmds.c:10752
+#: commands/tablecmds.c:11475
#, c-format
msgid "table is missing column \"%s\""
msgstr "Spalte »%s« fehlt in Tabelle"
-#: commands/tablecmds.c:10762
+#: commands/tablecmds.c:11485
#, c-format
msgid "table has column \"%s\" where type requires \"%s\""
msgstr "Tabelle hat Spalte »%s«, aber Typ benötigt »%s«"
-#: commands/tablecmds.c:10771
+#: commands/tablecmds.c:11494
#, c-format
msgid "table \"%s\" has different type for column \"%s\""
msgstr "Tabelle »%s« hat unterschiedlichen Typ für Spalte »%s«"
-#: commands/tablecmds.c:10784
+#: commands/tablecmds.c:11507
#, c-format
msgid "table has extra column \"%s\""
msgstr "Tabelle hat zusätzliche Spalte »%s«"
-#: commands/tablecmds.c:10836
+#: commands/tablecmds.c:11558
#, c-format
msgid "\"%s\" is not a typed table"
msgstr "»%s« ist keine getypte Tabelle"
-#: commands/tablecmds.c:11020
+#: commands/tablecmds.c:11739
#, c-format
msgid "cannot use non-unique index \"%s\" as replica identity"
msgstr "nicht eindeutiger Index »%s« kann nicht als Replik-Identität verwendet werden"
-#: commands/tablecmds.c:11026
+#: commands/tablecmds.c:11745
#, c-format
msgid "cannot use non-immediate index \"%s\" as replica identity"
msgstr "Index »%s« kann nicht als Replik-Identität verwendet werden, weil er nicht IMMEDIATE ist"
-#: commands/tablecmds.c:11032
+#: commands/tablecmds.c:11751
#, c-format
msgid "cannot use expression index \"%s\" as replica identity"
msgstr "Ausdrucksindex »%s« kann nicht als Replik-Identität verwendet werden"
-#: commands/tablecmds.c:11038
+#: commands/tablecmds.c:11757
#, c-format
msgid "cannot use partial index \"%s\" as replica identity"
msgstr "partieller Index »%s« kann nicht als Replik-Identität verwendet werden"
-#: commands/tablecmds.c:11044
+#: commands/tablecmds.c:11763
#, c-format
msgid "cannot use invalid index \"%s\" as replica identity"
msgstr "ungültiger Index »%s« kann nicht als Replik-Identität verwendet werden"
-#: commands/tablecmds.c:11065
+#: commands/tablecmds.c:11784
#, c-format
msgid "index \"%s\" cannot be used as replica identity because column %d is a system column"
msgstr "Index »%s« kann nicht als Replik-Identität verwendet werden, weil Spalte %d eine Systemspalte ist"
-#: commands/tablecmds.c:11072
+#: commands/tablecmds.c:11791
#, c-format
msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable"
msgstr "Index »%s« kann nicht als Replik-Identität verwendet werden, weil Spalte »%s« NULL-Werte akzeptiert"
-#: commands/tablecmds.c:11269
+#: commands/tablecmds.c:11984
#, c-format
msgid "cannot change logged status of table \"%s\" because it is temporary"
msgstr "kann den geloggten Status der Tabelle »%s« nicht ändern, weil sie temporär ist"
-#: commands/tablecmds.c:11328
+#: commands/tablecmds.c:12008
+#, fuzzy, c-format
+msgid "cannot change table \"%s\" to unlogged because it is part of a publication"
+msgstr "kann Tabelle »%s« nicht in ungeloggt ändern, weil sie Teil einer Publikation ist"
+
+#: commands/tablecmds.c:12010
+#, c-format
+msgid "Unlogged relations cannot be replicated."
+msgstr "Ungeloggte Relationen können nicht repliziert werden."
+
+#: commands/tablecmds.c:12055
#, c-format
msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\""
msgstr "konnte Tabelle »%s« nicht in geloggt ändern, weil sie auf die ungeloggte Tabelle »%s« verweist"
-#: commands/tablecmds.c:11338
+#: commands/tablecmds.c:12065
#, c-format
msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\""
msgstr "konnte Tabelle »%s« nicht in ungeloggt ändern, weil sie auf die geloggte Tabelle »%s« verweist"
-#: commands/tablecmds.c:11395
+#: commands/tablecmds.c:12122
#, c-format
msgid "cannot move an owned sequence into another schema"
msgstr "einer Tabelle zugeordnete Sequenz kann nicht in ein anderes Schema verschoben werden"
-#: commands/tablecmds.c:11500
+#: commands/tablecmds.c:12228
#, c-format
msgid "relation \"%s\" already exists in schema \"%s\""
msgstr "Relation »%s« existiert bereits in Schema »%s«"
-#: commands/tablecmds.c:12027
+#: commands/tablecmds.c:12754
#, c-format
msgid "\"%s\" is not a composite type"
msgstr "»%s« ist kein zusammengesetzter Typ"
-#: commands/tablecmds.c:12057
+#: commands/tablecmds.c:12785
#, c-format
msgid "\"%s\" is not a table, view, materialized view, sequence, or foreign table"
msgstr "»%s« ist weder Tabelle, Sicht, materialisierte Sicht, Sequenz noch Fremdtabelle"
+#: commands/tablecmds.c:12816
+#, fuzzy, c-format
+#| msgid "unrecognized privilege type \"%s\""
+msgid "unrecognized partitioning strategy \"%s\""
+msgstr "unbekannter Privilegtyp »%s«"
+
+#: commands/tablecmds.c:12842
+#, fuzzy, c-format
+#| msgid "common column name \"%s\" appears more than once in right table"
+msgid "column \"%s\" appears more than once in partition key"
+msgstr "gemeinsamer Spaltenname »%s« erscheint mehrmals in der rechten Tabelle"
+
+#: commands/tablecmds.c:12890
+#, fuzzy, c-format
+#| msgid "column \"%s\" named in key does not exist"
+msgid "column \"%s\" named in partition key does not exist"
+msgstr "Spalte »%s«, die im Schlüssel verwendet wird, existiert nicht"
+
+#: commands/tablecmds.c:12897
+#, fuzzy, c-format
+#| msgid "cannot alter system column \"%s\""
+msgid "cannot use system column \"%s\" in partition key"
+msgstr "Systemspalte »%s« kann nicht geändert werden"
+
+#: commands/tablecmds.c:12955
+#, fuzzy, c-format
+#| msgid "functions in index expression must be marked IMMUTABLE"
+msgid "functions in partition key expression must be marked IMMUTABLE"
+msgstr "Funktionen im Indexausdruck müssen als IMMUTABLE markiert sein"
+
+#: commands/tablecmds.c:12964
+#, fuzzy, c-format
+#| msgid "cannot use expression index \"%s\" as replica identity"
+msgid "cannot use constant expression as partition key"
+msgstr "Ausdrucksindex »%s« kann nicht als Replik-Identität verwendet werden"
+
+#: commands/tablecmds.c:12978
+#, fuzzy, c-format
+#| msgid "USING expression contains a whole-row table reference."
+msgid "partition key expressions cannot contain whole-row references"
+msgstr "USING-Ausdruck enthält einen Verweis auf die ganze Zeile der Tabelle."
+
+#: commands/tablecmds.c:12999
+#, fuzzy, c-format
+#| msgid "could not determine which collation to use for index expression"
+msgid "could not determine which collation to use for partition expression"
+msgstr "konnte die für den Indexausdruck zu verwendende Sortierfolge nicht bestimmen"
+
+#: commands/tablecmds.c:13024
+#, fuzzy, c-format
+#| msgid "data type %s has no default operator class for access method \"%s\""
+msgid "data type %s has no default btree operator class"
+msgstr "Datentyp %s hat keine Standardoperatorklasse für Zugriffsmethode »%s«"
+
+#: commands/tablecmds.c:13026
+#, fuzzy, c-format
+#| msgid "You must specify an operator class for the index or define a default operator class for the data type."
+msgid "You must specify a btree operator class or define a default btree operator class for the data type."
+msgstr "Sie müssen für den Index eine Operatorklasse angeben oder eine Standardoperatorklasse für den Datentyp definieren."
+
+#: commands/tablecmds.c:13073
+#, fuzzy, c-format
+#| msgid "\"%s\" is already a view"
+msgid "\"%s\" is already a partition"
+msgstr "»%s« ist bereits eine Sicht"
+
+#: commands/tablecmds.c:13079
+#, fuzzy, c-format
+#| msgid "cannot add column to typed table"
+msgid "cannot attach a typed table as partition"
+msgstr "zu einer getypten Tabelle kann keine Spalte hinzugefügt werden"
+
+#: commands/tablecmds.c:13095
+#, c-format
+msgid "cannot attach inheritance child as partition"
+msgstr ""
+
+#: commands/tablecmds.c:13109
+#, fuzzy, c-format
+#| msgid "cannot change inheritance of typed table"
+msgid "cannot attach inheritance parent as partition"
+msgstr "Vererbung einer getypten Tabelle kann nicht geändert werden"
+
+#: commands/tablecmds.c:13132
+#, fuzzy, c-format
+#| msgid "cannot inherit from temporary relation \"%s\""
+msgid "cannot attach a permanent relation as partition of temporary relation \"%s\""
+msgstr "von temporärer Relation »%s« kann nicht geerbt werden"
+
+#: commands/tablecmds.c:13140
+#, fuzzy, c-format
+#| msgid "cannot inherit to temporary relation of another session"
+msgid "cannot attach as partition of temporary relation of another session"
+msgstr "an temporäre Relation einer anderen Sitzung kann nicht vererbt werden"
+
+#: commands/tablecmds.c:13147
+#, fuzzy, c-format
+#| msgid "cannot inherit to temporary relation of another session"
+msgid "cannot attach temporary relation of another session as partition"
+msgstr "an temporäre Relation einer anderen Sitzung kann nicht vererbt werden"
+
+#: commands/tablecmds.c:13153
+#, fuzzy, c-format
+#| msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgid "cannot attach table \"%s\" without OIDs as partition of table \"%s\" with OIDs"
+msgstr "Tabelle »%s« ohne OIDs kann nicht von Tabelle »%s« mit OIDs erben"
+
+#: commands/tablecmds.c:13161
+#, fuzzy, c-format
+#| msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgid "cannot attach table \"%s\" with OIDs as partition of table \"%s\" without OIDs"
+msgstr "Tabelle »%s« ohne OIDs kann nicht von Tabelle »%s« mit OIDs erben"
+
+#: commands/tablecmds.c:13183
+#, fuzzy, c-format
+#| msgid "column \"%s\" not found in data type %s"
+msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\""
+msgstr "Spalte »%s« nicht gefunden im Datentyp %s"
+
+#: commands/tablecmds.c:13186
+#, c-format
+msgid "New partition should contain only the columns present in parent."
+msgstr ""
+
+#: commands/tablecmds.c:13358
+#, c-format
+msgid "partition constraint for table \"%s\" is implied by existing constraints"
+msgstr ""
+
#: commands/tablespace.c:162 commands/tablespace.c:179
#: commands/tablespace.c:190 commands/tablespace.c:198
-#: commands/tablespace.c:625 replication/slot.c:970 storage/file/copydir.c:47
+#: commands/tablespace.c:623 replication/slot.c:1017 storage/file/copydir.c:47
#, c-format
msgid "could not create directory \"%s\": %m"
msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m"
@@ -8545,258 +9169,307 @@ msgstr "Tablespace-Pfad »%s« ist zu lang"
msgid "tablespace location should not be inside the data directory"
msgstr "Tablespace-Pfad sollte nicht innerhalb des Datenverzeichnisses sein"
-#: commands/tablespace.c:304 commands/tablespace.c:952
+#: commands/tablespace.c:304 commands/tablespace.c:950
#, c-format
msgid "unacceptable tablespace name \"%s\""
msgstr "inakzeptabler Tablespace-Name »%s«"
-#: commands/tablespace.c:306 commands/tablespace.c:953
+#: commands/tablespace.c:306 commands/tablespace.c:951
#, c-format
msgid "The prefix \"pg_\" is reserved for system tablespaces."
msgstr "Der Präfix »pg_« ist für System-Tablespaces reserviert."
-#: commands/tablespace.c:316 commands/tablespace.c:965
+#: commands/tablespace.c:316 commands/tablespace.c:963
#, c-format
msgid "tablespace \"%s\" already exists"
msgstr "Tablespace »%s« existiert bereits"
-#: commands/tablespace.c:430 commands/tablespace.c:935
-#: commands/tablespace.c:1016 commands/tablespace.c:1085
-#: commands/tablespace.c:1218 commands/tablespace.c:1418
+#: commands/tablespace.c:428 commands/tablespace.c:933
+#: commands/tablespace.c:1013 commands/tablespace.c:1081
+#: commands/tablespace.c:1214 commands/tablespace.c:1414
#, c-format
msgid "tablespace \"%s\" does not exist"
msgstr "Tablespace »%s« existiert nicht"
-#: commands/tablespace.c:436
+#: commands/tablespace.c:434
#, c-format
msgid "tablespace \"%s\" does not exist, skipping"
msgstr "Tablespace »%s« existiert nicht, wird übersprungen"
-#: commands/tablespace.c:512
+#: commands/tablespace.c:510
#, c-format
msgid "tablespace \"%s\" is not empty"
msgstr "Tablespace »%s« ist nicht leer"
-#: commands/tablespace.c:584
+#: commands/tablespace.c:582
#, c-format
msgid "directory \"%s\" does not exist"
msgstr "Verzeichnis »%s« existiert nicht"
-#: commands/tablespace.c:585
+#: commands/tablespace.c:583
#, c-format
msgid "Create this directory for the tablespace before restarting the server."
msgstr "Erzeugen Sie dieses Verzeichnis für den Tablespace bevor Sie den Server neu starten."
-#: commands/tablespace.c:590
+#: commands/tablespace.c:588
#, c-format
msgid "could not set permissions on directory \"%s\": %m"
msgstr "konnte Zugriffsrechte für Verzeichnis »%s« nicht setzen: %m"
-#: commands/tablespace.c:620
+#: commands/tablespace.c:618
#, c-format
msgid "directory \"%s\" already in use as a tablespace"
msgstr "Verzeichnis »%s« ist bereits als Tablespace in Verwendung"
-#: commands/tablespace.c:744 commands/tablespace.c:757
-#: commands/tablespace.c:793 commands/tablespace.c:885
+#: commands/tablespace.c:742 commands/tablespace.c:755
+#: commands/tablespace.c:791 commands/tablespace.c:883
#, c-format
msgid "could not remove directory \"%s\": %m"
msgstr "konnte Verzeichnis »%s« nicht löschen: %m"
-#: commands/tablespace.c:806 commands/tablespace.c:894
+#: commands/tablespace.c:804 commands/tablespace.c:892
#, c-format
msgid "could not remove symbolic link \"%s\": %m"
msgstr "konnte symbolische Verknüpfung »%s« nicht löschen: %m"
-#: commands/tablespace.c:816 commands/tablespace.c:903
+#: commands/tablespace.c:814 commands/tablespace.c:901
#, c-format
msgid "\"%s\" is not a directory or symbolic link"
msgstr "»%s« ist kein Verzeichnis oder symbolische Verknüpfung"
-#: commands/tablespace.c:1090
+#: commands/tablespace.c:1086
#, c-format
msgid "Tablespace \"%s\" does not exist."
msgstr "Tablespace »%s« existiert nicht."
-#: commands/tablespace.c:1517
+#: commands/tablespace.c:1513
#, c-format
msgid "directories for tablespace %u could not be removed"
msgstr "Verzeichnisse für Tablespace %u konnten nicht entfernt werden"
-#: commands/tablespace.c:1519
+#: commands/tablespace.c:1515
#, c-format
msgid "You can remove the directories manually if necessary."
msgstr "Sie können die Verzeichnisse falls nötig manuell entfernen."
-#: commands/trigger.c:184
+#: commands/trigger.c:187
#, c-format
msgid "\"%s\" is a table"
msgstr "»%s« ist eine Tabelle"
-#: commands/trigger.c:186
+#: commands/trigger.c:189
#, c-format
msgid "Tables cannot have INSTEAD OF triggers."
msgstr "Tabellen können keine INSTEAD OF-Trigger haben."
-#: commands/trigger.c:197 commands/trigger.c:204
+#: commands/trigger.c:194
+#, fuzzy, c-format
+#| msgid "\"%s\" is a partial index"
+msgid "\"%s\" is a partitioned table"
+msgstr "»%s« ist ein partieller Index"
+
+#: commands/trigger.c:196
+#, fuzzy, c-format
+#| msgid "Foreign tables cannot have TRUNCATE triggers."
+msgid "Partitioned tables cannot have ROW triggers."
+msgstr "Fremdtabellen können keine TRUNCATE-Trigger haben."
+
+#: commands/trigger.c:207 commands/trigger.c:214
#, c-format
msgid "\"%s\" is a view"
msgstr "»%s« ist eine Sicht"
-#: commands/trigger.c:199
+#: commands/trigger.c:209
#, c-format
msgid "Views cannot have row-level BEFORE or AFTER triggers."
msgstr "Sichten können keine BEFORE- oder AFTER-Trigger auf Zeilenebene haben."
-#: commands/trigger.c:206
+#: commands/trigger.c:216
#, c-format
msgid "Views cannot have TRUNCATE triggers."
msgstr "Sichten können keine TRUNCATE-Trigger haben."
-#: commands/trigger.c:214 commands/trigger.c:221 commands/trigger.c:228
+#: commands/trigger.c:224 commands/trigger.c:231 commands/trigger.c:238
#, c-format
msgid "\"%s\" is a foreign table"
msgstr "»%s« ist eine Fremdtabelle"
-#: commands/trigger.c:216
+#: commands/trigger.c:226
#, c-format
msgid "Foreign tables cannot have INSTEAD OF triggers."
msgstr "Fremdtabellen können keine INSTEAD OF-Trigger haben."
-#: commands/trigger.c:223
+#: commands/trigger.c:233
#, c-format
msgid "Foreign tables cannot have TRUNCATE triggers."
msgstr "Fremdtabellen können keine TRUNCATE-Trigger haben."
-#: commands/trigger.c:230
+#: commands/trigger.c:240
#, c-format
msgid "Foreign tables cannot have constraint triggers."
msgstr "Fremdtabellen können keine Constraint-Trigger haben."
-#: commands/trigger.c:293
+#: commands/trigger.c:303
#, c-format
msgid "TRUNCATE FOR EACH ROW triggers are not supported"
msgstr "TRUNCATE FOR EACH ROW-Trigger werden nicht unterstützt"
-#: commands/trigger.c:301
+#: commands/trigger.c:311
#, c-format
msgid "INSTEAD OF triggers must be FOR EACH ROW"
msgstr "INSTEAD OF-Trigger müssen FOR EACH ROW sein"
-#: commands/trigger.c:305
+#: commands/trigger.c:315
#, c-format
msgid "INSTEAD OF triggers cannot have WHEN conditions"
msgstr "INSTEAD OF-Trigger können keine WHEN-Bedingungen haben"
-#: commands/trigger.c:309
+#: commands/trigger.c:319
#, c-format
msgid "INSTEAD OF triggers cannot have column lists"
msgstr "INSTEAD OF-Trigger können keine Spaltenlisten haben"
-#: commands/trigger.c:366 commands/trigger.c:379
+#: commands/trigger.c:348
+#, fuzzy, c-format
+#| msgid "using variable \"%s\" in different declare statements is not supported"
+msgid "ROW variable naming in the REFERENCING clause is not supported"
+msgstr "Verwendung der Variable »%s« in verschiedenen DECLARE-Anweisungen wird nicht unterstützt"
+
+#: commands/trigger.c:349
+#, c-format
+msgid "Use OLD TABLE or NEW TABLE for naming transition tables."
+msgstr ""
+
+#: commands/trigger.c:360
+#, fuzzy, c-format
+#| msgid "%s: transaction log directory location can only be specified in plain mode\n"
+msgid "transition table name can only be specified for an AFTER trigger"
+msgstr "%s: Transaktionslogverzeichnis kann nur im »plain«-Modus angegeben werden\n"
+
+#: commands/trigger.c:368
+#, c-format
+msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger"
+msgstr ""
+
+#: commands/trigger.c:373
+#, c-format
+msgid "NEW TABLE cannot be specified multiple times"
+msgstr ""
+
+#: commands/trigger.c:383
+#, c-format
+msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger"
+msgstr ""
+
+#: commands/trigger.c:388
+#, c-format
+msgid "OLD TABLE cannot be specified multiple times"
+msgstr ""
+
+#: commands/trigger.c:398
+#, c-format
+msgid "OLD TABLE name and NEW TABLE name cannot be the same"
+msgstr ""
+
+#: commands/trigger.c:455 commands/trigger.c:468
#, c-format
msgid "statement trigger's WHEN condition cannot reference column values"
msgstr "WHEN-Bedingung eines Statement-Triggers kann keine Verweise auf Spaltenwerte enthalten"
-#: commands/trigger.c:371
+#: commands/trigger.c:460
#, c-format
msgid "INSERT trigger's WHEN condition cannot reference OLD values"
msgstr "WHEN-Bedingung eines INSERT-Triggers kann keine Verweise auf OLD-Werte enthalten"
-#: commands/trigger.c:384
+#: commands/trigger.c:473
#, c-format
msgid "DELETE trigger's WHEN condition cannot reference NEW values"
msgstr "WHEN-Bedingung eines DELETE-Triggers kann keine Verweise auf NEW-Werte enthalten"
-#: commands/trigger.c:389
+#: commands/trigger.c:478
#, c-format
msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns"
msgstr "WHEN-Bedingung eines BEFORE-Triggers kann keine Verweise auf Systemspalten in NEW enthalten"
-#: commands/trigger.c:434
-#, c-format
-msgid "changing return type of function %s from \"opaque\" to \"trigger\""
-msgstr "ändere Rückgabetyp von Funktion %s von »opaque« in »trigger«"
-
-#: commands/trigger.c:553 commands/trigger.c:1303
+#: commands/trigger.c:643 commands/trigger.c:1414
#, c-format
msgid "trigger \"%s\" for relation \"%s\" already exists"
msgstr "Trigger »%s« für Relation »%s« existiert bereits"
-#: commands/trigger.c:838
+#: commands/trigger.c:939
msgid "Found referenced table's UPDATE trigger."
msgstr "UPDATE-Trigger der Zieltabelle wurde gefunden."
-#: commands/trigger.c:839
+#: commands/trigger.c:940
msgid "Found referenced table's DELETE trigger."
msgstr "DELETE-Trigger der Zieltabelle wurde gefunden."
-#: commands/trigger.c:840
+#: commands/trigger.c:941
msgid "Found referencing table's trigger."
msgstr "Trigger der Quelltabelle wurde gefunden."
-#: commands/trigger.c:949 commands/trigger.c:965
+#: commands/trigger.c:1050 commands/trigger.c:1066
#, c-format
msgid "ignoring incomplete trigger group for constraint \"%s\" %s"
msgstr "unvollständige Triggergruppe für Constraint \"%s\" %s ignoriert"
-#: commands/trigger.c:977
+#: commands/trigger.c:1079
#, c-format
msgid "converting trigger group into constraint \"%s\" %s"
msgstr "Triggergruppe wird in Constraint \"%s\" %s umgewandelt"
-#: commands/trigger.c:1190 commands/trigger.c:1351 commands/trigger.c:1469
+#: commands/trigger.c:1300 commands/trigger.c:1459 commands/trigger.c:1574
#, c-format
msgid "trigger \"%s\" for table \"%s\" does not exist"
msgstr "Trigger »%s« für Tabelle »%s« existiert nicht"
-#: commands/trigger.c:1434
+#: commands/trigger.c:1542
#, c-format
msgid "permission denied: \"%s\" is a system trigger"
msgstr "keine Berechtigung: »%s« ist ein Systemtrigger"
-#: commands/trigger.c:1930
+#: commands/trigger.c:2097
#, c-format
msgid "trigger function %u returned null value"
msgstr "Triggerfunktion %u gab NULL-Wert zurück"
-#: commands/trigger.c:1989 commands/trigger.c:2188 commands/trigger.c:2392
-#: commands/trigger.c:2664
+#: commands/trigger.c:2158 commands/trigger.c:2364 commands/trigger.c:2575
+#: commands/trigger.c:2854
#, c-format
msgid "BEFORE STATEMENT trigger cannot return a value"
msgstr "Trigger für BEFORE STATEMENT kann keinen Wert zurückgeben"
-#: commands/trigger.c:2726 executor/nodeModifyTable.c:664
-#: executor/nodeModifyTable.c:957
+#: commands/trigger.c:2916 executor/nodeModifyTable.c:746
+#: executor/nodeModifyTable.c:1041
#, c-format
msgid "tuple to be updated was already modified by an operation triggered by the current command"
msgstr "das zu aktualisierende Tupel wurde schon durch eine vom aktuellen Befehl ausgelöste Operation verändert"
-#: commands/trigger.c:2727 executor/nodeModifyTable.c:665
-#: executor/nodeModifyTable.c:958
+#: commands/trigger.c:2917 executor/nodeModifyTable.c:747
+#: executor/nodeModifyTable.c:1042
#, c-format
msgid "Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows."
msgstr "Verwenden Sie einen AFTER-Trigger anstelle eines BEFORE-Triggers, um Änderungen an andere Zeilen zu propagieren."
-#: commands/trigger.c:2741 executor/execMain.c:2377
-#: executor/nodeLockRows.c:216 executor/nodeModifyTable.c:200
-#: executor/nodeModifyTable.c:677 executor/nodeModifyTable.c:970
-#: executor/nodeModifyTable.c:1136
+#: commands/trigger.c:2931 executor/execMain.c:2526
+#: executor/nodeLockRows.c:216 executor/nodeModifyTable.c:213
+#: executor/nodeModifyTable.c:759 executor/nodeModifyTable.c:1054
+#: executor/nodeModifyTable.c:1220
#, c-format
msgid "could not serialize access due to concurrent update"
msgstr "kann Zugriff nicht serialisieren wegen gleichzeitiger Aktualisierung"
-#: commands/trigger.c:4579
+#: commands/trigger.c:4834
#, c-format
msgid "constraint \"%s\" is not deferrable"
msgstr "Constraint »%s« ist nicht aufschiebbar"
-#: commands/trigger.c:4602
+#: commands/trigger.c:4857
#, c-format
msgid "constraint \"%s\" does not exist"
msgstr "Constraint »%s« existiert nicht"
-#: commands/tsearchcmds.c:115 commands/tsearchcmds.c:685
+#: commands/tsearchcmds.c:115 commands/tsearchcmds.c:679
#, c-format
msgid "function %s should return type %s"
msgstr "Function %s sollte Rückgabetyp %s haben"
@@ -8831,675 +9504,672 @@ msgstr "Textsucheparserendemethode muss angegeben werden"
msgid "text search parser lextypes method is required"
msgstr "Lextypes-Methode für Textsucheparser muss angegeben werden"
-#: commands/tsearchcmds.c:386
+#: commands/tsearchcmds.c:384
#, c-format
msgid "text search template \"%s\" does not accept options"
msgstr "Textsuchevorlage »%s« akzeptiert keine Optionen"
-#: commands/tsearchcmds.c:460
+#: commands/tsearchcmds.c:458
#, c-format
msgid "text search template is required"
msgstr "Textsuchevorlage muss angegeben werden"
-#: commands/tsearchcmds.c:752
+#: commands/tsearchcmds.c:746
#, c-format
msgid "must be superuser to create text search templates"
msgstr "nur Superuser können Textsuchevorlagen erzeugen"
-#: commands/tsearchcmds.c:789
+#: commands/tsearchcmds.c:783
#, c-format
msgid "text search template parameter \"%s\" not recognized"
msgstr "Textsuchevorlageparameter »%s« nicht erkannt"
-#: commands/tsearchcmds.c:799
+#: commands/tsearchcmds.c:793
#, c-format
msgid "text search template lexize method is required"
msgstr "Lexize-Methode für Textsuchevorlage muss angegeben werden"
-#: commands/tsearchcmds.c:1008
+#: commands/tsearchcmds.c:1000
#, c-format
msgid "text search configuration parameter \"%s\" not recognized"
msgstr "Textsuchekonfigurationsparameter »%s« nicht erkannt"
-#: commands/tsearchcmds.c:1015
+#: commands/tsearchcmds.c:1007
#, c-format
msgid "cannot specify both PARSER and COPY options"
msgstr "Optionen PARSER und COPY können nicht beide angegeben werden"
-#: commands/tsearchcmds.c:1051
+#: commands/tsearchcmds.c:1043
#, c-format
msgid "text search parser is required"
msgstr "Textsucheparser muss angegeben werden"
-#: commands/tsearchcmds.c:1278
+#: commands/tsearchcmds.c:1266
#, c-format
msgid "token type \"%s\" does not exist"
msgstr "Tokentyp »%s« existiert nicht"
-#: commands/tsearchcmds.c:1502
+#: commands/tsearchcmds.c:1487
#, c-format
msgid "mapping for token type \"%s\" does not exist"
msgstr "Mapping für Tokentyp »%s« existiert nicht"
-#: commands/tsearchcmds.c:1508
+#: commands/tsearchcmds.c:1493
#, c-format
msgid "mapping for token type \"%s\" does not exist, skipping"
msgstr "Mapping für Tokentyp »%s« existiert nicht, wird übersprungen"
-#: commands/tsearchcmds.c:1663 commands/tsearchcmds.c:1774
+#: commands/tsearchcmds.c:1648 commands/tsearchcmds.c:1759
#, c-format
msgid "invalid parameter list format: \"%s\""
msgstr "ungültiges Parameterlistenformat: »%s«"
-#: commands/typecmds.c:181
+#: commands/typecmds.c:183
#, c-format
msgid "must be superuser to create a base type"
msgstr "nur Superuser können Basistypen anlegen"
-#: commands/typecmds.c:288 commands/typecmds.c:1421
+#: commands/typecmds.c:290 commands/typecmds.c:1414
#, c-format
msgid "type attribute \"%s\" not recognized"
msgstr "Typ-Attribut »%s« nicht erkannt"
-#: commands/typecmds.c:342
+#: commands/typecmds.c:346
#, c-format
msgid "invalid type category \"%s\": must be simple ASCII"
msgstr "ungültige Typenkategorie »%s«: muss einfacher ASCII-Wert sein"
-#: commands/typecmds.c:361
+#: commands/typecmds.c:365
#, c-format
msgid "array element type cannot be %s"
msgstr "Arrayelementtyp kann nicht %s sein"
-#: commands/typecmds.c:393
+#: commands/typecmds.c:397
#, c-format
msgid "alignment \"%s\" not recognized"
msgstr "Ausrichtung »%s« nicht erkannt"
-#: commands/typecmds.c:410
+#: commands/typecmds.c:414
#, c-format
msgid "storage \"%s\" not recognized"
msgstr "Storage-Typ »%s« nicht erkannt"
-#: commands/typecmds.c:421
+#: commands/typecmds.c:425
#, c-format
msgid "type input function must be specified"
msgstr "Typeingabefunktion muss angegeben werden"
-#: commands/typecmds.c:425
+#: commands/typecmds.c:429
#, c-format
msgid "type output function must be specified"
msgstr "Typausgabefunktion muss angegeben werden"
-#: commands/typecmds.c:430
+#: commands/typecmds.c:434
#, c-format
msgid "type modifier output function is useless without a type modifier input function"
msgstr "Typmodifikatorausgabefunktion ist nutzlos ohne Typmodifikatoreingabefunktion"
-#: commands/typecmds.c:453 commands/typecmds.c:470
-#, c-format
-msgid "changing return type of function %s from %s to %s"
-msgstr "ändere Rückgabetyp von Funktion %s von %s in %s"
-
-#: commands/typecmds.c:460
+#: commands/typecmds.c:464
#, c-format
msgid "type input function %s must return type %s"
msgstr "Typeingabefunktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:477
+#: commands/typecmds.c:481
#, c-format
msgid "type output function %s must return type %s"
msgstr "Typausgabefunktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:486
+#: commands/typecmds.c:490
#, c-format
msgid "type receive function %s must return type %s"
msgstr "Typempfangsfunktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:495
+#: commands/typecmds.c:499
#, c-format
msgid "type send function %s must return type %s"
msgstr "Typsendefunktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:560
+#: commands/typecmds.c:564
#, c-format
msgid "type input function %s should not be volatile"
msgstr "Typeingabefunktion %s sollte nicht VOLATILE sein"
-#: commands/typecmds.c:565
+#: commands/typecmds.c:569
#, c-format
msgid "type output function %s should not be volatile"
msgstr "Typausgabefunktion %s sollte nicht VOLATILE sein"
-#: commands/typecmds.c:570
+#: commands/typecmds.c:574
#, c-format
msgid "type receive function %s should not be volatile"
msgstr "Typempfangsfunktion %s sollte nicht VOLATILE sein"
-#: commands/typecmds.c:575
+#: commands/typecmds.c:579
#, c-format
msgid "type send function %s should not be volatile"
msgstr "Typsendefunktion %s sollte nicht VOLATILE sein"
-#: commands/typecmds.c:580
+#: commands/typecmds.c:584
#, c-format
msgid "type modifier input function %s should not be volatile"
msgstr "Typmodifikatoreingabefunktion %s sollte nicht VOLATILE sein"
-#: commands/typecmds.c:585
+#: commands/typecmds.c:589
#, c-format
msgid "type modifier output function %s should not be volatile"
msgstr "Typmodifikatorausgabefunktion %s sollte nicht VOLATILE sein"
-#: commands/typecmds.c:807
+#: commands/typecmds.c:811
#, c-format
msgid "\"%s\" is not a valid base type for a domain"
msgstr "»%s« ist kein gültiger Basistyp für eine Domäne"
-#: commands/typecmds.c:893
+#: commands/typecmds.c:897
#, c-format
msgid "multiple default expressions"
msgstr "mehrere Vorgabeausdrücke"
-#: commands/typecmds.c:955 commands/typecmds.c:964
+#: commands/typecmds.c:959 commands/typecmds.c:968
#, c-format
msgid "conflicting NULL/NOT NULL constraints"
msgstr "wiedersprüchliche NULL/NOT NULL-Constraints"
-#: commands/typecmds.c:980
+#: commands/typecmds.c:984
#, c-format
msgid "check constraints for domains cannot be marked NO INHERIT"
msgstr "Check-Constraints für Domänen können nicht als NO INHERIT markiert werden"
-#: commands/typecmds.c:989 commands/typecmds.c:2522
+#: commands/typecmds.c:993 commands/typecmds.c:2512
#, c-format
msgid "unique constraints not possible for domains"
msgstr "Unique-Constraints sind nicht für Domänen möglich"
-#: commands/typecmds.c:995 commands/typecmds.c:2528
+#: commands/typecmds.c:999 commands/typecmds.c:2518
#, c-format
msgid "primary key constraints not possible for domains"
msgstr "Primärschlüssel-Constraints sind nicht fürDomänen möglich"
-#: commands/typecmds.c:1001 commands/typecmds.c:2534
+#: commands/typecmds.c:1005 commands/typecmds.c:2524
#, c-format
msgid "exclusion constraints not possible for domains"
msgstr "Exclusion-Constraints sind nicht für Domänen möglich"
-#: commands/typecmds.c:1007 commands/typecmds.c:2540
+#: commands/typecmds.c:1011 commands/typecmds.c:2530
#, c-format
msgid "foreign key constraints not possible for domains"
msgstr "Fremdschlüssel-Constraints sind nicht für Domänen möglich"
-#: commands/typecmds.c:1016 commands/typecmds.c:2549
+#: commands/typecmds.c:1020 commands/typecmds.c:2539
#, c-format
msgid "specifying constraint deferrability not supported for domains"
msgstr "Setzen des Constraint-Modus wird für Domänen nicht unterstützt"
-#: commands/typecmds.c:1291 utils/cache/typcache.c:1634
+#: commands/typecmds.c:1284 utils/cache/typcache.c:1636
#, c-format
msgid "%s is not an enum"
msgstr "»%s« ist kein Enum"
-#: commands/typecmds.c:1429
+#: commands/typecmds.c:1422
#, c-format
msgid "type attribute \"subtype\" is required"
msgstr "Typ-Attribut »subtype« muss angegeben werden"
-#: commands/typecmds.c:1434
+#: commands/typecmds.c:1427
#, c-format
msgid "range subtype cannot be %s"
msgstr "Bereichtsuntertyp kann nicht %s sein"
-#: commands/typecmds.c:1453
+#: commands/typecmds.c:1446
#, c-format
msgid "range collation specified but subtype does not support collation"
msgstr "Sortierfolge für Bereichstyp angegeben, aber Untertyp unterstützt keine Sortierfolgen"
-#: commands/typecmds.c:1687
+#: commands/typecmds.c:1680
#, c-format
msgid "changing argument type of function %s from \"opaque\" to \"cstring\""
msgstr "ändere Argumenttyp von Funktion %s von »opaque« in »cstring«"
-#: commands/typecmds.c:1738
+#: commands/typecmds.c:1731
#, c-format
msgid "changing argument type of function %s from \"opaque\" to %s"
msgstr "ändere Argumenttyp von Funktion %s von »opaque« in %s"
-#: commands/typecmds.c:1837
+#: commands/typecmds.c:1830
#, c-format
msgid "typmod_in function %s must return type %s"
msgstr "typmod_in-Funktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:1864
+#: commands/typecmds.c:1857
#, c-format
msgid "typmod_out function %s must return type %s"
msgstr "typmod_out-Funktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:1891
+#: commands/typecmds.c:1884
#, c-format
msgid "type analyze function %s must return type %s"
msgstr "Typanalysefunktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:1937
+#: commands/typecmds.c:1930
#, c-format
msgid "You must specify an operator class for the range type or define a default operator class for the subtype."
msgstr "Sie müssen für den Bereichstyp eine Operatorklasse angeben oder eine Standardoperatorklasse für den Untertyp definieren."
-#: commands/typecmds.c:1968
+#: commands/typecmds.c:1961
#, c-format
msgid "range canonical function %s must return range type"
msgstr "Bereichstyp-Canonical-Funktion %s muss Bereichstyp zurückgeben"
-#: commands/typecmds.c:1974
+#: commands/typecmds.c:1967
#, c-format
msgid "range canonical function %s must be immutable"
msgstr "Bereichstyp-Canonical-Funktion %s muss »immutable« sein"
-#: commands/typecmds.c:2010
+#: commands/typecmds.c:2003
#, c-format
msgid "range subtype diff function %s must return type %s"
msgstr "Bereichstyp-Untertyp-Diff-Funktion %s muss Typ %s zurückgeben"
-#: commands/typecmds.c:2017
+#: commands/typecmds.c:2010
#, c-format
msgid "range subtype diff function %s must be immutable"
msgstr "Bereichstyp-Untertyp-Diff-Funktion %s muss »immutable« sein"
-#: commands/typecmds.c:2044
+#: commands/typecmds.c:2037
#, c-format
msgid "pg_type array OID value not set when in binary upgrade mode"
msgstr "Array-OID-Wert für pg_type ist im Binary-Upgrade-Modus nicht gesetzt"
-#: commands/typecmds.c:2348
+#: commands/typecmds.c:2340
#, c-format
msgid "column \"%s\" of table \"%s\" contains null values"
msgstr "Spalte »%s« von Tabelle »%s« enthält NULL-Werte"
-#: commands/typecmds.c:2463 commands/typecmds.c:2646
+#: commands/typecmds.c:2453 commands/typecmds.c:2636
#, c-format
msgid "constraint \"%s\" of domain \"%s\" does not exist"
msgstr "Constraint »%s« von Domäne »%s« existiert nicht"
-#: commands/typecmds.c:2467
+#: commands/typecmds.c:2457
#, c-format
msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping"
msgstr "Constraint »%s« von Domäne »%s« existiert nicht, wird übersprungen"
-#: commands/typecmds.c:2652
+#: commands/typecmds.c:2642
#, c-format
msgid "constraint \"%s\" of domain \"%s\" is not a check constraint"
msgstr "Constraint »%s« von Domäne »%s« ist kein Check-Constraint"
-#: commands/typecmds.c:2758
+#: commands/typecmds.c:2747
#, c-format
msgid "column \"%s\" of table \"%s\" contains values that violate the new constraint"
msgstr "Spalte »%s« von Tabelle »%s« enthält Werte, die den neuen Constraint verletzen"
-#: commands/typecmds.c:2971 commands/typecmds.c:3228 commands/typecmds.c:3417
+#: commands/typecmds.c:2960 commands/typecmds.c:3247 commands/typecmds.c:3434
#, c-format
msgid "%s is not a domain"
msgstr "%s ist keine Domäne"
-#: commands/typecmds.c:3005
+#: commands/typecmds.c:2994
#, c-format
msgid "constraint \"%s\" for domain \"%s\" already exists"
msgstr "Constraint »%s« für Domäne »%s« existiert bereits"
-#: commands/typecmds.c:3055
+#: commands/typecmds.c:3045
#, c-format
msgid "cannot use table references in domain check constraint"
msgstr "Tabellenverweise können in Domänen-Check-Constraints nicht verwendet werden"
-#: commands/typecmds.c:3158 commands/typecmds.c:3240 commands/typecmds.c:3534
+#: commands/typecmds.c:3177 commands/typecmds.c:3259 commands/typecmds.c:3551
#, c-format
msgid "%s is a table's row type"
msgstr "%s ist der Zeilentyp einer Tabelle"
-#: commands/typecmds.c:3160 commands/typecmds.c:3242 commands/typecmds.c:3536
+#: commands/typecmds.c:3179 commands/typecmds.c:3261 commands/typecmds.c:3553
#, c-format
msgid "Use ALTER TABLE instead."
msgstr "Verwenden Sie stattdessen ALTER TABLE."
-#: commands/typecmds.c:3167 commands/typecmds.c:3249 commands/typecmds.c:3449
+#: commands/typecmds.c:3186 commands/typecmds.c:3268 commands/typecmds.c:3466
#, c-format
msgid "cannot alter array type %s"
msgstr "Array-Typ %s kann nicht verändert werden"
-#: commands/typecmds.c:3169 commands/typecmds.c:3251 commands/typecmds.c:3451
+#: commands/typecmds.c:3188 commands/typecmds.c:3270 commands/typecmds.c:3468
#, c-format
msgid "You can alter type %s, which will alter the array type as well."
msgstr "Sie können den Typ %s ändern, wodurch der Array-Typ ebenfalls geändert wird."
-#: commands/typecmds.c:3519
+#: commands/typecmds.c:3536
#, c-format
msgid "type \"%s\" already exists in schema \"%s\""
msgstr "Typ %s existiert bereits in Schema »%s«"
-#: commands/user.c:149
+#: commands/user.c:154
#, c-format
msgid "SYSID can no longer be specified"
msgstr "SYSID kann nicht mehr angegeben werden"
-#: commands/user.c:291
+#: commands/user.c:308
#, c-format
msgid "must be superuser to create superusers"
msgstr "nur Superuser können Superuser anlegen"
-#: commands/user.c:298
+#: commands/user.c:315
#, c-format
msgid "must be superuser to create replication users"
msgstr "nur Superuser können Replikationsbenutzer anlegen"
-#: commands/user.c:305 commands/user.c:693
+#: commands/user.c:322 commands/user.c:708
#, c-format
msgid "must be superuser to change bypassrls attribute"
msgstr "nur Superuser können das Attribut »bypassrls« ändern"
-#: commands/user.c:312
+#: commands/user.c:329
#, c-format
msgid "permission denied to create role"
msgstr "keine Berechtigung, um Rolle zu erzeugen"
-#: commands/user.c:322 commands/user.c:1176 commands/user.c:1183 gram.y:13606
-#: gram.y:13641 utils/adt/acl.c:5279 utils/adt/acl.c:5285
+#: commands/user.c:339 commands/user.c:1183 commands/user.c:1190 gram.y:14233
+#: gram.y:14268 utils/adt/acl.c:5246 utils/adt/acl.c:5252
#, c-format
msgid "role name \"%s\" is reserved"
msgstr "Rollenname »%s« ist reserviert"
-#: commands/user.c:324 commands/user.c:1178 commands/user.c:1185
+#: commands/user.c:341 commands/user.c:1185 commands/user.c:1192
#, c-format
msgid "Role names starting with \"pg_\" are reserved."
msgstr "Rollennamen, die mit »pg_« anfangen, sind reserviert."
-#: commands/user.c:336 commands/user.c:1191
+#: commands/user.c:353 commands/user.c:1198
#, c-format
msgid "role \"%s\" already exists"
msgstr "Rolle »%s« existiert bereits"
-#: commands/user.c:414
+#: commands/user.c:426
#, c-format
msgid "pg_authid OID value not set when in binary upgrade mode"
msgstr "OID-Wert für pg_auth ist im Binary-Upgrade-Modus nicht gesetzt"
-#: commands/user.c:679 commands/user.c:896 commands/user.c:1432
-#: commands/user.c:1578
+#: commands/user.c:694 commands/user.c:903 commands/user.c:1437
+#: commands/user.c:1581
#, c-format
msgid "must be superuser to alter superusers"
msgstr "nur Superuser können Superuser ändern"
-#: commands/user.c:686
+#: commands/user.c:701
#, c-format
msgid "must be superuser to alter replication users"
msgstr "nur Superuser können Replikationsbenutzer ändern"
-#: commands/user.c:709 commands/user.c:904
+#: commands/user.c:724 commands/user.c:911
#, c-format
msgid "permission denied"
msgstr "keine Berechtigung"
-#: commands/user.c:934
+#: commands/user.c:941
#, c-format
msgid "must be superuser to alter settings globally"
msgstr "nur Superuser können globale Einstellungen ändern"
-#: commands/user.c:956
+#: commands/user.c:963
#, c-format
msgid "permission denied to drop role"
msgstr "keine Berechtigung, um Rolle zu entfernen"
-#: commands/user.c:980
+#: commands/user.c:987
#, c-format
msgid "cannot use special role specifier in DROP ROLE"
msgstr "in DROP ROLE kann kein Rollenplatzhalter verwendet werden"
-#: commands/user.c:990 commands/user.c:1147 commands/variable.c:825
-#: commands/variable.c:897 utils/adt/acl.c:5121 utils/adt/acl.c:5173
-#: utils/adt/acl.c:5206 utils/adt/acl.c:5224 utils/init/miscinit.c:502
+#: commands/user.c:997 commands/user.c:1154 commands/variable.c:822
+#: commands/variable.c:894 utils/adt/acl.c:5104 utils/adt/acl.c:5151
+#: utils/adt/acl.c:5179 utils/adt/acl.c:5197 utils/init/miscinit.c:502
#, c-format
msgid "role \"%s\" does not exist"
msgstr "Rolle »%s« existiert nicht"
-#: commands/user.c:995
+#: commands/user.c:1002
#, c-format
msgid "role \"%s\" does not exist, skipping"
msgstr "Rolle »%s« existiert nicht, wird übersprungen"
-#: commands/user.c:1007 commands/user.c:1011
+#: commands/user.c:1014 commands/user.c:1018
#, c-format
msgid "current user cannot be dropped"
msgstr "aktueller Benutzer kann nicht entfernt werden"
-#: commands/user.c:1015
+#: commands/user.c:1022
#, c-format
msgid "session user cannot be dropped"
msgstr "aktueller Sitzungsbenutzer kann nicht entfernt werden"
-#: commands/user.c:1026
+#: commands/user.c:1033
#, c-format
msgid "must be superuser to drop superusers"
msgstr "nur Superuser können Superuser löschen"
-#: commands/user.c:1042
+#: commands/user.c:1049
#, c-format
msgid "role \"%s\" cannot be dropped because some objects depend on it"
msgstr "kann Rolle »%s« nicht löschen, weil andere Objekte davon abhängen"
-#: commands/user.c:1163
+#: commands/user.c:1170
#, c-format
msgid "session user cannot be renamed"
msgstr "aktueller Sitzungsbenutzer kann nicht umbenannt werden"
-#: commands/user.c:1167
+#: commands/user.c:1174
#, c-format
msgid "current user cannot be renamed"
msgstr "aktueller Benutzer kann nicht umbenannt werden"
-#: commands/user.c:1201
+#: commands/user.c:1208
#, c-format
msgid "must be superuser to rename superusers"
msgstr "nur Superuser können Superuser umbenennen"
-#: commands/user.c:1208
+#: commands/user.c:1215
#, c-format
msgid "permission denied to rename role"
msgstr "keine Berechtigung, um Rolle umzubenennen"
-#: commands/user.c:1229
+#: commands/user.c:1236
#, c-format
msgid "MD5 password cleared because of role rename"
msgstr "MD5-Passwort wegen Rollenumbenennung gelöscht"
-#: commands/user.c:1291
+#: commands/user.c:1296
#, c-format
msgid "column names cannot be included in GRANT/REVOKE ROLE"
msgstr "bei GRANT/REVOKE ROLE können keine Spaltennamen angegeben werden"
-#: commands/user.c:1329
+#: commands/user.c:1334
#, c-format
msgid "permission denied to drop objects"
msgstr "keine Berechtigung, um Objekte zu löschen"
-#: commands/user.c:1356 commands/user.c:1365
+#: commands/user.c:1361 commands/user.c:1370
#, c-format
msgid "permission denied to reassign objects"
msgstr "keine Berechtigung, um Objekte neu zuzuordnen"
-#: commands/user.c:1440 commands/user.c:1586
+#: commands/user.c:1445 commands/user.c:1589
#, c-format
msgid "must have admin option on role \"%s\""
msgstr "Admin-Option für Rolle »%s« wird benötigt"
-#: commands/user.c:1457
+#: commands/user.c:1462
#, c-format
msgid "must be superuser to set grantor"
msgstr "nur Superuser können Grantor setzen"
-#: commands/user.c:1482
+#: commands/user.c:1487
#, c-format
msgid "role \"%s\" is a member of role \"%s\""
msgstr "Rolle »%s« ist ein Mitglied der Rolle »%s«"
-#: commands/user.c:1497
+#: commands/user.c:1502
#, c-format
msgid "role \"%s\" is already a member of role \"%s\""
msgstr "Rolle »%s« ist schon Mitglied der Rolle »%s«"
-#: commands/user.c:1608
+#: commands/user.c:1611
#, c-format
msgid "role \"%s\" is not a member of role \"%s\""
msgstr "Rolle »%s« ist kein Mitglied der Rolle »%s«"
-#: commands/vacuum.c:185
+#: commands/vacuum.c:186
#, c-format
msgid "%s cannot be executed from VACUUM or ANALYZE"
msgstr "%s kann nicht aus VACUUM oder ANALYZE ausgeführt werden"
-#: commands/vacuum.c:195
+#: commands/vacuum.c:196
#, c-format
msgid "VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL"
msgstr "VACUUM-Option DISABLE_PAGE_SKIPPING kann nicht zusammen mit FULL verwendet werden"
-#: commands/vacuum.c:537
+#: commands/vacuum.c:565
#, c-format
msgid "oldest xmin is far in the past"
msgstr "älteste xmin ist weit in der Vergangenheit"
-#: commands/vacuum.c:538
+#: commands/vacuum.c:566
#, c-format
msgid "Close open transactions soon to avoid wraparound problems."
msgstr "Schließen Sie bald alle offenen Transaktionen, um Überlaufprobleme zu vermeiden."
-#: commands/vacuum.c:577
+#: commands/vacuum.c:605
#, c-format
msgid "oldest multixact is far in the past"
msgstr "älteste Multixact ist weit in der Vergangenheit"
-#: commands/vacuum.c:578
+#: commands/vacuum.c:606
#, c-format
msgid "Close open transactions with multixacts soon to avoid wraparound problems."
msgstr "Schließen Sie bald alle offenen Transaktionen mit Multixacts, um Überlaufprobleme zu vermeiden."
-#: commands/vacuum.c:1148
+#: commands/vacuum.c:1176
#, c-format
msgid "some databases have not been vacuumed in over 2 billion transactions"
msgstr "einige Datenbanken sind seit über 2 Milliarden Transaktionen nicht gevacuumt worden"
-#: commands/vacuum.c:1149
+#: commands/vacuum.c:1177
#, c-format
msgid "You might have already suffered transaction-wraparound data loss."
msgstr "Sie haben möglicherweise bereits Daten wegen Transaktionsnummernüberlauf verloren."
-#: commands/vacuum.c:1270
+#: commands/vacuum.c:1306
#, c-format
msgid "skipping vacuum of \"%s\" --- lock not available"
msgstr "überspringe Vacuum von »%s« --- Sperre nicht verfügbar"
-#: commands/vacuum.c:1296
+#: commands/vacuum.c:1332
#, c-format
msgid "skipping \"%s\" --- only superuser can vacuum it"
msgstr "überspringe »%s« --- nur Superuser kann sie vacuumen"
-#: commands/vacuum.c:1300
+#: commands/vacuum.c:1336
#, c-format
msgid "skipping \"%s\" --- only superuser or database owner can vacuum it"
msgstr "überspringe »%s« --- nur Superuser oder Eigentümer der Datenbank kann sie vacuumen"
-#: commands/vacuum.c:1304
+#: commands/vacuum.c:1340
#, c-format
msgid "skipping \"%s\" --- only table or database owner can vacuum it"
msgstr "überspringe »%s« --- nur Eigentümer der Tabelle oder der Datenbank kann sie vacuumen"
-#: commands/vacuum.c:1322
+#: commands/vacuum.c:1359
#, c-format
msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables"
msgstr "überspringe »%s« --- kann Nicht-Tabellen oder besondere Systemtabellen nicht vacuumen"
-#: commands/vacuumlazy.c:366
+#: commands/vacuumlazy.c:372
#, c-format
msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"
msgstr "automatisches Vacuum der Tabelle »%s.%s.%s«: Index-Scans: %d\n"
-#: commands/vacuumlazy.c:371
+#: commands/vacuumlazy.c:377
#, c-format
msgid "pages: %u removed, %u remain, %u skipped due to pins, %u skipped frozen\n"
msgstr "Seiten: %u entfernt, %u verbleiben, %u übersprungen wegen Pins, %u übersprungen weil eingefroren\n"
-#: commands/vacuumlazy.c:377
-#, c-format
-msgid "tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"
+#: commands/vacuumlazy.c:383
+#, fuzzy, c-format
+#| msgid "tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"
+msgid "tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable, oldest xmin: %u\n"
msgstr "Tupel: %.0f entfernt, %.0f verbleiben, %.0f sind tot aber noch nicht entfernbar\n"
-#: commands/vacuumlazy.c:382
+#: commands/vacuumlazy.c:389
#, c-format
msgid "buffer usage: %d hits, %d misses, %d dirtied\n"
msgstr "Puffer-Verwendung: %d Treffer, %d Verfehlen, %d geändert\n"
-#: commands/vacuumlazy.c:386
+#: commands/vacuumlazy.c:393
#, c-format
msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"
msgstr "durchschn. Leserate: %.3f MB/s, durchschn. Schreibrate: %.3f MB/s\n"
-#: commands/vacuumlazy.c:388
+#: commands/vacuumlazy.c:395
#, c-format
msgid "system usage: %s"
msgstr "Systembenutzung: %s"
-#: commands/vacuumlazy.c:846
+#: commands/vacuumlazy.c:853
#, c-format
msgid "relation \"%s\" page %u is uninitialized --- fixing"
msgstr "Seite %2$u in Relation »%1$s« ist nicht initialisiert --- wird repariert"
-#: commands/vacuumlazy.c:1316
+#: commands/vacuumlazy.c:1323
#, c-format
msgid "\"%s\": removed %.0f row versions in %u pages"
msgstr "»%s«: %.0f Zeilenversionen in %u Seiten entfernt"
-#: commands/vacuumlazy.c:1326
-#, c-format
-msgid "%.0f dead row versions cannot be removed yet.\n"
+#: commands/vacuumlazy.c:1333
+#, fuzzy, c-format
+#| msgid "%.0f dead row versions cannot be removed yet.\n"
+msgid "%.0f dead row versions cannot be removed yet, oldest xmin: %u\n"
msgstr "%.0f tote Zeilenversionen können noch nicht entfernt werden.\n"
-#: commands/vacuumlazy.c:1328
+#: commands/vacuumlazy.c:1335
#, c-format
msgid "There were %.0f unused item pointers.\n"
msgstr "Es gab %.0f unbenutzte Itemzeiger.\n"
-#: commands/vacuumlazy.c:1330
+#: commands/vacuumlazy.c:1337
#, c-format
msgid "Skipped %u page due to buffer pins.\n"
msgid_plural "Skipped %u pages due to buffer pins.\n"
msgstr[0] "%u Seite wegen Buffer-Pins übersprungen.\n"
msgstr[1] "%u Seiten wegen Buffer-Pins übersprungen.\n"
-#: commands/vacuumlazy.c:1334
+#: commands/vacuumlazy.c:1341
#, c-format
msgid "%u page is entirely empty.\n"
msgid_plural "%u pages are entirely empty.\n"
msgstr[0] "%u Seite ist vollkommen leer.\n"
msgstr[1] "%u Seiten sind vollkommen leer.\n"
-#: commands/vacuumlazy.c:1342
+#: commands/vacuumlazy.c:1349
#, c-format
msgid "\"%s\": found %.0f removable, %.0f nonremovable row versions in %u out of %u pages"
msgstr "»%s«: %.0f entfernbare, %.0f nicht entfernbare Zeilenversionen in %u von %u Seiten gefunden"
-#: commands/vacuumlazy.c:1411
+#: commands/vacuumlazy.c:1418
#, c-format
msgid "\"%s\": removed %d row versions in %d pages"
msgstr "»%s«: %d Zeilenversionen in %d Seiten entfernt"
-#: commands/vacuumlazy.c:1600
+#: commands/vacuumlazy.c:1607
#, c-format
msgid "scanned index \"%s\" to remove %d row versions"
msgstr "Index »%s« gelesen und %d Zeilenversionen entfernt"
-#: commands/vacuumlazy.c:1646
+#: commands/vacuumlazy.c:1653
#, c-format
msgid "index \"%s\" now contains %.0f row versions in %u pages"
msgstr "Index »%s« enthält %.0f Zeilenversionen in %u Seiten"
-#: commands/vacuumlazy.c:1650
+#: commands/vacuumlazy.c:1657
#, c-format
msgid ""
"%.0f index row versions were removed.\n"
@@ -9510,117 +10180,117 @@ msgstr ""
"%u Indexseiten wurden gelöscht, %u sind gegenwärtig wiederverwendbar.\n"
"%s."
-#: commands/vacuumlazy.c:1745
+#: commands/vacuumlazy.c:1752
#, c-format
msgid "\"%s\": stopping truncate due to conflicting lock request"
msgstr "»%s«: Truncate wird gestoppt wegen Sperrkonflikt"
-#: commands/vacuumlazy.c:1810
+#: commands/vacuumlazy.c:1817
#, c-format
msgid "\"%s\": truncated %u to %u pages"
msgstr "»%s«: von %u auf %u Seiten verkürzt"
-#: commands/vacuumlazy.c:1866
+#: commands/vacuumlazy.c:1882
#, c-format
msgid "\"%s\": suspending truncate due to conflicting lock request"
msgstr "»%s«: Truncate wird ausgesetzt wegen Sperrkonflikt"
-#: commands/variable.c:164 utils/misc/guc.c:9879
+#: commands/variable.c:165 utils/misc/guc.c:9982 utils/misc/guc.c:10044
#, c-format
msgid "Unrecognized key word: \"%s\"."
msgstr "Unbekanntes Schlüsselwort: »%s«."
-#: commands/variable.c:176
+#: commands/variable.c:177
#, c-format
msgid "Conflicting \"datestyle\" specifications."
msgstr "Widersprüchliche »datestyle«-Angaben."
-#: commands/variable.c:298
+#: commands/variable.c:299
#, c-format
msgid "Cannot specify months in time zone interval."
msgstr "Im Zeitzonenintervall können keine Monate angegeben werden."
-#: commands/variable.c:304
+#: commands/variable.c:305
#, c-format
msgid "Cannot specify days in time zone interval."
msgstr "Im Zeitzonenintervall können keine Tage angegeben werden."
-#: commands/variable.c:346 commands/variable.c:428
+#: commands/variable.c:343 commands/variable.c:425
#, c-format
msgid "time zone \"%s\" appears to use leap seconds"
msgstr "Zeitzone »%s« verwendet anscheinend Schaltsekunden"
-#: commands/variable.c:348 commands/variable.c:430
+#: commands/variable.c:345 commands/variable.c:427
#, c-format
msgid "PostgreSQL does not support leap seconds."
msgstr "PostgreSQL unterstützt keine Schaltsekunden."
-#: commands/variable.c:357
+#: commands/variable.c:354
#, c-format
msgid "UTC timezone offset is out of range."
msgstr "Zeitzonenabstand zu UTC ist außerhalb des gültigen Bereichs."
-#: commands/variable.c:497
+#: commands/variable.c:494
#, c-format
msgid "cannot set transaction read-write mode inside a read-only transaction"
msgstr "kann den Read/Write-Modus einer Transaktion nicht in einer Read-Only-Transaktion setzen"
-#: commands/variable.c:504
+#: commands/variable.c:501
#, c-format
msgid "transaction read-write mode must be set before any query"
msgstr "Read/Write-Modus einer Transaktion muss vor allen Anfragen gesetzt werden"
-#: commands/variable.c:511
+#: commands/variable.c:508
#, c-format
msgid "cannot set transaction read-write mode during recovery"
msgstr "kann den Read/Write-Modus einer Transaktion nicht während der Wiederherstellung setzen"
-#: commands/variable.c:560
+#: commands/variable.c:557
#, c-format
msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query"
msgstr "SET TRANSACTION ISOLATION LEVEL muss vor allen Anfragen aufgerufen werden"
-#: commands/variable.c:567
+#: commands/variable.c:564
#, c-format
msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction"
msgstr "SET TRANSACTION ISOLATION LEVEL kann nicht in einer Subtransaktion aufgerufen werden"
-#: commands/variable.c:574 storage/lmgr/predicate.c:1587
+#: commands/variable.c:571 storage/lmgr/predicate.c:1576
#, c-format
msgid "cannot use serializable mode in a hot standby"
msgstr "kann serialisierbaren Modus nicht in einem Hot Standby verwenden"
-#: commands/variable.c:575
+#: commands/variable.c:572
#, c-format
msgid "You can use REPEATABLE READ instead."
msgstr "Sie können stattdessen REPEATABLE READ verwenden."
-#: commands/variable.c:623
+#: commands/variable.c:620
#, c-format
msgid "SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction"
msgstr "SET TRANSACTION [NOT] DEFERRABLE kann nicht in einer Subtransaktion aufgerufen werden"
-#: commands/variable.c:629
+#: commands/variable.c:626
#, c-format
msgid "SET TRANSACTION [NOT] DEFERRABLE must be called before any query"
msgstr "SET TRANSACTION [NOT] DEFERRABLE muss vor allen Anfragen aufgerufen werden"
-#: commands/variable.c:711
+#: commands/variable.c:708
#, c-format
msgid "Conversion between %s and %s is not supported."
msgstr "Umwandlung zwischen %s und %s wird nicht unterstützt."
-#: commands/variable.c:718
+#: commands/variable.c:715
#, c-format
msgid "Cannot change \"client_encoding\" now."
msgstr "»client_encoding« kann jetzt nicht geändert werden."
-#: commands/variable.c:779
+#: commands/variable.c:776
#, c-format
msgid "cannot change client_encoding in a parallel worker"
msgstr "client_encoding kann nicht in einem parallelen Arbeitsprozess geändert werden"
-#: commands/variable.c:915
+#: commands/variable.c:912
#, c-format
msgid "permission denied to set role \"%s\""
msgstr "keine Berechtigung, um Rolle »%s« zu setzen"
@@ -9635,52 +10305,52 @@ msgstr "ungültiger Wert für Option »check_option«"
msgid "Valid values are \"local\" and \"cascaded\"."
msgstr "Gültige Werte sind »local« und »cascaded«."
-#: commands/view.c:103
+#: commands/view.c:101
#, c-format
msgid "could not determine which collation to use for view column \"%s\""
msgstr "konnte die für die Sichtspalte »%s« zu verwendende Sortierfolge nicht bestimmen"
-#: commands/view.c:117
+#: commands/view.c:115
#, c-format
msgid "view must have at least one column"
msgstr "Sicht muss mindestens eine Spalte haben"
-#: commands/view.c:251 commands/view.c:263
+#: commands/view.c:281 commands/view.c:293
#, c-format
msgid "cannot drop columns from view"
msgstr "aus einer Sicht können keine Spalten gelöscht werden"
-#: commands/view.c:268
+#: commands/view.c:298
#, c-format
msgid "cannot change name of view column \"%s\" to \"%s\""
msgstr "kann Namen der Sichtspalte »%s« nicht in »%s« ändern"
-#: commands/view.c:276
+#: commands/view.c:306
#, c-format
msgid "cannot change data type of view column \"%s\" from %s to %s"
msgstr "kann Datentyp der Sichtspalte »%s« nicht von %s in %s ändern"
-#: commands/view.c:415
+#: commands/view.c:451
#, c-format
msgid "views must not contain SELECT INTO"
msgstr "Sichten dürfen kein SELECT INTO enthalten"
-#: commands/view.c:428
+#: commands/view.c:463
#, c-format
msgid "views must not contain data-modifying statements in WITH"
msgstr "Sichten dürfen keine datenmodifizierenden Anweisungen in WITH enthalten"
-#: commands/view.c:499
+#: commands/view.c:533
#, c-format
msgid "CREATE VIEW specifies more column names than columns"
msgstr "CREATE VIEW gibt mehr Spaltennamen als Spalten an"
-#: commands/view.c:507
+#: commands/view.c:541
#, c-format
msgid "views cannot be unlogged because they do not have storage"
msgstr "Sichten können nicht ungeloggt sein, weil sie keinen Speicherplatz verwenden"
-#: commands/view.c:521
+#: commands/view.c:555
#, c-format
msgid "view \"%s\" will be a temporary view"
msgstr "Sicht »%s« wird eine temporäre Sicht"
@@ -9715,372 +10385,392 @@ msgstr "Cursor »%s« ist nicht auf eine Zeile positioniert"
msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\""
msgstr "Cursor »%s« ist kein einfach aktualisierbarer Scan der Tabelle »%s«"
-#: executor/execCurrent.c:231 executor/execQual.c:1178
+#: executor/execCurrent.c:231 executor/execQual.c:1128
#, c-format
msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)"
msgstr "Typ von Parameter %d (%s) stimmt nicht mit dem überein, als der Plan vorbereitet worden ist (%s)"
-#: executor/execCurrent.c:243 executor/execQual.c:1190
+#: executor/execCurrent.c:243 executor/execQual.c:1140
#, c-format
msgid "no value found for parameter %d"
msgstr "kein Wert für Parameter %d gefunden"
-#: executor/execIndexing.c:544
+#: executor/execIndexing.c:545
#, c-format
msgid "ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"
msgstr "ON CONFLICT unterstützt keine aufschiebbaren Unique-Constraints/Exclusion-Constraints als Arbiter"
-#: executor/execIndexing.c:821
+#: executor/execIndexing.c:822
#, c-format
msgid "could not create exclusion constraint \"%s\""
msgstr "konnte Exclusion-Constraint »%s« nicht erzeugen"
-#: executor/execIndexing.c:824
+#: executor/execIndexing.c:825
#, c-format
msgid "Key %s conflicts with key %s."
msgstr "Schlüssel %s kollidiert mit Schlüssel %s."
-#: executor/execIndexing.c:826
+#: executor/execIndexing.c:827
#, c-format
msgid "Key conflicts exist."
msgstr "Es bestehen Schlüsselkonflikte."
-#: executor/execIndexing.c:832
+#: executor/execIndexing.c:833
#, c-format
msgid "conflicting key value violates exclusion constraint \"%s\""
msgstr "kollidierender Schlüsselwert verletzt Exclusion-Constraint »%s«"
-#: executor/execIndexing.c:835
+#: executor/execIndexing.c:836
#, c-format
msgid "Key %s conflicts with existing key %s."
msgstr "Schlüssel %s kollidiert mit vorhandenem Schlüssel %s."
-#: executor/execIndexing.c:837
+#: executor/execIndexing.c:838
#, c-format
msgid "Key conflicts with existing key."
msgstr "Der Schlüssel kollidiert mit einem vorhandenen Schlüssel."
-#: executor/execMain.c:1027
+#: executor/execMain.c:1040
#, c-format
msgid "cannot change sequence \"%s\""
msgstr "kann Sequenz »%s« nicht ändern"
-#: executor/execMain.c:1033
+#: executor/execMain.c:1046
#, c-format
msgid "cannot change TOAST relation \"%s\""
msgstr "kann TOAST-Relation »%s« nicht ändern"
-#: executor/execMain.c:1051 rewrite/rewriteHandler.c:2648
+#: executor/execMain.c:1064 rewrite/rewriteHandler.c:2661
#, c-format
msgid "cannot insert into view \"%s\""
msgstr "kann nicht in Sicht »%s« einfügen"
-#: executor/execMain.c:1053 rewrite/rewriteHandler.c:2651
+#: executor/execMain.c:1066 rewrite/rewriteHandler.c:2664
#, c-format
msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."
msgstr "Um Einfügen in die Sicht zu ermöglichen, richten Sie einen INSTEAD OF INSERT Trigger oder eine ON INSERT DO INSTEAD Regel ohne Bedingung ein."
-#: executor/execMain.c:1059 rewrite/rewriteHandler.c:2656
+#: executor/execMain.c:1072 rewrite/rewriteHandler.c:2669
#, c-format
msgid "cannot update view \"%s\""
msgstr "kann Sicht »%s« nicht aktualisieren"
-#: executor/execMain.c:1061 rewrite/rewriteHandler.c:2659
+#: executor/execMain.c:1074 rewrite/rewriteHandler.c:2672
#, c-format
msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule."
msgstr "Um Aktualisieren der Sicht zu ermöglichen, richten Sie einen INSTEAD OF UPDATE Trigger oder eine ON UPDATE DO INSTEAD Regel ohne Bedingung ein."
-#: executor/execMain.c:1067 rewrite/rewriteHandler.c:2664
+#: executor/execMain.c:1080 rewrite/rewriteHandler.c:2677
#, c-format
msgid "cannot delete from view \"%s\""
msgstr "kann nicht aus Sicht »%s« löschen"
-#: executor/execMain.c:1069 rewrite/rewriteHandler.c:2667
+#: executor/execMain.c:1082 rewrite/rewriteHandler.c:2680
#, c-format
msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule."
msgstr "Um Löschen aus der Sicht zu ermöglichen, richten Sie einen INSTEAD OF DELETE Trigger oder eine ON DELETE DO INSTEAD Regel ohne Bedingung ein."
-#: executor/execMain.c:1080
+#: executor/execMain.c:1093
#, c-format
msgid "cannot change materialized view \"%s\""
msgstr "kann materialisierte Sicht »%s« nicht ändern"
-#: executor/execMain.c:1092
+#: executor/execMain.c:1105
#, c-format
msgid "cannot insert into foreign table \"%s\""
msgstr "kann nicht in Fremdtabelle »%s« einfügen"
-#: executor/execMain.c:1098
+#: executor/execMain.c:1111
#, c-format
msgid "foreign table \"%s\" does not allow inserts"
msgstr "Fremdtabelle »%s« erlaubt kein Einfügen"
-#: executor/execMain.c:1105
+#: executor/execMain.c:1118
#, c-format
msgid "cannot update foreign table \"%s\""
msgstr "kann Fremdtabelle »%s« nicht aktualisieren"
-#: executor/execMain.c:1111
+#: executor/execMain.c:1124
#, c-format
msgid "foreign table \"%s\" does not allow updates"
msgstr "Fremdtabelle »%s« erlaubt kein Aktualisieren"
-#: executor/execMain.c:1118
+#: executor/execMain.c:1131
#, c-format
msgid "cannot delete from foreign table \"%s\""
msgstr "kann nicht aus Fremdtabelle »%s« löschen"
-#: executor/execMain.c:1124
+#: executor/execMain.c:1137
#, c-format
msgid "foreign table \"%s\" does not allow deletes"
msgstr "Fremdtabelle »%s« erlaubt kein Löschen"
-#: executor/execMain.c:1135
+#: executor/execMain.c:1148
#, c-format
msgid "cannot change relation \"%s\""
msgstr "kann Relation »%s« nicht ändern"
-#: executor/execMain.c:1161
+#: executor/execMain.c:1175
#, c-format
msgid "cannot lock rows in sequence \"%s\""
msgstr "kann Zeilen in Sequenz »%s« nicht sperren"
-#: executor/execMain.c:1168
+#: executor/execMain.c:1182
#, c-format
msgid "cannot lock rows in TOAST relation \"%s\""
msgstr "kann Zeilen in TOAST-Relation »%s« nicht sperren"
-#: executor/execMain.c:1175
+#: executor/execMain.c:1189
#, c-format
msgid "cannot lock rows in view \"%s\""
msgstr "kann Zeilen in Sicht »%s« nicht sperren"
-#: executor/execMain.c:1183
+#: executor/execMain.c:1197
#, c-format
msgid "cannot lock rows in materialized view \"%s\""
msgstr "kann Zeilen in materialisierter Sicht »%s« nicht sperren"
-#: executor/execMain.c:1192 executor/execMain.c:2611
+#: executor/execMain.c:1206 executor/execMain.c:2760
#: executor/nodeLockRows.c:132
#, c-format
msgid "cannot lock rows in foreign table \"%s\""
msgstr "kann Zeilen in Fremdtabelle »%s« nicht sperren"
-#: executor/execMain.c:1198
+#: executor/execMain.c:1212
#, c-format
msgid "cannot lock rows in relation \"%s\""
msgstr "kann Zeilen in Relation »%s« nicht sperren"
-#: executor/execMain.c:1729
+#: executor/execMain.c:1842
#, c-format
msgid "null value in column \"%s\" violates not-null constraint"
msgstr "NULL-Wert in Spalte »%s« verletzt Not-Null-Constraint"
-#: executor/execMain.c:1731 executor/execMain.c:1757 executor/execMain.c:1846
+#: executor/execMain.c:1844 executor/execMain.c:1878 executor/execMain.c:1908
+#: executor/execMain.c:1995
#, c-format
msgid "Failing row contains %s."
msgstr "Fehlgeschlagene Zeile enthält %s."
-#: executor/execMain.c:1755
+#: executor/execMain.c:1876
#, c-format
msgid "new row for relation \"%s\" violates check constraint \"%s\""
msgstr "neue Zeile für Relation »%s« verletzt Check-Constraint »%s«"
-#: executor/execMain.c:1844
+#: executor/execMain.c:1906
+#, fuzzy, c-format
+#| msgid "new row for relation \"%s\" violates check constraint \"%s\""
+msgid "new row for relation \"%s\" violates partition constraint"
+msgstr "neue Zeile für Relation »%s« verletzt Check-Constraint »%s«"
+
+#: executor/execMain.c:1993
#, c-format
msgid "new row violates check option for view \"%s\""
msgstr "neue Zeile verletzt Check-Option für Sicht »%s«"
-#: executor/execMain.c:1854
+#: executor/execMain.c:2003
#, c-format
msgid "new row violates row-level security policy \"%s\" for table \"%s\""
msgstr "neue Zeile verletzt Policy für Sicherheit auf Zeilenebene »%s« für Tabelle »%s«"
-#: executor/execMain.c:1859
+#: executor/execMain.c:2008
#, c-format
msgid "new row violates row-level security policy for table \"%s\""
msgstr "neue Zeile verletzt Policy für Sicherheit auf Zeilenebene für Tabelle »%s«"
-#: executor/execMain.c:1866
+#: executor/execMain.c:2015
#, c-format
msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\""
msgstr "neue Zeile verletzt Policy für Sicherheit auf Zeilenebene »%s« (USING-Ausdruck) für Tabelle »%s«"
-#: executor/execMain.c:1871
+#: executor/execMain.c:2020
#, c-format
msgid "new row violates row-level security policy (USING expression) for table \"%s\""
msgstr "neue Zeile verletzt Policy für Sicherheit auf Zeilenebene (USING-Ausdruck) für Tabelle »%s«"
-#: executor/execQual.c:302 executor/execQual.c:339 executor/execQual.c:3218
-#: utils/adt/array_userfuncs.c:472 utils/adt/arrayfuncs.c:260
+#: executor/execMain.c:3221
+#, fuzzy, c-format
+#| msgid "no matching relations in tablespace \"%s\" found"
+msgid "no partition of relation \"%s\" found for row"
+msgstr "keine passenden Relationen in Tablespace »%s« gefunden"
+
+#: executor/execMain.c:3223
+#, fuzzy, c-format
+#| msgid "Failing row contains %s."
+msgid "Partition key of the failing row contains %s."
+msgstr "Fehlgeschlagene Zeile enthält %s."
+
+#: executor/execQual.c:282 executor/execQual.c:318 executor/execQual.c:2985
+#: utils/adt/array_userfuncs.c:484 utils/adt/arrayfuncs.c:260
#: utils/adt/arrayfuncs.c:558 utils/adt/arrayfuncs.c:1288
-#: utils/adt/arrayfuncs.c:3361 utils/adt/arrayfuncs.c:5245
-#: utils/adt/arrayfuncs.c:5768
+#: utils/adt/arrayfuncs.c:3361 utils/adt/arrayfuncs.c:5241
+#: utils/adt/arrayfuncs.c:5758
#, c-format
msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)"
msgstr "Anzahl der Arraydimensionen (%d) überschreitet erlaubtes Maximum (%d)"
-#: executor/execQual.c:324 executor/execQual.c:360
+#: executor/execQual.c:303 executor/execQual.c:338
#, c-format
msgid "array subscript in assignment must not be null"
msgstr "Arrayindex in Zuweisung darf nicht NULL sein"
-#: executor/execQual.c:657 executor/execQual.c:4158
+#: executor/execQual.c:626 executor/execQual.c:3964
#, c-format
msgid "attribute %d has wrong type"
msgstr "Attribut %d hat falschen Typ"
-#: executor/execQual.c:658 executor/execQual.c:4159
+#: executor/execQual.c:627 executor/execQual.c:3965
#, c-format
msgid "Table has type %s, but query expects %s."
msgstr "Tabelle hat Typ %s, aber Anfrage erwartet %s."
-#: executor/execQual.c:851 executor/execQual.c:868 executor/execQual.c:1068
+#: executor/execQual.c:814 executor/execQual.c:831 executor/execQual.c:1027
#: executor/nodeModifyTable.c:95 executor/nodeModifyTable.c:105
#: executor/nodeModifyTable.c:122 executor/nodeModifyTable.c:130
#, c-format
msgid "table row type and query-specified row type do not match"
msgstr "Zeilentyp der Tabelle und der von der Anfrage angegebene Zeilentyp stimmen nicht überein"
-#: executor/execQual.c:852
+#: executor/execQual.c:815
#, c-format
msgid "Table row contains %d attribute, but query expects %d."
msgid_plural "Table row contains %d attributes, but query expects %d."
msgstr[0] "Tabellenzeile enthält %d Attribut, aber Anfrage erwartet %d."
msgstr[1] "Tabellenzeile enthält %d Attribute, aber Anfrage erwartet %d."
-#: executor/execQual.c:869 executor/nodeModifyTable.c:106
+#: executor/execQual.c:832 executor/nodeModifyTable.c:106
#, c-format
msgid "Table has type %s at ordinal position %d, but query expects %s."
msgstr "Tabelle hat Typ %s auf Position %d, aber Anfrage erwartet %s."
-#: executor/execQual.c:1069 executor/execQual.c:1665
+#: executor/execQual.c:1028 executor/execQual.c:1602
#, c-format
msgid "Physical storage mismatch on dropped attribute at ordinal position %d."
msgstr "Physischer Speicher stimmt nicht überein mit gelöschtem Attribut auf Position %d."
-#: executor/execQual.c:1344 parser/parse_func.c:115 parser/parse_func.c:542
-#: parser/parse_func.c:897
+#: executor/execQual.c:1294 parser/parse_func.c:116 parser/parse_func.c:543
+#: parser/parse_func.c:902
#, c-format
msgid "cannot pass more than %d argument to a function"
msgid_plural "cannot pass more than %d arguments to a function"
msgstr[0] "kann nicht mehr als %d Argument an Funktion übergeben"
msgstr[1] "kann nicht mehr als %d Argumente an Funktion übergeben"
-#: executor/execQual.c:1533
-#, c-format
-msgid "functions and operators can take at most one set argument"
-msgstr "Funktionen und Operatoren können höchstens ein Mengenargument haben"
-
-#: executor/execQual.c:1583
+#: executor/execQual.c:1520
#, c-format
msgid "function returning setof record called in context that cannot accept type record"
msgstr "Funktion mit Ergebnis SETOF RECORD in einem Zusammenhang aufgerufen, der den Typ RECORD nicht verarbeiten kann"
-#: executor/execQual.c:1638 executor/execQual.c:1654 executor/execQual.c:1664
+#: executor/execQual.c:1575 executor/execQual.c:1591 executor/execQual.c:1601
#, c-format
msgid "function return row and query-specified return row do not match"
msgstr "von Funktion zurückgegebene Zeile und von der Anfrage angegebene zurückzugebende Zeile stimmen nicht überein"
-#: executor/execQual.c:1639
+#: executor/execQual.c:1576
#, c-format
msgid "Returned row contains %d attribute, but query expects %d."
msgid_plural "Returned row contains %d attributes, but query expects %d."
msgstr[0] "Zurückgegebene Zeile enthält %d Attribut, aber Anfrage erwartet %d."
msgstr[1] "Zurückgegebene Zeile enthält %d Attribute, aber Anfrage erwartet %d."
-#: executor/execQual.c:1655
+#: executor/execQual.c:1592
#, c-format
msgid "Returned type %s at ordinal position %d, but query expects %s."
msgstr "Rückgabetyp war %s auf Position %d, aber Anfrage erwartet %s."
-#: executor/execQual.c:1897 executor/execQual.c:2335
+#: executor/execQual.c:1790 executor/execQual.c:2153
#, c-format
msgid "table-function protocol for materialize mode was not followed"
msgstr "Tabellenfunktionsprotokoll für Materialisierungsmodus wurde nicht befolgt"
-#: executor/execQual.c:1917 executor/execQual.c:2342
+#: executor/execQual.c:1808 executor/execQual.c:2160
#, c-format
msgid "unrecognized table-function returnMode: %d"
msgstr "unbekannter returnMode von Tabellenfunktion: %d"
-#: executor/execQual.c:2287
+#: executor/execQual.c:2105
#, c-format
msgid "rows returned by function are not all of the same row type"
msgstr "von Funktion zurückgegebene Zeilen haben nicht alle den selben Zeilentyp"
-#: executor/execQual.c:2522
-#, c-format
-msgid "IS DISTINCT FROM does not support set arguments"
-msgstr "IS DISTINCT FROM unterstützt keine Mengenargumente"
-
-#: executor/execQual.c:2599
-#, c-format
-msgid "op ANY/ALL (array) does not support set arguments"
-msgstr "op ANY/ALL (array) unterstützt keine Mengenargumente"
-
-#: executor/execQual.c:3196
+#: executor/execQual.c:2963
#, c-format
msgid "cannot merge incompatible arrays"
msgstr "kann inkompatible Arrays nicht verschmelzen"
-#: executor/execQual.c:3197
+#: executor/execQual.c:2964
#, c-format
msgid "Array with element type %s cannot be included in ARRAY construct with element type %s."
msgstr "Arrayelement mit Typ %s kann nicht in ARRAY-Konstrukt mit Elementtyp %s verwendet werden."
-#: executor/execQual.c:3238 executor/execQual.c:3265
+#: executor/execQual.c:3005 executor/execQual.c:3032
#, c-format
msgid "multidimensional arrays must have array expressions with matching dimensions"
msgstr "mehrdimensionale Arrays müssen Arraysausdrücke mit gleicher Anzahl Dimensionen haben"
-#: executor/execQual.c:3780
-#, c-format
-msgid "NULLIF does not support set arguments"
-msgstr "NULLIF unterstützt keine Mengenargumente"
-
-#: executor/execQual.c:4028 utils/adt/domains.c:136
+#: executor/execQual.c:3831 utils/adt/domains.c:146
#, c-format
msgid "domain %s does not allow null values"
msgstr "Domäne %s erlaubt keine NULL-Werte"
-#: executor/execQual.c:4058 utils/adt/domains.c:173
+#: executor/execQual.c:3868 utils/adt/domains.c:188
#, c-format
msgid "value for domain %s violates check constraint \"%s\""
msgstr "Wert für Domäne %s verletzt Check-Constraint »%s«"
-#: executor/execQual.c:4413
+#: executor/execQual.c:4209
#, c-format
msgid "WHERE CURRENT OF is not supported for this table type"
msgstr "WHERE CURRENT OF wird für diesen Tabellentyp nicht unterstützt"
-#: executor/execQual.c:4602 parser/parse_agg.c:758
+#: executor/execQual.c:4397 parser/parse_agg.c:764
#, c-format
msgid "window function calls cannot be nested"
msgstr "Aufrufe von Fensterfunktionen können nicht geschachtelt werden"
-#: executor/execQual.c:4814
+#: executor/execQual.c:4614
#, c-format
msgid "target type is not an array"
msgstr "Zieltyp ist kein Array"
-#: executor/execQual.c:4929
+#: executor/execQual.c:4730
#, c-format
msgid "ROW() column has type %s instead of type %s"
msgstr "ROW()-Spalte hat Typ %s statt Typ %s"
-#: executor/execQual.c:5064 utils/adt/arrayfuncs.c:3803
-#: utils/adt/arrayfuncs.c:6341 utils/adt/rowtypes.c:927
+#: executor/execReplication.c:195 executor/execReplication.c:342
#, c-format
-msgid "could not identify a comparison function for type %s"
-msgstr "konnte keine Vergleichsfunktion für Typ %s ermitteln"
+msgid "concurrent update, retrying"
+msgstr ""
+
+#: executor/execReplication.c:544
+#, fuzzy, c-format
+#| msgid "cannot alter type \"%s\" because it is the type of a typed table"
+msgid "cannot update table \"%s\" because it does not have replica identity and publishes updates"
+msgstr "kann Typ »%s« nicht ändern, weil er der Typ einer getypten Tabelle ist"
-#: executor/execUtils.c:819
+#: executor/execReplication.c:546
+#, c-format
+msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE."
+msgstr ""
+
+#: executor/execReplication.c:550
+#, fuzzy, c-format
+#| msgid "cannot alter type \"%s\" because it is the type of a typed table"
+msgid "cannot delete from table \"%s\" because it does not have replica identity and publishes deletes"
+msgstr "kann Typ »%s« nicht ändern, weil er der Typ einer getypten Tabelle ist"
+
+#: executor/execReplication.c:552
+#, c-format
+msgid "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE."
+msgstr ""
+
+#: executor/execUtils.c:808
#, c-format
msgid "materialized view \"%s\" has not been populated"
msgstr "materialisierte Sicht »%s« wurde noch nicht befüllt"
-#: executor/execUtils.c:821
+#: executor/execUtils.c:810
#, c-format
msgid "Use the REFRESH MATERIALIZED VIEW command."
msgstr "Verwenden Sie den Befehl REFRESH MATERIALIZED VIEW."
@@ -10090,19 +10780,24 @@ msgstr "Verwenden Sie den Befehl REFRESH MATERIALIZED VIEW."
msgid "could not determine actual type of argument declared %s"
msgstr "konnte tatsächlichen Typ von Argument mit deklarierten Typ %s nicht bestimmen"
+#: executor/functions.c:519
+#, c-format
+msgid "cannot COPY to/from client in a SQL function"
+msgstr "COPY vom/zum Client funktioniert in einer SQL-Funktion nicht"
+
#. translator: %s is a SQL statement name
-#: executor/functions.c:508
+#: executor/functions.c:525
#, c-format
msgid "%s is not allowed in a SQL function"
msgstr "%s ist in SQL-Funktionen nicht erlaubt"
#. translator: %s is a SQL statement name
-#: executor/functions.c:515 executor/spi.c:1368 executor/spi.c:2160
+#: executor/functions.c:533 executor/spi.c:1281 executor/spi.c:2052
#, c-format
msgid "%s is not allowed in a non-volatile function"
msgstr "%s ist in als nicht »volatile« markierten Funktionen nicht erlaubt"
-#: executor/functions.c:643
+#: executor/functions.c:653
#, c-format
msgid "could not determine actual result type for function declared to return type %s"
msgstr "konnte tatsächlichen Ergebnistyp von Funktion mit deklarierten Rückgabetyp %s nicht bestimmen"
@@ -10117,104 +10812,104 @@ msgstr "SQL-Funktion »%s« Anweisung %d"
msgid "SQL function \"%s\" during startup"
msgstr "SQL-Funktion »%s« beim Start"
-#: executor/functions.c:1593 executor/functions.c:1630
-#: executor/functions.c:1642 executor/functions.c:1755
-#: executor/functions.c:1788 executor/functions.c:1818
+#: executor/functions.c:1592 executor/functions.c:1629
+#: executor/functions.c:1641 executor/functions.c:1754
+#: executor/functions.c:1787 executor/functions.c:1817
#, c-format
msgid "return type mismatch in function declared to return %s"
msgstr "Rückgabetyp von Funktion stimmt nicht überein; deklariert als %s"
-#: executor/functions.c:1595
+#: executor/functions.c:1594
#, c-format
msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING."
msgstr "Die letzte Anweisung der Funktion muss ein SELECT oder INSERT/UPDATE/DELETE RETURNING sein."
-#: executor/functions.c:1632
+#: executor/functions.c:1631
#, c-format
msgid "Final statement must return exactly one column."
msgstr "Die letzte Anweisung muss genau eine Spalte zurückgeben."
-#: executor/functions.c:1644
+#: executor/functions.c:1643
#, c-format
msgid "Actual return type is %s."
msgstr "Eigentlicher Rückgabetyp ist %s."
-#: executor/functions.c:1757
+#: executor/functions.c:1756
#, c-format
msgid "Final statement returns too many columns."
msgstr "Die letzte Anweisung gibt zu viele Spalten zurück."
-#: executor/functions.c:1790
+#: executor/functions.c:1789
#, c-format
msgid "Final statement returns %s instead of %s at column %d."
msgstr "Die letzte Anweisung ergibt %s statt %s in Spalte %d."
-#: executor/functions.c:1820
+#: executor/functions.c:1819
#, c-format
msgid "Final statement returns too few columns."
msgstr "Die letzte Anweisung gibt zu wenige Spalten zurück."
-#: executor/functions.c:1869
+#: executor/functions.c:1868
#, c-format
msgid "return type %s is not supported for SQL functions"
msgstr "Rückgabetyp %s wird von SQL-Funktionen nicht unterstützt"
-#: executor/nodeAgg.c:2983
+#: executor/nodeAgg.c:3121
#, c-format
msgid "combine function for aggregate %u must be declared as STRICT"
msgstr "Kombinierfunktion für Aggregatfunktion %u muss als STRICT deklariert sein"
-#: executor/nodeAgg.c:3028 executor/nodeWindowAgg.c:2289
+#: executor/nodeAgg.c:3166 executor/nodeWindowAgg.c:2282
#, c-format
msgid "aggregate %u needs to have compatible input type and transition type"
msgstr "Aggregatfunktion %u muss kompatiblen Eingabe- und Übergangstyp haben"
-#: executor/nodeAgg.c:3094 parser/parse_agg.c:612 parser/parse_agg.c:642
+#: executor/nodeAgg.c:3220 parser/parse_agg.c:618 parser/parse_agg.c:648
#, c-format
msgid "aggregate function calls cannot be nested"
msgstr "Aufrufe von Aggregatfunktionen können nicht geschachtelt werden"
-#: executor/nodeCustom.c:148 executor/nodeCustom.c:159
+#: executor/nodeCustom.c:146 executor/nodeCustom.c:157
#, c-format
msgid "custom scan \"%s\" does not support MarkPos"
msgstr "Custom-Scan »%s« unterstützt MarkPos nicht"
-#: executor/nodeHashjoin.c:823 executor/nodeHashjoin.c:853
+#: executor/nodeHashjoin.c:768 executor/nodeHashjoin.c:798
#, c-format
msgid "could not rewind hash-join temporary file: %m"
msgstr "konnte Position in temporärer Datei für Hash-Verbund nicht auf Anfang setzen: %m"
-#: executor/nodeHashjoin.c:888 executor/nodeHashjoin.c:894
+#: executor/nodeHashjoin.c:833 executor/nodeHashjoin.c:839
#, c-format
msgid "could not write to hash-join temporary file: %m"
msgstr "konnte nicht in temporäre Datei für Hash-Verbund schreiben: %m"
-#: executor/nodeHashjoin.c:928 executor/nodeHashjoin.c:938
+#: executor/nodeHashjoin.c:880 executor/nodeHashjoin.c:890
#, c-format
msgid "could not read from hash-join temporary file: %m"
msgstr "konnte nicht aus temporärer Datei für Hash-Verbund lesen: %m"
-#: executor/nodeIndexonlyscan.c:179
+#: executor/nodeIndexonlyscan.c:233
#, c-format
msgid "lossy distance functions are not supported in index-only scans"
msgstr "verlustbehaftete Abstandsfunktionen werden in Index-Only-Scans nicht unterstützt"
-#: executor/nodeLimit.c:253
+#: executor/nodeLimit.c:252
#, c-format
msgid "OFFSET must not be negative"
msgstr "OFFSET darf nicht negativ sein"
-#: executor/nodeLimit.c:280
+#: executor/nodeLimit.c:278
#, c-format
msgid "LIMIT must not be negative"
msgstr "LIMIT darf nicht negativ sein"
-#: executor/nodeMergejoin.c:1584
+#: executor/nodeMergejoin.c:1535
#, c-format
msgid "RIGHT JOIN is only supported with merge-joinable join conditions"
msgstr "RIGHT JOIN wird nur für Merge-Verbund-fähige Verbundbedingungen unterstützt"
-#: executor/nodeMergejoin.c:1604
+#: executor/nodeMergejoin.c:1555
#, c-format
msgid "FULL JOIN is only supported with merge-joinable join conditions"
msgstr "FULL JOIN wird nur für Merge-Verbund-fähige Verbundbedingungen unterstützt"
@@ -10234,1659 +10929,1881 @@ msgstr "Anfrage liefert einen Wert für eine gelöschte Spalte auf Position %d."
msgid "Query has too few columns."
msgstr "Anfrage hat zu wenige Spalten."
-#: executor/nodeModifyTable.c:1117
+#: executor/nodeModifyTable.c:1201
#, c-format
msgid "ON CONFLICT DO UPDATE command cannot affect row a second time"
msgstr "Befehl in ON CONFLICT DO UPDATE kann eine Zeile nicht ein zweites Mal ändern"
-#: executor/nodeModifyTable.c:1118
+#: executor/nodeModifyTable.c:1202
#, c-format
msgid "Ensure that no rows proposed for insertion within the same command have duplicate constrained values."
msgstr "Stellen Sie sicher, dass keine im selben Befehl fürs Einfügen vorgesehene Zeilen doppelte Werte haben, die einen Constraint verletzen würden."
-#: executor/nodeSamplescan.c:307
+#: executor/nodeSamplescan.c:305
#, c-format
msgid "TABLESAMPLE parameter cannot be null"
msgstr "Parameter von TABLESAMPLE darf nicht NULL sein"
-#: executor/nodeSamplescan.c:320
+#: executor/nodeSamplescan.c:317
#, c-format
msgid "TABLESAMPLE REPEATABLE parameter cannot be null"
msgstr "Parameter von TABLESAMPLE REPEATABLE darf nicht NULL sein"
-#: executor/nodeSubplan.c:345 executor/nodeSubplan.c:384
-#: executor/nodeSubplan.c:1040
+#: executor/nodeSubplan.c:339 executor/nodeSubplan.c:378
+#: executor/nodeSubplan.c:1028
#, c-format
msgid "more than one row returned by a subquery used as an expression"
msgstr "als Ausdruck verwendete Unteranfrage ergab mehr als eine Zeile"
+#: executor/nodeTableFuncscan.c:369
+#, fuzzy, c-format
+#| msgid "slot name must not be null"
+msgid "namespace URI must not be null"
+msgstr "Slot-Name darf nicht NULL sein"
+
+#: executor/nodeTableFuncscan.c:380
+#, fuzzy, c-format
+#| msgid "FOREACH expression must not be null"
+msgid "row filter expression must not be null"
+msgstr "FOREACH-Ausdruck darf nicht NULL sein"
+
+#: executor/nodeTableFuncscan.c:405
+#, fuzzy, c-format
+#| msgid "FOREACH expression must not be null"
+msgid "column filter expression must not be null"
+msgstr "FOREACH-Ausdruck darf nicht NULL sein"
+
+#: executor/nodeTableFuncscan.c:406
+#, fuzzy, c-format
+#| msgid "missing data for column \"%s\""
+msgid "Filter for column \"%s\" is null."
+msgstr "fehlende Daten für Spalte »%s«"
+
+#: executor/nodeTableFuncscan.c:485
+#, fuzzy, c-format
+#| msgid "cannot alter inherited column \"%s\""
+msgid "null is not allowed in column \"%s\""
+msgstr "kann vererbte Spalte »%s« nicht ändern"
+
#: executor/nodeWindowAgg.c:353
#, c-format
msgid "moving-aggregate transition function must not return null"
msgstr "Moving-Aggregat-Übergangsfunktion darf nicht NULL zurückgeben"
-#: executor/nodeWindowAgg.c:1609
+#: executor/nodeWindowAgg.c:1621
#, c-format
msgid "frame starting offset must not be null"
msgstr "Frame-Start-Offset darf nicht NULL sein"
-#: executor/nodeWindowAgg.c:1622
+#: executor/nodeWindowAgg.c:1634
#, c-format
msgid "frame starting offset must not be negative"
msgstr "Frame-Start-Offset darf nicht negativ sein"
-#: executor/nodeWindowAgg.c:1635
+#: executor/nodeWindowAgg.c:1646
#, c-format
msgid "frame ending offset must not be null"
msgstr "Frame-Ende-Offset darf nicht NULL sein"
-#: executor/nodeWindowAgg.c:1648
+#: executor/nodeWindowAgg.c:1659
#, c-format
msgid "frame ending offset must not be negative"
msgstr "Frame-Ende-Offset darf nicht negativ sein"
-#: executor/spi.c:214
+#: executor/spi.c:196
#, c-format
msgid "transaction left non-empty SPI stack"
msgstr "Transaktion ließ nicht-leeren SPI-Stack zurück"
-#: executor/spi.c:215 executor/spi.c:279
+#: executor/spi.c:197 executor/spi.c:260
#, c-format
msgid "Check for missing \"SPI_finish\" calls."
msgstr "Prüfen Sie, ob Aufrufe von »SPI_finish« fehlen."
-#: executor/spi.c:278
+#: executor/spi.c:259
#, c-format
msgid "subtransaction left non-empty SPI stack"
msgstr "Subtransaktion ließ nicht-leeren SPI-Stack zurück"
-#: executor/spi.c:1229
+#: executor/spi.c:1142
#, c-format
msgid "cannot open multi-query plan as cursor"
msgstr "Plan mit mehreren Anfragen kann nicht als Cursor geöffnet werden"
#. translator: %s is name of a SQL command, eg INSERT
-#: executor/spi.c:1234
+#: executor/spi.c:1147
#, c-format
msgid "cannot open %s query as cursor"
msgstr "%s kann nicht als Cursor geöffnet werden"
-#: executor/spi.c:1342
+#: executor/spi.c:1255
#, c-format
msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"
msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE wird nicht unterstützt"
-#: executor/spi.c:1343 parser/analyze.c:2363
+#: executor/spi.c:1256 parser/analyze.c:2442
#, c-format
msgid "Scrollable cursors must be READ ONLY."
msgstr "Scrollbare Cursor müssen READ ONLY sein."
-#: executor/spi.c:2461
+#: executor/spi.c:2355
#, c-format
msgid "SQL statement \"%s\""
msgstr "SQL-Anweisung »%s«"
-#: executor/tqueue.c:319
+#: executor/tqueue.c:317
#, c-format
msgid "could not send tuple to shared-memory queue"
msgstr "konnte Tupel nicht an Shared-Memory-Queue senden"
-#: foreign/foreign.c:192
+#: foreign/foreign.c:188
#, c-format
msgid "user mapping not found for \"%s\""
msgstr "Benutzerabbildung für »%s« nicht gefunden"
-#: foreign/foreign.c:644
+#: foreign/foreign.c:640
#, c-format
msgid "invalid option \"%s\""
msgstr "ungültige Option »%s«"
-#: foreign/foreign.c:645
+#: foreign/foreign.c:641
#, c-format
msgid "Valid options in this context are: %s"
msgstr "Gültige Optionen in diesem Zusammenhang sind: %s"
-#: gram.y:1004
+#: gram.y:1060
#, c-format
msgid "unrecognized role option \"%s\""
msgstr "unbekannte Rollenoption »%s«"
-#: gram.y:1280 gram.y:1295
+#: gram.y:1334 gram.y:1349
#, c-format
msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements"
msgstr "CREATE SCHEMA IF NOT EXISTS kann keine Schemaelemente enthalten"
-#: gram.y:1440
+#: gram.y:1494
#, c-format
msgid "current database cannot be changed"
msgstr "aktuelle Datenbank kann nicht geändert werden"
-#: gram.y:1564
+#: gram.y:1618
#, c-format
msgid "time zone interval must be HOUR or HOUR TO MINUTE"
msgstr "Zeitzonenintervall muss HOUR oder HOUR TO MINUTE sein"
-#: gram.y:2602 gram.y:2631
+#: gram.y:2769 gram.y:2798
#, c-format
msgid "STDIN/STDOUT not allowed with PROGRAM"
msgstr "STDIN/STDOUT sind nicht mit PROGRAM erlaubt"
-#: gram.y:2897 gram.y:2904 gram.y:10286 gram.y:10294
+#: gram.y:3108 gram.y:3115 gram.y:10841 gram.y:10849
#, c-format
msgid "GLOBAL is deprecated in temporary table creation"
msgstr "die Verwendung von GLOBAL beim Erzeugen einer temporären Tabelle ist veraltet"
-#: gram.y:3345 utils/adt/ri_triggers.c:316 utils/adt/ri_triggers.c:373
-#: utils/adt/ri_triggers.c:792 utils/adt/ri_triggers.c:1015
-#: utils/adt/ri_triggers.c:1171 utils/adt/ri_triggers.c:1352
-#: utils/adt/ri_triggers.c:1517 utils/adt/ri_triggers.c:1693
-#: utils/adt/ri_triggers.c:1873 utils/adt/ri_triggers.c:2064
-#: utils/adt/ri_triggers.c:2122 utils/adt/ri_triggers.c:2227
-#: utils/adt/ri_triggers.c:2404
+#: gram.y:3592 utils/adt/ri_triggers.c:314 utils/adt/ri_triggers.c:371
+#: utils/adt/ri_triggers.c:790 utils/adt/ri_triggers.c:1013
+#: utils/adt/ri_triggers.c:1169 utils/adt/ri_triggers.c:1350
+#: utils/adt/ri_triggers.c:1515 utils/adt/ri_triggers.c:1691
+#: utils/adt/ri_triggers.c:1871 utils/adt/ri_triggers.c:2062
+#: utils/adt/ri_triggers.c:2120 utils/adt/ri_triggers.c:2225
+#: utils/adt/ri_triggers.c:2402
#, c-format
msgid "MATCH PARTIAL not yet implemented"
msgstr "MATCH PARTIAL ist noch nicht implementiert"
-#: gram.y:4800
+#: gram.y:4983
+#, fuzzy, c-format
+#| msgid "unrecognized role option \"%s\""
+msgid "unrecognized row security option \"%s\""
+msgstr "unbekannte Rollenoption »%s«"
+
+#: gram.y:4984
+#, c-format
+msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently."
+msgstr ""
+
+#: gram.y:5092
msgid "duplicate trigger events specified"
msgstr "mehrere Trigger-Ereignisse angegeben"
-#: gram.y:4893 parser/parse_utilcmd.c:2743 parser/parse_utilcmd.c:2769
+#: gram.y:5228 parser/parse_utilcmd.c:2794 parser/parse_utilcmd.c:2820
#, c-format
msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE"
msgstr "Constraint, der als INITIALLY DEFERRED deklariert wurde, muss DEFERRABLE sein"
-#: gram.y:4900
+#: gram.y:5235
#, c-format
msgid "conflicting constraint properties"
msgstr "widersprüchliche Constraint-Eigentschaften"
-#: gram.y:5032
+#: gram.y:5341
#, c-format
msgid "CREATE ASSERTION is not yet implemented"
msgstr "CREATE ASSERTION ist noch nicht implementiert"
-#: gram.y:5048
+#: gram.y:5356
#, c-format
msgid "DROP ASSERTION is not yet implemented"
msgstr "DROP ASSERTION ist noch nicht implementiert"
-#: gram.y:5394
+#: gram.y:5740
#, c-format
msgid "RECHECK is no longer required"
msgstr "RECHECK wird nicht mehr benötigt"
-#: gram.y:5395
+#: gram.y:5741
#, c-format
msgid "Update your data type."
msgstr "Aktualisieren Sie Ihren Datentyp."
-#: gram.y:6974
+#: gram.y:7350
#, c-format
msgid "aggregates cannot have output arguments"
msgstr "Aggregatfunktionen können keine OUT-Argumente haben"
-#: gram.y:7293 utils/adt/regproc.c:774 utils/adt/regproc.c:815
+#: gram.y:7679 utils/adt/regproc.c:776 utils/adt/regproc.c:817
#, c-format
msgid "missing argument"
msgstr "Argument fehlt"
-#: gram.y:7294 utils/adt/regproc.c:775 utils/adt/regproc.c:816
+#: gram.y:7680 utils/adt/regproc.c:777 utils/adt/regproc.c:818
#, c-format
msgid "Use NONE to denote the missing argument of a unary operator."
msgstr "Verwenden Sie NONE, um das fehlende Argument eines unären Operators anzugeben."
-#: gram.y:8844 gram.y:8862
+#: gram.y:9125
+#, fuzzy, c-format
+#| msgid "unrecognized role option \"%s\""
+msgid "unrecognized option \"%s\""
+msgstr "unbekannte Rollenoption »%s«"
+
+#: gram.y:9450 gram.y:9468
#, c-format
msgid "WITH CHECK OPTION not supported on recursive views"
msgstr "WITH CHECK OPTION wird für rekursive Sichten nicht unterstützt"
-#: gram.y:9380
+#: gram.y:9986
#, c-format
msgid "unrecognized VACUUM option \"%s\""
msgstr "unbekannte VACUUM-Option »%s«"
-#: gram.y:9878 parser/parse_expr.c:1501
-#, c-format
-msgid "number of columns does not match number of values"
-msgstr "Anzahl der Spalten stimmt nicht mit der Anzahl der Werte überein"
-
-#: gram.y:10394
+#: gram.y:10949
#, c-format
msgid "LIMIT #,# syntax is not supported"
msgstr "Syntax LIMIT x,y wird nicht unterstützt"
-#: gram.y:10395
+#: gram.y:10950
#, c-format
msgid "Use separate LIMIT and OFFSET clauses."
msgstr "Verwenden Sie die getrennten Klauseln LIMIT und OFFSET."
-#: gram.y:10658 gram.y:10683
+#: gram.y:11231 gram.y:11256
#, c-format
msgid "VALUES in FROM must have an alias"
msgstr "VALUES in FROM muss Aliasnamen erhalten"
-#: gram.y:10659 gram.y:10684
+#: gram.y:11232 gram.y:11257
#, c-format
msgid "For example, FROM (VALUES ...) [AS] foo."
msgstr "Zum Beispiel FROM (VALUES ...) [AS] xyz."
-#: gram.y:10664 gram.y:10689
+#: gram.y:11237 gram.y:11262
#, c-format
msgid "subquery in FROM must have an alias"
msgstr "Unteranfrage in FROM muss Aliasnamen erhalten"
-#: gram.y:10665 gram.y:10690
+#: gram.y:11238 gram.y:11263
#, c-format
msgid "For example, FROM (SELECT ...) [AS] foo."
msgstr "Zum Beispiel FROM (SELECT ...) [AS] xyz."
-#: gram.y:11264
+#: gram.y:11716
+#, c-format
+msgid "only one DEFAULT value is allowed"
+msgstr ""
+
+#: gram.y:11725
+#, c-format
+msgid "only one PATH value per column is allowed"
+msgstr ""
+
+#: gram.y:11734
+#, fuzzy, c-format
+#| msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\""
+msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\""
+msgstr "widersprüchliche NULL/NOT NULL-Deklarationen für Spalte »%s« von Tabelle »%s«"
+
+#: gram.y:11743
+#, fuzzy, c-format
+#| msgid "unrecognized role option \"%s\""
+msgid "unrecognized column option \"%s\""
+msgstr "unbekannte Rollenoption »%s«"
+
+#: gram.y:11997
#, c-format
msgid "precision for type float must be at least 1 bit"
msgstr "Präzision von Typ float muss mindestens 1 Bit sein"
-#: gram.y:11273
+#: gram.y:12006
#, c-format
msgid "precision for type float must be less than 54 bits"
msgstr "Präzision von Typ float muss weniger als 54 Bits sein"
-#: gram.y:11777
+#: gram.y:12497
#, c-format
msgid "wrong number of parameters on left side of OVERLAPS expression"
msgstr "falsche Anzahl Parameter auf linker Seite von OVERLAPS-Ausdruck"
-#: gram.y:11782
+#: gram.y:12502
#, c-format
msgid "wrong number of parameters on right side of OVERLAPS expression"
msgstr "falsche Anzahl Parameter auf rechter Seite von OVERLAPS-Ausdruck"
-#: gram.y:11957
+#: gram.y:12677
#, c-format
msgid "UNIQUE predicate is not yet implemented"
msgstr "UNIQUE-Prädikat ist noch nicht implementiert"
-#: gram.y:12287
+#: gram.y:13024
#, c-format
msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP"
msgstr "in WITHIN GROUP können nicht mehrere ORDER-BY-Klauseln verwendet werden"
-#: gram.y:12292
+#: gram.y:13029
#, c-format
msgid "cannot use DISTINCT with WITHIN GROUP"
msgstr "DISTINCT kann nicht mit WITHIN GROUP verwendet werden"
-#: gram.y:12297
+#: gram.y:13034
#, c-format
msgid "cannot use VARIADIC with WITHIN GROUP"
msgstr "VARIADIC kann nicht mit WITHIN GROUP verwendet werden"
-#: gram.y:12803
+#: gram.y:13460
#, c-format
msgid "RANGE PRECEDING is only supported with UNBOUNDED"
msgstr "RANGE PRECEDING wird nur mit UNBOUNDED unterstützt"
-#: gram.y:12809
+#: gram.y:13466
#, c-format
msgid "RANGE FOLLOWING is only supported with UNBOUNDED"
msgstr "RANGE FOLLOWING wird nur mit UNBOUNDED unterstützt"
-#: gram.y:12836 gram.y:12859
+#: gram.y:13493 gram.y:13516
#, c-format
msgid "frame start cannot be UNBOUNDED FOLLOWING"
msgstr "Frame-Beginn kann nicht UNBOUNDED FOLLOWING sein"
-#: gram.y:12841
+#: gram.y:13498
#, c-format
msgid "frame starting from following row cannot end with current row"
msgstr "Frame der in der folgenden Zeile beginnt kann nicht in der aktuellen Zeile enden"
-#: gram.y:12864
+#: gram.y:13521
#, c-format
msgid "frame end cannot be UNBOUNDED PRECEDING"
msgstr "Frame-Ende kann nicht UNBOUNDED PRECEDING sein"
-#: gram.y:12870
+#: gram.y:13527
#, c-format
msgid "frame starting from current row cannot have preceding rows"
msgstr "Frame der in der aktuellen Zeile beginnt kann keine vorhergehenden Zeilen haben"
-#: gram.y:12877
+#: gram.y:13534
#, c-format
msgid "frame starting from following row cannot have preceding rows"
msgstr "Frame der in der folgenden Zeile beginnt kann keine vorhergehenden Zeilen haben"
-#: gram.y:13542
+#: gram.y:14169
#, c-format
msgid "type modifier cannot have parameter name"
msgstr "Typmodifikator kann keinen Parameternamen haben"
-#: gram.y:13548
+#: gram.y:14175
#, c-format
msgid "type modifier cannot have ORDER BY"
msgstr "Typmodifikator kann kein ORDER BY haben"
-#: gram.y:13612 gram.y:13618
+#: gram.y:14239 gram.y:14245
#, c-format
msgid "%s cannot be used as a role name here"
msgstr "%s kann hier nicht als Rollenname verwendet werden"
-#: gram.y:14240 gram.y:14429
+#: gram.y:14905 gram.y:15094
msgid "improper use of \"*\""
msgstr "unzulässige Verwendung von »*«"
-#: gram.y:14392 gram.y:14409 tsearch/spell.c:955 tsearch/spell.c:972
-#: tsearch/spell.c:989 tsearch/spell.c:1006 tsearch/spell.c:1071
+#: gram.y:15057 gram.y:15074 tsearch/spell.c:954 tsearch/spell.c:971
+#: tsearch/spell.c:988 tsearch/spell.c:1005 tsearch/spell.c:1070
#, c-format
msgid "syntax error"
msgstr "Syntaxfehler"
-#: gram.y:14493
+#: gram.y:15158
#, c-format
msgid "an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"
msgstr "eine Ordered-Set-Aggregatfunktion mit einem direkten VARIADIC-Argument muss ein aggregiertes VARIADIC-Argument des selben Datentyps haben"
-#: gram.y:14530
+#: gram.y:15195
#, c-format
msgid "multiple ORDER BY clauses not allowed"
msgstr "mehrere ORDER-BY-Klauseln sind nicht erlaubt"
-#: gram.y:14541
+#: gram.y:15206
#, c-format
msgid "multiple OFFSET clauses not allowed"
msgstr "mehrere OFFSET-Klauseln sind nicht erlaubt"
-#: gram.y:14550
+#: gram.y:15215
#, c-format
msgid "multiple LIMIT clauses not allowed"
msgstr "mehrere LIMIT-Klauseln sind nicht erlaubt"
-#: gram.y:14559
+#: gram.y:15224
#, c-format
msgid "multiple WITH clauses not allowed"
msgstr "mehrere WITH-Klauseln sind nicht erlaubt"
-#: gram.y:14751
+#: gram.y:15428
#, c-format
msgid "OUT and INOUT arguments aren't allowed in TABLE functions"
msgstr "OUT- und INOUT-Argumente sind in TABLE-Funktionen nicht erlaubt"
-#: gram.y:14852
+#: gram.y:15529
#, c-format
msgid "multiple COLLATE clauses not allowed"
msgstr "mehrere COLLATE-Klauseln sind nicht erlaubt"
#. translator: %s is CHECK, UNIQUE, or similar
-#: gram.y:14890 gram.y:14903
+#: gram.y:15567 gram.y:15580
#, c-format
msgid "%s constraints cannot be marked DEFERRABLE"
msgstr "%s-Constraints können nicht als DEFERRABLE markiert werden"
#. translator: %s is CHECK, UNIQUE, or similar
-#: gram.y:14916
+#: gram.y:15593
#, c-format
msgid "%s constraints cannot be marked NOT VALID"
msgstr "%s-Constraints können nicht als NOT VALID markiert werden"
#. translator: %s is CHECK, UNIQUE, or similar
-#: gram.y:14929
+#: gram.y:15606
#, c-format
msgid "%s constraints cannot be marked NO INHERIT"
msgstr "%s-Constraints können nicht als NO INHERIT markiert werden"
-#: guc-file.l:315
+#: guc-file.l:313
#, c-format
msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %u"
msgstr "unbekannter Konfigurationsparameter »%s« in Datei »%s« Zeile %u"
-#: guc-file.l:352 utils/misc/guc.c:5894 utils/misc/guc.c:6087
-#: utils/misc/guc.c:6177 utils/misc/guc.c:6267 utils/misc/guc.c:6375
-#: utils/misc/guc.c:6470
+#: guc-file.l:350 utils/misc/guc.c:5962 utils/misc/guc.c:6155
+#: utils/misc/guc.c:6245 utils/misc/guc.c:6335 utils/misc/guc.c:6443
+#: utils/misc/guc.c:6538
#, c-format
msgid "parameter \"%s\" cannot be changed without restarting the server"
msgstr "Parameter »%s« kann nicht geändert werden, ohne den Server neu zu starten"
-#: guc-file.l:388
+#: guc-file.l:386
#, c-format
msgid "parameter \"%s\" removed from configuration file, reset to default"
msgstr "Parameter »%s« wurde aus Konfigurationsdatei entfernt, wird auf Standardwert zurückgesetzt"
-#: guc-file.l:454
+#: guc-file.l:452
#, c-format
msgid "parameter \"%s\" changed to \"%s\""
msgstr "Parameter »%s« auf »%s« gesetzt"
-#: guc-file.l:496
+#: guc-file.l:494
#, c-format
msgid "configuration file \"%s\" contains errors"
msgstr "Konfigurationsdatei »%s« enthält Fehler"
-#: guc-file.l:501
+#: guc-file.l:499
#, c-format
msgid "configuration file \"%s\" contains errors; unaffected changes were applied"
msgstr "Konfigurationsdatei »%s« enthält Fehler; nicht betroffene Änderungen wurden durchgeführt"
-#: guc-file.l:506
+#: guc-file.l:504
#, c-format
msgid "configuration file \"%s\" contains errors; no changes were applied"
msgstr "Konfigurationsdatei »%s« enthält Fehler; keine Änderungen wurden durchgeführt"
-#: guc-file.l:579
+#: guc-file.l:577
#, c-format
msgid "could not open configuration file \"%s\": maximum nesting depth exceeded"
msgstr "konnte Konfigurationsdatei »%s« nicht öffnen: maximale Verschachtelungstiefe überschritten"
-#: guc-file.l:595 libpq/hba.c:1808
+#: guc-file.l:593 libpq/hba.c:1961 libpq/hba.c:2361
#, c-format
msgid "could not open configuration file \"%s\": %m"
msgstr "konnte Konfigurationsdatei »%s« nicht öffnen: %m"
-#: guc-file.l:606
+#: guc-file.l:604
#, c-format
msgid "skipping missing configuration file \"%s\""
msgstr "fehlende Konfigurationsdatei »%s« wird übersprungen"
-#: guc-file.l:860
+#: guc-file.l:858
#, c-format
msgid "syntax error in file \"%s\" line %u, near end of line"
msgstr "Syntaxfehler in Datei »%s«, Zeile %u, am Ende der Zeile"
-#: guc-file.l:870
+#: guc-file.l:868
#, c-format
msgid "syntax error in file \"%s\" line %u, near token \"%s\""
msgstr "Syntaxfehler in Datei »%s«, Zeile %u, bei »%s«"
-#: guc-file.l:890
+#: guc-file.l:888
#, c-format
msgid "too many syntax errors found, abandoning file \"%s\""
msgstr "zu viele Syntaxfehler gefunden, Datei »%s« wird aufgegeben"
-#: guc-file.l:942
+#: guc-file.l:940
#, c-format
msgid "could not open configuration directory \"%s\": %m"
msgstr "konnte Konfigurationsverzeichnis »%s« nicht öffnen: %m"
-#: lib/stringinfo.c:259
+#: lib/stringinfo.c:301
#, c-format
msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes."
msgstr "Kann Zeichenkettenpuffer mit %d Bytes nicht um %d Bytes vergrößern."
-#: libpq/auth.c:251
+#: libpq/auth-scram.c:200
+#, fuzzy, c-format
+#| msgid "User does not have CONNECT privilege."
+msgid "User \"%s\" does not have a valid SCRAM verifier."
+msgstr "Benutzer hat das CONNECT-Privileg nicht."
+
+#: libpq/auth-scram.c:234
+#, c-format
+msgid "malformed SCRAM message (empty message)"
+msgstr ""
+
+#: libpq/auth-scram.c:238
+#, c-format
+msgid "malformed SCRAM message (length mismatch)"
+msgstr ""
+
+#: libpq/auth-scram.c:270
+#, c-format
+msgid "invalid SCRAM response (nonce mismatch)"
+msgstr ""
+
+#: libpq/auth-scram.c:343
+#, fuzzy, c-format
+#| msgid "could not generate random encryption vector"
+msgid "could not generate random salt"
+msgstr "konnte zufälligen Verschlüsselungsvektor nicht erzeugen"
+
+#: libpq/auth-scram.c:483
+#, c-format
+msgid "malformed SCRAM message (attribute '%c' expected, %s found)"
+msgstr ""
+
+#: libpq/auth-scram.c:490 libpq/auth-scram.c:579
+#, c-format
+msgid "malformed SCRAM message (expected = in attr %c)"
+msgstr ""
+
+#: libpq/auth-scram.c:570
+#, c-format
+msgid "malformed SCRAM message (attribute expected, invalid char %s found)"
+msgstr ""
+
+#: libpq/auth-scram.c:692
+#, c-format
+msgid "client requires SCRAM channel binding, but it is not supported"
+msgstr ""
+
+#: libpq/auth-scram.c:696
+#, c-format
+msgid "malformed SCRAM message (unexpected channel-binding flag %s)"
+msgstr ""
+
+#: libpq/auth-scram.c:702
+#, c-format
+msgid "malformed SCRAM message (comma expected, got %s)"
+msgstr ""
+
+#: libpq/auth-scram.c:712
+#, c-format
+msgid "client uses authorization identity, but it is not supported"
+msgstr ""
+
+#: libpq/auth-scram.c:716
+#, c-format
+msgid "malformed SCRAM message (unexpected attribute %s in client-first-message)"
+msgstr ""
+
+#: libpq/auth-scram.c:732
+#, c-format
+msgid "client requires mandatory SCRAM extension"
+msgstr ""
+
+#: libpq/auth-scram.c:746
+#, c-format
+msgid "non-printable characters in SCRAM nonce"
+msgstr ""
+
+#: libpq/auth-scram.c:863
+#, fuzzy, c-format
+#| msgid "could not generate random encryption vector"
+msgid "could not generate random nonce"
+msgstr "konnte zufälligen Verschlüsselungsvektor nicht erzeugen"
+
+#: libpq/auth-scram.c:931
+#, c-format
+msgid "unexpected SCRAM channel-binding attribute in client-final-message"
+msgstr ""
+
+#: libpq/auth-scram.c:945
+#, c-format
+msgid "malformed SCRAM message (malformed proof in client-final-message"
+msgstr ""
+
+#: libpq/auth-scram.c:952
+#, c-format
+msgid "malformed SCRAM message (garbage at end of client-final-message)"
+msgstr ""
+
+#: libpq/auth.c:280
#, c-format
msgid "authentication failed for user \"%s\": host rejected"
msgstr "Authentifizierung für Benutzer »%s« fehlgeschlagen: Host abgelehnt"
-#: libpq/auth.c:254
+#: libpq/auth.c:283
#, c-format
msgid "\"trust\" authentication failed for user \"%s\""
msgstr "»trust«-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:257
+#: libpq/auth.c:286
#, c-format
msgid "Ident authentication failed for user \"%s\""
msgstr "Ident-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:260
+#: libpq/auth.c:289
#, c-format
msgid "Peer authentication failed for user \"%s\""
msgstr "Peer-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:264
+#: libpq/auth.c:294
#, c-format
msgid "password authentication failed for user \"%s\""
msgstr "Passwort-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:269
+#: libpq/auth.c:299
#, c-format
msgid "GSSAPI authentication failed for user \"%s\""
msgstr "GSSAPI-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:272
+#: libpq/auth.c:302
#, c-format
msgid "SSPI authentication failed for user \"%s\""
msgstr "SSPI-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:275
+#: libpq/auth.c:305
#, c-format
msgid "PAM authentication failed for user \"%s\""
msgstr "PAM-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:278
+#: libpq/auth.c:308
#, c-format
msgid "BSD authentication failed for user \"%s\""
msgstr "BSD-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:281
+#: libpq/auth.c:311
#, c-format
msgid "LDAP authentication failed for user \"%s\""
msgstr "LDAP-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:284
+#: libpq/auth.c:314
#, c-format
msgid "certificate authentication failed for user \"%s\""
msgstr "Zertifikatauthentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:287
+#: libpq/auth.c:317
#, c-format
msgid "RADIUS authentication failed for user \"%s\""
msgstr "RADIUS-Authentifizierung für Benutzer »%s« fehlgeschlagen"
-#: libpq/auth.c:290
+#: libpq/auth.c:320
#, c-format
msgid "authentication failed for user \"%s\": invalid authentication method"
msgstr "Authentifizierung für Benutzer »%s« fehlgeschlagen: ungültige Authentifizierungsmethode"
-#: libpq/auth.c:294
+#: libpq/auth.c:324
#, c-format
msgid "Connection matched pg_hba.conf line %d: \"%s\""
msgstr "Verbindung stimmte mit pg_hba.conf-Zeile %d überein: »%s«"
-#: libpq/auth.c:349
+#: libpq/auth.c:371
+#, c-format
+msgid "client certificates can only be checked if a root certificate store is available"
+msgstr "Client-Zertifikate können nur überprüft werden, wenn Wurzelzertifikat verfügbar ist"
+
+#: libpq/auth.c:382
#, c-format
msgid "connection requires a valid client certificate"
msgstr "Verbindung erfordert ein gültiges Client-Zertifikat"
-#: libpq/auth.c:391
+#: libpq/auth.c:415
#, c-format
msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s"
msgstr "pg_hba.conf lehnt Replikationsverbindung ab für Host »%s«, Benutzer »%s«, %s"
-#: libpq/auth.c:393 libpq/auth.c:409 libpq/auth.c:467 libpq/auth.c:485
+#: libpq/auth.c:417 libpq/auth.c:433 libpq/auth.c:491 libpq/auth.c:509
msgid "SSL off"
msgstr "SSL aus"
-#: libpq/auth.c:393 libpq/auth.c:409 libpq/auth.c:467 libpq/auth.c:485
+#: libpq/auth.c:417 libpq/auth.c:433 libpq/auth.c:491 libpq/auth.c:509
msgid "SSL on"
msgstr "SSL an"
-#: libpq/auth.c:397
+#: libpq/auth.c:421
#, c-format
msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\""
msgstr "pg_hba.conf lehnt Replikationsverbindung ab für Host »%s«, Benutzer »%s«"
-#: libpq/auth.c:406
+#: libpq/auth.c:430
#, c-format
msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s"
msgstr "pg_hba.conf lehnt Verbindung ab für Host »%s«, Benutzer »%s«, Datenbank »%s«, %s"
-#: libpq/auth.c:413
+#: libpq/auth.c:437
#, c-format
msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\""
msgstr "pg_hba.conf lehnt Verbindung ab für Host »%s«, Benutzer »%s«, Datenbank »%s«"
-#: libpq/auth.c:442
+#: libpq/auth.c:466
#, c-format
msgid "Client IP address resolved to \"%s\", forward lookup matches."
msgstr "Auflösung der Client-IP-Adresse ergab »%s«, Vorwärtsauflösung stimmt überein."
-#: libpq/auth.c:445
+#: libpq/auth.c:469
#, c-format
msgid "Client IP address resolved to \"%s\", forward lookup not checked."
msgstr "Auflösung der Client-IP-Adresse ergab »%s«, Vorwärtsauflösung nicht geprüft."
-#: libpq/auth.c:448
+#: libpq/auth.c:472
#, c-format
msgid "Client IP address resolved to \"%s\", forward lookup does not match."
msgstr "Auflösung der Client-IP-Adresse ergab »%s«, Vorwärtsauflösung stimmt nicht überein."
-#: libpq/auth.c:451
+#: libpq/auth.c:475
#, c-format
msgid "Could not translate client host name \"%s\" to IP address: %s."
msgstr "Konnte Client-Hostnamen »%s« nicht in IP-Adresse übersetzen: %s."
-#: libpq/auth.c:456
+#: libpq/auth.c:480
#, c-format
msgid "Could not resolve client IP address to a host name: %s."
msgstr "Konnte Client-IP-Adresse nicht in einen Hostnamen auflösen: %s."
-#: libpq/auth.c:465
+#: libpq/auth.c:489
#, c-format
msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s"
msgstr "kein pg_hba.conf-Eintrag für Replikationsverbindung von Host »%s«, Benutzer »%s«, %s"
-#: libpq/auth.c:472
+#: libpq/auth.c:496
#, c-format
msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\""
msgstr "kein pg_hba.conf-Eintrag für Replikationsverbindung von Host »%s«, Benutzer »%s«"
-#: libpq/auth.c:482
+#: libpq/auth.c:506
#, c-format
msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s"
msgstr "kein pg_hba.conf-Eintrag für Host »%s«, Benutzer »%s«, Datenbank »%s«, %s"
-#: libpq/auth.c:490
+#: libpq/auth.c:514
#, c-format
msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\""
msgstr "kein pg_hba.conf-Eintrag für Host »%s«, Benutzer »%s«, Datenbank »%s«"
-#: libpq/auth.c:533 libpq/hba.c:1180
-#, c-format
-msgid "MD5 authentication is not supported when \"db_user_namespace\" is enabled"
-msgstr "MD5-Authentifizierung wird nicht unterstützt, wenn »db_user_namespace« angeschaltet ist"
-
-#: libpq/auth.c:667
+#: libpq/auth.c:669
#, c-format
msgid "expected password response, got message type %d"
msgstr "Passwort-Antwort erwartet, Message-Typ %d empfangen"
-#: libpq/auth.c:695
+#: libpq/auth.c:697
#, c-format
msgid "invalid password packet size"
msgstr "ungültige Größe des Passwortpakets"
-#: libpq/auth.c:825
+#: libpq/auth.c:727 libpq/hba.c:1319
+#, c-format
+msgid "MD5 authentication is not supported when \"db_user_namespace\" is enabled"
+msgstr "MD5-Authentifizierung wird nicht unterstützt, wenn »db_user_namespace« angeschaltet ist"
+
+#: libpq/auth.c:733
+#, fuzzy, c-format
+#| msgid "could not generate random encryption vector"
+msgid "could not generate random MD5 salt"
+msgstr "konnte zufälligen Verschlüsselungsvektor nicht erzeugen"
+
+#: libpq/auth.c:812
+#, fuzzy, c-format
+#| msgid "SSPI is not supported in protocol version 2"
+msgid "SASL authentication is not supported in protocol version 2"
+msgstr "SSL wird in Protokollversion 2 nicht unterstützt"
+
+#: libpq/auth.c:852
+#, fuzzy, c-format
+#| msgid "expected GSS response, got message type %d"
+msgid "expected SASL response, got message type %d"
+msgstr "GSS-Antwort erwartet, Message-Typ %d empfangen"
+
+#: libpq/auth.c:989
#, c-format
msgid "GSSAPI is not supported in protocol version 2"
msgstr "GSSAPI wird in Protokollversion 2 nicht unterstützt"
-#: libpq/auth.c:885
+#: libpq/auth.c:1049
#, c-format
msgid "expected GSS response, got message type %d"
msgstr "GSS-Antwort erwartet, Message-Typ %d empfangen"
-#: libpq/auth.c:946
+#: libpq/auth.c:1111
msgid "accepting GSS security context failed"
msgstr "Annahme des GSS-Sicherheitskontexts fehlgeschlagen"
-#: libpq/auth.c:972
+#: libpq/auth.c:1137
msgid "retrieving GSS user name failed"
msgstr "Abfrage des GSS-Benutzernamens fehlgeschlagen"
-#: libpq/auth.c:1091
+#: libpq/auth.c:1256
#, c-format
msgid "SSPI is not supported in protocol version 2"
msgstr "SSL wird in Protokollversion 2 nicht unterstützt"
-#: libpq/auth.c:1106
+#: libpq/auth.c:1271
msgid "could not acquire SSPI credentials"
msgstr "konnte SSPI-Credentials nicht erhalten"
-#: libpq/auth.c:1124
+#: libpq/auth.c:1289
#, c-format
msgid "expected SSPI response, got message type %d"
msgstr "SSPI-Antwort erwartet, Message-Typ %d empfangen"
-#: libpq/auth.c:1196
+#: libpq/auth.c:1362
msgid "could not accept SSPI security context"
msgstr "konnte SSPI-Sicherheitskontext nicht akzeptieren"
-#: libpq/auth.c:1258
+#: libpq/auth.c:1424
msgid "could not get token from SSPI security context"
msgstr "konnte kein Token vom SSPI-Sicherheitskontext erhalten"
-#: libpq/auth.c:1377 libpq/auth.c:1396
+#: libpq/auth.c:1543 libpq/auth.c:1562
#, c-format
msgid "could not translate name"
msgstr "konnte Namen nicht umwandeln"
-#: libpq/auth.c:1409
+#: libpq/auth.c:1575
#, c-format
msgid "realm name too long"
msgstr "Realm-Name zu lang"
-#: libpq/auth.c:1424
+#: libpq/auth.c:1590
#, c-format
msgid "translated account name too long"
msgstr "umgewandelter Account-Name zu lang"
-#: libpq/auth.c:1610
+#: libpq/auth.c:1776
#, c-format
msgid "could not create socket for Ident connection: %m"
msgstr "konnte Socket für Ident-Verbindung nicht erzeugen: %m"
-#: libpq/auth.c:1625
+#: libpq/auth.c:1791
#, c-format
msgid "could not bind to local address \"%s\": %m"
msgstr "konnte nicht mit lokaler Adresse »%s« verbinden: %m"
-#: libpq/auth.c:1637
+#: libpq/auth.c:1803
#, c-format
msgid "could not connect to Ident server at address \"%s\", port %s: %m"
msgstr "konnte nicht mit Ident-Server auf Adresse »%s«, Port %s verbinden: %m"
-#: libpq/auth.c:1659
+#: libpq/auth.c:1825
#, c-format
msgid "could not send query to Ident server at address \"%s\", port %s: %m"
msgstr "konnte Anfrage an Ident-Server auf Adresse »%s«, Port %s nicht senden: %m"
-#: libpq/auth.c:1676
+#: libpq/auth.c:1842
#, c-format
msgid "could not receive response from Ident server at address \"%s\", port %s: %m"
msgstr "konnte Antwort von Ident-Server auf Adresse »%s«, Port %s nicht empfangen: %m"
-#: libpq/auth.c:1686
+#: libpq/auth.c:1852
#, c-format
msgid "invalidly formatted response from Ident server: \"%s\""
msgstr "ungültig formatierte Antwort vom Ident-Server: »%s«"
-#: libpq/auth.c:1726
+#: libpq/auth.c:1892
#, c-format
msgid "peer authentication is not supported on this platform"
msgstr "Peer-Authentifizierung wird auf dieser Plattform nicht unterstützt"
-#: libpq/auth.c:1730
+#: libpq/auth.c:1896
#, c-format
msgid "could not get peer credentials: %m"
msgstr "konnte Credentials von Gegenstelle nicht ermitteln: %m"
-#: libpq/auth.c:1739
+#: libpq/auth.c:1905
#, c-format
msgid "could not look up local user ID %ld: %s"
msgstr "konnte lokale Benutzer-ID %ld nicht nachschlagen: %s"
-#: libpq/auth.c:1823 libpq/auth.c:2149 libpq/auth.c:2509
+#: libpq/auth.c:1989 libpq/auth.c:2315 libpq/auth.c:2675
#, c-format
msgid "empty password returned by client"
msgstr "Client gab leeres Passwort zurück"
-#: libpq/auth.c:1833
+#: libpq/auth.c:1999
#, c-format
msgid "error from underlying PAM layer: %s"
msgstr "Fehler von der unteren PAM-Ebene: %s"
-#: libpq/auth.c:1914
+#: libpq/auth.c:2080
#, c-format
msgid "could not create PAM authenticator: %s"
msgstr "konnte PAM-Authenticator nicht erzeugen: %s"
-#: libpq/auth.c:1925
+#: libpq/auth.c:2091
#, c-format
msgid "pam_set_item(PAM_USER) failed: %s"
msgstr "pam_set_item(PAM_USER) fehlgeschlagen: %s"
-#: libpq/auth.c:1936
+#: libpq/auth.c:2102
#, c-format
msgid "pam_set_item(PAM_RHOST) failed: %s"
msgstr "pam_set_item(PAM_RHOST) fehlgeschlagen: %s"
-#: libpq/auth.c:1947
+#: libpq/auth.c:2113
#, c-format
msgid "pam_set_item(PAM_CONV) failed: %s"
msgstr "pam_set_item(PAM_CONV) fehlgeschlagen: %s"
-#: libpq/auth.c:1958
+#: libpq/auth.c:2124
#, c-format
msgid "pam_authenticate failed: %s"
msgstr "pam_authenticate fehlgeschlagen: %s"
-#: libpq/auth.c:1969
+#: libpq/auth.c:2135
#, c-format
msgid "pam_acct_mgmt failed: %s"
msgstr "pam_acct_mgmt fehlgeschlagen: %s"
-#: libpq/auth.c:1980
+#: libpq/auth.c:2146
#, c-format
msgid "could not release PAM authenticator: %s"
msgstr "konnte PAM-Authenticator nicht freigeben: %s"
-#: libpq/auth.c:2045
+#: libpq/auth.c:2211
#, c-format
msgid "could not initialize LDAP: %m"
msgstr "konnte LDAP nicht initialisieren: %m"
-#: libpq/auth.c:2048
+#: libpq/auth.c:2214
#, c-format
msgid "could not initialize LDAP: error code %d"
msgstr "konnte LDAP nicht initialisieren: Fehlercode %d"
-#: libpq/auth.c:2058
+#: libpq/auth.c:2224
#, c-format
msgid "could not set LDAP protocol version: %s"
msgstr "konnte LDAP-Protokollversion nicht setzen: %s"
-#: libpq/auth.c:2087
+#: libpq/auth.c:2253
#, c-format
msgid "could not load wldap32.dll"
msgstr "konnte wldap32.dll nicht laden"
-#: libpq/auth.c:2095
+#: libpq/auth.c:2261
#, c-format
msgid "could not load function _ldap_start_tls_sA in wldap32.dll"
msgstr "konnte Funktion _ldap_start_tls_sA in wldap32.dll nicht laden"
-#: libpq/auth.c:2096
+#: libpq/auth.c:2262
#, c-format
msgid "LDAP over SSL is not supported on this platform."
msgstr "LDAP über SSL wird auf dieser Plattform nicht unterstützt."
-#: libpq/auth.c:2111
+#: libpq/auth.c:2277
#, c-format
msgid "could not start LDAP TLS session: %s"
msgstr "konnte LDAP-TLS-Sitzung nicht starten: %s"
-#: libpq/auth.c:2133
+#: libpq/auth.c:2299
#, c-format
msgid "LDAP server not specified"
msgstr "LDAP-Server nicht angegeben"
-#: libpq/auth.c:2186
+#: libpq/auth.c:2352
#, c-format
msgid "invalid character in user name for LDAP authentication"
msgstr "ungültiges Zeichen im Benutzernamen für LDAP-Authentifizierung"
-#: libpq/auth.c:2201
+#: libpq/auth.c:2367
#, c-format
msgid "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s"
msgstr "erstes LDAP-Binden für ldapbinddn »%s« auf Server »%s« fehlgeschlagen: %s"
-#: libpq/auth.c:2225
+#: libpq/auth.c:2391
#, c-format
msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s"
msgstr "konnte LDAP nicht mit Filter »%s« auf Server »%s« durchsuchen: %s"
-#: libpq/auth.c:2236
+#: libpq/auth.c:2402
#, c-format
msgid "LDAP user \"%s\" does not exist"
msgstr "LDAP-Benutzer »%s« existiert nicht"
-#: libpq/auth.c:2237
+#: libpq/auth.c:2403
#, c-format
msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries."
msgstr "LDAP-Suche nach Filter »%s« auf Server »%s« gab keine Einträge zurück."
-#: libpq/auth.c:2241
+#: libpq/auth.c:2407
#, c-format
msgid "LDAP user \"%s\" is not unique"
msgstr "LDAP-Benutzer »%s« ist nicht eindeutig"
-#: libpq/auth.c:2242
+#: libpq/auth.c:2408
#, c-format
msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry."
msgid_plural "LDAP search for filter \"%s\" on server \"%s\" returned %d entries."
msgstr[0] "LDAP-Suche nach Filter »%s« auf Server »%s« gab %d Eintrag zurück."
msgstr[1] "LDAP-Suche nach Filter »%s« auf Server »%s« gab %d Einträge zurück."
-#: libpq/auth.c:2260
+#: libpq/auth.c:2426
#, c-format
msgid "could not get dn for the first entry matching \"%s\" on server \"%s\": %s"
msgstr "konnte DN fũr den ersten Treffer für »%s« auf Server »%s« nicht lesen: %s"
-#: libpq/auth.c:2280
+#: libpq/auth.c:2446
#, c-format
msgid "could not unbind after searching for user \"%s\" on server \"%s\": %s"
msgstr "Losbinden fehlgeschlagen nach Suche nach Benutzer »%s« auf Server »%s«: %s"
-#: libpq/auth.c:2310
+#: libpq/auth.c:2476
#, c-format
msgid "LDAP login failed for user \"%s\" on server \"%s\": %s"
msgstr "LDAP-Login fehlgeschlagen für Benutzer »%s« auf Server »%s«: %s"
-#: libpq/auth.c:2338
+#: libpq/auth.c:2504
#, c-format
msgid "certificate authentication failed for user \"%s\": client certificate contains no user name"
msgstr "Zertifikatauthentifizierung für Benutzer »%s« fehlgeschlagen: Client-Zertifikat enthält keinen Benutzernamen"
-#: libpq/auth.c:2465
+#: libpq/auth.c:2631
#, c-format
msgid "RADIUS server not specified"
msgstr "RADIUS-Server nicht angegeben"
-#: libpq/auth.c:2472
+#: libpq/auth.c:2638
#, c-format
msgid "RADIUS secret not specified"
msgstr "RADIUS-Geheimnis nicht angegeben"
-#: libpq/auth.c:2488 libpq/hba.c:1634
+#: libpq/auth.c:2654 libpq/hba.c:1786
#, c-format
msgid "could not translate RADIUS server name \"%s\" to address: %s"
msgstr "konnte RADIUS-Servername »%s« nicht in Adresse übersetzen: %s"
-#: libpq/auth.c:2516
+#: libpq/auth.c:2682
#, c-format
msgid "RADIUS authentication does not support passwords longer than %d characters"
msgstr "RADIUS-Authentifizierung unterstützt keine Passwörter länger als %d Zeichen"
-#: libpq/auth.c:2528
+#: libpq/auth.c:2693
#, c-format
msgid "could not generate random encryption vector"
msgstr "konnte zufälligen Verschlüsselungsvektor nicht erzeugen"
-#: libpq/auth.c:2566
+#: libpq/auth.c:2726
#, c-format
msgid "could not perform MD5 encryption of password"
msgstr "konnte MD5-Verschlüsselung des Passworts nicht durchführen"
-#: libpq/auth.c:2591
+#: libpq/auth.c:2751
#, c-format
msgid "could not create RADIUS socket: %m"
msgstr "konnte RADIUS-Socket nicht erstellen: %m"
-#: libpq/auth.c:2612
+#: libpq/auth.c:2772
#, c-format
msgid "could not bind local RADIUS socket: %m"
msgstr "konnte lokales RADIUS-Socket nicht binden: %m"
-#: libpq/auth.c:2622
+#: libpq/auth.c:2782
#, c-format
msgid "could not send RADIUS packet: %m"
msgstr "konnte RADIUS-Paket nicht senden: %m"
-#: libpq/auth.c:2655 libpq/auth.c:2680
+#: libpq/auth.c:2815 libpq/auth.c:2840
#, c-format
msgid "timeout waiting for RADIUS response"
msgstr "Zeitüberschreitung beim Warten auf RADIUS-Antwort"
-#: libpq/auth.c:2673
+#: libpq/auth.c:2833
#, c-format
msgid "could not check status on RADIUS socket: %m"
msgstr "konnte Status des RADIUS-Sockets nicht prüfen: %m"
-#: libpq/auth.c:2702
+#: libpq/auth.c:2862
#, c-format
msgid "could not read RADIUS response: %m"
msgstr "konnte RADIUS-Antwort nicht lesen: %m"
-#: libpq/auth.c:2714 libpq/auth.c:2718
+#: libpq/auth.c:2874 libpq/auth.c:2878
#, c-format
msgid "RADIUS response was sent from incorrect port: %d"
msgstr "RADIUS-Antwort wurde von falschem Port gesendet: %d"
-#: libpq/auth.c:2727
+#: libpq/auth.c:2887
#, c-format
msgid "RADIUS response too short: %d"
msgstr "RADIUS-Antwort zu kurz: %d"
-#: libpq/auth.c:2734
+#: libpq/auth.c:2894
#, c-format
msgid "RADIUS response has corrupt length: %d (actual length %d)"
msgstr "RADIUS-Antwort hat verfälschte Länge: %d (tatsächliche Länge %d)"
-#: libpq/auth.c:2742
+#: libpq/auth.c:2902
#, c-format
msgid "RADIUS response is to a different request: %d (should be %d)"
msgstr "RADIUS-Antwort unterscheidet sich von Anfrage: %d (sollte %d sein)"
-#: libpq/auth.c:2767
+#: libpq/auth.c:2927
#, c-format
msgid "could not perform MD5 encryption of received packet"
msgstr "konnte MD5-Verschlüsselung des empfangenen Pakets nicht durchführen"
-#: libpq/auth.c:2776
+#: libpq/auth.c:2936
#, c-format
msgid "RADIUS response has incorrect MD5 signature"
msgstr "RADIUS-Antwort hat falsche MD5-Signatur"
-#: libpq/auth.c:2793
+#: libpq/auth.c:2953
#, c-format
msgid "RADIUS response has invalid code (%d) for user \"%s\""
msgstr "RADIUS-Antwort hat ungültigen Code (%d) für Benutzer »%s«"
-#: libpq/be-fsstubs.c:134 libpq/be-fsstubs.c:165 libpq/be-fsstubs.c:199
-#: libpq/be-fsstubs.c:239 libpq/be-fsstubs.c:264 libpq/be-fsstubs.c:312
-#: libpq/be-fsstubs.c:335 libpq/be-fsstubs.c:583
+#: libpq/be-fsstubs.c:132 libpq/be-fsstubs.c:163 libpq/be-fsstubs.c:197
+#: libpq/be-fsstubs.c:237 libpq/be-fsstubs.c:262 libpq/be-fsstubs.c:310
+#: libpq/be-fsstubs.c:333 libpq/be-fsstubs.c:581
#, c-format
msgid "invalid large-object descriptor: %d"
msgstr "ungültiger Large-Object-Deskriptor: %d"
-#: libpq/be-fsstubs.c:180 libpq/be-fsstubs.c:218 libpq/be-fsstubs.c:602
-#: libpq/be-fsstubs.c:790
+#: libpq/be-fsstubs.c:178 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:600
+#: libpq/be-fsstubs.c:788
#, c-format
msgid "permission denied for large object %u"
msgstr "keine Berechtigung für Large Object %u"
-#: libpq/be-fsstubs.c:205 libpq/be-fsstubs.c:589
+#: libpq/be-fsstubs.c:203 libpq/be-fsstubs.c:587
#, c-format
msgid "large object descriptor %d was not opened for writing"
msgstr "Large-Objekt-Deskriptor %d wurde nicht zum Schreiben geöffnet"
-#: libpq/be-fsstubs.c:247
+#: libpq/be-fsstubs.c:245
#, c-format
msgid "lo_lseek result out of range for large-object descriptor %d"
msgstr "Ergebnis von lo_lseek ist außerhalb des gültigen Bereichs für Large-Object-Deskriptor %d"
-#: libpq/be-fsstubs.c:320
+#: libpq/be-fsstubs.c:318
#, c-format
msgid "lo_tell result out of range for large-object descriptor %d"
msgstr "Ergebnis von lo_tell ist außerhalb des gültigen Bereichs für Large-Object-Deskriptor: %d"
-#: libpq/be-fsstubs.c:457
+#: libpq/be-fsstubs.c:455
#, c-format
msgid "must be superuser to use server-side lo_import()"
msgstr "nur Superuser können das serverseitige lo_import() verwenden"
-#: libpq/be-fsstubs.c:458
+#: libpq/be-fsstubs.c:456
#, c-format
msgid "Anyone can use the client-side lo_import() provided by libpq."
msgstr "Jeder kann das clientseitige lo_import() von libpq verwenden."
-#: libpq/be-fsstubs.c:471
+#: libpq/be-fsstubs.c:469
#, c-format
msgid "could not open server file \"%s\": %m"
msgstr "konnte Serverdatei »%s« nicht öffnen: %m"
-#: libpq/be-fsstubs.c:493
+#: libpq/be-fsstubs.c:491
#, c-format
msgid "could not read server file \"%s\": %m"
msgstr "konnte Serverdatei »%s« nicht lesen: %m"
-#: libpq/be-fsstubs.c:523
+#: libpq/be-fsstubs.c:521
#, c-format
msgid "must be superuser to use server-side lo_export()"
msgstr "nur Superuser können das serverseitige lo_export() verwenden"
-#: libpq/be-fsstubs.c:524
+#: libpq/be-fsstubs.c:522
#, c-format
msgid "Anyone can use the client-side lo_export() provided by libpq."
msgstr "Jeder kann das clientseitige lo_export() von libpq verwenden."
-#: libpq/be-fsstubs.c:549
+#: libpq/be-fsstubs.c:547
#, c-format
msgid "could not create server file \"%s\": %m"
msgstr "konnte Serverdatei »%s« nicht erstellen: %m"
-#: libpq/be-fsstubs.c:561
+#: libpq/be-fsstubs.c:559
#, c-format
msgid "could not write server file \"%s\": %m"
msgstr "konnte Serverdatei »%s« nicht schreiben: %m"
-#: libpq/be-fsstubs.c:815
+#: libpq/be-fsstubs.c:813
#, c-format
msgid "large object read request is too large"
msgstr "Large-Object-Leseaufforderung ist zu groß"
-#: libpq/be-fsstubs.c:857 utils/adt/genfile.c:211 utils/adt/genfile.c:252
+#: libpq/be-fsstubs.c:855 utils/adt/genfile.c:211 utils/adt/genfile.c:252
#, c-format
msgid "requested length cannot be negative"
msgstr "verlangte Länge darf nicht negativ sein"
-#: libpq/be-secure-openssl.c:184
+#: libpq/be-secure-openssl.c:197
#, c-format
msgid "could not create SSL context: %s"
msgstr "konnte SSL-Kontext nicht erzeugen: %s"
-#: libpq/be-secure-openssl.c:200
+#: libpq/be-secure-openssl.c:225
#, c-format
msgid "could not load server certificate file \"%s\": %s"
msgstr "konnte Serverzertifikatsdatei »%s« nicht laden: %s"
-#: libpq/be-secure-openssl.c:206
+#: libpq/be-secure-openssl.c:234
#, c-format
msgid "could not access private key file \"%s\": %m"
msgstr "konnte auf private Schlüsseldatei »%s« nicht zugreifen: %m"
-#: libpq/be-secure-openssl.c:212
+#: libpq/be-secure-openssl.c:243
#, c-format
msgid "private key file \"%s\" is not a regular file"
msgstr "private Schlüsseldatei »%s« ist keine normale Datei"
-#: libpq/be-secure-openssl.c:224
+#: libpq/be-secure-openssl.c:258
#, c-format
msgid "private key file \"%s\" must be owned by the database user or root"
msgstr "private Schlüsseldatei »%s« muss als Eigentümer den Datenbankbenutzer oder »root« haben"
-#: libpq/be-secure-openssl.c:244
+#: libpq/be-secure-openssl.c:281
#, c-format
msgid "private key file \"%s\" has group or world access"
msgstr "private Schlüsseldatei »%s« erlaubt Zugriff von Gruppe oder Welt"
-#: libpq/be-secure-openssl.c:246
+#: libpq/be-secure-openssl.c:283
#, c-format
msgid "File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root."
msgstr "Dateirechte müssen u=rw (0600) oder weniger sein, wenn der Eigentümer der Datenbankbenutzer ist, oder u=rw,g=r (0640) oder weniger, wenn der Eigentümer »root« ist."
-#: libpq/be-secure-openssl.c:253
+#: libpq/be-secure-openssl.c:300
+#, fuzzy, c-format
+#| msgid "private key file \"%s\" must be owned by the database user or root"
+msgid "private key file \"%s\" cannot be reloaded because it requires a passphrase"
+msgstr "private Schlüsseldatei »%s« muss als Eigentümer den Datenbankbenutzer oder »root« haben"
+
+#: libpq/be-secure-openssl.c:305
#, c-format
msgid "could not load private key file \"%s\": %s"
msgstr "konnte private Schlüsseldatei »%s« nicht laden: %s"
-#: libpq/be-secure-openssl.c:258
+#: libpq/be-secure-openssl.c:314
#, c-format
msgid "check of private key failed: %s"
msgstr "Überprüfung des privaten Schlüssels fehlgeschlagen: %s"
-#: libpq/be-secure-openssl.c:287
+#: libpq/be-secure-openssl.c:334
+#, c-format
+msgid "could not set the cipher list (no valid ciphers available)"
+msgstr ""
+
+#: libpq/be-secure-openssl.c:352
#, c-format
msgid "could not load root certificate file \"%s\": %s"
msgstr "konnte Root-Zertifikat-Datei »%s« nicht laden: %s"
-#: libpq/be-secure-openssl.c:311
+#: libpq/be-secure-openssl.c:379
#, c-format
msgid "SSL certificate revocation list file \"%s\" ignored"
msgstr "SSL-Certificate-Revocation-List-Datei »%s« ignoriert"
-#: libpq/be-secure-openssl.c:313
+#: libpq/be-secure-openssl.c:381
#, c-format
msgid "SSL library does not support certificate revocation lists."
msgstr "SSL-Bibliothek unterstützt keine Certificate-Revocation-Lists."
-#: libpq/be-secure-openssl.c:318
+#: libpq/be-secure-openssl.c:388
#, c-format
msgid "could not load SSL certificate revocation list file \"%s\": %s"
msgstr "konnte SSL-Certificate-Revocation-List-Datei »%s« nicht laden: %s"
-#: libpq/be-secure-openssl.c:365
+#: libpq/be-secure-openssl.c:469
+#, fuzzy, c-format
+#| msgid "could not initialize SSL connection: %s"
+msgid "could not initialize SSL connection: SSL context not set up"
+msgstr "konnte SSL-Verbindung nicht initialisieren: %s"
+
+#: libpq/be-secure-openssl.c:477
#, c-format
msgid "could not initialize SSL connection: %s"
msgstr "konnte SSL-Verbindung nicht initialisieren: %s"
-#: libpq/be-secure-openssl.c:373
+#: libpq/be-secure-openssl.c:485
#, c-format
msgid "could not set SSL socket: %s"
msgstr "konnte SSL-Socket nicht setzen: %s"
-#: libpq/be-secure-openssl.c:427
+#: libpq/be-secure-openssl.c:540
#, c-format
msgid "could not accept SSL connection: %m"
msgstr "konnte SSL-Verbindung nicht annehmen: %m"
-#: libpq/be-secure-openssl.c:431 libpq/be-secure-openssl.c:442
+#: libpq/be-secure-openssl.c:544 libpq/be-secure-openssl.c:555
#, c-format
msgid "could not accept SSL connection: EOF detected"
msgstr "konnte SSL-Verbindung nicht annehmen: EOF entdeckt"
-#: libpq/be-secure-openssl.c:436
+#: libpq/be-secure-openssl.c:549
#, c-format
msgid "could not accept SSL connection: %s"
msgstr "konnte SSL-Verbindung nicht annehmen: %s"
-#: libpq/be-secure-openssl.c:447 libpq/be-secure-openssl.c:588
-#: libpq/be-secure-openssl.c:648
+#: libpq/be-secure-openssl.c:560 libpq/be-secure-openssl.c:699
+#: libpq/be-secure-openssl.c:759
#, c-format
msgid "unrecognized SSL error code: %d"
msgstr "unbekannter SSL-Fehlercode: %d"
-#: libpq/be-secure-openssl.c:491
+#: libpq/be-secure-openssl.c:602
#, c-format
msgid "SSL certificate's common name contains embedded null"
msgstr "Common-Name im SSL-Zertifikat enthält Null-Byte"
-#: libpq/be-secure-openssl.c:502
+#: libpq/be-secure-openssl.c:613
#, c-format
msgid "SSL connection from \"%s\""
msgstr "SSL-Verbindung von »%s«"
-#: libpq/be-secure-openssl.c:579 libpq/be-secure-openssl.c:639
+#: libpq/be-secure-openssl.c:690 libpq/be-secure-openssl.c:750
#, c-format
msgid "SSL error: %s"
msgstr "SSL-Fehler: %s"
-#: libpq/be-secure-openssl.c:988
+#: libpq/be-secure-openssl.c:1179
#, c-format
msgid "ECDH: unrecognized curve name: %s"
msgstr "ECDH: unbekannter Kurvenname: %s"
-#: libpq/be-secure-openssl.c:993
+#: libpq/be-secure-openssl.c:1188
#, c-format
msgid "ECDH: could not create key"
msgstr "ECDH: konnte Schlüssel nicht erzeugen"
-#: libpq/be-secure-openssl.c:1017
+#: libpq/be-secure-openssl.c:1216
msgid "no SSL error reported"
msgstr "kein SSL-Fehler berichtet"
-#: libpq/be-secure-openssl.c:1021
+#: libpq/be-secure-openssl.c:1220
#, c-format
msgid "SSL error code %lu"
msgstr "SSL-Fehlercode %lu"
-#: libpq/be-secure.c:171 libpq/be-secure.c:256
+#: libpq/be-secure.c:188 libpq/be-secure.c:274
#, c-format
msgid "terminating connection due to unexpected postmaster exit"
msgstr "Verbindung wird abgebrochen wegen unerwartetem Ende des Postmasters"
-#: libpq/crypt.c:54
+#: libpq/crypt.c:58
#, c-format
msgid "Role \"%s\" does not exist."
msgstr "Rolle »%s« existiert nicht."
-#: libpq/crypt.c:64
+#: libpq/crypt.c:68
#, c-format
msgid "User \"%s\" has no password assigned."
msgstr "Benutzer »%s« hat kein Passwort zugewiesen."
-#: libpq/crypt.c:79
+#: libpq/crypt.c:83
#, c-format
msgid "User \"%s\" has an empty password."
msgstr "Benutzer »%s« hat ein leeres Passwort."
-#: libpq/crypt.c:159
+#: libpq/crypt.c:97
#, c-format
msgid "User \"%s\" has an expired password."
msgstr "Benutzer »%s« hat ein abgelaufenes Passwort."
-#: libpq/crypt.c:167
+#: libpq/crypt.c:254
+#, c-format
+msgid "User \"%s\" has a password that cannot be used with MD5 authentication."
+msgstr ""
+
+#: libpq/crypt.c:263 libpq/crypt.c:330
#, c-format
msgid "Password does not match for user \"%s\"."
msgstr "Passwort stimmt nicht überein für Benutzer »%s«."
-#: libpq/hba.c:188
+#: libpq/crypt.c:321
+#, c-format
+msgid "Password of user \"%s\" is in unrecognized format."
+msgstr ""
+
+#: libpq/hba.c:232
#, c-format
msgid "authentication file token too long, skipping: \"%s\""
msgstr "Token in Authentifizierungsdatei zu lang, wird übersprungen: »%s«"
-#: libpq/hba.c:332
+#: libpq/hba.c:404
#, c-format
msgid "could not open secondary authentication file \"@%s\" as \"%s\": %m"
msgstr "konnte sekundäre Authentifizierungsdatei »@%s« nicht als »%s« öffnen: %m"
-#: libpq/hba.c:409
+#: libpq/hba.c:506
#, c-format
msgid "authentication file line too long"
msgstr "Zeile in Authentifizierungsdatei zu lang"
-#: libpq/hba.c:410 libpq/hba.c:757 libpq/hba.c:773 libpq/hba.c:803
-#: libpq/hba.c:849 libpq/hba.c:862 libpq/hba.c:884 libpq/hba.c:893
-#: libpq/hba.c:914 libpq/hba.c:926 libpq/hba.c:945 libpq/hba.c:966
-#: libpq/hba.c:977 libpq/hba.c:1032 libpq/hba.c:1050 libpq/hba.c:1062
-#: libpq/hba.c:1079 libpq/hba.c:1089 libpq/hba.c:1103 libpq/hba.c:1119
-#: libpq/hba.c:1134 libpq/hba.c:1145 libpq/hba.c:1181 libpq/hba.c:1219
-#: libpq/hba.c:1230 libpq/hba.c:1250 libpq/hba.c:1261 libpq/hba.c:1278
-#: libpq/hba.c:1327 libpq/hba.c:1364 libpq/hba.c:1374 libpq/hba.c:1430
-#: libpq/hba.c:1442 libpq/hba.c:1455 libpq/hba.c:1547 libpq/hba.c:1636
-#: libpq/hba.c:1654 libpq/hba.c:1675 tsearch/ts_locale.c:182
+#: libpq/hba.c:507 libpq/hba.c:861 libpq/hba.c:881 libpq/hba.c:919
+#: libpq/hba.c:969 libpq/hba.c:983 libpq/hba.c:1005 libpq/hba.c:1014
+#: libpq/hba.c:1035 libpq/hba.c:1048 libpq/hba.c:1068 libpq/hba.c:1090
+#: libpq/hba.c:1102 libpq/hba.c:1158 libpq/hba.c:1178 libpq/hba.c:1192
+#: libpq/hba.c:1211 libpq/hba.c:1222 libpq/hba.c:1237 libpq/hba.c:1255
+#: libpq/hba.c:1271 libpq/hba.c:1283 libpq/hba.c:1320 libpq/hba.c:1361
+#: libpq/hba.c:1374 libpq/hba.c:1396 libpq/hba.c:1408 libpq/hba.c:1426
+#: libpq/hba.c:1476 libpq/hba.c:1515 libpq/hba.c:1526 libpq/hba.c:1583
+#: libpq/hba.c:1599 libpq/hba.c:1698 libpq/hba.c:1788 libpq/hba.c:1808
+#: libpq/hba.c:1830 tsearch/ts_locale.c:182
#, c-format
msgid "line %d of configuration file \"%s\""
msgstr "Zeile %d in Konfigurationsdatei »%s«"
#. translator: the second %s is a list of auth methods
-#: libpq/hba.c:755
+#: libpq/hba.c:859
#, c-format
msgid "authentication option \"%s\" is only valid for authentication methods %s"
msgstr "Authentifizierungsoption »%s« ist nur gültig für Authentifizierungsmethoden %s"
-#: libpq/hba.c:771
+#: libpq/hba.c:879
#, c-format
msgid "authentication method \"%s\" requires argument \"%s\" to be set"
msgstr "Authentifizierungsmethode »%s« benötigt Argument »%s«"
-#: libpq/hba.c:792
+#: libpq/hba.c:907
#, c-format
msgid "missing entry in file \"%s\" at end of line %d"
msgstr "fehlender Eintrag in Datei »%s« am Ende von Zeile %d"
-#: libpq/hba.c:802
+#: libpq/hba.c:918
#, c-format
msgid "multiple values in ident field"
msgstr "mehrere Werte in Ident-Feld"
-#: libpq/hba.c:847
+#: libpq/hba.c:967
#, c-format
msgid "multiple values specified for connection type"
msgstr "mehrere Werte angegeben für Verbindungstyp"
-#: libpq/hba.c:848
+#: libpq/hba.c:968
#, c-format
msgid "Specify exactly one connection type per line."
msgstr "Geben Sie genau einen Verbindungstyp pro Zeile an."
-#: libpq/hba.c:861
+#: libpq/hba.c:982
#, c-format
msgid "local connections are not supported by this build"
msgstr "lokale Verbindungen werden von dieser Installation nicht unterstützt"
-#: libpq/hba.c:882
+#: libpq/hba.c:1003
#, c-format
-msgid "hostssl requires SSL to be turned on"
-msgstr "für hostssl muss SSL angeschaltet sein"
+msgid "hostssl record cannot match because SSL is disabled"
+msgstr ""
-#: libpq/hba.c:883
+#: libpq/hba.c:1004
#, c-format
msgid "Set ssl = on in postgresql.conf."
msgstr "Setzen Sie ssl = on in postgresql.conf."
-#: libpq/hba.c:891
-#, c-format
-msgid "hostssl is not supported by this build"
+#: libpq/hba.c:1012
+#, fuzzy, c-format
+#| msgid "hostssl is not supported by this build"
+msgid "hostssl record cannot match because SSL is not supported by this build"
msgstr "hostssl wird von dieser Installation nicht unterstützt"
-#: libpq/hba.c:892
+#: libpq/hba.c:1013
#, c-format
msgid "Compile with --with-openssl to use SSL connections."
msgstr "Kompilieren Sie mit --with-openssl, um SSL-Verbindungen zu verwenden."
-#: libpq/hba.c:912
+#: libpq/hba.c:1033
#, c-format
msgid "invalid connection type \"%s\""
msgstr "ungültiger Verbindungstyp »%s«"
-#: libpq/hba.c:925
+#: libpq/hba.c:1047
#, c-format
msgid "end-of-line before database specification"
msgstr "Zeilenende vor Datenbankangabe"
-#: libpq/hba.c:944
+#: libpq/hba.c:1067
#, c-format
msgid "end-of-line before role specification"
msgstr "Zeilenende vor Rollenangabe"
-#: libpq/hba.c:965
+#: libpq/hba.c:1089
#, c-format
msgid "end-of-line before IP address specification"
msgstr "Zeilenende vor IP-Adressangabe"
-#: libpq/hba.c:975
+#: libpq/hba.c:1100
#, c-format
msgid "multiple values specified for host address"
msgstr "mehrere Werte für Hostadresse angegeben"
-#: libpq/hba.c:976
+#: libpq/hba.c:1101
#, c-format
msgid "Specify one address range per line."
msgstr "Geben Sie einen Adressbereich pro Zeile an."
-#: libpq/hba.c:1030
+#: libpq/hba.c:1156
#, c-format
msgid "invalid IP address \"%s\": %s"
msgstr "ungültige IP-Adresse »%s«: %s"
-#: libpq/hba.c:1048
+#: libpq/hba.c:1176
#, c-format
msgid "specifying both host name and CIDR mask is invalid: \"%s\""
msgstr "Angabe von sowohl Hostname als auch CIDR-Maske ist ungültig: »%s«"
-#: libpq/hba.c:1060
+#: libpq/hba.c:1190
#, c-format
msgid "invalid CIDR mask in address \"%s\""
msgstr "ungültige CIDR-Maske in Adresse »%s«"
-#: libpq/hba.c:1077
+#: libpq/hba.c:1209
#, c-format
msgid "end-of-line before netmask specification"
msgstr "Zeilenende vor Netzmaskenangabe"
-#: libpq/hba.c:1078
+#: libpq/hba.c:1210
#, c-format
msgid "Specify an address range in CIDR notation, or provide a separate netmask."
msgstr "Geben Sie einen Adressbereich in CIDR-Schreibweise oder eine separate Netzmaske an."
-#: libpq/hba.c:1088
+#: libpq/hba.c:1221
#, c-format
msgid "multiple values specified for netmask"
msgstr "mehrere Werte für Netzmaske angegeben"
-#: libpq/hba.c:1101
+#: libpq/hba.c:1235
#, c-format
msgid "invalid IP mask \"%s\": %s"
msgstr "ungültige IP-Maske »%s«: %s"
-#: libpq/hba.c:1118
+#: libpq/hba.c:1254
#, c-format
msgid "IP address and mask do not match"
msgstr "IP-Adresse und -Maske passen nicht zusammen"
-#: libpq/hba.c:1133
+#: libpq/hba.c:1270
#, c-format
msgid "end-of-line before authentication method"
msgstr "Zeilenende vor Authentifizierungsmethode"
-#: libpq/hba.c:1143
+#: libpq/hba.c:1281
#, c-format
msgid "multiple values specified for authentication type"
msgstr "mehrere Werte für Authentifizierungstyp angegeben"
-#: libpq/hba.c:1144
+#: libpq/hba.c:1282
#, c-format
msgid "Specify exactly one authentication type per line."
msgstr "Geben Sie genau einen Authentifizierungstyp pro Zeile an."
-#: libpq/hba.c:1217
+#: libpq/hba.c:1359
#, c-format
msgid "invalid authentication method \"%s\""
msgstr "ungültige Authentifizierungsmethode »%s«"
-#: libpq/hba.c:1228
+#: libpq/hba.c:1372
#, c-format
msgid "invalid authentication method \"%s\": not supported by this build"
msgstr "ungültige Authentifizierungsmethode »%s«: von dieser Installation nicht unterstützt"
-#: libpq/hba.c:1249
+#: libpq/hba.c:1395
#, c-format
msgid "gssapi authentication is not supported on local sockets"
msgstr "gssapi-Authentifizierung wird auf lokalen Sockets nicht unterstützt"
-#: libpq/hba.c:1260
+#: libpq/hba.c:1407
#, c-format
msgid "peer authentication is only supported on local sockets"
msgstr "peer-Authentifizierung wird nur auf lokalen Sockets unterstützt"
-#: libpq/hba.c:1277
+#: libpq/hba.c:1425
#, c-format
msgid "cert authentication is only supported on hostssl connections"
msgstr "cert-Authentifizierung wird nur auf »hostssl«-Verbindungen unterstützt"
-#: libpq/hba.c:1326
+#: libpq/hba.c:1475
#, c-format
msgid "authentication option not in name=value format: %s"
msgstr "Authentifizierungsoption nicht im Format name=wert: %s"
-#: libpq/hba.c:1363
+#: libpq/hba.c:1514
#, c-format
msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix"
msgstr "ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute oder ldapurl kann nicht zusammen mit ldapprefix verwendet werden"
-#: libpq/hba.c:1373
+#: libpq/hba.c:1525
#, c-format
msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set"
msgstr "Authentifizierungsmethode »ldap« benötigt Argument »ldapbasedn«, »ldapprefix« oder »ldapsuffix«"
-#: libpq/hba.c:1416
+#: libpq/hba.c:1573
msgid "ident, peer, gssapi, sspi, and cert"
msgstr "ident, peer, gssapi, sspi und cert"
-#: libpq/hba.c:1429
+#: libpq/hba.c:1582
#, c-format
msgid "clientcert can only be configured for \"hostssl\" rows"
msgstr "clientcert kann nur für »hostssl«-Zeilen konfiguriert werden"
-#: libpq/hba.c:1440
-#, c-format
-msgid "client certificates can only be checked if a root certificate store is available"
-msgstr "Client-Zertifikate können nur überprüft werden, wenn Wurzelzertifikat verfügbar ist"
-
-#: libpq/hba.c:1454
+#: libpq/hba.c:1598
#, c-format
msgid "clientcert can not be set to 0 when using \"cert\" authentication"
msgstr "clientcert kann nicht auf 0 gesetzt sein, wenn »cert«-Authentifizierung verwendet wird"
-#: libpq/hba.c:1490
+#: libpq/hba.c:1635
#, c-format
msgid "could not parse LDAP URL \"%s\": %s"
msgstr "konnte LDAP-URL »%s« nicht interpretieren: %s"
-#: libpq/hba.c:1498
+#: libpq/hba.c:1645
#, c-format
msgid "unsupported LDAP URL scheme: %s"
msgstr "nicht unterstütztes LDAP-URL-Schema: %s"
-#: libpq/hba.c:1514
+#: libpq/hba.c:1663
#, c-format
msgid "filters not supported in LDAP URLs"
msgstr "Filter in LDAP-URLs werden nicht unterstützt"
-#: libpq/hba.c:1522
+#: libpq/hba.c:1672
#, c-format
msgid "LDAP URLs not supported on this platform"
msgstr "LDAP-URLs werden auf dieser Plattform nicht unterstützt"
-#: libpq/hba.c:1546
+#: libpq/hba.c:1697
#, c-format
msgid "invalid LDAP port number: \"%s\""
msgstr "ungültige LDAP-Portnummer: »%s«"
-#: libpq/hba.c:1586 libpq/hba.c:1593
+#: libpq/hba.c:1738 libpq/hba.c:1745
msgid "gssapi and sspi"
msgstr "gssapi und sspi"
-#: libpq/hba.c:1602 libpq/hba.c:1611
+#: libpq/hba.c:1754 libpq/hba.c:1763
msgid "sspi"
msgstr "sspi"
-#: libpq/hba.c:1653
+#: libpq/hba.c:1807
#, c-format
msgid "invalid RADIUS port number: \"%s\""
msgstr "ungültige RADIUS-Portnummer: »%s«"
-#: libpq/hba.c:1673
+#: libpq/hba.c:1828
#, c-format
msgid "unrecognized authentication option name: \"%s\""
msgstr "unbekannter Authentifizierungsoptionsname: »%s«"
-#: libpq/hba.c:1859
+#: libpq/hba.c:2012
#, c-format
msgid "configuration file \"%s\" contains no entries"
msgstr "Konfigurationsdatei »%s« enthält keine Einträge"
-#: libpq/hba.c:1955
+#: libpq/hba.c:2517
#, c-format
msgid "invalid regular expression \"%s\": %s"
msgstr "ungültiger regulärer Ausdruck »%s«: %s"
-#: libpq/hba.c:2015
+#: libpq/hba.c:2577
#, c-format
msgid "regular expression match for \"%s\" failed: %s"
msgstr "Suche nach regulärem Ausdruck für »%s« fehlgeschlagen: %s"
-#: libpq/hba.c:2034
+#: libpq/hba.c:2596
#, c-format
msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\""
msgstr "regulärer Ausdruck »%s« hat keine Teilausdrücke wie von der Backreference in »%s« verlangt"
-#: libpq/hba.c:2131
+#: libpq/hba.c:2693
#, c-format
msgid "provided user name (%s) and authenticated user name (%s) do not match"
msgstr "angegebener Benutzername (%s) und authentifizierter Benutzername (%s) stimmen nicht überein"
-#: libpq/hba.c:2151
+#: libpq/hba.c:2713
#, c-format
msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\""
msgstr "kein passender Eintrag in Usermap »%s« für Benutzer »%s«, authentifiziert als »%s«"
-#: libpq/hba.c:2186
+#: libpq/hba.c:2746
#, c-format
msgid "could not open usermap file \"%s\": %m"
msgstr "konnte Usermap-Datei »%s« nicht öffnen: %m"
-#: libpq/pqcomm.c:202
+#: libpq/pqcomm.c:201
#, c-format
msgid "could not set socket to nonblocking mode: %m"
msgstr "konnte Socket nicht auf nicht-blockierenden Modus umstellen: %m"
-#: libpq/pqcomm.c:354
+#: libpq/pqcomm.c:355
#, c-format
msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)"
msgstr "Unix-Domain-Socket-Pfad »%s« ist zu lang (maximal %d Bytes)"
-#: libpq/pqcomm.c:375
+#: libpq/pqcomm.c:376
#, c-format
msgid "could not translate host name \"%s\", service \"%s\" to address: %s"
msgstr "konnte Hostname »%s«, Dienst »%s« nicht in Adresse übersetzen: %s"
-#: libpq/pqcomm.c:379
+#: libpq/pqcomm.c:380
#, c-format
msgid "could not translate service \"%s\" to address: %s"
msgstr "konnte Dienst »%s« nicht in Adresse übersetzen: %s"
-#: libpq/pqcomm.c:406
+#: libpq/pqcomm.c:407
#, c-format
msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded"
msgstr "konnte nicht an alle verlangten Adressen binden: MAXLISTEN (%d) überschritten"
-#: libpq/pqcomm.c:415
+#: libpq/pqcomm.c:416
msgid "IPv4"
msgstr "IPv4"
-#: libpq/pqcomm.c:419
+#: libpq/pqcomm.c:420
msgid "IPv6"
msgstr "IPv6"
-#: libpq/pqcomm.c:424
+#: libpq/pqcomm.c:425
msgid "Unix"
msgstr "Unix"
-#: libpq/pqcomm.c:429
+#: libpq/pqcomm.c:430
#, c-format
msgid "unrecognized address family %d"
msgstr "unbekannte Adressfamilie %d"
-#. translator: %s is IPv4, IPv6, or Unix
-#: libpq/pqcomm.c:440
-#, c-format
-msgid "could not create %s socket: %m"
-msgstr "konnte %s-Socket nicht erstellen: %m"
+#. translator: first %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:456
+#, fuzzy, c-format
+#| msgid "could not create listen socket for \"%s\""
+msgid "could not create %s socket for address \"%s\": %m"
+msgstr "konnte Listen-Socket für »%s« nicht erzeugen"
-#: libpq/pqcomm.c:465
-#, c-format
-msgid "setsockopt(SO_REUSEADDR) failed: %m"
+#. translator: first %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:482
+#, fuzzy, c-format
+#| msgid "setsockopt(SO_REUSEADDR) failed: %m"
+msgid "setsockopt(SO_REUSEADDR) failed for %s address \"%s\": %m"
msgstr "setsockopt(SO_REUSEADDR) fehlgeschlagen: %m"
-#: libpq/pqcomm.c:480
-#, c-format
-msgid "setsockopt(IPV6_V6ONLY) failed: %m"
+#. translator: first %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:499
+#, fuzzy, c-format
+#| msgid "setsockopt(IPV6_V6ONLY) failed: %m"
+msgid "setsockopt(IPV6_V6ONLY) failed for %s address \"%s\": %m"
msgstr "setsockopt(IPV6_V6ONLY) fehlgeschlagen: %m"
-#. translator: %s is IPv4, IPv6, or Unix
-#: libpq/pqcomm.c:499
-#, c-format
-msgid "could not bind %s socket: %m"
-msgstr "konnte %s-Socket nicht binden: %m"
+#. translator: first %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:519
+#, fuzzy, c-format
+#| msgid "could not bind to local address \"%s\": %m"
+msgid "could not bind %s address \"%s\": %m"
+msgstr "konnte nicht mit lokaler Adresse »%s« verbinden: %m"
-#: libpq/pqcomm.c:502
+#: libpq/pqcomm.c:522
#, c-format
msgid "Is another postmaster already running on port %d? If not, remove socket file \"%s\" and retry."
msgstr "Läuft bereits ein anderer Postmaster auf Port %d? Wenn nicht, entfernen Sie die Socketdatei »%s« und versuchen Sie erneut."
-#: libpq/pqcomm.c:505
+#: libpq/pqcomm.c:525
#, c-format
msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry."
msgstr "Läuft bereits ein anderer Postmaster auf Port %d? Wenn nicht, warten Sie einige Sekunden und versuchen Sie erneut."
-#. translator: %s is IPv4, IPv6, or Unix
-#: libpq/pqcomm.c:538
-#, c-format
-msgid "could not listen on %s socket: %m"
-msgstr "konnte nicht auf %s-Socket hören: %m"
+#. translator: first %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:558
+#, fuzzy, c-format
+#| msgid "could not bind to local address \"%s\": %m"
+msgid "could not listen on %s address \"%s\": %m"
+msgstr "konnte nicht mit lokaler Adresse »%s« verbinden: %m"
+
+#. translator: first %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:566
+#, fuzzy, c-format
+#| msgid "invalid CIDR mask in address \"%s\""
+msgid "listening on %s address \"%s\""
+msgstr "ungültige CIDR-Maske in Adresse »%s«"
-#: libpq/pqcomm.c:623
+#: libpq/pqcomm.c:649
#, c-format
msgid "group \"%s\" does not exist"
msgstr "Gruppe »%s« existiert nicht"
-#: libpq/pqcomm.c:633
+#: libpq/pqcomm.c:659
#, c-format
msgid "could not set group of file \"%s\": %m"
msgstr "konnte Gruppe von Datei »%s« nicht setzen: %m"
-#: libpq/pqcomm.c:644
+#: libpq/pqcomm.c:670
#, c-format
msgid "could not set permissions of file \"%s\": %m"
msgstr "konnte Zugriffsrechte von Datei »%s« nicht setzen: %m"
-#: libpq/pqcomm.c:674
+#: libpq/pqcomm.c:700
#, c-format
msgid "could not accept new connection: %m"
msgstr "konnte neue Verbindung nicht akzeptieren: %m"
-#: libpq/pqcomm.c:885
+#: libpq/pqcomm.c:901
#, c-format
msgid "there is no client connection"
msgstr "es besteht keine Client-Verbindung"
-#: libpq/pqcomm.c:936 libpq/pqcomm.c:1032
+#: libpq/pqcomm.c:952 libpq/pqcomm.c:1048
#, c-format
msgid "could not receive data from client: %m"
msgstr "konnte Daten vom Client nicht empfangen: %m"
-#: libpq/pqcomm.c:1177 tcop/postgres.c:3921
+#: libpq/pqcomm.c:1193 tcop/postgres.c:3907
#, c-format
msgid "terminating connection because protocol synchronization was lost"
msgstr "Verbindung wird abgebrochen, weil Protokollsynchronisierung verloren wurde"
-#: libpq/pqcomm.c:1243
+#: libpq/pqcomm.c:1259
#, c-format
msgid "unexpected EOF within message length word"
msgstr "unerwartetes EOF im Message-Längenwort"
-#: libpq/pqcomm.c:1254
+#: libpq/pqcomm.c:1270
#, c-format
msgid "invalid message length"
msgstr "ungültige Message-Länge"
-#: libpq/pqcomm.c:1276 libpq/pqcomm.c:1289
+#: libpq/pqcomm.c:1292 libpq/pqcomm.c:1305
#, c-format
msgid "incomplete message from client"
msgstr "unvollständige Message vom Client"
-#: libpq/pqcomm.c:1422
+#: libpq/pqcomm.c:1438
#, c-format
msgid "could not send data to client: %m"
msgstr "konnte Daten nicht an den Client senden: %m"
@@ -12212,763 +13129,795 @@ msgstr "erweiterbarer Knotentyp »%s« existiert bereits"
msgid "ExtensibleNodeMethods \"%s\" was not registered"
msgstr "ExtensibleNodeMethods »%s« wurde nicht registriert"
-#: nodes/nodeFuncs.c:124 nodes/nodeFuncs.c:155 parser/parse_coerce.c:1820
-#: parser/parse_coerce.c:1848 parser/parse_coerce.c:1924
-#: parser/parse_expr.c:2019 parser/parse_func.c:597 parser/parse_oper.c:952
+#: nodes/nodeFuncs.c:123 nodes/nodeFuncs.c:154 parser/parse_coerce.c:1844
+#: parser/parse_coerce.c:1872 parser/parse_coerce.c:1948
+#: parser/parse_expr.c:2089 parser/parse_func.c:598 parser/parse_oper.c:958
#, c-format
msgid "could not find array type for data type %s"
msgstr "konnte Arraytyp für Datentyp %s nicht finden"
-#: optimizer/path/allpaths.c:2676
-#, c-format
-msgid "WHERE CURRENT OF is not supported on a view with no underlying relation"
-msgstr "WHERE CURRENT OF wird nicht unterstützt für Sichten ohne zugrundeliegende Relation"
-
-#: optimizer/path/allpaths.c:2681
-#, c-format
-msgid "WHERE CURRENT OF is not supported on a view with more than one underlying relation"
-msgstr "WHERE CURRENT OF wird nicht unterstützt für Sichten mit mehr als einer zugrundeliegenden Relation"
-
-#: optimizer/path/allpaths.c:2686
-#, c-format
-msgid "WHERE CURRENT OF is not supported on a view with grouping or aggregation"
-msgstr "WHERE CURRENT OF wird nicht unterstützt für Sichten mit Gruppierung oder Aggregierung"
-
#: optimizer/path/joinrels.c:802
#, c-format
msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions"
msgstr "FULL JOIN wird nur für Merge- oder Hash-Verbund-fähige Verbundbedingungen unterstützt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: optimizer/plan/initsplan.c:1124
+#: optimizer/plan/initsplan.c:1200
#, c-format
msgid "%s cannot be applied to the nullable side of an outer join"
msgstr "%s kann nicht auf die nullbare Seite eines äußeren Verbundes angewendet werden"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: optimizer/plan/planner.c:1497 parser/analyze.c:1552 parser/analyze.c:1750
-#: parser/analyze.c:2531
+#: optimizer/plan/planner.c:1480 parser/analyze.c:1619 parser/analyze.c:1816
+#: parser/analyze.c:2610
#, c-format
msgid "%s is not allowed with UNION/INTERSECT/EXCEPT"
msgstr "%s ist nicht in UNION/INTERSECT/EXCEPT erlaubt"
-#: optimizer/plan/planner.c:3826
+#: optimizer/plan/planner.c:3854
#, c-format
msgid "could not implement GROUP BY"
msgstr "konnte GROUP BY nicht implementieren"
-#: optimizer/plan/planner.c:3827 optimizer/plan/planner.c:4220
-#: optimizer/prep/prepunion.c:929
+#: optimizer/plan/planner.c:3855 optimizer/plan/planner.c:4257
+#: optimizer/prep/prepunion.c:928
#, c-format
msgid "Some of the datatypes only support hashing, while others only support sorting."
msgstr "Einige Datentypen unterstützen nur Hashing, während andere nur Sortieren unterstützen."
-#: optimizer/plan/planner.c:4219
+#: optimizer/plan/planner.c:4256
#, c-format
msgid "could not implement DISTINCT"
msgstr "konnte DISTINCT nicht implementieren"
-#: optimizer/plan/planner.c:4849
+#: optimizer/plan/planner.c:4936
#, c-format
msgid "could not implement window PARTITION BY"
msgstr "konnte PARTITION BY für Fenster nicht implementieren"
-#: optimizer/plan/planner.c:4850
+#: optimizer/plan/planner.c:4937
#, c-format
msgid "Window partitioning columns must be of sortable datatypes."
msgstr "Fensterpartitionierungsspalten müssen sortierbare Datentypen haben."
-#: optimizer/plan/planner.c:4854
+#: optimizer/plan/planner.c:4941
#, c-format
msgid "could not implement window ORDER BY"
msgstr "konnte ORDER BY für Fenster nicht implementieren"
-#: optimizer/plan/planner.c:4855
+#: optimizer/plan/planner.c:4942
#, c-format
msgid "Window ordering columns must be of sortable datatypes."
msgstr "Fenstersortierspalten müssen sortierbare Datentypen haben."
-#: optimizer/plan/setrefs.c:415
+#: optimizer/plan/setrefs.c:413
#, c-format
msgid "too many range table entries"
msgstr "zu viele Range-Table-Einträge"
-#: optimizer/prep/prepunion.c:484
+#: optimizer/prep/prepunion.c:483
#, c-format
msgid "could not implement recursive UNION"
msgstr "konnte rekursive UNION nicht implementieren"
-#: optimizer/prep/prepunion.c:485
+#: optimizer/prep/prepunion.c:484
#, c-format
msgid "All column datatypes must be hashable."
msgstr "Alle Spaltendatentypen müssen hashbar sein."
#. translator: %s is UNION, INTERSECT, or EXCEPT
-#: optimizer/prep/prepunion.c:928
+#: optimizer/prep/prepunion.c:927
#, c-format
msgid "could not implement %s"
msgstr "konnte %s nicht implementieren"
-#: optimizer/util/clauses.c:4545
+#: optimizer/util/clauses.c:4634
#, c-format
msgid "SQL function \"%s\" during inlining"
msgstr "SQL-Funktion »%s« beim Inlining"
-#: optimizer/util/plancat.c:113
+#: optimizer/util/plancat.c:115
#, c-format
msgid "cannot access temporary or unlogged relations during recovery"
msgstr "während der Wiederherstellung kann nicht auf temporäre oder ungeloggte Tabellen zugegriffen werden"
-#: optimizer/util/plancat.c:598
+#: optimizer/util/plancat.c:613
#, c-format
msgid "whole row unique index inference specifications are not supported"
msgstr "Inferenzangaben mit Unique-Index über die gesamte Zeile werden nicht unterstützt"
-#: optimizer/util/plancat.c:615
+#: optimizer/util/plancat.c:630
#, c-format
msgid "constraint in ON CONFLICT clause has no associated index"
msgstr "Constraint in der ON-CONFLICT-Klausel hat keinen zugehörigen Index"
-#: optimizer/util/plancat.c:666
+#: optimizer/util/plancat.c:681
#, c-format
msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints"
msgstr "ON CONFLICT DO UDPATE nicht unterstützt mit Exclusion-Constraints"
-#: optimizer/util/plancat.c:771
+#: optimizer/util/plancat.c:786
#, c-format
msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification"
msgstr "es gibt keinen Unique-Constraint oder Exclusion-Constraint, der auf die ON-CONFLICT-Angabe passt"
-#: parser/analyze.c:663 parser/analyze.c:1324
+#: parser/analyze.c:695 parser/analyze.c:1382
#, c-format
msgid "VALUES lists must all be the same length"
msgstr "VALUES-Listen müssen alle die gleiche Länge haben"
-#: parser/analyze.c:859
+#: parser/analyze.c:850
+#, fuzzy, c-format
+#| msgid "ON CONFLICT is not supported with system catalog tables"
+msgid "ON CONFLICT clause is not supported with partitioned tables"
+msgstr "ON CONFLICT wird nicht mit Systemkatalogtabellen unterstützt"
+
+#: parser/analyze.c:913
#, c-format
msgid "INSERT has more expressions than target columns"
msgstr "INSERT hat mehr Ausdrücke als Zielspalten"
-#: parser/analyze.c:877
+#: parser/analyze.c:931
#, c-format
msgid "INSERT has more target columns than expressions"
msgstr "INSERT hat mehr Zielspalten als Ausdrücke"
-#: parser/analyze.c:881
+#: parser/analyze.c:935
#, c-format
msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?"
msgstr "Der einzufügende Wert ist ein Zeilenausdruck mit der gleichen Anzahl Spalten wie von INSERT erwartet. Haben Sie versehentlich zu viele Klammern gesetzt?"
-#: parser/analyze.c:1145 parser/analyze.c:1525
+#: parser/analyze.c:1195 parser/analyze.c:1592
#, c-format
msgid "SELECT ... INTO is not allowed here"
msgstr "SELECT ... INTO ist hier nicht erlaubt"
-#: parser/analyze.c:1338
-#, c-format
-msgid "DEFAULT can only appear in a VALUES list within INSERT"
-msgstr "DEFAULT kann nur in VALUES-Liste innerhalb von INSERT auftreten"
-
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:1457 parser/analyze.c:2701
+#: parser/analyze.c:1524 parser/analyze.c:2789
#, c-format
msgid "%s cannot be applied to VALUES"
msgstr "%s kann nicht auf VALUES angewendet werden"
-#: parser/analyze.c:1678
+#: parser/analyze.c:1743
#, c-format
msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause"
msgstr "ungültige ORDER-BY-Klausel mit UNION/INTERSECT/EXCEPT"
-#: parser/analyze.c:1679
+#: parser/analyze.c:1744
#, c-format
msgid "Only result column names can be used, not expressions or functions."
msgstr "Es können nur Ergebnisspaltennamen verwendet werden, keine Ausdrücke oder Funktionen."
-#: parser/analyze.c:1680
+#: parser/analyze.c:1745
#, c-format
msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause."
msgstr "Fügen Sie den Ausdrück/die Funktion jedem SELECT hinzu oder verlegen Sie die UNION in eine FROM-Klausel."
-#: parser/analyze.c:1740
+#: parser/analyze.c:1806
#, c-format
msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"
msgstr "INTO ist nur im ersten SELECT von UNION/INTERSECT/EXCEPT erlaubt"
-#: parser/analyze.c:1804
+#: parser/analyze.c:1878
#, c-format
msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"
msgstr "Teilanweisung von UNION/INTERSECT/EXCEPT kann nicht auf andere Relationen auf der selben Anfrageebene verweisen"
-#: parser/analyze.c:1893
+#: parser/analyze.c:1967
#, c-format
msgid "each %s query must have the same number of columns"
msgstr "jede %s-Anfrage muss die gleiche Anzahl Spalten haben"
-#: parser/analyze.c:2286
+#: parser/analyze.c:2360
#, c-format
msgid "RETURNING must have at least one column"
msgstr "RETURNING muss mindestens eine Spalte haben"
-#: parser/analyze.c:2323
+#: parser/analyze.c:2401
#, c-format
msgid "cannot specify both SCROLL and NO SCROLL"
msgstr "SCROLL und NO SCROLL können nicht beide angegeben werden"
-#: parser/analyze.c:2341
+#: parser/analyze.c:2420
#, c-format
msgid "DECLARE CURSOR must not contain data-modifying statements in WITH"
msgstr "DECLARE CURSOR darf keine datenmodifizierenden Anweisungen in WITH enthalten"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2349
+#: parser/analyze.c:2428
#, c-format
msgid "DECLARE CURSOR WITH HOLD ... %s is not supported"
msgstr "DECLARE CURSOR WITH HOLD ... %s wird nicht unterstützt"
-#: parser/analyze.c:2352
+#: parser/analyze.c:2431
#, c-format
msgid "Holdable cursors must be READ ONLY."
msgstr "Haltbare Cursor müssen READ ONLY sein."
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2360
+#: parser/analyze.c:2439
#, c-format
msgid "DECLARE SCROLL CURSOR ... %s is not supported"
msgstr "DECLARE SCROLL CURSOR ... %s wird nicht unterstützt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2371
+#: parser/analyze.c:2450
#, c-format
msgid "DECLARE INSENSITIVE CURSOR ... %s is not supported"
msgstr "DECLARE INSENSITIVE CURSOR ... %s wird nicht unterstützt"
-#: parser/analyze.c:2374
+#: parser/analyze.c:2453
#, c-format
msgid "Insensitive cursors must be READ ONLY."
msgstr "Insensitive Cursor müssen READ ONLY sein."
-#: parser/analyze.c:2440
+#: parser/analyze.c:2519
#, c-format
msgid "materialized views must not use data-modifying statements in WITH"
msgstr "materialisierte Sichten dürfen keine datenmodifizierenden Anweisungen in WITH verwenden"
-#: parser/analyze.c:2450
+#: parser/analyze.c:2529
#, c-format
msgid "materialized views must not use temporary tables or views"
msgstr "materialisierte Sichten dürfen keine temporären Tabellen oder Sichten verwenden"
-#: parser/analyze.c:2460
+#: parser/analyze.c:2539
#, c-format
msgid "materialized views may not be defined using bound parameters"
msgstr "materialisierte Sichten können nicht unter Verwendung von gebundenen Parametern definiert werden"
-#: parser/analyze.c:2472
+#: parser/analyze.c:2551
#, c-format
msgid "materialized views cannot be UNLOGGED"
msgstr "materialisierte Sichten können nicht UNLOGGED sein"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2538
+#: parser/analyze.c:2617
#, c-format
msgid "%s is not allowed with DISTINCT clause"
msgstr "%s ist nicht mit DISTINCT-Klausel erlaubt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2545
+#: parser/analyze.c:2624
#, c-format
msgid "%s is not allowed with GROUP BY clause"
msgstr "%s ist nicht mit GROUP-BY-Klausel erlaubt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2552
+#: parser/analyze.c:2631
#, c-format
msgid "%s is not allowed with HAVING clause"
msgstr "%s ist nicht mit HAVING-Klausel erlaubt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2559
+#: parser/analyze.c:2638
#, c-format
msgid "%s is not allowed with aggregate functions"
msgstr "%s ist nicht mit Aggregatfunktionen erlaubt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2566
+#: parser/analyze.c:2645
#, c-format
msgid "%s is not allowed with window functions"
msgstr "%s ist nicht mit Fensterfunktionen erlaubt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2573
+#: parser/analyze.c:2652
#, c-format
msgid "%s is not allowed with set-returning functions in the target list"
msgstr "%s ist nicht mit Funktionen mit Ergebnismenge in der Targetliste erlaubt"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2652
+#: parser/analyze.c:2731
#, c-format
msgid "%s must specify unqualified relation names"
msgstr "%s muss unqualifizierte Relationsnamen angeben"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2683
+#: parser/analyze.c:2762
#, c-format
msgid "%s cannot be applied to a join"
msgstr "%s kann nicht auf einen Verbund angewendet werden"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2692
+#: parser/analyze.c:2771
#, c-format
msgid "%s cannot be applied to a function"
msgstr "%s kann nicht auf eine Funktion angewendet werden"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2710
+#: parser/analyze.c:2780
+#, fuzzy, c-format
+#| msgid "%s cannot be applied to a function"
+msgid "%s cannot be applied to a table function"
+msgstr "%s kann nicht auf eine Funktion angewendet werden"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2798
#, c-format
msgid "%s cannot be applied to a WITH query"
msgstr "%s kann nicht auf eine WITH-Anfrage angewendet werden"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2727
+#: parser/analyze.c:2815
#, c-format
msgid "relation \"%s\" in %s clause not found in FROM clause"
msgstr "Relation »%s« in %s nicht in der FROM-Klausel gefunden"
-#: parser/parse_agg.c:223 parser/parse_oper.c:220
+#: parser/parse_agg.c:221 parser/parse_oper.c:222
#, c-format
msgid "could not identify an ordering operator for type %s"
msgstr "konnte keine Sortieroperator für Typ %s ermitteln"
-#: parser/parse_agg.c:225
+#: parser/parse_agg.c:223
#, c-format
msgid "Aggregates with DISTINCT must be able to sort their inputs."
msgstr "Aggregatfunktionen mit DISTINCT müssen ihre Eingaben sortieren können."
-#: parser/parse_agg.c:260
+#: parser/parse_agg.c:258
#, c-format
msgid "GROUPING must have fewer than 32 arguments"
msgstr "GROUPING muss weniger als 32 Argumente haben"
-#: parser/parse_agg.c:363
+#: parser/parse_agg.c:361
msgid "aggregate functions are not allowed in JOIN conditions"
msgstr "Aggregatfunktionen sind in JOIN-Bedingungen nicht erlaubt"
-#: parser/parse_agg.c:365
+#: parser/parse_agg.c:363
msgid "grouping operations are not allowed in JOIN conditions"
msgstr "Gruppieroperationen sind in JOIN-Bedingungen nicht erlaubt"
-#: parser/parse_agg.c:377
+#: parser/parse_agg.c:375
msgid "aggregate functions are not allowed in FROM clause of their own query level"
msgstr "Aggregatfunktionen sind nicht in der FROM-Klausel ihrer eigenen Anfrageebene erlaubt"
-#: parser/parse_agg.c:379
+#: parser/parse_agg.c:377
msgid "grouping operations are not allowed in FROM clause of their own query level"
msgstr "Gruppieroperationen sind nicht in der FROM-Klausel ihrer eigenen Anfrageebene erlaubt"
-#: parser/parse_agg.c:384
+#: parser/parse_agg.c:382
msgid "aggregate functions are not allowed in functions in FROM"
msgstr "Aggregatfunktionen sind in Funktionen in FROM nicht erlaubt"
-#: parser/parse_agg.c:386
+#: parser/parse_agg.c:384
msgid "grouping operations are not allowed in functions in FROM"
msgstr "Gruppieroperationen sind in Funktionen in FROM nicht erlaubt"
-#: parser/parse_agg.c:394
+#: parser/parse_agg.c:392
msgid "aggregate functions are not allowed in policy expressions"
msgstr "Aggregatfunktionen sind in Policy-Ausdrücken nicht erlaubt"
-#: parser/parse_agg.c:396
+#: parser/parse_agg.c:394
msgid "grouping operations are not allowed in policy expressions"
msgstr "Gruppieroperationen sind in Policy-Ausdrücken nicht erlaubt"
-#: parser/parse_agg.c:413
+#: parser/parse_agg.c:411
msgid "aggregate functions are not allowed in window RANGE"
msgstr "Aggregatfunktionen sind in der Fenster-RANGE-Klausel nicht erlaubt"
-#: parser/parse_agg.c:415
+#: parser/parse_agg.c:413
msgid "grouping operations are not allowed in window RANGE"
msgstr "Gruppieroperationen sind in der Fenster-RANGE-Klausel nicht erlaubt"
-#: parser/parse_agg.c:420
+#: parser/parse_agg.c:418
msgid "aggregate functions are not allowed in window ROWS"
msgstr "Aggregatfunktionen sind in der Fenster-ROWS-Klausel nicht erlaubt"
-#: parser/parse_agg.c:422
+#: parser/parse_agg.c:420
msgid "grouping operations are not allowed in window ROWS"
msgstr "Gruppieroperationen sind in der Fenster-ROWS-Klausel nicht erlaubt"
-#: parser/parse_agg.c:455
+#: parser/parse_agg.c:454
msgid "aggregate functions are not allowed in check constraints"
msgstr "Aggregatfunktionen sind in Check-Constraints nicht erlaubt"
-#: parser/parse_agg.c:457
+#: parser/parse_agg.c:456
msgid "grouping operations are not allowed in check constraints"
msgstr "Gruppieroperationen sind in Check-Constraints nicht erlaubt"
-#: parser/parse_agg.c:464
+#: parser/parse_agg.c:463
msgid "aggregate functions are not allowed in DEFAULT expressions"
msgstr "Aggregatfunktionen sind in DEFAULT-Ausdrücken nicht erlaubt"
-#: parser/parse_agg.c:466
+#: parser/parse_agg.c:465
msgid "grouping operations are not allowed in DEFAULT expressions"
msgstr "Gruppieroperationen sind in DEFAULT-Ausdrücken nicht erlaubt"
-#: parser/parse_agg.c:471
+#: parser/parse_agg.c:470
msgid "aggregate functions are not allowed in index expressions"
msgstr "Aggregatfunktionen sind in Indexausdrücken nicht erlaubt"
-#: parser/parse_agg.c:473
+#: parser/parse_agg.c:472
msgid "grouping operations are not allowed in index expressions"
msgstr "Gruppieroperationen sind in Indexausdrücken nicht erlaubt"
-#: parser/parse_agg.c:478
+#: parser/parse_agg.c:477
msgid "aggregate functions are not allowed in index predicates"
msgstr "Aggregatfunktionen sind in Indexprädikaten nicht erlaubt"
-#: parser/parse_agg.c:480
+#: parser/parse_agg.c:479
msgid "grouping operations are not allowed in index predicates"
msgstr "Gruppieroperationen sind in Indexprädikaten nicht erlaubt"
-#: parser/parse_agg.c:485
+#: parser/parse_agg.c:484
msgid "aggregate functions are not allowed in transform expressions"
msgstr "Aggregatfunktionen sind in Umwandlungsausdrücken nicht erlaubt"
-#: parser/parse_agg.c:487
+#: parser/parse_agg.c:486
msgid "grouping operations are not allowed in transform expressions"
msgstr "Gruppieroperationen sind in Umwandlungsausdrücken nicht erlaubt"
-#: parser/parse_agg.c:492
+#: parser/parse_agg.c:491
msgid "aggregate functions are not allowed in EXECUTE parameters"
msgstr "Aggregatfunktionen sind in EXECUTE-Parametern nicht erlaubt"
-#: parser/parse_agg.c:494
+#: parser/parse_agg.c:493
msgid "grouping operations are not allowed in EXECUTE parameters"
msgstr "Gruppieroperationen sind in EXECUTE-Parametern nicht erlaubt"
-#: parser/parse_agg.c:499
+#: parser/parse_agg.c:498
msgid "aggregate functions are not allowed in trigger WHEN conditions"
msgstr "Aggregatfunktionen sind in der WHEN-Bedingung eines Triggers nicht erlaubt"
-#: parser/parse_agg.c:501
+#: parser/parse_agg.c:500
msgid "grouping operations are not allowed in trigger WHEN conditions"
msgstr "Gruppieroperationen sind in der WHEN-Bedingung eines Triggers nicht erlaubt"
+#: parser/parse_agg.c:505
+#, fuzzy
+#| msgid "aggregate functions are not allowed in index expressions"
+msgid "aggregate functions are not allowed in partition key expression"
+msgstr "Aggregatfunktionen sind in Indexausdrücken nicht erlaubt"
+
+#: parser/parse_agg.c:507
+#, fuzzy
+#| msgid "grouping operations are not allowed in index expressions"
+msgid "grouping operations are not allowed in partition key expression"
+msgstr "Gruppieroperationen sind in Indexausdrücken nicht erlaubt"
+
#. translator: %s is name of a SQL construct, eg GROUP BY
-#: parser/parse_agg.c:524 parser/parse_clause.c:1550
+#: parser/parse_agg.c:530 parser/parse_clause.c:1767
#, c-format
msgid "aggregate functions are not allowed in %s"
msgstr "Aggregatfunktionen sind in %s nicht erlaubt"
#. translator: %s is name of a SQL construct, eg GROUP BY
-#: parser/parse_agg.c:527
+#: parser/parse_agg.c:533
#, c-format
msgid "grouping operations are not allowed in %s"
msgstr "Gruppieroperationen sind in %s nicht erlaubt"
-#: parser/parse_agg.c:635
+#: parser/parse_agg.c:641
#, c-format
msgid "outer-level aggregate cannot contain a lower-level variable in its direct arguments"
msgstr "Aggregatfunktion auf äußerer Ebene kann keine Variable einer unteren Ebene in ihren direkten Argumenten haben"
-#: parser/parse_agg.c:706
+#: parser/parse_agg.c:712
#, c-format
msgid "aggregate function calls cannot contain window function calls"
msgstr "Aufrufe von Aggregatfunktionen können keine Aufrufe von Fensterfunktionen enthalten"
-#: parser/parse_agg.c:784
+#: parser/parse_agg.c:790
msgid "window functions are not allowed in JOIN conditions"
msgstr "Fensterfunktionen sind in JOIN-Bedingungen nicht erlaubt"
-#: parser/parse_agg.c:791
+#: parser/parse_agg.c:797
msgid "window functions are not allowed in functions in FROM"
msgstr "Fensterfunktionen sind in Funktionen in FROM nicht erlaubt"
-#: parser/parse_agg.c:797
+#: parser/parse_agg.c:803
msgid "window functions are not allowed in policy expressions"
msgstr "Fensterfunktionen sind in Policy-Ausdrücken nicht erlaubt"
-#: parser/parse_agg.c:809
+#: parser/parse_agg.c:815
msgid "window functions are not allowed in window definitions"
msgstr "Fensterfunktionen sind in Fensterdefinitionen nicht erlaubt"
-#: parser/parse_agg.c:840
+#: parser/parse_agg.c:847
msgid "window functions are not allowed in check constraints"
msgstr "Fensterfunktionen sind in Check-Constraints nicht erlaubt"
-#: parser/parse_agg.c:844
+#: parser/parse_agg.c:851
msgid "window functions are not allowed in DEFAULT expressions"
msgstr "Fensterfunktionen sind in DEFAULT-Ausdrücken nicht erlaubt"
-#: parser/parse_agg.c:847
+#: parser/parse_agg.c:854
msgid "window functions are not allowed in index expressions"
msgstr "Fensterfunktionen sind in Indexausdrücken nicht erlaubt"
-#: parser/parse_agg.c:850
+#: parser/parse_agg.c:857
msgid "window functions are not allowed in index predicates"
msgstr "Fensterfunktionen sind in Indexprädikaten nicht erlaubt"
-#: parser/parse_agg.c:853
+#: parser/parse_agg.c:860
msgid "window functions are not allowed in transform expressions"
msgstr "Fensterfunktionen sind in Umwandlungsausdrücken nicht erlaubt"
-#: parser/parse_agg.c:856
+#: parser/parse_agg.c:863
msgid "window functions are not allowed in EXECUTE parameters"
msgstr "Fensterfunktionen sind in EXECUTE-Parametern nicht erlaubt"
-#: parser/parse_agg.c:859
+#: parser/parse_agg.c:866
msgid "window functions are not allowed in trigger WHEN conditions"
msgstr "Fensterfunktionen sind in der WHEN-Bedingung eines Triggers nicht erlaubt"
+#: parser/parse_agg.c:869
+#, fuzzy
+#| msgid "window functions are not allowed in index expressions"
+msgid "window functions are not allowed in partition key expression"
+msgstr "Fensterfunktionen sind in Indexausdrücken nicht erlaubt"
+
#. translator: %s is name of a SQL construct, eg GROUP BY
-#: parser/parse_agg.c:879 parser/parse_clause.c:1559
+#: parser/parse_agg.c:889 parser/parse_clause.c:1776
#, c-format
msgid "window functions are not allowed in %s"
msgstr "Fensterfunktionen sind in %s nicht erlaubt"
-#: parser/parse_agg.c:913 parser/parse_clause.c:2396
+#: parser/parse_agg.c:923 parser/parse_clause.c:2610
#, c-format
msgid "window \"%s\" does not exist"
msgstr "Fenster »%s« existiert nicht"
-#: parser/parse_agg.c:998
+#: parser/parse_agg.c:1008
#, c-format
msgid "too many grouping sets present (maximum 4096)"
msgstr "zu viele Grouping-Sets vorhanden (maximal 4096)"
-#: parser/parse_agg.c:1147
+#: parser/parse_agg.c:1157
#, c-format
msgid "aggregate functions are not allowed in a recursive query's recursive term"
msgstr "Aggregatfunktionen sind nicht im rekursiven Ausdruck einer rekursiven Anfrage erlaubt"
-#: parser/parse_agg.c:1340
+#: parser/parse_agg.c:1350
#, c-format
msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function"
msgstr "Spalte »%s.%s« muss in der GROUP-BY-Klausel erscheinen oder in einer Aggregatfunktion verwendet werden"
-#: parser/parse_agg.c:1343
+#: parser/parse_agg.c:1353
#, c-format
msgid "Direct arguments of an ordered-set aggregate must use only grouped columns."
msgstr "Direkte Argumente einer Ordered-Set-Aggregatfunktion dürfen nur gruppierte Spalten verwenden."
-#: parser/parse_agg.c:1348
+#: parser/parse_agg.c:1358
#, c-format
msgid "subquery uses ungrouped column \"%s.%s\" from outer query"
msgstr "Unteranfrage verwendet nicht gruppierte Spalte »%s.%s« aus äußerer Anfrage"
-#: parser/parse_agg.c:1512
+#: parser/parse_agg.c:1522
#, c-format
msgid "arguments to GROUPING must be grouping expressions of the associated query level"
msgstr "Argumente von GROUPING müssen Gruppierausdrücke der zugehörigen Anfrageebene sein"
-#: parser/parse_clause.c:649
+#: parser/parse_clause.c:626
#, c-format
msgid "multiple column definition lists are not allowed for the same function"
msgstr "mehrere Spaltendefinitionslisten für die selbe Funktion sind nicht erlaubt"
-#: parser/parse_clause.c:682
+#: parser/parse_clause.c:659
#, c-format
msgid "ROWS FROM() with multiple functions cannot have a column definition list"
msgstr "ROWS FROM() mit mehreren Funktionen kann keine Spaltendefinitionsliste haben"
-#: parser/parse_clause.c:683
+#: parser/parse_clause.c:660
#, c-format
msgid "Put a separate column definition list for each function inside ROWS FROM()."
msgstr "Geben Sie innerhalb von ROWS FROM() jeder Funktion eine eigene Spaltendefinitionsliste."
-#: parser/parse_clause.c:689
+#: parser/parse_clause.c:666
#, c-format
msgid "UNNEST() with multiple arguments cannot have a column definition list"
msgstr "UNNEST() mit mehreren Argumenten kann keine Spaltendefinitionsliste haben"
-#: parser/parse_clause.c:690
+#: parser/parse_clause.c:667
#, c-format
msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one."
msgstr "Verwenden Sie getrennte UNNEST()-Aufrufe innerhalb von ROWS FROM() und geben Sie jeder eine eigene Spaltendefinitionsliste."
-#: parser/parse_clause.c:697
+#: parser/parse_clause.c:674
#, c-format
msgid "WITH ORDINALITY cannot be used with a column definition list"
msgstr "WITH ORDINALITY kann nicht mit einer Spaltendefinitionsliste verwendet werden"
-#: parser/parse_clause.c:698
+#: parser/parse_clause.c:675
#, c-format
msgid "Put the column definition list inside ROWS FROM()."
msgstr "Geben Sie die Spaltendefinitionsliste innerhalb von ROWS FROM() an."
-#: parser/parse_clause.c:753
+#: parser/parse_clause.c:779
+#, c-format
+msgid "only one FOR ORDINALITY column is allowed"
+msgstr ""
+
+#: parser/parse_clause.c:840
+#, c-format
+msgid "column name \"%s\" is not unique"
+msgstr "Spaltenname »%s« ist nicht eindeutig"
+
+#: parser/parse_clause.c:882
+#, fuzzy, c-format
+#| msgid "function %s is not unique"
+msgid "namespace name \"%s\" is not unique"
+msgstr "Funktion %s ist nicht eindeutig"
+
+#: parser/parse_clause.c:892
+#, c-format
+msgid "only one default namespace is allowed"
+msgstr ""
+
+#: parser/parse_clause.c:953
#, c-format
msgid "tablesample method %s does not exist"
msgstr "Tablesample-Methode %s existiert nicht"
-#: parser/parse_clause.c:775
+#: parser/parse_clause.c:975
#, c-format
msgid "tablesample method %s requires %d argument, not %d"
msgid_plural "tablesample method %s requires %d arguments, not %d"
msgstr[0] "Tablesample-Methode %s benötigt %d Argument, nicht %d"
msgstr[1] "Tablesample-Methode %s benötigt %d Argumente, nicht %d"
-#: parser/parse_clause.c:809
+#: parser/parse_clause.c:1009
#, c-format
msgid "tablesample method %s does not support REPEATABLE"
msgstr "Tablesample-Methode %s unterstützt REPEATABLE nicht"
-#: parser/parse_clause.c:940
+#: parser/parse_clause.c:1157
#, c-format
msgid "TABLESAMPLE clause can only be applied to tables and materialized views"
msgstr "TABLESAMPLE-Klausel kann nur auf Tabellen und materialisierte Sichten angewendet werden"
-#: parser/parse_clause.c:1110
+#: parser/parse_clause.c:1327
#, c-format
msgid "column name \"%s\" appears more than once in USING clause"
msgstr "Spaltenname »%s« erscheint mehrmals in der USING-Klausel"
-#: parser/parse_clause.c:1125
+#: parser/parse_clause.c:1342
#, c-format
msgid "common column name \"%s\" appears more than once in left table"
msgstr "gemeinsamer Spaltenname »%s« erscheint mehrmals in der linken Tabelle"
-#: parser/parse_clause.c:1134
+#: parser/parse_clause.c:1351
#, c-format
msgid "column \"%s\" specified in USING clause does not exist in left table"
msgstr "Spalte »%s« aus der USING-Klausel existiert nicht in der linken Tabelle"
-#: parser/parse_clause.c:1148
+#: parser/parse_clause.c:1365
#, c-format
msgid "common column name \"%s\" appears more than once in right table"
msgstr "gemeinsamer Spaltenname »%s« erscheint mehrmals in der rechten Tabelle"
-#: parser/parse_clause.c:1157
+#: parser/parse_clause.c:1374
#, c-format
msgid "column \"%s\" specified in USING clause does not exist in right table"
msgstr "Spalte »%s« aus der USING-Klausel existiert nicht in der rechten Tabelle"
-#: parser/parse_clause.c:1211
+#: parser/parse_clause.c:1428
#, c-format
msgid "column alias list for \"%s\" has too many entries"
msgstr "Spaltenaliasliste für »%s« hat zu viele Einträge"
#. translator: %s is name of a SQL construct, eg LIMIT
-#: parser/parse_clause.c:1520
+#: parser/parse_clause.c:1737
#, c-format
msgid "argument of %s must not contain variables"
msgstr "Argument von %s darf keine Variablen enthalten"
#. translator: first %s is name of a SQL construct, eg ORDER BY
-#: parser/parse_clause.c:1685
+#: parser/parse_clause.c:1902
#, c-format
msgid "%s \"%s\" is ambiguous"
msgstr "%s »%s« ist nicht eindeutig"
#. translator: %s is name of a SQL construct, eg ORDER BY
-#: parser/parse_clause.c:1714
+#: parser/parse_clause.c:1931
#, c-format
msgid "non-integer constant in %s"
msgstr "Konstante in %s ist keine ganze Zahl"
#. translator: %s is name of a SQL construct, eg ORDER BY
-#: parser/parse_clause.c:1736
+#: parser/parse_clause.c:1953
#, c-format
msgid "%s position %d is not in select list"
msgstr "%s Position %d ist nicht in der Select-Liste"
-#: parser/parse_clause.c:2178
+#: parser/parse_clause.c:2394
#, c-format
msgid "CUBE is limited to 12 elements"
msgstr "CUBE ist auf 12 Elemente begrenzt"
-#: parser/parse_clause.c:2384
+#: parser/parse_clause.c:2598
#, c-format
msgid "window \"%s\" is already defined"
msgstr "Fenster »%s« ist bereits definiert"
-#: parser/parse_clause.c:2446
+#: parser/parse_clause.c:2659
#, c-format
msgid "cannot override PARTITION BY clause of window \"%s\""
msgstr "PARTITION-BY-Klausel von Fenster »%s« kann nicht aufgehoben werden"
-#: parser/parse_clause.c:2458
+#: parser/parse_clause.c:2671
#, c-format
msgid "cannot override ORDER BY clause of window \"%s\""
msgstr "ORDER-BY-Klausel von Fenster »%s« kann nicht aufgehoben werden"
-#: parser/parse_clause.c:2488 parser/parse_clause.c:2494
+#: parser/parse_clause.c:2701 parser/parse_clause.c:2707
#, c-format
msgid "cannot copy window \"%s\" because it has a frame clause"
msgstr "kann Fenster »%s« nicht kopieren, weil es eine Frame-Klausel hat"
-#: parser/parse_clause.c:2496
+#: parser/parse_clause.c:2709
#, c-format
msgid "Omit the parentheses in this OVER clause."
msgstr "Lassen Sie die Klammern in dieser OVER-Klausel weg."
-#: parser/parse_clause.c:2562
+#: parser/parse_clause.c:2775
#, c-format
msgid "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list"
msgstr "in einer Aggregatfunktion mit DISTINCT müssen ORDER-BY-Ausdrücke in der Argumentliste erscheinen"
-#: parser/parse_clause.c:2563
+#: parser/parse_clause.c:2776
#, c-format
msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list"
msgstr "bei SELECT DISTINCT müssen ORDER-BY-Ausdrücke in der Select-Liste erscheinen"
-#: parser/parse_clause.c:2596
+#: parser/parse_clause.c:2808
#, c-format
msgid "an aggregate with DISTINCT must have at least one argument"
msgstr "eine Aggregatfunktion mit DISTINCT muss mindestens ein Argument haben"
-#: parser/parse_clause.c:2597
+#: parser/parse_clause.c:2809
#, c-format
msgid "SELECT DISTINCT must have at least one column"
msgstr "SELECT DISTINCT muss mindestens eine Spalte haben"
-#: parser/parse_clause.c:2663 parser/parse_clause.c:2695
+#: parser/parse_clause.c:2875 parser/parse_clause.c:2907
#, c-format
msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions"
msgstr "Ausdrücke in SELECT DISTINCT ON müssen mit den ersten Ausdrücken in ORDER BY übereinstimmen"
-#: parser/parse_clause.c:2774
+#: parser/parse_clause.c:2985
#, c-format
msgid "ASC/DESC is not allowed in ON CONFLICT clause"
msgstr "ASC/DESC ist in der ON-CONFLICT-Klausel nicht erlaubt"
-#: parser/parse_clause.c:2780
+#: parser/parse_clause.c:2991
#, c-format
msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause"
msgstr "NULLS FIRST/LAST ist in der ON-CONFLICT-Klausel nicht erlaubt"
-#: parser/parse_clause.c:2860
+#: parser/parse_clause.c:3071
#, c-format
msgid "ON CONFLICT DO UPDATE requires inference specification or constraint name"
msgstr "ON CONFLICT DO UPDATE benötigt Inferenzangabe oder Constraint-Namen"
-#: parser/parse_clause.c:2861
+#: parser/parse_clause.c:3072
#, c-format
msgid "For example, ON CONFLICT (column_name)."
msgstr "Zum Bespiel ON CONFLICT (Spaltenname)."
-#: parser/parse_clause.c:2872
+#: parser/parse_clause.c:3083
#, c-format
msgid "ON CONFLICT is not supported with system catalog tables"
msgstr "ON CONFLICT wird nicht mit Systemkatalogtabellen unterstützt"
-#: parser/parse_clause.c:2880
+#: parser/parse_clause.c:3091
#, c-format
msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table"
msgstr "ON CONFLICT wird nicht unterstützt mit Tabelle »%s«, die als Katalogtabelle verwendet wird"
-#: parser/parse_clause.c:3012
+#: parser/parse_clause.c:3217
#, c-format
msgid "operator %s is not a valid ordering operator"
msgstr "Operator %s ist kein gültiger Sortieroperator"
-#: parser/parse_clause.c:3014
+#: parser/parse_clause.c:3219
#, c-format
msgid "Ordering operators must be \"<\" or \">\" members of btree operator families."
msgstr "Sortieroperatoren müssen die Mitglieder »<« oder »>« einer »btree«-Operatorfamilie sein."
#: parser/parse_coerce.c:971 parser/parse_coerce.c:1001
#: parser/parse_coerce.c:1019 parser/parse_coerce.c:1034
-#: parser/parse_expr.c:2053 parser/parse_expr.c:2577 parser/parse_target.c:874
+#: parser/parse_expr.c:2123 parser/parse_expr.c:2699 parser/parse_target.c:935
#, c-format
msgid "cannot cast type %s to %s"
msgstr "kann Typ %s nicht in Typ %s umwandeln"
@@ -12989,105 +13938,99 @@ msgid "Input has too many columns."
msgstr "Eingabe hat zu viele Spalten."
#. translator: first %s is name of a SQL construct, eg WHERE
-#: parser/parse_coerce.c:1080
+#. translator: first %s is name of a SQL construct, eg LIMIT
+#: parser/parse_coerce.c:1080 parser/parse_coerce.c:1128
#, c-format
-msgid "argument of %s must be type boolean, not type %s"
-msgstr "Argument von %s muss Typ boolean haben, nicht Typ %s"
+msgid "argument of %s must be type %s, not type %s"
+msgstr "Argument von %s muss Typ %s haben, nicht Typ %s"
#. translator: %s is name of a SQL construct, eg WHERE
#. translator: %s is name of a SQL construct, eg LIMIT
-#: parser/parse_coerce.c:1090 parser/parse_coerce.c:1139
+#: parser/parse_coerce.c:1091 parser/parse_coerce.c:1140
#, c-format
msgid "argument of %s must not return a set"
msgstr "Argument von %s darf keine Ergebnismenge zurückgeben"
-#. translator: first %s is name of a SQL construct, eg LIMIT
-#: parser/parse_coerce.c:1127
-#, c-format
-msgid "argument of %s must be type %s, not type %s"
-msgstr "Argument von %s muss Typ %s haben, nicht Typ %s"
-
#. translator: first %s is name of a SQL construct, eg CASE
-#: parser/parse_coerce.c:1260
+#: parser/parse_coerce.c:1280
#, c-format
msgid "%s types %s and %s cannot be matched"
msgstr "%s-Typen %s und %s passen nicht zusammen"
#. translator: first %s is name of a SQL construct, eg CASE
-#: parser/parse_coerce.c:1327
+#: parser/parse_coerce.c:1347
#, c-format
msgid "%s could not convert type %s to %s"
msgstr "%s konnte Typ %s nicht in %s umwandeln"
-#: parser/parse_coerce.c:1629
+#: parser/parse_coerce.c:1649
#, c-format
msgid "arguments declared \"anyelement\" are not all alike"
msgstr "als »anyelement« deklariert Argumente sind nicht alle gleich"
-#: parser/parse_coerce.c:1649
+#: parser/parse_coerce.c:1669
#, c-format
msgid "arguments declared \"anyarray\" are not all alike"
msgstr "als »anyarray« deklarierte Argumente sind nicht alle gleich"
-#: parser/parse_coerce.c:1669
+#: parser/parse_coerce.c:1689
#, c-format
msgid "arguments declared \"anyrange\" are not all alike"
msgstr "als »anyrange« deklarierte Argumente sind nicht alle gleich"
-#: parser/parse_coerce.c:1698 parser/parse_coerce.c:1909
-#: parser/parse_coerce.c:1943
-#, c-format
-msgid "argument declared \"anyarray\" is not an array but type %s"
+#: parser/parse_coerce.c:1718 parser/parse_coerce.c:1933
+#: parser/parse_coerce.c:1967
+#, fuzzy, c-format
+#| msgid "argument declared \"anyarray\" is not an array but type %s"
+msgid "argument declared %s is not an array but type %s"
msgstr "als »anyarray« deklariertes Argument ist kein Array sondern Typ %s"
-#: parser/parse_coerce.c:1714
-#, c-format
-msgid "argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""
+#: parser/parse_coerce.c:1734 parser/parse_coerce.c:1773
+#, fuzzy, c-format
+#| msgid "argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""
+msgid "argument declared %s is not consistent with argument declared %s"
msgstr "als »anyarray« deklariertes Argument ist nicht mit als »anyelement« deklariertem Argument konsistent"
-#: parser/parse_coerce.c:1735 parser/parse_coerce.c:1956
-#, c-format
-msgid "argument declared \"anyrange\" is not a range type but type %s"
+#: parser/parse_coerce.c:1756 parser/parse_coerce.c:1980
+#, fuzzy, c-format
+#| msgid "argument declared \"anyrange\" is not a range type but type %s"
+msgid "argument declared %s is not a range type but type %s"
msgstr "als »anyrange« deklariertes Argument ist kein Bereichstyp sondern Typ %s"
-#: parser/parse_coerce.c:1751
-#, c-format
-msgid "argument declared \"anyrange\" is not consistent with argument declared \"anyelement\""
-msgstr "als »anyrange« deklariertes Argument ist nicht mit als »anyelement« deklariertem Argument konsistent"
-
-#: parser/parse_coerce.c:1771
-#, c-format
-msgid "could not determine polymorphic type because input has type \"unknown\""
+#: parser/parse_coerce.c:1794
+#, fuzzy, c-format
+#| msgid "could not determine polymorphic type because input has type \"unknown\""
+msgid "could not determine polymorphic type because input has type %s"
msgstr "konnte polymorphischen Typ nicht bestimmen, weil Eingabe Typ »unknown« hat"
-#: parser/parse_coerce.c:1781
+#: parser/parse_coerce.c:1805
#, c-format
msgid "type matched to anynonarray is an array type: %s"
msgstr "mit »anynonarray« gepaarter Typ ist ein Array-Typ: %s"
-#: parser/parse_coerce.c:1791
+#: parser/parse_coerce.c:1815
#, c-format
msgid "type matched to anyenum is not an enum type: %s"
msgstr "mit »anyenum« gepaarter Typ ist kein Enum-Typ: %s"
-#: parser/parse_coerce.c:1831 parser/parse_coerce.c:1861
+#: parser/parse_coerce.c:1855 parser/parse_coerce.c:1885
#, c-format
msgid "could not find range type for data type %s"
msgstr "konnte Bereichstyp für Datentyp %s nicht finden"
#: parser/parse_collate.c:228 parser/parse_collate.c:475
-#: parser/parse_collate.c:986
+#: parser/parse_collate.c:981
#, c-format
msgid "collation mismatch between implicit collations \"%s\" and \"%s\""
msgstr "implizite Sortierfolgen »%s« und »%s« stimmen nicht überein"
#: parser/parse_collate.c:231 parser/parse_collate.c:478
-#: parser/parse_collate.c:989
+#: parser/parse_collate.c:984
#, c-format
msgid "You can choose the collation by applying the COLLATE clause to one or both expressions."
msgstr "Sie können die Sortierfolge auswählen, indem Sie die COLLATE-Klausel auf einen oder beide Ausdrücke anwenden."
-#: parser/parse_collate.c:834
+#: parser/parse_collate.c:831
#, c-format
msgid "collation mismatch between explicit collations \"%s\" and \"%s\""
msgstr "explizite Sortierfolgen »%s« und »%s« stimmen nicht überein"
@@ -13147,378 +14090,473 @@ msgstr "Spalte %2$d in rekursiver Anfrage »%1$s« hat Sortierfolge %3$s im nich
msgid "Use the COLLATE clause to set the collation of the non-recursive term."
msgstr "Verwenden Sie die COLLATE-Klausel, um die Sortierfolge des nicht-rekursiven Teilsausdrucks zu setzen."
-#: parser/parse_cte.c:419
+#: parser/parse_cte.c:418
#, c-format
msgid "WITH query \"%s\" has %d columns available but %d columns specified"
msgstr "WITH-Anfrage »%s« hat %d Spalten verfügbar, aber %d Spalten wurden angegeben"
-#: parser/parse_cte.c:599
+#: parser/parse_cte.c:598
#, c-format
msgid "mutual recursion between WITH items is not implemented"
msgstr "gegenseitige Rekursion zwischen WITH-Elementen ist nicht implementiert"
-#: parser/parse_cte.c:651
+#: parser/parse_cte.c:650
#, c-format
msgid "recursive query \"%s\" must not contain data-modifying statements"
msgstr "rekursive Anfrage »%s« darf keine datenmodifizierenden Anweisungen enthalten"
-#: parser/parse_cte.c:659
+#: parser/parse_cte.c:658
#, c-format
msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term"
msgstr "rekursive Anfrage »%s« hat nicht die Form nicht-rekursiver-Ausdruck UNION [ALL] rekursiver-Ausdruck"
-#: parser/parse_cte.c:703
+#: parser/parse_cte.c:702
#, c-format
msgid "ORDER BY in a recursive query is not implemented"
msgstr "ORDER BY in einer rekursiven Anfrage ist nicht implementiert"
-#: parser/parse_cte.c:709
+#: parser/parse_cte.c:708
#, c-format
msgid "OFFSET in a recursive query is not implemented"
msgstr "OFFSET in einer rekursiven Anfrage ist nicht implementiert"
-#: parser/parse_cte.c:715
+#: parser/parse_cte.c:714
#, c-format
msgid "LIMIT in a recursive query is not implemented"
msgstr "LIMIT in einer rekursiven Anfrage ist nicht implementiert"
-#: parser/parse_cte.c:721
+#: parser/parse_cte.c:720
#, c-format
msgid "FOR UPDATE/SHARE in a recursive query is not implemented"
msgstr "FOR UPDATE/SHARE in einer rekursiven Anfrage ist nicht implementiert"
-#: parser/parse_cte.c:778
+#: parser/parse_cte.c:777
#, c-format
msgid "recursive reference to query \"%s\" must not appear more than once"
msgstr "rekursiver Verweis auf Anfrage »%s« darf nicht mehrmals erscheinen"
-#: parser/parse_expr.c:390 parser/parse_relation.c:3083
-#: parser/parse_relation.c:3103
+#: parser/parse_expr.c:357
+#, fuzzy, c-format
+#| msgid "null array element not allowed in this context"
+msgid "DEFAULT is not allowed in this context"
+msgstr "NULL-Werte im Array sind in diesem Zusammenhang nicht erlaubt"
+
+#: parser/parse_expr.c:410 parser/parse_relation.c:3110
+#: parser/parse_relation.c:3130
#, c-format
msgid "column %s.%s does not exist"
msgstr "Spalte %s.%s existiert nicht"
-#: parser/parse_expr.c:402
+#: parser/parse_expr.c:422
#, c-format
msgid "column \"%s\" not found in data type %s"
msgstr "Spalte »%s« nicht gefunden im Datentyp %s"
-#: parser/parse_expr.c:408
+#: parser/parse_expr.c:428
#, c-format
msgid "could not identify column \"%s\" in record data type"
msgstr "konnte Spalte »%s« im Record-Datentyp nicht identifizieren"
-#: parser/parse_expr.c:414
+#: parser/parse_expr.c:434
#, c-format
msgid "column notation .%s applied to type %s, which is not a composite type"
msgstr "Spaltenschreibweise .%s mit Typ %s verwendet, der kein zusammengesetzter Typ ist"
-#: parser/parse_expr.c:444 parser/parse_target.c:660
+#: parser/parse_expr.c:464 parser/parse_target.c:721
#, c-format
msgid "row expansion via \"*\" is not supported here"
msgstr "Zeilenexpansion mit »*« wird hier nicht unterstützt"
-#: parser/parse_expr.c:770 parser/parse_relation.c:667
-#: parser/parse_relation.c:767 parser/parse_target.c:1109
+#: parser/parse_expr.c:769 parser/parse_relation.c:668
+#: parser/parse_relation.c:768 parser/parse_target.c:1170
#, c-format
msgid "column reference \"%s\" is ambiguous"
msgstr "Spaltenverweis »%s« ist nicht eindeutig"
-#: parser/parse_expr.c:826 parser/parse_param.c:110 parser/parse_param.c:142
+#: parser/parse_expr.c:825 parser/parse_param.c:110 parser/parse_param.c:142
#: parser/parse_param.c:199 parser/parse_param.c:298
#, c-format
msgid "there is no parameter $%d"
msgstr "es gibt keinen Parameter $%d"
-#: parser/parse_expr.c:1067
+#: parser/parse_expr.c:1064
#, c-format
msgid "NULLIF requires = operator to yield boolean"
msgstr "NULLIF erfordert, dass Operator = boolean ergibt"
-#: parser/parse_expr.c:1730
+#: parser/parse_expr.c:1508 parser/parse_expr.c:1540
+#, c-format
+msgid "number of columns does not match number of values"
+msgstr "Anzahl der Spalten stimmt nicht mit der Anzahl der Werte überein"
+
+#: parser/parse_expr.c:1554
+#, c-format
+msgid "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression"
+msgstr ""
+
+#: parser/parse_expr.c:1798
msgid "cannot use subquery in check constraint"
msgstr "Unteranfragen können nicht in Check-Constraints verwendet werden"
-#: parser/parse_expr.c:1734
+#: parser/parse_expr.c:1802
msgid "cannot use subquery in DEFAULT expression"
msgstr "Unteranfragen können nicht in DEFAULT-Ausdrücken verwendet werden"
-#: parser/parse_expr.c:1737
+#: parser/parse_expr.c:1805
msgid "cannot use subquery in index expression"
msgstr "Unteranfragen können nicht in Indexausdrücken verwendet werden"
-#: parser/parse_expr.c:1740
+#: parser/parse_expr.c:1808
msgid "cannot use subquery in index predicate"
msgstr "Unteranfragen können nicht im Indexprädikat verwendet werden"
-#: parser/parse_expr.c:1743
+#: parser/parse_expr.c:1811
msgid "cannot use subquery in transform expression"
msgstr "Unteranfragen können in Umwandlungsausdrücken nicht verwendet werden"
-#: parser/parse_expr.c:1746
+#: parser/parse_expr.c:1814
msgid "cannot use subquery in EXECUTE parameter"
msgstr "Unteranfragen können nicht in EXECUTE-Parameter verwendet werden"
-#: parser/parse_expr.c:1749
+#: parser/parse_expr.c:1817
msgid "cannot use subquery in trigger WHEN condition"
msgstr "Unteranfragen können nicht in der WHEN-Bedingung eines Triggers verwendet werden"
-#: parser/parse_expr.c:1803
+#: parser/parse_expr.c:1820
+#, fuzzy
+#| msgid "cannot use subquery in index expression"
+msgid "cannot use subquery in partition key expression"
+msgstr "Unteranfragen können nicht in Indexausdrücken verwendet werden"
+
+#: parser/parse_expr.c:1873
#, c-format
msgid "subquery must return only one column"
msgstr "Unteranfrage darf nur eine Spalte zurückgeben"
-#: parser/parse_expr.c:1887
+#: parser/parse_expr.c:1957
#, c-format
msgid "subquery has too many columns"
msgstr "Unteranfrage hat zu viele Spalten"
-#: parser/parse_expr.c:1892
+#: parser/parse_expr.c:1962
#, c-format
msgid "subquery has too few columns"
msgstr "Unteranfrage hat zu wenige Spalten"
-#: parser/parse_expr.c:1993
+#: parser/parse_expr.c:2063
#, c-format
msgid "cannot determine type of empty array"
msgstr "kann Typ eines leeren Arrays nicht bestimmen"
-#: parser/parse_expr.c:1994
+#: parser/parse_expr.c:2064
#, c-format
msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]."
msgstr "Wandeln Sie ausdrücklich in den gewünschten Typ um, zum Beispiel ARRAY[]::integer[]."
-#: parser/parse_expr.c:2008
+#: parser/parse_expr.c:2078
#, c-format
msgid "could not find element type for data type %s"
msgstr "konnte Elementtyp für Datentyp %s nicht finden"
-#: parser/parse_expr.c:2231
+#: parser/parse_expr.c:2353
#, c-format
msgid "unnamed XML attribute value must be a column reference"
msgstr "unbenannter XML-Attributwert muss ein Spaltenverweis sein"
-#: parser/parse_expr.c:2232
+#: parser/parse_expr.c:2354
#, c-format
msgid "unnamed XML element value must be a column reference"
msgstr "unbenannter XML-Elementwert muss ein Spaltenverweis sein"
-#: parser/parse_expr.c:2247
+#: parser/parse_expr.c:2369
#, c-format
msgid "XML attribute name \"%s\" appears more than once"
msgstr "XML-Attributname »%s« einscheint mehrmals"
-#: parser/parse_expr.c:2354
+#: parser/parse_expr.c:2476
#, c-format
msgid "cannot cast XMLSERIALIZE result to %s"
msgstr "kann das Ergebnis von XMLSERIALIZE nicht in Typ %s umwandeln"
-#: parser/parse_expr.c:2650 parser/parse_expr.c:2846
+#: parser/parse_expr.c:2772 parser/parse_expr.c:2967
#, c-format
msgid "unequal number of entries in row expressions"
msgstr "ungleiche Anzahl Einträge in Zeilenausdrücken"
-#: parser/parse_expr.c:2660
+#: parser/parse_expr.c:2782
#, c-format
msgid "cannot compare rows of zero length"
msgstr "kann Zeilen mit Länge null nicht vergleichen"
-#: parser/parse_expr.c:2685
+#: parser/parse_expr.c:2806
#, c-format
msgid "row comparison operator must yield type boolean, not type %s"
msgstr "Zeilenvergleichsoperator muss Typ boolean zurückgeben, nicht Typ %s"
-#: parser/parse_expr.c:2692
+#: parser/parse_expr.c:2813
#, c-format
msgid "row comparison operator must not return a set"
msgstr "Zeilenvergleichsoperator darf keine Ergebnismenge zurückgeben"
-#: parser/parse_expr.c:2751 parser/parse_expr.c:2792
+#: parser/parse_expr.c:2872 parser/parse_expr.c:2913
#, c-format
msgid "could not determine interpretation of row comparison operator %s"
msgstr "konnte Interpretation des Zeilenvergleichsoperators %s nicht bestimmen"
-#: parser/parse_expr.c:2753
+#: parser/parse_expr.c:2874
#, c-format
msgid "Row comparison operators must be associated with btree operator families."
msgstr "Zeilenvergleichsoperatoren müssen einer »btree«-Operatorfamilie zugeordnet sein."
-#: parser/parse_expr.c:2794
+#: parser/parse_expr.c:2915
#, c-format
msgid "There are multiple equally-plausible candidates."
msgstr "Es gibt mehrere gleichermaßen plausible Kandidaten."
-#: parser/parse_expr.c:2886
+#: parser/parse_expr.c:3007
#, c-format
msgid "IS DISTINCT FROM requires = operator to yield boolean"
msgstr "IS DISTINCT FROM erfordert, dass Operator = boolean ergibt"
-#: parser/parse_expr.c:3199 parser/parse_expr.c:3217
+#: parser/parse_expr.c:3320 parser/parse_expr.c:3338
#, c-format
msgid "operator precedence change: %s is now lower precedence than %s"
msgstr "Änderung der Operatorrangfolge: %s hat jetzt niedrigere Priorität als %s"
-#: parser/parse_func.c:174
+#: parser/parse_func.c:175
#, c-format
msgid "argument name \"%s\" used more than once"
msgstr "Argumentname »%s« mehrmals angegeben"
-#: parser/parse_func.c:185
+#: parser/parse_func.c:186
#, c-format
msgid "positional argument cannot follow named argument"
msgstr "Positionsargument kann nicht hinter benanntem Argument stehen"
-#: parser/parse_func.c:270
+#: parser/parse_func.c:271
#, c-format
msgid "%s(*) specified, but %s is not an aggregate function"
msgstr "%s(*) angegeben, aber %s ist keine Aggregatfunktion"
-#: parser/parse_func.c:277
+#: parser/parse_func.c:278
#, c-format
msgid "DISTINCT specified, but %s is not an aggregate function"
msgstr "DISTINCT wurde angegeben, aber %s ist keine Aggregatfunktion"
-#: parser/parse_func.c:283
+#: parser/parse_func.c:284
#, c-format
msgid "WITHIN GROUP specified, but %s is not an aggregate function"
msgstr "WITHIN GROUP wurde angegeben, aber %s ist keine Aggregatfunktion"
-#: parser/parse_func.c:289
+#: parser/parse_func.c:290
#, c-format
msgid "ORDER BY specified, but %s is not an aggregate function"
msgstr "ORDER BY angegeben, aber %s ist keine Aggregatfunktion"
-#: parser/parse_func.c:295
+#: parser/parse_func.c:296
#, c-format
msgid "FILTER specified, but %s is not an aggregate function"
msgstr "FILTER wurde angegeben, aber %s ist keine Aggregatfunktion"
-#: parser/parse_func.c:301
+#: parser/parse_func.c:302
#, c-format
msgid "OVER specified, but %s is not a window function nor an aggregate function"
msgstr "OVER angegeben, aber %s ist keine Fensterfunktion oder Aggregatfunktion"
-#: parser/parse_func.c:331
+#: parser/parse_func.c:332
#, c-format
msgid "WITHIN GROUP is required for ordered-set aggregate %s"
msgstr "WITHIN GROUP muss angegeben werden für Ordered-Set-Aggregatfunktion %s"
-#: parser/parse_func.c:337
+#: parser/parse_func.c:338
#, c-format
msgid "OVER is not supported for ordered-set aggregate %s"
msgstr "OVER wird für Ordered-Set-Aggregatfunktion %s nicht unterstützt"
-#: parser/parse_func.c:368 parser/parse_func.c:397
+#: parser/parse_func.c:369 parser/parse_func.c:398
#, c-format
msgid "There is an ordered-set aggregate %s, but it requires %d direct arguments, not %d."
msgstr "Es gibt eine Ordered-Set-Aggregatfunktion %s, aber sie benötigt %d direkte Argumente, nicht %d."
-#: parser/parse_func.c:422
+#: parser/parse_func.c:423
#, c-format
msgid "To use the hypothetical-set aggregate %s, the number of hypothetical direct arguments (here %d) must match the number of ordering columns (here %d)."
msgstr "Um die Hypothetical-Set-Aggregatfunktion %s zu verwenden, muss die Anzahl der hypothetischen direkten Argumente (hier %d) mit der Anzahl der Sortierspalten (hier %d) übereinstimmen."
-#: parser/parse_func.c:436
+#: parser/parse_func.c:437
#, c-format
msgid "There is an ordered-set aggregate %s, but it requires at least %d direct arguments."
msgstr "Es gibt eine Ordered-Set-Aggregatfunktion %s, aber sie benötigt mindestens %d direkte Argumente."
-#: parser/parse_func.c:455
+#: parser/parse_func.c:456
#, c-format
msgid "%s is not an ordered-set aggregate, so it cannot have WITHIN GROUP"
msgstr "%s ist keine Ordered-Set-Aggregatfunktion und kann deshalb kein WITHIN GROUP haben"
-#: parser/parse_func.c:468
+#: parser/parse_func.c:469
#, c-format
msgid "window function %s requires an OVER clause"
msgstr "Fensterfunktion %s erfordert eine OVER-Klausel"
-#: parser/parse_func.c:475
+#: parser/parse_func.c:476
#, c-format
msgid "window function %s cannot have WITHIN GROUP"
msgstr "Fensterfunktion %s kann kein WITHIN GROUP haben"
-#: parser/parse_func.c:496
+#: parser/parse_func.c:497
#, c-format
msgid "function %s is not unique"
msgstr "Funktion %s ist nicht eindeutig"
-#: parser/parse_func.c:499
+#: parser/parse_func.c:500
#, c-format
msgid "Could not choose a best candidate function. You might need to add explicit type casts."
msgstr "Konnte keine beste Kandidatfunktion auswählen. Sie müssen möglicherweise ausdrückliche Typumwandlungen hinzufügen."
-#: parser/parse_func.c:510
+#: parser/parse_func.c:511
#, c-format
msgid "No aggregate function matches the given name and argument types. Perhaps you misplaced ORDER BY; ORDER BY must appear after all regular arguments of the aggregate."
msgstr "Keine Aggregatfunktion stimmt mit dem angegebenen Namen und den Argumenttypen überein. Mõglicherweise steht ORDER BY an der falschen Stelle; ORDER BY muss hinter allen normalen Argumenten der Aggregatfunktion stehen."
-#: parser/parse_func.c:521
+#: parser/parse_func.c:522
#, c-format
msgid "No function matches the given name and argument types. You might need to add explicit type casts."
msgstr "Keine Funktion stimmt mit dem angegebenen Namen und den Argumenttypen überein. Sie müssen möglicherweise ausdrückliche Typumwandlungen hinzufügen."
-#: parser/parse_func.c:623
+#: parser/parse_func.c:624
#, c-format
msgid "VARIADIC argument must be an array"
msgstr "VARIADIC-Argument muss ein Array sein"
-#: parser/parse_func.c:671 parser/parse_func.c:735
+#: parser/parse_func.c:676 parser/parse_func.c:740
#, c-format
msgid "%s(*) must be used to call a parameterless aggregate function"
msgstr "beim Aufruf einer parameterlosen Aggregatfunktion muss %s(*) angegeben werden"
-#: parser/parse_func.c:678
+#: parser/parse_func.c:683
#, c-format
msgid "aggregates cannot return sets"
msgstr "Aggregatfunktionen können keine Ergebnismengen zurückgeben"
-#: parser/parse_func.c:693
+#: parser/parse_func.c:698
#, c-format
msgid "aggregates cannot use named arguments"
msgstr "Aggregatfunktionen können keine benannten Argumente verwenden"
-#: parser/parse_func.c:725
+#: parser/parse_func.c:730
#, c-format
msgid "DISTINCT is not implemented for window functions"
msgstr "DISTINCT ist für Fensterfunktionen nicht implementiert"
-#: parser/parse_func.c:745
+#: parser/parse_func.c:750
#, c-format
msgid "aggregate ORDER BY is not implemented for window functions"
msgstr "ORDER BY in Aggregatfunktion ist für Fensterfunktionen nicht implementiert"
-#: parser/parse_func.c:754
+#: parser/parse_func.c:759
#, c-format
msgid "FILTER is not implemented for non-aggregate window functions"
msgstr "FILTER ist für Fensterfunktionen, die keine Aggregatfunktionen sind, nicht implementiert"
-#: parser/parse_func.c:760
+#: parser/parse_func.c:765
#, c-format
msgid "window functions cannot return sets"
msgstr "Fensterfunktionen können keine Ergebnismengen zurückgeben"
-#: parser/parse_func.c:2010
+#: parser/parse_func.c:2014
#, c-format
msgid "aggregate %s(*) does not exist"
msgstr "Aggregatfunktion %s(*) existiert nicht"
-#: parser/parse_func.c:2015
+#: parser/parse_func.c:2019
#, c-format
msgid "aggregate %s does not exist"
msgstr "Aggregatfunktion %s existiert nicht"
-#: parser/parse_func.c:2034
+#: parser/parse_func.c:2038
#, c-format
msgid "function %s is not an aggregate"
msgstr "Funktion %s ist keine Aggregatfunktion"
-#: parser/parse_node.c:84
+#: parser/parse_func.c:2086
+#, fuzzy
+#| msgid "window functions are not allowed in JOIN conditions"
+msgid "set-returning functions are not allowed in JOIN conditions"
+msgstr "Fensterfunktionen sind in JOIN-Bedingungen nicht erlaubt"
+
+#: parser/parse_func.c:2099
+#, fuzzy
+#| msgid "window functions are not allowed in policy expressions"
+msgid "set-returning functions are not allowed in policy expressions"
+msgstr "Fensterfunktionen sind in Policy-Ausdrücken nicht erlaubt"
+
+#: parser/parse_func.c:2114
+#, fuzzy
+#| msgid "window functions are not allowed in window definitions"
+msgid "set-returning functions are not allowed in window definitions"
+msgstr "Fensterfunktionen sind in Fensterdefinitionen nicht erlaubt"
+
+#: parser/parse_func.c:2152
+#, fuzzy
+#| msgid "window functions are not allowed in check constraints"
+msgid "set-returning functions are not allowed in check constraints"
+msgstr "Fensterfunktionen sind in Check-Constraints nicht erlaubt"
+
+#: parser/parse_func.c:2156
+#, fuzzy
+#| msgid "window functions are not allowed in DEFAULT expressions"
+msgid "set-returning functions are not allowed in DEFAULT expressions"
+msgstr "Fensterfunktionen sind in DEFAULT-Ausdrücken nicht erlaubt"
+
+#: parser/parse_func.c:2159
+#, fuzzy
+#| msgid "window functions are not allowed in index expressions"
+msgid "set-returning functions are not allowed in index expressions"
+msgstr "Fensterfunktionen sind in Indexausdrücken nicht erlaubt"
+
+#: parser/parse_func.c:2162
+#, fuzzy
+#| msgid "window functions are not allowed in index predicates"
+msgid "set-returning functions are not allowed in index predicates"
+msgstr "Fensterfunktionen sind in Indexprädikaten nicht erlaubt"
+
+#: parser/parse_func.c:2165
+#, fuzzy
+#| msgid "window functions are not allowed in transform expressions"
+msgid "set-returning functions are not allowed in transform expressions"
+msgstr "Fensterfunktionen sind in Umwandlungsausdrücken nicht erlaubt"
+
+#: parser/parse_func.c:2168
+#, fuzzy
+#| msgid "window functions are not allowed in EXECUTE parameters"
+msgid "set-returning functions are not allowed in EXECUTE parameters"
+msgstr "Fensterfunktionen sind in EXECUTE-Parametern nicht erlaubt"
+
+#: parser/parse_func.c:2171
+#, fuzzy
+#| msgid "window functions are not allowed in trigger WHEN conditions"
+msgid "set-returning functions are not allowed in trigger WHEN conditions"
+msgstr "Fensterfunktionen sind in der WHEN-Bedingung eines Triggers nicht erlaubt"
+
+#: parser/parse_func.c:2174
+#, fuzzy
+#| msgid "window functions are not allowed in index expressions"
+msgid "set-returning functions are not allowed in partition key expression"
+msgstr "Fensterfunktionen sind in Indexausdrücken nicht erlaubt"
+
+#. translator: %s is name of a SQL construct, eg GROUP BY
+#: parser/parse_func.c:2194
+#, fuzzy, c-format
+#| msgid "window functions are not allowed in %s"
+msgid "set-returning functions are not allowed in %s"
+msgstr "Fensterfunktionen sind in %s nicht erlaubt"
+
+#: parser/parse_node.c:85
#, c-format
msgid "target lists can have at most %d entries"
msgstr "Targetlisten können höchstens %d Einträge haben"
-#: parser/parse_node.c:253
+#: parser/parse_node.c:254
#, c-format
msgid "cannot subscript type %s because it is not an array"
msgstr "kann aus Typ %s kein Element auswählen, weil er kein Array ist"
@@ -13533,61 +14571,61 @@ msgstr "Arrayindex muss Typ integer haben"
msgid "array assignment requires type %s but expression is of type %s"
msgstr "Arrayzuweisung erfordert Typ %s, aber Ausdruck hat Typ %s"
-#: parser/parse_oper.c:125 parser/parse_oper.c:722 utils/adt/regproc.c:583
-#: utils/adt/regproc.c:603 utils/adt/regproc.c:787
+#: parser/parse_oper.c:125 parser/parse_oper.c:724 utils/adt/regproc.c:585
+#: utils/adt/regproc.c:605 utils/adt/regproc.c:789
#, c-format
msgid "operator does not exist: %s"
msgstr "Operator existiert nicht: %s"
-#: parser/parse_oper.c:222
+#: parser/parse_oper.c:224
#, c-format
msgid "Use an explicit ordering operator or modify the query."
msgstr "Verwenden Sie einen ausdrücklichen Sortieroperator oder ändern Sie die Anfrage."
-#: parser/parse_oper.c:226 utils/adt/array_userfuncs.c:782
-#: utils/adt/array_userfuncs.c:920 utils/adt/arrayfuncs.c:3639
-#: utils/adt/arrayfuncs.c:4077 utils/adt/arrayfuncs.c:6055
+#: parser/parse_oper.c:228 utils/adt/array_userfuncs.c:794
+#: utils/adt/array_userfuncs.c:933 utils/adt/arrayfuncs.c:3639
+#: utils/adt/arrayfuncs.c:4077 utils/adt/arrayfuncs.c:6039
#: utils/adt/rowtypes.c:1167
#, c-format
msgid "could not identify an equality operator for type %s"
msgstr "konnte keinen Ist-Gleich-Operator für Typ %s ermitteln"
-#: parser/parse_oper.c:478
+#: parser/parse_oper.c:480
#, c-format
msgid "operator requires run-time type coercion: %s"
msgstr "Operator erfordert Typumwandlung zur Laufzeit: %s"
-#: parser/parse_oper.c:714
+#: parser/parse_oper.c:716
#, c-format
msgid "operator is not unique: %s"
msgstr "Operator ist nicht eindeutig: %s"
-#: parser/parse_oper.c:716
+#: parser/parse_oper.c:718
#, c-format
msgid "Could not choose a best candidate operator. You might need to add explicit type casts."
msgstr "Konnte keinen besten Kandidatoperator auswählen. Sie müssen möglicherweise ausdrückliche Typumwandlungen hinzufügen."
-#: parser/parse_oper.c:724
+#: parser/parse_oper.c:726
#, c-format
msgid "No operator matches the given name and argument type(s). You might need to add explicit type casts."
msgstr "Kein Operator stimmt mit dem angegebenen Namen und den Argumenttypen überein. Sie müssen möglicherweise ausdrückliche Typumwandlungen hinzufügen."
-#: parser/parse_oper.c:783 parser/parse_oper.c:897
+#: parser/parse_oper.c:785 parser/parse_oper.c:903
#, c-format
msgid "operator is only a shell: %s"
msgstr "Operator ist nur eine Hülle: %s"
-#: parser/parse_oper.c:885
+#: parser/parse_oper.c:891
#, c-format
msgid "op ANY/ALL (array) requires array on right side"
msgstr "op ANY/ALL (array) erfordert Array auf der rechten Seite"
-#: parser/parse_oper.c:927
+#: parser/parse_oper.c:933
#, c-format
msgid "op ANY/ALL (array) requires operator to yield boolean"
msgstr "op ANY/ALL (array) erfordert, dass Operator boolean ergibt"
-#: parser/parse_oper.c:932
+#: parser/parse_oper.c:938
#, c-format
msgid "op ANY/ALL (array) requires operator not to return a set"
msgstr "op ANY/ALL (array) erfordert, dass Operator keine Ergebnismenge zurückgibt"
@@ -13597,43 +14635,43 @@ msgstr "op ANY/ALL (array) erfordert, dass Operator keine Ergebnismenge zurückg
msgid "inconsistent types deduced for parameter $%d"
msgstr "inkonsistente Typen für Parameter $%d ermittelt"
-#: parser/parse_relation.c:174
+#: parser/parse_relation.c:175
#, c-format
msgid "table reference \"%s\" is ambiguous"
msgstr "Tabellenbezug »%s« ist nicht eindeutig"
-#: parser/parse_relation.c:218
+#: parser/parse_relation.c:219
#, c-format
msgid "table reference %u is ambiguous"
msgstr "Tabellenbezug %u ist nicht eindeutig"
-#: parser/parse_relation.c:397
+#: parser/parse_relation.c:398
#, c-format
msgid "table name \"%s\" specified more than once"
msgstr "Tabellenname »%s« mehrmals angegeben"
-#: parser/parse_relation.c:424 parser/parse_relation.c:3023
+#: parser/parse_relation.c:425 parser/parse_relation.c:3050
#, c-format
msgid "invalid reference to FROM-clause entry for table \"%s\""
msgstr "ungültiger Verweis auf FROM-Klausel-Eintrag für Tabelle »%s«"
-#: parser/parse_relation.c:427 parser/parse_relation.c:3028
+#: parser/parse_relation.c:428 parser/parse_relation.c:3055
#, c-format
msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query."
msgstr "Es gibt einen Eintrag für Tabelle »%s«, aber auf ihn kann aus diesem Teil der Anfrage nicht verwiesen werden."
-#: parser/parse_relation.c:429
+#: parser/parse_relation.c:430
#, c-format
msgid "The combining JOIN type must be INNER or LEFT for a LATERAL reference."
msgstr "Der JOIN-Typ für LATERAL muss INNER oder LEFT sein."
-#: parser/parse_relation.c:705
+#: parser/parse_relation.c:706
#, c-format
msgid "system column \"%s\" reference in check constraint is invalid"
msgstr "Verweis auf Systemspalte »%s« im Check-Constraint ist ungültig"
#: parser/parse_relation.c:1065 parser/parse_relation.c:1345
-#: parser/parse_relation.c:1847
+#: parser/parse_relation.c:1914
#, c-format
msgid "table \"%s\" has %d columns available but %d columns specified"
msgstr "Tabelle »%s« hat %d Spalten, aber %d Spalten wurden angegeben"
@@ -13663,92 +14701,92 @@ msgstr "eine Spaltendefinitionsliste ist erforderlich bei Funktionen, die »reco
msgid "function \"%s\" in FROM has unsupported return type %s"
msgstr "Funktion »%s« in FROM hat nicht unterstützten Rückgabetyp %s"
-#: parser/parse_relation.c:1675
+#: parser/parse_relation.c:1742
#, c-format
msgid "VALUES lists \"%s\" have %d columns available but %d columns specified"
msgstr "VALUES-Liste »%s« hat %d Spalten verfügbar, aber %d Spalten wurden angegeben"
-#: parser/parse_relation.c:1730
+#: parser/parse_relation.c:1797
#, c-format
msgid "joins can have at most %d columns"
msgstr "Verbunde können höchstens %d Spalten haben"
-#: parser/parse_relation.c:1820
+#: parser/parse_relation.c:1887
#, c-format
msgid "WITH query \"%s\" does not have a RETURNING clause"
msgstr "WITH-Anfrage »%s« hat keine RETURNING-Klausel"
-#: parser/parse_relation.c:2652 parser/parse_relation.c:2807
+#: parser/parse_relation.c:2685 parser/parse_relation.c:2834
#, c-format
msgid "column %d of relation \"%s\" does not exist"
msgstr "Spalte %d von Relation »%s« existiert nicht"
-#: parser/parse_relation.c:3026
+#: parser/parse_relation.c:3053
#, c-format
msgid "Perhaps you meant to reference the table alias \"%s\"."
msgstr "Vielleicht wurde beabsichtigt, auf den Tabellenalias »%s« zu verweisen."
-#: parser/parse_relation.c:3034
+#: parser/parse_relation.c:3061
#, c-format
msgid "missing FROM-clause entry for table \"%s\""
msgstr "fehlender Eintrag in FROM-Klausel für Tabelle »%s«"
-#: parser/parse_relation.c:3086
+#: parser/parse_relation.c:3113
#, c-format
msgid "Perhaps you meant to reference the column \"%s.%s\"."
msgstr "Vielleicht wurde beabsichtigt, auf die Spalte »%s.%s« zu verweisen."
-#: parser/parse_relation.c:3088
+#: parser/parse_relation.c:3115
#, c-format
msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query."
msgstr "Es gibt eine Spalte namens »%s« in Tabelle »%s«, aber auf sie kann aus diesem Teil der Anfrage nicht verwiesen werden."
-#: parser/parse_relation.c:3105
+#: parser/parse_relation.c:3132
#, c-format
msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"."
msgstr "Vielleicht wurde beabsichtigt, auf die Spalte »%s.%s« oder die Spalte »%s.%s« zu verweisen."
-#: parser/parse_target.c:421 parser/parse_target.c:713
+#: parser/parse_target.c:482 parser/parse_target.c:774
#, c-format
msgid "cannot assign to system column \"%s\""
msgstr "kann Systemspalte »%s« keinen Wert zuweisen"
-#: parser/parse_target.c:449
+#: parser/parse_target.c:510
#, c-format
msgid "cannot set an array element to DEFAULT"
msgstr "kann Arrayelement nicht auf DEFAULT setzen"
-#: parser/parse_target.c:454
+#: parser/parse_target.c:515
#, c-format
msgid "cannot set a subfield to DEFAULT"
msgstr "kann Subfeld nicht auf DEFAULT setzen"
-#: parser/parse_target.c:523
+#: parser/parse_target.c:584
#, c-format
msgid "column \"%s\" is of type %s but expression is of type %s"
msgstr "Spalte »%s« hat Typ %s, aber der Ausdruck hat Typ %s"
-#: parser/parse_target.c:697
+#: parser/parse_target.c:758
#, c-format
msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type"
msgstr "kann Feld »%s« in Spalte »%s« nicht setzen, weil ihr Typ %s kein zusammengesetzter Typ ist"
-#: parser/parse_target.c:706
+#: parser/parse_target.c:767
#, c-format
msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s"
msgstr "kann Feld »%s« in Spalte »%s« nicht setzen, weil es keine solche Spalte in Datentyp %s gibt"
-#: parser/parse_target.c:773
+#: parser/parse_target.c:834
#, c-format
msgid "array assignment to \"%s\" requires type %s but expression is of type %s"
msgstr "Wertzuweisung für »%s« erfordert Typ %s, aber Ausdruck hat Typ %s"
-#: parser/parse_target.c:783
+#: parser/parse_target.c:844
#, c-format
msgid "subfield \"%s\" is of type %s but expression is of type %s"
msgstr "Subfeld »%s« hat Typ %s, aber der Ausdruck hat Typ %s"
-#: parser/parse_target.c:1199
+#: parser/parse_target.c:1260
#, c-format
msgid "SELECT * with no tables specified is not valid"
msgstr "SELECT * ist nicht gültig, wenn keine Tabellen angegeben sind"
@@ -13768,7 +14806,7 @@ msgstr "falscher %%TYPE-Verweis (zu viele Namensteile): %s"
msgid "type reference %s converted to %s"
msgstr "Typverweis %s in %s umgewandelt"
-#: parser/parse_type.c:261 parser/parse_type.c:805 utils/cache/typcache.c:239
+#: parser/parse_type.c:261 parser/parse_type.c:804 utils/cache/typcache.c:243
#, c-format
msgid "type \"%s\" is only a shell"
msgstr "Typ »%s« ist nur eine Hülle"
@@ -13783,268 +14821,312 @@ msgstr "Typmodifikator ist für Typ »%s« nicht erlaubt"
msgid "type modifiers must be simple constants or identifiers"
msgstr "Typmodifikatoren müssen einfache Konstanten oder Bezeichner sein"
-#: parser/parse_type.c:671 parser/parse_type.c:770
+#: parser/parse_type.c:670 parser/parse_type.c:769
#, c-format
msgid "invalid type name \"%s\""
msgstr "ungültiger Typname: »%s«"
-#: parser/parse_utilcmd.c:399
+#: parser/parse_utilcmd.c:263
+#, fuzzy, c-format
+#| msgid "cannot create temporary tables in parallel mode"
+msgid "cannot create partitioned table as inheritance child"
+msgstr "im Parallelmodus können keine temporären Tabellen erzeugt werden"
+
+#: parser/parse_utilcmd.c:268
+#, fuzzy, c-format
+#| msgid "cannot use more than %d columns in an index"
+msgid "cannot partition using more than %d columns"
+msgstr "Index kann nicht mehr als %d Spalten enthalten"
+
+#: parser/parse_utilcmd.c:275
+#, c-format
+msgid "cannot list partition using more than one column"
+msgstr ""
+
+#: parser/parse_utilcmd.c:413
#, c-format
msgid "array of serial is not implemented"
msgstr "Array aus Typ serial ist nicht implementiert"
-#: parser/parse_utilcmd.c:447
+#: parser/parse_utilcmd.c:461
#, c-format
msgid "%s will create implicit sequence \"%s\" for serial column \"%s.%s\""
msgstr "%s erstellt implizit eine Sequenz »%s« für die »serial«-Spalte »%s.%s«"
-#: parser/parse_utilcmd.c:541 parser/parse_utilcmd.c:553
+#: parser/parse_utilcmd.c:554 parser/parse_utilcmd.c:566
#, c-format
msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\""
msgstr "widersprüchliche NULL/NOT NULL-Deklarationen für Spalte »%s« von Tabelle »%s«"
-#: parser/parse_utilcmd.c:565
+#: parser/parse_utilcmd.c:578
#, c-format
msgid "multiple default values specified for column \"%s\" of table \"%s\""
msgstr "mehrere Vorgabewerte angegeben für Spalte »%s« von Tabelle »%s«"
-#: parser/parse_utilcmd.c:582 parser/parse_utilcmd.c:673
+#: parser/parse_utilcmd.c:595 parser/parse_utilcmd.c:704
#, c-format
msgid "primary key constraints are not supported on foreign tables"
msgstr "Primärschlüssel für Fremdtabellen werden nicht unterstützt"
-#: parser/parse_utilcmd.c:591 parser/parse_utilcmd.c:683
+#: parser/parse_utilcmd.c:601 parser/parse_utilcmd.c:710
+#, fuzzy, c-format
+#| msgid "primary key constraints are not supported on foreign tables"
+msgid "primary key constraints are not supported on partitioned tables"
+msgstr "Primärschlüssel für Fremdtabellen werden nicht unterstützt"
+
+#: parser/parse_utilcmd.c:610 parser/parse_utilcmd.c:720
#, c-format
msgid "unique constraints are not supported on foreign tables"
msgstr "Unique-Constraints auf Fremdtabellen werden nicht unterstützt"
-#: parser/parse_utilcmd.c:608 parser/parse_utilcmd.c:707
+#: parser/parse_utilcmd.c:616 parser/parse_utilcmd.c:726
+#, fuzzy, c-format
+#| msgid "unique constraints are not supported on foreign tables"
+msgid "unique constraints are not supported on partitioned tables"
+msgstr "Unique-Constraints auf Fremdtabellen werden nicht unterstützt"
+
+#: parser/parse_utilcmd.c:633 parser/parse_utilcmd.c:756
#, c-format
msgid "foreign key constraints are not supported on foreign tables"
msgstr "Fremdschlüssel-Constraints auf Fremdtabellen werden nicht unterstützt"
-#: parser/parse_utilcmd.c:693
+#: parser/parse_utilcmd.c:639 parser/parse_utilcmd.c:762
+#, fuzzy, c-format
+#| msgid "foreign key constraints are not supported on foreign tables"
+msgid "foreign key constraints are not supported on partitioned tables"
+msgstr "Fremdschlüssel-Constraints auf Fremdtabellen werden nicht unterstützt"
+
+#: parser/parse_utilcmd.c:736
#, c-format
msgid "exclusion constraints are not supported on foreign tables"
msgstr "Exclusion-Constraints auf Fremdtabellen werden nicht unterstützt"
-#: parser/parse_utilcmd.c:757
+#: parser/parse_utilcmd.c:742
+#, fuzzy, c-format
+#| msgid "exclusion constraints are not supported on foreign tables"
+msgid "exclusion constraints are not supported on partitioned tables"
+msgstr "Exclusion-Constraints auf Fremdtabellen werden nicht unterstützt"
+
+#: parser/parse_utilcmd.c:812
#, c-format
msgid "LIKE is not supported for creating foreign tables"
msgstr "LIKE wird für das Erzeugen von Fremdtabellen nicht unterstützt"
-#: parser/parse_utilcmd.c:1290 parser/parse_utilcmd.c:1366
+#: parser/parse_utilcmd.c:1344 parser/parse_utilcmd.c:1420
#, c-format
msgid "Index \"%s\" contains a whole-row table reference."
msgstr "Index »%s« enthält einen Verweis auf die ganze Zeile der Tabelle."
-#: parser/parse_utilcmd.c:1636
+#: parser/parse_utilcmd.c:1689
#, c-format
msgid "cannot use an existing index in CREATE TABLE"
msgstr "bestehender Index kann nicht in CREATE TABLE verwendet werden"
-#: parser/parse_utilcmd.c:1656
+#: parser/parse_utilcmd.c:1709
#, c-format
msgid "index \"%s\" is already associated with a constraint"
msgstr "Index »%s« gehört bereits zu einem Constraint"
-#: parser/parse_utilcmd.c:1664
+#: parser/parse_utilcmd.c:1717
#, c-format
msgid "index \"%s\" does not belong to table \"%s\""
msgstr "Index »%s« gehört nicht zu Tabelle »%s«"
-#: parser/parse_utilcmd.c:1671
+#: parser/parse_utilcmd.c:1724
#, c-format
msgid "index \"%s\" is not valid"
msgstr "Index »%s« ist nicht gültig"
-#: parser/parse_utilcmd.c:1677
+#: parser/parse_utilcmd.c:1730
#, c-format
msgid "\"%s\" is not a unique index"
msgstr "»%s« ist kein Unique Index"
-#: parser/parse_utilcmd.c:1678 parser/parse_utilcmd.c:1685
-#: parser/parse_utilcmd.c:1692 parser/parse_utilcmd.c:1762
+#: parser/parse_utilcmd.c:1731 parser/parse_utilcmd.c:1738
+#: parser/parse_utilcmd.c:1745 parser/parse_utilcmd.c:1815
#, c-format
msgid "Cannot create a primary key or unique constraint using such an index."
msgstr "Ein Primärschlüssel oder Unique-Constraint kann nicht mit einem solchen Index erzeugt werden."
-#: parser/parse_utilcmd.c:1684
+#: parser/parse_utilcmd.c:1737
#, c-format
msgid "index \"%s\" contains expressions"
msgstr "Index »%s« enthält Ausdrücke"
-#: parser/parse_utilcmd.c:1691
+#: parser/parse_utilcmd.c:1744
#, c-format
msgid "\"%s\" is a partial index"
msgstr "»%s« ist ein partieller Index"
-#: parser/parse_utilcmd.c:1703
+#: parser/parse_utilcmd.c:1756
#, c-format
msgid "\"%s\" is a deferrable index"
msgstr "»%s« ist ein aufschiebbarer Index"
-#: parser/parse_utilcmd.c:1704
+#: parser/parse_utilcmd.c:1757
#, c-format
msgid "Cannot create a non-deferrable constraint using a deferrable index."
msgstr "Ein nicht aufschiebbarer Constraint kann nicht mit einem aufschiebbaren Index erzeugt werden."
-#: parser/parse_utilcmd.c:1761
+#: parser/parse_utilcmd.c:1814
#, c-format
msgid "index \"%s\" does not have default sorting behavior"
msgstr "Index »%s« hat nicht das Standardsortierverhalten"
-#: parser/parse_utilcmd.c:1908
+#: parser/parse_utilcmd.c:1958
#, c-format
msgid "column \"%s\" appears twice in primary key constraint"
msgstr "Spalte »%s« erscheint zweimal im Primärschlüssel-Constraint"
-#: parser/parse_utilcmd.c:1914
+#: parser/parse_utilcmd.c:1964
#, c-format
msgid "column \"%s\" appears twice in unique constraint"
msgstr "Spalte »%s« erscheint zweimal im Unique-Constraint"
-#: parser/parse_utilcmd.c:2118
-#, c-format
-msgid "index expression cannot return a set"
-msgstr "Indexausdruck kann keine Ergebnismenge zurückgeben"
-
-#: parser/parse_utilcmd.c:2129
+#: parser/parse_utilcmd.c:2173
#, c-format
msgid "index expressions and predicates can refer only to the table being indexed"
msgstr "Indexausdrücke und -prädikate können nur auf die zu indizierende Tabelle verweisen"
-#: parser/parse_utilcmd.c:2175
+#: parser/parse_utilcmd.c:2219
#, c-format
msgid "rules on materialized views are not supported"
msgstr "Regeln für materialisierte Sichten werden nicht unterstützt"
-#: parser/parse_utilcmd.c:2236
+#: parser/parse_utilcmd.c:2280
#, c-format
msgid "rule WHERE condition cannot contain references to other relations"
msgstr "WHERE-Bedingung einer Regel kann keine Verweise auf andere Relationen enthalten"
-#: parser/parse_utilcmd.c:2308
+#: parser/parse_utilcmd.c:2352
#, c-format
msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions"
msgstr "Regeln mit WHERE-Bedingungen können als Aktion nur SELECT, INSERT, UPDATE oder DELETE haben"
-#: parser/parse_utilcmd.c:2326 parser/parse_utilcmd.c:2425
-#: rewrite/rewriteHandler.c:485 rewrite/rewriteManip.c:1015
+#: parser/parse_utilcmd.c:2370 parser/parse_utilcmd.c:2469
+#: rewrite/rewriteHandler.c:498 rewrite/rewriteManip.c:1015
#, c-format
msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented"
msgstr "UNION/INTERSECTION/EXCEPT mit Bedingung sind nicht implementiert"
-#: parser/parse_utilcmd.c:2344
+#: parser/parse_utilcmd.c:2388
#, c-format
msgid "ON SELECT rule cannot use OLD"
msgstr "ON-SELECT-Regel kann nicht OLD verwenden"
-#: parser/parse_utilcmd.c:2348
+#: parser/parse_utilcmd.c:2392
#, c-format
msgid "ON SELECT rule cannot use NEW"
msgstr "ON-SELECT-Regel kann nicht NEW verwenden"
-#: parser/parse_utilcmd.c:2357
+#: parser/parse_utilcmd.c:2401
#, c-format
msgid "ON INSERT rule cannot use OLD"
msgstr "ON-INSERT-Regel kann nicht OLD verwenden"
-#: parser/parse_utilcmd.c:2363
+#: parser/parse_utilcmd.c:2407
#, c-format
msgid "ON DELETE rule cannot use NEW"
msgstr "ON-DELETE-Regel kann nicht NEW verwenden"
-#: parser/parse_utilcmd.c:2391
+#: parser/parse_utilcmd.c:2435
#, c-format
msgid "cannot refer to OLD within WITH query"
msgstr "in WITH-Anfrage kann nicht auf OLD verweisen werden"
-#: parser/parse_utilcmd.c:2398
+#: parser/parse_utilcmd.c:2442
#, c-format
msgid "cannot refer to NEW within WITH query"
msgstr "in WITH-Anfrage kann nicht auf NEW verwiesen werden"
-#: parser/parse_utilcmd.c:2601
-#, c-format
-msgid "transform expression must not return a set"
-msgstr "Umwandlungsausdruck kann keine Ergebnismenge zurückgeben"
-
-#: parser/parse_utilcmd.c:2715
+#: parser/parse_utilcmd.c:2766
#, c-format
msgid "misplaced DEFERRABLE clause"
msgstr "falsch platzierte DEFERRABLE-Klausel"
-#: parser/parse_utilcmd.c:2720 parser/parse_utilcmd.c:2735
+#: parser/parse_utilcmd.c:2771 parser/parse_utilcmd.c:2786
#, c-format
msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"
msgstr "mehrere DEFERRABLE/NOT DEFERRABLE-Klauseln sind nicht erlaubt"
-#: parser/parse_utilcmd.c:2730
+#: parser/parse_utilcmd.c:2781
#, c-format
msgid "misplaced NOT DEFERRABLE clause"
msgstr "falsch platzierte NOT DEFERRABLE-Klausel"
-#: parser/parse_utilcmd.c:2751
+#: parser/parse_utilcmd.c:2802
#, c-format
msgid "misplaced INITIALLY DEFERRED clause"
msgstr "falsch platzierte INITIALLY DEFERRED-Klausel"
-#: parser/parse_utilcmd.c:2756 parser/parse_utilcmd.c:2782
+#: parser/parse_utilcmd.c:2807 parser/parse_utilcmd.c:2833
#, c-format
msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"
msgstr "mehrere INITIALLY IMMEDIATE/DEFERRED-Klauseln sind nicht erlaubt"
-#: parser/parse_utilcmd.c:2777
+#: parser/parse_utilcmd.c:2828
#, c-format
msgid "misplaced INITIALLY IMMEDIATE clause"
msgstr "falsch platzierte INITIALLY IMMEDIATE-Klausel"
-#: parser/parse_utilcmd.c:2968
+#: parser/parse_utilcmd.c:3019
#, c-format
msgid "CREATE specifies a schema (%s) different from the one being created (%s)"
msgstr "CREATE gibt ein Schema an (%s) welches nicht gleich dem zu erzeugenden Schema ist (%s)"
-#: parser/scansup.c:204
-#, c-format
-msgid "identifier \"%s\" will be truncated to \"%s\""
-msgstr "Bezeichner »%s« wird auf »%s« gekürzt"
+#: parser/parse_utilcmd.c:3085
+#, fuzzy, c-format
+#| msgid "invalid format specification for an interval value"
+msgid "invalid bound specification for a list partition"
+msgstr "ungültige Formatangabe für Intervall-Wert"
-#: port/pg_sema.c:113 port/sysv_sema.c:113
-#, c-format
-msgid "could not create semaphores: %m"
-msgstr "konnte Semaphore nicht erzeugen: %m"
+#: parser/parse_utilcmd.c:3108 parser/parse_utilcmd.c:3208
+#: parser/parse_utilcmd.c:3235
+#, fuzzy, c-format
+#| msgid "cannot alter type of column \"%s\" twice"
+msgid "specified value cannot be cast to type \"%s\" of column \"%s\""
+msgstr "Typ der Spalte »%s« kann nicht zweimal geändert werden"
-#: port/pg_sema.c:114 port/sysv_sema.c:114
-#, c-format
-msgid "Failed system call was semget(%lu, %d, 0%o)."
-msgstr "Fehlgeschlagener Systemaufruf war semget(%lu, %d, 0%o)."
+#: parser/parse_utilcmd.c:3147
+#, fuzzy, c-format
+#| msgid "invalid format specification for an interval value"
+msgid "invalid bound specification for a range partition"
+msgstr "ungültige Formatangabe für Intervall-Wert"
-#: port/pg_sema.c:118 port/sysv_sema.c:118
-#, c-format
-msgid ""
-"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its max_connections parameter.\n"
-"The PostgreSQL documentation contains more information about configuring your system for PostgreSQL."
-msgstr ""
-"Dieser Fehler bedeutet *nicht*, dass kein Platz mehr auf der Festplatte ist. Er tritt auf, wenn entweder die Systemhöchstgrenze für die Anzahl Semaphor-Sets (SEMMNI) oder die Systemhöchstgrenze für die Anzahl Semaphore (SEMMNS) überschritten würde. Sie müssen den entsprechenden Kernelparameter erhöhen. Alternativ können Sie den Semaphorverbrauch von PostgreSQL reduzieren indem Sie den Parameter »max_connections« herabsetzen.\n"
-"Die PostgreSQL-Dokumentation enthält weitere Informationen, wie Sie Ihr System für PostgreSQL konfigurieren können."
+#: parser/parse_utilcmd.c:3155
+#, fuzzy, c-format
+#| msgid "must specify at least one column"
+msgid "FROM must specify exactly one value per partitioning column"
+msgstr "mindestens eine Spalte muss angegeben werden"
+
+#: parser/parse_utilcmd.c:3159
+#, fuzzy, c-format
+#| msgid "must specify at least one column"
+msgid "TO must specify exactly one value per partitioning column"
+msgstr "mindestens eine Spalte muss angegeben werden"
+
+#: parser/parse_utilcmd.c:3197 parser/parse_utilcmd.c:3224
+#, fuzzy, c-format
+#| msgid "cannot specify NULL in BINARY mode"
+msgid "cannot specify NULL in range bound"
+msgstr "NULL kann nicht im BINARY-Modus angegeben werden"
-#: port/pg_sema.c:148 port/sysv_sema.c:148
+#: parser/scansup.c:204
#, c-format
-msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details."
-msgstr "Sie müssen möglicherweise den Kernelparameter SEMVMX auf mindestens %d erhöhen. Weitere Informationen finden Sie in der PostgreSQL-Dokumentation."
+msgid "identifier \"%s\" will be truncated to \"%s\""
+msgstr "Bezeichner »%s« wird auf »%s« gekürzt"
-#: port/pg_shmem.c:141 port/sysv_shmem.c:141
+#: port/pg_shmem.c:175 port/sysv_shmem.c:175
#, c-format
msgid "could not create shared memory segment: %m"
msgstr "konnte Shared-Memory-Segment nicht erzeugen: %m"
-#: port/pg_shmem.c:142 port/sysv_shmem.c:142
+#: port/pg_shmem.c:176 port/sysv_shmem.c:176
#, c-format
msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)."
msgstr "Fehlgeschlagener Systemaufruf war shmget(Key=%lu, Größe=%zu, 0%o)."
-#: port/pg_shmem.c:146 port/sysv_shmem.c:146
+#: port/pg_shmem.c:180 port/sysv_shmem.c:180
#, c-format
msgid ""
"This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter, or possibly that it is less than your kernel's SHMMIN parameter.\n"
@@ -14053,7 +15135,7 @@ msgstr ""
"Dieser Fehler bedeutet gewöhnlich, dass das von PostgreSQL angeforderte Shared-Memory-Segment den Kernel-Parameter SHMMAX überschreitet, oder eventuell, dass es kleiner als der Kernel-Parameter SHMMIN ist.\n"
"Die PostgreSQL-Dokumentation enthält weitere Informationen über die Konfiguration von Shared Memory."
-#: port/pg_shmem.c:153 port/sysv_shmem.c:153
+#: port/pg_shmem.c:187 port/sysv_shmem.c:187
#, c-format
msgid ""
"This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMALL parameter. You might need to reconfigure the kernel with larger SHMALL.\n"
@@ -14062,7 +15144,7 @@ msgstr ""
"Dieser Fehler bedeutet gewöhnlich, dass das von PostgreSQL angeforderte Shared-Memory-Segment den Kernel-Parameter SHMALL überschreitet. Sie müssen eventuell den Kernel mit einem größeren SHMALL neu konfigurieren.\n"
"Die PostgreSQL-Dokumentation enthält weitere Informationen über die Konfiguration von Shared Memory."
-#: port/pg_shmem.c:159 port/sysv_shmem.c:159
+#: port/pg_shmem.c:193 port/sysv_shmem.c:193
#, c-format
msgid ""
"This error does *not* mean that you have run out of disk space. It occurs either if all available shared memory IDs have been taken, in which case you need to raise the SHMMNI parameter in your kernel, or because the system's overall limit for shared memory has been reached.\n"
@@ -14071,54 +15153,73 @@ msgstr ""
"Dieser Fehler bedeutet *nicht*, dass kein Platz mehr auf der Festplatte ist. Er tritt auf, wenn entweder alle verfügbaren Shared-Memory-IDs aufgebraucht sind, dann müssen den Kernelparameter SHMMNI erhöhen, oder weil die Systemhöchstgrenze für Shared Memory insgesamt erreicht wurde.\n"
"Die PostgreSQL-Dokumentation enthält weitere Informationen über die Konfiguration von Shared Memory."
-#: port/pg_shmem.c:340 port/sysv_shmem.c:340
-#, c-format
-msgid "huge TLB pages not supported on this platform"
-msgstr "Huge TLB-Pages werden auf dieser Plattform nicht unterstützt"
-
-#: port/pg_shmem.c:390 port/sysv_shmem.c:390
+#: port/pg_shmem.c:483 port/sysv_shmem.c:483
#, c-format
msgid "could not map anonymous shared memory: %m"
msgstr "konnte anonymes Shared Memory nicht mappen: %m"
-#: port/pg_shmem.c:392 port/sysv_shmem.c:392
+#: port/pg_shmem.c:485 port/sysv_shmem.c:485
#, c-format
msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections."
msgstr ""
"Dieser Fehler bedeutet gewöhnlich, dass das von PostgreSQL angeforderte Shared-Memory-Segment den verfügbaren Speicher, Swap-Space oder Huge Pages überschreitet. Um die benötigte Shared-Memory-Größe zu reduzieren (aktuell %zu Bytes), reduzieren Sie den Shared-Memory-Verbrauch von PostgreSQL, beispielsweise indem Sie »shared_buffers« oder »max_connections« reduzieren.\n"
"Die PostgreSQL-Dokumentation enthält weitere Informationen über die Konfiguration von Shared Memory."
-#: port/pg_shmem.c:439 port/sysv_shmem.c:439 port/win32_shmem.c:134
+#: port/pg_shmem.c:551 port/sysv_shmem.c:551 port/win32_shmem.c:134
#, c-format
msgid "huge pages not supported on this platform"
msgstr "Huge Pages werden auf dieser Plattform nicht unterstützt"
-#: port/pg_shmem.c:553 port/sysv_shmem.c:553
+#: port/pg_shmem.c:646 port/sysv_shmem.c:646
#, c-format
msgid "could not stat data directory \"%s\": %m"
msgstr "konnte »stat« für Datenverzeichnis »%s« nicht ausführen: %m"
-#: port/win32/crashdump.c:122
+#: port/sysv_sema.c:123
+#, c-format
+msgid "could not create semaphores: %m"
+msgstr "konnte Semaphore nicht erzeugen: %m"
+
+#: port/sysv_sema.c:124
+#, c-format
+msgid "Failed system call was semget(%lu, %d, 0%o)."
+msgstr "Fehlgeschlagener Systemaufruf war semget(%lu, %d, 0%o)."
+
+#: port/sysv_sema.c:128
+#, c-format
+msgid ""
+"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its max_connections parameter.\n"
+"The PostgreSQL documentation contains more information about configuring your system for PostgreSQL."
+msgstr ""
+"Dieser Fehler bedeutet *nicht*, dass kein Platz mehr auf der Festplatte ist. Er tritt auf, wenn entweder die Systemhöchstgrenze für die Anzahl Semaphor-Sets (SEMMNI) oder die Systemhöchstgrenze für die Anzahl Semaphore (SEMMNS) überschritten würde. Sie müssen den entsprechenden Kernelparameter erhöhen. Alternativ können Sie den Semaphorverbrauch von PostgreSQL reduzieren indem Sie den Parameter »max_connections« herabsetzen.\n"
+"Die PostgreSQL-Dokumentation enthält weitere Informationen, wie Sie Ihr System für PostgreSQL konfigurieren können."
+
+#: port/sysv_sema.c:158
+#, c-format
+msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details."
+msgstr "Sie müssen möglicherweise den Kernelparameter SEMVMX auf mindestens %d erhöhen. Weitere Informationen finden Sie in der PostgreSQL-Dokumentation."
+
+#: port/win32/crashdump.c:121
#, c-format
msgid "could not load dbghelp.dll, cannot write crash dump\n"
msgstr "konnte dbghelp.dll nicht laden, kann Crash-Dump nicht schreiben\n"
-#: port/win32/crashdump.c:130
+#: port/win32/crashdump.c:129
#, c-format
msgid "could not load required functions in dbghelp.dll, cannot write crash dump\n"
msgstr "konnte benötigte Funktionen in dbghelp.dll nicht laden, kann Crash-Dump nicht schreiben\n"
-#: port/win32/crashdump.c:161
+#: port/win32/crashdump.c:160
#, c-format
msgid "could not open crash dump file \"%s\" for writing: error code %lu\n"
msgstr "konnte Crash-Dump-Datei »%s« nicht zum Schreiben öffnen: Fehlercode %lu\n"
-#: port/win32/crashdump.c:168
+#: port/win32/crashdump.c:167
#, c-format
msgid "wrote crash dump to file \"%s\"\n"
msgstr "Crash-Dump nach Datei »%s« geschrieben\n"
-#: port/win32/crashdump.c:170
+#: port/win32/crashdump.c:169
#, c-format
msgid "could not write crash dump to file \"%s\": error code %lu\n"
msgstr "konnte Crash-Dump nicht nach Datei »%s« schreiben: Fehlercode %lu\n"
@@ -14138,22 +15239,22 @@ msgstr "konnte Listener-Pipe für Signale nicht erzeugen: Fehlercode %lu; wieder
msgid "could not create signal dispatch thread: error code %lu\n"
msgstr "konnte Signal-Dispatch-Thread nicht erzeugen: Fehlercode %lu\n"
-#: port/win32_sema.c:94
+#: port/win32_sema.c:104
#, c-format
msgid "could not create semaphore: error code %lu"
msgstr "konnte Semaphore nicht erzeugen: Fehlercode %lu"
-#: port/win32_sema.c:167
+#: port/win32_sema.c:181
#, c-format
msgid "could not lock semaphore: error code %lu"
msgstr "konnte Semaphore nicht sperren: Fehlercode %lu"
-#: port/win32_sema.c:187
+#: port/win32_sema.c:201
#, c-format
msgid "could not unlock semaphore: error code %lu"
msgstr "konnte Semaphore nicht entsperren: Fehlercode %lu"
-#: port/win32_sema.c:216
+#: port/win32_sema.c:231
#, c-format
msgid "could not try-lock semaphore: error code %lu"
msgstr "konnte Semaphore nicht versuchsweise sperren: Fehlercode %lu"
@@ -14198,104 +15299,100 @@ msgstr "konnte Autovacuum-Launcher-Prozess nicht starten (fork-Fehler): %m"
msgid "autovacuum launcher started"
msgstr "Autovacuum-Launcher startet"
-#: postmaster/autovacuum.c:781
+#: postmaster/autovacuum.c:780
#, c-format
msgid "autovacuum launcher shutting down"
msgstr "Autovacuum-Launcher fährt herunter"
-#: postmaster/autovacuum.c:1449
+#: postmaster/autovacuum.c:1442
#, c-format
msgid "could not fork autovacuum worker process: %m"
msgstr "konnte Autovacuum-Worker-Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/autovacuum.c:1647
+#: postmaster/autovacuum.c:1640
#, c-format
msgid "autovacuum: processing database \"%s\""
msgstr "Autovacuum: bearbeite Datenbank »%s«"
-#: postmaster/autovacuum.c:2060
-#, c-format
-msgid "autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\""
+#: postmaster/autovacuum.c:2214
+#, fuzzy, c-format
+#| msgid "autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\""
+msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\""
msgstr "Autovacuum: lösche verwaiste temporäre Tabelle »%s.%s« in Datenbank »%s«"
-#: postmaster/autovacuum.c:2072
-#, c-format
-msgid "autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\""
-msgstr "Autovacuum: verwaiste temporäre Tabelle »%s.%s« in Datenbank »%s« gefunden"
-
-#: postmaster/autovacuum.c:2356
+#: postmaster/autovacuum.c:2420
#, c-format
msgid "automatic vacuum of table \"%s.%s.%s\""
msgstr "automatisches Vacuum der Tabelle »%s.%s.%s«"
-#: postmaster/autovacuum.c:2359
+#: postmaster/autovacuum.c:2423
#, c-format
msgid "automatic analyze of table \"%s.%s.%s\""
msgstr "automatisches Analysieren der Tabelle »%s.%s.%s«"
-#: postmaster/autovacuum.c:2889
+#: postmaster/autovacuum.c:2972
#, c-format
msgid "autovacuum not started because of misconfiguration"
msgstr "Autovacuum wegen Fehlkonfiguration nicht gestartet"
-#: postmaster/autovacuum.c:2890
+#: postmaster/autovacuum.c:2973
#, c-format
msgid "Enable the \"track_counts\" option."
msgstr "Schalten Sie die Option »track_counts« ein."
-#: postmaster/bgworker.c:346 postmaster/bgworker.c:746
+#: postmaster/bgworker.c:375 postmaster/bgworker.c:814
#, c-format
msgid "registering background worker \"%s\""
msgstr "registriere Background-Worker »%s«"
-#: postmaster/bgworker.c:375
+#: postmaster/bgworker.c:407
#, c-format
msgid "unregistering background worker \"%s\""
msgstr "deregistriere Background-Worker »%s«"
-#: postmaster/bgworker.c:484
+#: postmaster/bgworker.c:551
#, c-format
msgid "background worker \"%s\": must attach to shared memory in order to request a database connection"
msgstr "Background-Worker »%s«: muss mit Shared Memory verbinden, um eine Datenbankverbindung anzufordern"
-#: postmaster/bgworker.c:493
+#: postmaster/bgworker.c:560
#, c-format
msgid "background worker \"%s\": cannot request database access if starting at postmaster start"
msgstr "Background-Worker »%s«: kann kein Datenbankzugriff anfordern, wenn er nach Postmaster-Start gestartet hat"
-#: postmaster/bgworker.c:507
+#: postmaster/bgworker.c:574
#, c-format
msgid "background worker \"%s\": invalid restart interval"
msgstr "Background-Worker »%s«: ungültiges Neustart-Intervall"
-#: postmaster/bgworker.c:552
+#: postmaster/bgworker.c:619
#, c-format
msgid "terminating background worker \"%s\" due to administrator command"
msgstr "Background-Worker »%s« wird abgebrochen aufgrund von Anweisung des Administrators"
-#: postmaster/bgworker.c:753
+#: postmaster/bgworker.c:830
#, c-format
msgid "background worker \"%s\": must be registered in shared_preload_libraries"
msgstr "Background-Worker »%s«: muss in shared_preload_libraries registriert sein"
-#: postmaster/bgworker.c:765
+#: postmaster/bgworker.c:842
#, c-format
msgid "background worker \"%s\": only dynamic background workers can request notification"
msgstr "Background-Worker »%s«: nur dynamische Background-Worker können Benachrichtigung verlangen"
-#: postmaster/bgworker.c:780
+#: postmaster/bgworker.c:857
#, c-format
msgid "too many background workers"
msgstr "zu viele Background-Worker"
-#: postmaster/bgworker.c:781
+#: postmaster/bgworker.c:858
#, c-format
msgid "Up to %d background worker can be registered with the current settings."
msgid_plural "Up to %d background workers can be registered with the current settings."
msgstr[0] "Mit den aktuellen Einstellungen können bis zu %d Background-Worker registriert werden."
msgstr[1] "Mit den aktuellen Einstellungen können bis zu %d Background-Worker registriert werden."
-#: postmaster/bgworker.c:785
+#: postmaster/bgworker.c:862
#, c-format
msgid "Consider increasing the configuration parameter \"max_worker_processes\"."
msgstr "Erhöhen Sie eventuell den Konfigurationsparameter »max_worker_processes«."
@@ -14312,22 +15409,22 @@ msgstr[1] "Checkpoints passieren zu oft (alle %d Sekunden)"
msgid "Consider increasing the configuration parameter \"max_wal_size\"."
msgstr "Erhöhen Sie eventuell den Konfigurationsparameter »max_wal_size«."
-#: postmaster/checkpointer.c:616
+#: postmaster/checkpointer.c:629
#, c-format
msgid "transaction log switch forced (archive_timeout=%d)"
msgstr "Umschalten des Transaktionslogs erzwungen (archive_timeout=%d)"
-#: postmaster/checkpointer.c:1074
+#: postmaster/checkpointer.c:1088
#, c-format
msgid "checkpoint request failed"
msgstr "Checkpoint-Anforderung fehlgeschlagen"
-#: postmaster/checkpointer.c:1075
+#: postmaster/checkpointer.c:1089
#, c-format
msgid "Consult recent messages in the server log for details."
msgstr "Einzelheiten finden Sie in den letzten Meldungen im Serverlog."
-#: postmaster/checkpointer.c:1270
+#: postmaster/checkpointer.c:1284
#, c-format
msgid "compacted fsync request queue from %d entries to %d entries"
msgstr "fsync-Anfrageschlange von %d Einträgen auf %d Einträge zusammengefasst"
@@ -14337,349 +15434,349 @@ msgstr "fsync-Anfrageschlange von %d Einträgen auf %d Einträge zusammengefasst
msgid "could not fork archiver: %m"
msgstr "konnte Archivierer nicht starten (fork-Fehler): %m"
-#: postmaster/pgarch.c:456
+#: postmaster/pgarch.c:457
#, c-format
msgid "archive_mode enabled, yet archive_command is not set"
msgstr "archive_mode ist an, aber archive_command ist nicht gesetzt"
-#: postmaster/pgarch.c:484
+#: postmaster/pgarch.c:485
#, c-format
msgid "archiving transaction log file \"%s\" failed too many times, will try again later"
msgstr "Archivieren der Transaktionslogdatei »%s« schlug zu oft fehl, wird später erneut versucht"
-#: postmaster/pgarch.c:587
+#: postmaster/pgarch.c:588
#, c-format
msgid "archive command failed with exit code %d"
msgstr "Archivbefehl ist fehlgeschlagen mit Statuscode %d"
-#: postmaster/pgarch.c:589 postmaster/pgarch.c:599 postmaster/pgarch.c:606
-#: postmaster/pgarch.c:612 postmaster/pgarch.c:621
+#: postmaster/pgarch.c:590 postmaster/pgarch.c:600 postmaster/pgarch.c:607
+#: postmaster/pgarch.c:613 postmaster/pgarch.c:622
#, c-format
msgid "The failed archive command was: %s"
msgstr "Der fehlgeschlagene Archivbefehl war: %s"
-#: postmaster/pgarch.c:596
+#: postmaster/pgarch.c:597
#, c-format
msgid "archive command was terminated by exception 0x%X"
msgstr "Archivbefehl wurde durch Ausnahme 0x%X beendet"
-#: postmaster/pgarch.c:598 postmaster/postmaster.c:3482
+#: postmaster/pgarch.c:599 postmaster/postmaster.c:3527
#, c-format
msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value."
msgstr "Sehen Sie die Beschreibung des Hexadezimalwerts in der C-Include-Datei »ntstatus.h« nach."
-#: postmaster/pgarch.c:603
+#: postmaster/pgarch.c:604
#, c-format
msgid "archive command was terminated by signal %d: %s"
msgstr "Archivbefehl wurde von Signal %d beendet: %s"
-#: postmaster/pgarch.c:610
+#: postmaster/pgarch.c:611
#, c-format
msgid "archive command was terminated by signal %d"
msgstr "Archivbefehl wurde von Signal %d beendet"
-#: postmaster/pgarch.c:619
+#: postmaster/pgarch.c:620
#, c-format
msgid "archive command exited with unrecognized status %d"
msgstr "Archivbefehl hat mit unbekanntem Status %d beendet"
-#: postmaster/pgarch.c:631
+#: postmaster/pgarch.c:632
#, c-format
msgid "archived transaction log file \"%s\""
msgstr "archivierte Transaktionslogdatei »%s«"
-#: postmaster/pgarch.c:680
+#: postmaster/pgarch.c:681
#, c-format
msgid "could not open archive status directory \"%s\": %m"
msgstr "konnte Archivstatusverzeichnis »%s« nicht öffnen: %m"
-#: postmaster/pgstat.c:352
+#: postmaster/pgstat.c:360
#, c-format
msgid "could not resolve \"localhost\": %s"
msgstr "konnte »localhost« nicht auflösen: %s"
-#: postmaster/pgstat.c:375
+#: postmaster/pgstat.c:383
#, c-format
msgid "trying another address for the statistics collector"
msgstr "andere Adresse für Statistiksammelprozess wird versucht"
-#: postmaster/pgstat.c:384
+#: postmaster/pgstat.c:392
#, c-format
msgid "could not create socket for statistics collector: %m"
msgstr "konnte Socket für Statistiksammelprozess nicht erzeugen: %m"
-#: postmaster/pgstat.c:396
+#: postmaster/pgstat.c:404
#, c-format
msgid "could not bind socket for statistics collector: %m"
msgstr "konnte Socket für Statistiksammelprozess nicht binden: %m"
-#: postmaster/pgstat.c:407
+#: postmaster/pgstat.c:415
#, c-format
msgid "could not get address of socket for statistics collector: %m"
msgstr "konnte Adresse für Socket für Statistiksammelprozess nicht ermitteln: %m"
-#: postmaster/pgstat.c:423
+#: postmaster/pgstat.c:431
#, c-format
msgid "could not connect socket for statistics collector: %m"
msgstr "konnte nicht mit Socket für Statistiksammelprozess verbinden: %m"
-#: postmaster/pgstat.c:444
+#: postmaster/pgstat.c:452
#, c-format
msgid "could not send test message on socket for statistics collector: %m"
msgstr "konnte Testnachricht auf Socket für Statistiksammelprozess nicht senden: %m"
-#: postmaster/pgstat.c:470
+#: postmaster/pgstat.c:478
#, c-format
msgid "select() failed in statistics collector: %m"
msgstr "select() im Statistiksammelprozess fehlgeschlagen: %m"
-#: postmaster/pgstat.c:485
+#: postmaster/pgstat.c:493
#, c-format
msgid "test message did not get through on socket for statistics collector"
msgstr "Testnachricht auf Socket für Statistiksammelprozess kam nicht durch"
-#: postmaster/pgstat.c:500
+#: postmaster/pgstat.c:508
#, c-format
msgid "could not receive test message on socket for statistics collector: %m"
msgstr "konnte Testnachricht auf Socket für Statistiksammelprozess nicht empfangen: %m"
-#: postmaster/pgstat.c:510
+#: postmaster/pgstat.c:518
#, c-format
msgid "incorrect test message transmission on socket for statistics collector"
msgstr "fehlerhafte Übertragung der Testnachricht auf Socket für Statistiksammelprozess"
-#: postmaster/pgstat.c:533
+#: postmaster/pgstat.c:541
#, c-format
msgid "could not set statistics collector socket to nonblocking mode: %m"
msgstr "konnte Socket von Statistiksammelprozess nicht auf nicht blockierenden Modus setzen: %m"
-#: postmaster/pgstat.c:543
+#: postmaster/pgstat.c:551
#, c-format
msgid "disabling statistics collector for lack of working socket"
msgstr "Statistiksammelprozess abgeschaltet wegen nicht funkionierender Socket"
-#: postmaster/pgstat.c:690
+#: postmaster/pgstat.c:698
#, c-format
msgid "could not fork statistics collector: %m"
msgstr "konnte Statistiksammelprozess nicht starten (fork-Fehler): %m"
-#: postmaster/pgstat.c:1258
+#: postmaster/pgstat.c:1266
#, c-format
msgid "unrecognized reset target: \"%s\""
msgstr "unbekanntes Reset-Ziel: »%s«"
-#: postmaster/pgstat.c:1259
+#: postmaster/pgstat.c:1267
#, c-format
msgid "Target must be \"archiver\" or \"bgwriter\"."
msgstr "Das Reset-Ziel muss »archiver« oder »bgwriter« sein."
-#: postmaster/pgstat.c:3579
+#: postmaster/pgstat.c:3816
#, c-format
msgid "could not read statistics message: %m"
msgstr "konnte Statistiknachricht nicht lesen: %m"
-#: postmaster/pgstat.c:3910 postmaster/pgstat.c:4067
+#: postmaster/pgstat.c:4148 postmaster/pgstat.c:4305
#, c-format
msgid "could not open temporary statistics file \"%s\": %m"
msgstr "konnte temporäre Statistikdatei »%s« nicht öffnen: %m"
-#: postmaster/pgstat.c:3977 postmaster/pgstat.c:4112
+#: postmaster/pgstat.c:4215 postmaster/pgstat.c:4350
#, c-format
msgid "could not write temporary statistics file \"%s\": %m"
msgstr "konnte temporäre Statistikdatei »%s« nicht schreiben: %m"
-#: postmaster/pgstat.c:3986 postmaster/pgstat.c:4121
+#: postmaster/pgstat.c:4224 postmaster/pgstat.c:4359
#, c-format
msgid "could not close temporary statistics file \"%s\": %m"
msgstr "konnte temporäre Statistikdatei »%s« nicht schließen: %m"
-#: postmaster/pgstat.c:3994 postmaster/pgstat.c:4129
+#: postmaster/pgstat.c:4232 postmaster/pgstat.c:4367
#, c-format
msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m"
msgstr "konnte temporäre Statistikdatei »%s« nicht in »%s« umbenennen: %m"
-#: postmaster/pgstat.c:4218 postmaster/pgstat.c:4403 postmaster/pgstat.c:4556
+#: postmaster/pgstat.c:4456 postmaster/pgstat.c:4641 postmaster/pgstat.c:4794
#, c-format
msgid "could not open statistics file \"%s\": %m"
msgstr "konnte Statistikdatei »%s« nicht öffnen: %m"
-#: postmaster/pgstat.c:4230 postmaster/pgstat.c:4240 postmaster/pgstat.c:4250
-#: postmaster/pgstat.c:4271 postmaster/pgstat.c:4286 postmaster/pgstat.c:4340
-#: postmaster/pgstat.c:4415 postmaster/pgstat.c:4435 postmaster/pgstat.c:4453
-#: postmaster/pgstat.c:4469 postmaster/pgstat.c:4487 postmaster/pgstat.c:4503
-#: postmaster/pgstat.c:4568 postmaster/pgstat.c:4580 postmaster/pgstat.c:4592
-#: postmaster/pgstat.c:4617 postmaster/pgstat.c:4639
+#: postmaster/pgstat.c:4468 postmaster/pgstat.c:4478 postmaster/pgstat.c:4488
+#: postmaster/pgstat.c:4509 postmaster/pgstat.c:4524 postmaster/pgstat.c:4578
+#: postmaster/pgstat.c:4653 postmaster/pgstat.c:4673 postmaster/pgstat.c:4691
+#: postmaster/pgstat.c:4707 postmaster/pgstat.c:4725 postmaster/pgstat.c:4741
+#: postmaster/pgstat.c:4806 postmaster/pgstat.c:4818 postmaster/pgstat.c:4830
+#: postmaster/pgstat.c:4855 postmaster/pgstat.c:4877
#, c-format
msgid "corrupted statistics file \"%s\""
msgstr "verfälschte Statistikdatei »%s«"
-#: postmaster/pgstat.c:4768
+#: postmaster/pgstat.c:5006
#, c-format
msgid "using stale statistics instead of current ones because stats collector is not responding"
msgstr "verwende veraltete Statistiken anstatt aktueller, weil der Statistiksammelprozess nicht antwortet"
-#: postmaster/pgstat.c:5097
+#: postmaster/pgstat.c:5333
#, c-format
msgid "database hash table corrupted during cleanup --- abort"
msgstr "Datenbank-Hash-Tabelle beim Aufräumen verfälscht --- Abbruch"
-#: postmaster/postmaster.c:676
+#: postmaster/postmaster.c:692
#, c-format
msgid "%s: invalid argument for option -f: \"%s\"\n"
msgstr "%s: ungültiges Argument für Option -f: »%s«\n"
-#: postmaster/postmaster.c:762
+#: postmaster/postmaster.c:778
#, c-format
msgid "%s: invalid argument for option -t: \"%s\"\n"
msgstr "%s: ungültiges Argument für Option -t: »%s«\n"
-#: postmaster/postmaster.c:813
+#: postmaster/postmaster.c:829
#, c-format
msgid "%s: invalid argument: \"%s\"\n"
msgstr "%s: ungültiges Argument: »%s«\n"
-#: postmaster/postmaster.c:852
+#: postmaster/postmaster.c:868
#, c-format
msgid "%s: superuser_reserved_connections must be less than max_connections\n"
msgstr "%s: superuser_reserved_connections muss kleiner als max_connections sein\n"
-#: postmaster/postmaster.c:857
+#: postmaster/postmaster.c:873
#, c-format
msgid "%s: max_wal_senders must be less than max_connections\n"
msgstr "%s: max_wal_senders muss kleiner als max_connections sein\n"
-#: postmaster/postmaster.c:862
+#: postmaster/postmaster.c:878
#, c-format
msgid "WAL archival cannot be enabled when wal_level is \"minimal\""
msgstr "WAL-Archivierung kann nicht eingeschaltet werden, wenn wal_level »minimal« ist"
-#: postmaster/postmaster.c:865
+#: postmaster/postmaster.c:881
#, c-format
msgid "WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or \"logical\""
msgstr "WAL-Streaming (max_wal_senders > 0) benötigt wal_level »replica« oder »logical«"
-#: postmaster/postmaster.c:873
+#: postmaster/postmaster.c:889
#, c-format
msgid "%s: invalid datetoken tables, please fix\n"
msgstr "%s: ungültige datetoken-Tabellen, bitte reparieren\n"
-#: postmaster/postmaster.c:965 postmaster/postmaster.c:1063
+#: postmaster/postmaster.c:992 postmaster/postmaster.c:1090
#: utils/init/miscinit.c:1429
#, c-format
msgid "invalid list syntax in parameter \"%s\""
msgstr "ungültige Listensyntax für Parameter »%s«"
-#: postmaster/postmaster.c:996
+#: postmaster/postmaster.c:1023
#, c-format
msgid "could not create listen socket for \"%s\""
msgstr "konnte Listen-Socket für »%s« nicht erzeugen"
-#: postmaster/postmaster.c:1002
+#: postmaster/postmaster.c:1029
#, c-format
msgid "could not create any TCP/IP sockets"
msgstr "konnte keine TCP/IP-Sockets erstellen"
-#: postmaster/postmaster.c:1085
+#: postmaster/postmaster.c:1112
#, c-format
msgid "could not create Unix-domain socket in directory \"%s\""
msgstr "konnte Unix-Domain-Socket in Verzeichnis »%s« nicht erzeugen"
-#: postmaster/postmaster.c:1091
+#: postmaster/postmaster.c:1118
#, c-format
msgid "could not create any Unix-domain sockets"
msgstr "konnte keine Unix-Domain-Sockets erzeugen"
-#: postmaster/postmaster.c:1103
+#: postmaster/postmaster.c:1130
#, c-format
msgid "no socket created for listening"
msgstr "keine Listen-Socket erzeugt"
-#: postmaster/postmaster.c:1143
+#: postmaster/postmaster.c:1170
#, c-format
msgid "could not create I/O completion port for child queue"
msgstr "konnte Ein-/Ausgabe-Completion-Port für Child-Queue nicht erzeugen"
-#: postmaster/postmaster.c:1172
+#: postmaster/postmaster.c:1199
#, c-format
msgid "%s: could not change permissions of external PID file \"%s\": %s\n"
msgstr "%s: konnte Rechte der externen PID-Datei »%s« nicht ändern: %s\n"
-#: postmaster/postmaster.c:1176
+#: postmaster/postmaster.c:1203
#, c-format
msgid "%s: could not write external PID file \"%s\": %s\n"
msgstr "%s: konnte externe PID-Datei »%s« nicht schreiben: %s\n"
-#: postmaster/postmaster.c:1226
+#: postmaster/postmaster.c:1260
#, c-format
msgid "ending log output to stderr"
msgstr "Logausgabe nach stderr endet"
-#: postmaster/postmaster.c:1227
+#: postmaster/postmaster.c:1261
#, c-format
msgid "Future log output will go to log destination \"%s\"."
msgstr "Die weitere Logausgabe geht an Logziel »%s«."
-#: postmaster/postmaster.c:1253 utils/init/postinit.c:215
+#: postmaster/postmaster.c:1287 utils/init/postinit.c:213
#, c-format
msgid "could not load pg_hba.conf"
msgstr "konnte pg_hba.conf nicht laden"
-#: postmaster/postmaster.c:1279
+#: postmaster/postmaster.c:1313
#, c-format
msgid "postmaster became multithreaded during startup"
msgstr "Postmaster ist während des Starts multithreaded geworden"
-#: postmaster/postmaster.c:1280
+#: postmaster/postmaster.c:1314
#, c-format
msgid "Set the LC_ALL environment variable to a valid locale."
msgstr "Setzen Sie die Umgebungsvariable LC_ALL auf eine gültige Locale."
-#: postmaster/postmaster.c:1377
+#: postmaster/postmaster.c:1413
#, c-format
msgid "%s: could not locate matching postgres executable"
msgstr "%s: konnte kein passendes Programm »postgres« finden"
-#: postmaster/postmaster.c:1400 utils/misc/tzparser.c:341
+#: postmaster/postmaster.c:1436 utils/misc/tzparser.c:341
#, c-format
msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location."
msgstr "Dies kann auf eine unvollständige PostgreSQL-Installation hindeuten, oder darauf, dass die Datei »%s« von ihrer richtigen Stelle verschoben worden ist."
-#: postmaster/postmaster.c:1428
+#: postmaster/postmaster.c:1464
#, c-format
msgid "data directory \"%s\" does not exist"
msgstr "Datenverzeichnis »%s« existiert nicht"
-#: postmaster/postmaster.c:1433
+#: postmaster/postmaster.c:1469
#, c-format
msgid "could not read permissions of directory \"%s\": %m"
msgstr "konnte Zugriffsrechte von Verzeichnis »%s« nicht lesen: %m"
-#: postmaster/postmaster.c:1441
+#: postmaster/postmaster.c:1477
#, c-format
msgid "specified data directory \"%s\" is not a directory"
msgstr "angegebenes Datenverzeichnis »%s« ist kein Verzeichnis"
-#: postmaster/postmaster.c:1457
+#: postmaster/postmaster.c:1493
#, c-format
msgid "data directory \"%s\" has wrong ownership"
msgstr "Datenverzeichnis »%s« hat falschen Eigentümer"
-#: postmaster/postmaster.c:1459
+#: postmaster/postmaster.c:1495
#, c-format
msgid "The server must be started by the user that owns the data directory."
msgstr "Der Server muss von dem Benutzer gestartet werden, dem das Datenverzeichnis gehört."
-#: postmaster/postmaster.c:1479
+#: postmaster/postmaster.c:1515
#, c-format
msgid "data directory \"%s\" has group or world access"
msgstr "Datenverzeichnis »%s« erlaubt Zugriff von Gruppe oder Welt"
-#: postmaster/postmaster.c:1481
+#: postmaster/postmaster.c:1517
#, c-format
msgid "Permissions should be u=rwx (0700)."
msgstr "Rechte sollten u=rwx (0700) sein."
-#: postmaster/postmaster.c:1492
+#: postmaster/postmaster.c:1528
#, c-format
msgid ""
"%s: could not find the database system\n"
@@ -14690,420 +15787,445 @@ msgstr ""
"Es wurde im Verzeichnis »%s« erwartet,\n"
"aber die Datei »%s« konnte nicht geöffnet werden: %s\n"
-#: postmaster/postmaster.c:1669
+#: postmaster/postmaster.c:1705
#, c-format
msgid "select() failed in postmaster: %m"
msgstr "select() fehlgeschlagen im Postmaster: %m"
-#: postmaster/postmaster.c:1819
+#: postmaster/postmaster.c:1856
#, c-format
msgid "performing immediate shutdown because data directory lock file is invalid"
msgstr "führe sofortiges Herunterfahren durch, weil Sperrdatei im Datenverzeichnis ungültig ist"
-#: postmaster/postmaster.c:1897 postmaster/postmaster.c:1928
+#: postmaster/postmaster.c:1934 postmaster/postmaster.c:1965
#, c-format
msgid "incomplete startup packet"
msgstr "unvollständiges Startpaket"
-#: postmaster/postmaster.c:1909
+#: postmaster/postmaster.c:1946
#, c-format
msgid "invalid length of startup packet"
msgstr "ungültige Länge des Startpakets"
-#: postmaster/postmaster.c:1967
+#: postmaster/postmaster.c:2004
#, c-format
msgid "failed to send SSL negotiation response: %m"
msgstr "konnte SSL-Verhandlungsantwort nicht senden: %m"
-#: postmaster/postmaster.c:1996
+#: postmaster/postmaster.c:2033
#, c-format
msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u"
msgstr "nicht unterstütztes Frontend-Protokoll %u.%u: Server unterstützt %u.0 bis %u.%u"
-#: postmaster/postmaster.c:2059 utils/misc/guc.c:5658 utils/misc/guc.c:5751
-#: utils/misc/guc.c:7049 utils/misc/guc.c:9785 utils/misc/guc.c:9819
+#: postmaster/postmaster.c:2096 utils/misc/guc.c:5726 utils/misc/guc.c:5819
+#: utils/misc/guc.c:7117 utils/misc/guc.c:9870 utils/misc/guc.c:9904
#, c-format
msgid "invalid value for parameter \"%s\": \"%s\""
msgstr "ungültiger Wert für Parameter »%s«: »%s«"
-#: postmaster/postmaster.c:2062
+#: postmaster/postmaster.c:2099
#, c-format
msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"."
msgstr "Gültige Werte sind: »false«, 0, »true«, 1, »database«."
-#: postmaster/postmaster.c:2082
+#: postmaster/postmaster.c:2119
#, c-format
msgid "invalid startup packet layout: expected terminator as last byte"
msgstr "ungültiges Layout des Startpakets: Abschluss als letztes Byte erwartet"
-#: postmaster/postmaster.c:2110
+#: postmaster/postmaster.c:2147
#, c-format
msgid "no PostgreSQL user name specified in startup packet"
msgstr "kein PostgreSQL-Benutzername im Startpaket angegeben"
-#: postmaster/postmaster.c:2169
+#: postmaster/postmaster.c:2206
#, c-format
msgid "the database system is starting up"
msgstr "das Datenbanksystem startet"
-#: postmaster/postmaster.c:2174
+#: postmaster/postmaster.c:2211
#, c-format
msgid "the database system is shutting down"
msgstr "das Datenbanksystem fährt herunter"
-#: postmaster/postmaster.c:2179
+#: postmaster/postmaster.c:2216
#, c-format
msgid "the database system is in recovery mode"
msgstr "das Datenbanksystem ist im Wiederherstellungsmodus"
-#: postmaster/postmaster.c:2184 storage/ipc/procarray.c:297
-#: storage/ipc/sinvaladt.c:298 storage/lmgr/proc.c:340
+#: postmaster/postmaster.c:2221 storage/ipc/procarray.c:290
+#: storage/ipc/sinvaladt.c:298 storage/lmgr/proc.c:338
#, c-format
msgid "sorry, too many clients already"
msgstr "tut mir leid, schon zu viele Verbindungen"
-#: postmaster/postmaster.c:2246
+#: postmaster/postmaster.c:2283
#, c-format
msgid "wrong key in cancel request for process %d"
msgstr "falscher Schlüssel in Stornierungsanfrage für Prozess %d"
-#: postmaster/postmaster.c:2254
+#: postmaster/postmaster.c:2291
#, c-format
msgid "PID %d in cancel request did not match any process"
msgstr "PID %d in Stornierungsanfrage stimmte mit keinem Prozess überein"
-#: postmaster/postmaster.c:2474
+#: postmaster/postmaster.c:2502
#, c-format
msgid "received SIGHUP, reloading configuration files"
msgstr "SIGHUP empfangen, Konfigurationsdateien werden neu geladen"
-#: postmaster/postmaster.c:2499
-#, c-format
-msgid "pg_hba.conf not reloaded"
+#: postmaster/postmaster.c:2527
+#, fuzzy, c-format
+#| msgid "pg_hba.conf not reloaded"
+msgid "pg_hba.conf was not reloaded"
msgstr "pg_hba.conf nicht neu geladen"
-#: postmaster/postmaster.c:2503
-#, c-format
-msgid "pg_ident.conf not reloaded"
+#: postmaster/postmaster.c:2531
+#, fuzzy, c-format
+#| msgid "pg_ident.conf not reloaded"
+msgid "pg_ident.conf was not reloaded"
msgstr "pg_ident.conf nicht neu geladen"
-#: postmaster/postmaster.c:2544
+#: postmaster/postmaster.c:2541
+#, fuzzy, c-format
+#| msgid "text search configuration parameter \"%s\" not recognized"
+msgid "SSL configuration was not reloaded"
+msgstr "Textsuchekonfigurationsparameter »%s« nicht erkannt"
+
+#: postmaster/postmaster.c:2589
#, c-format
msgid "received smart shutdown request"
msgstr "intelligentes Herunterfahren verlangt"
-#: postmaster/postmaster.c:2599
+#: postmaster/postmaster.c:2644
#, c-format
msgid "received fast shutdown request"
msgstr "schnelles Herunterfahren verlangt"
-#: postmaster/postmaster.c:2629
+#: postmaster/postmaster.c:2674
#, c-format
msgid "aborting any active transactions"
msgstr "etwaige aktive Transaktionen werden abgebrochen"
-#: postmaster/postmaster.c:2663
+#: postmaster/postmaster.c:2708
#, c-format
msgid "received immediate shutdown request"
msgstr "sofortiges Herunterfahren verlangt"
-#: postmaster/postmaster.c:2727
+#: postmaster/postmaster.c:2772
#, c-format
msgid "shutdown at recovery target"
msgstr "Herunterfahren beim Wiederherstellungsziel"
-#: postmaster/postmaster.c:2743 postmaster/postmaster.c:2766
+#: postmaster/postmaster.c:2788 postmaster/postmaster.c:2811
msgid "startup process"
msgstr "Startprozess"
-#: postmaster/postmaster.c:2746
+#: postmaster/postmaster.c:2791
#, c-format
msgid "aborting startup due to startup process failure"
msgstr "Serverstart abgebrochen wegen Startprozessfehler"
-#: postmaster/postmaster.c:2807
+#: postmaster/postmaster.c:2852
#, c-format
msgid "database system is ready to accept connections"
msgstr "Datenbanksystem ist bereit, um Verbindungen anzunehmen"
-#: postmaster/postmaster.c:2826
+#: postmaster/postmaster.c:2871
msgid "background writer process"
msgstr "Background-Writer-Prozess"
-#: postmaster/postmaster.c:2880
+#: postmaster/postmaster.c:2925
msgid "checkpointer process"
msgstr "Checkpointer-Prozess"
-#: postmaster/postmaster.c:2896
+#: postmaster/postmaster.c:2941
msgid "WAL writer process"
msgstr "WAL-Schreibprozess"
-#: postmaster/postmaster.c:2910
+#: postmaster/postmaster.c:2955
msgid "WAL receiver process"
msgstr "WAL-Receiver-Prozess"
-#: postmaster/postmaster.c:2925
+#: postmaster/postmaster.c:2970
msgid "autovacuum launcher process"
msgstr "Autovacuum-Launcher-Prozess"
-#: postmaster/postmaster.c:2940
+#: postmaster/postmaster.c:2985
msgid "archiver process"
msgstr "Archivierprozess"
-#: postmaster/postmaster.c:2956
+#: postmaster/postmaster.c:3001
msgid "statistics collector process"
msgstr "Statistiksammelprozess"
-#: postmaster/postmaster.c:2970
+#: postmaster/postmaster.c:3015
msgid "system logger process"
msgstr "Systemlogger-Prozess"
-#: postmaster/postmaster.c:3032
+#: postmaster/postmaster.c:3077
msgid "worker process"
msgstr "Worker-Prozess"
-#: postmaster/postmaster.c:3115 postmaster/postmaster.c:3135
-#: postmaster/postmaster.c:3142 postmaster/postmaster.c:3160
+#: postmaster/postmaster.c:3160 postmaster/postmaster.c:3180
+#: postmaster/postmaster.c:3187 postmaster/postmaster.c:3205
msgid "server process"
msgstr "Serverprozess"
-#: postmaster/postmaster.c:3214
+#: postmaster/postmaster.c:3259
#, c-format
msgid "terminating any other active server processes"
msgstr "aktive Serverprozesse werden abgebrochen"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3470
+#: postmaster/postmaster.c:3515
#, c-format
msgid "%s (PID %d) exited with exit code %d"
msgstr "%s (PID %d) beendete mit Status %d"
-#: postmaster/postmaster.c:3472 postmaster/postmaster.c:3483
-#: postmaster/postmaster.c:3494 postmaster/postmaster.c:3503
-#: postmaster/postmaster.c:3513
+#: postmaster/postmaster.c:3517 postmaster/postmaster.c:3528
+#: postmaster/postmaster.c:3539 postmaster/postmaster.c:3548
+#: postmaster/postmaster.c:3558
#, c-format
msgid "Failed process was running: %s"
msgstr "Der fehlgeschlagene Prozess führte aus: %s"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3480
+#: postmaster/postmaster.c:3525
#, c-format
msgid "%s (PID %d) was terminated by exception 0x%X"
msgstr "%s (PID %d) wurde durch Ausnahme 0x%X beendet"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3490
+#: postmaster/postmaster.c:3535
#, c-format
msgid "%s (PID %d) was terminated by signal %d: %s"
msgstr "%s (PID %d) wurde von Signal %d beendet: %s"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3501
+#: postmaster/postmaster.c:3546
#, c-format
msgid "%s (PID %d) was terminated by signal %d"
msgstr "%s (PID %d) wurde von Signal %d beendet"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3511
+#: postmaster/postmaster.c:3556
#, c-format
msgid "%s (PID %d) exited with unrecognized status %d"
msgstr "%s (PID %d) beendete mit unbekanntem Status %d"
-#: postmaster/postmaster.c:3698
+#: postmaster/postmaster.c:3743
#, c-format
msgid "abnormal database system shutdown"
msgstr "abnormales Herunterfahren des Datenbanksystems"
-#: postmaster/postmaster.c:3738
+#: postmaster/postmaster.c:3783
#, c-format
msgid "all server processes terminated; reinitializing"
msgstr "alle Serverprozesse beendet; initialisiere neu"
-#: postmaster/postmaster.c:3950
+#: postmaster/postmaster.c:3949 postmaster/postmaster.c:5343
+#: postmaster/postmaster.c:5649
+#, fuzzy, c-format
+#| msgid "could not generate random encryption vector"
+msgid "could not generate random cancel key"
+msgstr "konnte zufälligen Verschlüsselungsvektor nicht erzeugen"
+
+#: postmaster/postmaster.c:4003
#, c-format
msgid "could not fork new process for connection: %m"
msgstr "konnte neuen Prozess für Verbindung nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:3992
+#: postmaster/postmaster.c:4045
msgid "could not fork new process for connection: "
msgstr "konnte neuen Prozess für Verbindung nicht starten (fork-Fehler): "
-#: postmaster/postmaster.c:4106
+#: postmaster/postmaster.c:4159
#, c-format
msgid "connection received: host=%s port=%s"
msgstr "Verbindung empfangen: Host=%s Port=%s"
-#: postmaster/postmaster.c:4111
+#: postmaster/postmaster.c:4164
#, c-format
msgid "connection received: host=%s"
msgstr "Verbindung empfangen: Host=%s"
-#: postmaster/postmaster.c:4394
+#: postmaster/postmaster.c:4449
#, c-format
msgid "could not execute server process \"%s\": %m"
msgstr "konnte Serverprozess »%s« nicht ausführen: %m"
-#: postmaster/postmaster.c:4959
+#: postmaster/postmaster.c:4792
+#, c-format
+msgid "SSL configuration could not be loaded in child process"
+msgstr ""
+
+#: postmaster/postmaster.c:4924
+#, c-format
+msgid "Please report this to <[email protected]>."
+msgstr "Bitte berichten Sie das an <[email protected]>."
+
+#: postmaster/postmaster.c:5003
#, c-format
msgid "database system is ready to accept read only connections"
msgstr "Datenbanksystem ist bereit, um lesende Verbindungen anzunehmen"
-#: postmaster/postmaster.c:5246
+#: postmaster/postmaster.c:5271
#, c-format
msgid "could not fork startup process: %m"
msgstr "konnte Startprozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5250
+#: postmaster/postmaster.c:5275
#, c-format
msgid "could not fork background writer process: %m"
msgstr "konnte Background-Writer-Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5254
+#: postmaster/postmaster.c:5279
#, c-format
msgid "could not fork checkpointer process: %m"
msgstr "konnte Checkpointer-Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5258
+#: postmaster/postmaster.c:5283
#, c-format
msgid "could not fork WAL writer process: %m"
msgstr "konnte WAL-Writer-Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5262
+#: postmaster/postmaster.c:5287
#, c-format
msgid "could not fork WAL receiver process: %m"
msgstr "konnte WAL-Receiver-Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5266
+#: postmaster/postmaster.c:5291
#, c-format
msgid "could not fork process: %m"
msgstr "konnte Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5428 postmaster/postmaster.c:5451
+#: postmaster/postmaster.c:5460 postmaster/postmaster.c:5483
#, c-format
msgid "database connection requirement not indicated during registration"
msgstr "die Notwendigkeit, Datenbankverbindungen zu erzeugen, wurde bei der Registrierung nicht angezeigt"
-#: postmaster/postmaster.c:5435 postmaster/postmaster.c:5458
+#: postmaster/postmaster.c:5467 postmaster/postmaster.c:5490
#, c-format
msgid "invalid processing mode in background worker"
msgstr "ungültiger Verarbeitungsmodus in Background-Worker"
-#: postmaster/postmaster.c:5510
+#: postmaster/postmaster.c:5542
#, c-format
msgid "starting background worker process \"%s\""
msgstr "starte Background-Worker-Prozess »%s«"
-#: postmaster/postmaster.c:5521
+#: postmaster/postmaster.c:5553
#, c-format
msgid "could not fork worker process: %m"
msgstr "konnte Worker-Prozess nicht starten (fork-Fehler): %m"
-#: postmaster/postmaster.c:5909
+#: postmaster/postmaster.c:5950
#, c-format
msgid "could not duplicate socket %d for use in backend: error code %d"
msgstr "konnte Socket %d nicht für Verwendung in Backend duplizieren: Fehlercode %d"
-#: postmaster/postmaster.c:5941
+#: postmaster/postmaster.c:5982
#, c-format
msgid "could not create inherited socket: error code %d\n"
msgstr "konnte geerbtes Socket nicht erzeugen: Fehlercode %d\n"
-#: postmaster/postmaster.c:5970
+#: postmaster/postmaster.c:6011
#, c-format
msgid "could not open backend variables file \"%s\": %s\n"
msgstr "konnte Servervariablendatei »%s« nicht öffnen: %s\n"
-#: postmaster/postmaster.c:5977
+#: postmaster/postmaster.c:6018
#, c-format
msgid "could not read from backend variables file \"%s\": %s\n"
msgstr "konnte nicht aus Servervariablendatei »%s« lesen: %s\n"
-#: postmaster/postmaster.c:5986
+#: postmaster/postmaster.c:6027
#, c-format
msgid "could not remove file \"%s\": %s\n"
msgstr "konnte Datei »%s« nicht löschen: %s\n"
-#: postmaster/postmaster.c:6003
+#: postmaster/postmaster.c:6044
#, c-format
msgid "could not map view of backend variables: error code %lu\n"
msgstr "konnte Sicht der Backend-Variablen nicht mappen: Fehlercode %lu\n"
-#: postmaster/postmaster.c:6012
+#: postmaster/postmaster.c:6053
#, c-format
msgid "could not unmap view of backend variables: error code %lu\n"
msgstr "konnte Sicht der Backend-Variablen nicht unmappen: Fehlercode %lu\n"
-#: postmaster/postmaster.c:6019
+#: postmaster/postmaster.c:6060
#, c-format
msgid "could not close handle to backend parameter variables: error code %lu\n"
msgstr "konnte Handle für Backend-Parametervariablen nicht schließen: Fehlercode %lu\n"
-#: postmaster/postmaster.c:6180
+#: postmaster/postmaster.c:6221
#, c-format
msgid "could not read exit code for process\n"
msgstr "konnte Exitcode des Prozesses nicht lesen\n"
-#: postmaster/postmaster.c:6185
+#: postmaster/postmaster.c:6226
#, c-format
msgid "could not post child completion status\n"
msgstr "konnte Child-Completion-Status nicht versenden\n"
-#: postmaster/syslogger.c:441 postmaster/syslogger.c:1041
+#: postmaster/syslogger.c:452 postmaster/syslogger.c:1053
#, c-format
msgid "could not read from logger pipe: %m"
msgstr "konnte nicht aus Logger-Pipe lesen: %m"
-#: postmaster/syslogger.c:490
+#: postmaster/syslogger.c:502
#, c-format
msgid "logger shutting down"
msgstr "Logger fährt herunter"
-#: postmaster/syslogger.c:534 postmaster/syslogger.c:548
+#: postmaster/syslogger.c:546 postmaster/syslogger.c:560
#, c-format
msgid "could not create pipe for syslog: %m"
msgstr "konnte Pipe für Syslog nicht erzeugen: %m"
-#: postmaster/syslogger.c:584
+#: postmaster/syslogger.c:596
#, c-format
msgid "could not fork system logger: %m"
msgstr "konnte Systemlogger nicht starten (fork-Fehler): %m"
-#: postmaster/syslogger.c:620
+#: postmaster/syslogger.c:632
#, c-format
msgid "redirecting log output to logging collector process"
msgstr "Logausgabe wird an Logsammelprozess umgeleitet"
-#: postmaster/syslogger.c:621
+#: postmaster/syslogger.c:633
#, c-format
msgid "Future log output will appear in directory \"%s\"."
msgstr "Die weitere Logausgabe wird im Verzeichnis »%s« erscheinen."
-#: postmaster/syslogger.c:629
+#: postmaster/syslogger.c:641
#, c-format
msgid "could not redirect stdout: %m"
msgstr "konnte Standardausgabe nicht umleiten: %m"
-#: postmaster/syslogger.c:634 postmaster/syslogger.c:651
+#: postmaster/syslogger.c:646 postmaster/syslogger.c:663
#, c-format
msgid "could not redirect stderr: %m"
msgstr "konnte Standardfehlerausgabe nicht umleiten: %m"
-#: postmaster/syslogger.c:996
+#: postmaster/syslogger.c:1008
#, c-format
msgid "could not write to log file: %s\n"
msgstr "konnte nicht in Logdatei schreiben: %s\n"
-#: postmaster/syslogger.c:1136
+#: postmaster/syslogger.c:1150
#, c-format
msgid "could not open log file \"%s\": %m"
msgstr "konnte Logdatei »%s« nicht öffnen: %m"
-#: postmaster/syslogger.c:1198 postmaster/syslogger.c:1242
+#: postmaster/syslogger.c:1212 postmaster/syslogger.c:1256
#, c-format
msgid "disabling automatic rotation (use SIGHUP to re-enable)"
msgstr "automatische Rotation abgeschaltet (SIGHUP zum Wiederanschalten verwenden)"
@@ -15113,177 +16235,217 @@ msgstr "automatische Rotation abgeschaltet (SIGHUP zum Wiederanschalten verwende
msgid "could not determine which collation to use for regular expression"
msgstr "konnte die für den regulären Ausdruck zu verwendende Sortierfolge nicht bestimmen"
-#: repl_gram.y:260 repl_gram.y:292
+#: repl_gram.y:280 repl_gram.y:317
#, c-format
msgid "invalid timeline %u"
msgstr "ungültige Zeitleiste %u"
-#: repl_scanner.l:120
+#: repl_scanner.l:122
msgid "invalid streaming start location"
msgstr "ungültige Streaming-Startposition"
-#: repl_scanner.l:171 scan.l:670
+#: repl_scanner.l:173 scan.l:670
msgid "unterminated quoted string"
msgstr "Zeichenkette in Anführungszeichen nicht abgeschlossen"
-#: repl_scanner.l:181
+#: repl_scanner.l:183
#, c-format
msgid "syntax error: unexpected character \"%s\""
msgstr "Syntaxfehler: unerwartetes Zeichen »%s«"
-#: replication/basebackup.c:230
+#: replication/basebackup.c:303
#, c-format
msgid "could not stat control file \"%s\": %m"
msgstr "konnte »stat« für Kontrolldatei »%s« nicht ausführen: %m"
-#: replication/basebackup.c:339
+#: replication/basebackup.c:412
#, c-format
msgid "could not find any WAL files"
msgstr "konnte keine WAL-Dateien finden"
-#: replication/basebackup.c:352 replication/basebackup.c:366
-#: replication/basebackup.c:375
+#: replication/basebackup.c:425 replication/basebackup.c:439
+#: replication/basebackup.c:448
#, c-format
msgid "could not find WAL file \"%s\""
msgstr "konnte WAL-Datei »%s« nicht finden"
-#: replication/basebackup.c:414 replication/basebackup.c:440
+#: replication/basebackup.c:487 replication/basebackup.c:513
#, c-format
msgid "unexpected WAL file size \"%s\""
msgstr "unerwartete WAL-Dateigröße »%s«"
-#: replication/basebackup.c:426 replication/basebackup.c:1172
+#: replication/basebackup.c:499 replication/basebackup.c:1228
#, c-format
msgid "base backup could not send data, aborting backup"
msgstr "Basissicherung konnte keine Daten senden, Sicherung abgebrochen"
-#: replication/basebackup.c:528 replication/basebackup.c:537
-#: replication/basebackup.c:546 replication/basebackup.c:555
-#: replication/basebackup.c:564 replication/basebackup.c:575
-#: replication/basebackup.c:592
+#: replication/basebackup.c:601 replication/basebackup.c:610
+#: replication/basebackup.c:619 replication/basebackup.c:628
+#: replication/basebackup.c:637 replication/basebackup.c:648
+#: replication/basebackup.c:665
#, c-format
msgid "duplicate option \"%s\""
msgstr "doppelte Option »%s«"
-#: replication/basebackup.c:581 utils/misc/guc.c:5668
+#: replication/basebackup.c:654 utils/misc/guc.c:5736
#, c-format
msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)"
msgstr "%d ist außerhalb des gültigen Bereichs für Parameter »%s« (%d ... %d)"
-#: replication/basebackup.c:855 replication/basebackup.c:957
+#: replication/basebackup.c:928 replication/basebackup.c:1025
#, c-format
msgid "could not stat file or directory \"%s\": %m"
msgstr "konnte »stat« für Datei oder Verzeichnis »%s« nicht ausführen: %m"
-#: replication/basebackup.c:1124
+#: replication/basebackup.c:1180
#, c-format
msgid "skipping special file \"%s\""
msgstr "überspringe besondere Datei »%s«"
-#: replication/basebackup.c:1235
+#: replication/basebackup.c:1293
#, c-format
msgid "file name too long for tar format: \"%s\""
msgstr "Dateiname zu lang für Tar-Format: »%s«"
-#: replication/basebackup.c:1240
+#: replication/basebackup.c:1298
#, c-format
msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\""
msgstr "Ziel der symbolischen Verknüpfung zu lang für Tar-Format: Dateiname »%s«, Ziel »%s«"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:119
-#, c-format
-msgid "could not connect to the primary server: %s"
-msgstr "konnte nicht mit dem Primärserver verbinden: %s"
+#: replication/libpqwalreceiver/libpqwalreceiver.c:221
+#, fuzzy, c-format
+#| msgid "invalid connection type: %s"
+msgid "invalid connection string syntax: %s"
+msgstr "ungültiger Verbindungstyp: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:142
+#: replication/libpqwalreceiver/libpqwalreceiver.c:245
#, c-format
msgid "could not parse connection string: %s"
msgstr "konnte Verbindungsparameter nicht interpretieren: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:192
+#: replication/libpqwalreceiver/libpqwalreceiver.c:295
#, c-format
msgid "could not receive database system identifier and timeline ID from the primary server: %s"
msgstr "konnte Datenbanksystemidentifikator und Zeitleisten-ID nicht vom Primärserver empfangen: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:203
-#: replication/libpqwalreceiver/libpqwalreceiver.c:357
+#: replication/libpqwalreceiver/libpqwalreceiver.c:306
+#: replication/libpqwalreceiver/libpqwalreceiver.c:512
#, c-format
msgid "invalid response from primary server"
msgstr "ungültige Antwort vom Primärserver"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:204
+#: replication/libpqwalreceiver/libpqwalreceiver.c:307
#, c-format
msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields."
msgstr "Konnte System nicht identifizieren: %d Zeilen und %d Felder erhalten, %d Zeilen und %d oder mehr Felder erwartet."
-#: replication/libpqwalreceiver/libpqwalreceiver.c:220
-#, c-format
-msgid "database system identifier differs between the primary and standby"
-msgstr "Datenbanksystemidentifikator unterscheidet sich zwischen Primär- und Standby-Server"
-
-#: replication/libpqwalreceiver/libpqwalreceiver.c:221
-#, c-format
-msgid "The primary's identifier is %s, the standby's identifier is %s."
-msgstr "Identifikator des Primärservers ist %s, Identifikator des Standby ist %s."
-
-#: replication/libpqwalreceiver/libpqwalreceiver.c:263
+#: replication/libpqwalreceiver/libpqwalreceiver.c:373
+#: replication/libpqwalreceiver/libpqwalreceiver.c:379
+#: replication/libpqwalreceiver/libpqwalreceiver.c:404
#, c-format
msgid "could not start WAL streaming: %s"
msgstr "konnte WAL-Streaming nicht starten: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:281
+#: replication/libpqwalreceiver/libpqwalreceiver.c:423
#, c-format
msgid "could not send end-of-streaming message to primary: %s"
msgstr "konnte End-of-Streaming-Nachricht nicht an Primärserver senden: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:303
+#: replication/libpqwalreceiver/libpqwalreceiver.c:447
#, c-format
msgid "unexpected result set after end-of-streaming"
msgstr "unerwartete Ergebnismenge nach End-of-Streaming"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:315
+#: replication/libpqwalreceiver/libpqwalreceiver.c:467
#, c-format
msgid "error reading result of streaming command: %s"
msgstr "Fehler beim Lesen des Ergebnisses von Streaming-Befehl: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:323
+#: replication/libpqwalreceiver/libpqwalreceiver.c:475
#, c-format
msgid "unexpected result after CommandComplete: %s"
msgstr "unerwartetes Ergebnis nach CommandComplete: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:346
+#: replication/libpqwalreceiver/libpqwalreceiver.c:501
#, c-format
msgid "could not receive timeline history file from the primary server: %s"
msgstr "konnte Zeitleisten-History-Datei nicht vom Primärserver empfangen: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:358
+#: replication/libpqwalreceiver/libpqwalreceiver.c:513
#, c-format
msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields."
msgstr "1 Tupel mit 2 Feldern erwartet, %d Tupel mit %d Feldern erhalten."
-#: replication/libpqwalreceiver/libpqwalreceiver.c:386
-#, c-format
-msgid "invalid socket: %s"
-msgstr "ungültiges Socket: %s"
-
-#: replication/libpqwalreceiver/libpqwalreceiver.c:426
-#: storage/ipc/latch.c:1277
-#, c-format
-msgid "select() failed: %m"
-msgstr "select() fehlgeschlagen: %m"
-
-#: replication/libpqwalreceiver/libpqwalreceiver.c:549
-#: replication/libpqwalreceiver/libpqwalreceiver.c:576
-#: replication/libpqwalreceiver/libpqwalreceiver.c:582
+#: replication/libpqwalreceiver/libpqwalreceiver.c:660
+#: replication/libpqwalreceiver/libpqwalreceiver.c:687
+#: replication/libpqwalreceiver/libpqwalreceiver.c:693
#, c-format
msgid "could not receive data from WAL stream: %s"
msgstr "konnte keine Daten vom WAL-Stream empfangen: %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:601
+#: replication/libpqwalreceiver/libpqwalreceiver.c:712
#, c-format
msgid "could not send data to WAL stream: %s"
msgstr "konnte keine Daten an den WAL-Stream senden: %s"
+#: replication/libpqwalreceiver/libpqwalreceiver.c:746
+#, fuzzy, c-format
+#| msgid "could not create directory \"%s\": %s\n"
+msgid "could not create replication slot \"%s\": %s"
+msgstr "konnte Verzeichnis »%s« nicht erzeugen: %s\n"
+
+#: replication/logical/launcher.c:236
+#, fuzzy, c-format
+#| msgid "starting logical decoding for slot \"%s\""
+msgid "starting logical replication worker for subscription \"%s\""
+msgstr "starte logisches Dekodieren für Slot »%s«"
+
+#: replication/logical/launcher.c:243
+#, fuzzy, c-format
+#| msgid "cannot query or manipulate replication origin when max_replication_slots = 0"
+msgid "cannot start logical replication workers when max_replication_slots = 0"
+msgstr "Replication-Origin kann nicht abgefragt oder geändert werden, wenn max_replication_slots = 0"
+
+#: replication/logical/launcher.c:267
+#, c-format
+msgid "out of logical replication workers slots"
+msgstr ""
+
+#: replication/logical/launcher.c:268
+#, fuzzy, c-format
+#| msgid "You might need to increase max_locks_per_transaction."
+msgid "You might need to increase max_logical_replication_workers."
+msgstr "Sie müssen möglicherweise max_locks_per_transaction erhöhen."
+
+#: replication/logical/launcher.c:296
+#, fuzzy, c-format
+#| msgid "too many background workers"
+msgid "out of background workers slots"
+msgstr "zu viele Background-Worker"
+
+#: replication/logical/launcher.c:297
+#, fuzzy, c-format
+#| msgid "You might need to increase max_locks_per_transaction."
+msgid "You might need to increase max_worker_processes."
+msgstr "Sie müssen möglicherweise max_locks_per_transaction erhöhen."
+
+#: replication/logical/launcher.c:413
+#, c-format
+msgid "logical replication worker slot %d already used by another worker"
+msgstr ""
+
+#: replication/logical/launcher.c:556
+#, fuzzy, c-format
+#| msgid "autovacuum launcher started"
+msgid "logical replication launcher started"
+msgstr "Autovacuum-Launcher startet"
+
+#: replication/logical/launcher.c:656
+#, fuzzy, c-format
+#| msgid "autovacuum launcher shutting down"
+msgid "logical replication launcher shutting down"
+msgstr "Autovacuum-Launcher fährt herunter"
+
#: replication/logical/logical.c:83
#, c-format
msgid "logical decoding requires wal_level >= logical"
@@ -15299,844 +16461,1027 @@ msgstr "logische Dekodierung benötigt eine Datenbankverbindung"
msgid "logical decoding cannot be used while in recovery"
msgstr "logische Dekodierung kann nicht während der Wiederherstellung verwendet werden"
-#: replication/logical/logical.c:238 replication/logical/logical.c:350
+#: replication/logical/logical.c:236 replication/logical/logical.c:348
#, c-format
msgid "cannot use physical replication slot for logical decoding"
msgstr "physischer Replikations-Slot kann nicht für logisches Dekodieren verwendet werden"
-#: replication/logical/logical.c:243 replication/logical/logical.c:355
+#: replication/logical/logical.c:241 replication/logical/logical.c:353
#, c-format
msgid "replication slot \"%s\" was not created in this database"
msgstr "Replikations-Slot »%s« wurde nicht in dieser Datenbank erzeugt"
-#: replication/logical/logical.c:250
+#: replication/logical/logical.c:248
#, c-format
msgid "cannot create logical replication slot in transaction that has performed writes"
msgstr "logischer Replikations-Slot kann nicht in einer Transaktion erzeugt werden, die Schreibvorgänge ausgeführt hat"
-#: replication/logical/logical.c:392
+#: replication/logical/logical.c:390
#, c-format
msgid "starting logical decoding for slot \"%s\""
msgstr "starte logisches Dekodieren für Slot »%s«"
-#: replication/logical/logical.c:394
+#: replication/logical/logical.c:392
#, c-format
msgid "streaming transactions committing after %X/%X, reading WAL from %X/%X"
msgstr "Streaming beginnt bei Transaktionen, die nach %X/%X committen; lese WAL ab %X/%X"
-#: replication/logical/logical.c:529
+#: replication/logical/logical.c:527
#, c-format
msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X"
msgstr "Slot »%s«, Ausgabe-Plugin »%s«, im Callback %s, zugehörige LSN %X/%X"
-#: replication/logical/logical.c:536
+#: replication/logical/logical.c:534
#, c-format
msgid "slot \"%s\", output plugin \"%s\", in the %s callback"
msgstr "Slot »%s«, Ausgabe-Plugin »%s«, im Callback %s"
-#: replication/logical/logicalfuncs.c:113 replication/slotfuncs.c:32
+#: replication/logical/logicalfuncs.c:114 replication/slotfuncs.c:32
#, c-format
msgid "must be superuser or replication role to use replication slots"
msgstr "nur Superuser und Replikationsrollen können Replikations-Slots verwenden"
-#: replication/logical/logicalfuncs.c:152
+#: replication/logical/logicalfuncs.c:153
#, c-format
msgid "slot name must not be null"
msgstr "Slot-Name darf nicht NULL sein"
-#: replication/logical/logicalfuncs.c:168
+#: replication/logical/logicalfuncs.c:169
#, c-format
msgid "options array must not be null"
msgstr "Optionen-Array darf nicht NULL sein"
-#: replication/logical/logicalfuncs.c:199
+#: replication/logical/logicalfuncs.c:200
#, c-format
msgid "array must be one-dimensional"
msgstr "Array muss eindimensional sein"
-#: replication/logical/logicalfuncs.c:205
+#: replication/logical/logicalfuncs.c:206
#, c-format
msgid "array must not contain nulls"
msgstr "Array darf keine NULL-Werte enthalten"
-#: replication/logical/logicalfuncs.c:221 utils/adt/json.c:2277
-#: utils/adt/jsonb.c:1356
+#: replication/logical/logicalfuncs.c:222 utils/adt/json.c:2282
+#: utils/adt/jsonb.c:1357
#, c-format
msgid "array must have even number of elements"
msgstr "Array muss eine gerade Anzahl Elemente haben"
-#: replication/logical/logicalfuncs.c:264
+#: replication/logical/logicalfuncs.c:265
#, c-format
msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data"
msgstr "Ausgabe-Plugin »%s« erzeugt binäre Ausgabe, aber Funktion »%s« erwartet Textdaten"
-#: replication/logical/origin.c:181
+#: replication/logical/origin.c:180
#, c-format
msgid "only superusers can query or manipulate replication origins"
msgstr "nur Superuser können Replication-Origins abfragen oder ändern"
-#: replication/logical/origin.c:186
+#: replication/logical/origin.c:185
#, c-format
msgid "cannot query or manipulate replication origin when max_replication_slots = 0"
msgstr "Replication-Origin kann nicht abgefragt oder geändert werden, wenn max_replication_slots = 0"
-#: replication/logical/origin.c:191
+#: replication/logical/origin.c:190
#, c-format
msgid "cannot manipulate replication origins during recovery"
msgstr "Replication-Origins können nicht während der Wiederherstellung geändert werden"
-#: replication/logical/origin.c:316
+#: replication/logical/origin.c:314
#, c-format
msgid "could not find free replication origin OID"
msgstr "konnte keine freie Replication-Origin-OID finden"
-#: replication/logical/origin.c:353
+#: replication/logical/origin.c:351
#, c-format
msgid "could not drop replication origin with OID %d, in use by PID %d"
msgstr "konnte Replication-Origin mit OID %d nicht löschen, wird von PID %d verwendet"
-#: replication/logical/origin.c:671
+#: replication/logical/origin.c:664
#, c-format
msgid "replication checkpoint has wrong magic %u instead of %u"
msgstr "Replikations-Checkpoint hat falsche magische Zahl %u statt %u"
-#: replication/logical/origin.c:703
+#: replication/logical/origin.c:696
#, c-format
msgid "could not read file \"%s\": read %d of %zu"
msgstr "konnte Datei »%s« nicht lesen: %d von %zu gelesen"
-#: replication/logical/origin.c:712
+#: replication/logical/origin.c:705
#, c-format
msgid "could not find free replication state, increase max_replication_slots"
msgstr "konnte keinen freien Replication-State finden, erhöhen Sie max_replication_slots"
-#: replication/logical/origin.c:730
+#: replication/logical/origin.c:723
#, c-format
msgid "replication slot checkpoint has wrong checksum %u, expected %u"
msgstr "Replikations-Slot-Checkpoint hat falsche Prüfsumme %u, erwartet wurde %u"
-#: replication/logical/origin.c:854
+#: replication/logical/origin.c:847
#, c-format
msgid "replication origin with OID %d is already active for PID %d"
msgstr "Replication-Origin mit OID %d ist bereits aktiv für PID %d"
-#: replication/logical/origin.c:865 replication/logical/origin.c:1045
+#: replication/logical/origin.c:858 replication/logical/origin.c:1038
#, c-format
msgid "could not find free replication state slot for replication origin with OID %u"
msgstr "konnte keinen freien Replication-State-Slot für Replication-Origin mit OID %u finden"
-#: replication/logical/origin.c:867 replication/logical/origin.c:1047
-#: replication/slot.c:1289
+#: replication/logical/origin.c:860 replication/logical/origin.c:1040
+#: replication/slot.c:1336
#, c-format
msgid "Increase max_replication_slots and try again."
msgstr "Erhöhen Sie max_replication_slots und versuchen Sie es erneut."
-#: replication/logical/origin.c:1004
+#: replication/logical/origin.c:997
#, c-format
msgid "cannot setup replication origin when one is already setup"
msgstr "kann Replication-Origin nicht einrichten, wenn schon einer eingerichtet ist"
-#: replication/logical/origin.c:1033
+#: replication/logical/origin.c:1026
#, c-format
msgid "replication identifier %d is already active for PID %d"
msgstr "Replikationsidentifikator %d ist bereits aktiv für PID %d"
-#: replication/logical/origin.c:1079 replication/logical/origin.c:1274
-#: replication/logical/origin.c:1294
+#: replication/logical/origin.c:1072 replication/logical/origin.c:1267
+#: replication/logical/origin.c:1287
#, c-format
msgid "no replication origin is configured"
msgstr "kein Replication-Origin konfiguriert"
-#: replication/logical/reorderbuffer.c:2323
+#: replication/logical/relation.c:265
+#, fuzzy, c-format
+#| msgid "replication slot \"%s\" does not exist"
+msgid "logical replication target relation \"%s.%s\" does not exist"
+msgstr "Replikations-Slot »%s« existiert nicht"
+
+#: replication/logical/relation.c:276
+#, fuzzy, c-format
+#| msgid "referenced relation \"%s\" is not a table"
+msgid "logical replication target relation \"%s.%s\" is not a table"
+msgstr "Relation »%s«, auf die verwiesen wird, ist keine Tabelle"
+
+#: replication/logical/relation.c:303
+#, c-format
+msgid "logical replication target relation \"%s.%s\" is missing some replicated columns"
+msgstr ""
+
+#: replication/logical/relation.c:342
+#, c-format
+msgid "logical replication target relation \"%s.%s\" uses system columns in REPLICA IDENTITY index"
+msgstr ""
+
+#: replication/logical/relation.c:452
+#, fuzzy, c-format
+#| msgid "function \"%s\" not found\n"
+msgid "builtin type %u not found"
+msgstr "Funktion »%s« nicht gefunden\n"
+
+#: replication/logical/relation.c:453
+#, c-format
+msgid "This can be caused by having publisher with higher major version than subscriber"
+msgstr ""
+
+#: replication/logical/relation.c:485
+#, fuzzy, c-format
+#| msgid "database \"%s\" is used by a logical replication slot"
+msgid "data type \"%s.%s\" required for logical replication does not exist"
+msgstr "Datenbank »%s« wird von einem logischen Replikations-Slot verwendet"
+
+#: replication/logical/reorderbuffer.c:2286
#, c-format
msgid "could not write to data file for XID %u: %m"
msgstr "konnte nicht in Datendatei für XID %u schreiben: %m"
-#: replication/logical/reorderbuffer.c:2419
-#: replication/logical/reorderbuffer.c:2439
+#: replication/logical/reorderbuffer.c:2382
+#: replication/logical/reorderbuffer.c:2402
#, c-format
msgid "could not read from reorderbuffer spill file: %m"
msgstr "konnte nicht aus Reorder-Buffer-Spill-Datei lesen: %m"
-#: replication/logical/reorderbuffer.c:2423
-#: replication/logical/reorderbuffer.c:2443
+#: replication/logical/reorderbuffer.c:2386
+#: replication/logical/reorderbuffer.c:2406
#, c-format
msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes"
msgstr "konnte nicht aus Reorder-Buffer-Spill-Datei lesen: %d statt %u Bytes gelesen"
-#: replication/logical/reorderbuffer.c:3098
+#: replication/logical/reorderbuffer.c:3062
#, c-format
msgid "could not read from file \"%s\": read %d instead of %d bytes"
msgstr "konnte nicht aus Datei »%s« lesen: %d statt %d Bytes gelesen"
-#: replication/logical/snapbuild.c:600
+#: replication/logical/snapbuild.c:597
#, c-format
msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID"
msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs"
msgstr[0] "logischer Dekodierungs-Snapshot exportiert: »%s« mit %u Transaktions-ID"
msgstr[1] "logischer Dekodierungs-Snapshot exportiert: »%s« mit %u Transaktions-IDs"
-#: replication/logical/snapbuild.c:919 replication/logical/snapbuild.c:1284
-#: replication/logical/snapbuild.c:1815
+#: replication/logical/snapbuild.c:916 replication/logical/snapbuild.c:1281
+#: replication/logical/snapbuild.c:1812
#, c-format
msgid "logical decoding found consistent point at %X/%X"
msgstr "logisches Dekodieren fand konsistenten Punkt bei %X/%X"
-#: replication/logical/snapbuild.c:921
+#: replication/logical/snapbuild.c:918
#, c-format
msgid "Transaction ID %u finished; no more running transactions."
msgstr "Transaktions-ID %u beendet; keine laufenden Transaktionen mehr."
-#: replication/logical/snapbuild.c:1286
+#: replication/logical/snapbuild.c:1283
#, c-format
msgid "There are no running transactions."
msgstr "Keine laufenden Transaktionen."
-#: replication/logical/snapbuild.c:1348
+#: replication/logical/snapbuild.c:1345
#, c-format
msgid "logical decoding found initial starting point at %X/%X"
msgstr "logisches Dekodieren fand initialen Startpunkt bei %X/%X"
-#: replication/logical/snapbuild.c:1350
+#: replication/logical/snapbuild.c:1347
#, c-format
msgid "%u transaction needs to finish."
msgid_plural "%u transactions need to finish."
msgstr[0] "%u Transaktion muss noch abschließen."
msgstr[1] "%u Transaktionen müssen noch abschließen."
-#: replication/logical/snapbuild.c:1689 replication/logical/snapbuild.c:1715
-#: replication/logical/snapbuild.c:1729 replication/logical/snapbuild.c:1743
+#: replication/logical/snapbuild.c:1686 replication/logical/snapbuild.c:1712
+#: replication/logical/snapbuild.c:1726 replication/logical/snapbuild.c:1740
#, c-format
msgid "could not read file \"%s\", read %d of %d: %m"
msgstr "konnte Datei »%s« nicht lesen, %d von %d gelesen: %m"
-#: replication/logical/snapbuild.c:1695
+#: replication/logical/snapbuild.c:1692
#, c-format
msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u"
msgstr "Scanbuild-State-Datei »%s« hat falsche magische Zahl %u statt %u"
-#: replication/logical/snapbuild.c:1700
+#: replication/logical/snapbuild.c:1697
#, c-format
msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u"
msgstr "Snapbuild-State-Datei »%s« hat nicht unterstützte Version: %u statt %u"
-#: replication/logical/snapbuild.c:1756
+#: replication/logical/snapbuild.c:1753
#, c-format
msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u"
msgstr "Prüfsummenfehler bei Snapbuild-State-Datei »%s«: ist %u, sollte %u sein"
-#: replication/logical/snapbuild.c:1817
+#: replication/logical/snapbuild.c:1814
#, c-format
msgid "Logical decoding will begin using saved snapshot."
msgstr "Logische Dekodierung beginnt mit gespeichertem Snapshot."
-#: replication/logical/snapbuild.c:1890
+#: replication/logical/snapbuild.c:1887
#, c-format
msgid "could not parse file name \"%s\""
msgstr "konnte Dateinamen »%s« nicht parsen"
-#: replication/slot.c:183
+#: replication/logical/worker.c:256
+#, c-format
+msgid "processing remote data for replication target relation \"%s.%s\" column \"%s\", remote type %s, local type %s"
+msgstr ""
+
+#: replication/logical/worker.c:448
+#, c-format
+msgid "ORIGIN message sent out of order"
+msgstr ""
+
+#: replication/logical/worker.c:570
+#, c-format
+msgid "publisher does not send replica identity column expected by the logical replication target relation \"%s.%s\""
+msgstr ""
+
+#: replication/logical/worker.c:577
+#, c-format
+msgid "logical replication target relation \"%s.%s\" has neither REPLICA IDENTIY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL"
+msgstr ""
+
+#: replication/logical/worker.c:766
+#, fuzzy, c-format
+#| msgid "could not find free replication origin OID"
+msgid "logical replication could not find row for delete in replication target %s"
+msgstr "konnte keine freie Replication-Origin-OID finden"
+
+#: replication/logical/worker.c:833
+#, fuzzy, c-format
+#| msgid "invalid frontend message type %d"
+msgid "invalid logical replication message type %c"
+msgstr "ungültiger Frontend-Message-Typ %d"
+
+#: replication/logical/worker.c:972
+#, c-format
+msgid "data stream from publisher has ended"
+msgstr ""
+
+#: replication/logical/worker.c:1100
+#, fuzzy, c-format
+#| msgid "terminating walreceiver due to timeout"
+msgid "terminating logical replication worker due to timeout"
+msgstr "WAL-Receiver-Prozess wird abgebrochen wegen Zeitüberschreitung"
+
+#: replication/logical/worker.c:1239
+#, c-format
+msgid "logical replication worker for subscription \"%s\" will stop because the subscription was removed"
+msgstr ""
+
+#: replication/logical/worker.c:1254
+#, c-format
+msgid "logical replication worker for subscription \"%s\" will restart because the connection information was changed"
+msgstr ""
+
+#: replication/logical/worker.c:1269
+#, c-format
+msgid "logical replication worker for subscription \"%s\" will restart because subscription was renamed"
+msgstr ""
+
+#: replication/logical/worker.c:1284
+#, c-format
+msgid "logical replication worker for subscription \"%s\" will restart because subscription's publications were changed"
+msgstr ""
+
+#: replication/logical/worker.c:1300
+#, c-format
+msgid "logical replication worker for subscription \"%s\" will stop because the subscription was disabled"
+msgstr ""
+
+#: replication/logical/worker.c:1393
+#, c-format
+msgid "logical replication worker for subscription \"%s\" will not start because the subscription was disabled during startup"
+msgstr ""
+
+#: replication/logical/worker.c:1406
+#, fuzzy, c-format
+#| msgid "authentication failed for user \"%s\": host rejected"
+msgid "logical replication apply for subscription \"%s\" has started"
+msgstr "Authentifizierung für Benutzer »%s« fehlgeschlagen: Host abgelehnt"
+
+#: replication/pgoutput/pgoutput.c:113
+#, fuzzy, c-format
+#| msgid "invalid option \"%s\""
+msgid "invalid proto_version"
+msgstr "ungültige Option »%s«"
+
+#: replication/pgoutput/pgoutput.c:118
+#, fuzzy, c-format
+#| msgid "numeric time zone \"%s\" out of range"
+msgid "proto_verson \"%s\" out of range"
+msgstr "numerische Zeitzone »%s« ist außerhalb des gültigen Bereichs"
+
+#: replication/pgoutput/pgoutput.c:135
+#, fuzzy, c-format
+#| msgid "invalid name syntax"
+msgid "invalid publication_names syntax"
+msgstr "ungültige Namenssyntax"
+
+#: replication/pgoutput/pgoutput.c:179
+#, c-format
+msgid "client sent proto_version=%d but we only support protocol %d or lower"
+msgstr ""
+
+#: replication/pgoutput/pgoutput.c:185
+#, c-format
+msgid "client sent proto_version=%d but we only support protocol %d or higher"
+msgstr ""
+
+#: replication/pgoutput/pgoutput.c:191
+#, fuzzy, c-format
+#| msgid "multiple Dictionary parameters"
+msgid "publication_names parameter missing"
+msgstr "mehrere »Dictionary«-Parameter"
+
+#: replication/slot.c:180
#, c-format
msgid "replication slot name \"%s\" is too short"
msgstr "Replikations-Slot-Name »%s« ist zu kurz"
-#: replication/slot.c:192
+#: replication/slot.c:189
#, c-format
msgid "replication slot name \"%s\" is too long"
msgstr "Replikations-Slot-Name »%s« ist zu lang"
-#: replication/slot.c:205
+#: replication/slot.c:202
#, c-format
msgid "replication slot name \"%s\" contains invalid character"
msgstr "Replikations-Slot-Name »%s« enthält ungültiges Zeichen"
-#: replication/slot.c:207
+#: replication/slot.c:204
#, c-format
msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character."
msgstr "Replikations-Slot-Namen dürfen nur Kleinbuchstaben, Zahlen und Unterstriche enthalten."
-#: replication/slot.c:254
+#: replication/slot.c:251
#, c-format
msgid "replication slot \"%s\" already exists"
msgstr "Replikations-Slot »%s« existiert bereits"
-#: replication/slot.c:264
+#: replication/slot.c:261
#, c-format
msgid "all replication slots are in use"
msgstr "alle Replikations-Slots sind in Benutzung"
-#: replication/slot.c:265
+#: replication/slot.c:262
#, c-format
msgid "Free one or increase max_replication_slots."
msgstr "Geben Sie einen frei oder erhöhen Sie max_replication_slots."
-#: replication/slot.c:351
+#: replication/slot.c:358
#, c-format
msgid "replication slot \"%s\" does not exist"
msgstr "Replikations-Slot »%s« existiert nicht"
-#: replication/slot.c:355
+#: replication/slot.c:362
#, c-format
msgid "replication slot \"%s\" is active for PID %d"
msgstr "Replikations-Slot »%s« ist aktiv für PID %d"
-#: replication/slot.c:501 replication/slot.c:913 replication/slot.c:1250
+#: replication/slot.c:548 replication/slot.c:960 replication/slot.c:1297
#, c-format
msgid "could not remove directory \"%s\""
msgstr "konnte Verzeichnis »%s« nicht löschen"
-#: replication/slot.c:762
+#: replication/slot.c:809
#, c-format
msgid "replication slots can only be used if max_replication_slots > 0"
msgstr "Replikations-Slots können nur verwendet werden, wenn max_replication_slots > 0"
-#: replication/slot.c:767
+#: replication/slot.c:814
#, c-format
msgid "replication slots can only be used if wal_level >= replica"
msgstr "Replikations-Slots können nur verwendet werden, wenn wal_level >= replica"
-#: replication/slot.c:1182 replication/slot.c:1220
+#: replication/slot.c:1229 replication/slot.c:1267
#, c-format
msgid "could not read file \"%s\", read %d of %u: %m"
msgstr "konnte Datei »%s« nicht lesen, %d von %u gelesen: %m"
-#: replication/slot.c:1191
+#: replication/slot.c:1238
#, c-format
msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u"
msgstr "Replikations-Slot-Datei »%s« hat falsche magische Zahl: %u statt %u"
-#: replication/slot.c:1198
+#: replication/slot.c:1245
#, c-format
msgid "replication slot file \"%s\" has unsupported version %u"
msgstr "Replikations-Slot-Datei »%s« hat nicht unterstützte Version %u"
-#: replication/slot.c:1205
+#: replication/slot.c:1252
#, c-format
msgid "replication slot file \"%s\" has corrupted length %u"
msgstr "Replikations-Slot-Datei »%s« hat falsche Länge %u"
-#: replication/slot.c:1235
+#: replication/slot.c:1282
#, c-format
msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u"
msgstr "Prüfsummenfehler bei Replikations-Slot-Datei »%s«: ist %u, sollte %u sein"
-#: replication/slot.c:1288
+#: replication/slot.c:1335
#, c-format
msgid "too many replication slots active before shutdown"
msgstr "zu viele aktive Replikations-Slots vor dem Herunterfahren"
-#: replication/syncrep.c:228
+#: replication/syncrep.c:244
#, c-format
msgid "canceling the wait for synchronous replication and terminating connection due to administrator command"
msgstr "Warten auf synchrone Replikation wird storniert and Verbindung wird abgebrochen, aufgrund von Anweisung des Administrators"
-#: replication/syncrep.c:229 replication/syncrep.c:246
+#: replication/syncrep.c:245 replication/syncrep.c:262
#, c-format
msgid "The transaction has already committed locally, but might not have been replicated to the standby."
msgstr "Die Transaktion wurde lokal bereits committet, aber möglicherweise noch nicht zum Standby repliziert."
-#: replication/syncrep.c:245
+#: replication/syncrep.c:261
#, c-format
msgid "canceling wait for synchronous replication due to user request"
msgstr "storniere Warten auf synchrone Replikation wegen Benutzeraufforderung"
-#: replication/syncrep.c:375
+#: replication/syncrep.c:392
#, c-format
msgid "standby \"%s\" now has synchronous standby priority %u"
msgstr "Standby »%s« hat jetzt synchrone Standby-Priorität %u"
-#: replication/syncrep.c:435
+#: replication/syncrep.c:453
#, c-format
msgid "standby \"%s\" is now a synchronous standby with priority %u"
msgstr "Standby »%s« ist jetzt ein synchroner Standby mit Priorität %u"
-#: replication/syncrep.c:928
+#: replication/syncrep.c:457
+#, fuzzy, c-format
+#| msgid "standby \"%s\" is now a synchronous standby with priority %u"
+msgid "standby \"%s\" is now a candidate for quorum synchronous standby"
+msgstr "Standby »%s« ist jetzt ein synchroner Standby mit Priorität %u"
+
+#: replication/syncrep.c:1120
#, c-format
msgid "synchronous_standby_names parser failed"
msgstr "Parser für synchronous_standby_names fehlgeschlagen"
-#: replication/walreceiver.c:173
+#: replication/syncrep.c:1126
+#, c-format
+msgid "number of synchronous standbys (%d) must be greater than zero"
+msgstr "Anzahl synchroner Standbys (%d) muss größer als null sein"
+
+#: replication/walreceiver.c:167
#, c-format
msgid "terminating walreceiver process due to administrator command"
msgstr "WAL-Receiver-Prozess wird abgebrochen aufgrund von Anweisung des Administrators"
-#: replication/walreceiver.c:344
+#: replication/walreceiver.c:300
+#, c-format
+msgid "could not connect to the primary server: %s"
+msgstr "konnte nicht mit dem Primärserver verbinden: %s"
+
+#: replication/walreceiver.c:339
+#, c-format
+msgid "database system identifier differs between the primary and standby"
+msgstr "Datenbanksystemidentifikator unterscheidet sich zwischen Primär- und Standby-Server"
+
+#: replication/walreceiver.c:340
+#, c-format
+msgid "The primary's identifier is %s, the standby's identifier is %s."
+msgstr "Identifikator des Primärservers ist %s, Identifikator des Standby ist %s."
+
+#: replication/walreceiver.c:351
#, c-format
msgid "highest timeline %u of the primary is behind recovery timeline %u"
msgstr "höchste Zeitleiste %u des primären Servers liegt hinter Wiederherstellungszeitleiste %u zurück"
-#: replication/walreceiver.c:377
+#: replication/walreceiver.c:387
#, c-format
msgid "started streaming WAL from primary at %X/%X on timeline %u"
msgstr "WAL-Streaming vom Primärserver gestartet bei %X/%X auf Zeitleiste %u"
-#: replication/walreceiver.c:382
+#: replication/walreceiver.c:392
#, c-format
msgid "restarted WAL streaming at %X/%X on timeline %u"
msgstr "WAL-Streaming neu gestartet bei %X/%X auf Zeitleiste %u"
-#: replication/walreceiver.c:411
+#: replication/walreceiver.c:421
#, c-format
msgid "cannot continue WAL streaming, recovery has already ended"
msgstr "kann WAL-Streaming nicht fortsetzen, Wiederherstellung ist bereits beendet"
-#: replication/walreceiver.c:448
+#: replication/walreceiver.c:458
#, c-format
msgid "replication terminated by primary server"
msgstr "Replikation wurde durch Primärserver beendet"
-#: replication/walreceiver.c:449
+#: replication/walreceiver.c:459
#, c-format
msgid "End of WAL reached on timeline %u at %X/%X."
msgstr "WAL-Ende erreicht auf Zeitleiste %u bei %X/%X."
-#: replication/walreceiver.c:543
+#: replication/walreceiver.c:554
#, c-format
msgid "terminating walreceiver due to timeout"
msgstr "WAL-Receiver-Prozess wird abgebrochen wegen Zeitüberschreitung"
-#: replication/walreceiver.c:583
+#: replication/walreceiver.c:594
#, c-format
msgid "primary server contains no more WAL on requested timeline %u"
msgstr "Primärserver enthält kein WAL mehr auf angeforderter Zeitleiste %u"
-#: replication/walreceiver.c:598 replication/walreceiver.c:957
+#: replication/walreceiver.c:609 replication/walreceiver.c:968
#, c-format
msgid "could not close log segment %s: %m"
msgstr "konnte Logsegment %s nicht schließen: %m"
-#: replication/walreceiver.c:722
+#: replication/walreceiver.c:734
#, c-format
msgid "fetching timeline history file for timeline %u from primary server"
msgstr "hole Zeitleisten-History-Datei für Zeitleiste %u vom Primärserver"
-#: replication/walreceiver.c:1011
+#: replication/walreceiver.c:1022
#, c-format
msgid "could not write to log segment %s at offset %u, length %lu: %m"
msgstr "konnte nicht in Logsegment %s bei Position %u, Länge %lu schreiben: %m"
-#: replication/walsender.c:485
+#: replication/walsender.c:455
#, c-format
msgid "could not seek to beginning of file \"%s\": %m"
msgstr "konnte Positionszeiger nicht den Anfang der Datei »%s« setzen: %m"
-#: replication/walsender.c:536
+#: replication/walsender.c:494
+#, c-format
+msgid "IDENTIFY_SYSTEM has not been run before START_REPLICATION"
+msgstr ""
+
+#: replication/walsender.c:511
#, c-format
msgid "cannot use a logical replication slot for physical replication"
msgstr "logischer Replikations-Slot kann nicht für physische Replikation verwendet werden"
-#: replication/walsender.c:599
+#: replication/walsender.c:574
#, c-format
msgid "requested starting point %X/%X on timeline %u is not in this server's history"
msgstr "angeforderter Startpunkt %X/%X auf Zeitleiste %u ist nicht in der History dieses Servers"
-#: replication/walsender.c:603
+#: replication/walsender.c:578
#, c-format
msgid "This server's history forked from timeline %u at %X/%X."
msgstr "Die History dieses Servers zweigte von Zeitleiste %u bei %X/%X ab."
-#: replication/walsender.c:648
+#: replication/walsender.c:623
#, c-format
msgid "requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X"
msgstr "angeforderter Startpunkt %X/%X ist vor der WAL-Flush-Position dieses Servers %X/%X"
-#: replication/walsender.c:974
+#: replication/walsender.c:912
#, c-format
msgid "terminating walsender process after promotion"
msgstr "WAL-Sender-Prozess wird nach Beförderung abgebrochen"
-#: replication/walsender.c:1300
+#: replication/walsender.c:1240
#, c-format
msgid "received replication command: %s"
msgstr "Replikationsbefehl empfangen: %s"
-#: replication/walsender.c:1393 replication/walsender.c:1409
+#: replication/walsender.c:1348 replication/walsender.c:1364
#, c-format
msgid "unexpected EOF on standby connection"
msgstr "unerwartetes EOF auf Standby-Verbindung"
-#: replication/walsender.c:1423
+#: replication/walsender.c:1378
#, c-format
msgid "unexpected standby message type \"%c\", after receiving CopyDone"
msgstr "unerwarteter Standby-Message-Typ »%c«, nach Empfang von CopyDone"
-#: replication/walsender.c:1461
+#: replication/walsender.c:1416
#, c-format
msgid "invalid standby message type \"%c\""
msgstr "ungültiger Standby-Message-Typ »%c«"
-#: replication/walsender.c:1502
+#: replication/walsender.c:1457
#, c-format
msgid "unexpected message type \"%c\""
msgstr "unerwarteter Message-Typ »%c«"
-#: replication/walsender.c:1786
+#: replication/walsender.c:1741
#, c-format
msgid "terminating walsender process due to replication timeout"
msgstr "WAL-Sender-Prozess wird abgebrochen wegen Zeitüberschreitung bei der Replikation"
-#: replication/walsender.c:1879
+#: replication/walsender.c:1829
#, c-format
msgid "standby \"%s\" has now caught up with primary"
msgstr "Standby-Server »%s« hat jetzt den Primärserver eingeholt"
-#: replication/walsender.c:1982
+#: replication/walsender.c:1933
#, c-format
msgid "number of requested standby connections exceeds max_wal_senders (currently %d)"
msgstr "Anzahl angeforderter Standby-Verbindungen überschreitet max_wal_senders (aktuell %d)"
-#: rewrite/rewriteDefine.c:112 rewrite/rewriteDefine.c:973
+#: rewrite/rewriteDefine.c:112 rewrite/rewriteDefine.c:967
#, c-format
msgid "rule \"%s\" for relation \"%s\" already exists"
msgstr "Regel »%s« für Relation »%s« existiert bereits"
-#: rewrite/rewriteDefine.c:297
+#: rewrite/rewriteDefine.c:296
#, c-format
msgid "rule actions on OLD are not implemented"
msgstr "Regelaktionen für OLD sind nicht implementiert"
-#: rewrite/rewriteDefine.c:298
+#: rewrite/rewriteDefine.c:297
#, c-format
msgid "Use views or triggers instead."
msgstr "Verwenden Sie stattdessen Sichten oder Trigger."
-#: rewrite/rewriteDefine.c:302
+#: rewrite/rewriteDefine.c:301
#, c-format
msgid "rule actions on NEW are not implemented"
msgstr "Regelaktionen für NEW sind nicht implementiert"
-#: rewrite/rewriteDefine.c:303
+#: rewrite/rewriteDefine.c:302
#, c-format
msgid "Use triggers instead."
msgstr "Verwenden Sie stattdessen Trigger."
-#: rewrite/rewriteDefine.c:316
+#: rewrite/rewriteDefine.c:315
#, c-format
msgid "INSTEAD NOTHING rules on SELECT are not implemented"
msgstr "INSTEAD-NOTHING-Regeln für SELECT sind nicht implementiert"
-#: rewrite/rewriteDefine.c:317
+#: rewrite/rewriteDefine.c:316
#, c-format
msgid "Use views instead."
msgstr "Verwenden Sie stattdessen Sichten."
-#: rewrite/rewriteDefine.c:325
+#: rewrite/rewriteDefine.c:324
#, c-format
msgid "multiple actions for rules on SELECT are not implemented"
msgstr "mehrere Regelaktionen für SELECT-Regeln sind nicht implementiert"
-#: rewrite/rewriteDefine.c:336
+#: rewrite/rewriteDefine.c:334
#, c-format
msgid "rules on SELECT must have action INSTEAD SELECT"
msgstr "Regeln für SELECT müssen als Aktion INSTEAD SELECT haben"
-#: rewrite/rewriteDefine.c:344
+#: rewrite/rewriteDefine.c:342
#, c-format
msgid "rules on SELECT must not contain data-modifying statements in WITH"
msgstr "Regeln für SELECT dürfen keine datenmodifizierenden Anweisungen in WITH enthalten"
-#: rewrite/rewriteDefine.c:352
+#: rewrite/rewriteDefine.c:350
#, c-format
msgid "event qualifications are not implemented for rules on SELECT"
msgstr "Ereignisqualifikationen sind nicht implementiert für SELECT-Regeln"
-#: rewrite/rewriteDefine.c:379
+#: rewrite/rewriteDefine.c:377
#, c-format
msgid "\"%s\" is already a view"
msgstr "»%s« ist bereits eine Sicht"
-#: rewrite/rewriteDefine.c:403
+#: rewrite/rewriteDefine.c:401
#, c-format
msgid "view rule for \"%s\" must be named \"%s\""
msgstr "Sicht-Regel für »%s« muss »%s« heißen"
-#: rewrite/rewriteDefine.c:432
+#: rewrite/rewriteDefine.c:430
#, c-format
msgid "could not convert table \"%s\" to a view because it is not empty"
msgstr "konnte Tabelle »%s« nicht in Sicht umwandeln, weil sie nicht leer ist"
-#: rewrite/rewriteDefine.c:440
+#: rewrite/rewriteDefine.c:438
#, c-format
msgid "could not convert table \"%s\" to a view because it has triggers"
msgstr "konnte Tabelle »%s« nicht in Sicht umwandeln, weil sie Trigger hat"
-#: rewrite/rewriteDefine.c:442
+#: rewrite/rewriteDefine.c:440
#, c-format
msgid "In particular, the table cannot be involved in any foreign key relationships."
msgstr "Insbesondere darf die Tabelle nicht in Fremschlüsselverhältnisse eingebunden sein."
-#: rewrite/rewriteDefine.c:447
+#: rewrite/rewriteDefine.c:445
#, c-format
msgid "could not convert table \"%s\" to a view because it has indexes"
msgstr "konnte Tabelle »%s« nicht in Sicht umwandeln, weil sie Indexe hat"
-#: rewrite/rewriteDefine.c:453
+#: rewrite/rewriteDefine.c:451
#, c-format
msgid "could not convert table \"%s\" to a view because it has child tables"
msgstr "konnte Tabelle »%s« nicht in Sicht umwandeln, weil sie abgeleitete Tabellen hat"
-#: rewrite/rewriteDefine.c:459
+#: rewrite/rewriteDefine.c:457
#, c-format
msgid "could not convert table \"%s\" to a view because it has row security enabled"
msgstr "konnte Tabelle »%s« nicht in Sicht umwandeln, weil sie Sicherheit auf Zeilenebene eingeschaltet hat"
-#: rewrite/rewriteDefine.c:465
+#: rewrite/rewriteDefine.c:463
#, c-format
msgid "could not convert table \"%s\" to a view because it has row security policies"
msgstr "konnte Tabelle »%s« nicht in Sicht umwandeln, weil sie Policys für Sicherheit auf Zeilenebene hat"
-#: rewrite/rewriteDefine.c:492
+#: rewrite/rewriteDefine.c:490
#, c-format
msgid "cannot have multiple RETURNING lists in a rule"
msgstr "Regel kann nicht mehrere RETURNING-Listen enthalten"
-#: rewrite/rewriteDefine.c:497
+#: rewrite/rewriteDefine.c:495
#, c-format
msgid "RETURNING lists are not supported in conditional rules"
msgstr "RETURNING-Listen werden in Regeln mit Bedingung nicht unterstützt"
-#: rewrite/rewriteDefine.c:501
+#: rewrite/rewriteDefine.c:499
#, c-format
msgid "RETURNING lists are not supported in non-INSTEAD rules"
msgstr "RETURNING-Listen werden nur in INSTEAD-Regeln unterstützt"
-#: rewrite/rewriteDefine.c:667
+#: rewrite/rewriteDefine.c:664
#, c-format
msgid "SELECT rule's target list has too many entries"
msgstr "Targetliste von SELECT-Regel hat zu viele Einträge"
-#: rewrite/rewriteDefine.c:668
+#: rewrite/rewriteDefine.c:665
#, c-format
msgid "RETURNING list has too many entries"
msgstr "RETURNING-Liste hat zu viele Einträge"
-#: rewrite/rewriteDefine.c:695
+#: rewrite/rewriteDefine.c:692
#, c-format
msgid "cannot convert relation containing dropped columns to view"
msgstr "kann Relation mit gelöschten Spalten nicht in Sicht umwandeln"
-#: rewrite/rewriteDefine.c:696
+#: rewrite/rewriteDefine.c:693
#, c-format
msgid "cannot create a RETURNING list for a relation containing dropped columns"
msgstr "für eine Relation mit gelöschten Spalten kann keine RETURNING-Liste erzeugt werden"
-#: rewrite/rewriteDefine.c:702
+#: rewrite/rewriteDefine.c:699
#, c-format
msgid "SELECT rule's target entry %d has different column name from column \"%s\""
msgstr "Spaltenname in Targeteintrag %d von SELECT-Regel unterscheidet sich von Spalte »%s«"
-#: rewrite/rewriteDefine.c:704
+#: rewrite/rewriteDefine.c:701
#, c-format
msgid "SELECT target entry is named \"%s\"."
msgstr "SELECT-Targeteintrag heißt »%s«."
-#: rewrite/rewriteDefine.c:713
+#: rewrite/rewriteDefine.c:710
#, c-format
msgid "SELECT rule's target entry %d has different type from column \"%s\""
msgstr "Typ von Targeteintrag %d von SELECT-Regel unterscheidet sich von Spalte »%s«"
-#: rewrite/rewriteDefine.c:715
+#: rewrite/rewriteDefine.c:712
#, c-format
msgid "RETURNING list's entry %d has different type from column \"%s\""
msgstr "Eintrag %d in RETURNING-Liste hat anderen Typ als Spalte »%s«"
-#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:742
+#: rewrite/rewriteDefine.c:715 rewrite/rewriteDefine.c:739
#, c-format
msgid "SELECT target entry has type %s, but column has type %s."
msgstr "SELECT-Targeteintrag hat Typ %s, aber Spalte hat Typ %s."
-#: rewrite/rewriteDefine.c:721 rewrite/rewriteDefine.c:746
+#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:743
#, c-format
msgid "RETURNING list entry has type %s, but column has type %s."
msgstr "Eintrag in RETURNING-Liste hat Typ %s, aber Spalte hat Typ %s."
-#: rewrite/rewriteDefine.c:737
+#: rewrite/rewriteDefine.c:734
#, c-format
msgid "SELECT rule's target entry %d has different size from column \"%s\""
msgstr "Größe von Targeteintrag %d von SELECT-Regel unterscheidet sich von Spalte »%s«"
-#: rewrite/rewriteDefine.c:739
+#: rewrite/rewriteDefine.c:736
#, c-format
msgid "RETURNING list's entry %d has different size from column \"%s\""
msgstr "Eintrag %d in RETURNING-Liste hat andere Größe als Spalte »%s«"
-#: rewrite/rewriteDefine.c:756
+#: rewrite/rewriteDefine.c:753
#, c-format
msgid "SELECT rule's target list has too few entries"
msgstr "Targetliste von SELECT-Regeln hat zu wenige Einträge"
-#: rewrite/rewriteDefine.c:757
+#: rewrite/rewriteDefine.c:754
#, c-format
msgid "RETURNING list has too few entries"
msgstr "RETURNING-Liste hat zu wenige Einträge"
-#: rewrite/rewriteDefine.c:849 rewrite/rewriteDefine.c:964
-#: rewrite/rewriteSupport.c:112
+#: rewrite/rewriteDefine.c:846 rewrite/rewriteDefine.c:958
+#: rewrite/rewriteSupport.c:109
#, c-format
msgid "rule \"%s\" for relation \"%s\" does not exist"
msgstr "Regel »%s« für Relation »%s« existiert nicht"
-#: rewrite/rewriteDefine.c:983
+#: rewrite/rewriteDefine.c:977
#, c-format
msgid "renaming an ON SELECT rule is not allowed"
msgstr "Umbenennen einer ON-SELECT-Regel ist nicht erlaubt"
-#: rewrite/rewriteHandler.c:528
+#: rewrite/rewriteHandler.c:541
#, c-format
msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten"
msgstr "WITH-Anfragename »%s« erscheint sowohl in der Regelaktion als auch in der umzuschreibenden Anfrage"
-#: rewrite/rewriteHandler.c:588
+#: rewrite/rewriteHandler.c:601
#, c-format
msgid "cannot have RETURNING lists in multiple rules"
msgstr "RETURNING-Listen können nicht in mehreren Regeln auftreten"
-#: rewrite/rewriteHandler.c:928 rewrite/rewriteHandler.c:946
+#: rewrite/rewriteHandler.c:941 rewrite/rewriteHandler.c:959
#, c-format
msgid "multiple assignments to same column \"%s\""
msgstr "mehrere Zuweisungen zur selben Spalte »%s«"
-#: rewrite/rewriteHandler.c:1721 rewrite/rewriteHandler.c:3331
+#: rewrite/rewriteHandler.c:1735 rewrite/rewriteHandler.c:3349
#, c-format
msgid "infinite recursion detected in rules for relation \"%s\""
msgstr "unendliche Rekursion entdeckt in Regeln für Relation »%s«"
-#: rewrite/rewriteHandler.c:1806
+#: rewrite/rewriteHandler.c:1820
#, c-format
msgid "infinite recursion detected in policy for relation \"%s\""
msgstr "unendliche Rekursion entdeckt in Policys für Relation »%s«"
-#: rewrite/rewriteHandler.c:2123
+#: rewrite/rewriteHandler.c:2137
msgid "Junk view columns are not updatable."
msgstr "Junk-Sichtspalten sind nicht aktualisierbar."
-#: rewrite/rewriteHandler.c:2128
+#: rewrite/rewriteHandler.c:2142
msgid "View columns that are not columns of their base relation are not updatable."
msgstr "Sichtspalten, die nicht Spalten ihrer Basisrelation sind, sind nicht aktualisierbar."
-#: rewrite/rewriteHandler.c:2131
+#: rewrite/rewriteHandler.c:2145
msgid "View columns that refer to system columns are not updatable."
msgstr "Sichtspalten, die auf Systemspalten verweisen, sind nicht aktualisierbar."
-#: rewrite/rewriteHandler.c:2134
+#: rewrite/rewriteHandler.c:2148
msgid "View columns that return whole-row references are not updatable."
msgstr "Sichtspalten, die Verweise auf ganze Zeilen zurückgeben, sind nicht aktualisierbar."
-#: rewrite/rewriteHandler.c:2192
+#: rewrite/rewriteHandler.c:2206
msgid "Views containing DISTINCT are not automatically updatable."
msgstr "Sichten, die DISTINCT enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2195
+#: rewrite/rewriteHandler.c:2209
msgid "Views containing GROUP BY are not automatically updatable."
msgstr "Sichten, die GROUP BY enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2198
+#: rewrite/rewriteHandler.c:2212
msgid "Views containing HAVING are not automatically updatable."
msgstr "Sichten, die HAVING enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2201
+#: rewrite/rewriteHandler.c:2215
msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable."
msgstr "Sichten, die UNION, INTERSECT oder EXCEPT enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2204
+#: rewrite/rewriteHandler.c:2218
msgid "Views containing WITH are not automatically updatable."
msgstr "Sichten, die WITH enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2207
+#: rewrite/rewriteHandler.c:2221
msgid "Views containing LIMIT or OFFSET are not automatically updatable."
msgstr "Sichten, die LIMIT oder OFFSET enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2219
+#: rewrite/rewriteHandler.c:2233
msgid "Views that return aggregate functions are not automatically updatable."
msgstr "Sichten, die Aggregatfunktionen zurückgeben, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2222
+#: rewrite/rewriteHandler.c:2236
msgid "Views that return window functions are not automatically updatable."
msgstr "Sichten, die Fensterfunktionen zurückgeben, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2225
+#: rewrite/rewriteHandler.c:2239
msgid "Views that return set-returning functions are not automatically updatable."
msgstr "Sichten, die Funktionen mit Ergebnismenge zurückgeben, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2232 rewrite/rewriteHandler.c:2236
-#: rewrite/rewriteHandler.c:2243
+#: rewrite/rewriteHandler.c:2246 rewrite/rewriteHandler.c:2250
+#: rewrite/rewriteHandler.c:2258
msgid "Views that do not select from a single table or view are not automatically updatable."
msgstr "Sichten, die nicht aus einer einzigen Tabelle oder Sicht lesen, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2246
+#: rewrite/rewriteHandler.c:2261
msgid "Views containing TABLESAMPLE are not automatically updatable."
msgstr "Sichten, die TABLESAMPLE enthalten, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2270
+#: rewrite/rewriteHandler.c:2285
msgid "Views that have no updatable columns are not automatically updatable."
msgstr "Sichten, die keine aktualisierbaren Spalten haben, sind nicht automatisch aktualisierbar."
-#: rewrite/rewriteHandler.c:2724
+#: rewrite/rewriteHandler.c:2737
#, c-format
msgid "cannot insert into column \"%s\" of view \"%s\""
msgstr "kann nicht in Spalte »%s« von Sicht »%s« einfügen"
-#: rewrite/rewriteHandler.c:2732
+#: rewrite/rewriteHandler.c:2745
#, c-format
msgid "cannot update column \"%s\" of view \"%s\""
msgstr "kann Spalte »%s« von Sicht »%s« nicht aktualisieren"
-#: rewrite/rewriteHandler.c:3130
+#: rewrite/rewriteHandler.c:3148
#, c-format
msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH"
msgstr "DO INSTEAD NOTHING-Regeln werden für datenmodifizierende Anweisungen in WITH nicht unterstützt"
-#: rewrite/rewriteHandler.c:3144
+#: rewrite/rewriteHandler.c:3162
#, c-format
msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH"
msgstr "Do INSTEAD-Regeln mit Bedingung werden für datenmodifizierende Anweisungen in WITH nicht unterstützt"
-#: rewrite/rewriteHandler.c:3148
+#: rewrite/rewriteHandler.c:3166
#, c-format
msgid "DO ALSO rules are not supported for data-modifying statements in WITH"
msgstr "DO ALSO-Regeln werden für datenmodifizierende Anweisungen in WITH nicht unterstützt"
-#: rewrite/rewriteHandler.c:3153
+#: rewrite/rewriteHandler.c:3171
#, c-format
msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH"
msgstr "DO INSTEAD-Regeln mit mehreren Anweisungen werden für datenmodifizierende Anweisungen in WITH nicht unterstützt"
-#: rewrite/rewriteHandler.c:3368
+#: rewrite/rewriteHandler.c:3386
#, c-format
msgid "cannot perform INSERT RETURNING on relation \"%s\""
msgstr "INSERT RETURNING kann in Relation »%s« nicht ausgeführt werden"
-#: rewrite/rewriteHandler.c:3370
+#: rewrite/rewriteHandler.c:3388
#, c-format
msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause."
msgstr "Sie benötigen eine ON INSERT DO INSTEAD Regel ohne Bedingung, mit RETURNING-Klausel."
-#: rewrite/rewriteHandler.c:3375
+#: rewrite/rewriteHandler.c:3393
#, c-format
msgid "cannot perform UPDATE RETURNING on relation \"%s\""
msgstr "UPDATE RETURNING kann in Relation »%s« nicht ausgeführt werden"
-#: rewrite/rewriteHandler.c:3377
+#: rewrite/rewriteHandler.c:3395
#, c-format
msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause."
msgstr "Sie benötigen eine ON UPDATE DO INSTEAD Regel ohne Bedingung, mit RETURNING-Klausel."
-#: rewrite/rewriteHandler.c:3382
+#: rewrite/rewriteHandler.c:3400
#, c-format
msgid "cannot perform DELETE RETURNING on relation \"%s\""
msgstr "DELETE RETURNING kann in Relation »%s« nicht ausgeführt werden"
-#: rewrite/rewriteHandler.c:3384
+#: rewrite/rewriteHandler.c:3402
#, c-format
msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause."
msgstr "Sie benötigen eine ON DELETE DO INSTEAD Regel ohne Bedingung, mit RETURNING-Klausel."
-#: rewrite/rewriteHandler.c:3402
+#: rewrite/rewriteHandler.c:3420
#, c-format
msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules"
msgstr "INSERT mit ON-CONFLICT-Klausel kann nicht mit Tabelle verwendet werden, die INSERT- oder UPDATE-Regeln hat"
-#: rewrite/rewriteHandler.c:3459
+#: rewrite/rewriteHandler.c:3477
#, c-format
msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries"
msgstr "WITH kann nicht in einer Anfrage verwendet werden, die durch Regeln in mehrere Anfragen umgeschrieben wird"
@@ -16156,21 +17501,6 @@ msgstr "WHERE CURRENT OF mit einer Sicht ist nicht implementiert"
msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command"
msgstr "NEW-Variablen in ON UPDATE-Regeln können nicht auf Spalten verweisen, die Teil einer Mehrfachzuweisung in dem UPDATE-Befehl sind"
-#: rewrite/rewriteSupport.c:154
-#, c-format
-msgid "rule \"%s\" does not exist"
-msgstr "Regel »%s« existiert nicht"
-
-#: rewrite/rewriteSupport.c:167
-#, c-format
-msgid "there are multiple rules named \"%s\""
-msgstr "es gibt mehrere Regeln namens »%s«"
-
-#: rewrite/rewriteSupport.c:168
-#, c-format
-msgid "Specify a relation name as well as a rule name."
-msgstr "Geben Sie einen Relationsnamen und einen Regelnamen an."
-
#: scan.l:432
msgid "unterminated /* comment"
msgstr "/*-Kommentar nicht abgeschlossen"
@@ -16198,7 +17528,7 @@ msgid "invalid Unicode escape character"
msgstr "ungültiges Unicode-Escape-Zeichen"
#: scan.l:605 scan.l:613 scan.l:621 scan.l:622 scan.l:623 scan.l:1337
-#: scan.l:1364 scan.l:1368 scan.l:1406 scan.l:1410 scan.l:1432
+#: scan.l:1364 scan.l:1368 scan.l:1406 scan.l:1410 scan.l:1432 scan.l:1442
msgid "invalid Unicode surrogate pair"
msgstr "ungültiges Unicode-Surrogatpaar"
@@ -16230,7 +17560,7 @@ msgstr "Dollar-Quotes nicht abgeschlossen"
msgid "zero-length delimited identifier"
msgstr "Bezeichner in Anführungszeichen hat Länge null"
-#: scan.l:793 syncrep_scanner.l:84
+#: scan.l:793 syncrep_scanner.l:87
msgid "unterminated quoted identifier"
msgstr "Bezeichner in Anführungszeichen nicht abgeschlossen"
@@ -16258,32 +17588,32 @@ msgstr "Unicode-Escape-Werte können nicht für Code-Punkt-Werte über 007F verw
msgid "invalid Unicode escape value"
msgstr "ungültiger Unicode-Escape-Wert"
-#: scan.l:1481
+#: scan.l:1488
#, c-format
msgid "nonstandard use of \\' in a string literal"
msgstr "nicht standardkonforme Verwendung von \\' in Zeichenkettenkonstante"
-#: scan.l:1482
+#: scan.l:1489
#, c-format
msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')."
msgstr "Verwenden Sie '', um Quotes in Zeichenketten zu schreiben, oder verwenden Sie die Syntax für Escape-Zeichenketten (E'...')."
-#: scan.l:1491
+#: scan.l:1498
#, c-format
msgid "nonstandard use of \\\\ in a string literal"
msgstr "nicht standardkonforme Verwendung von \\\\ in Zeichenkettenkonstante"
-#: scan.l:1492
+#: scan.l:1499
#, c-format
msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'."
msgstr "Verwenden Sie die Syntax für Escape-Zeichenketten für Backslashes, z.B. E'\\\\'."
-#: scan.l:1506
+#: scan.l:1513
#, c-format
msgid "nonstandard use of escape in a string literal"
msgstr "nicht standardkonforme Verwendung von Escape in Zeichenkettenkonstante"
-#: scan.l:1507
+#: scan.l:1514
#, c-format
msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'."
msgstr "Verwenden Sie die Syntax für Escape-Zeichenketten, z.B. E'\\r\\n'."
@@ -16293,8 +17623,8 @@ msgstr "Verwenden Sie die Syntax für Escape-Zeichenketten, z.B. E'\\r\\n'."
msgid "no Snowball stemmer available for language \"%s\" and encoding \"%s\""
msgstr "kein Snowball-Stemmer für Sprache »%s« und Kodierung »%s« verfügbar"
-#: snowball/dict_snowball.c:200 tsearch/dict_ispell.c:73
-#: tsearch/dict_simple.c:48
+#: snowball/dict_snowball.c:200 tsearch/dict_ispell.c:74
+#: tsearch/dict_simple.c:49
#, c-format
msgid "multiple StopWords parameters"
msgstr "mehrere »StopWords«-Parameter"
@@ -16334,22 +17664,22 @@ msgstr "Das scheint mit fehlerhaften Kernels vorzukommen; Sie sollten eine Syste
msgid "invalid page in block %u of relation %s; zeroing out page"
msgstr "ungültige Seite in Block %u von Relation %s; fülle Seite mit Nullen"
-#: storage/buffer/bufmgr.c:3952
+#: storage/buffer/bufmgr.c:3996
#, c-format
msgid "could not write block %u of %s"
msgstr "konnte Block %u von %s nicht schreiben"
-#: storage/buffer/bufmgr.c:3954
+#: storage/buffer/bufmgr.c:3998
#, c-format
msgid "Multiple failures --- write error might be permanent."
msgstr "Mehrere Fehlschläge --- Schreibfehler ist möglicherweise dauerhaft."
-#: storage/buffer/bufmgr.c:3975 storage/buffer/bufmgr.c:3994
+#: storage/buffer/bufmgr.c:4019 storage/buffer/bufmgr.c:4038
#, c-format
msgid "writing block %u of relation %s"
msgstr "schreibe Block %u von Relation %s"
-#: storage/buffer/bufmgr.c:4295
+#: storage/buffer/bufmgr.c:4339
#, c-format
msgid "snapshot too old"
msgstr "Snapshot zu alt"
@@ -16364,205 +17694,216 @@ msgstr "kein leerer lokaler Puffer verfügbar"
msgid "cannot access temporary tables during a parallel operation"
msgstr "während einer parallelen Operation kann nicht auf temporäre Tabellen zugegriffen werden"
-#: storage/file/fd.c:436 storage/file/fd.c:508 storage/file/fd.c:544
+#: storage/file/fd.c:443 storage/file/fd.c:515 storage/file/fd.c:551
#, c-format
msgid "could not flush dirty data: %m"
msgstr "konnte schmutzige Daten nicht flushen: %m"
-#: storage/file/fd.c:466
+#: storage/file/fd.c:473
#, c-format
msgid "could not determine dirty data size: %m"
msgstr "konnte Größe der schmutzigen Daten nicht bestimmen: %m"
-#: storage/file/fd.c:518
+#: storage/file/fd.c:525
#, c-format
msgid "could not munmap() while flushing data: %m"
msgstr "munmap() fehlgeschlagen beim Flushen von Daten: %m"
-#: storage/file/fd.c:682
+#: storage/file/fd.c:689
#, c-format
msgid "could not link file \"%s\" to \"%s\": %m"
msgstr "konnte Datei »%s« nicht nach »%s« linken: %m"
-#: storage/file/fd.c:776
+#: storage/file/fd.c:783
#, c-format
msgid "getrlimit failed: %m"
msgstr "getrlimit fehlgeschlagen: %m"
-#: storage/file/fd.c:866
+#: storage/file/fd.c:873
#, c-format
msgid "insufficient file descriptors available to start server process"
msgstr "nicht genug Dateideskriptoren verfügbar, um Serverprozess zu starten"
-#: storage/file/fd.c:867
+#: storage/file/fd.c:874
#, c-format
msgid "System allows %d, we need at least %d."
msgstr "System erlaubt %d, wir benötigen mindestens %d."
-#: storage/file/fd.c:908 storage/file/fd.c:2001 storage/file/fd.c:2094
-#: storage/file/fd.c:2242
+#: storage/file/fd.c:915 storage/file/fd.c:2078 storage/file/fd.c:2171
+#: storage/file/fd.c:2319
#, c-format
msgid "out of file descriptors: %m; release and retry"
msgstr "keine Dateideskriptoren mehr: %m; freigeben und nochmal versuchen"
-#: storage/file/fd.c:1482
+#: storage/file/fd.c:1520
#, c-format
msgid "temporary file: path \"%s\", size %lu"
msgstr "temporäre Datei: Pfad »%s«, Größe %lu"
-#: storage/file/fd.c:1656
+#: storage/file/fd.c:1717
#, c-format
msgid "temporary file size exceeds temp_file_limit (%dkB)"
msgstr "Größe der temporären Datei überschreitet temp_file_limit (%dkB)"
-#: storage/file/fd.c:1977 storage/file/fd.c:2027
+#: storage/file/fd.c:2054 storage/file/fd.c:2104
#, c-format
msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\""
msgstr "maxAllocatedDescs (%d) überschritten beim Versuch, die Datei »%s« zu öffnen"
-#: storage/file/fd.c:2067
+#: storage/file/fd.c:2144
#, c-format
msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\""
msgstr "maxAllocatedDescs (%d) überschritten beim Versuch, den Befehl »%s« auszuführen"
-#: storage/file/fd.c:2218
+#: storage/file/fd.c:2295
#, c-format
msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\""
msgstr "maxAllocatedDescs (%d) überschritten beim Versuch, das Verzeichnis »%s« zu öffnen"
-#: storage/file/fd.c:2304
+#: storage/file/fd.c:2381
#, c-format
msgid "could not read directory \"%s\": %m"
msgstr "konnte Verzeichnis »%s« nicht lesen: %m"
-#: storage/ipc/dsm.c:363
+#: storage/ipc/dsm.c:364
#, c-format
msgid "dynamic shared memory control segment is corrupt"
msgstr "Kontrollsegment von dynamischem Shared Memory ist verfälscht"
-#: storage/ipc/dsm.c:410
+#: storage/ipc/dsm.c:411
#, c-format
msgid "dynamic shared memory is disabled"
msgstr "dynamisches Shared-Memory ist abgeschaltet"
-#: storage/ipc/dsm.c:411
+#: storage/ipc/dsm.c:412
#, c-format
msgid "Set dynamic_shared_memory_type to a value other than \"none\"."
msgstr "Setzen Sie dynamic_shared_memory_type auf einen anderen Wert als »none«."
-#: storage/ipc/dsm.c:431
+#: storage/ipc/dsm.c:432
#, c-format
msgid "dynamic shared memory control segment is not valid"
msgstr "Kontrollsegment von dynamischem Shared Memory ist ungültig"
-#: storage/ipc/dsm.c:516
+#: storage/ipc/dsm.c:521
#, c-format
msgid "too many dynamic shared memory segments"
msgstr "zu viele dynamische Shared-Memory-Segmente"
-#: storage/ipc/dsm_impl.c:261 storage/ipc/dsm_impl.c:361
-#: storage/ipc/dsm_impl.c:533 storage/ipc/dsm_impl.c:648
-#: storage/ipc/dsm_impl.c:811 storage/ipc/dsm_impl.c:953
+#: storage/ipc/dsm_impl.c:260 storage/ipc/dsm_impl.c:360
+#: storage/ipc/dsm_impl.c:532 storage/ipc/dsm_impl.c:647
+#: storage/ipc/dsm_impl.c:818 storage/ipc/dsm_impl.c:960
#, c-format
msgid "could not unmap shared memory segment \"%s\": %m"
msgstr "konnte Shared-Memory-Segment »%s« nicht unmappen: %m"
-#: storage/ipc/dsm_impl.c:271 storage/ipc/dsm_impl.c:543
-#: storage/ipc/dsm_impl.c:658 storage/ipc/dsm_impl.c:821
+#: storage/ipc/dsm_impl.c:270 storage/ipc/dsm_impl.c:542
+#: storage/ipc/dsm_impl.c:657 storage/ipc/dsm_impl.c:828
#, c-format
msgid "could not remove shared memory segment \"%s\": %m"
msgstr "konnte Shared-Memory-Segment »%s« nicht entfernen: %m"
-#: storage/ipc/dsm_impl.c:292 storage/ipc/dsm_impl.c:721
-#: storage/ipc/dsm_impl.c:835
+#: storage/ipc/dsm_impl.c:291 storage/ipc/dsm_impl.c:728
+#: storage/ipc/dsm_impl.c:842
#, c-format
msgid "could not open shared memory segment \"%s\": %m"
msgstr "konnte Shared-Memory-Segment »%s« nicht öffnen: %m"
-#: storage/ipc/dsm_impl.c:316 storage/ipc/dsm_impl.c:559
-#: storage/ipc/dsm_impl.c:766 storage/ipc/dsm_impl.c:859
+#: storage/ipc/dsm_impl.c:315 storage/ipc/dsm_impl.c:558
+#: storage/ipc/dsm_impl.c:773 storage/ipc/dsm_impl.c:866
#, c-format
msgid "could not stat shared memory segment \"%s\": %m"
msgstr "konnte »stat« für Shared-Memory-Segment »%s« nicht ausführen: %m"
-#: storage/ipc/dsm_impl.c:335 storage/ipc/dsm_impl.c:878
-#: storage/ipc/dsm_impl.c:926
+#: storage/ipc/dsm_impl.c:334 storage/ipc/dsm_impl.c:885
+#: storage/ipc/dsm_impl.c:933
#, c-format
msgid "could not resize shared memory segment \"%s\" to %zu bytes: %m"
msgstr "konnte Größe des Shared-Memory-Segments »%s« nicht auf %zu Bytes ändern: %m"
-#: storage/ipc/dsm_impl.c:385 storage/ipc/dsm_impl.c:580
-#: storage/ipc/dsm_impl.c:742 storage/ipc/dsm_impl.c:977
+#: storage/ipc/dsm_impl.c:384 storage/ipc/dsm_impl.c:579
+#: storage/ipc/dsm_impl.c:749 storage/ipc/dsm_impl.c:984
#, c-format
msgid "could not map shared memory segment \"%s\": %m"
msgstr "konnte Shared-Memory-Segment »%s« nicht mappen: %m"
-#: storage/ipc/dsm_impl.c:515
+#: storage/ipc/dsm_impl.c:514
#, c-format
msgid "could not get shared memory segment: %m"
msgstr "konnte Shared-Memory-Segment nicht finden: %m"
-#: storage/ipc/dsm_impl.c:694
+#: storage/ipc/dsm_impl.c:713
#, c-format
msgid "could not create shared memory segment \"%s\": %m"
msgstr "konnte Shared-Memory-Segment »%s« nicht erzeugen: %m"
-#: storage/ipc/dsm_impl.c:1018
+#: storage/ipc/dsm_impl.c:1026 storage/ipc/dsm_impl.c:1074
#, c-format
msgid "could not duplicate handle for \"%s\": %m"
msgstr "konnte Handle für »%s« nicht duplizieren: %m"
-#: storage/ipc/latch.c:775
+#: storage/ipc/latch.c:780
#, c-format
msgid "epoll_ctl() failed: %m"
msgstr "epoll_ctl() fehlgeschlagen: %m"
-#: storage/ipc/latch.c:999
+#: storage/ipc/latch.c:1009
#, c-format
msgid "epoll_wait() failed: %m"
msgstr "epoll_wait() fehlgeschlagen: %m"
-#: storage/ipc/latch.c:1119
+#: storage/ipc/latch.c:1129
#, c-format
msgid "poll() failed: %m"
msgstr "poll() fehlgeschlagen: %m"
-#: storage/ipc/shm_toc.c:108 storage/ipc/shm_toc.c:189 storage/ipc/shmem.c:212
-#: storage/lmgr/lock.c:883 storage/lmgr/lock.c:917 storage/lmgr/lock.c:2682
-#: storage/lmgr/lock.c:4007 storage/lmgr/lock.c:4072 storage/lmgr/lock.c:4364
-#: storage/lmgr/predicate.c:2329 storage/lmgr/predicate.c:2344
-#: storage/lmgr/predicate.c:3736 storage/lmgr/predicate.c:4879
-#: storage/lmgr/proc.c:203 utils/hash/dynahash.c:1045
+#: storage/ipc/latch.c:1287
+#, c-format
+msgid "select() failed: %m"
+msgstr "select() fehlgeschlagen: %m"
+
+#: storage/ipc/shm_toc.c:108 storage/ipc/shm_toc.c:189 storage/lmgr/lock.c:883
+#: storage/lmgr/lock.c:917 storage/lmgr/lock.c:2679 storage/lmgr/lock.c:4004
+#: storage/lmgr/lock.c:4069 storage/lmgr/lock.c:4361
+#: storage/lmgr/predicate.c:2318 storage/lmgr/predicate.c:2333
+#: storage/lmgr/predicate.c:3725 storage/lmgr/predicate.c:4868
+#: utils/hash/dynahash.c:1043
#, c-format
msgid "out of shared memory"
msgstr "Shared Memory aufgebraucht"
-#: storage/ipc/shmem.c:370 storage/ipc/shmem.c:421
-#, c-format
-msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)"
+#: storage/ipc/shmem.c:165 storage/ipc/shmem.c:246
+#, fuzzy, c-format
+#| msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)"
+msgid "out of shared memory (%zu bytes requested)"
msgstr "nicht genug Shared-Memory für Datenstruktur »%s« (%zu Bytes angefordert)"
-#: storage/ipc/shmem.c:389
+#: storage/ipc/shmem.c:421
#, c-format
msgid "could not create ShmemIndex entry for data structure \"%s\""
msgstr "konnte ShmemIndex-Eintrag für Datenstruktur »%s« nicht erzeugen"
-#: storage/ipc/shmem.c:404
+#: storage/ipc/shmem.c:436
#, c-format
msgid "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, actual %zu"
msgstr "ShmemIndex-Eintraggröße ist falsch für Datenstruktur »%s«: erwartet %zu, tatsächlich %zu"
-#: storage/ipc/shmem.c:452 storage/ipc/shmem.c:471
+#: storage/ipc/shmem.c:453
+#, c-format
+msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)"
+msgstr "nicht genug Shared-Memory für Datenstruktur »%s« (%zu Bytes angefordert)"
+
+#: storage/ipc/shmem.c:484 storage/ipc/shmem.c:503
#, c-format
msgid "requested shared memory size overflows size_t"
msgstr "angeforderte Shared-Memory-Größe übersteigt Kapazität von size_t"
-#: storage/ipc/standby.c:528 tcop/postgres.c:2978
+#: storage/ipc/standby.c:531 tcop/postgres.c:2964
#, c-format
msgid "canceling statement due to conflict with recovery"
msgstr "storniere Anfrage wegen Konflikt mit der Wiederherstellung"
-#: storage/ipc/standby.c:529 tcop/postgres.c:2265
+#: storage/ipc/standby.c:532 tcop/postgres.c:2271
#, c-format
msgid "User transaction caused buffer deadlock with recovery."
msgstr "Benutzertransaktion hat Verklemmung (Deadlock) mit Wiederherstellung verursacht."
@@ -16712,252 +18053,242 @@ msgstr "Sperrmodus %s kann während der Wiederherstellung nicht auf Datenbankobj
msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery."
msgstr "Nur Sperren gleich oder unter RowExclusiveLock können während der Wiederherstellung auf Datenbankobjekte gesetzt werden."
-#: storage/lmgr/lock.c:884 storage/lmgr/lock.c:918 storage/lmgr/lock.c:2683
-#: storage/lmgr/lock.c:4008 storage/lmgr/lock.c:4073 storage/lmgr/lock.c:4365
+#: storage/lmgr/lock.c:884 storage/lmgr/lock.c:918 storage/lmgr/lock.c:2680
+#: storage/lmgr/lock.c:4005 storage/lmgr/lock.c:4070 storage/lmgr/lock.c:4362
#, c-format
msgid "You might need to increase max_locks_per_transaction."
msgstr "Sie müssen möglicherweise max_locks_per_transaction erhöhen."
-#: storage/lmgr/lock.c:3124 storage/lmgr/lock.c:3240
+#: storage/lmgr/lock.c:3121 storage/lmgr/lock.c:3237
#, c-format
msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object"
msgstr "PREPARE kann nicht ausgeführt werden, wenn für das selbe Objekt Sperren auf Sitzungsebene und auf Transaktionsebene gehalten werden"
-#: storage/lmgr/predicate.c:675
+#: storage/lmgr/predicate.c:676
#, c-format
msgid "not enough elements in RWConflictPool to record a read/write conflict"
msgstr "nicht genügend Elemente in RWConflictPool, um einen Lese-/Schreibkonflikt aufzuzeichnen"
-#: storage/lmgr/predicate.c:676 storage/lmgr/predicate.c:704
+#: storage/lmgr/predicate.c:677 storage/lmgr/predicate.c:705
#, c-format
msgid "You might need to run fewer transactions at a time or increase max_connections."
msgstr "Sie müssten entweder weniger Transaktionen auf einmal ausführen oder max_connections erhöhen."
-#: storage/lmgr/predicate.c:703
+#: storage/lmgr/predicate.c:704
#, c-format
msgid "not enough elements in RWConflictPool to record a potential read/write conflict"
msgstr "nicht genügend Elemente in RWConflictPool, um einen möglichen Lese-/Schreibkonflikt aufzuzeichnen"
-#: storage/lmgr/predicate.c:909
+#: storage/lmgr/predicate.c:910
#, c-format
msgid "memory for serializable conflict tracking is nearly exhausted"
msgstr "Speicher für die Verfolgung von Serialisierungskonflikten ist fast aufgebraucht"
-#: storage/lmgr/predicate.c:910
+#: storage/lmgr/predicate.c:911
#, c-format
msgid "There might be an idle transaction or a forgotten prepared transaction causing this."
msgstr "Möglicherweise gibt es eine stillliegende Transaktion oder eine vergessene vorbereitete Transaktion, die der Grund dafür ist."
-#: storage/lmgr/predicate.c:1190 storage/lmgr/predicate.c:1261
-#, c-format
-msgid "not enough shared memory for elements of data structure \"%s\" (%zu bytes requested)"
-msgstr "nicht genug Shared-Memory für Elemente der Datenstruktur »%s« (%zu Bytes angefordert)"
-
-#: storage/lmgr/predicate.c:1549
+#: storage/lmgr/predicate.c:1538
#, c-format
msgid "deferrable snapshot was unsafe; trying a new one"
msgstr "aufschiebbarer Snapshot war unsicher; versuche einen neuen"
-#: storage/lmgr/predicate.c:1588
+#: storage/lmgr/predicate.c:1577
#, c-format
msgid "\"default_transaction_isolation\" is set to \"serializable\"."
msgstr "»default_transaction_isolation« ist auf »serializable« gesetzt."
-#: storage/lmgr/predicate.c:1589
+#: storage/lmgr/predicate.c:1578
#, c-format
msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default."
msgstr "Mit »SET default_transaction_isolation = 'repeatable read'« können Sie die Voreinstellung ändern."
-#: storage/lmgr/predicate.c:1628
+#: storage/lmgr/predicate.c:1617
#, c-format
msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE"
msgstr "eine Transaktion, die einen Snapshot importiert, must READ ONLY DEFERRABLE sein"
-#: storage/lmgr/predicate.c:1706 utils/time/snapmgr.c:576
-#: utils/time/snapmgr.c:582
+#: storage/lmgr/predicate.c:1695 utils/time/snapmgr.c:617
+#: utils/time/snapmgr.c:623
#, c-format
msgid "could not import the requested snapshot"
msgstr "konnte den angeforderten Snapshot nicht importieren"
-#: storage/lmgr/predicate.c:1707 utils/time/snapmgr.c:583
+#: storage/lmgr/predicate.c:1696 utils/time/snapmgr.c:624
#, c-format
msgid "The source transaction %u is not running anymore."
msgstr "Die Quelltransaktion %u läuft nicht mehr."
-#: storage/lmgr/predicate.c:2330 storage/lmgr/predicate.c:2345
-#: storage/lmgr/predicate.c:3737
+#: storage/lmgr/predicate.c:2319 storage/lmgr/predicate.c:2334
+#: storage/lmgr/predicate.c:3726
#, c-format
msgid "You might need to increase max_pred_locks_per_transaction."
msgstr "Sie müssen möglicherweise max_pred_locks_per_transaction erhöhen."
-#: storage/lmgr/predicate.c:3891 storage/lmgr/predicate.c:3980
-#: storage/lmgr/predicate.c:3988 storage/lmgr/predicate.c:4027
-#: storage/lmgr/predicate.c:4266 storage/lmgr/predicate.c:4603
-#: storage/lmgr/predicate.c:4615 storage/lmgr/predicate.c:4657
-#: storage/lmgr/predicate.c:4695
+#: storage/lmgr/predicate.c:3880 storage/lmgr/predicate.c:3969
+#: storage/lmgr/predicate.c:3977 storage/lmgr/predicate.c:4016
+#: storage/lmgr/predicate.c:4255 storage/lmgr/predicate.c:4592
+#: storage/lmgr/predicate.c:4604 storage/lmgr/predicate.c:4646
+#: storage/lmgr/predicate.c:4684
#, c-format
msgid "could not serialize access due to read/write dependencies among transactions"
msgstr "konnte Zugriff nicht serialisieren wegen Lese-/Schreib-Abhängigkeiten zwischen Transaktionen"
-#: storage/lmgr/predicate.c:3893 storage/lmgr/predicate.c:3982
-#: storage/lmgr/predicate.c:3990 storage/lmgr/predicate.c:4029
-#: storage/lmgr/predicate.c:4268 storage/lmgr/predicate.c:4605
-#: storage/lmgr/predicate.c:4617 storage/lmgr/predicate.c:4659
-#: storage/lmgr/predicate.c:4697
+#: storage/lmgr/predicate.c:3882 storage/lmgr/predicate.c:3971
+#: storage/lmgr/predicate.c:3979 storage/lmgr/predicate.c:4018
+#: storage/lmgr/predicate.c:4257 storage/lmgr/predicate.c:4594
+#: storage/lmgr/predicate.c:4606 storage/lmgr/predicate.c:4648
+#: storage/lmgr/predicate.c:4686
#, c-format
msgid "The transaction might succeed if retried."
msgstr "Die Transaktion könnte erfolgreich sein, wenn sie erneut versucht würde."
-#: storage/lmgr/proc.c:1263
+#: storage/lmgr/proc.c:1273
#, c-format
msgid "Process %d waits for %s on %s."
msgstr "Prozess %d wartet auf %s-Sperre auf %s."
-#: storage/lmgr/proc.c:1274
+#: storage/lmgr/proc.c:1284
#, c-format
msgid "sending cancel to blocking autovacuum PID %d"
msgstr "sende Stornierung an blockierende Autovacuum-PID %d"
-#: storage/lmgr/proc.c:1292 utils/adt/misc.c:270
+#: storage/lmgr/proc.c:1302 utils/adt/misc.c:269
#, c-format
msgid "could not send signal to process %d: %m"
msgstr "konnte Signal nicht an Prozess %d senden: %m"
-#: storage/lmgr/proc.c:1394
+#: storage/lmgr/proc.c:1404
#, c-format
msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms"
msgstr "Prozess %d vermied Verklemmung wegen %s-Sperre auf %s durch Umordnen der Queue nach %ld,%03d ms"
-#: storage/lmgr/proc.c:1409
+#: storage/lmgr/proc.c:1419
#, c-format
msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms"
msgstr "Prozess %d hat Verklemmung festgestellt beim Warten auf %s-Sperre auf %s nach %ld,%03d ms"
-#: storage/lmgr/proc.c:1418
+#: storage/lmgr/proc.c:1428
#, c-format
msgid "process %d still waiting for %s on %s after %ld.%03d ms"
msgstr "Prozess %d wartet immer noch auf %s-Sperre auf %s nach %ld,%03d ms"
-#: storage/lmgr/proc.c:1425
+#: storage/lmgr/proc.c:1435
#, c-format
msgid "process %d acquired %s on %s after %ld.%03d ms"
msgstr "Prozess %d erlangte %s-Sperre auf %s nach %ld,%03d ms"
-#: storage/lmgr/proc.c:1441
+#: storage/lmgr/proc.c:1451
#, c-format
msgid "process %d failed to acquire %s on %s after %ld.%03d ms"
msgstr "Prozess %d konnte %s-Sperre auf %s nach %ld,%03d ms nicht erlangen"
-#: storage/page/bufpage.c:144
+#: storage/page/bufpage.c:151
#, c-format
msgid "page verification failed, calculated checksum %u but expected %u"
msgstr "Seitenüberprüfung fehlgeschlagen, berechnete Prüfsumme %u, aber erwartet %u"
-#: storage/page/bufpage.c:203 storage/page/bufpage.c:522
-#: storage/page/bufpage.c:737 storage/page/bufpage.c:868
-#: storage/page/bufpage.c:968
+#: storage/page/bufpage.c:213 storage/page/bufpage.c:505
+#: storage/page/bufpage.c:748 storage/page/bufpage.c:881
+#: storage/page/bufpage.c:977 storage/page/bufpage.c:1087
#, c-format
msgid "corrupted page pointers: lower = %u, upper = %u, special = %u"
msgstr "verfälschte Seitenzeiger: lower = %u, upper = %u, special = %u"
-#: storage/page/bufpage.c:566
+#: storage/page/bufpage.c:549
#, c-format
msgid "corrupted item pointer: %u"
msgstr "verfälschter Item-Zeiger: %u"
-#: storage/page/bufpage.c:577 storage/page/bufpage.c:919
-#: storage/page/bufpage.c:1074
+#: storage/page/bufpage.c:560 storage/page/bufpage.c:932
#, c-format
msgid "corrupted item lengths: total %u, available space %u"
msgstr "verfälschte Item-Längen: gesamt %u, verfügbarer Platz %u"
-#: storage/page/bufpage.c:756 storage/page/bufpage.c:892
+#: storage/page/bufpage.c:767 storage/page/bufpage.c:905
+#: storage/page/bufpage.c:993 storage/page/bufpage.c:1103
#, c-format
msgid "corrupted item pointer: offset = %u, size = %u"
msgstr "verfälschter Item-Zeiger: offset = %u, size = %u"
-#: storage/page/bufpage.c:997
-#, c-format
-msgid "corrupted item pointer: offset = %u, length = %u"
-msgstr "verfälschter Item-Zeiger: offset = %u, length = %u"
-
-#: storage/smgr/md.c:453 storage/smgr/md.c:975
+#: storage/smgr/md.c:447 storage/smgr/md.c:973
#, c-format
msgid "could not truncate file \"%s\": %m"
msgstr "kann Datei »%s« nicht kürzen: %m"
-#: storage/smgr/md.c:520
+#: storage/smgr/md.c:514
#, c-format
msgid "cannot extend file \"%s\" beyond %u blocks"
msgstr "kann Datei »%s« nicht auf über %u Blöcke erweitern"
# XXX
-#: storage/smgr/md.c:542 storage/smgr/md.c:755 storage/smgr/md.c:831
+#: storage/smgr/md.c:536 storage/smgr/md.c:753 storage/smgr/md.c:829
#, c-format
msgid "could not seek to block %u in file \"%s\": %m"
msgstr "konnte Positionszeiger nicht auf Block %u in Datei »%s« setzen: %m"
-#: storage/smgr/md.c:550
+#: storage/smgr/md.c:544
#, c-format
msgid "could not extend file \"%s\": %m"
msgstr "konnte Datei »%s« nicht erweitern: %m"
-#: storage/smgr/md.c:552 storage/smgr/md.c:559 storage/smgr/md.c:858
+#: storage/smgr/md.c:546 storage/smgr/md.c:553 storage/smgr/md.c:856
#, c-format
msgid "Check free disk space."
msgstr "Prüfen Sie den freien Festplattenplatz."
-#: storage/smgr/md.c:556
+#: storage/smgr/md.c:550
#, c-format
msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u"
msgstr "konnte Datei »%s« nicht erweitern: es wurden nur %d von %d Bytes bei Block %u geschrieben"
-#: storage/smgr/md.c:773
+#: storage/smgr/md.c:771
#, c-format
msgid "could not read block %u in file \"%s\": %m"
msgstr "konnte Block %u in Datei »%s« nicht lesen: %m"
-#: storage/smgr/md.c:789
+#: storage/smgr/md.c:787
#, c-format
msgid "could not read block %u in file \"%s\": read only %d of %d bytes"
msgstr "konnte Block %u in Datei »%s« nicht lesen: es wurden nur %d von %d Bytes gelesen"
-#: storage/smgr/md.c:849
+#: storage/smgr/md.c:847
#, c-format
msgid "could not write block %u in file \"%s\": %m"
msgstr "konnte Block %u in Datei »%s« nicht schreiben: %m"
-#: storage/smgr/md.c:854
+#: storage/smgr/md.c:852
#, c-format
msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes"
msgstr "konnte Block %u in Datei »%s« nicht schreiben: es wurden nur %d von %d Bytes geschrieben"
-#: storage/smgr/md.c:951
+#: storage/smgr/md.c:944
#, c-format
msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now"
msgstr "konnte Datei »%s« nicht auf %u Blöcke kürzen: es sind jetzt nur %u Blöcke"
-#: storage/smgr/md.c:1000
+#: storage/smgr/md.c:999
#, c-format
msgid "could not truncate file \"%s\" to %u blocks: %m"
msgstr "konnte Datei »%s« nicht auf %u Blöcke kürzen: %m"
-#: storage/smgr/md.c:1282
+#: storage/smgr/md.c:1281
#, c-format
msgid "could not fsync file \"%s\" but retrying: %m"
msgstr "konnte Datei »%s« nicht fsyncen, versuche erneut: %m"
-#: storage/smgr/md.c:1445
+#: storage/smgr/md.c:1444
#, c-format
msgid "could not forward fsync request because request queue is full"
msgstr "konnte fsync-Anfrage nicht weiterleiten, weil Anfrageschlange voll ist"
-#: storage/smgr/md.c:1866
+#: storage/smgr/md.c:1913
#, c-format
msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks"
msgstr "konnte Datei »%s« nicht öffnen (Zielblock %u): vorhergehendes Segment hat nur %u Blöcke"
-#: storage/smgr/md.c:1880
+#: storage/smgr/md.c:1927
#, c-format
msgid "could not open file \"%s\" (target block %u): %m"
msgstr "konnte Datei »%s« nicht öffnen (Zielblock %u): %m"
@@ -16967,9 +18298,9 @@ msgstr "konnte Datei »%s« nicht öffnen (Zielblock %u): %m"
msgid "invalid argument size %d in function call message"
msgstr "ungültige Argumentgröße %d in Funktionsaufruf-Message"
-#: tcop/fastpath.c:291 tcop/postgres.c:992 tcop/postgres.c:1303
-#: tcop/postgres.c:1561 tcop/postgres.c:1966 tcop/postgres.c:2333
-#: tcop/postgres.c:2408
+#: tcop/fastpath.c:291 tcop/postgres.c:999 tcop/postgres.c:1308
+#: tcop/postgres.c:1567 tcop/postgres.c:1972 tcop/postgres.c:2339
+#: tcop/postgres.c:2414
#, c-format
msgid "current transaction is aborted, commands ignored until end of transaction block"
msgstr "aktuelle Transaktion wurde abgebrochen, Befehle werden bis zum Ende der Transaktion ignoriert"
@@ -16979,8 +18310,8 @@ msgstr "aktuelle Transaktion wurde abgebrochen, Befehle werden bis zum Ende der
msgid "fastpath function call: \"%s\" (OID %u)"
msgstr "Fastpath-Funktionsaufruf: »%s« (OID %u)"
-#: tcop/fastpath.c:401 tcop/postgres.c:1163 tcop/postgres.c:1428
-#: tcop/postgres.c:1807 tcop/postgres.c:2024
+#: tcop/fastpath.c:401 tcop/postgres.c:1170 tcop/postgres.c:1433
+#: tcop/postgres.c:1813 tcop/postgres.c:2030
#, c-format
msgid "duration: %s ms"
msgstr "Dauer: %s ms"
@@ -17011,492 +18342,491 @@ msgid "unexpected EOF on client connection"
msgstr "unerwartetes EOF auf Client-Verbindung"
#: tcop/postgres.c:438 tcop/postgres.c:450 tcop/postgres.c:461
-#: tcop/postgres.c:473 tcop/postgres.c:4312
+#: tcop/postgres.c:473 tcop/postgres.c:4304
#, c-format
msgid "invalid frontend message type %d"
msgstr "ungültiger Frontend-Message-Typ %d"
-#: tcop/postgres.c:933
+#: tcop/postgres.c:940
#, c-format
msgid "statement: %s"
msgstr "Anweisung: %s"
-#: tcop/postgres.c:1168
+#: tcop/postgres.c:1175
#, c-format
msgid "duration: %s ms statement: %s"
msgstr "Dauer: %s ms Anweisung: %s"
-#: tcop/postgres.c:1218
+#: tcop/postgres.c:1225
#, c-format
msgid "parse %s: %s"
msgstr "Parsen %s: %s"
-#: tcop/postgres.c:1276
+#: tcop/postgres.c:1281
#, c-format
msgid "cannot insert multiple commands into a prepared statement"
msgstr "kann nicht mehrere Befehle in vorbereitete Anweisung einfügen"
-#: tcop/postgres.c:1433
+#: tcop/postgres.c:1438
#, c-format
msgid "duration: %s ms parse %s: %s"
msgstr "Dauer: %s ms Parsen %s: %s"
-#: tcop/postgres.c:1478
+#: tcop/postgres.c:1483
#, c-format
msgid "bind %s to %s"
msgstr "Binden %s an %s"
-#: tcop/postgres.c:1497 tcop/postgres.c:2314
+#: tcop/postgres.c:1502 tcop/postgres.c:2320
#, c-format
msgid "unnamed prepared statement does not exist"
msgstr "unbenannte vorbereitete Anweisung existiert nicht"
-#: tcop/postgres.c:1539
+#: tcop/postgres.c:1544
#, c-format
msgid "bind message has %d parameter formats but %d parameters"
msgstr "Binden-Nachricht hat %d Parameterformate aber %d Parameter"
-#: tcop/postgres.c:1545
+#: tcop/postgres.c:1550
#, c-format
msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d"
msgstr "Binden-Nachricht enthält %d Parameter, aber vorbereitete Anweisung »%s« erfordert %d"
-#: tcop/postgres.c:1714
+#: tcop/postgres.c:1720
#, c-format
msgid "incorrect binary data format in bind parameter %d"
msgstr "falsches Binärdatenformat in Binden-Parameter %d"
-#: tcop/postgres.c:1812
+#: tcop/postgres.c:1818
#, c-format
msgid "duration: %s ms bind %s%s%s: %s"
msgstr "Dauer: %s ms Binden %s%s%s: %s"
-#: tcop/postgres.c:1860 tcop/postgres.c:2394
+#: tcop/postgres.c:1866 tcop/postgres.c:2400
#, c-format
msgid "portal \"%s\" does not exist"
msgstr "Portal »%s« existiert nicht"
-#: tcop/postgres.c:1945
+#: tcop/postgres.c:1951
#, c-format
msgid "%s %s%s%s: %s"
msgstr "%s %s%s%s: %s"
-#: tcop/postgres.c:1947 tcop/postgres.c:2032
+#: tcop/postgres.c:1953 tcop/postgres.c:2038
msgid "execute fetch from"
msgstr "Ausführen Fetch von"
-#: tcop/postgres.c:1948 tcop/postgres.c:2033
+#: tcop/postgres.c:1954 tcop/postgres.c:2039
msgid "execute"
msgstr "Ausführen"
-#: tcop/postgres.c:2029
+#: tcop/postgres.c:2035
#, c-format
msgid "duration: %s ms %s %s%s%s: %s"
msgstr "Dauer: %s ms %s %s%s%s: %s"
-#: tcop/postgres.c:2155
+#: tcop/postgres.c:2161
#, c-format
msgid "prepare: %s"
msgstr "Vorbereiten: %s"
-#: tcop/postgres.c:2218
+#: tcop/postgres.c:2224
#, c-format
msgid "parameters: %s"
msgstr "Parameter: %s"
-#: tcop/postgres.c:2237
+#: tcop/postgres.c:2243
#, c-format
msgid "abort reason: recovery conflict"
msgstr "Abbruchgrund: Konflikt bei Wiederherstellung"
-#: tcop/postgres.c:2253
+#: tcop/postgres.c:2259
#, c-format
msgid "User was holding shared buffer pin for too long."
msgstr "Benutzer hat Shared-Buffer-Pin zu lange gehalten."
-#: tcop/postgres.c:2256
+#: tcop/postgres.c:2262
#, c-format
msgid "User was holding a relation lock for too long."
msgstr "Benutzer hat Relationssperre zu lange gehalten."
-#: tcop/postgres.c:2259
+#: tcop/postgres.c:2265
#, c-format
msgid "User was or might have been using tablespace that must be dropped."
msgstr "Benutzer hat (möglicherweise) einen Tablespace verwendet, der gelöscht werden muss."
-#: tcop/postgres.c:2262
+#: tcop/postgres.c:2268
#, c-format
msgid "User query might have needed to see row versions that must be removed."
msgstr "Benutzeranfrage hat möglicherweise Zeilenversionen sehen müssen, die entfernt werden müssen."
-#: tcop/postgres.c:2268
+#: tcop/postgres.c:2274
#, c-format
msgid "User was connected to a database that must be dropped."
msgstr "Benutzer war mit einer Datenbank verbunden, die gelöscht werden muss."
-#: tcop/postgres.c:2597
+#: tcop/postgres.c:2583
#, c-format
msgid "terminating connection because of crash of another server process"
msgstr "Verbindung wird abgebrochen wegen Absturz eines anderen Serverprozesses"
-#: tcop/postgres.c:2598
+#: tcop/postgres.c:2584
#, c-format
msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory."
msgstr "Der Postmaster hat diesen Serverprozess angewiesen, die aktuelle Transaktion zurückzurollen und die Sitzung zu beenden, weil ein anderer Serverprozess abnormal beendet wurde und möglicherweise das Shared Memory verfälscht hat."
-#: tcop/postgres.c:2602 tcop/postgres.c:2906
+#: tcop/postgres.c:2588 tcop/postgres.c:2892
#, c-format
msgid "In a moment you should be able to reconnect to the database and repeat your command."
msgstr "In einem Moment sollten Sie wieder mit der Datenbank verbinden und Ihren Befehl wiederholen können."
-#: tcop/postgres.c:2688
+#: tcop/postgres.c:2674
#, c-format
msgid "floating-point exception"
msgstr "Fließkommafehler"
-#: tcop/postgres.c:2689
+#: tcop/postgres.c:2675
#, c-format
msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero."
msgstr "Eine ungültige Fließkommaoperation wurde signalisiert. Das bedeutet wahrscheinlich ein Ergebnis außerhalb des gültigen Bereichs oder eine ungültige Operation, zum Beispiel Division durch null."
-#: tcop/postgres.c:2851
+#: tcop/postgres.c:2837
#, c-format
msgid "canceling authentication due to timeout"
msgstr "storniere Authentifizierung wegen Zeitüberschreitung"
-#: tcop/postgres.c:2855
+#: tcop/postgres.c:2841
#, c-format
msgid "terminating autovacuum process due to administrator command"
msgstr "Autovacuum-Prozess wird abgebrochen aufgrund von Anweisung des Administrators"
-#: tcop/postgres.c:2861 tcop/postgres.c:2871 tcop/postgres.c:2904
+#: tcop/postgres.c:2847 tcop/postgres.c:2857 tcop/postgres.c:2890
#, c-format
msgid "terminating connection due to conflict with recovery"
msgstr "Verbindung wird abgebrochen wegen Konflikt mit der Wiederherstellung"
-#: tcop/postgres.c:2877
+#: tcop/postgres.c:2863
#, c-format
msgid "terminating connection due to administrator command"
msgstr "Verbindung wird abgebrochen aufgrund von Anweisung des Administrators"
-#: tcop/postgres.c:2887
+#: tcop/postgres.c:2873
#, c-format
msgid "connection to client lost"
msgstr "Verbindung zum Client wurde verloren"
-#: tcop/postgres.c:2955
+#: tcop/postgres.c:2941
#, c-format
msgid "canceling statement due to lock timeout"
msgstr "storniere Anfrage wegen Zeitüberschreitung einer Sperre"
-#: tcop/postgres.c:2962
+#: tcop/postgres.c:2948
#, c-format
msgid "canceling statement due to statement timeout"
msgstr "storniere Anfrage wegen Zeitüberschreitung der Anfrage"
-#: tcop/postgres.c:2969
+#: tcop/postgres.c:2955
#, c-format
msgid "canceling autovacuum task"
msgstr "storniere Autovacuum-Aufgabe"
-#: tcop/postgres.c:2992
+#: tcop/postgres.c:2978
#, c-format
msgid "canceling statement due to user request"
msgstr "storniere Anfrage wegen Benutzeraufforderung"
-#: tcop/postgres.c:3002
+#: tcop/postgres.c:2988
#, c-format
msgid "terminating connection due to idle-in-transaction timeout"
msgstr "Verbindung wird abgebrochen wegen Zeitüberschreitung in inaktiver Transaktion"
-#: tcop/postgres.c:3116
+#: tcop/postgres.c:3102
#, c-format
msgid "stack depth limit exceeded"
msgstr "Grenze für Stacktiefe überschritten"
-#: tcop/postgres.c:3117
+#: tcop/postgres.c:3103
#, c-format
msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate."
msgstr "Erhöhen Sie den Konfigurationsparameter »max_stack_depth« (aktuell %dkB), nachdem Sie sichergestellt haben, dass die Stacktiefenbegrenzung Ihrer Plattform ausreichend ist."
-#: tcop/postgres.c:3180
+#: tcop/postgres.c:3166
#, c-format
msgid "\"max_stack_depth\" must not exceed %ldkB."
msgstr "»max_stack_depth« darf %ldkB nicht überschreiten."
-#: tcop/postgres.c:3182
+#: tcop/postgres.c:3168
#, c-format
msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent."
msgstr "Erhöhen Sie die Stacktiefenbegrenzung Ihrer Plattform mit »ulimit -s« oder der lokalen Entsprechung."
-#: tcop/postgres.c:3542
+#: tcop/postgres.c:3528
#, c-format
msgid "invalid command-line argument for server process: %s"
msgstr "ungültiges Kommandozeilenargument für Serverprozess: %s"
-#: tcop/postgres.c:3543 tcop/postgres.c:3549
+#: tcop/postgres.c:3529 tcop/postgres.c:3535
#, c-format
msgid "Try \"%s --help\" for more information."
msgstr "Versuchen Sie »%s --help« für weitere Informationen."
-#: tcop/postgres.c:3547
+#: tcop/postgres.c:3533
#, c-format
msgid "%s: invalid command-line argument: %s"
msgstr "%s: ungültiges Kommandozeilenargument: %s"
-#: tcop/postgres.c:3609
+#: tcop/postgres.c:3595
#, c-format
msgid "%s: no database nor user name specified"
msgstr "%s: weder Datenbankname noch Benutzername angegeben"
-#: tcop/postgres.c:4220
+#: tcop/postgres.c:4212
#, c-format
msgid "invalid CLOSE message subtype %d"
msgstr "ungültiger Subtyp %d von CLOSE-Message"
-#: tcop/postgres.c:4255
+#: tcop/postgres.c:4247
#, c-format
msgid "invalid DESCRIBE message subtype %d"
msgstr "ungültiger Subtyp %d von DESCRIBE-Message"
-#: tcop/postgres.c:4333
+#: tcop/postgres.c:4325
#, c-format
msgid "fastpath function calls not supported in a replication connection"
msgstr "Fastpath-Funktionsaufrufe werden auf einer Replikationsverbindung nicht unterstützt"
-#: tcop/postgres.c:4337
+#: tcop/postgres.c:4329
#, c-format
msgid "extended query protocol not supported in a replication connection"
msgstr "erweitertes Anfrageprotokoll wird nicht auf einer Replikationsverbindung unterstützt"
-#: tcop/postgres.c:4507
+#: tcop/postgres.c:4499
#, c-format
msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s"
msgstr "Verbindungsende: Sitzungszeit: %d:%02d:%02d.%03d Benutzer=%s Datenbank=%s Host=%s%s%s"
-#: tcop/pquery.c:665
+#: tcop/pquery.c:638
#, c-format
msgid "bind message has %d result formats but query has %d columns"
msgstr "Bind-Message hat %d Ergebnisspalten, aber Anfrage hat %d Spalten"
-#: tcop/pquery.c:967
+#: tcop/pquery.c:940
#, c-format
msgid "cursor can only scan forward"
msgstr "Cursor kann nur vorwärts scannen"
-#: tcop/pquery.c:968
+#: tcop/pquery.c:941
#, c-format
msgid "Declare it with SCROLL option to enable backward scan."
msgstr "Deklarieren Sie ihn mit der Option SCROLL, um rückwarts scannen zu können."
#. translator: %s is name of a SQL command, eg CREATE
-#: tcop/utility.c:235
+#: tcop/utility.c:241
#, c-format
msgid "cannot execute %s in a read-only transaction"
msgstr "%s kann nicht in einer Read-Only-Transaktion ausgeführt werden"
#. translator: %s is name of a SQL command, eg CREATE
-#: tcop/utility.c:253
+#: tcop/utility.c:259
#, c-format
msgid "cannot execute %s during a parallel operation"
msgstr "%s kann nicht während einer parallelen Operation ausgeführt werden"
#. translator: %s is name of a SQL command, eg CREATE
-#: tcop/utility.c:272
+#: tcop/utility.c:278
#, c-format
msgid "cannot execute %s during recovery"
msgstr "%s kann nicht während der Wiederherstellung ausgeführt werden"
#. translator: %s is name of a SQL command, eg PREPARE
-#: tcop/utility.c:290
+#: tcop/utility.c:296
#, c-format
msgid "cannot execute %s within security-restricted operation"
msgstr "kann %s nicht in einer sicherheitsbeschränkten Operation ausführen"
-#: tcop/utility.c:744
+#: tcop/utility.c:759
#, c-format
msgid "must be superuser to do CHECKPOINT"
msgstr "nur Superuser können CHECKPOINT ausführen"
-#: tsearch/dict_ispell.c:51 tsearch/dict_thesaurus.c:623
+#: tsearch/dict_ispell.c:52 tsearch/dict_thesaurus.c:624
#, c-format
msgid "multiple DictFile parameters"
msgstr "mehrere DictFile-Parameter"
-#: tsearch/dict_ispell.c:62
+#: tsearch/dict_ispell.c:63
#, c-format
msgid "multiple AffFile parameters"
msgstr "mehrere AffFile-Parameter"
-#: tsearch/dict_ispell.c:81
+#: tsearch/dict_ispell.c:82
#, c-format
msgid "unrecognized Ispell parameter: \"%s\""
msgstr "unbekannter Ispell-Parameter: »%s«"
-#: tsearch/dict_ispell.c:95
+#: tsearch/dict_ispell.c:96
#, c-format
msgid "missing AffFile parameter"
msgstr "Parameter »AffFile« fehlt"
-#: tsearch/dict_ispell.c:101 tsearch/dict_thesaurus.c:647
+#: tsearch/dict_ispell.c:102 tsearch/dict_thesaurus.c:648
#, c-format
msgid "missing DictFile parameter"
msgstr "Parameter »DictFile« fehlt"
-#: tsearch/dict_simple.c:57
+#: tsearch/dict_simple.c:58
#, c-format
msgid "multiple Accept parameters"
msgstr "mehrere »Accept«-Parameter"
-#: tsearch/dict_simple.c:65
+#: tsearch/dict_simple.c:66
#, c-format
msgid "unrecognized simple dictionary parameter: \"%s\""
msgstr "unbekannter Parameter für das einfache Wörterbuch: »%s«"
-#: tsearch/dict_synonym.c:117
+#: tsearch/dict_synonym.c:118
#, c-format
msgid "unrecognized synonym parameter: \"%s\""
msgstr "unbekannter Synonymparameter: »%s«"
-#: tsearch/dict_synonym.c:124
+#: tsearch/dict_synonym.c:125
#, c-format
msgid "missing Synonyms parameter"
msgstr "Parameter »Synonyms« fehlt"
-#: tsearch/dict_synonym.c:131
+#: tsearch/dict_synonym.c:132
#, c-format
msgid "could not open synonym file \"%s\": %m"
msgstr "konnte Synonymdatei »%s« nicht öffnen: %m"
-#: tsearch/dict_thesaurus.c:178
+#: tsearch/dict_thesaurus.c:179
#, c-format
msgid "could not open thesaurus file \"%s\": %m"
msgstr "konnte Thesaurusdatei »%s« nicht öffnen: %m"
-#: tsearch/dict_thesaurus.c:211
+#: tsearch/dict_thesaurus.c:212
#, c-format
msgid "unexpected delimiter"
msgstr "unerwartetes Trennzeichen"
-#: tsearch/dict_thesaurus.c:261 tsearch/dict_thesaurus.c:277
+#: tsearch/dict_thesaurus.c:262 tsearch/dict_thesaurus.c:278
#, c-format
msgid "unexpected end of line or lexeme"
msgstr "unerwartetes Ende der Zeile oder des Lexems"
-#: tsearch/dict_thesaurus.c:286
+#: tsearch/dict_thesaurus.c:287
#, c-format
msgid "unexpected end of line"
msgstr "unerwartetes Ende der Zeile"
-#: tsearch/dict_thesaurus.c:296
+#: tsearch/dict_thesaurus.c:297
#, c-format
msgid "too many lexemes in thesaurus entry"
msgstr "zu viele Lexeme in Thesauruseintrag"
-#: tsearch/dict_thesaurus.c:420
+#: tsearch/dict_thesaurus.c:421
#, c-format
msgid "thesaurus sample word \"%s\" isn't recognized by subdictionary (rule %d)"
msgstr "Thesaurus-Beispielwort »%s« wird nicht vom Unterwörterbuch erkannt (Regel %d)"
-#: tsearch/dict_thesaurus.c:426
+#: tsearch/dict_thesaurus.c:427
#, c-format
msgid "thesaurus sample word \"%s\" is a stop word (rule %d)"
msgstr "Thesaurus-Beispielwort »%s« ist ein Stoppwort (Regel %d)"
-#: tsearch/dict_thesaurus.c:429
+#: tsearch/dict_thesaurus.c:430
#, c-format
msgid "Use \"?\" to represent a stop word within a sample phrase."
msgstr "Verwenden Sie »?«, um ein Stoppwort in einem Beispielsatz darzustellen."
-#: tsearch/dict_thesaurus.c:575
+#: tsearch/dict_thesaurus.c:576
#, c-format
msgid "thesaurus substitute word \"%s\" is a stop word (rule %d)"
msgstr "Thesaurus-Ersatzwort »%s« ist ein Stoppwort (Regel %d)"
-#: tsearch/dict_thesaurus.c:582
+#: tsearch/dict_thesaurus.c:583
#, c-format
msgid "thesaurus substitute word \"%s\" isn't recognized by subdictionary (rule %d)"
msgstr "Thesaurus-Ersatzwort »%s« wird nicht vom Unterwörterbuch erkannt (Regel %d)"
-#: tsearch/dict_thesaurus.c:594
+#: tsearch/dict_thesaurus.c:595
#, c-format
msgid "thesaurus substitute phrase is empty (rule %d)"
msgstr "Thesaurus-Ersatzausdruck ist leer (Regel %d)"
-#: tsearch/dict_thesaurus.c:632
+#: tsearch/dict_thesaurus.c:633
#, c-format
msgid "multiple Dictionary parameters"
msgstr "mehrere »Dictionary«-Parameter"
-#: tsearch/dict_thesaurus.c:639
+#: tsearch/dict_thesaurus.c:640
#, c-format
msgid "unrecognized Thesaurus parameter: \"%s\""
msgstr "unbekannter Thesaurus-Parameter: »%s«"
-#: tsearch/dict_thesaurus.c:651
+#: tsearch/dict_thesaurus.c:652
#, c-format
msgid "missing Dictionary parameter"
msgstr "Parameter »Dictionary« fehlt"
-#: tsearch/spell.c:382 tsearch/spell.c:399 tsearch/spell.c:408
-#: tsearch/spell.c:1035
+#: tsearch/spell.c:380 tsearch/spell.c:397 tsearch/spell.c:406
+#: tsearch/spell.c:1034
#, c-format
msgid "invalid affix flag \"%s\""
msgstr "ungültiges Affix-Flag »%s«"
-#: tsearch/spell.c:386 tsearch/spell.c:1039
+#: tsearch/spell.c:384 tsearch/spell.c:1038
#, c-format
msgid "affix flag \"%s\" is out of range"
msgstr "Affix-Flag »%s« ist außerhalb des gültigen Bereichs"
-#: tsearch/spell.c:416
+#: tsearch/spell.c:414
#, c-format
msgid "invalid character in affix flag \"%s\""
msgstr "ungültiges Zeichen in Affix-Flag »%s«"
-#: tsearch/spell.c:436
+#: tsearch/spell.c:434
#, c-format
msgid "invalid affix flag \"%s\" with \"long\" flag value"
msgstr "ungültiges Affix-Flag »%s« mit Flag-Wert »long«"
-#: tsearch/spell.c:523
+#: tsearch/spell.c:522
#, c-format
msgid "could not open dictionary file \"%s\": %m"
msgstr "konnte Wörterbuchdatei »%s« nicht öffnen: %m"
-#: tsearch/spell.c:741 utils/adt/regexp.c:204
+#: tsearch/spell.c:740 utils/adt/regexp.c:204
#, c-format
msgid "invalid regular expression: %s"
msgstr "ungültiger regulärer Ausdruck: %s"
-#: tsearch/spell.c:1162 tsearch/spell.c:1721
+#: tsearch/spell.c:1161 tsearch/spell.c:1721
#, c-format
msgid "invalid affix alias \"%s\""
msgstr "ungültiges Affixalias »%s«"
-#: tsearch/spell.c:1212 tsearch/spell.c:1282 tsearch/spell.c:1426
+#: tsearch/spell.c:1211 tsearch/spell.c:1282 tsearch/spell.c:1426
#, c-format
msgid "could not open affix file \"%s\": %m"
msgstr "konnte Affixdatei »%s« nicht öffnen: %m"
-#: tsearch/spell.c:1266
+#: tsearch/spell.c:1265
#, c-format
-msgid "Ispell dictionary supports only \"default\", \"long\", and \"num\" flag value"
+msgid "Ispell dictionary supports only \"default\", \"long\", and \"num\" flag values"
msgstr "Ispell-Wörterbuch unterstützt nur die Flag-Werte »default«, »long« und »num«"
#: tsearch/spell.c:1309
-#, fuzzy, c-format
-#| msgid "%s: invalid number of parallel jobs\n"
+#, c-format
msgid "invalid number of flag vector aliases"
-msgstr "%s: ungültige Anzahl paralleler Jobs\n"
+msgstr "ungültige Anzahl Flag-Vektor-Aliasse"
#: tsearch/spell.c:1542
#, c-format
msgid "affix file contains both old-style and new-style commands"
msgstr "Affixdatei enthält Befehle im alten und im neuen Stil"
-#: tsearch/to_tsany.c:170 utils/adt/tsvector.c:270
-#: utils/adt/tsvector_op.c:1132
+#: tsearch/to_tsany.c:170 utils/adt/tsvector.c:271
+#: utils/adt/tsvector_op.c:1134
#, c-format
msgid "string is too long for tsvector (%d bytes, max %d bytes)"
msgstr "Zeichenkette ist zu lang für tsvector (%d Bytes, maximal %d Bytes)"
@@ -17533,7 +18863,7 @@ msgstr "ungültiger Textsuchekonfigurationsdateiname »%s«"
msgid "could not open stop-word file \"%s\": %m"
msgstr "konnte Stoppwortdatei »%s« nicht öffnen: %m"
-#: tsearch/wparser.c:306
+#: tsearch/wparser.c:307
#, c-format
msgid "text search parser does not support headline creation"
msgstr "Textsucheparser unterstützt das Erzeugen von Headlines nicht"
@@ -17648,112 +18978,112 @@ msgstr "abhängige Privilegien existieren"
msgid "Use CASCADE to revoke them too."
msgstr "Verwenden Sie CASCADE, um diese auch zu entziehen."
-#: utils/adt/acl.c:1537
+#: utils/adt/acl.c:1520
#, c-format
msgid "aclinsert is no longer supported"
msgstr "aclinsert wird nicht mehr unterstützt"
-#: utils/adt/acl.c:1547
+#: utils/adt/acl.c:1530
#, c-format
msgid "aclremove is no longer supported"
msgstr "aclremove wird nicht mehr unterstützt"
-#: utils/adt/acl.c:1633 utils/adt/acl.c:1687
+#: utils/adt/acl.c:1616 utils/adt/acl.c:1670
#, c-format
msgid "unrecognized privilege type: \"%s\""
msgstr "unbekannter Privilegtyp: »%s«"
-#: utils/adt/acl.c:3427 utils/adt/regproc.c:123 utils/adt/regproc.c:144
-#: utils/adt/regproc.c:319
+#: utils/adt/acl.c:3410 utils/adt/regproc.c:125 utils/adt/regproc.c:146
+#: utils/adt/regproc.c:321
#, c-format
msgid "function \"%s\" does not exist"
msgstr "Funktion »%s« existiert nicht"
-#: utils/adt/acl.c:4881
+#: utils/adt/acl.c:4864
#, c-format
msgid "must be member of role \"%s\""
msgstr "Berechtigung nur für Mitglied von Rolle »%s«"
-#: utils/adt/array_expanded.c:276 utils/adt/arrayfuncs.c:931
+#: utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:931
#: utils/adt/arrayfuncs.c:1519 utils/adt/arrayfuncs.c:3251
-#: utils/adt/arrayfuncs.c:3389 utils/adt/arrayfuncs.c:5864
-#: utils/adt/arrayfuncs.c:6175 utils/adt/arrayutils.c:93
+#: utils/adt/arrayfuncs.c:3389 utils/adt/arrayfuncs.c:5848
+#: utils/adt/arrayfuncs.c:6159 utils/adt/arrayutils.c:93
#: utils/adt/arrayutils.c:102 utils/adt/arrayutils.c:109
#, c-format
msgid "array size exceeds the maximum allowed (%d)"
msgstr "Arraygröße überschreitet erlaubtes Maximum (%d)"
-#: utils/adt/array_userfuncs.c:67 utils/adt/array_userfuncs.c:529
-#: utils/adt/array_userfuncs.c:609 utils/adt/json.c:1759 utils/adt/json.c:1854
-#: utils/adt/json.c:1892 utils/adt/jsonb.c:1126 utils/adt/jsonb.c:1155
-#: utils/adt/jsonb.c:1591 utils/adt/jsonb.c:1755 utils/adt/jsonb.c:1765
+#: utils/adt/array_userfuncs.c:79 utils/adt/array_userfuncs.c:541
+#: utils/adt/array_userfuncs.c:621 utils/adt/json.c:1764 utils/adt/json.c:1859
+#: utils/adt/json.c:1897 utils/adt/jsonb.c:1127 utils/adt/jsonb.c:1156
+#: utils/adt/jsonb.c:1592 utils/adt/jsonb.c:1756 utils/adt/jsonb.c:1766
#, c-format
msgid "could not determine input data type"
msgstr "konnte Eingabedatentypen nicht bestimmen"
-#: utils/adt/array_userfuncs.c:72
+#: utils/adt/array_userfuncs.c:84
#, c-format
msgid "input data type is not an array"
msgstr "Eingabedatentyp ist kein Array"
-#: utils/adt/array_userfuncs.c:120 utils/adt/array_userfuncs.c:174
+#: utils/adt/array_userfuncs.c:132 utils/adt/array_userfuncs.c:186
#: utils/adt/arrayfuncs.c:1322 utils/adt/float.c:1228 utils/adt/float.c:1287
-#: utils/adt/float.c:3556 utils/adt/float.c:3572 utils/adt/int.c:623
-#: utils/adt/int.c:652 utils/adt/int.c:673 utils/adt/int.c:704
-#: utils/adt/int.c:737 utils/adt/int.c:759 utils/adt/int.c:907
-#: utils/adt/int.c:928 utils/adt/int.c:955 utils/adt/int.c:995
-#: utils/adt/int.c:1016 utils/adt/int.c:1043 utils/adt/int.c:1076
-#: utils/adt/int.c:1159 utils/adt/int8.c:1298 utils/adt/numeric.c:2907
-#: utils/adt/numeric.c:2916 utils/adt/varbit.c:1173 utils/adt/varbit.c:1565
-#: utils/adt/varlena.c:1055 utils/adt/varlena.c:2807
+#: utils/adt/float.c:3556 utils/adt/float.c:3572 utils/adt/int.c:608
+#: utils/adt/int.c:637 utils/adt/int.c:658 utils/adt/int.c:689
+#: utils/adt/int.c:722 utils/adt/int.c:744 utils/adt/int.c:892
+#: utils/adt/int.c:913 utils/adt/int.c:940 utils/adt/int.c:980
+#: utils/adt/int.c:1001 utils/adt/int.c:1028 utils/adt/int.c:1061
+#: utils/adt/int.c:1144 utils/adt/int8.c:1298 utils/adt/numeric.c:2953
+#: utils/adt/numeric.c:2962 utils/adt/varbit.c:1173 utils/adt/varbit.c:1575
+#: utils/adt/varlena.c:1056 utils/adt/varlena.c:2808
#, c-format
msgid "integer out of range"
msgstr "integer ist außerhalb des gültigen Bereichs"
-#: utils/adt/array_userfuncs.c:127 utils/adt/array_userfuncs.c:184
+#: utils/adt/array_userfuncs.c:139 utils/adt/array_userfuncs.c:196
#, c-format
msgid "argument must be empty or one-dimensional array"
msgstr "Argument muss entweder leer oder ein eindimensionales Array sein"
-#: utils/adt/array_userfuncs.c:266 utils/adt/array_userfuncs.c:305
-#: utils/adt/array_userfuncs.c:342 utils/adt/array_userfuncs.c:371
-#: utils/adt/array_userfuncs.c:399
+#: utils/adt/array_userfuncs.c:278 utils/adt/array_userfuncs.c:317
+#: utils/adt/array_userfuncs.c:354 utils/adt/array_userfuncs.c:383
+#: utils/adt/array_userfuncs.c:411
#, c-format
msgid "cannot concatenate incompatible arrays"
msgstr "inkompatible Arrays können nicht aneinandergehängt werden"
-#: utils/adt/array_userfuncs.c:267
+#: utils/adt/array_userfuncs.c:279
#, c-format
msgid "Arrays with element types %s and %s are not compatible for concatenation."
msgstr "Arrays mit Elementtypen %s und %s sind nicht kompatibel für Aneinanderhängen."
-#: utils/adt/array_userfuncs.c:306
+#: utils/adt/array_userfuncs.c:318
#, c-format
msgid "Arrays of %d and %d dimensions are not compatible for concatenation."
msgstr "Arrays mit %d und %d Dimensionen sind nicht kompatibel für Aneinanderhängen."
-#: utils/adt/array_userfuncs.c:343
+#: utils/adt/array_userfuncs.c:355
#, c-format
msgid "Arrays with differing element dimensions are not compatible for concatenation."
msgstr "Arrays mit unterschiedlichen Elementdimensionen sind nicht kompatibel für Aneinanderhängen."
-#: utils/adt/array_userfuncs.c:372 utils/adt/array_userfuncs.c:400
+#: utils/adt/array_userfuncs.c:384 utils/adt/array_userfuncs.c:412
#, c-format
msgid "Arrays with differing dimensions are not compatible for concatenation."
msgstr "Arrays mit unterschiedlichen Dimensionen sind nicht kompatibel für Aneinanderhängen."
-#: utils/adt/array_userfuncs.c:468 utils/adt/arrayfuncs.c:1284
-#: utils/adt/arrayfuncs.c:3357 utils/adt/arrayfuncs.c:5764
+#: utils/adt/array_userfuncs.c:480 utils/adt/arrayfuncs.c:1284
+#: utils/adt/arrayfuncs.c:3357 utils/adt/arrayfuncs.c:5754
#, c-format
msgid "invalid number of dimensions: %d"
msgstr "ungültige Anzahl Dimensionen: %d"
-#: utils/adt/array_userfuncs.c:725 utils/adt/array_userfuncs.c:876
+#: utils/adt/array_userfuncs.c:737 utils/adt/array_userfuncs.c:889
#, c-format
msgid "searching for elements in multidimensional arrays is not supported"
msgstr "Suche nach Elementen in mehrdimensionalen Arrays wird nicht unterstützt"
-#: utils/adt/array_userfuncs.c:749
+#: utils/adt/array_userfuncs.c:761
#, c-format
msgid "initial position must not be null"
msgstr "Startposition darf nicht NULL sein"
@@ -17811,7 +19141,7 @@ msgid "Specified array dimensions do not match array contents."
msgstr "Angegebene Array-Dimensionen stimmen nicht mit dem Array-Inhalt überein."
#: utils/adt/arrayfuncs.c:489 utils/adt/arrayfuncs.c:516
-#: utils/adt/rangetypes.c:2124 utils/adt/rangetypes.c:2132
+#: utils/adt/rangetypes.c:2114 utils/adt/rangetypes.c:2122
#: utils/adt/rowtypes.c:208 utils/adt/rowtypes.c:216
#, c-format
msgid "Unexpected end of input."
@@ -17877,11 +19207,12 @@ msgstr "Auswählen von Stücken aus Arrays mit fester Länge ist nicht implement
#: utils/adt/arrayfuncs.c:2230 utils/adt/arrayfuncs.c:2252
#: utils/adt/arrayfuncs.c:2301 utils/adt/arrayfuncs.c:2537
-#: utils/adt/arrayfuncs.c:2848 utils/adt/arrayfuncs.c:5744
-#: utils/adt/arrayfuncs.c:5776 utils/adt/arrayfuncs.c:5793
-#: utils/adt/json.c:2290 utils/adt/json.c:2365 utils/adt/jsonb.c:1369
-#: utils/adt/jsonb.c:1455 utils/adt/jsonfuncs.c:3537
-#: utils/adt/jsonfuncs.c:3582 utils/adt/jsonfuncs.c:3629
+#: utils/adt/arrayfuncs.c:2848 utils/adt/arrayfuncs.c:5740
+#: utils/adt/arrayfuncs.c:5766 utils/adt/arrayfuncs.c:5777
+#: utils/adt/json.c:2295 utils/adt/json.c:2370 utils/adt/jsonb.c:1370
+#: utils/adt/jsonb.c:1456 utils/adt/jsonfuncs.c:3465
+#: utils/adt/jsonfuncs.c:3616 utils/adt/jsonfuncs.c:3661
+#: utils/adt/jsonfuncs.c:3708
#, c-format
msgid "wrong number of array subscripts"
msgstr "falsche Anzahl Arrayindizes"
@@ -17903,15 +19234,14 @@ msgid "updates on slices of fixed-length arrays not implemented"
msgstr "Aktualisieren von Stücken aus Arrays mit fester Länge ist nicht implementiert"
#: utils/adt/arrayfuncs.c:2826
-#, fuzzy, c-format
-#| msgid "array subscript must have type integer"
+#, c-format
msgid "array slice subscript must provide both boundaries"
-msgstr "Arrayindex muss Typ integer haben"
+msgstr "Array-Slice-Index muss beide Begrenzungen angeben"
#: utils/adt/arrayfuncs.c:2827
#, c-format
msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified."
-msgstr ""
+msgstr "Wenn ein Slice eines leeren Array-Wertes zugewiesen wird, dann müssen die Slice-Begrenzungen vollständig angegeben werden."
#: utils/adt/arrayfuncs.c:2838 utils/adt/arrayfuncs.c:2933
#, c-format
@@ -17934,67 +19264,57 @@ msgstr "kann Arrays mit verschiedenen Elementtypen nicht vergleichen"
msgid "could not identify a hash function for type %s"
msgstr "konnte keine Hash-Funktion für Typ %s ermitteln"
-#: utils/adt/arrayfuncs.c:5156
+#: utils/adt/arrayfuncs.c:5154
#, c-format
msgid "data type %s is not an array type"
msgstr "Datentyp %s ist kein Array-Typ"
-#: utils/adt/arrayfuncs.c:5213
+#: utils/adt/arrayfuncs.c:5209
#, c-format
msgid "cannot accumulate null arrays"
msgstr "Arrays, die NULL sind, können nicht akkumuliert werden"
-#: utils/adt/arrayfuncs.c:5241
+#: utils/adt/arrayfuncs.c:5237
#, c-format
msgid "cannot accumulate empty arrays"
msgstr "leere Arrays können nicht akkumuliert werden"
-#: utils/adt/arrayfuncs.c:5270 utils/adt/arrayfuncs.c:5276
+#: utils/adt/arrayfuncs.c:5266 utils/adt/arrayfuncs.c:5272
#, c-format
msgid "cannot accumulate arrays of different dimensionality"
msgstr "Arrays unterschiedlicher Dimensionalität können nicht akkumuliert werden"
-#: utils/adt/arrayfuncs.c:5642 utils/adt/arrayfuncs.c:5682
+#: utils/adt/arrayfuncs.c:5638 utils/adt/arrayfuncs.c:5678
#, c-format
msgid "dimension array or low bound array cannot be null"
msgstr "Dimensions-Array oder Untergrenzen-Array darf nicht NULL sein"
-#: utils/adt/arrayfuncs.c:5745 utils/adt/arrayfuncs.c:5777
+#: utils/adt/arrayfuncs.c:5741 utils/adt/arrayfuncs.c:5767
#, c-format
msgid "Dimension array must be one dimensional."
msgstr "Dimensions-Array muss eindimensional sein."
-#: utils/adt/arrayfuncs.c:5750 utils/adt/arrayfuncs.c:5782
-#, c-format
-msgid "wrong range of array subscripts"
-msgstr "falscher Bereich der Arrayindizes"
-
-#: utils/adt/arrayfuncs.c:5751 utils/adt/arrayfuncs.c:5783
-#, c-format
-msgid "Lower bound of dimension array must be one."
-msgstr "Untergrenze des Dimensions-Arrays muss eins sein."
-
-#: utils/adt/arrayfuncs.c:5756 utils/adt/arrayfuncs.c:5788
+#: utils/adt/arrayfuncs.c:5746 utils/adt/arrayfuncs.c:5772
#, c-format
msgid "dimension values cannot be null"
msgstr "Dimensionswerte dürfen nicht NULL sein"
-#: utils/adt/arrayfuncs.c:5794
+#: utils/adt/arrayfuncs.c:5778
#, c-format
msgid "Low bound array has different size than dimensions array."
msgstr "Untergrenzen-Array hat andere Größe als Dimensions-Array."
-#: utils/adt/arrayfuncs.c:6040
+#: utils/adt/arrayfuncs.c:6024
#, c-format
msgid "removing elements from multidimensional arrays is not supported"
msgstr "Entfernen von Elementen aus mehrdimensionalen Arrays wird nicht unterstützt"
-#: utils/adt/arrayfuncs.c:6317
+#: utils/adt/arrayfuncs.c:6301
#, c-format
msgid "thresholds must be one-dimensional array"
msgstr "Parameter »thresholds« muss ein eindimensionales Array sein"
-#: utils/adt/arrayfuncs.c:6322
+#: utils/adt/arrayfuncs.c:6306
#, c-format
msgid "thresholds array must not contain NULLs"
msgstr "»thresholds«-Array darf keine NULL-Werte enthalten"
@@ -18014,31 +19334,48 @@ msgstr "Typmod-Arrays müssen eindimensional sein"
msgid "typmod array must not contain nulls"
msgstr "Typmod-Array darf keine NULL-Werte enthalten"
-#: utils/adt/ascii.c:75
+#: utils/adt/ascii.c:76
#, c-format
msgid "encoding conversion from %s to ASCII not supported"
msgstr "Kodierungsumwandlung zwischen %s und ASCII wird nicht unterstützt"
-#: utils/adt/bool.c:153
+#. translator: first %s is inet or cidr
+#: utils/adt/bool.c:153 utils/adt/cash.c:278 utils/adt/datetime.c:3799
+#: utils/adt/float.c:244 utils/adt/float.c:318 utils/adt/float.c:342
+#: utils/adt/float.c:461 utils/adt/float.c:544 utils/adt/float.c:570
+#: utils/adt/geo_ops.c:156 utils/adt/geo_ops.c:166 utils/adt/geo_ops.c:178
+#: utils/adt/geo_ops.c:210 utils/adt/geo_ops.c:255 utils/adt/geo_ops.c:265
+#: utils/adt/geo_ops.c:935 utils/adt/geo_ops.c:1321 utils/adt/geo_ops.c:1356
+#: utils/adt/geo_ops.c:1364 utils/adt/geo_ops.c:3430 utils/adt/geo_ops.c:4563
+#: utils/adt/geo_ops.c:4579 utils/adt/geo_ops.c:4586 utils/adt/mac.c:68
+#: utils/adt/nabstime.c:1539 utils/adt/network.c:58 utils/adt/numeric.c:593
+#: utils/adt/numeric.c:620 utils/adt/numeric.c:5488 utils/adt/numeric.c:5512
+#: utils/adt/numeric.c:5536 utils/adt/numeric.c:6338 utils/adt/numeric.c:6364
+#: utils/adt/oid.c:44 utils/adt/oid.c:58 utils/adt/oid.c:64 utils/adt/oid.c:86
+#: utils/adt/pg_lsn.c:44 utils/adt/pg_lsn.c:50 utils/adt/tid.c:72
+#: utils/adt/tid.c:80 utils/adt/tid.c:88 utils/adt/txid.c:339
+#: utils/adt/uuid.c:136
#, c-format
-msgid "invalid input syntax for type boolean: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ boolean: »%s«"
+msgid "invalid input syntax for type %s: \"%s\""
+msgstr "ungültige Eingabesyntax für Typ %s: »%s«"
-#: utils/adt/cash.c:246
+#: utils/adt/cash.c:211 utils/adt/cash.c:238 utils/adt/cash.c:249
+#: utils/adt/cash.c:290 utils/adt/int8.c:114 utils/adt/numutils.c:75
+#: utils/adt/numutils.c:82 utils/adt/oid.c:70 utils/adt/oid.c:109
#, c-format
-msgid "invalid input syntax for type money: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ money: »%s«"
+msgid "value \"%s\" is out of range for type %s"
+msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für Typ %s"
-#: utils/adt/cash.c:607 utils/adt/cash.c:657 utils/adt/cash.c:708
-#: utils/adt/cash.c:757 utils/adt/cash.c:809 utils/adt/cash.c:859
+#: utils/adt/cash.c:651 utils/adt/cash.c:701 utils/adt/cash.c:752
+#: utils/adt/cash.c:801 utils/adt/cash.c:853 utils/adt/cash.c:903
#: utils/adt/float.c:855 utils/adt/float.c:919 utils/adt/float.c:3315
-#: utils/adt/float.c:3378 utils/adt/geo_ops.c:4093 utils/adt/int.c:719
-#: utils/adt/int.c:861 utils/adt/int.c:969 utils/adt/int.c:1058
-#: utils/adt/int.c:1097 utils/adt/int.c:1125 utils/adt/int8.c:597
+#: utils/adt/float.c:3378 utils/adt/geo_ops.c:4093 utils/adt/int.c:704
+#: utils/adt/int.c:846 utils/adt/int.c:954 utils/adt/int.c:1043
+#: utils/adt/int.c:1082 utils/adt/int.c:1110 utils/adt/int8.c:597
#: utils/adt/int8.c:657 utils/adt/int8.c:897 utils/adt/int8.c:1005
-#: utils/adt/int8.c:1094 utils/adt/int8.c:1202 utils/adt/numeric.c:6815
-#: utils/adt/numeric.c:7104 utils/adt/numeric.c:8117
-#: utils/adt/timestamp.c:3446
+#: utils/adt/int8.c:1094 utils/adt/int8.c:1202 utils/adt/numeric.c:6902
+#: utils/adt/numeric.c:7191 utils/adt/numeric.c:8204
+#: utils/adt/timestamp.c:3186
#, c-format
msgid "division by zero"
msgstr "Division durch Null"
@@ -18048,179 +19385,162 @@ msgstr "Division durch Null"
msgid "\"char\" out of range"
msgstr "\"char\" ist außerhalb des gültigen Bereichs"
-#: utils/adt/date.c:67 utils/adt/timestamp.c:94 utils/adt/varbit.c:52
-#: utils/adt/varchar.c:45
+#: utils/adt/date.c:67 utils/adt/timestamp.c:94 utils/adt/varbit.c:53
+#: utils/adt/varchar.c:46
#, c-format
msgid "invalid type modifier"
msgstr "ungültige Typmodifikation"
-#: utils/adt/date.c:72
+#: utils/adt/date.c:79
#, c-format
msgid "TIME(%d)%s precision must not be negative"
msgstr "Präzision von TIME(%d)%s darf nicht negativ sein"
-#: utils/adt/date.c:78
+#: utils/adt/date.c:85
#, c-format
msgid "TIME(%d)%s precision reduced to maximum allowed, %d"
msgstr "Präzision von TIME(%d)%s auf erlaubten Höchstwert %d reduziert"
-#: utils/adt/date.c:141 utils/adt/datetime.c:1277 utils/adt/datetime.c:2148
+#: utils/adt/date.c:146 utils/adt/datetime.c:1209 utils/adt/datetime.c:2117
#, c-format
msgid "date/time value \"current\" is no longer supported"
msgstr "Datum/Zeitwert »current« wird nicht mehr unterstützt"
-#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:3529
-#: utils/adt/formatting.c:3538
+#: utils/adt/date.c:172 utils/adt/date.c:180 utils/adt/formatting.c:3523
+#: utils/adt/formatting.c:3532
#, c-format
msgid "date out of range: \"%s\""
msgstr "date ist außerhalb des gültigen Bereichs: »%s«"
-#: utils/adt/date.c:222 utils/adt/date.c:456 utils/adt/date.c:480
-#: utils/adt/xml.c:2029
+#: utils/adt/date.c:227 utils/adt/date.c:539 utils/adt/date.c:563
+#: utils/adt/xml.c:2086
#, c-format
msgid "date out of range"
msgstr "date ist außerhalb des gültigen Bereichs"
-#: utils/adt/date.c:264 utils/adt/timestamp.c:593
+#: utils/adt/date.c:273 utils/adt/timestamp.c:563
#, c-format
msgid "date field value out of range: %d-%02d-%02d"
msgstr "Datum-Feldwert ist außerhalb des gültigen Bereichs: %d-%02d-%02d"
-#: utils/adt/date.c:271 utils/adt/date.c:280 utils/adt/timestamp.c:599
+#: utils/adt/date.c:280 utils/adt/date.c:289 utils/adt/timestamp.c:569
#, c-format
msgid "date out of range: %d-%02d-%02d"
msgstr "date ist außerhalb des gültigen Bereichs: %d-%02d-%02d"
-#: utils/adt/date.c:431
+#: utils/adt/date.c:327 utils/adt/date.c:350 utils/adt/date.c:376
+#: utils/adt/date.c:1092 utils/adt/date.c:1138 utils/adt/date.c:1672
+#: utils/adt/date.c:1703 utils/adt/date.c:1732 utils/adt/date.c:2469
+#: utils/adt/datetime.c:1690 utils/adt/formatting.c:3398
+#: utils/adt/formatting.c:3430 utils/adt/formatting.c:3498
+#: utils/adt/json.c:1539 utils/adt/json.c:1561 utils/adt/jsonb.c:824
+#: utils/adt/jsonb.c:848 utils/adt/nabstime.c:456 utils/adt/nabstime.c:499
+#: utils/adt/nabstime.c:529 utils/adt/nabstime.c:572 utils/adt/timestamp.c:229
+#: utils/adt/timestamp.c:261 utils/adt/timestamp.c:691
+#: utils/adt/timestamp.c:700 utils/adt/timestamp.c:778
+#: utils/adt/timestamp.c:811 utils/adt/timestamp.c:2765
+#: utils/adt/timestamp.c:2786 utils/adt/timestamp.c:2799
+#: utils/adt/timestamp.c:2808 utils/adt/timestamp.c:2816
+#: utils/adt/timestamp.c:2871 utils/adt/timestamp.c:2894
+#: utils/adt/timestamp.c:2907 utils/adt/timestamp.c:2918
+#: utils/adt/timestamp.c:2926 utils/adt/timestamp.c:3482
+#: utils/adt/timestamp.c:3607 utils/adt/timestamp.c:3648
+#: utils/adt/timestamp.c:3729 utils/adt/timestamp.c:3775
+#: utils/adt/timestamp.c:3878 utils/adt/timestamp.c:4277
+#: utils/adt/timestamp.c:4376 utils/adt/timestamp.c:4386
+#: utils/adt/timestamp.c:4478 utils/adt/timestamp.c:4580
+#: utils/adt/timestamp.c:4590 utils/adt/timestamp.c:4822
+#: utils/adt/timestamp.c:4836 utils/adt/timestamp.c:4841
+#: utils/adt/timestamp.c:4855 utils/adt/timestamp.c:4900
+#: utils/adt/timestamp.c:4932 utils/adt/timestamp.c:4939
+#: utils/adt/timestamp.c:4972 utils/adt/timestamp.c:4976
+#: utils/adt/timestamp.c:5045 utils/adt/timestamp.c:5049
+#: utils/adt/timestamp.c:5063 utils/adt/timestamp.c:5097 utils/adt/xml.c:2108
+#: utils/adt/xml.c:2115 utils/adt/xml.c:2135 utils/adt/xml.c:2142
+#, c-format
+msgid "timestamp out of range"
+msgstr "timestamp ist außerhalb des gültigen Bereichs"
+
+#: utils/adt/date.c:514
#, c-format
msgid "cannot subtract infinite dates"
msgstr "kann unendliche date-Werte nicht subtrahieren"
-#: utils/adt/date.c:509 utils/adt/date.c:544 utils/adt/date.c:566
-#: utils/adt/date.c:2629 utils/adt/date.c:2643
+#: utils/adt/date.c:592 utils/adt/date.c:623 utils/adt/date.c:641
+#: utils/adt/date.c:2506 utils/adt/date.c:2516
#, c-format
msgid "date out of range for timestamp"
msgstr "Datum ist außerhalb des gültigen Bereichs für Typ »timestamp«"
-#: utils/adt/date.c:1022 utils/adt/date.c:1068 utils/adt/date.c:1678
-#: utils/adt/date.c:1714 utils/adt/date.c:1748 utils/adt/date.c:2592
-#: utils/adt/formatting.c:3404 utils/adt/formatting.c:3436
-#: utils/adt/formatting.c:3504 utils/adt/json.c:1534 utils/adt/json.c:1556
-#: utils/adt/jsonb.c:823 utils/adt/jsonb.c:847 utils/adt/nabstime.c:455
-#: utils/adt/nabstime.c:498 utils/adt/nabstime.c:528 utils/adt/nabstime.c:571
-#: utils/adt/timestamp.c:224 utils/adt/timestamp.c:268
-#: utils/adt/timestamp.c:726 utils/adt/timestamp.c:735
-#: utils/adt/timestamp.c:820 utils/adt/timestamp.c:860
-#: utils/adt/timestamp.c:3021 utils/adt/timestamp.c:3042
-#: utils/adt/timestamp.c:3055 utils/adt/timestamp.c:3064
-#: utils/adt/timestamp.c:3072 utils/adt/timestamp.c:3127
-#: utils/adt/timestamp.c:3150 utils/adt/timestamp.c:3163
-#: utils/adt/timestamp.c:3174 utils/adt/timestamp.c:3182
-#: utils/adt/timestamp.c:3756 utils/adt/timestamp.c:3885
-#: utils/adt/timestamp.c:3926 utils/adt/timestamp.c:4014
-#: utils/adt/timestamp.c:4060 utils/adt/timestamp.c:4171
-#: utils/adt/timestamp.c:4578 utils/adt/timestamp.c:4694
-#: utils/adt/timestamp.c:4704 utils/adt/timestamp.c:4800
-#: utils/adt/timestamp.c:4919 utils/adt/timestamp.c:4929
-#: utils/adt/timestamp.c:5250 utils/adt/timestamp.c:5264
-#: utils/adt/timestamp.c:5269 utils/adt/timestamp.c:5283
-#: utils/adt/timestamp.c:5366 utils/adt/timestamp.c:5398
-#: utils/adt/timestamp.c:5405 utils/adt/timestamp.c:5431
-#: utils/adt/timestamp.c:5435 utils/adt/timestamp.c:5504
-#: utils/adt/timestamp.c:5508 utils/adt/timestamp.c:5522
-#: utils/adt/timestamp.c:5560 utils/adt/xml.c:2051 utils/adt/xml.c:2058
-#: utils/adt/xml.c:2078 utils/adt/xml.c:2085
-#, c-format
-msgid "timestamp out of range"
-msgstr "timestamp ist außerhalb des gültigen Bereichs"
-
-#: utils/adt/date.c:1094
+#: utils/adt/date.c:1164
#, c-format
msgid "cannot convert reserved abstime value to date"
msgstr "kann reservierten »abstime«-Wert nicht in »date« umwandeln"
-#: utils/adt/date.c:1112 utils/adt/date.c:1118
+#: utils/adt/date.c:1182 utils/adt/date.c:1188
#, c-format
msgid "abstime out of range for date"
msgstr "abstime ist außerhalb des gültigen Bereichs für Typ »date«"
-#: utils/adt/date.c:1258 utils/adt/date.c:1265 utils/adt/date.c:2082
-#: utils/adt/date.c:2089
+#: utils/adt/date.c:1301 utils/adt/date.c:2020
#, c-format
msgid "time out of range"
msgstr "time ist außerhalb des gültigen Bereichs"
-#: utils/adt/date.c:1326 utils/adt/timestamp.c:618
+#: utils/adt/date.c:1357 utils/adt/timestamp.c:588
#, c-format
msgid "time field value out of range: %d:%02d:%02g"
msgstr "Zeit-Feldwert ist außerhalb des gültigen Bereichs: %d:%02d:%02g"
-#: utils/adt/date.c:1960 utils/adt/date.c:1977
+#: utils/adt/date.c:1907 utils/adt/date.c:1920
#, c-format
msgid "\"time\" units \"%s\" not recognized"
msgstr "»time«-Einheit »%s« nicht erkannt"
-#: utils/adt/date.c:2098
+#: utils/adt/date.c:2028
#, c-format
msgid "time zone displacement out of range"
msgstr "Zeitzonenunterschied ist außerhalb des gültigen Bereichs"
-#: utils/adt/date.c:2740 utils/adt/date.c:2757
+#: utils/adt/date.c:2601 utils/adt/date.c:2614
#, c-format
msgid "\"time with time zone\" units \"%s\" not recognized"
msgstr "»time with time zone«-Einheit »%s« nicht erkannt"
-#: utils/adt/date.c:2830 utils/adt/datetime.c:994 utils/adt/datetime.c:1874
-#: utils/adt/datetime.c:4700 utils/adt/timestamp.c:532
-#: utils/adt/timestamp.c:559 utils/adt/timestamp.c:5275
-#: utils/adt/timestamp.c:5514
+#: utils/adt/date.c:2687 utils/adt/datetime.c:931 utils/adt/datetime.c:1848
+#: utils/adt/datetime.c:4636 utils/adt/timestamp.c:502
+#: utils/adt/timestamp.c:529 utils/adt/timestamp.c:4847
+#: utils/adt/timestamp.c:5055
#, c-format
msgid "time zone \"%s\" not recognized"
msgstr "Zeitzone »%s« nicht erkannt"
-#: utils/adt/date.c:2870 utils/adt/timestamp.c:5351 utils/adt/timestamp.c:5545
+#: utils/adt/date.c:2719 utils/adt/timestamp.c:4889 utils/adt/timestamp.c:5086
#, c-format
msgid "interval time zone \"%s\" must not include months or days"
msgstr "Intervall-Zeitzone »%s« darf keine Monate oder Tage enthalten"
-#: utils/adt/datetime.c:1749
-#, c-format
-msgid "time zone abbreviation \"%s\" is not used in time zone \"%s\""
-msgstr "Zeitzonenabkürzung »%s« wird in Zeitzone »%s« nicht verwendet"
-
-#: utils/adt/datetime.c:3835 utils/adt/datetime.c:3842
+#: utils/adt/datetime.c:3772 utils/adt/datetime.c:3779
#, c-format
msgid "date/time field value out of range: \"%s\""
msgstr "Datum/Zeit-Feldwert ist außerhalb des gültigen Bereichs: »%s«"
-#: utils/adt/datetime.c:3844
+#: utils/adt/datetime.c:3781
#, c-format
msgid "Perhaps you need a different \"datestyle\" setting."
msgstr "Möglicherweise benötigen Sie eine andere »datestyle«-Einstellung."
-#: utils/adt/datetime.c:3849
+#: utils/adt/datetime.c:3786
#, c-format
msgid "interval field value out of range: \"%s\""
msgstr "»interval«-Feldwert ist außerhalb des gültigen Bereichs: »%s«"
-#: utils/adt/datetime.c:3855
+#: utils/adt/datetime.c:3792
#, c-format
msgid "time zone displacement out of range: \"%s\""
msgstr "Zeitzonenunterschied ist außerhalb des gültigen Bereichs: »%s«"
-#. translator: first %s is inet or cidr
-#: utils/adt/datetime.c:3862 utils/adt/float.c:461 utils/adt/float.c:544
-#: utils/adt/float.c:570 utils/adt/geo_ops.c:156 utils/adt/geo_ops.c:166
-#: utils/adt/geo_ops.c:178 utils/adt/geo_ops.c:210 utils/adt/geo_ops.c:255
-#: utils/adt/geo_ops.c:265 utils/adt/geo_ops.c:935 utils/adt/geo_ops.c:1321
-#: utils/adt/geo_ops.c:1356 utils/adt/geo_ops.c:1364 utils/adt/geo_ops.c:3430
-#: utils/adt/geo_ops.c:4563 utils/adt/geo_ops.c:4579 utils/adt/geo_ops.c:4586
-#: utils/adt/network.c:58
-#, c-format
-msgid "invalid input syntax for type %s: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ %s: »%s«"
-
-#: utils/adt/datetime.c:4702
+#: utils/adt/datetime.c:4638
#, c-format
msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"."
msgstr "Dieser Zeitzonenname erscheint in der Konfigurationsdatei für Zeitzonenabkürzung »%s«."
@@ -18230,27 +19550,27 @@ msgstr "Dieser Zeitzonenname erscheint in der Konfigurationsdatei für Zeitzonen
msgid "invalid Datum pointer"
msgstr "ungültiger »Datum«-Zeiger"
-#: utils/adt/dbsize.c:110
+#: utils/adt/dbsize.c:109
#, c-format
msgid "could not open tablespace directory \"%s\": %m"
msgstr "konnte Tablespace-Verzeichnis »%s« nicht öffnen: %m"
-#: utils/adt/dbsize.c:757 utils/adt/dbsize.c:776 utils/adt/dbsize.c:831
+#: utils/adt/dbsize.c:756 utils/adt/dbsize.c:824
#, c-format
msgid "invalid size: \"%s\""
msgstr "ungültige Größe: »%s«"
-#: utils/adt/dbsize.c:832
+#: utils/adt/dbsize.c:825
#, c-format
msgid "Invalid size unit: \"%s\"."
msgstr "Ungültige Größeneinheit: »%s«."
-#: utils/adt/dbsize.c:833
+#: utils/adt/dbsize.c:826
#, c-format
msgid "Valid units are \"bytes\", \"kB\", \"MB\", \"GB\", and \"TB\"."
msgstr "Gültige Einheiten sind »kB«, »MB«, »GB« und »TB«."
-#: utils/adt/domains.c:85
+#: utils/adt/domains.c:91
#, c-format
msgid "type %s is not a domain"
msgstr "Typ %s ist keine Domäne"
@@ -18290,30 +19610,47 @@ msgstr "ungültige Base64-Endsequenz"
msgid "Input data is missing padding, is truncated, or is otherwise corrupted."
msgstr "Die Eingabedaten haben fehlendes Padding, sind zu kurz oder sind anderweitig verfälscht."
-#: utils/adt/encode.c:442 utils/adt/encode.c:507 utils/adt/varlena.c:297
-#: utils/adt/varlena.c:338
+#: utils/adt/encode.c:442 utils/adt/encode.c:507 utils/adt/json.c:785
+#: utils/adt/json.c:825 utils/adt/json.c:841 utils/adt/json.c:853
+#: utils/adt/json.c:863 utils/adt/json.c:914 utils/adt/json.c:946
+#: utils/adt/json.c:965 utils/adt/json.c:977 utils/adt/json.c:989
+#: utils/adt/json.c:1134 utils/adt/json.c:1148 utils/adt/json.c:1159
+#: utils/adt/json.c:1167 utils/adt/json.c:1175 utils/adt/json.c:1183
+#: utils/adt/json.c:1191 utils/adt/json.c:1199 utils/adt/json.c:1207
+#: utils/adt/json.c:1215 utils/adt/json.c:1245 utils/adt/varlena.c:298
+#: utils/adt/varlena.c:339
#, c-format
-msgid "invalid input syntax for type bytea"
-msgstr "ungültige Eingabesyntax für Typ bytea"
+msgid "invalid input syntax for type %s"
+msgstr "ungültige Eingabesyntax für Typ %s"
+
+#: utils/adt/enum.c:115
+#, c-format
+msgid "unsafe use of new value \"%s\" of enum type %s"
+msgstr ""
-#: utils/adt/enum.c:48 utils/adt/enum.c:58 utils/adt/enum.c:113
-#: utils/adt/enum.c:123
+#: utils/adt/enum.c:118
+#, c-format
+msgid "New enum values must be committed before they can be used."
+msgstr ""
+
+#: utils/adt/enum.c:136 utils/adt/enum.c:146 utils/adt/enum.c:204
+#: utils/adt/enum.c:214
#, c-format
msgid "invalid input value for enum %s: \"%s\""
msgstr "ungültiger Eingabewert für Enum %s: »%s«"
-#: utils/adt/enum.c:85 utils/adt/enum.c:148 utils/adt/enum.c:198
+#: utils/adt/enum.c:176 utils/adt/enum.c:242 utils/adt/enum.c:301
#, c-format
msgid "invalid internal value for enum: %u"
msgstr "ungültiger interner Wert für Enum: %u"
-#: utils/adt/enum.c:356 utils/adt/enum.c:385 utils/adt/enum.c:425
-#: utils/adt/enum.c:445
+#: utils/adt/enum.c:461 utils/adt/enum.c:490 utils/adt/enum.c:530
+#: utils/adt/enum.c:550
#, c-format
msgid "could not determine actual enum type"
msgstr "konnte tatsächlichen Enum-Typen nicht bestimmen"
-#: utils/adt/enum.c:364 utils/adt/enum.c:393
+#: utils/adt/enum.c:469 utils/adt/enum.c:498
#, c-format
msgid "enum %s contains no values"
msgstr "Enum %s enthält keine Werte"
@@ -18328,11 +19665,6 @@ msgstr "Wert ist außerhalb des gültigen Bereichs: Überlauf"
msgid "value out of range: underflow"
msgstr "Wert ist außerhalb des gültigen Bereichs: Unterlauf"
-#: utils/adt/float.c:244 utils/adt/float.c:318 utils/adt/float.c:342
-#, c-format
-msgid "invalid input syntax for type real: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ real: »%s«"
-
#: utils/adt/float.c:312
#, c-format
msgid "\"%s\" is out of range for type real"
@@ -18343,35 +19675,35 @@ msgstr "»%s« ist außerhalb des gültigen Bereichs für Typ real"
msgid "\"%s\" is out of range for type double precision"
msgstr "»%s« ist außerhalb des gültigen Bereichs für Typ double precision"
-#: utils/adt/float.c:1246 utils/adt/float.c:1304 utils/adt/int.c:349
-#: utils/adt/int.c:775 utils/adt/int.c:804 utils/adt/int.c:825
-#: utils/adt/int.c:845 utils/adt/int.c:879 utils/adt/int.c:1174
-#: utils/adt/int8.c:1323 utils/adt/numeric.c:3004 utils/adt/numeric.c:3013
+#: utils/adt/float.c:1246 utils/adt/float.c:1304 utils/adt/int.c:334
+#: utils/adt/int.c:760 utils/adt/int.c:789 utils/adt/int.c:810
+#: utils/adt/int.c:830 utils/adt/int.c:864 utils/adt/int.c:1159
+#: utils/adt/int8.c:1323 utils/adt/numeric.c:3050 utils/adt/numeric.c:3059
#, c-format
msgid "smallint out of range"
msgstr "smallint ist außerhalb des gültigen Bereichs"
-#: utils/adt/float.c:1430 utils/adt/numeric.c:7537
+#: utils/adt/float.c:1430 utils/adt/numeric.c:7624
#, c-format
msgid "cannot take square root of a negative number"
msgstr "Quadratwurzel von negativer Zahl kann nicht ermittelt werden"
-#: utils/adt/float.c:1472 utils/adt/numeric.c:2807
+#: utils/adt/float.c:1472 utils/adt/numeric.c:2853
#, c-format
msgid "zero raised to a negative power is undefined"
msgstr "null hoch eine negative Zahl ist undefiniert"
-#: utils/adt/float.c:1476 utils/adt/numeric.c:2813
+#: utils/adt/float.c:1476 utils/adt/numeric.c:2859
#, c-format
msgid "a negative number raised to a non-integer power yields a complex result"
msgstr "eine negative Zahl hoch eine nicht ganze Zahl ergibt ein komplexes Ergebnis"
-#: utils/adt/float.c:1542 utils/adt/float.c:1572 utils/adt/numeric.c:7803
+#: utils/adt/float.c:1542 utils/adt/float.c:1572 utils/adt/numeric.c:7890
#, c-format
msgid "cannot take logarithm of zero"
msgstr "Logarithmus von null kann nicht ermittelt werden"
-#: utils/adt/float.c:1546 utils/adt/float.c:1576 utils/adt/numeric.c:7807
+#: utils/adt/float.c:1546 utils/adt/float.c:1576 utils/adt/numeric.c:7894
#, c-format
msgid "cannot take logarithm of a negative number"
msgstr "Logarithmus negativer Zahlen kann nicht ermittelt werden"
@@ -18384,12 +19716,12 @@ msgstr "Logarithmus negativer Zahlen kann nicht ermittelt werden"
msgid "input is out of range"
msgstr "Eingabe ist außerhalb des gültigen Bereichs"
-#: utils/adt/float.c:3532 utils/adt/numeric.c:1447
+#: utils/adt/float.c:3532 utils/adt/numeric.c:1493
#, c-format
msgid "count must be greater than zero"
msgstr "Anzahl muss größer als null sein"
-#: utils/adt/float.c:3537 utils/adt/numeric.c:1454
+#: utils/adt/float.c:3537 utils/adt/numeric.c:1500
#, c-format
msgid "operand, lower bound, and upper bound cannot be NaN"
msgstr "Operand, Untergrenze und Obergrenze dürfen nicht NaN sein"
@@ -18399,218 +19731,219 @@ msgstr "Operand, Untergrenze und Obergrenze dürfen nicht NaN sein"
msgid "lower and upper bounds must be finite"
msgstr "Untergrenze und Obergrenze müssen endlich sein"
-#: utils/adt/float.c:3581 utils/adt/numeric.c:1467
+#: utils/adt/float.c:3581 utils/adt/numeric.c:1513
#, c-format
msgid "lower bound cannot equal upper bound"
msgstr "Untergrenze kann nicht gleich der Obergrenze sein"
-#: utils/adt/formatting.c:485
+#: utils/adt/formatting.c:489
#, c-format
msgid "invalid format specification for an interval value"
msgstr "ungültige Formatangabe für Intervall-Wert"
-#: utils/adt/formatting.c:486
+#: utils/adt/formatting.c:490
#, c-format
msgid "Intervals are not tied to specific calendar dates."
msgstr "Intervalle beziehen sich nicht auf bestimmte Kalenderdaten."
-#: utils/adt/formatting.c:1058
+#: utils/adt/formatting.c:1056
#, c-format
msgid "\"EEEE\" must be the last pattern used"
msgstr "»EEEE« muss das letzte Muster sein"
-#: utils/adt/formatting.c:1066
+#: utils/adt/formatting.c:1064
#, c-format
msgid "\"9\" must be ahead of \"PR\""
msgstr "»9« muss vor »PR« stehen"
-#: utils/adt/formatting.c:1082
+#: utils/adt/formatting.c:1080
#, c-format
msgid "\"0\" must be ahead of \"PR\""
msgstr "»0« muss vor »PR« stehen"
-#: utils/adt/formatting.c:1109
+#: utils/adt/formatting.c:1107
#, c-format
msgid "multiple decimal points"
msgstr "mehrere Dezimalpunkte"
-#: utils/adt/formatting.c:1113 utils/adt/formatting.c:1196
+#: utils/adt/formatting.c:1111 utils/adt/formatting.c:1194
#, c-format
msgid "cannot use \"V\" and decimal point together"
msgstr "»V« und Dezimalpunkt können nicht zusammen verwendet werden"
-#: utils/adt/formatting.c:1125
+#: utils/adt/formatting.c:1123
#, c-format
msgid "cannot use \"S\" twice"
msgstr "»S« kann nicht zweimal verwendet werden"
-#: utils/adt/formatting.c:1129
+#: utils/adt/formatting.c:1127
#, c-format
msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together"
msgstr "»S« und »PL«/»MI«/»SG«/»PR« können nicht zusammen verwendet werden"
-#: utils/adt/formatting.c:1149
+#: utils/adt/formatting.c:1147
#, c-format
msgid "cannot use \"S\" and \"MI\" together"
msgstr "»S« und »MI« können nicht zusammen verwendet werden"
-#: utils/adt/formatting.c:1159
+#: utils/adt/formatting.c:1157
#, c-format
msgid "cannot use \"S\" and \"PL\" together"
msgstr "»S« und »PL« können nicht zusammen verwendet werden"
-#: utils/adt/formatting.c:1169
+#: utils/adt/formatting.c:1167
#, c-format
msgid "cannot use \"S\" and \"SG\" together"
msgstr "»S« und »SG« können nicht zusammen verwendet werden"
-#: utils/adt/formatting.c:1178
+#: utils/adt/formatting.c:1176
#, c-format
msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together"
msgstr "»PR« und »S«/»PL«/»MI«/»SG« können nicht zusammen verwendet werden"
-#: utils/adt/formatting.c:1204
+#: utils/adt/formatting.c:1202
#, c-format
msgid "cannot use \"EEEE\" twice"
msgstr "»EEEE« kann nicht zweimal verwendet werden"
-#: utils/adt/formatting.c:1210
+#: utils/adt/formatting.c:1208
#, c-format
msgid "\"EEEE\" is incompatible with other formats"
msgstr "»EEEE« ist mit anderen Formaten inkompatibel"
-#: utils/adt/formatting.c:1211
+#: utils/adt/formatting.c:1209
#, c-format
msgid "\"EEEE\" may only be used together with digit and decimal point patterns."
msgstr "»EEEE« kann nur zusammen mit Platzhaltern für Ziffern oder Dezimalpunkt verwendet werden."
-#: utils/adt/formatting.c:1411
+#: utils/adt/formatting.c:1398
#, c-format
msgid "\"%s\" is not a number"
msgstr "»%s« ist keine Zahl"
-#: utils/adt/formatting.c:1512 utils/adt/formatting.c:1564
+#: utils/adt/formatting.c:1499 utils/adt/formatting.c:1551
#, c-format
msgid "could not determine which collation to use for lower() function"
msgstr "konnte die für die Funktion lower() zu verwendende Sortierfolge nicht bestimmen"
-#: utils/adt/formatting.c:1632 utils/adt/formatting.c:1684
+#: utils/adt/formatting.c:1619 utils/adt/formatting.c:1671
#, c-format
msgid "could not determine which collation to use for upper() function"
msgstr "konnte die für die Funktion upper() zu verwendende Sortierfolge nicht bestimmen"
-#: utils/adt/formatting.c:1753 utils/adt/formatting.c:1817
+#: utils/adt/formatting.c:1740 utils/adt/formatting.c:1804
#, c-format
msgid "could not determine which collation to use for initcap() function"
msgstr "konnte die für die Funktion initcap() zu verwendende Sortierfolge nicht bestimmen"
-#: utils/adt/formatting.c:2114
+#: utils/adt/formatting.c:2101
#, c-format
msgid "invalid combination of date conventions"
msgstr "ungültige Kombination von Datumskonventionen"
-#: utils/adt/formatting.c:2115
+#: utils/adt/formatting.c:2102
#, c-format
msgid "Do not mix Gregorian and ISO week date conventions in a formatting template."
msgstr "Die Gregorianische und die ISO-Konvention für Wochendaten können nicht einer Formatvorlage gemischt werden."
-#: utils/adt/formatting.c:2132
+#: utils/adt/formatting.c:2119
#, c-format
msgid "conflicting values for \"%s\" field in formatting string"
msgstr "widersprüchliche Werte für das Feld »%s« in Formatzeichenkette"
-#: utils/adt/formatting.c:2134
+#: utils/adt/formatting.c:2121
#, c-format
msgid "This value contradicts a previous setting for the same field type."
msgstr "Der Wert widerspricht einer vorherigen Einstellung für den selben Feldtyp."
-#: utils/adt/formatting.c:2195
+#: utils/adt/formatting.c:2182
#, c-format
msgid "source string too short for \"%s\" formatting field"
msgstr "Quellzeichenkette zu kurz für Formatfeld »%s»"
-#: utils/adt/formatting.c:2197
+#: utils/adt/formatting.c:2184
#, c-format
msgid "Field requires %d characters, but only %d remain."
msgstr "Feld benötigt %d Zeichen, aber nur %d verbleiben."
-#: utils/adt/formatting.c:2200 utils/adt/formatting.c:2214
+#: utils/adt/formatting.c:2187 utils/adt/formatting.c:2201
#, c-format
msgid "If your source string is not fixed-width, try using the \"FM\" modifier."
msgstr "Wenn die Quellzeichenkette keine feste Breite hat, versuchen Sie den Modifikator »FM«."
-#: utils/adt/formatting.c:2210 utils/adt/formatting.c:2223
-#: utils/adt/formatting.c:2353
+#: utils/adt/formatting.c:2197 utils/adt/formatting.c:2210
+#: utils/adt/formatting.c:2340
#, c-format
msgid "invalid value \"%s\" for \"%s\""
msgstr "ungültiger Wert »%s« für »%s«"
-#: utils/adt/formatting.c:2212
+#: utils/adt/formatting.c:2199
#, c-format
msgid "Field requires %d characters, but only %d could be parsed."
msgstr "Feld benötigt %d Zeichen, aber nur %d konnten geparst werden."
-#: utils/adt/formatting.c:2225
+#: utils/adt/formatting.c:2212
#, c-format
msgid "Value must be an integer."
msgstr "Der Wert muss eine ganze Zahl sein."
-#: utils/adt/formatting.c:2230
+#: utils/adt/formatting.c:2217
#, c-format
msgid "value for \"%s\" in source string is out of range"
msgstr "Wert für »%s« in der Eingabezeichenkette ist außerhalb des gültigen Bereichs"
-#: utils/adt/formatting.c:2232
+#: utils/adt/formatting.c:2219
#, c-format
msgid "Value must be in the range %d to %d."
msgstr "Der Wert muss im Bereich %d bis %d sein."
-#: utils/adt/formatting.c:2355
+#: utils/adt/formatting.c:2342
#, c-format
msgid "The given value did not match any of the allowed values for this field."
msgstr "Der angegebene Wert stimmte mit keinem der für dieses Feld zulässigen Werte überein."
-#: utils/adt/formatting.c:2550 utils/adt/formatting.c:2570
-#: utils/adt/formatting.c:2590 utils/adt/formatting.c:2610
-#: utils/adt/formatting.c:2629 utils/adt/formatting.c:2648
-#: utils/adt/formatting.c:2672 utils/adt/formatting.c:2690
-#: utils/adt/formatting.c:2708 utils/adt/formatting.c:2726
-#: utils/adt/formatting.c:2743 utils/adt/formatting.c:2760
+#: utils/adt/formatting.c:2527 utils/adt/formatting.c:2547
+#: utils/adt/formatting.c:2567 utils/adt/formatting.c:2587
+#: utils/adt/formatting.c:2606 utils/adt/formatting.c:2625
+#: utils/adt/formatting.c:2649 utils/adt/formatting.c:2667
+#: utils/adt/formatting.c:2685 utils/adt/formatting.c:2703
+#: utils/adt/formatting.c:2720 utils/adt/formatting.c:2737
#, c-format
msgid "localized string format value too long"
msgstr "lokalisierter Formatwert ist zu lang"
-#: utils/adt/formatting.c:3047
-#, c-format
-msgid "\"TZ\"/\"tz\"/\"OF\" format patterns are not supported in to_date"
-msgstr "Formatmuster »TZ«/»tz«/»OF« werden in to_date nicht unterstützt"
+#: utils/adt/formatting.c:3024
+#, fuzzy, c-format
+#| msgid "replication slot file \"%s\" has unsupported version %u"
+msgid "formatting field \"%s\" is only supported in to_char"
+msgstr "Replikations-Slot-Datei »%s« hat nicht unterstützte Version %u"
-#: utils/adt/formatting.c:3156
+#: utils/adt/formatting.c:3135
#, c-format
msgid "invalid input string for \"Y,YYY\""
msgstr "ungültige Eingabe für »Y,YYY«"
-#: utils/adt/formatting.c:3668
+#: utils/adt/formatting.c:3641
#, c-format
msgid "hour \"%d\" is invalid for the 12-hour clock"
msgstr "Stunde »%d« ist bei einer 12-Stunden-Uhr ungültig"
-#: utils/adt/formatting.c:3670
+#: utils/adt/formatting.c:3643
#, c-format
msgid "Use the 24-hour clock, or give an hour between 1 and 12."
msgstr "Verwenden Sie die 24-Stunden-Uhr oder geben Sie eine Stunde zwischen 1 und 12 an."
-#: utils/adt/formatting.c:3765
+#: utils/adt/formatting.c:3749
#, c-format
msgid "cannot calculate day of year without year information"
msgstr "kann Tag des Jahres nicht berechnen ohne Jahrinformationen"
-#: utils/adt/formatting.c:4614
+#: utils/adt/formatting.c:4616
#, c-format
msgid "\"EEEE\" not supported for input"
msgstr "»E« wird nicht bei der Eingabe unterstützt"
-#: utils/adt/formatting.c:4626
+#: utils/adt/formatting.c:4628
#, c-format
msgid "\"RN\" not supported for input"
msgstr "»RN« wird nicht bei der Eingabe unterstützt"
@@ -18748,27 +20081,23 @@ msgstr "int2vector-Wert hat zu viele Elemente"
msgid "invalid int2vector data"
msgstr "ungültige int2vector-Daten"
-#: utils/adt/int.c:243 utils/adt/oid.c:212 utils/adt/oid.c:293
+#: utils/adt/int.c:243 utils/adt/oid.c:215 utils/adt/oid.c:296
#, c-format
msgid "oidvector has too many elements"
msgstr "oidvector-Wert hat zu viele Elemente"
-#: utils/adt/int.c:1362 utils/adt/int8.c:1460 utils/adt/numeric.c:1355
-#: utils/adt/timestamp.c:5611 utils/adt/timestamp.c:5692
+#: utils/adt/int.c:1347 utils/adt/int8.c:1460 utils/adt/numeric.c:1401
+#: utils/adt/timestamp.c:5148 utils/adt/timestamp.c:5229
#, c-format
msgid "step size cannot equal zero"
msgstr "Schrittgröße kann nicht gleich null sein"
#: utils/adt/int8.c:98 utils/adt/int8.c:133 utils/adt/numutils.c:51
-#: utils/adt/numutils.c:61 utils/adt/numutils.c:103
-#, c-format
-msgid "invalid input syntax for integer: \"%s\""
-msgstr "ungültige Eingabesyntax für ganze Zahl: »%s«"
-
-#: utils/adt/int8.c:114
-#, c-format
-msgid "value \"%s\" is out of range for type bigint"
-msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für Typ bigint"
+#: utils/adt/numutils.c:61 utils/adt/numutils.c:105
+#, fuzzy, c-format
+#| msgid "invalid input syntax for type %s: \"%s\""
+msgid "invalid input syntax for %s: \"%s\""
+msgstr "ungültige Eingabesyntax für Typ %s: »%s«"
#: utils/adt/int8.c:500 utils/adt/int8.c:529 utils/adt/int8.c:550
#: utils/adt/int8.c:581 utils/adt/int8.c:615 utils/adt/int8.c:640
@@ -18778,8 +20107,8 @@ msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für Typ bigint"
#: utils/adt/int8.c:964 utils/adt/int8.c:991 utils/adt/int8.c:1031
#: utils/adt/int8.c:1052 utils/adt/int8.c:1079 utils/adt/int8.c:1112
#: utils/adt/int8.c:1140 utils/adt/int8.c:1161 utils/adt/int8.c:1188
-#: utils/adt/int8.c:1361 utils/adt/int8.c:1400 utils/adt/numeric.c:2959
-#: utils/adt/varbit.c:1645
+#: utils/adt/int8.c:1361 utils/adt/int8.c:1400 utils/adt/numeric.c:3005
+#: utils/adt/varbit.c:1655
#, c-format
msgid "bigint out of range"
msgstr "bigint ist außerhalb des gültigen Bereichs"
@@ -18789,170 +20118,159 @@ msgstr "bigint ist außerhalb des gültigen Bereichs"
msgid "OID out of range"
msgstr "OID ist außerhalb des gültigen Bereichs"
-#: utils/adt/json.c:785 utils/adt/json.c:825 utils/adt/json.c:840
-#: utils/adt/json.c:851 utils/adt/json.c:861 utils/adt/json.c:912
-#: utils/adt/json.c:943 utils/adt/json.c:961 utils/adt/json.c:973
-#: utils/adt/json.c:985 utils/adt/json.c:1130 utils/adt/json.c:1144
-#: utils/adt/json.c:1155 utils/adt/json.c:1163 utils/adt/json.c:1171
-#: utils/adt/json.c:1179 utils/adt/json.c:1187 utils/adt/json.c:1195
-#: utils/adt/json.c:1203 utils/adt/json.c:1211 utils/adt/json.c:1241
-#, c-format
-msgid "invalid input syntax for type json"
-msgstr "ungültige Eingabesyntax für Typ json"
-
#: utils/adt/json.c:786
#, c-format
msgid "Character with value 0x%02x must be escaped."
msgstr "Zeichen mit Wert 0x%02x muss escapt werden."
-#: utils/adt/json.c:826
+#: utils/adt/json.c:827
#, c-format
msgid "\"\\u\" must be followed by four hexadecimal digits."
msgstr "Nach »\\u« müssen vier Hexadezimalziffern folgen."
-#: utils/adt/json.c:841
+#: utils/adt/json.c:843
#, c-format
msgid "Unicode high surrogate must not follow a high surrogate."
msgstr "Unicode-High-Surrogate darf nicht auf ein High-Surrogate folgen."
-#: utils/adt/json.c:852 utils/adt/json.c:862 utils/adt/json.c:913
-#: utils/adt/json.c:974 utils/adt/json.c:986
+#: utils/adt/json.c:854 utils/adt/json.c:864 utils/adt/json.c:916
+#: utils/adt/json.c:978 utils/adt/json.c:990
#, c-format
msgid "Unicode low surrogate must follow a high surrogate."
msgstr "Unicode-Low-Surrogate muss auf ein High-Surrogate folgen."
-#: utils/adt/json.c:877 utils/adt/json.c:900
+#: utils/adt/json.c:879 utils/adt/json.c:902
#, c-format
msgid "unsupported Unicode escape sequence"
msgstr "nicht unterstützte Unicode-Escape-Sequenz"
-#: utils/adt/json.c:878
+#: utils/adt/json.c:880
#, c-format
msgid "\\u0000 cannot be converted to text."
msgstr "\\u0000 kann nicht in »text« umgewandelt werden."
-#: utils/adt/json.c:901
+#: utils/adt/json.c:903
#, c-format
msgid "Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."
msgstr "Unicode-Escape-Werte können nicht für Code-Punkt-Werte über 007F verwendet werden, wenn die Serverkodierung nicht UTF8 ist."
-#: utils/adt/json.c:944 utils/adt/json.c:962
+#: utils/adt/json.c:948 utils/adt/json.c:966
#, c-format
msgid "Escape sequence \"\\%s\" is invalid."
msgstr "Escape-Sequenz »\\%s« ist nicht gültig."
-#: utils/adt/json.c:1131
+#: utils/adt/json.c:1135
#, c-format
msgid "The input string ended unexpectedly."
msgstr "Die Eingabezeichenkette endete unerwartet."
-#: utils/adt/json.c:1145
+#: utils/adt/json.c:1149
#, c-format
msgid "Expected end of input, but found \"%s\"."
msgstr "Ende der Eingabe erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1156
+#: utils/adt/json.c:1160
#, c-format
msgid "Expected JSON value, but found \"%s\"."
msgstr "JSON-Wert erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1164 utils/adt/json.c:1212
+#: utils/adt/json.c:1168 utils/adt/json.c:1216
#, c-format
msgid "Expected string, but found \"%s\"."
msgstr "Zeichenkette erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1172
+#: utils/adt/json.c:1176
#, c-format
msgid "Expected array element or \"]\", but found \"%s\"."
msgstr "Array-Element oder »]« erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1180
+#: utils/adt/json.c:1184
#, c-format
msgid "Expected \",\" or \"]\", but found \"%s\"."
msgstr "»,« oder »]« erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1188
+#: utils/adt/json.c:1192
#, c-format
msgid "Expected string or \"}\", but found \"%s\"."
msgstr "Zeichenkette oder »}« erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1196
+#: utils/adt/json.c:1200
#, c-format
msgid "Expected \":\", but found \"%s\"."
msgstr "»:« erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1204
+#: utils/adt/json.c:1208
#, c-format
msgid "Expected \",\" or \"}\", but found \"%s\"."
msgstr "»,« oder »}« erwartet, aber »%s« gefunden."
-#: utils/adt/json.c:1242
+#: utils/adt/json.c:1246
#, c-format
msgid "Token \"%s\" is invalid."
msgstr "Token »%s« ist ungültig."
-#: utils/adt/json.c:1314
+#: utils/adt/json.c:1318
#, c-format
msgid "JSON data, line %d: %s%s%s"
msgstr "JSON-Daten, Zeile %d: %s%s%s"
-#: utils/adt/json.c:1469 utils/adt/jsonb.c:724
+#: utils/adt/json.c:1474 utils/adt/jsonb.c:725
#, c-format
msgid "key value must be scalar, not array, composite, or json"
msgstr "Schlüsselwert muss skalar sein, nicht Array, zusammengesetzt oder json"
-#: utils/adt/json.c:2006
+#: utils/adt/json.c:2011
#, c-format
msgid "could not determine data type for argument 1"
msgstr "konnte Datentyp von Argument 1 nicht ermitteln"
-#: utils/adt/json.c:2016
+#: utils/adt/json.c:2021
#, c-format
msgid "could not determine data type for argument 2"
msgstr "konnte Datentyp von Argument 2 nicht ermitteln"
-#: utils/adt/json.c:2040 utils/adt/jsonb.c:1781
+#: utils/adt/json.c:2045 utils/adt/jsonb.c:1782
#, c-format
msgid "field name must not be null"
msgstr "Feldname darf nicht NULL sein"
-#: utils/adt/json.c:2117
+#: utils/adt/json.c:2122
#, c-format
msgid "argument list must have even number of elements"
msgstr "Argumentliste muss gerade Anzahl Elemente haben"
-#: utils/adt/json.c:2118
+#: utils/adt/json.c:2123
#, c-format
msgid "The arguments of json_build_object() must consist of alternating keys and values."
msgstr "Die Argumente von json_build_object() müssen abwechselnd Schlüssel und Werte sein."
-#: utils/adt/json.c:2142 utils/adt/json.c:2163 utils/adt/json.c:2222
+#: utils/adt/json.c:2147 utils/adt/json.c:2168 utils/adt/json.c:2227
#, c-format
msgid "could not determine data type for argument %d"
msgstr "konnte Datentyp von Argument %d nicht ermitteln"
-#: utils/adt/json.c:2148
+#: utils/adt/json.c:2153
#, c-format
msgid "argument %d cannot be null"
msgstr "Argument %d darf nicht NULL sein"
-#: utils/adt/json.c:2149
+#: utils/adt/json.c:2154
#, c-format
msgid "Object keys should be text."
msgstr "Objektschlüssel sollten Text sein."
-#: utils/adt/json.c:2284 utils/adt/jsonb.c:1363
+#: utils/adt/json.c:2289 utils/adt/jsonb.c:1364
#, c-format
msgid "array must have two columns"
msgstr "Array muss zwei Spalten haben"
-#: utils/adt/json.c:2308 utils/adt/json.c:2392 utils/adt/jsonb.c:1387
-#: utils/adt/jsonb.c:1482
+#: utils/adt/json.c:2313 utils/adt/json.c:2397 utils/adt/jsonb.c:1388
+#: utils/adt/jsonb.c:1483
#, c-format
msgid "null value not allowed for object key"
msgstr "NULL-Werte sind nicht als Objektschlüssel erlaubt"
-#: utils/adt/json.c:2381 utils/adt/jsonb.c:1471
+#: utils/adt/json.c:2386 utils/adt/jsonb.c:1472
#, c-format
msgid "mismatched array dimensions"
msgstr "Array-Dimensionen passen nicht"
@@ -18967,167 +20285,168 @@ msgstr "Zeichenkette ist zu lang für jsonb"
msgid "Due to an implementation restriction, jsonb strings cannot exceed %d bytes."
msgstr "Aufgrund einer Einschränkung der Implementierung können jsonb-Zeichenketten nicht länger als %d Bytes sein."
-#: utils/adt/jsonb.c:1182
+#: utils/adt/jsonb.c:1183
#, c-format
msgid "invalid number of arguments: object must be matched key value pairs"
msgstr "ungültige Anzahl Argumente: Objekt muss aus Schlüssel-Wert-Paaren bestehen"
-#: utils/adt/jsonb.c:1195
+#: utils/adt/jsonb.c:1196
#, c-format
msgid "argument %d: key must not be null"
msgstr "Argument %d: Schlüssel darf nicht NULL sein"
-#: utils/adt/jsonb.c:1214 utils/adt/jsonb.c:1237 utils/adt/jsonb.c:1297
+#: utils/adt/jsonb.c:1215 utils/adt/jsonb.c:1238 utils/adt/jsonb.c:1298
#, c-format
msgid "argument %d: could not determine data type"
msgstr "Argument %d: konnte Datentypen nicht bestimmen"
-#: utils/adt/jsonb.c:1834
+#: utils/adt/jsonb.c:1835
#, c-format
msgid "object keys must be strings"
msgstr "Objektschlüssel müssen Zeichenketten sein"
-#: utils/adt/jsonb_util.c:656
+#: utils/adt/jsonb_util.c:657
#, c-format
msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)"
msgstr "Anzahl der jsonb-Objekte-Paare überschreitet erlaubtes Maximum (%zu)"
-#: utils/adt/jsonb_util.c:697
+#: utils/adt/jsonb_util.c:698
#, c-format
msgid "number of jsonb array elements exceeds the maximum allowed (%zu)"
msgstr "Anzahl der jsonb-Arrayelemente überschreitet erlaubtes Maximum (%zu)"
-#: utils/adt/jsonb_util.c:1525 utils/adt/jsonb_util.c:1545
+#: utils/adt/jsonb_util.c:1526 utils/adt/jsonb_util.c:1546
#, c-format
msgid "total size of jsonb array elements exceeds the maximum of %u bytes"
msgstr "Gesamtgröße der jsonb-Array-Elemente überschreitet die maximale Größe von %u Bytes"
-#: utils/adt/jsonb_util.c:1606 utils/adt/jsonb_util.c:1641
-#: utils/adt/jsonb_util.c:1661
+#: utils/adt/jsonb_util.c:1607 utils/adt/jsonb_util.c:1642
+#: utils/adt/jsonb_util.c:1662
#, c-format
msgid "total size of jsonb object elements exceeds the maximum of %u bytes"
msgstr "Gesamtgröße der jsonb-Objektelemente überschreitet die maximale Größe von %u Bytes"
-#: utils/adt/jsonfuncs.c:305 utils/adt/jsonfuncs.c:470
-#: utils/adt/jsonfuncs.c:2065 utils/adt/jsonfuncs.c:2506
-#: utils/adt/jsonfuncs.c:3012
+#: utils/adt/jsonfuncs.c:306 utils/adt/jsonfuncs.c:471
+#: utils/adt/jsonfuncs.c:2058 utils/adt/jsonfuncs.c:2499
+#: utils/adt/jsonfuncs.c:3005
#, c-format
msgid "cannot call %s on a scalar"
msgstr "%s kann nicht mit einem skalaren Wert aufgerufen werden"
-#: utils/adt/jsonfuncs.c:310 utils/adt/jsonfuncs.c:457
-#: utils/adt/jsonfuncs.c:2495
+#: utils/adt/jsonfuncs.c:311 utils/adt/jsonfuncs.c:458
+#: utils/adt/jsonfuncs.c:2488
#, c-format
msgid "cannot call %s on an array"
msgstr "%s kann nicht mit einem Array aufgerufen werden"
-#: utils/adt/jsonfuncs.c:1373 utils/adt/jsonfuncs.c:1408
+#: utils/adt/jsonfuncs.c:1374 utils/adt/jsonfuncs.c:1409
#, c-format
msgid "cannot get array length of a scalar"
msgstr "kann nicht die Arraylänge eines skalaren Wertes ermitteln"
-#: utils/adt/jsonfuncs.c:1377 utils/adt/jsonfuncs.c:1396
+#: utils/adt/jsonfuncs.c:1378 utils/adt/jsonfuncs.c:1397
#, c-format
msgid "cannot get array length of a non-array"
msgstr "kann nicht die Arraylänge eines Nicht-Arrays ermitteln"
-#: utils/adt/jsonfuncs.c:1473
+#: utils/adt/jsonfuncs.c:1474
#, c-format
msgid "cannot call %s on a non-object"
msgstr "%s kann nicht mit etwas aufgerufen werden, das kein Objekt ist"
-#: utils/adt/jsonfuncs.c:1491 utils/adt/jsonfuncs.c:2178
-#: utils/adt/jsonfuncs.c:2715
+#: utils/adt/jsonfuncs.c:1492 utils/adt/jsonfuncs.c:2171
+#: utils/adt/jsonfuncs.c:2708
#, c-format
msgid "function returning record called in context that cannot accept type record"
msgstr "Funktion, die einen Record zurückgibt, in einem Zusammenhang aufgerufen, der Typ record nicht verarbeiten kann"
-#: utils/adt/jsonfuncs.c:1734
+#: utils/adt/jsonfuncs.c:1731
#, c-format
msgid "cannot deconstruct an array as an object"
msgstr "kann Array nicht in ein Objekt zerlegen"
-#: utils/adt/jsonfuncs.c:1746
+#: utils/adt/jsonfuncs.c:1743
#, c-format
msgid "cannot deconstruct a scalar"
msgstr "kann skalaren Wert nicht zerlegen"
-#: utils/adt/jsonfuncs.c:1792
+#: utils/adt/jsonfuncs.c:1789
#, c-format
msgid "cannot extract elements from a scalar"
msgstr "kann keine Elemente aus einem skalaren Wert auswählen"
-#: utils/adt/jsonfuncs.c:1796
+#: utils/adt/jsonfuncs.c:1793
#, c-format
msgid "cannot extract elements from an object"
msgstr "kann keine Elemente aus einem Objekt auswählen"
-#: utils/adt/jsonfuncs.c:2052 utils/adt/jsonfuncs.c:2811
+#: utils/adt/jsonfuncs.c:2045 utils/adt/jsonfuncs.c:2804
#, c-format
msgid "cannot call %s on a non-array"
msgstr "%s kann nicht mit etwas aufgerufen werden, das kein Array ist"
-#: utils/adt/jsonfuncs.c:2139 utils/adt/jsonfuncs.c:2691
+#: utils/adt/jsonfuncs.c:2132 utils/adt/jsonfuncs.c:2684
#, c-format
msgid "first argument of %s must be a row type"
msgstr "erstes Argument von %s muss ein Zeilentyp sein"
-#: utils/adt/jsonfuncs.c:2180
+#: utils/adt/jsonfuncs.c:2173
#, c-format
msgid "Try calling the function in the FROM clause using a column definition list."
msgstr "Versuchen Sie, die Funktion in der FROM-Klausel mit einer Spaltendefinitionsliste aufzurufen."
-#: utils/adt/jsonfuncs.c:2827 utils/adt/jsonfuncs.c:2994
+#: utils/adt/jsonfuncs.c:2820 utils/adt/jsonfuncs.c:2987
#, c-format
msgid "argument of %s must be an array of objects"
msgstr "Argument von %s muss ein Array von Objekten sein"
-#: utils/adt/jsonfuncs.c:2851
+#: utils/adt/jsonfuncs.c:2844
#, c-format
msgid "cannot call %s on an object"
msgstr "%s kann nicht mit einem Objekt aufgerufen werden"
-#: utils/adt/jsonfuncs.c:3418 utils/adt/jsonfuncs.c:3471
+#: utils/adt/jsonfuncs.c:3411 utils/adt/jsonfuncs.c:3470
+#: utils/adt/jsonfuncs.c:3550
#, c-format
msgid "cannot delete from scalar"
msgstr "kann nicht aus skalarem Wert löschen"
-#: utils/adt/jsonfuncs.c:3476
+#: utils/adt/jsonfuncs.c:3555
#, c-format
msgid "cannot delete from object using integer index"
msgstr "aus einem Objekt kann nicht per numerischem Index gelöscht werden"
-#: utils/adt/jsonfuncs.c:3542 utils/adt/jsonfuncs.c:3634
+#: utils/adt/jsonfuncs.c:3621 utils/adt/jsonfuncs.c:3713
#, c-format
msgid "cannot set path in scalar"
msgstr "in einem skalaren Wert kann kein Pfad gesetzt werden"
-#: utils/adt/jsonfuncs.c:3587
+#: utils/adt/jsonfuncs.c:3666
#, c-format
msgid "cannot delete path in scalar"
msgstr "in einem skalaren Wert kann kein Pfad gelöscht werden"
-#: utils/adt/jsonfuncs.c:3757
+#: utils/adt/jsonfuncs.c:3836
#, c-format
msgid "invalid concatenation of jsonb objects"
msgstr "ungültiges Aneinanderhängen von jsonb-Objekten"
-#: utils/adt/jsonfuncs.c:3791
+#: utils/adt/jsonfuncs.c:3870
#, c-format
msgid "path element at position %d is null"
msgstr "Pfadelement auf Position %d ist NULL"
-#: utils/adt/jsonfuncs.c:3877
+#: utils/adt/jsonfuncs.c:3956
#, c-format
msgid "cannot replace existing key"
msgstr "existierender Schlüssel kann nicht ersetzt werden"
-#: utils/adt/jsonfuncs.c:3878
+#: utils/adt/jsonfuncs.c:3957
#, c-format
msgid "Try using the function jsonb_set to replace key value."
msgstr "Verwenden Sie die Funktion jsonb_set, um den Schlüsselwert zu ersetzen."
-#: utils/adt/jsonfuncs.c:3960
+#: utils/adt/jsonfuncs.c:4039
#, c-format
msgid "path element at position %d is not an integer: \"%s\""
msgstr "Pfadelement auf Position %d ist keine ganze Zahl: »%s«"
@@ -19137,7 +20456,7 @@ msgstr "Pfadelement auf Position %d ist keine ganze Zahl: »%s«"
msgid "levenshtein argument exceeds maximum length of %d characters"
msgstr "Levenshtein-Argument überschreitet die maximale Länge von %d Zeichen"
-#: utils/adt/like.c:212 utils/adt/selfuncs.c:5333
+#: utils/adt/like.c:212 utils/adt/selfuncs.c:5331
#, c-format
msgid "could not determine which collation to use for ILIKE"
msgstr "konnte die für ILIKE zu verwendende Sortierfolge nicht bestimmen"
@@ -19162,128 +20481,129 @@ msgstr "ESCAPE-Zeichenkette muss null oder ein Zeichen lang sein."
msgid "cannot use advisory locks during a parallel operation"
msgstr "während einer parallelen Operation können keine Benutzersperren verwendet werden"
-#: utils/adt/mac.c:68
-#, c-format
-msgid "invalid input syntax for type macaddr: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ macaddr: »%s«"
-
-#: utils/adt/mac.c:75
+#: utils/adt/mac.c:76
#, c-format
msgid "invalid octet value in \"macaddr\" value: \"%s\""
msgstr "ungültiger Oktettwert in »macaddr«-Wert: »%s«"
-#: utils/adt/misc.c:239
+#: utils/adt/misc.c:238
#, c-format
msgid "PID %d is not a PostgreSQL server process"
msgstr "PID %d ist kein PostgreSQL-Serverprozess"
-#: utils/adt/misc.c:290
+#: utils/adt/misc.c:289
#, c-format
msgid "must be a superuser to cancel superuser query"
msgstr "nur Superuser können Anfragen eines Superusers stornieren"
-#: utils/adt/misc.c:295
+#: utils/adt/misc.c:294
#, c-format
msgid "must be a member of the role whose query is being canceled or member of pg_signal_backend"
msgstr "muss Mitglied der Rolle sein, deren Anfrage storniert wird, oder Mitglied von pg_signal_backend"
-#: utils/adt/misc.c:314
+#: utils/adt/misc.c:313
#, c-format
msgid "must be a superuser to terminate superuser process"
msgstr "nur Superuser können Prozesse eines Superusers beenden"
-#: utils/adt/misc.c:319
+#: utils/adt/misc.c:318
#, c-format
msgid "must be a member of the role whose process is being terminated or member of pg_signal_backend"
msgstr "muss Mitglied der Rolle sein, deren Prozess beendet wird, oder Mitglied von pg_signal_backend"
-#: utils/adt/misc.c:336
+#: utils/adt/misc.c:335
#, c-format
msgid "failed to send signal to postmaster: %m"
msgstr "konnte Signal nicht an Postmaster senden: %m"
-#: utils/adt/misc.c:356
+#: utils/adt/misc.c:355
#, c-format
msgid "rotation not possible because log collection not active"
msgstr "Rotierung nicht möglich, weil Logsammlung nicht aktiv ist"
-#: utils/adt/misc.c:393
+#: utils/adt/misc.c:392
#, c-format
msgid "global tablespace never has databases"
msgstr "globaler Tablespace hat niemals Datenbanken"
-#: utils/adt/misc.c:414
+#: utils/adt/misc.c:413
#, c-format
msgid "%u is not a tablespace OID"
msgstr "%u ist keine Tablespace-OID"
-#: utils/adt/misc.c:611
+#: utils/adt/misc.c:606
msgid "unreserved"
msgstr "unreserviert"
-#: utils/adt/misc.c:615
+#: utils/adt/misc.c:610
msgid "unreserved (cannot be function or type name)"
msgstr "unreserviert (kann nicht Funktions- oder Typname sein)"
-#: utils/adt/misc.c:619
+#: utils/adt/misc.c:614
msgid "reserved (can be function or type name)"
msgstr "reserviert (kann Funktions- oder Typname sein)"
-#: utils/adt/misc.c:623
+#: utils/adt/misc.c:618
msgid "reserved"
msgstr "reserviert"
-#: utils/adt/misc.c:797 utils/adt/misc.c:811 utils/adt/misc.c:850
-#: utils/adt/misc.c:856 utils/adt/misc.c:862 utils/adt/misc.c:885
+#: utils/adt/misc.c:792 utils/adt/misc.c:806 utils/adt/misc.c:845
+#: utils/adt/misc.c:851 utils/adt/misc.c:857 utils/adt/misc.c:880
#, c-format
msgid "string is not a valid identifier: \"%s\""
msgstr "Zeichenkette ist kein gültiger Bezeichner: »%s«"
-#: utils/adt/misc.c:799
+#: utils/adt/misc.c:794
#, c-format
msgid "String has unclosed double quotes."
msgstr "Zeichenkette hat nicht geschlossene doppelte Anführungszeichen."
-#: utils/adt/misc.c:813
+#: utils/adt/misc.c:808
#, c-format
msgid "Quoted identifier must not be empty."
msgstr "Bezeichner in Anführungszeichen darf nicht leer sein."
-#: utils/adt/misc.c:852
+#: utils/adt/misc.c:847
#, c-format
msgid "No valid identifier before \".\"."
msgstr "Kein gültiger Bezeichner vor ».«."
-#: utils/adt/misc.c:858
+#: utils/adt/misc.c:853
#, c-format
msgid "No valid identifier after \".\"."
msgstr "Kein gültiger Bezeichner nach ».«."
-#: utils/adt/nabstime.c:136
+#: utils/adt/misc.c:914
+#, fuzzy, c-format
+#| msgid "interval units \"%s\" not supported"
+msgid "log format \"%s\" is not supported"
+msgstr "»interval«-Einheit »%s« nicht unterstützt"
+
+#: utils/adt/misc.c:915
+#, c-format
+msgid "The supported log formats are \"stderr\" and \"csvlog\"."
+msgstr ""
+
+#: utils/adt/nabstime.c:137
#, c-format
msgid "invalid time zone name: \"%s\""
msgstr "ungültiger Zeitzonenname: »%s«"
-#: utils/adt/nabstime.c:481 utils/adt/nabstime.c:554
+#: utils/adt/nabstime.c:482 utils/adt/nabstime.c:555
#, c-format
msgid "cannot convert abstime \"invalid\" to timestamp"
msgstr "kann »abstime«-Wert »invalid« nicht »timestamp« umwandeln"
-#: utils/adt/nabstime.c:781
+#: utils/adt/nabstime.c:782
#, c-format
msgid "invalid status in external \"tinterval\" value"
msgstr "ungültiger Status in externem »tinterval«-Wert"
-#: utils/adt/nabstime.c:855
+#: utils/adt/nabstime.c:852
#, c-format
msgid "cannot convert reltime \"invalid\" to interval"
msgstr "kann »reltime«-Wert »invalid« nicht in »interval« umwandeln"
-#: utils/adt/nabstime.c:1550
-#, c-format
-msgid "invalid input syntax for type tinterval: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ tinterval: »%s«"
-
#: utils/adt/network.c:69
#, c-format
msgid "invalid cidr value: \"%s\""
@@ -19294,8 +20614,8 @@ msgstr "ungültiger cidr-Wert: »%s«"
msgid "Value has bits set to right of mask."
msgstr "Wert hat gesetzte Bits rechts von der Maske."
-#: utils/adt/network.c:111 utils/adt/network.c:607 utils/adt/network.c:632
-#: utils/adt/network.c:657
+#: utils/adt/network.c:111 utils/adt/network.c:582 utils/adt/network.c:607
+#: utils/adt/network.c:632
#, c-format
msgid "could not format inet value: %m"
msgstr "konnte inet-Wert nicht formatieren: %m"
@@ -19323,159 +20643,124 @@ msgstr "ungültige Länge in externem »%s«-Wert"
msgid "invalid external \"cidr\" value"
msgstr "ungültiger externer »cidr«-Wert"
-#: utils/adt/network.c:321 utils/adt/network.c:348
+#: utils/adt/network.c:295 utils/adt/network.c:318
#, c-format
msgid "invalid mask length: %d"
msgstr "ungültige Maskenlänge: %d"
-#: utils/adt/network.c:675
+#: utils/adt/network.c:650
#, c-format
msgid "could not format cidr value: %m"
msgstr "konnte cidr-Wert nicht formatieren: %m"
-#: utils/adt/network.c:917
+#: utils/adt/network.c:883
#, c-format
msgid "cannot merge addresses from different families"
msgstr "Adressen verschiedener Familien können nicht zusammengeführt werden"
-#: utils/adt/network.c:1343
+#: utils/adt/network.c:1292
#, c-format
msgid "cannot AND inet values of different sizes"
msgstr "binäres »Und« nicht mit »inet«-Werten unterschiedlicher Größe möglich"
-#: utils/adt/network.c:1375
+#: utils/adt/network.c:1324
#, c-format
msgid "cannot OR inet values of different sizes"
msgstr "binäres »Oder« nicht mit »inet«-Werten unterschiedlicher Größe möglich"
-#: utils/adt/network.c:1436 utils/adt/network.c:1512
+#: utils/adt/network.c:1385 utils/adt/network.c:1461
#, c-format
msgid "result is out of range"
msgstr "Ergebnis ist außerhalb des gültigen Bereichs"
-#: utils/adt/network.c:1477
+#: utils/adt/network.c:1426
#, c-format
msgid "cannot subtract inet values of different sizes"
msgstr "Subtraktion von »inet«-Werten unterschiedlicher Größe nicht möglich"
-#: utils/adt/numeric.c:542 utils/adt/numeric.c:569 utils/adt/numeric.c:5409
-#: utils/adt/numeric.c:5432 utils/adt/numeric.c:5456 utils/adt/numeric.c:5463
-#, c-format
-msgid "invalid input syntax for type numeric: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ numeric: »%s«"
-
-#: utils/adt/numeric.c:759
-#, c-format
-msgid "invalid length in external \"numeric\" value"
-msgstr "ungültige Länge in externem »numeric«-Wert"
-
-#: utils/adt/numeric.c:772
+#: utils/adt/numeric.c:819
#, c-format
msgid "invalid sign in external \"numeric\" value"
msgstr "ungültiges Vorzeichen in externem »numeric«-Wert"
-#: utils/adt/numeric.c:778
+#: utils/adt/numeric.c:825
#, c-format
msgid "invalid scale in external \"numeric\" value"
msgstr "ungültige Skala in externem »numeric«-Wert"
-#: utils/adt/numeric.c:787
+#: utils/adt/numeric.c:834
#, c-format
msgid "invalid digit in external \"numeric\" value"
msgstr "ungültige Ziffer in externem »numeric«-Wert"
-#: utils/adt/numeric.c:978 utils/adt/numeric.c:992
+#: utils/adt/numeric.c:1024 utils/adt/numeric.c:1038
#, c-format
msgid "NUMERIC precision %d must be between 1 and %d"
msgstr "Präzision von NUMERIC (%d) muss zwischen 1 und %d liegen"
-#: utils/adt/numeric.c:983
+#: utils/adt/numeric.c:1029
#, c-format
msgid "NUMERIC scale %d must be between 0 and precision %d"
msgstr "Skala von NUMERIC (%d) muss zwischen 0 und %d liegen"
-#: utils/adt/numeric.c:1001
+#: utils/adt/numeric.c:1047
#, c-format
msgid "invalid NUMERIC type modifier"
msgstr "ungültiker Modifikator für Typ NUMERIC"
-#: utils/adt/numeric.c:1333
+#: utils/adt/numeric.c:1379
#, c-format
msgid "start value cannot be NaN"
msgstr "Startwert kann nicht NaN sein"
-#: utils/adt/numeric.c:1338
+#: utils/adt/numeric.c:1384
#, c-format
msgid "stop value cannot be NaN"
msgstr "Stoppwert kann nicht NaN sein"
-#: utils/adt/numeric.c:1348
+#: utils/adt/numeric.c:1394
#, c-format
msgid "step size cannot be NaN"
msgstr "Schrittgröße kann nicht NaN sein"
-#: utils/adt/numeric.c:2543 utils/adt/numeric.c:5909 utils/adt/numeric.c:7613
-#: utils/adt/numeric.c:8038 utils/adt/numeric.c:8153 utils/adt/numeric.c:8226
+#: utils/adt/numeric.c:2589 utils/adt/numeric.c:5551 utils/adt/numeric.c:5996
+#: utils/adt/numeric.c:7700 utils/adt/numeric.c:8125 utils/adt/numeric.c:8240
+#: utils/adt/numeric.c:8313
#, c-format
msgid "value overflows numeric format"
msgstr "Wert verursacht Überlauf im »numeric«-Format"
-#: utils/adt/numeric.c:2885
+#: utils/adt/numeric.c:2931
#, c-format
msgid "cannot convert NaN to integer"
msgstr "kann NaN nicht in integer umwandeln"
-#: utils/adt/numeric.c:2951
+#: utils/adt/numeric.c:2997
#, c-format
msgid "cannot convert NaN to bigint"
msgstr "kann NaN nicht in bigint umwandeln"
-#: utils/adt/numeric.c:2996
+#: utils/adt/numeric.c:3042
#, c-format
msgid "cannot convert NaN to smallint"
msgstr "kann NaN nicht in smallint umwandeln"
-#: utils/adt/numeric.c:5979
+#: utils/adt/numeric.c:6066
#, c-format
msgid "numeric field overflow"
msgstr "Feldüberlauf bei Typ »numeric«"
-#: utils/adt/numeric.c:5980
+#: utils/adt/numeric.c:6067
#, c-format
msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d."
msgstr "Ein Feld mit Präzision %d, Skala %d muss beim Runden einen Betrag von weniger als %s%d ergeben."
-#: utils/adt/numeric.c:6251 utils/adt/numeric.c:6277
-#, c-format
-msgid "invalid input syntax for type double precision: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ double precision: »%s«"
-
-#: utils/adt/numutils.c:75
-#, c-format
-msgid "value \"%s\" is out of range for type integer"
-msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für Typ integer"
-
-#: utils/adt/numutils.c:81
-#, c-format
-msgid "value \"%s\" is out of range for type smallint"
-msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für Typ smallint"
-
-#: utils/adt/numutils.c:87
+#: utils/adt/numutils.c:89
#, c-format
msgid "value \"%s\" is out of range for 8-bit integer"
msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für 8-Bit-Ganzzahl"
-#: utils/adt/oid.c:43 utils/adt/oid.c:57 utils/adt/oid.c:63 utils/adt/oid.c:84
-#, c-format
-msgid "invalid input syntax for type oid: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ »oid«: »%s«"
-
-#: utils/adt/oid.c:69 utils/adt/oid.c:107
-#, c-format
-msgid "value \"%s\" is out of range for type oid"
-msgstr "Wert »%s« ist außerhalb des gültigen Bereichs für Typ »oid«"
-
-#: utils/adt/oid.c:287
+#: utils/adt/oid.c:290
#, c-format
msgid "invalid oidvector data"
msgstr "ungültige oidvector-Daten"
@@ -19500,208 +20785,87 @@ msgstr "gewünschtes Zeichen ist nicht gültig für die Kodierung: %d"
msgid "null character not permitted"
msgstr "Null-Zeichen ist nicht erlaubt"
-#: utils/adt/orderedsetaggs.c:425 utils/adt/orderedsetaggs.c:530
-#: utils/adt/orderedsetaggs.c:669
+#: utils/adt/orderedsetaggs.c:426 utils/adt/orderedsetaggs.c:531
+#: utils/adt/orderedsetaggs.c:670
#, c-format
msgid "percentile value %g is not between 0 and 1"
msgstr "Perzentilwert %g ist nicht zwischen 0 und 1"
-#: utils/adt/pg_locale.c:917
+#: utils/adt/pg_locale.c:1028
#, c-format
msgid "Apply system library package updates."
msgstr "Aktualisieren Sie die Systembibliotheken."
-#: utils/adt/pg_locale.c:1122
+#: utils/adt/pg_locale.c:1233
#, c-format
msgid "could not create locale \"%s\": %m"
msgstr "konnte Locale »%s« nicht erzeugen: %m"
-#: utils/adt/pg_locale.c:1125
+#: utils/adt/pg_locale.c:1236
#, c-format
msgid "The operating system could not find any locale data for the locale name \"%s\"."
msgstr "Das Betriebssystem konnte keine Locale-Daten für den Locale-Namen »%s« finden."
-#: utils/adt/pg_locale.c:1212
+#: utils/adt/pg_locale.c:1323
#, c-format
msgid "collations with different collate and ctype values are not supported on this platform"
msgstr "Sortierfolgen mit unterschiedlichen »collate«- und »ctype«-Werten werden auf dieser Plattform nicht unterstützt"
-#: utils/adt/pg_locale.c:1227
+#: utils/adt/pg_locale.c:1338
#, c-format
msgid "nondefault collations are not supported on this platform"
msgstr "Sortierfolgen außer der Standardsortierfolge werden auf dieser Plattform nicht unterstützt"
-#: utils/adt/pg_locale.c:1398
+#: utils/adt/pg_locale.c:1509
#, c-format
msgid "invalid multibyte character for locale"
msgstr "ungültiges Mehrbytezeichen für Locale"
-#: utils/adt/pg_locale.c:1399
+#: utils/adt/pg_locale.c:1510
#, c-format
msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding."
msgstr "Die LC_CTYPE-Locale des Servers ist wahrscheinlich mit der Kodierung der Datenbank inkompatibel."
-#: utils/adt/pg_lsn.c:44 utils/adt/pg_lsn.c:49
-#, c-format
-msgid "invalid input syntax for type pg_lsn: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ pg_lsn: »%s«"
-
-#: utils/adt/pg_upgrade_support.c:40
+#: utils/adt/pg_upgrade_support.c:28
#, c-format
msgid "function can only be called when server is in binary upgrade mode"
msgstr "Funktion kann nur aufgerufen werden, wenn der Server im Binary-Upgrade-Modus ist"
-#: utils/adt/pgstatfuncs.c:571
+#: utils/adt/pgstatfuncs.c:471
#, c-format
msgid "invalid command name: \"%s\""
msgstr "ungültiger Befehlsname: »%s«"
-#: utils/adt/pseudotypes.c:95
-#, c-format
-msgid "cannot accept a value of type any"
-msgstr "kann keinen Wert vom Typ any annehmen"
-
-#: utils/adt/pseudotypes.c:108
-#, c-format
-msgid "cannot display a value of type any"
-msgstr "kann keinen Wert vom Typ any anzeigen"
-
-#: utils/adt/pseudotypes.c:122 utils/adt/pseudotypes.c:150
-#, c-format
-msgid "cannot accept a value of type anyarray"
-msgstr "kann keinen Wert vom Typ anyarray annehmen"
-
-#: utils/adt/pseudotypes.c:175
-#, c-format
-msgid "cannot accept a value of type anyenum"
-msgstr "kann keinen Wert vom Typ anyenum annehmen"
-
-#: utils/adt/pseudotypes.c:199
-#, c-format
-msgid "cannot accept a value of type anyrange"
-msgstr "kann keinen Wert vom Typ anyrange annehmen"
-
-#: utils/adt/pseudotypes.c:276
-#, c-format
-msgid "cannot accept a value of type trigger"
-msgstr "kann keinen Wert vom Typ trigger annehmen"
-
-#: utils/adt/pseudotypes.c:289
-#, c-format
-msgid "cannot display a value of type trigger"
-msgstr "kann keinen Wert vom Typ trigger anzeigen"
-
-#: utils/adt/pseudotypes.c:303
-#, c-format
-msgid "cannot accept a value of type event_trigger"
-msgstr "kann keinen Wert vom Typ event_trigger annehmen"
-
-#: utils/adt/pseudotypes.c:316
-#, c-format
-msgid "cannot display a value of type event_trigger"
-msgstr "kann keinen Wert vom Typ event_trigger anzeigen"
-
-#: utils/adt/pseudotypes.c:330
-#, c-format
-msgid "cannot accept a value of type language_handler"
-msgstr "kann keinen Wert vom Typ language_handler annehmen"
-
-#: utils/adt/pseudotypes.c:343
-#, c-format
-msgid "cannot display a value of type language_handler"
-msgstr "kann keinen Wert vom Typ language_handler anzeigen"
-
-#: utils/adt/pseudotypes.c:357
-#, c-format
-msgid "cannot accept a value of type fdw_handler"
-msgstr "kann keinen Wert vom Typ fdw_handler annehmen"
-
-#: utils/adt/pseudotypes.c:370
-#, c-format
-msgid "cannot display a value of type fdw_handler"
-msgstr "kann keinen Wert vom Typ fdw_handler anzeigen"
-
-#: utils/adt/pseudotypes.c:384
-#, c-format
-msgid "cannot accept a value of type index_am_handler"
-msgstr "kann keinen Wert vom Typ index_am_handler annehmen"
-
-#: utils/adt/pseudotypes.c:397
-#, c-format
-msgid "cannot display a value of type index_am_handler"
-msgstr "kann keinen Wert vom Typ index_am_handler anzeigen"
-
-#: utils/adt/pseudotypes.c:411
-#, c-format
-msgid "cannot accept a value of type tsm_handler"
-msgstr "kann keinen Wert vom Typ tsm_handler annehmen"
-
-#: utils/adt/pseudotypes.c:424
-#, c-format
-msgid "cannot display a value of type tsm_handler"
-msgstr "kann keinen Wert vom Typ tsm_handler anzeigen"
-
-#: utils/adt/pseudotypes.c:438
-#, c-format
-msgid "cannot accept a value of type internal"
-msgstr "kann keinen Wert vom Typ internal annehmen"
-
-#: utils/adt/pseudotypes.c:451
-#, c-format
-msgid "cannot display a value of type internal"
-msgstr "kann keinen Wert vom Typ internal anzeigen"
-
-#: utils/adt/pseudotypes.c:465
-#, c-format
-msgid "cannot accept a value of type opaque"
-msgstr "kann keinen Wert vom Typ opaque annehmen"
-
-#: utils/adt/pseudotypes.c:478
-#, c-format
-msgid "cannot display a value of type opaque"
-msgstr "kann keinen Wert vom Typ opaque anzeigen"
-
-#: utils/adt/pseudotypes.c:492
-#, c-format
-msgid "cannot accept a value of type anyelement"
-msgstr "kann keinen Wert vom Typ anyelement annehmen"
-
-#: utils/adt/pseudotypes.c:505
-#, c-format
-msgid "cannot display a value of type anyelement"
-msgstr "kann keinen Wert vom Typ anyelement anzeigen"
-
-#: utils/adt/pseudotypes.c:518
+#: utils/adt/pseudotypes.c:94 utils/adt/pseudotypes.c:122
+#: utils/adt/pseudotypes.c:147 utils/adt/pseudotypes.c:171
+#: utils/adt/pseudotypes.c:282 utils/adt/pseudotypes.c:307
+#: utils/adt/pseudotypes.c:335 utils/adt/pseudotypes.c:363
+#: utils/adt/pseudotypes.c:393
#, c-format
-msgid "cannot accept a value of type anynonarray"
-msgstr "kann keinen Wert vom Typ anynonarray annehmen"
-
-#: utils/adt/pseudotypes.c:531
-#, c-format
-msgid "cannot display a value of type anynonarray"
-msgstr "kann keinen Wert vom Typ anynonarray anzeigen"
+msgid "cannot accept a value of type %s"
+msgstr "kann keinen Wert vom Typ %s annehmen"
-#: utils/adt/pseudotypes.c:544
+#: utils/adt/pseudotypes.c:247
#, c-format
msgid "cannot accept a value of a shell type"
msgstr "kann keinen Wert eines Hüllentyps annehmen"
-#: utils/adt/pseudotypes.c:557
+#: utils/adt/pseudotypes.c:260
#, c-format
msgid "cannot display a value of a shell type"
msgstr "kann keinen Wert eines Hüllentyps anzeigen"
-#: utils/adt/pseudotypes.c:579 utils/adt/pseudotypes.c:604
-#: utils/adt/pseudotypes.c:632 utils/adt/pseudotypes.c:660
-#, c-format
-msgid "cannot accept a value of type %s"
-msgstr "kann keinen Wert vom Typ %s annehmen"
-
-#: utils/adt/pseudotypes.c:647 utils/adt/pseudotypes.c:673
+#: utils/adt/pseudotypes.c:350 utils/adt/pseudotypes.c:376
#, c-format
msgid "cannot output a value of type %s"
msgstr "kann keinen Wert vom Typ %s anzeigen"
+#: utils/adt/pseudotypes.c:403
+#, fuzzy, c-format
+#| msgid "cannot display a value of type any"
+msgid "cannot display a value of type %s"
+msgstr "kann keinen Wert vom Typ any anzeigen"
+
#: utils/adt/rangetypes.c:405
#, c-format
msgid "range constructor flags argument must not be null"
@@ -19717,57 +20881,57 @@ msgstr "Ergebnis von Bereichsdifferenz würde nicht zusammenhängend sein"
msgid "result of range union would not be contiguous"
msgstr "Ergebnis von Bereichsvereinigung würde nicht zusammenhängend sein"
-#: utils/adt/rangetypes.c:1543
+#: utils/adt/rangetypes.c:1533
#, c-format
msgid "range lower bound must be less than or equal to range upper bound"
msgstr "Bereichsuntergrenze muss kleiner als oder gleich der Bereichsobergrenze sein"
-#: utils/adt/rangetypes.c:1926 utils/adt/rangetypes.c:1939
-#: utils/adt/rangetypes.c:1953
+#: utils/adt/rangetypes.c:1916 utils/adt/rangetypes.c:1929
+#: utils/adt/rangetypes.c:1943
#, c-format
msgid "invalid range bound flags"
msgstr "ungültige Markierungen für Bereichsgrenzen"
-#: utils/adt/rangetypes.c:1927 utils/adt/rangetypes.c:1940
-#: utils/adt/rangetypes.c:1954
+#: utils/adt/rangetypes.c:1917 utils/adt/rangetypes.c:1930
+#: utils/adt/rangetypes.c:1944
#, c-format
msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"."
msgstr "Gültige Werte sind »[]«, »[)«, »(]« und »()«."
-#: utils/adt/rangetypes.c:2019 utils/adt/rangetypes.c:2036
-#: utils/adt/rangetypes.c:2049 utils/adt/rangetypes.c:2067
-#: utils/adt/rangetypes.c:2078 utils/adt/rangetypes.c:2122
-#: utils/adt/rangetypes.c:2130
+#: utils/adt/rangetypes.c:2009 utils/adt/rangetypes.c:2026
+#: utils/adt/rangetypes.c:2039 utils/adt/rangetypes.c:2057
+#: utils/adt/rangetypes.c:2068 utils/adt/rangetypes.c:2112
+#: utils/adt/rangetypes.c:2120
#, c-format
msgid "malformed range literal: \"%s\""
msgstr "fehlerhafte Bereichskonstante: »%s«"
-#: utils/adt/rangetypes.c:2021
+#: utils/adt/rangetypes.c:2011
#, c-format
msgid "Junk after \"empty\" key word."
msgstr "Müll nach Schlüsselwort »empty«."
-#: utils/adt/rangetypes.c:2038
+#: utils/adt/rangetypes.c:2028
#, c-format
msgid "Missing left parenthesis or bracket."
msgstr "Linke runde oder eckige Klammer fehlt."
-#: utils/adt/rangetypes.c:2051
+#: utils/adt/rangetypes.c:2041
#, c-format
msgid "Missing comma after lower bound."
msgstr "Komma fehlt nach Untergrenze."
-#: utils/adt/rangetypes.c:2069
+#: utils/adt/rangetypes.c:2059
#, c-format
msgid "Too many commas."
msgstr "Zu viele Kommas."
-#: utils/adt/rangetypes.c:2080
+#: utils/adt/rangetypes.c:2070
#, c-format
msgid "Junk after right parenthesis or bracket."
msgstr "Müll nach rechter runder oder eckiger Klammer."
-#: utils/adt/regexp.c:285 utils/adt/regexp.c:1288 utils/adt/varlena.c:3829
+#: utils/adt/regexp.c:285 utils/adt/regexp.c:1344 utils/adt/varlena.c:3816
#, c-format
msgid "regular expression failed: %s"
msgstr "regulärer Ausdruck fehlgeschlagen: %s"
@@ -19777,126 +20941,144 @@ msgstr "regulärer Ausdruck fehlgeschlagen: %s"
msgid "invalid regexp option: \"%c\""
msgstr "ungültige Option für regulären Ausdruck: »%c«"
-#: utils/adt/regexp.c:948
+#: utils/adt/regexp.c:862
+#, fuzzy, c-format
+#| msgid "regexp_split does not support the global option"
+msgid "regexp_match does not support the global option"
+msgstr "regexp_split unterstützt die »Global«-Option nicht"
+
+#: utils/adt/regexp.c:863
#, c-format
-msgid "regexp_split does not support the global option"
+msgid "Use the regexp_matches function instead."
+msgstr ""
+
+#: utils/adt/regexp.c:1163
+#, fuzzy, c-format
+#| msgid "regexp_split does not support the global option"
+msgid "regexp_split_to_table does not support the global option"
+msgstr "regexp_split unterstützt die »Global«-Option nicht"
+
+#: utils/adt/regexp.c:1219
+#, fuzzy, c-format
+#| msgid "regexp_split does not support the global option"
+msgid "regexp_split_to_array does not support the global option"
msgstr "regexp_split unterstützt die »Global«-Option nicht"
-#: utils/adt/regproc.c:128 utils/adt/regproc.c:148
+#: utils/adt/regproc.c:130 utils/adt/regproc.c:150
#, c-format
msgid "more than one function named \"%s\""
msgstr "es gibt mehrere Funktionen namens »%s«"
-#: utils/adt/regproc.c:587 utils/adt/regproc.c:607
+#: utils/adt/regproc.c:589 utils/adt/regproc.c:609
#, c-format
msgid "more than one operator named %s"
msgstr "es gibt mehrere Operatoren namens %s"
-#: utils/adt/regproc.c:779 utils/adt/regproc.c:820 utils/adt/regproc.c:2006
-#: utils/adt/ruleutils.c:8364 utils/adt/ruleutils.c:8533
+#: utils/adt/regproc.c:781 utils/adt/regproc.c:822 utils/adt/regproc.c:2008
+#: utils/adt/ruleutils.c:8718 utils/adt/ruleutils.c:8886
#, c-format
msgid "too many arguments"
msgstr "zu viele Argumente"
-#: utils/adt/regproc.c:780 utils/adt/regproc.c:821
+#: utils/adt/regproc.c:782 utils/adt/regproc.c:823
#, c-format
msgid "Provide two argument types for operator."
msgstr "Geben Sie zwei Argumente für den Operator an."
-#: utils/adt/regproc.c:1594 utils/adt/regproc.c:1618 utils/adt/regproc.c:1715
-#: utils/adt/regproc.c:1739 utils/adt/regproc.c:1841 utils/adt/regproc.c:1846
-#: utils/adt/varlena.c:3084 utils/adt/varlena.c:3089
+#: utils/adt/regproc.c:1596 utils/adt/regproc.c:1620 utils/adt/regproc.c:1717
+#: utils/adt/regproc.c:1741 utils/adt/regproc.c:1843 utils/adt/regproc.c:1848
+#: utils/adt/varlena.c:3071 utils/adt/varlena.c:3076
#, c-format
msgid "invalid name syntax"
msgstr "ungültige Namenssyntax"
-#: utils/adt/regproc.c:1904
+#: utils/adt/regproc.c:1906
#, c-format
msgid "expected a left parenthesis"
msgstr "linke Klammer erwartet"
-#: utils/adt/regproc.c:1920
+#: utils/adt/regproc.c:1922
#, c-format
msgid "expected a right parenthesis"
msgstr "rechte Klammer erwartet"
-#: utils/adt/regproc.c:1939
+#: utils/adt/regproc.c:1941
#, c-format
msgid "expected a type name"
msgstr "Typname erwartet"
-#: utils/adt/regproc.c:1971
+#: utils/adt/regproc.c:1973
#, c-format
msgid "improper type name"
msgstr "falscher Typname"
-#: utils/adt/ri_triggers.c:345 utils/adt/ri_triggers.c:2492
-#: utils/adt/ri_triggers.c:3317
+#: utils/adt/ri_triggers.c:343 utils/adt/ri_triggers.c:2490
+#: utils/adt/ri_triggers.c:3315
#, c-format
msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\""
msgstr "Einfügen oder Aktualisieren in Tabelle »%s« verletzt Fremdschlüssel-Constraint »%s«"
-#: utils/adt/ri_triggers.c:348 utils/adt/ri_triggers.c:2495
+#: utils/adt/ri_triggers.c:346 utils/adt/ri_triggers.c:2493
#, c-format
msgid "MATCH FULL does not allow mixing of null and nonnull key values."
msgstr "MATCH FULL erlaubt das Mischen von Schlüsseln, die NULL und nicht NULL sind, nicht."
-#: utils/adt/ri_triggers.c:2734
+#: utils/adt/ri_triggers.c:2732
#, c-format
msgid "function \"%s\" must be fired for INSERT"
msgstr "Funktion »%s« muss von INSERT ausgelöst werden"
-#: utils/adt/ri_triggers.c:2740
+#: utils/adt/ri_triggers.c:2738
#, c-format
msgid "function \"%s\" must be fired for UPDATE"
msgstr "Funktion »%s« muss von UPDATE ausgelöst werden"
-#: utils/adt/ri_triggers.c:2746
+#: utils/adt/ri_triggers.c:2744
#, c-format
msgid "function \"%s\" must be fired for DELETE"
msgstr "Funktion »%s« muss von DELETE ausgelöst werden"
-#: utils/adt/ri_triggers.c:2769
+#: utils/adt/ri_triggers.c:2767
#, c-format
msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\""
msgstr "kein »pg_constraint«-Eintrag für Trigger »%s« für Tabelle »%s«"
-#: utils/adt/ri_triggers.c:2771
+#: utils/adt/ri_triggers.c:2769
#, c-format
msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT."
msgstr "Entfernen Sie diesen Referentielle-Integritäts-Trigger und seine Partner und führen Sie dann ALTER TABLE ADD CONSTRAINT aus."
-#: utils/adt/ri_triggers.c:3227
+#: utils/adt/ri_triggers.c:3225
#, c-format
msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result"
msgstr "RI-Anfrage in Tabelle »%s« für Constraint »%s« von Tabelle »%s« ergab unerwartetes Ergebnis"
-#: utils/adt/ri_triggers.c:3231
+#: utils/adt/ri_triggers.c:3229
#, c-format
msgid "This is most likely due to a rule having rewritten the query."
msgstr "Das liegt höchstwahrscheinlich daran, dass eine Regel die Anfrage umgeschrieben hat."
-#: utils/adt/ri_triggers.c:3321
+#: utils/adt/ri_triggers.c:3319
#, c-format
msgid "Key (%s)=(%s) is not present in table \"%s\"."
msgstr "Schlüssel (%s)=(%s) ist nicht in Tabelle »%s« vorhanden."
-#: utils/adt/ri_triggers.c:3324
+#: utils/adt/ri_triggers.c:3322
#, c-format
msgid "Key is not present in table \"%s\"."
msgstr "Der Schlüssel ist nicht in Tabelle »%s« vorhanden."
-#: utils/adt/ri_triggers.c:3330
+#: utils/adt/ri_triggers.c:3328
#, c-format
msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\""
msgstr "Aktualisieren oder Löschen in Tabelle »%s« verletzt Fremdschlüssel-Constraint »%s« von Tabelle »%s«"
-#: utils/adt/ri_triggers.c:3335
+#: utils/adt/ri_triggers.c:3333
#, c-format
msgid "Key (%s)=(%s) is still referenced from table \"%s\"."
msgstr "Auf Schlüssel (%s)=(%s) wird noch aus Tabelle »%s« verwiesen."
-#: utils/adt/ri_triggers.c:3338
+#: utils/adt/ri_triggers.c:3336
#, c-format
msgid "Key is still referenced from table \"%s\"."
msgstr "Auf den Schlüssel wird noch aus Tabelle »%s« verwiesen."
@@ -19959,157 +21141,151 @@ msgstr "kann unterschiedliche Spaltentyp %s und %s in Record-Spalte %d nicht ver
msgid "cannot compare record types with different numbers of columns"
msgstr "kann Record-Typen mit unterschiedlicher Anzahl Spalten nicht vergleichen"
-#: utils/adt/ruleutils.c:4286
+#: utils/adt/ruleutils.c:4494
#, c-format
msgid "rule \"%s\" has unsupported event type %d"
msgstr "Regel »%s« hat nicht unterstützten Ereignistyp %d"
-#: utils/adt/selfuncs.c:5318
+#: utils/adt/selfuncs.c:5316
#, c-format
msgid "case insensitive matching not supported on type bytea"
msgstr "Mustersuche ohne Rücksicht auf Groß-/Kleinschreibung wird für Typ bytea nicht unterstützt"
-#: utils/adt/selfuncs.c:5421
+#: utils/adt/selfuncs.c:5418
#, c-format
msgid "regular-expression matching not supported on type bytea"
msgstr "Mustersuche mit regulären Ausdrücken wird für Typ bytea nicht unterstützt"
-#: utils/adt/tid.c:71 utils/adt/tid.c:79 utils/adt/tid.c:87
-#, c-format
-msgid "invalid input syntax for type tid: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ tid: »%s«"
-
-#: utils/adt/timestamp.c:99
+#: utils/adt/timestamp.c:106
#, c-format
msgid "TIMESTAMP(%d)%s precision must not be negative"
msgstr "Präzision von TIMESTAMP(%d)%s darf nicht negativ sein"
-#: utils/adt/timestamp.c:105
+#: utils/adt/timestamp.c:112
#, c-format
msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d"
msgstr "Präzision von TIMESTAMP(%d)%s auf erlaubten Höchstwert %d reduziert"
-#: utils/adt/timestamp.c:170 utils/adt/timestamp.c:445
+#: utils/adt/timestamp.c:175 utils/adt/timestamp.c:415
#, c-format
msgid "timestamp out of range: \"%s\""
msgstr "timestamp ist außerhalb des gültigen Bereichs: »%s«"
-#: utils/adt/timestamp.c:188 utils/adt/timestamp.c:463
-#: utils/adt/timestamp.c:993
+#: utils/adt/timestamp.c:193 utils/adt/timestamp.c:433
+#: utils/adt/timestamp.c:940
#, c-format
msgid "date/time value \"%s\" is no longer supported"
msgstr "Datum/Zeit-Wert »%s« wird nicht mehr unterstützt"
-#: utils/adt/timestamp.c:258 utils/adt/timestamp.c:754
-#, c-format
-msgid "timestamp cannot be NaN"
-msgstr "timestamp kann nicht NaN sein"
-
-#: utils/adt/timestamp.c:380
+#: utils/adt/timestamp.c:361
#, c-format
msgid "timestamp(%d) precision must be between %d and %d"
msgstr "Präzision von timestamp(%d) muss zwischen %d und %d sein"
-#: utils/adt/timestamp.c:513
+#: utils/adt/timestamp.c:483
#, c-format
msgid "invalid input syntax for numeric time zone: \"%s\""
msgstr "ungültige Eingabesyntax für numerische Zeitzone: »%s«"
-#: utils/adt/timestamp.c:515
+#: utils/adt/timestamp.c:485
#, c-format
msgid "Numeric time zones must have \"-\" or \"+\" as first character."
msgstr "Numerische Zeitzonen müssen »-« oder »+« als erstes Zeichen haben."
-#: utils/adt/timestamp.c:528
+#: utils/adt/timestamp.c:498
#, c-format
msgid "numeric time zone \"%s\" out of range"
msgstr "numerische Zeitzone »%s« ist außerhalb des gültigen Bereichs"
-#: utils/adt/timestamp.c:631 utils/adt/timestamp.c:641
-#: utils/adt/timestamp.c:653
+#: utils/adt/timestamp.c:600 utils/adt/timestamp.c:610
+#: utils/adt/timestamp.c:618
#, c-format
msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g"
msgstr "timestamp ist außerhalb des gültigen Bereichs: %d-%02d-%02d %d:%02d:%02g"
-#: utils/adt/timestamp.c:770 utils/adt/timestamp.c:776
-#: utils/adt/timestamp.c:791
+#: utils/adt/timestamp.c:719
+#, c-format
+msgid "timestamp cannot be NaN"
+msgstr "timestamp kann nicht NaN sein"
+
+#: utils/adt/timestamp.c:737 utils/adt/timestamp.c:749
#, c-format
msgid "timestamp out of range: \"%g\""
msgstr "timestamp ist außerhalb des gültigen Bereichs: »%g«"
-#: utils/adt/timestamp.c:987 utils/adt/timestamp.c:1558
-#: utils/adt/timestamp.c:2068 utils/adt/timestamp.c:3220
-#: utils/adt/timestamp.c:3225 utils/adt/timestamp.c:3230
-#: utils/adt/timestamp.c:3280 utils/adt/timestamp.c:3287
-#: utils/adt/timestamp.c:3294 utils/adt/timestamp.c:3314
-#: utils/adt/timestamp.c:3321 utils/adt/timestamp.c:3328
-#: utils/adt/timestamp.c:3358 utils/adt/timestamp.c:3366
-#: utils/adt/timestamp.c:3411 utils/adt/timestamp.c:3751
-#: utils/adt/timestamp.c:3880 utils/adt/timestamp.c:4271
+#: utils/adt/timestamp.c:934 utils/adt/timestamp.c:1504
+#: utils/adt/timestamp.c:1917 utils/adt/timestamp.c:2964
+#: utils/adt/timestamp.c:2969 utils/adt/timestamp.c:2974
+#: utils/adt/timestamp.c:3024 utils/adt/timestamp.c:3031
+#: utils/adt/timestamp.c:3038 utils/adt/timestamp.c:3058
+#: utils/adt/timestamp.c:3065 utils/adt/timestamp.c:3072
+#: utils/adt/timestamp.c:3102 utils/adt/timestamp.c:3110
+#: utils/adt/timestamp.c:3154 utils/adt/timestamp.c:3477
+#: utils/adt/timestamp.c:3602 utils/adt/timestamp.c:3970
#, c-format
msgid "interval out of range"
msgstr "interval-Wert ist außerhalb des gültigen Bereichs"
-#: utils/adt/timestamp.c:1128 utils/adt/timestamp.c:1161
+#: utils/adt/timestamp.c:1067 utils/adt/timestamp.c:1100
#, c-format
msgid "invalid INTERVAL type modifier"
msgstr "ungültiger Modifikator für Typ INTERVAL"
-#: utils/adt/timestamp.c:1144
+#: utils/adt/timestamp.c:1083
#, c-format
msgid "INTERVAL(%d) precision must not be negative"
msgstr "INTERVAL(%d)-Präzision darf nicht negativ sein"
-#: utils/adt/timestamp.c:1150
+#: utils/adt/timestamp.c:1089
#, c-format
msgid "INTERVAL(%d) precision reduced to maximum allowed, %d"
msgstr "INTERVAL(%d)-Präzision auf erlaubtes Maximum %d reduziert"
-#: utils/adt/timestamp.c:1502
+#: utils/adt/timestamp.c:1461
#, c-format
msgid "interval(%d) precision must be between %d and %d"
msgstr "Präzision von interval(%d) muss zwischen %d und %d sein"
-#: utils/adt/timestamp.c:2797
+#: utils/adt/timestamp.c:2565
#, c-format
msgid "cannot subtract infinite timestamps"
msgstr "kann unendliche timestamp-Werte nicht subtrahieren"
-#: utils/adt/timestamp.c:4006 utils/adt/timestamp.c:4531
-#: utils/adt/timestamp.c:4715 utils/adt/timestamp.c:4740
+#: utils/adt/timestamp.c:3721 utils/adt/timestamp.c:4230
+#: utils/adt/timestamp.c:4397 utils/adt/timestamp.c:4418
#, c-format
msgid "timestamp units \"%s\" not supported"
msgstr "»timestamp«-Einheit »%s« nicht unterstützt"
-#: utils/adt/timestamp.c:4020 utils/adt/timestamp.c:4485
-#: utils/adt/timestamp.c:4750
+#: utils/adt/timestamp.c:3735 utils/adt/timestamp.c:4184
+#: utils/adt/timestamp.c:4428
#, c-format
msgid "timestamp units \"%s\" not recognized"
msgstr "»timestamp«-Einheit »%s« nicht erkannt"
-#: utils/adt/timestamp.c:4160 utils/adt/timestamp.c:4526
-#: utils/adt/timestamp.c:4937 utils/adt/timestamp.c:4963
+#: utils/adt/timestamp.c:3867 utils/adt/timestamp.c:4225
+#: utils/adt/timestamp.c:4598 utils/adt/timestamp.c:4620
#, c-format
msgid "timestamp with time zone units \"%s\" not supported"
msgstr "»timestamp with time zone«-Einheit »%s« nicht unterstützt"
-#: utils/adt/timestamp.c:4177 utils/adt/timestamp.c:4480
-#: utils/adt/timestamp.c:4972
+#: utils/adt/timestamp.c:3884 utils/adt/timestamp.c:4179
+#: utils/adt/timestamp.c:4629
#, c-format
msgid "timestamp with time zone units \"%s\" not recognized"
msgstr "»timestamp with time zone«-Einheit »%s« nicht erkannt"
-#: utils/adt/timestamp.c:4258
+#: utils/adt/timestamp.c:3957
#, c-format
msgid "interval units \"%s\" not supported because months usually have fractional weeks"
msgstr "»interval«-Einheit »%s« wird nicht unterstützt, weil Monate gewöhnlich partielle Wochen haben"
-#: utils/adt/timestamp.c:4264 utils/adt/timestamp.c:5078
+#: utils/adt/timestamp.c:3963 utils/adt/timestamp.c:4723
#, c-format
msgid "interval units \"%s\" not supported"
msgstr "»interval«-Einheit »%s« nicht unterstützt"
-#: utils/adt/timestamp.c:4280 utils/adt/timestamp.c:5105
+#: utils/adt/timestamp.c:3979 utils/adt/timestamp.c:4746
#, c-format
msgid "interval units \"%s\" not recognized"
msgstr "»interval«-Einheit »%s« nicht erkannt"
@@ -20134,7 +21310,7 @@ msgstr "suppress_redundant_updates_trigger: muss vor dem UPDATE aufgerufen werde
msgid "suppress_redundant_updates_trigger: must be called for each row"
msgstr "suppress_redundant_updates_trigger: muss für jede Zeile aufgerufen werden"
-#: utils/adt/tsgistidx.c:99
+#: utils/adt/tsgistidx.c:100
#, c-format
msgid "gtsvector_in not implemented"
msgstr "gtsvector_in ist nicht implementiert"
@@ -20142,9 +21318,9 @@ msgstr "gtsvector_in ist nicht implementiert"
#: utils/adt/tsquery.c:166
#, c-format
msgid "distance in phrase operator should not be greater than %d"
-msgstr ""
+msgstr "Abstand im Phrasenoperator sollte nicht größer als %d sein"
-#: utils/adt/tsquery.c:254 utils/adt/tsquery.c:512
+#: utils/adt/tsquery.c:254 utils/adt/tsquery.c:513
#: utils/adt/tsvector_parser.c:141
#, c-format
msgid "syntax error in tsquery: \"%s\""
@@ -20175,110 +21351,108 @@ msgstr "Wort ist zu lang in tsquery: »%s«"
msgid "text-search query doesn't contain lexemes: \"%s\""
msgstr "Textsucheanfrage enthält keine Lexeme: »%s«"
-#: utils/adt/tsquery.c:653 utils/adt/tsquery_util.c:347
+#: utils/adt/tsquery.c:653 utils/adt/tsquery_util.c:375
#, c-format
msgid "tsquery is too large"
msgstr "tsquery ist zu groß"
-#: utils/adt/tsquery_cleanup.c:601
+#: utils/adt/tsquery_cleanup.c:407
#, c-format
msgid "text-search query contains only stop words or doesn't contain lexemes, ignored"
msgstr "Textsucheanfrage enthält nur Stoppwörter oder enthält keine Lexeme, ignoriert"
-#: utils/adt/tsquery_op.c:122
+#: utils/adt/tsquery_op.c:123
#, c-format
msgid "distance in phrase operator should be non-negative and less than %d"
-msgstr ""
+msgstr "Abstand im Phrasenoperator sollte nicht negativ und kleiner als %d sein"
-#: utils/adt/tsquery_rewrite.c:292
+#: utils/adt/tsquery_rewrite.c:321
#, c-format
msgid "ts_rewrite query must return two tsquery columns"
msgstr "ts_rewrite-Anfrage muss zwei tsquery-Spalten zurückgeben"
-#: utils/adt/tsrank.c:412
+#: utils/adt/tsrank.c:413
#, c-format
msgid "array of weight must be one-dimensional"
msgstr "Gewichtungs-Array muss eindimensional sein"
-#: utils/adt/tsrank.c:417
+#: utils/adt/tsrank.c:418
#, c-format
msgid "array of weight is too short"
msgstr "Gewichtungs-Array ist zu kurz"
-#: utils/adt/tsrank.c:422
+#: utils/adt/tsrank.c:423
#, c-format
msgid "array of weight must not contain nulls"
msgstr "Gewichtungs-Array darf keine NULL-Werte enthalten"
-#: utils/adt/tsrank.c:431 utils/adt/tsrank.c:868
+#: utils/adt/tsrank.c:432 utils/adt/tsrank.c:869
#, c-format
msgid "weight out of range"
msgstr "Gewichtung ist außerhalb des gültigen Bereichs"
-#: utils/adt/tsvector.c:213
+#: utils/adt/tsvector.c:214
#, c-format
msgid "word is too long (%ld bytes, max %ld bytes)"
msgstr "Wort ist zu lang (%ld Bytes, maximal %ld Bytes)"
-#: utils/adt/tsvector.c:220
+#: utils/adt/tsvector.c:221
#, c-format
msgid "string is too long for tsvector (%ld bytes, max %ld bytes)"
msgstr "Zeichenkette ist zu lang für tsvector (%ld Bytes, maximal %ld Bytes)"
-#: utils/adt/tsvector_op.c:321 utils/adt/tsvector_op.c:608
-#: utils/adt/tsvector_op.c:776
+#: utils/adt/tsvector_op.c:323 utils/adt/tsvector_op.c:610
+#: utils/adt/tsvector_op.c:778
#, c-format
msgid "lexeme array may not contain nulls"
msgstr "Lexem-Array darf keine NULL-Werte enthalten"
-#: utils/adt/tsvector_op.c:851
-#, fuzzy, c-format
-#| msgid "array must not contain nulls"
+#: utils/adt/tsvector_op.c:853
+#, c-format
msgid "weight array may not contain nulls"
-msgstr "Array darf keine NULL-Werte enthalten"
+msgstr "Gewichtungs-Array darf keine NULL-Werte enthalten"
-#: utils/adt/tsvector_op.c:875
-#, fuzzy, c-format
-#| msgid "unrecognized encoding: \"%s\""
+#: utils/adt/tsvector_op.c:877
+#, c-format
msgid "unrecognized weight: \"%c\""
-msgstr "unbekannte Kodierung: »%s«"
+msgstr "unbekannte Gewichtung: »%c«"
-#: utils/adt/tsvector_op.c:2061
+#: utils/adt/tsvector_op.c:2314
#, c-format
msgid "ts_stat query must return one tsvector column"
msgstr "ts_stat-Anfrage muss eine tsvector-Spalte zurückgeben"
-#: utils/adt/tsvector_op.c:2243
+#: utils/adt/tsvector_op.c:2496
#, c-format
msgid "tsvector column \"%s\" does not exist"
msgstr "tsvector-Spalte »%s« existiert nicht"
-#: utils/adt/tsvector_op.c:2249
+#: utils/adt/tsvector_op.c:2503
#, c-format
msgid "column \"%s\" is not of tsvector type"
msgstr "Spalte »%s« hat nicht Typ tsvector"
-#: utils/adt/tsvector_op.c:2261
+#: utils/adt/tsvector_op.c:2515
#, c-format
msgid "configuration column \"%s\" does not exist"
msgstr "Konfigurationsspalte »%s« existiert nicht"
-#: utils/adt/tsvector_op.c:2267
+#: utils/adt/tsvector_op.c:2521
#, c-format
msgid "column \"%s\" is not of regconfig type"
msgstr "Spalte »%s« hat nicht Typ regconfig"
-#: utils/adt/tsvector_op.c:2274
+#: utils/adt/tsvector_op.c:2528
#, c-format
msgid "configuration column \"%s\" must not be null"
msgstr "Konfigurationsspalte »%s« darf nicht NULL sein"
-#: utils/adt/tsvector_op.c:2287
+#: utils/adt/tsvector_op.c:2541
#, c-format
msgid "text search configuration name \"%s\" must be schema-qualified"
msgstr "Textsuchekonfigurationsname »%s« muss Schemaqualifikation haben"
-#: utils/adt/tsvector_op.c:2312
+#: utils/adt/tsvector_op.c:2566
#, c-format
msgid "column \"%s\" is not of a character type"
msgstr "Spalte »%s« hat keinen Zeichentyp"
@@ -20298,64 +21472,54 @@ msgstr "es gibt kein escaptes Zeichen: »%s«"
msgid "wrong position info in tsvector: \"%s\""
msgstr "falsche Positionsinformationen in tsvector: »%s«"
-#: utils/adt/txid.c:339
-#, c-format
-msgid "invalid input syntax for type txid_snapshot: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ txid_snapshot: »%s«"
-
-#: utils/adt/txid.c:534
+#: utils/adt/txid.c:555
#, c-format
msgid "invalid external txid_snapshot data"
msgstr "ungültige externe txid_snapshot-Daten"
-#: utils/adt/uuid.c:145
-#, c-format
-msgid "invalid input syntax for uuid: \"%s\""
-msgstr "ungültige Eingabesyntax für Typ uuid: »%s«"
-
-#: utils/adt/varbit.c:57 utils/adt/varchar.c:50
+#: utils/adt/varbit.c:58 utils/adt/varchar.c:51
#, c-format
msgid "length for type %s must be at least 1"
msgstr "Länge von Typ %s muss mindestens 1 sein"
-#: utils/adt/varbit.c:62 utils/adt/varchar.c:54
+#: utils/adt/varbit.c:63 utils/adt/varchar.c:55
#, c-format
msgid "length for type %s cannot exceed %d"
msgstr "Länge von Typ %s kann %d nicht überschreiten"
-#: utils/adt/varbit.c:163 utils/adt/varbit.c:475 utils/adt/varbit.c:973
+#: utils/adt/varbit.c:164 utils/adt/varbit.c:476 utils/adt/varbit.c:973
#, c-format
msgid "bit string length exceeds the maximum allowed (%d)"
msgstr "Länge der Bitkette überschreitet erlaubtes Maximum (%d)"
-#: utils/adt/varbit.c:177 utils/adt/varbit.c:320 utils/adt/varbit.c:377
+#: utils/adt/varbit.c:178 utils/adt/varbit.c:321 utils/adt/varbit.c:378
#, c-format
msgid "bit string length %d does not match type bit(%d)"
msgstr "Länge der Bitkette %d stimmt nicht mit Typ bit(%d) überein"
-#: utils/adt/varbit.c:199 utils/adt/varbit.c:511
+#: utils/adt/varbit.c:200 utils/adt/varbit.c:512
#, c-format
msgid "\"%c\" is not a valid binary digit"
msgstr "»%c« ist keine gültige Binärziffer"
-#: utils/adt/varbit.c:224 utils/adt/varbit.c:536
+#: utils/adt/varbit.c:225 utils/adt/varbit.c:537
#, c-format
msgid "\"%c\" is not a valid hexadecimal digit"
msgstr "»%c« ist keine gültige Hexadezimalziffer"
-#: utils/adt/varbit.c:311 utils/adt/varbit.c:627
+#: utils/adt/varbit.c:312 utils/adt/varbit.c:628
#, c-format
msgid "invalid length in external bit string"
msgstr "ungültige Länge in externer Bitkette"
-#: utils/adt/varbit.c:489 utils/adt/varbit.c:636 utils/adt/varbit.c:731
+#: utils/adt/varbit.c:490 utils/adt/varbit.c:637 utils/adt/varbit.c:731
#, c-format
msgid "bit string too long for type bit varying(%d)"
msgstr "Bitkette ist zu lang für Typ bit varying(%d)"
-#: utils/adt/varbit.c:1066 utils/adt/varbit.c:1168 utils/adt/varlena.c:842
-#: utils/adt/varlena.c:906 utils/adt/varlena.c:1050 utils/adt/varlena.c:2735
-#: utils/adt/varlena.c:2802
+#: utils/adt/varbit.c:1066 utils/adt/varbit.c:1168 utils/adt/varlena.c:843
+#: utils/adt/varlena.c:907 utils/adt/varlena.c:1051 utils/adt/varlena.c:2736
+#: utils/adt/varlena.c:2803
#, c-format
msgid "negative substring length not allowed"
msgstr "negative Teilzeichenkettenlänge nicht erlaubt"
@@ -20375,95 +21539,88 @@ msgstr "binäres »Oder« nicht mit Bitketten unterschiedlicher Länge möglich"
msgid "cannot XOR bit strings of different sizes"
msgstr "binäres »Exklusiv-Oder« nicht mit Bitketten unterschiedlicher Länge möglich"
-#: utils/adt/varbit.c:1793 utils/adt/varbit.c:1851
+#: utils/adt/varbit.c:1803 utils/adt/varbit.c:1861
#, c-format
msgid "bit index %d out of valid range (0..%d)"
msgstr "Bitindex %d ist außerhalb des gültigen Bereichs (0..%d)"
-#: utils/adt/varbit.c:1802 utils/adt/varlena.c:3002
+#: utils/adt/varbit.c:1812 utils/adt/varlena.c:2995
#, c-format
msgid "new bit must be 0 or 1"
msgstr "neues Bit muss 0 oder 1 sein"
-#: utils/adt/varchar.c:154 utils/adt/varchar.c:307
+#: utils/adt/varchar.c:155 utils/adt/varchar.c:308
#, c-format
msgid "value too long for type character(%d)"
msgstr "Wert zu lang für Typ character(%d)"
-#: utils/adt/varchar.c:469 utils/adt/varchar.c:623
+#: utils/adt/varchar.c:470 utils/adt/varchar.c:623
#, c-format
msgid "value too long for type character varying(%d)"
msgstr "Wert zu lang für Typ character varying(%d)"
-#: utils/adt/varlena.c:1420 utils/adt/varlena.c:1825
+#: utils/adt/varlena.c:1421 utils/adt/varlena.c:1826
#, c-format
msgid "could not determine which collation to use for string comparison"
msgstr "konnte die für den Zeichenkettenvergleich zu verwendende Sortierfolge nicht bestimmen"
-#: utils/adt/varlena.c:1478 utils/adt/varlena.c:1491
+#: utils/adt/varlena.c:1479 utils/adt/varlena.c:1492
#, c-format
msgid "could not convert string to UTF-16: error code %lu"
msgstr "konnte Zeichenkette nicht in UTF-16 umwandeln: Fehlercode %lu"
-#: utils/adt/varlena.c:1506
+#: utils/adt/varlena.c:1507
#, c-format
msgid "could not compare Unicode strings: %m"
msgstr "konnte Unicode-Zeichenketten nicht vergleichen: %m"
-#: utils/adt/varlena.c:2880 utils/adt/varlena.c:2911 utils/adt/varlena.c:2947
-#: utils/adt/varlena.c:2990
+#: utils/adt/varlena.c:2881 utils/adt/varlena.c:2912 utils/adt/varlena.c:2947
+#: utils/adt/varlena.c:2983
#, c-format
msgid "index %d out of valid range, 0..%d"
msgstr "Index %d ist außerhalb des gültigen Bereichs, 0..%d"
-#: utils/adt/varlena.c:3925
+#: utils/adt/varlena.c:3912
#, c-format
msgid "field position must be greater than zero"
msgstr "Feldposition muss größer als null sein"
-#: utils/adt/varlena.c:4804
-#, fuzzy, c-format
-#| msgid "unterminated format specifier"
+#: utils/adt/varlena.c:4791
+#, c-format
msgid "unterminated format() type specifier"
-msgstr "Formatspezifikation nicht abgeschlossen"
+msgstr "Typspezifikation in format() nicht abgeschlossen"
-#: utils/adt/varlena.c:4805 utils/adt/varlena.c:4939 utils/adt/varlena.c:5060
+#: utils/adt/varlena.c:4792 utils/adt/varlena.c:4926 utils/adt/varlena.c:5047
#, c-format
msgid "For a single \"%%\" use \"%%%%\"."
msgstr "Für ein einzelnes »%%« geben Sie »%%%%« an."
-#: utils/adt/varlena.c:4937 utils/adt/varlena.c:5058
-#, fuzzy, c-format
-#| msgid "unrecognized conversion type specifier \"%c\""
+#: utils/adt/varlena.c:4924 utils/adt/varlena.c:5045
+#, c-format
msgid "unrecognized format() type specifier \"%c\""
-msgstr "unbekannte Konvertierungstypspezifikation »%c«"
+msgstr "unbekannte Typspezifikation in format(): »%c«"
-#: utils/adt/varlena.c:4950
+#: utils/adt/varlena.c:4937 utils/adt/varlena.c:4994
#, c-format
msgid "too few arguments for format()"
msgstr "zu wenige Argumente für format()"
-#: utils/adt/varlena.c:5007
-#, c-format
-msgid "too few arguments for format"
-msgstr "zu wenige Argumente für Format"
-
-#: utils/adt/varlena.c:5102 utils/adt/varlena.c:5285
+#: utils/adt/varlena.c:5089 utils/adt/varlena.c:5272
#, c-format
msgid "number is out of range"
msgstr "Zahl ist außerhalb des gültigen Bereichs"
-#: utils/adt/varlena.c:5166 utils/adt/varlena.c:5194
+#: utils/adt/varlena.c:5153 utils/adt/varlena.c:5181
#, c-format
msgid "format specifies argument 0, but arguments are numbered from 1"
msgstr "Format gibt Argument 0 an, aber die Argumente sind von 1 an nummeriert"
-#: utils/adt/varlena.c:5187
+#: utils/adt/varlena.c:5174
#, c-format
msgid "width argument position must be ended by \"$\""
msgstr "Argumentposition der Breitenangabe muss mit »$« enden"
-#: utils/adt/varlena.c:5232
+#: utils/adt/varlena.c:5219
#, c-format
msgid "null values cannot be formatted as an SQL identifier"
msgstr "NULL-Werte können nicht als SQL-Bezeichner formatiert werden"
@@ -20478,145 +21635,169 @@ msgstr "Argument von ntile muss größer als null sein"
msgid "argument of nth_value must be greater than zero"
msgstr "Argument von nth_value muss größer als null sein"
-#: utils/adt/xml.c:171
+#: utils/adt/xml.c:217
#, c-format
msgid "unsupported XML feature"
msgstr "nicht unterstützte XML-Funktionalität"
-#: utils/adt/xml.c:172
+#: utils/adt/xml.c:218
#, c-format
msgid "This functionality requires the server to be built with libxml support."
msgstr "Diese Funktionalität verlangt, dass der Server mit Libxml-Unterstützung gebaut wird."
-#: utils/adt/xml.c:173
+#: utils/adt/xml.c:219
#, c-format
msgid "You need to rebuild PostgreSQL using --with-libxml."
msgstr "Sie müssen PostgreSQL mit --with-libxml neu bauen."
-#: utils/adt/xml.c:192 utils/mb/mbutils.c:523
+#: utils/adt/xml.c:238 utils/mb/mbutils.c:523
#, c-format
msgid "invalid encoding name \"%s\""
msgstr "ungültiger Kodierungsname »%s«"
-#: utils/adt/xml.c:435 utils/adt/xml.c:440
+#: utils/adt/xml.c:481 utils/adt/xml.c:486
#, c-format
msgid "invalid XML comment"
msgstr "ungültiger XML-Kommentar"
-#: utils/adt/xml.c:569
+#: utils/adt/xml.c:615
#, c-format
msgid "not an XML document"
msgstr "kein XML-Dokument"
-#: utils/adt/xml.c:728 utils/adt/xml.c:751
+#: utils/adt/xml.c:774 utils/adt/xml.c:797
#, c-format
msgid "invalid XML processing instruction"
msgstr "ungültige XML-Verarbeitungsanweisung"
-#: utils/adt/xml.c:729
+#: utils/adt/xml.c:775
#, c-format
msgid "XML processing instruction target name cannot be \"%s\"."
msgstr "Die Zielangabe der XML-Verarbeitungsanweisung darf nicht »%s« sein."
-#: utils/adt/xml.c:752
+#: utils/adt/xml.c:798
#, c-format
msgid "XML processing instruction cannot contain \"?>\"."
msgstr "XML-Verarbeitungsanweisung darf nicht »?>« enthalten."
-#: utils/adt/xml.c:831
+#: utils/adt/xml.c:877
#, c-format
msgid "xmlvalidate is not implemented"
msgstr "xmlvalidate ist nicht implementiert"
-#: utils/adt/xml.c:910
+#: utils/adt/xml.c:956
#, c-format
msgid "could not initialize XML library"
msgstr "konnte XML-Bibliothek nicht initialisieren"
-#: utils/adt/xml.c:911
+#: utils/adt/xml.c:957
#, c-format
msgid "libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u."
msgstr "libxml2 hat inkompatiblen char-Typ: sizeof(char)=%u, sizeof(xmlChar)=%u."
-#: utils/adt/xml.c:997
+#: utils/adt/xml.c:1043
#, c-format
msgid "could not set up XML error handler"
msgstr "konnte XML-Fehlerbehandlung nicht einrichten"
-#: utils/adt/xml.c:998
+#: utils/adt/xml.c:1044
#, c-format
msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with."
msgstr "Das deutet wahrscheinlich darauf hin, dass die verwendete Version von libxml2 nicht mit den Header-Dateien der Version, mit der PostgreSQL gebaut wurde, kompatibel ist."
-#: utils/adt/xml.c:1737
+#: utils/adt/xml.c:1794
msgid "Invalid character value."
msgstr "Ungültiger Zeichenwert."
-#: utils/adt/xml.c:1740
+#: utils/adt/xml.c:1797
msgid "Space required."
msgstr "Leerzeichen benötigt."
-#: utils/adt/xml.c:1743
+#: utils/adt/xml.c:1800
msgid "standalone accepts only 'yes' or 'no'."
msgstr "standalone akzeptiert nur »yes« oder »no«."
-#: utils/adt/xml.c:1746
+#: utils/adt/xml.c:1803
msgid "Malformed declaration: missing version."
msgstr "Fehlerhafte Deklaration: Version fehlt."
-#: utils/adt/xml.c:1749
+#: utils/adt/xml.c:1806
msgid "Missing encoding in text declaration."
msgstr "Fehlende Kodierung in Textdeklaration."
-#: utils/adt/xml.c:1752
+#: utils/adt/xml.c:1809
msgid "Parsing XML declaration: '?>' expected."
msgstr "Beim Parsen der XML-Deklaration: »?>« erwartet."
-#: utils/adt/xml.c:1755
+#: utils/adt/xml.c:1812
#, c-format
msgid "Unrecognized libxml error code: %d."
msgstr "Unbekannter Libxml-Fehlercode: %d."
-#: utils/adt/xml.c:2030
+#: utils/adt/xml.c:2087
#, c-format
msgid "XML does not support infinite date values."
msgstr "XML unterstützt keine unendlichen Datumswerte."
-#: utils/adt/xml.c:2052 utils/adt/xml.c:2079
+#: utils/adt/xml.c:2109 utils/adt/xml.c:2136
#, c-format
msgid "XML does not support infinite timestamp values."
msgstr "XML unterstützt keine unendlichen timestamp-Werte."
-#: utils/adt/xml.c:2470
+#: utils/adt/xml.c:2539
#, c-format
msgid "invalid query"
msgstr "ungültige Anfrage"
-#: utils/adt/xml.c:3795
+#: utils/adt/xml.c:3858
#, c-format
msgid "invalid array for XML namespace mapping"
msgstr "ungültiges Array for XML-Namensraumabbildung"
-#: utils/adt/xml.c:3796
+#: utils/adt/xml.c:3859
#, c-format
msgid "The array must be two-dimensional with length of the second axis equal to 2."
msgstr "Das Array muss zweidimensional sein und die Länge der zweiten Achse muss gleich 2 sein."
-#: utils/adt/xml.c:3820
+#: utils/adt/xml.c:3883
#, c-format
msgid "empty XPath expression"
msgstr "leerer XPath-Ausdruck"
-#: utils/adt/xml.c:3869
+#: utils/adt/xml.c:3927
#, c-format
msgid "neither namespace name nor URI may be null"
msgstr "weder Namensraumname noch URI dürfen NULL sein"
-#: utils/adt/xml.c:3876
+#: utils/adt/xml.c:3934
#, c-format
msgid "could not register XML namespace with name \"%s\" and URI \"%s\""
msgstr "konnte XML-Namensraum mit Namen »%s« und URI »%s« nicht registrieren"
+#: utils/adt/xml.c:4288
+#, fuzzy, c-format
+#| msgid "LIMIT #,# syntax is not supported"
+msgid "DEFAULT namespace is not supported"
+msgstr "Syntax LIMIT x,y wird nicht unterstützt"
+
+#: utils/adt/xml.c:4317
+#, fuzzy, c-format
+#| msgid "Quoted identifier must not be empty."
+msgid "row path filter must not be empty string"
+msgstr "Bezeichner in Anführungszeichen darf nicht leer sein."
+
+#: utils/adt/xml.c:4348
+#, fuzzy, c-format
+#| msgid "Quoted identifier must not be empty."
+msgid "column path filter must not be empty string"
+msgstr "Bezeichner in Anführungszeichen darf nicht leer sein."
+
+#: utils/adt/xml.c:4531
+#, fuzzy, c-format
+#| msgid "more than one row returned by a subquery used as an expression"
+msgid "more than one value returned by column XPath expression"
+msgstr "als Ausdruck verwendete Unteranfrage ergab mehr als eine Zeile"
+
#: utils/cache/lsyscache.c:2580 utils/cache/lsyscache.c:2613
#: utils/cache/lsyscache.c:2646 utils/cache/lsyscache.c:2679
#, c-format
@@ -20633,22 +21814,22 @@ msgstr "keine Eingabefunktion verfügbar für Typ %s"
msgid "no output function available for type %s"
msgstr "keine Ausgabefunktion verfügbar für Typ %s"
-#: utils/cache/plancache.c:720
+#: utils/cache/plancache.c:718
#, c-format
msgid "cached plan must not change result type"
msgstr "gecachter Plan darf den Ergebnistyp nicht ändern"
-#: utils/cache/relcache.c:5209
+#: utils/cache/relcache.c:5700
#, c-format
msgid "could not create relation-cache initialization file \"%s\": %m"
msgstr "konnte Initialisierungsdatei für Relationscache »%s« nicht erzeugen: %m"
-#: utils/cache/relcache.c:5211
+#: utils/cache/relcache.c:5702
#, c-format
msgid "Continuing anyway, but there's something wrong."
msgstr "Setze trotzdem fort, aber irgendwas stimmt nicht."
-#: utils/cache/relcache.c:5485
+#: utils/cache/relcache.c:5976
#, c-format
msgid "could not remove cache file \"%s\": %m"
msgstr "konnte Cache-Datei »%s« nicht löschen: %m"
@@ -20718,96 +21899,96 @@ msgstr "TRAP: %s(»%s«, Datei: »%s«, Zeile: %d)\n"
msgid "error occurred at %s:%d before error message processing is available\n"
msgstr "Fehler geschah bei %s:%d bevor Fehlermeldungsverarbeitung bereit war\n"
-#: utils/error/elog.c:1880
+#: utils/error/elog.c:1889
#, c-format
msgid "could not reopen file \"%s\" as stderr: %m"
msgstr "konnte Datei »%s« nicht als stderr neu öffnen: %m"
-#: utils/error/elog.c:1893
+#: utils/error/elog.c:1902
#, c-format
msgid "could not reopen file \"%s\" as stdout: %m"
msgstr "konnte Datei »%s« nicht als stdou neu öffnen: %m"
-#: utils/error/elog.c:2380 utils/error/elog.c:2397 utils/error/elog.c:2413
+#: utils/error/elog.c:2389 utils/error/elog.c:2406 utils/error/elog.c:2422
msgid "[unknown]"
msgstr "[unbekannt]"
-#: utils/error/elog.c:2872 utils/error/elog.c:3171 utils/error/elog.c:3279
+#: utils/error/elog.c:2882 utils/error/elog.c:3185 utils/error/elog.c:3293
msgid "missing error text"
msgstr "fehlender Fehlertext"
-#: utils/error/elog.c:2875 utils/error/elog.c:2878 utils/error/elog.c:3282
-#: utils/error/elog.c:3285
+#: utils/error/elog.c:2885 utils/error/elog.c:2888 utils/error/elog.c:3296
+#: utils/error/elog.c:3299
#, c-format
msgid " at character %d"
msgstr " bei Zeichen %d"
-#: utils/error/elog.c:2888 utils/error/elog.c:2895
+#: utils/error/elog.c:2898 utils/error/elog.c:2905
msgid "DETAIL: "
msgstr "DETAIL: "
-#: utils/error/elog.c:2902
+#: utils/error/elog.c:2912
msgid "HINT: "
msgstr "TIPP: "
-#: utils/error/elog.c:2909
+#: utils/error/elog.c:2919
msgid "QUERY: "
msgstr "ANFRAGE: "
-#: utils/error/elog.c:2916
+#: utils/error/elog.c:2926
msgid "CONTEXT: "
msgstr "ZUSAMMENHANG: "
-#: utils/error/elog.c:2926
+#: utils/error/elog.c:2936
#, c-format
msgid "LOCATION: %s, %s:%d\n"
msgstr "ORT: %s, %s:%d\n"
-#: utils/error/elog.c:2933
+#: utils/error/elog.c:2943
#, c-format
msgid "LOCATION: %s:%d\n"
msgstr "ORT: %s:%d\n"
-#: utils/error/elog.c:2947
+#: utils/error/elog.c:2957
msgid "STATEMENT: "
msgstr "ANWEISUNG: "
#. translator: This string will be truncated at 47
#. characters expanded.
-#: utils/error/elog.c:3400
+#: utils/error/elog.c:3414
#, c-format
msgid "operating system error %d"
msgstr "Betriebssystemfehler %d"
-#: utils/error/elog.c:3595
+#: utils/error/elog.c:3612
msgid "DEBUG"
msgstr "DEBUG"
-#: utils/error/elog.c:3599
+#: utils/error/elog.c:3616
msgid "LOG"
msgstr "LOG"
-#: utils/error/elog.c:3602
+#: utils/error/elog.c:3619
msgid "INFO"
msgstr "INFO"
-#: utils/error/elog.c:3605
+#: utils/error/elog.c:3622
msgid "NOTICE"
msgstr "HINWEIS"
-#: utils/error/elog.c:3608
+#: utils/error/elog.c:3625
msgid "WARNING"
msgstr "WARNUNG"
-#: utils/error/elog.c:3611
+#: utils/error/elog.c:3628
msgid "ERROR"
msgstr "FEHLER"
-#: utils/error/elog.c:3614
+#: utils/error/elog.c:3631
msgid "FATAL"
msgstr "FATAL"
-#: utils/error/elog.c:3617
+#: utils/error/elog.c:3634
msgid "PANIC"
msgstr "PANIK"
@@ -20816,7 +21997,7 @@ msgstr "PANIK"
msgid "could not find function \"%s\" in file \"%s\""
msgstr "konnte Funktion »%s« nicht in Datei »%s« finden"
-#: utils/fmgr/dfmgr.c:196 utils/fmgr/dfmgr.c:405 utils/fmgr/dfmgr.c:453
+#: utils/fmgr/dfmgr.c:196 utils/fmgr/dfmgr.c:413 utils/fmgr/dfmgr.c:461
#, c-format
msgid "could not access file \"%s\": %m"
msgstr "konnte nicht auf Datei »%s« zugreifen: %m"
@@ -20836,106 +22017,106 @@ msgstr "inkompatible Bibliothek »%s«: magischer Block fehlt"
msgid "Extension libraries are required to use the PG_MODULE_MAGIC macro."
msgstr "Erweiterungsbibliotheken müssen das Makro PG_MODULE_MAGIC verwenden."
-#: utils/fmgr/dfmgr.c:304
+#: utils/fmgr/dfmgr.c:314
#, c-format
msgid "incompatible library \"%s\": version mismatch"
msgstr "inkompatible Bibliothek »%s«: Version stimmt nicht überein"
-#: utils/fmgr/dfmgr.c:306
+#: utils/fmgr/dfmgr.c:316
#, c-format
-msgid "Server is version %d.%d, library is version %d.%d."
-msgstr "Serverversion ist %d.%d, Bibliotheksversion ist %d.%d."
+msgid "Server is version %d, library is version %s."
+msgstr "Serverversion ist %d, Bibliotheksversion ist %s."
-#: utils/fmgr/dfmgr.c:325
+#: utils/fmgr/dfmgr.c:333
#, c-format
msgid "Server has FUNC_MAX_ARGS = %d, library has %d."
msgstr "Server hat FUNC_MAX_ARGS = %d, Bibliothek hat %d."
-#: utils/fmgr/dfmgr.c:334
+#: utils/fmgr/dfmgr.c:342
#, c-format
msgid "Server has INDEX_MAX_KEYS = %d, library has %d."
msgstr "Server hat INDEX_MAX_KEYS = %d, Bibliothek hat %d."
-#: utils/fmgr/dfmgr.c:343
+#: utils/fmgr/dfmgr.c:351
#, c-format
msgid "Server has NAMEDATALEN = %d, library has %d."
msgstr "Server hat NAMEDATALEN = %d, Bibliothek hat %d."
-#: utils/fmgr/dfmgr.c:352
+#: utils/fmgr/dfmgr.c:360
#, c-format
msgid "Server has FLOAT4PASSBYVAL = %s, library has %s."
msgstr "Server hat FLOAT4PASSBYVAL = %s, Bibliothek hat %s."
-#: utils/fmgr/dfmgr.c:361
+#: utils/fmgr/dfmgr.c:369
#, c-format
msgid "Server has FLOAT8PASSBYVAL = %s, library has %s."
msgstr "Server hat FLOAT8PASSBYVAL = %s, Bibliothek hat %s."
-#: utils/fmgr/dfmgr.c:368
+#: utils/fmgr/dfmgr.c:376
msgid "Magic block has unexpected length or padding difference."
msgstr "Magischer Block hat unerwartete Länge oder unterschiedliches Padding."
-#: utils/fmgr/dfmgr.c:371
+#: utils/fmgr/dfmgr.c:379
#, c-format
msgid "incompatible library \"%s\": magic block mismatch"
msgstr "inkompatible Bibliothek »%s«: magischer Block stimmt überein"
-#: utils/fmgr/dfmgr.c:535
+#: utils/fmgr/dfmgr.c:543
#, c-format
msgid "access to library \"%s\" is not allowed"
msgstr "Zugriff auf Bibliothek »%s« ist nicht erlaubt"
-#: utils/fmgr/dfmgr.c:561
+#: utils/fmgr/dfmgr.c:569
#, c-format
msgid "invalid macro name in dynamic library path: %s"
msgstr "ungültiger Makroname in Parameter »dynamic_library_path«: %s"
-#: utils/fmgr/dfmgr.c:601
+#: utils/fmgr/dfmgr.c:609
#, c-format
msgid "zero-length component in parameter \"dynamic_library_path\""
msgstr "eine Komponente im Parameter »dynamic_library_path« hat Länge null"
-#: utils/fmgr/dfmgr.c:620
+#: utils/fmgr/dfmgr.c:628
#, c-format
msgid "component in parameter \"dynamic_library_path\" is not an absolute path"
msgstr "eine Komponente im Parameter »dynamic_library_path« ist kein absoluter Pfad"
-#: utils/fmgr/fmgr.c:272
+#: utils/fmgr/fmgr.c:271
#, c-format
msgid "internal function \"%s\" is not in internal lookup table"
msgstr "interne Funktion »%s« ist nicht in der internen Suchtabelle"
-#: utils/fmgr/fmgr.c:479
+#: utils/fmgr/fmgr.c:478
#, c-format
msgid "unrecognized API version %d reported by info function \"%s\""
msgstr "Info-Funktion »%2$s« berichtete unbekannte API-Version %1$d"
-#: utils/fmgr/fmgr.c:849 utils/fmgr/fmgr.c:2106
+#: utils/fmgr/fmgr.c:848 utils/fmgr/fmgr.c:2068
#, c-format
msgid "function %u has too many arguments (%d, maximum is %d)"
msgstr "Funktion %u hat zu viele Argumente (%d, Maximum ist %d)"
-#: utils/fmgr/fmgr.c:2527
+#: utils/fmgr/fmgr.c:2443
#, c-format
msgid "language validation function %u called for language %u instead of %u"
msgstr "Sprachvalidierungsfunktion %u wurde für Sprache %u statt %u aufgerufen"
-#: utils/fmgr/funcapi.c:355
+#: utils/fmgr/funcapi.c:354
#, c-format
msgid "could not determine actual result type for function \"%s\" declared to return type %s"
msgstr "konnte tatsächlichen Ergebnistyp von Funktion »%s« mit deklarierten Rückgabetyp %s nicht bestimmen"
-#: utils/fmgr/funcapi.c:1342 utils/fmgr/funcapi.c:1373
+#: utils/fmgr/funcapi.c:1341 utils/fmgr/funcapi.c:1372
#, c-format
msgid "number of aliases does not match number of columns"
msgstr "Anzahl der Aliasnamen stimmt nicht mit der Anzahl der Spalten überein"
-#: utils/fmgr/funcapi.c:1367
+#: utils/fmgr/funcapi.c:1366
#, c-format
msgid "no column alias was provided"
msgstr "Spaltenalias fehlt"
-#: utils/fmgr/funcapi.c:1391
+#: utils/fmgr/funcapi.c:1390
#, c-format
msgid "could not determine row description for function returning record"
msgstr "konnte Zeilenbeschreibung für Funktion, die »record« zurückgibt, nicht ermitteln"
@@ -20945,7 +22126,7 @@ msgstr "konnte Zeilenbeschreibung für Funktion, die »record« zurückgibt, nic
msgid "could not change directory to \"%s\": %m"
msgstr "konnte nicht in Verzeichnis »%s« wechseln: %m"
-#: utils/init/miscinit.c:449 utils/misc/guc.c:6014
+#: utils/init/miscinit.c:449 utils/misc/guc.c:6082
#, c-format
msgid "cannot set parameter \"%s\" within security-restricted operation"
msgstr "kann Parameter »%s« nicht in einer sicherheitsbeschränkten Operation setzen"
@@ -21056,7 +22237,7 @@ msgstr "Die Datei ist anscheinend aus Versehen übrig geblieben, konnte aber nic
msgid "could not write lock file \"%s\": %m"
msgstr "konnte Sperrdatei »%s« nicht schreiben: %m"
-#: utils/init/miscinit.c:1172 utils/init/miscinit.c:1301 utils/misc/guc.c:8808
+#: utils/init/miscinit.c:1172 utils/init/miscinit.c:1301 utils/misc/guc.c:8883
#, c-format
msgid "could not read from file \"%s\": %m"
msgstr "konnte nicht aus Datei »%s« lesen: %m"
@@ -21071,12 +22252,12 @@ msgstr "konnte Datei »%s« nicht öffnen: %m; setze trotzdem fort"
msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld"
msgstr "Sperrdatei »%s« enthält falsche PID: %ld statt %ld"
-#: utils/init/miscinit.c:1356 utils/init/miscinit.c:1369
+#: utils/init/miscinit.c:1353 utils/init/miscinit.c:1369
#, c-format
msgid "\"%s\" is not a valid data directory"
msgstr "»%s« ist kein gültiges Datenverzeichnis"
-#: utils/init/miscinit.c:1358
+#: utils/init/miscinit.c:1355
#, c-format
msgid "File \"%s\" is missing."
msgstr "Die Datei »%s« fehlt."
@@ -21093,160 +22274,160 @@ msgstr "Sie müssen möglicherweise initdb ausführen."
#: utils/init/miscinit.c:1381
#, c-format
-msgid "The data directory was initialized by PostgreSQL version %ld.%ld, which is not compatible with this version %s."
-msgstr "Das Datenverzeichnis wurde von PostgreSQL Version %ld.%ld initialisiert, welche nicht mit dieser Version %s kompatibel ist."
+msgid "The data directory was initialized by PostgreSQL version %s, which is not compatible with this version %s."
+msgstr "Das Datenverzeichnis wurde von PostgreSQL Version %s initialisiert, welche nicht mit dieser Version %s kompatibel ist."
#: utils/init/miscinit.c:1452
#, c-format
msgid "loaded library \"%s\""
msgstr "Bibliothek »%s« geladen"
-#: utils/init/postinit.c:253
+#: utils/init/postinit.c:251
#, c-format
msgid "replication connection authorized: user=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)"
msgstr "Replikationsverbindung autorisiert: Benutzer=%s SSL an (Protokoll=%s, Verschlüsselungsmethode=%s, Komprimierung=%s)"
-#: utils/init/postinit.c:255 utils/init/postinit.c:269
+#: utils/init/postinit.c:253 utils/init/postinit.c:267
msgid "off"
msgstr "aus"
-#: utils/init/postinit.c:255 utils/init/postinit.c:269
+#: utils/init/postinit.c:253 utils/init/postinit.c:267
msgid "on"
msgstr "an"
-#: utils/init/postinit.c:259
+#: utils/init/postinit.c:257
#, c-format
msgid "replication connection authorized: user=%s"
msgstr "Replikationsverbindung autorisiert: Benutzer=%s"
-#: utils/init/postinit.c:267
+#: utils/init/postinit.c:265
#, c-format
msgid "connection authorized: user=%s database=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)"
msgstr "Verbindung autorisiert: Benutzer=%s Datenbank=%s SSL an (Protokoll=%s, Verschlüsselungsmethode=%s, Komprimierung=%s)"
-#: utils/init/postinit.c:273
+#: utils/init/postinit.c:271
#, c-format
msgid "connection authorized: user=%s database=%s"
msgstr "Verbindung autorisiert: Benutzer=%s Datenbank=%s"
-#: utils/init/postinit.c:305
+#: utils/init/postinit.c:303
#, c-format
msgid "database \"%s\" has disappeared from pg_database"
msgstr "Datenbank »%s« ist aus pg_database verschwunden"
-#: utils/init/postinit.c:307
+#: utils/init/postinit.c:305
#, c-format
msgid "Database OID %u now seems to belong to \"%s\"."
msgstr "Datenbank-OID %u gehört jetzt anscheinend zu »%s«."
-#: utils/init/postinit.c:327
+#: utils/init/postinit.c:325
#, c-format
msgid "database \"%s\" is not currently accepting connections"
msgstr "Datenbank »%s« akzeptiert gegenwärtig keine Verbindungen"
-#: utils/init/postinit.c:340
+#: utils/init/postinit.c:338
#, c-format
msgid "permission denied for database \"%s\""
msgstr "keine Berechtigung für Datenbank »%s«"
-#: utils/init/postinit.c:341
+#: utils/init/postinit.c:339
#, c-format
msgid "User does not have CONNECT privilege."
msgstr "Benutzer hat das CONNECT-Privileg nicht."
-#: utils/init/postinit.c:358
+#: utils/init/postinit.c:356
#, c-format
msgid "too many connections for database \"%s\""
msgstr "zu viele Verbindungen für Datenbank »%s«"
-#: utils/init/postinit.c:380 utils/init/postinit.c:387
+#: utils/init/postinit.c:378 utils/init/postinit.c:385
#, c-format
msgid "database locale is incompatible with operating system"
msgstr "Datenbank-Locale ist inkompatibel mit Betriebssystem"
-#: utils/init/postinit.c:381
+#: utils/init/postinit.c:379
#, c-format
msgid "The database was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()."
msgstr "Die Datenbank wurde mit LC_COLLATE »%s« initialisiert, was von setlocale() nicht erkannt wird."
-#: utils/init/postinit.c:383 utils/init/postinit.c:390
+#: utils/init/postinit.c:381 utils/init/postinit.c:388
#, c-format
msgid "Recreate the database with another locale or install the missing locale."
msgstr "Erzeugen Sie die Datenbank neu mit einer anderen Locale oder installieren Sie die fehlende Locale."
-#: utils/init/postinit.c:388
+#: utils/init/postinit.c:386
#, c-format
msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()."
msgstr "Die Datenbank wurde mit LC_CTYPE »%s« initialisiert, was von setlocale() nicht erkannt wird."
-#: utils/init/postinit.c:716
+#: utils/init/postinit.c:714
#, c-format
msgid "no roles are defined in this database system"
msgstr "in diesem Datenbanksystem sind keine Rollen definiert"
-#: utils/init/postinit.c:717
+#: utils/init/postinit.c:715
#, c-format
msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;."
msgstr "Sie sollten sofort CREATE USER \"%s\" SUPERUSER; ausführen."
-#: utils/init/postinit.c:753
+#: utils/init/postinit.c:751
#, c-format
msgid "new replication connections are not allowed during database shutdown"
msgstr "während des Herunterfahrens der Datenbank sind keine neuen Replikationsverbindungen erlaubt"
-#: utils/init/postinit.c:757
+#: utils/init/postinit.c:755
#, c-format
msgid "must be superuser to connect during database shutdown"
msgstr "nur Superuser können während des Herunterfahrens der Datenbank verbinden"
-#: utils/init/postinit.c:767
+#: utils/init/postinit.c:765
#, c-format
msgid "must be superuser to connect in binary upgrade mode"
msgstr "nur Superuser können im Binary-Upgrade-Modus verbinden"
-#: utils/init/postinit.c:781
+#: utils/init/postinit.c:779
#, c-format
msgid "remaining connection slots are reserved for non-replication superuser connections"
msgstr "die verbleibenden Verbindungen sind für Superuser auf Nicht-Replikationsverbindungen reserviert"
-#: utils/init/postinit.c:791
+#: utils/init/postinit.c:789
#, c-format
msgid "must be superuser or replication role to start walsender"
msgstr "nur Superuser und Replikationsrollen können WAL-Sender starten"
-#: utils/init/postinit.c:860
+#: utils/init/postinit.c:858
#, c-format
msgid "database %u does not exist"
msgstr "Datenbank %u existiert nicht"
-#: utils/init/postinit.c:946
+#: utils/init/postinit.c:944
#, c-format
msgid "It seems to have just been dropped or renamed."
msgstr "Sie wurde anscheinend gerade gelöscht oder umbenannt."
-#: utils/init/postinit.c:964
+#: utils/init/postinit.c:962
#, c-format
msgid "The database subdirectory \"%s\" is missing."
msgstr "Das Datenbankunterverzeichnis »%s« fehlt."
-#: utils/init/postinit.c:969
+#: utils/init/postinit.c:967
#, c-format
msgid "could not access directory \"%s\": %m"
msgstr "konnte nicht auf Verzeichnis »%s« zugreifen: %m"
-#: utils/mb/conv.c:405 utils/mb/conv.c:591
+#: utils/mb/conv.c:488 utils/mb/conv.c:679
#, c-format
msgid "invalid encoding number: %d"
msgstr "ungültige Kodierungsnummer: %d"
-#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:137
-#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:169
+#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:122
+#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:154
#, c-format
msgid "unexpected encoding ID %d for ISO 8859 character sets"
msgstr "unerwartete Kodierungs-ID %d für ISO-8859-Zeichensatz"
-#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:127
-#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:159
+#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:103
+#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:135
#, c-format
msgid "unexpected encoding ID %d for WIN character sets"
msgstr "unerwartete Kodierungs-ID %d für WIN-Zeichensatz"
@@ -21301,1514 +22482,1544 @@ msgstr "ungültige Byte-Sequenz für Kodierung »%s«: %s"
msgid "character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\""
msgstr "Zeichen mit Byte-Folge %s in Kodierung »%s« hat keine Entsprechung in Kodierung »%s«"
-#: utils/misc/guc.c:548
+#: utils/misc/guc.c:573
msgid "Ungrouped"
msgstr "Ungruppiert"
-#: utils/misc/guc.c:550
+#: utils/misc/guc.c:575
msgid "File Locations"
msgstr "Dateipfade"
-#: utils/misc/guc.c:552
+#: utils/misc/guc.c:577
msgid "Connections and Authentication"
msgstr "Verbindungen und Authentifizierung"
-#: utils/misc/guc.c:554
+#: utils/misc/guc.c:579
msgid "Connections and Authentication / Connection Settings"
msgstr "Verbindungen und Authentifizierung / Verbindungseinstellungen"
-#: utils/misc/guc.c:556
+#: utils/misc/guc.c:581
msgid "Connections and Authentication / Security and Authentication"
msgstr "Verbindungen und Authentifizierung / Sicherheit und Authentifizierung"
-#: utils/misc/guc.c:558
+#: utils/misc/guc.c:583
msgid "Resource Usage"
msgstr "Resourcenbenutzung"
-#: utils/misc/guc.c:560
+#: utils/misc/guc.c:585
msgid "Resource Usage / Memory"
msgstr "Resourcenbenutzung / Speicher"
-#: utils/misc/guc.c:562
+#: utils/misc/guc.c:587
msgid "Resource Usage / Disk"
msgstr "Resourcenbenutzung / Festplatte"
-#: utils/misc/guc.c:564
+#: utils/misc/guc.c:589
msgid "Resource Usage / Kernel Resources"
msgstr "Resourcenbenutzung / Kernelresourcen"
-#: utils/misc/guc.c:566
+#: utils/misc/guc.c:591
msgid "Resource Usage / Cost-Based Vacuum Delay"
msgstr "Resourcenbenutzung / Kostenbasierte Vacuum-Verzögerung"
-#: utils/misc/guc.c:568
+#: utils/misc/guc.c:593
msgid "Resource Usage / Background Writer"
msgstr "Resourcenbenutzung / Background-Writer"
-#: utils/misc/guc.c:570
+#: utils/misc/guc.c:595
msgid "Resource Usage / Asynchronous Behavior"
msgstr "Resourcenbenutzung / Asynchrones Verhalten"
-#: utils/misc/guc.c:572
+#: utils/misc/guc.c:597
msgid "Write-Ahead Log"
msgstr "Write-Ahead-Log"
-#: utils/misc/guc.c:574
+#: utils/misc/guc.c:599
msgid "Write-Ahead Log / Settings"
msgstr "Write-Ahead-Log / Einstellungen"
-#: utils/misc/guc.c:576
+#: utils/misc/guc.c:601
msgid "Write-Ahead Log / Checkpoints"
msgstr "Write-Ahead-Log / Checkpoints"
-#: utils/misc/guc.c:578
+#: utils/misc/guc.c:603
msgid "Write-Ahead Log / Archiving"
msgstr "Write-Ahead-Log / Archivierung"
-#: utils/misc/guc.c:580
+#: utils/misc/guc.c:605
msgid "Replication"
msgstr "Replikation"
-#: utils/misc/guc.c:582
+#: utils/misc/guc.c:607
msgid "Replication / Sending Servers"
msgstr "Replikation / sendende Server"
-#: utils/misc/guc.c:584
+#: utils/misc/guc.c:609
msgid "Replication / Master Server"
msgstr "Replikation / Master-Server"
-#: utils/misc/guc.c:586
+#: utils/misc/guc.c:611
msgid "Replication / Standby Servers"
msgstr "Replikation / Standby-Server"
-#: utils/misc/guc.c:588
+#: utils/misc/guc.c:613
msgid "Query Tuning"
msgstr "Anfragetuning"
-#: utils/misc/guc.c:590
+#: utils/misc/guc.c:615
msgid "Query Tuning / Planner Method Configuration"
msgstr "Anfragetuning / Planermethoden"
-#: utils/misc/guc.c:592
+#: utils/misc/guc.c:617
msgid "Query Tuning / Planner Cost Constants"
msgstr "Anfragetuning / Planerkosten"
-#: utils/misc/guc.c:594
+#: utils/misc/guc.c:619
msgid "Query Tuning / Genetic Query Optimizer"
msgstr "Anfragetuning / Genetischer Anfrageoptimierer"
-#: utils/misc/guc.c:596
+#: utils/misc/guc.c:621
msgid "Query Tuning / Other Planner Options"
msgstr "Anfragetuning / Andere Planeroptionen"
-#: utils/misc/guc.c:598
+#: utils/misc/guc.c:623
msgid "Reporting and Logging"
msgstr "Berichte und Logging"
-#: utils/misc/guc.c:600
+#: utils/misc/guc.c:625
msgid "Reporting and Logging / Where to Log"
msgstr "Berichte und Logging / Wohin geloggt wird"
-#: utils/misc/guc.c:602
+#: utils/misc/guc.c:627
msgid "Reporting and Logging / When to Log"
msgstr "Berichte und Logging / Wann geloggt wird"
-#: utils/misc/guc.c:604
+#: utils/misc/guc.c:629
msgid "Reporting and Logging / What to Log"
msgstr "Berichte und Logging / Was geloggt wird"
-#: utils/misc/guc.c:606
+#: utils/misc/guc.c:631
msgid "Process Title"
msgstr "Prozesstitel"
-#: utils/misc/guc.c:608
+#: utils/misc/guc.c:633
msgid "Statistics"
msgstr "Statistiken"
-#: utils/misc/guc.c:610
+#: utils/misc/guc.c:635
msgid "Statistics / Monitoring"
msgstr "Statistiken / Überwachung"
-#: utils/misc/guc.c:612
+#: utils/misc/guc.c:637
msgid "Statistics / Query and Index Statistics Collector"
msgstr "Statistiken / Statistiksammler für Anfragen und Indexe"
-#: utils/misc/guc.c:614
+#: utils/misc/guc.c:639
msgid "Autovacuum"
msgstr "Autovacuum"
-#: utils/misc/guc.c:616
+#: utils/misc/guc.c:641
msgid "Client Connection Defaults"
msgstr "Standardeinstellungen für Clientverbindungen"
-#: utils/misc/guc.c:618
+#: utils/misc/guc.c:643
msgid "Client Connection Defaults / Statement Behavior"
msgstr "Standardeinstellungen für Clientverbindungen / Anweisungsverhalten"
-#: utils/misc/guc.c:620
+#: utils/misc/guc.c:645
msgid "Client Connection Defaults / Locale and Formatting"
msgstr "Standardeinstellungen für Clientverbindungen / Locale und Formatierung"
-#: utils/misc/guc.c:622
+#: utils/misc/guc.c:647
msgid "Client Connection Defaults / Shared Library Preloading"
msgstr "Standardeinstellungen für Clientverbindungen / Shared Library Preloading"
-#: utils/misc/guc.c:624
+#: utils/misc/guc.c:649
msgid "Client Connection Defaults / Other Defaults"
msgstr "Standardeinstellungen für Clientverbindungen / Andere"
-#: utils/misc/guc.c:626
+#: utils/misc/guc.c:651
msgid "Lock Management"
msgstr "Sperrenverwaltung"
-#: utils/misc/guc.c:628
+#: utils/misc/guc.c:653
msgid "Version and Platform Compatibility"
msgstr "Versions- und Plattformkompatibilität"
-#: utils/misc/guc.c:630
+#: utils/misc/guc.c:655
msgid "Version and Platform Compatibility / Previous PostgreSQL Versions"
msgstr "Versions- und Plattformkompatibilität / Frühere PostgreSQL-Versionen"
-#: utils/misc/guc.c:632
+#: utils/misc/guc.c:657
msgid "Version and Platform Compatibility / Other Platforms and Clients"
msgstr "Versions- und Plattformkompatibilität / Andere Plattformen und Clients"
-#: utils/misc/guc.c:634
+#: utils/misc/guc.c:659
msgid "Error Handling"
msgstr "Fehlerbehandlung"
-#: utils/misc/guc.c:636
+#: utils/misc/guc.c:661
msgid "Preset Options"
msgstr "Voreingestellte Optionen"
-#: utils/misc/guc.c:638
+#: utils/misc/guc.c:663
msgid "Customized Options"
msgstr "Angepasste Optionen"
-#: utils/misc/guc.c:640
+#: utils/misc/guc.c:665
msgid "Developer Options"
msgstr "Entwickleroptionen"
-#: utils/misc/guc.c:697
+#: utils/misc/guc.c:722
msgid "Valid units for this parameter are \"kB\", \"MB\", \"GB\", and \"TB\"."
msgstr "Gültige Einheiten für diesen Parameter sind »kB«, »MB«, »GB« und »TB«."
-#: utils/misc/guc.c:724
+#: utils/misc/guc.c:749
msgid "Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\"."
msgstr "Gültige Einheiten für diesen Parameter sind »ms«, »s«, »min«, »h« und »d«."
-#: utils/misc/guc.c:783
+#: utils/misc/guc.c:808
msgid "Enables the planner's use of sequential-scan plans."
msgstr "Ermöglicht sequenzielle Scans in Planer."
-#: utils/misc/guc.c:792
+#: utils/misc/guc.c:817
msgid "Enables the planner's use of index-scan plans."
msgstr "Ermöglicht Index-Scans im Planer."
-#: utils/misc/guc.c:801
+#: utils/misc/guc.c:826
msgid "Enables the planner's use of index-only-scan plans."
msgstr "Ermöglicht Index-Only-Scans im Planer."
-#: utils/misc/guc.c:810
+#: utils/misc/guc.c:835
msgid "Enables the planner's use of bitmap-scan plans."
msgstr "Ermöglicht Bitmap-Scans im Planer."
-#: utils/misc/guc.c:819
+#: utils/misc/guc.c:844
msgid "Enables the planner's use of TID scan plans."
msgstr "Ermöglicht TID-Scans im Planer."
-#: utils/misc/guc.c:828
+#: utils/misc/guc.c:853
msgid "Enables the planner's use of explicit sort steps."
msgstr "Ermöglicht Sortierschritte im Planer."
-#: utils/misc/guc.c:837
+#: utils/misc/guc.c:862
msgid "Enables the planner's use of hashed aggregation plans."
msgstr "Ermöglicht Hash-Aggregierung im Planer."
-#: utils/misc/guc.c:846
+#: utils/misc/guc.c:871
msgid "Enables the planner's use of materialization."
msgstr "Ermöglicht Materialisierung im Planer."
-#: utils/misc/guc.c:855
+#: utils/misc/guc.c:880
msgid "Enables the planner's use of nested-loop join plans."
msgstr "Ermöglicht Nested-Loop-Verbunde im Planer."
-#: utils/misc/guc.c:864
+#: utils/misc/guc.c:889
msgid "Enables the planner's use of merge join plans."
msgstr "Ermöglicht Merge-Verbunde im Planer."
-#: utils/misc/guc.c:873
+#: utils/misc/guc.c:898
msgid "Enables the planner's use of hash join plans."
msgstr "Ermöglicht Hash-Verbunde im Planer."
-#: utils/misc/guc.c:883
+#: utils/misc/guc.c:907
+#, fuzzy
+#| msgid "Enables the planner's use of merge join plans."
+msgid "Enables the planner's use of gather merge plans."
+msgstr "Ermöglicht Merge-Verbunde im Planer."
+
+#: utils/misc/guc.c:917
msgid "Enables genetic query optimization."
msgstr "Ermöglicht genetische Anfrageoptimierung."
-#: utils/misc/guc.c:884
+#: utils/misc/guc.c:918
msgid "This algorithm attempts to do planning without exhaustive searching."
msgstr "Dieser Algorithmus versucht das Planen ohne erschöpfende Suche durchzuführen."
-#: utils/misc/guc.c:894
+#: utils/misc/guc.c:928
msgid "Shows whether the current user is a superuser."
msgstr "Zeigt, ob der aktuelle Benutzer ein Superuser ist."
-#: utils/misc/guc.c:904
+#: utils/misc/guc.c:938
msgid "Enables advertising the server via Bonjour."
msgstr "Ermöglicht die Bekanntgabe des Servers mit Bonjour."
-#: utils/misc/guc.c:913
+#: utils/misc/guc.c:947
msgid "Collects transaction commit time."
msgstr "Sammelt Commit-Timestamps von Transaktionen."
-#: utils/misc/guc.c:922
+#: utils/misc/guc.c:956
msgid "Enables SSL connections."
msgstr "Ermöglicht SSL-Verbindungen."
-#: utils/misc/guc.c:931
+#: utils/misc/guc.c:965
msgid "Give priority to server ciphersuite order."
msgstr "Der Ciphersuite-Reihenfolge des Servers Vorrang geben."
-#: utils/misc/guc.c:940
+#: utils/misc/guc.c:974
msgid "Forces synchronization of updates to disk."
msgstr "Erzwingt die Synchronisierung von Aktualisierungen auf Festplatte."
-#: utils/misc/guc.c:941
+#: utils/misc/guc.c:975
msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This insures that a database cluster will recover to a consistent state after an operating system or hardware crash."
msgstr "Der Server verwendet den Systemaufruf fsync() an mehreren Stellen, um sicherzustellen, dass Datenänderungen physikalisch auf die Festplatte geschrieben werden. Das stellt sicher, dass der Datenbankcluster nach einem Betriebssystemabsturz oder Hardwarefehler in einem korrekten Zustand wiederhergestellt werden kann."
-#: utils/misc/guc.c:952
+#: utils/misc/guc.c:986
msgid "Continues processing after a checksum failure."
msgstr "Setzt die Verarbeitung trotz Prüfsummenfehler fort."
-#: utils/misc/guc.c:953
+#: utils/misc/guc.c:987
msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled."
msgstr "Wenn eine fehlerhafte Prüfsumme entdeckt wird, gibt PostgreSQL normalerweise ein Fehler aus und bricht die aktuelle Transaktion ab. Wenn »ignore_checksum_failure« an ist, dann wird der Fehler ignoriert (aber trotzdem eine Warnung ausgegeben) und die Verarbeitung geht weiter. Dieses Verhalten kann Abstürze und andere ernsthafte Probleme verursachen. Es hat keine Auswirkungen, wenn Prüfsummen nicht eingeschaltet sind."
-#: utils/misc/guc.c:967
+#: utils/misc/guc.c:1001
msgid "Continues processing past damaged page headers."
msgstr "Setzt die Verarbeitung trotz kaputter Seitenköpfe fort."
-#: utils/misc/guc.c:968
+#: utils/misc/guc.c:1002
msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting zero_damaged_pages to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page."
msgstr "Wenn ein kaputter Seitenkopf entdeckt wird, gibt PostgreSQL normalerweise einen Fehler aus und bricht die aktuelle Transaktion ab. Wenn »zero_damaged_pages« an ist, dann wird eine Warnung ausgegeben, die kaputte Seite mit Nullen gefüllt und die Verarbeitung geht weiter. Dieses Verhalten zerstört Daten, nämlich alle Zeilen in der kaputten Seite."
-#: utils/misc/guc.c:981
+#: utils/misc/guc.c:1015
msgid "Writes full pages to WAL when first modified after a checkpoint."
msgstr "Schreibt volle Seiten in den WAL, sobald sie nach einem Checkpoint geändert werden."
-#: utils/misc/guc.c:982
+#: utils/misc/guc.c:1016
msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible."
msgstr "Ein Seitenschreibvorgang während eines Betriebssystemabsturzes könnte eventuell nur teilweise geschrieben worden sein. Bei der Wiederherstellung sind die im WAL gespeicherten Zeilenänderungen nicht ausreichend. Diese Option schreibt Seiten, sobald sie nach einem Checkpoint geändert worden sind, damit eine volle Wiederherstellung möglich ist."
-#: utils/misc/guc.c:995
+#: utils/misc/guc.c:1029
msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modifications."
msgstr "Schreibt volle Seiten in den WAL, sobald sie nach einem Checkpoint geändert werden, auch für nicht kritische Änderungen."
-#: utils/misc/guc.c:1005
+#: utils/misc/guc.c:1039
msgid "Compresses full-page writes written in WAL file."
msgstr "Komprimiert in WAL-Dateien geschriebene volle Seiten."
-#: utils/misc/guc.c:1015
+#: utils/misc/guc.c:1049
msgid "Logs each checkpoint."
msgstr "Schreibt jeden Checkpoint in den Log."
-#: utils/misc/guc.c:1024
+#: utils/misc/guc.c:1058
msgid "Logs each successful connection."
msgstr "Schreibt jede erfolgreiche Verbindung in den Log."
-#: utils/misc/guc.c:1033
+#: utils/misc/guc.c:1067
msgid "Logs end of a session, including duration."
msgstr "Schreibt jedes Verbindungsende mit Sitzungszeit in den Log."
-#: utils/misc/guc.c:1042
+#: utils/misc/guc.c:1076
msgid "Logs each replication command."
msgstr "Schreibt jeden Replikationsbefehl in den Log."
-#: utils/misc/guc.c:1051
+#: utils/misc/guc.c:1085
msgid "Shows whether the running server has assertion checks enabled."
msgstr "Zeigt, ob der laufende Server Assertion-Prüfungen aktiviert hat."
-#: utils/misc/guc.c:1066
+#: utils/misc/guc.c:1100
msgid "Terminate session on any error."
msgstr "Sitzung bei jedem Fehler abbrechen."
-#: utils/misc/guc.c:1075
+#: utils/misc/guc.c:1109
msgid "Reinitialize server after backend crash."
msgstr "Server nach Absturz eines Serverprozesses reinitialisieren."
-#: utils/misc/guc.c:1085
+#: utils/misc/guc.c:1119
msgid "Logs the duration of each completed SQL statement."
msgstr "Loggt die Dauer jeder abgeschlossenen SQL-Anweisung."
-#: utils/misc/guc.c:1094
+#: utils/misc/guc.c:1128
msgid "Logs each query's parse tree."
msgstr "Scheibt den Parsebaum jeder Anfrage in den Log."
-#: utils/misc/guc.c:1103
+#: utils/misc/guc.c:1137
msgid "Logs each query's rewritten parse tree."
msgstr "Schreibt den umgeschriebenen Parsebaum jeder Anfrage in den Log."
-#: utils/misc/guc.c:1112
+#: utils/misc/guc.c:1146
msgid "Logs each query's execution plan."
msgstr "Schreibt den Ausführungsplan jeder Anfrage in den Log."
-#: utils/misc/guc.c:1121
+#: utils/misc/guc.c:1155
msgid "Indents parse and plan tree displays."
msgstr "Rückt die Anzeige von Parse- und Planbäumen ein."
-#: utils/misc/guc.c:1130
+#: utils/misc/guc.c:1164
msgid "Writes parser performance statistics to the server log."
msgstr "Schreibt Parser-Leistungsstatistiken in den Serverlog."
-#: utils/misc/guc.c:1139
+#: utils/misc/guc.c:1173
msgid "Writes planner performance statistics to the server log."
msgstr "Schreibt Planer-Leistungsstatistiken in den Serverlog."
-#: utils/misc/guc.c:1148
+#: utils/misc/guc.c:1182
msgid "Writes executor performance statistics to the server log."
msgstr "Schreibt Executor-Leistungsstatistiken in den Serverlog."
-#: utils/misc/guc.c:1157
+#: utils/misc/guc.c:1191
msgid "Writes cumulative performance statistics to the server log."
msgstr "Schreibt Gesamtleistungsstatistiken in den Serverlog."
-#: utils/misc/guc.c:1167
+#: utils/misc/guc.c:1201
msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations."
msgstr "Loggt Statistiken über Systemressourcen (Speicher und CPU) während diverser B-Baum-Operationen."
-#: utils/misc/guc.c:1179
+#: utils/misc/guc.c:1213
msgid "Collects information about executing commands."
msgstr "Sammelt Informationen über ausgeführte Befehle."
-#: utils/misc/guc.c:1180
+#: utils/misc/guc.c:1214
msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution."
msgstr "Schaltet die Sammlung von Informationen über den aktuell ausgeführten Befehl jeder Sitzung ein, einschließlich der Zeit, and dem die Befehlsausführung begann."
-#: utils/misc/guc.c:1190
+#: utils/misc/guc.c:1224
msgid "Collects statistics on database activity."
msgstr "Sammelt Statistiken über Datenbankaktivität."
-#: utils/misc/guc.c:1199
+#: utils/misc/guc.c:1233
msgid "Collects timing statistics for database I/O activity."
msgstr "Sammelt Zeitmessungsstatistiken über Datenbank-I/O-Aktivität."
-#: utils/misc/guc.c:1209
+#: utils/misc/guc.c:1243
msgid "Updates the process title to show the active SQL command."
msgstr "Der Prozesstitel wird aktualisiert, um den aktuellen SQL-Befehl anzuzeigen."
-#: utils/misc/guc.c:1210
+#: utils/misc/guc.c:1244
msgid "Enables updating of the process title every time a new SQL command is received by the server."
msgstr "Ermöglicht das Aktualisieren des Prozesstitels bei jedem von Server empfangenen neuen SQL-Befehl."
-#: utils/misc/guc.c:1219
+#: utils/misc/guc.c:1257
msgid "Starts the autovacuum subprocess."
msgstr "Startet den Autovacuum-Prozess."
-#: utils/misc/guc.c:1229
+#: utils/misc/guc.c:1267
msgid "Generates debugging output for LISTEN and NOTIFY."
msgstr "Erzeugt Debug-Ausgabe für LISTEN und NOTIFY."
-#: utils/misc/guc.c:1241
+#: utils/misc/guc.c:1279
msgid "Emits information about lock usage."
msgstr "Gibt Informationen über Sperrenverwendung aus."
-#: utils/misc/guc.c:1251
+#: utils/misc/guc.c:1289
msgid "Emits information about user lock usage."
msgstr "Gibt Informationen über Benutzersperrenverwendung aus."
-#: utils/misc/guc.c:1261
+#: utils/misc/guc.c:1299
msgid "Emits information about lightweight lock usage."
msgstr "Gibt Informationen über die Verwendung von Lightweight Locks aus."
-#: utils/misc/guc.c:1271
+#: utils/misc/guc.c:1309
msgid "Dumps information about all current locks when a deadlock timeout occurs."
msgstr "Gibt Informationen über alle aktuellen Sperren aus, wenn eine Verklemmung auftritt."
-#: utils/misc/guc.c:1283
+#: utils/misc/guc.c:1321
msgid "Logs long lock waits."
msgstr "Schreibt Meldungen über langes Warten auf Sperren in den Log."
-#: utils/misc/guc.c:1293
+#: utils/misc/guc.c:1331
msgid "Logs the host name in the connection logs."
msgstr "Schreibt den Hostnamen jeder Verbindung in den Log."
-#: utils/misc/guc.c:1294
+#: utils/misc/guc.c:1332
msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty."
msgstr "In der Standardeinstellung zeigen die Verbindungslogs nur die IP-Adresse der Clienthosts. Wenn Sie den Hostnamen auch anzeigen wollen, dann können Sie diese Option anschalten, aber je nachdem, wie Ihr DNS eingerichtet ist, kann das die Leistung nicht unerheblich beeinträchtigen."
-#: utils/misc/guc.c:1305
-msgid "Causes subtables to be included by default in various commands."
-msgstr "Schließt abgeleitete Tabellen in diverse Befehle automatisch ein."
-
-#: utils/misc/guc.c:1314
-msgid "Encrypt passwords."
-msgstr "Verschlüsselt Passwörter."
-
-#: utils/misc/guc.c:1315
-msgid "When a password is specified in CREATE USER or ALTER USER without writing either ENCRYPTED or UNENCRYPTED, this parameter determines whether the password is to be encrypted."
-msgstr "Wenn in CREATE USER oder ALTER USER ein Passwort ohne ENCRYPTED oder UNENCRYPTED angegeben ist, bestimmt dieser Parameter, ob das Passwort verschlüsselt wird."
-
-#: utils/misc/guc.c:1325
+#: utils/misc/guc.c:1343
msgid "Treats \"expr=NULL\" as \"expr IS NULL\"."
msgstr "Behandelt »ausdruck=NULL« als »ausdruck IS NULL«."
-#: utils/misc/guc.c:1326
+#: utils/misc/guc.c:1344
msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)."
msgstr "Wenn an, dann werden Ausdrücke der Form ausdruck = NULL (oder NULL = ausdruck) wie ausdruck IS NULL behandelt, das heißt, sie ergeben wahr, wenn das Ergebnis von ausdruck der NULL-Wert ist, und ansonsten falsch. Das korrekte Verhalten von ausdruck = NULL ist immer den NULL-Wert (für unbekannt) zurückzugeben."
-#: utils/misc/guc.c:1338
+#: utils/misc/guc.c:1356
msgid "Enables per-database user names."
msgstr "Ermöglicht Datenbank-lokale Benutzernamen."
-#: utils/misc/guc.c:1347
+#: utils/misc/guc.c:1365
msgid "Sets the default read-only status of new transactions."
msgstr "Setzt den Standardwert für die Read-Only-Einstellung einer neuen Transaktion."
-#: utils/misc/guc.c:1356
+#: utils/misc/guc.c:1374
msgid "Sets the current transaction's read-only status."
msgstr "Setzt die Read-Only-Einstellung der aktuellen Transaktion."
-#: utils/misc/guc.c:1366
+#: utils/misc/guc.c:1384
msgid "Sets the default deferrable status of new transactions."
msgstr "Setzt den Standardwert für die Deferrable-Einstellung einer neuen Transaktion."
-#: utils/misc/guc.c:1375
+#: utils/misc/guc.c:1393
msgid "Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."
msgstr "Ob eine serialisierbare Read-Only-Transaktion aufgeschoben werden soll, bis sie ohne mögliche Serialisierungsfehler ausgeführt werden kann."
-#: utils/misc/guc.c:1385
+#: utils/misc/guc.c:1403
msgid "Enable row security."
msgstr "Schaltet Sicherheit auf Zeilenebene ein."
-#: utils/misc/guc.c:1386
+#: utils/misc/guc.c:1404
msgid "When enabled, row security will be applied to all users."
msgstr "Wenn eingeschaltet, wird Sicherheit auf Zeilenebene auf alle Benutzer angewendet."
-#: utils/misc/guc.c:1394
+#: utils/misc/guc.c:1412
msgid "Check function bodies during CREATE FUNCTION."
msgstr "Prüft Funktionskörper bei der Ausführung von CREATE FUNCTION."
-#: utils/misc/guc.c:1403
+#: utils/misc/guc.c:1421
msgid "Enable input of NULL elements in arrays."
msgstr "Ermöglicht die Eingabe von NULL-Elementen in Arrays."
-#: utils/misc/guc.c:1404
+#: utils/misc/guc.c:1422
msgid "When turned on, unquoted NULL in an array input value means a null value; otherwise it is taken literally."
msgstr "Wenn dies eingeschaltet ist, wird ein nicht gequotetes NULL in einem Array-Eingabewert als NULL-Wert interpretiert, ansonsten als Zeichenkette."
-#: utils/misc/guc.c:1414
+#: utils/misc/guc.c:1432
msgid "Create new tables with OIDs by default."
msgstr "Erzeugt neue Tabellen standardmäßig mit OIDs."
-#: utils/misc/guc.c:1423
+#: utils/misc/guc.c:1441
msgid "Start a subprocess to capture stderr output and/or csvlogs into log files."
msgstr "Startet einen Subprozess, um die Stderr-Ausgabe und/oder CSV-Logs in Logdateien auszugeben."
-#: utils/misc/guc.c:1432
+#: utils/misc/guc.c:1450
msgid "Truncate existing log files of same name during log rotation."
msgstr "Kürzt existierende Logdateien mit dem selben Namen beim Rotieren."
-#: utils/misc/guc.c:1443
+#: utils/misc/guc.c:1461
msgid "Emit information about resource usage in sorting."
msgstr "Gibt Informationen über die Ressourcenverwendung beim Sortieren aus."
-#: utils/misc/guc.c:1457
+#: utils/misc/guc.c:1475
msgid "Generate debugging output for synchronized scanning."
msgstr "Erzeugt Debug-Ausgabe für synchronisiertes Scannen."
-#: utils/misc/guc.c:1472
+#: utils/misc/guc.c:1490
msgid "Enable bounded sorting using heap sort."
msgstr "Ermöglicht Bounded Sorting mittels Heap-Sort."
-#: utils/misc/guc.c:1485
+#: utils/misc/guc.c:1503
msgid "Emit WAL-related debugging output."
msgstr "Gibt diverse Debug-Meldungen über WAL aus."
-#: utils/misc/guc.c:1497
+#: utils/misc/guc.c:1515
msgid "Datetimes are integer based."
msgstr "Datum/Zeit verwendet intern ganze Zahlen."
-#: utils/misc/guc.c:1512
+#: utils/misc/guc.c:1526
msgid "Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."
msgstr "Bestimmt, ob Groß-/Kleinschreibung bei Kerberos- und GSSAPI-Benutzernamen ignoriert werden soll."
-#: utils/misc/guc.c:1522
+#: utils/misc/guc.c:1536
msgid "Warn about backslash escapes in ordinary string literals."
msgstr "Warnt bei Backslash-Escapes in normalen Zeichenkettenkonstanten."
-#: utils/misc/guc.c:1532
+#: utils/misc/guc.c:1546
msgid "Causes '...' strings to treat backslashes literally."
msgstr "Bewirkt, dass Zeichenketten der Art '...' Backslashes als normales Zeichen behandeln."
-#: utils/misc/guc.c:1543
+#: utils/misc/guc.c:1557
msgid "Enable synchronized sequential scans."
msgstr "Ermöglicht synchronisierte sequenzielle Scans."
-#: utils/misc/guc.c:1553
+#: utils/misc/guc.c:1567
msgid "Allows connections and queries during recovery."
msgstr "Erlaubt Verbindungen und Anfragen während der Wiederherstellung."
-#: utils/misc/guc.c:1563
+#: utils/misc/guc.c:1577
msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts."
msgstr "Erlaubt Rückmeldungen von einem Hot Standby an den Primärserver, um Anfragekonflikte zu vermeiden."
-#: utils/misc/guc.c:1573
+#: utils/misc/guc.c:1587
msgid "Allows modifications of the structure of system tables."
msgstr "Erlaubt Änderungen an der Struktur von Systemtabellen."
-#: utils/misc/guc.c:1584
+#: utils/misc/guc.c:1598
msgid "Disables reading from system indexes."
msgstr "Schaltet das Lesen aus Systemindexen ab."
-#: utils/misc/guc.c:1585
+#: utils/misc/guc.c:1599
msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness."
msgstr "Das Aktualisieren der Indexe wird nicht verhindert, also ist die Verwendung unbedenklich. Schlimmstenfalls wird alles langsamer."
-#: utils/misc/guc.c:1596
+#: utils/misc/guc.c:1610
msgid "Enables backward compatibility mode for privilege checks on large objects."
msgstr "Schaltet den rückwärtskompatiblen Modus für Privilegienprüfungen bei Large Objects ein."
-#: utils/misc/guc.c:1597
+#: utils/misc/guc.c:1611
msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0."
msgstr "Überspringt Privilegienprüfungen beim Lesen oder Ändern von Large Objects, zur Kompatibilität mit PostgreSQL-Versionen vor 9.0."
-#: utils/misc/guc.c:1607
+#: utils/misc/guc.c:1621
msgid "Emit a warning for constructs that changed meaning since PostgreSQL 9.4."
msgstr "Warnung ausgeben für Konstrukte, deren Bedeutung sich seit PostgreSQL 9.4 geändert hat."
-#: utils/misc/guc.c:1617
+#: utils/misc/guc.c:1631
msgid "When generating SQL fragments, quote all identifiers."
msgstr "Wenn SQL-Fragmente erzeugt werden, alle Bezeichner quoten."
-#: utils/misc/guc.c:1627
+#: utils/misc/guc.c:1641
msgid "Shows whether data checksums are turned on for this cluster."
msgstr "Zeigt, ob Datenprüfsummen in diesem Cluster angeschaltet sind."
-#: utils/misc/guc.c:1638
+#: utils/misc/guc.c:1652
msgid "Add sequence number to syslog messages to avoid duplicate suppression."
msgstr "Syslog-Nachrichten mit Sequenznummern versehen, um Unterdrückung doppelter Nachrichten zu unterbinden."
-#: utils/misc/guc.c:1648
+#: utils/misc/guc.c:1662
msgid "Split messages sent to syslog by lines and to fit into 1024 bytes."
msgstr "An Syslog gesendete Nachrichten nach Zeilen und in maximal 1024 Bytes aufteilen."
-#: utils/misc/guc.c:1667
-msgid "Forces a switch to the next xlog file if a new file has not been started within N seconds."
-msgstr "Erzwingt das Umschalten zur nächsten Transaktionslogdatei, wenn seit N Sekunden keine neue Datei begonnen worden ist."
+#: utils/misc/guc.c:1681
+msgid "Forces a switch to the next WAL file if a new file has not been started within N seconds."
+msgstr "Erzwingt das Umschalten zur nächsten WAL-Datei, wenn seit N Sekunden keine neue Datei begonnen worden ist."
-#: utils/misc/guc.c:1678
+#: utils/misc/guc.c:1692
msgid "Waits N seconds on connection startup after authentication."
msgstr "Wartet beim Starten einer Verbindung N Sekunden nach der Authentifizierung."
-#: utils/misc/guc.c:1679 utils/misc/guc.c:2202
+#: utils/misc/guc.c:1693 utils/misc/guc.c:2216
msgid "This allows attaching a debugger to the process."
msgstr "Das ermöglicht es, einen Debugger in den Prozess einzuhängen."
-#: utils/misc/guc.c:1688
+#: utils/misc/guc.c:1702
msgid "Sets the default statistics target."
msgstr "Setzt das voreingestellte Statistikziel."
-#: utils/misc/guc.c:1689
+#: utils/misc/guc.c:1703
msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS."
msgstr "Diese Einstellung gilt für Tabellenspalten, für die kein spaltenspezifisches Ziel mit ALTER TABLE SET STATISTICS gesetzt worden ist."
-#: utils/misc/guc.c:1698
+#: utils/misc/guc.c:1712
msgid "Sets the FROM-list size beyond which subqueries are not collapsed."
msgstr "Setzt die Größe der FROM-Liste, ab der Unteranfragen nicht kollabiert werden."
-#: utils/misc/guc.c:1700
+#: utils/misc/guc.c:1714
msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items."
msgstr "Der Planer bindet Unteranfragen in die übergeordneten Anfragen ein, wenn die daraus resultierende FROM-Liste nicht mehr als so viele Elemente haben würde."
-#: utils/misc/guc.c:1710
+#: utils/misc/guc.c:1724
msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened."
msgstr "Setzt die Größe der FROM-Liste, ab der JOIN-Konstrukte nicht aufgelöst werden."
-#: utils/misc/guc.c:1712
+#: utils/misc/guc.c:1726
msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result."
msgstr "Der Planer löst ausdrückliche JOIN-Konstrukte in FROM-Listen auf, wenn die daraus resultierende FROM-Liste nicht mehr als so viele Elemente haben würde."
-#: utils/misc/guc.c:1722
+#: utils/misc/guc.c:1736
msgid "Sets the threshold of FROM items beyond which GEQO is used."
msgstr "Setzt die Anzahl der Elemente in der FROM-Liste, ab der GEQO verwendet wird."
-#: utils/misc/guc.c:1731
+#: utils/misc/guc.c:1745
msgid "GEQO: effort is used to set the default for other GEQO parameters."
msgstr "GEQO: wird für die Berechnung der Vorgabewerte anderer GEQO-Parameter verwendet."
-#: utils/misc/guc.c:1740
+#: utils/misc/guc.c:1754
msgid "GEQO: number of individuals in the population."
msgstr "GEQO: Anzahl der Individien in der Bevölkerung."
-#: utils/misc/guc.c:1741 utils/misc/guc.c:1750
+#: utils/misc/guc.c:1755 utils/misc/guc.c:1764
msgid "Zero selects a suitable default value."
msgstr "Null wählt einen passenden Vorgabewert."
-#: utils/misc/guc.c:1749
+#: utils/misc/guc.c:1763
msgid "GEQO: number of iterations of the algorithm."
msgstr "GEQO: Anzahl der Iterationen im Algorithmus."
-#: utils/misc/guc.c:1760
+#: utils/misc/guc.c:1774
msgid "Sets the time to wait on a lock before checking for deadlock."
msgstr "Setzt die Zeit, die gewartet wird, bis auf Verklemmung geprüft wird."
-#: utils/misc/guc.c:1771
+#: utils/misc/guc.c:1785
msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."
msgstr "Setzt die maximale Verzögerung bevor Anfragen storniert werden, wenn ein Hot-Standby-Server archivierte WAL-Daten verarbeitet."
-#: utils/misc/guc.c:1782
+#: utils/misc/guc.c:1796
msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."
msgstr "Setzt die maximale Verzögerung bevor Anfragen storniert werden, wenn ein Hot-Standby-Server gestreamte WAL-Daten verarbeitet."
-#: utils/misc/guc.c:1793
+#: utils/misc/guc.c:1807
msgid "Sets the maximum interval between WAL receiver status reports to the primary."
msgstr "Setzt das maximale Intervall zwischen Statusberichten des WAL-Receivers an den Primärserver."
-#: utils/misc/guc.c:1804
+#: utils/misc/guc.c:1818
msgid "Sets the maximum wait time to receive data from the primary."
msgstr "Setzt die maximale Zeit, um auf den Empfang von Daten vom Primärserver zu warten."
-#: utils/misc/guc.c:1815
+#: utils/misc/guc.c:1829
msgid "Sets the maximum number of concurrent connections."
msgstr "Setzt die maximale Anzahl gleichzeitiger Verbindungen."
-#: utils/misc/guc.c:1825
+#: utils/misc/guc.c:1839
msgid "Sets the number of connection slots reserved for superusers."
msgstr "Setzt die Anzahl der für Superuser reservierten Verbindungen."
-#: utils/misc/guc.c:1839
+#: utils/misc/guc.c:1853
msgid "Sets the number of shared memory buffers used by the server."
msgstr "Setzt die Anzahl der vom Server verwendeten Shared-Memory-Puffer."
-#: utils/misc/guc.c:1850
+#: utils/misc/guc.c:1864
msgid "Sets the maximum number of temporary buffers used by each session."
msgstr "Setzt die maximale Anzahl der von jeder Sitzung verwendeten temporären Puffer."
-#: utils/misc/guc.c:1861
+#: utils/misc/guc.c:1875
msgid "Sets the TCP port the server listens on."
msgstr "Setzt den TCP-Port, auf dem der Server auf Verbindungen wartet."
-#: utils/misc/guc.c:1871
+#: utils/misc/guc.c:1885
msgid "Sets the access permissions of the Unix-domain socket."
msgstr "Setzt die Zugriffsrechte für die Unix-Domain-Socket."
-#: utils/misc/guc.c:1872
+#: utils/misc/guc.c:1886
msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)"
msgstr "Unix-Domain-Sockets verwenden die üblichen Zugriffsrechte für Unix-Dateisysteme. Der Wert dieser Option muss ein numerischer Wert in der von den Systemaufrufen chmod und umask verwendeten Form sein. (Um das gebräuchliche Oktalformat zu verwenden, muss die Zahl mit 0 (einer Null) anfangen.)"
-#: utils/misc/guc.c:1886
+#: utils/misc/guc.c:1900
msgid "Sets the file permissions for log files."
msgstr "Setzt die Dateizugriffsrechte für Logdateien."
-#: utils/misc/guc.c:1887
+#: utils/misc/guc.c:1901
msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)"
msgstr "Der Wert dieser Option muss ein numerischer Wert in der von den Systemaufrufen chmod und umask verwendeten Form sein. (Um das gebräuchliche Oktalformat zu verwenden, muss die Zahl mit 0 (einer Null) anfangen.)"
-#: utils/misc/guc.c:1900
+#: utils/misc/guc.c:1914
msgid "Sets the maximum memory to be used for query workspaces."
msgstr "Setzt die maximale Speichergröße für Anfrage-Arbeitsbereiche."
-#: utils/misc/guc.c:1901
+#: utils/misc/guc.c:1915
msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files."
msgstr "Gibt die Speichermenge an, die für interne Sortiervorgänge und Hashtabellen verwendet werden kann, bevor auf temporäre Dateien umgeschaltet wird."
-#: utils/misc/guc.c:1913
+#: utils/misc/guc.c:1927
msgid "Sets the maximum memory to be used for maintenance operations."
msgstr "Setzt die maximale Speichergröße für Wartungsoperationen."
-#: utils/misc/guc.c:1914
+#: utils/misc/guc.c:1928
msgid "This includes operations such as VACUUM and CREATE INDEX."
msgstr "Das schließt Operationen wie VACUUM und CREATE INDEX ein."
-#: utils/misc/guc.c:1924
-#, fuzzy
-#| msgid "Sets the maximum number of temporary buffers used by each session."
+#: utils/misc/guc.c:1938
msgid "Sets the maximum number of tuples to be sorted using replacement selection."
-msgstr "Setzt die maximale Anzahl der von jeder Sitzung verwendeten temporären Puffer."
+msgstr "Setzt die maximale Anzahl Tupel, die mit Replacement-Selection sortiert werden."
-#: utils/misc/guc.c:1925
+#: utils/misc/guc.c:1939
msgid "When more tuples than this are present, quicksort will be used."
msgstr "Wenn mehr Tupel als dieser Wert vorhanden sind, dann wird Quicksort verwendet."
-#: utils/misc/guc.c:1939
+#: utils/misc/guc.c:1953
msgid "Sets the maximum stack depth, in kilobytes."
msgstr "Setzt die maximale Stackgröße, in Kilobytes."
-#: utils/misc/guc.c:1950
+#: utils/misc/guc.c:1964
msgid "Limits the total size of all temporary files used by each process."
msgstr "Beschränkt die Gesamtgröße aller temporären Dateien, die von einem Prozess verwendet werden."
-#: utils/misc/guc.c:1951
+#: utils/misc/guc.c:1965
msgid "-1 means no limit."
msgstr "-1 bedeutet keine Grenze."
-#: utils/misc/guc.c:1961
+#: utils/misc/guc.c:1975
msgid "Vacuum cost for a page found in the buffer cache."
msgstr "Vacuum-Kosten für eine im Puffer-Cache gefundene Seite."
-#: utils/misc/guc.c:1971
+#: utils/misc/guc.c:1985
msgid "Vacuum cost for a page not found in the buffer cache."
msgstr "Vacuum-Kosten für eine nicht im Puffer-Cache gefundene Seite."
-#: utils/misc/guc.c:1981
+#: utils/misc/guc.c:1995
msgid "Vacuum cost for a page dirtied by vacuum."
msgstr "Vacuum-Kosten für eine durch Vacuum schmutzig gemachte Seite."
-#: utils/misc/guc.c:1991
+#: utils/misc/guc.c:2005
msgid "Vacuum cost amount available before napping."
msgstr "Verfügbare Vacuum-Kosten vor Nickerchen."
-#: utils/misc/guc.c:2001
+#: utils/misc/guc.c:2015
msgid "Vacuum cost delay in milliseconds."
msgstr "Vacuum-Kosten-Verzögerung in Millisekunden."
-#: utils/misc/guc.c:2012
+#: utils/misc/guc.c:2026
msgid "Vacuum cost delay in milliseconds, for autovacuum."
msgstr "Vacuum-Kosten-Verzögerung in Millisekunden, für Autovacuum."
-#: utils/misc/guc.c:2023
+#: utils/misc/guc.c:2037
msgid "Vacuum cost amount available before napping, for autovacuum."
msgstr "Verfügbare Vacuum-Kosten vor Nickerchen, für Autovacuum."
-#: utils/misc/guc.c:2033
+#: utils/misc/guc.c:2047
msgid "Sets the maximum number of simultaneously open files for each server process."
msgstr "Setzt die maximale Zahl gleichzeitig geöffneter Dateien für jeden Serverprozess."
-#: utils/misc/guc.c:2046
+#: utils/misc/guc.c:2060
msgid "Sets the maximum number of simultaneously prepared transactions."
msgstr "Setzt die maximale Anzahl von gleichzeitig vorbereiteten Transaktionen."
-#: utils/misc/guc.c:2057
+#: utils/misc/guc.c:2071
msgid "Sets the minimum OID of tables for tracking locks."
msgstr "Setzt die minimale Tabellen-OID für das Verfolgen von Sperren."
-#: utils/misc/guc.c:2058
+#: utils/misc/guc.c:2072
msgid "Is used to avoid output on system tables."
msgstr "Wird verwendet, um Ausgabe für Systemtabellen zu vermeiden."
-#: utils/misc/guc.c:2067
+#: utils/misc/guc.c:2081
msgid "Sets the OID of the table with unconditionally lock tracing."
msgstr "Setzt die OID der Tabelle mit bedingungsloser Sperrenverfolgung."
-#: utils/misc/guc.c:2079
+#: utils/misc/guc.c:2093
msgid "Sets the maximum allowed duration of any statement."
msgstr "Setzt die maximal erlaubte Dauer jeder Anweisung."
-#: utils/misc/guc.c:2080 utils/misc/guc.c:2091 utils/misc/guc.c:2102
+#: utils/misc/guc.c:2094 utils/misc/guc.c:2105 utils/misc/guc.c:2116
msgid "A value of 0 turns off the timeout."
msgstr "Der Wert 0 schaltet die Zeitprüfung aus."
-#: utils/misc/guc.c:2090
+#: utils/misc/guc.c:2104
msgid "Sets the maximum allowed duration of any wait for a lock."
msgstr "Setzt die maximal erlaubte Dauer, um auf eine Sperre zu warten."
-#: utils/misc/guc.c:2101
+#: utils/misc/guc.c:2115
msgid "Sets the maximum allowed duration of any idling transaction."
msgstr "Setzt die maximal erlaubte Dauer einer inaktiven Transaktion."
-#: utils/misc/guc.c:2112
+#: utils/misc/guc.c:2126
msgid "Minimum age at which VACUUM should freeze a table row."
msgstr "Mindestalter, bei dem VACUUM eine Tabellenzeile einfrieren soll."
-#: utils/misc/guc.c:2122
+#: utils/misc/guc.c:2136
msgid "Age at which VACUUM should scan whole table to freeze tuples."
msgstr "Alter, bei dem VACUUM die ganze Tabelle durchsuchen soll, um Zeilen einzufrieren."
-#: utils/misc/guc.c:2132
+#: utils/misc/guc.c:2146
msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row."
msgstr "Mindestalter, bei dem VACUUM eine MultiXactId in einer Tabellenzeile einfrieren soll."
-#: utils/misc/guc.c:2142
+#: utils/misc/guc.c:2156
msgid "Multixact age at which VACUUM should scan whole table to freeze tuples."
msgstr "Multixact-Alter, bei dem VACUUM die ganze Tabelle durchsuchen soll, um Zeilen einzufrieren."
-#: utils/misc/guc.c:2152
+#: utils/misc/guc.c:2166
msgid "Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."
msgstr "Anzahl Transaktionen, um die VACUUM- und HOT-Aufräumen aufgeschoben werden soll."
-#: utils/misc/guc.c:2165
+#: utils/misc/guc.c:2179
msgid "Sets the maximum number of locks per transaction."
msgstr "Setzt die maximale Anzahl Sperren pro Transaktion."
-#: utils/misc/guc.c:2166
+#: utils/misc/guc.c:2180
msgid "The shared lock table is sized on the assumption that at most max_locks_per_transaction * max_connections distinct objects will need to be locked at any one time."
msgstr "Die globale Sperrentabelle wird mit der Annahme angelegt, das höchstens max_locks_per_transaction * max_connections verschiedene Objekte gleichzeitig gesperrt werden müssen."
-#: utils/misc/guc.c:2177
+#: utils/misc/guc.c:2191
msgid "Sets the maximum number of predicate locks per transaction."
msgstr "Setzt die maximale Anzahl Prädikatsperren pro Transaktion."
-#: utils/misc/guc.c:2178
+#: utils/misc/guc.c:2192
msgid "The shared predicate lock table is sized on the assumption that at most max_pred_locks_per_transaction * max_connections distinct objects will need to be locked at any one time."
msgstr "Die globale Prädikatsperrentabelle wird mit der Annahme angelegt, das höchstens max_pred_locks_per_transaction * max_connections verschiedene Objekte gleichzeitig gesperrt werden müssen."
-#: utils/misc/guc.c:2189
+#: utils/misc/guc.c:2203
msgid "Sets the maximum allowed time to complete client authentication."
msgstr "Setzt die maximale Zeit, um die Client-Authentifizierung zu beenden."
-#: utils/misc/guc.c:2201
+#: utils/misc/guc.c:2215
msgid "Waits N seconds on connection startup before authentication."
msgstr "Wartet beim Starten einer Verbindung N Sekunden vor der Authentifizierung."
-#: utils/misc/guc.c:2212
+#: utils/misc/guc.c:2226
msgid "Sets the number of WAL files held for standby servers."
msgstr "Setzt die maximale Anzahl der für Standby-Server vorgehaltenen WAL-Dateien."
-#: utils/misc/guc.c:2222
+#: utils/misc/guc.c:2236
msgid "Sets the minimum size to shrink the WAL to."
msgstr "Setzt die minimale Größe, auf die der WAL geschrumpft wird."
-#: utils/misc/guc.c:2233
+#: utils/misc/guc.c:2247
msgid "Sets the WAL size that triggers a checkpoint."
msgstr "Setzt die WAL-Größe, die einen Checkpoint auslöst."
-#: utils/misc/guc.c:2244
+#: utils/misc/guc.c:2258
msgid "Sets the maximum time between automatic WAL checkpoints."
msgstr "Setzt die maximale Zeit zwischen automatischen WAL-Checkpoints."
-#: utils/misc/guc.c:2255
+#: utils/misc/guc.c:2269
msgid "Enables warnings if checkpoint segments are filled more frequently than this."
msgstr "Schreibt eine Logmeldung, wenn Checkpoint-Segmente häufiger als dieser Wert gefüllt werden."
-#: utils/misc/guc.c:2257
+#: utils/misc/guc.c:2271
msgid "Write a message to the server log if checkpoints caused by the filling of checkpoint segment files happens more frequently than this number of seconds. Zero turns off the warning."
msgstr "Schreibe Meldung in den Serverlog, wenn Checkpoints, die durch Füllen der Checkpoint-Segmente ausgelöst werden, häufiger als dieser Wert in Sekunden passieren. Null schaltet die Warnung ab."
-#: utils/misc/guc.c:2269 utils/misc/guc.c:2427 utils/misc/guc.c:2455
+#: utils/misc/guc.c:2283 utils/misc/guc.c:2440 utils/misc/guc.c:2467
msgid "Number of pages after which previously performed writes are flushed to disk."
-msgstr ""
+msgstr "Anzahl der Seiten, nach denen getätigte Schreibvorgänge auf die Festplatte zurückgeschrieben werden."
-#: utils/misc/guc.c:2281
+#: utils/misc/guc.c:2294
msgid "Sets the number of disk-page buffers in shared memory for WAL."
msgstr "Setzt die Anzahl Diskseitenpuffer für WAL im Shared Memory."
-#: utils/misc/guc.c:2292
+#: utils/misc/guc.c:2305
msgid "Time between WAL flushes performed in the WAL writer."
msgstr "Zeit zwischen WAL-Flush-Operationen im WAL-Writer."
-#: utils/misc/guc.c:2303
-msgid "Amount of WAL written out by WAL writer triggering a flush."
-msgstr ""
+#: utils/misc/guc.c:2316
+msgid "Amount of WAL written out by WAL writer that triggers a flush."
+msgstr "Ein Flush wird ausgelöst, wenn diese Menge WAL vom WAL-Writer geschrieben worden ist."
-#: utils/misc/guc.c:2315
+#: utils/misc/guc.c:2328
msgid "Sets the maximum number of simultaneously running WAL sender processes."
msgstr "Setzt die maximale Anzahl gleichzeitig laufender WAL-Sender-Prozesse."
-#: utils/misc/guc.c:2326
+#: utils/misc/guc.c:2339
msgid "Sets the maximum number of simultaneously defined replication slots."
msgstr "Setzt die maximale Anzahl von gleichzeitig definierten Replikations-Slots."
-#: utils/misc/guc.c:2336
+#: utils/misc/guc.c:2349
msgid "Sets the maximum time to wait for WAL replication."
msgstr "Setzt die maximale Zeit, um auf WAL-Replikation zu warten."
-#: utils/misc/guc.c:2347
+#: utils/misc/guc.c:2360
msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk."
msgstr "Setzt die Verzögerung in Millisekunden zwischen Transaktionsabschluss und dem Schreiben von WAL auf die Festplatte."
-#: utils/misc/guc.c:2359
+#: utils/misc/guc.c:2372
msgid "Sets the minimum concurrent open transactions before performing commit_delay."
msgstr "Setzt die minimale Anzahl gleichzeitig offener Transaktionen bevor »commit_delay« angewendet wird."
-#: utils/misc/guc.c:2370
+#: utils/misc/guc.c:2383
msgid "Sets the number of digits displayed for floating-point values."
msgstr "Setzt die Anzahl ausgegebener Ziffern für Fließkommawerte."
-#: utils/misc/guc.c:2371
+#: utils/misc/guc.c:2384
msgid "This affects real, double precision, and geometric data types. The parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate)."
msgstr "Diese Einstellung betrifft real, double precision und geometrische Datentypen. Der Parameterwert wird zur Standardziffernanzahl (FLT_DIG bzw. DBL_DIG) hinzuaddiert."
-#: utils/misc/guc.c:2382
+#: utils/misc/guc.c:2395
msgid "Sets the minimum execution time above which statements will be logged."
msgstr "Setzt die minimale Ausführungszeit, über der Anweisungen geloggt werden."
-#: utils/misc/guc.c:2384
+#: utils/misc/guc.c:2397
msgid "Zero prints all queries. -1 turns this feature off."
msgstr "Null zeigt alle Anfragen. -1 schaltet dieses Feature aus."
-#: utils/misc/guc.c:2394
+#: utils/misc/guc.c:2407
msgid "Sets the minimum execution time above which autovacuum actions will be logged."
msgstr "Setzt die minimale Ausführungszeit, über der Autovacuum-Aktionen geloggt werden."
-#: utils/misc/guc.c:2396
+#: utils/misc/guc.c:2409
msgid "Zero prints all actions. -1 turns autovacuum logging off."
msgstr "Null gibt alls Aktionen aus. -1 schaltet die Log-Aufzeichnung über Autovacuum aus."
-#: utils/misc/guc.c:2406
+#: utils/misc/guc.c:2419
msgid "Background writer sleep time between rounds."
msgstr "Schlafzeit zwischen Durchläufen des Background-Writers."
-#: utils/misc/guc.c:2417
+#: utils/misc/guc.c:2430
msgid "Background writer maximum number of LRU pages to flush per round."
msgstr "Maximale Anzahl der vom Background-Writer pro Durchlauf zu flushenden LRU-Seiten."
-#: utils/misc/guc.c:2441
+#: utils/misc/guc.c:2453
msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem."
msgstr "Anzahl simultaner Anfragen, die das Festplattensubsystem effizient bearbeiten kann."
-#: utils/misc/guc.c:2442
+#: utils/misc/guc.c:2454
msgid "For RAID arrays, this should be approximately the number of drive spindles in the array."
msgstr "Für RAID-Arrays sollte dies ungefähr die Anzahl Spindeln im Array sein."
-#: utils/misc/guc.c:2468
+#: utils/misc/guc.c:2480
msgid "Maximum number of concurrent worker processes."
msgstr "Maximale Anzahl gleichzeitiger Worker-Prozesse."
-#: utils/misc/guc.c:2478
+#: utils/misc/guc.c:2492
+#, fuzzy
+#| msgid "Maximum number of concurrent worker processes."
+msgid "Maximum number of logical replication worker processes."
+msgstr "Maximale Anzahl gleichzeitiger Worker-Prozesse."
+
+#: utils/misc/guc.c:2502
msgid "Automatic log file rotation will occur after N minutes."
msgstr "Automatische Rotation der Logdateien geschieht nach N Minuten."
-#: utils/misc/guc.c:2489
+#: utils/misc/guc.c:2513
msgid "Automatic log file rotation will occur after N kilobytes."
msgstr "Automatische Rotation der Logdateien geschieht nach N Kilobytes."
-#: utils/misc/guc.c:2500
+#: utils/misc/guc.c:2524
msgid "Shows the maximum number of function arguments."
msgstr "Setzt die maximale Anzahl von Funktionsargumenten."
-#: utils/misc/guc.c:2511
+#: utils/misc/guc.c:2535
msgid "Shows the maximum number of index keys."
msgstr "Zeigt die maximale Anzahl von Indexschlüsseln."
-#: utils/misc/guc.c:2522
+#: utils/misc/guc.c:2546
msgid "Shows the maximum identifier length."
msgstr "Zeigt die maximale Länge von Bezeichnern."
-#: utils/misc/guc.c:2533
+#: utils/misc/guc.c:2557
msgid "Shows the size of a disk block."
msgstr "Zeigt die Größe eines Diskblocks."
-#: utils/misc/guc.c:2544
+#: utils/misc/guc.c:2568
msgid "Shows the number of pages per disk file."
msgstr "Zeigt die Anzahl Seiten pro Diskdatei."
-#: utils/misc/guc.c:2555
+#: utils/misc/guc.c:2579
msgid "Shows the block size in the write ahead log."
msgstr "Zeigt die Blockgröße im Write-Ahead-Log."
-#: utils/misc/guc.c:2566
+#: utils/misc/guc.c:2590
msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt."
msgstr "Setzt die Zeit, die gewartet wird, bevor nach einem fehlgeschlagenen Versuch neue WAL-Daten angefordert werden."
-#: utils/misc/guc.c:2578
+#: utils/misc/guc.c:2602
msgid "Shows the number of pages per write ahead log segment."
msgstr "Zeit die Anzahl Seiten pro Write-Ahead-Log-Segment."
-#: utils/misc/guc.c:2591
+#: utils/misc/guc.c:2615
msgid "Time to sleep between autovacuum runs."
msgstr "Wartezeit zwischen Autovacuum-Durchläufen."
-#: utils/misc/guc.c:2601
+#: utils/misc/guc.c:2625
msgid "Minimum number of tuple updates or deletes prior to vacuum."
msgstr "Mindestanzahl an geänderten oder gelöschten Tupeln vor einem Vacuum."
-#: utils/misc/guc.c:2610
+#: utils/misc/guc.c:2634
msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze."
msgstr "Mindestanzahl an Einfüge-, Änderungs- oder Löschoperationen von einem Analyze."
-#: utils/misc/guc.c:2620
+#: utils/misc/guc.c:2644
msgid "Age at which to autovacuum a table to prevent transaction ID wraparound."
msgstr "Alter, nach dem eine Tabelle automatisch gevacuumt wird, um Transaktionsnummernüberlauf zu verhindern."
-#: utils/misc/guc.c:2631
+#: utils/misc/guc.c:2655
msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound."
msgstr "Multixact-Alter, nach dem eine Tabelle automatisch gevacuumt wird, um Transaktionsnummernüberlauf zu verhindern."
-#: utils/misc/guc.c:2641
+#: utils/misc/guc.c:2665
msgid "Sets the maximum number of simultaneously running autovacuum worker processes."
msgstr "Setzt die maximale Anzahl gleichzeitig laufender Autovacuum-Worker-Prozesse."
-#: utils/misc/guc.c:2651
+#: utils/misc/guc.c:2675
msgid "Sets the maximum number of parallel processes per executor node."
msgstr "Setzt die maximale Anzahl paralleler Prozesse pro Executor-Knoten."
-#: utils/misc/guc.c:2661
+#: utils/misc/guc.c:2685
+#, fuzzy
+#| msgid "Sets the maximum number of predicate locks per transaction."
+msgid "Sets the maximum number of parallel workers than can be active at one time."
+msgstr "Setzt die maximale Anzahl Prädikatsperren pro Transaktion."
+
+#: utils/misc/guc.c:2695
msgid "Sets the maximum memory to be used by each autovacuum worker process."
msgstr "Setzt die maximale Speichergröße für jeden Autovacuum-Worker-Prozess."
-#: utils/misc/guc.c:2672
+#: utils/misc/guc.c:2706
msgid "Time before a snapshot is too old to read pages changed after the snapshot was taken."
-msgstr ""
+msgstr "Zeit bevor ein Snapshot zu alt ist, um Seiten zu lesen, die geändert wurden, nachdem der Snapshot gemacht wurde."
-#: utils/misc/guc.c:2673
+#: utils/misc/guc.c:2707
msgid "A value of -1 disables this feature."
msgstr "Der Wert -1 schaltet dieses Feature aus."
-#: utils/misc/guc.c:2683
+#: utils/misc/guc.c:2717
msgid "Time between issuing TCP keepalives."
msgstr "Zeit zwischen TCP-Keepalive-Sendungen."
-#: utils/misc/guc.c:2684 utils/misc/guc.c:2695
+#: utils/misc/guc.c:2718 utils/misc/guc.c:2729
msgid "A value of 0 uses the system default."
msgstr "Der Wert 0 verwendet die Systemvoreinstellung."
-#: utils/misc/guc.c:2694
+#: utils/misc/guc.c:2728
msgid "Time between TCP keepalive retransmits."
msgstr "Zeit zwischen TCP-Keepalive-Neuübertragungen."
-#: utils/misc/guc.c:2705
+#: utils/misc/guc.c:2739
msgid "SSL renegotiation is no longer supported; this can only be 0."
msgstr "SSL-Renegotiation wird nicht mehr unterstützt; kann nur auf 0 gesetzt werden."
-#: utils/misc/guc.c:2716
+#: utils/misc/guc.c:2750
msgid "Maximum number of TCP keepalive retransmits."
msgstr "Maximale Anzahl an TCP-Keepalive-Neuübertragungen."
-#: utils/misc/guc.c:2717
+#: utils/misc/guc.c:2751
msgid "This controls the number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default."
msgstr "Dies bestimmt die Anzahl von aufeinanderfolgenden Keepalive-Neuübertragungen, die verloren gehen dürfen, bis die Verbindung als tot betrachtet wird. Der Wert 0 verwendet die Betriebssystemvoreinstellung."
-#: utils/misc/guc.c:2728
+#: utils/misc/guc.c:2762
msgid "Sets the maximum allowed result for exact search by GIN."
msgstr "Setzt die maximal erlaubte Anzahl Ergebnisse für eine genaue Suche mit GIN."
-#: utils/misc/guc.c:2739
+#: utils/misc/guc.c:2773
msgid "Sets the planner's assumption about the size of the disk cache."
msgstr "Setzt die Annahme des Planers über die Größe des Festplatten-Caches."
-#: utils/misc/guc.c:2740
+#: utils/misc/guc.c:2774
msgid "That is, the portion of the kernel's disk cache that will be used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each."
msgstr "Setzt die Annahme des Planers über die effektive Größe des Diskcaches (das heißt des Teils des Diskcaches vom Kernel, der für die Datendateien von PostgreSQL verwendet wird). Das wird in Diskseiten gemessen, welche normalerweise 8 kB groß sind."
-#: utils/misc/guc.c:2752
-msgid "Sets the minimum size of relations to be considered for parallel scan."
+#: utils/misc/guc.c:2786
+#, fuzzy
+#| msgid "Sets the minimum size of relations to be considered for parallel scan."
+msgid "Sets the minimum amount of table data for a parallel scan."
+msgstr "Setzt die minimale Größe einer Relation, um für einen parallelen Scan in Betracht gezogen werden zu können."
+
+#: utils/misc/guc.c:2787
+msgid "If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered."
+msgstr ""
+
+#: utils/misc/guc.c:2797
+#, fuzzy
+#| msgid "Sets the minimum size of relations to be considered for parallel scan."
+msgid "Sets the minimum amount of index data for a parallel scan."
msgstr "Setzt die minimale Größe einer Relation, um für einen parallelen Scan in Betracht gezogen werden zu können."
-#: utils/misc/guc.c:2764
+#: utils/misc/guc.c:2798
+msgid "If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered."
+msgstr ""
+
+#: utils/misc/guc.c:2809
msgid "Shows the server version as an integer."
msgstr "Zeigt die Serverversion als Zahl."
-#: utils/misc/guc.c:2775
+#: utils/misc/guc.c:2820
msgid "Log the use of temporary files larger than this number of kilobytes."
msgstr "Schreibt Meldungen über die Verwendung von temporären Dateien in den Log, wenn sie größer als diese Anzahl an Kilobytes sind."
-#: utils/misc/guc.c:2776
+#: utils/misc/guc.c:2821
msgid "Zero logs all files. The default is -1 (turning this feature off)."
msgstr "Null loggt alle Dateien. Die Standardeinstellung ist -1 (wodurch dieses Feature ausgeschaltet wird)."
-#: utils/misc/guc.c:2786
+#: utils/misc/guc.c:2831
msgid "Sets the size reserved for pg_stat_activity.query, in bytes."
msgstr "Setzt die für pg_stat_activity.query reservierte Größe, in Bytes."
-#: utils/misc/guc.c:2801
+#: utils/misc/guc.c:2846
msgid "Sets the maximum size of the pending list for GIN index."
msgstr "Setzt die maximale Größe der Pending-Liste eines GIN-Index."
-#: utils/misc/guc.c:2821
+#: utils/misc/guc.c:2866
msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page."
msgstr "Setzt den vom Planer geschätzten Aufwand, um eine sequenzielle Diskseite zu lesen."
-#: utils/misc/guc.c:2831
+#: utils/misc/guc.c:2876
msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page."
msgstr "Setzt den vom Planer geschätzten Aufwand, um eine nichtsequenzielle Diskseite zu lesen."
-#: utils/misc/guc.c:2841
+#: utils/misc/guc.c:2886
msgid "Sets the planner's estimate of the cost of processing each tuple (row)."
msgstr "Setzt den vom Planer geschätzten Aufwand für die Verarbeitung einer Zeile."
-#: utils/misc/guc.c:2851
+#: utils/misc/guc.c:2896
msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan."
msgstr "Setzt den vom Planer geschätzten Aufwand für die Verarbeitung eines Indexeintrags während eines Index-Scans."
-#: utils/misc/guc.c:2861
+#: utils/misc/guc.c:2906
msgid "Sets the planner's estimate of the cost of processing each operator or function call."
msgstr "Setzt den vom Planer geschätzten Aufwand für die Verarbeitung eines Operators oder Funktionsaufrufs."
-#: utils/misc/guc.c:2871
-#, fuzzy
-#| msgid "Sets the planner's estimate of the cost of processing each tuple (row)."
+#: utils/misc/guc.c:2916
msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to master backend."
-msgstr "Setzt den vom Planer geschätzten Aufwand für die Verarbeitung einer Zeile."
+msgstr "Setzt den vom Planer geschätzten Aufwand, um eine Zeile vom Arbeitsprozess and das Master-Backend zu senden."
-#: utils/misc/guc.c:2881
-#, fuzzy
-#| msgid "Sets the planner's estimate of the cost of processing each tuple (row)."
+#: utils/misc/guc.c:2926
msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query."
-msgstr "Setzt den vom Planer geschätzten Aufwand für die Verarbeitung einer Zeile."
+msgstr "Setzt den vom Planer geschätzten Aufwand für das Starten von Arbeitsprozessen für parallele Anfragen."
-#: utils/misc/guc.c:2892
+#: utils/misc/guc.c:2937
msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved."
msgstr "Setzt den vom Planer geschätzten Anteil der Cursor-Zeilen, die ausgelesen werden werden."
-#: utils/misc/guc.c:2903
+#: utils/misc/guc.c:2948
msgid "GEQO: selective pressure within the population."
msgstr "GEQO: selektiver Auswahldruck in der Bevölkerung."
-#: utils/misc/guc.c:2913
+#: utils/misc/guc.c:2958
msgid "GEQO: seed for random path selection."
msgstr "GEQO: Ausgangswert für die zufällige Pfadauswahl."
-#: utils/misc/guc.c:2923
+#: utils/misc/guc.c:2968
msgid "Multiple of the average buffer usage to free per round."
msgstr "Vielfaches der durchschnittlichen freizugebenden Pufferverwendung pro Runde."
-#: utils/misc/guc.c:2933
+#: utils/misc/guc.c:2978
msgid "Sets the seed for random-number generation."
msgstr "Setzt den Ausgangswert für die Zufallszahlenerzeugung."
-#: utils/misc/guc.c:2944
+#: utils/misc/guc.c:2989
msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."
msgstr "Anzahl geänderter oder gelöschter Tupel vor einem Vacuum, relativ zu reltuples."
-#: utils/misc/guc.c:2953
+#: utils/misc/guc.c:2998
msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."
msgstr "Anzahl eingefügter, geänderter oder gelöschter Tupel vor einem Analyze, relativ zu reltuples."
-#: utils/misc/guc.c:2963
+#: utils/misc/guc.c:3008
msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."
msgstr "Zeit, die damit verbracht wird, modifizierte Puffer während eines Checkpoints zurückzuschreiben, als Bruchteil des Checkpoint-Intervalls."
-#: utils/misc/guc.c:2982
+#: utils/misc/guc.c:3027
msgid "Sets the shell command that will be called to archive a WAL file."
msgstr "Setzt den Shell-Befehl, der aufgerufen wird, um eine WAL-Datei zu archivieren."
-#: utils/misc/guc.c:2992
+#: utils/misc/guc.c:3037
msgid "Sets the client's character set encoding."
msgstr "Setzt die Zeichensatzkodierung des Clients."
-#: utils/misc/guc.c:3003
+#: utils/misc/guc.c:3048
msgid "Controls information prefixed to each log line."
msgstr "Bestimmt die Informationen, die vor jede Logzeile geschrieben werden."
-#: utils/misc/guc.c:3004
+#: utils/misc/guc.c:3049
msgid "If blank, no prefix is used."
msgstr "Wenn leer, dann wird kein Präfix verwendet."
-#: utils/misc/guc.c:3013
+#: utils/misc/guc.c:3058
msgid "Sets the time zone to use in log messages."
msgstr "Setzt die in Logmeldungen verwendete Zeitzone."
-#: utils/misc/guc.c:3023
+#: utils/misc/guc.c:3068
msgid "Sets the display format for date and time values."
msgstr "Setzt das Ausgabeformat für Datums- und Zeitwerte."
-#: utils/misc/guc.c:3024
+#: utils/misc/guc.c:3069
msgid "Also controls interpretation of ambiguous date inputs."
msgstr "Kontrolliert auch die Interpretation von zweideutigen Datumseingaben."
-#: utils/misc/guc.c:3035
+#: utils/misc/guc.c:3080
msgid "Sets the default tablespace to create tables and indexes in."
msgstr "Setzt den Standard-Tablespace für Tabellen und Indexe."
-#: utils/misc/guc.c:3036
+#: utils/misc/guc.c:3081
msgid "An empty string selects the database's default tablespace."
msgstr "Eine leere Zeichenkette wählt den Standard-Tablespace der Datenbank."
-#: utils/misc/guc.c:3046
+#: utils/misc/guc.c:3091
msgid "Sets the tablespace(s) to use for temporary tables and sort files."
msgstr "Setzt den oder die Tablespaces für temporäre Tabellen und Sortierdateien."
-#: utils/misc/guc.c:3057
+#: utils/misc/guc.c:3102
msgid "Sets the path for dynamically loadable modules."
msgstr "Setzt den Pfad für ladbare dynamische Bibliotheken."
-#: utils/misc/guc.c:3058
+#: utils/misc/guc.c:3103
msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file."
msgstr "Wenn ein dynamisch ladbares Modul geöffnet werden muss und der angegebene Name keine Verzeichniskomponente hat (das heißt er enthält keinen Schrägstrich), dann sucht das System in diesem Pfad nach der angegebenen Datei."
-#: utils/misc/guc.c:3071
+#: utils/misc/guc.c:3116
msgid "Sets the location of the Kerberos server key file."
msgstr "Setzt den Ort der Kerberos-Server-Schlüsseldatei."
-#: utils/misc/guc.c:3082
+#: utils/misc/guc.c:3127
msgid "Sets the Bonjour service name."
msgstr "Setzt den Bonjour-Servicenamen."
-#: utils/misc/guc.c:3094
+#: utils/misc/guc.c:3139
msgid "Shows the collation order locale."
msgstr "Zeigt die Locale für die Sortierreihenfolge."
-#: utils/misc/guc.c:3105
+#: utils/misc/guc.c:3150
msgid "Shows the character classification and case conversion locale."
msgstr "Zeigt die Locale für Zeichenklassifizierung und Groß-/Kleinschreibung."
-#: utils/misc/guc.c:3116
+#: utils/misc/guc.c:3161
msgid "Sets the language in which messages are displayed."
msgstr "Setzt die Sprache, in der Mitteilungen ausgegeben werden."
-#: utils/misc/guc.c:3126
+#: utils/misc/guc.c:3171
msgid "Sets the locale for formatting monetary amounts."
msgstr "Setzt die Locale für die Formatierung von Geldbeträgen."
-#: utils/misc/guc.c:3136
+#: utils/misc/guc.c:3181
msgid "Sets the locale for formatting numbers."
msgstr "Setzt die Locale für die Formatierung von Zahlen."
-#: utils/misc/guc.c:3146
+#: utils/misc/guc.c:3191
msgid "Sets the locale for formatting date and time values."
msgstr "Setzt die Locale für die Formatierung von Datums- und Zeitwerten."
-#: utils/misc/guc.c:3156
+#: utils/misc/guc.c:3201
msgid "Lists shared libraries to preload into each backend."
msgstr "Listet dynamische Bibliotheken, die vorab in jeden Serverprozess geladen werden."
-#: utils/misc/guc.c:3167
+#: utils/misc/guc.c:3212
msgid "Lists shared libraries to preload into server."
msgstr "Listet dynamische Bibliotheken, die vorab in den Server geladen werden."
-#: utils/misc/guc.c:3178
+#: utils/misc/guc.c:3223
msgid "Lists unprivileged shared libraries to preload into each backend."
msgstr "Listet unprivilegierte dynamische Bibliotheken, die vorab in jeden Serverprozess geladen werden."
-#: utils/misc/guc.c:3189
+#: utils/misc/guc.c:3234
msgid "Sets the schema search order for names that are not schema-qualified."
msgstr "Setzt die Schemasuchreihenfolge für Namen ohne Schemaqualifikation."
-#: utils/misc/guc.c:3201
+#: utils/misc/guc.c:3246
msgid "Sets the server (database) character set encoding."
msgstr "Setzt die Zeichensatzkodierung des Servers (der Datenbank)."
-#: utils/misc/guc.c:3213
+#: utils/misc/guc.c:3258
msgid "Shows the server version."
msgstr "Zeigt die Serverversion."
-#: utils/misc/guc.c:3225
+#: utils/misc/guc.c:3270
msgid "Sets the current role."
msgstr "Setzt die aktuelle Rolle."
-#: utils/misc/guc.c:3237
+#: utils/misc/guc.c:3282
msgid "Sets the session user name."
msgstr "Setzt den Sitzungsbenutzernamen."
-#: utils/misc/guc.c:3248
+#: utils/misc/guc.c:3293
msgid "Sets the destination for server log output."
msgstr "Setzt das Ziel für die Serverlogausgabe."
-#: utils/misc/guc.c:3249
+#: utils/misc/guc.c:3294
msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", and \"eventlog\", depending on the platform."
msgstr "Gültige Werte sind Kombinationen von »stderr«, »syslog«, »csvlog« und »eventlog«, je nach Plattform."
-#: utils/misc/guc.c:3260
+#: utils/misc/guc.c:3305
msgid "Sets the destination directory for log files."
msgstr "Bestimmt das Zielverzeichnis für Logdateien."
-#: utils/misc/guc.c:3261
+#: utils/misc/guc.c:3306
msgid "Can be specified as relative to the data directory or as absolute path."
msgstr "Kann relativ zum Datenverzeichnis oder als absoluter Pfad angegeben werden."
-#: utils/misc/guc.c:3271
+#: utils/misc/guc.c:3316
msgid "Sets the file name pattern for log files."
msgstr "Bestimmt das Dateinamenmuster für Logdateien."
-#: utils/misc/guc.c:3282
+#: utils/misc/guc.c:3327
msgid "Sets the program name used to identify PostgreSQL messages in syslog."
msgstr "Setzt den Programmnamen, mit dem PostgreSQL-Meldungen im Syslog identifiziert werden."
-#: utils/misc/guc.c:3293
+#: utils/misc/guc.c:3338
msgid "Sets the application name used to identify PostgreSQL messages in the event log."
msgstr "Setzt den Programmnamen, mit dem PostgreSQL-Meldungen im Ereignisprotokoll identifiziert werden."
-#: utils/misc/guc.c:3304
+#: utils/misc/guc.c:3349
msgid "Sets the time zone for displaying and interpreting time stamps."
msgstr "Setzt die Zeitzone, in der Zeitangaben interpretiert und ausgegeben werden."
-#: utils/misc/guc.c:3314
+#: utils/misc/guc.c:3359
msgid "Selects a file of time zone abbreviations."
msgstr "Wählt eine Datei mit Zeitzonenabkürzungen."
-#: utils/misc/guc.c:3324
+#: utils/misc/guc.c:3369
msgid "Sets the current transaction's isolation level."
msgstr "Zeigt den Isolationsgrad der aktuellen Transaktion."
-#: utils/misc/guc.c:3335
+#: utils/misc/guc.c:3380
msgid "Sets the owning group of the Unix-domain socket."
msgstr "Setzt die Eigentümergruppe der Unix-Domain-Socket."
-#: utils/misc/guc.c:3336
+#: utils/misc/guc.c:3381
msgid "The owning user of the socket is always the user that starts the server."
msgstr "Der Eigentümer ist immer der Benutzer, der den Server startet."
-#: utils/misc/guc.c:3346
+#: utils/misc/guc.c:3391
msgid "Sets the directories where Unix-domain sockets will be created."
msgstr "Setzt die Verzeichnisse, in denen Unix-Domain-Sockets erzeugt werden sollen."
-#: utils/misc/guc.c:3361
+#: utils/misc/guc.c:3406
msgid "Sets the host name or IP address(es) to listen to."
msgstr "Setzt den Hostnamen oder die IP-Adresse(n), auf der auf Verbindungen gewartet wird."
-#: utils/misc/guc.c:3376
+#: utils/misc/guc.c:3421
msgid "Sets the server's data directory."
msgstr "Setzt das Datenverzeichnis des Servers."
-#: utils/misc/guc.c:3387
+#: utils/misc/guc.c:3432
msgid "Sets the server's main configuration file."
msgstr "Setzt die Hauptkonfigurationsdatei des Servers."
-#: utils/misc/guc.c:3398
+#: utils/misc/guc.c:3443
msgid "Sets the server's \"hba\" configuration file."
msgstr "Setzt die »hba«-Konfigurationsdatei des Servers."
-#: utils/misc/guc.c:3409
+#: utils/misc/guc.c:3454
msgid "Sets the server's \"ident\" configuration file."
msgstr "Setzt die »ident«-Konfigurationsdatei des Servers."
-#: utils/misc/guc.c:3420
+#: utils/misc/guc.c:3465
msgid "Writes the postmaster PID to the specified file."
msgstr "Schreibt die Postmaster-PID in die angegebene Datei."
-#: utils/misc/guc.c:3431
+#: utils/misc/guc.c:3476
msgid "Location of the SSL server certificate file."
msgstr "Ort der SSL-Serverzertifikatsdatei."
-#: utils/misc/guc.c:3441
+#: utils/misc/guc.c:3486
msgid "Location of the SSL server private key file."
msgstr "Setzt den Ort der Datei mit dem privaten SSL-Server-Schlüssel."
-#: utils/misc/guc.c:3451
+#: utils/misc/guc.c:3496
msgid "Location of the SSL certificate authority file."
msgstr "Ort der SSL-Certificate-Authority-Datei."
-#: utils/misc/guc.c:3461
+#: utils/misc/guc.c:3506
msgid "Location of the SSL certificate revocation list file."
msgstr "Ort der SSL-Certificate-Revocation-List-Datei."
-#: utils/misc/guc.c:3471
+#: utils/misc/guc.c:3516
msgid "Writes temporary statistics files to the specified directory."
msgstr "Schreibt temporäre Statistikdateien in das angegebene Verzeichnis."
-#: utils/misc/guc.c:3482
-#, fuzzy
-#| msgid "List of names of potential synchronous standbys."
+#: utils/misc/guc.c:3527
msgid "Number of synchronous standbys and list of names of potential synchronous ones."
-msgstr "Liste der Namen der möglichen synchronen Standbys."
+msgstr "Anzahl synchroner Standbys und Liste der Namen der möglichen synchronen Standbys."
-#: utils/misc/guc.c:3493
+#: utils/misc/guc.c:3538
msgid "Sets default text search configuration."
msgstr "Setzt die vorgegebene Textsuchekonfiguration."
-#: utils/misc/guc.c:3503
+#: utils/misc/guc.c:3548
msgid "Sets the list of allowed SSL ciphers."
msgstr "Setzt die Liste der erlaubten SSL-Verschlüsselungsalgorithmen."
-#: utils/misc/guc.c:3518
+#: utils/misc/guc.c:3563
msgid "Sets the curve to use for ECDH."
msgstr "Setzt die für ECDH zu verwendende Kurve."
-#: utils/misc/guc.c:3533
+#: utils/misc/guc.c:3578
msgid "Sets the application name to be reported in statistics and logs."
msgstr "Setzt den Anwendungsnamen, der in Statistiken und Logs verzeichnet wird."
-#: utils/misc/guc.c:3544
+#: utils/misc/guc.c:3589
msgid "Sets the name of the cluster, which is included in the process title."
msgstr "Setzt den Namen des Clusters, welcher im Prozesstitel angezeigt wird."
-#: utils/misc/guc.c:3564
+#: utils/misc/guc.c:3600
+msgid "Sets the WAL resource managers for which WAL consistency checks are done."
+msgstr ""
+
+#: utils/misc/guc.c:3601
+msgid "Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay."
+msgstr ""
+
+#: utils/misc/guc.c:3620
msgid "Sets whether \"\\'\" is allowed in string literals."
msgstr "Bestimmt, ob »\\'« in Zeichenkettenkonstanten erlaubt ist."
-#: utils/misc/guc.c:3574
+#: utils/misc/guc.c:3630
msgid "Sets the output format for bytea."
msgstr "Setzt das Ausgabeformat für bytea."
-#: utils/misc/guc.c:3584
+#: utils/misc/guc.c:3640
msgid "Sets the message levels that are sent to the client."
msgstr "Setzt die Meldungstypen, die an den Client gesendet werden."
-#: utils/misc/guc.c:3585 utils/misc/guc.c:3638 utils/misc/guc.c:3649
-#: utils/misc/guc.c:3715
+#: utils/misc/guc.c:3641 utils/misc/guc.c:3694 utils/misc/guc.c:3705
+#: utils/misc/guc.c:3771
msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent."
msgstr "Jeder Wert schließt alle ihm folgenden Werte mit ein. Je weiter hinten der Wert steht, desto weniger Meldungen werden gesendet werden."
-#: utils/misc/guc.c:3595
+#: utils/misc/guc.c:3651
msgid "Enables the planner to use constraints to optimize queries."
msgstr "Ermöglicht dem Planer die Verwendung von Constraints, um Anfragen zu optimieren."
-#: utils/misc/guc.c:3596
+#: utils/misc/guc.c:3652
msgid "Table scans will be skipped if their constraints guarantee that no rows match the query."
msgstr "Tabellen-Scans werden übersprungen, wenn deren Constraints garantieren, dass keine Zeile mit der Abfrage übereinstimmt."
-#: utils/misc/guc.c:3606
+#: utils/misc/guc.c:3662
msgid "Sets the transaction isolation level of each new transaction."
msgstr "Setzt den Transaktionsisolationsgrad neuer Transaktionen."
-#: utils/misc/guc.c:3616
+#: utils/misc/guc.c:3672
msgid "Sets the display format for interval values."
msgstr "Setzt das Ausgabeformat für Intervallwerte."
-#: utils/misc/guc.c:3627
+#: utils/misc/guc.c:3683
msgid "Sets the verbosity of logged messages."
msgstr "Setzt den Detailgrad von geloggten Meldungen."
-#: utils/misc/guc.c:3637
+#: utils/misc/guc.c:3693
msgid "Sets the message levels that are logged."
msgstr "Setzt die Meldungstypen, die geloggt werden."
-#: utils/misc/guc.c:3648
+#: utils/misc/guc.c:3704
msgid "Causes all statements generating error at or above this level to be logged."
msgstr "Schreibt alle Anweisungen, die einen Fehler auf dieser Stufe oder höher verursachen, in den Log."
-#: utils/misc/guc.c:3659
+#: utils/misc/guc.c:3715
msgid "Sets the type of statements logged."
msgstr "Setzt die Anweisungsarten, die geloggt werden."
-#: utils/misc/guc.c:3669
+#: utils/misc/guc.c:3725
msgid "Sets the syslog \"facility\" to be used when syslog enabled."
msgstr "Setzt die zu verwendende Syslog-»Facility«, wenn Syslog angeschaltet ist."
-#: utils/misc/guc.c:3684
+#: utils/misc/guc.c:3740
msgid "Sets the session's behavior for triggers and rewrite rules."
msgstr "Setzt das Sitzungsverhalten für Trigger und Regeln."
-#: utils/misc/guc.c:3694
+#: utils/misc/guc.c:3750
msgid "Sets the current transaction's synchronization level."
msgstr "Setzt den Synchronisationsgrad der aktuellen Transaktion."
-#: utils/misc/guc.c:3704
+#: utils/misc/guc.c:3760
msgid "Allows archiving of WAL files using archive_command."
msgstr "Erlaubt die Archivierung von WAL-Dateien mittels archive_command."
-#: utils/misc/guc.c:3714
+#: utils/misc/guc.c:3770
msgid "Enables logging of recovery-related debugging information."
msgstr "Ermöglicht das Loggen von Debug-Informationen über die Wiederherstellung."
-#: utils/misc/guc.c:3730
+#: utils/misc/guc.c:3786
msgid "Collects function-level statistics on database activity."
msgstr "Sammelt Statistiken auf Funktionsebene über Datenbankaktivität."
-#: utils/misc/guc.c:3740
+#: utils/misc/guc.c:3796
msgid "Set the level of information written to the WAL."
msgstr "Setzt den Umfang der in den WAL geschriebenen Informationen."
-#: utils/misc/guc.c:3750
+#: utils/misc/guc.c:3806
msgid "Selects the dynamic shared memory implementation used."
msgstr "Wählt die zu verwendende Implementierung von dynamischem Shared Memory."
-#: utils/misc/guc.c:3760
+#: utils/misc/guc.c:3816
msgid "Selects the method used for forcing WAL updates to disk."
msgstr "Wählt die Methode, um das Schreiben von WAL-Änderungen auf die Festplatte zu erzwingen."
-#: utils/misc/guc.c:3770
+#: utils/misc/guc.c:3826
msgid "Sets how binary values are to be encoded in XML."
msgstr "Setzt, wie binäre Werte in XML kodiert werden."
-#: utils/misc/guc.c:3780
+#: utils/misc/guc.c:3836
msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments."
msgstr "Setzt, ob XML-Daten in impliziten Parse- und Serialisierungsoperationen als Dokument oder Fragment betrachtet werden sollen."
-#: utils/misc/guc.c:3791
+#: utils/misc/guc.c:3847
msgid "Use of huge pages on Linux."
msgstr "Huge Pages auf Linux verwenden."
-#: utils/misc/guc.c:3801
+#: utils/misc/guc.c:3857
msgid "Forces use of parallel query facilities."
msgstr "Verwendung der Einrichtungen für parallele Anfragen erzwingen."
-#: utils/misc/guc.c:3802
+#: utils/misc/guc.c:3858
msgid "If possible, run query using a parallel worker and with parallel restrictions."
msgstr "Wenn möglich werden Anfragen in einem parallelen Arbeitsprozess und mit parallelen Beschränkungen ausgeführt."
-#: utils/misc/guc.c:4602
+#: utils/misc/guc.c:3867
+msgid "Encrypt passwords."
+msgstr "Verschlüsselt Passwörter."
+
+#: utils/misc/guc.c:3868
+msgid "When a password is specified in CREATE USER or ALTER USER without writing either ENCRYPTED or UNENCRYPTED, this parameter determines whether the password is to be encrypted."
+msgstr "Wenn in CREATE USER oder ALTER USER ein Passwort ohne ENCRYPTED oder UNENCRYPTED angegeben ist, bestimmt dieser Parameter, ob das Passwort verschlüsselt wird."
+
+#: utils/misc/guc.c:4670
#, c-format
msgid "%s: could not access directory \"%s\": %s\n"
msgstr "%s: konnte nicht auf Verzeichnis »%s« zugreifen: %s\n"
-#: utils/misc/guc.c:4607
+#: utils/misc/guc.c:4675
#, c-format
msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n"
msgstr "Führen Sie initdb oder pg_basebackup aus, um ein PostgreSQL-Datenverzeichnis zu initialisieren.\n"
-#: utils/misc/guc.c:4627
+#: utils/misc/guc.c:4695
#, c-format
msgid ""
"%s does not know where to find the server configuration file.\n"
@@ -22818,12 +24029,12 @@ msgstr ""
"Sie müssen die Kommandozeilenoption --config-file oder -D angegeben oder\n"
"die Umgebungsvariable PGDATA setzen.\n"
-#: utils/misc/guc.c:4646
+#: utils/misc/guc.c:4714
#, c-format
msgid "%s: could not access the server configuration file \"%s\": %s\n"
msgstr "%s: konnte nicht auf die Serverkonfigurationsdatei »%s« zugreifen: %s\n"
-#: utils/misc/guc.c:4672
+#: utils/misc/guc.c:4740
#, c-format
msgid ""
"%s does not know where to find the database system data.\n"
@@ -22833,7 +24044,7 @@ msgstr ""
"zu finden sind. Sie können dies mit »data_directory« in »%s«, mit der\n"
"Kommandozeilenoption -D oder der Umgebungsvariable PGDATA angeben.\n"
-#: utils/misc/guc.c:4720
+#: utils/misc/guc.c:4788
#, c-format
msgid ""
"%s does not know where to find the \"hba\" configuration file.\n"
@@ -22843,7 +24054,7 @@ msgstr ""
"Sie können dies mit »hba_file« in »%s«, mit der\n"
"Kommandozeilenoption -D oder der Umgebungsvariable PGDATA angeben.\n"
-#: utils/misc/guc.c:4743
+#: utils/misc/guc.c:4811
#, c-format
msgid ""
"%s does not know where to find the \"ident\" configuration file.\n"
@@ -22853,138 +24064,138 @@ msgstr ""
"Sie können dies mit »ident_file« in »%s«, mit der\n"
"Kommandozeilenoption -D oder der Umgebungsvariable PGDATA angeben.\n"
-#: utils/misc/guc.c:5417 utils/misc/guc.c:5464
+#: utils/misc/guc.c:5485 utils/misc/guc.c:5532
msgid "Value exceeds integer range."
msgstr "Wert überschreitet Bereich für ganze Zahlen."
-#: utils/misc/guc.c:5687
+#: utils/misc/guc.c:5755
#, c-format
msgid "parameter \"%s\" requires a numeric value"
msgstr "Parameter »%s« erfordert einen numerischen Wert"
-#: utils/misc/guc.c:5696
+#: utils/misc/guc.c:5764
#, c-format
msgid "%g is outside the valid range for parameter \"%s\" (%g .. %g)"
msgstr "%g ist außerhalb des gültigen Bereichs für Parameter »%s« (%g ... %g)"
-#: utils/misc/guc.c:5849 utils/misc/guc.c:7192
+#: utils/misc/guc.c:5917 utils/misc/guc.c:7260
#, c-format
msgid "cannot set parameters during a parallel operation"
msgstr "während einer parallelen Operation können keine Parameter gesetzt werden"
-#: utils/misc/guc.c:5856 utils/misc/guc.c:6607 utils/misc/guc.c:6659
-#: utils/misc/guc.c:7020 utils/misc/guc.c:7780 utils/misc/guc.c:7948
-#: utils/misc/guc.c:9605
+#: utils/misc/guc.c:5924 utils/misc/guc.c:6675 utils/misc/guc.c:6727
+#: utils/misc/guc.c:7088 utils/misc/guc.c:7847 utils/misc/guc.c:8015
+#: utils/misc/guc.c:9690
#, c-format
msgid "unrecognized configuration parameter \"%s\""
msgstr "unbekannter Konfigurationsparameter »%s«"
-#: utils/misc/guc.c:5871 utils/misc/guc.c:7032
+#: utils/misc/guc.c:5939 utils/misc/guc.c:7100
#, c-format
msgid "parameter \"%s\" cannot be changed"
msgstr "Parameter »%s« kann nicht geändert werden"
-#: utils/misc/guc.c:5904
+#: utils/misc/guc.c:5972
#, c-format
msgid "parameter \"%s\" cannot be changed now"
msgstr "Parameter »%s« kann jetzt nicht geändert werden"
-#: utils/misc/guc.c:5922 utils/misc/guc.c:5968 utils/misc/guc.c:9621
+#: utils/misc/guc.c:5990 utils/misc/guc.c:6036 utils/misc/guc.c:9706
#, c-format
msgid "permission denied to set parameter \"%s\""
msgstr "keine Berechtigung, um Parameter »%s« zu setzen"
-#: utils/misc/guc.c:5958
+#: utils/misc/guc.c:6026
#, c-format
msgid "parameter \"%s\" cannot be set after connection start"
msgstr "Parameter »%s« kann nach Start der Verbindung nicht geändert werden"
-#: utils/misc/guc.c:6006
+#: utils/misc/guc.c:6074
#, c-format
msgid "cannot set parameter \"%s\" within security-definer function"
msgstr "Parameter »%s« kann nicht in einer Security-Definer-Funktion gesetzt werden"
-#: utils/misc/guc.c:6615 utils/misc/guc.c:6663 utils/misc/guc.c:7954
+#: utils/misc/guc.c:6683 utils/misc/guc.c:6731 utils/misc/guc.c:8021
#, c-format
msgid "must be superuser to examine \"%s\""
msgstr "nur Superuser können »%s« ansehen"
-#: utils/misc/guc.c:6729
+#: utils/misc/guc.c:6797
#, c-format
msgid "SET %s takes only one argument"
msgstr "SET %s darf nur ein Argument haben"
-#: utils/misc/guc.c:6980
+#: utils/misc/guc.c:7048
#, c-format
msgid "must be superuser to execute ALTER SYSTEM command"
msgstr "nur Superuser können den Befehl ALTER SYSTEM ausführen"
-#: utils/misc/guc.c:7065
+#: utils/misc/guc.c:7133
#, c-format
msgid "parameter value for ALTER SYSTEM must not contain a newline"
msgstr "Parameterwert für ALTER SYSTEM darf keine Newline enthalten"
-#: utils/misc/guc.c:7110
+#: utils/misc/guc.c:7178
#, c-format
msgid "could not parse contents of file \"%s\""
msgstr "konnte Inhalt der Datei »%s« nicht parsen"
-#: utils/misc/guc.c:7268
+#: utils/misc/guc.c:7336
#, c-format
msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented"
msgstr "SET LOCAL TRANSACTION SNAPSHOT ist nicht implementiert"
-#: utils/misc/guc.c:7353
+#: utils/misc/guc.c:7420
#, c-format
msgid "SET requires parameter name"
msgstr "SET benötigt Parameternamen"
-#: utils/misc/guc.c:7477
+#: utils/misc/guc.c:7544
#, c-format
msgid "attempt to redefine parameter \"%s\""
msgstr "Versuch, den Parameter »%s« zu redefinieren"
-#: utils/misc/guc.c:9238
+#: utils/misc/guc.c:9323
#, c-format
msgid "parameter \"%s\" could not be set"
msgstr "Parameter »%s« kann nicht gesetzt werden"
-#: utils/misc/guc.c:9325
+#: utils/misc/guc.c:9410
#, c-format
msgid "could not parse setting for parameter \"%s\""
msgstr "konnte Wert von Parameter »%s« nicht lesen"
-#: utils/misc/guc.c:9683 utils/misc/guc.c:9717
+#: utils/misc/guc.c:9768 utils/misc/guc.c:9802
#, c-format
msgid "invalid value for parameter \"%s\": %d"
msgstr "ungültiger Wert für Parameter »%s«: %d"
-#: utils/misc/guc.c:9751
+#: utils/misc/guc.c:9836
#, c-format
msgid "invalid value for parameter \"%s\": %g"
msgstr "ungültiger Wert für Parameter »%s«: %g"
-#: utils/misc/guc.c:9941
+#: utils/misc/guc.c:10106
#, c-format
msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session."
msgstr "»temp_buffers« kann nicht geändert werden, nachdem in der Sitzung auf temporäre Tabellen zugriffen wurde."
-#: utils/misc/guc.c:9953
+#: utils/misc/guc.c:10118
#, c-format
msgid "Bonjour is not supported by this build"
msgstr "Bonjour wird von dieser Installation nicht unterstützt"
-#: utils/misc/guc.c:9966
+#: utils/misc/guc.c:10131
#, c-format
msgid "SSL is not supported by this build"
msgstr "SSL wird von dieser Installation nicht unterstützt"
-#: utils/misc/guc.c:9978
+#: utils/misc/guc.c:10143
#, c-format
msgid "Cannot enable parameter when \"log_statement_stats\" is true."
msgstr "Kann Parameter nicht einschalten, wenn »log_statement_stats« an ist."
-#: utils/misc/guc.c:9990
+#: utils/misc/guc.c:10155
#, c-format
msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true."
msgstr "Kann »log_statement_stats« nicht einschalten, wenn »log_parser_stats«, »log_planner_stats« oder »log_executor_stats« an ist."
@@ -22997,14 +24208,20 @@ msgstr "interner Fehler: unbekannter Parametertyp\n"
#: utils/misc/pg_config.c:61
#, c-format
msgid "query-specified return tuple and function return type are not compatible"
-msgstr ""
+msgstr "in der Anfrage angegebenes Rückgabetupel und Rückgabetyp der Funktion sind nicht kompatibel"
+
+#: utils/misc/pg_controldata.c:58 utils/misc/pg_controldata.c:138
+#: utils/misc/pg_controldata.c:244 utils/misc/pg_controldata.c:311
+#, c-format
+msgid "calculated CRC checksum does not match value stored in file"
+msgstr "berechnete CRC-Prüfsumme stimmt nicht mit dem Wert in der Datei überein"
-#: utils/misc/rls.c:127
+#: utils/misc/rls.c:128
#, c-format
msgid "query would be affected by row-level security policy for table \"%s\""
msgstr "Policy für Sicherheit auf Zeilenebene für Tabelle »%s« würde Auswirkung auf die Anfrage haben"
-#: utils/misc/rls.c:129
+#: utils/misc/rls.c:130
#, c-format
msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY."
msgstr "Um die Policy für den Tabelleneigentümer zu deaktivieren, verwenden Sie ALTER TABLE NO FORCE ROW LEVEL SECURITY."
@@ -23079,65 +24296,77 @@ msgstr "Zeile ist zu lang in Zeitzonendatei »%s«, Zeile %d"
msgid "@INCLUDE without file name in time zone file \"%s\", line %d"
msgstr "@INCLUDE ohne Dateiname in Zeitzonendatei »%s«, Zeile %d"
-#: utils/mmgr/aset.c:506
+#: utils/mmgr/aset.c:405
#, c-format
msgid "Failed while creating memory context \"%s\"."
msgstr "Fehler während der Erzeugung des Speicherkontexts »%s«."
-#: utils/mmgr/mcxt.c:771 utils/mmgr/mcxt.c:806 utils/mmgr/mcxt.c:843
-#: utils/mmgr/mcxt.c:880 utils/mmgr/mcxt.c:914 utils/mmgr/mcxt.c:943
-#: utils/mmgr/mcxt.c:977 utils/mmgr/mcxt.c:1059 utils/mmgr/mcxt.c:1093
-#: utils/mmgr/mcxt.c:1142
+#: utils/mmgr/dsa.c:518
+#, fuzzy, c-format
+#| msgid "could not set up XML error handler"
+msgid "could not attach to dsa_handle"
+msgstr "konnte XML-Fehlerbehandlung nicht einrichten"
+
+#: utils/mmgr/dsa.c:714 utils/mmgr/dsa.c:796
+#, fuzzy, c-format
+#| msgid "Failed on request of size %zu."
+msgid "Failed on DSA request of size %zu."
+msgstr "Fehler bei Anfrage mit Größe %zu."
+
+#: utils/mmgr/mcxt.c:726 utils/mmgr/mcxt.c:761 utils/mmgr/mcxt.c:798
+#: utils/mmgr/mcxt.c:835 utils/mmgr/mcxt.c:869 utils/mmgr/mcxt.c:898
+#: utils/mmgr/mcxt.c:932 utils/mmgr/mcxt.c:983 utils/mmgr/mcxt.c:1017
+#: utils/mmgr/mcxt.c:1051
#, c-format
msgid "Failed on request of size %zu."
msgstr "Fehler bei Anfrage mit Größe %zu."
-#: utils/mmgr/portalmem.c:209
+#: utils/mmgr/portalmem.c:186
#, c-format
msgid "cursor \"%s\" already exists"
msgstr "Cursor »%s« existiert bereits"
-#: utils/mmgr/portalmem.c:213
+#: utils/mmgr/portalmem.c:190
#, c-format
msgid "closing existing cursor \"%s\""
msgstr "bestehender Cursor »%s« wird geschlossen"
-#: utils/mmgr/portalmem.c:421
+#: utils/mmgr/portalmem.c:394
#, c-format
msgid "portal \"%s\" cannot be run"
msgstr "Portal »%s« kann nicht ausgeführt werden"
-#: utils/mmgr/portalmem.c:501
+#: utils/mmgr/portalmem.c:474
#, c-format
msgid "cannot drop active portal \"%s\""
msgstr "aktives Portal »%s« kann nicht gelöscht werden"
-#: utils/mmgr/portalmem.c:705
+#: utils/mmgr/portalmem.c:678
#, c-format
msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD"
msgstr "PREPARE kann nicht in einer Transaktion ausgeführt werden, die einen Cursor mit WITH HOLD erzeugt hat"
-#: utils/sort/logtape.c:226
+#: utils/sort/logtape.c:252
#, c-format
msgid "could not read block %ld of temporary file: %m"
msgstr "konnte Block %ld von temporärer Datei nicht lesen: %m"
-#: utils/sort/tuplesort.c:3378
+#: utils/sort/tuplesort.c:3056
#, c-format
msgid "cannot have more than %d runs for an external sort"
msgstr "ein externer Sortiervorgang kann nicht mehr als %d Durchgänge haben"
-#: utils/sort/tuplesort.c:4450
+#: utils/sort/tuplesort.c:4125
#, c-format
msgid "could not create unique index \"%s\""
msgstr "konnte Unique Index »%s« nicht erstellen"
-#: utils/sort/tuplesort.c:4452
+#: utils/sort/tuplesort.c:4127
#, c-format
msgid "Key %s is duplicated."
msgstr "Schlüssel %s ist doppelt vorhanden."
-#: utils/sort/tuplesort.c:4453
+#: utils/sort/tuplesort.c:4128
#, c-format
msgid "Duplicate keys exist."
msgstr "Es existieren doppelte Schlüssel."
@@ -23163,60 +24392,153 @@ msgstr "konnte nicht aus temporärer Datei für Tuplestore lesen: %m"
msgid "could not write to tuplestore temporary file: %m"
msgstr "konnte nicht in temporäre Datei für Tuplestore schreiben: %m"
-#: utils/time/snapmgr.c:577
+#: utils/time/snapmgr.c:618
#, c-format
msgid "The source transaction is not running anymore."
msgstr "Die Quelltransaktion läuft nicht mehr."
-#: utils/time/snapmgr.c:1138
+#: utils/time/snapmgr.c:1190
#, c-format
msgid "cannot export a snapshot from a subtransaction"
msgstr "aus einer Subtransaktion kann kein Snapshot exportiert werden"
-#: utils/time/snapmgr.c:1287 utils/time/snapmgr.c:1292
-#: utils/time/snapmgr.c:1297 utils/time/snapmgr.c:1312
-#: utils/time/snapmgr.c:1317 utils/time/snapmgr.c:1322
-#: utils/time/snapmgr.c:1421 utils/time/snapmgr.c:1437
-#: utils/time/snapmgr.c:1462
+#: utils/time/snapmgr.c:1339 utils/time/snapmgr.c:1344
+#: utils/time/snapmgr.c:1349 utils/time/snapmgr.c:1364
+#: utils/time/snapmgr.c:1369 utils/time/snapmgr.c:1374
+#: utils/time/snapmgr.c:1473 utils/time/snapmgr.c:1489
+#: utils/time/snapmgr.c:1514
#, c-format
msgid "invalid snapshot data in file \"%s\""
msgstr "ungültige Snapshot-Daten in Datei »%s«"
-#: utils/time/snapmgr.c:1359
+#: utils/time/snapmgr.c:1411
#, c-format
msgid "SET TRANSACTION SNAPSHOT must be called before any query"
msgstr "SET TRANSACTION SNAPSHOT muss vor allen Anfragen aufgerufen werden"
-#: utils/time/snapmgr.c:1368
+#: utils/time/snapmgr.c:1420
#, c-format
msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ"
msgstr "eine Snapshot-importierende Transaktion muss Isolationsgrad SERIALIZABLE oder REPEATABLE READ haben"
-#: utils/time/snapmgr.c:1377 utils/time/snapmgr.c:1386
+#: utils/time/snapmgr.c:1429 utils/time/snapmgr.c:1438
#, c-format
msgid "invalid snapshot identifier: \"%s\""
msgstr "ungültiger Snapshot-Bezeichner: »%s«"
-#: utils/time/snapmgr.c:1475
+#: utils/time/snapmgr.c:1527
#, c-format
msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction"
msgstr "eine serialisierbare Transaktion kann keinen Snapshot aus einer nicht-serialisierbaren Transaktion importieren"
-#: utils/time/snapmgr.c:1479
+#: utils/time/snapmgr.c:1531
#, c-format
msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction"
msgstr "eine serialisierbare Transaktion, die nicht im Read-Only-Modus ist, kann keinen Snapshot aus einer Read-Only-Transaktion importieren"
-#: utils/time/snapmgr.c:1494
+#: utils/time/snapmgr.c:1546
#, c-format
msgid "cannot import a snapshot from a different database"
msgstr "kann keinen Snapshot aus einer anderen Datenbank importieren"
-#~ msgid "could not open process token: error code %lu\n"
-#~ msgstr "konnte Prozess-Token nicht öffnen: Fehlercode %lu\n"
+#~ msgid ""
+#~ "WARNING: Calculated CRC checksum does not match value stored in file.\n"
+#~ "Either the file is corrupt, or it has a different layout than this program\n"
+#~ "is expecting. The results below are untrustworthy.\n"
+#~ "\n"
+#~ msgstr ""
+#~ "WARNUNG: Berechnete CRC-Prüfsumme stimmt nicht mit dem Wert in der Datei\n"
+#~ "überein. Entweder ist die Datei kaputt oder sie hat ein anderes Layout\n"
+#~ "als von diesem Programm erwartet. Die Ergebnisse unten sind nicht\n"
+#~ "verlässlich.\n"
+#~ "\n"
+
+#~ msgid "Proceeding with relation creation anyway."
+#~ msgstr "Relation wird trotzdem erzeugt."
+
+#~ msgid "default expression must not return a set"
+#~ msgstr "Vorgabeausdruck kann keine Ergebnismenge zurückgeben"
+
+#~ msgid "changing return type of function %s from \"opaque\" to \"language_handler\""
+#~ msgstr "ändere Rückgabetyp von Funktion %s von »opaque« in »language_handler«"
+
+#~ msgid "changing return type of function %s from \"opaque\" to \"trigger\""
+#~ msgstr "ändere Rückgabetyp von Funktion %s von »opaque« in »trigger«"
+
+#~ msgid "functions and operators can take at most one set argument"
+#~ msgstr "Funktionen und Operatoren können höchstens ein Mengenargument haben"
+
+#~ msgid "IS DISTINCT FROM does not support set arguments"
+#~ msgstr "IS DISTINCT FROM unterstützt keine Mengenargumente"
+
+#~ msgid "op ANY/ALL (array) does not support set arguments"
+#~ msgstr "op ANY/ALL (array) unterstützt keine Mengenargumente"
+
+#~ msgid "NULLIF does not support set arguments"
+#~ msgstr "NULLIF unterstützt keine Mengenargumente"
+
+#~ msgid "hostssl requires SSL to be turned on"
+#~ msgstr "für hostssl muss SSL angeschaltet sein"
+
+#~ msgid "could not create %s socket: %m"
+#~ msgstr "konnte %s-Socket nicht erstellen: %m"
+
+#~ msgid "could not bind %s socket: %m"
+#~ msgstr "konnte %s-Socket nicht binden: %m"
+
+#~ msgid "could not listen on %s socket: %m"
+#~ msgstr "konnte nicht auf %s-Socket hören: %m"
+
+#~ msgid "WHERE CURRENT OF is not supported on a view with no underlying relation"
+#~ msgstr "WHERE CURRENT OF wird nicht unterstützt für Sichten ohne zugrundeliegende Relation"
+
+#~ msgid "WHERE CURRENT OF is not supported on a view with more than one underlying relation"
+#~ msgstr "WHERE CURRENT OF wird nicht unterstützt für Sichten mit mehr als einer zugrundeliegenden Relation"
+
+#~ msgid "WHERE CURRENT OF is not supported on a view with grouping or aggregation"
+#~ msgstr "WHERE CURRENT OF wird nicht unterstützt für Sichten mit Gruppierung oder Aggregierung"
+
+#~ msgid "DEFAULT can only appear in a VALUES list within INSERT"
+#~ msgstr "DEFAULT kann nur in VALUES-Liste innerhalb von INSERT auftreten"
+
+#~ msgid "argument of %s must be type boolean, not type %s"
+#~ msgstr "Argument von %s muss Typ boolean haben, nicht Typ %s"
+
+#~ msgid "argument declared \"anyrange\" is not consistent with argument declared \"anyelement\""
+#~ msgstr "als »anyrange« deklariertes Argument ist nicht mit als »anyelement« deklariertem Argument konsistent"
+
+#~ msgid "index expression cannot return a set"
+#~ msgstr "Indexausdruck kann keine Ergebnismenge zurückgeben"
+
+#~ msgid "transform expression must not return a set"
+#~ msgstr "Umwandlungsausdruck kann keine Ergebnismenge zurückgeben"
+
+#~ msgid "autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\""
+#~ msgstr "Autovacuum: verwaiste temporäre Tabelle »%s.%s« in Datenbank »%s« gefunden"
+
+#~ msgid "invalid socket: %s"
+#~ msgstr "ungültiges Socket: %s"
+
+#~ msgid "rule \"%s\" does not exist"
+#~ msgstr "Regel »%s« existiert nicht"
+
+#~ msgid "there are multiple rules named \"%s\""
+#~ msgstr "es gibt mehrere Regeln namens »%s«"
+
+#~ msgid "Specify a relation name as well as a rule name."
+#~ msgstr "Geben Sie einen Relationsnamen und einen Regelnamen an."
+
+#~ msgid "not enough shared memory for elements of data structure \"%s\" (%zu bytes requested)"
+#~ msgstr "nicht genug Shared-Memory für Elemente der Datenstruktur »%s« (%zu Bytes angefordert)"
+
+#~ msgid "corrupted item pointer: offset = %u, length = %u"
+#~ msgstr "verfälschter Item-Zeiger: offset = %u, length = %u"
+
+#~ msgid "\"TZ\"/\"tz\"/\"OF\" format patterns are not supported in to_date"
+#~ msgstr "Formatmuster »TZ«/»tz«/»OF« werden in to_date nicht unterstützt"
-#~ msgid "could not get SID for Administrators group: error code %lu\n"
-#~ msgstr "konnte SID der Administrators-Gruppe nicht ermitteln: Fehlercode %lu\n"
+#~ msgid "invalid input syntax for integer: \"%s\""
+#~ msgstr "ungültige Eingabesyntax für ganze Zahl: »%s«"
-#~ msgid "could not get SID for PowerUsers group: error code %lu\n"
-#~ msgstr "konnte SID der PowerUsers-Gruppe nicht ermitteln: Fehlercode %lu\n"
+#~ msgid "Causes subtables to be included by default in various commands."
+#~ msgstr "Schließt abgeleitete Tabellen in diverse Befehle automatisch ein."
diff --git a/src/backend/po/fr.po b/src/backend/po/fr.po
index af5ee56238..c70937040c 100644
--- a/src/backend/po/fr.po
+++ b/src/backend/po/fr.po
@@ -1,52 +1,52 @@
# translation of postgres.po to fr_fr
# french message translation file for postgres
#
-# Use these quotes: � %s �
+# Use these quotes: « %s »
# Guillaume Lelarge <[email protected]>, 2003-2009.
#
msgid ""
msgstr ""
"Project-Id-Version: PostgreSQL 9.6\n"
"Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2016-05-09 08:38+0000\n"
-"PO-Revision-Date: 2016-05-09 23:02+0200\n"
+"POT-Creation-Date: 2017-02-06 16:08+0000\n"
+"PO-Revision-Date: 2017-02-06 19:01+0100\n"
"Last-Translator: Guillaume Lelarge <[email protected]>\n"
"Language-Team: French <[email protected]>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 1.8.7.1\n"
+"X-Generator: Poedit 1.8.11\n"
#: ../common/config_info.c:131 ../common/config_info.c:139 ../common/config_info.c:147 ../common/config_info.c:155 ../common/config_info.c:163 ../common/config_info.c:171 ../common/config_info.c:179 ../common/config_info.c:187 ../common/config_info.c:195
msgid "not recorded"
-msgstr "non enregistr�"
+msgstr "non enregistré"
-#: ../common/controldata_utils.c:52 commands/copy.c:2798 commands/extension.c:3120 utils/adt/genfile.c:134
+#: ../common/controldata_utils.c:52 commands/copy.c:2833 commands/extension.c:3141 utils/adt/genfile.c:134
#, c-format
msgid "could not open file \"%s\" for reading: %m"
-msgstr "n'a pas pu ouvrir le fichier � %s � pour une lecture : %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m"
#: ../common/controldata_utils.c:56
#, c-format
msgid "%s: could not open file \"%s\" for reading: %s\n"
-msgstr "%s : n'a pas pu ouvrir le fichier � %s � en lecture : %s\n"
+msgstr "%s : n'a pas pu ouvrir le fichier « %s » en lecture : %s\n"
-#: ../common/controldata_utils.c:66 access/transam/timeline.c:346 access/transam/xlog.c:3193 access/transam/xlog.c:10338 access/transam/xlog.c:10351 access/transam/xlog.c:10714 access/transam/xlog.c:10757 access/transam/xlog.c:10796 access/transam/xlog.c:10839 access/transam/xlogfuncs.c:666 access/transam/xlogfuncs.c:685 commands/extension.c:3130 replication/logical/origin.c:665 replication/logical/origin.c:695
-#: replication/logical/reorderbuffer.c:3090 replication/walsender.c:499 storage/file/copydir.c:176 utils/adt/genfile.c:151
+#: ../common/controldata_utils.c:66 access/transam/timeline.c:346 access/transam/xlog.c:3220 access/transam/xlog.c:10423 access/transam/xlog.c:10436 access/transam/xlog.c:10828 access/transam/xlog.c:10871 access/transam/xlog.c:10910 access/transam/xlog.c:10953 access/transam/xlogfuncs.c:665 access/transam/xlogfuncs.c:684 commands/extension.c:3151 replication/logical/origin.c:665 replication/logical/origin.c:695
+#: replication/logical/reorderbuffer.c:3099 replication/walsender.c:499 storage/file/copydir.c:176 utils/adt/genfile.c:151
#, c-format
msgid "could not read file \"%s\": %m"
-msgstr "n'a pas pu lire le fichier � %s � : %m"
+msgstr "n'a pas pu lire le fichier « %s » : %m"
#: ../common/controldata_utils.c:69
#, c-format
msgid "%s: could not read file \"%s\": %s\n"
-msgstr "%s : n'a pas pu lire le fichier � %s � : %s\n"
+msgstr "%s : n'a pas pu lire le fichier « %s » : %s\n"
#: ../common/controldata_utils.c:86
msgid "calculated CRC checksum does not match value stored in file"
-msgstr "la somme de contr�le CRC calcul�e ne correspond par � la valeur enregistr�e dans le fichier"
+msgstr "la somme de contrôle CRC calculée ne correspond par à la valeur enregistrée dans le fichier"
#: ../common/controldata_utils.c:88
#, c-format
@@ -56,16 +56,16 @@ msgid ""
"is expecting. The results below are untrustworthy.\n"
"\n"
msgstr ""
-"ATTENTION : Les sommes de contr�le (CRC) calcul�es ne correspondent pas aux\n"
-"valeurs stock�es dans le fichier.\n"
-"Soit le fichier est corrompu, soit son organisation diff�re de celle\n"
+"ATTENTION : Les sommes de contrôle (CRC) calculées ne correspondent pas aux\n"
+"valeurs stockées dans le fichier.\n"
+"Soit le fichier est corrompu, soit son organisation diffère de celle\n"
"attendue par le programme.\n"
-"Les r�sultats ci-dessous ne sont pas dignes de confiance.\n"
+"Les résultats ci-dessous ne sont pas dignes de confiance.\n"
"\n"
#: ../common/controldata_utils.c:97
msgid "byte ordering mismatch"
-msgstr "diff�rence de l'ordre des octets"
+msgstr "différence de l'ordre des octets"
#: ../common/controldata_utils.c:99
#, c-format
@@ -75,51 +75,51 @@ msgid ""
"used by this program. In that case the results below would be incorrect, and\n"
"the PostgreSQL installation would be incompatible with this data directory.\n"
msgstr ""
-"ATTENTION : possible incoh�rence dans l'ordre des octets\n"
-"L'ordre des octets utilis� pour enregistrer le fichier pg_control peut ne\n"
-"pas correspondre � celui utilis� par ce programme. Dans ce cas, les\n"
-"r�sultats ci-dessous sont incorrects, et l'installation PostgreSQL\n"
-"incompatible avec ce r�pertoire des donn�es.\n"
+"ATTENTION : possible incohérence dans l'ordre des octets\n"
+"L'ordre des octets utilisé pour enregistrer le fichier pg_control peut ne\n"
+"pas correspondre à celui utilisé par ce programme. Dans ce cas, les\n"
+"résultats ci-dessous sont incorrects, et l'installation PostgreSQL\n"
+"incompatible avec ce répertoire des données.\n"
#: ../common/exec.c:127 ../common/exec.c:241 ../common/exec.c:284
#, c-format
msgid "could not identify current directory: %s"
-msgstr "n'a pas pu identifier le r�pertoire courant : %s"
+msgstr "n'a pas pu identifier le répertoire courant : %s"
#: ../common/exec.c:146
#, c-format
msgid "invalid binary \"%s\""
-msgstr "binaire � %s � invalide"
+msgstr "binaire « %s » invalide"
#: ../common/exec.c:195
#, c-format
msgid "could not read binary \"%s\""
-msgstr "n'a pas pu lire le binaire � %s �"
+msgstr "n'a pas pu lire le binaire « %s »"
#: ../common/exec.c:202
#, c-format
msgid "could not find a \"%s\" to execute"
-msgstr "n'a pas pu trouver un � %s � � ex�cuter"
+msgstr "n'a pas pu trouver un « %s » à exécuter"
#: ../common/exec.c:257 ../common/exec.c:293
#, c-format
msgid "could not change directory to \"%s\": %s"
-msgstr "n'a pas pu changer le r�pertoire par � %s � : %s"
+msgstr "n'a pas pu changer le répertoire par « %s » : %s"
#: ../common/exec.c:272
#, c-format
msgid "could not read symbolic link \"%s\""
-msgstr "n'a pas pu lire le lien symbolique � %s �"
+msgstr "n'a pas pu lire le lien symbolique « %s »"
#: ../common/exec.c:523
#, c-format
msgid "pclose failed: %s"
-msgstr "�chec de pclose : %s"
+msgstr "échec de pclose : %s"
#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 ../common/fe_memutils.c:98 ../common/psprintf.c:181 ../port/path.c:632 ../port/path.c:670 ../port/path.c:687
#, c-format
msgid "out of memory\n"
-msgstr "m�moire �puis�e\n"
+msgstr "mémoire épuisée\n"
#: ../common/fe_memutils.c:92
#, c-format
@@ -129,25 +129,25 @@ msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n"
#: ../common/pgfnames.c:45
#, c-format
msgid "could not open directory \"%s\": %s\n"
-msgstr "n'a pas pu ouvrir le r�pertoire � %s � : %s\n"
+msgstr "n'a pas pu ouvrir le répertoire « %s » : %s\n"
#: ../common/pgfnames.c:72
#, c-format
msgid "could not read directory \"%s\": %s\n"
-msgstr "n'a pas pu lire le r�pertoire � %s � : %s\n"
+msgstr "n'a pas pu lire le répertoire « %s » : %s\n"
#: ../common/pgfnames.c:84
#, c-format
msgid "could not close directory \"%s\": %s\n"
-msgstr "n'a pas pu fermer le r�pertoire � %s � : %s\n"
+msgstr "n'a pas pu fermer le répertoire « %s » : %s\n"
-#: ../common/psprintf.c:179 ../port/path.c:630 ../port/path.c:668 ../port/path.c:685 access/transam/twophase.c:1261 access/transam/xlog.c:6069 lib/stringinfo.c:258 libpq/auth.c:847 libpq/auth.c:1210 libpq/auth.c:1278 libpq/auth.c:1794 postmaster/bgworker.c:289 postmaster/bgworker.c:797 postmaster/postmaster.c:2323 postmaster/postmaster.c:2354 postmaster/postmaster.c:3886 postmaster/postmaster.c:4576 postmaster/postmaster.c:4644
-#: postmaster/postmaster.c:5343 postmaster/postmaster.c:5596 replication/logical/logical.c:170 storage/buffer/localbuf.c:422 storage/file/fd.c:729 storage/file/fd.c:1126 storage/file/fd.c:1244 storage/file/fd.c:1916 storage/ipc/procarray.c:1060 storage/ipc/procarray.c:1546 storage/ipc/procarray.c:1553 storage/ipc/procarray.c:1967 storage/ipc/procarray.c:2570 utils/adt/formatting.c:1522 utils/adt/formatting.c:1642 utils/adt/formatting.c:1763
-#: utils/adt/regexp.c:219 utils/adt/varlena.c:4440 utils/adt/varlena.c:4461 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:431 utils/hash/dynahash.c:537 utils/hash/dynahash.c:1049 utils/mb/mbutils.c:376 utils/mb/mbutils.c:709 utils/misc/guc.c:3885 utils/misc/guc.c:3901 utils/misc/guc.c:3914 utils/misc/guc.c:6859 utils/misc/tzparser.c:470 utils/mmgr/aset.c:505 utils/mmgr/mcxt.c:770 utils/mmgr/mcxt.c:805 utils/mmgr/mcxt.c:842
-#: utils/mmgr/mcxt.c:879 utils/mmgr/mcxt.c:913 utils/mmgr/mcxt.c:942 utils/mmgr/mcxt.c:976 utils/mmgr/mcxt.c:1058 utils/mmgr/mcxt.c:1092 utils/mmgr/mcxt.c:1141
+#: ../common/psprintf.c:179 ../port/path.c:630 ../port/path.c:668 ../port/path.c:685 access/transam/twophase.c:1262 access/transam/xlog.c:6108 lib/stringinfo.c:258 libpq/auth.c:850 libpq/auth.c:1213 libpq/auth.c:1281 libpq/auth.c:1797 postmaster/bgworker.c:289 postmaster/bgworker.c:796 postmaster/postmaster.c:2335 postmaster/postmaster.c:2366 postmaster/postmaster.c:3899 postmaster/postmaster.c:4589 postmaster/postmaster.c:4664
+#: postmaster/postmaster.c:5339 postmaster/postmaster.c:5603 replication/libpqwalreceiver/libpqwalreceiver.c:143 replication/logical/logical.c:168 storage/buffer/localbuf.c:436 storage/file/fd.c:729 storage/file/fd.c:1126 storage/file/fd.c:1244 storage/file/fd.c:1916 storage/ipc/procarray.c:1061 storage/ipc/procarray.c:1547 storage/ipc/procarray.c:1554 storage/ipc/procarray.c:1968 storage/ipc/procarray.c:2571 utils/adt/formatting.c:1522
+#: utils/adt/formatting.c:1642 utils/adt/formatting.c:1763 utils/adt/pg_locale.c:463 utils/adt/pg_locale.c:647 utils/adt/regexp.c:219 utils/adt/varlena.c:4440 utils/adt/varlena.c:4461 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:429 utils/hash/dynahash.c:535 utils/hash/dynahash.c:1047 utils/mb/mbutils.c:376 utils/mb/mbutils.c:709 utils/misc/guc.c:3888 utils/misc/guc.c:3904 utils/misc/guc.c:3917 utils/misc/guc.c:6863 utils/misc/tzparser.c:468
+#: utils/mmgr/aset.c:509 utils/mmgr/mcxt.c:767 utils/mmgr/mcxt.c:802 utils/mmgr/mcxt.c:839 utils/mmgr/mcxt.c:876 utils/mmgr/mcxt.c:910 utils/mmgr/mcxt.c:939 utils/mmgr/mcxt.c:973 utils/mmgr/mcxt.c:1055 utils/mmgr/mcxt.c:1089 utils/mmgr/mcxt.c:1138
#, c-format
msgid "out of memory"
-msgstr "m�moire �puis�e"
+msgstr "mémoire épuisée"
#: ../common/relpath.c:59
#, c-format
@@ -157,12 +157,12 @@ msgstr "nom du fork invalide"
#: ../common/relpath.c:60
#, c-format
msgid "Valid fork names are \"main\", \"fsm\", \"vm\", and \"init\"."
-msgstr "Les noms de fork valides sont � main �, � fsm �, � vm � et � init �."
+msgstr "Les noms de fork valides sont « main », « fsm », « vm » et « init »."
#: ../common/restricted_token.c:68
#, c-format
msgid "%s: WARNING: cannot create restricted tokens on this platform\n"
-msgstr "%s : ATTENTION : ne peut pas cr�r les jetons restreints sur cette plateforme\n"
+msgstr "%s : ATTENTION : ne peut pas crér les jetons restreints sur cette plateforme\n"
#: ../common/restricted_token.c:77
#, c-format
@@ -177,53 +177,53 @@ msgstr "%s : n'a pas pu allouer les SID : code d'erreur %lu\n"
#: ../common/restricted_token.c:110
#, c-format
msgid "%s: could not create restricted token: error code %lu\n"
-msgstr "%s : n'a pas pu cr�er le jeton restreint : code d'erreur %lu\n"
+msgstr "%s : n'a pas pu créer le jeton restreint : code d'erreur %lu\n"
#: ../common/restricted_token.c:132
#, c-format
msgid "%s: could not start process for command \"%s\": error code %lu\n"
-msgstr "%s : n'a pas pu d�marrer le processus pour la commande � %s � : code d'erreur %lu\n"
+msgstr "%s : n'a pas pu démarrer le processus pour la commande « %s » : code d'erreur %lu\n"
#: ../common/restricted_token.c:170
#, c-format
msgid "%s: could not re-execute with restricted token: error code %lu\n"
-msgstr "%s : n'a pas pu r�-ex�cuter le jeton restreint : code d'erreur %lu\n"
+msgstr "%s : n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu\n"
#: ../common/restricted_token.c:186
#, c-format
msgid "%s: could not get exit code from subprocess: error code %lu\n"
-msgstr "%s : n'a pas pu r�cup�rer le code de statut du sous-processus : code d'erreur %lu\n"
+msgstr "%s : n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu\n"
#: ../common/rmtree.c:77
#, c-format
msgid "could not stat file or directory \"%s\": %s\n"
msgstr ""
-"n'a pas pu r�cup�rer les informations sur le fichier ou r�pertoire\n"
-"� %s � : %s\n"
+"n'a pas pu récupérer les informations sur le fichier ou répertoire\n"
+"« %s » : %s\n"
#: ../common/rmtree.c:104 ../common/rmtree.c:121
#, c-format
msgid "could not remove file or directory \"%s\": %s\n"
-msgstr "n'a pas pu supprimer le fichier ou r�pertoire � %s � : %s\n"
+msgstr "n'a pas pu supprimer le fichier ou répertoire « %s » : %s\n"
#: ../common/username.c:45
#, c-format
msgid "could not look up effective user ID %ld: %s"
-msgstr "n'a pas pu trouver l'identifiant r�el %ld de l'utilisateur : %s"
+msgstr "n'a pas pu trouver l'identifiant réel %ld de l'utilisateur : %s"
-#: ../common/username.c:47 libpq/auth.c:1741
+#: ../common/username.c:47 libpq/auth.c:1744
msgid "user does not exist"
msgstr "l'utilisateur n'existe pas"
#: ../common/username.c:62
#, c-format
msgid "user name lookup failure: error code %lu"
-msgstr "�chec de la recherche du nom d'utilisateur : code d'erreur %lu"
+msgstr "échec de la recherche du nom d'utilisateur : code d'erreur %lu"
#: ../common/wait_error.c:47
#, c-format
msgid "command not executable"
-msgstr "commande non ex�cutable"
+msgstr "commande non exécutable"
#: ../common/wait_error.c:51
#, c-format
@@ -233,67 +233,67 @@ msgstr "commande introuvable"
#: ../common/wait_error.c:56
#, c-format
msgid "child process exited with exit code %d"
-msgstr "le processus fils a quitt� avec le code de sortie %d"
+msgstr "le processus fils a quitté avec le code de sortie %d"
#: ../common/wait_error.c:63
#, c-format
msgid "child process was terminated by exception 0x%X"
-msgstr "le processus fils a �t� termin� par l'exception 0x%X"
+msgstr "le processus fils a été terminé par l'exception 0x%X"
#: ../common/wait_error.c:73
#, c-format
msgid "child process was terminated by signal %s"
-msgstr "le processus fils a �t� termin� par le signal %s"
+msgstr "le processus fils a été terminé par le signal %s"
#: ../common/wait_error.c:77
#, c-format
msgid "child process was terminated by signal %d"
-msgstr "le processus fils a �t� termin� par le signal %d"
+msgstr "le processus fils a été terminé par le signal %d"
#: ../common/wait_error.c:82
#, c-format
msgid "child process exited with unrecognized status %d"
-msgstr "le processus fils a quitt� avec un statut %d non reconnu"
+msgstr "le processus fils a quitté avec un statut %d non reconnu"
-#: ../port/chklocale.c:294
+#: ../port/chklocale.c:293
#, c-format
msgid "could not determine encoding for codeset \"%s\""
-msgstr "n'a pas pu d�terminer l'encodage pour le codeset � %s �"
+msgstr "n'a pas pu déterminer l'encodage pour le codeset « %s »"
-#: ../port/chklocale.c:295 ../port/chklocale.c:424 postmaster/postmaster.c:4876
+#: ../port/chklocale.c:294 ../port/chklocale.c:423 postmaster/postmaster.c:4868
#, c-format
msgid "Please report this to <[email protected]>."
-msgstr "Veuillez rapporter ceci � <[email protected]>."
+msgstr "Veuillez rapporter ceci à <[email protected]>."
-#: ../port/chklocale.c:416 ../port/chklocale.c:422
+#: ../port/chklocale.c:415 ../port/chklocale.c:421
#, c-format
msgid "could not determine encoding for locale \"%s\": codeset is \"%s\""
-msgstr "n'a pas pu d�terminer l'encodage pour la locale � %s � : le codeset vaut � %s �"
+msgstr "n'a pas pu déterminer l'encodage pour la locale « %s » : le codeset vaut « %s »"
#: ../port/dirmod.c:218
#, c-format
msgid "could not set junction for \"%s\": %s"
-msgstr "n'a pas pu configurer la jonction pour � %s � : %s"
+msgstr "n'a pas pu configurer la jonction pour « %s » : %s"
#: ../port/dirmod.c:221
#, c-format
msgid "could not set junction for \"%s\": %s\n"
-msgstr "n'a pas pu configurer la jonction pour � %s � : %s\n"
+msgstr "n'a pas pu configurer la jonction pour « %s » : %s\n"
#: ../port/dirmod.c:295
#, c-format
msgid "could not get junction for \"%s\": %s"
-msgstr "n'a pas pu obtenir la jonction pour � %s � : %s"
+msgstr "n'a pas pu obtenir la jonction pour « %s » : %s"
#: ../port/dirmod.c:298
#, c-format
msgid "could not get junction for \"%s\": %s\n"
-msgstr "n'a pas pu obtenir la jonction pour � %s � : %s\n"
+msgstr "n'a pas pu obtenir la jonction pour « %s » : %s\n"
#: ../port/open.c:112
#, c-format
msgid "could not open file \"%s\": %s"
-msgstr "n'a pas pu ouvrir le fichier � %s � : %s"
+msgstr "n'a pas pu ouvrir le fichier « %s » : %s"
#: ../port/open.c:113
msgid "lock violation"
@@ -306,31 +306,48 @@ msgstr "violation du partage"
#: ../port/open.c:114
#, c-format
msgid "Continuing to retry for 30 seconds."
-msgstr "Continue � tenter pendant 30 secondes."
+msgstr "Continue à tenter pendant 30 secondes."
#: ../port/open.c:115
#, c-format
msgid "You might have antivirus, backup, or similar software interfering with the database system."
msgstr ""
"Vous pouvez avoir un antivirus, un outil de sauvegarde ou un logiciel\n"
-"similaire interf�rant avec le syst�me de bases de donn�es."
+"similaire interférant avec le système de bases de données."
#: ../port/path.c:654
#, c-format
msgid "could not get current working directory: %s\n"
-msgstr "n'a pas pu obtenir le r�pertoire de travail : %s\n"
+msgstr "n'a pas pu obtenir le répertoire de travail : %s\n"
#: ../port/strerror.c:25
#, c-format
msgid "unrecognized error %d"
msgstr "erreur %d non reconnue"
-#: access/brin/brin.c:813
+#: ../port/win32security.c:68
+#, c-format
+msgid "could not open process token: error code %lu\n"
+msgstr "n'a pas pu ouvrir le jeton du processus : code d'erreur %lu\n"
+
+#: ../port/win32security.c:89
+#, c-format
+msgid "could not get SID for Administrators group: error code %lu\n"
+msgstr "n'a pas pu obtenir le SID du groupe d'administrateurs : code d'erreur %lu\n"
+
+#: ../port/win32security.c:99
+#, c-format
+msgid "could not get SID for PowerUsers group: error code %lu\n"
+msgstr ""
+"n'a pas pu obtenir le SID du groupe des utilisateurs avec pouvoir :\n"
+"code d'erreur %lu\n"
+
+#: access/brin/brin.c:810
#, c-format
msgid "\"%s\" is not a BRIN index"
-msgstr "� %s � n'est pas un index BRIN"
+msgstr "« %s » n'est pas un index BRIN"
-#: access/brin/brin.c:829
+#: access/brin/brin.c:826
#, c-format
msgid "could not open parent table of index %s"
msgstr "n'a pas pu ouvrir la table parent de l'index %s"
@@ -338,714 +355,774 @@ msgstr "n'a pas pu ouvrir la table parent de l'index %s"
#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362 access/brin/brin_pageops.c:828
#, c-format
msgid "index row size %lu exceeds maximum %lu for index \"%s\""
-msgstr "la taille de la ligne index, %lu, d�passe le maximum, %lu, pour l'index � %s �"
+msgstr "la taille de la ligne index, %lu, dépasse le maximum, %lu, pour l'index « %s »"
-#: access/brin/brin_revmap.c:455
+#: access/brin/brin_revmap.c:459
#, c-format
msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u"
-msgstr "type de page 0x%04X dans l'index BRIN � %s �, bloc %u"
+msgstr "type de page 0x%04X dans l'index BRIN « %s », bloc %u"
#: access/brin/brin_validate.c:115
#, c-format
-msgid "brin opfamily %s contains function %s with invalid support number %d"
+msgid "brin operator family \"%s\" contains function %s with invalid support number %d"
msgstr ""
+"la famille d'opérateur brin « %s » contient la fonction %s\n"
+"avec le numéro de support %d invalide"
#: access/brin/brin_validate.c:131
#, c-format
-msgid "brin opfamily %s contains function %s with wrong signature for support number %d"
+msgid "brin operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr ""
+"la famille d'opérateur brin « %s » contient la fonction %s\n"
+"avec une mauvaise signature pour le numéro de support %d"
#: access/brin/brin_validate.c:153
#, c-format
-msgid "brin opfamily %s contains operator %s with invalid strategy number %d"
+msgid "brin operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr ""
+"la famille d'opérateur brin « %s » contient l'opérateur %s\n"
+"avec le numéro de stratégie %d invalide"
#: access/brin/brin_validate.c:182
#, c-format
-msgid "brin opfamily %s contains invalid ORDER BY specification for operator %s"
+msgid "brin operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr ""
+"la famille d'opérateur brin « %s » contient une spécification\n"
+"ORDER BY invalide pour l'opérateur %s"
#: access/brin/brin_validate.c:195
#, c-format
-msgid "brin opfamily %s contains operator %s with wrong signature"
-msgstr ""
+msgid "brin operator family \"%s\" contains operator %s with wrong signature"
+msgstr "la famille d'opérateur brin « %s » contient l'opérateur %s avec une mauvaise signature"
#: access/brin/brin_validate.c:233
#, c-format
-msgid "brin opfamily %s is missing operator(s) for types %s and %s"
+msgid "brin operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr ""
+"famille d'opérateur brin « %s » nécessite des opérateurs supplémentaires\n"
+"pour les types %s et %s"
#: access/brin/brin_validate.c:243
#, c-format
-msgid "brin opfamily %s is missing support function(s) for types %s and %s"
+msgid "brin operator family \"%s\" is missing support function(s) for types %s and %s"
msgstr ""
+"la famille d'opérateur brin « %s » nécessite des fonctions de support\n"
+"manquantes pour les types %s et %s"
#: access/brin/brin_validate.c:256
#, c-format
-msgid "brin opclass %s is missing operator(s)"
-msgstr ""
+msgid "brin operator class \"%s\" is missing operator(s)"
+msgstr "il manque des opérateurs à la classe d'opérateur brin « %s »"
#: access/brin/brin_validate.c:267
-#, fuzzy, c-format
-#| msgid "return type %s is not supported for SQL functions"
-msgid "brin opclass %s is missing support function %d"
-msgstr "le type de retour %s n'est pas support� pour les fonctions SQL"
+#, c-format
+msgid "brin operator class \"%s\" is missing support function %d"
+msgstr "la classe d'opérateur brin « %s » nécessite la fonction de support %d"
#: access/common/heaptuple.c:708 access/common/heaptuple.c:1339
#, c-format
msgid "number of columns (%d) exceeds limit (%d)"
-msgstr "le nombre de colonnes (%d) d�passe la limite (%d)"
+msgstr "le nombre de colonnes (%d) dépasse la limite (%d)"
#: access/common/indextuple.c:60
#, c-format
msgid "number of index columns (%d) exceeds limit (%d)"
-msgstr "le nombre de colonnes index�es (%d) d�passe la limite (%d)"
+msgstr "le nombre de colonnes indexées (%d) dépasse la limite (%d)"
-#: access/common/indextuple.c:176 access/spgist/spgutils.c:641
+#: access/common/indextuple.c:176 access/spgist/spgutils.c:642
#, c-format
msgid "index row requires %zu bytes, maximum size is %zu"
msgstr "la ligne index requiert %zu octets, la taille maximum est %zu"
-#: access/common/printtup.c:294 tcop/fastpath.c:182 tcop/fastpath.c:544 tcop/postgres.c:1721
+#: access/common/printtup.c:292 tcop/fastpath.c:182 tcop/fastpath.c:544 tcop/postgres.c:1719
#, c-format
msgid "unsupported format code: %d"
-msgstr "code de format non support� : %d"
+msgstr "code de format non supporté : %d"
-#: access/common/reloptions.c:488
+#: access/common/reloptions.c:493
#, c-format
msgid "user-defined relation parameter types limit exceeded"
-msgstr "limite d�pass�e des types de param�tres de la relation d�finie par l'utilisateur"
+msgstr "limite dépassée des types de paramètres de la relation définie par l'utilisateur"
-#: access/common/reloptions.c:770
+#: access/common/reloptions.c:775
#, c-format
msgid "RESET must not include values for parameters"
-msgstr "RESET ne doit pas inclure de valeurs pour les param�tres"
+msgstr "RESET ne doit pas inclure de valeurs pour les paramètres"
-#: access/common/reloptions.c:803
+#: access/common/reloptions.c:808
#, c-format
msgid "unrecognized parameter namespace \"%s\""
-msgstr "espace de nom du param�tre � %s � non reconnu"
+msgstr "espace de nom du paramètre « %s » non reconnu"
-#: access/common/reloptions.c:1045 parser/parse_clause.c:281
+#: access/common/reloptions.c:1050 parser/parse_clause.c:281
#, c-format
msgid "unrecognized parameter \"%s\""
-msgstr "param�tre � %s � non reconnu"
+msgstr "paramètre « %s » non reconnu"
-#: access/common/reloptions.c:1075
+#: access/common/reloptions.c:1080
#, c-format
msgid "parameter \"%s\" specified more than once"
-msgstr "le param�tre � %s � est sp�cifi� plus d'une fois"
+msgstr "le paramètre « %s » est spécifié plus d'une fois"
-#: access/common/reloptions.c:1091
+#: access/common/reloptions.c:1096
#, c-format
msgid "invalid value for boolean option \"%s\": %s"
-msgstr "valeur invalide pour l'option bool�enne � %s � : %s"
+msgstr "valeur invalide pour l'option booléenne « %s » : %s"
-#: access/common/reloptions.c:1103
+#: access/common/reloptions.c:1108
#, c-format
msgid "invalid value for integer option \"%s\": %s"
-msgstr "valeur invalide pour l'option de type integer � %s � : %s"
+msgstr "valeur invalide pour l'option de type integer « %s » : %s"
-#: access/common/reloptions.c:1109 access/common/reloptions.c:1129
+#: access/common/reloptions.c:1114 access/common/reloptions.c:1134
#, c-format
msgid "value %s out of bounds for option \"%s\""
-msgstr "valeur %s en dehors des limites pour l'option � %s �"
+msgstr "valeur %s en dehors des limites pour l'option « %s »"
-#: access/common/reloptions.c:1111
+#: access/common/reloptions.c:1116
#, c-format
msgid "Valid values are between \"%d\" and \"%d\"."
-msgstr "Les valeurs valides sont entre � %d � et � %d �."
+msgstr "Les valeurs valides sont entre « %d » et « %d »."
-#: access/common/reloptions.c:1123
+#: access/common/reloptions.c:1128
#, c-format
msgid "invalid value for floating point option \"%s\": %s"
-msgstr "valeur invalide pour l'option de type float � %s � : %s"
+msgstr "valeur invalide pour l'option de type float « %s » : %s"
-#: access/common/reloptions.c:1131
+#: access/common/reloptions.c:1136
#, c-format
msgid "Valid values are between \"%f\" and \"%f\"."
-msgstr "Les valeurs valides sont entre � %f � et � %f �."
+msgstr "Les valeurs valides sont entre « %f » et « %f »."
#: access/common/tupconvert.c:108
#, c-format
msgid "Returned type %s does not match expected type %s in column %d."
-msgstr "Le type %s renvoy� ne correspond pas au type %s attendu dans la colonne %d."
+msgstr "Le type %s renvoyé ne correspond pas au type %s attendu dans la colonne %d."
#: access/common/tupconvert.c:136
#, c-format
msgid "Number of returned columns (%d) does not match expected column count (%d)."
msgstr ""
-"Le nombre de colonnes renvoy�es (%d) ne correspond pas au nombre de colonnes\n"
+"Le nombre de colonnes renvoyées (%d) ne correspond pas au nombre de colonnes\n"
"attendues (%d)."
-#: access/common/tupconvert.c:241
+#: access/common/tupconvert.c:314
#, c-format
msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s."
-msgstr "L'attribut � %s � du type %s ne correspond pas � l'attribut correspondant de type %s."
+msgstr "L'attribut « %s » du type %s ne correspond pas à l'attribut correspondant de type %s."
-#: access/common/tupconvert.c:253
+#: access/common/tupconvert.c:326
#, c-format
msgid "Attribute \"%s\" of type %s does not exist in type %s."
-msgstr "L'attribut � %s � du type %s n'existe pas dans le type %s."
+msgstr "L'attribut « %s » du type %s n'existe pas dans le type %s."
-#: access/common/tupdesc.c:635 parser/parse_relation.c:1517
+#: access/common/tupdesc.c:635 parser/parse_relation.c:1518
#, c-format
msgid "column \"%s\" cannot be declared SETOF"
-msgstr "la colonne � %s � ne peut pas �tre d�clar�e SETOF"
+msgstr "la colonne « %s » ne peut pas être déclarée SETOF"
#: access/gin/ginbulk.c:44
-#, fuzzy, c-format
-#| msgid "payload string too long"
+#, c-format
msgid "posting list is too long"
-msgstr "cha�ne de charge trop longue"
+msgstr "la posting list est trop longue"
#: access/gin/ginbulk.c:45
#, c-format
-msgid "Reduce maintenance_work_mem"
-msgstr "R�duire maintenance_work_mem"
+msgid "Reduce maintenance_work_mem."
+msgstr "Réduisez le maintenance_work_mem"
-#: access/gin/ginentrypage.c:109 access/gist/gist.c:1338 access/nbtree/nbtinsert.c:575 access/nbtree/nbtsort.c:488 access/spgist/spgdoinsert.c:1907
+#: access/gin/ginentrypage.c:109 access/gist/gist.c:1337 access/nbtree/nbtinsert.c:576 access/nbtree/nbtsort.c:488 access/spgist/spgdoinsert.c:1907
#, c-format
msgid "index row size %zu exceeds maximum %zu for index \"%s\""
-msgstr "la taille de la ligne index, %zu, d�passe le maximum, %zu, pour l'index � %s �"
+msgstr "la taille de la ligne index, %zu, dépasse le maximum, %zu, pour l'index « %s »"
-#: access/gin/ginfast.c:991 access/transam/xlog.c:9795 access/transam/xlog.c:10266 access/transam/xlogfuncs.c:294 access/transam/xlogfuncs.c:321 access/transam/xlogfuncs.c:360 access/transam/xlogfuncs.c:381 access/transam/xlogfuncs.c:402 access/transam/xlogfuncs.c:472 access/transam/xlogfuncs.c:528
+#: access/gin/ginfast.c:989 access/transam/xlog.c:9858 access/transam/xlog.c:10362 access/transam/xlogfuncs.c:293 access/transam/xlogfuncs.c:320 access/transam/xlogfuncs.c:359 access/transam/xlogfuncs.c:380 access/transam/xlogfuncs.c:401 access/transam/xlogfuncs.c:471 access/transam/xlogfuncs.c:527
#, c-format
msgid "recovery is in progress"
msgstr "restauration en cours"
-#: access/gin/ginfast.c:992
-#, fuzzy, c-format
-#| msgid "WAL control functions cannot be executed during recovery."
+#: access/gin/ginfast.c:990
+#, c-format
msgid "GIN pending list cannot be cleaned up during recovery."
-msgstr ""
-"les fonctions de contr�le des journaux de transactions ne peuvent pas\n"
-"�tre ex�cut�es lors de la restauration."
+msgstr "la pending list GIN ne peut pas être nettoyée lors de la restauration"
-#: access/gin/ginfast.c:999
-#, fuzzy, c-format
-#| msgid "\"%s\" is not a BRIN index"
+#: access/gin/ginfast.c:997
+#, c-format
msgid "\"%s\" is not a GIN index"
-msgstr "� %s � n'est pas un index BRIN"
+msgstr "« %s » n'est pas un index GIN"
-#: access/gin/ginfast.c:1010
-#, fuzzy, c-format
-#| msgid "cannot access temporary tables of other sessions"
+#: access/gin/ginfast.c:1008
+#, c-format
msgid "cannot access temporary indexes of other sessions"
-msgstr "ne peut pas acc�der aux tables temporaires d'autres sessions"
+msgstr "ne peut pas accéder aux index temporaires d'autres sessions"
-#: access/gin/ginscan.c:409
+#: access/gin/ginscan.c:405
#, c-format
msgid "old GIN indexes do not support whole-index scans nor searches for nulls"
msgstr ""
"les anciens index GIN ne supportent pas les parcours complets d'index et les\n"
"recherches de valeurs NULL"
-#: access/gin/ginscan.c:410
+#: access/gin/ginscan.c:406
#, c-format
msgid "To fix this, do REINDEX INDEX \"%s\"."
-msgstr "Pour corriger ceci, faites un REINDEX INDEX � %s �."
+msgstr "Pour corriger ceci, faites un REINDEX INDEX « %s »."
#: access/gin/ginvalidate.c:92
#, c-format
-msgid "gin opfamily %s contains support procedure %s with cross-type registration"
+msgid "gin operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr ""
+"la famille d'opérateur gin « %s » contient la procédure de support\n"
+"%s avec un enregistrement inter-type"
#: access/gin/ginvalidate.c:148
#, c-format
-msgid "gin opfamily %s contains function %s with invalid support number %d"
+msgid "gin operator family \"%s\" contains function %s with invalid support number %d"
msgstr ""
+"la famille d'opérateur gin « %s » contient la fonction %s avec\n"
+"le numéro de support invalide %d"
#: access/gin/ginvalidate.c:160
#, c-format
-msgid "gin opfamily %s contains function %s with wrong signature for support number %d"
+msgid "gin operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr ""
+"la famille d'opérateur gin « %s » contient la fonction %s avec une mauvaise\n"
+"signature pour le numéro de support %d"
#: access/gin/ginvalidate.c:179
#, c-format
-msgid "gin opfamily %s contains operator %s with invalid strategy number %d"
+msgid "gin operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr ""
+"la famille d'opérateur gin « %s » contient l'opérateur %s avec le numéro\n"
+"de stratégie invalide %d"
#: access/gin/ginvalidate.c:192
#, c-format
-msgid "gin opfamily %s contains invalid ORDER BY specification for operator %s"
+msgid "gin operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr ""
+"la famille d'opérateur gin « %s » contient la spécification ORDER BY\n"
+"invalide pour l'opérateur %s"
#: access/gin/ginvalidate.c:205
#, c-format
-msgid "gin opfamily %s contains operator %s with wrong signature"
-msgstr ""
+msgid "gin operator family \"%s\" contains operator %s with wrong signature"
+msgstr "la famille d'opérateur gin « %s » contient l'opérateur %s avec une mauvaise signature"
#: access/gin/ginvalidate.c:246
#, c-format
-msgid "gin opclass %s is missing support function %d"
-msgstr ""
+msgid "gin operator class \"%s\" is missing support function %d"
+msgstr "la famille d'opérateur gin « %s » nécessite la fonction de support %d"
#: access/gin/ginvalidate.c:256
#, c-format
-msgid "gin opclass %s is missing support function %d or %d"
-msgstr ""
+msgid "gin operator class \"%s\" is missing support function %d or %d"
+msgstr "la famille d'opérateur gin « %s » nécessite la fonction de support %d ou %d"
-#: access/gist/gist.c:681 access/gist/gistvacuum.c:258
+#: access/gist/gist.c:680 access/gist/gistvacuum.c:258
#, c-format
msgid "index \"%s\" contains an inner tuple marked as invalid"
-msgstr "l'index � %s � contient une ligne interne marqu�e comme invalide"
+msgstr "l'index « %s » contient une ligne interne marquée comme invalide"
-#: access/gist/gist.c:683 access/gist/gistvacuum.c:260
+#: access/gist/gist.c:682 access/gist/gistvacuum.c:260
#, c-format
msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1."
msgstr ""
-"Ceci est d� � la division d'une page incompl�te � la restauration suite � un\n"
-"crash avant la mise � jour en 9.1."
+"Ceci est dû à la division d'une page incomplète à la restauration suite à un\n"
+"crash avant la mise à jour en 9.1."
-#: access/gist/gist.c:684 access/gist/gistutil.c:735 access/gist/gistutil.c:746 access/gist/gistvacuum.c:261 access/hash/hashutil.c:172 access/hash/hashutil.c:183 access/hash/hashutil.c:195 access/hash/hashutil.c:216 access/nbtree/nbtpage.c:518 access/nbtree/nbtpage.c:529
+#: access/gist/gist.c:683 access/gist/gistutil.c:738 access/gist/gistutil.c:749 access/gist/gistvacuum.c:261 access/hash/hashutil.c:172 access/hash/hashutil.c:183 access/hash/hashutil.c:195 access/hash/hashutil.c:216 access/nbtree/nbtpage.c:518 access/nbtree/nbtpage.c:529
#, c-format
msgid "Please REINDEX it."
-msgstr "Merci d'ex�cuter REINDEX sur cet objet."
+msgstr "Merci d'exécuter REINDEX sur cet objet."
#: access/gist/gistbuild.c:249
#, c-format
msgid "invalid value for \"buffering\" option"
-msgstr "valeur invalide pour l'option � buffering �"
+msgstr "valeur invalide pour l'option « buffering »"
#: access/gist/gistbuild.c:250
#, c-format
msgid "Valid values are \"on\", \"off\", and \"auto\"."
-msgstr "Les valeurs valides sont entre � on �, � off � et � auto �."
+msgstr "Les valeurs valides sont entre « on », « off » et « auto »."
#: access/gist/gistbuildbuffers.c:778 utils/sort/logtape.c:209
#, c-format
msgid "could not write block %ld of temporary file: %m"
-msgstr "n'a pas pu �crire le bloc %ld du fichier temporaire : %m"
+msgstr "n'a pas pu écrire le bloc %ld du fichier temporaire : %m"
#: access/gist/gistsplit.c:446
#, c-format
msgid "picksplit method for column %d of index \"%s\" failed"
-msgstr "�chec de la m�thode picksplit pour la colonne %d de l'index � %s �"
+msgstr "échec de la méthode picksplit pour la colonne %d de l'index « %s »"
#: access/gist/gistsplit.c:448
#, c-format
msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command."
msgstr ""
-"L'index n'est pas optimal. Pour l'optimiser, contactez un d�veloppeur\n"
+"L'index n'est pas optimal. Pour l'optimiser, contactez un développeur\n"
"ou essayez d'utiliser la colonne comme second dans la commande\n"
"CREATE INDEX."
-#: access/gist/gistutil.c:732 access/hash/hashutil.c:169 access/nbtree/nbtpage.c:515
+#: access/gist/gistutil.c:735 access/hash/hashutil.c:169 access/nbtree/nbtpage.c:515
#, c-format
msgid "index \"%s\" contains unexpected zero page at block %u"
-msgstr "l'index � %s � contient une page z�ro inattendue au bloc %u"
+msgstr "l'index « %s » contient une page zéro inattendue au bloc %u"
-#: access/gist/gistutil.c:743 access/hash/hashutil.c:180 access/hash/hashutil.c:192 access/nbtree/nbtpage.c:526
+#: access/gist/gistutil.c:746 access/hash/hashutil.c:180 access/hash/hashutil.c:192 access/nbtree/nbtpage.c:526
#, c-format
msgid "index \"%s\" contains corrupted page at block %u"
-msgstr "l'index � %s � contient une page corrompue au bloc %u"
+msgstr "l'index « %s » contient une page corrompue au bloc %u"
#: access/gist/gistvalidate.c:92
#, c-format
-msgid "gist opfamily %s contains support procedure %s with cross-type registration"
+msgid "gist operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr ""
+"la famille d'opérateur gist « %s » contient la procédure de support\n"
+"%s avec un enregistrement inter-type"
#: access/gist/gistvalidate.c:145
#, c-format
-msgid "gist opfamily %s contains function %s with invalid support number %d"
+msgid "gist operator family \"%s\" contains function %s with invalid support number %d"
msgstr ""
+"la famille d'opérateur gist « %s » contient la fonction %s avec\n"
+"le numéro de support invalide %d"
#: access/gist/gistvalidate.c:157
#, c-format
-msgid "gist opfamily %s contains function %s with wrong signature for support number %d"
+msgid "gist operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr ""
+"la famille d'opérateur gist « %s » contient la fonction %s avec une mauvaise\n"
+"signature pour le numéro de support %d"
#: access/gist/gistvalidate.c:177
#, c-format
-msgid "gist opfamily %s contains operator %s with invalid strategy number %d"
+msgid "gist operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr ""
+"la famille d'opérateur gist « %s » contient l'opérateur %s avec le numéro\n"
+"de stratégie invalide %d"
#: access/gist/gistvalidate.c:195
#, c-format
-msgid "gist opfamily %s contains unsupported ORDER BY specification for operator %s"
+msgid "gist operator family \"%s\" contains unsupported ORDER BY specification for operator %s"
msgstr ""
+"la famille d'opérateur gist « %s » contient la spécification ORDER BY\n"
+"non supportée pour l'opérateur %s"
#: access/gist/gistvalidate.c:206
#, c-format
-msgid "gist opfamily %s contains incorrect ORDER BY opfamily specification for operator %s"
+msgid "gist operator family \"%s\" contains incorrect ORDER BY opfamily specification for operator %s"
msgstr ""
+"la famille d'opérateur gist « %s » contient la spécification opfamily ORDER BY\n"
+"incorrecte pour l'opérateur %s"
#: access/gist/gistvalidate.c:225
#, c-format
-msgid "gist opfamily %s contains operator %s with wrong signature"
-msgstr ""
+msgid "gist operator family \"%s\" contains operator %s with wrong signature"
+msgstr "la famille d'opérateur gist « %s » contient l'opérateur %s avec une mauvaise signature"
#: access/gist/gistvalidate.c:264
#, c-format
-msgid "gist opclass %s is missing support function %d"
-msgstr ""
+msgid "gist operator class \"%s\" is missing support function %d"
+msgstr "la famille d'opérateur gist « %s » nécessite la fonction de support %d"
-#: access/hash/hashinsert.c:68
+#: access/hash/hashinsert.c:70
#, c-format
msgid "index row size %zu exceeds hash maximum %zu"
-msgstr "la taille de la ligne index, %zu, d�passe le hachage maximum, %zu"
+msgstr "la taille de la ligne index, %zu, dépasse le hachage maximum, %zu"
-#: access/hash/hashinsert.c:70 access/spgist/spgdoinsert.c:1911 access/spgist/spgutils.c:702
+#: access/hash/hashinsert.c:72 access/spgist/spgdoinsert.c:1911 access/spgist/spgutils.c:703
#, c-format
msgid "Values larger than a buffer page cannot be indexed."
-msgstr "Les valeurs plus larges qu'une page de tampon ne peuvent pas �tre index�es."
+msgstr "Les valeurs plus larges qu'une page de tampon ne peuvent pas être indexées."
#: access/hash/hashovfl.c:546
#, c-format
msgid "out of overflow pages in hash index \"%s\""
-msgstr "en dehors des pages surcharg�es dans l'index hach� � %s �"
+msgstr "en dehors des pages surchargées dans l'index haché « %s »"
#: access/hash/hashsearch.c:153
#, c-format
msgid "hash indexes do not support whole-index scans"
-msgstr "les index h�ch�s ne supportent pas les parcours complets d'index"
+msgstr "les index hâchés ne supportent pas les parcours complets d'index"
#: access/hash/hashutil.c:208
#, c-format
msgid "index \"%s\" is not a hash index"
-msgstr "l'index � %s � n'est pas un index hach�"
+msgstr "l'index « %s » n'est pas un index haché"
#: access/hash/hashutil.c:214
#, c-format
msgid "index \"%s\" has wrong hash version"
-msgstr "l'index � %s � a la mauvaise version de hachage"
+msgstr "l'index « %s » a la mauvaise version de hachage"
#: access/hash/hashvalidate.c:98
#, c-format
-msgid "hash opfamily %s contains support procedure %s with cross-type registration"
+msgid "hash operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr ""
+"la famille d'opérateur hash « %s » contient la procédure de support\n"
+"%s avec un enregistrement inter-type"
#: access/hash/hashvalidate.c:113
#, c-format
-msgid "hash opfamily %s contains function %s with wrong signature for support number %d"
+msgid "hash operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr ""
+"la famille d'opérateur hash « %s » contient la fonction %s avec une mauvaise\n"
+"signature pour le numéro de support %d"
#: access/hash/hashvalidate.c:130
#, c-format
-msgid "hash opfamily %s contains function %s with invalid support number %d"
+msgid "hash operator family \"%s\" contains function %s with invalid support number %d"
msgstr ""
+"la famille d'opérateur hash « %s » contient la fonction %s avec\n"
+"le numéro de support invalide %d"
#: access/hash/hashvalidate.c:151
#, c-format
-msgid "hash opfamily %s contains operator %s with invalid strategy number %d"
+msgid "hash operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr ""
+"la famille d'opérateur hash « %s » contient l'opérateur %s avec le numéro\n"
+"de stratégie invalide %d"
#: access/hash/hashvalidate.c:164
#, c-format
-msgid "hash opfamily %s contains invalid ORDER BY specification for operator %s"
+msgid "hash operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr ""
+"la famille d'opérateur hash « %s » contient la spécification ORDER BY\n"
+"non supportée pour l'opérateur %s"
#: access/hash/hashvalidate.c:177
#, c-format
-msgid "hash opfamily %s contains operator %s with wrong signature"
-msgstr ""
+msgid "hash operator family \"%s\" contains operator %s with wrong signature"
+msgstr "la famille d'opérateur hash « %s » contient l'opérateur %s avec une mauvaise signature"
#: access/hash/hashvalidate.c:189
#, c-format
-msgid "hash opfamily %s lacks support function for operator %s"
+msgid "hash operator family \"%s\" lacks support function for operator %s"
msgstr ""
+"la famille d'opérateur hash « %s » requiert la fonction de support\n"
+"pour l'opérateur %s"
#: access/hash/hashvalidate.c:217
#, c-format
-msgid "hash opfamily %s is missing operator(s) for types %s and %s"
+msgid "hash operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr ""
+"la famille d'opérateur hash « %s » nécessite des opérateurs supplémentaires\n"
+"pour les types %s et %s"
#: access/hash/hashvalidate.c:231
#, c-format
-msgid "hash opclass %s is missing operator(s)"
-msgstr ""
+msgid "hash operator class \"%s\" is missing operator(s)"
+msgstr "il manque des opérateurs pour la classe d'opérateur hash « %s »"
#: access/hash/hashvalidate.c:247
#, c-format
-msgid "hash opfamily %s is missing cross-type operator(s)"
-msgstr ""
-
-#: access/heap/heapam.c:1138 access/heap/heapam.c:1190
-#, c-format
-msgid "cannot access temporary tables during a parallel operation"
-msgstr "ne peut pas acc�der � des tables temporaires pendant une op�ration parall�le"
+msgid "hash operator family \"%s\" is missing cross-type operator(s)"
+msgstr "il manque des opérateurs inter-type pour la famille d'opérateur hash « %s »"
-#: access/heap/heapam.c:1307 access/heap/heapam.c:1335 access/heap/heapam.c:1367 catalog/aclchk.c:1748
+#: access/heap/heapam.c:1295 access/heap/heapam.c:1323 access/heap/heapam.c:1355 catalog/aclchk.c:1756
#, c-format
msgid "\"%s\" is an index"
-msgstr "� %s � est un index"
+msgstr "« %s » est un index"
-#: access/heap/heapam.c:1312 access/heap/heapam.c:1340 access/heap/heapam.c:1372 catalog/aclchk.c:1755 commands/tablecmds.c:8984 commands/tablecmds.c:12042
+#: access/heap/heapam.c:1300 access/heap/heapam.c:1328 access/heap/heapam.c:1360 catalog/aclchk.c:1763 commands/tablecmds.c:9081 commands/tablecmds.c:12189
#, c-format
msgid "\"%s\" is a composite type"
-msgstr "� %s � est un type composite"
+msgstr "« %s » est un type composite"
-#: access/heap/heapam.c:2579
+#: access/heap/heapam.c:2567
#, c-format
msgid "cannot insert tuples during a parallel operation"
-msgstr "ne peut pas ins�rer les lignes lors d'une op�ration parall�le"
+msgstr "ne peut pas insérer les lignes lors d'une opération parallèle"
-#: access/heap/heapam.c:3029
+#: access/heap/heapam.c:3017
#, c-format
msgid "cannot delete tuples during a parallel operation"
-msgstr "ne peut pas supprimer les lignes lors d'une op�ration parall�le"
+msgstr "ne peut pas supprimer les lignes lors d'une opération parallèle"
-#: access/heap/heapam.c:3075
+#: access/heap/heapam.c:3063
#, c-format
msgid "attempted to delete invisible tuple"
-msgstr "a tent� de supprimer la ligne invisible"
+msgstr "a tenté de supprimer la ligne invisible"
-#: access/heap/heapam.c:3502 access/heap/heapam.c:6053
+#: access/heap/heapam.c:3489 access/heap/heapam.c:6240
#, c-format
msgid "cannot update tuples during a parallel operation"
-msgstr "ne peut pas mettre � jour les lignes lors d'une op�ration parall�le"
+msgstr "ne peut pas mettre à jour les lignes lors d'une opération parallèle"
-#: access/heap/heapam.c:3624
+#: access/heap/heapam.c:3611
#, c-format
msgid "attempted to update invisible tuple"
-msgstr "a tent� de mettre � jour la ligne invisible"
+msgstr "a tenté de mettre à jour la ligne invisible"
-#: access/heap/heapam.c:4875 access/heap/heapam.c:4913 access/heap/heapam.c:5136 executor/execMain.c:2304
+#: access/heap/heapam.c:4963 access/heap/heapam.c:5001 access/heap/heapam.c:5253 executor/execMain.c:2314
#, c-format
msgid "could not obtain lock on row in relation \"%s\""
-msgstr "n'a pas pu obtenir un verrou sur la relation � %s �"
+msgstr "n'a pas pu obtenir un verrou sur la relation « %s »"
-#: access/heap/hio.c:322 access/heap/rewriteheap.c:666
+#: access/heap/hio.c:322 access/heap/rewriteheap.c:664
#, c-format
msgid "row is too big: size %zu, maximum size %zu"
msgstr "la ligne est trop grande : taille %zu, taille maximale %zu"
-#: access/heap/rewriteheap.c:925
+#: access/heap/rewriteheap.c:923
#, c-format
msgid "could not write to file \"%s\", wrote %d of %d: %m"
-msgstr "n'a pas pu �crire le fichier � %s �, a �crit %d de %d : %m"
+msgstr "n'a pas pu écrire le fichier « %s », a écrit %d de %d : %m"
-#: access/heap/rewriteheap.c:965 access/heap/rewriteheap.c:1177 access/heap/rewriteheap.c:1274 access/transam/timeline.c:407 access/transam/timeline.c:483 access/transam/xlog.c:3060 access/transam/xlog.c:3222 replication/logical/snapbuild.c:1607 replication/slot.c:1077 replication/slot.c:1162 storage/file/fd.c:624 storage/file/fd.c:3052 storage/smgr/md.c:1044 storage/smgr/md.c:1277 storage/smgr/md.c:1450 utils/misc/guc.c:6881
+#: access/heap/rewriteheap.c:963 access/heap/rewriteheap.c:1175 access/heap/rewriteheap.c:1272 access/transam/timeline.c:407 access/transam/timeline.c:483 access/transam/xlog.c:3087 access/transam/xlog.c:3249 replication/logical/snapbuild.c:1605 replication/slot.c:1088 replication/slot.c:1173 storage/file/fd.c:624 storage/file/fd.c:3052 storage/smgr/md.c:1041 storage/smgr/md.c:1274 storage/smgr/md.c:1447 utils/misc/guc.c:6885
#, c-format
msgid "could not fsync file \"%s\": %m"
-msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier � %s � : %m"
+msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m"
-#: access/heap/rewriteheap.c:1020 access/heap/rewriteheap.c:1140 access/transam/timeline.c:315 access/transam/timeline.c:461 access/transam/xlog.c:3016 access/transam/xlog.c:3165 access/transam/xlog.c:10124 access/transam/xlog.c:10162 access/transam/xlog.c:10489 postmaster/postmaster.c:4351 replication/logical/origin.c:542 replication/slot.c:1034 storage/file/copydir.c:162 storage/smgr/md.c:331 utils/time/snapmgr.c:1182
+#: access/heap/rewriteheap.c:1018 access/heap/rewriteheap.c:1138 access/transam/timeline.c:315 access/transam/timeline.c:461 access/transam/xlog.c:3043 access/transam/xlog.c:3192 access/transam/xlog.c:10192 access/transam/xlog.c:10230 access/transam/xlog.c:10603 postmaster/postmaster.c:4364 replication/logical/origin.c:542 replication/slot.c:1045 storage/file/copydir.c:162 storage/smgr/md.c:327 utils/time/snapmgr.c:1275
#, c-format
msgid "could not create file \"%s\": %m"
-msgstr "n'a pas pu cr�er le fichier � %s � : %m"
+msgstr "n'a pas pu créer le fichier « %s » : %m"
-#: access/heap/rewriteheap.c:1149
+#: access/heap/rewriteheap.c:1147
#, c-format
msgid "could not truncate file \"%s\" to %u: %m"
-msgstr "n'a pas pu tronquer le fichier � %s � en %u : %m"
+msgstr "n'a pas pu tronquer le fichier « %s » en %u : %m"
-#: access/heap/rewriteheap.c:1156 replication/walsender.c:481 storage/smgr/md.c:1902
+#: access/heap/rewriteheap.c:1154 replication/walsender.c:481 storage/smgr/md.c:1899
#, c-format
msgid "could not seek to end of file \"%s\": %m"
-msgstr "n'a pas pu trouver la fin du fichier � %s � : %m"
+msgstr "n'a pas pu trouver la fin du fichier « %s » : %m"
-#: access/heap/rewriteheap.c:1167 access/transam/timeline.c:367 access/transam/timeline.c:401 access/transam/timeline.c:477 access/transam/xlog.c:3051 access/transam/xlog.c:3215 postmaster/postmaster.c:4361 postmaster/postmaster.c:4371 replication/logical/origin.c:551 replication/logical/origin.c:587 replication/logical/origin.c:603 replication/logical/snapbuild.c:1591 replication/slot.c:1063 storage/file/copydir.c:187
-#: utils/init/miscinit.c:1228 utils/init/miscinit.c:1237 utils/init/miscinit.c:1244 utils/misc/guc.c:6842 utils/misc/guc.c:6873 utils/misc/guc.c:8715 utils/misc/guc.c:8729 utils/time/snapmgr.c:1187 utils/time/snapmgr.c:1194
+#: access/heap/rewriteheap.c:1165 access/transam/timeline.c:367 access/transam/timeline.c:401 access/transam/timeline.c:477 access/transam/xlog.c:3078 access/transam/xlog.c:3242 postmaster/postmaster.c:4374 postmaster/postmaster.c:4384 replication/logical/origin.c:551 replication/logical/origin.c:587 replication/logical/origin.c:603 replication/logical/snapbuild.c:1589 replication/slot.c:1074 storage/file/copydir.c:187
+#: utils/init/miscinit.c:1228 utils/init/miscinit.c:1237 utils/init/miscinit.c:1244 utils/misc/guc.c:6846 utils/misc/guc.c:6877 utils/misc/guc.c:8727 utils/misc/guc.c:8741 utils/time/snapmgr.c:1280 utils/time/snapmgr.c:1287
#, c-format
msgid "could not write to file \"%s\": %m"
-msgstr "n'a pas pu �crire dans le fichier � %s � : %m"
+msgstr "n'a pas pu écrire dans le fichier « %s » : %m"
-#: access/heap/rewriteheap.c:1250 access/transam/xlog.c:10356 access/transam/xlogarchive.c:114 access/transam/xlogarchive.c:468 replication/logical/origin.c:529 replication/logical/reorderbuffer.c:2624 replication/logical/reorderbuffer.c:2681 replication/logical/snapbuild.c:1535 replication/logical/snapbuild.c:1910 replication/slot.c:1136 storage/ipc/dsm.c:326 storage/smgr/md.c:431 storage/smgr/md.c:480 storage/smgr/md.c:1397
+#: access/heap/rewriteheap.c:1248 access/transam/xlog.c:10441 access/transam/xlogarchive.c:114 access/transam/xlogarchive.c:468 replication/logical/origin.c:529 replication/logical/reorderbuffer.c:2632 replication/logical/reorderbuffer.c:2689 replication/logical/snapbuild.c:1533 replication/logical/snapbuild.c:1908 replication/slot.c:1147 storage/ipc/dsm.c:326 storage/smgr/md.c:427 storage/smgr/md.c:476 storage/smgr/md.c:1394
#, c-format
msgid "could not remove file \"%s\": %m"
-msgstr "n'a pas pu supprimer le fichier � %s � : %m"
+msgstr "n'a pas pu supprimer le fichier « %s » : %m"
-#: access/heap/rewriteheap.c:1264 access/transam/timeline.c:111 access/transam/timeline.c:236 access/transam/timeline.c:334 access/transam/xlog.c:2992 access/transam/xlog.c:3109 access/transam/xlog.c:3150 access/transam/xlog.c:3423 access/transam/xlog.c:3501 access/transam/xlogutils.c:700 replication/basebackup.c:401 replication/basebackup.c:1162 replication/logical/origin.c:658 replication/logical/reorderbuffer.c:2154
-#: replication/logical/reorderbuffer.c:2394 replication/logical/reorderbuffer.c:3072 replication/logical/snapbuild.c:1584 replication/logical/snapbuild.c:1668 replication/slot.c:1151 replication/walsender.c:474 replication/walsender.c:2104 storage/file/copydir.c:155 storage/file/fd.c:607 storage/file/fd.c:2964 storage/file/fd.c:3031 storage/smgr/md.c:613 utils/error/elog.c:1870 utils/init/miscinit.c:1163 utils/init/miscinit.c:1284
-#: utils/init/miscinit.c:1362 utils/misc/guc.c:7101 utils/misc/guc.c:7134
+#: access/heap/rewriteheap.c:1262 access/transam/timeline.c:111 access/transam/timeline.c:236 access/transam/timeline.c:334 access/transam/xlog.c:3019 access/transam/xlog.c:3136 access/transam/xlog.c:3177 access/transam/xlog.c:3450 access/transam/xlog.c:3528 access/transam/xlogutils.c:701 replication/basebackup.c:403 replication/basebackup.c:1150 replication/logical/origin.c:658 replication/logical/reorderbuffer.c:2156
+#: replication/logical/reorderbuffer.c:2402 replication/logical/reorderbuffer.c:3081 replication/logical/snapbuild.c:1582 replication/logical/snapbuild.c:1666 replication/slot.c:1162 replication/walsender.c:474 replication/walsender.c:2102 storage/file/copydir.c:155 storage/file/fd.c:607 storage/file/fd.c:2964 storage/file/fd.c:3031 storage/smgr/md.c:609 utils/error/elog.c:1879 utils/init/miscinit.c:1163 utils/init/miscinit.c:1284
+#: utils/init/miscinit.c:1362 utils/misc/guc.c:7105 utils/misc/guc.c:7138
#, c-format
msgid "could not open file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » : %m"
-#: access/index/amapi.c:69 commands/amcmds.c:164
-#, fuzzy, c-format
-#| msgid "access method \"%s\" does not exist"
+#: access/index/amapi.c:82 commands/amcmds.c:164
+#, c-format
msgid "access method \"%s\" is not of type %s"
-msgstr "la m�thode d'acc�s � %s � n'existe pas"
+msgstr "la méthode d'accès « %s » n'est pas de type %s"
-#: access/index/amapi.c:78
-#, fuzzy, c-format
-#| msgid "access method \"%s\" does not exist"
+#: access/index/amapi.c:98
+#, c-format
msgid "index access method \"%s\" does not have a handler"
-msgstr "la m�thode d'acc�s � %s � n'existe pas"
+msgstr "la méthode d'accès « %s » n'a pas de handler"
-#: access/index/indexam.c:155 catalog/objectaddress.c:1196 commands/indexcmds.c:1799 commands/tablecmds.c:241 commands/tablecmds.c:12033
+#: access/index/indexam.c:155 catalog/objectaddress.c:1196 commands/indexcmds.c:1799 commands/tablecmds.c:242 commands/tablecmds.c:12180
#, c-format
msgid "\"%s\" is not an index"
-msgstr "� %s � n'est pas un index"
+msgstr "« %s » n'est pas un index"
-#: access/nbtree/nbtinsert.c:427
+#: access/nbtree/nbtinsert.c:428
#, c-format
msgid "duplicate key value violates unique constraint \"%s\""
-msgstr "la valeur d'une cl� dupliqu�e rompt la contrainte unique � %s �"
+msgstr "la valeur d'une clé dupliquée rompt la contrainte unique « %s »"
-#: access/nbtree/nbtinsert.c:429
+#: access/nbtree/nbtinsert.c:430
#, c-format
msgid "Key %s already exists."
-msgstr "La cl� � %s � existe d�j�."
+msgstr "La clé « %s » existe déjà."
-#: access/nbtree/nbtinsert.c:496
+#: access/nbtree/nbtinsert.c:497
#, c-format
msgid "failed to re-find tuple within index \"%s\""
-msgstr "�chec pour retrouver la ligne dans l'index � %s �"
+msgstr "échec pour retrouver la ligne dans l'index « %s »"
-#: access/nbtree/nbtinsert.c:498
+#: access/nbtree/nbtinsert.c:499
#, c-format
msgid "This may be because of a non-immutable index expression."
-msgstr "Ceci peut �tre d� � une expression d'index immutable."
+msgstr "Ceci peut être dû à une expression d'index immutable."
-#: access/nbtree/nbtinsert.c:578 access/nbtree/nbtsort.c:491
+#: access/nbtree/nbtinsert.c:579 access/nbtree/nbtsort.c:491
#, c-format
msgid ""
"Values larger than 1/3 of a buffer page cannot be indexed.\n"
"Consider a function index of an MD5 hash of the value, or use full text indexing."
msgstr ""
-"Les valeurs plus larges qu'un tiers d'une page de tampon ne peuvent pas �tre\n"
-"index�es.\n"
-"Utilisez un index sur le hachage MD5 de la valeur ou passez � l'indexation\n"
+"Les valeurs plus larges qu'un tiers d'une page de tampon ne peuvent pas être\n"
+"indexées.\n"
+"Utilisez un index sur le hachage MD5 de la valeur ou passez à l'indexation\n"
"de la recherche plein texte."
-#: access/nbtree/nbtpage.c:168 access/nbtree/nbtpage.c:371 access/nbtree/nbtpage.c:458 parser/parse_utilcmd.c:1715
+#: access/nbtree/nbtpage.c:168 access/nbtree/nbtpage.c:371 access/nbtree/nbtpage.c:458 parser/parse_utilcmd.c:1702
#, c-format
msgid "index \"%s\" is not a btree"
-msgstr "l'index � %s � n'est pas un btree"
+msgstr "l'index « %s » n'est pas un btree"
#: access/nbtree/nbtpage.c:174 access/nbtree/nbtpage.c:377 access/nbtree/nbtpage.c:464
#, c-format
msgid "version mismatch in index \"%s\": file version %d, code version %d"
-msgstr "la version ne correspond pas dans l'index � %s � : version du fichier %d, version du code %d"
+msgstr "la version ne correspond pas dans l'index « %s » : version du fichier %d, version du code %d"
#: access/nbtree/nbtpage.c:1152
#, c-format
msgid "index \"%s\" contains a half-dead internal page"
-msgstr "l'index � %s � contient une page interne � moiti� morte"
+msgstr "l'index « %s » contient une page interne à moitié morte"
#: access/nbtree/nbtpage.c:1154
#, c-format
msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it."
-msgstr "Ceci peut �tre d� � un VACUUM interrompu en version 9.3 ou ant�rieure, avant la mise � jour. Merci d'utiliser REINDEX."
+msgstr "Ceci peut être dû à un VACUUM interrompu en version 9.3 ou antérieure, avant la mise à jour. Merci d'utiliser REINDEX."
#: access/nbtree/nbtvalidate.c:100
#, c-format
-msgid "btree opfamily %s contains function %s with invalid support number %d"
+msgid "btree operator family \"%s\" contains function %s with invalid support number %d"
msgstr ""
+"la famille d'opérateur btree « %s » contient la fonction %s\n"
+"avec le numéro de support invalide %d"
#: access/nbtree/nbtvalidate.c:112
#, c-format
-msgid "btree opfamily %s contains function %s with wrong signature for support number %d"
+msgid "btree operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr ""
+"la famille d'opérateur btree « %s » contient la fonction %s\n"
+"avec une mauvaise signature pour le numéro de support %d"
#: access/nbtree/nbtvalidate.c:132
#, c-format
-msgid "btree opfamily %s contains operator %s with invalid strategy number %d"
+msgid "btree operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr ""
+"la famille d'opérateur btree « %s » contient l'opérateur %s\n"
+"avec le numéro de stratégie invalide %d"
#: access/nbtree/nbtvalidate.c:145
#, c-format
-msgid "btree opfamily %s contains invalid ORDER BY specification for operator %s"
+msgid "btree operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr ""
+"la famille d'opérateur btree « %s » contient une spécification\n"
+"ORDER BY invalide pour l'opérateur %s"
#: access/nbtree/nbtvalidate.c:158
#, c-format
-msgid "btree opfamily %s contains operator %s with wrong signature"
-msgstr ""
+msgid "btree operator family \"%s\" contains operator %s with wrong signature"
+msgstr "la famille d'opérateur btree « %s » contient l'opérateur %s avec une mauvaise signature"
#: access/nbtree/nbtvalidate.c:200
#, c-format
-msgid "btree opfamily %s is missing operator(s) for types %s and %s"
+msgid "btree operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr ""
+"la famille d'opérateur btree « %s » nécessite des opérateurs supplémentaires\n"
+"pour les types %s et %s"
#: access/nbtree/nbtvalidate.c:210
#, c-format
-msgid "btree opfamily %s is missing support function for types %s and %s"
+msgid "btree operator family \"%s\" is missing support function for types %s and %s"
msgstr ""
+"la famille d'opérateur btree « %s » nécessite une fonction de support\n"
+"pour les types %s et %s"
#: access/nbtree/nbtvalidate.c:224
#, c-format
-msgid "btree opclass %s is missing operator(s)"
-msgstr ""
+msgid "btree operator class \"%s\" is missing operator(s)"
+msgstr "il manque des opérateurs pour la classe d'opérateur btree « %s »"
#: access/nbtree/nbtvalidate.c:241
#, c-format
-msgid "btree opfamily %s is missing cross-type operator(s)"
-msgstr ""
+msgid "btree operator family \"%s\" is missing cross-type operator(s)"
+msgstr "il manque des opérateurs inter-type pour la famille d'opérateur btree « %s »"
-#: access/spgist/spgutils.c:699
+#: access/spgist/spgutils.c:700
#, c-format
msgid "SP-GiST inner tuple size %zu exceeds maximum %zu"
-msgstr "la taille de la ligne interne SP-GiST, %zu, d�passe le maximum, %zu"
+msgstr "la taille de la ligne interne SP-GiST, %zu, dépasse le maximum, %zu"
#: access/spgist/spgvalidate.c:92
#, c-format
-msgid "spgist opfamily %s contains support procedure %s with cross-type registration"
+msgid "spgist operator family \"%s\" contains support procedure %s with cross-type registration"
msgstr ""
+"la famille d'opérateur spgist « %s » contient la procédure de support\n"
+"%s avec un enregistrement inter-type"
#: access/spgist/spgvalidate.c:115
#, c-format
-msgid "spgist opfamily %s contains function %s with invalid support number %d"
+msgid "spgist operator family \"%s\" contains function %s with invalid support number %d"
msgstr ""
+"la famille d'opérateur spgist « %s » contient la fonction %s\n"
+"avec le numéro de support %d invalide"
#: access/spgist/spgvalidate.c:127
#, c-format
-msgid "spgist opfamily %s contains function %s with wrong signature for support number %d"
+msgid "spgist operator family \"%s\" contains function %s with wrong signature for support number %d"
msgstr ""
+"la famille d'opérateur spgist « %s » contient la fonction %s\n"
+"avec une mauvaise signature pour le numéro de support %d"
#: access/spgist/spgvalidate.c:146
#, c-format
-msgid "spgist opfamily %s contains operator %s with invalid strategy number %d"
+msgid "spgist operator family \"%s\" contains operator %s with invalid strategy number %d"
msgstr ""
+"la famille d'opérateur spgist « %s » contient l'opérateur %s\n"
+"avec le numéro de stratégie invalide %d"
#: access/spgist/spgvalidate.c:159
#, c-format
-msgid "spgist opfamily %s contains invalid ORDER BY specification for operator %s"
+msgid "spgist operator family \"%s\" contains invalid ORDER BY specification for operator %s"
msgstr ""
+"la famille d'opérateur spgist « %s » contient une spécification\n"
+"ORDER BY invalide pour l'opérateur %s"
#: access/spgist/spgvalidate.c:172
#, c-format
-msgid "spgist opfamily %s contains operator %s with wrong signature"
-msgstr ""
+msgid "spgist operator family \"%s\" contains operator %s with wrong signature"
+msgstr "la famille d'opérateur spgist « %s » contient l'opérateur %s avec une mauvaise signature"
#: access/spgist/spgvalidate.c:200
#, c-format
-msgid "spgist opfamily %s is missing operator(s) for types %s and %s"
+msgid "spgist operator family \"%s\" is missing operator(s) for types %s and %s"
msgstr ""
+"la famille d'opérateur spgist « %s » nécessite des opérateurs supplémentaires\n"
+"pour les types %s et %s"
#: access/spgist/spgvalidate.c:220
#, c-format
-msgid "spgist opfamily %s is missing support function %d for type %s"
+msgid "spgist operator family \"%s\" is missing support function %d for type %s"
msgstr ""
+"la famille d'opérateur spgist « %s » nécessite la fonction de support %d\n"
+"pour le type %s"
#: access/spgist/spgvalidate.c:233
#, c-format
-msgid "spgist opclass %s is missing operator(s)"
-msgstr ""
+msgid "spgist operator class \"%s\" is missing operator(s)"
+msgstr "il manque des opérateurs pour la classe d'opérateur spgist « %s »"
#: access/tablesample/bernoulli.c:152 access/tablesample/system.c:156
#, c-format
msgid "sample percentage must be between 0 and 100"
-msgstr "le pourcentage de l'�chantillonnage doit �tre compris entre 0 et 100"
+msgstr "le pourcentage de l'échantillonnage doit être compris entre 0 et 100"
-#: access/transam/commit_ts.c:295
+#: access/transam/commit_ts.c:294
#, c-format
msgid "cannot retrieve commit timestamp for transaction %u"
-msgstr "ne peut pas r�cup�rer l'horodatage de la validation pour la transaction %u"
+msgstr "ne peut pas récupérer l'horodatage de la validation pour la transaction %u"
-#: access/transam/commit_ts.c:385
+#: access/transam/commit_ts.c:392
#, c-format
msgid "could not get commit timestamp data"
-msgstr "n'a pas pu r�cup�rer les donn�es d'horodatage de la validation"
+msgstr "n'a pas pu récupérer les données d'horodatage de la validation"
-#: access/transam/commit_ts.c:387
+#: access/transam/commit_ts.c:394
#, c-format
msgid "Make sure the configuration parameter \"%s\" is set on the master server."
-msgstr "Assurez-vous que le param�tre de configuration � %s � soit configur� sur le serveur primaire."
+msgstr "Assurez-vous que le paramètre de configuration « %s » soit configuré sur le serveur primaire."
-#: access/transam/commit_ts.c:389 libpq/hba.c:1441
+#: access/transam/commit_ts.c:396 libpq/hba.c:1439
#, c-format
msgid "Make sure the configuration parameter \"%s\" is set."
-msgstr "Assurez-vous que le param�tre de configuration � %s � soit configur�."
+msgstr "Assurez-vous que le paramètre de configuration « %s » soit configuré."
#: access/transam/multixact.c:1000
#, c-format
msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\""
-msgstr "la base de donn�es n'accepte pas de commandes qui g�n�rent de nouveaux MultiXactId pour �viter les pertes de donn�es suite � une r�initialisation de l'identifiant de transaction dans la base de donn�es � %s �"
+msgstr "la base de données n'accepte pas de commandes qui génèrent de nouveaux MultiXactId pour éviter les pertes de données suite à une réinitialisation de l'identifiant de transaction dans la base de données « %s »"
#: access/transam/multixact.c:1002 access/transam/multixact.c:1009 access/transam/multixact.c:1033 access/transam/multixact.c:1042
#, c-format
@@ -1053,195 +1130,192 @@ msgid ""
"Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions."
msgstr ""
-"Ex�cutez un VACUUM sur toute cette base.\n"
-"Vous pouvez avoir besoin de valider ou d'annuler les anciennes transactions pr�par�es."
+"Exécutez un VACUUM sur toute cette base.\n"
+"Vous pouvez avoir besoin de valider ou d'annuler les anciennes transactions préparées."
#: access/transam/multixact.c:1007
#, c-format
msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u"
msgstr ""
-"la base de donn�es n'accepte pas de commandes qui g�n�rent de nouveaux MultiXactId pour �viter des pertes de donn�es � cause de la r�initialisation de l'identifiant de transaction dans\n"
-"la base de donn�es d'OID %u"
+"la base de données n'accepte pas de commandes qui génèrent de nouveaux MultiXactId pour éviter des pertes de données à cause de la réinitialisation de l'identifiant de transaction dans\n"
+"la base de données d'OID %u"
-#: access/transam/multixact.c:1028 access/transam/multixact.c:2317
+#: access/transam/multixact.c:1028 access/transam/multixact.c:2314
#, c-format
msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used"
msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used"
-msgstr[0] "un VACUUM doit �tre ex�cut� sur la base de donn�es � %s � dans un maximum de %u MultiXactId"
-msgstr[1] "un VACUUM doit �tre ex�cut� sur la base de donn�es � %s � dans un maximum de %u MultiXactId"
+msgstr[0] "un VACUUM doit être exécuté sur la base de données « %s » dans un maximum de %u MultiXactId"
+msgstr[1] "un VACUUM doit être exécuté sur la base de données « %s » dans un maximum de %u MultiXactId"
-#: access/transam/multixact.c:1037 access/transam/multixact.c:2326
+#: access/transam/multixact.c:1037 access/transam/multixact.c:2323
#, c-format
msgid "database with OID %u must be vacuumed before %u more MultiXactId is used"
msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used"
-msgstr[0] "un VACUUM doit �tre ex�cut� sur la base de donn�es d'OID %u dans un maximum de %u MultiXactId"
-msgstr[1] "un VACUUM doit �tre ex�cut� sur la base de donn�es d'OID %u dans un maximum de %u MultiXactId"
+msgstr[0] "un VACUUM doit être exécuté sur la base de données d'OID %u dans un maximum de %u MultiXactId"
+msgstr[1] "un VACUUM doit être exécuté sur la base de données d'OID %u dans un maximum de %u MultiXactId"
#: access/transam/multixact.c:1098
#, c-format
msgid "multixact \"members\" limit exceeded"
-msgstr "d�passement de limite des membres du multixact"
+msgstr "dépassement de limite des membres du multixact"
#: access/transam/multixact.c:1099
#, c-format
msgid "This command would create a multixact with %u members, but the remaining space is only enough for %u member."
msgid_plural "This command would create a multixact with %u members, but the remaining space is only enough for %u members."
-msgstr[0] "Cette commande cr�era un multixact avec %u membres, mais l'espace restant est seulement suffisant pour %u membre."
-msgstr[1] "Cette commande cr�era un multixact avec %u membres, mais l'espace restant est seulement suffisant pour %u membres."
+msgstr[0] "Cette commande créera un multixact avec %u membres, mais l'espace restant est seulement suffisant pour %u membre."
+msgstr[1] "Cette commande créera un multixact avec %u membres, mais l'espace restant est seulement suffisant pour %u membres."
#: access/transam/multixact.c:1104
#, c-format
msgid "Execute a database-wide VACUUM in database with OID %u with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings."
-msgstr "Ex�cute un VACUUM sur la base dans la base d'OID %u avec une configuration r�duite pour vacuum_multixact_freeze_min_age et vacuum_multixact_freeze_table_age."
+msgstr "Exécute un VACUUM sur la base dans la base d'OID %u avec une configuration réduite pour vacuum_multixact_freeze_min_age et vacuum_multixact_freeze_table_age."
#: access/transam/multixact.c:1135
#, c-format
msgid "database with OID %u must be vacuumed before %d more multixact member is used"
msgid_plural "database with OID %u must be vacuumed before %d more multixact members are used"
-msgstr[0] "un VACUUM doit �tre ex�cut� sur la base de donn�es d'OID %u avant que %d MultiXactId suppl�mentaire ne soit utilis�"
-msgstr[1] "un VACUUM doit �tre ex�cut� sur la base de donn�es d'OID %u avant que %d MultiXactId suppl�mentaires ne soient utilis�s"
+msgstr[0] "un VACUUM doit être exécuté sur la base de données d'OID %u avant que %d MultiXactId supplémentaire ne soit utilisé"
+msgstr[1] "un VACUUM doit être exécuté sur la base de données d'OID %u avant que %d MultiXactId supplémentaires ne soient utilisés"
#: access/transam/multixact.c:1140
#, c-format
msgid "Execute a database-wide VACUUM in that database with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings."
-msgstr "Ex�cute un VACUUM sur la base dans cette base avec une configuration r�duite pour vacuum_multixact_freeze_min_age et vacuum_multixact_freeze_table_age."
+msgstr "Exécute un VACUUM sur la base dans cette base avec une configuration réduite pour vacuum_multixact_freeze_min_age et vacuum_multixact_freeze_table_age."
-#: access/transam/multixact.c:1278
+#: access/transam/multixact.c:1277
#, c-format
msgid "MultiXactId %u does no longer exist -- apparent wraparound"
msgstr "le MultiXactId %u n'existe plus - wraparound apparent"
-#: access/transam/multixact.c:1286
+#: access/transam/multixact.c:1285
#, c-format
msgid "MultiXactId %u has not been created yet -- apparent wraparound"
-msgstr "le MultiXactId %u n'a pas encore �t� cr�er : wraparound apparent"
+msgstr "le MultiXactId %u n'a pas encore été créer : wraparound apparent"
-#: access/transam/multixact.c:2267
+#: access/transam/multixact.c:2264
#, c-format
msgid "MultiXactId wrap limit is %u, limited by database with OID %u"
-msgstr "La limite de r�initialisation MultiXactId est %u, limit� par la base de donn�es d'OID %u"
+msgstr "La limite de réinitialisation MultiXactId est %u, limité par la base de données d'OID %u"
-#: access/transam/multixact.c:2322 access/transam/multixact.c:2331 access/transam/varsup.c:146 access/transam/varsup.c:153 access/transam/varsup.c:384 access/transam/varsup.c:391
+#: access/transam/multixact.c:2319 access/transam/multixact.c:2328 access/transam/varsup.c:146 access/transam/varsup.c:153 access/transam/varsup.c:384 access/transam/varsup.c:391
#, c-format
msgid ""
"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions."
msgstr ""
-"Pour �viter un arr�t de la base de donn�es, ex�cutez un VACUUM sur toute cette\n"
+"Pour éviter un arrêt de la base de données, exécutez un VACUUM sur toute cette\n"
"base. Vous pouvez avoir besoin d'enregistrer ou d'annuler les anciennes\n"
-"transactions pr�par�es."
+"transactions préparées."
-#: access/transam/multixact.c:2601
+#: access/transam/multixact.c:2598
#, c-format
msgid "oldest MultiXactId member is at offset %u"
-msgstr "le membre le plus ancien du MultiXactId est au d�calage %u"
+msgstr "le membre le plus ancien du MultiXactId est au décalage %u"
-#: access/transam/multixact.c:2605
+#: access/transam/multixact.c:2602
#, c-format
msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk"
-msgstr "Les protections sur la r�utilisation d'un membre MultiXact sont d�sactiv�es car le plus ancien MultiXact g�r� par un checkpoint, %u, n'existe pas sur disque"
+msgstr "Les protections sur la réutilisation d'un membre MultiXact sont désactivées car le plus ancien MultiXact géré par un checkpoint, %u, n'existe pas sur disque"
-#: access/transam/multixact.c:2627
+#: access/transam/multixact.c:2624
#, c-format
msgid "MultiXact member wraparound protections are now enabled"
-msgstr "Les protections sur la r�utilisation d'un membre MultiXact sont maintenant activ�es"
+msgstr "Les protections sur la réutilisation d'un membre MultiXact sont maintenant activées"
-#: access/transam/multixact.c:2629
+#: access/transam/multixact.c:2626
#, c-format
msgid "MultiXact member stop limit is now %u based on MultiXact %u"
-msgstr "La limite d'arr�t d'un membre MultiXact est maintenant %x, base sur le MultiXact %u"
+msgstr "La limite d'arrêt d'un membre MultiXact est maintenant %x, base sur le MultiXact %u"
-#: access/transam/multixact.c:3009
+#: access/transam/multixact.c:3006
#, c-format
msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation"
-msgstr "plus ancien MultiXact introuvable %u, plus r�cent MultiXact %u, ignore le troncage"
+msgstr "plus ancien MultiXact introuvable %u, plus récent MultiXact %u, ignore le troncage"
-#: access/transam/multixact.c:3027
+#: access/transam/multixact.c:3024
#, c-format
msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation"
msgstr "ne peut pas tronquer jusqu'au MutiXact %u car il n'existe pas sur disque, ignore le troncage"
-#: access/transam/multixact.c:3353
+#: access/transam/multixact.c:3350
#, c-format
msgid "invalid MultiXactId: %u"
msgstr "MultiXactId invalide : %u"
-#: access/transam/parallel.c:583
+#: access/transam/parallel.c:589
#, c-format
msgid "postmaster exited during a parallel transaction"
-msgstr "postmaster a quitt� pendant une transaction parall�le"
+msgstr "postmaster a quitté pendant une transaction parallèle"
-#: access/transam/parallel.c:741
+#: access/transam/parallel.c:774
#, c-format
msgid "lost connection to parallel worker"
-msgstr "perte de la connexion au processus parall�le"
+msgstr "perte de la connexion au processus parallèle"
-#: access/transam/parallel.c:916
-#, fuzzy, c-format
-#| msgid "too many dynamic shared memory segments"
-msgid "could not map dynamic shared memory segment"
-msgstr "trop de segments de m�moire partag�e dynamique"
+#: access/transam/parallel.c:833 access/transam/parallel.c:835
+msgid "parallel worker"
+msgstr "processus parallèle"
-#: access/transam/parallel.c:921
-#, fuzzy, c-format
-#| msgid "too many dynamic shared memory segments"
-msgid "invalid magic number in dynamic shared memory segment"
-msgstr "trop de segments de m�moire partag�e dynamique"
+#: access/transam/parallel.c:974
+#, c-format
+msgid "could not map dynamic shared memory segment"
+msgstr "n'a pas pu mapper le segment de mémoire partagée dynamique"
-#: access/transam/parallel.c:1086
+#: access/transam/parallel.c:979
#, c-format
-msgid "parallel worker, PID %d"
-msgstr "processus en parall�le, PID %d"
+msgid "invalid magic number in dynamic shared memory segment"
+msgstr "numéro magique invalide dans le segment de mémoire partagée dynamique"
#: access/transam/slru.c:665
#, c-format
msgid "file \"%s\" doesn't exist, reading as zeroes"
-msgstr "le fichier � %s � n'existe pas, contenu lu comme des z�ros"
+msgstr "le fichier « %s » n'existe pas, contenu lu comme des zéros"
#: access/transam/slru.c:895 access/transam/slru.c:901 access/transam/slru.c:908 access/transam/slru.c:915 access/transam/slru.c:922 access/transam/slru.c:929
#, c-format
msgid "could not access status of transaction %u"
-msgstr "n'a pas pu acc�der au statut de la transaction %u"
+msgstr "n'a pas pu accéder au statut de la transaction %u"
#: access/transam/slru.c:896
#, c-format
msgid "Could not open file \"%s\": %m."
-msgstr "N'a pas pu ouvrir le fichier � %s � : %m"
+msgstr "N'a pas pu ouvrir le fichier « %s » : %m"
#: access/transam/slru.c:902
#, c-format
msgid "Could not seek in file \"%s\" to offset %u: %m."
-msgstr "N'a pas pu se d�placer dans le fichier � %s � au d�calage %u : %m"
+msgstr "N'a pas pu se déplacer dans le fichier « %s » au décalage %u : %m"
#: access/transam/slru.c:909
#, c-format
msgid "Could not read from file \"%s\" at offset %u: %m."
-msgstr "N'a pas pu lire le fichier � %s � au d�calage %u : %m"
+msgstr "N'a pas pu lire le fichier « %s » au décalage %u : %m"
#: access/transam/slru.c:916
#, c-format
msgid "Could not write to file \"%s\" at offset %u: %m."
-msgstr "N'a pas pu �crire le fichier � %s � au d�calage %u : %m"
+msgstr "N'a pas pu écrire le fichier « %s » au décalage %u : %m"
#: access/transam/slru.c:923
#, c-format
msgid "Could not fsync file \"%s\": %m."
-msgstr "N'a pas pu synchroniser sur disque (fsync) le fichier � %s � : %m"
+msgstr "N'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m"
#: access/transam/slru.c:930
#, c-format
msgid "Could not close file \"%s\": %m."
-msgstr "N'a pas pu fermer le fichier � %s � : %m"
+msgstr "N'a pas pu fermer le fichier « %s » : %m"
#: access/transam/slru.c:1185
#, c-format
msgid "could not truncate directory \"%s\": apparent wraparound"
-msgstr "n'a pas pu tronquer le r�pertoire � %s � : contournement apparent"
+msgstr "n'a pas pu tronquer le répertoire « %s » : contournement apparent"
#: access/transam/slru.c:1240 access/transam/slru.c:1296
#, c-format
msgid "removing file \"%s\""
-msgstr "suppression du fichier � %s �"
+msgstr "suppression du fichier « %s »"
#: access/transam/timeline.c:148 access/transam/timeline.c:153
#, c-format
@@ -1251,7 +1325,7 @@ msgstr "erreur de syntaxe dans le fichier historique : %s"
#: access/transam/timeline.c:149
#, c-format
msgid "Expected a numeric timeline ID."
-msgstr "Identifiant timeline num�rique attendue"
+msgstr "Identifiant timeline numérique attendue"
#: access/transam/timeline.c:154
#, c-format
@@ -1261,29 +1335,29 @@ msgstr "Attendait un emplacement de bascule dans le journal de transactions."
#: access/transam/timeline.c:158
#, c-format
msgid "invalid data in history file: %s"
-msgstr "donn�es invalides dans le fichier historique : � %s �"
+msgstr "données invalides dans le fichier historique : « %s »"
#: access/transam/timeline.c:159
#, c-format
msgid "Timeline IDs must be in increasing sequence."
-msgstr "Les identifiants timeline doivent �tre en ordre croissant."
+msgstr "Les identifiants timeline doivent être en ordre croissant."
#: access/transam/timeline.c:179
#, c-format
msgid "invalid data in history file \"%s\""
-msgstr "donn�es invalides dans le fichier historique � %s �"
+msgstr "données invalides dans le fichier historique « %s »"
#: access/transam/timeline.c:180
#, c-format
msgid "Timeline IDs must be less than child timeline's ID."
msgstr ""
-"Les identifiants timeline doivent �tre plus petits que les enfants des\n"
+"Les identifiants timeline doivent être plus petits que les enfants des\n"
"identifiants timeline."
-#: access/transam/timeline.c:412 access/transam/timeline.c:488 access/transam/xlog.c:3066 access/transam/xlog.c:3227 access/transam/xlogfuncs.c:691 commands/copy.c:1671 storage/file/copydir.c:201
+#: access/transam/timeline.c:412 access/transam/timeline.c:488 access/transam/xlog.c:3093 access/transam/xlog.c:3254 access/transam/xlogfuncs.c:690 commands/copy.c:1708 storage/file/copydir.c:201
#, c-format
msgid "could not close file \"%s\": %m"
-msgstr "n'a pas pu fermer le fichier � %s � : %m"
+msgstr "n'a pas pu fermer le fichier « %s » : %m"
#: access/transam/timeline.c:570
#, c-format
@@ -1293,176 +1367,177 @@ msgstr "la timeline %u requise n'est pas dans l'historique de ce serveur"
#: access/transam/twophase.c:363
#, c-format
msgid "transaction identifier \"%s\" is too long"
-msgstr "l'identifiant de la transaction � %s � est trop long"
+msgstr "l'identifiant de la transaction « %s » est trop long"
#: access/transam/twophase.c:370
#, c-format
msgid "prepared transactions are disabled"
-msgstr "les transactions pr�par�es sont d�sactiv�es"
+msgstr "les transactions préparées sont désactivées"
#: access/transam/twophase.c:371
#, c-format
msgid "Set max_prepared_transactions to a nonzero value."
-msgstr "Configure max_prepared_transactions � une valeur diff�rente de z�ro."
+msgstr "Configure max_prepared_transactions à une valeur différente de zéro."
#: access/transam/twophase.c:390
#, c-format
msgid "transaction identifier \"%s\" is already in use"
-msgstr "l'identifiant de la transaction � %s � est d�j� utilis�"
+msgstr "l'identifiant de la transaction « %s » est déjà utilisé"
#: access/transam/twophase.c:399
#, c-format
msgid "maximum number of prepared transactions reached"
-msgstr "nombre maximum de transactions pr�par�es obtenu"
+msgstr "nombre maximum de transactions préparées obtenu"
#: access/transam/twophase.c:400
#, c-format
msgid "Increase max_prepared_transactions (currently %d)."
msgstr "Augmentez max_prepared_transactions (actuellement %d)."
-#: access/transam/twophase.c:539
+#: access/transam/twophase.c:540
#, c-format
msgid "prepared transaction with identifier \"%s\" is busy"
-msgstr "la transaction pr�par�e d'identifiant � %s � est occup�e"
+msgstr "la transaction préparée d'identifiant « %s » est occupée"
-#: access/transam/twophase.c:545
+#: access/transam/twophase.c:546
#, c-format
msgid "permission denied to finish prepared transaction"
-msgstr "droit refus� pour terminer la transaction pr�par�e"
+msgstr "droit refusé pour terminer la transaction préparée"
-#: access/transam/twophase.c:546
+#: access/transam/twophase.c:547
#, c-format
msgid "Must be superuser or the user that prepared the transaction."
-msgstr "Doit �tre super-utilisateur ou l'utilisateur qui a pr�par� la transaction."
+msgstr "Doit être super-utilisateur ou l'utilisateur qui a préparé la transaction."
-#: access/transam/twophase.c:557
+#: access/transam/twophase.c:558
#, c-format
msgid "prepared transaction belongs to another database"
-msgstr "la transaction pr�par�e appartient � une autre base de donn�es"
+msgstr "la transaction préparée appartient à une autre base de données"
-#: access/transam/twophase.c:558
+#: access/transam/twophase.c:559
#, c-format
msgid "Connect to the database where the transaction was prepared to finish it."
msgstr ""
-"Connectez-vous � la base de donn�es o� la transaction a �t� pr�par�e pour\n"
+"Connectez-vous à la base de données où la transaction a été préparée pour\n"
"la terminer."
-#: access/transam/twophase.c:573
+#: access/transam/twophase.c:574
#, c-format
msgid "prepared transaction with identifier \"%s\" does not exist"
-msgstr "la transaction pr�par�e d'identifiant � %s � n'existe pas"
+msgstr "la transaction préparée d'identifiant « %s » n'existe pas"
-#: access/transam/twophase.c:1042
+#: access/transam/twophase.c:1043
#, c-format
msgid "two-phase state file maximum length exceeded"
msgstr ""
-"longueur maximale d�pass�e pour le fichier de statut de la validation en\n"
+"longueur maximale dépassée pour le fichier de statut de la validation en\n"
"deux phase"
-#: access/transam/twophase.c:1160
+#: access/transam/twophase.c:1161
#, c-format
msgid "could not open two-phase state file \"%s\": %m"
msgstr ""
-"n'a pas pu ouvrir le fichier d'�tat de la validation en deux phases nomm�\n"
-"� %s � : %m"
+"n'a pas pu ouvrir le fichier d'état de la validation en deux phases nommé\n"
+"« %s » : %m"
-#: access/transam/twophase.c:1177
+#: access/transam/twophase.c:1178
#, c-format
msgid "could not stat two-phase state file \"%s\": %m"
msgstr ""
-"n'a pas pu r�cup�rer des informations sur le fichier d'�tat de la validation\n"
-"en deux phases nomm� � %s � : %m"
+"n'a pas pu récupérer des informations sur le fichier d'état de la validation\n"
+"en deux phases nommé « %s » : %m"
-#: access/transam/twophase.c:1209
+#: access/transam/twophase.c:1210
#, c-format
msgid "could not read two-phase state file \"%s\": %m"
msgstr ""
-"n'a pas pu lire le fichier d'�tat de la validation en deux phases nomm�\n"
-"� %s � : %m"
+"n'a pas pu lire le fichier d'état de la validation en deux phases nommé\n"
+"« %s » : %m"
-#: access/transam/twophase.c:1262 access/transam/xlog.c:6070
+#: access/transam/twophase.c:1263 access/transam/xlog.c:6109
#, c-format
msgid "Failed while allocating an XLog reading processor."
-msgstr "�chec lors de l'allocation d'un processeur de lecture XLog"
+msgstr "Échec lors de l'allocation d'un processeur de lecture XLog"
-#: access/transam/twophase.c:1268
-#, fuzzy, c-format
-#| msgid "could not read two-phase state file \"%s\": %m"
+#: access/transam/twophase.c:1269
+#, c-format
msgid "could not read two-phase state from xlog at %X/%X"
-msgstr ""
-"n'a pas pu lire le fichier d'�tat de la validation en deux phases nomm�\n"
-"� %s � : %m"
+msgstr "n'a pas pu lire le fichier d'état de la validation en deux phases depuis les journaux de transaction à %X/%X"
-#: access/transam/twophase.c:1276
+#: access/transam/twophase.c:1277
#, c-format
msgid "expected two-phase state data is not present in xlog at %X/%X"
msgstr ""
+"le fichier d'état de la validation en deux phases attendu n'est pas présent\n"
+"dans les journaux de transaction à %X/%X"
#: access/transam/twophase.c:1512
#, c-format
msgid "could not remove two-phase state file \"%s\": %m"
msgstr ""
-"n'a pas pu supprimer le fichier d'�tat de la validation en deux phases\n"
-"� %s � : %m"
+"n'a pas pu supprimer le fichier d'état de la validation en deux phases\n"
+"« %s » : %m"
#: access/transam/twophase.c:1542
#, c-format
msgid "could not recreate two-phase state file \"%s\": %m"
msgstr ""
-"n'a pas pu re-cr�er le fichier d'�tat de la validation en deux phases nomm�\n"
-"� %s � : %m"
+"n'a pas pu re-créer le fichier d'état de la validation en deux phases nommé\n"
+"« %s » : %m"
#: access/transam/twophase.c:1551 access/transam/twophase.c:1558
#, c-format
msgid "could not write two-phase state file: %m"
-msgstr "n'a pas pu �crire dans le fichier d'�tat de la validation en deux phases : %m"
+msgstr "n'a pas pu écrire dans le fichier d'état de la validation en deux phases : %m"
#: access/transam/twophase.c:1570
#, c-format
msgid "could not fsync two-phase state file: %m"
msgstr ""
-"n'a pas pu synchroniser sur disque (fsync) le fichier d'�tat de la\n"
+"n'a pas pu synchroniser sur disque (fsync) le fichier d'état de la\n"
"validation en deux phases : %m"
#: access/transam/twophase.c:1576
#, c-format
msgid "could not close two-phase state file: %m"
-msgstr "n'a pas pu fermer le fichier d'�tat de la validation en deux phases : %m"
+msgstr "n'a pas pu fermer le fichier d'état de la validation en deux phases : %m"
-#: access/transam/twophase.c:1651
+#: access/transam/twophase.c:1649
#, c-format
-msgid "%u two-phase state files were written for long-running prepared transactions"
-msgstr ""
+msgid "%u two-phase state file was written for long-running prepared transactions"
+msgid_plural "%u two-phase state files were written for long-running prepared transactions"
+msgstr[0] "le fichier d'état de la validation en deux phases %u a été écrit pour des transaction préparée de longue duré"
+msgstr[1] "les fichiers d'état de la validation en deux phases %u a été écrit pour des transaction préparée de longue duré"
-#: access/transam/twophase.c:1712
+#: access/transam/twophase.c:1713
#, c-format
msgid "removing future two-phase state file \"%s\""
-msgstr "suppression du futur fichier d'�tat de la validation en deux phases nomm� � %s �"
+msgstr "suppression du futur fichier d'état de la validation en deux phases nommé « %s »"
-#: access/transam/twophase.c:1728 access/transam/twophase.c:1739 access/transam/twophase.c:1858 access/transam/twophase.c:1869 access/transam/twophase.c:1943
+#: access/transam/twophase.c:1729 access/transam/twophase.c:1740 access/transam/twophase.c:1860 access/transam/twophase.c:1871 access/transam/twophase.c:1948
#, c-format
msgid "removing corrupt two-phase state file \"%s\""
msgstr ""
-"suppression du fichier d'�tat corrompu de la validation en deux phases nomm�\n"
-"� %s �"
+"suppression du fichier d'état corrompu de la validation en deux phases nommé\n"
+"« %s »"
-#: access/transam/twophase.c:1847 access/transam/twophase.c:1932
+#: access/transam/twophase.c:1849 access/transam/twophase.c:1937
#, c-format
msgid "removing stale two-phase state file \"%s\""
-msgstr "suppression du vieux fichier d'�tat de la validation en deux phases nomm� � %s �"
+msgstr "suppression du vieux fichier d'état de la validation en deux phases nommé « %s »"
-#: access/transam/twophase.c:1950
+#: access/transam/twophase.c:1955
#, c-format
msgid "recovering prepared transaction %u"
-msgstr "r�cup�ration de la transaction pr�par�e %u"
+msgstr "récupération de la transaction préparée %u"
#: access/transam/varsup.c:124
#, c-format
msgid "database is not accepting commands to avoid wraparound data loss in database \"%s\""
msgstr ""
-"la base de donn�es n'accepte plus de requ�tes pour �viter des pertes de\n"
-"donn�es � cause de la r�initialisation de l'identifiant de transaction dans\n"
-"la base de donn�es � %s �"
+"la base de données n'accepte plus de requêtes pour éviter des pertes de\n"
+"données à cause de la réinitialisation de l'identifiant de transaction dans\n"
+"la base de données « %s »"
#: access/transam/varsup.c:126 access/transam/varsup.c:133
#, c-format
@@ -1470,1249 +1545,1248 @@ msgid ""
"Stop the postmaster and vacuum that database in single-user mode.\n"
"You might also need to commit or roll back old prepared transactions."
msgstr ""
-"Arr�tez le postmaster et utilisez un moteur autonome pour ex�cuter VACUUM\n"
-"sur cette base de donn�es.\n"
-"Vous pouvez avoir besoin de valider ou d'annuler les anciennes transactions pr�par�es."
+"Arrêtez le postmaster et utilisez un moteur autonome pour exécuter VACUUM\n"
+"sur cette base de données.\n"
+"Vous pouvez avoir besoin de valider ou d'annuler les anciennes transactions préparées."
#: access/transam/varsup.c:131
#, c-format
msgid "database is not accepting commands to avoid wraparound data loss in database with OID %u"
msgstr ""
-"la base de donn�es n'accepte plus de requ�tes pour �viter des pertes de\n"
-"donn�es � cause de la r�initialisation de l'identifiant de transaction dans\n"
-"la base de donn�es %u"
+"la base de données n'accepte plus de requêtes pour éviter des pertes de\n"
+"données à cause de la réinitialisation de l'identifiant de transaction dans\n"
+"la base de données %u"
#: access/transam/varsup.c:143 access/transam/varsup.c:381
#, c-format
msgid "database \"%s\" must be vacuumed within %u transactions"
msgstr ""
-"Un VACUUM doit �tre ex�cut� sur la base de donn�es � %s � dans un maximum de\n"
+"Un VACUUM doit être exécuté sur la base de données « %s » dans un maximum de\n"
"%u transactions"
#: access/transam/varsup.c:150 access/transam/varsup.c:388
#, c-format
msgid "database with OID %u must be vacuumed within %u transactions"
msgstr ""
-"un VACUUM doit �tre ex�cut� sur la base de donn�es d'OID %u dans un maximum de\n"
+"un VACUUM doit être exécuté sur la base de données d'OID %u dans un maximum de\n"
"%u transactions"
#: access/transam/varsup.c:346
#, c-format
msgid "transaction ID wrap limit is %u, limited by database with OID %u"
msgstr ""
-"la limite de r�initialisation de l'identifiant de transaction est %u,\n"
-"limit� par la base de donn�es d'OID %u"
+"la limite de réinitialisation de l'identifiant de transaction est %u,\n"
+"limité par la base de données d'OID %u"
#: access/transam/xact.c:943
#, c-format
msgid "cannot have more than 2^32-2 commands in a transaction"
msgstr "ne peux pas avoir plus de 2^32-2 commandes dans une transaction"
-#: access/transam/xact.c:1471
+#: access/transam/xact.c:1467
#, c-format
msgid "maximum number of committed subtransactions (%d) exceeded"
-msgstr "nombre maximum de sous-transactions valid�es (%d) d�pass�"
+msgstr "nombre maximum de sous-transactions validées (%d) dépassé"
-#: access/transam/xact.c:2267
+#: access/transam/xact.c:2263
#, c-format
msgid "cannot PREPARE a transaction that has operated on temporary tables"
msgstr ""
-"ne peut pas pr�parer (PREPARE) une transaction qui a travaill� sur des\n"
+"ne peut pas préparer (PREPARE) une transaction qui a travaillé sur des\n"
"tables temporaires"
-#: access/transam/xact.c:2277
+#: access/transam/xact.c:2273
#, c-format
msgid "cannot PREPARE a transaction that has exported snapshots"
-msgstr "ne peut pas pr�parer (PREPARE) une transaction qui a export� des snapshots"
+msgstr "ne peut pas préparer (PREPARE) une transaction qui a exporté des snapshots"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3159
+#: access/transam/xact.c:3155
#, c-format
msgid "%s cannot run inside a transaction block"
-msgstr "%s ne peut pas �tre ex�cut� dans un bloc de transaction"
+msgstr "%s ne peut pas être exécuté dans un bloc de transaction"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3169
+#: access/transam/xact.c:3165
#, c-format
msgid "%s cannot run inside a subtransaction"
-msgstr "%s ne peut pas �tre ex�cut� dans un sous-bloc de transaction"
+msgstr "%s ne peut pas être exécuté dans un sous-bloc de transaction"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3179
+#: access/transam/xact.c:3175
#, c-format
msgid "%s cannot be executed from a function or multi-command string"
msgstr ""
-"%s ne peut pas �tre ex�cut� � partir d'une fonction ou d'une cha�ne\n"
+"%s ne peut pas être exécuté à partir d'une fonction ou d'une chaîne\n"
"contenant plusieurs commandes"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3250
+#: access/transam/xact.c:3246
#, c-format
msgid "%s can only be used in transaction blocks"
-msgstr "%s peut seulement �tre utilis� dans des blocs de transaction"
+msgstr "%s peut seulement être utilisé dans des blocs de transaction"
-#: access/transam/xact.c:3434
+#: access/transam/xact.c:3430
#, c-format
msgid "there is already a transaction in progress"
-msgstr "une transaction est d�j� en cours"
+msgstr "une transaction est déjà en cours"
-#: access/transam/xact.c:3602 access/transam/xact.c:3705
+#: access/transam/xact.c:3598 access/transam/xact.c:3701
#, c-format
msgid "there is no transaction in progress"
msgstr "aucune transaction en cours"
-#: access/transam/xact.c:3613
+#: access/transam/xact.c:3609
#, c-format
msgid "cannot commit during a parallel operation"
-msgstr "ne peut pas valider pendant une op�ration parall�le"
+msgstr "ne peut pas valider pendant une opération parallèle"
-#: access/transam/xact.c:3716
+#: access/transam/xact.c:3712
#, c-format
msgid "cannot abort during a parallel operation"
-msgstr "ne peut pas annuler pendant une op�ration en parall�le"
+msgstr "ne peut pas annuler pendant une opération en parallèle"
-#: access/transam/xact.c:3758
+#: access/transam/xact.c:3754
#, c-format
msgid "cannot define savepoints during a parallel operation"
-msgstr "ne peut pas d�finir de points de sauvegarde lors d'une op�ration parall�le"
+msgstr "ne peut pas définir de points de sauvegarde lors d'une opération parallèle"
-#: access/transam/xact.c:3825
+#: access/transam/xact.c:3821
#, c-format
msgid "cannot release savepoints during a parallel operation"
-msgstr "ne peut pas rel�cher de points de sauvegarde pendant une op�ration parall�le"
+msgstr "ne peut pas relâcher de points de sauvegarde pendant une opération parallèle"
-#: access/transam/xact.c:3836 access/transam/xact.c:3888 access/transam/xact.c:3894 access/transam/xact.c:3950 access/transam/xact.c:4000 access/transam/xact.c:4006
+#: access/transam/xact.c:3832 access/transam/xact.c:3884 access/transam/xact.c:3890 access/transam/xact.c:3946 access/transam/xact.c:3996 access/transam/xact.c:4002
#, c-format
msgid "no such savepoint"
msgstr "aucun point de sauvegarde"
-#: access/transam/xact.c:3938
+#: access/transam/xact.c:3934
#, c-format
msgid "cannot rollback to savepoints during a parallel operation"
-msgstr "ne peut pas retourner � un point de sauvegarde pendant un op�ration parall�le"
+msgstr "ne peut pas retourner à un point de sauvegarde pendant un opération parallèle"
-#: access/transam/xact.c:4066
+#: access/transam/xact.c:4062
#, c-format
msgid "cannot start subtransactions during a parallel operation"
-msgstr "ne peut pas lancer de sous-transactions pendant une op�ration parall�le"
+msgstr "ne peut pas lancer de sous-transactions pendant une opération parallèle"
-#: access/transam/xact.c:4133
+#: access/transam/xact.c:4129
#, c-format
msgid "cannot commit subtransactions during a parallel operation"
-msgstr "ne peut pas valider de sous-transactions pendant une op�ration parall�le"
+msgstr "ne peut pas valider de sous-transactions pendant une opération parallèle"
-#: access/transam/xact.c:4741
+#: access/transam/xact.c:4737
#, c-format
msgid "cannot have more than 2^32-1 subtransactions in a transaction"
msgstr "ne peut pas avoir plus de 2^32-1 sous-transactions dans une transaction"
-#: access/transam/xlog.c:2272
+#: access/transam/xlog.c:2299
#, c-format
msgid "could not seek in log file %s to offset %u: %m"
-msgstr "n'a pas pu se d�placer dans le fichier de transactions � %s � au d�calage %u : %m"
+msgstr "n'a pas pu se déplacer dans le fichier de transactions « %s » au décalage %u : %m"
-#: access/transam/xlog.c:2292
+#: access/transam/xlog.c:2319
#, c-format
msgid "could not write to log file %s at offset %u, length %zu: %m"
-msgstr "n'a pas pu �crire le fichier de transactions %s au d�calage %u, longueur %zu : %m"
+msgstr "n'a pas pu écrire le fichier de transactions %s au décalage %u, longueur %zu : %m"
-#: access/transam/xlog.c:2555
+#: access/transam/xlog.c:2582
#, c-format
msgid "updated min recovery point to %X/%X on timeline %u"
-msgstr "mise � jour du point minimum de restauration sur %X/%X pour la timeline %u"
+msgstr "mise à jour du point minimum de restauration sur %X/%X pour la timeline %u"
-#: access/transam/xlog.c:3197
+#: access/transam/xlog.c:3224
#, c-format
msgid "not enough data in file \"%s\""
-msgstr "donn�es insuffisantes dans le fichier � %s �"
+msgstr "données insuffisantes dans le fichier « %s »"
-#: access/transam/xlog.c:3338
+#: access/transam/xlog.c:3365
#, c-format
msgid "could not open transaction log file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le journal des transactions � %s � : %m"
+msgstr "n'a pas pu ouvrir le journal des transactions « %s » : %m"
-#: access/transam/xlog.c:3527 access/transam/xlog.c:5300
+#: access/transam/xlog.c:3554 access/transam/xlog.c:5339
#, c-format
msgid "could not close log file %s: %m"
-msgstr "n'a pas pu fermer le fichier de transactions � %s � : %m"
+msgstr "n'a pas pu fermer le fichier de transactions « %s » : %m"
-#: access/transam/xlog.c:3584 access/transam/xlogutils.c:695 replication/walsender.c:2099
+#: access/transam/xlog.c:3611 access/transam/xlogutils.c:696 replication/walsender.c:2097
#, c-format
msgid "requested WAL segment %s has already been removed"
-msgstr "le segment demand� du journal de transaction, %s, a d�j� �t� supprim�"
+msgstr "le segment demandé du journal de transaction, %s, a déjà été supprimé"
-#: access/transam/xlog.c:3644 access/transam/xlog.c:3719 access/transam/xlog.c:3917
+#: access/transam/xlog.c:3671 access/transam/xlog.c:3746 access/transam/xlog.c:3944
#, c-format
msgid "could not open transaction log directory \"%s\": %m"
-msgstr "n'a pas pu ouvrir le r�pertoire des journaux de transactions � %s � : %m"
+msgstr "n'a pas pu ouvrir le répertoire des journaux de transactions « %s » : %m"
-#: access/transam/xlog.c:3800
+#: access/transam/xlog.c:3827
#, c-format
msgid "recycled transaction log file \"%s\""
-msgstr "recyclage du journal de transactions � %s �"
+msgstr "recyclage du journal de transactions « %s »"
-#: access/transam/xlog.c:3812
+#: access/transam/xlog.c:3839
#, c-format
msgid "removing transaction log file \"%s\""
-msgstr "suppression du journal de transactions � %s �"
+msgstr "suppression du journal de transactions « %s »"
-#: access/transam/xlog.c:3832
+#: access/transam/xlog.c:3859
#, c-format
msgid "could not rename old transaction log file \"%s\": %m"
-msgstr "n'a pas pu renommer l'ancien journal de transactions � %s � : %m"
+msgstr "n'a pas pu renommer l'ancien journal de transactions « %s » : %m"
-#: access/transam/xlog.c:3844
+#: access/transam/xlog.c:3871
#, c-format
msgid "could not remove old transaction log file \"%s\": %m"
-msgstr "n'a pas pu supprimer l'ancien journal de transaction � %s � : %m"
+msgstr "n'a pas pu supprimer l'ancien journal de transaction « %s » : %m"
-#: access/transam/xlog.c:3877 access/transam/xlog.c:3887
+#: access/transam/xlog.c:3904 access/transam/xlog.c:3914
#, c-format
msgid "required WAL directory \"%s\" does not exist"
-msgstr "le r�pertoire � %s � requis pour les journaux de transactions n'existe pas"
+msgstr "le répertoire « %s » requis pour les journaux de transactions n'existe pas"
-#: access/transam/xlog.c:3893
+#: access/transam/xlog.c:3920
#, c-format
msgid "creating missing WAL directory \"%s\""
-msgstr "cr�ation du r�pertoire manquant � %s � pour les journaux de transactions"
+msgstr "création du répertoire manquant « %s » pour les journaux de transactions"
-#: access/transam/xlog.c:3896
+#: access/transam/xlog.c:3923
#, c-format
msgid "could not create missing directory \"%s\": %m"
-msgstr "n'a pas pu cr�er le r�pertoire � %s � manquant : %m"
+msgstr "n'a pas pu créer le répertoire « %s » manquant : %m"
-#: access/transam/xlog.c:3927
+#: access/transam/xlog.c:3954
#, c-format
msgid "removing transaction log backup history file \"%s\""
-msgstr "suppression du fichier historique des journaux de transaction � %s �"
+msgstr "suppression du fichier historique des journaux de transaction « %s »"
-#: access/transam/xlog.c:4008
+#: access/transam/xlog.c:4035
#, c-format
msgid "unexpected timeline ID %u in log segment %s, offset %u"
-msgstr "identifiant timeline %u inattendu dans le journal de transactions %s, d�calage %u"
+msgstr "identifiant timeline %u inattendu dans le journal de transactions %s, décalage %u"
-#: access/transam/xlog.c:4130
+#: access/transam/xlog.c:4157
#, c-format
msgid "new timeline %u is not a child of database system timeline %u"
msgstr ""
-"le nouveau timeline %u n'est pas un fils du timeline %u du syst�me de bases\n"
-"de donn�es"
+"le nouveau timeline %u n'est pas un fils du timeline %u du système de bases\n"
+"de données"
-#: access/transam/xlog.c:4144
+#: access/transam/xlog.c:4171
#, c-format
msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X"
msgstr ""
-"la nouvelle timeline %u a �t� cr��e � partir de la timeline de la base de donn�es syst�me %u\n"
+"la nouvelle timeline %u a été créée à partir de la timeline de la base de données système %u\n"
"avant le point de restauration courant %X/%X"
-#: access/transam/xlog.c:4163
+#: access/transam/xlog.c:4190
#, c-format
msgid "new target timeline is %u"
msgstr "la nouvelle timeline cible est %u"
-#: access/transam/xlog.c:4243
+#: access/transam/xlog.c:4270
#, c-format
msgid "could not create control file \"%s\": %m"
-msgstr "n'a pas pu cr�er le fichier de contr�le � %s � : %m"
+msgstr "n'a pas pu créer le fichier de contrôle « %s » : %m"
-#: access/transam/xlog.c:4254 access/transam/xlog.c:4490
+#: access/transam/xlog.c:4281 access/transam/xlog.c:4517
#, c-format
msgid "could not write to control file: %m"
-msgstr "n'a pas pu �crire le fichier de contr�le : %m"
+msgstr "n'a pas pu écrire le fichier de contrôle : %m"
-#: access/transam/xlog.c:4260 access/transam/xlog.c:4496
+#: access/transam/xlog.c:4287 access/transam/xlog.c:4523
#, c-format
msgid "could not fsync control file: %m"
-msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier de contr�le : %m"
+msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier de contrôle : %m"
-#: access/transam/xlog.c:4265 access/transam/xlog.c:4501
+#: access/transam/xlog.c:4292 access/transam/xlog.c:4528
#, c-format
msgid "could not close control file: %m"
-msgstr "n'a pas pu fermer le fichier de contr�le : %m"
+msgstr "n'a pas pu fermer le fichier de contrôle : %m"
-#: access/transam/xlog.c:4283 access/transam/xlog.c:4479
+#: access/transam/xlog.c:4310 access/transam/xlog.c:4506
#, c-format
msgid "could not open control file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier de contr�le � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier de contrôle « %s » : %m"
-#: access/transam/xlog.c:4289
+#: access/transam/xlog.c:4316
#, c-format
msgid "could not read from control file: %m"
-msgstr "n'a pas pu lire le fichier de contr�le : %m"
+msgstr "n'a pas pu lire le fichier de contrôle : %m"
-#: access/transam/xlog.c:4302 access/transam/xlog.c:4311 access/transam/xlog.c:4335 access/transam/xlog.c:4342 access/transam/xlog.c:4349 access/transam/xlog.c:4354 access/transam/xlog.c:4361 access/transam/xlog.c:4368 access/transam/xlog.c:4375 access/transam/xlog.c:4382 access/transam/xlog.c:4389 access/transam/xlog.c:4396 access/transam/xlog.c:4403 access/transam/xlog.c:4412 access/transam/xlog.c:4419 access/transam/xlog.c:4428
-#: access/transam/xlog.c:4435 access/transam/xlog.c:4444 access/transam/xlog.c:4451 utils/init/miscinit.c:1380
+#: access/transam/xlog.c:4329 access/transam/xlog.c:4338 access/transam/xlog.c:4362 access/transam/xlog.c:4369 access/transam/xlog.c:4376 access/transam/xlog.c:4381 access/transam/xlog.c:4388 access/transam/xlog.c:4395 access/transam/xlog.c:4402 access/transam/xlog.c:4409 access/transam/xlog.c:4416 access/transam/xlog.c:4423 access/transam/xlog.c:4430 access/transam/xlog.c:4439 access/transam/xlog.c:4446 access/transam/xlog.c:4455
+#: access/transam/xlog.c:4462 access/transam/xlog.c:4471 access/transam/xlog.c:4478 utils/init/miscinit.c:1380
#, c-format
msgid "database files are incompatible with server"
-msgstr "les fichiers de la base de donn�es sont incompatibles avec le serveur"
+msgstr "les fichiers de la base de données sont incompatibles avec le serveur"
-#: access/transam/xlog.c:4303
+#: access/transam/xlog.c:4330
#, c-format
msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec un PG_CONTROL_VERSION �\n"
-"%d (0x%08x) alors que le serveur a �t� compil� avec un PG_CONTROL_VERSION �\n"
+"Le cluster de base de données a été initialisé avec un PG_CONTROL_VERSION à\n"
+"%d (0x%08x) alors que le serveur a été compilé avec un PG_CONTROL_VERSION à\n"
"%d (0x%08x)."
-#: access/transam/xlog.c:4307
+#: access/transam/xlog.c:4334
#, c-format
msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb."
msgstr ""
-"Ceci peut �tre un probl�me d'incoh�rence dans l'ordre des octets.\n"
+"Ceci peut être un problème d'incohérence dans l'ordre des octets.\n"
"Il se peut que vous ayez besoin d'initdb."
-#: access/transam/xlog.c:4312
+#: access/transam/xlog.c:4339
#, c-format
msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec un PG_CONTROL_VERSION �\n"
-"%d alors que le serveur a �t� compil� avec un PG_CONTROL_VERSION � %d."
+"Le cluster de base de données a été initialisé avec un PG_CONTROL_VERSION à\n"
+"%d alors que le serveur a été compilé avec un PG_CONTROL_VERSION à %d."
-#: access/transam/xlog.c:4315 access/transam/xlog.c:4339 access/transam/xlog.c:4346 access/transam/xlog.c:4351
+#: access/transam/xlog.c:4342 access/transam/xlog.c:4366 access/transam/xlog.c:4373 access/transam/xlog.c:4378
#, c-format
msgid "It looks like you need to initdb."
msgstr "Il semble que vous avez besoin d'initdb."
-#: access/transam/xlog.c:4326
+#: access/transam/xlog.c:4353
#, c-format
msgid "incorrect checksum in control file"
-msgstr "somme de contr�le incorrecte dans le fichier de contr�le"
+msgstr "somme de contrôle incorrecte dans le fichier de contrôle"
-#: access/transam/xlog.c:4336
+#: access/transam/xlog.c:4363
#, c-format
msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec un CATALOG_VERSION_NO �\n"
-"%d alors que le serveur a �t� compil� avec un CATALOG_VERSION_NO � %d."
+"Le cluster de base de données a été initialisé avec un CATALOG_VERSION_NO à\n"
+"%d alors que le serveur a été compilé avec un CATALOG_VERSION_NO à %d."
-#: access/transam/xlog.c:4343
+#: access/transam/xlog.c:4370
#, c-format
msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d."
msgstr ""
-"Le cluster de bases de donn�es a �t� initialis� avec un MAXALIGN � %d alors\n"
-"que le serveur a �t� compil� avec un MAXALIGN � %d."
+"Le cluster de bases de données a été initialisé avec un MAXALIGN à %d alors\n"
+"que le serveur a été compilé avec un MAXALIGN à %d."
-#: access/transam/xlog.c:4350
+#: access/transam/xlog.c:4377
#, c-format
msgid "The database cluster appears to use a different floating-point number format than the server executable."
msgstr ""
-"Le cluster de bases de donn�es semble utiliser un format diff�rent pour les\n"
-"nombres � virgule flottante de celui de l'ex�cutable serveur."
+"Le cluster de bases de données semble utiliser un format différent pour les\n"
+"nombres à virgule flottante de celui de l'exécutable serveur."
-#: access/transam/xlog.c:4355
+#: access/transam/xlog.c:4382
#, c-format
msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec un BLCKSZ � %d alors que\n"
-"le serveur a �t� compil� avec un BLCKSZ � %d."
+"Le cluster de base de données a été initialisé avec un BLCKSZ à %d alors que\n"
+"le serveur a été compilé avec un BLCKSZ à %d."
-#: access/transam/xlog.c:4358 access/transam/xlog.c:4365 access/transam/xlog.c:4372 access/transam/xlog.c:4379 access/transam/xlog.c:4386 access/transam/xlog.c:4393 access/transam/xlog.c:4400 access/transam/xlog.c:4407 access/transam/xlog.c:4415 access/transam/xlog.c:4422 access/transam/xlog.c:4431 access/transam/xlog.c:4438 access/transam/xlog.c:4447 access/transam/xlog.c:4454
+#: access/transam/xlog.c:4385 access/transam/xlog.c:4392 access/transam/xlog.c:4399 access/transam/xlog.c:4406 access/transam/xlog.c:4413 access/transam/xlog.c:4420 access/transam/xlog.c:4427 access/transam/xlog.c:4434 access/transam/xlog.c:4442 access/transam/xlog.c:4449 access/transam/xlog.c:4458 access/transam/xlog.c:4465 access/transam/xlog.c:4474 access/transam/xlog.c:4481
#, c-format
msgid "It looks like you need to recompile or initdb."
msgstr "Il semble que vous avez besoin de recompiler ou de relancer initdb."
-#: access/transam/xlog.c:4362
+#: access/transam/xlog.c:4389
#, c-format
msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d."
msgstr ""
-"Le cluster de bases de donn�es a �t� initialis� avec un RELSEG_SIZE � %d\n"
-"alors que le serveur a �t� compil� avec un RELSEG_SIZE � %d."
+"Le cluster de bases de données a été initialisé avec un RELSEG_SIZE à %d\n"
+"alors que le serveur a été compilé avec un RELSEG_SIZE à %d."
-#: access/transam/xlog.c:4369
+#: access/transam/xlog.c:4396
#, c-format
msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec un XLOG_BLCKSZ � %d\n"
-"alors que le serveur a �t� compil� avec un XLOG_BLCKSZ � %d."
+"Le cluster de base de données a été initialisé avec un XLOG_BLCKSZ à %d\n"
+"alors que le serveur a été compilé avec un XLOG_BLCKSZ à %d."
-#: access/transam/xlog.c:4376
+#: access/transam/xlog.c:4403
#, c-format
msgid "The database cluster was initialized with XLOG_SEG_SIZE %d, but the server was compiled with XLOG_SEG_SIZE %d."
msgstr ""
-"Le cluster de bases de donn�es a �t� initialis� avec un XLOG_SEG_SIZE � %d\n"
-"alors que le serveur a �t� compil� avec un XLOG_SEG_SIZE � %d."
+"Le cluster de bases de données a été initialisé avec un XLOG_SEG_SIZE à %d\n"
+"alors que le serveur a été compilé avec un XLOG_SEG_SIZE à %d."
-#: access/transam/xlog.c:4383
+#: access/transam/xlog.c:4410
#, c-format
msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d."
msgstr ""
-"Le cluster de bases de donn�es a �t� initialis� avec un NAMEDATALEN � %d\n"
-"alors que le serveur a �t� compil� avec un NAMEDATALEN � %d."
+"Le cluster de bases de données a été initialisé avec un NAMEDATALEN à %d\n"
+"alors que le serveur a été compilé avec un NAMEDATALEN à %d."
-#: access/transam/xlog.c:4390
+#: access/transam/xlog.c:4417
#, c-format
msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d."
msgstr ""
-"Le groupe de bases de donn�es a �t� initialis� avec un INDEX_MAX_KEYS � %d\n"
-"alors que le serveur a �t� compil� avec un INDEX_MAX_KEYS � %d."
+"Le groupe de bases de données a été initialisé avec un INDEX_MAX_KEYS à %d\n"
+"alors que le serveur a été compilé avec un INDEX_MAX_KEYS à %d."
-#: access/transam/xlog.c:4397
+#: access/transam/xlog.c:4424
#, c-format
msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d."
msgstr ""
-"Le cluster de bases de donn�es a �t� initialis� avec un TOAST_MAX_CHUNK_SIZE\n"
-"� %d alors que le serveur a �t� compil� avec un TOAST_MAX_CHUNK_SIZE � %d."
+"Le cluster de bases de données a été initialisé avec un TOAST_MAX_CHUNK_SIZE\n"
+"à %d alors que le serveur a été compilé avec un TOAST_MAX_CHUNK_SIZE à %d."
-#: access/transam/xlog.c:4404
+#: access/transam/xlog.c:4431
#, c-format
msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec un LOBLKSIZE � %d alors que\n"
-"le serveur a �t� compil� avec un LOBLKSIZE � %d."
+"Le cluster de base de données a été initialisé avec un LOBLKSIZE à %d alors que\n"
+"le serveur a été compilé avec un LOBLKSIZE à %d."
-#: access/transam/xlog.c:4413
+#: access/transam/xlog.c:4440
#, c-format
msgid "The database cluster was initialized without HAVE_INT64_TIMESTAMP but the server was compiled with HAVE_INT64_TIMESTAMP."
-msgstr "Le cluster de bases de donn�es a �t� initialis� sans HAVE_INT64_TIMESTAMPalors que le serveur a �t� compil� avec."
+msgstr "Le cluster de bases de données a été initialisé sans HAVE_INT64_TIMESTAMPalors que le serveur a été compilé avec."
-#: access/transam/xlog.c:4420
+#: access/transam/xlog.c:4447
#, c-format
msgid "The database cluster was initialized with HAVE_INT64_TIMESTAMP but the server was compiled without HAVE_INT64_TIMESTAMP."
msgstr ""
-"Le cluster de bases de donn�es a �t� initialis� avec HAVE_INT64_TIMESTAMP\n"
-"alors que le serveur a �t� compil� sans."
+"Le cluster de bases de données a été initialisé avec HAVE_INT64_TIMESTAMP\n"
+"alors que le serveur a été compilé sans."
-#: access/transam/xlog.c:4429
+#: access/transam/xlog.c:4456
#, c-format
msgid "The database cluster was initialized without USE_FLOAT4_BYVAL but the server was compiled with USE_FLOAT4_BYVAL."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� sans USE_FLOAT4_BYVAL\n"
-"alors que le serveur a �t� compil� avec USE_FLOAT4_BYVAL."
+"Le cluster de base de données a été initialisé sans USE_FLOAT4_BYVAL\n"
+"alors que le serveur a été compilé avec USE_FLOAT4_BYVAL."
-#: access/transam/xlog.c:4436
+#: access/transam/xlog.c:4463
#, c-format
msgid "The database cluster was initialized with USE_FLOAT4_BYVAL but the server was compiled without USE_FLOAT4_BYVAL."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec USE_FLOAT4_BYVAL\n"
-"alors que le serveur a �t� compil� sans USE_FLOAT4_BYVAL."
+"Le cluster de base de données a été initialisé avec USE_FLOAT4_BYVAL\n"
+"alors que le serveur a été compilé sans USE_FLOAT4_BYVAL."
-#: access/transam/xlog.c:4445
+#: access/transam/xlog.c:4472
#, c-format
msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� sans USE_FLOAT8_BYVAL\n"
-"alors que le serveur a �t� compil� avec USE_FLOAT8_BYVAL."
+"Le cluster de base de données a été initialisé sans USE_FLOAT8_BYVAL\n"
+"alors que le serveur a été compilé avec USE_FLOAT8_BYVAL."
-#: access/transam/xlog.c:4452
+#: access/transam/xlog.c:4479
#, c-format
msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL."
msgstr ""
-"Le cluster de base de donn�es a �t� initialis� avec USE_FLOAT8_BYVAL\n"
-"alors que le serveur a �t� compil� sans USE_FLOAT8_BYVAL."
+"Le cluster de base de données a été initialisé avec USE_FLOAT8_BYVAL\n"
+"alors que le serveur a été compilé sans USE_FLOAT8_BYVAL."
-#: access/transam/xlog.c:4875
+#: access/transam/xlog.c:4900
#, c-format
msgid "could not write bootstrap transaction log file: %m"
-msgstr "n'a pas pu �crire le � bootstrap � du journal des transactions : %m"
+msgstr "n'a pas pu écrire le « bootstrap » du journal des transactions : %m"
-#: access/transam/xlog.c:4881
+#: access/transam/xlog.c:4906
#, c-format
msgid "could not fsync bootstrap transaction log file: %m"
msgstr ""
-"n'a pas pu synchroniser sur disque (fsync) le � bootstrap � du journal des\n"
+"n'a pas pu synchroniser sur disque (fsync) le « bootstrap » du journal des\n"
"transactions : %m"
-#: access/transam/xlog.c:4886
+#: access/transam/xlog.c:4911
#, c-format
msgid "could not close bootstrap transaction log file: %m"
-msgstr "n'a pas pu fermer le � bootstrap � du journal des transactions : %m"
+msgstr "n'a pas pu fermer le « bootstrap » du journal des transactions : %m"
-#: access/transam/xlog.c:4961
+#: access/transam/xlog.c:4986
#, c-format
msgid "could not open recovery command file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier de restauration � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier de restauration « %s » : %m"
-#: access/transam/xlog.c:5007 access/transam/xlog.c:5090
+#: access/transam/xlog.c:5032 access/transam/xlog.c:5117
#, c-format
msgid "invalid value for recovery parameter \"%s\": \"%s\""
-msgstr "valeur invalide pour le param�tre de restauration � %s � : � %s �"
+msgstr "valeur invalide pour le paramètre de restauration « %s » : « %s »"
-#: access/transam/xlog.c:5010
+#: access/transam/xlog.c:5035
#, c-format
msgid "Valid values are \"pause\", \"promote\", and \"shutdown\"."
-msgstr "Les valeurs valides sont � pause �, � promote � et � shutdown �."
+msgstr "Les valeurs valides sont « pause », « promote » et « shutdown »."
-#: access/transam/xlog.c:5029
+#: access/transam/xlog.c:5055
#, c-format
msgid "recovery_target_timeline is not a valid number: \"%s\""
-msgstr "recovery_target_timeline n'est pas un nombre valide : � %s �"
+msgstr "recovery_target_timeline n'est pas un nombre valide : « %s »"
-#: access/transam/xlog.c:5045
+#: access/transam/xlog.c:5072
#, c-format
msgid "recovery_target_xid is not a valid number: \"%s\""
-msgstr "recovery_target_xid n'est pas un nombre valide : � %s �"
+msgstr "recovery_target_xid n'est pas un nombre valide : « %s »"
-#: access/transam/xlog.c:5076
+#: access/transam/xlog.c:5103
#, c-format
msgid "recovery_target_name is too long (maximum %d characters)"
-msgstr "recovery_target_name est trop long (%d caract�res maximum)"
+msgstr "recovery_target_name est trop long (%d caractères maximum)"
-#: access/transam/xlog.c:5093
+#: access/transam/xlog.c:5120
#, c-format
msgid "The only allowed value is \"immediate\"."
-msgstr "La seule valeur autoris�e est � immediate �."
+msgstr "La seule valeur autorisée est « immediate »."
-#: access/transam/xlog.c:5106 access/transam/xlog.c:5117 commands/extension.c:533 commands/extension.c:541 utils/misc/guc.c:5637
+#: access/transam/xlog.c:5133 access/transam/xlog.c:5144 commands/extension.c:534 commands/extension.c:542 utils/misc/guc.c:5640
#, c-format
msgid "parameter \"%s\" requires a Boolean value"
-msgstr "le param�tre � %s � requiert une valeur bool�enne"
+msgstr "le paramètre « %s » requiert une valeur booléenne"
-#: access/transam/xlog.c:5152
+#: access/transam/xlog.c:5179
#, c-format
msgid "parameter \"%s\" requires a temporal value"
-msgstr "le param�tre � %s � requiert une valeur temporelle"
+msgstr "le paramètre « %s » requiert une valeur temporelle"
-#: access/transam/xlog.c:5154 catalog/dependency.c:991 catalog/dependency.c:992 catalog/dependency.c:998 catalog/dependency.c:999 catalog/dependency.c:1010 catalog/dependency.c:1011 catalog/objectaddress.c:1100 commands/tablecmds.c:795 commands/tablecmds.c:9445 commands/user.c:1045 commands/view.c:482 libpq/auth.c:304 replication/syncrep.c:926 storage/lmgr/deadlock.c:1139 storage/lmgr/proc.c:1276 utils/adt/acl.c:5281 utils/misc/guc.c:5659
-#: utils/misc/guc.c:5752 utils/misc/guc.c:9686 utils/misc/guc.c:9720 utils/misc/guc.c:9754 utils/misc/guc.c:9788 utils/misc/guc.c:9823
+#: access/transam/xlog.c:5181 catalog/dependency.c:990 catalog/dependency.c:991 catalog/dependency.c:997 catalog/dependency.c:998 catalog/dependency.c:1009 catalog/dependency.c:1010 catalog/objectaddress.c:1100 commands/tablecmds.c:796 commands/tablecmds.c:9542 commands/user.c:1045 commands/view.c:499 libpq/auth.c:307 replication/syncrep.c:919 storage/lmgr/deadlock.c:1139 storage/lmgr/proc.c:1278 utils/adt/acl.c:5281 utils/misc/guc.c:5662
+#: utils/misc/guc.c:5755 utils/misc/guc.c:9708 utils/misc/guc.c:9742 utils/misc/guc.c:9776 utils/misc/guc.c:9810 utils/misc/guc.c:9845
#, c-format
msgid "%s"
msgstr "%s"
-#: access/transam/xlog.c:5160
+#: access/transam/xlog.c:5188
#, c-format
msgid "unrecognized recovery parameter \"%s\""
-msgstr "param�tre de restauration � %s � non reconnu"
+msgstr "paramètre de restauration « %s » non reconnu"
-#: access/transam/xlog.c:5171
+#: access/transam/xlog.c:5199
#, c-format
msgid "recovery command file \"%s\" specified neither primary_conninfo nor restore_command"
-msgstr "le fichier de restauration � %s � n'a sp�cifi� ni primary_conninfo ni restore_command"
+msgstr "le fichier de restauration « %s » n'a spécifié ni primary_conninfo ni restore_command"
-#: access/transam/xlog.c:5173
+#: access/transam/xlog.c:5201
#, c-format
msgid "The database server will regularly poll the pg_xlog subdirectory to check for files placed there."
msgstr ""
-"Le serveur de la base de donn�es va r�guli�rement interroger le sous-r�pertoire\n"
-"pg_xlog pour v�rifier les fichiers plac�s ici."
+"Le serveur de la base de données va régulièrement interroger le sous-répertoire\n"
+"pg_xlog pour vérifier les fichiers placés ici."
-#: access/transam/xlog.c:5179
+#: access/transam/xlog.c:5208
#, c-format
msgid "recovery command file \"%s\" must specify restore_command when standby mode is not enabled"
msgstr ""
-"le fichier de restauration � %s � doit sp�cifier restore_command quand le mode\n"
-"de restauration n'est pas activ�"
+"le fichier de restauration « %s » doit spécifier restore_command quand le mode\n"
+"de restauration n'est pas activé"
-#: access/transam/xlog.c:5209
+#: access/transam/xlog.c:5229
+#, c-format
+msgid "standby mode is not supported by single-user servers"
+msgstr "le mode de restauration n'est pas supporté pour les serveurs mono-utilisateur"
+
+#: access/transam/xlog.c:5248
#, c-format
msgid "recovery target timeline %u does not exist"
msgstr "le timeline cible, %u, de la restauration n'existe pas"
-#: access/transam/xlog.c:5330
+#: access/transam/xlog.c:5369
#, c-format
msgid "archive recovery complete"
-msgstr "restauration termin�e de l'archive"
+msgstr "restauration terminée de l'archive"
-#: access/transam/xlog.c:5389 access/transam/xlog.c:5617
+#: access/transam/xlog.c:5428 access/transam/xlog.c:5656
#, c-format
msgid "recovery stopping after reaching consistency"
-msgstr "arr�t de la restauration apr�s avoir atteint le point de coh�rence"
+msgstr "arrêt de la restauration après avoir atteint le point de cohérence"
-#: access/transam/xlog.c:5477
+#: access/transam/xlog.c:5516
#, c-format
msgid "recovery stopping before commit of transaction %u, time %s"
-msgstr "arr�t de la restauration avant validation de la transaction %u, %s"
+msgstr "arrêt de la restauration avant validation de la transaction %u, %s"
-#: access/transam/xlog.c:5484
+#: access/transam/xlog.c:5523
#, c-format
msgid "recovery stopping before abort of transaction %u, time %s"
-msgstr "arr�t de la restauration avant annulation de la transaction %u, %s"
+msgstr "arrêt de la restauration avant annulation de la transaction %u, %s"
-#: access/transam/xlog.c:5529
+#: access/transam/xlog.c:5568
#, c-format
msgid "recovery stopping at restore point \"%s\", time %s"
-msgstr "restauration en arr�t au point de restauration � %s �, heure %s"
+msgstr "restauration en arrêt au point de restauration « %s », heure %s"
-#: access/transam/xlog.c:5597
+#: access/transam/xlog.c:5636
#, c-format
msgid "recovery stopping after commit of transaction %u, time %s"
-msgstr "arr�t de la restauration apr�s validation de la transaction %u, %s"
+msgstr "arrêt de la restauration après validation de la transaction %u, %s"
-#: access/transam/xlog.c:5605
+#: access/transam/xlog.c:5644
#, c-format
msgid "recovery stopping after abort of transaction %u, time %s"
-msgstr "arr�t de la restauration apr�s annulation de la transaction %u, %s"
+msgstr "arrêt de la restauration après annulation de la transaction %u, %s"
-#: access/transam/xlog.c:5644
+#: access/transam/xlog.c:5683
#, c-format
msgid "recovery has paused"
msgstr "restauration en pause"
-#: access/transam/xlog.c:5645
+#: access/transam/xlog.c:5684
#, c-format
msgid "Execute pg_xlog_replay_resume() to continue."
-msgstr "Ex�cuter pg_xlog_replay_resume() pour continuer."
+msgstr "Exécuter pg_xlog_replay_resume() pour continuer."
-#: access/transam/xlog.c:5852
+#: access/transam/xlog.c:5891
#, c-format
msgid "hot standby is not possible because %s = %d is a lower setting than on the master server (its value was %d)"
msgstr ""
"les connexions en restauration ne sont pas possibles car %s = %d est un\n"
-"param�trage plus bas que celui du serveur ma�tre des journaux de transactions\n"
-"(la valeur �tait %d)"
+"paramètrage plus bas que celui du serveur maître des journaux de transactions\n"
+"(la valeur était %d)"
-#: access/transam/xlog.c:5878
+#: access/transam/xlog.c:5917
#, c-format
msgid "WAL was generated with wal_level=minimal, data may be missing"
msgstr ""
-"le journal de transactions a �t� g�n�r� avec le param�tre wal_level configur�\n"
-"� � minimal �, des donn�es pourraient manquer"
+"le journal de transactions a été généré avec le paramètre wal_level configuré\n"
+"à « minimal », des données pourraient manquer"
-#: access/transam/xlog.c:5879
+#: access/transam/xlog.c:5918
#, c-format
msgid "This happens if you temporarily set wal_level=minimal without taking a new base backup."
msgstr ""
-"Ceci peut arriver si vous configurez temporairement wal_level � minimal sans avoir\n"
+"Ceci peut arriver si vous configurez temporairement wal_level à minimal sans avoir\n"
"pris une nouvelle sauvegarde de base."
-#: access/transam/xlog.c:5890
-#, fuzzy, c-format
-#| msgid "hot standby is not possible because wal_level was not set to \"hot_standby\" or higher on the master server"
+#: access/transam/xlog.c:5929
+#, c-format
msgid "hot standby is not possible because wal_level was not set to \"replica\" or higher on the master server"
msgstr ""
-"les connexions en lecture seule ne sont pas possibles parce que le param�tre\n"
-"wal_level n'a pas �t� configur� � � hot_standby � ou � une valeur plus importante\n"
-"sur le serveur ma�tre"
+"les connexions en lecture seules ne sont pas possibles parce que le paramètre wal_level\n"
+"n'a pas été positionné à « replica » ou plus sur le serveur maître"
-#: access/transam/xlog.c:5891
-#, fuzzy, c-format
-#| msgid "Either set wal_level to \"hot_standby\" on the master, or turn off hot_standby here."
+#: access/transam/xlog.c:5930
+#, c-format
msgid "Either set wal_level to \"replica\" on the master, or turn off hot_standby here."
msgstr ""
-"Soit vous initialisez wal_level � � hot_standby � sur le ma�tre, soit vous\n"
-"d�sactivez hot_standby ici."
+"Vous devez soit positionner le paramètre wal_level à « replica » sur le maître,\n"
+"soit désactiver le hot_standby ici."
-#: access/transam/xlog.c:5948
+#: access/transam/xlog.c:5987
#, c-format
msgid "control file contains invalid data"
-msgstr "le fichier de contr�le contient des donn�es invalides"
+msgstr "le fichier de contrôle contient des données invalides"
-#: access/transam/xlog.c:5954
+#: access/transam/xlog.c:5993
#, c-format
msgid "database system was shut down at %s"
-msgstr "le syst�me de bases de donn�es a �t� arr�t� � %s"
+msgstr "le système de bases de données a été arrêté à %s"
-#: access/transam/xlog.c:5959
+#: access/transam/xlog.c:5998
#, c-format
msgid "database system was shut down in recovery at %s"
-msgstr "le syst�me de bases de donn�es a �t� arr�t� pendant la restauration � %s"
+msgstr "le système de bases de données a été arrêté pendant la restauration à %s"
-#: access/transam/xlog.c:5963
+#: access/transam/xlog.c:6002
#, c-format
msgid "database system shutdown was interrupted; last known up at %s"
-msgstr "le syst�me de bases de donn�es a �t� interrompu ; dernier lancement connu � %s"
+msgstr "le système de bases de données a été interrompu ; dernier lancement connu à %s"
-#: access/transam/xlog.c:5967
+#: access/transam/xlog.c:6006
#, c-format
msgid "database system was interrupted while in recovery at %s"
-msgstr "le syst�me de bases de donn�es a �t� interrompu lors d'une restauration � %s"
+msgstr "le système de bases de données a été interrompu lors d'une restauration à %s"
-#: access/transam/xlog.c:5969
+#: access/transam/xlog.c:6008
#, c-format
msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery."
msgstr ""
-"Ceci signifie probablement que des donn�es ont �t� corrompues et que vous\n"
-"devrez utiliser la derni�re sauvegarde pour la restauration."
+"Ceci signifie probablement que des données ont été corrompues et que vous\n"
+"devrez utiliser la dernière sauvegarde pour la restauration."
-#: access/transam/xlog.c:5973
+#: access/transam/xlog.c:6012
#, c-format
msgid "database system was interrupted while in recovery at log time %s"
msgstr ""
-"le syst�me de bases de donn�es a �t� interrompu lors d'une r�cup�ration � %s\n"
+"le système de bases de données a été interrompu lors d'une récupération à %s\n"
"(moment de la journalisation)"
-#: access/transam/xlog.c:5975
+#: access/transam/xlog.c:6014
#, c-format
msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target."
msgstr ""
-"Si c'est arriv� plus d'une fois, des donn�es ont pu �tre corrompues et vous\n"
-"pourriez avoir besoin de choisir une cible de r�cup�ration ant�rieure."
+"Si c'est arrivé plus d'une fois, des données ont pu être corrompues et vous\n"
+"pourriez avoir besoin de choisir une cible de récupération antérieure."
-#: access/transam/xlog.c:5979
+#: access/transam/xlog.c:6018
#, c-format
msgid "database system was interrupted; last known up at %s"
-msgstr "le syst�me de bases de donn�es a �t� interrompu ; dernier lancement connu � %s"
+msgstr "le système de bases de données a été interrompu ; dernier lancement connu à %s"
-#: access/transam/xlog.c:6035
+#: access/transam/xlog.c:6074
#, c-format
msgid "entering standby mode"
msgstr "entre en mode standby"
-#: access/transam/xlog.c:6038
+#: access/transam/xlog.c:6077
#, c-format
msgid "starting point-in-time recovery to XID %u"
-msgstr "d�but de la restauration de l'archive au XID %u"
+msgstr "début de la restauration de l'archive au XID %u"
-#: access/transam/xlog.c:6042
+#: access/transam/xlog.c:6081
#, c-format
msgid "starting point-in-time recovery to %s"
-msgstr "d�but de la restauration de l'archive � %s"
+msgstr "début de la restauration de l'archive à %s"
-#: access/transam/xlog.c:6046
+#: access/transam/xlog.c:6085
#, c-format
msgid "starting point-in-time recovery to \"%s\""
-msgstr "d�but de la restauration PITR � � %s �"
+msgstr "début de la restauration PITR à « %s »"
-#: access/transam/xlog.c:6050
+#: access/transam/xlog.c:6089
#, c-format
msgid "starting point-in-time recovery to earliest consistent point"
-msgstr "d�but de la restauration de l'archive jusqu'au point de coh�rence le plus proche"
+msgstr "début de la restauration de l'archive jusqu'au point de cohérence le plus proche"
-#: access/transam/xlog.c:6053
+#: access/transam/xlog.c:6092
#, c-format
msgid "starting archive recovery"
-msgstr "d�but de la restauration de l'archive"
+msgstr "début de la restauration de l'archive"
-#: access/transam/xlog.c:6097 access/transam/xlog.c:6225
+#: access/transam/xlog.c:6136 access/transam/xlog.c:6264
#, c-format
msgid "checkpoint record is at %X/%X"
-msgstr "l'enregistrement du point de v�rification est � %X/%X"
+msgstr "l'enregistrement du point de vérification est à %X/%X"
-#: access/transam/xlog.c:6111
+#: access/transam/xlog.c:6150
#, c-format
msgid "could not find redo location referenced by checkpoint record"
-msgstr "n'a pas pu localiser l'enregistrement redo r�f�renc� par le point de v�rification"
+msgstr "n'a pas pu localiser l'enregistrement redo référencé par le point de vérification"
-#: access/transam/xlog.c:6112 access/transam/xlog.c:6119
+#: access/transam/xlog.c:6151 access/transam/xlog.c:6158
#, c-format
msgid "If you are not restoring from a backup, try removing the file \"%s/backup_label\"."
msgstr ""
"Si vous n'avez pas pu restaurer une sauvegarde, essayez de supprimer le\n"
-"fichier � %s/backup_label �."
+"fichier « %s/backup_label »."
-#: access/transam/xlog.c:6118
+#: access/transam/xlog.c:6157
#, c-format
msgid "could not locate required checkpoint record"
-msgstr "n'a pas pu localiser l'enregistrement d'un point de v�rification requis"
+msgstr "n'a pas pu localiser l'enregistrement d'un point de vérification requis"
-#: access/transam/xlog.c:6144 commands/tablespace.c:641
+#: access/transam/xlog.c:6183 commands/tablespace.c:641
#, c-format
msgid "could not create symbolic link \"%s\": %m"
-msgstr "n'a pas pu cr�er le lien symbolique � %s � : %m"
+msgstr "n'a pas pu créer le lien symbolique « %s » : %m"
-#: access/transam/xlog.c:6176 access/transam/xlog.c:6182
+#: access/transam/xlog.c:6215 access/transam/xlog.c:6221
#, c-format
msgid "ignoring file \"%s\" because no file \"%s\" exists"
-msgstr "ignore le fichier � %s � car le fichier � %s � n'existe pas"
+msgstr "ignore le fichier « %s » car le fichier « %s » n'existe pas"
-#: access/transam/xlog.c:6178 access/transam/xlog.c:10918
+#: access/transam/xlog.c:6217 access/transam/xlog.c:11032
#, c-format
msgid "File \"%s\" was renamed to \"%s\"."
-msgstr "Le fichier � %s � a �t� renomm� en � %s �."
+msgstr "Le fichier « %s » a été renommé en « %s »."
-#: access/transam/xlog.c:6184
+#: access/transam/xlog.c:6223
#, c-format
msgid "Could not rename file \"%s\" to \"%s\": %m."
-msgstr "N'a pas pu renommer le fichier � %s � en � %s � : %m"
+msgstr "N'a pas pu renommer le fichier « %s » en « %s » : %m"
-#: access/transam/xlog.c:6235 access/transam/xlog.c:6250
+#: access/transam/xlog.c:6274 access/transam/xlog.c:6289
#, c-format
msgid "could not locate a valid checkpoint record"
-msgstr "n'a pas pu localiser un enregistrement d'un point de v�rification valide"
+msgstr "n'a pas pu localiser un enregistrement d'un point de vérification valide"
-#: access/transam/xlog.c:6244
+#: access/transam/xlog.c:6283
#, c-format
msgid "using previous checkpoint record at %X/%X"
-msgstr "utilisation du pr�c�dent enregistrement d'un point de v�rification � %X/%X"
+msgstr "utilisation du précédent enregistrement d'un point de vérification à %X/%X"
-#: access/transam/xlog.c:6288
+#: access/transam/xlog.c:6327
#, c-format
msgid "requested timeline %u is not a child of this server's history"
msgstr "la timeline requise %u n'est pas un fils de l'historique de ce serveur"
-#: access/transam/xlog.c:6290
+#: access/transam/xlog.c:6329
#, c-format
msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X."
-msgstr "Le dernier checkpoint est � %X/%X sur la timeline %u, mais dans l'historique de la timeline demand�e, le serveur est sorti de cette timeline � %X/%X."
+msgstr "Le dernier checkpoint est à %X/%X sur la timeline %u, mais dans l'historique de la timeline demandée, le serveur est sorti de cette timeline à %X/%X."
-#: access/transam/xlog.c:6306
+#: access/transam/xlog.c:6345
#, c-format
msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u"
msgstr "la timeline requise, %u, ne contient pas le point de restauration minimum (%X/%X) sur la timeline %u"
-#: access/transam/xlog.c:6337
+#: access/transam/xlog.c:6376
#, c-format
msgid "invalid next transaction ID"
msgstr "prochain ID de transaction invalide"
-#: access/transam/xlog.c:6420
+#: access/transam/xlog.c:6459
#, c-format
msgid "invalid redo in checkpoint record"
-msgstr "r�-ex�cution invalide dans l'enregistrement du point de v�rification"
+msgstr "ré-exécution invalide dans l'enregistrement du point de vérification"
-#: access/transam/xlog.c:6431
+#: access/transam/xlog.c:6470
#, c-format
msgid "invalid redo record in shutdown checkpoint"
-msgstr "enregistrement de r�-ex�cution invalide dans le point de v�rification d'arr�t"
+msgstr "enregistrement de ré-exécution invalide dans le point de vérification d'arrêt"
-#: access/transam/xlog.c:6459
+#: access/transam/xlog.c:6498
#, c-format
msgid "database system was not properly shut down; automatic recovery in progress"
msgstr ""
-"le syst�me de bases de donn�es n'a pas �t� arr�t� proprement ; restauration\n"
+"le système de bases de données n'a pas été arrêté proprement ; restauration\n"
"automatique en cours"
-#: access/transam/xlog.c:6463
+#: access/transam/xlog.c:6502
#, c-format
msgid "crash recovery starts in timeline %u and has target timeline %u"
-msgstr "la restauration apr�s crash commence avec la timeline %u et a la timeline %u en cible"
+msgstr "la restauration après crash commence avec la timeline %u et a la timeline %u en cible"
-#: access/transam/xlog.c:6507
+#: access/transam/xlog.c:6546
#, c-format
msgid "backup_label contains data inconsistent with control file"
-msgstr "backup_label contient des donn�es incoh�rentes avec le fichier de contr�le"
+msgstr "backup_label contient des données incohérentes avec le fichier de contrôle"
-#: access/transam/xlog.c:6508
+#: access/transam/xlog.c:6547
#, c-format
msgid "This means that the backup is corrupted and you will have to use another backup for recovery."
msgstr ""
-"Ceci signifie que la sauvegarde a �t� corrompue et que vous devrez utiliser\n"
-"la derni�re sauvegarde pour la restauration."
+"Ceci signifie que la sauvegarde a été corrompue et que vous devrez utiliser\n"
+"la dernière sauvegarde pour la restauration."
-#: access/transam/xlog.c:6582
+#: access/transam/xlog.c:6621
#, c-format
msgid "initializing for hot standby"
-msgstr "initialisation pour � Hot Standby �"
+msgstr "initialisation pour « Hot Standby »"
-#: access/transam/xlog.c:6714
+#: access/transam/xlog.c:6753
#, c-format
msgid "redo starts at %X/%X"
-msgstr "la r�-ex�cution commence � %X/%X"
+msgstr "la ré-exécution commence à %X/%X"
-#: access/transam/xlog.c:6939
+#: access/transam/xlog.c:6978
#, c-format
msgid "requested recovery stop point is before consistent recovery point"
msgstr ""
-"le point d'arr�t de la restauration demand�e se trouve avant le point\n"
-"coh�rent de restauration"
+"le point d'arrêt de la restauration demandée se trouve avant le point\n"
+"cohérent de restauration"
-#: access/transam/xlog.c:6977
+#: access/transam/xlog.c:7016
#, c-format
msgid "redo done at %X/%X"
-msgstr "r�-ex�cution faite � %X/%X"
+msgstr "ré-exécution faite à %X/%X"
-#: access/transam/xlog.c:6982 access/transam/xlog.c:8906
+#: access/transam/xlog.c:7021 access/transam/xlog.c:8969
#, c-format
msgid "last completed transaction was at log time %s"
-msgstr "la derni�re transaction a eu lieu � %s (moment de la journalisation)"
+msgstr "la dernière transaction a eu lieu à %s (moment de la journalisation)"
-#: access/transam/xlog.c:6991
+#: access/transam/xlog.c:7030
#, c-format
msgid "redo is not required"
-msgstr "la r�-ex�cution n'est pas n�cessaire"
+msgstr "la ré-exécution n'est pas nécessaire"
-#: access/transam/xlog.c:7066 access/transam/xlog.c:7070
+#: access/transam/xlog.c:7105 access/transam/xlog.c:7109
#, c-format
msgid "WAL ends before end of online backup"
msgstr "le journal de transactions se termine avant la fin de la sauvegarde de base"
-#: access/transam/xlog.c:7067
+#: access/transam/xlog.c:7106
#, c-format
msgid "All WAL generated while online backup was taken must be available at recovery."
msgstr ""
-"Tous les journaux de transactions g�n�r�s pendant la sauvegarde en ligne\n"
-"doivent �tre disponibles pour la restauration."
+"Tous les journaux de transactions générés pendant la sauvegarde en ligne\n"
+"doivent être disponibles pour la restauration."
-#: access/transam/xlog.c:7071
+#: access/transam/xlog.c:7110
#, c-format
msgid "Online backup started with pg_start_backup() must be ended with pg_stop_backup(), and all WAL up to that point must be available at recovery."
msgstr ""
-"Une sauvegarde en ligne commenc�e avec pg_start_backup() doit se terminer avec\n"
-"pg_stop_backup() et tous les journaux de transactions g�n�r�s entre les deux\n"
-"doivent �tre disponibles pour la restauration."
+"Une sauvegarde en ligne commencée avec pg_start_backup() doit se terminer avec\n"
+"pg_stop_backup() et tous les journaux de transactions générés entre les deux\n"
+"doivent être disponibles pour la restauration."
-#: access/transam/xlog.c:7074
+#: access/transam/xlog.c:7113
#, c-format
msgid "WAL ends before consistent recovery point"
-msgstr "Le journal de transaction se termine avant un point de restauration coh�rent"
+msgstr "Le journal de transaction se termine avant un point de restauration cohérent"
-#: access/transam/xlog.c:7101
+#: access/transam/xlog.c:7140
#, c-format
msgid "selected new timeline ID: %u"
-msgstr "identifiant d'un timeline nouvellement s�lectionn� : %u"
+msgstr "identifiant d'un timeline nouvellement sélectionné : %u"
-#: access/transam/xlog.c:7512
+#: access/transam/xlog.c:7551
#, c-format
msgid "consistent recovery state reached at %X/%X"
-msgstr "�tat de restauration coh�rent atteint � %X/%X"
+msgstr "état de restauration cohérent atteint à %X/%X"
-#: access/transam/xlog.c:7703
+#: access/transam/xlog.c:7742
#, c-format
msgid "invalid primary checkpoint link in control file"
-msgstr "lien du point de v�rification primaire invalide dans le fichier de contr�le"
+msgstr "lien du point de vérification primaire invalide dans le fichier de contrôle"
-#: access/transam/xlog.c:7707
+#: access/transam/xlog.c:7746
#, c-format
msgid "invalid secondary checkpoint link in control file"
-msgstr "lien du point de v�rification secondaire invalide dans le fichier de contr�le"
+msgstr "lien du point de vérification secondaire invalide dans le fichier de contrôle"
-#: access/transam/xlog.c:7711
+#: access/transam/xlog.c:7750
#, c-format
msgid "invalid checkpoint link in backup_label file"
-msgstr "lien du point de v�rification invalide dans le fichier backup_label"
+msgstr "lien du point de vérification invalide dans le fichier backup_label"
-#: access/transam/xlog.c:7728
+#: access/transam/xlog.c:7767
#, c-format
msgid "invalid primary checkpoint record"
-msgstr "enregistrement du point de v�rification primaire invalide"
+msgstr "enregistrement du point de vérification primaire invalide"
-#: access/transam/xlog.c:7732
+#: access/transam/xlog.c:7771
#, c-format
msgid "invalid secondary checkpoint record"
-msgstr "enregistrement du point de v�rification secondaire invalide"
+msgstr "enregistrement du point de vérification secondaire invalide"
-#: access/transam/xlog.c:7736
+#: access/transam/xlog.c:7775
#, c-format
msgid "invalid checkpoint record"
-msgstr "enregistrement du point de v�rification invalide"
+msgstr "enregistrement du point de vérification invalide"
-#: access/transam/xlog.c:7747
+#: access/transam/xlog.c:7786
#, c-format
msgid "invalid resource manager ID in primary checkpoint record"
-msgstr "identifiant du gestionnaire de ressource invalide dans l'enregistrement primaire du point de v�rification"
+msgstr "identifiant du gestionnaire de ressource invalide dans l'enregistrement primaire du point de vérification"
-#: access/transam/xlog.c:7751
+#: access/transam/xlog.c:7790
#, c-format
msgid "invalid resource manager ID in secondary checkpoint record"
-msgstr "identifiant du gestionnaire de ressource invalide dans l'enregistrement secondaire du point de v�rification"
+msgstr "identifiant du gestionnaire de ressource invalide dans l'enregistrement secondaire du point de vérification"
-#: access/transam/xlog.c:7755
+#: access/transam/xlog.c:7794
#, c-format
msgid "invalid resource manager ID in checkpoint record"
-msgstr "identifiant du gestionnaire de ressource invalide dans l'enregistrement du point de v�rification"
+msgstr "identifiant du gestionnaire de ressource invalide dans l'enregistrement du point de vérification"
-#: access/transam/xlog.c:7767
+#: access/transam/xlog.c:7806
#, c-format
msgid "invalid xl_info in primary checkpoint record"
-msgstr "xl_info invalide dans l'enregistrement du point de v�rification primaire"
+msgstr "xl_info invalide dans l'enregistrement du point de vérification primaire"
-#: access/transam/xlog.c:7771
+#: access/transam/xlog.c:7810
#, c-format
msgid "invalid xl_info in secondary checkpoint record"
-msgstr "xl_info invalide dans l'enregistrement du point de v�rification secondaire"
+msgstr "xl_info invalide dans l'enregistrement du point de vérification secondaire"
-#: access/transam/xlog.c:7775
+#: access/transam/xlog.c:7814
#, c-format
msgid "invalid xl_info in checkpoint record"
-msgstr "xl_info invalide dans l'enregistrement du point de v�rification"
+msgstr "xl_info invalide dans l'enregistrement du point de vérification"
-#: access/transam/xlog.c:7786
+#: access/transam/xlog.c:7825
#, c-format
msgid "invalid length of primary checkpoint record"
-msgstr "longueur invalide de l'enregistrement primaire du point de v�rification"
+msgstr "longueur invalide de l'enregistrement primaire du point de vérification"
-#: access/transam/xlog.c:7790
+#: access/transam/xlog.c:7829
#, c-format
msgid "invalid length of secondary checkpoint record"
-msgstr "longueur invalide de l'enregistrement secondaire du point de v�rification"
+msgstr "longueur invalide de l'enregistrement secondaire du point de vérification"
-#: access/transam/xlog.c:7794
+#: access/transam/xlog.c:7833
#, c-format
msgid "invalid length of checkpoint record"
-msgstr "longueur invalide de l'enregistrement du point de v�rification"
+msgstr "longueur invalide de l'enregistrement du point de vérification"
-#: access/transam/xlog.c:7962
+#: access/transam/xlog.c:8001
#, c-format
msgid "shutting down"
-msgstr "arr�t en cours"
+msgstr "arrêt en cours"
-#: access/transam/xlog.c:8475
+#: access/transam/xlog.c:8514
#, c-format
msgid "concurrent transaction log activity while database system is shutting down"
msgstr ""
-"activit� en cours du journal de transactions alors que le syst�me de bases\n"
-"de donn�es est en cours d'arr�t"
+"activité en cours du journal de transactions alors que le système de bases\n"
+"de données est en cours d'arrêt"
-#: access/transam/xlog.c:8726
+#: access/transam/xlog.c:8768
#, c-format
msgid "skipping restartpoint, recovery has already ended"
-msgstr "restartpoint ignor�, la r�cup�ration est d�j� termin�e"
+msgstr "restartpoint ignoré, la récupération est déjà terminée"
-#: access/transam/xlog.c:8749
+#: access/transam/xlog.c:8791
#, c-format
msgid "skipping restartpoint, already performed at %X/%X"
-msgstr "ignore le point de red�marrage, d�j� r�alis� � %X/%X"
+msgstr "ignore le point de redémarrage, déjà réalisé à %X/%X"
-#: access/transam/xlog.c:8904
+#: access/transam/xlog.c:8967
#, c-format
msgid "recovery restart point at %X/%X"
-msgstr "la r�-ex�cution en restauration commence � %X/%X"
+msgstr "la ré-exécution en restauration commence à %X/%X"
-#: access/transam/xlog.c:9037
+#: access/transam/xlog.c:9100
#, c-format
msgid "restore point \"%s\" created at %X/%X"
-msgstr "point de restauration � %s � cr�� � %X/%X"
+msgstr "point de restauration « %s » créé à %X/%X"
-#: access/transam/xlog.c:9167
+#: access/transam/xlog.c:9230
#, c-format
msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record"
-msgstr "identifiant de timeline pr�c�dent %u inattendu (identifiant de la timeline courante %u) dans l'enregistrement du point de v�rification"
+msgstr "identifiant de timeline précédent %u inattendu (identifiant de la timeline courante %u) dans l'enregistrement du point de vérification"
-#: access/transam/xlog.c:9176
+#: access/transam/xlog.c:9239
#, c-format
msgid "unexpected timeline ID %u (after %u) in checkpoint record"
msgstr ""
-"identifiant timeline %u inattendu (apr�s %u) dans l'enregistrement du point\n"
-"de v�rification"
+"identifiant timeline %u inattendu (après %u) dans l'enregistrement du point\n"
+"de vérification"
-#: access/transam/xlog.c:9192
+#: access/transam/xlog.c:9255
#, c-format
msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u"
msgstr "identifiant timeline %u inattendu dans l'enregistrement du checkpoint, avant d'atteindre le point de restauration minimum %X/%X sur la timeline %u"
-#: access/transam/xlog.c:9263
+#: access/transam/xlog.c:9326
#, c-format
msgid "online backup was canceled, recovery cannot continue"
-msgstr "la sauvegarde en ligne a �t� annul�e, la restauration ne peut pas continuer"
+msgstr "la sauvegarde en ligne a été annulée, la restauration ne peut pas continuer"
-#: access/transam/xlog.c:9319 access/transam/xlog.c:9366 access/transam/xlog.c:9389
+#: access/transam/xlog.c:9382 access/transam/xlog.c:9429 access/transam/xlog.c:9452
#, c-format
msgid "unexpected timeline ID %u (should be %u) in checkpoint record"
msgstr ""
-"identifiant timeline %u inattendu (devrait �tre %u) dans l'enregistrement du\n"
-"point de v�rification"
+"identifiant timeline %u inattendu (devrait être %u) dans l'enregistrement du\n"
+"point de vérification"
-#: access/transam/xlog.c:9664
+#: access/transam/xlog.c:9727
#, c-format
msgid "could not fsync log segment %s: %m"
msgstr "n'a pas pu synchroniser sur disque (fsync) le segment du journal des transactions %s : %m"
-#: access/transam/xlog.c:9688
+#: access/transam/xlog.c:9751
#, c-format
msgid "could not fsync log file %s: %m"
-msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier de transactions � %s � : %m"
+msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier de transactions « %s » : %m"
-#: access/transam/xlog.c:9696
+#: access/transam/xlog.c:9759
#, c-format
msgid "could not fsync write-through log file %s: %m"
msgstr "n'a pas pu synchroniser sur disque (fsync) le journal des transactions %s : %m"
-#: access/transam/xlog.c:9705
+#: access/transam/xlog.c:9768
#, c-format
msgid "could not fdatasync log file %s: %m"
msgstr "n'a pas pu synchroniser sur disque (fdatasync) le journal de transactions %s : %m"
-#: access/transam/xlog.c:9796 access/transam/xlog.c:10267 access/transam/xlogfuncs.c:295 access/transam/xlogfuncs.c:322 access/transam/xlogfuncs.c:361 access/transam/xlogfuncs.c:382 access/transam/xlogfuncs.c:403
+#: access/transam/xlog.c:9859 access/transam/xlog.c:10363 access/transam/xlogfuncs.c:294 access/transam/xlogfuncs.c:321 access/transam/xlogfuncs.c:360 access/transam/xlogfuncs.c:381 access/transam/xlogfuncs.c:402
#, c-format
msgid "WAL control functions cannot be executed during recovery."
msgstr ""
-"les fonctions de contr�le des journaux de transactions ne peuvent pas\n"
-"�tre ex�cut�es lors de la restauration."
+"les fonctions de contrôle des journaux de transactions ne peuvent pas\n"
+"être exécutées lors de la restauration."
-#: access/transam/xlog.c:9805 access/transam/xlog.c:10276
+#: access/transam/xlog.c:9868 access/transam/xlog.c:10372
#, c-format
msgid "WAL level not sufficient for making an online backup"
msgstr ""
-"Le niveau de journalisation (configur� par wal_level) n'est pas suffisant pour\n"
+"Le niveau de journalisation (configuré par wal_level) n'est pas suffisant pour\n"
"faire une sauvegarde en ligne."
-#: access/transam/xlog.c:9806 access/transam/xlog.c:10277 access/transam/xlogfuncs.c:328
-#, fuzzy, c-format
-#| msgid "wal_level must be set to \"archive\", \"hot_standby\", or \"logical\" at server start."
+#: access/transam/xlog.c:9869 access/transam/xlog.c:10373 access/transam/xlogfuncs.c:327
+#, c-format
msgid "wal_level must be set to \"replica\" or \"logical\" at server start."
msgstr ""
-"wal_level doit �tre configur� � � archive �, � hot_standby � ou � logical �\n"
-"au d�marrage du serveur."
+"wal_level doit être configuré à « replica » ou « logical »\n"
+"au démarrage du serveur."
-#: access/transam/xlog.c:9811
+#: access/transam/xlog.c:9874
#, c-format
msgid "backup label too long (max %d bytes)"
msgstr "label de sauvegarde trop long (%d octets maximum)"
-#: access/transam/xlog.c:9843 access/transam/xlog.c:10115 access/transam/xlog.c:10153
+#: access/transam/xlog.c:9911 access/transam/xlog.c:10183 access/transam/xlog.c:10221
#, c-format
msgid "a backup is already in progress"
-msgstr "une sauvegarde est d�j� en cours"
+msgstr "une sauvegarde est déjà en cours"
-#: access/transam/xlog.c:9844
+#: access/transam/xlog.c:9912
#, c-format
msgid "Run pg_stop_backup() and try again."
-msgstr "Ex�cutez pg_stop_backup() et tentez de nouveau."
+msgstr "Exécutez pg_stop_backup() et tentez de nouveau."
-#: access/transam/xlog.c:9939
+#: access/transam/xlog.c:10007
#, c-format
msgid "WAL generated with full_page_writes=off was replayed since last restartpoint"
-msgstr "Les journaux g�n�r�s avec full_page_writes=off ont �t� rejou�s depuis le dernier restartpoint."
+msgstr "Les journaux générés avec full_page_writes=off ont été rejoués depuis le dernier restartpoint."
-#: access/transam/xlog.c:9941 access/transam/xlog.c:10440
+#: access/transam/xlog.c:10009 access/transam/xlog.c:10554
#, c-format
msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable full_page_writes and run CHECKPOINT on the master, and then try an online backup again."
msgstr ""
-"Cela signifie que la sauvegarde en cours de r�alisation sur l'esclave est\n"
-"corrompue et ne doit pas �tre utilis�e. Activez full_page_writes et lancez\n"
-"CHECKPOINT sur le ma�tre, puis recommencez la sauvegarde."
+"Cela signifie que la sauvegarde en cours de réalisation sur l'esclave est\n"
+"corrompue et ne doit pas être utilisée. Activez full_page_writes et lancez\n"
+"CHECKPOINT sur le maître, puis recommencez la sauvegarde."
-#: access/transam/xlog.c:10008 replication/basebackup.c:1038 utils/adt/misc.c:498
+#: access/transam/xlog.c:10076 replication/basebackup.c:1026 utils/adt/misc.c:498
#, c-format
msgid "could not read symbolic link \"%s\": %m"
-msgstr "n'a pas pu lire le lien symbolique � %s � : %m"
+msgstr "n'a pas pu lire le lien symbolique « %s » : %m"
-#: access/transam/xlog.c:10015 replication/basebackup.c:1043 utils/adt/misc.c:503
+#: access/transam/xlog.c:10083 replication/basebackup.c:1031 utils/adt/misc.c:503
#, c-format
msgid "symbolic link \"%s\" target is too long"
-msgstr "la cible du lien symbolique � %s � est trop long"
+msgstr "la cible du lien symbolique « %s » est trop long"
-#: access/transam/xlog.c:10068 commands/tablespace.c:391 commands/tablespace.c:553 replication/basebackup.c:1059 utils/adt/misc.c:511
+#: access/transam/xlog.c:10136 commands/tablespace.c:391 commands/tablespace.c:553 replication/basebackup.c:1047 utils/adt/misc.c:511
#, c-format
msgid "tablespaces are not supported on this platform"
-msgstr "les tablespaces ne sont pas support�s sur cette plateforme"
+msgstr "les tablespaces ne sont pas supportés sur cette plateforme"
-#: access/transam/xlog.c:10109 access/transam/xlog.c:10147 access/transam/xlog.c:10326 access/transam/xlogarchive.c:106 access/transam/xlogarchive.c:265 commands/copy.c:1778 commands/copy.c:2804 commands/extension.c:3109 commands/tablespace.c:782 commands/tablespace.c:873 guc-file.l:1003 replication/basebackup.c:407 replication/basebackup.c:475 replication/logical/snapbuild.c:1493 storage/file/copydir.c:72 storage/file/copydir.c:115
+#: access/transam/xlog.c:10177 access/transam/xlog.c:10215 access/transam/xlog.c:10411 access/transam/xlogarchive.c:106 access/transam/xlogarchive.c:265 commands/copy.c:1815 commands/copy.c:2839 commands/extension.c:3130 commands/tablespace.c:782 commands/tablespace.c:873 guc-file.l:1001 replication/basebackup.c:409 replication/basebackup.c:477 replication/logical/snapbuild.c:1491 storage/file/copydir.c:72 storage/file/copydir.c:115
#: storage/file/fd.c:2826 storage/file/fd.c:2918 utils/adt/dbsize.c:70 utils/adt/dbsize.c:220 utils/adt/dbsize.c:300 utils/adt/genfile.c:114 utils/adt/genfile.c:333
#, c-format
msgid "could not stat file \"%s\": %m"
-msgstr "n'a pas pu tester le fichier � %s � : %m"
+msgstr "n'a pas pu tester le fichier « %s » : %m"
-#: access/transam/xlog.c:10116 access/transam/xlog.c:10154
+#: access/transam/xlog.c:10184 access/transam/xlog.c:10222
#, c-format
msgid "If you're sure there is no backup in progress, remove file \"%s\" and try again."
msgstr ""
-"Si vous �tes certain qu'aucune sauvegarde n'est en cours, supprimez le\n"
-"fichier � %s � et recommencez de nouveau."
+"Si vous êtes certain qu'aucune sauvegarde n'est en cours, supprimez le\n"
+"fichier « %s » et recommencez de nouveau."
-#: access/transam/xlog.c:10133 access/transam/xlog.c:10171 access/transam/xlog.c:10501
+#: access/transam/xlog.c:10201 access/transam/xlog.c:10239 access/transam/xlog.c:10615
#, c-format
msgid "could not write file \"%s\": %m"
-msgstr "impossible d'�crire le fichier � %s � : %m"
+msgstr "impossible d'écrire le fichier « %s » : %m"
-#: access/transam/xlog.c:10290
-#, fuzzy, c-format
-#| msgid "a backup is not in progress"
+#: access/transam/xlog.c:10388
+#, c-format
msgid "exclusive backup not in progress"
-msgstr "une sauvegarde n'est pas en cours"
+msgstr "une sauvegarde exclusive n'est pas en cours"
-#: access/transam/xlog.c:10330
+#: access/transam/xlog.c:10415
#, c-format
msgid "a backup is not in progress"
msgstr "une sauvegarde n'est pas en cours"
-#: access/transam/xlog.c:10375 access/transam/xlog.c:10388 access/transam/xlog.c:10728 access/transam/xlog.c:10734 access/transam/xlog.c:10818 access/transam/xlogfuncs.c:696
+#: access/transam/xlog.c:10489 access/transam/xlog.c:10502 access/transam/xlog.c:10842 access/transam/xlog.c:10848 access/transam/xlog.c:10932 access/transam/xlogfuncs.c:695
#, c-format
msgid "invalid data in file \"%s\""
-msgstr "donn�es invalides dans le fichier � %s �"
+msgstr "données invalides dans le fichier « %s »"
-#: access/transam/xlog.c:10392 replication/basebackup.c:936
+#: access/transam/xlog.c:10506 replication/basebackup.c:938
#, c-format
msgid "the standby was promoted during online backup"
-msgstr "le standby a �t� promu lors de la sauvegarde en ligne"
+msgstr "le standby a été promu lors de la sauvegarde en ligne"
-#: access/transam/xlog.c:10393 replication/basebackup.c:937
+#: access/transam/xlog.c:10507 replication/basebackup.c:939
#, c-format
msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup."
msgstr ""
-"Cela signifie que la sauvegarde en cours de r�alisation est corrompue et ne\n"
-"doit pas �tre utilis�e. Recommencez la sauvegarde."
+"Cela signifie que la sauvegarde en cours de réalisation est corrompue et ne\n"
+"doit pas être utilisée. Recommencez la sauvegarde."
-#: access/transam/xlog.c:10438
+#: access/transam/xlog.c:10552
#, c-format
msgid "WAL generated with full_page_writes=off was replayed during online backup"
msgstr ""
-"le journal de transactions g�n�r� avec full_page_writes=off a �t� rejou� lors\n"
+"le journal de transactions généré avec full_page_writes=off a été rejoué lors\n"
"de la sauvegarde en ligne"
-#: access/transam/xlog.c:10550
+#: access/transam/xlog.c:10664
#, c-format
msgid "pg_stop_backup cleanup done, waiting for required WAL segments to be archived"
-msgstr "nettoyage de pg_stop_backup termin�, en attente des journaux de transactions requis � archiver"
+msgstr "nettoyage de pg_stop_backup terminé, en attente des journaux de transactions requis à archiver"
-#: access/transam/xlog.c:10560
+#: access/transam/xlog.c:10674
#, c-format
msgid "pg_stop_backup still waiting for all required WAL segments to be archived (%d seconds elapsed)"
msgstr ""
"pg_stop_backup toujours en attente de la fin de l'archivage des segments de\n"
-"journaux de transactions requis (%d secondes pass�es)"
+"journaux de transactions requis (%d secondes passées)"
-#: access/transam/xlog.c:10562
+#: access/transam/xlog.c:10676
#, c-format
msgid "Check that your archive_command is executing properly. pg_stop_backup can be canceled safely, but the database backup will not be usable without all the WAL segments."
msgstr ""
-"V�rifiez que votre archive_command s'ex�cute correctement. pg_stop_backup\n"
-"peut �tre annul� avec s�ret� mais la sauvegarde de la base ne sera pas\n"
+"Vérifiez que votre archive_command s'exécute correctement. pg_stop_backup\n"
+"peut être annulé avec sûreté mais la sauvegarde de la base ne sera pas\n"
"utilisable sans tous les segments WAL."
-#: access/transam/xlog.c:10569
+#: access/transam/xlog.c:10683
#, c-format
msgid "pg_stop_backup complete, all required WAL segments have been archived"
-msgstr "pg_stop_backup termin�, tous les journaux de transactions requis ont �t� archiv�s"
+msgstr "pg_stop_backup terminé, tous les journaux de transactions requis ont été archivés"
-#: access/transam/xlog.c:10573
+#: access/transam/xlog.c:10687
#, c-format
msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup"
msgstr ""
-"L'archivage des journaux de transactions n'est pas activ� ;\n"
+"L'archivage des journaux de transactions n'est pas activé ;\n"
"vous devez vous assurer que tous les fichiers requis des journaux de\n"
-"transactions sont copi�s par d'autre moyens pour terminer la sauvegarde."
+"transactions sont copiés par d'autre moyens pour terminer la sauvegarde."
#. translator: %s is an XLog record description
-#: access/transam/xlog.c:10858
-#, fuzzy, c-format
-#| msgid "xlog redo %s"
+#: access/transam/xlog.c:10972
+#, c-format
msgid "xlog redo at %X/%X for %s"
-msgstr "xlog redo %s"
+msgstr "xlog redo à %X/%X pour %s"
-#: access/transam/xlog.c:10907
+#: access/transam/xlog.c:11021
#, c-format
msgid "online backup mode was not canceled"
-msgstr "le mode de sauvegarde en ligne n'a pas �t� annul�"
+msgstr "le mode de sauvegarde en ligne n'a pas été annulé"
-#: access/transam/xlog.c:10908
+#: access/transam/xlog.c:11022
#, c-format
msgid "File \"%s\" could not be renamed to \"%s\": %m."
-msgstr "Le fichier � %s � n'a pas pu �tre renomm� en � %s � : %m"
+msgstr "Le fichier « %s » n'a pas pu être renommé en « %s » : %m"
-#: access/transam/xlog.c:10917 access/transam/xlog.c:10929 access/transam/xlog.c:10939
+#: access/transam/xlog.c:11031 access/transam/xlog.c:11043 access/transam/xlog.c:11053
#, c-format
msgid "online backup mode canceled"
-msgstr "mode de sauvegarde en ligne annul�"
+msgstr "mode de sauvegarde en ligne annulé"
-#: access/transam/xlog.c:10930
+#: access/transam/xlog.c:11044
#, c-format
msgid "Files \"%s\" and \"%s\" were renamed to \"%s\" and \"%s\", respectively."
-msgstr "Les fichiers � %s � et � %s � sont renomm�s respectivement � %s � et � %s �."
+msgstr "Les fichiers « %s » et « %s » sont renommés respectivement « %s » et « %s »."
-#: access/transam/xlog.c:10940
+#: access/transam/xlog.c:11054
#, c-format
msgid "File \"%s\" was renamed to \"%s\", but file \"%s\" could not be renamed to \"%s\": %m."
-msgstr "Le fichier � %s � a �t� renomm� en � %s �, mais le fichier � %s � n'a pas pu �tre renomm� en � %s � : %m"
+msgstr "Le fichier « %s » a été renommé en « %s », mais le fichier « %s » n'a pas pu être renommé en « %s » : %m"
-#: access/transam/xlog.c:11062 access/transam/xlogutils.c:717 replication/walreceiver.c:973 replication/walsender.c:2116
+#: access/transam/xlog.c:11176 access/transam/xlogutils.c:718 replication/walreceiver.c:994 replication/walsender.c:2114
#, c-format
msgid "could not seek in log segment %s to offset %u: %m"
-msgstr "n'a pas pu se d�placer dans le journal de transactions %s au d�calage %u : %m"
+msgstr "n'a pas pu se déplacer dans le journal de transactions %s au décalage %u : %m"
-#: access/transam/xlog.c:11074
+#: access/transam/xlog.c:11188
#, c-format
msgid "could not read from log segment %s, offset %u: %m"
-msgstr "n'a pas pu lire le journal de transactions %s, d�calage %u : %m"
+msgstr "n'a pas pu lire le journal de transactions %s, décalage %u : %m"
-#: access/transam/xlog.c:11548
+#: access/transam/xlog.c:11662
#, c-format
msgid "received promote request"
-msgstr "a re�u une demande de promotion"
+msgstr "a reçu une demande de promotion"
-#: access/transam/xlog.c:11561
+#: access/transam/xlog.c:11675
#, c-format
msgid "trigger file found: %s"
-msgstr "fichier trigger trouv� : %s"
+msgstr "fichier trigger trouvé : %s"
-#: access/transam/xlog.c:11570
+#: access/transam/xlog.c:11684
#, c-format
msgid "could not stat trigger file \"%s\": %m"
-msgstr "n'a pas pu tester le fichier trigger � %s � : %m"
+msgstr "n'a pas pu tester le fichier trigger « %s » : %m"
#: access/transam/xlogarchive.c:244
#, c-format
msgid "archive file \"%s\" has wrong size: %lu instead of %lu"
-msgstr "le fichier d'archive � %s � a la mauvaise taille : %lu au lieu de %lu"
+msgstr "le fichier d'archive « %s » a la mauvaise taille : %lu au lieu de %lu"
#: access/transam/xlogarchive.c:253
#, c-format
msgid "restored log file \"%s\" from archive"
-msgstr "restauration du journal de transactions � %s � � partir de l'archive"
+msgstr "restauration du journal de transactions « %s » à partir de l'archive"
#: access/transam/xlogarchive.c:303
#, c-format
msgid "could not restore file \"%s\" from archive: %s"
-msgstr "n'a pas pu restaurer le fichier � %s � � partir de l'archive : %s"
+msgstr "n'a pas pu restaurer le fichier « %s » à partir de l'archive : %s"
#. translator: First %s represents a recovery.conf parameter name like
#. "recovery_end_command", the 2nd is the value of that parameter, the
@@ -2720,180 +2794,177 @@ msgstr "n'a pas pu restaurer le fichier � %s � � partir de l'archive : %s"
#: access/transam/xlogarchive.c:415
#, c-format
msgid "%s \"%s\": %s"
-msgstr "%s � %s �: %s"
+msgstr "%s « %s »: %s"
-#: access/transam/xlogarchive.c:458 replication/logical/snapbuild.c:1621 replication/slot.c:470 replication/slot.c:981 replication/slot.c:1089 storage/file/fd.c:635 storage/file/fd.c:693 utils/time/snapmgr.c:1205
+#: access/transam/xlogarchive.c:458 replication/logical/snapbuild.c:1619 replication/slot.c:480 replication/slot.c:992 replication/slot.c:1100 storage/file/fd.c:635 storage/file/fd.c:693 utils/time/snapmgr.c:1298
#, c-format
msgid "could not rename file \"%s\" to \"%s\": %m"
-msgstr "n'a pas pu renommer le fichier � %s � en � %s � : %m"
+msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m"
#: access/transam/xlogarchive.c:525 access/transam/xlogarchive.c:589
#, c-format
msgid "could not create archive status file \"%s\": %m"
-msgstr "n'a pas pu cr�er le fichier de statut d'archivage � %s � : %m"
+msgstr "n'a pas pu créer le fichier de statut d'archivage « %s » : %m"
#: access/transam/xlogarchive.c:533 access/transam/xlogarchive.c:597
#, c-format
msgid "could not write archive status file \"%s\": %m"
-msgstr "n'a pas pu �crire le fichier de statut d'archivage � %s � : %m"
+msgstr "n'a pas pu écrire le fichier de statut d'archivage « %s » : %m"
#: access/transam/xlogfuncs.c:58
#, c-format
msgid "aborting backup due to backend exiting before pg_stop_backup was called"
-msgstr ""
+msgstr "annulation de la sauvegarde due à la déconnexion du processus serveur avant que pg_stop_backup ne soit appelé"
#: access/transam/xlogfuncs.c:88
-#, fuzzy, c-format
-#| msgid "a backup is already in progress"
+#, c-format
msgid "a backup is already in progress in this session"
-msgstr "une sauvegarde est d�j� en cours"
+msgstr "une sauvegarde est déjà en cours dans cette session"
-#: access/transam/xlogfuncs.c:94 commands/tablespace.c:705 commands/tablespace.c:715 postmaster/postmaster.c:1395 replication/basebackup.c:295 replication/basebackup.c:635 storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2292 storage/file/fd.c:2891 storage/ipc/dsm.c:300 utils/adt/genfile.c:439 utils/adt/misc.c:411 utils/misc/tzparser.c:339
+#: access/transam/xlogfuncs.c:94 commands/tablespace.c:705 commands/tablespace.c:715 postmaster/postmaster.c:1406 replication/basebackup.c:297 replication/basebackup.c:637 storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2292 storage/file/fd.c:2891 storage/ipc/dsm.c:300 utils/adt/genfile.c:439 utils/adt/misc.c:411 utils/misc/tzparser.c:339
#, c-format
msgid "could not open directory \"%s\": %m"
-msgstr "n'a pas pu ouvrir le r�pertoire � %s � : %m"
+msgstr "n'a pas pu ouvrir le répertoire « %s » : %m"
#: access/transam/xlogfuncs.c:155 access/transam/xlogfuncs.c:229
-#, fuzzy, c-format
-#| msgid "a backup is not in progress"
+#, c-format
msgid "non-exclusive backup in progress"
-msgstr "une sauvegarde n'est pas en cours"
+msgstr "une sauvegarde non exclusive est en cours"
#: access/transam/xlogfuncs.c:156 access/transam/xlogfuncs.c:230
#, c-format
-msgid "did you mean to use pg_stop_backup('f')?"
-msgstr "souhaitiez-vous utiliser pg_stop_backup('f') ?"
+msgid "Did you mean to use pg_stop_backup('f')?"
+msgstr "Souhaitiez-vous utiliser pg_stop_backup('f') ?"
-#: access/transam/xlogfuncs.c:200 commands/event_trigger.c:1449 commands/event_trigger.c:2000 commands/extension.c:1728 commands/extension.c:1837 commands/extension.c:2030 commands/prepare.c:702 executor/execQual.c:1757 executor/execQual.c:1782 executor/execQual.c:2157 executor/execQual.c:5393 executor/functions.c:1024 foreign/foreign.c:598 replication/logical/logicalfuncs.c:175 replication/logical/origin.c:1391 replication/slotfuncs.c:189
-#: replication/walsender.c:2765 utils/adt/jsonfuncs.c:1483 utils/adt/jsonfuncs.c:1615 utils/adt/jsonfuncs.c:1805 utils/adt/jsonfuncs.c:1934 utils/adt/jsonfuncs.c:2702 utils/adt/pgstatfuncs.c:554 utils/adt/pgstatfuncs.c:655 utils/fmgr/funcapi.c:61 utils/misc/guc.c:8424 utils/mmgr/portalmem.c:1064
+#: access/transam/xlogfuncs.c:200 commands/event_trigger.c:1445 commands/event_trigger.c:1996 commands/extension.c:1729 commands/extension.c:1838 commands/extension.c:2031 commands/prepare.c:702 executor/execQual.c:1757 executor/execQual.c:1782 executor/execQual.c:2157 executor/execQual.c:5438 executor/functions.c:1031 foreign/foreign.c:492 replication/logical/logicalfuncs.c:175 replication/logical/origin.c:1391 replication/slotfuncs.c:189
+#: replication/walsender.c:2763 utils/adt/jsonfuncs.c:1483 utils/adt/jsonfuncs.c:1613 utils/adt/jsonfuncs.c:1801 utils/adt/jsonfuncs.c:1928 utils/adt/jsonfuncs.c:2694 utils/adt/pgstatfuncs.c:554 utils/adt/pgstatfuncs.c:655 utils/fmgr/funcapi.c:61 utils/misc/guc.c:8436 utils/mmgr/portalmem.c:1074
#, c-format
msgid "set-valued function called in context that cannot accept a set"
msgstr ""
-"la fonction avec set-value a �t� appel� dans un contexte qui n'accepte pas\n"
+"la fonction avec set-value a été appelé dans un contexte qui n'accepte pas\n"
"un ensemble"
-#: access/transam/xlogfuncs.c:204 commands/event_trigger.c:1453 commands/event_trigger.c:2004 commands/extension.c:1732 commands/extension.c:1841 commands/extension.c:2034 commands/prepare.c:706 foreign/foreign.c:603 replication/logical/logicalfuncs.c:179 replication/logical/origin.c:1395 replication/slotfuncs.c:193 replication/walsender.c:2769 utils/adt/pgstatfuncs.c:558 utils/adt/pgstatfuncs.c:659 utils/misc/guc.c:8428
-#: utils/misc/pg_config.c:44 utils/mmgr/portalmem.c:1068
+#: access/transam/xlogfuncs.c:204 commands/event_trigger.c:1449 commands/event_trigger.c:2000 commands/extension.c:1733 commands/extension.c:1842 commands/extension.c:2035 commands/prepare.c:706 foreign/foreign.c:497 replication/logical/logicalfuncs.c:179 replication/logical/origin.c:1395 replication/slotfuncs.c:193 replication/walsender.c:2767 utils/adt/pgstatfuncs.c:558 utils/adt/pgstatfuncs.c:659 utils/misc/guc.c:8440
+#: utils/misc/pg_config.c:44 utils/mmgr/portalmem.c:1078
#, c-format
msgid "materialize mode required, but it is not allowed in this context"
-msgstr "mode mat�rialis� requis mais interdit dans ce contexte"
+msgstr "mode matérialisé requis mais interdit dans ce contexte"
#: access/transam/xlogfuncs.c:247
-#, fuzzy, c-format
-#| msgid "a backup is not in progress"
+#, c-format
msgid "non-exclusive backup is not in progress"
-msgstr "une sauvegarde n'est pas en cours"
+msgstr "une sauvegarde non exclusive n'est pas en cours"
#: access/transam/xlogfuncs.c:248
#, c-format
-msgid "did you mean to use pg_stop_backup('t')?"
-msgstr "souhaitiez-vous utiliser pg_stop_backup('t') ?"
+msgid "Did you mean to use pg_stop_backup('t')?"
+msgstr "Souhaitiez-vous utiliser pg_stop_backup('t') ?"
-#: access/transam/xlogfuncs.c:327
+#: access/transam/xlogfuncs.c:326
#, c-format
msgid "WAL level not sufficient for creating a restore point"
msgstr ""
-"le niveau de journalisation (configur� par wal_level) n'est pas suffisant pour\n"
-"cr�er un point de restauration"
+"le niveau de journalisation (configuré par wal_level) n'est pas suffisant pour\n"
+"créer un point de restauration"
-#: access/transam/xlogfuncs.c:335
+#: access/transam/xlogfuncs.c:334
#, c-format
msgid "value too long for restore point (maximum %d characters)"
-msgstr "valeur trop longue pour le point de restauration (%d caract�res maximum)"
+msgstr "valeur trop longue pour le point de restauration (%d caractères maximum)"
-#: access/transam/xlogfuncs.c:473
+#: access/transam/xlogfuncs.c:472
#, c-format
msgid "pg_xlogfile_name_offset() cannot be executed during recovery."
-msgstr "pg_xlogfile_name_offset() ne peut pas �tre ex�cut� lors de la restauration."
+msgstr "pg_xlogfile_name_offset() ne peut pas être exécuté lors de la restauration."
-#: access/transam/xlogfuncs.c:529
+#: access/transam/xlogfuncs.c:528
#, c-format
msgid "pg_xlogfile_name() cannot be executed during recovery."
-msgstr "pg_xlogfile_name() ne peut pas �tre ex�cut� lors de la restauration."
+msgstr "pg_xlogfile_name() ne peut pas être exécuté lors de la restauration."
-#: access/transam/xlogfuncs.c:549 access/transam/xlogfuncs.c:569 access/transam/xlogfuncs.c:586
+#: access/transam/xlogfuncs.c:548 access/transam/xlogfuncs.c:568 access/transam/xlogfuncs.c:585
#, c-format
msgid "recovery is not in progress"
msgstr "la restauration n'est pas en cours"
-#: access/transam/xlogfuncs.c:550 access/transam/xlogfuncs.c:570 access/transam/xlogfuncs.c:587
+#: access/transam/xlogfuncs.c:549 access/transam/xlogfuncs.c:569 access/transam/xlogfuncs.c:586
#, c-format
msgid "Recovery control functions can only be executed during recovery."
msgstr ""
-"Les fonctions de contr�le de la restauration peuvent seulement �tre ex�cut�es\n"
+"Les fonctions de contrôle de la restauration peuvent seulement être exécutées\n"
"lors de la restauration."
#: access/transam/xlogreader.c:276
#, c-format
msgid "invalid record offset at %X/%X"
-msgstr "d�calage invalide de l'enregistrement %X/%X"
+msgstr "décalage invalide de l'enregistrement %X/%X"
#: access/transam/xlogreader.c:284
#, c-format
msgid "contrecord is requested by %X/%X"
-msgstr "� contrecord � est requis par %X/%X"
+msgstr "« contrecord » est requis par %X/%X"
#: access/transam/xlogreader.c:325 access/transam/xlogreader.c:624
#, c-format
msgid "invalid record length at %X/%X: wanted %u, got %u"
-msgstr "longueur invalide de l'enregistrement � %X/%X : voulait %u, a eu %u"
+msgstr "longueur invalide de l'enregistrement à %X/%X : voulait %u, a eu %u"
#: access/transam/xlogreader.c:340
#, c-format
msgid "record length %u at %X/%X too long"
-msgstr "longueur trop importante de l'enregistrement %u � %X/%X"
+msgstr "longueur trop importante de l'enregistrement %u à %X/%X"
#: access/transam/xlogreader.c:381
#, c-format
msgid "there is no contrecord flag at %X/%X"
-msgstr "il n'existe pas de drapeau contrecord � %X/%X"
+msgstr "il n'existe pas de drapeau contrecord à %X/%X"
#: access/transam/xlogreader.c:394
#, c-format
msgid "invalid contrecord length %u at %X/%X"
-msgstr "longueur %u invalide du contrecord � %X/%X"
+msgstr "longueur %u invalide du contrecord à %X/%X"
#: access/transam/xlogreader.c:632
#, c-format
msgid "invalid resource manager ID %u at %X/%X"
-msgstr "identifiant du gestionnaire de ressources invalide %u � %X/%X"
+msgstr "identifiant du gestionnaire de ressources invalide %u à %X/%X"
#: access/transam/xlogreader.c:646 access/transam/xlogreader.c:663
#, c-format
msgid "record with incorrect prev-link %X/%X at %X/%X"
-msgstr "enregistrement avec prev-link %X/%X incorrect � %X/%X"
+msgstr "enregistrement avec prev-link %X/%X incorrect à %X/%X"
#: access/transam/xlogreader.c:700
#, c-format
msgid "incorrect resource manager data checksum in record at %X/%X"
msgstr ""
-"somme de contr�le des donn�es du gestionnaire de ressources incorrecte �\n"
+"somme de contrôle des données du gestionnaire de ressources incorrecte à\n"
"l'enregistrement %X/%X"
#: access/transam/xlogreader.c:733
#, c-format
msgid "invalid magic number %04X in log segment %s, offset %u"
-msgstr "num�ro magique invalide %04X dans le segment %s, d�calage %u"
+msgstr "numéro magique invalide %04X dans le segment %s, décalage %u"
#: access/transam/xlogreader.c:747 access/transam/xlogreader.c:798
#, c-format
msgid "invalid info bits %04X in log segment %s, offset %u"
-msgstr "bits d'information %04X invalides dans le segment %s, d�calage %u"
+msgstr "bits d'information %04X invalides dans le segment %s, décalage %u"
#: access/transam/xlogreader.c:773
#, c-format
msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s"
-msgstr "le fichier WAL provient d'un syst�me diff�rent : l'identifiant syst�me de la base dans le fichier WAL est %s, alors que l'identifiant syst�me de la base dans pg_control est %s"
+msgstr "le fichier WAL provient d'un système différent : l'identifiant système de la base dans le fichier WAL est %s, alors que l'identifiant système de la base dans pg_control est %s"
#: access/transam/xlogreader.c:780
#, c-format
msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header"
-msgstr "le fichier WAL provient d'un syst�me diff�rent : XLOG_SEG_SIZE invalide dans l'en-t�te de page"
+msgstr "le fichier WAL provient d'un système différent : XLOG_SEG_SIZE invalide dans l'en-tête de page"
#: access/transam/xlogreader.c:786
#, c-format
msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
-msgstr "le fichier WAL provient d'un syst�me diff�rent : XLOG_BLCKSZ invalide dans l'en-t�te de page"
+msgstr "le fichier WAL provient d'un système différent : XLOG_BLCKSZ invalide dans l'en-tête de page"
#: access/transam/xlogreader.c:812
#, c-format
@@ -2903,205 +2974,205 @@ msgstr "pageaddr %X/%X inattendue dans le journal de transactions %s, segment %u
#: access/transam/xlogreader.c:837
#, c-format
msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
-msgstr "identifiant timeline %u hors de la s�quence (apr�s %u) dans le segment %s, d�calage %u"
+msgstr "identifiant timeline %u hors de la séquence (après %u) dans le segment %s, décalage %u"
-#: access/transam/xlogreader.c:1044
+#: access/transam/xlogreader.c:1081
#, c-format
msgid "out-of-order block_id %u at %X/%X"
-msgstr "block_id %u d�sordonn� � %X/%X"
+msgstr "block_id %u désordonné à %X/%X"
-#: access/transam/xlogreader.c:1066
+#: access/transam/xlogreader.c:1103
#, c-format
msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
-msgstr "BKPBLOCK_HAS_DATA configur�, mais aucune donn�e inclus � %X/%X"
+msgstr "BKPBLOCK_HAS_DATA configuré, mais aucune donnée inclus à %X/%X"
-#: access/transam/xlogreader.c:1073
+#: access/transam/xlogreader.c:1110
#, c-format
msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
-msgstr "BKPBLOCK_HAS_DATA non configur�, mais la longueur des donn�es est %u � %X/%X"
+msgstr "BKPBLOCK_HAS_DATA non configuré, mais la longueur des données est %u à %X/%X"
-#: access/transam/xlogreader.c:1106
+#: access/transam/xlogreader.c:1143
#, c-format
msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
-msgstr "BKPIMAGE_HAS_HOLE initialis�, mais d�calage du trou %u longueur %u longueur de l'image du bloc %u � %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE initialisé, mais décalage du trou %u longueur %u longueur de l'image du bloc %u à %X/%X"
-#: access/transam/xlogreader.c:1122
+#: access/transam/xlogreader.c:1159
#, c-format
msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
-msgstr "BKPIMAGE_HAS_HOLE non initialis�, mais d�calage du trou %u longueur %u � %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE non initialisé, mais décalage du trou %u longueur %u à %X/%X"
-#: access/transam/xlogreader.c:1137
+#: access/transam/xlogreader.c:1174
#, c-format
msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
-msgstr "BKPIMAGE_IS_COMPRESSED configur�, mais la longueur de l'image du bloc est %u � %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X"
-#: access/transam/xlogreader.c:1152
+#: access/transam/xlogreader.c:1189
#, c-format
msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
-msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_IS_COMPRESSED configur�, mais la longueur de l'image du bloc est %u � %X/%X"
+msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_IS_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X"
-#: access/transam/xlogreader.c:1168
+#: access/transam/xlogreader.c:1205
#, c-format
msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
-msgstr "BKPBLOCK_SAME_REL configur�, mais pas de relation pr�c�dente � %X/%X"
+msgstr "BKPBLOCK_SAME_REL configuré, mais pas de relation précédente à %X/%X"
-#: access/transam/xlogreader.c:1180
+#: access/transam/xlogreader.c:1217
#, c-format
msgid "invalid block_id %u at %X/%X"
-msgstr "block_id %u invalide � %X/%X"
+msgstr "block_id %u invalide à %X/%X"
-#: access/transam/xlogreader.c:1245
+#: access/transam/xlogreader.c:1282
#, c-format
msgid "record with invalid length at %X/%X"
-msgstr "enregistrement de longueur invalide � %X/%X"
+msgstr "enregistrement de longueur invalide à %X/%X"
-#: access/transam/xlogreader.c:1334
+#: access/transam/xlogreader.c:1371
#, c-format
msgid "invalid compressed image at %X/%X, block %d"
-msgstr "image compress�e invalide � %X/%X, bloc %d"
+msgstr "image compressée invalide à %X/%X, bloc %d"
-#: access/transam/xlogutils.c:738 replication/walsender.c:2133
+#: access/transam/xlogutils.c:739 replication/walsender.c:2131
#, c-format
msgid "could not read from log segment %s, offset %u, length %lu: %m"
-msgstr "n'a pas pu lire le journal de transactions %s, d�calage %u, longueur %lu : %m"
+msgstr "n'a pas pu lire le journal de transactions %s, décalage %u, longueur %lu : %m"
-#: bootstrap/bootstrap.c:269 postmaster/postmaster.c:785 tcop/postgres.c:3488
+#: bootstrap/bootstrap.c:269 postmaster/postmaster.c:793 tcop/postgres.c:3501
#, c-format
msgid "--%s requires a value"
msgstr "--%s requiert une valeur"
-#: bootstrap/bootstrap.c:274 postmaster/postmaster.c:790 tcop/postgres.c:3493
+#: bootstrap/bootstrap.c:274 postmaster/postmaster.c:798 tcop/postgres.c:3506
#, c-format
msgid "-c %s requires a value"
msgstr "-c %s requiert une valeur"
-#: bootstrap/bootstrap.c:285 postmaster/postmaster.c:802 postmaster/postmaster.c:815
+#: bootstrap/bootstrap.c:285 postmaster/postmaster.c:810 postmaster/postmaster.c:823
#, c-format
msgid "Try \"%s --help\" for more information.\n"
-msgstr "Essayez � %s --help � pour plus d'informations.\n"
+msgstr "Essayez « %s --help » pour plus d'informations.\n"
#: bootstrap/bootstrap.c:294
#, c-format
msgid "%s: invalid command-line arguments\n"
msgstr "%s : arguments invalides en ligne de commande\n"
-#: catalog/aclchk.c:193
+#: catalog/aclchk.c:201
#, c-format
msgid "grant options can only be granted to roles"
-msgstr "les options grant peuvent seulement �tre donn�es aux r�les"
+msgstr "les options grant peuvent seulement être données aux rôles"
-#: catalog/aclchk.c:316
+#: catalog/aclchk.c:324
#, c-format
msgid "no privileges were granted for column \"%s\" of relation \"%s\""
-msgstr "aucun droit n'a pu �tre accord� pour la colonne � %s � de la relation � %s �"
+msgstr "aucun droit n'a pu être accordé pour la colonne « %s » de la relation « %s »"
-#: catalog/aclchk.c:321
+#: catalog/aclchk.c:329
#, c-format
msgid "no privileges were granted for \"%s\""
-msgstr "aucun droit n'a �t� accord� pour � %s �"
+msgstr "aucun droit n'a été accordé pour « %s »"
-#: catalog/aclchk.c:329
+#: catalog/aclchk.c:337
#, c-format
msgid "not all privileges were granted for column \"%s\" of relation \"%s\""
-msgstr "certains droits n'ont pu �tre accord� pour la colonne � %s � de la relation � %s �"
+msgstr "certains droits n'ont pu être accordé pour la colonne « %s » de la relation « %s »"
-#: catalog/aclchk.c:334
+#: catalog/aclchk.c:342
#, c-format
msgid "not all privileges were granted for \"%s\""
-msgstr "tous les droits n'ont pas �t� accord�s pour � %s �"
+msgstr "tous les droits n'ont pas été accordés pour « %s »"
-#: catalog/aclchk.c:345
+#: catalog/aclchk.c:353
#, c-format
msgid "no privileges could be revoked for column \"%s\" of relation \"%s\""
-msgstr "aucun droit n'a pu �tre r�voqu� pour la colonne � %s � de la relation � %s �"
+msgstr "aucun droit n'a pu être révoqué pour la colonne « %s » de la relation « %s »"
-#: catalog/aclchk.c:350
+#: catalog/aclchk.c:358
#, c-format
msgid "no privileges could be revoked for \"%s\""
-msgstr "aucun droit n'a pu �tre r�voqu� pour � %s �"
+msgstr "aucun droit n'a pu être révoqué pour « %s »"
-#: catalog/aclchk.c:358
+#: catalog/aclchk.c:366
#, c-format
msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\""
-msgstr "certains droits n'ont pu �tre r�voqu� pour la colonne � %s � de la relation � %s �"
+msgstr "certains droits n'ont pu être révoqué pour la colonne « %s » de la relation « %s »"
-#: catalog/aclchk.c:363
+#: catalog/aclchk.c:371
#, c-format
msgid "not all privileges could be revoked for \"%s\""
-msgstr "certains droits n'ont pu �tre r�voqu� pour � %s �"
+msgstr "certains droits n'ont pu être révoqué pour « %s »"
-#: catalog/aclchk.c:445 catalog/aclchk.c:935
+#: catalog/aclchk.c:453 catalog/aclchk.c:943
#, c-format
msgid "invalid privilege type %s for relation"
msgstr "droit %s invalide pour la relation"
-#: catalog/aclchk.c:449 catalog/aclchk.c:939
+#: catalog/aclchk.c:457 catalog/aclchk.c:947
#, c-format
msgid "invalid privilege type %s for sequence"
-msgstr "droit %s invalide pour la s�quence"
+msgstr "droit %s invalide pour la séquence"
-#: catalog/aclchk.c:453
+#: catalog/aclchk.c:461
#, c-format
msgid "invalid privilege type %s for database"
-msgstr "droit %s invalide pour la base de donn�es"
+msgstr "droit %s invalide pour la base de données"
-#: catalog/aclchk.c:457
+#: catalog/aclchk.c:465
#, c-format
msgid "invalid privilege type %s for domain"
msgstr "type de droit %s invalide pour le domaine"
-#: catalog/aclchk.c:461 catalog/aclchk.c:943
+#: catalog/aclchk.c:469 catalog/aclchk.c:951
#, c-format
msgid "invalid privilege type %s for function"
msgstr "droit %s invalide pour la fonction"
-#: catalog/aclchk.c:465
+#: catalog/aclchk.c:473
#, c-format
msgid "invalid privilege type %s for language"
msgstr "droit %s invalide pour le langage"
-#: catalog/aclchk.c:469
+#: catalog/aclchk.c:477
#, c-format
msgid "invalid privilege type %s for large object"
msgstr "type de droit invalide, %s, pour le Large Object"
-#: catalog/aclchk.c:473
+#: catalog/aclchk.c:481
#, c-format
msgid "invalid privilege type %s for schema"
-msgstr "droit %s invalide pour le sch�ma"
+msgstr "droit %s invalide pour le schéma"
-#: catalog/aclchk.c:477
+#: catalog/aclchk.c:485
#, c-format
msgid "invalid privilege type %s for tablespace"
msgstr "droit %s invalide pour le tablespace"
-#: catalog/aclchk.c:481 catalog/aclchk.c:947
+#: catalog/aclchk.c:489 catalog/aclchk.c:955
#, c-format
msgid "invalid privilege type %s for type"
msgstr "type de droit %s invalide pour le type"
-#: catalog/aclchk.c:485
+#: catalog/aclchk.c:493
#, c-format
msgid "invalid privilege type %s for foreign-data wrapper"
-msgstr "type de droit %s invalide pour le wrapper de donn�es distantes"
+msgstr "type de droit %s invalide pour le wrapper de données distantes"
-#: catalog/aclchk.c:489
+#: catalog/aclchk.c:497
#, c-format
msgid "invalid privilege type %s for foreign server"
msgstr "type de droit %s invalide pour le serveur distant"
-#: catalog/aclchk.c:528
+#: catalog/aclchk.c:536
#, c-format
msgid "column privileges are only valid for relations"
msgstr "les droits sur la colonne sont seulement valides pour les relations"
-#: catalog/aclchk.c:687 catalog/aclchk.c:3914 catalog/aclchk.c:4691 catalog/objectaddress.c:873 catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:291
+#: catalog/aclchk.c:695 catalog/aclchk.c:3923 catalog/aclchk.c:4705 catalog/objectaddress.c:873 catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:291
#, c-format
msgid "large object %u does not exist"
-msgstr "le � Large Object � %u n'existe pas"
+msgstr "le « Large Object » %u n'existe pas"
-#: catalog/aclchk.c:874 catalog/aclchk.c:882 commands/collationcmds.c:92 commands/copy.c:1008 commands/copy.c:1026 commands/copy.c:1034 commands/copy.c:1042 commands/copy.c:1050 commands/copy.c:1058 commands/copy.c:1066 commands/copy.c:1074 commands/copy.c:1082 commands/copy.c:1098 commands/copy.c:1112 commands/copy.c:1131 commands/copy.c:1146 commands/dbcommands.c:155 commands/dbcommands.c:163 commands/dbcommands.c:171
-#: commands/dbcommands.c:179 commands/dbcommands.c:187 commands/dbcommands.c:195 commands/dbcommands.c:203 commands/dbcommands.c:211 commands/dbcommands.c:219 commands/dbcommands.c:1397 commands/dbcommands.c:1405 commands/dbcommands.c:1413 commands/dbcommands.c:1421 commands/extension.c:1218 commands/extension.c:1226 commands/extension.c:1234 commands/extension.c:1242 commands/extension.c:2760 commands/foreigncmds.c:539
+#: catalog/aclchk.c:882 catalog/aclchk.c:890 commands/collationcmds.c:92 commands/copy.c:1047 commands/copy.c:1065 commands/copy.c:1073 commands/copy.c:1081 commands/copy.c:1089 commands/copy.c:1097 commands/copy.c:1105 commands/copy.c:1113 commands/copy.c:1121 commands/copy.c:1137 commands/copy.c:1151 commands/copy.c:1170 commands/copy.c:1185 commands/dbcommands.c:155 commands/dbcommands.c:163 commands/dbcommands.c:171
+#: commands/dbcommands.c:179 commands/dbcommands.c:187 commands/dbcommands.c:195 commands/dbcommands.c:203 commands/dbcommands.c:211 commands/dbcommands.c:219 commands/dbcommands.c:1397 commands/dbcommands.c:1405 commands/dbcommands.c:1413 commands/dbcommands.c:1421 commands/extension.c:1219 commands/extension.c:1227 commands/extension.c:1235 commands/extension.c:1243 commands/extension.c:2761 commands/foreigncmds.c:539
#: commands/foreigncmds.c:548 commands/functioncmds.c:533 commands/functioncmds.c:649 commands/functioncmds.c:657 commands/functioncmds.c:665 commands/functioncmds.c:673 commands/functioncmds.c:2085 commands/functioncmds.c:2093 commands/sequence.c:1189 commands/sequence.c:1197 commands/sequence.c:1205 commands/sequence.c:1213 commands/sequence.c:1221 commands/sequence.c:1229 commands/sequence.c:1237 commands/sequence.c:1245
#: commands/typecmds.c:295 commands/typecmds.c:1382 commands/typecmds.c:1391 commands/typecmds.c:1399 commands/typecmds.c:1407 commands/typecmds.c:1415 commands/user.c:139 commands/user.c:156 commands/user.c:164 commands/user.c:172 commands/user.c:180 commands/user.c:188 commands/user.c:196 commands/user.c:204 commands/user.c:212 commands/user.c:220 commands/user.c:228 commands/user.c:236 commands/user.c:244 commands/user.c:537
#: commands/user.c:549 commands/user.c:557 commands/user.c:565 commands/user.c:573 commands/user.c:581 commands/user.c:589 commands/user.c:597 commands/user.c:606 commands/user.c:614 commands/user.c:622
@@ -3109,410 +3180,408 @@ msgstr "le � Large Object � %u n'existe pas"
msgid "conflicting or redundant options"
msgstr "options en conflit ou redondantes"
-#: catalog/aclchk.c:980
+#: catalog/aclchk.c:988
#, c-format
msgid "default privileges cannot be set for columns"
-msgstr "les droits par d�faut ne peuvent pas �tre configur�s pour les colonnes"
+msgstr "les droits par défaut ne peuvent pas être configurés pour les colonnes"
-#: catalog/aclchk.c:1494 catalog/objectaddress.c:1390 commands/analyze.c:378 commands/copy.c:4423 commands/sequence.c:1491 commands/tablecmds.c:5197 commands/tablecmds.c:5303 commands/tablecmds.c:5363 commands/tablecmds.c:5476 commands/tablecmds.c:5533 commands/tablecmds.c:5627 commands/tablecmds.c:5723 commands/tablecmds.c:7875 commands/tablecmds.c:8080 commands/tablecmds.c:8500 commands/trigger.c:642 parser/analyze.c:2160
-#: parser/parse_relation.c:2542 parser/parse_relation.c:2604 parser/parse_target.c:940 parser/parse_type.c:127 utils/adt/acl.c:2840 utils/adt/ruleutils.c:1870
+#: catalog/aclchk.c:1502 catalog/objectaddress.c:1390 commands/analyze.c:376 commands/copy.c:4458 commands/sequence.c:1491 commands/tablecmds.c:5198 commands/tablecmds.c:5304 commands/tablecmds.c:5364 commands/tablecmds.c:5477 commands/tablecmds.c:5534 commands/tablecmds.c:5628 commands/tablecmds.c:5724 commands/tablecmds.c:7915 commands/tablecmds.c:8177 commands/tablecmds.c:8597 commands/trigger.c:642 parser/analyze.c:2228
+#: parser/parse_relation.c:2628 parser/parse_relation.c:2690 parser/parse_target.c:951 parser/parse_type.c:127 utils/adt/acl.c:2840 utils/adt/ruleutils.c:1984
#, c-format
msgid "column \"%s\" of relation \"%s\" does not exist"
-msgstr "la colonne � %s � de la relation � %s � n'existe pas"
+msgstr "la colonne « %s » de la relation « %s » n'existe pas"
-#: catalog/aclchk.c:1763 catalog/objectaddress.c:1203 commands/sequence.c:1078 commands/tablecmds.c:223 commands/tablecmds.c:12007 utils/adt/acl.c:2076 utils/adt/acl.c:2106 utils/adt/acl.c:2138 utils/adt/acl.c:2170 utils/adt/acl.c:2198 utils/adt/acl.c:2228
+#: catalog/aclchk.c:1771 catalog/objectaddress.c:1203 commands/sequence.c:1078 commands/tablecmds.c:224 commands/tablecmds.c:12154 utils/adt/acl.c:2076 utils/adt/acl.c:2106 utils/adt/acl.c:2138 utils/adt/acl.c:2170 utils/adt/acl.c:2198 utils/adt/acl.c:2228
#, c-format
msgid "\"%s\" is not a sequence"
-msgstr "� %s � n'est pas une s�quence"
+msgstr "« %s » n'est pas une séquence"
-#: catalog/aclchk.c:1801
+#: catalog/aclchk.c:1809
#, c-format
msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges"
-msgstr "la s�quence � %s � accepte seulement les droits USAGE, SELECT et UPDATE"
+msgstr "la séquence « %s » accepte seulement les droits USAGE, SELECT et UPDATE"
-#: catalog/aclchk.c:1818
+#: catalog/aclchk.c:1826
#, c-format
msgid "invalid privilege type USAGE for table"
msgstr "droit USAGE invalide pour la table"
-#: catalog/aclchk.c:1986
+#: catalog/aclchk.c:1994
#, c-format
msgid "invalid privilege type %s for column"
msgstr "type de droit %s invalide pour la colonne"
-#: catalog/aclchk.c:1999
+#: catalog/aclchk.c:2007
#, c-format
msgid "sequence \"%s\" only supports SELECT column privileges"
-msgstr "la s�quence � %s � accepte seulement le droit SELECT pour les colonnes"
+msgstr "la séquence « %s » accepte seulement le droit SELECT pour les colonnes"
-#: catalog/aclchk.c:2593
+#: catalog/aclchk.c:2601
#, c-format
msgid "language \"%s\" is not trusted"
-msgstr "le langage � %s � n'est pas de confiance"
+msgstr "le langage « %s » n'est pas de confiance"
-#: catalog/aclchk.c:2595
+#: catalog/aclchk.c:2603
#, c-format
-msgid "Only superusers can use untrusted languages."
-msgstr ""
-"Seuls les super-utilisateurs peuvent utiliser des langages qui ne sont pas\n"
-"de confiance."
+msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages."
+msgstr "GRANT et REVOKE ne sont pas autorisés sur des langages qui ne sont pas de confiance car seuls les super-utilisateurs peuvent utiliser ces langages"
-#: catalog/aclchk.c:3120
+#: catalog/aclchk.c:3129
#, c-format
msgid "cannot set privileges of array types"
msgstr "ne peut pas configurer les droits des types tableau"
-#: catalog/aclchk.c:3121
+#: catalog/aclchk.c:3130
#, c-format
msgid "Set the privileges of the element type instead."
-msgstr "Configurez les droits du type �l�ment � la place."
+msgstr "Configurez les droits du type élément à la place."
-#: catalog/aclchk.c:3128 catalog/objectaddress.c:1523 commands/typecmds.c:3146
+#: catalog/aclchk.c:3137 catalog/objectaddress.c:1523 commands/typecmds.c:3146
#, c-format
msgid "\"%s\" is not a domain"
-msgstr "� %s � n'est pas un domaine"
+msgstr "« %s » n'est pas un domaine"
-#: catalog/aclchk.c:3251
+#: catalog/aclchk.c:3260
#, c-format
msgid "unrecognized privilege type \"%s\""
-msgstr "droit � %s � non reconnu"
+msgstr "droit « %s » non reconnu"
-#: catalog/aclchk.c:3300
+#: catalog/aclchk.c:3309
#, c-format
msgid "permission denied for column %s"
-msgstr "droit refus� pour la colonne %s"
+msgstr "droit refusé pour la colonne %s"
-#: catalog/aclchk.c:3302
+#: catalog/aclchk.c:3311
#, c-format
msgid "permission denied for relation %s"
-msgstr "droit refus� pour la relation %s"
+msgstr "droit refusé pour la relation %s"
-#: catalog/aclchk.c:3304 commands/sequence.c:561 commands/sequence.c:786 commands/sequence.c:828 commands/sequence.c:865 commands/sequence.c:1543
+#: catalog/aclchk.c:3313 commands/sequence.c:561 commands/sequence.c:786 commands/sequence.c:828 commands/sequence.c:865 commands/sequence.c:1543
#, c-format
msgid "permission denied for sequence %s"
-msgstr "droit refus� pour la s�quence %s"
+msgstr "droit refusé pour la séquence %s"
-#: catalog/aclchk.c:3306
+#: catalog/aclchk.c:3315
#, c-format
msgid "permission denied for database %s"
-msgstr "droit refus� pour la base de donn�es %s"
+msgstr "droit refusé pour la base de données %s"
-#: catalog/aclchk.c:3308
+#: catalog/aclchk.c:3317
#, c-format
msgid "permission denied for function %s"
-msgstr "droit refus� pour la fonction %s"
+msgstr "droit refusé pour la fonction %s"
-#: catalog/aclchk.c:3310
+#: catalog/aclchk.c:3319
#, c-format
msgid "permission denied for operator %s"
-msgstr "droit refus� pour l'op�rateur %s"
+msgstr "droit refusé pour l'opérateur %s"
-#: catalog/aclchk.c:3312
+#: catalog/aclchk.c:3321
#, c-format
msgid "permission denied for type %s"
-msgstr "droit refus� pour le type %s"
+msgstr "droit refusé pour le type %s"
-#: catalog/aclchk.c:3314
+#: catalog/aclchk.c:3323
#, c-format
msgid "permission denied for language %s"
-msgstr "droit refus� pour le langage %s"
+msgstr "droit refusé pour le langage %s"
-#: catalog/aclchk.c:3316
+#: catalog/aclchk.c:3325
#, c-format
msgid "permission denied for large object %s"
-msgstr "droit refus� pour le Large Object %s"
+msgstr "droit refusé pour le Large Object %s"
-#: catalog/aclchk.c:3318
+#: catalog/aclchk.c:3327
#, c-format
msgid "permission denied for schema %s"
-msgstr "droit refus� pour le sch�ma %s"
+msgstr "droit refusé pour le schéma %s"
-#: catalog/aclchk.c:3320
+#: catalog/aclchk.c:3329
#, c-format
msgid "permission denied for operator class %s"
-msgstr "droit refus� pour la classe d'op�rateur %s"
+msgstr "droit refusé pour la classe d'opérateur %s"
-#: catalog/aclchk.c:3322
+#: catalog/aclchk.c:3331
#, c-format
msgid "permission denied for operator family %s"
-msgstr "droit refus� pour la famille d'op�rateur %s"
+msgstr "droit refusé pour la famille d'opérateur %s"
-#: catalog/aclchk.c:3324
+#: catalog/aclchk.c:3333
#, c-format
msgid "permission denied for collation %s"
-msgstr "droit refus� pour le collationnement %s"
+msgstr "droit refusé pour le collationnement %s"
-#: catalog/aclchk.c:3326
+#: catalog/aclchk.c:3335
#, c-format
msgid "permission denied for conversion %s"
-msgstr "droit refus� pour la conversion %s"
+msgstr "droit refusé pour la conversion %s"
-#: catalog/aclchk.c:3328
+#: catalog/aclchk.c:3337
#, c-format
msgid "permission denied for tablespace %s"
-msgstr "droit refus� pour le tablespace %s"
+msgstr "droit refusé pour le tablespace %s"
-#: catalog/aclchk.c:3330
+#: catalog/aclchk.c:3339
#, c-format
msgid "permission denied for text search dictionary %s"
-msgstr "droit refus� pour le dictionnaire de recherche plein texte %s"
+msgstr "droit refusé pour le dictionnaire de recherche plein texte %s"
-#: catalog/aclchk.c:3332
+#: catalog/aclchk.c:3341
#, c-format
msgid "permission denied for text search configuration %s"
-msgstr "droit refus� pour la configuration de recherche plein texte %s"
+msgstr "droit refusé pour la configuration de recherche plein texte %s"
-#: catalog/aclchk.c:3334
+#: catalog/aclchk.c:3343
#, c-format
msgid "permission denied for foreign-data wrapper %s"
-msgstr "droit refus� pour le wrapper de donn�es distantes %s"
+msgstr "droit refusé pour le wrapper de données distantes %s"
-#: catalog/aclchk.c:3336
+#: catalog/aclchk.c:3345
#, c-format
msgid "permission denied for foreign server %s"
-msgstr "droit refus� pour le serveur distant %s"
+msgstr "droit refusé pour le serveur distant %s"
-#: catalog/aclchk.c:3338
+#: catalog/aclchk.c:3347
#, c-format
msgid "permission denied for event trigger %s"
-msgstr "droit refus� pour le trigger sur �v�nement %s"
+msgstr "droit refusé pour le trigger sur événement %s"
-#: catalog/aclchk.c:3340
+#: catalog/aclchk.c:3349
#, c-format
msgid "permission denied for extension %s"
-msgstr "droit refus� pour l'extension %s"
+msgstr "droit refusé pour l'extension %s"
-#: catalog/aclchk.c:3346 catalog/aclchk.c:3348
+#: catalog/aclchk.c:3355 catalog/aclchk.c:3357
#, c-format
msgid "must be owner of relation %s"
-msgstr "doit �tre le propri�taire de la relation %s"
+msgstr "doit être le propriétaire de la relation %s"
-#: catalog/aclchk.c:3350
+#: catalog/aclchk.c:3359
#, c-format
msgid "must be owner of sequence %s"
-msgstr "doit �tre le propri�taire de la s�quence %s"
+msgstr "doit être le propriétaire de la séquence %s"
-#: catalog/aclchk.c:3352
+#: catalog/aclchk.c:3361
#, c-format
msgid "must be owner of database %s"
-msgstr "doit �tre le propri�taire de la base de donn�es %s"
+msgstr "doit être le propriétaire de la base de données %s"
-#: catalog/aclchk.c:3354
+#: catalog/aclchk.c:3363
#, c-format
msgid "must be owner of function %s"
-msgstr "doit �tre le propri�taire de la fonction %s"
+msgstr "doit être le propriétaire de la fonction %s"
-#: catalog/aclchk.c:3356
+#: catalog/aclchk.c:3365
#, c-format
msgid "must be owner of operator %s"
-msgstr "doit �tre le prorpri�taire de l'op�rateur %s"
+msgstr "doit être le prorpriétaire de l'opérateur %s"
-#: catalog/aclchk.c:3358
+#: catalog/aclchk.c:3367
#, c-format
msgid "must be owner of type %s"
-msgstr "doit �tre le propri�taire du type %s"
+msgstr "doit être le propriétaire du type %s"
-#: catalog/aclchk.c:3360
+#: catalog/aclchk.c:3369
#, c-format
msgid "must be owner of language %s"
-msgstr "doit �tre le propri�taire du langage %s"
+msgstr "doit être le propriétaire du langage %s"
-#: catalog/aclchk.c:3362
+#: catalog/aclchk.c:3371
#, c-format
msgid "must be owner of large object %s"
-msgstr "doit �tre le propri�taire du Large Object %s"
+msgstr "doit être le propriétaire du Large Object %s"
-#: catalog/aclchk.c:3364
+#: catalog/aclchk.c:3373
#, c-format
msgid "must be owner of schema %s"
-msgstr "doit �tre le propri�taire du sch�ma %s"
+msgstr "doit être le propriétaire du schéma %s"
-#: catalog/aclchk.c:3366
+#: catalog/aclchk.c:3375
#, c-format
msgid "must be owner of operator class %s"
-msgstr "doit �tre le propri�taire de la classe d'op�rateur %s"
+msgstr "doit être le propriétaire de la classe d'opérateur %s"
-#: catalog/aclchk.c:3368
+#: catalog/aclchk.c:3377
#, c-format
msgid "must be owner of operator family %s"
-msgstr "doit �tre le prorpri�taire de la famille d'op�rateur %s"
+msgstr "doit être le prorpriétaire de la famille d'opérateur %s"
-#: catalog/aclchk.c:3370
+#: catalog/aclchk.c:3379
#, c-format
msgid "must be owner of collation %s"
-msgstr "doit �tre le propri�taire du collationnement %s"
+msgstr "doit être le propriétaire du collationnement %s"
-#: catalog/aclchk.c:3372
+#: catalog/aclchk.c:3381
#, c-format
msgid "must be owner of conversion %s"
-msgstr "doit �tre le propri�taire de la conversion %s"
+msgstr "doit être le propriétaire de la conversion %s"
-#: catalog/aclchk.c:3374
+#: catalog/aclchk.c:3383
#, c-format
msgid "must be owner of tablespace %s"
-msgstr "doit �tre le propri�taire du tablespace %s"
+msgstr "doit être le propriétaire du tablespace %s"
-#: catalog/aclchk.c:3376
+#: catalog/aclchk.c:3385
#, c-format
msgid "must be owner of text search dictionary %s"
-msgstr "doit �tre le propri�taire du dictionnaire de recherche plein texte %s"
+msgstr "doit être le propriétaire du dictionnaire de recherche plein texte %s"
-#: catalog/aclchk.c:3378
+#: catalog/aclchk.c:3387
#, c-format
msgid "must be owner of text search configuration %s"
-msgstr "doit �tre le propri�taire de la configuration de recherche plein texte %s"
+msgstr "doit être le propriétaire de la configuration de recherche plein texte %s"
-#: catalog/aclchk.c:3380
+#: catalog/aclchk.c:3389
#, c-format
msgid "must be owner of foreign-data wrapper %s"
-msgstr "doit �tre le propri�taire du wrapper de donn�es distantes %s"
+msgstr "doit être le propriétaire du wrapper de données distantes %s"
-#: catalog/aclchk.c:3382
+#: catalog/aclchk.c:3391
#, c-format
msgid "must be owner of foreign server %s"
-msgstr "doit �tre le propri�taire de serveur distant %s"
+msgstr "doit être le propriétaire de serveur distant %s"
-#: catalog/aclchk.c:3384
+#: catalog/aclchk.c:3393
#, c-format
msgid "must be owner of event trigger %s"
-msgstr "doit �tre le propri�taire du trigger sur �v�nement %s"
+msgstr "doit être le propriétaire du trigger sur événement %s"
-#: catalog/aclchk.c:3386
+#: catalog/aclchk.c:3395
#, c-format
msgid "must be owner of extension %s"
-msgstr "doit �tre le propri�taire de l'extension %s"
+msgstr "doit être le propriétaire de l'extension %s"
-#: catalog/aclchk.c:3428
+#: catalog/aclchk.c:3437
#, c-format
msgid "permission denied for column \"%s\" of relation \"%s\""
-msgstr "droit refus� pour la colonne � %s � de la relation � %s �"
+msgstr "droit refusé pour la colonne « %s » de la relation « %s »"
-#: catalog/aclchk.c:3547 catalog/aclchk.c:3555
+#: catalog/aclchk.c:3556 catalog/aclchk.c:3564
#, c-format
msgid "attribute %d of relation with OID %u does not exist"
msgstr "l'attribut %d de la relation d'OID %u n'existe pas"
-#: catalog/aclchk.c:3628 catalog/aclchk.c:4542
+#: catalog/aclchk.c:3637 catalog/aclchk.c:4556
#, c-format
msgid "relation with OID %u does not exist"
msgstr "la relation d'OID %u n'existe pas"
-#: catalog/aclchk.c:3727 catalog/aclchk.c:4960
+#: catalog/aclchk.c:3736 catalog/aclchk.c:4974
#, c-format
msgid "database with OID %u does not exist"
-msgstr "la base de donn�es d'OID %u n'existe pas"
+msgstr "la base de données d'OID %u n'existe pas"
-#: catalog/aclchk.c:3781 catalog/aclchk.c:4620 tcop/fastpath.c:223
+#: catalog/aclchk.c:3790 catalog/aclchk.c:4634 tcop/fastpath.c:223
#, c-format
msgid "function with OID %u does not exist"
msgstr "la fonction d'OID %u n'existe pas"
-#: catalog/aclchk.c:3835 catalog/aclchk.c:4646
+#: catalog/aclchk.c:3844 catalog/aclchk.c:4660
#, c-format
msgid "language with OID %u does not exist"
msgstr "le langage d'OID %u n'existe pas"
-#: catalog/aclchk.c:3999 catalog/aclchk.c:4718
+#: catalog/aclchk.c:4008 catalog/aclchk.c:4732
#, c-format
msgid "schema with OID %u does not exist"
-msgstr "le sch�ma d'OID %u n'existe pas"
+msgstr "le schéma d'OID %u n'existe pas"
-#: catalog/aclchk.c:4053 catalog/aclchk.c:4745
+#: catalog/aclchk.c:4062 catalog/aclchk.c:4759
#, c-format
msgid "tablespace with OID %u does not exist"
msgstr "le tablespace d'OID %u n'existe pas"
-#: catalog/aclchk.c:4111 catalog/aclchk.c:4879 commands/foreigncmds.c:325
+#: catalog/aclchk.c:4121 catalog/aclchk.c:4893 commands/foreigncmds.c:325
#, c-format
msgid "foreign-data wrapper with OID %u does not exist"
-msgstr "le wrapper de donn�es distantes d'OID %u n'existe pas"
+msgstr "le wrapper de données distantes d'OID %u n'existe pas"
-#: catalog/aclchk.c:4172 catalog/aclchk.c:4906 commands/foreigncmds.c:461
+#: catalog/aclchk.c:4183 catalog/aclchk.c:4920 commands/foreigncmds.c:461
#, c-format
msgid "foreign server with OID %u does not exist"
msgstr "le serveur distant d'OID %u n'existe pas"
-#: catalog/aclchk.c:4231 catalog/aclchk.c:4245 catalog/aclchk.c:4568
+#: catalog/aclchk.c:4243 catalog/aclchk.c:4582
#, c-format
msgid "type with OID %u does not exist"
msgstr "le type d'OID %u n'existe pas"
-#: catalog/aclchk.c:4594
+#: catalog/aclchk.c:4608
#, c-format
msgid "operator with OID %u does not exist"
-msgstr "l'op�rateur d'OID %u n'existe pas"
+msgstr "l'opérateur d'OID %u n'existe pas"
-#: catalog/aclchk.c:4771
+#: catalog/aclchk.c:4785
#, c-format
msgid "operator class with OID %u does not exist"
-msgstr "la classe d'op�rateur d'OID %u n'existe pas"
+msgstr "la classe d'opérateur d'OID %u n'existe pas"
-#: catalog/aclchk.c:4798
+#: catalog/aclchk.c:4812
#, c-format
msgid "operator family with OID %u does not exist"
-msgstr "la famille d'op�rateur d'OID %u n'existe pas"
+msgstr "la famille d'opérateur d'OID %u n'existe pas"
-#: catalog/aclchk.c:4825
+#: catalog/aclchk.c:4839
#, c-format
msgid "text search dictionary with OID %u does not exist"
msgstr "le dictionnaire de recherche plein texte d'OID %u n'existe pas"
-#: catalog/aclchk.c:4852
+#: catalog/aclchk.c:4866
#, c-format
msgid "text search configuration with OID %u does not exist"
msgstr "la configuration de recherche plein texte d'OID %u n'existe pas"
-#: catalog/aclchk.c:4933 commands/event_trigger.c:587
+#: catalog/aclchk.c:4947 commands/event_trigger.c:587
#, c-format
msgid "event trigger with OID %u does not exist"
-msgstr "le trigger sur �v�nement d'OID %u n'existe pas"
+msgstr "le trigger sur événement d'OID %u n'existe pas"
-#: catalog/aclchk.c:4986
+#: catalog/aclchk.c:5000
#, c-format
msgid "collation with OID %u does not exist"
msgstr "le collationnement d'OID %u n'existe pas"
-#: catalog/aclchk.c:5012
+#: catalog/aclchk.c:5026
#, c-format
msgid "conversion with OID %u does not exist"
msgstr "la conversion d'OID %u n'existe pas"
-#: catalog/aclchk.c:5053
+#: catalog/aclchk.c:5067
#, c-format
msgid "extension with OID %u does not exist"
msgstr "l'extension d'OID %u n'existe pas"
-#: catalog/dependency.c:646
+#: catalog/dependency.c:645
#, c-format
msgid "cannot drop %s because %s requires it"
msgstr "n'a pas pu supprimer %s car il est requis par %s"
-#: catalog/dependency.c:649
+#: catalog/dependency.c:648
#, c-format
msgid "You can drop %s instead."
-msgstr "Vous pouvez supprimer %s � la place."
+msgstr "Vous pouvez supprimer %s à la place."
-#: catalog/dependency.c:811 catalog/pg_shdepend.c:576
+#: catalog/dependency.c:810 catalog/pg_shdepend.c:576
#, c-format
msgid "cannot drop %s because it is required by the database system"
-msgstr "n'a pas pu supprimer %s car il est requis par le syst�me de bases de donn�es"
+msgstr "n'a pas pu supprimer %s car il est requis par le système de bases de données"
-#: catalog/dependency.c:927
+#: catalog/dependency.c:926
#, c-format
msgid "drop auto-cascades to %s"
msgstr "DROP cascade automatiquement sur %s"
-#: catalog/dependency.c:939 catalog/dependency.c:948
+#: catalog/dependency.c:938 catalog/dependency.c:947
#, c-format
msgid "%s depends on %s"
-msgstr "%s d�pend de %s"
+msgstr "%s dépend de %s"
-#: catalog/dependency.c:960 catalog/dependency.c:969
+#: catalog/dependency.c:959 catalog/dependency.c:968
#, c-format
msgid "drop cascades to %s"
msgstr "DROP cascade sur %s"
-#: catalog/dependency.c:977 catalog/pg_shdepend.c:687
+#: catalog/dependency.c:976 catalog/pg_shdepend.c:687
#, c-format
msgid ""
"\n"
@@ -3527,321 +3596,331 @@ msgstr[1] ""
"\n"
"et %d autres objets (voir le journal applicatif du serveur pour une liste)"
-#: catalog/dependency.c:989
+#: catalog/dependency.c:988
#, c-format
msgid "cannot drop %s because other objects depend on it"
-msgstr "n'a pas pu supprimer %s car d'autres objets en d�pendent"
+msgstr "n'a pas pu supprimer %s car d'autres objets en dépendent"
-#: catalog/dependency.c:993 catalog/dependency.c:1000
+#: catalog/dependency.c:992 catalog/dependency.c:999
#, c-format
msgid "Use DROP ... CASCADE to drop the dependent objects too."
-msgstr "Utilisez DROP ... CASCADE pour supprimer aussi les objets d�pendants."
+msgstr "Utilisez DROP ... CASCADE pour supprimer aussi les objets dépendants."
-#: catalog/dependency.c:997
+#: catalog/dependency.c:996
#, c-format
msgid "cannot drop desired object(s) because other objects depend on them"
-msgstr "ne peut pas supprimer les objets d�sir�s car d'autres objets en d�pendent"
+msgstr "ne peut pas supprimer les objets désirés car d'autres objets en dépendent"
#. translator: %d always has a value larger than 1
-#: catalog/dependency.c:1006
+#: catalog/dependency.c:1005
#, c-format
msgid "drop cascades to %d other object"
msgid_plural "drop cascades to %d other objects"
msgstr[0] "DROP cascade sur %d autre objet"
msgstr[1] "DROP cascade sur %d autres objets"
-#: catalog/dependency.c:1634
+#: catalog/dependency.c:1633
#, c-format
msgid "constant of the type \"regrole\" cannot be used here"
-msgstr "une constante de type � regrole � ne peut pas �tre utilis�e ici"
+msgstr "une constante de type « regrole » ne peut pas être utilisée ici"
-#: catalog/heap.c:277
+#: catalog/heap.c:278
#, c-format
msgid "permission denied to create \"%s.%s\""
-msgstr "droit refus� pour cr�er � %s.%s �"
+msgstr "droit refusé pour créer « %s.%s »"
-#: catalog/heap.c:279
+#: catalog/heap.c:280
#, c-format
msgid "System catalog modifications are currently disallowed."
-msgstr "Les modifications du catalogue syst�me sont actuellement interdites."
+msgstr "Les modifications du catalogue système sont actuellement interdites."
-#: catalog/heap.c:414 commands/tablecmds.c:1438 commands/tablecmds.c:1895 commands/tablecmds.c:4819
+#: catalog/heap.c:415 commands/tablecmds.c:1439 commands/tablecmds.c:1896 commands/tablecmds.c:4820
#, c-format
msgid "tables can have at most %d columns"
msgstr "les tables peuvent avoir au plus %d colonnes"
-#: catalog/heap.c:431 commands/tablecmds.c:5080
+#: catalog/heap.c:432 commands/tablecmds.c:5081
#, c-format
msgid "column name \"%s\" conflicts with a system column name"
-msgstr "le nom de la colonne � %s � entre en conflit avec le nom d'une colonne syst�me"
+msgstr "le nom de la colonne « %s » entre en conflit avec le nom d'une colonne système"
-#: catalog/heap.c:447
+#: catalog/heap.c:448
#, c-format
msgid "column name \"%s\" specified more than once"
-msgstr "colonne � %s � sp�cifi�e plus d'une fois"
+msgstr "colonne « %s » spécifiée plus d'une fois"
-#: catalog/heap.c:497
+#: catalog/heap.c:498
#, c-format
msgid "column \"%s\" has type \"unknown\""
-msgstr "la colonne � %s � est de type � unknown �"
+msgstr "la colonne « %s » est de type « unknown »"
-#: catalog/heap.c:498
+#: catalog/heap.c:499
#, c-format
msgid "Proceeding with relation creation anyway."
-msgstr "Poursuit malgr� tout la cr�ation de la relation."
+msgstr "Poursuit malgré tout la création de la relation."
-#: catalog/heap.c:511
+#: catalog/heap.c:512
#, c-format
msgid "column \"%s\" has pseudo-type %s"
-msgstr "la colonne � %s � a le pseudo type %s"
+msgstr "la colonne « %s » a le pseudo type %s"
-#: catalog/heap.c:541
+#: catalog/heap.c:542
#, c-format
msgid "composite type %s cannot be made a member of itself"
-msgstr "le type composite %s ne peut pas �tre membre de lui-m�me"
+msgstr "le type composite %s ne peut pas être membre de lui-même"
-#: catalog/heap.c:583 commands/createas.c:373
+#: catalog/heap.c:584 commands/createas.c:201 commands/createas.c:498
#, c-format
msgid "no collation was derived for column \"%s\" with collatable type %s"
-msgstr "aucun collationnement n'a �t� d�riv� pour la colonne � %s � de type collationnable %s"
+msgstr "aucun collationnement n'a été dérivé pour la colonne « %s » de type collationnable %s"
-#: catalog/heap.c:585 commands/createas.c:375 commands/indexcmds.c:1132 commands/view.c:116 regex/regc_pg_locale.c:262 utils/adt/formatting.c:1513 utils/adt/formatting.c:1565 utils/adt/formatting.c:1633 utils/adt/formatting.c:1685 utils/adt/formatting.c:1754 utils/adt/formatting.c:1818 utils/adt/like.c:213 utils/adt/selfuncs.c:5330 utils/adt/varlena.c:1421 utils/adt/varlena.c:1826
+#: catalog/heap.c:586 commands/createas.c:204 commands/createas.c:501 commands/indexcmds.c:1132 commands/view.c:103 regex/regc_pg_locale.c:262 utils/adt/formatting.c:1513 utils/adt/formatting.c:1565 utils/adt/formatting.c:1633 utils/adt/formatting.c:1685 utils/adt/formatting.c:1754 utils/adt/formatting.c:1818 utils/adt/like.c:213 utils/adt/selfuncs.c:5334 utils/adt/varlena.c:1421 utils/adt/varlena.c:1826
#, c-format
msgid "Use the COLLATE clause to set the collation explicitly."
msgstr "Utilisez la clause COLLARE pour configurer explicitement le collationnement."
-#: catalog/heap.c:1066 catalog/index.c:792 commands/tablecmds.c:2622
+#: catalog/heap.c:1067 catalog/index.c:792 commands/tablecmds.c:2623
#, c-format
msgid "relation \"%s\" already exists"
-msgstr "la relation � %s � existe d�j�"
+msgstr "la relation « %s » existe déjà"
-#: catalog/heap.c:1082 catalog/pg_type.c:412 catalog/pg_type.c:722 commands/typecmds.c:237 commands/typecmds.c:784 commands/typecmds.c:1135 commands/typecmds.c:1357 commands/typecmds.c:2113
+#: catalog/heap.c:1083 catalog/pg_type.c:412 catalog/pg_type.c:722 commands/typecmds.c:237 commands/typecmds.c:784 commands/typecmds.c:1135 commands/typecmds.c:1357 commands/typecmds.c:2113
#, c-format
msgid "type \"%s\" already exists"
-msgstr "le type � %s � existe d�j�"
+msgstr "le type « %s » existe déjà"
-#: catalog/heap.c:1083
+#: catalog/heap.c:1084
#, c-format
msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type."
msgstr ""
-"Une relation a un type associ� du m�me nom, donc vous devez utiliser un nom\n"
+"Une relation a un type associé du même nom, donc vous devez utiliser un nom\n"
"qui n'entre pas en conflit avec un type existant."
-#: catalog/heap.c:1111
+#: catalog/heap.c:1112
#, c-format
msgid "pg_class heap OID value not set when in binary upgrade mode"
-msgstr "OID du heap de pg_class non configur� en mode de mise � jour binaire"
+msgstr "OID du heap de pg_class non configuré en mode de mise à jour binaire"
-#: catalog/heap.c:2289
+#: catalog/heap.c:2291
#, c-format
msgid "check constraint \"%s\" already exists"
-msgstr "la contrainte de v�rification � %s � existe d�j�"
+msgstr "la contrainte de vérification « %s » existe déjà"
-#: catalog/heap.c:2442 catalog/pg_constraint.c:654 commands/tablecmds.c:6068
+#: catalog/heap.c:2456 catalog/pg_constraint.c:654 commands/tablecmds.c:6069
#, c-format
msgid "constraint \"%s\" for relation \"%s\" already exists"
-msgstr "la contrainte � %s � de la relation � %s � existe d�j�"
+msgstr "la contrainte « %s » de la relation « %s » existe déjà"
-#: catalog/heap.c:2452
+#: catalog/heap.c:2463
#, c-format
msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\""
-msgstr "la contrainte � %s � entre en conflit avec la constrainte non h�rit�e sur la relation � %s �"
+msgstr "la contrainte « %s » entre en conflit avec la constrainte non héritée sur la relation « %s »"
+
+#: catalog/heap.c:2474
+#, c-format
+msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\""
+msgstr "la contrainte « %s » entre en conflit avec une contrainte héritée sur la relation « %s »"
+
+#: catalog/heap.c:2484
+#, c-format
+msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\""
+msgstr "la contrainte « %s » entre en conflit avec une contrainte NOT VALID sur la relation « %s »"
-#: catalog/heap.c:2466
+#: catalog/heap.c:2489
#, c-format
msgid "merging constraint \"%s\" with inherited definition"
-msgstr "assemblage de la contrainte � %s � avec une d�finition h�rit�e"
+msgstr "assemblage de la contrainte « %s » avec une définition héritée"
-#: catalog/heap.c:2559
+#: catalog/heap.c:2595
#, c-format
msgid "cannot use column references in default expression"
-msgstr "ne peut pas utiliser les r�f�rences de colonnes dans l'expression par d�faut"
+msgstr "ne peut pas utiliser les références de colonnes dans l'expression par défaut"
-#: catalog/heap.c:2570
+#: catalog/heap.c:2606
#, c-format
msgid "default expression must not return a set"
-msgstr "l'expression par d�faut ne doit pas renvoyer un ensemble"
+msgstr "l'expression par défaut ne doit pas renvoyer un ensemble"
-#: catalog/heap.c:2589 rewrite/rewriteHandler.c:1084
+#: catalog/heap.c:2625 rewrite/rewriteHandler.c:1084
#, c-format
msgid "column \"%s\" is of type %s but default expression is of type %s"
-msgstr "la colonne � %s � est de type %s alors que l'expression par d�faut est de type %s"
+msgstr "la colonne « %s » est de type %s alors que l'expression par défaut est de type %s"
-#: catalog/heap.c:2594 commands/prepare.c:374 parser/parse_node.c:428 parser/parse_target.c:528 parser/parse_target.c:778 parser/parse_target.c:788 rewrite/rewriteHandler.c:1089
+#: catalog/heap.c:2630 commands/prepare.c:374 parser/parse_node.c:428 parser/parse_target.c:539 parser/parse_target.c:789 parser/parse_target.c:799 rewrite/rewriteHandler.c:1089
#, c-format
msgid "You will need to rewrite or cast the expression."
-msgstr "Vous devez r��crire l'expression ou lui appliquer une transformation de type."
+msgstr "Vous devez réécrire l'expression ou lui appliquer une transformation de type."
-#: catalog/heap.c:2641
+#: catalog/heap.c:2677
#, c-format
msgid "only table \"%s\" can be referenced in check constraint"
-msgstr "seule la table � %s � peut �tre r�f�renc�e dans la contrainte de v�rification"
+msgstr "seule la table « %s » peut être référencée dans la contrainte de vérification"
-#: catalog/heap.c:2881
+#: catalog/heap.c:2917
#, c-format
msgid "unsupported ON COMMIT and foreign key combination"
-msgstr "combinaison ON COMMIT et cl� �trang�re non support�e"
+msgstr "combinaison ON COMMIT et clé étrangère non supportée"
-#: catalog/heap.c:2882
+#: catalog/heap.c:2918
#, c-format
msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting."
msgstr ""
-"La table � %s � r�f�rence � %s � mais elles n'ont pas la m�me valeur pour le\n"
-"param�tre ON COMMIT."
+"La table « %s » référence « %s » mais elles n'ont pas la même valeur pour le\n"
+"paramètre ON COMMIT."
-#: catalog/heap.c:2887
+#: catalog/heap.c:2923
#, c-format
msgid "cannot truncate a table referenced in a foreign key constraint"
-msgstr "ne peut pas tronquer une table r�f�renc�e dans une contrainte de cl� �trang�re"
+msgstr "ne peut pas tronquer une table référencée dans une contrainte de clé étrangère"
-#: catalog/heap.c:2888
+#: catalog/heap.c:2924
#, c-format
msgid "Table \"%s\" references \"%s\"."
-msgstr "La table � %s � r�f�rence � %s �."
+msgstr "La table « %s » référence « %s »."
-#: catalog/heap.c:2890
+#: catalog/heap.c:2926
#, c-format
msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE."
-msgstr "Tronquez la table � %s � en m�me temps, ou utilisez TRUNCATE ... CASCADE."
+msgstr "Tronquez la table « %s » en même temps, ou utilisez TRUNCATE ... CASCADE."
-#: catalog/index.c:210 parser/parse_utilcmd.c:1486 parser/parse_utilcmd.c:1572
+#: catalog/index.c:210 parser/parse_utilcmd.c:1473 parser/parse_utilcmd.c:1559
#, c-format
msgid "multiple primary keys for table \"%s\" are not allowed"
-msgstr "les cl�s primaires multiples ne sont pas autoris�es pour la table � %s �"
+msgstr "les clés primaires multiples ne sont pas autorisées pour la table « %s »"
#: catalog/index.c:228
#, c-format
msgid "primary keys cannot be expressions"
-msgstr "les cl�s primaires ne peuvent pas �tre des expressions"
+msgstr "les clés primaires ne peuvent pas être des expressions"
#: catalog/index.c:742 catalog/index.c:1160
#, c-format
msgid "user-defined indexes on system catalog tables are not supported"
-msgstr "les index d�finis par l'utilisateur sur les tables du catalogue syst�me ne sont pas support�s"
+msgstr "les index définis par l'utilisateur sur les tables du catalogue système ne sont pas supportés"
#: catalog/index.c:752
#, c-format
msgid "concurrent index creation on system catalog tables is not supported"
msgstr ""
-"la cr�ation en parall�le d'un index sur les tables du catalogue syst�me\n"
-"n'est pas support�e"
+"la création en parallèle d'un index sur les tables du catalogue système\n"
+"n'est pas supportée"
#: catalog/index.c:770
#, c-format
msgid "shared indexes cannot be created after initdb"
-msgstr "les index partag�s ne peuvent pas �tre cr��s apr�s initdb"
+msgstr "les index partagés ne peuvent pas être créés après initdb"
-#: catalog/index.c:784 commands/createas.c:100 commands/sequence.c:141 parser/parse_utilcmd.c:192
+#: catalog/index.c:784 commands/createas.c:249 commands/sequence.c:141 parser/parse_utilcmd.c:191
#, c-format
msgid "relation \"%s\" already exists, skipping"
-msgstr "la relation � %s � existe d�j�, poursuite du traitement"
+msgstr "la relation « %s » existe déjà, poursuite du traitement"
#: catalog/index.c:820
#, c-format
msgid "pg_class index OID value not set when in binary upgrade mode"
-msgstr "OID de l'index de pg_class non configur� en mode de mise � jour binaire"
+msgstr "OID de l'index de pg_class non configuré en mode de mise à jour binaire"
#: catalog/index.c:1422
#, c-format
msgid "DROP INDEX CONCURRENTLY must be first action in transaction"
-msgstr "DROP INDEX CONCURRENTLY doit �tre la premi�re action dans une transaction"
+msgstr "DROP INDEX CONCURRENTLY doit être la première action dans une transaction"
#: catalog/index.c:2004
#, c-format
msgid "building index \"%s\" on table \"%s\""
-msgstr "construction de l'index � %s � sur la table � %s �"
+msgstr "construction de l'index « %s » sur la table « %s »"
-#: catalog/index.c:3315
+#: catalog/index.c:3322
#, c-format
msgid "cannot reindex temporary tables of other sessions"
-msgstr "ne peut pas r�-indexer les tables temporaires des autres sessions"
+msgstr "ne peut pas ré-indexer les tables temporaires des autres sessions"
-#: catalog/index.c:3440
+#: catalog/index.c:3454
#, c-format
msgid "index \"%s\" was reindexed"
-msgstr "l'index � %s � a �t� r�index�e"
+msgstr "l'index « %s » a été réindexée"
-#: catalog/index.c:3442 commands/vacuumlazy.c:1323 commands/vacuumlazy.c:1399 commands/vacuumlazy.c:1588 commands/vacuumlazy.c:1789
+#: catalog/index.c:3456 commands/vacuumlazy.c:1338 commands/vacuumlazy.c:1414 commands/vacuumlazy.c:1603 commands/vacuumlazy.c:1813
#, c-format
msgid "%s."
msgstr "%s."
-#: catalog/namespace.c:249 catalog/namespace.c:447 catalog/namespace.c:541 commands/trigger.c:4527
+#: catalog/namespace.c:249 catalog/namespace.c:447 catalog/namespace.c:541 commands/trigger.c:4523
#, c-format
msgid "cross-database references are not implemented: \"%s.%s.%s\""
-msgstr "les r�f�rences entre bases de donn�es ne sont pas impl�ment�es : � %s.%s.%s �"
+msgstr "les références entre bases de données ne sont pas implémentées : « %s.%s.%s »"
#: catalog/namespace.c:306
#, c-format
msgid "temporary tables cannot specify a schema name"
-msgstr "les tables temporaires ne peuvent pas sp�cifier un nom de sch�ma"
+msgstr "les tables temporaires ne peuvent pas spécifier un nom de schéma"
#: catalog/namespace.c:385
#, c-format
msgid "could not obtain lock on relation \"%s.%s\""
-msgstr "n'a pas pu obtenir un verrou sur la relation � %s.%s �"
+msgstr "n'a pas pu obtenir un verrou sur la relation « %s.%s »"
#: catalog/namespace.c:390 commands/lockcmds.c:146
#, c-format
msgid "could not obtain lock on relation \"%s\""
-msgstr "n'a pas pu obtenir un verrou sur la relation � %s �"
+msgstr "n'a pas pu obtenir un verrou sur la relation « %s »"
-#: catalog/namespace.c:414 parser/parse_relation.c:1137
+#: catalog/namespace.c:414 parser/parse_relation.c:1138
#, c-format
msgid "relation \"%s.%s\" does not exist"
-msgstr "la relation � %s.%s � n'existe pas"
+msgstr "la relation « %s.%s » n'existe pas"
-#: catalog/namespace.c:419 parser/parse_relation.c:1150 parser/parse_relation.c:1158 utils/adt/regproc.c:1034
+#: catalog/namespace.c:419 parser/parse_relation.c:1151 parser/parse_relation.c:1159 utils/adt/regproc.c:1034
#, c-format
msgid "relation \"%s\" does not exist"
-msgstr "la relation � %s � n'existe pas"
+msgstr "la relation « %s » n'existe pas"
-#: catalog/namespace.c:487 catalog/namespace.c:2841 commands/extension.c:1382 commands/extension.c:1388
+#: catalog/namespace.c:487 catalog/namespace.c:2841 commands/extension.c:1383 commands/extension.c:1389
#, c-format
msgid "no schema has been selected to create in"
-msgstr "aucun sch�ma n'a �t� s�lectionn� pour cette cr�ation"
+msgstr "aucun schéma n'a été sélectionné pour cette création"
#: catalog/namespace.c:639 catalog/namespace.c:652
#, c-format
msgid "cannot create relations in temporary schemas of other sessions"
-msgstr "ne peut pas cr�er les relations dans les sch�mas temporaires d'autres sessions"
+msgstr "ne peut pas créer les relations dans les schémas temporaires d'autres sessions"
#: catalog/namespace.c:643
#, c-format
msgid "cannot create temporary relation in non-temporary schema"
-msgstr "ne peut pas cr�er une relation temporaire dans un sch�ma non temporaire"
+msgstr "ne peut pas créer une relation temporaire dans un schéma non temporaire"
#: catalog/namespace.c:658
#, c-format
msgid "only temporary relations may be created in temporary schemas"
-msgstr "seules les relations temporaires peuvent �tre cr��es dans des sch�mas temporaires"
+msgstr "seules les relations temporaires peuvent être créées dans des schémas temporaires"
#: catalog/namespace.c:2154
#, c-format
msgid "text search parser \"%s\" does not exist"
-msgstr "l'analyseur de recherche plein texte � %s � n'existe pas"
+msgstr "l'analyseur de recherche plein texte « %s » n'existe pas"
#: catalog/namespace.c:2280
#, c-format
msgid "text search dictionary \"%s\" does not exist"
-msgstr "le dictionnaire de recherche plein texte � %s � n'existe pas"
+msgstr "le dictionnaire de recherche plein texte « %s » n'existe pas"
#: catalog/namespace.c:2407
#, c-format
msgid "text search template \"%s\" does not exist"
-msgstr "le mod�le de recherche plein texte � %s � n'existe pas"
+msgstr "le modèle de recherche plein texte « %s » n'existe pas"
-#: catalog/namespace.c:2533 commands/tsearchcmds.c:1197 utils/cache/ts_cache.c:613
+#: catalog/namespace.c:2533 commands/tsearchcmds.c:1197 utils/cache/ts_cache.c:611
#, c-format
msgid "text search configuration \"%s\" does not exist"
-msgstr "la configuration de recherche plein texte � %s � n'existe pas"
+msgstr "la configuration de recherche plein texte « %s » n'existe pas"
-#: catalog/namespace.c:2646 parser/parse_expr.c:789 parser/parse_target.c:1130
+#: catalog/namespace.c:2646 parser/parse_expr.c:792 parser/parse_target.c:1141
#, c-format
msgid "cross-database references are not implemented: %s"
-msgstr "les r�f�rences entre bases de donn�es ne sont pas impl�ment�es : %s"
+msgstr "les références entre bases de données ne sont pas implémentées : %s"
-#: catalog/namespace.c:2652 gram.y:13434 gram.y:14791 parser/parse_expr.c:796 parser/parse_target.c:1137
+#: catalog/namespace.c:2652 gram.y:13450 gram.y:14819 parser/parse_expr.c:799 parser/parse_target.c:1148
#, c-format
msgid "improper qualified name (too many dotted names): %s"
msgstr "mauvaise qualification du nom (trop de points entre les noms) : %s"
@@ -3849,135 +3928,133 @@ msgstr "mauvaise qualification du nom (trop de points entre les noms) : %s"
#: catalog/namespace.c:2783
#, c-format
msgid "cannot move objects into or out of temporary schemas"
-msgstr "ne peut pas d�placer les objets dans ou � partir des sch�mas temporaires"
+msgstr "ne peut pas déplacer les objets dans ou à partir des schémas temporaires"
#: catalog/namespace.c:2789
#, c-format
msgid "cannot move objects into or out of TOAST schema"
-msgstr "ne peut pas d�placer les objets dans ou � partir des sch�mas TOAST"
+msgstr "ne peut pas déplacer les objets dans ou à partir des schémas TOAST"
-#: catalog/namespace.c:2862 commands/schemacmds.c:238 commands/schemacmds.c:317 commands/tablecmds.c:740
+#: catalog/namespace.c:2862 commands/schemacmds.c:238 commands/schemacmds.c:317 commands/tablecmds.c:741
#, c-format
msgid "schema \"%s\" does not exist"
-msgstr "le sch�ma � %s � n'existe pas"
+msgstr "le schéma « %s » n'existe pas"
#: catalog/namespace.c:2893
#, c-format
msgid "improper relation name (too many dotted names): %s"
msgstr "nom de relation incorrecte (trop de points entre les noms) : %s"
-#: catalog/namespace.c:3358
+#: catalog/namespace.c:3403
#, c-format
msgid "collation \"%s\" for encoding \"%s\" does not exist"
-msgstr "le collationnement � %s � pour l'encodage � %s � n'existe pas"
+msgstr "le collationnement « %s » pour l'encodage « %s » n'existe pas"
-#: catalog/namespace.c:3413
+#: catalog/namespace.c:3458
#, c-format
msgid "conversion \"%s\" does not exist"
-msgstr "la conversion � %s � n'existe pas"
+msgstr "la conversion « %s » n'existe pas"
-#: catalog/namespace.c:3621
+#: catalog/namespace.c:3666
#, c-format
msgid "permission denied to create temporary tables in database \"%s\""
-msgstr "droit refus� pour la cr�ation de tables temporaires dans la base de donn�es � %s �"
+msgstr "droit refusé pour la création de tables temporaires dans la base de données « %s »"
-#: catalog/namespace.c:3637
+#: catalog/namespace.c:3682
#, c-format
msgid "cannot create temporary tables during recovery"
-msgstr "ne peut pas cr�er des tables temporaires lors de la restauration"
+msgstr "ne peut pas créer des tables temporaires lors de la restauration"
-#: catalog/namespace.c:3643
+#: catalog/namespace.c:3688
#, c-format
msgid "cannot create temporary tables in parallel mode"
-msgstr "ne peut pas cr�er des tables temporaires dans le mode de parall�lisation"
+msgstr "ne peut pas créer des tables temporaires dans le mode de parallélisation"
-#: catalog/namespace.c:3887 commands/tablespace.c:1173 commands/variable.c:63 utils/misc/guc.c:9853
+#: catalog/namespace.c:3932 commands/tablespace.c:1173 commands/variable.c:63 utils/misc/guc.c:9875
#, c-format
msgid "List syntax is invalid."
msgstr "La syntaxe de la liste est invalide."
#: catalog/objectaddress.c:1065
-#, fuzzy
-#| msgid "schema name cannot be qualified"
msgid "access method name cannot be qualified"
-msgstr "le nom du sch�ma ne peut pas �tre qualifi�"
+msgstr "le nom de la méthode d'accès ne peut pas être qualifiée"
#: catalog/objectaddress.c:1068
msgid "database name cannot be qualified"
-msgstr "le nom de la base de donn�e ne peut �tre qualifi�"
+msgstr "le nom de la base de donnée ne peut être qualifié"
-#: catalog/objectaddress.c:1071 commands/extension.c:2506
+#: catalog/objectaddress.c:1071 commands/extension.c:2507
#, c-format
msgid "extension name cannot be qualified"
-msgstr "le nom de l'extension ne peut pas �tre qualifi�"
+msgstr "le nom de l'extension ne peut pas être qualifié"
#: catalog/objectaddress.c:1074
msgid "tablespace name cannot be qualified"
-msgstr "le nom du tablespace ne peut pas �tre qualifi�"
+msgstr "le nom du tablespace ne peut pas être qualifié"
#: catalog/objectaddress.c:1077
msgid "role name cannot be qualified"
-msgstr "le nom du r�le ne peut pas �tre qualifi�"
+msgstr "le nom du rôle ne peut pas être qualifié"
#: catalog/objectaddress.c:1080
msgid "schema name cannot be qualified"
-msgstr "le nom du sch�ma ne peut pas �tre qualifi�"
+msgstr "le nom du schéma ne peut pas être qualifié"
#: catalog/objectaddress.c:1083
msgid "language name cannot be qualified"
-msgstr "le nom du langage ne peut pas �tre qualifi�"
+msgstr "le nom du langage ne peut pas être qualifié"
#: catalog/objectaddress.c:1086
msgid "foreign-data wrapper name cannot be qualified"
-msgstr "le nom du wrapper de donn�es distantes ne peut pas �tre qualifi�"
+msgstr "le nom du wrapper de données distantes ne peut pas être qualifié"
#: catalog/objectaddress.c:1089
msgid "server name cannot be qualified"
-msgstr "le nom du serveur ne peut pas �tre qualifi�"
+msgstr "le nom du serveur ne peut pas être qualifié"
#: catalog/objectaddress.c:1092
msgid "event trigger name cannot be qualified"
-msgstr "le nom du trigger sur �v�nement ne peut pas �tre qualifi�"
+msgstr "le nom du trigger sur événement ne peut pas être qualifié"
-#: catalog/objectaddress.c:1210 commands/lockcmds.c:94 commands/policy.c:94 commands/policy.c:384 commands/policy.c:473 commands/tablecmds.c:217 commands/tablecmds.c:1299 commands/tablecmds.c:4346 commands/tablecmds.c:7977
+#: catalog/objectaddress.c:1210 commands/lockcmds.c:94 commands/policy.c:94 commands/policy.c:382 commands/policy.c:471 commands/tablecmds.c:218 commands/tablecmds.c:1300 commands/tablecmds.c:4347 commands/tablecmds.c:8017
#, c-format
msgid "\"%s\" is not a table"
-msgstr "� %s � n'est pas une table"
+msgstr "« %s » n'est pas une table"
-#: catalog/objectaddress.c:1217 commands/tablecmds.c:229 commands/tablecmds.c:4376 commands/tablecmds.c:12012 commands/view.c:155
+#: catalog/objectaddress.c:1217 commands/tablecmds.c:230 commands/tablecmds.c:4377 commands/tablecmds.c:12159 commands/view.c:141
#, c-format
msgid "\"%s\" is not a view"
-msgstr "� %s � n'est pas une vue"
+msgstr "« %s » n'est pas une vue"
-#: catalog/objectaddress.c:1224 commands/matview.c:174 commands/tablecmds.c:235 commands/tablecmds.c:12017
+#: catalog/objectaddress.c:1224 commands/matview.c:174 commands/tablecmds.c:236 commands/tablecmds.c:12164
#, c-format
msgid "\"%s\" is not a materialized view"
-msgstr "� %s � n'est pas une vue mat�rialis�e"
+msgstr "« %s » n'est pas une vue matérialisée"
-#: catalog/objectaddress.c:1231 commands/tablecmds.c:253 commands/tablecmds.c:4379 commands/tablecmds.c:12022
+#: catalog/objectaddress.c:1231 commands/tablecmds.c:254 commands/tablecmds.c:4380 commands/tablecmds.c:12169
#, c-format
msgid "\"%s\" is not a foreign table"
-msgstr "� %s � n'est pas une table distante"
+msgstr "« %s » n'est pas une table distante"
#: catalog/objectaddress.c:1376 catalog/objectaddress.c:1429
#, c-format
msgid "column name must be qualified"
-msgstr "le nom de la colonne doit �tre qualifi�"
+msgstr "le nom de la colonne doit être qualifié"
#: catalog/objectaddress.c:1472
#, c-format
msgid "default value for column \"%s\" of relation \"%s\" does not exist"
-msgstr "la valeur par d�faut de la colonne � %s � de la relation � %s � n'existe pas"
+msgstr "la valeur par défaut de la colonne « %s » de la relation « %s » n'existe pas"
-#: catalog/objectaddress.c:1512 commands/functioncmds.c:128 commands/tablecmds.c:245 commands/typecmds.c:3214 parser/parse_type.c:226 parser/parse_type.c:255 parser/parse_type.c:795 utils/adt/acl.c:4374 utils/adt/regproc.c:1225
+#: catalog/objectaddress.c:1512 commands/functioncmds.c:128 commands/tablecmds.c:246 commands/typecmds.c:3214 parser/parse_type.c:226 parser/parse_type.c:255 parser/parse_type.c:795 utils/adt/acl.c:4374 utils/adt/regproc.c:1225
#, c-format
msgid "type \"%s\" does not exist"
-msgstr "le type � %s � n'existe pas"
+msgstr "le type « %s » n'existe pas"
#: catalog/objectaddress.c:1629
#, c-format
msgid "operator %d (%s, %s) of %s does not exist"
-msgstr "l'op�rateur %d (%s, %s) de %s n'existe pas"
+msgstr "l'opérateur %d (%s, %s) de %s n'existe pas"
#: catalog/objectaddress.c:1658
#, c-format
@@ -3987,32 +4064,32 @@ msgstr "la fonction %d (%s, %s) de %s n'existe pas"
#: catalog/objectaddress.c:1707 catalog/objectaddress.c:1733
#, c-format
msgid "user mapping for user \"%s\" on server \"%s\" does not exist"
-msgstr "la correspondance pour l'utilisateur � %s � sur le serveur � %s � n'existe pas"
+msgstr "la correspondance pour l'utilisateur « %s » sur le serveur « %s » n'existe pas"
-#: catalog/objectaddress.c:1722 commands/foreigncmds.c:430 commands/foreigncmds.c:997 commands/foreigncmds.c:1359 foreign/foreign.c:798
+#: catalog/objectaddress.c:1722 commands/foreigncmds.c:430 commands/foreigncmds.c:997 commands/foreigncmds.c:1359 foreign/foreign.c:692
#, c-format
msgid "server \"%s\" does not exist"
-msgstr "le serveur � %s � n'existe pas"
+msgstr "le serveur « %s » n'existe pas"
#: catalog/objectaddress.c:1794
#, c-format
msgid "unrecognized default ACL object type %c"
-msgstr "type d'objet de droits par d�faut non reconnu %c"
+msgstr "type d'objet de droits par défaut non reconnu %c"
#: catalog/objectaddress.c:1795
#, c-format
msgid "Valid object types are \"r\", \"S\", \"f\", and \"T\"."
-msgstr "Les types d'objet valides sont � r �, � S �, � f � et � T �."
+msgstr "Les types d'objet valides sont « r », « S », « f » et « T »."
#: catalog/objectaddress.c:1841
#, c-format
msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist"
-msgstr "le droit par d�faut pour l'utilisateur � % s� dans le sch�ma � %s � de %s n'existe pas"
+msgstr "le droit par défaut pour l'utilisateur « % s» dans le schéma « %s » de %s n'existe pas"
#: catalog/objectaddress.c:1846
#, c-format
msgid "default ACL for user \"%s\" on %s does not exist"
-msgstr "le droit par d�faut pour l'utilisateur � %s � sur %s n'existe pas"
+msgstr "le droit par défaut pour l'utilisateur « %s » sur %s n'existe pas"
#: catalog/objectaddress.c:1873 catalog/objectaddress.c:1929 catalog/objectaddress.c:1984
#, c-format
@@ -4022,598 +4099,593 @@ msgstr "le nom ou les listes d'arguments ne peuvent pas contenir de valeurs NULL
#: catalog/objectaddress.c:1905
#, c-format
msgid "unsupported object type \"%s\""
-msgstr "type d'objet � %s � non support�"
+msgstr "type d'objet « %s » non supporté"
#: catalog/objectaddress.c:1925 catalog/objectaddress.c:1943
#, c-format
msgid "name list length must be exactly %d"
-msgstr "la liste de nom doit �tre exactement de longueur %d"
+msgstr "la liste de nom doit être exactement de longueur %d"
#: catalog/objectaddress.c:1947
#, c-format
msgid "large object OID may not be null"
-msgstr "l'OID du Large Object peut ne pas �tre NULL"
+msgstr "l'OID du Large Object peut ne pas être NULL"
#: catalog/objectaddress.c:1956 catalog/objectaddress.c:2016 catalog/objectaddress.c:2023
#, c-format
msgid "name list length must be at least %d"
-msgstr "la longueur de la liste de nom doit au moins �tre %d"
+msgstr "la longueur de la liste de nom doit au moins être %d"
#: catalog/objectaddress.c:2009 catalog/objectaddress.c:2029
#, c-format
msgid "argument list length must be exactly %d"
-msgstr "la longueur de la liste d'arguments doit �tre %d exactement"
+msgstr "la longueur de la liste d'arguments doit être %d exactement"
-#: catalog/objectaddress.c:2165 libpq/be-fsstubs.c:352
+#: catalog/objectaddress.c:2165 libpq/be-fsstubs.c:350
#, c-format
msgid "must be owner of large object %u"
-msgstr "doit �tre le propri�taire du Large Object %u"
+msgstr "doit être le propriétaire du Large Object %u"
#: catalog/objectaddress.c:2180 commands/functioncmds.c:1426
#, c-format
msgid "must be owner of type %s or type %s"
-msgstr "doit �tre le propri�taire du type %s ou du type %s"
+msgstr "doit être le propriétaire du type %s ou du type %s"
#: catalog/objectaddress.c:2220 catalog/objectaddress.c:2237
#, c-format
msgid "must be superuser"
-msgstr "doit �tre super-utilisateur"
+msgstr "doit être super-utilisateur"
#: catalog/objectaddress.c:2227
#, c-format
msgid "must have CREATEROLE privilege"
msgstr "doit avoir l'attribut CREATEROLE"
-#: catalog/objectaddress.c:2307
+#: catalog/objectaddress.c:2302
#, c-format
msgid "unrecognized object type \"%s\""
-msgstr "type d'objet non reconnu � %s �"
+msgstr "type d'objet non reconnu « %s »"
-#: catalog/objectaddress.c:2502
+#: catalog/objectaddress.c:2497
#, c-format
msgid " column %s"
msgstr " colonne %s"
-#: catalog/objectaddress.c:2508
+#: catalog/objectaddress.c:2503
#, c-format
msgid "function %s"
msgstr "fonction %s"
-#: catalog/objectaddress.c:2513
+#: catalog/objectaddress.c:2508
#, c-format
msgid "type %s"
msgstr "type %s"
-#: catalog/objectaddress.c:2543
+#: catalog/objectaddress.c:2538
#, c-format
msgid "cast from %s to %s"
msgstr "conversion de %s en %s"
-#: catalog/objectaddress.c:2563
+#: catalog/objectaddress.c:2558
#, c-format
msgid "collation %s"
msgstr "collationnement %s"
-#: catalog/objectaddress.c:2587
+#: catalog/objectaddress.c:2582
#, c-format
msgid "constraint %s on %s"
msgstr "contrainte %s sur %s"
-#: catalog/objectaddress.c:2593
+#: catalog/objectaddress.c:2588
#, c-format
msgid "constraint %s"
msgstr "contrainte %s"
-#: catalog/objectaddress.c:2610
+#: catalog/objectaddress.c:2605
#, c-format
msgid "conversion %s"
msgstr "conversion %s"
-#: catalog/objectaddress.c:2647
+#: catalog/objectaddress.c:2642
#, c-format
msgid "default for %s"
-msgstr "valeur par d�faut pour %s"
+msgstr "valeur par défaut pour %s"
-#: catalog/objectaddress.c:2656
+#: catalog/objectaddress.c:2651
#, c-format
msgid "language %s"
msgstr "langage %s"
-#: catalog/objectaddress.c:2661
+#: catalog/objectaddress.c:2656
#, c-format
msgid "large object %u"
-msgstr "� Large Object � %u"
+msgstr "« Large Object » %u"
-#: catalog/objectaddress.c:2666
+#: catalog/objectaddress.c:2661
#, c-format
msgid "operator %s"
-msgstr "op�rateur %s"
+msgstr "opérateur %s"
-#: catalog/objectaddress.c:2698
+#: catalog/objectaddress.c:2693
#, c-format
msgid "operator class %s for access method %s"
-msgstr "classe d'op�rateur %s pour la m�thode d'acc�s %s"
+msgstr "classe d'opérateur %s pour la méthode d'accès %s"
#. translator: %d is the operator strategy (a number), the
#. first two %s's are data type names, the third %s is the
#. description of the operator family, and the last %s is the
#. textual form of the operator with arguments.
-#: catalog/objectaddress.c:2748
+#: catalog/objectaddress.c:2743
#, c-format
msgid "operator %d (%s, %s) of %s: %s"
-msgstr "op�rateur %d (%s, %s) de %s : %s"
+msgstr "opérateur %d (%s, %s) de %s : %s"
#. translator: %d is the function number, the first two %s's
#. are data type names, the third %s is the description of the
#. operator family, and the last %s is the textual form of the
#. function with arguments.
-#: catalog/objectaddress.c:2798
+#: catalog/objectaddress.c:2793
#, c-format
msgid "function %d (%s, %s) of %s: %s"
msgstr "fonction %d (%s, %s) de %s : %s"
-#: catalog/objectaddress.c:2838
+#: catalog/objectaddress.c:2833
#, c-format
msgid "rule %s on "
-msgstr "r�gle %s active "
+msgstr "règle %s active "
-#: catalog/objectaddress.c:2860
+#: catalog/objectaddress.c:2855
#, c-format
msgid "transform for %s language %s"
msgstr "transformation pour %s langage %s"
-#: catalog/objectaddress.c:2894
+#: catalog/objectaddress.c:2889
#, c-format
msgid "trigger %s on "
msgstr "trigger %s actif "
-#: catalog/objectaddress.c:2911
+#: catalog/objectaddress.c:2906
#, c-format
msgid "schema %s"
-msgstr "sch�ma %s"
+msgstr "schéma %s"
-#: catalog/objectaddress.c:2924
+#: catalog/objectaddress.c:2919
#, c-format
msgid "text search parser %s"
msgstr "analyseur %s de la recherche plein texte"
-#: catalog/objectaddress.c:2939
+#: catalog/objectaddress.c:2934
#, c-format
msgid "text search dictionary %s"
msgstr "dictionnaire %s de la recherche plein texte"
-#: catalog/objectaddress.c:2954
+#: catalog/objectaddress.c:2949
#, c-format
msgid "text search template %s"
-msgstr "mod�le %s de la recherche plein texte"
+msgstr "modèle %s de la recherche plein texte"
-#: catalog/objectaddress.c:2969
+#: catalog/objectaddress.c:2964
#, c-format
msgid "text search configuration %s"
msgstr "configuration %s de recherche plein texte"
-#: catalog/objectaddress.c:2977
+#: catalog/objectaddress.c:2972
#, c-format
msgid "role %s"
-msgstr "r�le %s"
+msgstr "rôle %s"
-#: catalog/objectaddress.c:2990
+#: catalog/objectaddress.c:2985
#, c-format
msgid "database %s"
-msgstr "base de donn�es %s"
+msgstr "base de données %s"
-#: catalog/objectaddress.c:3002
+#: catalog/objectaddress.c:2997
#, c-format
msgid "tablespace %s"
msgstr "tablespace %s"
-#: catalog/objectaddress.c:3011
+#: catalog/objectaddress.c:3006
#, c-format
msgid "foreign-data wrapper %s"
-msgstr "wrapper de donn�es distantes %s"
+msgstr "wrapper de données distantes %s"
-#: catalog/objectaddress.c:3020
+#: catalog/objectaddress.c:3015
#, c-format
msgid "server %s"
msgstr "serveur %s"
-#: catalog/objectaddress.c:3048
+#: catalog/objectaddress.c:3043
#, c-format
msgid "user mapping for %s on server %s"
msgstr "correspondance utilisateur pour %s sur le serveur %s"
-#: catalog/objectaddress.c:3083
+#: catalog/objectaddress.c:3078
#, c-format
msgid "default privileges on new relations belonging to role %s"
-msgstr "droits par d�faut pour les nouvelles relations appartenant au r�le %s"
+msgstr "droits par défaut pour les nouvelles relations appartenant au rôle %s"
-#: catalog/objectaddress.c:3088
+#: catalog/objectaddress.c:3083
#, c-format
msgid "default privileges on new sequences belonging to role %s"
-msgstr "droits par d�faut pour les nouvelles s�quences appartenant au r�le %s"
+msgstr "droits par défaut pour les nouvelles séquences appartenant au rôle %s"
-#: catalog/objectaddress.c:3093
+#: catalog/objectaddress.c:3088
#, c-format
msgid "default privileges on new functions belonging to role %s"
-msgstr "droits par d�faut pour les nouvelles fonctions appartenant au r�le %s"
+msgstr "droits par défaut pour les nouvelles fonctions appartenant au rôle %s"
-#: catalog/objectaddress.c:3098
+#: catalog/objectaddress.c:3093
#, c-format
msgid "default privileges on new types belonging to role %s"
-msgstr "droits par d�faut pour les nouveaux types appartenant au r�le %s"
+msgstr "droits par défaut pour les nouveaux types appartenant au rôle %s"
-#: catalog/objectaddress.c:3104
+#: catalog/objectaddress.c:3099
#, c-format
msgid "default privileges belonging to role %s"
-msgstr "droits par d�faut appartenant au r�le %s"
+msgstr "droits par défaut appartenant au rôle %s"
-#: catalog/objectaddress.c:3112
+#: catalog/objectaddress.c:3107
#, c-format
msgid " in schema %s"
-msgstr " dans le sch�ma %s"
+msgstr " dans le schéma %s"
-#: catalog/objectaddress.c:3129
+#: catalog/objectaddress.c:3124
#, c-format
msgid "extension %s"
msgstr "extension %s"
-#: catalog/objectaddress.c:3142
+#: catalog/objectaddress.c:3137
#, c-format
msgid "event trigger %s"
-msgstr "trigger sur �v�nement %s"
+msgstr "trigger sur événement %s"
-#: catalog/objectaddress.c:3174
+#: catalog/objectaddress.c:3169
#, c-format
msgid "policy %s on "
msgstr "politique %s sur "
-#: catalog/objectaddress.c:3192
-#, fuzzy, c-format
-#| msgid "access to %s"
+#: catalog/objectaddress.c:3187
+#, c-format
msgid "access method %s"
-msgstr "acc�s � %s"
+msgstr "méthode d'accès %s"
-#: catalog/objectaddress.c:3252
+#: catalog/objectaddress.c:3247
#, c-format
msgid "table %s"
msgstr "table %s"
-#: catalog/objectaddress.c:3256
+#: catalog/objectaddress.c:3251
#, c-format
msgid "index %s"
msgstr "index %s"
-#: catalog/objectaddress.c:3260
+#: catalog/objectaddress.c:3255
#, c-format
msgid "sequence %s"
-msgstr "s�quence %s"
+msgstr "séquence %s"
-#: catalog/objectaddress.c:3264
+#: catalog/objectaddress.c:3259
#, c-format
msgid "toast table %s"
msgstr "table TOAST %s"
-#: catalog/objectaddress.c:3268
+#: catalog/objectaddress.c:3263
#, c-format
msgid "view %s"
msgstr "vue %s"
-#: catalog/objectaddress.c:3272
+#: catalog/objectaddress.c:3267
#, c-format
msgid "materialized view %s"
-msgstr "vue mat�rialis�e %s"
+msgstr "vue matérialisée %s"
-#: catalog/objectaddress.c:3276
+#: catalog/objectaddress.c:3271
#, c-format
msgid "composite type %s"
msgstr "type composite %s"
-#: catalog/objectaddress.c:3280
+#: catalog/objectaddress.c:3275
#, c-format
msgid "foreign table %s"
msgstr "table distante %s"
-#: catalog/objectaddress.c:3285
+#: catalog/objectaddress.c:3280
#, c-format
msgid "relation %s"
msgstr "relation %s"
-#: catalog/objectaddress.c:3322
+#: catalog/objectaddress.c:3317
#, c-format
msgid "operator family %s for access method %s"
-msgstr "famille d'op�rateur %s pour la m�thode d'acc�s %s"
+msgstr "famille d'opérateur %s pour la méthode d'accès %s"
-#: catalog/pg_aggregate.c:126
+#: catalog/pg_aggregate.c:125
#, c-format
msgid "aggregates cannot have more than %d argument"
msgid_plural "aggregates cannot have more than %d arguments"
-msgstr[0] "les agr�gats ne peuvent avoir plus de %d argument"
-msgstr[1] "les agr�gats ne peuvent avoir plus de %d arguments"
+msgstr[0] "les agrégats ne peuvent avoir plus de %d argument"
+msgstr[1] "les agrégats ne peuvent avoir plus de %d arguments"
-#: catalog/pg_aggregate.c:149 catalog/pg_aggregate.c:159
+#: catalog/pg_aggregate.c:148 catalog/pg_aggregate.c:158
#, c-format
msgid "cannot determine transition data type"
-msgstr "n'a pas pu d�terminer le type de donn�es de transition"
+msgstr "n'a pas pu déterminer le type de données de transition"
-#: catalog/pg_aggregate.c:150 catalog/pg_aggregate.c:160
+#: catalog/pg_aggregate.c:149 catalog/pg_aggregate.c:159
#, c-format
msgid "An aggregate using a polymorphic transition type must have at least one polymorphic argument."
msgstr ""
-"Un agr�gat utilisant un type de transition polymorphique doit avoir au moins\n"
+"Un agrégat utilisant un type de transition polymorphique doit avoir au moins\n"
"un argument polymorphique."
-#: catalog/pg_aggregate.c:173
+#: catalog/pg_aggregate.c:172
#, c-format
msgid "a variadic ordered-set aggregate must use VARIADIC type ANY"
-msgstr "un agr�gat � ensemble tri� variadique doit �tre VARIADIC sur le type ANY"
+msgstr "un agrégat à ensemble trié variadique doit être VARIADIC sur le type ANY"
-#: catalog/pg_aggregate.c:199
+#: catalog/pg_aggregate.c:198
#, c-format
msgid "a hypothetical-set aggregate must have direct arguments matching its aggregated arguments"
-msgstr "un agr�gat � ensemble hypoth�tique doit avoir des arguments directs correspondant aux arguments agr�g�s"
+msgstr "un agrégat à ensemble hypothétique doit avoir des arguments directs correspondant aux arguments agrégés"
-#: catalog/pg_aggregate.c:246 catalog/pg_aggregate.c:290
+#: catalog/pg_aggregate.c:245 catalog/pg_aggregate.c:289
#, c-format
msgid "return type of transition function %s is not %s"
msgstr "le type de retour de la fonction de transition %s n'est pas %s"
-#: catalog/pg_aggregate.c:266 catalog/pg_aggregate.c:309
+#: catalog/pg_aggregate.c:265 catalog/pg_aggregate.c:308
#, c-format
msgid "must not omit initial value when transition function is strict and transition type is not compatible with input type"
msgstr ""
"ne doit pas omettre la valeur initiale lorsque la fonction de transition est\n"
"stricte et que le type de transition n'est pas compatible avec le type en\n"
-"entr�e"
+"entrée"
-#: catalog/pg_aggregate.c:335
+#: catalog/pg_aggregate.c:334
#, c-format
msgid "return type of inverse transition function %s is not %s"
msgstr "le type de retour de la fonction de transition inverse %s n'est pas %s"
-#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2305
+#: catalog/pg_aggregate.c:351 executor/nodeWindowAgg.c:2334
#, c-format
msgid "strictness of aggregate's forward and inverse transition functions must match"
-msgstr "la fonction de transition d'agr�gat en d�placement ne doit pas renvoyer null"
+msgstr "la fonction de transition d'agrégat en déplacement ne doit pas renvoyer null"
-#: catalog/pg_aggregate.c:396 catalog/pg_aggregate.c:547
+#: catalog/pg_aggregate.c:395 catalog/pg_aggregate.c:545
#, c-format
msgid "final function with extra arguments must not be declared STRICT"
-msgstr "la fonction finale avec des arguments suppl�mentaires ne doit pas �tre d�clar�e avec la clause STRICT"
+msgstr "la fonction finale avec des arguments supplémentaires ne doit pas être déclarée avec la clause STRICT"
-#: catalog/pg_aggregate.c:426
-#, fuzzy, c-format
-#| msgid "return type of transition function %s is not %s"
+#: catalog/pg_aggregate.c:425
+#, c-format
msgid "return type of combine function %s is not %s"
-msgstr "le type de retour de la fonction de transition %s n'est pas %s"
+msgstr "le type de retour de la fonction de d'unification %s n'est pas %s"
-#: catalog/pg_aggregate.c:437
-#, fuzzy, c-format
-#| msgid "final function with extra arguments must not be declared STRICT"
+#: catalog/pg_aggregate.c:436
+#, c-format
msgid "combine function with \"%s\" transition type must not be declared STRICT"
-msgstr "la fonction finale avec des arguments suppl�mentaires ne doit pas �tre d�clar�e avec la clause STRICT"
+msgstr "la fonction d'unification avec le type de transaction «%s » ne doit pas être déclaré STRICT"
-#: catalog/pg_aggregate.c:457
-#, fuzzy, c-format
-#| msgid "return type of transition function %s is not %s"
+#: catalog/pg_aggregate.c:455
+#, c-format
msgid "return type of serialization function %s is not %s"
-msgstr "le type de retour de la fonction de transition %s n'est pas %s"
+msgstr "le type de retour de la fonction de sérialisation %s n'est pas %s"
-#: catalog/pg_aggregate.c:477
-#, fuzzy, c-format
-#| msgid "return type of transition function %s is not %s"
+#: catalog/pg_aggregate.c:475
+#, c-format
msgid "return type of deserialization function %s is not %s"
-msgstr "le type de retour de la fonction de transition %s n'est pas %s"
+msgstr "le type de retour de la fonction de désérialisation %s n'est pas %s"
-#: catalog/pg_aggregate.c:493 catalog/pg_proc.c:246 catalog/pg_proc.c:253
+#: catalog/pg_aggregate.c:491 catalog/pg_proc.c:246 catalog/pg_proc.c:253
#, c-format
msgid "cannot determine result data type"
-msgstr "n'a pas pu d�terminer le type de donn�es en r�sultat"
+msgstr "n'a pas pu déterminer le type de données en résultat"
-#: catalog/pg_aggregate.c:494
+#: catalog/pg_aggregate.c:492
#, c-format
msgid "An aggregate returning a polymorphic type must have at least one polymorphic argument."
msgstr ""
-"Un agr�gat renvoyant un type polymorphique doit avoir au moins un argument\n"
+"Un agrégat renvoyant un type polymorphique doit avoir au moins un argument\n"
"de type polymorphique."
-#: catalog/pg_aggregate.c:506 catalog/pg_proc.c:259
+#: catalog/pg_aggregate.c:504 catalog/pg_proc.c:259
#, c-format
msgid "unsafe use of pseudo-type \"internal\""
-msgstr "utilisation non s�re des pseudo-types � INTERNAL �"
+msgstr "utilisation non sûre des pseudo-types « INTERNAL »"
-#: catalog/pg_aggregate.c:507 catalog/pg_proc.c:260
+#: catalog/pg_aggregate.c:505 catalog/pg_proc.c:260
#, c-format
msgid "A function returning \"internal\" must have at least one \"internal\" argument."
msgstr ""
-"Une fonction renvoyant � internal � doit avoir au moins un argument du type\n"
-"� internal �."
+"Une fonction renvoyant « internal » doit avoir au moins un argument du type\n"
+"« internal »."
-#: catalog/pg_aggregate.c:560
+#: catalog/pg_aggregate.c:558
#, c-format
msgid "moving-aggregate implementation returns type %s, but plain implementation returns type %s"
-msgstr ""
+msgstr "l'impémentation d'aggrégat glissant retourne le type %s, mais l'implémentation standard retourne le type %s"
-#: catalog/pg_aggregate.c:571
+#: catalog/pg_aggregate.c:569
#, c-format
msgid "sort operator can only be specified for single-argument aggregates"
-msgstr "l'op�rateur de tri peut seulement �tre indiqu� pour des agr�gats � un seul argument"
+msgstr "l'opérateur de tri peut seulement être indiqué pour des agrégats à un seul argument"
-#: catalog/pg_aggregate.c:816 commands/typecmds.c:1705 commands/typecmds.c:1756 commands/typecmds.c:1787 commands/typecmds.c:1810 commands/typecmds.c:1831 commands/typecmds.c:1858 commands/typecmds.c:1885 commands/typecmds.c:1962 commands/typecmds.c:2004 parser/parse_func.c:364 parser/parse_func.c:393 parser/parse_func.c:418 parser/parse_func.c:432 parser/parse_func.c:507 parser/parse_func.c:518 parser/parse_func.c:1921
+#: catalog/pg_aggregate.c:812 commands/typecmds.c:1705 commands/typecmds.c:1756 commands/typecmds.c:1787 commands/typecmds.c:1810 commands/typecmds.c:1831 commands/typecmds.c:1858 commands/typecmds.c:1885 commands/typecmds.c:1962 commands/typecmds.c:2004 parser/parse_func.c:364 parser/parse_func.c:393 parser/parse_func.c:418 parser/parse_func.c:432 parser/parse_func.c:507 parser/parse_func.c:518 parser/parse_func.c:1923
#, c-format
msgid "function %s does not exist"
msgstr "la fonction %s n'existe pas"
-#: catalog/pg_aggregate.c:822
+#: catalog/pg_aggregate.c:818
#, c-format
msgid "function %s returns a set"
msgstr "la fonction %s renvoie un ensemble"
-#: catalog/pg_aggregate.c:837
+#: catalog/pg_aggregate.c:833
#, c-format
msgid "function %s must accept VARIADIC ANY to be used in this aggregate"
-msgstr "la fonction %s doit accepter VARIADIC ANY pour �tre utilis� dans cet agr�gat"
+msgstr "la fonction %s doit accepter VARIADIC ANY pour être utilisé dans cet agrégat"
-#: catalog/pg_aggregate.c:861
+#: catalog/pg_aggregate.c:857
#, c-format
msgid "function %s requires run-time type coercion"
-msgstr "la fonction %s requiert une coercion sur le type � l'ex�cution"
+msgstr "la fonction %s requiert une coercion sur le type à l'exécution"
#: catalog/pg_collation.c:77
#, c-format
msgid "collation \"%s\" for encoding \"%s\" already exists"
-msgstr "le collationnement � %s � pour l'encodage � %s � existe d�j�"
+msgstr "le collationnement « %s » pour l'encodage « %s » existe déjà"
#: catalog/pg_collation.c:91
#, c-format
msgid "collation \"%s\" already exists"
-msgstr "le collationnement � %s � existe d�j�"
+msgstr "le collationnement « %s » existe déjà"
#: catalog/pg_constraint.c:663
#, c-format
msgid "constraint \"%s\" for domain %s already exists"
-msgstr "la contrainte � %s � du domaine %s existe d�j�"
+msgstr "la contrainte « %s » du domaine %s existe déjà"
#: catalog/pg_constraint.c:797
#, c-format
msgid "table \"%s\" has multiple constraints named \"%s\""
-msgstr "la table � %s � a de nombreuses contraintes nomm�es � %s �"
+msgstr "la table « %s » a de nombreuses contraintes nommées « %s »"
#: catalog/pg_constraint.c:809
#, c-format
msgid "constraint \"%s\" for table \"%s\" does not exist"
-msgstr "la contrainte � %s � de la table � %s � n'existe pas"
+msgstr "la contrainte « %s » de la table « %s » n'existe pas"
#: catalog/pg_constraint.c:855
#, c-format
msgid "domain \"%s\" has multiple constraints named \"%s\""
-msgstr "le domaine � %s � a plusieurs contraintes nomm�es � %s �"
+msgstr "le domaine « %s » a plusieurs contraintes nommées « %s »"
#: catalog/pg_constraint.c:867
#, c-format
msgid "constraint \"%s\" for domain \"%s\" does not exist"
-msgstr "la contrainte � %s � du domaine � %s � n'existe pas"
+msgstr "la contrainte « %s » du domaine « %s » n'existe pas"
#: catalog/pg_conversion.c:66
#, c-format
msgid "conversion \"%s\" already exists"
-msgstr "la conversion � %s � existe d�j�"
+msgstr "la conversion « %s » existe déjà"
#: catalog/pg_conversion.c:79
#, c-format
msgid "default conversion for %s to %s already exists"
-msgstr "la conversion par d�faut de %s vers %s existe d�j�"
+msgstr "la conversion par défaut de %s vers %s existe déjà"
-#: catalog/pg_depend.c:165 commands/extension.c:3028
+#: catalog/pg_depend.c:165 commands/extension.c:3029
#, c-format
msgid "%s is already a member of extension \"%s\""
-msgstr "%s est d�j� un membre de l'extension � %s �"
+msgstr "%s est déjà un membre de l'extension « %s »"
#: catalog/pg_depend.c:324
#, c-format
msgid "cannot remove dependency on %s because it is a system object"
-msgstr "ne peut pas supprimer la d�pendance sur %s car il s'agit d'un objet syst�me"
+msgstr "ne peut pas supprimer la dépendance sur %s car il s'agit d'un objet système"
#: catalog/pg_enum.c:115 catalog/pg_enum.c:202
#, c-format
msgid "invalid enum label \"%s\""
-msgstr "nom du label enum � %s � invalide"
+msgstr "nom du label enum « %s » invalide"
#: catalog/pg_enum.c:116 catalog/pg_enum.c:203
#, c-format
msgid "Labels must be %d characters or less."
-msgstr "Les labels doivent avoir au plus %d caract�res"
+msgstr "Les labels doivent avoir au plus %d caractères"
#: catalog/pg_enum.c:231
#, c-format
msgid "enum label \"%s\" already exists, skipping"
-msgstr "le label � %s � existe d�j�, poursuite du traitement"
+msgstr "le label « %s » existe déjà, poursuite du traitement"
#: catalog/pg_enum.c:238
#, c-format
msgid "enum label \"%s\" already exists"
-msgstr "le label � %s � existe d�j�"
+msgstr "le label « %s » existe déjà"
#: catalog/pg_enum.c:293
#, c-format
msgid "\"%s\" is not an existing enum label"
-msgstr "� %s � n'est pas un label enum existant"
+msgstr "« %s » n'est pas un label enum existant"
#: catalog/pg_enum.c:349
#, c-format
msgid "pg_enum OID value not set when in binary upgrade mode"
-msgstr "OID de pg_enum non configur� en mode de mise � jour binaire"
+msgstr "OID de pg_enum non configuré en mode de mise à jour binaire"
#: catalog/pg_enum.c:359
#, c-format
msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade"
-msgstr "ALTER TYPE ADD BEFORE/AFTER est incompatible avec la mise � jour binaire"
+msgstr "ALTER TYPE ADD BEFORE/AFTER est incompatible avec la mise à jour binaire"
#: catalog/pg_namespace.c:61 commands/schemacmds.c:246
#, c-format
msgid "schema \"%s\" already exists"
-msgstr "le sch�ma � %s � existe d�j�"
+msgstr "le schéma « %s » existe déjà"
#: catalog/pg_operator.c:219 catalog/pg_operator.c:360
#, c-format
msgid "\"%s\" is not a valid operator name"
-msgstr "� %s � n'est pas un nom d'op�rateur valide"
+msgstr "« %s » n'est pas un nom d'opérateur valide"
#: catalog/pg_operator.c:369
#, c-format
msgid "only binary operators can have commutators"
-msgstr "seuls les op�rateurs binaires peuvent avoir des commutateurs"
+msgstr "seuls les opérateurs binaires peuvent avoir des commutateurs"
#: catalog/pg_operator.c:373 commands/operatorcmds.c:485
#, c-format
msgid "only binary operators can have join selectivity"
-msgstr "seuls les op�rateurs binaires peuvent avoir une s�lectivit� des jointures"
+msgstr "seuls les opérateurs binaires peuvent avoir une sélectivité des jointures"
#: catalog/pg_operator.c:377
#, c-format
msgid "only binary operators can merge join"
-msgstr "seuls les op�rateurs binaires peuvent ex�cuter des jointures MERGE"
+msgstr "seuls les opérateurs binaires peuvent exécuter des jointures MERGE"
#: catalog/pg_operator.c:381
#, c-format
msgid "only binary operators can hash"
-msgstr "seuls les op�rateurs binaires ont du hachage"
+msgstr "seuls les opérateurs binaires ont du hachage"
#: catalog/pg_operator.c:392
#, c-format
msgid "only boolean operators can have negators"
-msgstr "seuls les op�rateurs bool�ens peuvent avoir des n�gations"
+msgstr "seuls les opérateurs booléens peuvent avoir des négations"
#: catalog/pg_operator.c:396 commands/operatorcmds.c:493
#, c-format
msgid "only boolean operators can have restriction selectivity"
-msgstr "seuls les op�rateurs bool�ens peuvent avoir une s�lectivit� des restrictions"
+msgstr "seuls les opérateurs booléens peuvent avoir une sélectivité des restrictions"
#: catalog/pg_operator.c:400 commands/operatorcmds.c:497
#, c-format
msgid "only boolean operators can have join selectivity"
-msgstr "seuls les op�rateurs bool�ens peuvent avoir une s�lectivit� des jointures"
+msgstr "seuls les opérateurs booléens peuvent avoir une sélectivité des jointures"
#: catalog/pg_operator.c:404
#, c-format
msgid "only boolean operators can merge join"
-msgstr "seuls les op�rateurs bool�ens peuvent ex�cuter des jointures MERGE"
+msgstr "seuls les opérateurs booléens peuvent exécuter des jointures MERGE"
#: catalog/pg_operator.c:408
#, c-format
msgid "only boolean operators can hash"
-msgstr "seuls les op�rateurs bool�ens peuvent hacher"
+msgstr "seuls les opérateurs booléens peuvent hacher"
#: catalog/pg_operator.c:420
#, c-format
msgid "operator %s already exists"
-msgstr "l'op�rateur %s existe d�j�"
+msgstr "l'opérateur %s existe déjà"
#: catalog/pg_operator.c:617
#, c-format
msgid "operator cannot be its own negator or sort operator"
-msgstr "l'op�rateur ne peut pas �tre son propre op�rateur de n�gation ou de tri"
+msgstr "l'opérateur ne peut pas être son propre opérateur de négation ou de tri"
-#: catalog/pg_proc.c:134 parser/parse_func.c:1945 parser/parse_func.c:1985
+#: catalog/pg_proc.c:134 parser/parse_func.c:1947 parser/parse_func.c:1987
#, c-format
msgid "functions cannot have more than %d argument"
msgid_plural "functions cannot have more than %d arguments"
@@ -4630,17 +4702,17 @@ msgstr ""
#: catalog/pg_proc.c:254
#, c-format
msgid "A function returning \"anyrange\" must have at least one \"anyrange\" argument."
-msgstr "Une fonction renvoyant � anyrange � doit avoir au moins un argument du type � anyrange �."
+msgstr "Une fonction renvoyant « anyrange » doit avoir au moins un argument du type « anyrange »."
#: catalog/pg_proc.c:272
#, c-format
msgid "\"%s\" is already an attribute of type %s"
-msgstr "� %s � est d�j� un attribut du type %s"
+msgstr "« %s » est déjà un attribut du type %s"
#: catalog/pg_proc.c:403
#, c-format
msgid "function \"%s\" already exists with same argument types"
-msgstr "la fonction � %s � existe d�j� avec des types d'arguments identiques"
+msgstr "la fonction « %s » existe déjà avec des types d'arguments identiques"
#: catalog/pg_proc.c:417 catalog/pg_proc.c:440
#, c-format
@@ -4655,51 +4727,51 @@ msgstr "Utilisez tout d'abord DROP FUNCTION %s."
#: catalog/pg_proc.c:441
#, c-format
msgid "Row type defined by OUT parameters is different."
-msgstr "Le type de ligne d�fini par les param�tres OUT est diff�rent."
+msgstr "Le type de ligne défini par les paramètres OUT est différent."
#: catalog/pg_proc.c:483
#, c-format
msgid "cannot change name of input parameter \"%s\""
-msgstr "ne peut pas modifier le nom du param�tre en entr�e � %s �"
+msgstr "ne peut pas modifier le nom du paramètre en entrée « %s »"
#: catalog/pg_proc.c:508
#, c-format
msgid "cannot remove parameter defaults from existing function"
msgstr ""
-"ne peut pas supprimer les valeurs par d�faut des param�tres de la\n"
+"ne peut pas supprimer les valeurs par défaut des paramètres de la\n"
"fonction existante"
#: catalog/pg_proc.c:535
#, c-format
msgid "cannot change data type of existing parameter default value"
msgstr ""
-"ne peut pas modifier le type de donn�es d'un param�tre avec une valeur\n"
-"par d�faut"
+"ne peut pas modifier le type de données d'un paramètre avec une valeur\n"
+"par défaut"
#: catalog/pg_proc.c:548
#, c-format
msgid "function \"%s\" is an aggregate function"
-msgstr "la fonction � %s � est une fonction d'agr�gat"
+msgstr "la fonction « %s » est une fonction d'agrégat"
#: catalog/pg_proc.c:553
#, c-format
msgid "function \"%s\" is not an aggregate function"
-msgstr "la fonction � %s � n'est pas une fonction d'agr�gat"
+msgstr "la fonction « %s » n'est pas une fonction d'agrégat"
#: catalog/pg_proc.c:561
#, c-format
msgid "function \"%s\" is a window function"
-msgstr "la fonction � %s � est une fonction window"
+msgstr "la fonction « %s » est une fonction window"
#: catalog/pg_proc.c:566
#, c-format
msgid "function \"%s\" is not a window function"
-msgstr "la fonction � %s � n'est pas une fonction window"
+msgstr "la fonction « %s » n'est pas une fonction window"
#: catalog/pg_proc.c:774
#, c-format
msgid "there is no built-in function named \"%s\""
-msgstr "il n'existe pas de fonction int�gr�e nomm�e � %s �"
+msgstr "il n'existe pas de fonction intégrée nommée « %s »"
#: catalog/pg_proc.c:872
#, c-format
@@ -4711,10 +4783,10 @@ msgstr "les fonctions SQL ne peuvent pas renvoyer un type %s"
msgid "SQL functions cannot have arguments of type %s"
msgstr "les fonctions SQL ne peuvent avoir d'arguments du type %s"
-#: catalog/pg_proc.c:973 executor/functions.c:1424
+#: catalog/pg_proc.c:973 executor/functions.c:1431
#, c-format
msgid "SQL function \"%s\""
-msgstr "Fonction SQL � %s �"
+msgstr "Fonction SQL « %s »"
#: catalog/pg_shdepend.c:694
#, c-format
@@ -4726,37 +4798,37 @@ msgid_plural ""
"and objects in %d other databases (see server log for list)"
msgstr[0] ""
"\n"
-"et des objets dans %d autre base de donn�es (voir le journal applicatif du\n"
+"et des objets dans %d autre base de données (voir le journal applicatif du\n"
"serveur pour une liste)"
msgstr[1] ""
"\n"
-"et des objets dans %d autres bases de donn�es (voir le journal applicatif du\n"
+"et des objets dans %d autres bases de données (voir le journal applicatif du\n"
"serveur pour une liste)"
#: catalog/pg_shdepend.c:1006
#, c-format
msgid "role %u was concurrently dropped"
-msgstr "le r�le %u a �t� supprim� simultan�ment"
+msgstr "le rôle %u a été supprimé simultanément"
#: catalog/pg_shdepend.c:1025
#, c-format
msgid "tablespace %u was concurrently dropped"
-msgstr "le tablespace %u a �t� supprim� simultan�ment"
+msgstr "le tablespace %u a été supprimé simultanément"
#: catalog/pg_shdepend.c:1040
#, c-format
msgid "database %u was concurrently dropped"
-msgstr "la base de donn�es %u a �t� supprim� simultan�ment"
+msgstr "la base de données %u a été supprimé simultanément"
#: catalog/pg_shdepend.c:1085
#, c-format
msgid "owner of %s"
-msgstr "propri�taire de %s"
+msgstr "propriétaire de %s"
#: catalog/pg_shdepend.c:1087
#, c-format
msgid "privileges for %s"
-msgstr "droits pour � %s �"
+msgstr "droits pour « %s »"
#: catalog/pg_shdepend.c:1089
#, c-format
@@ -4775,20 +4847,20 @@ msgstr[1] "%d objets dans %s"
#, c-format
msgid "cannot drop objects owned by %s because they are required by the database system"
msgstr ""
-"n'a pas pu supprimer les objets appartenant � %s car ils sont n�cessaires au\n"
-"syst�me de bases de donn�es"
+"n'a pas pu supprimer les objets appartenant à %s car ils sont nécessaires au\n"
+"système de bases de données"
#: catalog/pg_shdepend.c:1323
#, c-format
msgid "cannot reassign ownership of objects owned by %s because they are required by the database system"
msgstr ""
-"ne peut pas r�affecter les objets appartenant � %s car ils sont n�cessaires au\n"
-"syst�me de bases de donn�es"
+"ne peut pas réaffecter les objets appartenant à %s car ils sont nécessaires au\n"
+"système de bases de données"
#: catalog/pg_type.c:136 catalog/pg_type.c:454
#, c-format
msgid "pg_type OID value not set when in binary upgrade mode"
-msgstr "OID de pg_type non configur� en mode de mise � jour binaire"
+msgstr "OID de pg_type non configuré en mode de mise à jour binaire"
#: catalog/pg_type.c:253
#, c-format
@@ -4798,17 +4870,17 @@ msgstr "taille interne de type invalide %d"
#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285 catalog/pg_type.c:294
#, c-format
msgid "alignment \"%c\" is invalid for passed-by-value type of size %d"
-msgstr "l'alignement � %c � est invalide pour le type pass� par valeur de taille %d"
+msgstr "l'alignement « %c » est invalide pour le type passé par valeur de taille %d"
#: catalog/pg_type.c:301
#, c-format
msgid "internal size %d is invalid for passed-by-value type"
-msgstr "la taille interne %d est invalide pour le type pass� par valeur"
+msgstr "la taille interne %d est invalide pour le type passé par valeur"
#: catalog/pg_type.c:310 catalog/pg_type.c:316
#, c-format
msgid "alignment \"%c\" is invalid for variable-length type"
-msgstr "l'alignement � %c � est invalide pour le type de longueur variable"
+msgstr "l'alignement « %c » est invalide pour le type de longueur variable"
#: catalog/pg_type.c:324
#, c-format
@@ -4818,509 +4890,473 @@ msgstr "les types de taille fixe doivent avoir un stockage de base"
#: catalog/pg_type.c:789
#, c-format
msgid "could not form array type name for type \"%s\""
-msgstr "n'a pas pu former le nom du type array pour le type de donn�es %s"
+msgstr "n'a pas pu former le nom du type array pour le type de données %s"
-#: catalog/toasting.c:105 commands/indexcmds.c:389 commands/tablecmds.c:4358 commands/tablecmds.c:11900
+#: catalog/toasting.c:105 commands/indexcmds.c:389 commands/tablecmds.c:4359 commands/tablecmds.c:12047
#, c-format
msgid "\"%s\" is not a table or materialized view"
-msgstr "� %s � n'est pas une table ou une vue mat�rialis�e"
+msgstr "« %s » n'est pas une table ou une vue matérialisée"
#: catalog/toasting.c:158
#, c-format
msgid "shared tables cannot be toasted after initdb"
msgstr ""
-"les tables partag�es ne peuvent pas avoir une table TOAST apr�s la commande\n"
+"les tables partagées ne peuvent pas avoir une table TOAST après la commande\n"
"initdb"
-#: commands/aggregatecmds.c:161
+#: commands/aggregatecmds.c:159
#, c-format
msgid "only ordered-set aggregates can be hypothetical"
-msgstr "seuls les agr�gats � ensemble ordonn� peuvent �tre hypoth�tiques"
+msgstr "seuls les agrégats à ensemble ordonné peuvent être hypothétiques"
-#: commands/aggregatecmds.c:188
+#: commands/aggregatecmds.c:184
#, c-format
msgid "aggregate attribute \"%s\" not recognized"
-msgstr "l'attribut de l'agr�gat � %s � n'est pas reconnu"
+msgstr "l'attribut de l'agrégat « %s » n'est pas reconnu"
-#: commands/aggregatecmds.c:198
+#: commands/aggregatecmds.c:194
#, c-format
msgid "aggregate stype must be specified"
-msgstr "le type source de l'agr�gat doit �tre sp�cifi�"
+msgstr "le type source de l'agrégat doit être spécifié"
-#: commands/aggregatecmds.c:202
+#: commands/aggregatecmds.c:198
#, c-format
msgid "aggregate sfunc must be specified"
-msgstr "la fonction source de l'agr�gat doit �tre sp�cifi�e"
+msgstr "la fonction source de l'agrégat doit être spécifiée"
-#: commands/aggregatecmds.c:214
+#: commands/aggregatecmds.c:210
#, c-format
msgid "aggregate msfunc must be specified when mstype is specified"
-msgstr "la fonction msfunc de l'agr�gat doit �tre sp�cifi�e quand mstype est sp�cifi�"
+msgstr "la fonction msfunc de l'agrégat doit être spécifiée quand mstype est spécifié"
-#: commands/aggregatecmds.c:218
+#: commands/aggregatecmds.c:214
#, c-format
msgid "aggregate minvfunc must be specified when mstype is specified"
-msgstr "la fonction minvfunc de l'agr�gat doit �tre sp�cifi�e quand mstype est sp�cifi�"
+msgstr "la fonction minvfunc de l'agrégat doit être spécifiée quand mstype est spécifié"
-#: commands/aggregatecmds.c:225
+#: commands/aggregatecmds.c:221
#, c-format
msgid "aggregate msfunc must not be specified without mstype"
-msgstr "la fonction msfunc de l'agr�gat ne doit pas �tre sp�cifi�e sans mstype"
+msgstr "la fonction msfunc de l'agrégat ne doit pas être spécifiée sans mstype"
-#: commands/aggregatecmds.c:229
+#: commands/aggregatecmds.c:225
#, c-format
msgid "aggregate minvfunc must not be specified without mstype"
-msgstr "la fonction minvfunc de l'agr�gat ne doit pas �tre sp�cifi�e sans mstype"
+msgstr "la fonction minvfunc de l'agrégat ne doit pas être spécifiée sans mstype"
-#: commands/aggregatecmds.c:233
+#: commands/aggregatecmds.c:229
#, c-format
msgid "aggregate mfinalfunc must not be specified without mstype"
-msgstr "la fonction mfinalfunc de l'agr�gat ne doit pas �tre sp�cifi�e sans mstype"
+msgstr "la fonction mfinalfunc de l'agrégat ne doit pas être spécifiée sans mstype"
-#: commands/aggregatecmds.c:237
+#: commands/aggregatecmds.c:233
#, c-format
msgid "aggregate msspace must not be specified without mstype"
-msgstr "la fonction msspace de l'agr�gat ne doit pas �tre sp�cifi�e sans mstype"
+msgstr "la fonction msspace de l'agrégat ne doit pas être spécifiée sans mstype"
-#: commands/aggregatecmds.c:241
+#: commands/aggregatecmds.c:237
#, c-format
msgid "aggregate minitcond must not be specified without mstype"
-msgstr "la fonction minitcond de l'agr�gat ne doit pas �tre sp�cifi�e sans mstype"
+msgstr "la fonction minitcond de l'agrégat ne doit pas être spécifiée sans mstype"
-#: commands/aggregatecmds.c:261
+#: commands/aggregatecmds.c:257
#, c-format
msgid "aggregate input type must be specified"
-msgstr "le type de saisie de l'agr�gat doit �tre pr�cis�"
+msgstr "le type de saisie de l'agrégat doit être précisé"
-#: commands/aggregatecmds.c:291
+#: commands/aggregatecmds.c:287
#, c-format
msgid "basetype is redundant with aggregate input type specification"
-msgstr "le type de base est redondant avec la sp�cification du type en entr�e de l'agr�gat"
+msgstr "le type de base est redondant avec la spécification du type en entrée de l'agrégat"
-#: commands/aggregatecmds.c:332 commands/aggregatecmds.c:421
+#: commands/aggregatecmds.c:328 commands/aggregatecmds.c:369
#, c-format
msgid "aggregate transition data type cannot be %s"
-msgstr "Le type de donn�es de transition de l'agr�gat ne peut pas �tre %s"
-
-#: commands/aggregatecmds.c:347
-#, c-format
-msgid "a serialization type must only be specified when the aggregate transition data type is \"%s\""
-msgstr ""
-
-#: commands/aggregatecmds.c:356
-#, fuzzy, c-format
-#| msgid "aggregate transition data type cannot be %s"
-msgid "aggregate serialization data type cannot be %s"
-msgstr "Le type de donn�es de transition de l'agr�gat ne peut pas �tre %s"
-
-#: commands/aggregatecmds.c:369
-#, fuzzy, c-format
-#| msgid "aggregate transition data type cannot be %s"
-msgid "aggregate serialization type cannot be \"%s\""
-msgstr "Le type de donn�es de transition de l'agr�gat ne peut pas �tre %s"
+msgstr "Le type de données de transition de l'agrégat ne peut pas être %s"
-#: commands/aggregatecmds.c:380
-#, fuzzy, c-format
-#| msgid "aggregate minvfunc must be specified when mstype is specified"
-msgid "aggregate serialization function must be specified when serialization type is specified"
-msgstr "la fonction minvfunc de l'agr�gat doit �tre sp�cifi�e quand mstype est sp�cifi�"
-
-#: commands/aggregatecmds.c:385
-#, fuzzy, c-format
-#| msgid "aggregate minvfunc must be specified when mstype is specified"
-msgid "aggregate deserialization function must be specified when serialization type is specified"
-msgstr "la fonction minvfunc de l'agr�gat doit �tre sp�cifi�e quand mstype est sp�cifi�"
-
-#: commands/aggregatecmds.c:396
+#: commands/aggregatecmds.c:340
#, c-format
-msgid "must specify serialization type when specifying serialization function"
-msgstr ""
+msgid "serialization functions may be specified only when the aggregate transition data type is %s"
+msgstr "les fonctions de sérialisation ne peuvent être spécifiées que quand le type de données des transitions d'aggrégat est %s"
-#: commands/aggregatecmds.c:402
+#: commands/aggregatecmds.c:350
#, c-format
-msgid "must specify serialization type when specifying deserialization function"
-msgstr ""
+msgid "must specify both or neither of serialization and deserialization functions"
+msgstr "doit spécifier soit toutes soit aucunes des fonctions de sérialisation et désérialisation"
-#: commands/aggregatecmds.c:467 commands/functioncmds.c:570
+#: commands/aggregatecmds.c:415 commands/functioncmds.c:570
#, c-format
msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE"
-msgstr ""
+msgstr "le paramètre « parallel » doit être SAFE, RESTRICTED ou UNSAFE"
#: commands/alter.c:80 commands/event_trigger.c:231
#, c-format
msgid "event trigger \"%s\" already exists"
-msgstr "le trigger sur �v�nement � %s � existe d�j�"
+msgstr "le trigger sur événement « %s » existe déjà"
#: commands/alter.c:83 commands/foreigncmds.c:597
#, c-format
msgid "foreign-data wrapper \"%s\" already exists"
-msgstr "le wrapper de donn�es distantes � %s � existe d�j�"
+msgstr "le wrapper de données distantes « %s » existe déjà"
#: commands/alter.c:86 commands/foreigncmds.c:890
#, c-format
msgid "server \"%s\" already exists"
-msgstr "le serveur � %s � existe d�j�"
+msgstr "le serveur « %s » existe déjà"
#: commands/alter.c:89 commands/proclang.c:366
#, c-format
msgid "language \"%s\" already exists"
-msgstr "le langage � %s � existe d�j�"
+msgstr "le langage « %s » existe déjà"
#: commands/alter.c:112
#, c-format
msgid "conversion \"%s\" already exists in schema \"%s\""
-msgstr "la conversion � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "la conversion « %s » existe déjà dans le schéma « %s »"
#: commands/alter.c:116
#, c-format
msgid "text search parser \"%s\" already exists in schema \"%s\""
-msgstr "l'analyseur de recherche plein texte � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "l'analyseur de recherche plein texte « %s » existe déjà dans le schéma « %s »"
#: commands/alter.c:120
#, c-format
msgid "text search dictionary \"%s\" already exists in schema \"%s\""
-msgstr "le dictionnaire de recherche plein texte � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "le dictionnaire de recherche plein texte « %s » existe déjà dans le schéma « %s »"
#: commands/alter.c:124
#, c-format
msgid "text search template \"%s\" already exists in schema \"%s\""
-msgstr "le mod�le de recherche plein texte � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "le modèle de recherche plein texte « %s » existe déjà dans le schéma « %s »"
#: commands/alter.c:128
#, c-format
msgid "text search configuration \"%s\" already exists in schema \"%s\""
-msgstr "la configuration de recherche plein texte � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "la configuration de recherche plein texte « %s » existe déjà dans le schéma « %s »"
#: commands/alter.c:202
#, c-format
msgid "must be superuser to rename %s"
-msgstr "doit �tre super-utilisateur pour renommer � %s �"
+msgstr "doit être super-utilisateur pour renommer « %s »"
-#: commands/alter.c:656
+#: commands/alter.c:655
#, c-format
msgid "must be superuser to set schema of %s"
-msgstr "doit �tre super-utilisateur pour configurer le sch�ma de %s"
+msgstr "doit être super-utilisateur pour configurer le schéma de %s"
#: commands/amcmds.c:58
-#, fuzzy, c-format
-#| msgid "permission denied to create tablespace \"%s\""
+#, c-format
msgid "permission denied to create access method \"%s\""
-msgstr "droit refus� pour cr�er le tablespace � %s �"
+msgstr "droit refusé pour créer la méthode d'accès « %s »"
#: commands/amcmds.c:60
-#, fuzzy, c-format
-#| msgid "Must be superuser to create a tablespace."
+#, c-format
msgid "Must be superuser to create an access method."
-msgstr "Doit �tre super-utilisateur pour cr�er un tablespace."
+msgstr "Doit être super-utilisateur pour créer une méthode d'accès."
#: commands/amcmds.c:68
-#, fuzzy, c-format
-#| msgid "access method \"%s\" does not exist"
+#, c-format
msgid "access method \"%s\" already exists"
-msgstr "la m�thode d'acc�s � %s � n'existe pas"
+msgstr "la méthode d'accès « %s » existe déjà"
#: commands/amcmds.c:124
-#, fuzzy, c-format
-#| msgid "must be superuser to drop superusers"
+#, c-format
msgid "must be superuser to drop access methods"
-msgstr "doit �tre super-utilisateur pour supprimer des super-utilisateurs"
+msgstr "doit être super-utilisateur pour supprimer des méthodes d'accès"
#: commands/amcmds.c:175 commands/indexcmds.c:164 commands/indexcmds.c:495 commands/opclasscmds.c:365 commands/opclasscmds.c:790
#, c-format
msgid "access method \"%s\" does not exist"
-msgstr "la m�thode d'acc�s � %s � n'existe pas"
+msgstr "la méthode d'accès « %s » n'existe pas"
#: commands/amcmds.c:251
-#, fuzzy, c-format
-#| msgid "no function body specified"
+#, c-format
msgid "handler function is not specified"
-msgstr "aucun corps de fonction sp�cifi�"
+msgstr "la fonction handler n'est pas spécifiée"
#: commands/amcmds.c:263 commands/event_trigger.c:240 commands/foreigncmds.c:489 commands/proclang.c:117 commands/proclang.c:288 commands/trigger.c:441 parser/parse_clause.c:761
-#, fuzzy, c-format
-#| msgid "function %s should return type %s"
+#, c-format
msgid "function %s must return type %s"
msgstr "la fonction %s doit renvoyer le type %s"
#: commands/analyze.c:145
#, c-format
msgid "skipping analyze of \"%s\" --- lock not available"
-msgstr "ignore l'analyse de � %s � --- verrou non disponible"
+msgstr "ignore l'analyse de « %s » --- verrou non disponible"
#: commands/analyze.c:162
#, c-format
msgid "skipping \"%s\" --- only superuser can analyze it"
-msgstr "ignore � %s � --- seul le super-utilisateur peut l'analyser"
+msgstr "ignore « %s » --- seul le super-utilisateur peut l'analyser"
#: commands/analyze.c:166
#, c-format
msgid "skipping \"%s\" --- only superuser or database owner can analyze it"
msgstr ""
-"ignore � %s � --- seul le super-utilisateur ou le propri�taire de la base de\n"
-"donn�es peut l'analyser"
+"ignore « %s » --- seul le super-utilisateur ou le propriétaire de la base de\n"
+"données peut l'analyser"
#: commands/analyze.c:170
#, c-format
msgid "skipping \"%s\" --- only table or database owner can analyze it"
msgstr ""
-"ignore � %s � --- seul le propri�taire de la table ou de la base de donn�es\n"
+"ignore « %s » --- seul le propriétaire de la table ou de la base de données\n"
"peut l'analyser"
#: commands/analyze.c:230
#, c-format
msgid "skipping \"%s\" --- cannot analyze this foreign table"
-msgstr "ignore � %s � --- ne peut pas analyser cette table distante"
+msgstr "ignore « %s » --- ne peut pas analyser cette table distante"
#: commands/analyze.c:241
#, c-format
msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables"
-msgstr "ignore � %s � --- ne peut pas analyser les objets autres que les tables et les tables syst�me"
+msgstr "ignore « %s » --- ne peut pas analyser les objets autres que les tables et les tables système"
#: commands/analyze.c:320
#, c-format
msgid "analyzing \"%s.%s\" inheritance tree"
-msgstr "analyse l'arbre d'h�ritage � %s.%s �"
+msgstr "analyse l'arbre d'héritage « %s.%s »"
#: commands/analyze.c:325
#, c-format
msgid "analyzing \"%s.%s\""
-msgstr "analyse � %s.%s �"
+msgstr "analyse « %s.%s »"
-#: commands/analyze.c:651
+#: commands/analyze.c:650
#, c-format
msgid "automatic analyze of table \"%s.%s.%s\" system usage: %s"
-msgstr "ANALYZE automatique de la table � %s.%s.%s � ; utilisation syst�me : %s"
+msgstr "ANALYZE automatique de la table « %s.%s.%s » ; utilisation système : %s"
-#: commands/analyze.c:1207
+#: commands/analyze.c:1204
#, c-format
msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows"
msgstr ""
-"� %s � : %d pages parcourues sur %u,\n"
-" contenant %.0f lignes � conserver et %.0f lignes � supprimer,\n"
-" %d lignes dans l'�chantillon,\n"
-" %.0f lignes totales estim�es"
+"« %s » : %d pages parcourues sur %u,\n"
+" contenant %.0f lignes à conserver et %.0f lignes à supprimer,\n"
+" %d lignes dans l'échantillon,\n"
+" %.0f lignes totales estimées"
-#: commands/analyze.c:1286
+#: commands/analyze.c:1283
#, c-format
msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables"
-msgstr "ignore l'analyse de l'arbre d'h�ritage � %s.%s � --- cet arbre d'h�ritage ne contient pas de tables enfants"
+msgstr "ignore l'analyse de l'arbre d'héritage « %s.%s » --- cet arbre d'héritage ne contient pas de tables enfants"
-#: commands/analyze.c:1375
+#: commands/analyze.c:1372
#, c-format
msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables"
-msgstr "ignore l'analyse de l'arbre d'h�ritage � %s.%s � --- cet arbre d'h�ritage ne contient pas de tables enfants analysables"
+msgstr "ignore l'analyse de l'arbre d'héritage « %s.%s » --- cet arbre d'héritage ne contient pas de tables enfants analysables"
-#: commands/analyze.c:1423 executor/execQual.c:2922
+#: commands/analyze.c:1420 commands/tablecmds.c:8079 executor/execQual.c:2927
msgid "could not convert row type"
msgstr "n'a pas pu convertir le type de ligne"
-#: commands/async.c:558
+#: commands/async.c:555
#, c-format
msgid "channel name cannot be empty"
-msgstr "le nom du canal ne peut pas �tre vide"
+msgstr "le nom du canal ne peut pas être vide"
-#: commands/async.c:563
+#: commands/async.c:560
#, c-format
msgid "channel name too long"
msgstr "nom du canal trop long"
-#: commands/async.c:570
+#: commands/async.c:567
#, c-format
msgid "payload string too long"
-msgstr "cha�ne de charge trop longue"
+msgstr "chaîne de charge trop longue"
-#: commands/async.c:756
+#: commands/async.c:753
#, c-format
msgid "cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY"
msgstr ""
-"ne peut pas ex�cuter PREPARE sur une transaction qui a ex�cut� LISTEN,\n"
+"ne peut pas exécuter PREPARE sur une transaction qui a exécuté LISTEN,\n"
"UNLISTEN ou NOTIFY"
-#: commands/async.c:859
+#: commands/async.c:856
#, c-format
msgid "too many notifications in the NOTIFY queue"
msgstr "trop de notifications dans la queue NOTIFY"
-#: commands/async.c:1489
+#: commands/async.c:1486
#, c-format
msgid "NOTIFY queue is %.0f%% full"
-msgstr "la queue NOTIFY est pleine � %.0f%%"
+msgstr "la queue NOTIFY est pleine à %.0f%%"
-#: commands/async.c:1491
+#: commands/async.c:1488
#, c-format
msgid "The server process with PID %d is among those with the oldest transactions."
msgstr "Le processus serveur de PID %d est parmi ceux qui ont les transactions les plus anciennes."
-#: commands/async.c:1494
+#: commands/async.c:1491
#, c-format
msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction."
msgstr ""
-"La queue NOTIFY ne peut pas �tre vid�e jusqu'� ce que le processus finisse\n"
+"La queue NOTIFY ne peut pas être vidée jusqu'à ce que le processus finisse\n"
"sa transaction en cours."
-#: commands/cluster.c:129 commands/cluster.c:366
+#: commands/cluster.c:129 commands/cluster.c:364
#, c-format
msgid "cannot cluster temporary tables of other sessions"
-msgstr "ne peut pas ex�cuter CLUSTER sur les tables temporaires des autres sessions"
+msgstr "ne peut pas exécuter CLUSTER sur les tables temporaires des autres sessions"
#: commands/cluster.c:159
#, c-format
msgid "there is no previously clustered index for table \"%s\""
-msgstr "Il n'existe pas d'index CLUSTER pour la table � %s �"
+msgstr "Il n'existe pas d'index CLUSTER pour la table « %s »"
-#: commands/cluster.c:173 commands/tablecmds.c:9286 commands/tablecmds.c:11002
+#: commands/cluster.c:173 commands/tablecmds.c:9383 commands/tablecmds.c:11143
#, c-format
msgid "index \"%s\" for table \"%s\" does not exist"
-msgstr "l'index � %s � pour la table � %s � n'existe pas"
+msgstr "l'index « %s » pour la table « %s » n'existe pas"
-#: commands/cluster.c:355
+#: commands/cluster.c:353
#, c-format
msgid "cannot cluster a shared catalog"
-msgstr "ne peut pas ex�cuter CLUSTER sur un catalogue partag�"
+msgstr "ne peut pas exécuter CLUSTER sur un catalogue partagé"
-#: commands/cluster.c:370
+#: commands/cluster.c:368
#, c-format
msgid "cannot vacuum temporary tables of other sessions"
-msgstr "ne peut pas ex�cuter VACUUM sur les tables temporaires des autres sessions"
+msgstr "ne peut pas exécuter VACUUM sur les tables temporaires des autres sessions"
-#: commands/cluster.c:433 commands/tablecmds.c:11012
+#: commands/cluster.c:431 commands/tablecmds.c:11153
#, c-format
msgid "\"%s\" is not an index for table \"%s\""
-msgstr "� %s � n'est pas un index de la table � %s �"
+msgstr "« %s » n'est pas un index de la table « %s »"
-#: commands/cluster.c:441
+#: commands/cluster.c:439
#, c-format
msgid "cannot cluster on index \"%s\" because access method does not support clustering"
msgstr ""
-"ne peut pas ex�cuter CLUSTER sur l'index � %s � car la m�thode d'acc�s de\n"
-"l'index ne g�re pas cette commande"
+"ne peut pas exécuter CLUSTER sur l'index « %s » car la méthode d'accès de\n"
+"l'index ne gère pas cette commande"
-#: commands/cluster.c:453
+#: commands/cluster.c:451
#, c-format
msgid "cannot cluster on partial index \"%s\""
-msgstr "ne peut pas ex�cuter CLUSTER sur l'index partiel � %s �"
+msgstr "ne peut pas exécuter CLUSTER sur l'index partiel « %s »"
-#: commands/cluster.c:467
+#: commands/cluster.c:465
#, c-format
msgid "cannot cluster on invalid index \"%s\""
-msgstr "ne peut pas ex�cuter la commande CLUSTER sur l'index invalide � %s �"
+msgstr "ne peut pas exécuter la commande CLUSTER sur l'index invalide « %s »"
-#: commands/cluster.c:920
+#: commands/cluster.c:918
#, c-format
msgid "clustering \"%s.%s\" using index scan on \"%s\""
-msgstr "cluster sur � %s.%s � en utilisant un parcours d'index sur � %s �"
+msgstr "cluster sur « %s.%s » en utilisant un parcours d'index sur « %s »"
-#: commands/cluster.c:926
+#: commands/cluster.c:924
#, c-format
msgid "clustering \"%s.%s\" using sequential scan and sort"
-msgstr "cluster sur � %s.%s � en utilisant un parcours s�quentiel puis un tri"
+msgstr "cluster sur « %s.%s » en utilisant un parcours séquentiel puis un tri"
-#: commands/cluster.c:931 commands/vacuumlazy.c:476
+#: commands/cluster.c:929 commands/vacuumlazy.c:479
#, c-format
msgid "vacuuming \"%s.%s\""
-msgstr "ex�cution du VACUUM sur � %s.%s �"
+msgstr "exécution du VACUUM sur « %s.%s »"
-#: commands/cluster.c:1090
+#: commands/cluster.c:1088
#, c-format
msgid "\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages"
msgstr ""
-"� %s � : %.0f versions de ligne supprimables, %.0f non supprimables\n"
+"« %s » : %.0f versions de ligne supprimables, %.0f non supprimables\n"
"parmi %u pages"
-#: commands/cluster.c:1094
+#: commands/cluster.c:1092
#, c-format
msgid ""
"%.0f dead row versions cannot be removed yet.\n"
"%s."
msgstr ""
-"%.0f versions de lignes ne peuvent pas encore �tre supprim�es.\n"
+"%.0f versions de lignes ne peuvent pas encore être supprimées.\n"
"%s."
#: commands/collationcmds.c:80
#, c-format
msgid "collation attribute \"%s\" not recognized"
-msgstr "attribut de collationnement � %s � non reconnu"
+msgstr "attribut de collationnement « %s » non reconnu"
#: commands/collationcmds.c:125
#, c-format
msgid "parameter \"lc_collate\" must be specified"
-msgstr "le param�tre � lc_collate � doit �tre sp�cifi�"
+msgstr "le paramètre « lc_collate » doit être spécifié"
#: commands/collationcmds.c:130
#, c-format
msgid "parameter \"lc_ctype\" must be specified"
-msgstr "le param�tre � lc_ctype � doit �tre sp�cifi�"
+msgstr "le paramètre « lc_ctype » doit être spécifié"
#: commands/collationcmds.c:166
#, c-format
msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\""
-msgstr "le collationnament � %s � pour l'encodage � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "le collationnament « %s » pour l'encodage « %s » existe déjà dans le schéma « %s »"
#: commands/collationcmds.c:177
#, c-format
msgid "collation \"%s\" already exists in schema \"%s\""
-msgstr "le collationnement � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "le collationnement « %s » existe déjà dans le schéma « %s »"
-#: commands/comment.c:62 commands/dbcommands.c:797 commands/dbcommands.c:962 commands/dbcommands.c:1067 commands/dbcommands.c:1257 commands/dbcommands.c:1477 commands/dbcommands.c:1594 commands/dbcommands.c:2011 utils/init/postinit.c:842 utils/init/postinit.c:944 utils/init/postinit.c:961
+#: commands/comment.c:62 commands/dbcommands.c:797 commands/dbcommands.c:962 commands/dbcommands.c:1067 commands/dbcommands.c:1257 commands/dbcommands.c:1477 commands/dbcommands.c:1594 commands/dbcommands.c:2011 utils/init/postinit.c:841 utils/init/postinit.c:943 utils/init/postinit.c:960
#, c-format
msgid "database \"%s\" does not exist"
-msgstr "la base de donn�es � %s � n'existe pas"
+msgstr "la base de données « %s » n'existe pas"
-#: commands/comment.c:101 commands/seclabel.c:116 parser/parse_utilcmd.c:768
+#: commands/comment.c:101 commands/seclabel.c:116 parser/parse_utilcmd.c:753
#, c-format
msgid "\"%s\" is not a table, view, materialized view, composite type, or foreign table"
-msgstr "� %s � n'est ni une table, ni une vue, ni une vue mat�rialis�e, ni un type composite, ni une table distante"
+msgstr "« %s » n'est ni une table, ni une vue, ni une vue matérialisée, ni un type composite, ni une table distante"
-#: commands/constraint.c:60 utils/adt/ri_triggers.c:2717
+#: commands/constraint.c:60 utils/adt/ri_triggers.c:2715
#, c-format
msgid "function \"%s\" was not called by trigger manager"
-msgstr "la fonction � %s � n'a pas �t� appel�e par le gestionnaire de triggers"
+msgstr "la fonction « %s » n'a pas été appelée par le gestionnaire de triggers"
-#: commands/constraint.c:67 utils/adt/ri_triggers.c:2726
+#: commands/constraint.c:67 utils/adt/ri_triggers.c:2724
#, c-format
msgid "function \"%s\" must be fired AFTER ROW"
-msgstr "la fonction � %s � doit �tre ex�cut�e pour l'instruction AFTER ROW"
+msgstr "la fonction « %s » doit être exécutée pour l'instruction AFTER ROW"
#: commands/constraint.c:81
#, c-format
msgid "function \"%s\" must be fired for INSERT or UPDATE"
-msgstr "la fonction � %s � doit �tre ex�cut�e pour les instructions INSERT ou UPDATE"
+msgstr "la fonction « %s » doit être exécutée pour les instructions INSERT ou UPDATE"
#: commands/conversioncmds.c:67
#, c-format
msgid "source encoding \"%s\" does not exist"
-msgstr "le codage source � %s � n'existe pas"
+msgstr "le codage source « %s » n'existe pas"
#: commands/conversioncmds.c:74
#, c-format
msgid "destination encoding \"%s\" does not exist"
-msgstr "l'encodage de destination � %s � n'existe pas"
+msgstr "l'encodage de destination « %s » n'existe pas"
#: commands/conversioncmds.c:88
-#, fuzzy, c-format
-#| msgid "encoding conversion function %s must return type \"void\""
+#, c-format
msgid "encoding conversion function %s must return type %s"
-msgstr "la fonction de conversion d'encodage %s doit renvoyer le type � void �"
+msgstr "la fonction de conversion d'encodage %s doit renvoyer le type %s"
#: commands/copy.c:362 commands/copy.c:374 commands/copy.c:408 commands/copy.c:420
#, c-format
msgid "COPY BINARY is not supported to stdout or from stdin"
-msgstr "COPY BINARY n'est pas support� vers stdout ou � partir de stdin"
+msgstr "COPY BINARY n'est pas supporté vers stdout ou à partir de stdin"
#: commands/copy.c:520
#, c-format
msgid "could not write to COPY program: %m"
-msgstr "n'a pas pu �crire vers le programme COPY : %m"
+msgstr "n'a pas pu écrire vers le programme COPY : %m"
#: commands/copy.c:525
#, c-format
msgid "could not write to COPY file: %m"
-msgstr "n'a pas pu �crire dans le fichier COPY : %m"
+msgstr "n'a pas pu écrire dans le fichier COPY : %m"
#: commands/copy.c:538
#, c-format
msgid "connection lost during COPY to stdout"
-msgstr "connexion perdue lors de l'op�ration COPY vers stdout"
+msgstr "connexion perdue lors de l'opération COPY vers stdout"
#: commands/copy.c:579
#, c-format
@@ -5337,518 +5373,501 @@ msgstr ""
#: commands/copy.c:633
#, c-format
msgid "COPY from stdin failed: %s"
-msgstr "�chec de la commande COPY � partir de stdin : %s"
+msgstr "échec de la commande COPY à partir de stdin : %s"
#: commands/copy.c:649
#, c-format
msgid "unexpected message type 0x%02X during COPY from stdin"
-msgstr "type 0x%02X du message, inattendu, lors d'une op�ration COPY � partir de stdin"
+msgstr "type 0x%02X du message, inattendu, lors d'une opération COPY à partir de stdin"
#: commands/copy.c:806
#, c-format
msgid "must be superuser to COPY to or from an external program"
-msgstr "doit �tre super-utilisateur pour utiliser COPY avec un programme externe"
+msgstr "doit être super-utilisateur pour utiliser COPY avec un programme externe"
#: commands/copy.c:807 commands/copy.c:813
#, c-format
msgid "Anyone can COPY to stdout or from stdin. psql's \\copy command also works for anyone."
msgstr ""
-"Tout le monde peut utiliser COPY vers stdout ou � partir de stdin.\n"
+"Tout le monde peut utiliser COPY vers stdout ou à partir de stdin.\n"
"La commande \\copy de psql fonctionne aussi pour tout le monde."
#: commands/copy.c:812
#, c-format
msgid "must be superuser to COPY to or from a file"
-msgstr "doit �tre super-utilisateur pour utiliser COPY � partir ou vers un fichier"
+msgstr "doit être super-utilisateur pour utiliser COPY à partir ou vers un fichier"
-#: commands/copy.c:878
+#: commands/copy.c:879
#, c-format
msgid "COPY FROM not supported with row-level security"
-msgstr "COPY FROM non support� avec la s�curit� niveau ligne"
+msgstr "COPY FROM non supporté avec la sécurité niveau ligne"
-#: commands/copy.c:879
+#: commands/copy.c:880
#, c-format
msgid "Use INSERT statements instead."
-msgstr "Utilisez des instructions INSERT � la place."
+msgstr "Utilisez des instructions INSERT à la place."
-#: commands/copy.c:1019
+#: commands/copy.c:1058
#, c-format
msgid "COPY format \"%s\" not recognized"
-msgstr "format COPY � %s � non reconnu"
+msgstr "format COPY « %s » non reconnu"
-#: commands/copy.c:1090 commands/copy.c:1104 commands/copy.c:1118 commands/copy.c:1138
+#: commands/copy.c:1129 commands/copy.c:1143 commands/copy.c:1157 commands/copy.c:1177
#, c-format
msgid "argument to option \"%s\" must be a list of column names"
-msgstr "l'argument de l'option � %s � doit �tre une liste de noms de colonnes"
+msgstr "l'argument de l'option « %s » doit être une liste de noms de colonnes"
-#: commands/copy.c:1151
+#: commands/copy.c:1190
#, c-format
msgid "argument to option \"%s\" must be a valid encoding name"
-msgstr "l'argument de l'option � %s � doit �tre un nom d'encodage valide"
+msgstr "l'argument de l'option « %s » doit être un nom d'encodage valide"
-#: commands/copy.c:1157 commands/dbcommands.c:232 commands/dbcommands.c:1427
+#: commands/copy.c:1196 commands/dbcommands.c:232 commands/dbcommands.c:1427
#, c-format
msgid "option \"%s\" not recognized"
-msgstr "option � %s � non reconnu"
+msgstr "option « %s » non reconnu"
-#: commands/copy.c:1168
+#: commands/copy.c:1207
#, c-format
msgid "cannot specify DELIMITER in BINARY mode"
-msgstr "ne peut pas sp�cifier le d�limiteur (DELIMITER) en mode binaire (BINARY)"
+msgstr "ne peut pas spécifier le délimiteur (DELIMITER) en mode binaire (BINARY)"
-#: commands/copy.c:1173
+#: commands/copy.c:1212
#, c-format
msgid "cannot specify NULL in BINARY mode"
-msgstr "ne peut pas sp�cifier NULL en mode binaire (BINARY)"
+msgstr "ne peut pas spécifier NULL en mode binaire (BINARY)"
-#: commands/copy.c:1195
+#: commands/copy.c:1234
#, c-format
msgid "COPY delimiter must be a single one-byte character"
-msgstr "le d�limiteur COPY doit �tre sur un seul caract�re sur un octet"
+msgstr "le délimiteur COPY doit être sur un seul caractère sur un octet"
-#: commands/copy.c:1202
+#: commands/copy.c:1241
#, c-format
msgid "COPY delimiter cannot be newline or carriage return"
-msgstr "le d�limiteur de COPY ne peut pas �tre un retour � la ligne ou un retour chariot"
+msgstr "le délimiteur de COPY ne peut pas être un retour à la ligne ou un retour chariot"
-#: commands/copy.c:1208
+#: commands/copy.c:1247
#, c-format
msgid "COPY null representation cannot use newline or carriage return"
msgstr ""
-"la repr�sentation du NULL dans COPY ne peut pas utiliser le caract�re du\n"
-"retour � la ligne ou du retour chariot"
+"la représentation du NULL dans COPY ne peut pas utiliser le caractère du\n"
+"retour à la ligne ou du retour chariot"
-#: commands/copy.c:1225
+#: commands/copy.c:1264
#, c-format
msgid "COPY delimiter cannot be \"%s\""
-msgstr "le d�limiteur de COPY ne peut pas �tre � %s �"
+msgstr "le délimiteur de COPY ne peut pas être « %s »"
-#: commands/copy.c:1231
+#: commands/copy.c:1270
#, c-format
msgid "COPY HEADER available only in CSV mode"
msgstr "COPY HEADER disponible uniquement en mode CSV"
-#: commands/copy.c:1237
+#: commands/copy.c:1276
#, c-format
msgid "COPY quote available only in CSV mode"
msgstr "le guillemet COPY n'est disponible que dans le mode CSV"
-#: commands/copy.c:1242
+#: commands/copy.c:1281
#, c-format
msgid "COPY quote must be a single one-byte character"
-msgstr "le guillemet COPY doit �tre sur un seul caract�re sur un octet"
+msgstr "le guillemet COPY doit être sur un seul caractère sur un octet"
-#: commands/copy.c:1247
+#: commands/copy.c:1286
#, c-format
msgid "COPY delimiter and quote must be different"
-msgstr "le d�limiteur de COPY ne doit pas �tre un guillemet"
+msgstr "le délimiteur de COPY ne doit pas être un guillemet"
-#: commands/copy.c:1253
+#: commands/copy.c:1292
#, c-format
msgid "COPY escape available only in CSV mode"
-msgstr "le caract�re d'�chappement COPY n'est disponible que dans le mode CSV"
+msgstr "le caractère d'échappement COPY n'est disponible que dans le mode CSV"
-#: commands/copy.c:1258
+#: commands/copy.c:1297
#, c-format
msgid "COPY escape must be a single one-byte character"
-msgstr "le caract�re d'�chappement COPY doit �tre sur un seul caract�re sur un octet"
+msgstr "le caractère d'échappement COPY doit être sur un seul caractère sur un octet"
-#: commands/copy.c:1264
+#: commands/copy.c:1303
#, c-format
msgid "COPY force quote available only in CSV mode"
-msgstr "le guillemet forc� COPY n'est disponible que dans le mode CSV"
+msgstr "le guillemet forcé COPY n'est disponible que dans le mode CSV"
-#: commands/copy.c:1268
+#: commands/copy.c:1307
#, c-format
msgid "COPY force quote only available using COPY TO"
-msgstr "le guillemet forc� COPY n'est disponible qu'en utilisant COPY TO"
+msgstr "le guillemet forcé COPY n'est disponible qu'en utilisant COPY TO"
-#: commands/copy.c:1274
+#: commands/copy.c:1313
#, c-format
msgid "COPY force not null available only in CSV mode"
-msgstr "� COPY force not null � n'est disponible que dans la version CSV"
+msgstr "« COPY force not null » n'est disponible que dans la version CSV"
-#: commands/copy.c:1278
+#: commands/copy.c:1317
#, c-format
msgid "COPY force not null only available using COPY FROM"
-msgstr "� COPY force not null � n'est disponible qu'en utilisant COPY FROM"
+msgstr "« COPY force not null » n'est disponible qu'en utilisant COPY FROM"
-#: commands/copy.c:1284
+#: commands/copy.c:1323
#, c-format
msgid "COPY force null available only in CSV mode"
-msgstr "� COPY force null � n'est disponible que dans le mode CSV"
+msgstr "« COPY force null » n'est disponible que dans le mode CSV"
-#: commands/copy.c:1289
+#: commands/copy.c:1328
#, c-format
msgid "COPY force null only available using COPY FROM"
-msgstr "� COPY force null � n'est disponible qu'en utilisant COPY FROM"
+msgstr "« COPY force null » n'est disponible qu'en utilisant COPY FROM"
-#: commands/copy.c:1295
+#: commands/copy.c:1334
#, c-format
msgid "COPY delimiter must not appear in the NULL specification"
-msgstr "le d�limiteur COPY ne doit pas appara�tre dans la sp�cification de NULL"
+msgstr "le délimiteur COPY ne doit pas apparaître dans la spécification de NULL"
-#: commands/copy.c:1302
+#: commands/copy.c:1341
#, c-format
msgid "CSV quote character must not appear in the NULL specification"
-msgstr "le caract�re guillemet de CSV ne doit pas appara�tre dans la sp�cification de NULL"
+msgstr "le caractère guillemet de CSV ne doit pas apparaître dans la spécification de NULL"
-#: commands/copy.c:1365
+#: commands/copy.c:1402
#, c-format
msgid "table \"%s\" does not have OIDs"
-msgstr "la table � %s � n'a pas d'OID"
+msgstr "la table « %s » n'a pas d'OID"
-#: commands/copy.c:1382
-#, fuzzy, c-format
-#| msgid "COPY (SELECT) WITH OIDS is not supported"
+#: commands/copy.c:1419
+#, c-format
msgid "COPY (query) WITH OIDS is not supported"
-msgstr "COPY (SELECT) WITH OIDS n'est pas support�"
+msgstr "COPY (requête) WITH OIDS n'est pas supporté"
-#: commands/copy.c:1402
-#, fuzzy, c-format
-#| msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH"
+#: commands/copy.c:1439
+#, c-format
msgid "DO INSTEAD NOTHING rules are not supported for COPY"
-msgstr ""
-"les r�gles DO INSTEAD NOTHING ne sont pas support�es par les instructions\n"
-"de modification de donn�es dans WITH"
+msgstr "les règles DO INSTEAD NOTHING ne sont pas supportées par l'instruction COPY"
-#: commands/copy.c:1416
-#, fuzzy, c-format
-#| msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH"
+#: commands/copy.c:1453
+#, c-format
msgid "conditional DO INSTEAD rules are not supported for COPY"
-msgstr ""
-"les r�gles DO INSTEAD conditionnelles ne sont pas support�es par les\n"
-"instructions de modification de donn�es dans WITH"
+msgstr "les règles DO INSTEAD conditionnelles ne sont pas supportées par l'instruction COPY"
-#: commands/copy.c:1420
-#, fuzzy, c-format
-#| msgid "DO ALSO rules are not supported for data-modifying statements in WITH"
+#: commands/copy.c:1457
+#, c-format
msgid "DO ALSO rules are not supported for the COPY"
-msgstr ""
-"les r�gles DO ALSO ne sont pas support�es par les instructions de modification\n"
-"de donn�es dans WITH"
+msgstr "les règles DO ALSO ne sont pas supportées par l'instruction COPY"
-#: commands/copy.c:1425
-#, fuzzy, c-format
-#| msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH"
+#: commands/copy.c:1462
+#, c-format
msgid "multi-statement DO INSTEAD rules are not supported for COPY"
-msgstr ""
-"les r�gles DO INSTEAD multi-instructions ne sont pas support�es pour les\n"
-"instructions de modification de donn�es dans WITH"
+msgstr "les règles DO INSTEAD multi-instructions ne sont pas supportées par l'instruction COPY"
-#: commands/copy.c:1435
+#: commands/copy.c:1472
#, c-format
msgid "COPY (SELECT INTO) is not supported"
-msgstr "COPY (SELECT INTO) n'est pas support�"
+msgstr "COPY (SELECT INTO) n'est pas supporté"
-#: commands/copy.c:1452
-#, fuzzy, c-format
-#| msgid "WITH query \"%s\" does not have a RETURNING clause"
+#: commands/copy.c:1489
+#, c-format
msgid "COPY query must have a RETURNING clause"
-msgstr "La requ�te WITH � %s � n'a pas de clause RETURNING"
+msgstr "La requête COPY doit avoir une clause RETURNING"
-#: commands/copy.c:1480
+#: commands/copy.c:1517
#, c-format
msgid "relation referenced by COPY statement has changed"
-msgstr "la relation r�f�renc�e par l'instruction COPY a chang�"
+msgstr "la relation référencée par l'instruction COPY a changé"
-#: commands/copy.c:1538
-#, fuzzy, c-format
-#| msgid "FORCE QUOTE column \"%s\" not referenced by COPY"
+#: commands/copy.c:1575
+#, c-format
msgid "FORCE_QUOTE column \"%s\" not referenced by COPY"
-msgstr "la colonne � %s � FORCE QUOTE n'est pas r�f�renc�e par COPY"
+msgstr "la colonne « %s » FORCE_QUOTE n'est pas référencée par COPY"
-#: commands/copy.c:1560
-#, fuzzy, c-format
-#| msgid "FORCE NOT NULL column \"%s\" not referenced by COPY"
+#: commands/copy.c:1597
+#, c-format
msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY"
-msgstr "la colonne � %s � FORCE NOT NULL n'est pas r�f�renc�e par COPY"
+msgstr "la colonne « %s » FORCE_NOT_NULL n'est pas référencée par COPY"
-#: commands/copy.c:1582
-#, fuzzy, c-format
-#| msgid "FORCE NULL column \"%s\" not referenced by COPY"
+#: commands/copy.c:1619
+#, c-format
msgid "FORCE_NULL column \"%s\" not referenced by COPY"
-msgstr "colonne � %s � FORCE NULL non r�f�renc�e par COPY"
+msgstr "colonne « %s » FORCE_NULL non référencée par COPY"
-#: commands/copy.c:1647
+#: commands/copy.c:1684
#, c-format
msgid "could not close pipe to external command: %m"
msgstr "n'a pas pu fermer le fichier pipe vers la commande externe : %m"
-#: commands/copy.c:1651
+#: commands/copy.c:1688
#, c-format
msgid "program \"%s\" failed"
-msgstr "le programme � %s � a �chou�"
+msgstr "le programme « %s » a échoué"
-#: commands/copy.c:1701
+#: commands/copy.c:1738
#, c-format
msgid "cannot copy from view \"%s\""
-msgstr "ne peut pas copier � partir de la vue � %s �"
+msgstr "ne peut pas copier à partir de la vue « %s »"
-#: commands/copy.c:1703 commands/copy.c:1709 commands/copy.c:1715
+#: commands/copy.c:1740 commands/copy.c:1746 commands/copy.c:1752
#, c-format
msgid "Try the COPY (SELECT ...) TO variant."
msgstr "Tentez la variante COPY (SELECT ...) TO."
-#: commands/copy.c:1707
+#: commands/copy.c:1744
#, c-format
msgid "cannot copy from materialized view \"%s\""
-msgstr "ne peut pas copier � partir de la vue mat�rialis�e � %s �"
+msgstr "ne peut pas copier à partir de la vue matérialisée « %s »"
-#: commands/copy.c:1713
+#: commands/copy.c:1750
#, c-format
msgid "cannot copy from foreign table \"%s\""
-msgstr "ne peut pas copier � partir de la table distante � %s �"
+msgstr "ne peut pas copier à partir de la table distante « %s »"
-#: commands/copy.c:1719
+#: commands/copy.c:1756
#, c-format
msgid "cannot copy from sequence \"%s\""
-msgstr "ne peut pas copier � partir de la s�quence � %s �"
+msgstr "ne peut pas copier à partir de la séquence « %s »"
-#: commands/copy.c:1724
+#: commands/copy.c:1761
#, c-format
msgid "cannot copy from non-table relation \"%s\""
-msgstr "ne peut pas copier � partir de la relation � %s �, qui n'est pas une table"
+msgstr "ne peut pas copier à partir de la relation « %s », qui n'est pas une table"
-#: commands/copy.c:1749 commands/copy.c:2787
+#: commands/copy.c:1786 commands/copy.c:2822
#, c-format
msgid "could not execute command \"%s\": %m"
-msgstr "n'a pas pu ex�cuter la commande � %s � : %m"
+msgstr "n'a pas pu exécuter la commande « %s » : %m"
-#: commands/copy.c:1764
+#: commands/copy.c:1801
#, c-format
msgid "relative path not allowed for COPY to file"
-msgstr "un chemin relatif n'est pas autoris� � utiliser COPY vers un fichier"
+msgstr "un chemin relatif n'est pas autorisé à utiliser COPY vers un fichier"
-#: commands/copy.c:1772
+#: commands/copy.c:1809
#, c-format
msgid "could not open file \"%s\" for writing: %m"
-msgstr "n'a pas pu ouvrir le fichier � %s � en �criture : %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » en écriture : %m"
-#: commands/copy.c:1784 commands/copy.c:2810
+#: commands/copy.c:1821 commands/copy.c:2845
#, c-format
msgid "\"%s\" is a directory"
-msgstr "� %s � est un r�pertoire"
+msgstr "« %s » est un répertoire"
-#: commands/copy.c:2109
+#: commands/copy.c:2144
#, c-format
msgid "COPY %s, line %d, column %s"
msgstr "COPY %s, ligne %d, colonne %s"
-#: commands/copy.c:2113 commands/copy.c:2160
+#: commands/copy.c:2148 commands/copy.c:2195
#, c-format
msgid "COPY %s, line %d"
msgstr "COPY %s, ligne %d"
-#: commands/copy.c:2124
+#: commands/copy.c:2159
#, c-format
msgid "COPY %s, line %d, column %s: \"%s\""
-msgstr "COPY %s, ligne %d, colonne %s : � %s �"
+msgstr "COPY %s, ligne %d, colonne %s : « %s »"
-#: commands/copy.c:2132
+#: commands/copy.c:2167
#, c-format
msgid "COPY %s, line %d, column %s: null input"
-msgstr "COPY %s, ligne %d, colonne %s : NULL en entr�e"
+msgstr "COPY %s, ligne %d, colonne %s : NULL en entrée"
-#: commands/copy.c:2154
+#: commands/copy.c:2189
#, c-format
msgid "COPY %s, line %d: \"%s\""
-msgstr "COPY %s, ligne %d : � %s �"
+msgstr "COPY %s, ligne %d : « %s »"
-#: commands/copy.c:2238
+#: commands/copy.c:2273
#, c-format
msgid "cannot copy to view \"%s\""
-msgstr "ne peut pas copier vers la vue � %s �"
+msgstr "ne peut pas copier vers la vue « %s »"
-#: commands/copy.c:2243
+#: commands/copy.c:2278
#, c-format
msgid "cannot copy to materialized view \"%s\""
-msgstr "ne peut pas copier vers la vue mat�rialis�e � %s �"
+msgstr "ne peut pas copier vers la vue matérialisée « %s »"
-#: commands/copy.c:2248
+#: commands/copy.c:2283
#, c-format
msgid "cannot copy to foreign table \"%s\""
-msgstr "ne peut pas copier vers la table distante � %s �"
+msgstr "ne peut pas copier vers la table distante « %s »"
-#: commands/copy.c:2253
+#: commands/copy.c:2288
#, c-format
msgid "cannot copy to sequence \"%s\""
-msgstr "ne peut pas copier vers la s�quence � %s �"
+msgstr "ne peut pas copier vers la séquence « %s »"
-#: commands/copy.c:2258
+#: commands/copy.c:2293
#, c-format
msgid "cannot copy to non-table relation \"%s\""
-msgstr "ne peut pas copier vers une relation � %s � qui n'est pas une table"
+msgstr "ne peut pas copier vers une relation « %s » qui n'est pas une table"
-#: commands/copy.c:2321
+#: commands/copy.c:2356
#, c-format
msgid "cannot perform FREEZE because of prior transaction activity"
-msgstr "n'a pas pu ex�cuter un FREEZE � cause d'une activit� transactionnelle pr�c�dente"
+msgstr "n'a pas pu exécuter un FREEZE à cause d'une activité transactionnelle précédente"
-#: commands/copy.c:2327
+#: commands/copy.c:2362
#, c-format
msgid "cannot perform FREEZE because the table was not created or truncated in the current subtransaction"
-msgstr "n'a pas pu ex�cuter un FREEZE parce que la table n'�tait pas cr��e ou tronqu�e dans la transaction en cours"
+msgstr "n'a pas pu exécuter un FREEZE parce que la table n'était pas créée ou tronquée dans la transaction en cours"
-#: commands/copy.c:2830
+#: commands/copy.c:2865
#, c-format
msgid "COPY file signature not recognized"
msgstr "la signature du fichier COPY n'est pas reconnue"
-#: commands/copy.c:2835
+#: commands/copy.c:2870
#, c-format
msgid "invalid COPY file header (missing flags)"
-msgstr "en-t�te du fichier COPY invalide (options manquantes)"
+msgstr "en-tête du fichier COPY invalide (options manquantes)"
-#: commands/copy.c:2841
+#: commands/copy.c:2876
#, c-format
msgid "unrecognized critical flags in COPY file header"
-msgstr "options critiques non reconnues dans l'en-t�te du fichier COPY"
+msgstr "options critiques non reconnues dans l'en-tête du fichier COPY"
-#: commands/copy.c:2847
+#: commands/copy.c:2882
#, c-format
msgid "invalid COPY file header (missing length)"
-msgstr "en-t�te du fichier COPY invalide (longueur manquante)"
+msgstr "en-tête du fichier COPY invalide (longueur manquante)"
-#: commands/copy.c:2854
+#: commands/copy.c:2889
#, c-format
msgid "invalid COPY file header (wrong length)"
-msgstr "en-t�te du fichier COPY invalide (mauvaise longueur)"
+msgstr "en-tête du fichier COPY invalide (mauvaise longueur)"
-#: commands/copy.c:2987 commands/copy.c:3694 commands/copy.c:3924
+#: commands/copy.c:3022 commands/copy.c:3729 commands/copy.c:3959
#, c-format
msgid "extra data after last expected column"
-msgstr "donn�es suppl�mentaires apr�s la derni�re colonne attendue"
+msgstr "données supplémentaires après la dernière colonne attendue"
-#: commands/copy.c:2997
+#: commands/copy.c:3032
#, c-format
msgid "missing data for OID column"
-msgstr "donn�es manquantes pour la colonne OID"
+msgstr "données manquantes pour la colonne OID"
-#: commands/copy.c:3003
+#: commands/copy.c:3038
#, c-format
msgid "null OID in COPY data"
-msgstr "OID NULL dans les donn�es du COPY"
+msgstr "OID NULL dans les données du COPY"
-#: commands/copy.c:3013 commands/copy.c:3136
+#: commands/copy.c:3048 commands/copy.c:3171
#, c-format
msgid "invalid OID in COPY data"
-msgstr "OID invalide dans les donn�es du COPY"
+msgstr "OID invalide dans les données du COPY"
-#: commands/copy.c:3028
+#: commands/copy.c:3063
#, c-format
msgid "missing data for column \"%s\""
-msgstr "donn�es manquantes pour la colonne � %s �"
+msgstr "données manquantes pour la colonne « %s »"
-#: commands/copy.c:3111
+#: commands/copy.c:3146
#, c-format
msgid "received copy data after EOF marker"
-msgstr "a re�u des donn�es de COPY apr�s le marqueur de fin"
+msgstr "a reçu des données de COPY après le marqueur de fin"
-#: commands/copy.c:3118
+#: commands/copy.c:3153
#, c-format
msgid "row field count is %d, expected %d"
msgstr "le nombre de champs de la ligne est %d, %d attendus"
-#: commands/copy.c:3458 commands/copy.c:3475
+#: commands/copy.c:3493 commands/copy.c:3510
#, c-format
msgid "literal carriage return found in data"
-msgstr "retour chariot trouv� dans les donn�es"
+msgstr "retour chariot trouvé dans les données"
-#: commands/copy.c:3459 commands/copy.c:3476
+#: commands/copy.c:3494 commands/copy.c:3511
#, c-format
msgid "unquoted carriage return found in data"
-msgstr "retour chariot sans guillemet trouv� dans les donn�es"
+msgstr "retour chariot sans guillemet trouvé dans les données"
-#: commands/copy.c:3461 commands/copy.c:3478
+#: commands/copy.c:3496 commands/copy.c:3513
#, c-format
msgid "Use \"\\r\" to represent carriage return."
-msgstr "Utilisez � \\r � pour repr�senter un retour chariot."
+msgstr "Utilisez « \\r » pour représenter un retour chariot."
-#: commands/copy.c:3462 commands/copy.c:3479
+#: commands/copy.c:3497 commands/copy.c:3514
#, c-format
msgid "Use quoted CSV field to represent carriage return."
-msgstr "Utiliser le champ CSV entre guillemets pour repr�senter un retour chariot."
+msgstr "Utiliser le champ CSV entre guillemets pour représenter un retour chariot."
-#: commands/copy.c:3491
+#: commands/copy.c:3526
#, c-format
msgid "literal newline found in data"
-msgstr "retour � la ligne trouv� dans les donn�es"
+msgstr "retour à la ligne trouvé dans les données"
-#: commands/copy.c:3492
+#: commands/copy.c:3527
#, c-format
msgid "unquoted newline found in data"
-msgstr "retour � la ligne trouv� dans les donn�es"
+msgstr "retour à la ligne trouvé dans les données"
-#: commands/copy.c:3494
+#: commands/copy.c:3529
#, c-format
msgid "Use \"\\n\" to represent newline."
-msgstr "Utilisez � \\n � pour repr�senter un retour � la ligne."
+msgstr "Utilisez « \\n » pour représenter un retour à la ligne."
-#: commands/copy.c:3495
+#: commands/copy.c:3530
#, c-format
msgid "Use quoted CSV field to represent newline."
-msgstr "Utiliser un champ CSV entre guillemets pour repr�senter un retour � la ligne."
+msgstr "Utiliser un champ CSV entre guillemets pour représenter un retour à la ligne."
-#: commands/copy.c:3541 commands/copy.c:3577
+#: commands/copy.c:3576 commands/copy.c:3612
#, c-format
msgid "end-of-copy marker does not match previous newline style"
-msgstr "le marqueur fin-de-copie ne correspond pas � un pr�c�dent style de fin de ligne"
+msgstr "le marqueur fin-de-copie ne correspond pas à un précédent style de fin de ligne"
-#: commands/copy.c:3550 commands/copy.c:3566
+#: commands/copy.c:3585 commands/copy.c:3601
#, c-format
msgid "end-of-copy marker corrupt"
msgstr "marqueur fin-de-copie corrompu"
-#: commands/copy.c:4008
+#: commands/copy.c:4043
#, c-format
msgid "unterminated CSV quoted field"
-msgstr "champ CSV entre guillemets non termin�"
+msgstr "champ CSV entre guillemets non terminé"
-#: commands/copy.c:4085 commands/copy.c:4104
+#: commands/copy.c:4120 commands/copy.c:4139
#, c-format
msgid "unexpected EOF in COPY data"
-msgstr "fin de fichier (EOF) inattendu dans les donn�es du COPY"
+msgstr "fin de fichier (EOF) inattendu dans les données du COPY"
-#: commands/copy.c:4094
+#: commands/copy.c:4129
#, c-format
msgid "invalid field size"
msgstr "taille du champ invalide"
-#: commands/copy.c:4117
+#: commands/copy.c:4152
#, c-format
msgid "incorrect binary data format"
-msgstr "format de donn�es binaires incorrect"
+msgstr "format de données binaires incorrect"
-#: commands/copy.c:4428 commands/indexcmds.c:1053 commands/tablecmds.c:1463 commands/tablecmds.c:2290 parser/parse_relation.c:3084 parser/parse_relation.c:3104 utils/adt/tsvector_op.c:2224
+#: commands/copy.c:4463 commands/indexcmds.c:1053 commands/tablecmds.c:1464 commands/tablecmds.c:2291 parser/parse_relation.c:3177 parser/parse_relation.c:3197 utils/adt/tsvector_op.c:2559
#, c-format
msgid "column \"%s\" does not exist"
-msgstr "la colonne � %s � n'existe pas"
+msgstr "la colonne « %s » n'existe pas"
-#: commands/copy.c:4435 commands/tablecmds.c:1489 commands/trigger.c:651 parser/parse_target.c:956 parser/parse_target.c:967
+#: commands/copy.c:4470 commands/tablecmds.c:1490 commands/trigger.c:651 parser/parse_target.c:967 parser/parse_target.c:978
#, c-format
msgid "column \"%s\" specified more than once"
-msgstr "la colonne � %s � est sp�cifi�e plus d'une fois"
+msgstr "la colonne « %s » est spécifiée plus d'une fois"
-#: commands/createas.c:383
+#: commands/createas.c:213 commands/createas.c:509
#, c-format
msgid "too many column names were specified"
-msgstr "trop de noms de colonnes ont �t� sp�cifi�s"
+msgstr "trop de noms de colonnes ont été spécifiés"
-#: commands/createas.c:452
+#: commands/createas.c:550
#, c-format
msgid "policies not yet implemented for this command"
-msgstr "politiques non encore impl�ment�es pour cette commande"
+msgstr "politiques non encore implémentées pour cette commande"
#: commands/dbcommands.c:226
#, c-format
msgid "LOCATION is not supported anymore"
-msgstr "LOCATION n'est plus support�"
+msgstr "LOCATION n'est plus supporté"
#: commands/dbcommands.c:227
#, c-format
msgid "Consider using tablespaces instead."
-msgstr "Consid�rer l'utilisation de tablespaces."
+msgstr "Considérer l'utilisation de tablespaces."
#: commands/dbcommands.c:251 utils/adt/ascii.c:144
#, c-format
@@ -5868,17 +5887,17 @@ msgstr "limite de connexion invalide : %d"
#: commands/dbcommands.c:298
#, c-format
msgid "permission denied to create database"
-msgstr "droit refus� pour cr�er une base de donn�es"
+msgstr "droit refusé pour créer une base de données"
#: commands/dbcommands.c:321
#, c-format
msgid "template database \"%s\" does not exist"
-msgstr "la base de donn�es mod�le � %s � n'existe pas"
+msgstr "la base de données modèle « %s » n'existe pas"
#: commands/dbcommands.c:333
#, c-format
msgid "permission denied to copy database \"%s\""
-msgstr "droit refus� pour copier la base de donn�es � %s �"
+msgstr "droit refusé pour copier la base de données « %s »"
#: commands/dbcommands.c:349
#, c-format
@@ -5888,111 +5907,111 @@ msgstr "encodage serveur %d invalide"
#: commands/dbcommands.c:355 commands/dbcommands.c:360
#, c-format
msgid "invalid locale name: \"%s\""
-msgstr "nom de locale invalide : � %s �"
+msgstr "nom de locale invalide : « %s »"
#: commands/dbcommands.c:380
#, c-format
msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)"
msgstr ""
-"le nouvel encodage (%s� est incompatible avec l'encodage de la base de\n"
-"donn�es mod�le (%s)"
+"le nouvel encodage (%sà est incompatible avec l'encodage de la base de\n"
+"données modèle (%s)"
#: commands/dbcommands.c:383
#, c-format
msgid "Use the same encoding as in the template database, or use template0 as template."
msgstr ""
-"Utilisez le m�me encodage que celui de la base de donn�es mod�le,\n"
-"ou utilisez template0 comme mod�le."
+"Utilisez le même encodage que celui de la base de données modèle,\n"
+"ou utilisez template0 comme modèle."
#: commands/dbcommands.c:388
#, c-format
msgid "new collation (%s) is incompatible with the collation of the template database (%s)"
msgstr ""
"le nouveau tri (%s) est incompatible avec le tri de la base de\n"
-"donn�es mod�le (%s)"
+"données modèle (%s)"
#: commands/dbcommands.c:390
#, c-format
msgid "Use the same collation as in the template database, or use template0 as template."
msgstr ""
-"Utilisez le m�me tri que celui de la base de donn�es mod�le,\n"
-"ou utilisez template0 comme mod�le."
+"Utilisez le même tri que celui de la base de données modèle,\n"
+"ou utilisez template0 comme modèle."
#: commands/dbcommands.c:395
#, c-format
msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)"
msgstr ""
"le nouveau LC_CTYPE (%s) est incompatible avec le LC_CTYPE de la base de\n"
-"donn�es mod�le (%s)"
+"données modèle (%s)"
#: commands/dbcommands.c:397
#, c-format
msgid "Use the same LC_CTYPE as in the template database, or use template0 as template."
msgstr ""
-"Utilisez le m�me LC_CTYPE que celui de la base de donn�es mod�le,\n"
-"ou utilisez template0 comme mod�le."
+"Utilisez le même LC_CTYPE que celui de la base de données modèle,\n"
+"ou utilisez template0 comme modèle."
#: commands/dbcommands.c:419 commands/dbcommands.c:1113
#, c-format
msgid "pg_global cannot be used as default tablespace"
-msgstr "pg_global ne peut pas �tre utilis� comme tablespace par d�faut"
+msgstr "pg_global ne peut pas être utilisé comme tablespace par défaut"
#: commands/dbcommands.c:445
#, c-format
msgid "cannot assign new default tablespace \"%s\""
-msgstr "ne peut pas affecter un nouveau tablespace par d�faut � %s �"
+msgstr "ne peut pas affecter un nouveau tablespace par défaut « %s »"
#: commands/dbcommands.c:447
#, c-format
msgid "There is a conflict because database \"%s\" already has some tables in this tablespace."
msgstr ""
-"Il existe un conflit car la base de donn�es � %s � a d�j� quelques tables\n"
+"Il existe un conflit car la base de données « %s » a déjà quelques tables\n"
"dans son tablespace."
#: commands/dbcommands.c:467 commands/dbcommands.c:982
#, c-format
msgid "database \"%s\" already exists"
-msgstr "la base de donn�es � %s � existe d�j�"
+msgstr "la base de données « %s » existe déjà"
#: commands/dbcommands.c:481
#, c-format
msgid "source database \"%s\" is being accessed by other users"
-msgstr "la base de donn�es source � %s � est acc�d�e par d'autres utilisateurs"
+msgstr "la base de données source « %s » est accédée par d'autres utilisateurs"
#: commands/dbcommands.c:726 commands/dbcommands.c:741
#, c-format
msgid "encoding \"%s\" does not match locale \"%s\""
-msgstr "l'encodage � %s � ne correspond pas � la locale � %s �"
+msgstr "l'encodage « %s » ne correspond pas à la locale « %s »"
#: commands/dbcommands.c:729
#, c-format
msgid "The chosen LC_CTYPE setting requires encoding \"%s\"."
-msgstr "Le param�tre LC_CTYPE choisi n�cessite l'encodage � %s �."
+msgstr "Le paramètre LC_CTYPE choisi nécessite l'encodage « %s »."
#: commands/dbcommands.c:744
#, c-format
msgid "The chosen LC_COLLATE setting requires encoding \"%s\"."
-msgstr "Le param�tre LC_COLLATE choisi n�cessite l'encodage � %s �."
+msgstr "Le paramètre LC_COLLATE choisi nécessite l'encodage « %s »."
#: commands/dbcommands.c:804
#, c-format
msgid "database \"%s\" does not exist, skipping"
-msgstr "la base de donn�es � %s � n'existe pas, poursuite du traitement"
+msgstr "la base de données « %s » n'existe pas, poursuite du traitement"
#: commands/dbcommands.c:828
#, c-format
msgid "cannot drop a template database"
-msgstr "ne peut pas supprimer une base de donn�es mod�le"
+msgstr "ne peut pas supprimer une base de données modèle"
#: commands/dbcommands.c:834
#, c-format
msgid "cannot drop the currently open database"
-msgstr "ne peut pas supprimer la base de donn�es actuellement ouverte"
+msgstr "ne peut pas supprimer la base de données actuellement ouverte"
#: commands/dbcommands.c:844
#, c-format
msgid "database \"%s\" is used by a logical replication slot"
-msgstr "la base de donn�es � %s � est utilis�e par un slot de r�plication logique"
+msgstr "la base de données « %s » est utilisée par un slot de réplication logique"
#: commands/dbcommands.c:846
#, c-format
@@ -6004,650 +6023,652 @@ msgstr[1] "Il existe %d slots, et %d actifs."
#: commands/dbcommands.c:860 commands/dbcommands.c:1004 commands/dbcommands.c:1135
#, c-format
msgid "database \"%s\" is being accessed by other users"
-msgstr "la base de donn�es � %s � est en cours d'utilisation par d'autres utilisateurs"
+msgstr "la base de données « %s » est en cours d'utilisation par d'autres utilisateurs"
#: commands/dbcommands.c:973
#, c-format
msgid "permission denied to rename database"
-msgstr "droit refus� pour le renommage de la base de donn�es"
+msgstr "droit refusé pour le renommage de la base de données"
#: commands/dbcommands.c:993
#, c-format
msgid "current database cannot be renamed"
-msgstr "la base de donn�es actuelle ne peut pas �tre renomm�e"
+msgstr "la base de données actuelle ne peut pas être renommée"
#: commands/dbcommands.c:1091
#, c-format
msgid "cannot change the tablespace of the currently open database"
-msgstr "ne peut pas modifier le tablespace de la base de donn�es actuellement ouverte"
+msgstr "ne peut pas modifier le tablespace de la base de données actuellement ouverte"
#: commands/dbcommands.c:1194
#, c-format
msgid "some relations of database \"%s\" are already in tablespace \"%s\""
msgstr ""
-"certaines relations de la base de donn�es � %s � sont d�j� dans le\n"
-"tablespace � %s �"
+"certaines relations de la base de données « %s » sont déjà dans le\n"
+"tablespace « %s »"
#: commands/dbcommands.c:1196
#, c-format
msgid "You must move them back to the database's default tablespace before using this command."
msgstr ""
-"Vous devez d'abord les d�placer dans le tablespace par d�faut de la base\n"
-"de donn�es avant d'utiliser cette commande."
+"Vous devez d'abord les déplacer dans le tablespace par défaut de la base\n"
+"de données avant d'utiliser cette commande."
#: commands/dbcommands.c:1325 commands/dbcommands.c:1868 commands/dbcommands.c:2072 commands/dbcommands.c:2120 commands/tablespace.c:606
#, c-format
msgid "some useless files may be left behind in old database directory \"%s\""
msgstr ""
-"certains fichiers inutiles pourraient se trouver dans l'ancien r�pertoire\n"
-"de la base de donn�es � %s �"
+"certains fichiers inutiles pourraient se trouver dans l'ancien répertoire\n"
+"de la base de données « %s »"
#: commands/dbcommands.c:1440
#, c-format
msgid "option \"%s\" cannot be specified with other options"
-msgstr "l'option � %s � ne peut pas �tre sp�cifi� avec d'autres options"
+msgstr "l'option « %s » ne peut pas être spécifié avec d'autres options"
#: commands/dbcommands.c:1494
#, c-format
msgid "cannot disallow connections for current database"
-msgstr "ne peut pas d�sactiver les connexions pour la base de donn�es courante"
+msgstr "ne peut pas désactiver les connexions pour la base de données courante"
#: commands/dbcommands.c:1634
#, c-format
msgid "permission denied to change owner of database"
-msgstr "droit refus� pour modifier le propri�taire de la base de donn�es"
+msgstr "droit refusé pour modifier le propriétaire de la base de données"
#: commands/dbcommands.c:1955
#, c-format
msgid "There are %d other session(s) and %d prepared transaction(s) using the database."
-msgstr "%d autres sessions et %d transactions pr�par�es utilisent la base de donn�es."
+msgstr "%d autres sessions et %d transactions préparées utilisent la base de données."
#: commands/dbcommands.c:1958
#, c-format
msgid "There is %d other session using the database."
msgid_plural "There are %d other sessions using the database."
-msgstr[0] "%d autre session utilise la base de donn�es."
-msgstr[1] "%d autres sessions utilisent la base de donn�es."
+msgstr[0] "%d autre session utilise la base de données."
+msgstr[1] "%d autres sessions utilisent la base de données."
#: commands/dbcommands.c:1963
#, c-format
msgid "There is %d prepared transaction using the database."
msgid_plural "There are %d prepared transactions using the database."
-msgstr[0] "%d transaction pr�par�e utilise la base de donn�es"
-msgstr[1] "%d transactions pr�par�es utilisent la base de donn�es"
+msgstr[0] "%d transaction préparée utilise la base de données"
+msgstr[1] "%d transactions préparées utilisent la base de données"
#: commands/define.c:54 commands/define.c:228 commands/define.c:260 commands/define.c:288
#, c-format
msgid "%s requires a parameter"
-msgstr "%s requiert un param�tre"
+msgstr "%s requiert un paramètre"
#: commands/define.c:90 commands/define.c:101 commands/define.c:195 commands/define.c:213
#, c-format
msgid "%s requires a numeric value"
-msgstr "%s requiert une valeur num�rique"
+msgstr "%s requiert une valeur numérique"
#: commands/define.c:157
#, c-format
msgid "%s requires a Boolean value"
-msgstr "%s requiert une valeur bool�enne"
+msgstr "%s requiert une valeur booléenne"
#: commands/define.c:171 commands/define.c:180 commands/define.c:297
#, c-format
msgid "%s requires an integer value"
-msgstr "%s requiert une valeur enti�re"
+msgstr "%s requiert une valeur entière"
#: commands/define.c:242
#, c-format
msgid "argument of %s must be a name"
-msgstr "l'argument de %s doit �tre un nom"
+msgstr "l'argument de %s doit être un nom"
#: commands/define.c:272
#, c-format
msgid "argument of %s must be a type name"
-msgstr "l'argument de %s doit �tre un nom de type"
+msgstr "l'argument de %s doit être un nom de type"
#: commands/define.c:318
#, c-format
msgid "invalid argument for %s: \"%s\""
-msgstr "argument invalide pour %s : � %s �"
+msgstr "argument invalide pour %s : « %s »"
-#: commands/dropcmds.c:112 commands/functioncmds.c:1203 utils/adt/ruleutils.c:1965
+#: commands/dropcmds.c:112 commands/functioncmds.c:1203 utils/adt/ruleutils.c:2080
#, c-format
msgid "\"%s\" is an aggregate function"
-msgstr "� %s � est une fonction d'agr�gat"
+msgstr "« %s » est une fonction d'agrégat"
#: commands/dropcmds.c:114
#, c-format
msgid "Use DROP AGGREGATE to drop aggregate functions."
-msgstr "Utiliser DROP AGGREGATE pour supprimer les fonctions d'agr�gat."
+msgstr "Utiliser DROP AGGREGATE pour supprimer les fonctions d'agrégat."
-#: commands/dropcmds.c:165 commands/sequence.c:424 commands/tablecmds.c:2377 commands/tablecmds.c:2528 commands/tablecmds.c:2570 commands/tablecmds.c:11377 tcop/utility.c:1119
+#: commands/dropcmds.c:165 commands/sequence.c:424 commands/tablecmds.c:2378 commands/tablecmds.c:2529 commands/tablecmds.c:2571 commands/tablecmds.c:11524 tcop/utility.c:1119
#, c-format
msgid "relation \"%s\" does not exist, skipping"
-msgstr "la relation � %s � n'existe pas, poursuite du traitement"
+msgstr "la relation « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:195 commands/dropcmds.c:292 commands/tablecmds.c:745
+#: commands/dropcmds.c:195 commands/dropcmds.c:296 commands/tablecmds.c:746
#, c-format
msgid "schema \"%s\" does not exist, skipping"
-msgstr "le sch�ma � %s � n'existe pas, poursuite du traitement"
+msgstr "le schéma « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:237 commands/dropcmds.c:272 commands/tablecmds.c:246
+#: commands/dropcmds.c:237 commands/dropcmds.c:276 commands/tablecmds.c:247
#, c-format
msgid "type \"%s\" does not exist, skipping"
-msgstr "le type � %s � n'existe pas, poursuite du traitement"
+msgstr "le type « %s » n'existe pas, poursuite du traitement"
+
+#: commands/dropcmds.c:266
+#, c-format
+msgid "access method \"%s\" does not exist, skipping"
+msgstr "la méthode d'accès « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:280
+#: commands/dropcmds.c:284
#, c-format
msgid "collation \"%s\" does not exist, skipping"
-msgstr "le collationnement � %s � n'existe pas, poursuite du traitement"
+msgstr "le collationnement « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:287
+#: commands/dropcmds.c:291
#, c-format
msgid "conversion \"%s\" does not exist, skipping"
-msgstr "la conversion � %s � n'existe pas, poursuite du traitement"
+msgstr "la conversion « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:298
+#: commands/dropcmds.c:302
#, c-format
msgid "text search parser \"%s\" does not exist, skipping"
msgstr ""
-"l'analyseur de recherche plein texte � %s � n'existe pas, poursuite du\n"
+"l'analyseur de recherche plein texte « %s » n'existe pas, poursuite du\n"
"traitement"
-#: commands/dropcmds.c:305
+#: commands/dropcmds.c:309
#, c-format
msgid "text search dictionary \"%s\" does not exist, skipping"
msgstr ""
-"le dictionnaire de recherche plein texte � %s � n'existe pas, poursuite du\n"
+"le dictionnaire de recherche plein texte « %s » n'existe pas, poursuite du\n"
"traitement"
-#: commands/dropcmds.c:312
+#: commands/dropcmds.c:316
#, c-format
msgid "text search template \"%s\" does not exist, skipping"
-msgstr "le mod�le de recherche plein texte � %s � n'existe pas, poursuite du traitement"
+msgstr "le modèle de recherche plein texte « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:319
+#: commands/dropcmds.c:323
#, c-format
msgid "text search configuration \"%s\" does not exist, skipping"
msgstr ""
-"la configuration de recherche plein texte � %s � n'existe pas, poursuite du\n"
+"la configuration de recherche plein texte « %s » n'existe pas, poursuite du\n"
"traitement"
-#: commands/dropcmds.c:324
+#: commands/dropcmds.c:328
#, c-format
msgid "extension \"%s\" does not exist, skipping"
-msgstr "l'extension � %s � n'existe pas, poursuite du traitement"
+msgstr "l'extension « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:331
+#: commands/dropcmds.c:335
#, c-format
msgid "function %s(%s) does not exist, skipping"
msgstr "la fonction %s(%s) n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:340
+#: commands/dropcmds.c:344
#, c-format
msgid "aggregate %s(%s) does not exist, skipping"
-msgstr "L'agr�gat %s(%s) n'existe pas, poursuite du traitement"
+msgstr "L'agrégat %s(%s) n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:349
+#: commands/dropcmds.c:353
#, c-format
msgid "operator %s does not exist, skipping"
-msgstr "l'op�rateur %s n'existe pas, poursuite du traitement"
+msgstr "l'opérateur %s n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:354
+#: commands/dropcmds.c:358
#, c-format
msgid "language \"%s\" does not exist, skipping"
-msgstr "le langage � %s � n'existe pas, poursuite du traitement"
+msgstr "le langage « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:363
+#: commands/dropcmds.c:367
#, c-format
msgid "cast from type %s to type %s does not exist, skipping"
msgstr "la conversion du type %s vers le type %s n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:372
+#: commands/dropcmds.c:376
#, c-format
msgid "transform for type %s language \"%s\" does not exist, skipping"
-msgstr "la transformation pour le type %s et le langage � %s � n'existe pas, poursuite du traitement"
+msgstr "la transformation pour le type %s et le langage « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:380
+#: commands/dropcmds.c:384
#, c-format
msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping"
-msgstr "le trigger � %s � de la relation � %s � n'existe pas, poursuite du traitement"
+msgstr "le trigger « %s » de la relation « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:389
+#: commands/dropcmds.c:393
#, c-format
msgid "policy \"%s\" for relation \"%s\" does not exist, skipping"
-msgstr "la politique � %s � de la relation � %s � n'existe pas, poursuite du traitement"
+msgstr "la politique « %s » de la relation « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:396
+#: commands/dropcmds.c:400
#, c-format
msgid "event trigger \"%s\" does not exist, skipping"
-msgstr "le trigger sur �v�nement � %s � n'existe pas, poursuite du traitement"
+msgstr "le trigger sur événement « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:402
+#: commands/dropcmds.c:406
#, c-format
msgid "rule \"%s\" for relation \"%s\" does not exist, skipping"
-msgstr "la r�gle � %s � de la relation � %s � n'existe pas, poursuite du traitement"
+msgstr "la règle « %s » de la relation « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:409
+#: commands/dropcmds.c:413
#, c-format
msgid "foreign-data wrapper \"%s\" does not exist, skipping"
-msgstr "le wrapper de donn�es distantes � %s � n'existe pas, poursuite du traitement"
+msgstr "le wrapper de données distantes « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:413
+#: commands/dropcmds.c:417
#, c-format
msgid "server \"%s\" does not exist, skipping"
-msgstr "le serveur � %s � n'existe pas, poursuite du traitement"
+msgstr "le serveur « %s » n'existe pas, poursuite du traitement"
-#: commands/dropcmds.c:422
+#: commands/dropcmds.c:426
#, c-format
msgid "operator class \"%s\" does not exist for access method \"%s\", skipping"
-msgstr "la classe d'op�rateur � %s � n'existe pas pour la m�thode d'acc�s � %s �, ignor�"
+msgstr "la classe d'opérateur « %s » n'existe pas pour la méthode d'accès « %s », ignoré"
-#: commands/dropcmds.c:434
+#: commands/dropcmds.c:438
#, c-format
msgid "operator family \"%s\" does not exist for access method \"%s\", skipping"
-msgstr "la famille d'op�rateur � %s � n'existe pas pour la m�thode d'acc�s � %s �, ignor�"
+msgstr "la famille d'opérateur « %s » n'existe pas pour la méthode d'accès « %s », ignoré"
#: commands/event_trigger.c:182
#, c-format
msgid "permission denied to create event trigger \"%s\""
-msgstr "droit refus� pour cr�er le trigger sur �v�nement � %s �"
+msgstr "droit refusé pour créer le trigger sur événement « %s »"
#: commands/event_trigger.c:184
#, c-format
msgid "Must be superuser to create an event trigger."
-msgstr "Doit �tre super-utilisateur pour cr�er un trigger sur �v�nement."
+msgstr "Doit être super-utilisateur pour créer un trigger sur événement."
#: commands/event_trigger.c:193
#, c-format
msgid "unrecognized event name \"%s\""
-msgstr "nom d'�v�nement non reconnu : � %s �"
+msgstr "nom d'événement non reconnu : « %s »"
#: commands/event_trigger.c:210
#, c-format
msgid "unrecognized filter variable \"%s\""
-msgstr "variable � %s � du filtre non reconnu"
+msgstr "variable « %s » du filtre non reconnu"
#: commands/event_trigger.c:265
#, c-format
msgid "filter value \"%s\" not recognized for filter variable \"%s\""
-msgstr "valeur de filtre � %s � non reconnu pour la variable de filtre � %s �"
+msgstr "valeur de filtre « %s » non reconnu pour la variable de filtre « %s »"
#. translator: %s represents an SQL statement name
#: commands/event_trigger.c:271 commands/event_trigger.c:341
#, c-format
msgid "event triggers are not supported for %s"
-msgstr "les triggers sur �v�nemenr ne sont pas support�s pour %s"
+msgstr "les triggers sur événemenr ne sont pas supportés pour %s"
#: commands/event_trigger.c:364
#, c-format
msgid "filter variable \"%s\" specified more than once"
-msgstr "variable � %s � du filtre sp�cifi�e plus d'une fois"
+msgstr "variable « %s » du filtre spécifiée plus d'une fois"
#: commands/event_trigger.c:512 commands/event_trigger.c:556 commands/event_trigger.c:649
#, c-format
msgid "event trigger \"%s\" does not exist"
-msgstr "le trigger sur �v�nement � %s � n'existe pas"
+msgstr "le trigger sur événement « %s » n'existe pas"
#: commands/event_trigger.c:617
#, c-format
msgid "permission denied to change owner of event trigger \"%s\""
-msgstr "droit refus� pour modifier le propri�taire du trigger sur �v�nement � %s �"
+msgstr "droit refusé pour modifier le propriétaire du trigger sur événement « %s »"
#: commands/event_trigger.c:619
#, c-format
msgid "The owner of an event trigger must be a superuser."
-msgstr "Le propri�taire du trigger sur �v�nement doit �tre un super-utilisateur."
+msgstr "Le propriétaire du trigger sur événement doit être un super-utilisateur."
-#: commands/event_trigger.c:1442
+#: commands/event_trigger.c:1438
#, c-format
msgid "%s can only be called in a sql_drop event trigger function"
-msgstr "%s peut seulement �tre appel� dans une fonction de trigger sur �v�nement sql_drop"
+msgstr "%s peut seulement être appelé dans une fonction de trigger sur événement sql_drop"
-#: commands/event_trigger.c:1562 commands/event_trigger.c:1583
+#: commands/event_trigger.c:1558 commands/event_trigger.c:1579
#, c-format
msgid "%s can only be called in a table_rewrite event trigger function"
-msgstr "%s peut seulement �tre appel� dans une fonction de trigger sur �v�nement table_rewrite"
+msgstr "%s peut seulement être appelé dans une fonction de trigger sur événement table_rewrite"
-#: commands/event_trigger.c:1993
+#: commands/event_trigger.c:1989
#, c-format
msgid "%s can only be called in an event trigger function"
-msgstr "%s peut seulement �tre appel� dans une fonction de trigger sur �v�nement"
+msgstr "%s peut seulement être appelé dans une fonction de trigger sur événement"
-#: commands/explain.c:184
+#: commands/explain.c:185
#, c-format
msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\""
-msgstr "valeur non reconnue pour l'option EXPLAIN � %s � : %s"
+msgstr "valeur non reconnue pour l'option EXPLAIN « %s » : %s"
-#: commands/explain.c:190
+#: commands/explain.c:191
#, c-format
msgid "unrecognized EXPLAIN option \"%s\""
-msgstr "option EXPLAIN � %s � non reconnu"
+msgstr "option EXPLAIN « %s » non reconnu"
-#: commands/explain.c:197
+#: commands/explain.c:198
#, c-format
msgid "EXPLAIN option BUFFERS requires ANALYZE"
-msgstr "l'option BUFFERS d'EXPLAIN n�cessite ANALYZE"
+msgstr "l'option BUFFERS d'EXPLAIN nécessite ANALYZE"
-#: commands/explain.c:206
+#: commands/explain.c:207
#, c-format
msgid "EXPLAIN option TIMING requires ANALYZE"
-msgstr "l'option TIMING d'EXPLAIN n�cessite ANALYZE"
+msgstr "l'option TIMING d'EXPLAIN nécessite ANALYZE"
-#: commands/extension.c:154 commands/extension.c:2718
+#: commands/extension.c:155 commands/extension.c:2719
#, c-format
msgid "extension \"%s\" does not exist"
-msgstr "l'extension � %s � n'existe pas"
+msgstr "l'extension « %s » n'existe pas"
-#: commands/extension.c:253 commands/extension.c:262 commands/extension.c:274 commands/extension.c:284
+#: commands/extension.c:254 commands/extension.c:263 commands/extension.c:275 commands/extension.c:285
#, c-format
msgid "invalid extension name: \"%s\""
-msgstr "nom d'extension invalide : � %s �"
+msgstr "nom d'extension invalide : « %s »"
-#: commands/extension.c:254
+#: commands/extension.c:255
#, c-format
msgid "Extension names must not be empty."
-msgstr "Les noms d'extension ne doivent pas �tre vides."
+msgstr "Les noms d'extension ne doivent pas être vides."
-#: commands/extension.c:263
+#: commands/extension.c:264
#, c-format
msgid "Extension names must not contain \"--\"."
-msgstr "Les noms d'extension ne doivent pas contenir � -- �."
+msgstr "Les noms d'extension ne doivent pas contenir « -- »."
-#: commands/extension.c:275
+#: commands/extension.c:276
#, c-format
msgid "Extension names must not begin or end with \"-\"."
-msgstr "Les noms des extensions ne doivent pas commencer ou finir avec un tiret (� - �)."
+msgstr "Les noms des extensions ne doivent pas commencer ou finir avec un tiret (« - »)."
-#: commands/extension.c:285
+#: commands/extension.c:286
#, c-format
msgid "Extension names must not contain directory separator characters."
-msgstr "Les noms des extensions ne doivent pas contenir des caract�res s�parateurs de r�pertoire."
+msgstr "Les noms des extensions ne doivent pas contenir des caractères séparateurs de répertoire."
-#: commands/extension.c:300 commands/extension.c:309 commands/extension.c:318 commands/extension.c:328
+#: commands/extension.c:301 commands/extension.c:310 commands/extension.c:319 commands/extension.c:329
#, c-format
msgid "invalid extension version name: \"%s\""
-msgstr "nom de version de l'extension invalide : � %s �"
+msgstr "nom de version de l'extension invalide : « %s »"
-#: commands/extension.c:301
+#: commands/extension.c:302
#, c-format
msgid "Version names must not be empty."
-msgstr "Les noms de version ne doivent pas �tre vides."
+msgstr "Les noms de version ne doivent pas être vides."
-#: commands/extension.c:310
+#: commands/extension.c:311
#, c-format
msgid "Version names must not contain \"--\"."
-msgstr "Les noms de version ne doivent pas contenir � -- �."
+msgstr "Les noms de version ne doivent pas contenir « -- »."
-#: commands/extension.c:319
+#: commands/extension.c:320
#, c-format
msgid "Version names must not begin or end with \"-\"."
msgstr "Les noms de version ne doivent ni commencer ni se terminer avec un tiret."
-#: commands/extension.c:329
+#: commands/extension.c:330
#, c-format
msgid "Version names must not contain directory separator characters."
msgstr ""
-"Les noms de version ne doivent pas contenir de caract�res s�parateurs de\n"
-"r�pertoire."
+"Les noms de version ne doivent pas contenir de caractères séparateurs de\n"
+"répertoire."
-#: commands/extension.c:479
+#: commands/extension.c:480
#, c-format
msgid "could not open extension control file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier de contr�le d'extension � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier de contrôle d'extension « %s » : %m"
-#: commands/extension.c:501 commands/extension.c:511
+#: commands/extension.c:502 commands/extension.c:512
#, c-format
msgid "parameter \"%s\" cannot be set in a secondary extension control file"
msgstr ""
-"le param�tre � %s � ne peut pas �tre configur� dans un fichier de contr�le\n"
+"le paramètre « %s » ne peut pas être configuré dans un fichier de contrôle\n"
"secondaire de l'extension"
-#: commands/extension.c:550
+#: commands/extension.c:551
#, c-format
msgid "\"%s\" is not a valid encoding name"
-msgstr "� %s � n'est pas un nom d'encodage valide"
+msgstr "« %s » n'est pas un nom d'encodage valide"
-#: commands/extension.c:564
+#: commands/extension.c:565
#, c-format
msgid "parameter \"%s\" must be a list of extension names"
-msgstr "l'argument � %s � doit �tre une liste de noms d'extension"
+msgstr "l'argument « %s » doit être une liste de noms d'extension"
-#: commands/extension.c:571
+#: commands/extension.c:572
#, c-format
msgid "unrecognized parameter \"%s\" in file \"%s\""
-msgstr "param�tre � %s � non reconnu dans le fichier � %s �"
+msgstr "paramètre « %s » non reconnu dans le fichier « %s »"
-#: commands/extension.c:580
+#: commands/extension.c:581
#, c-format
msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true"
-msgstr "le param�tre � schema � ne peut pas �tre indiqu� quand � relocatable � est vrai"
+msgstr "le paramètre « schema » ne peut pas être indiqué quand « relocatable » est vrai"
-#: commands/extension.c:721
+#: commands/extension.c:722
#, c-format
msgid "transaction control statements are not allowed within an extension script"
msgstr ""
-"les instructions de contr�le des transactions ne sont pas autoris�es dans un\n"
+"les instructions de contrôle des transactions ne sont pas autorisées dans un\n"
"script d'extension"
-#: commands/extension.c:789
+#: commands/extension.c:790
#, c-format
msgid "permission denied to create extension \"%s\""
-msgstr "droit refus� pour cr�er l'extension � %s �"
+msgstr "droit refusé pour créer l'extension « %s »"
-#: commands/extension.c:791
+#: commands/extension.c:792
#, c-format
msgid "Must be superuser to create this extension."
-msgstr "Doit �tre super-utilisateur pour cr�er cette extension."
+msgstr "Doit être super-utilisateur pour créer cette extension."
-#: commands/extension.c:795
+#: commands/extension.c:796
#, c-format
msgid "permission denied to update extension \"%s\""
-msgstr "droit refus� pour mettre � jour l'extension � %s �"
+msgstr "droit refusé pour mettre à jour l'extension « %s »"
-#: commands/extension.c:797
+#: commands/extension.c:798
#, c-format
msgid "Must be superuser to update this extension."
-msgstr "Doit �tre super-utilisateur pour mettre � jour cette extension."
+msgstr "Doit être super-utilisateur pour mettre à jour cette extension."
-#: commands/extension.c:1079
+#: commands/extension.c:1080
#, c-format
msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\""
-msgstr "l'extension � %s � n'a pas de chemin de mise � jour pour aller de la version � %s � � la version � %s �"
+msgstr "l'extension « %s » n'a pas de chemin de mise à jour pour aller de la version « %s » à la version « %s »"
-#: commands/extension.c:1261 commands/extension.c:2778
+#: commands/extension.c:1262 commands/extension.c:2779
#, c-format
msgid "version to install must be specified"
-msgstr "la version � installer doit �tre pr�cis�e"
+msgstr "la version à installer doit être précisée"
-#: commands/extension.c:1278
+#: commands/extension.c:1279
#, c-format
msgid "FROM version must be different from installation target version \"%s\""
-msgstr "la version FROM doit �tre diff�rente de la version cible d'installation � %s �"
+msgstr "la version FROM doit être différente de la version cible d'installation « %s »"
-#: commands/extension.c:1343
+#: commands/extension.c:1344
#, c-format
msgid "extension \"%s\" must be installed in schema \"%s\""
-msgstr "l'extension � %s � doit �tre install�e dans le sch�ma � %s �"
+msgstr "l'extension « %s » doit être installée dans le schéma « %s »"
-#: commands/extension.c:1435
-#, fuzzy, c-format
-#| msgid "collation mismatch between explicit collations \"%s\" and \"%s\""
+#: commands/extension.c:1436
+#, c-format
msgid "cyclic dependency detected between extensions \"%s\" and \"%s\""
-msgstr "le collationnement ne correspond pas aux collationnements explicites � %s � et � %s �"
+msgstr "dépendance cyclique détectée entre les extensions « %s » et « %s »"
-#: commands/extension.c:1440
-#, fuzzy, c-format
-#| msgid "invalid extension name: \"%s\""
+#: commands/extension.c:1441
+#, c-format
msgid "installing required extension \"%s\""
-msgstr "nom d'extension invalide : � %s �"
+msgstr "installation de l'extension requise « %s »"
-#: commands/extension.c:1468 commands/extension.c:2923
+#: commands/extension.c:1469 commands/extension.c:2924
#, c-format
msgid "required extension \"%s\" is not installed"
-msgstr "l'extension � %s � requise n'est pas install�e"
+msgstr "l'extension « %s » requise n'est pas installée"
-#: commands/extension.c:1470
-#, fuzzy, c-format
-#| msgid "Use ALTER ... CASCADE to alter the typed tables too."
-msgid "Use CREATE EXTENSION CASCADE to install required extensions too."
-msgstr "Utilisez ALTER ... CASCADE pour modifier aussi les tables de type."
+#: commands/extension.c:1471
+#, c-format
+msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too."
+msgstr "Utilisez CREATE EXTENSION ... CASCADE pour installer également les extensions requises."
-#: commands/extension.c:1534
+#: commands/extension.c:1535
#, c-format
msgid "extension \"%s\" already exists, skipping"
-msgstr "l'extension � %s � existe d�j�, poursuite du traitement"
+msgstr "l'extension « %s » existe déjà, poursuite du traitement"
-#: commands/extension.c:1541
+#: commands/extension.c:1542
#, c-format
msgid "extension \"%s\" already exists"
-msgstr "l'extension � %s � existe d�j�"
+msgstr "l'extension « %s » existe déjà"
-#: commands/extension.c:1552
+#: commands/extension.c:1553
#, c-format
msgid "nested CREATE EXTENSION is not supported"
-msgstr "CREATE EXTENSION imbriqu� n'est pas support�"
+msgstr "CREATE EXTENSION imbriqué n'est pas supporté"
-#: commands/extension.c:1680
+#: commands/extension.c:1681
#, c-format
msgid "cannot drop extension \"%s\" because it is being modified"
-msgstr "ne peut pas supprimer l'extension � %s � car il est en cours de modification"
+msgstr "ne peut pas supprimer l'extension « %s » car il est en cours de modification"
-#: commands/extension.c:2151
+#: commands/extension.c:2152
#, c-format
msgid "pg_extension_config_dump() can only be called from an SQL script executed by CREATE EXTENSION"
msgstr ""
-"pg_extension_config_dump() peut seulement �tre appel� � partir d'un script SQL\n"
-"ex�cut� par CREATE EXTENSION"
+"pg_extension_config_dump() peut seulement être appelé à partir d'un script SQL\n"
+"exécuté par CREATE EXTENSION"
-#: commands/extension.c:2163
+#: commands/extension.c:2164
#, c-format
msgid "OID %u does not refer to a table"
-msgstr "l'OID %u ne fait pas r�f�rence � une table"
+msgstr "l'OID %u ne fait pas référence à une table"
-#: commands/extension.c:2168
+#: commands/extension.c:2169
#, c-format
msgid "table \"%s\" is not a member of the extension being created"
-msgstr "la table � %s � n'est pas un membre de l'extension en cours de cr�ation"
+msgstr "la table « %s » n'est pas un membre de l'extension en cours de création"
-#: commands/extension.c:2533
+#: commands/extension.c:2534
#, c-format
msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema"
msgstr ""
-"ne peut pas d�placer l'extension � %s � dans le sch�ma � %s � car l'extension\n"
-"contient le sch�ma"
+"ne peut pas déplacer l'extension « %s » dans le schéma « %s » car l'extension\n"
+"contient le schéma"
-#: commands/extension.c:2573 commands/extension.c:2636
+#: commands/extension.c:2574 commands/extension.c:2637
#, c-format
msgid "extension \"%s\" does not support SET SCHEMA"
-msgstr "l'extension � %s � ne supporte pas SET SCHEMA"
+msgstr "l'extension « %s » ne supporte pas SET SCHEMA"
-#: commands/extension.c:2638
+#: commands/extension.c:2639
#, c-format
msgid "%s is not in the extension's schema \"%s\""
-msgstr "%s n'est pas dans le sch�ma � %s � de l'extension"
+msgstr "%s n'est pas dans le schéma « %s » de l'extension"
-#: commands/extension.c:2698
+#: commands/extension.c:2699
#, c-format
msgid "nested ALTER EXTENSION is not supported"
-msgstr "un ALTER EXTENSION imbriqu� n'est pas support�"
+msgstr "un ALTER EXTENSION imbriqué n'est pas supporté"
-#: commands/extension.c:2789
+#: commands/extension.c:2790
#, c-format
msgid "version \"%s\" of extension \"%s\" is already installed"
-msgstr "la version � %s � de l'extension � %s � est d�j� install�e"
+msgstr "la version « %s » de l'extension « %s » est déjà installée"
-#: commands/extension.c:3040
+#: commands/extension.c:3041
#, c-format
msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension"
msgstr ""
-"ne peut pas ajouter le sch�ma � %s � � l'extension � %s � car le sch�ma\n"
+"ne peut pas ajouter le schéma « %s » à l'extension « %s » car le schéma\n"
"contient l'extension"
-#: commands/extension.c:3058
+#: commands/extension.c:3069
#, c-format
msgid "%s is not a member of extension \"%s\""
-msgstr "%s n'est pas un membre de l'extension � %s �"
+msgstr "%s n'est pas un membre de l'extension « %s »"
-#: commands/extension.c:3114
+#: commands/extension.c:3135
#, c-format
msgid "file \"%s\" is too large"
-msgstr "le fichier � %s � est trop gros"
+msgstr "le fichier « %s » est trop gros"
#: commands/foreigncmds.c:150 commands/foreigncmds.c:159
#, c-format
msgid "option \"%s\" not found"
-msgstr "option � %s � non trouv�"
+msgstr "option « %s » non trouvé"
#: commands/foreigncmds.c:169
#, c-format
msgid "option \"%s\" provided more than once"
-msgstr "option � %s � fournie plus d'une fois"
+msgstr "option « %s » fournie plus d'une fois"
#: commands/foreigncmds.c:223 commands/foreigncmds.c:231
#, c-format
msgid "permission denied to change owner of foreign-data wrapper \"%s\""
-msgstr "droit refus� pour modifier le propri�taire du wrapper de donn�es distantes � %s �"
+msgstr "droit refusé pour modifier le propriétaire du wrapper de données distantes « %s »"
#: commands/foreigncmds.c:225
#, c-format
msgid "Must be superuser to change owner of a foreign-data wrapper."
msgstr ""
-"Doit �tre super-utilisateur pour modifier le propri�taire du wrapper de\n"
-"donn�es distantes."
+"Doit être super-utilisateur pour modifier le propriétaire du wrapper de\n"
+"données distantes."
#: commands/foreigncmds.c:233
#, c-format
msgid "The owner of a foreign-data wrapper must be a superuser."
-msgstr "Le propri�taire du wrapper de donn�es distantes doit �tre un super-utilisateur."
+msgstr "Le propriétaire du wrapper de données distantes doit être un super-utilisateur."
-#: commands/foreigncmds.c:292 commands/foreigncmds.c:709 foreign/foreign.c:777
+#: commands/foreigncmds.c:292 commands/foreigncmds.c:709 foreign/foreign.c:671
#, c-format
msgid "foreign-data wrapper \"%s\" does not exist"
-msgstr "le wrapper de donn�es distantes � %s � n'existe pas"
+msgstr "le wrapper de données distantes « %s » n'existe pas"
#: commands/foreigncmds.c:584
#, c-format
msgid "permission denied to create foreign-data wrapper \"%s\""
-msgstr "droit refus� pour la cr�ation du wrapper de donn�es distantes � %s �"
+msgstr "droit refusé pour la création du wrapper de données distantes « %s »"
#: commands/foreigncmds.c:586
#, c-format
msgid "Must be superuser to create a foreign-data wrapper."
-msgstr "Doit �tre super-utilisateur pour cr�er un wrapper de donn�es distantes."
+msgstr "Doit être super-utilisateur pour créer un wrapper de données distantes."
#: commands/foreigncmds.c:699
#, c-format
msgid "permission denied to alter foreign-data wrapper \"%s\""
-msgstr "droit refus� pour modifier le wrapper de donn�es distantes � %s �"
+msgstr "droit refusé pour modifier le wrapper de données distantes « %s »"
#: commands/foreigncmds.c:701
#, c-format
msgid "Must be superuser to alter a foreign-data wrapper."
-msgstr "Doit �tre super-utilisateur pour modifier un wrapper de donn�es distantes"
+msgstr "Doit être super-utilisateur pour modifier un wrapper de données distantes"
#: commands/foreigncmds.c:732
#, c-format
msgid "changing the foreign-data wrapper handler can change behavior of existing foreign tables"
msgstr ""
-"la modification du validateur de wrapper de donn�es distantes peut modifier\n"
+"la modification du validateur de wrapper de données distantes peut modifier\n"
"le comportement des tables distantes existantes"
#: commands/foreigncmds.c:747
#, c-format
msgid "changing the foreign-data wrapper validator can cause the options for dependent objects to become invalid"
msgstr ""
-"la modification du validateur du wrapper de donn�es distantes peut faire en\n"
-"sorte que les options des objets d�pendants deviennent invalides"
+"la modification du validateur du wrapper de données distantes peut faire en\n"
+"sorte que les options des objets dépendants deviennent invalides"
#: commands/foreigncmds.c:1165
#, c-format
msgid "user mapping \"%s\" already exists for server %s"
-msgstr "la correspondance utilisateur � %s � existe d�j� dans le serveur � %s �"
+msgstr "la correspondance utilisateur « %s » existe déjà dans le serveur « %s »"
#: commands/foreigncmds.c:1259 commands/foreigncmds.c:1375
#, c-format
msgid "user mapping \"%s\" does not exist for the server"
-msgstr "la correspondance utilisateur � %s � n'existe pas pour le serveur"
+msgstr "la correspondance utilisateur « %s » n'existe pas pour le serveur"
#: commands/foreigncmds.c:1362
#, c-format
@@ -6658,23 +6679,23 @@ msgstr "le serveur n'existe pas, poursuite du traitement"
#, c-format
msgid "user mapping \"%s\" does not exist for the server, skipping"
msgstr ""
-"la correspondance utilisateur � %s � n'existe pas pour le serveur, poursuite\n"
+"la correspondance utilisateur « %s » n'existe pas pour le serveur, poursuite\n"
"du traitement"
-#: commands/foreigncmds.c:1532 foreign/foreign.c:467
+#: commands/foreigncmds.c:1532 foreign/foreign.c:361
#, c-format
msgid "foreign-data wrapper \"%s\" has no handler"
-msgstr "le wrapper de donn�es distantes � %s � n'a pas de gestionnaire"
+msgstr "le wrapper de données distantes « %s » n'a pas de gestionnaire"
#: commands/foreigncmds.c:1538
#, c-format
msgid "foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA"
-msgstr "le wrapper de donn�es distantes � %s � ne supporte pas IMPORT FOREIGN SCHEMA"
+msgstr "le wrapper de données distantes « %s » ne supporte pas IMPORT FOREIGN SCHEMA"
#: commands/foreigncmds.c:1631
#, c-format
msgid "importing foreign table \"%s\""
-msgstr "import de la table distante � %s �"
+msgstr "import de la table distante « %s »"
#: commands/functioncmds.c:99
#, c-format
@@ -6689,17 +6710,17 @@ msgstr "le type de retour %s est seulement un shell"
#: commands/functioncmds.c:134 parser/parse_type.c:337
#, c-format
msgid "type modifier cannot be specified for shell type \"%s\""
-msgstr "le modificateur de type ne peut pas �tre pr�cis� pour le type shell � %s �"
+msgstr "le modificateur de type ne peut pas être précisé pour le type shell « %s »"
#: commands/functioncmds.c:140
#, c-format
msgid "type \"%s\" is not yet defined"
-msgstr "le type � %s � n'est pas encore d�fini"
+msgstr "le type « %s » n'est pas encore défini"
#: commands/functioncmds.c:141
#, c-format
msgid "Creating a shell type definition."
-msgstr "Cr�ation d'une d�finition d'un type shell."
+msgstr "Création d'une définition d'un type shell."
#: commands/functioncmds.c:239
#, c-format
@@ -6709,7 +6730,7 @@ msgstr "la fonction SQL ne peut pas accepter le type shell %s"
#: commands/functioncmds.c:245
#, c-format
msgid "aggregate cannot accept shell type %s"
-msgstr "l'agr�gat ne peut pas accepter le type shell %s"
+msgstr "l'agrégat ne peut pas accepter le type shell %s"
#: commands/functioncmds.c:250
#, c-format
@@ -6724,7 +6745,7 @@ msgstr "le type %s n'existe pas"
#: commands/functioncmds.c:274
#, c-format
msgid "aggregates cannot accept set arguments"
-msgstr "les agr�gats ne peuvent pas utiliser des arguments d'ensemble"
+msgstr "les agrégats ne peuvent pas utiliser des arguments d'ensemble"
#: commands/functioncmds.c:278
#, c-format
@@ -6734,89 +6755,89 @@ msgstr "les fonctions ne peuvent pas accepter des arguments d'ensemble"
#: commands/functioncmds.c:288
#, c-format
msgid "VARIADIC parameter must be the last input parameter"
-msgstr "le param�tre VARIADIC doit �tre le dernier param�tre en entr�e"
+msgstr "le paramètre VARIADIC doit être le dernier paramètre en entrée"
#: commands/functioncmds.c:316
#, c-format
msgid "VARIADIC parameter must be an array"
-msgstr "le param�tre VARIADIC doit �tre un tableau"
+msgstr "le paramètre VARIADIC doit être un tableau"
#: commands/functioncmds.c:356
#, c-format
msgid "parameter name \"%s\" used more than once"
-msgstr "le nom du param�tre � %s � est utilis� plus d'une fois"
+msgstr "le nom du paramètre « %s » est utilisé plus d'une fois"
#: commands/functioncmds.c:371
#, c-format
msgid "only input parameters can have default values"
-msgstr "seuls les param�tres en entr�e peuvent avoir des valeurs par d�faut"
+msgstr "seuls les paramètres en entrée peuvent avoir des valeurs par défaut"
#: commands/functioncmds.c:386
#, c-format
msgid "cannot use table references in parameter default value"
msgstr ""
-"ne peut pas utiliser les r�f�rences de tables dans la valeur par d�faut des\n"
-"param�tres"
+"ne peut pas utiliser les références de tables dans la valeur par défaut des\n"
+"paramètres"
#: commands/functioncmds.c:410
#, c-format
msgid "input parameters after one with a default value must also have defaults"
-msgstr "les param�tres en entr�e suivant un param�tre avec valeur par d�faut doivent aussi avoir des valeurs par d�faut"
+msgstr "les paramètres en entrée suivant un paramètre avec valeur par défaut doivent aussi avoir des valeurs par défaut"
#: commands/functioncmds.c:701
#, c-format
msgid "no function body specified"
-msgstr "aucun corps de fonction sp�cifi�"
+msgstr "aucun corps de fonction spécifié"
#: commands/functioncmds.c:711
#, c-format
msgid "no language specified"
-msgstr "aucun langage sp�cifi�"
+msgstr "aucun langage spécifié"
#: commands/functioncmds.c:736 commands/functioncmds.c:1243
#, c-format
msgid "COST must be positive"
-msgstr "COST doit �tre positif"
+msgstr "COST doit être positif"
#: commands/functioncmds.c:744 commands/functioncmds.c:1251
#, c-format
msgid "ROWS must be positive"
-msgstr "ROWS doit �tre positif"
+msgstr "ROWS doit être positif"
#: commands/functioncmds.c:785
#, c-format
msgid "unrecognized function attribute \"%s\" ignored"
-msgstr "l'attribut � %s � non reconnu de la fonction a �t� ignor�"
+msgstr "l'attribut « %s » non reconnu de la fonction a été ignoré"
#: commands/functioncmds.c:836
#, c-format
msgid "only one AS item needed for language \"%s\""
-msgstr "seul un �l�ment AS est n�cessaire pour le langage � %s �"
+msgstr "seul un élément AS est nécessaire pour le langage « %s »"
#: commands/functioncmds.c:929 commands/functioncmds.c:2119 commands/proclang.c:563
#, c-format
msgid "language \"%s\" does not exist"
-msgstr "le langage � %s � n'existe pas"
+msgstr "le langage « %s » n'existe pas"
#: commands/functioncmds.c:931 commands/functioncmds.c:2121
#, c-format
msgid "Use CREATE LANGUAGE to load the language into the database."
-msgstr "Utiliser CREATE LANGUAGE pour charger le langage dans la base de donn�es."
+msgstr "Utiliser CREATE LANGUAGE pour charger le langage dans la base de données."
#: commands/functioncmds.c:966 commands/functioncmds.c:1235
#, c-format
msgid "only superuser can define a leakproof function"
-msgstr "seul un superutilisateur peut d�finir une fonction leakproof"
+msgstr "seul un superutilisateur peut définir une fonction leakproof"
#: commands/functioncmds.c:1010
#, c-format
msgid "function result type must be %s because of OUT parameters"
-msgstr "le type de r�sultat de la fonction doit �tre %s � cause des param�tres OUT"
+msgstr "le type de résultat de la fonction doit être %s à cause des paramètres OUT"
#: commands/functioncmds.c:1023
#, c-format
msgid "function result type must be specified"
-msgstr "le type de r�sultat de la fonction doit �tre sp�cifi�"
+msgstr "le type de résultat de la fonction doit être spécifié"
#: commands/functioncmds.c:1077 commands/functioncmds.c:1255
#, c-format
@@ -6826,66 +6847,66 @@ msgstr "ROWS n'est pas applicable quand la fonction ne renvoie pas un ensemble"
#: commands/functioncmds.c:1412
#, c-format
msgid "source data type %s is a pseudo-type"
-msgstr "le type de donn�es source %s est un pseudo-type"
+msgstr "le type de données source %s est un pseudo-type"
#: commands/functioncmds.c:1418
#, c-format
msgid "target data type %s is a pseudo-type"
-msgstr "le type de donn�es cible %s est un pseudo-type"
+msgstr "le type de données cible %s est un pseudo-type"
#: commands/functioncmds.c:1442
#, c-format
msgid "cast will be ignored because the source data type is a domain"
-msgstr "la conversion sera ignor�e car le type de donn�es source est un domaine"
+msgstr "la conversion sera ignorée car le type de données source est un domaine"
#: commands/functioncmds.c:1447
#, c-format
msgid "cast will be ignored because the target data type is a domain"
-msgstr "la conversion sera ignor�e car le type de donn�es cible est un domaine"
+msgstr "la conversion sera ignorée car le type de données cible est un domaine"
#: commands/functioncmds.c:1474
#, c-format
msgid "cast function must take one to three arguments"
-msgstr "la fonction de conversion doit prendre de un � trois arguments"
+msgstr "la fonction de conversion doit prendre de un à trois arguments"
#: commands/functioncmds.c:1478
#, c-format
msgid "argument of cast function must match or be binary-coercible from source data type"
msgstr ""
-"l'argument de la fonction de conversion doit correspondre ou �tre binary-coercible\n"
-"� partir du type de la donn�e source"
+"l'argument de la fonction de conversion doit correspondre ou être binary-coercible\n"
+"à partir du type de la donnée source"
#: commands/functioncmds.c:1482
#, c-format
msgid "second argument of cast function must be type integer"
-msgstr "le second argument de la fonction de conversion doit �tre de type entier"
+msgstr "le second argument de la fonction de conversion doit être de type entier"
#: commands/functioncmds.c:1486
#, c-format
msgid "third argument of cast function must be type boolean"
-msgstr "le troisi�me argument de la fonction de conversion doit �tre de type bool�en"
+msgstr "le troisième argument de la fonction de conversion doit être de type booléen"
#: commands/functioncmds.c:1490
#, c-format
msgid "return data type of cast function must match or be binary-coercible to target data type"
msgstr ""
-"le type de donn�e en retour de la fonction de conversion doit correspondre\n"
-"ou �tre coercible binairement au type de donn�es cible"
+"le type de donnée en retour de la fonction de conversion doit correspondre\n"
+"ou être coercible binairement au type de données cible"
#: commands/functioncmds.c:1501
#, c-format
msgid "cast function must not be volatile"
-msgstr "la fonction de conversion ne doit pas �tre volatile"
+msgstr "la fonction de conversion ne doit pas être volatile"
#: commands/functioncmds.c:1506
#, c-format
msgid "cast function must not be an aggregate function"
-msgstr "la fonction de conversion ne doit pas �tre une fonction d'agr�gat"
+msgstr "la fonction de conversion ne doit pas être une fonction d'agrégat"
#: commands/functioncmds.c:1510
#, c-format
msgid "cast function must not be a window function"
-msgstr "la fonction de conversion ne doit pas �tre une fonction window"
+msgstr "la fonction de conversion ne doit pas être une fonction window"
#: commands/functioncmds.c:1514
#, c-format
@@ -6895,42 +6916,42 @@ msgstr "la fonction de conversion ne doit pas renvoyer un ensemble"
#: commands/functioncmds.c:1540
#, c-format
msgid "must be superuser to create a cast WITHOUT FUNCTION"
-msgstr "doit �tre super-utilisateur pour cr�er une fonction de conversion SANS FONCTION"
+msgstr "doit être super-utilisateur pour créer une fonction de conversion SANS FONCTION"
#: commands/functioncmds.c:1555
#, c-format
msgid "source and target data types are not physically compatible"
-msgstr "les types de donn�es source et cible ne sont pas physiquement compatibles"
+msgstr "les types de données source et cible ne sont pas physiquement compatibles"
#: commands/functioncmds.c:1570
#, c-format
msgid "composite data types are not binary-compatible"
-msgstr "les types de donn�es composites ne sont pas compatibles binairement"
+msgstr "les types de données composites ne sont pas compatibles binairement"
#: commands/functioncmds.c:1576
#, c-format
msgid "enum data types are not binary-compatible"
-msgstr "les types de donn�es enum ne sont pas compatibles binairement"
+msgstr "les types de données enum ne sont pas compatibles binairement"
#: commands/functioncmds.c:1582
#, c-format
msgid "array data types are not binary-compatible"
-msgstr "les types de donn�es tableau ne sont pas compatibles binairement"
+msgstr "les types de données tableau ne sont pas compatibles binairement"
#: commands/functioncmds.c:1599
#, c-format
msgid "domain data types must not be marked binary-compatible"
-msgstr "les types de donn�es domaines ne sont pas compatibles binairement"
+msgstr "les types de données domaines ne sont pas compatibles binairement"
#: commands/functioncmds.c:1609
#, c-format
msgid "source data type and target data type are the same"
-msgstr "les types de donn�es source et cible sont identiques"
+msgstr "les types de données source et cible sont identiques"
#: commands/functioncmds.c:1642
#, c-format
msgid "cast from type %s to type %s already exists"
-msgstr "la conversion du type %s vers le type %s existe d�j�"
+msgstr "la conversion du type %s vers le type %s existe déjà"
#: commands/functioncmds.c:1717
#, c-format
@@ -6940,17 +6961,17 @@ msgstr "la conversion du type %s vers le type %s n'existe pas"
#: commands/functioncmds.c:1756
#, c-format
msgid "transform function must not be volatile"
-msgstr "la fonction de transformation ne doit pas �tre volatile"
+msgstr "la fonction de transformation ne doit pas être volatile"
#: commands/functioncmds.c:1760
#, c-format
msgid "transform function must not be an aggregate function"
-msgstr "la fonction de transformation ne doit pas �tre une fonction d'agr�gat"
+msgstr "la fonction de transformation ne doit pas être une fonction d'agrégat"
#: commands/functioncmds.c:1764
#, c-format
msgid "transform function must not be a window function"
-msgstr "la fonction de transformation ne doit pas �tre une fonction window"
+msgstr "la fonction de transformation ne doit pas être une fonction window"
#: commands/functioncmds.c:1768
#, c-format
@@ -6965,57 +6986,57 @@ msgstr "la fonction de transformation doit prendre de un argument"
#: commands/functioncmds.c:1776
#, c-format
msgid "first argument of transform function must be type \"internal\""
-msgstr "le premier argument de la fonction de transformation doit �tre de type � internal �"
+msgstr "le premier argument de la fonction de transformation doit être de type « internal »"
#: commands/functioncmds.c:1813
#, c-format
msgid "data type %s is a pseudo-type"
-msgstr "le type de donn�es %s est un pseudo-type"
+msgstr "le type de données %s est un pseudo-type"
#: commands/functioncmds.c:1819
#, c-format
msgid "data type %s is a domain"
-msgstr "le type de donn�es %s est un domaine"
+msgstr "le type de données %s est un domaine"
#: commands/functioncmds.c:1859
#, c-format
msgid "return data type of FROM SQL function must be \"internal\""
-msgstr "le type de donn�e en retour de la fonction FROM SQL doit �tre � internal �"
+msgstr "le type de donnée en retour de la fonction FROM SQL doit être « internal »"
#: commands/functioncmds.c:1884
#, c-format
msgid "return data type of TO SQL function must be the transform data type"
-msgstr "le type de donn�e en retour de la fonction TO SQL doit �tre du type de donn�es de la transformation"
+msgstr "le type de donnée en retour de la fonction TO SQL doit être du type de données de la transformation"
#: commands/functioncmds.c:1911
#, c-format
msgid "transform for type %s language \"%s\" already exists"
-msgstr "la transformation pour le type %s et le langage � %s � existe d�j�"
+msgstr "la transformation pour le type %s et le langage « %s » existe déjà"
#: commands/functioncmds.c:2002
#, c-format
msgid "transform for type %s language \"%s\" does not exist"
-msgstr "la transformation pour le type %s et le langage � %s � n'existe pas"
+msgstr "la transformation pour le type %s et le langage « %s » n'existe pas"
#: commands/functioncmds.c:2053
#, c-format
msgid "function %s already exists in schema \"%s\""
-msgstr "la fonction %s existe d�j� dans le sch�ma � %s �"
+msgstr "la fonction %s existe déjà dans le schéma « %s »"
#: commands/functioncmds.c:2106
#, c-format
msgid "no inline code specified"
-msgstr "aucun code en ligne sp�cifi�"
+msgstr "aucun code en ligne spécifié"
#: commands/functioncmds.c:2151
#, c-format
msgid "language \"%s\" does not support inline code execution"
-msgstr "le langage � %s � ne supporte pas l'ex�cution de code en ligne"
+msgstr "le langage « %s » ne supporte pas l'exécution de code en ligne"
#: commands/indexcmds.c:349
#, c-format
msgid "must specify at least one column"
-msgstr "doit sp�cifier au moins une colonne"
+msgstr "doit spécifier au moins une colonne"
#: commands/indexcmds.c:353
#, c-format
@@ -7025,187 +7046,184 @@ msgstr "ne peut pas utiliser plus de %d colonnes dans un index"
#: commands/indexcmds.c:384
#, c-format
msgid "cannot create index on foreign table \"%s\""
-msgstr "ne peut pas cr�er un index sur la table distante � %s �"
+msgstr "ne peut pas créer un index sur la table distante « %s »"
#: commands/indexcmds.c:399
#, c-format
msgid "cannot create indexes on temporary tables of other sessions"
-msgstr "ne peut pas cr�er les index sur les tables temporaires des autres sessions"
+msgstr "ne peut pas créer les index sur les tables temporaires des autres sessions"
-#: commands/indexcmds.c:454 commands/tablecmds.c:545 commands/tablecmds.c:9597
+#: commands/indexcmds.c:454 commands/tablecmds.c:546 commands/tablecmds.c:9694
#, c-format
msgid "only shared relations can be placed in pg_global tablespace"
-msgstr "seules les relations partag�es peuvent �tre plac�es dans le tablespace pg_global"
+msgstr "seules les relations partagées peuvent être placées dans le tablespace pg_global"
#: commands/indexcmds.c:487
#, c-format
msgid "substituting access method \"gist\" for obsolete method \"rtree\""
-msgstr "substitution de la m�thode d'acc�s obsol�te � rtree � par � gist � "
+msgstr "substitution de la méthode d'accès obsolète « rtree » par « gist » "
#: commands/indexcmds.c:505
#, c-format
msgid "hash indexes are not WAL-logged and their use is discouraged"
-msgstr "les index hash ne sont pas journalis�s, leur utilisation est donc d�conseill�e"
+msgstr "les index hash ne sont pas journalisés, leur utilisation est donc déconseillée"
#: commands/indexcmds.c:510
#, c-format
msgid "access method \"%s\" does not support unique indexes"
-msgstr "la m�thode d'acc�s � %s � ne supporte pas les index uniques"
+msgstr "la méthode d'accès « %s » ne supporte pas les index uniques"
#: commands/indexcmds.c:515
#, c-format
msgid "access method \"%s\" does not support multicolumn indexes"
-msgstr "la m�thode d'acc�s � %s � ne supporte pas les index multi-colonnes"
+msgstr "la méthode d'accès « %s » ne supporte pas les index multi-colonnes"
#: commands/indexcmds.c:520
#, c-format
msgid "access method \"%s\" does not support exclusion constraints"
-msgstr "la m�thode d'acc�s � %s � ne supporte pas les contraintes d'exclusion"
+msgstr "la méthode d'accès « %s » ne supporte pas les contraintes d'exclusion"
#: commands/indexcmds.c:590 commands/indexcmds.c:610
-#, fuzzy, c-format
-#| msgid "concurrent index creation on system catalog tables is not supported"
+#, c-format
msgid "index creation on system columns is not supported"
-msgstr ""
-"la cr�ation en parall�le d'un index sur les tables du catalogue syst�me\n"
-"n'est pas support�e"
+msgstr "la création d'un index sur les tables du catalogue système n'est pas supportée"
#: commands/indexcmds.c:635
#, c-format
msgid "%s %s will create implicit index \"%s\" for table \"%s\""
-msgstr "%s %s cr�era un index implicite � %s � pour la table � %s �"
+msgstr "%s %s créera un index implicite « %s » pour la table « %s »"
#: commands/indexcmds.c:982
#, c-format
msgid "functions in index predicate must be marked IMMUTABLE"
-msgstr "les fonctions dans un pr�dicat d'index doivent �tre marqu�es comme IMMUTABLE"
+msgstr "les fonctions dans un prédicat d'index doivent être marquées comme IMMUTABLE"
-#: commands/indexcmds.c:1048 parser/parse_utilcmd.c:1894
+#: commands/indexcmds.c:1048 parser/parse_utilcmd.c:1881
#, c-format
msgid "column \"%s\" named in key does not exist"
-msgstr "la colonne � %s � nomm�e dans la cl� n'existe pas"
+msgstr "la colonne « %s » nommée dans la clé n'existe pas"
#: commands/indexcmds.c:1108
#, c-format
msgid "functions in index expression must be marked IMMUTABLE"
msgstr ""
-"les fonctions dans l'expression de l'index doivent �tre marqu�es comme\n"
+"les fonctions dans l'expression de l'index doivent être marquées comme\n"
"IMMUTABLE"
#: commands/indexcmds.c:1131
#, c-format
msgid "could not determine which collation to use for index expression"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour l'expression d'index"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour l'expression d'index"
-#: commands/indexcmds.c:1139 commands/typecmds.c:827 parser/parse_expr.c:2583 parser/parse_type.c:550 parser/parse_utilcmd.c:2820 utils/adt/misc.c:666
+#: commands/indexcmds.c:1139 commands/typecmds.c:827 parser/parse_expr.c:2608 parser/parse_type.c:550 parser/parse_utilcmd.c:2807 utils/adt/misc.c:666
#, c-format
msgid "collations are not supported by type %s"
-msgstr "les collationnements ne sont pas support�s par le type %s"
+msgstr "les collationnements ne sont pas supportés par le type %s"
#: commands/indexcmds.c:1177
#, c-format
msgid "operator %s is not commutative"
-msgstr "l'op�rateur %s n'est pas commutatif"
+msgstr "l'opérateur %s n'est pas commutatif"
#: commands/indexcmds.c:1179
#, c-format
msgid "Only commutative operators can be used in exclusion constraints."
-msgstr "Seuls les op�rateurs commutatifs peuvent �tre utilis�s dans les contraintes d'exclusion."
+msgstr "Seuls les opérateurs commutatifs peuvent être utilisés dans les contraintes d'exclusion."
#: commands/indexcmds.c:1205
#, c-format
msgid "operator %s is not a member of operator family \"%s\""
-msgstr "l'op�rateur %s n'est pas un membre de la famille d'op�rateur � %s �"
+msgstr "l'opérateur %s n'est pas un membre de la famille d'opérateur « %s »"
#: commands/indexcmds.c:1208
#, c-format
msgid "The exclusion operator must be related to the index operator class for the constraint."
msgstr ""
-"L'op�rateur d'exclusion doit �tre en relation avec la classe d'op�rateur de\n"
+"L'opérateur d'exclusion doit être en relation avec la classe d'opérateur de\n"
"l'index pour la contrainte."
#: commands/indexcmds.c:1243
#, c-format
msgid "access method \"%s\" does not support ASC/DESC options"
-msgstr "la m�thode d'acc�s � %s � ne supporte pas les options ASC/DESC"
+msgstr "la méthode d'accès « %s » ne supporte pas les options ASC/DESC"
#: commands/indexcmds.c:1248
#, c-format
msgid "access method \"%s\" does not support NULLS FIRST/LAST options"
-msgstr "la m�thode d'acc�s � %s � ne supporte pas les options NULLS FIRST/LAST"
+msgstr "la méthode d'accès « %s » ne supporte pas les options NULLS FIRST/LAST"
#: commands/indexcmds.c:1304 commands/typecmds.c:1935
#, c-format
msgid "data type %s has no default operator class for access method \"%s\""
msgstr ""
-"le type de donn�es %s n'a pas de classe d'op�rateurs par d�faut pour la\n"
-"m�thode d'acc�s � %s �"
+"le type de données %s n'a pas de classe d'opérateurs par défaut pour la\n"
+"méthode d'accès « %s »"
#: commands/indexcmds.c:1306
#, c-format
msgid "You must specify an operator class for the index or define a default operator class for the data type."
msgstr ""
-"Vous devez sp�cifier une classe d'op�rateur pour l'index ou d�finir une\n"
-"classe d'op�rateur par d�faut pour le type de donn�es."
+"Vous devez spécifier une classe d'opérateur pour l'index ou définir une\n"
+"classe d'opérateur par défaut pour le type de données."
#: commands/indexcmds.c:1335 commands/indexcmds.c:1343 commands/opclasscmds.c:205
#, c-format
msgid "operator class \"%s\" does not exist for access method \"%s\""
-msgstr "la classe d'op�rateur � %s � n'existe pas pour la m�thode d'acc�s � %s �"
+msgstr "la classe d'opérateur « %s » n'existe pas pour la méthode d'accès « %s »"
#: commands/indexcmds.c:1356 commands/typecmds.c:1923
#, c-format
msgid "operator class \"%s\" does not accept data type %s"
-msgstr "la classe d'op�rateur � %s � n'accepte pas le type de donn�es %s"
+msgstr "la classe d'opérateur « %s » n'accepte pas le type de données %s"
#: commands/indexcmds.c:1446
#, c-format
msgid "there are multiple default operator classes for data type %s"
msgstr ""
-"il existe de nombreuses classes d'op�rateur par d�faut pour le type de\n"
-"donn�es %s"
+"il existe de nombreuses classes d'opérateur par défaut pour le type de\n"
+"données %s"
#: commands/indexcmds.c:1837
#, c-format
msgid "table \"%s\" has no indexes"
-msgstr "la table � %s � n'a pas d'index"
+msgstr "la table « %s » n'a pas d'index"
#: commands/indexcmds.c:1892
#, c-format
msgid "can only reindex the currently open database"
-msgstr "peut seulement r�indexer la base de donn�es en cours"
+msgstr "peut seulement réindexer la base de données en cours"
-#: commands/indexcmds.c:1994
+#: commands/indexcmds.c:1992
#, c-format
msgid "table \"%s.%s\" was reindexed"
-msgstr "la table � %s.%s � a �t� r�index�e"
+msgstr "la table « %s.%s » a été réindexée"
#: commands/matview.c:181
#, c-format
msgid "CONCURRENTLY cannot be used when the materialized view is not populated"
-msgstr "CONCURRENTLY ne peut pas �tre utilis� quand la vue mat�rialis�e n'est pas peupl�e"
+msgstr "CONCURRENTLY ne peut pas être utilisé quand la vue matérialisée n'est pas peuplée"
#: commands/matview.c:187
#, c-format
msgid "CONCURRENTLY and WITH NO DATA options cannot be used together"
-msgstr "Les options CONCURRENTLY et WITH NO DATA ne peuvent pas �tre utilis�es ensemble"
+msgstr "Les options CONCURRENTLY et WITH NO DATA ne peuvent pas être utilisées ensemble"
-#: commands/matview.c:258
+#: commands/matview.c:257
#, c-format
msgid "cannot refresh materialized view \"%s\" concurrently"
-msgstr "ne peut pas rafraichir en parall�le la vue mat�rialis�e � %s �"
+msgstr "ne peut pas rafraichir en parallèle la vue matérialisée « %s »"
-#: commands/matview.c:261
+#: commands/matview.c:260
#, c-format
msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view."
-msgstr "Cr�e un index unique sans clause WHERE sur une ou plusieurs colonnes de la vue mat�rialis�e."
+msgstr "Crée un index unique sans clause WHERE sur une ou plusieurs colonnes de la vue matérialisée."
-#: commands/matview.c:656
+#: commands/matview.c:657
#, c-format
msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns"
-msgstr "les nouvelles donn�es pour la vue mat�rialis�e � %s � contiennent des lignes dupliqu�es sans colonnes NULL"
+msgstr "les nouvelles données pour la vue matérialisée « %s » contiennent des lignes dupliquées sans colonnes NULL"
-#: commands/matview.c:658
+#: commands/matview.c:659
#, c-format
msgid "Row: %s"
msgstr "Ligne : %s"
@@ -7213,452 +7231,449 @@ msgstr "Ligne : %s"
#: commands/opclasscmds.c:126
#, c-format
msgid "operator family \"%s\" does not exist for access method \"%s\""
-msgstr "la famille d'op�rateur � %s � n'existe pas pour la m�thode d'acc�s � %s �"
+msgstr "la famille d'opérateur « %s » n'existe pas pour la méthode d'accès « %s »"
#: commands/opclasscmds.c:264
#, c-format
msgid "operator family \"%s\" for access method \"%s\" already exists"
-msgstr "la famille d'op�rateur � %s � existe d�j� pour la m�thode d'acc�s � %s �"
+msgstr "la famille d'opérateur « %s » existe déjà pour la méthode d'accès « %s »"
#: commands/opclasscmds.c:404
#, c-format
msgid "must be superuser to create an operator class"
-msgstr "doit �tre super-utilisateur pour cr�er une classe d'op�rateur"
+msgstr "doit être super-utilisateur pour créer une classe d'opérateur"
#: commands/opclasscmds.c:478 commands/opclasscmds.c:863 commands/opclasscmds.c:996
#, c-format
msgid "invalid operator number %d, must be between 1 and %d"
-msgstr "num�ro d'op�rateur %d invalide, doit �tre compris entre 1 et %d"
+msgstr "numéro d'opérateur %d invalide, doit être compris entre 1 et %d"
#: commands/opclasscmds.c:529 commands/opclasscmds.c:914 commands/opclasscmds.c:1011
#, c-format
msgid "invalid procedure number %d, must be between 1 and %d"
-msgstr "num�ro de proc�dure %d invalide, doit �tre compris entre 1 et %d"
+msgstr "numéro de procédure %d invalide, doit être compris entre 1 et %d"
#: commands/opclasscmds.c:559
#, c-format
msgid "storage type specified more than once"
-msgstr "type de stockage sp�cifi� plus d'une fois"
+msgstr "type de stockage spécifié plus d'une fois"
#: commands/opclasscmds.c:586
#, c-format
msgid "storage type cannot be different from data type for access method \"%s\""
msgstr ""
-"le type de stockage ne peut pas �tre diff�rent du type de donn�es pour la\n"
-"m�thode d'acc�s � %s �"
+"le type de stockage ne peut pas être différent du type de données pour la\n"
+"méthode d'accès « %s »"
#: commands/opclasscmds.c:602
#, c-format
msgid "operator class \"%s\" for access method \"%s\" already exists"
-msgstr "la classe d'op�rateur � %s � existe d�j� pour la m�thode d'acc�s � %s �"
+msgstr "la classe d'opérateur « %s » existe déjà pour la méthode d'accès « %s »"
#: commands/opclasscmds.c:630
#, c-format
msgid "could not make operator class \"%s\" be default for type %s"
-msgstr "n'a pas pu rendre la classe d'op�rateur � %s � par d�faut pour le type %s"
+msgstr "n'a pas pu rendre la classe d'opérateur « %s » par défaut pour le type %s"
#: commands/opclasscmds.c:633
#, c-format
msgid "Operator class \"%s\" already is the default."
-msgstr "La classe d'op�rateur � %s � est d�j� la classe par d�faut."
+msgstr "La classe d'opérateur « %s » est déjà la classe par défaut."
#: commands/opclasscmds.c:760
#, c-format
msgid "must be superuser to create an operator family"
-msgstr "doit �tre super-utilisateur pour cr�er une famille d'op�rateur"
+msgstr "doit être super-utilisateur pour créer une famille d'opérateur"
#: commands/opclasscmds.c:816
#, c-format
msgid "must be superuser to alter an operator family"
-msgstr "doit �tre super-utilisateur pour modifier une famille d'op�rateur"
+msgstr "doit être super-utilisateur pour modifier une famille d'opérateur"
#: commands/opclasscmds.c:879
#, c-format
msgid "operator argument types must be specified in ALTER OPERATOR FAMILY"
msgstr ""
-"les types d'argument de l'op�rateur doivent �tre indiqu�s dans ALTER\n"
+"les types d'argument de l'opérateur doivent être indiqués dans ALTER\n"
"OPERATOR FAMILY"
#: commands/opclasscmds.c:943
#, c-format
msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY"
-msgstr "STORAGE ne peut pas �tre sp�cifi� dans ALTER OPERATOR FAMILY"
+msgstr "STORAGE ne peut pas être spécifié dans ALTER OPERATOR FAMILY"
#: commands/opclasscmds.c:1066
#, c-format
msgid "one or two argument types must be specified"
-msgstr "un ou deux types d'argument doit �tre sp�cifi�"
+msgstr "un ou deux types d'argument doit être spécifié"
#: commands/opclasscmds.c:1092
#, c-format
msgid "index operators must be binary"
-msgstr "les op�rateurs d'index doivent �tre binaires"
+msgstr "les opérateurs d'index doivent être binaires"
#: commands/opclasscmds.c:1111
#, c-format
msgid "access method \"%s\" does not support ordering operators"
-msgstr "la m�thode d'acc�s � %s � ne supporte pas les op�rateurs de tri"
+msgstr "la méthode d'accès « %s » ne supporte pas les opérateurs de tri"
#: commands/opclasscmds.c:1122
#, c-format
msgid "index search operators must return boolean"
-msgstr "les op�rateurs de recherche d'index doivent renvoyer un bool�en"
+msgstr "les opérateurs de recherche d'index doivent renvoyer un booléen"
#: commands/opclasscmds.c:1164
#, c-format
msgid "btree comparison procedures must have two arguments"
-msgstr "les proc�dures de comparaison btree doivent avoir deux arguments"
+msgstr "les procédures de comparaison btree doivent avoir deux arguments"
#: commands/opclasscmds.c:1168
#, c-format
msgid "btree comparison procedures must return integer"
-msgstr "les proc�dures de comparaison btree doivent renvoyer un entier"
+msgstr "les procédures de comparaison btree doivent renvoyer un entier"
#: commands/opclasscmds.c:1185
#, c-format
msgid "btree sort support procedures must accept type \"internal\""
-msgstr "les proc�dures de support de tri btree doivent accepter le type � internal �"
+msgstr "les procédures de support de tri btree doivent accepter le type « internal »"
#: commands/opclasscmds.c:1189
#, c-format
msgid "btree sort support procedures must return void"
-msgstr "les proc�dures de support de tri btree doivent renvoyer void"
+msgstr "les procédures de support de tri btree doivent renvoyer void"
#: commands/opclasscmds.c:1201
#, c-format
msgid "hash procedures must have one argument"
-msgstr "les proc�dures de hachage doivent avoir un argument"
+msgstr "les procédures de hachage doivent avoir un argument"
#: commands/opclasscmds.c:1205
#, c-format
msgid "hash procedures must return integer"
-msgstr "les proc�dures de hachage doivent renvoyer un entier"
+msgstr "les procédures de hachage doivent renvoyer un entier"
#: commands/opclasscmds.c:1229
#, c-format
msgid "associated data types must be specified for index support procedure"
msgstr ""
-"les types de donn�es associ�s doivent �tre indiqu�s pour la proc�dure de\n"
+"les types de données associés doivent être indiqués pour la procédure de\n"
"support de l'index"
#: commands/opclasscmds.c:1254
#, c-format
msgid "procedure number %d for (%s,%s) appears more than once"
-msgstr "le num�ro de proc�dure %d pour (%s, %s) appara�t plus d'une fois"
+msgstr "le numéro de procédure %d pour (%s, %s) apparaît plus d'une fois"
#: commands/opclasscmds.c:1261
#, c-format
msgid "operator number %d for (%s,%s) appears more than once"
-msgstr "le num�ro d'op�rateur %d pour (%s, %s) appara�t plus d'une fois"
+msgstr "le numéro d'opérateur %d pour (%s, %s) apparaît plus d'une fois"
#: commands/opclasscmds.c:1310
#, c-format
msgid "operator %d(%s,%s) already exists in operator family \"%s\""
-msgstr "l'op�rateur %d(%s, %s) existe d�j� dans la famille d'op�rateur � %s �"
+msgstr "l'opérateur %d(%s, %s) existe déjà dans la famille d'opérateur « %s »"
#: commands/opclasscmds.c:1426
#, c-format
msgid "function %d(%s,%s) already exists in operator family \"%s\""
-msgstr "la fonction %d(%s, %s) existe d�j� dans la famille d'op�rateur � %s �"
+msgstr "la fonction %d(%s, %s) existe déjà dans la famille d'opérateur « %s »"
#: commands/opclasscmds.c:1516
#, c-format
msgid "operator %d(%s,%s) does not exist in operator family \"%s\""
-msgstr "l'op�rateur %d(%s, %s) n'existe pas dans la famille d'op�rateur � %s �"
+msgstr "l'opérateur %d(%s, %s) n'existe pas dans la famille d'opérateur « %s »"
#: commands/opclasscmds.c:1556
#, c-format
msgid "function %d(%s,%s) does not exist in operator family \"%s\""
-msgstr "la fonction %d(%s, %s) n'existe pas dans la famille d'op�rateur � %s �"
+msgstr "la fonction %d(%s, %s) n'existe pas dans la famille d'opérateur « %s »"
#: commands/opclasscmds.c:1686
#, c-format
msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\""
msgstr ""
-"la classe d'op�rateur � %s � de la m�thode d'acc�s � %s � existe d�j� dans\n"
-"le sch�ma � %s �"
+"la classe d'opérateur « %s » de la méthode d'accès « %s » existe déjà dans\n"
+"le schéma « %s »"
#: commands/opclasscmds.c:1709
#, c-format
msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\""
msgstr ""
-"la famille d'op�rateur � %s � de la m�thode d'acc�s � %s � existe d�j� dans\n"
-"le sch�ma � %s �"
+"la famille d'opérateur « %s » de la méthode d'accès « %s » existe déjà dans\n"
+"le schéma « %s »"
#: commands/operatorcmds.c:114 commands/operatorcmds.c:122
#, c-format
msgid "SETOF type not allowed for operator argument"
-msgstr "type SETOF non autoris� pour l'argument de l'op�rateur"
+msgstr "type SETOF non autorisé pour l'argument de l'opérateur"
#: commands/operatorcmds.c:152 commands/operatorcmds.c:457
#, c-format
msgid "operator attribute \"%s\" not recognized"
-msgstr "l'attribut � %s � de l'op�rateur n'est pas reconnu"
+msgstr "l'attribut « %s » de l'opérateur n'est pas reconnu"
#: commands/operatorcmds.c:163
#, c-format
msgid "operator procedure must be specified"
-msgstr "la proc�dure de l'op�rateur doit �tre sp�cifi�e"
+msgstr "la procédure de l'opérateur doit être spécifiée"
#: commands/operatorcmds.c:174
#, c-format
msgid "at least one of leftarg or rightarg must be specified"
-msgstr "au moins un des arguments (le gauche ou le droit) doit �tre sp�cifi�"
+msgstr "au moins un des arguments (le gauche ou le droit) doit être spécifié"
#: commands/operatorcmds.c:278
-#, fuzzy, c-format
-#| msgid "restriction estimator function %s must return type \"float8\""
+#, c-format
msgid "restriction estimator function %s must return type %s"
msgstr ""
"la fonction d'estimation de la restriction, de nom %s, doit renvoyer le type\n"
-"� float8 �"
+"%s"
#: commands/operatorcmds.c:324
-#, fuzzy, c-format
-#| msgid "join estimator function %s must return type \"float8\""
+#, c-format
msgid "join estimator function %s must return type %s"
msgstr ""
"la fonction d'estimation de la jointure, de nom %s, doit renvoyer le type\n"
-"� float8 �"
+"%s"
#: commands/operatorcmds.c:451
-#, fuzzy, c-format
-#| msgid "operator attribute \"%s\" not recognized"
-msgid "operator attribute \"%s\" can not be changed"
-msgstr "l'attribut � %s � de l'op�rateur n'est pas reconnu"
+#, c-format
+msgid "operator attribute \"%s\" cannot be changed"
+msgstr "l'attribut « %s » de l'opérateur ne peut pas être changé"
-#: commands/policy.c:87 commands/policy.c:390 commands/policy.c:479 commands/tablecmds.c:970 commands/tablecmds.c:1312 commands/tablecmds.c:2184 commands/tablecmds.c:4328 commands/tablecmds.c:6279 commands/tablecmds.c:11933 commands/tablecmds.c:11968 commands/trigger.c:241 commands/trigger.c:1125 commands/trigger.c:1233 rewrite/rewriteDefine.c:273 rewrite/rewriteDefine.c:917
+#: commands/policy.c:87 commands/policy.c:388 commands/policy.c:477 commands/tablecmds.c:971 commands/tablecmds.c:1313 commands/tablecmds.c:2185 commands/tablecmds.c:4329 commands/tablecmds.c:6280 commands/tablecmds.c:12080 commands/tablecmds.c:12115 commands/trigger.c:241 commands/trigger.c:1125 commands/trigger.c:1233 rewrite/rewriteDefine.c:273 rewrite/rewriteDefine.c:917
#, c-format
msgid "permission denied: \"%s\" is a system catalog"
-msgstr "droit refus� : � %s � est un catalogue syst�me"
+msgstr "droit refusé : « %s » est un catalogue système"
#: commands/policy.c:170
#, c-format
msgid "ignoring specified roles other than PUBLIC"
-msgstr "ingore les r�les sp�cifi�s autre que PUBLIC"
+msgstr "ingore les rôles spécifiés autre que PUBLIC"
#: commands/policy.c:171
#, c-format
msgid "All roles are members of the PUBLIC role."
-msgstr "Tous les r�les sont membres du r�le PUBLIC."
+msgstr "Tous les rôles sont membres du rôle PUBLIC."
-#: commands/policy.c:503
+#: commands/policy.c:501
#, c-format
msgid "role \"%s\" could not be removed from policy \"%s\" on \"%s\""
-msgstr "le r�le � %s � n'a pas pu �tre supprim� de la politique � %s � sur � %s �"
+msgstr "le rôle « %s » n'a pas pu être supprimé de la politique « %s » sur « %s »"
-#: commands/policy.c:712
+#: commands/policy.c:710
#, c-format
msgid "WITH CHECK cannot be applied to SELECT or DELETE"
-msgstr "WITH CHECK ne peut pas �tre appliqu� � SELECT et DELETE"
+msgstr "WITH CHECK ne peut pas être appliqué à SELECT et DELETE"
-#: commands/policy.c:721 commands/policy.c:1021
+#: commands/policy.c:719 commands/policy.c:1019
#, c-format
msgid "only WITH CHECK expression allowed for INSERT"
-msgstr "seule une expression WITH CHECK est autoris�e pour INSERT"
+msgstr "seule une expression WITH CHECK est autorisée pour INSERT"
-#: commands/policy.c:794 commands/policy.c:1244
+#: commands/policy.c:792 commands/policy.c:1242
#, c-format
msgid "policy \"%s\" for table \"%s\" already exists"
-msgstr "la politique � %s � pour la table � %s � existe d�j�"
+msgstr "la politique « %s » pour la table « %s » existe déjà"
-#: commands/policy.c:993 commands/policy.c:1272 commands/policy.c:1347
+#: commands/policy.c:991 commands/policy.c:1270 commands/policy.c:1345
#, c-format
msgid "policy \"%s\" for table \"%s\" does not exist"
-msgstr "la politique � %s � pour la table � %s � n'existe pas"
+msgstr "la politique « %s » pour la table « %s » n'existe pas"
-#: commands/policy.c:1011
+#: commands/policy.c:1009
#, c-format
msgid "only USING expression allowed for SELECT, DELETE"
-msgstr "seule une expression USING est autoris�e pour SELECT, DELETE"
+msgstr "seule une expression USING est autorisée pour SELECT, DELETE"
#: commands/portalcmds.c:61 commands/portalcmds.c:160 commands/portalcmds.c:212
#, c-format
msgid "invalid cursor name: must not be empty"
-msgstr "nom de curseur invalide : il ne doit pas �tre vide"
+msgstr "nom de curseur invalide : il ne doit pas être vide"
-#: commands/portalcmds.c:168 commands/portalcmds.c:222 executor/execCurrent.c:67 utils/adt/xml.c:2391 utils/adt/xml.c:2558
+#: commands/portalcmds.c:168 commands/portalcmds.c:222 executor/execCurrent.c:67 utils/adt/xml.c:2389 utils/adt/xml.c:2556
#, c-format
msgid "cursor \"%s\" does not exist"
-msgstr "le curseur � %s � n'existe pas"
+msgstr "le curseur « %s » n'existe pas"
#: commands/prepare.c:71
#, c-format
msgid "invalid statement name: must not be empty"
-msgstr "nom de l'instruction invalide : ne doit pas �tre vide"
+msgstr "nom de l'instruction invalide : ne doit pas être vide"
-#: commands/prepare.c:129 parser/parse_param.c:304 tcop/postgres.c:1345
+#: commands/prepare.c:129 parser/parse_param.c:304 tcop/postgres.c:1343
#, c-format
msgid "could not determine data type of parameter $%d"
-msgstr "n'a pas pu d�terminer le type de donn�es du param�tre $%d"
+msgstr "n'a pas pu déterminer le type de données du paramètre $%d"
#: commands/prepare.c:147
#, c-format
msgid "utility statements cannot be prepared"
-msgstr "les instructions utilitaires ne peuvent pas �tre pr�par�es"
+msgstr "les instructions utilitaires ne peuvent pas être préparées"
#: commands/prepare.c:257 commands/prepare.c:264
#, c-format
msgid "prepared statement is not a SELECT"
-msgstr "l'instruction pr�par�e n'est pas un SELECT"
+msgstr "l'instruction préparée n'est pas un SELECT"
#: commands/prepare.c:332
#, c-format
msgid "wrong number of parameters for prepared statement \"%s\""
-msgstr "mauvais nombre de param�tres pour l'instruction pr�par�e � %s �"
+msgstr "mauvais nombre de paramètres pour l'instruction préparée « %s »"
#: commands/prepare.c:334
#, c-format
msgid "Expected %d parameters but got %d."
-msgstr "%d param�tres attendus mais %d re�us."
+msgstr "%d paramètres attendus mais %d reçus."
#: commands/prepare.c:370
#, c-format
msgid "parameter $%d of type %s cannot be coerced to the expected type %s"
msgstr ""
-"le param�tre $%d de type %s ne peut �tre utilis� dans la coercion � cause du\n"
+"le paramètre $%d de type %s ne peut être utilisé dans la coercion à cause du\n"
"type %s attendu"
#: commands/prepare.c:465
#, c-format
msgid "prepared statement \"%s\" already exists"
-msgstr "l'instruction pr�par�e � %s � existe d�j�"
+msgstr "l'instruction préparée « %s » existe déjà"
#: commands/prepare.c:504
#, c-format
msgid "prepared statement \"%s\" does not exist"
-msgstr "l'instruction pr�par�e � %s � n'existe pas"
+msgstr "l'instruction préparée « %s » n'existe pas"
#: commands/proclang.c:87
#, c-format
msgid "using pg_pltemplate information instead of CREATE LANGUAGE parameters"
msgstr ""
-"utilisation des informations de pg_pltemplate au lieu des param�tres de\n"
+"utilisation des informations de pg_pltemplate au lieu des paramètres de\n"
"CREATE LANGUAGE"
#: commands/proclang.c:97
#, c-format
msgid "must be superuser to create procedural language \"%s\""
-msgstr "doit �tre super-utilisateur pour cr�er le langage de proc�dures � %s �"
+msgstr "doit être super-utilisateur pour créer le langage de procédures « %s »"
#: commands/proclang.c:252
#, c-format
msgid "unsupported language \"%s\""
-msgstr "langage non support� � %s �"
+msgstr "langage non supporté « %s »"
#: commands/proclang.c:254
#, c-format
msgid "The supported languages are listed in the pg_pltemplate system catalog."
-msgstr "Les langages support�s sont list�s dans le catalogue syst�me pg_pltemplate."
+msgstr "Les langages supportés sont listés dans le catalogue système pg_pltemplate."
#: commands/proclang.c:262
#, c-format
msgid "must be superuser to create custom procedural language"
-msgstr "doit �tre super-utilisateur pour cr�er un langage de proc�dures personnalis�"
+msgstr "doit être super-utilisateur pour créer un langage de procédures personnalisé"
#: commands/proclang.c:281
#, c-format
msgid "changing return type of function %s from \"opaque\" to \"language_handler\""
msgstr ""
-"changement du type du code retour de la fonction %s d'� opaque � �\n"
-"� language_handler �"
+"changement du type du code retour de la fonction %s d'« opaque » à\n"
+"« language_handler »"
#: commands/schemacmds.c:99 commands/schemacmds.c:262
#, c-format
msgid "unacceptable schema name \"%s\""
-msgstr "nom de sch�ma � %s � inacceptable"
+msgstr "nom de schéma « %s » inacceptable"
#: commands/schemacmds.c:100 commands/schemacmds.c:263
#, c-format
msgid "The prefix \"pg_\" is reserved for system schemas."
-msgstr "Le pr�fixe � pg_ � est r�serv� pour les sch�mas syst�me."
+msgstr "Le préfixe « pg_ » est réservé pour les schémas système."
#: commands/schemacmds.c:114
#, c-format
msgid "schema \"%s\" already exists, skipping"
-msgstr "la sch�ma � %s � existe d�j�, poursuite du traitement"
+msgstr "la schéma « %s » existe déjà, poursuite du traitement"
#: commands/seclabel.c:60
#, c-format
msgid "no security label providers have been loaded"
-msgstr "aucun fournisseur de label de s�curit� n'a �t� charg�"
+msgstr "aucun fournisseur de label de sécurité n'a été chargé"
#: commands/seclabel.c:64
#, c-format
msgid "must specify provider when multiple security label providers have been loaded"
-msgstr "doit indiquer le fournisseur quand plusieurs fournisseurs de labels de s�curit� sont charg�s"
+msgstr "doit indiquer le fournisseur quand plusieurs fournisseurs de labels de sécurité sont chargés"
#: commands/seclabel.c:82
#, c-format
msgid "security label provider \"%s\" is not loaded"
-msgstr "le fournisseur � %s � de label de s�curit� n'est pas charg�"
+msgstr "le fournisseur « %s » de label de sécurité n'est pas chargé"
#: commands/sequence.c:127
#, c-format
msgid "unlogged sequences are not supported"
-msgstr "les s�quences non trac�es ne sont pas support�es"
+msgstr "les séquences non tracées ne sont pas supportées"
#: commands/sequence.c:651
#, c-format
msgid "nextval: reached maximum value of sequence \"%s\" (%s)"
-msgstr "nextval : valeur maximale de la s�quence � %s � (%s) atteinte"
+msgstr "nextval : valeur maximale de la séquence « %s » (%s) atteinte"
#: commands/sequence.c:674
#, c-format
msgid "nextval: reached minimum value of sequence \"%s\" (%s)"
-msgstr "nextval : valeur minimale de la s�quence � %s � (%s) atteinte"
+msgstr "nextval : valeur minimale de la séquence « %s » (%s) atteinte"
#: commands/sequence.c:792
#, c-format
msgid "currval of sequence \"%s\" is not yet defined in this session"
msgstr ""
-"la valeur courante (currval) de la s�quence � %s � n'est pas encore d�finie\n"
+"la valeur courante (currval) de la séquence « %s » n'est pas encore définie\n"
"dans cette session"
#: commands/sequence.c:811 commands/sequence.c:817
#, c-format
msgid "lastval is not yet defined in this session"
-msgstr "la derni�re valeur (lastval) n'est pas encore d�finie dans cette session"
+msgstr "la dernière valeur (lastval) n'est pas encore définie dans cette session"
#: commands/sequence.c:893
#, c-format
msgid "setval: value %s is out of bounds for sequence \"%s\" (%s..%s)"
-msgstr "setval : la valeur %s est en dehors des limites de la s�quence � %s � (%s..%s)"
+msgstr "setval : la valeur %s est en dehors des limites de la séquence « %s » (%s..%s)"
#: commands/sequence.c:1267
#, c-format
msgid "INCREMENT must not be zero"
-msgstr "la valeur INCREMENT ne doit pas �tre z�ro"
+msgstr "la valeur INCREMENT ne doit pas être zéro"
#: commands/sequence.c:1323
#, c-format
msgid "MINVALUE (%s) must be less than MAXVALUE (%s)"
-msgstr "la valeur MINVALUE (%s) doit �tre moindre que la valeur MAXVALUE (%s)"
+msgstr "la valeur MINVALUE (%s) doit être moindre que la valeur MAXVALUE (%s)"
#: commands/sequence.c:1348
#, c-format
msgid "START value (%s) cannot be less than MINVALUE (%s)"
-msgstr "la valeur START (%s) ne peut pas �tre plus petite que celle de MINVALUE (%s)"
+msgstr "la valeur START (%s) ne peut pas être plus petite que celle de MINVALUE (%s)"
#: commands/sequence.c:1360
#, c-format
msgid "START value (%s) cannot be greater than MAXVALUE (%s)"
-msgstr "la valeur START (%s) ne peut pas �tre plus grande que celle de MAXVALUE (%s)"
+msgstr "la valeur START (%s) ne peut pas être plus grande que celle de MAXVALUE (%s)"
#: commands/sequence.c:1390
#, c-format
msgid "RESTART value (%s) cannot be less than MINVALUE (%s)"
-msgstr "la valeur RESTART (%s) ne peut pas �tre plus petite que celle de MINVALUE (%s)"
+msgstr "la valeur RESTART (%s) ne peut pas être plus petite que celle de MINVALUE (%s)"
#: commands/sequence.c:1402
#, c-format
msgid "RESTART value (%s) cannot be greater than MAXVALUE (%s)"
-msgstr "la valeur RESTART (%s) ne peut pas �tre plus grande que celle de MAXVALUE (%s)"
+msgstr "la valeur RESTART (%s) ne peut pas être plus grande que celle de MAXVALUE (%s)"
#: commands/sequence.c:1417
#, c-format
msgid "CACHE (%s) must be greater than zero"
-msgstr "la valeur CACHE (%s) doit �tre plus grande que z�ro"
+msgstr "la valeur CACHE (%s) doit être plus grande que zéro"
#: commands/sequence.c:1449
#, c-format
@@ -7673,960 +7688,968 @@ msgstr "Indiquer OWNED BY table.colonne ou OWNED BY NONE."
#: commands/sequence.c:1473
#, c-format
msgid "referenced relation \"%s\" is not a table or foreign table"
-msgstr "la relation r�f�renc�e � %s � n'est ni une table ni une table distante"
+msgstr "la relation référencée « %s » n'est ni une table ni une table distante"
#: commands/sequence.c:1480
#, c-format
msgid "sequence must have same owner as table it is linked to"
-msgstr "la s�quence doit avoir le m�me propri�taire que la table avec laquelle elle est li�e"
+msgstr "la séquence doit avoir le même propriétaire que la table avec laquelle elle est liée"
#: commands/sequence.c:1484
#, c-format
msgid "sequence must be in same schema as table it is linked to"
-msgstr "la s�quence doit �tre dans le m�me sch�ma que la table avec laquelle elle est li�e"
+msgstr "la séquence doit être dans le même schéma que la table avec laquelle elle est liée"
-#: commands/tablecmds.c:215
+#: commands/tablecmds.c:216
#, c-format
msgid "table \"%s\" does not exist"
-msgstr "la table � %s � n'existe pas"
+msgstr "la table « %s » n'existe pas"
-#: commands/tablecmds.c:216
+#: commands/tablecmds.c:217
#, c-format
msgid "table \"%s\" does not exist, skipping"
-msgstr "la table � %s � n'existe pas, poursuite du traitement"
+msgstr "la table « %s » n'existe pas, poursuite du traitement"
-#: commands/tablecmds.c:218
+#: commands/tablecmds.c:219
msgid "Use DROP TABLE to remove a table."
msgstr "Utilisez DROP TABLE pour supprimer une table."
-#: commands/tablecmds.c:221
+#: commands/tablecmds.c:222
#, c-format
msgid "sequence \"%s\" does not exist"
-msgstr "la s�quence � %s � n'existe pas"
+msgstr "la séquence « %s » n'existe pas"
-#: commands/tablecmds.c:222
+#: commands/tablecmds.c:223
#, c-format
msgid "sequence \"%s\" does not exist, skipping"
-msgstr "la s�quence � %s � n'existe pas, poursuite du traitement"
+msgstr "la séquence « %s » n'existe pas, poursuite du traitement"
-#: commands/tablecmds.c:224
+#: commands/tablecmds.c:225
msgid "Use DROP SEQUENCE to remove a sequence."
-msgstr "Utilisez DROP SEQUENCE pour supprimer une s�quence."
+msgstr "Utilisez DROP SEQUENCE pour supprimer une séquence."
-#: commands/tablecmds.c:227
+#: commands/tablecmds.c:228
#, c-format
msgid "view \"%s\" does not exist"
-msgstr "la vue � %s � n'existe pas"
+msgstr "la vue « %s » n'existe pas"
-#: commands/tablecmds.c:228
+#: commands/tablecmds.c:229
#, c-format
msgid "view \"%s\" does not exist, skipping"
-msgstr "la vue � %s � n'existe pas, poursuite du traitement"
+msgstr "la vue « %s » n'existe pas, poursuite du traitement"
-#: commands/tablecmds.c:230
+#: commands/tablecmds.c:231
msgid "Use DROP VIEW to remove a view."
msgstr "Utilisez DROP VIEW pour supprimer une vue."
-#: commands/tablecmds.c:233
+#: commands/tablecmds.c:234
#, c-format
msgid "materialized view \"%s\" does not exist"
-msgstr "la vue mat�rialis�e � %s � n'existe pas"
+msgstr "la vue matérialisée « %s » n'existe pas"
-#: commands/tablecmds.c:234
+#: commands/tablecmds.c:235
#, c-format
msgid "materialized view \"%s\" does not exist, skipping"
-msgstr "la vue mat�rialis�e � %s � n'existe pas, poursuite du traitement"
+msgstr "la vue matérialisée « %s » n'existe pas, poursuite du traitement"
-#: commands/tablecmds.c:236
+#: commands/tablecmds.c:237
msgid "Use DROP MATERIALIZED VIEW to remove a materialized view."
-msgstr "Utilisez DROP MATERIALIZED VIEW pour supprimer une vue mat�rialis�e."
+msgstr "Utilisez DROP MATERIALIZED VIEW pour supprimer une vue matérialisée."
-#: commands/tablecmds.c:239 parser/parse_utilcmd.c:1643
+#: commands/tablecmds.c:240 parser/parse_utilcmd.c:1630
#, c-format
msgid "index \"%s\" does not exist"
-msgstr "l'index � %s � n'existe pas"
+msgstr "l'index « %s » n'existe pas"
-#: commands/tablecmds.c:240
+#: commands/tablecmds.c:241
#, c-format
msgid "index \"%s\" does not exist, skipping"
-msgstr "l'index � %s � n'existe pas, poursuite du traitement"
+msgstr "l'index « %s » n'existe pas, poursuite du traitement"
-#: commands/tablecmds.c:242
+#: commands/tablecmds.c:243
msgid "Use DROP INDEX to remove an index."
msgstr "Utilisez DROP INDEX pour supprimer un index."
-#: commands/tablecmds.c:247
+#: commands/tablecmds.c:248
#, c-format
msgid "\"%s\" is not a type"
-msgstr "� %s � n'est pas un type"
+msgstr "« %s » n'est pas un type"
-#: commands/tablecmds.c:248
+#: commands/tablecmds.c:249
msgid "Use DROP TYPE to remove a type."
msgstr "Utilisez DROP TYPE pour supprimer un type."
-#: commands/tablecmds.c:251 commands/tablecmds.c:8486 commands/tablecmds.c:11194
+#: commands/tablecmds.c:252 commands/tablecmds.c:8583 commands/tablecmds.c:11335
#, c-format
msgid "foreign table \"%s\" does not exist"
-msgstr "la table distante � %s � n'existe pas"
+msgstr "la table distante « %s » n'existe pas"
-#: commands/tablecmds.c:252
+#: commands/tablecmds.c:253
#, c-format
msgid "foreign table \"%s\" does not exist, skipping"
-msgstr "la table distante � %s � n'existe pas, poursuite du traitement"
+msgstr "la table distante « %s » n'existe pas, poursuite du traitement"
-#: commands/tablecmds.c:254
+#: commands/tablecmds.c:255
msgid "Use DROP FOREIGN TABLE to remove a foreign table."
msgstr "Utilisez DROP FOREIGN TABLE pour supprimer une table distante."
-#: commands/tablecmds.c:493
+#: commands/tablecmds.c:494
#, c-format
msgid "ON COMMIT can only be used on temporary tables"
-msgstr "ON COMMIT peut seulement �tre utilis� sur des tables temporaires"
+msgstr "ON COMMIT peut seulement être utilisé sur des tables temporaires"
-#: commands/tablecmds.c:513
+#: commands/tablecmds.c:514
#, c-format
msgid "cannot create temporary table within security-restricted operation"
msgstr ""
-"ne peut pas cr�er une table temporaire � l'int�rieur d'une fonction\n"
-"restreinte pour s�curit�"
+"ne peut pas créer une table temporaire à l'intérieur d'une fonction\n"
+"restreinte pour sécurité"
-#: commands/tablecmds.c:821
+#: commands/tablecmds.c:822
#, c-format
msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects"
msgstr "DROP INDEX CONCURRENTLY ne permet pas de supprimer plusieurs objets"
-#: commands/tablecmds.c:825
+#: commands/tablecmds.c:826
#, c-format
msgid "DROP INDEX CONCURRENTLY does not support CASCADE"
msgstr "DROP INDEX CONCURRENTLY ne permet pas la CASCADE"
-#: commands/tablecmds.c:1084
+#: commands/tablecmds.c:1085
#, c-format
msgid "truncate cascades to table \"%s\""
-msgstr "TRUNCATE cascade sur la table � %s �"
+msgstr "TRUNCATE cascade sur la table « %s »"
-#: commands/tablecmds.c:1322
+#: commands/tablecmds.c:1323
#, c-format
msgid "cannot truncate temporary tables of other sessions"
msgstr "ne peut pas tronquer les tables temporaires des autres sessions"
-#: commands/tablecmds.c:1528 parser/parse_utilcmd.c:1857
+#: commands/tablecmds.c:1529 parser/parse_utilcmd.c:1844
#, c-format
msgid "inherited relation \"%s\" is not a table or foreign table"
-msgstr "la relation h�rit�e � %s � n'est ni une table ni une table distante"
+msgstr "la relation héritée « %s » n'est ni une table ni une table distante"
-#: commands/tablecmds.c:1535 commands/tablecmds.c:10053
+#: commands/tablecmds.c:1536 commands/tablecmds.c:10150
#, c-format
msgid "cannot inherit from temporary relation \"%s\""
-msgstr "ine peut pas h�riter � partir d'une relation temporaire � %s �"
+msgstr "ine peut pas hériter à partir d'une relation temporaire « %s »"
-#: commands/tablecmds.c:1543 commands/tablecmds.c:10061
+#: commands/tablecmds.c:1544 commands/tablecmds.c:10158
#, c-format
msgid "cannot inherit from temporary relation of another session"
-msgstr "ne peut pas h�riter de la table temporaire d'une autre session"
+msgstr "ne peut pas hériter de la table temporaire d'une autre session"
-#: commands/tablecmds.c:1559 commands/tablecmds.c:10095
+#: commands/tablecmds.c:1560 commands/tablecmds.c:10192
#, c-format
msgid "relation \"%s\" would be inherited from more than once"
-msgstr "la relation � %s � serait h�rit�e plus d'une fois"
+msgstr "la relation « %s » serait héritée plus d'une fois"
-#: commands/tablecmds.c:1607
+#: commands/tablecmds.c:1608
#, c-format
msgid "merging multiple inherited definitions of column \"%s\""
-msgstr "assemblage de plusieurs d�finitions d'h�ritage pour la colonne � %s �"
+msgstr "assemblage de plusieurs définitions d'héritage pour la colonne « %s »"
-#: commands/tablecmds.c:1615
+#: commands/tablecmds.c:1616
#, c-format
msgid "inherited column \"%s\" has a type conflict"
-msgstr "la colonne h�rit�e � %s � a un conflit de type"
+msgstr "la colonne héritée « %s » a un conflit de type"
-#: commands/tablecmds.c:1617 commands/tablecmds.c:1640 commands/tablecmds.c:1838 commands/tablecmds.c:1862 parser/parse_coerce.c:1630 parser/parse_coerce.c:1650 parser/parse_coerce.c:1670 parser/parse_coerce.c:1715 parser/parse_coerce.c:1752 parser/parse_param.c:218
+#: commands/tablecmds.c:1618 commands/tablecmds.c:1641 commands/tablecmds.c:1839 commands/tablecmds.c:1863 parser/parse_coerce.c:1630 parser/parse_coerce.c:1650 parser/parse_coerce.c:1670 parser/parse_coerce.c:1715 parser/parse_coerce.c:1752 parser/parse_param.c:218
#, c-format
msgid "%s versus %s"
msgstr "%s versus %s"
-#: commands/tablecmds.c:1626
+#: commands/tablecmds.c:1627
#, c-format
msgid "inherited column \"%s\" has a collation conflict"
-msgstr "la colonne h�rit�e � %s � a un conflit sur le collationnement"
+msgstr "la colonne héritée « %s » a un conflit sur le collationnement"
-#: commands/tablecmds.c:1628 commands/tablecmds.c:1850 commands/tablecmds.c:4766
+#: commands/tablecmds.c:1629 commands/tablecmds.c:1851 commands/tablecmds.c:4767
#, c-format
msgid "\"%s\" versus \"%s\""
-msgstr "� %s � versus � %s �"
+msgstr "« %s » versus « %s »"
-#: commands/tablecmds.c:1638
+#: commands/tablecmds.c:1639
#, c-format
msgid "inherited column \"%s\" has a storage parameter conflict"
-msgstr "la colonne h�rit�e � %s � a un conflit de param�tre de stockage"
+msgstr "la colonne héritée « %s » a un conflit de paramètre de stockage"
-#: commands/tablecmds.c:1751 parser/parse_utilcmd.c:938 parser/parse_utilcmd.c:1287 parser/parse_utilcmd.c:1363
+#: commands/tablecmds.c:1752 commands/tablecmds.c:8088 parser/parse_utilcmd.c:923 parser/parse_utilcmd.c:1274 parser/parse_utilcmd.c:1350
#, c-format
msgid "cannot convert whole-row table reference"
-msgstr "ne peut pas convertir une r�f�rence de ligne compl�te de table"
+msgstr "ne peut pas convertir une référence de ligne complète de table"
-#: commands/tablecmds.c:1752 parser/parse_utilcmd.c:939
+#: commands/tablecmds.c:1753 parser/parse_utilcmd.c:924
#, c-format
msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"."
-msgstr "La constrainte � %s � contient une r�f�rence de ligne compl�te vers la table � %s �."
+msgstr "La constrainte « %s » contient une référence de ligne complète vers la table « %s »."
-#: commands/tablecmds.c:1824
+#: commands/tablecmds.c:1825
#, c-format
msgid "merging column \"%s\" with inherited definition"
-msgstr "assemblage de la colonne � %s � avec une d�finition h�rit�e"
+msgstr "assemblage de la colonne « %s » avec une définition héritée"
-#: commands/tablecmds.c:1828
+#: commands/tablecmds.c:1829
#, c-format
msgid "moving and merging column \"%s\" with inherited definition"
-msgstr "d�placement et assemblage de la colonne � %s � avec une d�finition h�rit�e"
+msgstr "déplacement et assemblage de la colonne « %s » avec une définition héritée"
-#: commands/tablecmds.c:1829
+#: commands/tablecmds.c:1830
#, c-format
msgid "User-specified column moved to the position of the inherited column."
-msgstr "Colonne utilisateur d�plac�e � la position de la colonne h�rit�e."
+msgstr "Colonne utilisateur déplacée à la position de la colonne héritée."
-#: commands/tablecmds.c:1836
+#: commands/tablecmds.c:1837
#, c-format
msgid "column \"%s\" has a type conflict"
-msgstr "la colonne � %s � a un conflit de type"
+msgstr "la colonne « %s » a un conflit de type"
-#: commands/tablecmds.c:1848
+#: commands/tablecmds.c:1849
#, c-format
msgid "column \"%s\" has a collation conflict"
-msgstr "la colonne � %s � a un conflit sur le collationnement"
+msgstr "la colonne « %s » a un conflit sur le collationnement"
-#: commands/tablecmds.c:1860
+#: commands/tablecmds.c:1861
#, c-format
msgid "column \"%s\" has a storage parameter conflict"
-msgstr "la colonne � %s � a un conflit de param�tre de stockage"
+msgstr "la colonne « %s » a un conflit de paramètre de stockage"
-#: commands/tablecmds.c:1912
+#: commands/tablecmds.c:1913
#, c-format
msgid "column \"%s\" inherits conflicting default values"
-msgstr "la colonne � %s � h�rite de valeurs par d�faut conflictuelles"
+msgstr "la colonne « %s » hérite de valeurs par défaut conflictuelles"
-#: commands/tablecmds.c:1914
+#: commands/tablecmds.c:1915
#, c-format
msgid "To resolve the conflict, specify a default explicitly."
-msgstr "Pour r�soudre le conflit, sp�cifiez explicitement une valeur par d�faut."
+msgstr "Pour résoudre le conflit, spécifiez explicitement une valeur par défaut."
-#: commands/tablecmds.c:1961
+#: commands/tablecmds.c:1962
#, c-format
msgid "check constraint name \"%s\" appears multiple times but with different expressions"
msgstr ""
-"le nom de la contrainte de v�rification, � %s �, appara�t plusieurs fois\n"
-"mais avec des expressions diff�rentes"
+"le nom de la contrainte de vérification, « %s », apparaît plusieurs fois\n"
+"mais avec des expressions différentes"
-#: commands/tablecmds.c:2155
+#: commands/tablecmds.c:2156
#, c-format
msgid "cannot rename column of typed table"
-msgstr "ne peut pas renommer une colonne d'une table typ�e"
+msgstr "ne peut pas renommer une colonne d'une table typée"
-#: commands/tablecmds.c:2172
+#: commands/tablecmds.c:2173
#, c-format
msgid "\"%s\" is not a table, view, materialized view, composite type, index, or foreign table"
-msgstr "� %s � n'est ni une table, ni une vue, ni une vue mat�rialis�e, ni un type composite, ni un index, ni une table distante"
+msgstr "« %s » n'est ni une table, ni une vue, ni une vue matérialisée, ni un type composite, ni un index, ni une table distante"
-#: commands/tablecmds.c:2266
+#: commands/tablecmds.c:2267
#, c-format
msgid "inherited column \"%s\" must be renamed in child tables too"
-msgstr "la colonne h�rit�e � %s � doit aussi �tre renomm�e pour les tables filles"
+msgstr "la colonne héritée « %s » doit aussi être renommée pour les tables filles"
-#: commands/tablecmds.c:2298
+#: commands/tablecmds.c:2299
#, c-format
msgid "cannot rename system column \"%s\""
-msgstr "ne peut pas renommer la colonne syst�me � %s �"
+msgstr "ne peut pas renommer la colonne système « %s »"
-#: commands/tablecmds.c:2313
+#: commands/tablecmds.c:2314
#, c-format
msgid "cannot rename inherited column \"%s\""
-msgstr "ne peut pas renommer la colonne h�rit�e � %s �"
+msgstr "ne peut pas renommer la colonne héritée « %s »"
-#: commands/tablecmds.c:2468
+#: commands/tablecmds.c:2469
#, c-format
msgid "inherited constraint \"%s\" must be renamed in child tables too"
-msgstr "la contrainte h�rit�e � %s � doit aussi �tre renomm�e pour les tables enfants"
+msgstr "la contrainte héritée « %s » doit aussi être renommée pour les tables enfants"
-#: commands/tablecmds.c:2475
+#: commands/tablecmds.c:2476
#, c-format
msgid "cannot rename inherited constraint \"%s\""
-msgstr "ne peut pas renommer la colonne h�rit�e � %s �"
+msgstr "ne peut pas renommer la colonne héritée « %s »"
#. translator: first %s is a SQL command, eg ALTER TABLE
-#: commands/tablecmds.c:2701
+#: commands/tablecmds.c:2702
#, c-format
msgid "cannot %s \"%s\" because it is being used by active queries in this session"
msgstr ""
-"ne peut pas ex�cuter %s � %s � car cet objet est en cours d'utilisation par\n"
-"des requ�tes actives dans cette session"
+"ne peut pas exécuter %s « %s » car cet objet est en cours d'utilisation par\n"
+"des requêtes actives dans cette session"
#. translator: first %s is a SQL command, eg ALTER TABLE
-#: commands/tablecmds.c:2710
+#: commands/tablecmds.c:2711
#, c-format
msgid "cannot %s \"%s\" because it has pending trigger events"
-msgstr "ne peut pas ex�cuter %s � %s � car il reste des �v�nements sur les triggers"
+msgstr "ne peut pas exécuter %s « %s » car il reste des événements sur les triggers"
-#: commands/tablecmds.c:3784
+#: commands/tablecmds.c:3785
#, c-format
msgid "cannot rewrite system relation \"%s\""
-msgstr "ne peut pas r�-�crire la relation syst�me � %s �"
+msgstr "ne peut pas ré-écrire la relation système « %s »"
-#: commands/tablecmds.c:3790
+#: commands/tablecmds.c:3791
#, c-format
msgid "cannot rewrite table \"%s\" used as a catalog table"
-msgstr "ne peut pas r��crire la table � %s � utilis�e comme une table catalogue"
+msgstr "ne peut pas réécrire la table « %s » utilisée comme une table catalogue"
-#: commands/tablecmds.c:3800
+#: commands/tablecmds.c:3801
#, c-format
msgid "cannot rewrite temporary tables of other sessions"
-msgstr "ne peut pas r�-�crire les tables temporaires des autres sessions"
+msgstr "ne peut pas ré-écrire les tables temporaires des autres sessions"
-#: commands/tablecmds.c:4068
+#: commands/tablecmds.c:4069
#, c-format
msgid "rewriting table \"%s\""
-msgstr "r�-�criture de la table � %s �"
+msgstr "ré-écriture de la table « %s »"
-#: commands/tablecmds.c:4072
+#: commands/tablecmds.c:4073
#, c-format
msgid "verifying table \"%s\""
-msgstr "v�rification de la table � %s �"
+msgstr "vérification de la table « %s »"
-#: commands/tablecmds.c:4186
+#: commands/tablecmds.c:4187
#, c-format
msgid "column \"%s\" contains null values"
-msgstr "la colonne � %s � contient des valeurs NULL"
+msgstr "la colonne « %s » contient des valeurs NULL"
-#: commands/tablecmds.c:4201 commands/tablecmds.c:7366
+#: commands/tablecmds.c:4202 commands/tablecmds.c:7385
#, c-format
msgid "check constraint \"%s\" is violated by some row"
-msgstr "la contrainte de v�rification � %s � est rompue par une ligne"
+msgstr "la contrainte de vérification « %s » est rompue par une ligne"
-#: commands/tablecmds.c:4349 commands/trigger.c:235 rewrite/rewriteDefine.c:267 rewrite/rewriteDefine.c:912
+#: commands/tablecmds.c:4350 commands/trigger.c:235 rewrite/rewriteDefine.c:267 rewrite/rewriteDefine.c:912
#, c-format
msgid "\"%s\" is not a table or view"
-msgstr "� %s � n'est pas une table ou une vue"
+msgstr "« %s » n'est pas une table ou une vue"
-#: commands/tablecmds.c:4352 commands/trigger.c:1119 commands/trigger.c:1224
+#: commands/tablecmds.c:4353 commands/trigger.c:1119 commands/trigger.c:1224
#, c-format
msgid "\"%s\" is not a table, view, or foreign table"
-msgstr "� %s � n'est pas une table, une vue ou une table distante"
+msgstr "« %s » n'est pas une table, une vue ou une table distante"
-#: commands/tablecmds.c:4355
+#: commands/tablecmds.c:4356
#, c-format
msgid "\"%s\" is not a table, view, materialized view, or index"
-msgstr "� %s � n'est pas une table, une vue, une vue mat�rialis�e, une s�quence ou une table distante"
+msgstr "« %s » n'est pas une table, une vue, une vue matérialisée, une séquence ou une table distante"
-#: commands/tablecmds.c:4361
+#: commands/tablecmds.c:4362
#, c-format
msgid "\"%s\" is not a table, materialized view, or index"
-msgstr "� %s � n'est pas une table, une vue mat�rialis�e ou un index"
+msgstr "« %s » n'est pas une table, une vue matérialisée ou un index"
-#: commands/tablecmds.c:4364
+#: commands/tablecmds.c:4365
#, c-format
msgid "\"%s\" is not a table, materialized view, or foreign table"
-msgstr "� %s � n'est pas une table, une vue mat�rialis�e ou une table distante"
+msgstr "« %s » n'est pas une table, une vue matérialisée ou une table distante"
-#: commands/tablecmds.c:4367
+#: commands/tablecmds.c:4368
#, c-format
msgid "\"%s\" is not a table or foreign table"
-msgstr "� %s � n'est pas une table ou une table distante"
+msgstr "« %s » n'est pas une table ou une table distante"
-#: commands/tablecmds.c:4370
+#: commands/tablecmds.c:4371
#, c-format
msgid "\"%s\" is not a table, composite type, or foreign table"
-msgstr "� %s � n'est ni une table, ni un type composite, ni une table distante"
+msgstr "« %s » n'est ni une table, ni un type composite, ni une table distante"
-#: commands/tablecmds.c:4373 commands/tablecmds.c:5425
+#: commands/tablecmds.c:4374 commands/tablecmds.c:5426
#, c-format
msgid "\"%s\" is not a table, materialized view, index, or foreign table"
-msgstr "� %s � n'est pas une table, une vue mat�rialis�e, un index ou une table distante"
+msgstr "« %s » n'est pas une table, une vue matérialisée, un index ou une table distante"
-#: commands/tablecmds.c:4383
+#: commands/tablecmds.c:4384
#, c-format
msgid "\"%s\" is of the wrong type"
-msgstr "� %s � est du mauvais type"
+msgstr "« %s » est du mauvais type"
-#: commands/tablecmds.c:4535 commands/tablecmds.c:4542
+#: commands/tablecmds.c:4536 commands/tablecmds.c:4543
#, c-format
msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it"
-msgstr "ne peux pas modifier le type � %s � car la colonne � %s.%s � l'utilise"
+msgstr "ne peux pas modifier le type « %s » car la colonne « %s.%s » l'utilise"
-#: commands/tablecmds.c:4549
+#: commands/tablecmds.c:4550
#, c-format
msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type"
msgstr ""
-"ne peut pas modifier la table distante � %s � car la colonne � %s.%s � utilise\n"
+"ne peut pas modifier la table distante « %s » car la colonne « %s.%s » utilise\n"
"son type de ligne"
-#: commands/tablecmds.c:4556
+#: commands/tablecmds.c:4557
#, c-format
msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type"
msgstr ""
-"ne peut pas modifier la table � %s � car la colonne � %s.%s � utilise\n"
+"ne peut pas modifier la table « %s » car la colonne « %s.%s » utilise\n"
"son type de ligne"
-#: commands/tablecmds.c:4618
+#: commands/tablecmds.c:4619
#, c-format
msgid "cannot alter type \"%s\" because it is the type of a typed table"
-msgstr "ne peut pas modifier le type � %s � car il s'agit du type d'une table de type"
+msgstr "ne peut pas modifier le type « %s » car il s'agit du type d'une table de type"
-#: commands/tablecmds.c:4620
+#: commands/tablecmds.c:4621
#, c-format
msgid "Use ALTER ... CASCADE to alter the typed tables too."
msgstr "Utilisez ALTER ... CASCADE pour modifier aussi les tables de type."
-#: commands/tablecmds.c:4664
+#: commands/tablecmds.c:4665
#, c-format
msgid "type %s is not a composite type"
msgstr "le type %s n'est pas un type composite"
-#: commands/tablecmds.c:4690
+#: commands/tablecmds.c:4691
#, c-format
msgid "cannot add column to typed table"
-msgstr "ne peut pas ajouter une colonne � une table typ�e"
+msgstr "ne peut pas ajouter une colonne à une table typée"
-#: commands/tablecmds.c:4758 commands/tablecmds.c:10254
+#: commands/tablecmds.c:4759 commands/tablecmds.c:10351
#, c-format
msgid "child table \"%s\" has different type for column \"%s\""
-msgstr "la table fille � %s � a un type diff�rent pour la colonne � %s �"
+msgstr "la table fille « %s » a un type différent pour la colonne « %s »"
-#: commands/tablecmds.c:4764 commands/tablecmds.c:10261
+#: commands/tablecmds.c:4765 commands/tablecmds.c:10358
#, c-format
msgid "child table \"%s\" has different collation for column \"%s\""
-msgstr "la table fille � %s � a un collationnement diff�rent pour la colonne � %s �"
+msgstr "la table fille « %s » a un collationnement différent pour la colonne « %s »"
-#: commands/tablecmds.c:4774
+#: commands/tablecmds.c:4775
#, c-format
msgid "child table \"%s\" has a conflicting \"%s\" column"
-msgstr "la table fille � %s � a une colonne conflictuelle, � %s �"
+msgstr "la table fille « %s » a une colonne conflictuelle, « %s »"
-#: commands/tablecmds.c:4786
+#: commands/tablecmds.c:4787
#, c-format
msgid "merging definition of column \"%s\" for child \"%s\""
-msgstr "assemblage de la d�finition de la colonne � %s � pour le fils � %s �"
+msgstr "assemblage de la définition de la colonne « %s » pour le fils « %s »"
-#: commands/tablecmds.c:5013
+#: commands/tablecmds.c:5014
#, c-format
msgid "column must be added to child tables too"
-msgstr "la colonne doit aussi �tre ajout�e aux tables filles"
+msgstr "la colonne doit aussi être ajoutée aux tables filles"
-#: commands/tablecmds.c:5088
-#, fuzzy, c-format
-#| msgid "column \"%s\" of relation \"%s\" already exists"
+#: commands/tablecmds.c:5089
+#, c-format
msgid "column \"%s\" of relation \"%s\" already exists, skipping"
-msgstr "la colonne � %s � de la relation � %s � existe d�j�"
+msgstr "la colonne « %s » de la relation « %s » existe déjà, poursuite du traitement"
-#: commands/tablecmds.c:5095
+#: commands/tablecmds.c:5096
#, c-format
msgid "column \"%s\" of relation \"%s\" already exists"
-msgstr "la colonne � %s � de la relation � %s � existe d�j�"
+msgstr "la colonne « %s » de la relation « %s » existe déjà"
-#: commands/tablecmds.c:5206 commands/tablecmds.c:5312 commands/tablecmds.c:5370 commands/tablecmds.c:5484 commands/tablecmds.c:5541 commands/tablecmds.c:5635 commands/tablecmds.c:7884 commands/tablecmds.c:8509
+#: commands/tablecmds.c:5207 commands/tablecmds.c:5313 commands/tablecmds.c:5371 commands/tablecmds.c:5485 commands/tablecmds.c:5542 commands/tablecmds.c:5636 commands/tablecmds.c:7924 commands/tablecmds.c:8606
#, c-format
msgid "cannot alter system column \"%s\""
-msgstr "n'a pas pu modifier la colonne syst�me � %s �"
+msgstr "n'a pas pu modifier la colonne système « %s »"
-#: commands/tablecmds.c:5242
+#: commands/tablecmds.c:5243
#, c-format
msgid "column \"%s\" is in a primary key"
-msgstr "la colonne � %s � est dans une cl� primaire"
+msgstr "la colonne « %s » est dans une clé primaire"
-#: commands/tablecmds.c:5457
+#: commands/tablecmds.c:5458
#, c-format
msgid "statistics target %d is too low"
msgstr "la cible statistique %d est trop basse"
-#: commands/tablecmds.c:5465
+#: commands/tablecmds.c:5466
#, c-format
msgid "lowering statistics target to %d"
-msgstr "abaissement de la cible statistique � %d"
+msgstr "abaissement de la cible statistique à %d"
-#: commands/tablecmds.c:5615
+#: commands/tablecmds.c:5616
#, c-format
msgid "invalid storage type \"%s\""
-msgstr "type � %s � de stockage invalide"
+msgstr "type « %s » de stockage invalide"
-#: commands/tablecmds.c:5647
+#: commands/tablecmds.c:5648
#, c-format
msgid "column data type %s can only have storage PLAIN"
-msgstr "le type de donn�es %s de la colonne peut seulement avoir un stockage PLAIN"
+msgstr "le type de données %s de la colonne peut seulement avoir un stockage PLAIN"
-#: commands/tablecmds.c:5685
+#: commands/tablecmds.c:5686
#, c-format
msgid "cannot drop column from typed table"
-msgstr "ne peut pas supprimer une colonne � une table typ�e"
+msgstr "ne peut pas supprimer une colonne à une table typée"
-#: commands/tablecmds.c:5729
+#: commands/tablecmds.c:5730
#, c-format
msgid "column \"%s\" of relation \"%s\" does not exist, skipping"
-msgstr "la colonne � %s � de la relation � %s � n'existe pas, ignore"
+msgstr "la colonne « %s » de la relation « %s » n'existe pas, ignore"
-#: commands/tablecmds.c:5742
+#: commands/tablecmds.c:5743
#, c-format
msgid "cannot drop system column \"%s\""
-msgstr "ne peut pas supprimer la colonne syst�me � %s �"
+msgstr "ne peut pas supprimer la colonne système « %s »"
-#: commands/tablecmds.c:5749
+#: commands/tablecmds.c:5750
#, c-format
msgid "cannot drop inherited column \"%s\""
-msgstr "ne peut pas supprimer la colonne h�rit�e � %s �"
+msgstr "ne peut pas supprimer la colonne héritée « %s »"
-#: commands/tablecmds.c:5989
+#: commands/tablecmds.c:5990
#, c-format
msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\""
-msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX renommera l'index � %s � en � %s �"
+msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX renommera l'index « %s » en « %s »"
-#: commands/tablecmds.c:6202
+#: commands/tablecmds.c:6203
#, c-format
msgid "constraint must be added to child tables too"
-msgstr "la contrainte doit aussi �tre ajout�e aux tables filles"
+msgstr "la contrainte doit aussi être ajoutée aux tables filles"
-#: commands/tablecmds.c:6273
+#: commands/tablecmds.c:6274
#, c-format
msgid "referenced relation \"%s\" is not a table"
-msgstr "la relation r�f�renc�e � %s � n'est pas une table"
+msgstr "la relation référencée « %s » n'est pas une table"
-#: commands/tablecmds.c:6296
+#: commands/tablecmds.c:6297
#, c-format
msgid "constraints on permanent tables may reference only permanent tables"
-msgstr "les contraintes sur les tables permanentes peuvent seulement r�f�rencer des tables permanentes"
+msgstr "les contraintes sur les tables permanentes peuvent seulement référencer des tables permanentes"
-#: commands/tablecmds.c:6303
+#: commands/tablecmds.c:6304
#, c-format
msgid "constraints on unlogged tables may reference only permanent or unlogged tables"
-msgstr "les contraintes sur les tables non trac�es peuvent seulement r�f�rencer des tables permanentes ou non trac�es"
+msgstr "les contraintes sur les tables non tracées peuvent seulement référencer des tables permanentes ou non tracées"
-#: commands/tablecmds.c:6309
+#: commands/tablecmds.c:6310
#, c-format
msgid "constraints on temporary tables may reference only temporary tables"
msgstr ""
-"les constraintes sur des tables temporaires ne peuvent r�f�rencer que des\n"
+"les constraintes sur des tables temporaires ne peuvent référencer que des\n"
"tables temporaires"
-#: commands/tablecmds.c:6313
+#: commands/tablecmds.c:6314
#, c-format
msgid "constraints on temporary tables must involve temporary tables of this session"
msgstr ""
-"les contraintes sur des tables temporaires doivent r�f�rencer les tables\n"
+"les contraintes sur des tables temporaires doivent référencer les tables\n"
"temporaires de cette session"
-#: commands/tablecmds.c:6374
+#: commands/tablecmds.c:6375
#, c-format
msgid "number of referencing and referenced columns for foreign key disagree"
-msgstr "nombre de colonnes de r�f�rence et r�f�renc�es pour la cl� �trang�re en d�saccord"
+msgstr "nombre de colonnes de référence et référencées pour la clé étrangère en désaccord"
-#: commands/tablecmds.c:6481
+#: commands/tablecmds.c:6482
#, c-format
msgid "foreign key constraint \"%s\" cannot be implemented"
-msgstr "la contrainte de cl� �trang�re � %s � ne peut pas �tre impl�ment�e"
+msgstr "la contrainte de clé étrangère « %s » ne peut pas être implémentée"
-#: commands/tablecmds.c:6484
+#: commands/tablecmds.c:6485
#, c-format
msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s."
-msgstr "Les colonnes cl�s � %s � et � %s � sont de types incompatibles : %s et %s."
+msgstr "Les colonnes clés « %s » et « %s » sont de types incompatibles : %s et %s."
-#: commands/tablecmds.c:6691 commands/tablecmds.c:6841 commands/tablecmds.c:7723 commands/tablecmds.c:7779
+#: commands/tablecmds.c:6692 commands/tablecmds.c:6860 commands/tablecmds.c:7763 commands/tablecmds.c:7819
#, c-format
msgid "constraint \"%s\" of relation \"%s\" does not exist"
-msgstr "la contrainte � %s � de la relation � %s � n'existe pas"
+msgstr "la contrainte « %s » de la relation « %s » n'existe pas"
-#: commands/tablecmds.c:6697
+#: commands/tablecmds.c:6698
#, c-format
msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint"
-msgstr "la contrainte � %s � de la relation � %s � n'est pas une cl� �trang�re"
+msgstr "la contrainte « %s » de la relation « %s » n'est pas une clé étrangère"
-#: commands/tablecmds.c:6848
+#: commands/tablecmds.c:6867
#, c-format
msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint"
-msgstr "la contrainte � %s � de la relation � %s � n'est pas une cl� �trang�re ou une contrainte de v�rification"
+msgstr "la contrainte « %s » de la relation « %s » n'est pas une clé étrangère ou une contrainte de vérification"
-#: commands/tablecmds.c:6916
+#: commands/tablecmds.c:6935
#, c-format
msgid "constraint must be validated on child tables too"
-msgstr "la contrainte doit aussi �tre valid�es sur les tables enfants"
+msgstr "la contrainte doit aussi être validées sur les tables enfants"
-#: commands/tablecmds.c:6985
+#: commands/tablecmds.c:7004
#, c-format
msgid "column \"%s\" referenced in foreign key constraint does not exist"
-msgstr "la colonne � %s � r�f�renc�e dans la contrainte de cl� �trang�re n'existe pas"
+msgstr "la colonne « %s » référencée dans la contrainte de clé étrangère n'existe pas"
-#: commands/tablecmds.c:6990
+#: commands/tablecmds.c:7009
#, c-format
msgid "cannot have more than %d keys in a foreign key"
-msgstr "ne peut pas avoir plus de %d cl�s dans une cl� �trang�re"
+msgstr "ne peut pas avoir plus de %d clés dans une clé étrangère"
-#: commands/tablecmds.c:7055
+#: commands/tablecmds.c:7074
#, c-format
msgid "cannot use a deferrable primary key for referenced table \"%s\""
-msgstr "ne peut pas utiliser une cl� primaire d�ferrable pour la table � %s � r�f�renc�e"
+msgstr "ne peut pas utiliser une clé primaire déferrable pour la table « %s » référencée"
-#: commands/tablecmds.c:7072
+#: commands/tablecmds.c:7091
#, c-format
msgid "there is no primary key for referenced table \"%s\""
-msgstr "il n'existe pas de cl� �trang�re pour la table � %s � r�f�renc�e"
+msgstr "il n'existe pas de clé étrangère pour la table « %s » référencée"
-#: commands/tablecmds.c:7137
+#: commands/tablecmds.c:7156
#, c-format
msgid "foreign key referenced-columns list must not contain duplicates"
-msgstr "la liste de colonnes r�f�renc�es dans la cl� �trang�re ne doit pas contenir de duplicats"
+msgstr "la liste de colonnes référencées dans la clé étrangère ne doit pas contenir de duplicats"
-#: commands/tablecmds.c:7231
+#: commands/tablecmds.c:7250
#, c-format
msgid "cannot use a deferrable unique constraint for referenced table \"%s\""
msgstr ""
-"ne peut pas utiliser une contrainte unique d�ferrable pour la table\n"
-"r�f�renc�e � %s �"
+"ne peut pas utiliser une contrainte unique déferrable pour la table\n"
+"référencée « %s »"
-#: commands/tablecmds.c:7236
+#: commands/tablecmds.c:7255
#, c-format
msgid "there is no unique constraint matching given keys for referenced table \"%s\""
msgstr ""
-"il n'existe aucune contrainte unique correspondant aux cl�s donn�es pour la\n"
-"table � %s � r�f�renc�e"
+"il n'existe aucune contrainte unique correspondant aux clés données pour la\n"
+"table « %s » référencée"
-#: commands/tablecmds.c:7399
+#: commands/tablecmds.c:7418
#, c-format
msgid "validating foreign key constraint \"%s\""
-msgstr "validation de la contraintes de cl� �trang�re � %s �"
+msgstr "validation de la contraintes de clé étrangère « %s »"
-#: commands/tablecmds.c:7695
+#: commands/tablecmds.c:7717
#, c-format
msgid "cannot drop inherited constraint \"%s\" of relation \"%s\""
-msgstr "ne peut pas supprimer la contrainte h�rit�e � %s � de la relation � %s �"
+msgstr "ne peut pas supprimer la contrainte héritée « %s » de la relation « %s »"
-#: commands/tablecmds.c:7729
+#: commands/tablecmds.c:7769
#, c-format
msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping"
-msgstr "la contrainte � %s � de la relation � %s � n'existe pas, ignore"
+msgstr "la contrainte « %s » de la relation « %s » n'existe pas, ignore"
-#: commands/tablecmds.c:7868
+#: commands/tablecmds.c:7908
#, c-format
msgid "cannot alter column type of typed table"
-msgstr "ne peut pas modifier le type d'une colonne appartenant � une table typ�e"
+msgstr "ne peut pas modifier le type d'une colonne appartenant à une table typée"
-#: commands/tablecmds.c:7891
+#: commands/tablecmds.c:7931
#, c-format
msgid "cannot alter inherited column \"%s\""
-msgstr "ne peut pas modifier la colonne h�rit�e � %s �"
+msgstr "ne peut pas modifier la colonne héritée « %s »"
-#: commands/tablecmds.c:7940
+#: commands/tablecmds.c:7980
#, c-format
msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s"
-msgstr "le r�sultat de la clause USING pour la colonne � %s � ne peut pas �tre converti automatiquement vers le type %s"
+msgstr "le résultat de la clause USING pour la colonne « %s » ne peut pas être converti automatiquement vers le type %s"
-#: commands/tablecmds.c:7943
+#: commands/tablecmds.c:7983
#, c-format
msgid "You might need to add an explicit cast."
msgstr "Vous pouvez avoir besoin d'ajouter une conversion explicite."
-#: commands/tablecmds.c:7947
+#: commands/tablecmds.c:7987
#, c-format
msgid "column \"%s\" cannot be cast automatically to type %s"
-msgstr "la colonne � %s � ne peut pas �tre convertie vers le type %s"
+msgstr "la colonne « %s » ne peut pas être convertie vers le type %s"
#. translator: USING is SQL, don't translate it
-#: commands/tablecmds.c:7950
+#: commands/tablecmds.c:7990
#, c-format
msgid "You might need to specify \"USING %s::%s\"."
-msgstr "Vous pouvez avoir besoin de sp�cifier \"USING %s::%s\"."
+msgstr "Vous pouvez avoir besoin de spécifier \"USING %s::%s\"."
+
+#: commands/tablecmds.c:8089
+#, c-format
+msgid "USING expression contains a whole-row table reference."
+msgstr "l'expression USING contient une référence de table de ligne complète"
-#: commands/tablecmds.c:8003
+#: commands/tablecmds.c:8100
#, c-format
msgid "type of inherited column \"%s\" must be changed in child tables too"
-msgstr "le type de colonne h�rit�e � %s � doit aussi �tre renomm�e pour les tables filles"
+msgstr "le type de colonne héritée « %s » doit aussi être renommée pour les tables filles"
-#: commands/tablecmds.c:8090
+#: commands/tablecmds.c:8187
#, c-format
msgid "cannot alter type of column \"%s\" twice"
-msgstr "ne peut pas modifier la colonne � %s � deux fois"
+msgstr "ne peut pas modifier la colonne « %s » deux fois"
-#: commands/tablecmds.c:8126
+#: commands/tablecmds.c:8223
#, c-format
msgid "default for column \"%s\" cannot be cast automatically to type %s"
msgstr ""
-"la valeur par d�faut de la colonne � %s � ne peut pas �tre convertie vers le\n"
+"la valeur par défaut de la colonne « %s » ne peut pas être convertie vers le\n"
"type %s automatiquement"
-#: commands/tablecmds.c:8252
+#: commands/tablecmds.c:8349
#, c-format
msgid "cannot alter type of a column used by a view or rule"
-msgstr "ne peut pas modifier le type d'une colonne utilis�e dans une vue ou une r�gle"
+msgstr "ne peut pas modifier le type d'une colonne utilisée dans une vue ou une règle"
-#: commands/tablecmds.c:8253 commands/tablecmds.c:8272 commands/tablecmds.c:8290
+#: commands/tablecmds.c:8350 commands/tablecmds.c:8369 commands/tablecmds.c:8387
#, c-format
msgid "%s depends on column \"%s\""
-msgstr "%s d�pend de la colonne � %s �"
+msgstr "%s dépend de la colonne « %s »"
-#: commands/tablecmds.c:8271
+#: commands/tablecmds.c:8368
#, c-format
msgid "cannot alter type of a column used in a trigger definition"
-msgstr "ne peut pas modifier le type d'une colonne utilis�e dans la d�finition d'un trigger"
+msgstr "ne peut pas modifier le type d'une colonne utilisée dans la définition d'un trigger"
-#: commands/tablecmds.c:8289
+#: commands/tablecmds.c:8386
#, c-format
msgid "cannot alter type of a column used in a policy definition"
-msgstr "ne peut pas modifier le type d'une colonne utilis�e dans la d�finition d'une politique"
+msgstr "ne peut pas modifier le type d'une colonne utilisée dans la définition d'une politique"
-#: commands/tablecmds.c:8954
+#: commands/tablecmds.c:9051
#, c-format
msgid "cannot change owner of index \"%s\""
-msgstr "ne peut pas modifier le propri�taire de l'index � %s �"
+msgstr "ne peut pas modifier le propriétaire de l'index « %s »"
-#: commands/tablecmds.c:8956
+#: commands/tablecmds.c:9053
#, c-format
msgid "Change the ownership of the index's table, instead."
-msgstr "Modifier � la place le propri�taire de la table concern�e par l'index."
+msgstr "Modifier à la place le propriétaire de la table concernée par l'index."
-#: commands/tablecmds.c:8972
+#: commands/tablecmds.c:9069
#, c-format
msgid "cannot change owner of sequence \"%s\""
-msgstr "ne peut pas modifier le propri�taire de la s�quence � %s �"
+msgstr "ne peut pas modifier le propriétaire de la séquence « %s »"
-#: commands/tablecmds.c:8974 commands/tablecmds.c:11396
+#: commands/tablecmds.c:9071 commands/tablecmds.c:11543
#, c-format
msgid "Sequence \"%s\" is linked to table \"%s\"."
-msgstr "La s�quence � %s � est li�e � la table � %s �."
+msgstr "La séquence « %s » est liée à la table « %s »."
-#: commands/tablecmds.c:8986 commands/tablecmds.c:12043
+#: commands/tablecmds.c:9083 commands/tablecmds.c:12190
#, c-format
msgid "Use ALTER TYPE instead."
-msgstr "Utilisez ALTER TYPE � la place."
+msgstr "Utilisez ALTER TYPE à la place."
-#: commands/tablecmds.c:8995
+#: commands/tablecmds.c:9092
#, c-format
msgid "\"%s\" is not a table, view, sequence, or foreign table"
-msgstr "� %s � n'est pas une table, une vue, une s�quence ou une table distante"
+msgstr "« %s » n'est pas une table, une vue, une séquence ou une table distante"
-#: commands/tablecmds.c:9338
+#: commands/tablecmds.c:9435
#, c-format
msgid "cannot have multiple SET TABLESPACE subcommands"
msgstr "ne peut pas avoir de nombreuses sous-commandes SET TABLESPACE"
-#: commands/tablecmds.c:9411
+#: commands/tablecmds.c:9508
#, c-format
msgid "\"%s\" is not a table, view, materialized view, index, or TOAST table"
-msgstr "� %s � n'est pas une table, une vue, une vue mat�rialis�e, un index ou une table TOAST"
+msgstr "« %s » n'est pas une table, une vue, une vue matérialisée, un index ou une table TOAST"
-#: commands/tablecmds.c:9444 commands/view.c:481
+#: commands/tablecmds.c:9541 commands/view.c:498
#, c-format
msgid "WITH CHECK OPTION is supported only on automatically updatable views"
-msgstr "WITH CHECK OPTION est uniquement accept� pour les vues dont la mise � jour est automatique"
+msgstr "WITH CHECK OPTION est uniquement accepté pour les vues dont la mise à jour est automatique"
-#: commands/tablecmds.c:9590
+#: commands/tablecmds.c:9687
#, c-format
msgid "cannot move system relation \"%s\""
-msgstr "ne peut pas d�placer la colonne syst�me � %s �"
+msgstr "ne peut pas déplacer la colonne système « %s »"
-#: commands/tablecmds.c:9606
+#: commands/tablecmds.c:9703
#, c-format
msgid "cannot move temporary tables of other sessions"
-msgstr "ne peut pas d�placer les tables temporaires d'autres sessions"
+msgstr "ne peut pas déplacer les tables temporaires d'autres sessions"
-#: commands/tablecmds.c:9743
+#: commands/tablecmds.c:9840
#, c-format
msgid "only tables, indexes, and materialized views exist in tablespaces"
-msgstr "seuls les tables, index et vues mat�rialis�es existent dans les tablespaces"
+msgstr "seuls les tables, index et vues matérialisées existent dans les tablespaces"
-#: commands/tablecmds.c:9755
+#: commands/tablecmds.c:9852
#, c-format
msgid "cannot move relations in to or out of pg_global tablespace"
-msgstr "ne peut pas d�placer les relations dans ou � partir du tablespace pg_global"
+msgstr "ne peut pas déplacer les relations dans ou à partir du tablespace pg_global"
-#: commands/tablecmds.c:9846
+#: commands/tablecmds.c:9943
#, c-format
msgid "aborting because lock on relation \"%s.%s\" is not available"
-msgstr "annulation car le verrou sur la relation � %s.%s � n'est pas disponible"
+msgstr "annulation car le verrou sur la relation « %s.%s » n'est pas disponible"
-#: commands/tablecmds.c:9862
+#: commands/tablecmds.c:9959
#, c-format
msgid "no matching relations in tablespace \"%s\" found"
-msgstr "aucune relation correspondante trouv�e dans le tablespace � %s �"
+msgstr "aucune relation correspondante trouvée dans le tablespace « %s »"
-#: commands/tablecmds.c:9936 storage/buffer/bufmgr.c:915
+#: commands/tablecmds.c:10033 storage/buffer/bufmgr.c:915
#, c-format
msgid "invalid page in block %u of relation %s"
msgstr "page invalide dans le bloc %u de la relation %s"
-#: commands/tablecmds.c:10018
+#: commands/tablecmds.c:10115
#, c-format
msgid "cannot change inheritance of typed table"
-msgstr "ne peut pas modifier l'h�ritage d'une table typ�e"
+msgstr "ne peut pas modifier l'héritage d'une table typée"
-#: commands/tablecmds.c:10068
+#: commands/tablecmds.c:10165
#, c-format
msgid "cannot inherit to temporary relation of another session"
-msgstr "ne peut pas h�riter � partir d'une relation temporaire d'une autre session"
+msgstr "ne peut pas hériter à partir d'une relation temporaire d'une autre session"
-#: commands/tablecmds.c:10122
+#: commands/tablecmds.c:10219
#, c-format
msgid "circular inheritance not allowed"
-msgstr "h�ritage circulaire interdit"
+msgstr "héritage circulaire interdit"
-#: commands/tablecmds.c:10123
+#: commands/tablecmds.c:10220
#, c-format
msgid "\"%s\" is already a child of \"%s\"."
-msgstr "� %s � est d�j� un enfant de � %s �."
+msgstr "« %s » est déjà un enfant de « %s »."
-#: commands/tablecmds.c:10131
+#: commands/tablecmds.c:10228
#, c-format
msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
-msgstr "la table � %s � qui n'a pas d'OID ne peut pas h�riter de la table � %s � qui en a"
+msgstr "la table « %s » qui n'a pas d'OID ne peut pas hériter de la table « %s » qui en a"
-#: commands/tablecmds.c:10272
+#: commands/tablecmds.c:10369
#, c-format
msgid "column \"%s\" in child table must be marked NOT NULL"
-msgstr "la colonne � %s � de la table enfant doit �tre marqu�e comme NOT NULL"
+msgstr "la colonne « %s » de la table enfant doit être marquée comme NOT NULL"
-#: commands/tablecmds.c:10288
+#: commands/tablecmds.c:10385 commands/tablecmds.c:10418
#, c-format
msgid "child table is missing column \"%s\""
-msgstr "la colonne � %s � manque � la table enfant"
+msgstr "la colonne « %s » manque à la table enfant"
-#: commands/tablecmds.c:10371
+#: commands/tablecmds.c:10501
#, c-format
msgid "child table \"%s\" has different definition for check constraint \"%s\""
-msgstr "la table fille � %s � a un type diff�rent pour la contrainte de v�rification � %s �"
+msgstr "la table fille « %s » a un type différent pour la contrainte de vérification « %s »"
-#: commands/tablecmds.c:10379
+#: commands/tablecmds.c:10509
#, c-format
msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\""
-msgstr "la contrainte � %s � entre en conflit avec une contrainte non h�rit�e sur la table fille � %s �"
+msgstr "la contrainte « %s » entre en conflit avec une contrainte non héritée sur la table fille « %s »"
+
+#: commands/tablecmds.c:10520
+#, c-format
+msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\""
+msgstr "la contrainte « %s » entre en conflit avec une contrainte NOT VALID sur la table fille « %s »"
-#: commands/tablecmds.c:10403
+#: commands/tablecmds.c:10544
#, c-format
msgid "child table is missing constraint \"%s\""
-msgstr "la contrainte � %s � manque � la table enfant"
+msgstr "la contrainte « %s » manque à la table enfant"
-#: commands/tablecmds.c:10487
+#: commands/tablecmds.c:10628
#, c-format
msgid "relation \"%s\" is not a parent of relation \"%s\""
-msgstr "la relation � %s � n'est pas un parent de la relation � %s �"
+msgstr "la relation « %s » n'est pas un parent de la relation « %s »"
-#: commands/tablecmds.c:10721
+#: commands/tablecmds.c:10862
#, c-format
msgid "typed tables cannot inherit"
-msgstr "les tables avec type ne peuvent pas h�riter d'autres tables"
+msgstr "les tables avec type ne peuvent pas hériter d'autres tables"
-#: commands/tablecmds.c:10752
+#: commands/tablecmds.c:10893
#, c-format
msgid "table is missing column \"%s\""
-msgstr "la colonne � %s � manque � la table"
+msgstr "la colonne « %s » manque à la table"
-#: commands/tablecmds.c:10762
+#: commands/tablecmds.c:10903
#, c-format
msgid "table has column \"%s\" where type requires \"%s\""
-msgstr "la table a une colonne � %s � alors que le type impose � %s �."
+msgstr "la table a une colonne « %s » alors que le type impose « %s »."
-#: commands/tablecmds.c:10771
+#: commands/tablecmds.c:10912
#, c-format
msgid "table \"%s\" has different type for column \"%s\""
-msgstr "la table � %s � a un type diff�rent pour la colonne � %s �"
+msgstr "la table « %s » a un type différent pour la colonne « %s »"
-#: commands/tablecmds.c:10784
+#: commands/tablecmds.c:10925
#, c-format
msgid "table has extra column \"%s\""
-msgstr "la table a une colonne suppl�mentaire � %s �"
+msgstr "la table a une colonne supplémentaire « %s »"
-#: commands/tablecmds.c:10836
+#: commands/tablecmds.c:10977
#, c-format
msgid "\"%s\" is not a typed table"
-msgstr "� %s � n'est pas une table typ�e"
+msgstr "« %s » n'est pas une table typée"
-#: commands/tablecmds.c:11020
+#: commands/tablecmds.c:11161
#, c-format
msgid "cannot use non-unique index \"%s\" as replica identity"
-msgstr "ne peut pas utiliser l'index non unique � %s � comme identit� de r�plicat"
+msgstr "ne peut pas utiliser l'index non unique « %s » comme identité de réplicat"
-#: commands/tablecmds.c:11026
+#: commands/tablecmds.c:11167
#, c-format
msgid "cannot use non-immediate index \"%s\" as replica identity"
-msgstr "ne peut pas utiliser l'index � %s � imm�diat comme identit� de r�plicat"
+msgstr "ne peut pas utiliser l'index « %s » immédiat comme identité de réplicat"
-#: commands/tablecmds.c:11032
+#: commands/tablecmds.c:11173
#, c-format
msgid "cannot use expression index \"%s\" as replica identity"
-msgstr "ne peut pas utiliser un index par expression � %s � comme identit� de r�plicat"
+msgstr "ne peut pas utiliser un index par expression « %s » comme identité de réplicat"
-#: commands/tablecmds.c:11038
+#: commands/tablecmds.c:11179
#, c-format
msgid "cannot use partial index \"%s\" as replica identity"
-msgstr "ne peut pas utiliser l'index partiel � %s � comme identit� de r�plicat"
+msgstr "ne peut pas utiliser l'index partiel « %s » comme identité de réplicat"
-#: commands/tablecmds.c:11044
+#: commands/tablecmds.c:11185
#, c-format
msgid "cannot use invalid index \"%s\" as replica identity"
-msgstr "ne peut pas utiliser l'index invalide � %s � comme identit� de r�plicat"
+msgstr "ne peut pas utiliser l'index invalide « %s » comme identité de réplicat"
-#: commands/tablecmds.c:11065
-#, fuzzy, c-format
-#| msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable"
+#: commands/tablecmds.c:11206
+#, c-format
msgid "index \"%s\" cannot be used as replica identity because column %d is a system column"
-msgstr "l'index � %s � ne peut pas �tre utilis� comme identit� de r�plicat car la colonne � %s � peut �tre NULL"
+msgstr "l'index « %s » ne peut pas être utilisé comme identité de réplicat car la colonne %d est une colonne système"
-#: commands/tablecmds.c:11072
+#: commands/tablecmds.c:11213
#, c-format
msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable"
-msgstr "l'index � %s � ne peut pas �tre utilis� comme identit� de r�plicat car la colonne � %s � peut �tre NULL"
+msgstr "l'index « %s » ne peut pas être utilisé comme identité de réplicat car la colonne « %s » peut être NULL"
-#: commands/tablecmds.c:11269
+#: commands/tablecmds.c:11416
#, c-format
msgid "cannot change logged status of table \"%s\" because it is temporary"
-msgstr "ne peut pas modifier le statut de journalisation de la table � %s � parce qu'elle est temporaire"
+msgstr "ne peut pas modifier le statut de journalisation de la table « %s » parce qu'elle est temporaire"
-#: commands/tablecmds.c:11328
+#: commands/tablecmds.c:11475
#, c-format
msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\""
-msgstr "n'a pas pu passer la table � %s � en journalis� car elle r�f�rence la table non journalis�e � %s �"
+msgstr "n'a pas pu passer la table « %s » en journalisé car elle référence la table non journalisée « %s »"
-#: commands/tablecmds.c:11338
+#: commands/tablecmds.c:11485
#, c-format
msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\""
-msgstr "n'a pas pu passer la table � %s � en non journalis� car elle r�f�rence la table journalis�e � %s �"
+msgstr "n'a pas pu passer la table « %s » en non journalisé car elle référence la table journalisée « %s »"
-#: commands/tablecmds.c:11395
+#: commands/tablecmds.c:11542
#, c-format
msgid "cannot move an owned sequence into another schema"
-msgstr "ne peut pas d�placer une s�quence OWNED BY dans un autre sch�ma"
+msgstr "ne peut pas déplacer une séquence OWNED BY dans un autre schéma"
-#: commands/tablecmds.c:11500
+#: commands/tablecmds.c:11647
#, c-format
msgid "relation \"%s\" already exists in schema \"%s\""
-msgstr "la relation � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "la relation « %s » existe déjà dans le schéma « %s »"
-#: commands/tablecmds.c:12027
+#: commands/tablecmds.c:12174
#, c-format
msgid "\"%s\" is not a composite type"
-msgstr "� %s � n'est pas un type composite"
+msgstr "« %s » n'est pas un type composite"
-#: commands/tablecmds.c:12057
+#: commands/tablecmds.c:12204
#, c-format
msgid "\"%s\" is not a table, view, materialized view, sequence, or foreign table"
-msgstr "� %s � n'est pas une table, une vue, une vue mat�rialis�e, une s�quence ou une table distante"
+msgstr "« %s » n'est pas une table, une vue, une vue matérialisée, une séquence ou une table distante"
-#: commands/tablespace.c:162 commands/tablespace.c:179 commands/tablespace.c:190 commands/tablespace.c:198 commands/tablespace.c:625 replication/slot.c:969 storage/file/copydir.c:47
+#: commands/tablespace.c:162 commands/tablespace.c:179 commands/tablespace.c:190 commands/tablespace.c:198 commands/tablespace.c:625 replication/slot.c:980 storage/file/copydir.c:47
#, c-format
msgid "could not create directory \"%s\": %m"
-msgstr "n'a pas pu cr�er le r�pertoire � %s � : %m"
+msgstr "n'a pas pu créer le répertoire « %s » : %m"
#: commands/tablespace.c:209
#, c-format
msgid "could not stat directory \"%s\": %m"
-msgstr "n'a pas pu lire les informations sur le r�pertoire � %s � : %m"
+msgstr "n'a pas pu lire les informations sur le répertoire « %s » : %m"
#: commands/tablespace.c:218
#, c-format
msgid "\"%s\" exists but is not a directory"
-msgstr "� %s � existe mais n'est pas un r�pertoire"
+msgstr "« %s » existe mais n'est pas un répertoire"
#: commands/tablespace.c:249
#, c-format
msgid "permission denied to create tablespace \"%s\""
-msgstr "droit refus� pour cr�er le tablespace � %s �"
+msgstr "droit refusé pour créer le tablespace « %s »"
#: commands/tablespace.c:251
#, c-format
msgid "Must be superuser to create a tablespace."
-msgstr "Doit �tre super-utilisateur pour cr�er un tablespace."
+msgstr "Doit être super-utilisateur pour créer un tablespace."
#: commands/tablespace.c:267
#, c-format
@@ -8636,102 +8659,102 @@ msgstr "le chemin du tablespace ne peut pas contenir de guillemets simples"
#: commands/tablespace.c:277
#, c-format
msgid "tablespace location must be an absolute path"
-msgstr "le chemin du tablespace doit �tre un chemin absolu"
+msgstr "le chemin du tablespace doit être un chemin absolu"
#: commands/tablespace.c:288
#, c-format
msgid "tablespace location \"%s\" is too long"
-msgstr "le chemin du tablespace � %s � est trop long"
+msgstr "le chemin du tablespace « %s » est trop long"
#: commands/tablespace.c:295
#, c-format
msgid "tablespace location should not be inside the data directory"
-msgstr "l'emplacement du tablespace ne doit pas �tre dans le r�pertoire de donn�es"
+msgstr "l'emplacement du tablespace ne doit pas être dans le répertoire de données"
#: commands/tablespace.c:304 commands/tablespace.c:952
#, c-format
msgid "unacceptable tablespace name \"%s\""
-msgstr "nom inacceptable pour le tablespace � %s �"
+msgstr "nom inacceptable pour le tablespace « %s »"
#: commands/tablespace.c:306 commands/tablespace.c:953
#, c-format
msgid "The prefix \"pg_\" is reserved for system tablespaces."
-msgstr "Le pr�fixe � pg_ � est r�serv� pour les tablespaces syst�me."
+msgstr "Le préfixe « pg_ » est réservé pour les tablespaces système."
#: commands/tablespace.c:316 commands/tablespace.c:965
#, c-format
msgid "tablespace \"%s\" already exists"
-msgstr "le tablespace � %s � existe d�j�"
+msgstr "le tablespace « %s » existe déjà"
#: commands/tablespace.c:430 commands/tablespace.c:935 commands/tablespace.c:1016 commands/tablespace.c:1085 commands/tablespace.c:1218 commands/tablespace.c:1418
#, c-format
msgid "tablespace \"%s\" does not exist"
-msgstr "le tablespace � %s � n'existe pas"
+msgstr "le tablespace « %s » n'existe pas"
#: commands/tablespace.c:436
#, c-format
msgid "tablespace \"%s\" does not exist, skipping"
-msgstr "le tablespace � %s � n'existe pas, poursuite du traitement"
+msgstr "le tablespace « %s » n'existe pas, poursuite du traitement"
#: commands/tablespace.c:512
#, c-format
msgid "tablespace \"%s\" is not empty"
-msgstr "le tablespace � %s � n'est pas vide"
+msgstr "le tablespace « %s » n'est pas vide"
#: commands/tablespace.c:584
#, c-format
msgid "directory \"%s\" does not exist"
-msgstr "le r�pertoire � %s � n'existe pas"
+msgstr "le répertoire « %s » n'existe pas"
#: commands/tablespace.c:585
#, c-format
msgid "Create this directory for the tablespace before restarting the server."
-msgstr "Cr�er le r�pertoire pour ce tablespace avant de red�marrer le serveur."
+msgstr "Créer le répertoire pour ce tablespace avant de redémarrer le serveur."
#: commands/tablespace.c:590
#, c-format
msgid "could not set permissions on directory \"%s\": %m"
-msgstr "n'a pas pu configurer les droits du r�pertoire � %s � : %m"
+msgstr "n'a pas pu configurer les droits du répertoire « %s » : %m"
#: commands/tablespace.c:620
#, c-format
msgid "directory \"%s\" already in use as a tablespace"
-msgstr "r�pertoire � %s � d�j� en cours d'utilisation"
+msgstr "répertoire « %s » déjà utilisé comme tablespace"
#: commands/tablespace.c:744 commands/tablespace.c:757 commands/tablespace.c:793 commands/tablespace.c:885
#, c-format
msgid "could not remove directory \"%s\": %m"
-msgstr "n'a pas pu supprimer le r�pertoire � %s � : %m"
+msgstr "n'a pas pu supprimer le répertoire « %s » : %m"
#: commands/tablespace.c:806 commands/tablespace.c:894
#, c-format
msgid "could not remove symbolic link \"%s\": %m"
-msgstr "n'a pas pu supprimer le lien symbolique � %s � : %m"
+msgstr "n'a pas pu supprimer le lien symbolique « %s » : %m"
#: commands/tablespace.c:816 commands/tablespace.c:903
#, c-format
msgid "\"%s\" is not a directory or symbolic link"
-msgstr "� %s � n'est pas un r�pertoire ou un lien symbolique"
+msgstr "« %s » n'est pas un répertoire ou un lien symbolique"
#: commands/tablespace.c:1090
#, c-format
msgid "Tablespace \"%s\" does not exist."
-msgstr "Le tablespace � %s � n'existe pas."
+msgstr "Le tablespace « %s » n'existe pas."
#: commands/tablespace.c:1517
#, c-format
msgid "directories for tablespace %u could not be removed"
-msgstr "les r�pertoires du tablespace %u n'ont pas pu �tre supprim�s"
+msgstr "les répertoires du tablespace %u n'ont pas pu être supprimés"
#: commands/tablespace.c:1519
#, c-format
msgid "You can remove the directories manually if necessary."
-msgstr "Vous pouvez supprimer les r�pertoires manuellement si n�cessaire."
+msgstr "Vous pouvez supprimer les répertoires manuellement si nécessaire."
#: commands/trigger.c:184
#, c-format
msgid "\"%s\" is a table"
-msgstr "� %s � est une table"
+msgstr "« %s » est une table"
#: commands/trigger.c:186
#, c-format
@@ -8741,7 +8764,7 @@ msgstr "Les tables ne peuvent pas avoir de triggers INSTEAD OF."
#: commands/trigger.c:197 commands/trigger.c:204
#, c-format
msgid "\"%s\" is a view"
-msgstr "� %s � est une vue"
+msgstr "« %s » est une vue"
#: commands/trigger.c:199
#, c-format
@@ -8756,7 +8779,7 @@ msgstr "Les vues ne peuvent pas avoir de triggers TRUNCATE."
#: commands/trigger.c:214 commands/trigger.c:221 commands/trigger.c:228
#, c-format
msgid "\"%s\" is a foreign table"
-msgstr "� %s � est une table distante"
+msgstr "« %s » est une table distante"
#: commands/trigger.c:216
#, c-format
@@ -8776,12 +8799,12 @@ msgstr "Les tables distantes ne peuvent pas avoir de triggers de contrainte."
#: commands/trigger.c:293
#, c-format
msgid "TRUNCATE FOR EACH ROW triggers are not supported"
-msgstr "les triggers TRUNCATE FOR EACH ROW ne sont pas support�s"
+msgstr "les triggers TRUNCATE FOR EACH ROW ne sont pas supportés"
#: commands/trigger.c:301
#, c-format
msgid "INSTEAD OF triggers must be FOR EACH ROW"
-msgstr "les triggers INSTEAD OF doivent �tre FOR EACH ROW"
+msgstr "les triggers INSTEAD OF doivent être FOR EACH ROW"
#: commands/trigger.c:305
#, c-format
@@ -8797,102 +8820,102 @@ msgstr "les triggers INSTEAD OF ne peuvent pas avoir de liste de colonnes"
#, c-format
msgid "statement trigger's WHEN condition cannot reference column values"
msgstr ""
-"la condition WHEN de l'instruction du trigger ne peut pas r�f�rencer les valeurs\n"
+"la condition WHEN de l'instruction du trigger ne peut pas référencer les valeurs\n"
"des colonnes"
#: commands/trigger.c:371
#, c-format
msgid "INSERT trigger's WHEN condition cannot reference OLD values"
-msgstr "la condition WHEN du trigger INSERT ne peut pas r�f�rencer les valeurs OLD"
+msgstr "la condition WHEN du trigger INSERT ne peut pas référencer les valeurs OLD"
#: commands/trigger.c:384
#, c-format
msgid "DELETE trigger's WHEN condition cannot reference NEW values"
-msgstr "la condition WHEN du trigger DELETE ne peut pas r�f�rencer les valeurs NEW"
+msgstr "la condition WHEN du trigger DELETE ne peut pas référencer les valeurs NEW"
#: commands/trigger.c:389
#, c-format
msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns"
msgstr ""
-"la condition WHEN d'un trigger BEFORE ne doit pas r�f�rencer les colonnes\n"
-"syst�me avec NEW"
+"la condition WHEN d'un trigger BEFORE ne doit pas référencer les colonnes\n"
+"système avec NEW"
#: commands/trigger.c:434
#, c-format
msgid "changing return type of function %s from \"opaque\" to \"trigger\""
-msgstr "changement du type de retour de la fonction %s de � opaque � vers � trigger �"
+msgstr "changement du type de retour de la fonction %s de « opaque » vers « trigger »"
#: commands/trigger.c:553 commands/trigger.c:1303
#, c-format
msgid "trigger \"%s\" for relation \"%s\" already exists"
-msgstr "le trigger � %s � de la relation � %s � existe d�j�"
+msgstr "le trigger « %s » de la relation « %s » existe déjà"
#: commands/trigger.c:838
msgid "Found referenced table's UPDATE trigger."
-msgstr "Trigger UPDATE de la table r�f�renc�e trouv�."
+msgstr "Trigger UPDATE de la table référencée trouvé."
#: commands/trigger.c:839
msgid "Found referenced table's DELETE trigger."
-msgstr "Trigger DELETE de la table r�f�renc�e trouv�."
+msgstr "Trigger DELETE de la table référencée trouvé."
#: commands/trigger.c:840
msgid "Found referencing table's trigger."
-msgstr "Trigger de la table r�f�renc�e trouv�."
+msgstr "Trigger de la table référencée trouvé."
#: commands/trigger.c:949 commands/trigger.c:965
#, c-format
msgid "ignoring incomplete trigger group for constraint \"%s\" %s"
-msgstr "ignore le groupe de trigger incomplet pour la contrainte � %s � %s"
+msgstr "ignore le groupe de trigger incomplet pour la contrainte « %s » %s"
#: commands/trigger.c:977
#, c-format
msgid "converting trigger group into constraint \"%s\" %s"
-msgstr "conversion du groupe de trigger en une contrainte � %s � %s"
+msgstr "conversion du groupe de trigger en une contrainte « %s » %s"
#: commands/trigger.c:1190 commands/trigger.c:1351 commands/trigger.c:1469
#, c-format
msgid "trigger \"%s\" for table \"%s\" does not exist"
-msgstr "le trigger � %s � de la table � %s � n'existe pas"
+msgstr "le trigger « %s » de la table « %s » n'existe pas"
#: commands/trigger.c:1434
#, c-format
msgid "permission denied: \"%s\" is a system trigger"
-msgstr "droit refus� : � %s � est un trigger syst�me"
+msgstr "droit refusé : « %s » est un trigger système"
#: commands/trigger.c:1930
#, c-format
msgid "trigger function %u returned null value"
-msgstr "la fonction trigger %u a renvoy� la valeur NULL"
+msgstr "la fonction trigger %u a renvoyé la valeur NULL"
#: commands/trigger.c:1989 commands/trigger.c:2188 commands/trigger.c:2392 commands/trigger.c:2664
#, c-format
msgid "BEFORE STATEMENT trigger cannot return a value"
msgstr "le trigger BEFORE STATEMENT ne peut pas renvoyer une valeur"
-#: commands/trigger.c:2726 executor/nodeModifyTable.c:664 executor/nodeModifyTable.c:957
+#: commands/trigger.c:2726 executor/nodeModifyTable.c:679 executor/nodeModifyTable.c:972
#, c-format
msgid "tuple to be updated was already modified by an operation triggered by the current command"
-msgstr "la ligne � mettre � jour �tait d�j� modifi�e par une op�ration d�clench�e par la commande courante"
+msgstr "la ligne à mettre à jour était déjà modifiée par une opération déclenchée par la commande courante"
-#: commands/trigger.c:2727 executor/nodeModifyTable.c:665 executor/nodeModifyTable.c:958
+#: commands/trigger.c:2727 executor/nodeModifyTable.c:680 executor/nodeModifyTable.c:973
#, c-format
msgid "Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows."
-msgstr "Consid�rez l'utilisation d'un trigger AFTER au lieu d'un trigger BEFORE pour propager les changements sur les autres lignes."
+msgstr "Considérez l'utilisation d'un trigger AFTER au lieu d'un trigger BEFORE pour propager les changements sur les autres lignes."
-#: commands/trigger.c:2741 executor/execMain.c:2369 executor/nodeLockRows.c:216 executor/nodeModifyTable.c:200 executor/nodeModifyTable.c:677 executor/nodeModifyTable.c:970 executor/nodeModifyTable.c:1136
+#: commands/trigger.c:2741 executor/execMain.c:2379 executor/nodeLockRows.c:216 executor/nodeModifyTable.c:213 executor/nodeModifyTable.c:692 executor/nodeModifyTable.c:985 executor/nodeModifyTable.c:1151
#, c-format
msgid "could not serialize access due to concurrent update"
-msgstr "n'a pas pu s�rialiser un acc�s � cause d'une mise � jour en parall�le"
+msgstr "n'a pas pu sérialiser un accès à cause d'une mise à jour en parallèle"
-#: commands/trigger.c:4579
+#: commands/trigger.c:4575
#, c-format
msgid "constraint \"%s\" is not deferrable"
-msgstr "la contrainte � %s � n'est pas DEFERRABLE"
+msgstr "la contrainte « %s » n'est pas DEFERRABLE"
-#: commands/trigger.c:4602
+#: commands/trigger.c:4598
#, c-format
msgid "constraint \"%s\" does not exist"
-msgstr "la contrainte � %s � n'existe pas"
+msgstr "la contrainte « %s » n'existe pas"
#: commands/tsearchcmds.c:115 commands/tsearchcmds.c:685
#, c-format
@@ -8902,67 +8925,67 @@ msgstr "la fonction %s doit renvoyer le type %s"
#: commands/tsearchcmds.c:192
#, c-format
msgid "must be superuser to create text search parsers"
-msgstr "doit �tre super-utilisateur pour cr�er des analyseurs de recherche plein texte"
+msgstr "doit être super-utilisateur pour créer des analyseurs de recherche plein texte"
#: commands/tsearchcmds.c:240
#, c-format
msgid "text search parser parameter \"%s\" not recognized"
-msgstr "param�tre de l'analyseur de recherche plein texte � %s � non reconnu"
+msgstr "paramètre de l'analyseur de recherche plein texte « %s » non reconnu"
#: commands/tsearchcmds.c:250
#, c-format
msgid "text search parser start method is required"
-msgstr "la m�thode start de l'analyseur de recherche plein texte est requise"
+msgstr "la méthode start de l'analyseur de recherche plein texte est requise"
#: commands/tsearchcmds.c:255
#, c-format
msgid "text search parser gettoken method is required"
-msgstr "la m�thode gettoken de l'analyseur de recherche plein texte est requise"
+msgstr "la méthode gettoken de l'analyseur de recherche plein texte est requise"
#: commands/tsearchcmds.c:260
#, c-format
msgid "text search parser end method is required"
-msgstr "la m�thode end l'analyseur de recherche de texte est requise"
+msgstr "la méthode end l'analyseur de recherche de texte est requise"
#: commands/tsearchcmds.c:265
#, c-format
msgid "text search parser lextypes method is required"
-msgstr "la m�thode lextypes de l'analyseur de recherche plein texte est requise"
+msgstr "la méthode lextypes de l'analyseur de recherche plein texte est requise"
#: commands/tsearchcmds.c:386
#, c-format
msgid "text search template \"%s\" does not accept options"
-msgstr "le mod�le de recherche plein texte � %s � n'accepte pas d'options"
+msgstr "le modèle de recherche plein texte « %s » n'accepte pas d'options"
#: commands/tsearchcmds.c:460
#, c-format
msgid "text search template is required"
-msgstr "le mod�le de la recherche plein texte est requis"
+msgstr "le modèle de la recherche plein texte est requis"
#: commands/tsearchcmds.c:752
#, c-format
msgid "must be superuser to create text search templates"
-msgstr "doit �tre super-utilisateur pour cr�er des mod�les de recherche plein texte"
+msgstr "doit être super-utilisateur pour créer des modèles de recherche plein texte"
#: commands/tsearchcmds.c:789
#, c-format
msgid "text search template parameter \"%s\" not recognized"
-msgstr "param�tre de mod�le de recherche plein texte � %s � non reconnu"
+msgstr "paramètre de modèle de recherche plein texte « %s » non reconnu"
#: commands/tsearchcmds.c:799
#, c-format
msgid "text search template lexize method is required"
-msgstr "la m�thode lexize du mod�le de recherche plein texte est requise"
+msgstr "la méthode lexize du modèle de recherche plein texte est requise"
#: commands/tsearchcmds.c:1008
#, c-format
msgid "text search configuration parameter \"%s\" not recognized"
-msgstr "param�tre de configuration de recherche plein texte � %s � non reconnu"
+msgstr "paramètre de configuration de recherche plein texte « %s » non reconnu"
#: commands/tsearchcmds.c:1015
#, c-format
msgid "cannot specify both PARSER and COPY options"
-msgstr "ne peut pas sp�cifier � la fois PARSER et COPY"
+msgstr "ne peut pas spécifier à la fois PARSER et COPY"
#: commands/tsearchcmds.c:1051
#, c-format
@@ -8972,88 +8995,86 @@ msgstr "l'analyseur de la recherche plein texte est requis"
#: commands/tsearchcmds.c:1278
#, c-format
msgid "token type \"%s\" does not exist"
-msgstr "le type de jeton � %s � n'existe pas"
+msgstr "le type de jeton « %s » n'existe pas"
#: commands/tsearchcmds.c:1502
#, c-format
msgid "mapping for token type \"%s\" does not exist"
-msgstr "la correspondance pour le type de jeton � %s � n'existe pas"
+msgstr "la correspondance pour le type de jeton « %s » n'existe pas"
#: commands/tsearchcmds.c:1508
#, c-format
msgid "mapping for token type \"%s\" does not exist, skipping"
msgstr ""
-"la correspondance pour le type de jeton � %s � n'existe pas, poursuite du\n"
+"la correspondance pour le type de jeton « %s » n'existe pas, poursuite du\n"
"traitement"
#: commands/tsearchcmds.c:1663 commands/tsearchcmds.c:1774
#, c-format
msgid "invalid parameter list format: \"%s\""
-msgstr "format de liste de param�tres invalide : � %s �"
+msgstr "format de liste de paramètres invalide : « %s »"
#: commands/typecmds.c:181
#, c-format
msgid "must be superuser to create a base type"
-msgstr "doit �tre super-utilisateur pour cr�er un type de base"
+msgstr "doit être super-utilisateur pour créer un type de base"
#: commands/typecmds.c:288 commands/typecmds.c:1421
#, c-format
msgid "type attribute \"%s\" not recognized"
-msgstr "attribut du type � %s � non reconnu"
+msgstr "attribut du type « %s » non reconnu"
#: commands/typecmds.c:342
#, c-format
msgid "invalid type category \"%s\": must be simple ASCII"
-msgstr "cat�gorie de type � %s � invalide : doit �tre de l'ASCII pur"
+msgstr "catégorie de type « %s » invalide : doit être de l'ASCII pur"
#: commands/typecmds.c:361
#, c-format
msgid "array element type cannot be %s"
-msgstr "le type d'�l�ment tableau ne peut pas �tre %s"
+msgstr "le type d'élément tableau ne peut pas être %s"
#: commands/typecmds.c:393
#, c-format
msgid "alignment \"%s\" not recognized"
-msgstr "alignement � %s � non reconnu"
+msgstr "alignement « %s » non reconnu"
#: commands/typecmds.c:410
#, c-format
msgid "storage \"%s\" not recognized"
-msgstr "stockage � %s � non reconnu"
+msgstr "stockage « %s » non reconnu"
#: commands/typecmds.c:421
#, c-format
msgid "type input function must be specified"
-msgstr "le type d'entr�e de la fonction doit �tre sp�cifi�"
+msgstr "le type d'entrée de la fonction doit être spécifié"
#: commands/typecmds.c:425
#, c-format
msgid "type output function must be specified"
-msgstr "le type de sortie de la fonction doit �tre sp�cifi�"
+msgstr "le type de sortie de la fonction doit être spécifié"
#: commands/typecmds.c:430
#, c-format
msgid "type modifier output function is useless without a type modifier input function"
msgstr ""
"la fonction en sortie du modificateur de type est inutile sans une fonction\n"
-"en entr�e du modificateur de type"
+"en entrée du modificateur de type"
#: commands/typecmds.c:453 commands/typecmds.c:470
-#, fuzzy, c-format
-#| msgid "changing return type of function %s from \"opaque\" to %s"
+#, c-format
msgid "changing return type of function %s from %s to %s"
-msgstr "changement du type de retour de la fonction %s d'� opaque � vers %s"
+msgstr "changement du type de retour de la fonction %s de %s vers %s"
#: commands/typecmds.c:460
#, c-format
msgid "type input function %s must return type %s"
-msgstr "le type d'entr�e de la fonction %s doit �tre %s"
+msgstr "le type d'entrée de la fonction %s doit être %s"
#: commands/typecmds.c:477
-#, fuzzy, c-format
-#| msgid "type input function %s must return type %s"
+#, c-format
msgid "type output function %s must return type %s"
-msgstr "le type d'entr�e de la fonction %s doit �tre %s"
+msgstr "le type de sortie de la fonction %s doit être %s"
#: commands/typecmds.c:486
#, c-format
@@ -9061,54 +9082,49 @@ msgid "type receive function %s must return type %s"
msgstr "la fonction receive du type %s doit renvoyer le type %s"
#: commands/typecmds.c:495
-#, fuzzy, c-format
-#| msgid "type input function %s must return type %s"
+#, c-format
msgid "type send function %s must return type %s"
-msgstr "le type d'entr�e de la fonction %s doit �tre %s"
+msgstr "le type de sortie de la fonction d'envoi %s doit être %s"
#: commands/typecmds.c:560
#, c-format
msgid "type input function %s should not be volatile"
-msgstr "la fonction en entr�e du type %s ne doit pas �tre volatile"
+msgstr "la fonction en entrée du type %s ne doit pas être volatile"
#: commands/typecmds.c:565
#, c-format
msgid "type output function %s should not be volatile"
-msgstr "la fonction en entr�e du type %s ne doit pas �tre volatile"
+msgstr "la fonction en entrée du type %s ne doit pas être volatile"
#: commands/typecmds.c:570
#, c-format
msgid "type receive function %s should not be volatile"
-msgstr "la fonction receive du type %s ne doit pas �tre volatile"
+msgstr "la fonction receive du type %s ne doit pas être volatile"
#: commands/typecmds.c:575
#, c-format
msgid "type send function %s should not be volatile"
-msgstr "la fonction send du type %s ne doit pas �tre volatile"
+msgstr "la fonction send du type %s ne doit pas être volatile"
#: commands/typecmds.c:580
-#, fuzzy, c-format
-#| msgid "cast function must not be volatile"
+#, c-format
msgid "type modifier input function %s should not be volatile"
-msgstr "la fonction de conversion ne doit pas �tre volatile"
+msgstr "la fonction en entrée du modificateur de type %s ne devrait pas être volatile"
#: commands/typecmds.c:585
-#, fuzzy, c-format
-#| msgid "type modifier output function is useless without a type modifier input function"
+#, c-format
msgid "type modifier output function %s should not be volatile"
-msgstr ""
-"la fonction en sortie du modificateur de type est inutile sans une fonction\n"
-"en entr�e du modificateur de type"
+msgstr "la fonction en sortie du modificateur de type %s ne devrait pas être volatile"
#: commands/typecmds.c:807
#, c-format
msgid "\"%s\" is not a valid base type for a domain"
-msgstr "� %s � n'est pas un type de base valide pour un domaine"
+msgstr "« %s » n'est pas un type de base valide pour un domaine"
#: commands/typecmds.c:893
#, c-format
msgid "multiple default expressions"
-msgstr "multiples expressions par d�faut"
+msgstr "multiples expressions par défaut"
#: commands/typecmds.c:955 commands/typecmds.c:964
#, c-format
@@ -9118,7 +9134,7 @@ msgstr "contraintes NULL/NOT NULL en conflit"
#: commands/typecmds.c:980
#, c-format
msgid "check constraints for domains cannot be marked NO INHERIT"
-msgstr "les contraintes CHECK pour les domaines ne peuvent pas �tre marqu�es NO INHERIT"
+msgstr "les contraintes CHECK pour les domaines ne peuvent pas être marquées NO INHERIT"
#: commands/typecmds.c:989 commands/typecmds.c:2522
#, c-format
@@ -9128,7 +9144,7 @@ msgstr "contraintes uniques impossible pour les domaines"
#: commands/typecmds.c:995 commands/typecmds.c:2528
#, c-format
msgid "primary key constraints not possible for domains"
-msgstr "contraintes de cl� primaire impossible pour les domaines"
+msgstr "contraintes de clé primaire impossible pour les domaines"
#: commands/typecmds.c:1001 commands/typecmds.c:2534
#, c-format
@@ -9138,14 +9154,14 @@ msgstr "contraintes d'exclusion impossible pour les domaines"
#: commands/typecmds.c:1007 commands/typecmds.c:2540
#, c-format
msgid "foreign key constraints not possible for domains"
-msgstr "contraintes de cl� �trang�re impossible pour les domaines"
+msgstr "contraintes de clé étrangère impossible pour les domaines"
#: commands/typecmds.c:1016 commands/typecmds.c:2549
#, c-format
msgid "specifying constraint deferrability not supported for domains"
-msgstr "sp�cifier des contraintes d�ferrantes n'est pas support� par les domaines"
+msgstr "spécifier des contraintes déferrantes n'est pas supporté par les domaines"
-#: commands/typecmds.c:1291 utils/cache/typcache.c:1634
+#: commands/typecmds.c:1291 utils/cache/typcache.c:1630
#, c-format
msgid "%s is not an enum"
msgstr "%s n'est pas un enum"
@@ -9158,47 +9174,44 @@ msgstr "l'attribut du sous-type est requis"
#: commands/typecmds.c:1434
#, c-format
msgid "range subtype cannot be %s"
-msgstr "le sous-type de l'intervalle ne peut pas �tre %s"
+msgstr "le sous-type de l'intervalle ne peut pas être %s"
#: commands/typecmds.c:1453
#, c-format
msgid "range collation specified but subtype does not support collation"
-msgstr "collationnement sp�cifi� pour l'intervalle mais le sous-type ne supporte pas les collationnements"
+msgstr "collationnement spécifié pour l'intervalle mais le sous-type ne supporte pas les collationnements"
#: commands/typecmds.c:1687
#, c-format
msgid "changing argument type of function %s from \"opaque\" to \"cstring\""
-msgstr "changement du type d'argument de la fonction %s d'� opaque � � � cstring �"
+msgstr "changement du type d'argument de la fonction %s d'« opaque » à « cstring »"
#: commands/typecmds.c:1738
#, c-format
msgid "changing argument type of function %s from \"opaque\" to %s"
-msgstr "changement du type d'argument de la fonction %s d'� opaque � � %s"
+msgstr "changement du type d'argument de la fonction %s d'« opaque » à %s"
#: commands/typecmds.c:1837
-#, fuzzy, c-format
-#| msgid "type input function %s must return type %s"
+#, c-format
msgid "typmod_in function %s must return type %s"
-msgstr "le type d'entr�e de la fonction %s doit �tre %s"
+msgstr "le type de sortie de la fonction typmod_in %s doit être %s"
#: commands/typecmds.c:1864
-#, fuzzy, c-format
-#| msgid "typmod_out function %s must return type \"cstring\""
+#, c-format
msgid "typmod_out function %s must return type %s"
-msgstr "la fonction typmod_out %s doit renvoyer le type � cstring �"
+msgstr "le type de sortie de la fonction typmod_out %s doit être %s"
#: commands/typecmds.c:1891
-#, fuzzy, c-format
-#| msgid "type analyze function %s must return type \"boolean\""
+#, c-format
msgid "type analyze function %s must return type %s"
-msgstr "la fonction analyze du type %s doit renvoyer le type � boolean �"
+msgstr "la fonction analyze du type %s doit renvoyer le type %s"
#: commands/typecmds.c:1937
#, c-format
msgid "You must specify an operator class for the range type or define a default operator class for the subtype."
msgstr ""
-"Vous devez sp�cifier une classe d'op�rateur pour le type range ou d�finir une\n"
-"classe d'op�rateur par d�faut pour le sous-type."
+"Vous devez spécifier une classe d'opérateur pour le type range ou définir une\n"
+"classe d'opérateur par défaut pour le sous-type."
#: commands/typecmds.c:1968
#, c-format
@@ -9208,54 +9221,52 @@ msgstr "la fonction canonical %s du range doit renvoyer le type range"
#: commands/typecmds.c:1974
#, c-format
msgid "range canonical function %s must be immutable"
-msgstr "la fonction canonical %s du range doit �tre immutable"
+msgstr "la fonction canonical %s du range doit être immutable"
#: commands/typecmds.c:2010
-#, fuzzy, c-format
-#| msgid "range subtype diff function %s must return type double precision"
+#, c-format
msgid "range subtype diff function %s must return type %s"
msgstr ""
-"la fonction %s de calcul de diff�rence pour le sous-type d'un intervalle de\n"
-"valeur doit renvoyer le type double precision"
+"la fonction %s de calcul de différence pour le sous-type d'un intervalle de\n"
+"valeur doit renvoyer le type %s"
#: commands/typecmds.c:2017
#, c-format
msgid "range subtype diff function %s must be immutable"
msgstr ""
-"la fonction %s de calcul de diff�rence pour le sous-type d'un intervalle de\n"
-"valeur doit �tre immutable"
+"la fonction %s de calcul de différence pour le sous-type d'un intervalle de\n"
+"valeur doit être immutable"
#: commands/typecmds.c:2044
-#, fuzzy, c-format
-#| msgid "must be superuser to connect in binary upgrade mode"
+#, c-format
msgid "pg_type array OID value not set when in binary upgrade mode"
-msgstr "doit �tre super-utilisateur pour se connecter en mode de mise � jour binaire"
+msgstr "les valeurs d'OID du tableau pgtype ne sont pas positionnées en mode de mise à jour binaire"
#: commands/typecmds.c:2348
#, c-format
msgid "column \"%s\" of table \"%s\" contains null values"
-msgstr "la colonne � %s � de la table � %s � contient des valeurs NULL"
+msgstr "la colonne « %s » de la table « %s » contient des valeurs NULL"
#: commands/typecmds.c:2463 commands/typecmds.c:2646
#, c-format
msgid "constraint \"%s\" of domain \"%s\" does not exist"
-msgstr "la contrainte � %s � du domaine � %s � n'existe pas"
+msgstr "la contrainte « %s » du domaine « %s » n'existe pas"
#: commands/typecmds.c:2467
#, c-format
msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping"
-msgstr "la contrainte � %s � du domaine � %s � n'existe pas, ignore"
+msgstr "la contrainte « %s » du domaine « %s » n'existe pas, ignore"
#: commands/typecmds.c:2652
#, c-format
msgid "constraint \"%s\" of domain \"%s\" is not a check constraint"
-msgstr "la contrainte � %s � du domaine � %s � n'est pas une contrainte de v�rification"
+msgstr "la contrainte « %s » du domaine « %s » n'est pas une contrainte de vérification"
#: commands/typecmds.c:2758
#, c-format
msgid "column \"%s\" of table \"%s\" contains values that violate the new constraint"
msgstr ""
-"la colonne � %s � de la table � %s � contient des valeurs violant la\n"
+"la colonne « %s » de la table « %s » contient des valeurs violant la\n"
"nouvelle contrainte"
#: commands/typecmds.c:2971 commands/typecmds.c:3228 commands/typecmds.c:3417
@@ -9266,24 +9277,24 @@ msgstr "%s n'est pas un domaine"
#: commands/typecmds.c:3005
#, c-format
msgid "constraint \"%s\" for domain \"%s\" already exists"
-msgstr "la contrainte � %s � du domaine � %s � existe d�j�"
+msgstr "la contrainte « %s » du domaine « %s » existe déjà"
#: commands/typecmds.c:3055
#, c-format
msgid "cannot use table references in domain check constraint"
msgstr ""
-"ne peut pas utiliser les r�f�rences de table dans la contrainte de\n"
-"v�rification du domaine"
+"ne peut pas utiliser les références de table dans la contrainte de\n"
+"vérification du domaine"
#: commands/typecmds.c:3158 commands/typecmds.c:3240 commands/typecmds.c:3534
#, c-format
msgid "%s is a table's row type"
-msgstr "� %s � est du type ligne de table"
+msgstr "« %s » est du type ligne de table"
#: commands/typecmds.c:3160 commands/typecmds.c:3242 commands/typecmds.c:3536
#, c-format
msgid "Use ALTER TABLE instead."
-msgstr "Utilisez ALTER TABLE � la place."
+msgstr "Utilisez ALTER TABLE à la place."
#: commands/typecmds.c:3167 commands/typecmds.c:3249 commands/typecmds.c:3449
#, c-format
@@ -9298,937 +9309,938 @@ msgstr "Vous pouvez modifier le type %s, ce qui va modifier aussi le type tablea
#: commands/typecmds.c:3519
#, c-format
msgid "type \"%s\" already exists in schema \"%s\""
-msgstr "le type � %s � existe d�j� dans le sch�ma � %s �"
+msgstr "le type « %s » existe déjà dans le schéma « %s »"
#: commands/user.c:149
#, c-format
msgid "SYSID can no longer be specified"
-msgstr "SYSID ne peut plus �tre sp�cifi�"
+msgstr "SYSID ne peut plus être spécifié"
#: commands/user.c:291
#, c-format
msgid "must be superuser to create superusers"
-msgstr "doit �tre super-utilisateur pour cr�er des super-utilisateurs"
+msgstr "doit être super-utilisateur pour créer des super-utilisateurs"
#: commands/user.c:298
#, c-format
msgid "must be superuser to create replication users"
-msgstr "doit �tre super-utilisateur pour cr�er des utilisateurs avec l'attribut r�plication"
+msgstr "doit être super-utilisateur pour créer des utilisateurs avec l'attribut réplication"
#: commands/user.c:305 commands/user.c:693
#, c-format
msgid "must be superuser to change bypassrls attribute"
-msgstr "doit �tre super-utilisateur pour modifier l'attribut bypassrls"
+msgstr "doit être super-utilisateur pour modifier l'attribut bypassrls"
#: commands/user.c:312
#, c-format
msgid "permission denied to create role"
-msgstr "droit refus� pour cr�er un r�le"
+msgstr "droit refusé pour créer un rôle"
-#: commands/user.c:322 commands/user.c:1176 commands/user.c:1183 gram.y:13599 gram.y:13634
+#: commands/user.c:322 commands/user.c:1176 commands/user.c:1183 gram.y:13615 gram.y:13650 utils/adt/acl.c:5279 utils/adt/acl.c:5285
#, c-format
msgid "role name \"%s\" is reserved"
-msgstr "le nom du r�le � %s � est r�serv�"
+msgstr "le nom du rôle « %s » est réservé"
#: commands/user.c:324 commands/user.c:1178 commands/user.c:1185
-#, fuzzy, c-format
-#| msgid "%s: role name starting with \"pg_\" skipped (%s)\n"
+#, c-format
msgid "Role names starting with \"pg_\" are reserved."
-msgstr "%s : nom de r�le commen�ant par � pg_ � ignor� (� %s �)\n"
+msgstr "Les noms de rôle commençant par « pg_ » sont réservés."
#: commands/user.c:336 commands/user.c:1191
#, c-format
msgid "role \"%s\" already exists"
-msgstr "le r�le � %s � existe d�j�"
+msgstr "le rôle « %s » existe déjà"
#: commands/user.c:414
-#, fuzzy, c-format
-#| msgid "must be superuser to connect in binary upgrade mode"
+#, c-format
msgid "pg_authid OID value not set when in binary upgrade mode"
-msgstr "doit �tre super-utilisateur pour se connecter en mode de mise � jour binaire"
+msgstr "la valeur d'OID de pg_authid n'est pas positionnée en mode de mise à jour binaire"
#: commands/user.c:679 commands/user.c:896 commands/user.c:1432 commands/user.c:1578
#, c-format
msgid "must be superuser to alter superusers"
-msgstr "doit �tre super-utilisateur pour modifier des super-utilisateurs"
+msgstr "doit être super-utilisateur pour modifier des super-utilisateurs"
#: commands/user.c:686
#, c-format
msgid "must be superuser to alter replication users"
-msgstr "doit �tre super-utilisateur pour modifier des utilisateurs ayant l'attribut r�plication"
+msgstr "doit être super-utilisateur pour modifier des utilisateurs ayant l'attribut réplication"
#: commands/user.c:709 commands/user.c:904
#, c-format
msgid "permission denied"
-msgstr "droit refus�"
+msgstr "droit refusé"
#: commands/user.c:934
#, c-format
msgid "must be superuser to alter settings globally"
-msgstr "doit �tre super-utilisateur pour modifier globalement les configurations"
+msgstr "doit être super-utilisateur pour modifier globalement les configurations"
#: commands/user.c:956
#, c-format
msgid "permission denied to drop role"
-msgstr "droit refus� pour supprimer le r�le"
+msgstr "droit refusé pour supprimer le rôle"
#: commands/user.c:980
#, c-format
msgid "cannot use special role specifier in DROP ROLE"
-msgstr "ne peut pas �tre le sp�cificateur de r�le sp�cial dans DROP ROLE"
+msgstr "ne peut pas être le spécificateur de rôle spécial dans DROP ROLE"
-#: commands/user.c:990 commands/user.c:1147 commands/variable.c:801 commands/variable.c:873 utils/adt/acl.c:5121 utils/adt/acl.c:5173 utils/adt/acl.c:5206 utils/adt/acl.c:5224 utils/init/miscinit.c:502
+#: commands/user.c:990 commands/user.c:1147 commands/variable.c:825 commands/variable.c:897 utils/adt/acl.c:5121 utils/adt/acl.c:5173 utils/adt/acl.c:5206 utils/adt/acl.c:5224 utils/init/miscinit.c:502
#, c-format
msgid "role \"%s\" does not exist"
-msgstr "le r�le � %s � n'existe pas"
+msgstr "le rôle « %s » n'existe pas"
#: commands/user.c:995
#, c-format
msgid "role \"%s\" does not exist, skipping"
-msgstr "le r�le � %s � n'existe pas, poursuite du traitement"
+msgstr "le rôle « %s » n'existe pas, poursuite du traitement"
#: commands/user.c:1007 commands/user.c:1011
#, c-format
msgid "current user cannot be dropped"
-msgstr "l'utilisateur actuel ne peut pas �tre supprim�"
+msgstr "l'utilisateur actuel ne peut pas être supprimé"
#: commands/user.c:1015
#, c-format
msgid "session user cannot be dropped"
-msgstr "l'utilisateur de la session ne peut pas �tre supprim�"
+msgstr "l'utilisateur de la session ne peut pas être supprimé"
#: commands/user.c:1026
#, c-format
msgid "must be superuser to drop superusers"
-msgstr "doit �tre super-utilisateur pour supprimer des super-utilisateurs"
+msgstr "doit être super-utilisateur pour supprimer des super-utilisateurs"
#: commands/user.c:1042
#, c-format
msgid "role \"%s\" cannot be dropped because some objects depend on it"
-msgstr "le r�le � %s � ne peut pas �tre supprim� car d'autres objets en d�pendent"
+msgstr "le rôle « %s » ne peut pas être supprimé car d'autres objets en dépendent"
#: commands/user.c:1163
#, c-format
msgid "session user cannot be renamed"
-msgstr "l'utilisateur de la session ne peut pas �tre renomm�"
+msgstr "l'utilisateur de la session ne peut pas être renommé"
#: commands/user.c:1167
#, c-format
msgid "current user cannot be renamed"
-msgstr "l'utilisateur courant ne peut pas �tre renomm�"
+msgstr "l'utilisateur courant ne peut pas être renommé"
#: commands/user.c:1201
#, c-format
msgid "must be superuser to rename superusers"
-msgstr "doit �tre super-utilisateur pour renommer les super-utilisateurs"
+msgstr "doit être super-utilisateur pour renommer les super-utilisateurs"
#: commands/user.c:1208
#, c-format
msgid "permission denied to rename role"
-msgstr "droit refus� pour renommer le r�le"
+msgstr "droit refusé pour renommer le rôle"
#: commands/user.c:1229
#, c-format
msgid "MD5 password cleared because of role rename"
-msgstr "mot de passe MD5 effac� � cause du renommage du r�le"
+msgstr "mot de passe MD5 effacé à cause du renommage du rôle"
#: commands/user.c:1291
#, c-format
msgid "column names cannot be included in GRANT/REVOKE ROLE"
-msgstr "les noms de colonne ne peuvent pas �tre inclus dans GRANT/REVOKE ROLE"
+msgstr "les noms de colonne ne peuvent pas être inclus dans GRANT/REVOKE ROLE"
#: commands/user.c:1329
#, c-format
msgid "permission denied to drop objects"
-msgstr "droit refus� pour supprimer les objets"
+msgstr "droit refusé pour supprimer les objets"
#: commands/user.c:1356 commands/user.c:1365
#, c-format
msgid "permission denied to reassign objects"
-msgstr "droit refus� pour r�-affecter les objets"
+msgstr "droit refusé pour ré-affecter les objets"
#: commands/user.c:1440 commands/user.c:1586
#, c-format
msgid "must have admin option on role \"%s\""
-msgstr "doit avoir l'option admin sur le r�le � %s �"
+msgstr "doit avoir l'option admin sur le rôle « %s »"
#: commands/user.c:1457
#, c-format
msgid "must be superuser to set grantor"
-msgstr "doit �tre super-utilisateur pour configurer le � donneur de droits �"
+msgstr "doit être super-utilisateur pour configurer le « donneur de droits »"
#: commands/user.c:1482
#, c-format
msgid "role \"%s\" is a member of role \"%s\""
-msgstr "le r�le � %s � est un membre du r�le � %s �"
+msgstr "le rôle « %s » est un membre du rôle « %s »"
#: commands/user.c:1497
#, c-format
msgid "role \"%s\" is already a member of role \"%s\""
-msgstr "le r�le � %s � est d�j� un membre du r�le � %s �"
+msgstr "le rôle « %s » est déjà un membre du rôle « %s »"
#: commands/user.c:1608
#, c-format
msgid "role \"%s\" is not a member of role \"%s\""
-msgstr "le r�le � %s � n'est pas un membre du r�le � %s �"
+msgstr "le rôle « %s » n'est pas un membre du rôle « %s »"
#: commands/vacuum.c:185
-#, fuzzy, c-format
-#| msgid "%s: cannot be executed by \"root\"\n"
+#, c-format
msgid "%s cannot be executed from VACUUM or ANALYZE"
-msgstr "%s : ne peut pas �tre ex�cut� par � root �\n"
+msgstr "%s ne peut pas être exécuté dans un VACUUM ou un ANALYZE"
+
+#: commands/vacuum.c:195
+#, c-format
+msgid "VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL"
+msgstr ""
+"l'option DISABLE_PAGE_SKIPPING de la commande VACUUM ne pas pas être utilisée\n"
+"en même temps que l'option FULL"
-#: commands/vacuum.c:528
+#: commands/vacuum.c:535
#, c-format
msgid "oldest xmin is far in the past"
-msgstr "le plus ancien xmin est loin dans le pass�"
+msgstr "le plus ancien xmin est loin dans le passé"
-#: commands/vacuum.c:529
+#: commands/vacuum.c:536
#, c-format
msgid "Close open transactions soon to avoid wraparound problems."
msgstr ""
-"Fermez les transactions ouvertes rapidement pour �viter des probl�mes de\n"
-"r�initialisation."
+"Fermez les transactions ouvertes rapidement pour éviter des problèmes de\n"
+"réinitialisation."
-#: commands/vacuum.c:568
+#: commands/vacuum.c:575
#, c-format
msgid "oldest multixact is far in the past"
-msgstr "le plus ancien multixact est loin dans le pass�"
+msgstr "le plus ancien multixact est loin dans le passé"
-#: commands/vacuum.c:569
+#: commands/vacuum.c:576
#, c-format
msgid "Close open transactions with multixacts soon to avoid wraparound problems."
msgstr ""
-"Fermez les transactions ouvertes avec multixacts rapidement pour �viter des probl�mes de\n"
-"r�initialisation."
+"Fermez les transactions ouvertes avec multixacts rapidement pour éviter des problèmes de\n"
+"réinitialisation."
-#: commands/vacuum.c:1131
+#: commands/vacuum.c:1146
#, c-format
msgid "some databases have not been vacuumed in over 2 billion transactions"
msgstr ""
-"certaines bases de donn�es n'ont pas eu droit � l'op�ration de maintenance\n"
+"certaines bases de données n'ont pas eu droit à l'opération de maintenance\n"
"VACUUM depuis plus de 2 milliards de transactions"
-#: commands/vacuum.c:1132
+#: commands/vacuum.c:1147
#, c-format
msgid "You might have already suffered transaction-wraparound data loss."
msgstr ""
-"Vous pouvez avoir d�j� souffert de pertes de donn�es suite � une\n"
-"r�initialisation de l'identifiant des transactions."
+"Vous pouvez avoir déjà souffert de pertes de données suite à une\n"
+"réinitialisation de l'identifiant des transactions."
-#: commands/vacuum.c:1253
+#: commands/vacuum.c:1268
#, c-format
msgid "skipping vacuum of \"%s\" --- lock not available"
-msgstr "ignore le vacuum de � %s � --- verrou non disponible"
+msgstr "ignore le vacuum de « %s » --- verrou non disponible"
-#: commands/vacuum.c:1279
+#: commands/vacuum.c:1294
#, c-format
msgid "skipping \"%s\" --- only superuser can vacuum it"
-msgstr "ignore � %s � --- seul le super-utilisateur peut ex�cuter un VACUUM"
+msgstr "ignore « %s » --- seul le super-utilisateur peut exécuter un VACUUM"
-#: commands/vacuum.c:1283
+#: commands/vacuum.c:1298
#, c-format
msgid "skipping \"%s\" --- only superuser or database owner can vacuum it"
msgstr ""
-"ignore � %s � --- seul le super-utilisateur ou le propri�taire de la base de donn�es\n"
-"peuvent ex�cuter un VACUUM"
+"ignore « %s » --- seul le super-utilisateur ou le propriétaire de la base de données\n"
+"peuvent exécuter un VACUUM"
-#: commands/vacuum.c:1287
+#: commands/vacuum.c:1302
#, c-format
msgid "skipping \"%s\" --- only table or database owner can vacuum it"
msgstr ""
-"ignore � %s � --- seul le propri�taire de la table ou de la base de donn�es\n"
-"peut ex�cuter un VACUUM"
+"ignore « %s » --- seul le propriétaire de la table ou de la base de données\n"
+"peut exécuter un VACUUM"
-#: commands/vacuum.c:1305
+#: commands/vacuum.c:1320
#, c-format
msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables"
msgstr ""
-"ignore � %s � --- n'a pas pu ex�cuter un VACUUM sur les objets autres que\n"
-"des tables et les tables syst�mes"
+"ignore « %s » --- n'a pas pu exécuter un VACUUM sur les objets autres que\n"
+"des tables et les tables systèmes"
-#: commands/vacuumlazy.c:363
+#: commands/vacuumlazy.c:366
#, c-format
msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"
-msgstr "VACUUM automatique de la table � %s.%s.%s � : %d parcours d'index\n"
+msgstr "VACUUM automatique de la table « %s.%s.%s » : %d parcours d'index\n"
-#: commands/vacuumlazy.c:368
-#, fuzzy, c-format
-#| msgid "pages: %u removed, %u remain, %u skipped due to pins\n"
+#: commands/vacuumlazy.c:371
+#, c-format
msgid "pages: %u removed, %u remain, %u skipped due to pins, %u skipped frozen\n"
-msgstr "pages : %u supprim�es, %u restants, %u ignor�es � cause de verrous\n"
+msgstr "pages : %u supprimées, %u restants, %u ignorées à cause de verrous; %u ignorées car gelées\n"
-#: commands/vacuumlazy.c:374
+#: commands/vacuumlazy.c:377
#, c-format
msgid "tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"
-msgstr "lignes : %.0f supprim�es, %.0f restantes, %.0f sont mortes mais pas encore supprimables\n"
+msgstr "lignes : %.0f supprimées, %.0f restantes, %.0f sont mortes mais pas encore supprimables\n"
-#: commands/vacuumlazy.c:379
+#: commands/vacuumlazy.c:382
#, c-format
msgid "buffer usage: %d hits, %d misses, %d dirtied\n"
-msgstr "utilisation du tampon : %d r�cup�r�es, %d rat�es, %d modifi�es\n"
+msgstr "utilisation du tampon : %d récupérées, %d ratées, %d modifiées\n"
-#: commands/vacuumlazy.c:383
+#: commands/vacuumlazy.c:386
#, c-format
msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"
-msgstr "taux moyen de lecture : %.3f Mo/s, taux moyen d'�criture : %.3f Mo/s\n"
+msgstr "taux moyen de lecture : %.3f Mo/s, taux moyen d'écriture : %.3f Mo/s\n"
-#: commands/vacuumlazy.c:385
+#: commands/vacuumlazy.c:388
#, c-format
msgid "system usage: %s"
-msgstr "utilisation du syst�me : %s"
+msgstr "utilisation du système : %s"
-#: commands/vacuumlazy.c:837
+#: commands/vacuumlazy.c:846
#, c-format
msgid "relation \"%s\" page %u is uninitialized --- fixing"
-msgstr "relation � %s � : la page %u n'est pas initialis�e --- correction en cours"
+msgstr "relation « %s » : la page %u n'est pas initialisée --- correction en cours"
-#: commands/vacuumlazy.c:1301
+#: commands/vacuumlazy.c:1316
#, c-format
msgid "\"%s\": removed %.0f row versions in %u pages"
-msgstr "� %s � : %.0f versions de ligne supprim�es parmi %u pages"
+msgstr "« %s » : %.0f versions de ligne supprimées parmi %u pages"
-#: commands/vacuumlazy.c:1311
+#: commands/vacuumlazy.c:1326
#, c-format
msgid "%.0f dead row versions cannot be removed yet.\n"
-msgstr "%.0f versions de lignes mortes ne peuvent pas encore �tre supprim�es.\n"
+msgstr "%.0f versions de lignes mortes ne peuvent pas encore être supprimées.\n"
-#: commands/vacuumlazy.c:1313
+#: commands/vacuumlazy.c:1328
#, c-format
msgid "There were %.0f unused item pointers.\n"
-msgstr "Il y avait %.0f pointeurs d'�l�ments inutilis�s.\n"
+msgstr "Il y avait %.0f pointeurs d'éléments inutilisés.\n"
-#: commands/vacuumlazy.c:1315
+#: commands/vacuumlazy.c:1330
#, c-format
msgid "Skipped %u page due to buffer pins.\n"
msgid_plural "Skipped %u pages due to buffer pins.\n"
-msgstr[0] "Ignore %u page � cause des verrous de blocs.\n"
-msgstr[1] "Ignore %u pages � cause des verrous de blocs.\n"
+msgstr[0] "Ignore %u page à cause des verrous de blocs.\n"
+msgstr[1] "Ignore %u pages à cause des verrous de blocs.\n"
-#: commands/vacuumlazy.c:1319
+#: commands/vacuumlazy.c:1334
#, c-format
msgid "%u page is entirely empty.\n"
msgid_plural "%u pages are entirely empty.\n"
-msgstr[0] "%u page est enti�rement vide.\n"
-msgstr[1] "%u pages sont enti�rement vides.\n"
+msgstr[0] "%u page est entièrement vide.\n"
+msgstr[1] "%u pages sont entièrement vides.\n"
-#: commands/vacuumlazy.c:1327
+#: commands/vacuumlazy.c:1342
#, c-format
msgid "\"%s\": found %.0f removable, %.0f nonremovable row versions in %u out of %u pages"
msgstr ""
-"� %s � : %.0f versions de ligne supprimables, %.0f non supprimables\n"
+"« %s » : %.0f versions de ligne supprimables, %.0f non supprimables\n"
"parmi %u pages sur %u"
-#: commands/vacuumlazy.c:1396
+#: commands/vacuumlazy.c:1411
#, c-format
msgid "\"%s\": removed %d row versions in %d pages"
-msgstr "� %s �: %d versions de ligne supprim�e parmi %d pages"
+msgstr "« %s »: %d versions de ligne supprimée parmi %d pages"
-#: commands/vacuumlazy.c:1585
+#: commands/vacuumlazy.c:1600
#, c-format
msgid "scanned index \"%s\" to remove %d row versions"
-msgstr "a parcouru l'index � %s � pour supprimer %d versions de lignes"
+msgstr "a parcouru l'index « %s » pour supprimer %d versions de lignes"
-#: commands/vacuumlazy.c:1631
+#: commands/vacuumlazy.c:1646
#, c-format
msgid "index \"%s\" now contains %.0f row versions in %u pages"
-msgstr "l'index � %s � contient maintenant %.0f versions de ligne dans %u pages"
+msgstr "l'index « %s » contient maintenant %.0f versions de ligne dans %u pages"
-#: commands/vacuumlazy.c:1635
+#: commands/vacuumlazy.c:1650
#, c-format
msgid ""
"%.0f index row versions were removed.\n"
"%u index pages have been deleted, %u are currently reusable.\n"
"%s."
msgstr ""
-"%.0f versions de ligne d'index ont �t� supprim�es.\n"
-"%u pages d'index ont �t� supprim�es, %u sont actuellement r�utilisables.\n"
+"%.0f versions de ligne d'index ont été supprimées.\n"
+"%u pages d'index ont été supprimées, %u sont actuellement réutilisables.\n"
"%s."
-#: commands/vacuumlazy.c:1721
+#: commands/vacuumlazy.c:1745
#, c-format
msgid "\"%s\": stopping truncate due to conflicting lock request"
-msgstr "� %s � : mis en suspens du tronquage � cause d'un conflit dans la demande de verrou"
+msgstr "« %s » : mis en suspens du tronquage à cause d'un conflit dans la demande de verrou"
-#: commands/vacuumlazy.c:1786
+#: commands/vacuumlazy.c:1810
#, c-format
msgid "\"%s\": truncated %u to %u pages"
-msgstr "� %s � : %u pages tronqu�s en %u"
+msgstr "« %s » : %u pages tronqués en %u"
-#: commands/vacuumlazy.c:1842
+#: commands/vacuumlazy.c:1866
#, c-format
msgid "\"%s\": suspending truncate due to conflicting lock request"
-msgstr "� %s � : mis en suspens du tronquage � cause d'un conflit dans la demande de verrou"
+msgstr "« %s » : mis en suspens du tronquage à cause d'un conflit dans la demande de verrou"
-#: commands/variable.c:164 utils/misc/guc.c:9877
+#: commands/variable.c:164 utils/misc/guc.c:9899
#, c-format
msgid "Unrecognized key word: \"%s\"."
-msgstr "Mot cl� non reconnu : � %s �"
+msgstr "Mot clé non reconnu : « %s »"
#: commands/variable.c:176
#, c-format
msgid "Conflicting \"datestyle\" specifications."
-msgstr "Sp�cifications � datestyle � conflictuelles"
+msgstr "Spécifications « datestyle » conflictuelles"
#: commands/variable.c:298
#, c-format
msgid "Cannot specify months in time zone interval."
-msgstr "Ne peut pas sp�cifier des mois dans un interval avec fuseau horaire."
+msgstr "Ne peut pas spécifier des mois dans un interval avec fuseau horaire."
#: commands/variable.c:304
#, c-format
msgid "Cannot specify days in time zone interval."
-msgstr "Ne peut pas sp�cifier des jours dans un interval avec fuseau horaire."
+msgstr "Ne peut pas spécifier des jours dans un interval avec fuseau horaire."
#: commands/variable.c:346 commands/variable.c:428
#, c-format
msgid "time zone \"%s\" appears to use leap seconds"
-msgstr "le fuseau horaire � %s � semble utiliser les secondes � leap �"
+msgstr "le fuseau horaire « %s » semble utiliser les secondes « leap »"
#: commands/variable.c:348 commands/variable.c:430
#, c-format
msgid "PostgreSQL does not support leap seconds."
-msgstr "PostgreSQL ne supporte pas les secondes � leap �."
+msgstr "PostgreSQL ne supporte pas les secondes « leap »."
#: commands/variable.c:357
#, c-format
msgid "UTC timezone offset is out of range."
-msgstr "le d�calage du fuseau horaire UTC est en dehors des limites."
+msgstr "le décalage du fuseau horaire UTC est en dehors des limites."
#: commands/variable.c:497
#, c-format
msgid "cannot set transaction read-write mode inside a read-only transaction"
msgstr ""
-"ne peut pas initialiser le mode lecture-�criture de la transaction �\n"
-"l'int�rieur d'une transaction en lecture seule"
+"ne peut pas initialiser le mode lecture-écriture de la transaction à\n"
+"l'intérieur d'une transaction en lecture seule"
#: commands/variable.c:504
#, c-format
msgid "transaction read-write mode must be set before any query"
msgstr ""
-"le mode de transaction lecture/�criture doit �tre configur� avant d'ex�cuter\n"
-"la premi�re requ�te"
+"le mode de transaction lecture/écriture doit être configuré avant d'exécuter\n"
+"la première requête"
#: commands/variable.c:511
#, c-format
msgid "cannot set transaction read-write mode during recovery"
msgstr ""
-"ne peut pas initialiser le mode lecture-�criture des transactions lors de la\n"
+"ne peut pas initialiser le mode lecture-écriture des transactions lors de la\n"
"restauration"
#: commands/variable.c:560
#, c-format
msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query"
-msgstr "SET TRANSACTION ISOLATION LEVEL doit �tre appel� avant toute requ�te"
+msgstr "SET TRANSACTION ISOLATION LEVEL doit être appelé avant toute requête"
#: commands/variable.c:567
#, c-format
msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction"
msgstr ""
-"SET TRANSACTION ISOLATION LEVEL ne doit pas �tre appel� dans une\n"
+"SET TRANSACTION ISOLATION LEVEL ne doit pas être appelé dans une\n"
"sous-transaction"
#: commands/variable.c:574 storage/lmgr/predicate.c:1587
#, c-format
msgid "cannot use serializable mode in a hot standby"
-msgstr "ne peut pas utiliser le mode s�rialisable sur un serveur en � Hot Standby �"
+msgstr "ne peut pas utiliser le mode sérialisable sur un serveur en « Hot Standby »"
#: commands/variable.c:575
#, c-format
msgid "You can use REPEATABLE READ instead."
-msgstr "Vous pouvez utiliser REPEATABLE READ � la place."
+msgstr "Vous pouvez utiliser REPEATABLE READ à la place."
#: commands/variable.c:623
#, c-format
msgid "SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction"
msgstr ""
-"SET TRANSACTION [NOT] DEFERRABLE ne doit pas �tre appel� dans une\n"
+"SET TRANSACTION [NOT] DEFERRABLE ne doit pas être appelé dans une\n"
"sous-transaction"
#: commands/variable.c:629
#, c-format
msgid "SET TRANSACTION [NOT] DEFERRABLE must be called before any query"
-msgstr "SET TRANSACTION [NOT] DEFERRABLE doit �tre appel� avant toute requ�te"
+msgstr "SET TRANSACTION [NOT] DEFERRABLE doit être appelé avant toute requête"
#: commands/variable.c:711
#, c-format
msgid "Conversion between %s and %s is not supported."
-msgstr "La conversion entre %s et %s n'est pas support�e."
+msgstr "La conversion entre %s et %s n'est pas supportée."
#: commands/variable.c:718
#, c-format
msgid "Cannot change \"client_encoding\" now."
-msgstr "Ne peut pas modifier � client_encoding � maintenant."
+msgstr "Ne peut pas modifier « client_encoding » maintenant."
+
+#: commands/variable.c:779
+#, c-format
+msgid "cannot change client_encoding in a parallel worker"
+msgstr "Ne peut pas modifier le client_encoding dans un processus parallèle"
-#: commands/variable.c:891
+#: commands/variable.c:915
#, c-format
msgid "permission denied to set role \"%s\""
-msgstr "droit refus� pour configurer le r�le � %s �"
+msgstr "droit refusé pour configurer le rôle « %s »"
#: commands/view.c:54
#, c-format
msgid "invalid value for \"check_option\" option"
-msgstr "valeur invalide pour l'option � check_option �"
+msgstr "valeur invalide pour l'option « check_option »"
#: commands/view.c:55
#, c-format
msgid "Valid values are \"local\" and \"cascaded\"."
-msgstr "Les valeurs valides sont entre � local � et � cascaded �."
+msgstr "Les valeurs valides sont entre « local » et « cascaded »."
-#: commands/view.c:114
+#: commands/view.c:101
#, c-format
msgid "could not determine which collation to use for view column \"%s\""
msgstr ""
-"n'a pas pu d�terminer le collationnement � utiliser pour la colonne � %s �\n"
+"n'a pas pu déterminer le collationnement à utiliser pour la colonne « %s »\n"
"de la vue"
-#: commands/view.c:129
+#: commands/view.c:115
#, c-format
msgid "view must have at least one column"
msgstr "la vue doit avoir au moins une colonne"
-#: commands/view.c:263 commands/view.c:275
+#: commands/view.c:280 commands/view.c:292
#, c-format
msgid "cannot drop columns from view"
msgstr "ne peut pas supprimer les colonnes d'une vue"
-#: commands/view.c:280
+#: commands/view.c:297
#, c-format
msgid "cannot change name of view column \"%s\" to \"%s\""
-msgstr "ne peut pas modifier le nom de la colonne � %s � de la vue en � %s �"
+msgstr "ne peut pas modifier le nom de la colonne « %s » de la vue en « %s »"
-#: commands/view.c:288
+#: commands/view.c:305
#, c-format
msgid "cannot change data type of view column \"%s\" from %s to %s"
-msgstr "ne peut pas modifier le type de donn�es de la colonne � %s � de la vue de %s � %s"
+msgstr "ne peut pas modifier le type de données de la colonne « %s » de la vue de %s à %s"
-#: commands/view.c:427
+#: commands/view.c:444
#, c-format
msgid "views must not contain SELECT INTO"
msgstr "les vues ne peuvent pas contenir SELECT INTO"
-#: commands/view.c:440
+#: commands/view.c:457
#, c-format
msgid "views must not contain data-modifying statements in WITH"
-msgstr "les vues ne peuvent pas contenir d'instructions de modifications de donn�es avec WITH"
+msgstr "les vues ne peuvent pas contenir d'instructions de modifications de données avec WITH"
-#: commands/view.c:511
+#: commands/view.c:528
#, c-format
msgid "CREATE VIEW specifies more column names than columns"
-msgstr "CREATE VIEW sp�cifie plus de noms de colonnes que de colonnes"
+msgstr "CREATE VIEW spécifie plus de noms de colonnes que de colonnes"
-#: commands/view.c:519
+#: commands/view.c:536
#, c-format
msgid "views cannot be unlogged because they do not have storage"
-msgstr "les vues ne peuvent pas �tre non trac�es car elles n'ont pas de stockage"
+msgstr "les vues ne peuvent pas être non tracées car elles n'ont pas de stockage"
-#: commands/view.c:533
+#: commands/view.c:550
#, c-format
msgid "view \"%s\" will be a temporary view"
-msgstr "la vue � %s � sera une vue temporaire"
+msgstr "la vue « %s » sera une vue temporaire"
#: executor/execCurrent.c:76
#, c-format
msgid "cursor \"%s\" is not a SELECT query"
-msgstr "le curseur � %s � n'est pas une requ�te SELECT"
+msgstr "le curseur « %s » n'est pas une requête SELECT"
#: executor/execCurrent.c:82
#, c-format
msgid "cursor \"%s\" is held from a previous transaction"
-msgstr "le curseur � %s � est d�tenu par une transaction pr�c�dente"
+msgstr "le curseur « %s » est détenu par une transaction précédente"
#: executor/execCurrent.c:114
#, c-format
msgid "cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\""
-msgstr "le curseur � %s � a plusieurs r�f�rences FOR UPDATE/SHARE pour la table � %s �"
+msgstr "le curseur « %s » a plusieurs références FOR UPDATE/SHARE pour la table « %s »"
#: executor/execCurrent.c:123
#, c-format
msgid "cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\""
-msgstr "le curseur � %s � n'a pas de r�f�rence FOR UPDATE/SHARE pour la table � %s �"
+msgstr "le curseur « %s » n'a pas de référence FOR UPDATE/SHARE pour la table « %s »"
#: executor/execCurrent.c:133 executor/execCurrent.c:179
#, c-format
msgid "cursor \"%s\" is not positioned on a row"
-msgstr "le curseur � %s � n'est pas positionn� sur une ligne"
+msgstr "le curseur « %s » n'est pas positionné sur une ligne"
#: executor/execCurrent.c:166
#, c-format
msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\""
-msgstr "le curseur � %s � n'est pas un parcours modifiable de la table � %s �"
+msgstr "le curseur « %s » n'est pas un parcours modifiable de la table « %s »"
#: executor/execCurrent.c:231 executor/execQual.c:1178
#, c-format
msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)"
-msgstr "le type de param�tre %d (%s) ne correspond pas � ce qui est pr�par� dans le plan (%s)"
+msgstr "le type de paramètre %d (%s) ne correspond pas à ce qui est préparé dans le plan (%s)"
#: executor/execCurrent.c:243 executor/execQual.c:1190
#, c-format
msgid "no value found for parameter %d"
-msgstr "aucune valeur trouv�e pour le param�tre %d"
+msgstr "aucune valeur trouvée pour le paramètre %d"
-#: executor/execIndexing.c:539
+#: executor/execIndexing.c:544
#, c-format
msgid "ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"
-msgstr "ON CONFLICT ne supporte pas les contraintes uniques diferrables et les contraintes d'exclusion diff�rables comme arbitres"
+msgstr "ON CONFLICT ne supporte pas les contraintes uniques diferrables et les contraintes d'exclusion différables comme arbitres"
-#: executor/execIndexing.c:816
+#: executor/execIndexing.c:821
#, c-format
msgid "could not create exclusion constraint \"%s\""
-msgstr "n'a pas pu cr�er la contrainte d'exclusion � %s �"
+msgstr "n'a pas pu créer la contrainte d'exclusion « %s »"
-#: executor/execIndexing.c:819
+#: executor/execIndexing.c:824
#, c-format
msgid "Key %s conflicts with key %s."
-msgstr "La cl� %s est en conflit avec la cl� %s."
+msgstr "La clé %s est en conflit avec la clé %s."
-#: executor/execIndexing.c:821
+#: executor/execIndexing.c:826
#, c-format
msgid "Key conflicts exist."
-msgstr "Un conflit de cl�s est pr�sent."
+msgstr "Un conflit de clés est présent."
-#: executor/execIndexing.c:827
+#: executor/execIndexing.c:832
#, c-format
msgid "conflicting key value violates exclusion constraint \"%s\""
-msgstr "la valeur d'une cl� en conflit rompt la contrainte d'exclusion � %s �"
+msgstr "la valeur d'une clé en conflit rompt la contrainte d'exclusion « %s »"
-#: executor/execIndexing.c:830
+#: executor/execIndexing.c:835
#, c-format
msgid "Key %s conflicts with existing key %s."
-msgstr "La cl� %s est en conflit avec la cl� existante %s."
+msgstr "La clé %s est en conflit avec la clé existante %s."
-#: executor/execIndexing.c:832
+#: executor/execIndexing.c:837
#, c-format
msgid "Key conflicts with existing key."
-msgstr "La cl� est en conflit avec une cl� existante."
+msgstr "La clé est en conflit avec une clé existante."
#: executor/execMain.c:1027
#, c-format
msgid "cannot change sequence \"%s\""
-msgstr "ne peut pas modifier la s�quence � %s �"
+msgstr "ne peut pas modifier la séquence « %s »"
#: executor/execMain.c:1033
#, c-format
msgid "cannot change TOAST relation \"%s\""
-msgstr "ne peut pas modifier la relation TOAST � %s �"
+msgstr "ne peut pas modifier la relation TOAST « %s »"
#: executor/execMain.c:1051 rewrite/rewriteHandler.c:2648
#, c-format
msgid "cannot insert into view \"%s\""
-msgstr "ne peut pas ins�rer dans la vue � %s �"
+msgstr "ne peut pas insérer dans la vue « %s »"
#: executor/execMain.c:1053 rewrite/rewriteHandler.c:2651
#, c-format
msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."
-msgstr "Pour activer l'insertion dans la vue, fournissez un trigger INSTEAD OF INSERT ou une r�gle ON INSERT DO INSTEAD sans condition."
+msgstr "Pour activer l'insertion dans la vue, fournissez un trigger INSTEAD OF INSERT ou une règle ON INSERT DO INSTEAD sans condition."
#: executor/execMain.c:1059 rewrite/rewriteHandler.c:2656
#, c-format
msgid "cannot update view \"%s\""
-msgstr "ne peut pas mettre � jour la vue � %s �"
+msgstr "ne peut pas mettre à jour la vue « %s »"
#: executor/execMain.c:1061 rewrite/rewriteHandler.c:2659
#, c-format
msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule."
-msgstr "Pour activer la mise � jour dans la vue, fournissez un trigger INSTEAD OF UPDATE ou une r�gle ON UPDATE DO INSTEAD sans condition."
+msgstr "Pour activer la mise à jour dans la vue, fournissez un trigger INSTEAD OF UPDATE ou une règle ON UPDATE DO INSTEAD sans condition."
#: executor/execMain.c:1067 rewrite/rewriteHandler.c:2664
#, c-format
msgid "cannot delete from view \"%s\""
-msgstr "ne peut pas supprimer � partir de la vue � %s �"
+msgstr "ne peut pas supprimer à partir de la vue « %s »"
#: executor/execMain.c:1069 rewrite/rewriteHandler.c:2667
#, c-format
msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule."
-msgstr "Pour activer la suppression dans la vue, fournissez un trigger INSTEAD OF DELETE ou une r�gle ON DELETE DO INSTEAD sans condition."
+msgstr "Pour activer la suppression dans la vue, fournissez un trigger INSTEAD OF DELETE ou une règle ON DELETE DO INSTEAD sans condition."
#: executor/execMain.c:1080
#, c-format
msgid "cannot change materialized view \"%s\""
-msgstr "ne peut pas modifier la vue mat�rialis�e � %s �"
+msgstr "ne peut pas modifier la vue matérialisée « %s »"
#: executor/execMain.c:1092
#, c-format
msgid "cannot insert into foreign table \"%s\""
-msgstr "ne peut pas ins�rer dans la table distante � %s �"
+msgstr "ne peut pas insérer dans la table distante « %s »"
#: executor/execMain.c:1098
#, c-format
msgid "foreign table \"%s\" does not allow inserts"
-msgstr "la table distante � %s � n'autorise pas les insertions"
+msgstr "la table distante « %s » n'autorise pas les insertions"
#: executor/execMain.c:1105
#, c-format
msgid "cannot update foreign table \"%s\""
-msgstr "ne peut pas modifier la table distante � %s �"
+msgstr "ne peut pas modifier la table distante « %s »"
#: executor/execMain.c:1111
#, c-format
msgid "foreign table \"%s\" does not allow updates"
-msgstr "la table distante � %s � n'autorise pas les modifications"
+msgstr "la table distante « %s » n'autorise pas les modifications"
#: executor/execMain.c:1118
#, c-format
msgid "cannot delete from foreign table \"%s\""
-msgstr "ne peut pas supprimer � partir de la table distante � %s �"
+msgstr "ne peut pas supprimer à partir de la table distante « %s »"
#: executor/execMain.c:1124
#, c-format
msgid "foreign table \"%s\" does not allow deletes"
-msgstr "la table distante � %s � n'autorise pas les suppressions"
+msgstr "la table distante « %s » n'autorise pas les suppressions"
#: executor/execMain.c:1135
#, c-format
msgid "cannot change relation \"%s\""
-msgstr "ne peut pas modifier la relation � %s �"
+msgstr "ne peut pas modifier la relation « %s »"
#: executor/execMain.c:1161
#, c-format
msgid "cannot lock rows in sequence \"%s\""
-msgstr "ne peut pas verrouiller les lignes dans la s�quence � %s �"
+msgstr "ne peut pas verrouiller les lignes dans la séquence « %s »"
#: executor/execMain.c:1168
#, c-format
msgid "cannot lock rows in TOAST relation \"%s\""
-msgstr "ne peut pas verrouiller les lignes dans la relation TOAST � %s �"
+msgstr "ne peut pas verrouiller les lignes dans la relation TOAST « %s »"
#: executor/execMain.c:1175
#, c-format
msgid "cannot lock rows in view \"%s\""
-msgstr "ne peut pas verrouiller les lignes dans la vue � %s �"
+msgstr "ne peut pas verrouiller les lignes dans la vue « %s »"
#: executor/execMain.c:1183
#, c-format
msgid "cannot lock rows in materialized view \"%s\""
-msgstr "ne peut pas verrouiller les lignes dans la vue mat�rialis�e � %s �"
+msgstr "ne peut pas verrouiller les lignes dans la vue matérialisée « %s »"
-#: executor/execMain.c:1192 executor/execMain.c:2603 executor/nodeLockRows.c:132
+#: executor/execMain.c:1192 executor/execMain.c:2613 executor/nodeLockRows.c:132
#, c-format
msgid "cannot lock rows in foreign table \"%s\""
-msgstr "ne peut pas verrouiller la table distante � %s �"
+msgstr "ne peut pas verrouiller la table distante « %s »"
#: executor/execMain.c:1198
#, c-format
msgid "cannot lock rows in relation \"%s\""
-msgstr "n'a pas pu verrouiller les lignes dans la relation � %s �"
+msgstr "n'a pas pu verrouiller les lignes dans la relation « %s »"
-#: executor/execMain.c:1721
+#: executor/execMain.c:1731
#, c-format
msgid "null value in column \"%s\" violates not-null constraint"
-msgstr "une valeur NULL viole la contrainte NOT NULL de la colonne � %s �"
+msgstr "une valeur NULL viole la contrainte NOT NULL de la colonne « %s »"
-#: executor/execMain.c:1723 executor/execMain.c:1749 executor/execMain.c:1838
+#: executor/execMain.c:1733 executor/execMain.c:1759 executor/execMain.c:1848
#, c-format
msgid "Failing row contains %s."
-msgstr "La ligne en �chec contient %s"
+msgstr "La ligne en échec contient %s"
-#: executor/execMain.c:1747
+#: executor/execMain.c:1757
#, c-format
msgid "new row for relation \"%s\" violates check constraint \"%s\""
-msgstr "la nouvelle ligne viole la contrainte de v�rification � %s � de la relation � %s �"
+msgstr "la nouvelle ligne viole la contrainte de vérification « %s » de la relation « %s »"
-#: executor/execMain.c:1836
+#: executor/execMain.c:1846
#, c-format
msgid "new row violates check option for view \"%s\""
-msgstr "la nouvelle ligne viole la contrainte de v�rification pour la vue � %s �"
+msgstr "la nouvelle ligne viole la contrainte de vérification pour la vue « %s »"
-#: executor/execMain.c:1846
+#: executor/execMain.c:1856
#, c-format
msgid "new row violates row-level security policy \"%s\" for table \"%s\""
-msgstr "la nouvelle ligne viole la politique de s�curit� au niveau ligne � %s � pour la table � %s �"
+msgstr "la nouvelle ligne viole la politique de sécurité au niveau ligne « %s » pour la table « %s »"
-#: executor/execMain.c:1851
+#: executor/execMain.c:1861
#, c-format
msgid "new row violates row-level security policy for table \"%s\""
-msgstr "la nouvelle ligne viole la politique de s�curit� au niveau ligne pour la table � %s �"
+msgstr "la nouvelle ligne viole la politique de sécurité au niveau ligne pour la table « %s »"
-#: executor/execMain.c:1858
+#: executor/execMain.c:1868
#, c-format
msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\""
-msgstr "la nouvelle ligne viole la politique de s�curit� au niveau ligne � %s � (expression USING) pour la table � %s �"
+msgstr "la nouvelle ligne viole la politique de sécurité au niveau ligne « %s » (expression USING) pour la table « %s »"
-#: executor/execMain.c:1863
+#: executor/execMain.c:1873
#, c-format
msgid "new row violates row-level security policy (USING expression) for table \"%s\""
-msgstr "la nouvelle ligne viole la politique de s�curit� au niveau ligne (expression USING) pour la table � %s �"
+msgstr "la nouvelle ligne viole la politique de sécurité au niveau ligne (expression USING) pour la table « %s »"
-#: executor/execQual.c:302 executor/execQual.c:339 executor/execQual.c:3213 utils/adt/array_userfuncs.c:472 utils/adt/arrayfuncs.c:260 utils/adt/arrayfuncs.c:558 utils/adt/arrayfuncs.c:1288 utils/adt/arrayfuncs.c:3361 utils/adt/arrayfuncs.c:5245 utils/adt/arrayfuncs.c:5768
+#: executor/execQual.c:302 executor/execQual.c:339 executor/execQual.c:3236 utils/adt/array_userfuncs.c:484 utils/adt/arrayfuncs.c:260 utils/adt/arrayfuncs.c:558 utils/adt/arrayfuncs.c:1288 utils/adt/arrayfuncs.c:3361 utils/adt/arrayfuncs.c:5241 utils/adt/arrayfuncs.c:5758
#, c-format
msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)"
-msgstr "le nombre de dimensions du tableau (%d) d�passe le maximum autoris� (%d)"
+msgstr "le nombre de dimensions du tableau (%d) dépasse le maximum autorisé (%d)"
#: executor/execQual.c:324 executor/execQual.c:360
#, c-format
msgid "array subscript in assignment must not be null"
-msgstr "l'indice du tableau dans l'affectation ne doit pas �tre NULL"
+msgstr "l'indice du tableau dans l'affectation ne doit pas être NULL"
-#: executor/execQual.c:657 executor/execQual.c:4138
+#: executor/execQual.c:657 executor/execQual.c:4183
#, c-format
msgid "attribute %d has wrong type"
msgstr "l'attribut %d a un type invalide"
-#: executor/execQual.c:658 executor/execQual.c:4139
+#: executor/execQual.c:658 executor/execQual.c:4184
#, c-format
msgid "Table has type %s, but query expects %s."
-msgstr "La table a le type %s alors que la requ�te attend %s."
+msgstr "La table a le type %s alors que la requête attend %s."
#: executor/execQual.c:851 executor/execQual.c:868 executor/execQual.c:1068 executor/nodeModifyTable.c:95 executor/nodeModifyTable.c:105 executor/nodeModifyTable.c:122 executor/nodeModifyTable.c:130
#, c-format
msgid "table row type and query-specified row type do not match"
-msgstr "Le type de ligne de la table et celui sp�cifi� par la requ�te ne correspondent pas"
+msgstr "Le type de ligne de la table et celui spécifié par la requête ne correspondent pas"
#: executor/execQual.c:852
#, c-format
msgid "Table row contains %d attribute, but query expects %d."
msgid_plural "Table row contains %d attributes, but query expects %d."
-msgstr[0] "La ligne de la table contient %d attribut alors que la requ�te en attend %d."
-msgstr[1] "La ligne de la table contient %d attributs alors que la requ�te en attend %d."
+msgstr[0] "La ligne de la table contient %d attribut alors que la requête en attend %d."
+msgstr[1] "La ligne de la table contient %d attributs alors que la requête en attend %d."
#: executor/execQual.c:869 executor/nodeModifyTable.c:106
#, c-format
msgid "Table has type %s at ordinal position %d, but query expects %s."
-msgstr "La table a le type %s � la position ordinale %d alors que la requ�te attend %s."
+msgstr "La table a le type %s à la position ordinale %d alors que la requête attend %s."
#: executor/execQual.c:1069 executor/execQual.c:1665
#, c-format
msgid "Physical storage mismatch on dropped attribute at ordinal position %d."
msgstr ""
-"Le stockage physique ne correspond pas � l'attribut supprim� � la position\n"
+"Le stockage physique ne correspond pas à l'attribut supprimé à la position\n"
"ordinale %d."
-#: executor/execQual.c:1344 parser/parse_func.c:115 parser/parse_func.c:542 parser/parse_func.c:895
+#: executor/execQual.c:1344 parser/parse_func.c:115 parser/parse_func.c:542 parser/parse_func.c:897
#, c-format
msgid "cannot pass more than %d argument to a function"
msgid_plural "cannot pass more than %d arguments to a function"
-msgstr[0] "ne peut pas passer plus de %d argument � une fonction"
-msgstr[1] "ne peut pas passer plus de %d arguments � une fonction"
+msgstr[0] "ne peut pas passer plus de %d argument à une fonction"
+msgstr[1] "ne peut pas passer plus de %d arguments à une fonction"
#: executor/execQual.c:1533
#, c-format
msgid "functions and operators can take at most one set argument"
-msgstr "les fonctions et op�rateurs peuvent prendre au plus un argument d'ensemble"
+msgstr "les fonctions et opérateurs peuvent prendre au plus un argument d'ensemble"
#: executor/execQual.c:1583
#, c-format
msgid "function returning setof record called in context that cannot accept type record"
msgstr ""
-"la fonction renvoyant des lignes a �t� appel�e dans un contexte qui\n"
+"la fonction renvoyant des lignes a été appelée dans un contexte qui\n"
"n'accepte pas un ensemble"
#: executor/execQual.c:1638 executor/execQual.c:1654 executor/execQual.c:1664
#, c-format
msgid "function return row and query-specified return row do not match"
-msgstr "la ligne de retour sp�cifi�e par la requ�te et la ligne de retour de la fonction ne correspondent pas"
+msgstr "la ligne de retour spécifiée par la requête et la ligne de retour de la fonction ne correspondent pas"
#: executor/execQual.c:1639
#, c-format
msgid "Returned row contains %d attribute, but query expects %d."
msgid_plural "Returned row contains %d attributes, but query expects %d."
-msgstr[0] "La ligne renvoy�e contient %d attribut mais la requ�te en attend %d."
-msgstr[1] "La ligne renvoy�e contient %d attributs mais la requ�te en attend %d."
+msgstr[0] "La ligne renvoyée contient %d attribut mais la requête en attend %d."
+msgstr[1] "La ligne renvoyée contient %d attributs mais la requête en attend %d."
#: executor/execQual.c:1655
#, c-format
msgid "Returned type %s at ordinal position %d, but query expects %s."
-msgstr "A renvoy� le type %s � la position ordinale %d, mais la requ�te attend %s."
+msgstr "A renvoyé le type %s à la position ordinale %d, mais la requête attend %s."
-#: executor/execQual.c:1897 executor/execQual.c:2328
+#: executor/execQual.c:1897 executor/execQual.c:2335
#, c-format
msgid "table-function protocol for materialize mode was not followed"
-msgstr "le protocole de la fonction table pour le mode mat�rialis� n'a pas �t� respect�"
+msgstr "le protocole de la fonction table pour le mode matérialisé n'a pas été respecté"
-#: executor/execQual.c:1917 executor/execQual.c:2335
+#: executor/execQual.c:1917 executor/execQual.c:2342
#, c-format
msgid "unrecognized table-function returnMode: %d"
msgstr "returnMode de la fonction table non reconnu : %d"
-#: executor/execQual.c:2245
-#, c-format
-msgid "function returning set of rows cannot return null value"
-msgstr ""
-"la fonction renvoyant un ensemble de lignes ne peut pas renvoyer une valeur\n"
-"NULL"
-
-#: executor/execQual.c:2302
+#: executor/execQual.c:2287
#, c-format
msgid "rows returned by function are not all of the same row type"
-msgstr "les lignes renvoy�es par la fonction ne sont pas toutes du m�me type ligne"
+msgstr "les lignes renvoyées par la fonction ne sont pas toutes du même type ligne"
-#: executor/execQual.c:2517
+#: executor/execQual.c:2522
#, c-format
msgid "IS DISTINCT FROM does not support set arguments"
msgstr "IS DISTINCT FROM ne supporte pas les arguments d'ensemble"
-#: executor/execQual.c:2594
+#: executor/execQual.c:2599
#, c-format
msgid "op ANY/ALL (array) does not support set arguments"
msgstr ""
-"l'op�rateur ANY/ALL (pour les types array) ne supporte pas les arguments\n"
+"l'opérateur ANY/ALL (pour les types array) ne supporte pas les arguments\n"
"d'ensemble"
-#: executor/execQual.c:3191
+#: executor/execQual.c:3214
#, c-format
msgid "cannot merge incompatible arrays"
msgstr "ne peut pas fusionner les tableaux incompatibles"
-#: executor/execQual.c:3192
+#: executor/execQual.c:3215
#, c-format
msgid "Array with element type %s cannot be included in ARRAY construct with element type %s."
-msgstr "Le tableau avec le type d'�l�ment %s ne peut pas �tre inclus dans la construction ARRAY avec le type d'�l�ment %s."
+msgstr "Le tableau avec le type d'élément %s ne peut pas être inclus dans la construction ARRAY avec le type d'élément %s."
-#: executor/execQual.c:3233 executor/execQual.c:3260
+#: executor/execQual.c:3256 executor/execQual.c:3283
#, c-format
msgid "multidimensional arrays must have array expressions with matching dimensions"
msgstr ""
"les tableaux multidimensionnels doivent avoir des expressions de tableaux\n"
"avec les dimensions correspondantes"
-#: executor/execQual.c:3775
+#: executor/execQual.c:3798
#, c-format
msgid "NULLIF does not support set arguments"
msgstr "NULLIF ne supporte pas les arguments d'ensemble"
-#: executor/execQual.c:4008 utils/adt/domains.c:136
+#: executor/execQual.c:4046 utils/adt/domains.c:137
#, c-format
msgid "domain %s does not allow null values"
msgstr "le domaine %s n'autorise pas les valeurs NULL"
-#: executor/execQual.c:4038 utils/adt/domains.c:173
+#: executor/execQual.c:4083 utils/adt/domains.c:179
#, c-format
msgid "value for domain %s violates check constraint \"%s\""
-msgstr "la valeur pour le domaine %s viole la contrainte de v�rification � %s �"
+msgstr "la valeur pour le domaine %s viole la contrainte de vérification « %s »"
-#: executor/execQual.c:4393
+#: executor/execQual.c:4438
#, c-format
msgid "WHERE CURRENT OF is not supported for this table type"
-msgstr "WHERE CURRENT OF n'est pas support� pour ce type de table"
+msgstr "WHERE CURRENT OF n'est pas supporté pour ce type de table"
-#: executor/execQual.c:4597 parser/parse_agg.c:743
+#: executor/execQual.c:4627 parser/parse_agg.c:758
#, c-format
msgid "window function calls cannot be nested"
-msgstr "les appels � la fonction window ne peuvent pas �tre imbriqu�s"
+msgstr "les appels à la fonction window ne peuvent pas être imbriqués"
-#: executor/execQual.c:4809
+#: executor/execQual.c:4839
#, c-format
msgid "target type is not an array"
msgstr "le type cible n'est pas un tableau"
-#: executor/execQual.c:4924
+#: executor/execQual.c:4956
#, c-format
msgid "ROW() column has type %s instead of type %s"
msgstr "une colonne ROW() a le type %s au lieu du type %s"
-#: executor/execQual.c:5059 utils/adt/arrayfuncs.c:3803 utils/adt/arrayfuncs.c:6341 utils/adt/rowtypes.c:927
+#: executor/execQual.c:5091 utils/adt/arrayfuncs.c:3803 utils/adt/arrayfuncs.c:6325 utils/adt/rowtypes.c:927
#, c-format
msgid "could not identify a comparison function for type %s"
msgstr "n'a pas pu identifier une fonction de comparaison pour le type %s"
-#: executor/execUtils.c:819
+#: executor/execUtils.c:813
#, c-format
msgid "materialized view \"%s\" has not been populated"
-msgstr "la vue mat�rialis�e � %s � n'a pas �t� peupl�e"
+msgstr "la vue matérialisée « %s » n'a pas été peuplée"
-#: executor/execUtils.c:821
+#: executor/execUtils.c:815
#, c-format
msgid "Use the REFRESH MATERIALIZED VIEW command."
msgstr "Utilisez la commande REFRESH MATERIALIZED VIEW."
@@ -10236,261 +10248,270 @@ msgstr "Utilisez la commande REFRESH MATERIALIZED VIEW."
#: executor/functions.c:225
#, c-format
msgid "could not determine actual type of argument declared %s"
-msgstr "n'a pas pu d�terminer le type actuel de l'argument d�clar� %s"
+msgstr "n'a pas pu déterminer le type actuel de l'argument déclaré %s"
+
+#: executor/functions.c:511
+#, c-format
+msgid "cannot COPY to/from client in a SQL function"
+msgstr "ne peut pas utiliser COPY TO/FROM dans une fonction SQL"
#. translator: %s is a SQL statement name
-#: executor/functions.c:508
+#: executor/functions.c:517
#, c-format
msgid "%s is not allowed in a SQL function"
-msgstr "%s n'est pas autoris� dans une fonction SQL"
+msgstr "%s n'est pas autorisé dans une fonction SQL"
#. translator: %s is a SQL statement name
-#: executor/functions.c:515 executor/spi.c:1368 executor/spi.c:2158
+#: executor/functions.c:524 executor/spi.c:1364 executor/spi.c:2154
#, c-format
msgid "%s is not allowed in a non-volatile function"
-msgstr "%s n'est pas autoris� dans une fonction non volatile"
+msgstr "%s n'est pas autorisé dans une fonction non volatile"
-#: executor/functions.c:643
+#: executor/functions.c:650
#, c-format
msgid "could not determine actual result type for function declared to return type %s"
msgstr ""
-"n'a pas pu d�terminer le type du r�sultat actuel pour la fonction d�clarant\n"
+"n'a pas pu déterminer le type du résultat actuel pour la fonction déclarant\n"
"renvoyer le type %s"
-#: executor/functions.c:1408
+#: executor/functions.c:1415
#, c-format
msgid "SQL function \"%s\" statement %d"
-msgstr "fonction SQL � %s �, instruction %d"
+msgstr "fonction SQL « %s », instruction %d"
-#: executor/functions.c:1434
+#: executor/functions.c:1441
#, c-format
msgid "SQL function \"%s\" during startup"
-msgstr "fonction SQL � %s � lors du lancement"
+msgstr "fonction SQL « %s » lors du lancement"
-#: executor/functions.c:1593 executor/functions.c:1630 executor/functions.c:1642 executor/functions.c:1755 executor/functions.c:1788 executor/functions.c:1818
+#: executor/functions.c:1600 executor/functions.c:1637 executor/functions.c:1649 executor/functions.c:1762 executor/functions.c:1795 executor/functions.c:1825
#, c-format
msgid "return type mismatch in function declared to return %s"
-msgstr "le type de retour ne correspond pas � la fonction d�clarant renvoyer %s"
+msgstr "le type de retour ne correspond pas à la fonction déclarant renvoyer %s"
-#: executor/functions.c:1595
+#: executor/functions.c:1602
#, c-format
msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING."
msgstr ""
-"L'instruction finale de la fonction doit �tre un SELECT ou un\n"
+"L'instruction finale de la fonction doit être un SELECT ou un\n"
"INSERT/UPDATE/DELETE RETURNING."
-#: executor/functions.c:1632
+#: executor/functions.c:1639
#, c-format
msgid "Final statement must return exactly one column."
msgstr "L'instruction finale doit renvoyer exactement une colonne."
-#: executor/functions.c:1644
+#: executor/functions.c:1651
#, c-format
msgid "Actual return type is %s."
-msgstr "Le code de retour r�el est %s."
+msgstr "Le code de retour réel est %s."
-#: executor/functions.c:1757
+#: executor/functions.c:1764
#, c-format
msgid "Final statement returns too many columns."
msgstr "L'instruction finale renvoie beaucoup trop de colonnes."
-#: executor/functions.c:1790
+#: executor/functions.c:1797
#, c-format
msgid "Final statement returns %s instead of %s at column %d."
msgstr "L'instruction finale renvoie %s au lieu de %s pour la colonne %d."
-#: executor/functions.c:1820
+#: executor/functions.c:1827
#, c-format
msgid "Final statement returns too few columns."
msgstr "L'instruction finale renvoie trop peu de colonnes."
-#: executor/functions.c:1869
+#: executor/functions.c:1876
#, c-format
msgid "return type %s is not supported for SQL functions"
-msgstr "le type de retour %s n'est pas support� pour les fonctions SQL"
+msgstr "le type de retour %s n'est pas supporté pour les fonctions SQL"
-#: executor/nodeAgg.c:3011
-#, fuzzy, c-format
-#| msgid "final function with extra arguments must not be declared STRICT"
-msgid "combine function for aggregate %u must to be declared as strict"
-msgstr "la fonction finale avec des arguments suppl�mentaires ne doit pas �tre d�clar�e avec la clause STRICT"
+#: executor/nodeAgg.c:3038
+#, c-format
+msgid "combine function for aggregate %u must be declared as STRICT"
+msgstr "la fonction d'unification pour l'aggrégat %u doit être déclarée comme STRICT"
-#: executor/nodeAgg.c:3056 executor/nodeWindowAgg.c:2289
+#: executor/nodeAgg.c:3083 executor/nodeWindowAgg.c:2318
#, c-format
msgid "aggregate %u needs to have compatible input type and transition type"
msgstr ""
-"L'agr�gat %u a besoin d'avoir un type en entr�e compatible avec le type en\n"
+"L'agrégat %u a besoin d'avoir un type en entrée compatible avec le type en\n"
"transition"
-#: executor/nodeAgg.c:3128 parser/parse_agg.c:597 parser/parse_agg.c:627
+#: executor/nodeAgg.c:3149 parser/parse_agg.c:612 parser/parse_agg.c:642
#, c-format
msgid "aggregate function calls cannot be nested"
-msgstr "les appels � la fonction d'agr�gat ne peuvent pas �tre imbriqu�s"
+msgstr "les appels à la fonction d'agrégat ne peuvent pas être imbriqués"
#: executor/nodeCustom.c:148 executor/nodeCustom.c:159
#, c-format
msgid "custom scan \"%s\" does not support MarkPos"
-msgstr "le parcours personnalis� � %s � ne supporte pas MarkPos"
+msgstr "le parcours personnalisé « %s » ne supporte pas MarkPos"
#: executor/nodeHashjoin.c:823 executor/nodeHashjoin.c:853
#, c-format
msgid "could not rewind hash-join temporary file: %m"
-msgstr "n'a pas pu revenir au d�but du fichier temporaire de la jointure h�ch�e : %m"
+msgstr "n'a pas pu revenir au début du fichier temporaire de la jointure hâchée : %m"
#: executor/nodeHashjoin.c:888 executor/nodeHashjoin.c:894
#, c-format
msgid "could not write to hash-join temporary file: %m"
-msgstr "n'a pas pu �crire le fichier temporaire de la jointure h�ch�e : %m"
+msgstr "n'a pas pu écrire le fichier temporaire de la jointure hâchée : %m"
#: executor/nodeHashjoin.c:928 executor/nodeHashjoin.c:938
#, c-format
msgid "could not read from hash-join temporary file: %m"
-msgstr "n'a pas pu lire le fichier temporaire contenant la jointure h�ch�e : %m"
+msgstr "n'a pas pu lire le fichier temporaire contenant la jointure hâchée : %m"
#: executor/nodeIndexonlyscan.c:179
#, c-format
msgid "lossy distance functions are not supported in index-only scans"
-msgstr "les fonctions de distance � perte ne sont pas support�s dans les parcours d'index seul"
+msgstr "les fonctions de distance à perte ne sont pas supportés dans les parcours d'index seul"
#: executor/nodeLimit.c:253
#, c-format
msgid "OFFSET must not be negative"
-msgstr "OFFSET ne doit pas �tre n�gatif"
+msgstr "OFFSET ne doit pas être négatif"
#: executor/nodeLimit.c:280
#, c-format
msgid "LIMIT must not be negative"
-msgstr "LIMIT ne doit pas �tre n�gative"
+msgstr "LIMIT ne doit pas être négative"
#: executor/nodeMergejoin.c:1584
#, c-format
msgid "RIGHT JOIN is only supported with merge-joinable join conditions"
-msgstr "RIGHT JOIN est support� seulement avec les conditions de jointures MERGE"
+msgstr "RIGHT JOIN est supporté seulement avec les conditions de jointures MERGE"
#: executor/nodeMergejoin.c:1604
#, c-format
msgid "FULL JOIN is only supported with merge-joinable join conditions"
-msgstr "FULL JOIN est support� seulement avec les conditions de jointures MERGE"
+msgstr "FULL JOIN est supporté seulement avec les conditions de jointures MERGE"
#: executor/nodeModifyTable.c:96
#, c-format
msgid "Query has too many columns."
-msgstr "La requ�te a trop de colonnes."
+msgstr "La requête a trop de colonnes."
#: executor/nodeModifyTable.c:123
#, c-format
msgid "Query provides a value for a dropped column at ordinal position %d."
msgstr ""
-"La requ�te fournit une valeur pour une colonne supprim�e � la position\n"
+"La requête fournit une valeur pour une colonne supprimée à la position\n"
"ordinale %d."
#: executor/nodeModifyTable.c:131
#, c-format
msgid "Query has too few columns."
-msgstr "La requ�te n'a pas assez de colonnes."
+msgstr "La requête n'a pas assez de colonnes."
-#: executor/nodeModifyTable.c:1117
+#: executor/nodeModifyTable.c:1132
#, c-format
msgid "ON CONFLICT DO UPDATE command cannot affect row a second time"
-msgstr "la commande ON CONFLICT DO UPDATE ne peut pas affecter une ligne la deuxi�me fois"
+msgstr "la commande ON CONFLICT DO UPDATE ne peut pas affecter une ligne la deuxième fois"
-#: executor/nodeModifyTable.c:1118
+#: executor/nodeModifyTable.c:1133
#, c-format
msgid "Ensure that no rows proposed for insertion within the same command have duplicate constrained values."
-msgstr "S'assure qu'aucune ligne propos�e � l'insertion dans la m�me commande n'a de valeurs contraintes dupliqu�es."
+msgstr "S'assure qu'aucune ligne proposée à l'insertion dans la même commande n'a de valeurs contraintes dupliquées."
#: executor/nodeSamplescan.c:307
#, c-format
msgid "TABLESAMPLE parameter cannot be null"
-msgstr "le param�tre de TABLESAMPLE ne peut pas �tre NULL"
+msgstr "le paramètre de TABLESAMPLE ne peut pas être NULL"
#: executor/nodeSamplescan.c:320
#, c-format
msgid "TABLESAMPLE REPEATABLE parameter cannot be null"
-msgstr "le param�tre TABLESAMPLE REPEATABLE ne peut pas �tre NULL"
+msgstr "le paramètre TABLESAMPLE REPEATABLE ne peut pas être NULL"
-#: executor/nodeSubplan.c:345 executor/nodeSubplan.c:384 executor/nodeSubplan.c:1040
+#: executor/nodeSubplan.c:345 executor/nodeSubplan.c:384 executor/nodeSubplan.c:1036
#, c-format
msgid "more than one row returned by a subquery used as an expression"
-msgstr "plus d'une ligne renvoy�e par une sous-requ�te utilis�e comme une expression"
+msgstr "plus d'une ligne renvoyée par une sous-requête utilisée comme une expression"
#: executor/nodeWindowAgg.c:353
#, c-format
msgid "moving-aggregate transition function must not return null"
-msgstr "la fonction de conversion de l'agr�gat en d�placement ne doit pas renvoyer null"
+msgstr "la fonction de conversion de l'agrégat en déplacement ne doit pas renvoyer null"
-#: executor/nodeWindowAgg.c:1609
+#: executor/nodeWindowAgg.c:1642
#, c-format
msgid "frame starting offset must not be null"
-msgstr "l'offset de d�but de frame ne doit pas �tre NULL"
+msgstr "l'offset de début de frame ne doit pas être NULL"
-#: executor/nodeWindowAgg.c:1622
+#: executor/nodeWindowAgg.c:1655
#, c-format
msgid "frame starting offset must not be negative"
-msgstr "l'offset de d�but de frame ne doit pas �tre n�gatif"
+msgstr "l'offset de début de frame ne doit pas être négatif"
-#: executor/nodeWindowAgg.c:1635
+#: executor/nodeWindowAgg.c:1668
#, c-format
msgid "frame ending offset must not be null"
-msgstr "l'offset de fin de frame ne doit pas �tre NULL"
+msgstr "l'offset de fin de frame ne doit pas être NULL"
-#: executor/nodeWindowAgg.c:1648
+#: executor/nodeWindowAgg.c:1681
#, c-format
msgid "frame ending offset must not be negative"
-msgstr "l'offset de fin de frame ne doit pas �tre n�gatif"
+msgstr "l'offset de fin de frame ne doit pas être négatif"
-#: executor/spi.c:214
+#: executor/spi.c:210
#, c-format
msgid "transaction left non-empty SPI stack"
msgstr "transaction gauche non vide dans la pile SPI"
-#: executor/spi.c:215 executor/spi.c:279
+#: executor/spi.c:211 executor/spi.c:275
#, c-format
msgid "Check for missing \"SPI_finish\" calls."
-msgstr "V�rifiez les appels manquants � � SPI_finish �."
+msgstr "Vérifiez les appels manquants à « SPI_finish »."
-#: executor/spi.c:278
+#: executor/spi.c:274
#, c-format
msgid "subtransaction left non-empty SPI stack"
msgstr "sous-transaction gauche non vide dans la pile SPI"
-#: executor/spi.c:1229
+#: executor/spi.c:1225
#, c-format
msgid "cannot open multi-query plan as cursor"
-msgstr "ne peut pas ouvrir le plan � plusieurs requ�tes comme curseur"
+msgstr "ne peut pas ouvrir le plan à plusieurs requêtes comme curseur"
#. translator: %s is name of a SQL command, eg INSERT
-#: executor/spi.c:1234
+#: executor/spi.c:1230
#, c-format
msgid "cannot open %s query as cursor"
-msgstr "ne peut pas ouvrir la requ�te %s comme curseur"
+msgstr "ne peut pas ouvrir la requête %s comme curseur"
-#: executor/spi.c:1342
+#: executor/spi.c:1338
#, c-format
msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"
-msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE n'est pas support�"
+msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE n'est pas supporté"
-#: executor/spi.c:1343 parser/analyze.c:2292
+#: executor/spi.c:1339 parser/analyze.c:2360
#, c-format
msgid "Scrollable cursors must be READ ONLY."
-msgstr "Les curseurs d�pla�ables doivent �tre en lecture seule (READ ONLY)."
+msgstr "Les curseurs déplaçables doivent être en lecture seule (READ ONLY)."
#: executor/spi.c:2459
#, c-format
msgid "SQL statement \"%s\""
-msgstr "instruction SQL � %s �"
+msgstr "instruction SQL « %s »"
+
+#: executor/tqueue.c:317
+#, c-format
+msgid "could not send tuple to shared-memory queue"
+msgstr "n'a pas pu envoyer la ligne dans la queue en mémoire partagée"
-#: foreign/foreign.c:314
+#: foreign/foreign.c:192
#, c-format
msgid "user mapping not found for \"%s\""
-msgstr "correspondance utilisateur non trouv�e pour � %s �"
+msgstr "correspondance utilisateur non trouvée pour « %s »"
-#: foreign/foreign.c:750
+#: foreign/foreign.c:644
#, c-format
msgid "invalid option \"%s\""
-msgstr "option � %s � invalide"
+msgstr "option « %s » invalide"
-#: foreign/foreign.c:751
+#: foreign/foreign.c:645
#, c-format
msgid "Valid options in this context are: %s"
msgstr "Les options valides dans ce contexte sont %s"
@@ -10498,1451 +10519,1447 @@ msgstr "Les options valides dans ce contexte sont %s"
#: gram.y:1004
#, c-format
msgid "unrecognized role option \"%s\""
-msgstr "option � %s � du r�le non reconnu"
+msgstr "option « %s » du rôle non reconnu"
-#: gram.y:1280 gram.y:1295
+#: gram.y:1278 gram.y:1293
#, c-format
msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements"
-msgstr "CREATE SCHEMA IF NOT EXISTS n'inclut pas les �l�ments du sch�ma"
+msgstr "CREATE SCHEMA IF NOT EXISTS n'inclut pas les éléments du schéma"
-#: gram.y:1440
+#: gram.y:1438
#, c-format
msgid "current database cannot be changed"
-msgstr "la base de donn�es actuelle ne peut pas �tre chang�e"
+msgstr "la base de données actuelle ne peut pas être changée"
-#: gram.y:1564
+#: gram.y:1562
#, c-format
msgid "time zone interval must be HOUR or HOUR TO MINUTE"
-msgstr "l'intervalle de fuseau horaire doit �tre HOUR ou HOUR TO MINUTE"
+msgstr "l'intervalle de fuseau horaire doit être HOUR ou HOUR TO MINUTE"
-#: gram.y:2602 gram.y:2631
+#: gram.y:2600 gram.y:2629
#, c-format
msgid "STDIN/STDOUT not allowed with PROGRAM"
-msgstr "STDIN/STDOUT non autoris� dans PROGRAM"
+msgstr "STDIN/STDOUT non autorisé dans PROGRAM"
-#: gram.y:2897 gram.y:2904 gram.y:10275 gram.y:10283
+#: gram.y:2895 gram.y:2902 gram.y:10295 gram.y:10303
#, c-format
msgid "GLOBAL is deprecated in temporary table creation"
-msgstr "GLOBAL est obsol�te dans la cr�ation de la table temporaire"
+msgstr "GLOBAL est obsolète dans la création de la table temporaire"
-#: gram.y:3345 utils/adt/ri_triggers.c:316 utils/adt/ri_triggers.c:373 utils/adt/ri_triggers.c:792 utils/adt/ri_triggers.c:1015 utils/adt/ri_triggers.c:1171 utils/adt/ri_triggers.c:1352 utils/adt/ri_triggers.c:1517 utils/adt/ri_triggers.c:1693 utils/adt/ri_triggers.c:1873 utils/adt/ri_triggers.c:2064 utils/adt/ri_triggers.c:2122 utils/adt/ri_triggers.c:2227 utils/adt/ri_triggers.c:2404
+#: gram.y:3343 utils/adt/ri_triggers.c:314 utils/adt/ri_triggers.c:371 utils/adt/ri_triggers.c:790 utils/adt/ri_triggers.c:1013 utils/adt/ri_triggers.c:1169 utils/adt/ri_triggers.c:1350 utils/adt/ri_triggers.c:1515 utils/adt/ri_triggers.c:1691 utils/adt/ri_triggers.c:1871 utils/adt/ri_triggers.c:2062 utils/adt/ri_triggers.c:2120 utils/adt/ri_triggers.c:2225 utils/adt/ri_triggers.c:2402
#, c-format
msgid "MATCH PARTIAL not yet implemented"
-msgstr "MATCH PARTIAL non impl�ment�"
+msgstr "MATCH PARTIAL non implémenté"
-#: gram.y:4800
+#: gram.y:4809
msgid "duplicate trigger events specified"
-msgstr "�v�nements de trigger dupliqu�s sp�cifi�s"
+msgstr "événements de trigger dupliqués spécifiés"
-#: gram.y:4893 parser/parse_utilcmd.c:2741 parser/parse_utilcmd.c:2767
+#: gram.y:4902 parser/parse_utilcmd.c:2728 parser/parse_utilcmd.c:2754
#, c-format
msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE"
-msgstr "la contrainte d�clar�e INITIALLY DEFERRED doit �tre DEFERRABLE"
+msgstr "la contrainte déclarée INITIALLY DEFERRED doit être DEFERRABLE"
-#: gram.y:4900
+#: gram.y:4909
#, c-format
msgid "conflicting constraint properties"
-msgstr "propri�t�s de contrainte en conflit"
+msgstr "propriétés de contrainte en conflit"
-#: gram.y:5032
+#: gram.y:5041
#, c-format
msgid "CREATE ASSERTION is not yet implemented"
-msgstr "CREATE ASSERTION n'est pas encore impl�ment�"
+msgstr "CREATE ASSERTION n'est pas encore implémenté"
-#: gram.y:5048
+#: gram.y:5057
#, c-format
msgid "DROP ASSERTION is not yet implemented"
-msgstr "DROP ASSERTION n'est pas encore impl�ment�"
+msgstr "DROP ASSERTION n'est pas encore implémenté"
-#: gram.y:5394
+#: gram.y:5403
#, c-format
msgid "RECHECK is no longer required"
-msgstr "RECHECK n'est plus n�cessaire"
+msgstr "RECHECK n'est plus nécessaire"
-#: gram.y:5395
+#: gram.y:5404
#, c-format
msgid "Update your data type."
-msgstr "Mettez � jour votre type de donn�es."
+msgstr "Mettez à jour votre type de données."
-#: gram.y:6973
+#: gram.y:6983
#, c-format
msgid "aggregates cannot have output arguments"
-msgstr "les agr�gats ne peuvent pas avoir d'arguments en sortie"
+msgstr "les agrégats ne peuvent pas avoir d'arguments en sortie"
-#: gram.y:7292 utils/adt/regproc.c:774 utils/adt/regproc.c:815
+#: gram.y:7302 utils/adt/regproc.c:774 utils/adt/regproc.c:815
#, c-format
msgid "missing argument"
msgstr "argument manquant"
-#: gram.y:7293 utils/adt/regproc.c:775 utils/adt/regproc.c:816
+#: gram.y:7303 utils/adt/regproc.c:775 utils/adt/regproc.c:816
#, c-format
msgid "Use NONE to denote the missing argument of a unary operator."
-msgstr "Utilisez NONE pour d�noter l'argument manquant d'un op�rateur unitaire."
+msgstr "Utilisez NONE pour dénoter l'argument manquant d'un opérateur unitaire."
-#: gram.y:8843 gram.y:8861
+#: gram.y:8853 gram.y:8871
#, c-format
msgid "WITH CHECK OPTION not supported on recursive views"
-msgstr "WITH CHECK OPTION non support� sur les vues r�cursives"
+msgstr "WITH CHECK OPTION non supporté sur les vues récursives"
-#: gram.y:9867 parser/parse_expr.c:1476
+#: gram.y:9389
+#, c-format
+msgid "unrecognized VACUUM option \"%s\""
+msgstr "option « %s » de la commande VACUUM non reconnue"
+
+#: gram.y:9887 parser/parse_expr.c:1501
#, c-format
msgid "number of columns does not match number of values"
msgstr "le nombre de colonnes ne correspond pas au nombre de valeurs"
-#: gram.y:10383
+#: gram.y:10403
#, c-format
msgid "LIMIT #,# syntax is not supported"
-msgstr "la syntaxe LIMIT #,# n'est pas support�e"
+msgstr "la syntaxe LIMIT #,# n'est pas supportée"
-#: gram.y:10384
+#: gram.y:10404
#, c-format
msgid "Use separate LIMIT and OFFSET clauses."
-msgstr "Utilisez les clauses s�par�es LIMIT et OFFSET."
+msgstr "Utilisez les clauses séparées LIMIT et OFFSET."
-#: gram.y:10647 gram.y:10672
+#: gram.y:10667 gram.y:10692
#, c-format
msgid "VALUES in FROM must have an alias"
msgstr "VALUES dans FROM doit avoir un alias"
-#: gram.y:10648 gram.y:10673
+#: gram.y:10668 gram.y:10693
#, c-format
msgid "For example, FROM (VALUES ...) [AS] foo."
msgstr "Par exemple, FROM (VALUES ...) [AS] quelquechose."
-#: gram.y:10653 gram.y:10678
+#: gram.y:10673 gram.y:10698
#, c-format
msgid "subquery in FROM must have an alias"
-msgstr "la sous-requ�te du FROM doit avoir un alias"
+msgstr "la sous-requête du FROM doit avoir un alias"
-#: gram.y:10654 gram.y:10679
+#: gram.y:10674 gram.y:10699
#, c-format
msgid "For example, FROM (SELECT ...) [AS] foo."
msgstr "Par exemple, FROM (SELECT...) [AS] quelquechose."
-#: gram.y:11253
+#: gram.y:11273
#, c-format
msgid "precision for type float must be at least 1 bit"
-msgstr "la pr�cision du type float doit �tre d'au moins un bit"
+msgstr "la précision du type float doit être d'au moins un bit"
-#: gram.y:11262
+#: gram.y:11282
#, c-format
msgid "precision for type float must be less than 54 bits"
-msgstr "la pr�cision du type float doit �tre inf�rieur � 54 bits"
+msgstr "la précision du type float doit être inférieur à 54 bits"
-#: gram.y:11766
+#: gram.y:11786
#, c-format
msgid "wrong number of parameters on left side of OVERLAPS expression"
-msgstr "mauvais nombre de param�tres sur le c�t� gauche de l'expression OVERLAPS"
+msgstr "mauvais nombre de paramètres sur le côté gauche de l'expression OVERLAPS"
-#: gram.y:11771
+#: gram.y:11791
#, c-format
msgid "wrong number of parameters on right side of OVERLAPS expression"
-msgstr "mauvais nombre de param�tres sur le c�t� droit de l'expression OVERLAPS"
+msgstr "mauvais nombre de paramètres sur le côté droit de l'expression OVERLAPS"
-#: gram.y:11948
+#: gram.y:11966
#, c-format
msgid "UNIQUE predicate is not yet implemented"
-msgstr "pr�dicat UNIQUE non impl�ment�"
+msgstr "prédicat UNIQUE non implémenté"
-#: gram.y:12280
+#: gram.y:12296
#, c-format
msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP"
msgstr "ne peut pas utiliser des clauses ORDER BY multiples dans WITHIN GROUP"
-#: gram.y:12285
+#: gram.y:12301
#, c-format
msgid "cannot use DISTINCT with WITHIN GROUP"
msgstr "ne peut pas utiliser DISTINCT avec WITHIN GROUP"
-#: gram.y:12290
+#: gram.y:12306
#, c-format
msgid "cannot use VARIADIC with WITHIN GROUP"
msgstr "ne peut pas utiliser VARIADIC avec WITHIN GROUP"
-#: gram.y:12796
+#: gram.y:12812
#, c-format
msgid "RANGE PRECEDING is only supported with UNBOUNDED"
-msgstr "RANGE PRECEDING est seulement support� avec UNBOUNDED"
+msgstr "RANGE PRECEDING est seulement supporté avec UNBOUNDED"
-#: gram.y:12802
+#: gram.y:12818
#, c-format
msgid "RANGE FOLLOWING is only supported with UNBOUNDED"
-msgstr "RANGE FOLLOWING est seulement support� avec UNBOUNDED"
+msgstr "RANGE FOLLOWING est seulement supporté avec UNBOUNDED"
-#: gram.y:12829 gram.y:12852
+#: gram.y:12845 gram.y:12868
#, c-format
msgid "frame start cannot be UNBOUNDED FOLLOWING"
-msgstr "la fin du frame ne peut pas �tre UNBOUNDED FOLLOWING"
+msgstr "la fin du frame ne peut pas être UNBOUNDED FOLLOWING"
-#: gram.y:12834
+#: gram.y:12850
#, c-format
msgid "frame starting from following row cannot end with current row"
-msgstr "la frame commen�ant apr�s la ligne suivante ne peut pas se terminer avec la ligne actuelle"
+msgstr "la frame commençant après la ligne suivante ne peut pas se terminer avec la ligne actuelle"
-#: gram.y:12857
+#: gram.y:12873
#, c-format
msgid "frame end cannot be UNBOUNDED PRECEDING"
-msgstr "la fin du frame ne peut pas �tre UNBOUNDED PRECEDING"
+msgstr "la fin du frame ne peut pas être UNBOUNDED PRECEDING"
-#: gram.y:12863
+#: gram.y:12879
#, c-format
msgid "frame starting from current row cannot have preceding rows"
-msgstr "la frame commen�ant � la ligne courante ne peut pas avoir des lignes pr�c�dentes"
+msgstr "la frame commençant à la ligne courante ne peut pas avoir des lignes précédentes"
-#: gram.y:12870
+#: gram.y:12886
#, c-format
msgid "frame starting from following row cannot have preceding rows"
-msgstr "la frame commen�ant � la ligne suivante ne peut pas avoir des lignes pr�c�dentes"
+msgstr "la frame commençant à la ligne suivante ne peut pas avoir des lignes précédentes"
-#: gram.y:13535
+#: gram.y:13551
#, c-format
msgid "type modifier cannot have parameter name"
-msgstr "le modificateur de type ne peut pas avoir de nom de param�tre"
+msgstr "le modificateur de type ne peut pas avoir de nom de paramètre"
-#: gram.y:13541
+#: gram.y:13557
#, c-format
msgid "type modifier cannot have ORDER BY"
msgstr "le modificateur de type ne peut pas avoir de clause ORDER BY"
-#: gram.y:13605 gram.y:13611
+#: gram.y:13621 gram.y:13627
#, c-format
msgid "%s cannot be used as a role name here"
-msgstr "%s ne peut pas �tre utilis� comme nom de r�le ici"
+msgstr "%s ne peut pas être utilisé comme nom de rôle ici"
-#: gram.y:14233 gram.y:14422
+#: gram.y:14249 gram.y:14438
msgid "improper use of \"*\""
-msgstr "mauvaise utilisation de � * �"
+msgstr "mauvaise utilisation de « * »"
-#: gram.y:14385 gram.y:14402 tsearch/spell.c:954 tsearch/spell.c:971 tsearch/spell.c:988 tsearch/spell.c:1005 tsearch/spell.c:1070
+#: gram.y:14401 gram.y:14418 tsearch/spell.c:954 tsearch/spell.c:971 tsearch/spell.c:988 tsearch/spell.c:1005 tsearch/spell.c:1070
#, c-format
msgid "syntax error"
msgstr "erreur de syntaxe"
-#: gram.y:14486
+#: gram.y:14502
#, c-format
msgid "an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"
-msgstr "un agr�gat par ensemble ordonn� avec un argument VARIADIC direct doit avoir un argument VARIADIC agr�g� du m�me type de donn�es"
+msgstr "un agrégat par ensemble ordonné avec un argument VARIADIC direct doit avoir un argument VARIADIC agrégé du même type de données"
-#: gram.y:14523
+#: gram.y:14539
#, c-format
msgid "multiple ORDER BY clauses not allowed"
-msgstr "clauses ORDER BY multiples non autoris�es"
+msgstr "clauses ORDER BY multiples non autorisées"
-#: gram.y:14534
+#: gram.y:14550
#, c-format
msgid "multiple OFFSET clauses not allowed"
-msgstr "clauses OFFSET multiples non autoris�es"
+msgstr "clauses OFFSET multiples non autorisées"
-#: gram.y:14543
+#: gram.y:14559
#, c-format
msgid "multiple LIMIT clauses not allowed"
-msgstr "clauses LIMIT multiples non autoris�es"
+msgstr "clauses LIMIT multiples non autorisées"
-#: gram.y:14552
+#: gram.y:14568
#, c-format
msgid "multiple WITH clauses not allowed"
-msgstr "clauses WITH multiples non autoris�es"
+msgstr "clauses WITH multiples non autorisées"
-#: gram.y:14732
+#: gram.y:14760
#, c-format
msgid "OUT and INOUT arguments aren't allowed in TABLE functions"
-msgstr "les arguments OUT et INOUT ne sont pas autoris�s dans des fonctions TABLE"
+msgstr "les arguments OUT et INOUT ne sont pas autorisés dans des fonctions TABLE"
-#: gram.y:14833
+#: gram.y:14861
#, c-format
msgid "multiple COLLATE clauses not allowed"
-msgstr "clauses COLLATE multiples non autoris�es"
+msgstr "clauses COLLATE multiples non autorisées"
#. translator: %s is CHECK, UNIQUE, or similar
-#: gram.y:14871 gram.y:14884
+#: gram.y:14899 gram.y:14912
#, c-format
msgid "%s constraints cannot be marked DEFERRABLE"
-msgstr "les contraintes %s ne peuvent pas �tre marqu�es comme DEFERRABLE"
+msgstr "les contraintes %s ne peuvent pas être marquées comme DEFERRABLE"
#. translator: %s is CHECK, UNIQUE, or similar
-#: gram.y:14897
+#: gram.y:14925
#, c-format
msgid "%s constraints cannot be marked NOT VALID"
-msgstr "les contraintes %s ne peuvent pas �tre marqu�es comme NOT VALID"
+msgstr "les contraintes %s ne peuvent pas être marquées comme NOT VALID"
#. translator: %s is CHECK, UNIQUE, or similar
-#: gram.y:14910
+#: gram.y:14938
#, c-format
msgid "%s constraints cannot be marked NO INHERIT"
-msgstr "les contraintes %s ne peuvent pas �tre marqu�es NO INHERIT"
+msgstr "les contraintes %s ne peuvent pas être marquées NO INHERIT"
-#: guc-file.l:315
+#: guc-file.l:313
#, c-format
msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %u"
-msgstr "param�tre de configuration � %s � non reconnu dans le fichier � %s �, ligne %u"
+msgstr "paramètre de configuration « %s » non reconnu dans le fichier « %s », ligne %u"
-#: guc-file.l:352 utils/misc/guc.c:5893 utils/misc/guc.c:6085 utils/misc/guc.c:6175 utils/misc/guc.c:6265 utils/misc/guc.c:6373 utils/misc/guc.c:6468
+#: guc-file.l:350 utils/misc/guc.c:5896 utils/misc/guc.c:6089 utils/misc/guc.c:6179 utils/misc/guc.c:6269 utils/misc/guc.c:6377 utils/misc/guc.c:6472
#, c-format
msgid "parameter \"%s\" cannot be changed without restarting the server"
-msgstr "le param�tre � %s � ne peut pas �tre modifi� sans red�marrer le serveur"
+msgstr "le paramètre « %s » ne peut pas être modifié sans redémarrer le serveur"
-#: guc-file.l:388
+#: guc-file.l:386
#, c-format
msgid "parameter \"%s\" removed from configuration file, reset to default"
msgstr ""
-"param�tre � %s � supprim� du fichier de configuration ;\n"
-"r�initialisation � la valeur par d�faut"
+"paramètre « %s » supprimé du fichier de configuration ;\n"
+"réinitialisation à la valeur par défaut"
-#: guc-file.l:454
+#: guc-file.l:452
#, c-format
msgid "parameter \"%s\" changed to \"%s\""
-msgstr "param�tre � %s � modifi� par � %s �"
+msgstr "paramètre « %s » modifié par « %s »"
-#: guc-file.l:496
+#: guc-file.l:494
#, c-format
msgid "configuration file \"%s\" contains errors"
-msgstr "le fichier de configuration � %s � contient des erreurs"
+msgstr "le fichier de configuration « %s » contient des erreurs"
-#: guc-file.l:501
+#: guc-file.l:499
#, c-format
msgid "configuration file \"%s\" contains errors; unaffected changes were applied"
-msgstr "le fichier de configuration � %s � contient des erreurs ; les modifications non affect�es ont �t� appliqu�es"
+msgstr "le fichier de configuration « %s » contient des erreurs ; les modifications non affectées ont été appliquées"
-#: guc-file.l:506
+#: guc-file.l:504
#, c-format
msgid "configuration file \"%s\" contains errors; no changes were applied"
-msgstr "le fichier de configuration � %s � contient des erreurs ; aucune modification n'a �t� appliqu�e"
+msgstr "le fichier de configuration « %s » contient des erreurs ; aucune modification n'a été appliquée"
-#: guc-file.l:579
+#: guc-file.l:577
#, c-format
msgid "could not open configuration file \"%s\": maximum nesting depth exceeded"
msgstr ""
-"n'a pas pu ouvrir le fichier de configuration � %s � : profondeur\n"
-"d'imbrication d�pass�"
+"n'a pas pu ouvrir le fichier de configuration « %s » : profondeur\n"
+"d'imbrication dépassé"
-#: guc-file.l:595 libpq/hba.c:1808
+#: guc-file.l:593 libpq/hba.c:1806
#, c-format
msgid "could not open configuration file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier de configuration � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier de configuration « %s » : %m"
-#: guc-file.l:606
+#: guc-file.l:604
#, c-format
msgid "skipping missing configuration file \"%s\""
-msgstr "ignore le fichier de configuration � %s � manquant"
+msgstr "ignore le fichier de configuration « %s » manquant"
-#: guc-file.l:860
+#: guc-file.l:858
#, c-format
msgid "syntax error in file \"%s\" line %u, near end of line"
-msgstr "erreur de syntaxe dans le fichier � %s �, ligne %u, pr�s de la fin de ligne"
+msgstr "erreur de syntaxe dans le fichier « %s », ligne %u, près de la fin de ligne"
-#: guc-file.l:870
+#: guc-file.l:868
#, c-format
msgid "syntax error in file \"%s\" line %u, near token \"%s\""
-msgstr "erreur de syntaxe dans le fichier � %s �, ligne %u, pr�s du mot cl� � %s �"
+msgstr "erreur de syntaxe dans le fichier « %s », ligne %u, près du mot clé « %s »"
-#: guc-file.l:890
+#: guc-file.l:888
#, c-format
msgid "too many syntax errors found, abandoning file \"%s\""
-msgstr "trop d'erreurs de syntaxe trouv�es, abandon du fichier � %s �"
+msgstr "trop d'erreurs de syntaxe trouvées, abandon du fichier « %s »"
-#: guc-file.l:942
+#: guc-file.l:940
#, c-format
msgid "could not open configuration directory \"%s\": %m"
-msgstr "n'a pas pu ouvrir le r�pertoire de configuration � %s � : %m"
+msgstr "n'a pas pu ouvrir le répertoire de configuration « %s » : %m"
#: lib/stringinfo.c:259
#, c-format
msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes."
-msgstr "Ne peut pas agrandir de %d octets le tampon de cha�ne contenant d�j� %d octets"
+msgstr "Ne peut pas agrandir de %d octets le tampon de chaîne contenant déjà %d octets"
-#: libpq/auth.c:251
+#: libpq/auth.c:254
#, c-format
msgid "authentication failed for user \"%s\": host rejected"
-msgstr "authentification �chou�e pour l'utilisateur � %s � : h�te rejet�"
+msgstr "authentification échouée pour l'utilisateur « %s » : hôte rejeté"
-#: libpq/auth.c:254
+#: libpq/auth.c:257
#, c-format
msgid "\"trust\" authentication failed for user \"%s\""
-msgstr "authentification � trust � �chou�e pour l'utilisateur � %s �"
+msgstr "authentification « trust » échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:257
+#: libpq/auth.c:260
#, c-format
msgid "Ident authentication failed for user \"%s\""
-msgstr "authentification Ident �chou�e pour l'utilisateur � %s �"
+msgstr "authentification Ident échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:260
+#: libpq/auth.c:263
#, c-format
msgid "Peer authentication failed for user \"%s\""
-msgstr "authentification peer �chou�e pour l'utilisateur � %s �"
+msgstr "authentification peer échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:264
+#: libpq/auth.c:267
#, c-format
msgid "password authentication failed for user \"%s\""
-msgstr "authentification par mot de passe �chou�e pour l'utilisateur � %s �"
+msgstr "authentification par mot de passe échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:269
+#: libpq/auth.c:272
#, c-format
msgid "GSSAPI authentication failed for user \"%s\""
-msgstr "authentification GSSAPI �chou�e pour l'utilisateur � %s �"
+msgstr "authentification GSSAPI échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:272
+#: libpq/auth.c:275
#, c-format
msgid "SSPI authentication failed for user \"%s\""
-msgstr "authentification SSPI �chou�e pour l'utilisateur � %s �"
+msgstr "authentification SSPI échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:275
+#: libpq/auth.c:278
#, c-format
msgid "PAM authentication failed for user \"%s\""
-msgstr "authentification PAM �chou�e pour l'utilisateur � %s �"
+msgstr "authentification PAM échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:278
-#, fuzzy, c-format
-#| msgid "SSPI authentication failed for user \"%s\""
+#: libpq/auth.c:281
+#, c-format
msgid "BSD authentication failed for user \"%s\""
-msgstr "authentification SSPI �chou�e pour l'utilisateur � %s �"
+msgstr "authentification BSD échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:281
+#: libpq/auth.c:284
#, c-format
msgid "LDAP authentication failed for user \"%s\""
-msgstr "authentification LDAP �chou�e pour l'utilisateur � %s �"
+msgstr "authentification LDAP échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:284
+#: libpq/auth.c:287
#, c-format
msgid "certificate authentication failed for user \"%s\""
-msgstr "authentification par le certificat �chou�e pour l'utilisateur � %s �"
+msgstr "authentification par le certificat échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:287
+#: libpq/auth.c:290
#, c-format
msgid "RADIUS authentication failed for user \"%s\""
-msgstr "authentification RADIUS �chou�e pour l'utilisateur � %s �"
+msgstr "authentification RADIUS échouée pour l'utilisateur « %s »"
-#: libpq/auth.c:290
+#: libpq/auth.c:293
#, c-format
msgid "authentication failed for user \"%s\": invalid authentication method"
msgstr ""
-"authentification �chou�e pour l'utilisateur � %s � :\n"
-"m�thode d'authentification invalide"
+"authentification échouée pour l'utilisateur « %s » :\n"
+"méthode d'authentification invalide"
-#: libpq/auth.c:294
+#: libpq/auth.c:297
#, c-format
msgid "Connection matched pg_hba.conf line %d: \"%s\""
-msgstr "La connexion correspond � la ligne %d du pg_hba.conf : � %s �"
+msgstr "La connexion correspond à la ligne %d du pg_hba.conf : « %s »"
-#: libpq/auth.c:349
+#: libpq/auth.c:352
#, c-format
msgid "connection requires a valid client certificate"
msgstr "la connexion requiert un certificat client valide"
-#: libpq/auth.c:391
+#: libpq/auth.c:394
#, c-format
msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s"
msgstr ""
-"pg_hba.conf rejette la connexion de la r�plication pour l'h�te � %s �,\n"
-"utilisateur � %s �, %s"
+"pg_hba.conf rejette la connexion de la réplication pour l'hôte « %s »,\n"
+"utilisateur « %s », %s"
-#: libpq/auth.c:393 libpq/auth.c:409 libpq/auth.c:467 libpq/auth.c:485
+#: libpq/auth.c:396 libpq/auth.c:412 libpq/auth.c:470 libpq/auth.c:488
msgid "SSL off"
msgstr "SSL inactif"
-#: libpq/auth.c:393 libpq/auth.c:409 libpq/auth.c:467 libpq/auth.c:485
+#: libpq/auth.c:396 libpq/auth.c:412 libpq/auth.c:470 libpq/auth.c:488
msgid "SSL on"
msgstr "SSL actif"
-#: libpq/auth.c:397
+#: libpq/auth.c:400
#, c-format
msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\""
msgstr ""
-"pg_hba.conf rejette la connexion de la r�plication pour l'h�te � %s �,\n"
-"utilisateur � %s �"
+"pg_hba.conf rejette la connexion de la réplication pour l'hôte « %s »,\n"
+"utilisateur « %s »"
-#: libpq/auth.c:406
+#: libpq/auth.c:409
#, c-format
msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s"
msgstr ""
-"pg_hba.conf rejette la connexion pour l'h�te � %s �, utilisateur � %s �, base\n"
-"de donn�es � %s �, %s"
+"pg_hba.conf rejette la connexion pour l'hôte « %s », utilisateur « %s », base\n"
+"de données « %s », %s"
-#: libpq/auth.c:413
+#: libpq/auth.c:416
#, c-format
msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\""
msgstr ""
-"pg_hba.conf rejette la connexion pour l'h�te � %s �, utilisateur � %s �, base\n"
-"de donn�es � %s �"
+"pg_hba.conf rejette la connexion pour l'hôte « %s », utilisateur « %s », base\n"
+"de données « %s »"
-#: libpq/auth.c:442
+#: libpq/auth.c:445
#, c-format
msgid "Client IP address resolved to \"%s\", forward lookup matches."
-msgstr "Adresse IP du client r�solue en � %s �, la recherche inverse correspond bien."
+msgstr "Adresse IP du client résolue en « %s », la recherche inverse correspond bien."
-#: libpq/auth.c:445
+#: libpq/auth.c:448
#, c-format
msgid "Client IP address resolved to \"%s\", forward lookup not checked."
-msgstr "Adresse IP du client r�solue en � %s �, la recherche inverse n'est pas v�rifi�e."
+msgstr "Adresse IP du client résolue en « %s », la recherche inverse n'est pas vérifiée."
-#: libpq/auth.c:448
+#: libpq/auth.c:451
#, c-format
msgid "Client IP address resolved to \"%s\", forward lookup does not match."
-msgstr "Adresse IP du client r�solue en � %s �, la recherche inverse ne correspond pas."
+msgstr "Adresse IP du client résolue en « %s », la recherche inverse ne correspond pas."
-#: libpq/auth.c:451
+#: libpq/auth.c:454
#, c-format
msgid "Could not translate client host name \"%s\" to IP address: %s."
-msgstr "N'a pas pu traduire le nom d'h�te � %s � du client en adresse IP : %s."
+msgstr "N'a pas pu traduire le nom d'hôte « %s » du client en adresse IP : %s."
-#: libpq/auth.c:456
+#: libpq/auth.c:459
#, c-format
msgid "Could not resolve client IP address to a host name: %s."
-msgstr "N'a pas pu r�soudre l'adresse IP du client � partir du nom d'h�te : %s."
+msgstr "N'a pas pu résoudre l'adresse IP du client à partir du nom d'hôte : %s."
-#: libpq/auth.c:465
+#: libpq/auth.c:468
#, c-format
msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s"
msgstr ""
-"aucune entr�e dans pg_hba.conf pour la connexion de la r�plication � partir de\n"
-"l'h�te � %s �, utilisateur � %s �, %s"
+"aucune entrée dans pg_hba.conf pour la connexion de la réplication à partir de\n"
+"l'hôte « %s », utilisateur « %s », %s"
-#: libpq/auth.c:472
+#: libpq/auth.c:475
#, c-format
msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\""
msgstr ""
-"aucune entr�e dans pg_hba.conf pour la connexion de la r�plication � partir de\n"
-"l'h�te � %s �, utilisateur � %s �"
+"aucune entrée dans pg_hba.conf pour la connexion de la réplication à partir de\n"
+"l'hôte « %s », utilisateur « %s »"
-#: libpq/auth.c:482
+#: libpq/auth.c:485
#, c-format
msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s"
msgstr ""
-"aucune entr�e dans pg_hba.conf pour l'h�te � %s �, utilisateur � %s �,\n"
-"base de donn�es � %s �, %s"
+"aucune entrée dans pg_hba.conf pour l'hôte « %s », utilisateur « %s »,\n"
+"base de données « %s », %s"
-#: libpq/auth.c:490
+#: libpq/auth.c:493
#, c-format
msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\""
msgstr ""
-"aucune entr�e dans pg_hba.conf pour l'h�te � %s �, utilisateur � %s �,\n"
-"base de donn�es � %s �"
+"aucune entrée dans pg_hba.conf pour l'hôte « %s », utilisateur « %s »,\n"
+"base de données « %s »"
-#: libpq/auth.c:533 libpq/hba.c:1180
+#: libpq/auth.c:536 libpq/hba.c:1178
#, c-format
msgid "MD5 authentication is not supported when \"db_user_namespace\" is enabled"
-msgstr "l'authentification MD5 n'est pas support�e quand � db_user_namespace � est activ�"
+msgstr "l'authentification MD5 n'est pas supportée quand « db_user_namespace » est activé"
-#: libpq/auth.c:667
+#: libpq/auth.c:670
#, c-format
msgid "expected password response, got message type %d"
-msgstr "en attente du mot de passe, a re�u un type de message %d"
+msgstr "en attente du mot de passe, a reçu un type de message %d"
-#: libpq/auth.c:695
+#: libpq/auth.c:698
#, c-format
msgid "invalid password packet size"
msgstr "taille du paquet du mot de passe invalide"
-#: libpq/auth.c:825
+#: libpq/auth.c:828
#, c-format
msgid "GSSAPI is not supported in protocol version 2"
-msgstr "GSSAPI n'est pas support� dans le protocole de version 2"
+msgstr "GSSAPI n'est pas supporté dans le protocole de version 2"
-#: libpq/auth.c:885
+#: libpq/auth.c:888
#, c-format
msgid "expected GSS response, got message type %d"
-msgstr "en attente d'une r�ponse GSS, a re�u un message de type %d"
+msgstr "en attente d'une réponse GSS, a reçu un message de type %d"
-#: libpq/auth.c:946
+#: libpq/auth.c:949
msgid "accepting GSS security context failed"
-msgstr "�chec de l'acceptation du contexte de s�curit� GSS"
+msgstr "échec de l'acceptation du contexte de sécurité GSS"
-#: libpq/auth.c:972
+#: libpq/auth.c:975
msgid "retrieving GSS user name failed"
-msgstr "�chec lors de la r�cup�ration du nom de l'utilisateur avec GSS"
+msgstr "échec lors de la récupération du nom de l'utilisateur avec GSS"
-#: libpq/auth.c:1091
+#: libpq/auth.c:1094
#, c-format
msgid "SSPI is not supported in protocol version 2"
-msgstr "SSPI n'est pas support� dans le protocole de version 2"
+msgstr "SSPI n'est pas supporté dans le protocole de version 2"
-#: libpq/auth.c:1106
+#: libpq/auth.c:1109
msgid "could not acquire SSPI credentials"
-msgstr "n'a pas pu obtenir les pi�ces d'identit� SSPI"
+msgstr "n'a pas pu obtenir les pièces d'identité SSPI"
-#: libpq/auth.c:1124
+#: libpq/auth.c:1127
#, c-format
msgid "expected SSPI response, got message type %d"
-msgstr "en attente d'une r�ponse SSPI, a re�u un message de type %d"
+msgstr "en attente d'une réponse SSPI, a reçu un message de type %d"
-#: libpq/auth.c:1196
+#: libpq/auth.c:1199
msgid "could not accept SSPI security context"
-msgstr "n'a pas pu accepter le contexte de s�curit� SSPI"
+msgstr "n'a pas pu accepter le contexte de sécurité SSPI"
-#: libpq/auth.c:1258
+#: libpq/auth.c:1261
msgid "could not get token from SSPI security context"
-msgstr "n'a pas pu obtenir le jeton du contexte de s�curit� SSPI"
+msgstr "n'a pas pu obtenir le jeton du contexte de sécurité SSPI"
-#: libpq/auth.c:1377 libpq/auth.c:1396
-#, fuzzy, c-format
-#| msgid "could not parse file name \"%s\""
+#: libpq/auth.c:1380 libpq/auth.c:1399
+#, c-format
msgid "could not translate name"
-msgstr "n'a pas pu analyser le mode du fichier � %s �"
+msgstr "n'a pas pu traduit le nom"
-#: libpq/auth.c:1409
-#, fuzzy, c-format
-#| msgid "channel name too long"
+#: libpq/auth.c:1412
+#, c-format
msgid "realm name too long"
-msgstr "nom du canal trop long"
+msgstr "nom du royaume trop long"
-#: libpq/auth.c:1424
-#, fuzzy, c-format
-#| msgid "encoding name too long"
+#: libpq/auth.c:1427
+#, c-format
msgid "translated account name too long"
-msgstr "nom d'encodage trop long"
+msgstr "traduction du nom de compte trop longue"
-#: libpq/auth.c:1610
+#: libpq/auth.c:1613
#, c-format
msgid "could not create socket for Ident connection: %m"
-msgstr "n'a pas pu cr�er le socket pour la connexion Ident : %m"
+msgstr "n'a pas pu créer le socket pour la connexion Ident : %m"
-#: libpq/auth.c:1625
+#: libpq/auth.c:1628
#, c-format
msgid "could not bind to local address \"%s\": %m"
-msgstr "n'a pas pu se lier � l'adresse locale � %s � : %m"
+msgstr "n'a pas pu se lier à l'adresse locale « %s » : %m"
-#: libpq/auth.c:1637
+#: libpq/auth.c:1640
#, c-format
msgid "could not connect to Ident server at address \"%s\", port %s: %m"
-msgstr "n'a pas pu se connecter au serveur Ident � l'adresse � %s �, port %s : %m"
+msgstr "n'a pas pu se connecter au serveur Ident à l'adresse « %s », port %s : %m"
-#: libpq/auth.c:1659
+#: libpq/auth.c:1662
#, c-format
msgid "could not send query to Ident server at address \"%s\", port %s: %m"
-msgstr "n'a pas pu envoyer la requ�te au serveur Ident � l'adresse � %s �, port %s : %m"
+msgstr "n'a pas pu envoyer la requête au serveur Ident à l'adresse « %s », port %s : %m"
-#: libpq/auth.c:1676
+#: libpq/auth.c:1679
#, c-format
msgid "could not receive response from Ident server at address \"%s\", port %s: %m"
msgstr ""
-"n'a pas pu recevoir la r�ponse du serveur Ident � l'adresse � %s �, port %s :\n"
+"n'a pas pu recevoir la réponse du serveur Ident à l'adresse « %s », port %s :\n"
"%m"
-#: libpq/auth.c:1686
+#: libpq/auth.c:1689
#, c-format
msgid "invalidly formatted response from Ident server: \"%s\""
-msgstr "r�ponse mal format�e du serveur Ident : � %s �"
+msgstr "réponse mal formatée du serveur Ident : « %s »"
-#: libpq/auth.c:1726
+#: libpq/auth.c:1729
#, c-format
msgid "peer authentication is not supported on this platform"
-msgstr "la m�thode d'authentification �peer n'est pas support�e sur cette plateforme"
+msgstr "la méthode d'authentification «peer n'est pas supportée sur cette plateforme"
-#: libpq/auth.c:1730
+#: libpq/auth.c:1733
#, c-format
msgid "could not get peer credentials: %m"
msgstr "n'a pas pu obtenir l'authentification de l'autre : %m"
-#: libpq/auth.c:1739
+#: libpq/auth.c:1742
#, c-format
msgid "could not look up local user ID %ld: %s"
msgstr "n'a pas pu rechercher l'identifiant %ld de l'utilisateur local : %s"
-#: libpq/auth.c:1823 libpq/auth.c:2149 libpq/auth.c:2509
+#: libpq/auth.c:1826 libpq/auth.c:2152 libpq/auth.c:2512
#, c-format
msgid "empty password returned by client"
-msgstr "mot de passe vide renvoy� par le client"
+msgstr "mot de passe vide renvoyé par le client"
-#: libpq/auth.c:1833
+#: libpq/auth.c:1836
#, c-format
msgid "error from underlying PAM layer: %s"
msgstr "erreur provenant de la couche PAM : %s"
-#: libpq/auth.c:1914
+#: libpq/auth.c:1917
#, c-format
msgid "could not create PAM authenticator: %s"
-msgstr "n'a pas pu cr�er l'authenticateur PAM : %s"
+msgstr "n'a pas pu créer l'authenticateur PAM : %s"
-#: libpq/auth.c:1925
+#: libpq/auth.c:1928
#, c-format
msgid "pam_set_item(PAM_USER) failed: %s"
-msgstr "pam_set_item(PAM_USER) a �chou� : %s"
+msgstr "pam_set_item(PAM_USER) a échoué : %s"
-#: libpq/auth.c:1936
-#, fuzzy, c-format
-#| msgid "pam_set_item(PAM_USER) failed: %s"
+#: libpq/auth.c:1939
+#, c-format
msgid "pam_set_item(PAM_RHOST) failed: %s"
-msgstr "pam_set_item(PAM_USER) a �chou� : %s"
+msgstr "pam_set_item(PAM_RHOST) a échoué : %s"
-#: libpq/auth.c:1947
+#: libpq/auth.c:1950
#, c-format
msgid "pam_set_item(PAM_CONV) failed: %s"
-msgstr "pam_set_item(PAM_CONV) a �chou� : %s"
+msgstr "pam_set_item(PAM_CONV) a échoué : %s"
-#: libpq/auth.c:1958
+#: libpq/auth.c:1961
#, c-format
msgid "pam_authenticate failed: %s"
-msgstr "pam_authenticate a �chou� : %s"
+msgstr "pam_authenticate a échoué : %s"
-#: libpq/auth.c:1969
+#: libpq/auth.c:1972
#, c-format
msgid "pam_acct_mgmt failed: %s"
-msgstr "pam_acct_mgmt a �chou� : %s"
+msgstr "pam_acct_mgmt a échoué : %s"
-#: libpq/auth.c:1980
+#: libpq/auth.c:1983
#, c-format
msgid "could not release PAM authenticator: %s"
msgstr "n'a pas pu fermer l'authenticateur PAM : %s"
-#: libpq/auth.c:2045
+#: libpq/auth.c:2048
#, c-format
msgid "could not initialize LDAP: %m"
msgstr "n'a pas pu initialiser LDAP : %m"
-#: libpq/auth.c:2048
+#: libpq/auth.c:2051
#, c-format
msgid "could not initialize LDAP: error code %d"
msgstr "n'a pas pu initialiser LDAP : code d'erreur %d"
-#: libpq/auth.c:2058
+#: libpq/auth.c:2061
#, c-format
msgid "could not set LDAP protocol version: %s"
msgstr "n'a pas pu initialiser la version du protocole LDAP : %s"
-#: libpq/auth.c:2087
+#: libpq/auth.c:2090
#, c-format
msgid "could not load wldap32.dll"
msgstr "n'a pas pu charger wldap32.dll"
-#: libpq/auth.c:2095
+#: libpq/auth.c:2098
#, c-format
msgid "could not load function _ldap_start_tls_sA in wldap32.dll"
msgstr "n'a pas pu charger la fonction _ldap_start_tls_sA de wldap32.dll"
-#: libpq/auth.c:2096
+#: libpq/auth.c:2099
#, c-format
msgid "LDAP over SSL is not supported on this platform."
-msgstr "LDAP via SSL n'est pas support� sur cette plateforme."
+msgstr "LDAP via SSL n'est pas supporté sur cette plateforme."
-#: libpq/auth.c:2111
+#: libpq/auth.c:2114
#, c-format
msgid "could not start LDAP TLS session: %s"
-msgstr "n'a pas pu d�marrer la session TLS LDAP : %s"
+msgstr "n'a pas pu démarrer la session TLS LDAP : %s"
-#: libpq/auth.c:2133
+#: libpq/auth.c:2136
#, c-format
msgid "LDAP server not specified"
-msgstr "serveur LDAP non pr�cis�"
+msgstr "serveur LDAP non précisé"
-#: libpq/auth.c:2186
+#: libpq/auth.c:2189
#, c-format
msgid "invalid character in user name for LDAP authentication"
-msgstr "caract�re invalide dans le nom de l'utilisateur pour l'authentification LDAP"
+msgstr "caractère invalide dans le nom de l'utilisateur pour l'authentification LDAP"
-#: libpq/auth.c:2201
+#: libpq/auth.c:2204
#, c-format
msgid "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s"
-msgstr "n'a pas pu r�aliser le lien LDAP initiale pour ldapbinddn � %s � sur le serveur � %s � : %s"
+msgstr "n'a pas pu réaliser le lien LDAP initiale pour ldapbinddn « %s » sur le serveur « %s » : %s"
-#: libpq/auth.c:2225
+#: libpq/auth.c:2228
#, c-format
msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s"
-msgstr "n'a pas pu rechercher dans LDAP pour filtrer � %s � sur le serveur � %s � : %s"
+msgstr "n'a pas pu rechercher dans LDAP pour filtrer « %s » sur le serveur « %s » : %s"
-#: libpq/auth.c:2236
+#: libpq/auth.c:2239
#, c-format
msgid "LDAP user \"%s\" does not exist"
-msgstr "l'utilisateur LDAP � %s � n'existe pas"
+msgstr "l'utilisateur LDAP « %s » n'existe pas"
-#: libpq/auth.c:2237
+#: libpq/auth.c:2240
#, c-format
msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries."
-msgstr "la recherche LDAP pour le filtre � %s � sur le serveur � %s � n'a renvoy� aucun enregistrement."
+msgstr "la recherche LDAP pour le filtre « %s » sur le serveur « %s » n'a renvoyé aucun enregistrement."
-#: libpq/auth.c:2241
+#: libpq/auth.c:2244
#, c-format
msgid "LDAP user \"%s\" is not unique"
-msgstr "l'utilisateur LDAP � %s � n'est pas unique"
+msgstr "l'utilisateur LDAP « %s » n'est pas unique"
-#: libpq/auth.c:2242
+#: libpq/auth.c:2245
#, c-format
msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry."
msgid_plural "LDAP search for filter \"%s\" on server \"%s\" returned %d entries."
-msgstr[0] "la recherche LDAP pour le filtre � %s � sur le serveur � %s � a renvoy� %d enregistrement."
-msgstr[1] "la recherche LDAP pour le filtre � %s � sur le serveur � %s � a renvoy� %d enregistrements."
+msgstr[0] "la recherche LDAP pour le filtre « %s » sur le serveur « %s » a renvoyé %d enregistrement."
+msgstr[1] "la recherche LDAP pour le filtre « %s » sur le serveur « %s » a renvoyé %d enregistrements."
-#: libpq/auth.c:2260
+#: libpq/auth.c:2263
#, c-format
msgid "could not get dn for the first entry matching \"%s\" on server \"%s\": %s"
msgstr ""
-"n'a pas pu obtenir le dn pour la premi�re entr�e correspondante � %s � sur\n"
-"le serveur � %s � : %s"
+"n'a pas pu obtenir le dn pour la première entrée correspondante « %s » sur\n"
+"le serveur « %s » : %s"
-#: libpq/auth.c:2280
+#: libpq/auth.c:2283
#, c-format
msgid "could not unbind after searching for user \"%s\" on server \"%s\": %s"
msgstr ""
-"n'a pas pu ex�cuter le unbind apr�s la recherche de l'utilisateur � %s �\n"
-"sur le serveur � %s � : %s"
+"n'a pas pu exécuter le unbind après la recherche de l'utilisateur « %s »\n"
+"sur le serveur « %s » : %s"
-#: libpq/auth.c:2310
+#: libpq/auth.c:2313
#, c-format
msgid "LDAP login failed for user \"%s\" on server \"%s\": %s"
-msgstr "�chec de connexion LDAP pour l'utilisateur � %s � sur le serveur � %s � : %s"
+msgstr "échec de connexion LDAP pour l'utilisateur « %s » sur le serveur « %s » : %s"
-#: libpq/auth.c:2338
+#: libpq/auth.c:2341
#, c-format
msgid "certificate authentication failed for user \"%s\": client certificate contains no user name"
msgstr ""
-"l'authentification par le certificat a �chou� pour l'utilisateur � %s � :\n"
+"l'authentification par le certificat a échoué pour l'utilisateur « %s » :\n"
"le certificat du client ne contient aucun nom d'utilisateur"
-#: libpq/auth.c:2465
+#: libpq/auth.c:2468
#, c-format
msgid "RADIUS server not specified"
-msgstr "serveur RADIUS non pr�cis�"
+msgstr "serveur RADIUS non précisé"
-#: libpq/auth.c:2472
+#: libpq/auth.c:2475
#, c-format
msgid "RADIUS secret not specified"
-msgstr "secret RADIUS non pr�cis�"
+msgstr "secret RADIUS non précisé"
-#: libpq/auth.c:2488 libpq/hba.c:1634
+#: libpq/auth.c:2491 libpq/hba.c:1632
#, c-format
msgid "could not translate RADIUS server name \"%s\" to address: %s"
-msgstr "n'a pas pu traduire le nom du serveur RADIUS � %s � en une adresse : %s"
+msgstr "n'a pas pu traduire le nom du serveur RADIUS « %s » en une adresse : %s"
-#: libpq/auth.c:2516
-#, fuzzy, c-format
-#| msgid "RADIUS authentication does not support passwords longer than 16 characters"
+#: libpq/auth.c:2519
+#, c-format
msgid "RADIUS authentication does not support passwords longer than %d characters"
msgstr ""
-"l'authentification RADIUS ne supporte pas les mots de passe de plus de 16\n"
-"caract�res"
+"l'authentification RADIUS ne supporte pas les mots de passe de plus de %d\n"
+"caractères"
-#: libpq/auth.c:2528
+#: libpq/auth.c:2531
#, c-format
msgid "could not generate random encryption vector"
-msgstr "n'a pas pu g�n�rer le vecteur de chiffrement al�atoire"
+msgstr "n'a pas pu générer le vecteur de chiffrement aléatoire"
-#: libpq/auth.c:2563
+#: libpq/auth.c:2569
#, c-format
msgid "could not perform MD5 encryption of password"
-msgstr "n'a pas pu r�aliser le chiffrement MD5 du mot de passe"
+msgstr "n'a pas pu réaliser le chiffrement MD5 du mot de passe"
-#: libpq/auth.c:2588
+#: libpq/auth.c:2594
#, c-format
msgid "could not create RADIUS socket: %m"
-msgstr "n'a pas pu cr�er le socket RADIUS : %m"
+msgstr "n'a pas pu créer le socket RADIUS : %m"
-#: libpq/auth.c:2609
+#: libpq/auth.c:2615
#, c-format
msgid "could not bind local RADIUS socket: %m"
-msgstr "n'a pas pu se lier � la socket RADIUS : %m"
+msgstr "n'a pas pu se lier à la socket RADIUS : %m"
-#: libpq/auth.c:2619
+#: libpq/auth.c:2625
#, c-format
msgid "could not send RADIUS packet: %m"
msgstr "n'a pas pu transmettre le paquet RADIUS : %m"
-#: libpq/auth.c:2652 libpq/auth.c:2677
+#: libpq/auth.c:2658 libpq/auth.c:2683
#, c-format
msgid "timeout waiting for RADIUS response"
-msgstr "d�passement du d�lai pour la r�ponse du RADIUS"
+msgstr "dépassement du délai pour la réponse du RADIUS"
-#: libpq/auth.c:2670
+#: libpq/auth.c:2676
#, c-format
msgid "could not check status on RADIUS socket: %m"
-msgstr "n'a pas pu v�rifier le statut sur la socket RADIUS : %m"
+msgstr "n'a pas pu vérifier le statut sur la socket RADIUS : %m"
-#: libpq/auth.c:2699
+#: libpq/auth.c:2705
#, c-format
msgid "could not read RADIUS response: %m"
-msgstr "n'a pas pu lire la r�ponse RADIUS : %m"
+msgstr "n'a pas pu lire la réponse RADIUS : %m"
-#: libpq/auth.c:2711 libpq/auth.c:2715
+#: libpq/auth.c:2717 libpq/auth.c:2721
#, c-format
msgid "RADIUS response was sent from incorrect port: %d"
-msgstr "la r�ponse RADIUS a �t� envoy�e � partir d'un mauvais port : %d"
+msgstr "la réponse RADIUS a été envoyée à partir d'un mauvais port : %d"
-#: libpq/auth.c:2724
+#: libpq/auth.c:2730
#, c-format
msgid "RADIUS response too short: %d"
-msgstr "r�ponse RADIUS trop courte : %d"
+msgstr "réponse RADIUS trop courte : %d"
-#: libpq/auth.c:2731
+#: libpq/auth.c:2737
#, c-format
msgid "RADIUS response has corrupt length: %d (actual length %d)"
-msgstr "la r�ponse RADIUS a une longueur corrompue : %d (longueur actuelle %d)"
+msgstr "la réponse RADIUS a une longueur corrompue : %d (longueur actuelle %d)"
-#: libpq/auth.c:2739
+#: libpq/auth.c:2745
#, c-format
msgid "RADIUS response is to a different request: %d (should be %d)"
-msgstr "la r�ponse RADIUS correspond � une demande diff�rente : %d (devrait �tre %d)"
+msgstr "la réponse RADIUS correspond à une demande différente : %d (devrait être %d)"
-#: libpq/auth.c:2764
+#: libpq/auth.c:2770
#, c-format
msgid "could not perform MD5 encryption of received packet"
-msgstr "n'a pas pu r�aliser le chiffrement MD5 du paquet re�u"
+msgstr "n'a pas pu réaliser le chiffrement MD5 du paquet reçu"
-#: libpq/auth.c:2773
+#: libpq/auth.c:2779
#, c-format
msgid "RADIUS response has incorrect MD5 signature"
-msgstr "la r�ponse RADIUS a une signature MD5 erron�e"
+msgstr "la réponse RADIUS a une signature MD5 erronée"
-#: libpq/auth.c:2790
+#: libpq/auth.c:2796
#, c-format
msgid "RADIUS response has invalid code (%d) for user \"%s\""
-msgstr "la r�ponse RADIUS a un code invalide (%d) pour l'utilisateur � %s �"
+msgstr "la réponse RADIUS a un code invalide (%d) pour l'utilisateur « %s »"
-#: libpq/be-fsstubs.c:134 libpq/be-fsstubs.c:165 libpq/be-fsstubs.c:199 libpq/be-fsstubs.c:239 libpq/be-fsstubs.c:264 libpq/be-fsstubs.c:312 libpq/be-fsstubs.c:335 libpq/be-fsstubs.c:583
+#: libpq/be-fsstubs.c:132 libpq/be-fsstubs.c:163 libpq/be-fsstubs.c:197 libpq/be-fsstubs.c:237 libpq/be-fsstubs.c:262 libpq/be-fsstubs.c:310 libpq/be-fsstubs.c:333 libpq/be-fsstubs.c:581
#, c-format
msgid "invalid large-object descriptor: %d"
-msgstr "descripteur invalide de � Large Object � : %d"
+msgstr "descripteur invalide de « Large Object » : %d"
-#: libpq/be-fsstubs.c:180 libpq/be-fsstubs.c:218 libpq/be-fsstubs.c:602 libpq/be-fsstubs.c:790
+#: libpq/be-fsstubs.c:178 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:600 libpq/be-fsstubs.c:788
#, c-format
msgid "permission denied for large object %u"
-msgstr "droit refus� pour le Large Object %u"
+msgstr "droit refusé pour le Large Object %u"
-#: libpq/be-fsstubs.c:205 libpq/be-fsstubs.c:589
+#: libpq/be-fsstubs.c:203 libpq/be-fsstubs.c:587
#, c-format
msgid "large object descriptor %d was not opened for writing"
-msgstr "le descripteur %d du � Large Object � n'a pas �t� ouvert pour l'�criture"
+msgstr "le descripteur %d du « Large Object » n'a pas été ouvert pour l'écriture"
-#: libpq/be-fsstubs.c:247
+#: libpq/be-fsstubs.c:245
#, c-format
msgid "lo_lseek result out of range for large-object descriptor %d"
-msgstr "r�sultat de lo_lseek en dehors de l'intervalle pour le descripteur de Large Object %d"
+msgstr "résultat de lo_lseek en dehors de l'intervalle pour le descripteur de Large Object %d"
-#: libpq/be-fsstubs.c:320
+#: libpq/be-fsstubs.c:318
#, c-format
msgid "lo_tell result out of range for large-object descriptor %d"
-msgstr "r�sultat de lo_tell en dehors de l'intervalle pour le descripteur de Large Object %d"
+msgstr "résultat de lo_tell en dehors de l'intervalle pour le descripteur de Large Object %d"
-#: libpq/be-fsstubs.c:457
+#: libpq/be-fsstubs.c:455
#, c-format
msgid "must be superuser to use server-side lo_import()"
-msgstr "doit �tre super-utilisateur pour utiliser lo_import() du c�t� serveur"
+msgstr "doit être super-utilisateur pour utiliser lo_import() du côté serveur"
-#: libpq/be-fsstubs.c:458
+#: libpq/be-fsstubs.c:456
#, c-format
msgid "Anyone can use the client-side lo_import() provided by libpq."
-msgstr "Tout le monde peut utiliser lo_import(), fourni par libpq, du c�t� client."
+msgstr "Tout le monde peut utiliser lo_import(), fourni par libpq, du côté client."
-#: libpq/be-fsstubs.c:471
+#: libpq/be-fsstubs.c:469
#, c-format
msgid "could not open server file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier serveur � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier serveur « %s » : %m"
-#: libpq/be-fsstubs.c:493
+#: libpq/be-fsstubs.c:491
#, c-format
msgid "could not read server file \"%s\": %m"
-msgstr "n'a pas pu lire le fichier serveur � %s � : %m"
+msgstr "n'a pas pu lire le fichier serveur « %s » : %m"
-#: libpq/be-fsstubs.c:523
+#: libpq/be-fsstubs.c:521
#, c-format
msgid "must be superuser to use server-side lo_export()"
-msgstr "doit �tre super-utilisateur pour utiliser lo_export() du c�t� serveur"
+msgstr "doit être super-utilisateur pour utiliser lo_export() du côté serveur"
-#: libpq/be-fsstubs.c:524
+#: libpq/be-fsstubs.c:522
#, c-format
msgid "Anyone can use the client-side lo_export() provided by libpq."
-msgstr "Tout le monde peut utiliser lo_export(), fournie par libpq, du c�t� client."
+msgstr "Tout le monde peut utiliser lo_export(), fournie par libpq, du côté client."
-#: libpq/be-fsstubs.c:549
+#: libpq/be-fsstubs.c:547
#, c-format
msgid "could not create server file \"%s\": %m"
-msgstr "n'a pas pu cr�er le fichier serveur � %s � : %m"
+msgstr "n'a pas pu créer le fichier serveur « %s » : %m"
-#: libpq/be-fsstubs.c:561
+#: libpq/be-fsstubs.c:559
#, c-format
msgid "could not write server file \"%s\": %m"
-msgstr "n'a pas pu �crire le fichier serveur � %s � : %m"
+msgstr "n'a pas pu écrire le fichier serveur « %s » : %m"
-#: libpq/be-fsstubs.c:815
+#: libpq/be-fsstubs.c:813
#, c-format
msgid "large object read request is too large"
msgstr "la demande de lecture du Large Object est trop grande"
-#: libpq/be-fsstubs.c:857 utils/adt/genfile.c:211 utils/adt/genfile.c:252
+#: libpq/be-fsstubs.c:855 utils/adt/genfile.c:211 utils/adt/genfile.c:252
#, c-format
msgid "requested length cannot be negative"
-msgstr "la longueur demand�e ne peut pas �tre n�gative"
+msgstr "la longueur demandée ne peut pas être négative"
-#: libpq/be-secure-openssl.c:184
+#: libpq/be-secure-openssl.c:189
#, c-format
msgid "could not create SSL context: %s"
-msgstr "n'a pas pu cr�er le contexte SSL : %s"
+msgstr "n'a pas pu créer le contexte SSL : %s"
-#: libpq/be-secure-openssl.c:200
+#: libpq/be-secure-openssl.c:205
#, c-format
msgid "could not load server certificate file \"%s\": %s"
-msgstr "n'a pas pu charger le fichier du certificat serveur � %s � : %s"
+msgstr "n'a pas pu charger le fichier du certificat serveur « %s » : %s"
-#: libpq/be-secure-openssl.c:206
+#: libpq/be-secure-openssl.c:211
#, c-format
msgid "could not access private key file \"%s\": %m"
-msgstr "n'a pas pu acc�der au fichier de la cl� priv�e � %s � : %m"
+msgstr "n'a pas pu accéder au fichier de la clé privée « %s » : %m"
-#: libpq/be-secure-openssl.c:212
-#, fuzzy, c-format
-#| msgid "%s: file \"%s\" is not a regular file\n"
+#: libpq/be-secure-openssl.c:217
+#, c-format
msgid "private key file \"%s\" is not a regular file"
-msgstr "%s : � %s � n'est pas un fichier\n"
+msgstr "le fichier de clé privée « %s » n'est pas un fichier"
-#: libpq/be-secure-openssl.c:224
+#: libpq/be-secure-openssl.c:229
#, c-format
msgid "private key file \"%s\" must be owned by the database user or root"
-msgstr ""
+msgstr "le fichier de clé privée « %s » doit avoir le même propriétaire que la base de donnée ou root"
-#: libpq/be-secure-openssl.c:244
+#: libpq/be-secure-openssl.c:249
#, c-format
msgid "private key file \"%s\" has group or world access"
msgstr ""
-"le fichier de cl� priv� � %s � est accessible par le groupe et/ou par les\n"
+"le fichier de clé privé « %s » est accessible par le groupe et/ou par les\n"
"autres"
-#: libpq/be-secure-openssl.c:246
+#: libpq/be-secure-openssl.c:251
#, c-format
msgid "File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root."
msgstr ""
+"Le fichier doit avoir les permissions u=rw (0600) ou moins si le propriétaire est le même que la base de données,\n"
+"ou les permissions u=rw,g=r (0640) ou moins si le propriétaire est root."
-#: libpq/be-secure-openssl.c:253
+#: libpq/be-secure-openssl.c:258
#, c-format
msgid "could not load private key file \"%s\": %s"
-msgstr "n'a pas pu charger le fichier de cl� priv�e � %s � : %s"
+msgstr "n'a pas pu charger le fichier de clé privée « %s » : %s"
-#: libpq/be-secure-openssl.c:258
+#: libpq/be-secure-openssl.c:263
#, c-format
msgid "check of private key failed: %s"
-msgstr "�chec de la v�rification de la cl� priv�e : %s"
+msgstr "échec de la vérification de la clé privée : %s"
-#: libpq/be-secure-openssl.c:287
+#: libpq/be-secure-openssl.c:292
#, c-format
msgid "could not load root certificate file \"%s\": %s"
-msgstr "n'a pas pu charger le fichier du certificat racine � %s � : %s"
+msgstr "n'a pas pu charger le fichier du certificat racine « %s » : %s"
-#: libpq/be-secure-openssl.c:311
+#: libpq/be-secure-openssl.c:316
#, c-format
msgid "SSL certificate revocation list file \"%s\" ignored"
-msgstr "liste de r�vocation des certificats SSL � %s � ignor�e"
+msgstr "liste de révocation des certificats SSL « %s » ignorée"
-#: libpq/be-secure-openssl.c:313
+#: libpq/be-secure-openssl.c:318
#, c-format
msgid "SSL library does not support certificate revocation lists."
-msgstr "La biblioth�que SSL ne supporte pas les listes de r�vocation des certificats."
+msgstr "La bibliothèque SSL ne supporte pas les listes de révocation des certificats."
-#: libpq/be-secure-openssl.c:318
+#: libpq/be-secure-openssl.c:323
#, c-format
msgid "could not load SSL certificate revocation list file \"%s\": %s"
-msgstr "n'a pas pu charger le fichier de liste de r�vocation des certificats SSL (� %s �) : %s"
+msgstr "n'a pas pu charger le fichier de liste de révocation des certificats SSL (« %s ») : %s"
-#: libpq/be-secure-openssl.c:365
+#: libpq/be-secure-openssl.c:370
#, c-format
msgid "could not initialize SSL connection: %s"
msgstr "n'a pas pu initialiser la connexion SSL : %s"
-#: libpq/be-secure-openssl.c:373
+#: libpq/be-secure-openssl.c:378
#, c-format
msgid "could not set SSL socket: %s"
-msgstr "n'a pas pu cr�er le socket SSL : %s"
+msgstr "n'a pas pu créer le socket SSL : %s"
-#: libpq/be-secure-openssl.c:427
+#: libpq/be-secure-openssl.c:432
#, c-format
msgid "could not accept SSL connection: %m"
msgstr "n'a pas pu accepter la connexion SSL : %m"
-#: libpq/be-secure-openssl.c:431 libpq/be-secure-openssl.c:442
+#: libpq/be-secure-openssl.c:436 libpq/be-secure-openssl.c:447
#, c-format
msgid "could not accept SSL connection: EOF detected"
-msgstr "n'a pas pu accepter la connexion SSL : fin de fichier d�tect�"
+msgstr "n'a pas pu accepter la connexion SSL : fin de fichier détecté"
-#: libpq/be-secure-openssl.c:436
+#: libpq/be-secure-openssl.c:441
#, c-format
msgid "could not accept SSL connection: %s"
msgstr "n'a pas pu accepter la connexion SSL : %s"
-#: libpq/be-secure-openssl.c:447 libpq/be-secure-openssl.c:588 libpq/be-secure-openssl.c:648
+#: libpq/be-secure-openssl.c:452 libpq/be-secure-openssl.c:593 libpq/be-secure-openssl.c:653
#, c-format
msgid "unrecognized SSL error code: %d"
msgstr "code d'erreur SSL inconnu : %d"
-#: libpq/be-secure-openssl.c:491
+#: libpq/be-secure-openssl.c:496
#, c-format
msgid "SSL certificate's common name contains embedded null"
msgstr "le nom commun du certificat SSL contient des NULL"
-#: libpq/be-secure-openssl.c:502
+#: libpq/be-secure-openssl.c:507
#, c-format
msgid "SSL connection from \"%s\""
-msgstr "connexion SSL de � %s �"
+msgstr "connexion SSL de « %s »"
-#: libpq/be-secure-openssl.c:579 libpq/be-secure-openssl.c:639
+#: libpq/be-secure-openssl.c:584 libpq/be-secure-openssl.c:644
#, c-format
msgid "SSL error: %s"
msgstr "erreur SSL : %s"
-#: libpq/be-secure-openssl.c:988
+#: libpq/be-secure-openssl.c:1055
#, c-format
msgid "ECDH: unrecognized curve name: %s"
msgstr "ECDH : nome de courbe non reconnu : %s"
-#: libpq/be-secure-openssl.c:993
+#: libpq/be-secure-openssl.c:1060
#, c-format
msgid "ECDH: could not create key"
-msgstr "ECDH : n'a pas pu cr�er la cl�"
+msgstr "ECDH : n'a pas pu créer la clé"
-#: libpq/be-secure-openssl.c:1017
+#: libpq/be-secure-openssl.c:1084
msgid "no SSL error reported"
-msgstr "aucune erreur SSL report�e"
+msgstr "aucune erreur SSL reportée"
-#: libpq/be-secure-openssl.c:1021
+#: libpq/be-secure-openssl.c:1088
#, c-format
msgid "SSL error code %lu"
msgstr "erreur SSL %lu"
#: libpq/be-secure.c:171 libpq/be-secure.c:256
-#, fuzzy, c-format
-#| msgid "terminating connection due to administrator command"
+#, c-format
msgid "terminating connection due to unexpected postmaster exit"
-msgstr "arr�t des connexions suite � la demande de l'administrateur"
+msgstr "arrêt des connexions suite à un arrêt inatendu du postmaster"
#: libpq/crypt.c:54
-#, fuzzy, c-format
-#| msgid "role \"%s\" does not exist"
+#, c-format
msgid "Role \"%s\" does not exist."
-msgstr "le r�le � %s � n'existe pas"
+msgstr "Le rôle « %s » n'existe pas"
#: libpq/crypt.c:64
#, c-format
msgid "User \"%s\" has no password assigned."
-msgstr "L'utilisateur � %s � n'a pas de mot de passe affect�."
+msgstr "L'utilisateur « %s » n'a pas de mot de passe affecté."
#: libpq/crypt.c:79
-#, fuzzy, c-format
-#| msgid "User \"%s\" has an expired password."
+#, c-format
msgid "User \"%s\" has an empty password."
-msgstr "L'utilisateur � %s � a un mot de passe expir�."
+msgstr "L'utilisateur « %s » a un mot de passe vide."
#: libpq/crypt.c:159
#, c-format
msgid "User \"%s\" has an expired password."
-msgstr "L'utilisateur � %s � a un mot de passe expir�."
+msgstr "L'utilisateur « %s » a un mot de passe expiré."
#: libpq/crypt.c:167
-#, fuzzy, c-format
-#| msgid "Password for user %s: "
+#, c-format
msgid "Password does not match for user \"%s\"."
-msgstr "Mot de passe pour l'utilisateur %s : "
+msgstr "Mot de passe ne correspond pas pour l'utilisateur %s : "
#: libpq/hba.c:188
#, c-format
msgid "authentication file token too long, skipping: \"%s\""
-msgstr "jeton du fichier d'authentification trop long, ignore : � %s �"
+msgstr "jeton du fichier d'authentification trop long, ignore : « %s »"
#: libpq/hba.c:332
#, c-format
msgid "could not open secondary authentication file \"@%s\" as \"%s\": %m"
msgstr ""
-"n'a pas pu ouvrir le fichier d'authentification secondaire � @%s � comme\n"
-"� %s � : %m"
+"n'a pas pu ouvrir le fichier d'authentification secondaire « @%s » comme\n"
+"« %s » : %m"
-#: libpq/hba.c:409
+#: libpq/hba.c:407
#, c-format
msgid "authentication file line too long"
msgstr "ligne du fichier d'authentification trop longue"
-#: libpq/hba.c:410 libpq/hba.c:757 libpq/hba.c:773 libpq/hba.c:803 libpq/hba.c:849 libpq/hba.c:862 libpq/hba.c:884 libpq/hba.c:893 libpq/hba.c:914 libpq/hba.c:926 libpq/hba.c:945 libpq/hba.c:966 libpq/hba.c:977 libpq/hba.c:1032 libpq/hba.c:1050 libpq/hba.c:1062 libpq/hba.c:1079 libpq/hba.c:1089 libpq/hba.c:1103 libpq/hba.c:1119 libpq/hba.c:1134 libpq/hba.c:1145 libpq/hba.c:1181 libpq/hba.c:1219 libpq/hba.c:1230 libpq/hba.c:1250
-#: libpq/hba.c:1261 libpq/hba.c:1278 libpq/hba.c:1327 libpq/hba.c:1364 libpq/hba.c:1374 libpq/hba.c:1430 libpq/hba.c:1442 libpq/hba.c:1455 libpq/hba.c:1547 libpq/hba.c:1636 libpq/hba.c:1654 libpq/hba.c:1675 tsearch/ts_locale.c:182
+#: libpq/hba.c:408 libpq/hba.c:755 libpq/hba.c:771 libpq/hba.c:801 libpq/hba.c:847 libpq/hba.c:860 libpq/hba.c:882 libpq/hba.c:891 libpq/hba.c:912 libpq/hba.c:924 libpq/hba.c:943 libpq/hba.c:964 libpq/hba.c:975 libpq/hba.c:1030 libpq/hba.c:1048 libpq/hba.c:1060 libpq/hba.c:1077 libpq/hba.c:1087 libpq/hba.c:1101 libpq/hba.c:1117 libpq/hba.c:1132 libpq/hba.c:1143 libpq/hba.c:1179 libpq/hba.c:1217 libpq/hba.c:1228 libpq/hba.c:1248
+#: libpq/hba.c:1259 libpq/hba.c:1276 libpq/hba.c:1325 libpq/hba.c:1362 libpq/hba.c:1372 libpq/hba.c:1428 libpq/hba.c:1440 libpq/hba.c:1453 libpq/hba.c:1545 libpq/hba.c:1634 libpq/hba.c:1652 libpq/hba.c:1673 tsearch/ts_locale.c:182
#, c-format
msgid "line %d of configuration file \"%s\""
-msgstr "ligne %d du fichier de configuration � %s �"
+msgstr "ligne %d du fichier de configuration « %s »"
#. translator: the second %s is a list of auth methods
-#: libpq/hba.c:755
+#: libpq/hba.c:753
#, c-format
msgid "authentication option \"%s\" is only valid for authentication methods %s"
msgstr ""
-"l'option d'authentification � %s � est seulement valide pour les m�thodes\n"
-"d'authentification � %s �"
+"l'option d'authentification « %s » est seulement valide pour les méthodes\n"
+"d'authentification « %s »"
-#: libpq/hba.c:771
+#: libpq/hba.c:769
#, c-format
msgid "authentication method \"%s\" requires argument \"%s\" to be set"
-msgstr "la m�thode d'authentification � %s � requiert un argument � %s � pour �tremise en place"
+msgstr "la méthode d'authentification « %s » requiert un argument « %s » pour êtremise en place"
-#: libpq/hba.c:792
+#: libpq/hba.c:790
#, c-format
msgid "missing entry in file \"%s\" at end of line %d"
-msgstr "entr�e manquante dans le fichier � %s � � la fin de la ligne %d"
+msgstr "entrée manquante dans le fichier « %s » à la fin de la ligne %d"
-#: libpq/hba.c:802
+#: libpq/hba.c:800
#, c-format
msgid "multiple values in ident field"
msgstr "plusieurs valeurs dans le champ ident"
-#: libpq/hba.c:847
+#: libpq/hba.c:845
#, c-format
msgid "multiple values specified for connection type"
-msgstr "plusieurs valeurs indiqu�es pour le type de connexion"
+msgstr "plusieurs valeurs indiquées pour le type de connexion"
-#: libpq/hba.c:848
+#: libpq/hba.c:846
#, c-format
msgid "Specify exactly one connection type per line."
msgstr "Indiquez uniquement un type de connexion par ligne."
-#: libpq/hba.c:861
+#: libpq/hba.c:859
#, c-format
msgid "local connections are not supported by this build"
-msgstr "les connexions locales ne sont pas support�es dans cette installation"
+msgstr "les connexions locales ne sont pas supportées dans cette installation"
-#: libpq/hba.c:882
+#: libpq/hba.c:880
#, c-format
msgid "hostssl requires SSL to be turned on"
-msgstr "hostssl requiert que SSL soit activ�"
+msgstr "hostssl requiert que SSL soit activé"
-#: libpq/hba.c:883
+#: libpq/hba.c:881
#, c-format
msgid "Set ssl = on in postgresql.conf."
msgstr "Configurez ssl = on dans le postgresql.conf."
-#: libpq/hba.c:891
+#: libpq/hba.c:889
#, c-format
msgid "hostssl is not supported by this build"
-msgstr "hostssl n'est pas support� par cette installation"
+msgstr "hostssl n'est pas supporté par cette installation"
-#: libpq/hba.c:892
+#: libpq/hba.c:890
#, c-format
msgid "Compile with --with-openssl to use SSL connections."
msgstr "Compilez avec --with-openssl pour utiliser les connexions SSL."
-#: libpq/hba.c:912
+#: libpq/hba.c:910
#, c-format
msgid "invalid connection type \"%s\""
-msgstr "type de connexion � %s � invalide"
+msgstr "type de connexion « %s » invalide"
-#: libpq/hba.c:925
+#: libpq/hba.c:923
#, c-format
msgid "end-of-line before database specification"
-msgstr "fin de ligne avant la sp�cification de la base de donn�es"
+msgstr "fin de ligne avant la spécification de la base de données"
-#: libpq/hba.c:944
+#: libpq/hba.c:942
#, c-format
msgid "end-of-line before role specification"
-msgstr "fin de ligne avant la sp�cification du r�le"
+msgstr "fin de ligne avant la spécification du rôle"
-#: libpq/hba.c:965
+#: libpq/hba.c:963
#, c-format
msgid "end-of-line before IP address specification"
-msgstr "fin de ligne avant la sp�cification de l'adresse IP"
+msgstr "fin de ligne avant la spécification de l'adresse IP"
-#: libpq/hba.c:975
+#: libpq/hba.c:973
#, c-format
msgid "multiple values specified for host address"
-msgstr "plusieurs valeurs indiqu�es pour l'adresse h�te"
+msgstr "plusieurs valeurs indiquées pour l'adresse hôte"
-#: libpq/hba.c:976
+#: libpq/hba.c:974
#, c-format
msgid "Specify one address range per line."
-msgstr "Indiquez un sous-r�seau par ligne."
+msgstr "Indiquez un sous-réseau par ligne."
-#: libpq/hba.c:1030
+#: libpq/hba.c:1028
#, c-format
msgid "invalid IP address \"%s\": %s"
-msgstr "adresse IP � %s � invalide : %s"
+msgstr "adresse IP « %s » invalide : %s"
-#: libpq/hba.c:1048
+#: libpq/hba.c:1046
#, c-format
msgid "specifying both host name and CIDR mask is invalid: \"%s\""
-msgstr "sp�cifier le nom d'h�te et le masque CIDR n'est pas valide : � %s �"
+msgstr "spécifier le nom d'hôte et le masque CIDR n'est pas valide : « %s »"
-#: libpq/hba.c:1060
+#: libpq/hba.c:1058
#, c-format
msgid "invalid CIDR mask in address \"%s\""
-msgstr "masque CIDR invalide dans l'adresse � %s �"
+msgstr "masque CIDR invalide dans l'adresse « %s »"
-#: libpq/hba.c:1077
+#: libpq/hba.c:1075
#, c-format
msgid "end-of-line before netmask specification"
-msgstr "fin de ligne avant la sp�cification du masque r�seau"
+msgstr "fin de ligne avant la spécification du masque réseau"
-#: libpq/hba.c:1078
+#: libpq/hba.c:1076
#, c-format
msgid "Specify an address range in CIDR notation, or provide a separate netmask."
-msgstr "Indiquez un sous-r�seau en notation CIDR ou donnez un masque r�seau s�par�."
+msgstr "Indiquez un sous-réseau en notation CIDR ou donnez un masque réseau séparé."
-#: libpq/hba.c:1088
+#: libpq/hba.c:1086
#, c-format
msgid "multiple values specified for netmask"
-msgstr "plusieurs valeurs indiqu�es pour le masque r�seau"
+msgstr "plusieurs valeurs indiquées pour le masque réseau"
-#: libpq/hba.c:1101
+#: libpq/hba.c:1099
#, c-format
msgid "invalid IP mask \"%s\": %s"
-msgstr "masque IP � %s � invalide : %s"
+msgstr "masque IP « %s » invalide : %s"
-#: libpq/hba.c:1118
+#: libpq/hba.c:1116
#, c-format
msgid "IP address and mask do not match"
msgstr "l'adresse IP et le masque ne correspondent pas"
-#: libpq/hba.c:1133
+#: libpq/hba.c:1131
#, c-format
msgid "end-of-line before authentication method"
-msgstr "fin de ligne avant la m�thode d'authentification"
+msgstr "fin de ligne avant la méthode d'authentification"
-#: libpq/hba.c:1143
+#: libpq/hba.c:1141
#, c-format
msgid "multiple values specified for authentication type"
-msgstr "plusieurs valeurs indiqu�es pour le type d'authentification"
+msgstr "plusieurs valeurs indiquées pour le type d'authentification"
-#: libpq/hba.c:1144
+#: libpq/hba.c:1142
#, c-format
msgid "Specify exactly one authentication type per line."
msgstr "Indiquez uniquement un type d'authentification par ligne."
-#: libpq/hba.c:1217
+#: libpq/hba.c:1215
#, c-format
msgid "invalid authentication method \"%s\""
-msgstr "m�thode d'authentification � %s � invalide"
+msgstr "méthode d'authentification « %s » invalide"
-#: libpq/hba.c:1228
+#: libpq/hba.c:1226
#, c-format
msgid "invalid authentication method \"%s\": not supported by this build"
msgstr ""
-"m�thode d'authentification � %s � invalide : non support�e sur cette\n"
+"méthode d'authentification « %s » invalide : non supportée sur cette\n"
"installation"
-#: libpq/hba.c:1249
+#: libpq/hba.c:1247
#, c-format
msgid "gssapi authentication is not supported on local sockets"
msgstr ""
-"l'authentification gssapi n'est pas support�e sur les connexions locales par\n"
+"l'authentification gssapi n'est pas supportée sur les connexions locales par\n"
"socket"
-#: libpq/hba.c:1260
+#: libpq/hba.c:1258
#, c-format
msgid "peer authentication is only supported on local sockets"
msgstr ""
-"l'authentification peer est seulement support�e sur les connexions locales par\n"
+"l'authentification peer est seulement supportée sur les connexions locales par\n"
"socket"
-#: libpq/hba.c:1277
+#: libpq/hba.c:1275
#, c-format
msgid "cert authentication is only supported on hostssl connections"
-msgstr "l'authentification cert est seulement support�e sur les connexions hostssl"
+msgstr "l'authentification cert est seulement supportée sur les connexions hostssl"
-#: libpq/hba.c:1326
+#: libpq/hba.c:1324
#, c-format
msgid "authentication option not in name=value format: %s"
msgstr "l'option d'authentification n'est pas dans le format nom=valeur : %s"
-#: libpq/hba.c:1363
+#: libpq/hba.c:1361
#, c-format
msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix"
msgstr "ne peut pas utiliser ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ou ldapurl avec ldapprefix"
-#: libpq/hba.c:1373
+#: libpq/hba.c:1371
#, c-format
msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set"
msgstr ""
-"la m�thode d'authentification � ldap � requiert un argument � ldapbasedn �,\n"
-"� ldapprefix � ou � ldapsuffix � pour �tre mise en place"
+"la méthode d'authentification « ldap » requiert un argument « ldapbasedn »,\n"
+"« ldapprefix » ou « ldapsuffix » pour être mise en place"
-#: libpq/hba.c:1416
+#: libpq/hba.c:1414
msgid "ident, peer, gssapi, sspi, and cert"
msgstr "ident, peer, gssapi, sspi et cert"
-#: libpq/hba.c:1429
+#: libpq/hba.c:1427
#, c-format
msgid "clientcert can only be configured for \"hostssl\" rows"
-msgstr "clientcert peut seulement �tre configur� pour les lignes � hostssl �"
+msgstr "clientcert peut seulement être configuré pour les lignes « hostssl »"
-#: libpq/hba.c:1440
+#: libpq/hba.c:1438
#, c-format
msgid "client certificates can only be checked if a root certificate store is available"
msgstr ""
-"les certificats cert peuvent seulement �tre v�rifi�s si un emplacement de\n"
+"les certificats cert peuvent seulement être vérifiés si un emplacement de\n"
"certificat racine est disponible"
-#: libpq/hba.c:1454
+#: libpq/hba.c:1452
#, c-format
msgid "clientcert can not be set to 0 when using \"cert\" authentication"
-msgstr "clientcert ne peut pas �tre initialis� � 0 si vous utilisez l'authentification � cert �"
+msgstr "clientcert ne peut pas être initialisé à 0 si vous utilisez l'authentification « cert »"
-#: libpq/hba.c:1490
+#: libpq/hba.c:1488
#, c-format
msgid "could not parse LDAP URL \"%s\": %s"
-msgstr "n'a pas pu analyser l'URL LDAP � %s � : %s"
+msgstr "n'a pas pu analyser l'URL LDAP « %s » : %s"
-#: libpq/hba.c:1498
+#: libpq/hba.c:1496
#, c-format
msgid "unsupported LDAP URL scheme: %s"
-msgstr "m�thode URL LDAP non support� : %s"
+msgstr "méthode URL LDAP non supporté : %s"
-#: libpq/hba.c:1514
+#: libpq/hba.c:1512
#, c-format
msgid "filters not supported in LDAP URLs"
-msgstr "filtres non support�s dans les URL LDAP"
+msgstr "filtres non supportés dans les URL LDAP"
-#: libpq/hba.c:1522
+#: libpq/hba.c:1520
#, c-format
msgid "LDAP URLs not supported on this platform"
-msgstr "URL LDAP non support�s sur cette plateforme."
+msgstr "URL LDAP non supportés sur cette plateforme."
-#: libpq/hba.c:1546
+#: libpq/hba.c:1544
#, c-format
msgid "invalid LDAP port number: \"%s\""
-msgstr "num�ro de port LDAP invalide : � %s �"
+msgstr "numéro de port LDAP invalide : « %s »"
-#: libpq/hba.c:1586 libpq/hba.c:1593
+#: libpq/hba.c:1584 libpq/hba.c:1591
msgid "gssapi and sspi"
msgstr "gssapi et sspi"
-#: libpq/hba.c:1602 libpq/hba.c:1611
+#: libpq/hba.c:1600 libpq/hba.c:1609
msgid "sspi"
-msgstr ""
+msgstr "sspi"
-#: libpq/hba.c:1653
+#: libpq/hba.c:1651
#, c-format
msgid "invalid RADIUS port number: \"%s\""
-msgstr "num�ro de port RADIUS invalide : � %s �"
+msgstr "numéro de port RADIUS invalide : « %s »"
-#: libpq/hba.c:1673
+#: libpq/hba.c:1671
#, c-format
msgid "unrecognized authentication option name: \"%s\""
-msgstr "nom d'option de l'authentification inconnu : � %s �"
+msgstr "nom d'option de l'authentification inconnu : « %s »"
-#: libpq/hba.c:1859
+#: libpq/hba.c:1855
#, c-format
msgid "configuration file \"%s\" contains no entries"
-msgstr "le fichier de configuration � %s � ne contient aucun enregistrement"
+msgstr "le fichier de configuration « %s » ne contient aucun enregistrement"
-#: libpq/hba.c:1955
+#: libpq/hba.c:1951
#, c-format
msgid "invalid regular expression \"%s\": %s"
-msgstr "expression rationnelle invalide � %s � : %s"
+msgstr "expression rationnelle invalide « %s » : %s"
-#: libpq/hba.c:2015
+#: libpq/hba.c:2011
#, c-format
msgid "regular expression match for \"%s\" failed: %s"
-msgstr "la correspondance de l'expression rationnelle pour � %s � a �chou� : %s"
+msgstr "la correspondance de l'expression rationnelle pour « %s » a échoué : %s"
-#: libpq/hba.c:2034
+#: libpq/hba.c:2030
#, c-format
msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\""
msgstr ""
-"l'expression rationnelle � %s � n'a pas de sous-expressions comme celle\n"
-"demand�e par la r�f�rence dans � %s �"
+"l'expression rationnelle « %s » n'a pas de sous-expressions comme celle\n"
+"demandée par la référence dans « %s »"
-#: libpq/hba.c:2131
+#: libpq/hba.c:2127
#, c-format
msgid "provided user name (%s) and authenticated user name (%s) do not match"
msgstr ""
-"le nom d'utilisateur (%s) et le nom d'utilisateur authentifi� (%s) fournis ne\n"
+"le nom d'utilisateur (%s) et le nom d'utilisateur authentifié (%s) fournis ne\n"
"correspondent pas"
-#: libpq/hba.c:2151
+#: libpq/hba.c:2147
#, c-format
msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\""
msgstr ""
-"pas de correspondance dans la usermap � %s � pour l'utilisateur � %s �\n"
-"authentifi� en tant que � %s �"
+"pas de correspondance dans la usermap « %s » pour l'utilisateur « %s »\n"
+"authentifié en tant que « %s »"
-#: libpq/hba.c:2186
+#: libpq/hba.c:2182
#, c-format
msgid "could not open usermap file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier usermap � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier usermap « %s » : %m"
#: libpq/pqcomm.c:202
#, c-format
@@ -11952,22 +11969,22 @@ msgstr "n'a pas pu activer le mode non-bloquant pour la socket : %m"
#: libpq/pqcomm.c:354
#, c-format
msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)"
-msgstr "Le chemin du socket de domaine Unix, � %s �, est trop (maximum %d octets)"
+msgstr "Le chemin du socket de domaine Unix, « %s », est trop (maximum %d octets)"
#: libpq/pqcomm.c:375
#, c-format
msgid "could not translate host name \"%s\", service \"%s\" to address: %s"
-msgstr "n'a pas pu r�soudre le nom de l'h�te � %s �, service � %s � par l'adresse : %s"
+msgstr "n'a pas pu résoudre le nom de l'hôte « %s », service « %s » par l'adresse : %s"
#: libpq/pqcomm.c:379
#, c-format
msgid "could not translate service \"%s\" to address: %s"
-msgstr "n'a pas pu r�soudre le service � %s � par l'adresse : %s"
+msgstr "n'a pas pu résoudre le service « %s » par l'adresse : %s"
#: libpq/pqcomm.c:406
#, c-format
msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded"
-msgstr "n'a pas pu se lier � toutes les adresses requises : MAXLISTEN (%d) d�pass�"
+msgstr "n'a pas pu se lier à toutes les adresses requises : MAXLISTEN (%d) dépassé"
#: libpq/pqcomm.c:415
msgid "IPv4"
@@ -11990,56 +12007,56 @@ msgstr "famille d'adresse %d non reconnue"
#: libpq/pqcomm.c:440
#, c-format
msgid "could not create %s socket: %m"
-msgstr "n'a pas pu cr�er le socket %s : %m"
+msgstr "n'a pas pu créer le socket %s : %m"
#: libpq/pqcomm.c:465
#, c-format
msgid "setsockopt(SO_REUSEADDR) failed: %m"
-msgstr "setsockopt(SO_REUSEADDR) a �chou� : %m"
+msgstr "setsockopt(SO_REUSEADDR) a échoué : %m"
#: libpq/pqcomm.c:480
#, c-format
msgid "setsockopt(IPV6_V6ONLY) failed: %m"
-msgstr "setsockopt(IPV6_V6ONLY) a �chou� : %m"
+msgstr "setsockopt(IPV6_V6ONLY) a échoué : %m"
#. translator: %s is IPv4, IPv6, or Unix
#: libpq/pqcomm.c:499
#, c-format
msgid "could not bind %s socket: %m"
-msgstr "n'a pas pu se lier � la socket %s : %m"
+msgstr "n'a pas pu se lier à la socket %s : %m"
#: libpq/pqcomm.c:502
#, c-format
msgid "Is another postmaster already running on port %d? If not, remove socket file \"%s\" and retry."
-msgstr "Un autre postmaster fonctionne-t'il d�j� sur le port %d ?Sinon, supprimez le fichier socket � %s � et r�essayez."
+msgstr "Un autre postmaster fonctionne-t'il déjà sur le port %d ?Sinon, supprimez le fichier socket « %s » et réessayez."
#: libpq/pqcomm.c:505
#, c-format
msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry."
msgstr ""
-"Un autre postmaster fonctionne-t'il d�j� sur le port %d ?\n"
-"Sinon, attendez quelques secondes et r�essayez."
+"Un autre postmaster fonctionne-t'il déjà sur le port %d ?\n"
+"Sinon, attendez quelques secondes et réessayez."
#. translator: %s is IPv4, IPv6, or Unix
#: libpq/pqcomm.c:538
#, c-format
msgid "could not listen on %s socket: %m"
-msgstr "n'a pas pu �couter sur le socket %s : %m"
+msgstr "n'a pas pu écouter sur le socket %s : %m"
#: libpq/pqcomm.c:623
#, c-format
msgid "group \"%s\" does not exist"
-msgstr "le groupe � %s � n'existe pas"
+msgstr "le groupe « %s » n'existe pas"
#: libpq/pqcomm.c:633
#, c-format
msgid "could not set group of file \"%s\": %m"
-msgstr "n'a pas pu initialiser le groupe du fichier � %s � : %m"
+msgstr "n'a pas pu initialiser le groupe du fichier « %s » : %m"
#: libpq/pqcomm.c:644
#, c-format
msgid "could not set permissions of file \"%s\": %m"
-msgstr "n'a pas pu initialiser les droits du fichier � %s � : %m"
+msgstr "n'a pas pu initialiser les droits du fichier « %s » : %m"
#: libpq/pqcomm.c:674
#, c-format
@@ -12054,17 +12071,17 @@ msgstr "il n'y a pas de connexion client"
#: libpq/pqcomm.c:936 libpq/pqcomm.c:1032
#, c-format
msgid "could not receive data from client: %m"
-msgstr "n'a pas pu recevoir les donn�es du client : %m"
+msgstr "n'a pas pu recevoir les données du client : %m"
-#: libpq/pqcomm.c:1177 tcop/postgres.c:3906
+#: libpq/pqcomm.c:1177 tcop/postgres.c:3917
#, c-format
msgid "terminating connection because protocol synchronization was lost"
-msgstr "arr�t de la connexion � cause d'une perte de synchronisation du protocole"
+msgstr "arrêt de la connexion à cause d'une perte de synchronisation du protocole"
#: libpq/pqcomm.c:1243
#, c-format
msgid "unexpected EOF within message length word"
-msgstr "fin de fichier (EOF) inattendue � l'int�rieur de la longueur du message"
+msgstr "fin de fichier (EOF) inattendue à l'intérieur de la longueur du message"
#: libpq/pqcomm.c:1254
#, c-format
@@ -12079,24 +12096,24 @@ msgstr "message incomplet du client"
#: libpq/pqcomm.c:1422
#, c-format
msgid "could not send data to client: %m"
-msgstr "n'a pas pu envoyer les donn�es au client : %m"
+msgstr "n'a pas pu envoyer les données au client : %m"
-#: libpq/pqformat.c:436
+#: libpq/pqformat.c:437
#, c-format
msgid "no data left in message"
-msgstr "pas de donn�es dans le message"
+msgstr "pas de données dans le message"
-#: libpq/pqformat.c:556 libpq/pqformat.c:574 libpq/pqformat.c:595 utils/adt/arrayfuncs.c:1457 utils/adt/rowtypes.c:563
+#: libpq/pqformat.c:557 libpq/pqformat.c:575 libpq/pqformat.c:596 utils/adt/arrayfuncs.c:1457 utils/adt/rowtypes.c:563
#, c-format
msgid "insufficient data left in message"
-msgstr "donn�es insuffisantes laiss�es dans le message"
+msgstr "données insuffisantes laissées dans le message"
-#: libpq/pqformat.c:636
+#: libpq/pqformat.c:637 libpq/pqformat.c:666
#, c-format
msgid "invalid string in message"
-msgstr "cha�ne invalide dans le message"
+msgstr "chaîne invalide dans le message"
-#: libpq/pqformat.c:652
+#: libpq/pqformat.c:682
#, c-format
msgid "invalid message format"
msgstr "format du message invalide"
@@ -12104,9 +12121,9 @@ msgstr "format du message invalide"
#: main/main.c:264
#, c-format
msgid "%s: WSAStartup failed: %d\n"
-msgstr "%s : WSAStartup a �chou� : %d\n"
+msgstr "%s : WSAStartup a échoué : %d\n"
-#: main/main.c:327
+#: main/main.c:328
#, c-format
msgid ""
"%s is the PostgreSQL server.\n"
@@ -12115,7 +12132,7 @@ msgstr ""
"%s est le serveur PostgreSQL.\n"
"\n"
-#: main/main.c:328
+#: main/main.c:329
#, c-format
msgid ""
"Usage:\n"
@@ -12126,166 +12143,166 @@ msgstr ""
" %s [OPTION]...\n"
"\n"
-#: main/main.c:329
+#: main/main.c:330
#, c-format
msgid "Options:\n"
msgstr "Options :\n"
-#: main/main.c:330
+#: main/main.c:331
#, c-format
msgid " -B NBUFFERS number of shared buffers\n"
-msgstr " -B NBUFFERS nombre de tampons partag�s\n"
+msgstr " -B NBUFFERS nombre de tampons partagés\n"
-#: main/main.c:331
+#: main/main.c:332
#, c-format
msgid " -c NAME=VALUE set run-time parameter\n"
-msgstr " -c NOM=VALEUR configure un param�tre d'ex�cution\n"
+msgstr " -c NOM=VALEUR configure un paramètre d'exécution\n"
-#: main/main.c:332
+#: main/main.c:333
#, c-format
msgid " -C NAME print value of run-time parameter, then exit\n"
msgstr ""
-" -C NOM affiche la valeur d'un param�tre en ex�cution,\n"
+" -C NOM affiche la valeur d'un paramètre en exécution,\n"
" puis quitte\n"
-#: main/main.c:333
+#: main/main.c:334
#, c-format
msgid " -d 1-5 debugging level\n"
-msgstr " -d 1-5 niveau de d�bogage\n"
+msgstr " -d 1-5 niveau de débogage\n"
-#: main/main.c:334
+#: main/main.c:335
#, c-format
msgid " -D DATADIR database directory\n"
-msgstr " -D R�PDONNEES r�pertoire de la base de donn�es\n"
+msgstr " -D RÉPDONNEES répertoire de la base de données\n"
-#: main/main.c:335
+#: main/main.c:336
#, c-format
msgid " -e use European date input format (DMY)\n"
-msgstr " -e utilise le format de saisie europ�en des dates (DMY)\n"
+msgstr " -e utilise le format de saisie européen des dates (DMY)\n"
-#: main/main.c:336
+#: main/main.c:337
#, c-format
msgid " -F turn fsync off\n"
-msgstr " -F d�sactive fsync\n"
+msgstr " -F désactive fsync\n"
-#: main/main.c:337
+#: main/main.c:338
#, c-format
msgid " -h HOSTNAME host name or IP address to listen on\n"
-msgstr " -h NOMHOTE nom d'h�te ou adresse IP � �couter\n"
+msgstr " -h NOMHOTE nom d'hôte ou adresse IP à écouter\n"
-#: main/main.c:338
+#: main/main.c:339
#, c-format
msgid " -i enable TCP/IP connections\n"
msgstr " -i active les connexions TCP/IP\n"
-#: main/main.c:339
+#: main/main.c:340
#, c-format
msgid " -k DIRECTORY Unix-domain socket location\n"
-msgstr " -k R�PERTOIRE emplacement des sockets de domaine Unix\n"
+msgstr " -k RÉPERTOIRE emplacement des sockets de domaine Unix\n"
-#: main/main.c:341
+#: main/main.c:342
#, c-format
msgid " -l enable SSL connections\n"
msgstr " -l active les connexions SSL\n"
-#: main/main.c:343
+#: main/main.c:344
#, c-format
msgid " -N MAX-CONNECT maximum number of allowed connections\n"
-msgstr " -N MAX-CONNECT nombre maximum de connexions simultan�es\n"
+msgstr " -N MAX-CONNECT nombre maximum de connexions simultanées\n"
-#: main/main.c:344
+#: main/main.c:345
#, c-format
msgid " -o OPTIONS pass \"OPTIONS\" to each server process (obsolete)\n"
-msgstr " -o OPTIONS passe � OPTIONS � � chaque processus serveur (obsol�te)\n"
+msgstr " -o OPTIONS passe « OPTIONS » à chaque processus serveur (obsolète)\n"
-#: main/main.c:345
+#: main/main.c:346
#, c-format
msgid " -p PORT port number to listen on\n"
-msgstr " -p PORT num�ro du port � �couter\n"
+msgstr " -p PORT numéro du port à écouter\n"
-#: main/main.c:346
+#: main/main.c:347
#, c-format
msgid " -s show statistics after each query\n"
-msgstr " -s affiche les statistiques apr�s chaque requ�te\n"
+msgstr " -s affiche les statistiques après chaque requête\n"
-#: main/main.c:347
+#: main/main.c:348
#, c-format
msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n"
-msgstr " -S WORK-MEM configure la m�moire pour les tris (en Ko)\n"
+msgstr " -S WORK-MEM configure la mémoire pour les tris (en Ko)\n"
-#: main/main.c:348
+#: main/main.c:349
#, c-format
msgid " -V, --version output version information, then exit\n"
msgstr " -V, --version affiche la version et quitte\n"
-#: main/main.c:349
+#: main/main.c:350
#, c-format
msgid " --NAME=VALUE set run-time parameter\n"
-msgstr " --NOM=VALEUR configure un param�tre d'ex�cution\n"
+msgstr " --NOM=VALEUR configure un paramètre d'exécution\n"
-#: main/main.c:350
+#: main/main.c:351
#, c-format
msgid " --describe-config describe configuration parameters, then exit\n"
-msgstr " --describe-config d�crit les param�tres de configuration, puis quitte\n"
+msgstr " --describe-config décrit les paramètres de configuration, puis quitte\n"
-#: main/main.c:351
+#: main/main.c:352
#, c-format
msgid " -?, --help show this help, then exit\n"
msgstr " -?, --help affiche cette aide et quitte\n"
-#: main/main.c:353
+#: main/main.c:354
#, c-format
msgid ""
"\n"
"Developer options:\n"
msgstr ""
"\n"
-"Options pour le d�veloppeur :\n"
+"Options pour le développeur :\n"
-#: main/main.c:354
+#: main/main.c:355
#, c-format
msgid " -f s|i|n|m|h forbid use of some plan types\n"
msgstr " -f s|i|n|m|h interdit l'utilisation de certains types de plan\n"
-#: main/main.c:355
+#: main/main.c:356
#, c-format
msgid " -n do not reinitialize shared memory after abnormal exit\n"
msgstr ""
-" -n ne r�initialise pas la m�moire partag�e apr�s un arr�t\n"
+" -n ne réinitialise pas la mémoire partagée après un arrêt\n"
" brutal\n"
-#: main/main.c:356
+#: main/main.c:357
#, c-format
msgid " -O allow system table structure changes\n"
msgstr ""
" -O autorise les modifications de structure des tables\n"
-" syst�me\n"
+" système\n"
-#: main/main.c:357
+#: main/main.c:358
#, c-format
msgid " -P disable system indexes\n"
-msgstr " -P d�sactive les index syst�mes\n"
+msgstr " -P désactive les index systèmes\n"
-#: main/main.c:358
+#: main/main.c:359
#, c-format
msgid " -t pa|pl|ex show timings after each query\n"
-msgstr " -t pa|pl|ex affiche les horodatages pour chaque requ�te\n"
+msgstr " -t pa|pl|ex affiche les horodatages pour chaque requête\n"
-#: main/main.c:359
+#: main/main.c:360
#, c-format
msgid " -T send SIGSTOP to all backend processes if one dies\n"
msgstr ""
-" -T envoie SIGSTOP � tous les processus serveur si l'un\n"
+" -T envoie SIGSTOP à tous les processus serveur si l'un\n"
" d'entre eux meurt\n"
-#: main/main.c:360
+#: main/main.c:361
#, c-format
msgid " -W NUM wait NUM seconds to allow attach from a debugger\n"
msgstr ""
" -W NUM attends NUM secondes pour permettre l'attache d'un\n"
-" d�bogueur\n"
+" débogueur\n"
-#: main/main.c:362
+#: main/main.c:363
#, c-format
msgid ""
"\n"
@@ -12294,69 +12311,69 @@ msgstr ""
"\n"
"Options pour le mode mono-utilisateur :\n"
-#: main/main.c:363
+#: main/main.c:364
#, c-format
msgid " --single selects single-user mode (must be first argument)\n"
msgstr ""
-" --single s�lectionne le mode mono-utilisateur (doit �tre le\n"
+" --single sélectionne le mode mono-utilisateur (doit être le\n"
" premier argument)\n"
-#: main/main.c:364
+#: main/main.c:365
#, c-format
msgid " DBNAME database name (defaults to user name)\n"
-msgstr " NOMBASE nom de la base (par d�faut, celui de l'utilisateur)\n"
+msgstr " NOMBASE nom de la base (par défaut, celui de l'utilisateur)\n"
-#: main/main.c:365
+#: main/main.c:366
#, c-format
msgid " -d 0-5 override debugging level\n"
-msgstr " -d 0-5 surcharge le niveau de d�bogage\n"
+msgstr " -d 0-5 surcharge le niveau de débogage\n"
-#: main/main.c:366
+#: main/main.c:367
#, c-format
msgid " -E echo statement before execution\n"
-msgstr " -E affiche la requ�te avant de l'ex�cuter\n"
+msgstr " -E affiche la requête avant de l'exécuter\n"
-#: main/main.c:367
+#: main/main.c:368
#, c-format
msgid " -j do not use newline as interactive query delimiter\n"
msgstr ""
-" -j n'utilise pas le retour � la ligne comme d�limiteur de\n"
-" requ�te\n"
+" -j n'utilise pas le retour à la ligne comme délimiteur de\n"
+" requête\n"
-#: main/main.c:368 main/main.c:373
+#: main/main.c:369 main/main.c:374
#, c-format
msgid " -r FILENAME send stdout and stderr to given file\n"
-msgstr " -r FICHIER envoie stdout et stderr dans le fichier indiqu�\n"
+msgstr " -r FICHIER envoie stdout et stderr dans le fichier indiqué\n"
-#: main/main.c:370
+#: main/main.c:371
#, c-format
msgid ""
"\n"
"Options for bootstrapping mode:\n"
msgstr ""
"\n"
-"Options pour le mode � bootstrapping � :\n"
+"Options pour le mode « bootstrapping » :\n"
-#: main/main.c:371
+#: main/main.c:372
#, c-format
msgid " --boot selects bootstrapping mode (must be first argument)\n"
msgstr ""
-" --boot s�lectionne le mode � bootstrapping � (doit �tre le\n"
+" --boot sélectionne le mode « bootstrapping » (doit être le\n"
" premier argument)\n"
-#: main/main.c:372
+#: main/main.c:373
#, c-format
msgid " DBNAME database name (mandatory argument in bootstrapping mode)\n"
msgstr ""
" NOMBASE nom de la base (argument obligatoire dans le mode\n"
-" � bootstrapping �)\n"
+" « bootstrapping »)\n"
-#: main/main.c:374
+#: main/main.c:375
#, c-format
msgid " -x NUM internal use\n"
msgstr " -x NUM utilisation interne\n"
-#: main/main.c:376
+#: main/main.c:377
#, c-format
msgid ""
"\n"
@@ -12367,13 +12384,13 @@ msgid ""
"Report bugs to <[email protected]>.\n"
msgstr ""
"\n"
-"Merci de lire la documentation pour la liste compl�te des param�tres de\n"
-"configuration � l'ex�cution et pour savoir comment les configurer � la\n"
+"Merci de lire la documentation pour la liste complète des paramètres de\n"
+"configuration à l'exécution et pour savoir comment les configurer à la\n"
"ligne de commande ou dans le fichier de configuration.\n"
"\n"
-"Rapportez les bogues � <[email protected]>.\n"
+"Rapportez les bogues à <[email protected]>.\n"
-#: main/main.c:390
+#: main/main.c:391
#, c-format
msgid ""
"\"root\" execution of the PostgreSQL server is not permitted.\n"
@@ -12381,18 +12398,18 @@ msgid ""
"possible system security compromise. See the documentation for\n"
"more information on how to properly start the server.\n"
msgstr ""
-"L'ex�cution du serveur PostgreSQL par l'utilisateur � root � n'est pas\n"
-"autoris�e.\n"
-"Le serveur doit �tre lanc� avec un utilisateur non privil�gi� pour emp�cher\n"
-"tout probl�me possible de s�curit� sur le serveur. Voir la documentation pour\n"
+"L'exécution du serveur PostgreSQL par l'utilisateur « root » n'est pas\n"
+"autorisée.\n"
+"Le serveur doit être lancé avec un utilisateur non privilégié pour empêcher\n"
+"tout problème possible de sécurité sur le serveur. Voir la documentation pour\n"
"plus d'informations sur le lancement propre du serveur.\n"
-#: main/main.c:407
+#: main/main.c:408
#, c-format
msgid "%s: real and effective user IDs must match\n"
-msgstr "%s : les identifiants r�el et effectif de l'utilisateur doivent correspondre\n"
+msgstr "%s : les identifiants réel et effectif de l'utilisateur doivent correspondre\n"
-#: main/main.c:414
+#: main/main.c:415
#, c-format
msgid ""
"Execution of PostgreSQL by a user with administrative permissions is not\n"
@@ -12401,751 +12418,749 @@ msgid ""
"possible system security compromises. See the documentation for\n"
"more information on how to properly start the server.\n"
msgstr ""
-"L'ex�cution du serveur PostgreSQL par un utilisateur dot� de droits d'administrateur n'est pas permise.\n"
-"Le serveur doit �tre lanc� avec un utilisateur non privil�gi� pour emp�cher\n"
-"tout probl�me de s�curit� sur le serveur. Voir la documentation pour\n"
+"L'exécution du serveur PostgreSQL par un utilisateur doté de droits d'administrateur n'est pas permise.\n"
+"Le serveur doit être lancé avec un utilisateur non privilégié pour empêcher\n"
+"tout problème de sécurité sur le serveur. Voir la documentation pour\n"
"plus d'informations sur le lancement propre du serveur.\n"
#: nodes/extensible.c:66
-#, fuzzy, c-format
-#| msgid "extension \"%s\" already exists"
+#, c-format
msgid "extensible node type \"%s\" already exists"
-msgstr "l'extension � %s � existe d�j�"
+msgstr "le type de nœud extensible « %s » existe déjà"
#: nodes/extensible.c:114
-#, fuzzy, c-format
-#| msgid "extension \"%s\" does not exist"
+#, c-format
msgid "ExtensibleNodeMethods \"%s\" was not registered"
-msgstr "l'extension � %s � n'existe pas"
+msgstr "ExtensibleNodeMethods \"%s\" n'a pas été enregistré"
-#: nodes/nodeFuncs.c:123 nodes/nodeFuncs.c:154 parser/parse_coerce.c:1820 parser/parse_coerce.c:1848 parser/parse_coerce.c:1924 parser/parse_expr.c:1994 parser/parse_func.c:597 parser/parse_oper.c:952
+#: nodes/nodeFuncs.c:124 nodes/nodeFuncs.c:155 parser/parse_coerce.c:1820 parser/parse_coerce.c:1848 parser/parse_coerce.c:1924 parser/parse_expr.c:2019 parser/parse_func.c:597 parser/parse_oper.c:952
#, c-format
msgid "could not find array type for data type %s"
-msgstr "n'a pas pu trouver le type array pour le type de donn�es %s"
+msgstr "n'a pas pu trouver de type tableau pour le type de données %s"
-#: optimizer/path/allpaths.c:2618
+#: optimizer/path/allpaths.c:2653
#, c-format
msgid "WHERE CURRENT OF is not supported on a view with no underlying relation"
-msgstr "WHERE CURRENT OF n'est pas support� pour une vue sans table sous-jacente"
+msgstr "WHERE CURRENT OF n'est pas supporté pour une vue sans table sous-jacente"
-#: optimizer/path/allpaths.c:2623
+#: optimizer/path/allpaths.c:2658
#, c-format
msgid "WHERE CURRENT OF is not supported on a view with more than one underlying relation"
-msgstr "WHERE CURRENT OF n'est pas support� pour une vue avec plus d'une table sous-jacente"
+msgstr "WHERE CURRENT OF n'est pas supporté pour une vue avec plus d'une table sous-jacente"
-#: optimizer/path/allpaths.c:2628
+#: optimizer/path/allpaths.c:2663
#, c-format
msgid "WHERE CURRENT OF is not supported on a view with grouping or aggregation"
-msgstr "WHERE CURRENT OF n'est pas support� pour une vue avec regroupement ou agr�gat"
+msgstr "WHERE CURRENT OF n'est pas supporté pour une vue avec regroupement ou agrégat"
#: optimizer/path/joinrels.c:802
#, c-format
msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions"
msgstr ""
-"FULL JOIN est support� seulement avec les conditions de jointures MERGE et de\n"
+"FULL JOIN est supporté seulement avec les conditions de jointures MERGE et de\n"
"jointures HASH JOIN"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
#: optimizer/plan/initsplan.c:1124
#, c-format
msgid "%s cannot be applied to the nullable side of an outer join"
-msgstr "%s ne peut �tre appliqu� sur le c�t� possiblement NULL d'une jointure externe"
+msgstr "%s ne peut être appliqué sur le côté possiblement NULL d'une jointure externe"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: optimizer/plan/planner.c:1473 parser/analyze.c:1481 parser/analyze.c:1679 parser/analyze.c:2460
+#: optimizer/plan/planner.c:1480 parser/analyze.c:1549 parser/analyze.c:1747 parser/analyze.c:2528
#, c-format
msgid "%s is not allowed with UNION/INTERSECT/EXCEPT"
-msgstr "%s n'est pas autoris� avec UNION/INTERSECT/EXCEPT"
+msgstr "%s n'est pas autorisé avec UNION/INTERSECT/EXCEPT"
-#: optimizer/plan/planner.c:3752
+#: optimizer/plan/planner.c:3809
#, c-format
msgid "could not implement GROUP BY"
-msgstr "n'a pas pu implant� GROUP BY"
+msgstr "n'a pas pu implanté GROUP BY"
-#: optimizer/plan/planner.c:3753 optimizer/plan/planner.c:4095 optimizer/prep/prepunion.c:927
+#: optimizer/plan/planner.c:3810 optimizer/plan/planner.c:4203 optimizer/prep/prepunion.c:929
#, c-format
msgid "Some of the datatypes only support hashing, while others only support sorting."
msgstr ""
-"Certains des types de donn�es supportent seulement le hachage,\n"
+"Certains des types de données supportent seulement le hachage,\n"
"alors que les autres supportent seulement le tri."
-#: optimizer/plan/planner.c:4094
+#: optimizer/plan/planner.c:4202
#, c-format
msgid "could not implement DISTINCT"
-msgstr "n'a pas pu implant� DISTINCT"
+msgstr "n'a pas pu implanté DISTINCT"
-#: optimizer/plan/planner.c:4633
+#: optimizer/plan/planner.c:4832
#, c-format
msgid "could not implement window PARTITION BY"
msgstr "n'a pas pu implanter PARTITION BY de window"
-#: optimizer/plan/planner.c:4634
+#: optimizer/plan/planner.c:4833
#, c-format
msgid "Window partitioning columns must be of sortable datatypes."
msgstr ""
-"Les colonnes de partitionnement de window doivent �tre d'un type de donn�es\n"
+"Les colonnes de partitionnement de window doivent être d'un type de données\n"
"triables."
-#: optimizer/plan/planner.c:4638
+#: optimizer/plan/planner.c:4837
#, c-format
msgid "could not implement window ORDER BY"
msgstr "n'a pas pu implanter ORDER BY dans le window"
-#: optimizer/plan/planner.c:4639
+#: optimizer/plan/planner.c:4838
#, c-format
msgid "Window ordering columns must be of sortable datatypes."
-msgstr "Les colonnes de tri de la window doivent �tre d'un type de donn�es triable."
+msgstr "Les colonnes de tri de la window doivent être d'un type de données triable."
-#: optimizer/plan/setrefs.c:423
+#: optimizer/plan/setrefs.c:415
#, c-format
msgid "too many range table entries"
msgstr "trop d'enregistrements dans la table range"
-#: optimizer/prep/prepunion.c:480
+#: optimizer/prep/prepunion.c:484
#, c-format
msgid "could not implement recursive UNION"
-msgstr "n'a pas pu implant� le UNION r�cursif"
+msgstr "n'a pas pu implanté le UNION récursif"
-#: optimizer/prep/prepunion.c:481
+#: optimizer/prep/prepunion.c:485
#, c-format
msgid "All column datatypes must be hashable."
-msgstr "Tous les types de donn�es colonnes doivent �tre hachables."
+msgstr "Tous les types de données colonnes doivent être hachables."
#. translator: %s is UNION, INTERSECT, or EXCEPT
-#: optimizer/prep/prepunion.c:926
+#: optimizer/prep/prepunion.c:928
#, c-format
msgid "could not implement %s"
-msgstr "n'a pas pu implant� %s"
+msgstr "n'a pas pu implanté %s"
-#: optimizer/util/clauses.c:4965
+#: optimizer/util/clauses.c:4634
#, c-format
msgid "SQL function \"%s\" during inlining"
-msgstr "fonction SQL � %s � durant � inlining �"
+msgstr "fonction SQL « %s » durant « inlining »"
#: optimizer/util/plancat.c:114
#, c-format
msgid "cannot access temporary or unlogged relations during recovery"
-msgstr "ne peut pas acc�der � des tables temporaires et non trac�es lors de la restauration"
+msgstr "ne peut pas accéder à des tables temporaires et non tracées lors de la restauration"
-#: optimizer/util/plancat.c:591
+#: optimizer/util/plancat.c:611
#, c-format
-msgid "system columns cannot be used in an ON CONFLICT clause"
-msgstr "les colonnes syst�mes ne peuvent pas �tre utilis�es dans une clause ON CONFLICT"
+msgid "whole row unique index inference specifications are not supported"
+msgstr "les spécifications d'inférence d'index unique pour une ligne entière ne sont pas supportées"
-#: optimizer/util/plancat.c:609
+#: optimizer/util/plancat.c:628
#, c-format
msgid "constraint in ON CONFLICT clause has no associated index"
-msgstr "la contrainte de la clause ON CONFLICT n'a pas d'index associ�"
+msgstr "la contrainte de la clause ON CONFLICT n'a pas d'index associé"
-#: optimizer/util/plancat.c:661
+#: optimizer/util/plancat.c:679
#, c-format
msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints"
-msgstr "ON CONFLICT DO UPDATE non support� avec les contraintes d'exclusion"
+msgstr "ON CONFLICT DO UPDATE non supporté avec les contraintes d'exclusion"
-#: optimizer/util/plancat.c:768
+#: optimizer/util/plancat.c:784
#, c-format
msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification"
-msgstr "il n'existe aucune contrainte unique ou contrainte d'exclusion correspondant � la sp�cification ON CONFLICT"
+msgstr "il n'existe aucune contrainte unique ou contrainte d'exclusion correspondant à la spécification ON CONFLICT"
-#: parser/analyze.c:639 parser/analyze.c:1253
+#: parser/analyze.c:663 parser/analyze.c:1321
#, c-format
msgid "VALUES lists must all be the same length"
-msgstr "les listes VALUES doivent toutes �tre de la m�me longueur"
+msgstr "les listes VALUES doivent toutes être de la même longueur"
-#: parser/analyze.c:811
+#: parser/analyze.c:859
#, c-format
msgid "INSERT has more expressions than target columns"
msgstr "INSERT a plus d'expressions que les colonnes cibles"
-#: parser/analyze.c:829
+#: parser/analyze.c:877
#, c-format
msgid "INSERT has more target columns than expressions"
msgstr "INSERT a plus de colonnes cibles que d'expressions"
-#: parser/analyze.c:833
+#: parser/analyze.c:881
#, c-format
msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?"
msgstr ""
-"La source d'insertion est une expression de ligne contenant le m�me nombre\n"
-"de colonnes que celui attendu par INSERT. Auriez-vous utilis� des parenth�ses\n"
-"suppl�mentaires ?"
+"La source d'insertion est une expression de ligne contenant le même nombre\n"
+"de colonnes que celui attendu par INSERT. Auriez-vous utilisé des parenthèses\n"
+"supplémentaires ?"
-#: parser/analyze.c:1074 parser/analyze.c:1454
+#: parser/analyze.c:1142 parser/analyze.c:1522
#, c-format
msgid "SELECT ... INTO is not allowed here"
-msgstr "SELECT ... INTO n'est pas autoris� ici"
+msgstr "SELECT ... INTO n'est pas autorisé ici"
-#: parser/analyze.c:1267
+#: parser/analyze.c:1335
#, c-format
msgid "DEFAULT can only appear in a VALUES list within INSERT"
-msgstr "DEFAULT peut seulement appara�tre dans la liste VALUES comprise dans un INSERT"
+msgstr "DEFAULT peut seulement apparaître dans la liste VALUES comprise dans un INSERT"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:1386 parser/analyze.c:2630
+#: parser/analyze.c:1454 parser/analyze.c:2698
#, c-format
msgid "%s cannot be applied to VALUES"
-msgstr "%s ne peut pas �tre appliqu� � VALUES"
+msgstr "%s ne peut pas être appliqué à VALUES"
-#: parser/analyze.c:1607
+#: parser/analyze.c:1675
#, c-format
msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause"
msgstr "clause UNION/INTERSECT/EXCEPT ORDER BY invalide"
-#: parser/analyze.c:1608
+#: parser/analyze.c:1676
#, c-format
msgid "Only result column names can be used, not expressions or functions."
msgstr ""
-"Seuls les noms de colonnes r�sultats peuvent �tre utilis�s, pas les\n"
+"Seuls les noms de colonnes résultats peuvent être utilisés, pas les\n"
"expressions et les fonctions."
-#: parser/analyze.c:1609
+#: parser/analyze.c:1677
#, c-format
msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause."
-msgstr "Ajouter l'expression/fonction � chaque SELECT, ou d�placer l'UNION dans une clause FROM."
+msgstr "Ajouter l'expression/fonction à chaque SELECT, ou déplacer l'UNION dans une clause FROM."
-#: parser/analyze.c:1669
+#: parser/analyze.c:1737
#, c-format
msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"
-msgstr "INTO est autoris� uniquement sur le premier SELECT d'un UNION/INTERSECT/EXCEPT"
+msgstr "INTO est autorisé uniquement sur le premier SELECT d'un UNION/INTERSECT/EXCEPT"
-#: parser/analyze.c:1733
+#: parser/analyze.c:1801
#, c-format
msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"
msgstr ""
-"L'instruction membre UNION/INTERSECT/EXCEPT ne peut pas faire r�f�rence �\n"
-"d'autres relations que celles de la requ�te de m�me niveau"
+"L'instruction membre UNION/INTERSECT/EXCEPT ne peut pas faire référence à\n"
+"d'autres relations que celles de la requête de même niveau"
-#: parser/analyze.c:1822
+#: parser/analyze.c:1890
#, c-format
msgid "each %s query must have the same number of columns"
-msgstr "chaque requ�te %s doit avoir le m�me nombre de colonnes"
+msgstr "chaque requête %s doit avoir le même nombre de colonnes"
-#: parser/analyze.c:2215
+#: parser/analyze.c:2283
#, c-format
msgid "RETURNING must have at least one column"
msgstr "RETURNING doit avoir au moins une colonne"
-#: parser/analyze.c:2252
+#: parser/analyze.c:2320
#, c-format
msgid "cannot specify both SCROLL and NO SCROLL"
-msgstr "ne peut pas sp�cifier � la fois SCROLL et NO SCROLL"
+msgstr "ne peut pas spécifier à la fois SCROLL et NO SCROLL"
-#: parser/analyze.c:2270
+#: parser/analyze.c:2338
#, c-format
msgid "DECLARE CURSOR must not contain data-modifying statements in WITH"
-msgstr "DECLARE CURSOR ne doit pas contenir des instructions de modification de donn�es dans WITH"
+msgstr "DECLARE CURSOR ne doit pas contenir des instructions de modification de données dans WITH"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2278
+#: parser/analyze.c:2346
#, c-format
msgid "DECLARE CURSOR WITH HOLD ... %s is not supported"
-msgstr "DECLARE CURSOR WITH HOLD ... %s n'est pas support�"
+msgstr "DECLARE CURSOR WITH HOLD ... %s n'est pas supporté"
-#: parser/analyze.c:2281
+#: parser/analyze.c:2349
#, c-format
msgid "Holdable cursors must be READ ONLY."
-msgstr "Les curseurs d�tenables doivent �tre en lecture seule (READ ONLY)."
+msgstr "Les curseurs détenables doivent être en lecture seule (READ ONLY)."
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2289
+#: parser/analyze.c:2357
#, c-format
msgid "DECLARE SCROLL CURSOR ... %s is not supported"
-msgstr "DECLARE SCROLL CURSOR ... %s n'est pas support�"
+msgstr "DECLARE SCROLL CURSOR ... %s n'est pas supporté"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2300
+#: parser/analyze.c:2368
#, c-format
msgid "DECLARE INSENSITIVE CURSOR ... %s is not supported"
-msgstr "DECLARE INSENSITIVE CURSOR ... %s n'est pas support�"
+msgstr "DECLARE INSENSITIVE CURSOR ... %s n'est pas supporté"
-#: parser/analyze.c:2303
+#: parser/analyze.c:2371
#, c-format
msgid "Insensitive cursors must be READ ONLY."
-msgstr "Les curseurs insensibles doivent �tre en lecture seule (READ ONLY)."
+msgstr "Les curseurs insensibles doivent être en lecture seule (READ ONLY)."
-#: parser/analyze.c:2369
+#: parser/analyze.c:2437
#, c-format
msgid "materialized views must not use data-modifying statements in WITH"
-msgstr "les vues mat�rialis�es ne peuvent pas contenir d'instructions de modifications de donn�es avec WITH"
+msgstr "les vues matérialisées ne peuvent pas contenir d'instructions de modifications de données avec WITH"
-#: parser/analyze.c:2379
+#: parser/analyze.c:2447
#, c-format
msgid "materialized views must not use temporary tables or views"
-msgstr "les vues mat�rialis�es ne doivent pas utiliser de tables temporaires ou de vues"
+msgstr "les vues matérialisées ne doivent pas utiliser de tables temporaires ou de vues"
-#: parser/analyze.c:2389
+#: parser/analyze.c:2457
#, c-format
msgid "materialized views may not be defined using bound parameters"
-msgstr "les vues mat�rialis�es ne peuvent pas �tre d�finies en utilisant des param�tres li�s"
+msgstr "les vues matérialisées ne peuvent pas être définies en utilisant des paramètres liés"
-#: parser/analyze.c:2401
+#: parser/analyze.c:2469
#, c-format
msgid "materialized views cannot be UNLOGGED"
-msgstr "les vues mat�rialis�es ne peuvent pas �tre UNLOGGED"
+msgstr "les vues matérialisées ne peuvent pas être UNLOGGED"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2467
+#: parser/analyze.c:2535
#, c-format
msgid "%s is not allowed with DISTINCT clause"
-msgstr "%s n'est pas autoris� avec la clause DISTINCT"
+msgstr "%s n'est pas autorisé avec la clause DISTINCT"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2474
+#: parser/analyze.c:2542
#, c-format
msgid "%s is not allowed with GROUP BY clause"
-msgstr "%s n'est pas autoris� avec la clause GROUP BY"
+msgstr "%s n'est pas autorisé avec la clause GROUP BY"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2481
+#: parser/analyze.c:2549
#, c-format
msgid "%s is not allowed with HAVING clause"
-msgstr "%s n'est pas autoris� avec la clause HAVING"
+msgstr "%s n'est pas autorisé avec la clause HAVING"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2488
+#: parser/analyze.c:2556
#, c-format
msgid "%s is not allowed with aggregate functions"
-msgstr "%s n'est pas autoris� avec les fonctions d'agr�gat"
+msgstr "%s n'est pas autorisé avec les fonctions d'agrégat"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2495
+#: parser/analyze.c:2563
#, c-format
msgid "%s is not allowed with window functions"
-msgstr "%s n'est pas autoris� avec les fonctions de fen�trage"
+msgstr "%s n'est pas autorisé avec les fonctions de fenêtrage"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2502
+#: parser/analyze.c:2570
#, c-format
msgid "%s is not allowed with set-returning functions in the target list"
-msgstr "%s n'est pas autoris� avec les fonctions renvoyant plusieurs lignes dans la liste cible"
+msgstr "%s n'est pas autorisé avec les fonctions renvoyant plusieurs lignes dans la liste cible"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2581
+#: parser/analyze.c:2649
#, c-format
msgid "%s must specify unqualified relation names"
-msgstr "%s doit indiquer les noms de relation non qualifi�s"
+msgstr "%s doit indiquer les noms de relation non qualifiés"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2612
+#: parser/analyze.c:2680
#, c-format
msgid "%s cannot be applied to a join"
-msgstr "%s ne peut pas �tre appliqu� � une jointure"
+msgstr "%s ne peut pas être appliqué à une jointure"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2621
+#: parser/analyze.c:2689
#, c-format
msgid "%s cannot be applied to a function"
-msgstr "%s ne peut pas �tre appliqu� � une fonction"
+msgstr "%s ne peut pas être appliqué à une fonction"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2639
+#: parser/analyze.c:2707
#, c-format
msgid "%s cannot be applied to a WITH query"
-msgstr "%s ne peut pas �tre appliqu� � une requ�te WITH"
+msgstr "%s ne peut pas être appliqué à une requête WITH"
#. translator: %s is a SQL row locking clause such as FOR UPDATE
-#: parser/analyze.c:2656
+#: parser/analyze.c:2724
#, c-format
msgid "relation \"%s\" in %s clause not found in FROM clause"
-msgstr "relation � %s � dans une clause %s introuvable dans la clause FROM"
+msgstr "relation « %s » dans une clause %s introuvable dans la clause FROM"
-#: parser/parse_agg.c:208 parser/parse_oper.c:220
+#: parser/parse_agg.c:223 parser/parse_oper.c:220
#, c-format
msgid "could not identify an ordering operator for type %s"
-msgstr "n'a pas pu identifier un op�rateur de tri pour le type %s"
+msgstr "n'a pas pu identifier un opérateur de tri pour le type %s"
-#: parser/parse_agg.c:210
+#: parser/parse_agg.c:225
#, c-format
msgid "Aggregates with DISTINCT must be able to sort their inputs."
-msgstr "Les agr�gats avec DISTINCT doivent �tre capable de trier leur entr�e."
+msgstr "Les agrégats avec DISTINCT doivent être capable de trier leur entrée."
-#: parser/parse_agg.c:245
+#: parser/parse_agg.c:260
#, c-format
msgid "GROUPING must have fewer than 32 arguments"
msgstr "GROUPING doit avoir moins de 32 arguments"
-#: parser/parse_agg.c:348
+#: parser/parse_agg.c:363
msgid "aggregate functions are not allowed in JOIN conditions"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les conditions de jointures"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les conditions de jointures"
-#: parser/parse_agg.c:350
+#: parser/parse_agg.c:365
msgid "grouping operations are not allowed in JOIN conditions"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les conditions de jointure"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les conditions de jointure"
-#: parser/parse_agg.c:362
+#: parser/parse_agg.c:377
msgid "aggregate functions are not allowed in FROM clause of their own query level"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans la clause FROM du m�me niveau de la requ�te"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans la clause FROM du même niveau de la requête"
-#: parser/parse_agg.c:364
+#: parser/parse_agg.c:379
msgid "grouping operations are not allowed in FROM clause of their own query level"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans la clause FROM du m�me niveau de la requ�te"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans la clause FROM du même niveau de la requête"
-#: parser/parse_agg.c:369
+#: parser/parse_agg.c:384
msgid "aggregate functions are not allowed in functions in FROM"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les fonctions contenues dans la clause FROM"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les fonctions contenues dans la clause FROM"
-#: parser/parse_agg.c:371
+#: parser/parse_agg.c:386
msgid "grouping operations are not allowed in functions in FROM"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les fonctions contenues dans la clause FROM"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les fonctions contenues dans la clause FROM"
-#: parser/parse_agg.c:379
+#: parser/parse_agg.c:394
msgid "aggregate functions are not allowed in policy expressions"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les expressions de politique"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les expressions de politique"
-#: parser/parse_agg.c:381
+#: parser/parse_agg.c:396
msgid "grouping operations are not allowed in policy expressions"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les expressions de politique"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les expressions de politique"
-#: parser/parse_agg.c:398
+#: parser/parse_agg.c:413
msgid "aggregate functions are not allowed in window RANGE"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans le RANGE de fen�trage"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans le RANGE de fenêtrage"
-#: parser/parse_agg.c:400
+#: parser/parse_agg.c:415
msgid "grouping operations are not allowed in window RANGE"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans le RANGE de fen�trage"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans le RANGE de fenêtrage"
-#: parser/parse_agg.c:405
+#: parser/parse_agg.c:420
msgid "aggregate functions are not allowed in window ROWS"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans le ROWS de fen�trage"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans le ROWS de fenêtrage"
-#: parser/parse_agg.c:407
+#: parser/parse_agg.c:422
msgid "grouping operations are not allowed in window ROWS"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans le ROWS de fen�trage"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans le ROWS de fenêtrage"
-#: parser/parse_agg.c:440
+#: parser/parse_agg.c:455
msgid "aggregate functions are not allowed in check constraints"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les contraintes CHECK"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les contraintes CHECK"
-#: parser/parse_agg.c:442
+#: parser/parse_agg.c:457
msgid "grouping operations are not allowed in check constraints"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les contraintes CHECK"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les contraintes CHECK"
-#: parser/parse_agg.c:449
+#: parser/parse_agg.c:464
msgid "aggregate functions are not allowed in DEFAULT expressions"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les expressions par d�faut"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les expressions par défaut"
-#: parser/parse_agg.c:451
+#: parser/parse_agg.c:466
msgid "grouping operations are not allowed in DEFAULT expressions"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les expressions par d�faut"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les expressions par défaut"
-#: parser/parse_agg.c:456
+#: parser/parse_agg.c:471
msgid "aggregate functions are not allowed in index expressions"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les expressions d'index"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les expressions d'index"
-#: parser/parse_agg.c:458
+#: parser/parse_agg.c:473
msgid "grouping operations are not allowed in index expressions"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les expressions d'index"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les expressions d'index"
-#: parser/parse_agg.c:463
+#: parser/parse_agg.c:478
msgid "aggregate functions are not allowed in index predicates"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les pr�dicats d'index"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les prédicats d'index"
-#: parser/parse_agg.c:465
+#: parser/parse_agg.c:480
msgid "grouping operations are not allowed in index predicates"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les pr�dicats d'index"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les prédicats d'index"
-#: parser/parse_agg.c:470
+#: parser/parse_agg.c:485
msgid "aggregate functions are not allowed in transform expressions"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les expressions de transformation"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les expressions de transformation"
-#: parser/parse_agg.c:472
+#: parser/parse_agg.c:487
msgid "grouping operations are not allowed in transform expressions"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les expressions de transformation"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les expressions de transformation"
-#: parser/parse_agg.c:477
+#: parser/parse_agg.c:492
msgid "aggregate functions are not allowed in EXECUTE parameters"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les param�tres d'EXECUTE"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les paramètres d'EXECUTE"
-#: parser/parse_agg.c:479
+#: parser/parse_agg.c:494
msgid "grouping operations are not allowed in EXECUTE parameters"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les param�tres d'EXECUTE"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les paramètres d'EXECUTE"
-#: parser/parse_agg.c:484
+#: parser/parse_agg.c:499
msgid "aggregate functions are not allowed in trigger WHEN conditions"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans les conditions WHEN des triggers"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans les conditions WHEN des triggers"
-#: parser/parse_agg.c:486
+#: parser/parse_agg.c:501
msgid "grouping operations are not allowed in trigger WHEN conditions"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans les conditions WHEN des triggers"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans les conditions WHEN des triggers"
#. translator: %s is name of a SQL construct, eg GROUP BY
-#: parser/parse_agg.c:509 parser/parse_clause.c:1550
+#: parser/parse_agg.c:524 parser/parse_clause.c:1550
#, c-format
msgid "aggregate functions are not allowed in %s"
-msgstr "les fonctions d'agr�gats ne sont pas autoris�s dans %s"
+msgstr "les fonctions d'agrégats ne sont pas autorisés dans %s"
#. translator: %s is name of a SQL construct, eg GROUP BY
-#: parser/parse_agg.c:512
+#: parser/parse_agg.c:527
#, c-format
msgid "grouping operations are not allowed in %s"
-msgstr "les fonctions de regroupement ne sont pas autoris�s dans %s"
+msgstr "les fonctions de regroupement ne sont pas autorisés dans %s"
-#: parser/parse_agg.c:620
+#: parser/parse_agg.c:635
#, c-format
msgid "outer-level aggregate cannot contain a lower-level variable in its direct arguments"
-msgstr ""
+msgstr "un aggrégat de niveau externe ne peut pas contenir de variable de niveau inférieur dans ses arguments directs"
-#: parser/parse_agg.c:691
+#: parser/parse_agg.c:706
#, c-format
msgid "aggregate function calls cannot contain window function calls"
msgstr ""
-"les appels � la fonction d'agr�gat ne peuvent pas contenir des appels � la\n"
+"les appels à la fonction d'agrégat ne peuvent pas contenir des appels à la\n"
"fonction window"
-#: parser/parse_agg.c:769
+#: parser/parse_agg.c:784
msgid "window functions are not allowed in JOIN conditions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les conditions de jointure"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les conditions de jointure"
-#: parser/parse_agg.c:776
+#: parser/parse_agg.c:791
msgid "window functions are not allowed in functions in FROM"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les fonctions contenues dans la clause FROM"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les fonctions contenues dans la clause FROM"
-#: parser/parse_agg.c:782
+#: parser/parse_agg.c:797
msgid "window functions are not allowed in policy expressions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les expressions de politique"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les expressions de politique"
-#: parser/parse_agg.c:794
+#: parser/parse_agg.c:809
msgid "window functions are not allowed in window definitions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les d�finitions de fen�tres"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les définitions de fenêtres"
-#: parser/parse_agg.c:825
+#: parser/parse_agg.c:840
msgid "window functions are not allowed in check constraints"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les contraintes CHECK"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les contraintes CHECK"
-#: parser/parse_agg.c:829
+#: parser/parse_agg.c:844
msgid "window functions are not allowed in DEFAULT expressions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les expressions par d�faut"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les expressions par défaut"
-#: parser/parse_agg.c:832
+#: parser/parse_agg.c:847
msgid "window functions are not allowed in index expressions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les expressions d'index"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les expressions d'index"
-#: parser/parse_agg.c:835
+#: parser/parse_agg.c:850
msgid "window functions are not allowed in index predicates"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les pr�dicats d'index"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les prédicats d'index"
-#: parser/parse_agg.c:838
+#: parser/parse_agg.c:853
msgid "window functions are not allowed in transform expressions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les expressions de transformation"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les expressions de transformation"
-#: parser/parse_agg.c:841
+#: parser/parse_agg.c:856
msgid "window functions are not allowed in EXECUTE parameters"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les param�tres d'EXECUTE"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les paramètres d'EXECUTE"
-#: parser/parse_agg.c:844
+#: parser/parse_agg.c:859
msgid "window functions are not allowed in trigger WHEN conditions"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans les conditions WHEN des triggers"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans les conditions WHEN des triggers"
#. translator: %s is name of a SQL construct, eg GROUP BY
-#: parser/parse_agg.c:864 parser/parse_clause.c:1559
+#: parser/parse_agg.c:879 parser/parse_clause.c:1559
#, c-format
msgid "window functions are not allowed in %s"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans %s"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans %s"
-#: parser/parse_agg.c:898 parser/parse_clause.c:2396
+#: parser/parse_agg.c:913 parser/parse_clause.c:2396
#, c-format
msgid "window \"%s\" does not exist"
-msgstr "le window � %s � n'existe pas"
+msgstr "le window « %s » n'existe pas"
-#: parser/parse_agg.c:983
+#: parser/parse_agg.c:998
#, c-format
msgid "too many grouping sets present (maximum 4096)"
-msgstr "trop d'ensembles de regroupement pr�sents (4096 maximum)"
+msgstr "trop d'ensembles de regroupement présents (4096 maximum)"
-#: parser/parse_agg.c:1132
+#: parser/parse_agg.c:1147
#, c-format
msgid "aggregate functions are not allowed in a recursive query's recursive term"
-msgstr "les fonctions de fen�trage ne sont pas autoris�s dans le terme r�cursif d'une requ�te r�cursive"
+msgstr "les fonctions de fenêtrage ne sont pas autorisés dans le terme récursif d'une requête récursive"
-#: parser/parse_agg.c:1325
+#: parser/parse_agg.c:1340
#, c-format
msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function"
-msgstr "la colonne � %s.%s � doit appara�tre dans la clause GROUP BY ou doit �tre utilis� dans une fonction d'agr�gat"
+msgstr "la colonne « %s.%s » doit apparaître dans la clause GROUP BY ou doit être utilisé dans une fonction d'agrégat"
-#: parser/parse_agg.c:1328
+#: parser/parse_agg.c:1343
#, c-format
msgid "Direct arguments of an ordered-set aggregate must use only grouped columns."
-msgstr "Les arguments directs d'un ag�gat par ensemble ordonn� doivent seulement utiliser des colonnes group�es."
+msgstr "Les arguments directs d'un agégat par ensemble ordonné doivent seulement utiliser des colonnes groupées."
-#: parser/parse_agg.c:1333
+#: parser/parse_agg.c:1348
#, c-format
msgid "subquery uses ungrouped column \"%s.%s\" from outer query"
msgstr ""
-"la sous-requ�te utilise une colonne � %s.%s � non group�e dans la requ�te\n"
+"la sous-requête utilise une colonne « %s.%s » non groupée dans la requête\n"
"externe"
-#: parser/parse_agg.c:1497
+#: parser/parse_agg.c:1512
#, c-format
msgid "arguments to GROUPING must be grouping expressions of the associated query level"
-msgstr "les arguments de la clause GROUPING doivent �tre des expressions de regroupement du niveau de la requ�te associ�e"
+msgstr "les arguments de la clause GROUPING doivent être des expressions de regroupement du niveau de la requête associée"
#: parser/parse_clause.c:649
#, c-format
msgid "multiple column definition lists are not allowed for the same function"
-msgstr "plusieurs listes de d�finition de colonnes ne sont pas autoris�es pour la m�me fonction"
+msgstr "plusieurs listes de définition de colonnes ne sont pas autorisées pour la même fonction"
#: parser/parse_clause.c:682
#, c-format
msgid "ROWS FROM() with multiple functions cannot have a column definition list"
-msgstr "ROWS FROM() avec plusieurs fonctions ne peut pas avoir une liste de d�finitions de colonnes"
+msgstr "ROWS FROM() avec plusieurs fonctions ne peut pas avoir une liste de définitions de colonnes"
#: parser/parse_clause.c:683
#, c-format
msgid "Put a separate column definition list for each function inside ROWS FROM()."
-msgstr "Placer une liste de d�finitions de colonnes s�par�e pour chaque fonction � l'int�rieur de ROWS FROM()."
+msgstr "Placer une liste de définitions de colonnes séparée pour chaque fonction à l'intérieur de ROWS FROM()."
#: parser/parse_clause.c:689
#, c-format
msgid "UNNEST() with multiple arguments cannot have a column definition list"
-msgstr "UNNEST() avec plusieurs arguments ne peut pas avoir de liste de d�finition de colonnes"
+msgstr "UNNEST() avec plusieurs arguments ne peut pas avoir de liste de définition de colonnes"
#: parser/parse_clause.c:690
#, c-format
msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one."
-msgstr "Utiliser des appels s�par�s UNNEST() � l'int�rieur de ROWS FROM(), et attacher une liste de d�finition des colonnes pour chaque."
+msgstr "Utiliser des appels séparés UNNEST() à l'intérieur de ROWS FROM(), et attacher une liste de définition des colonnes pour chaque."
#: parser/parse_clause.c:697
#, c-format
msgid "WITH ORDINALITY cannot be used with a column definition list"
-msgstr "WITH ORDINALITY ne peut pas �tre utilis� avec une liste de d�finitions de colonnes"
+msgstr "WITH ORDINALITY ne peut pas être utilisé avec une liste de définitions de colonnes"
#: parser/parse_clause.c:698
#, c-format
msgid "Put the column definition list inside ROWS FROM()."
-msgstr "Placez la liste de d�finitions des colonnes dans ROWS FROM()."
+msgstr "Placez la liste de définitions des colonnes dans ROWS FROM()."
#: parser/parse_clause.c:753
#, c-format
msgid "tablesample method %s does not exist"
-msgstr "la m�thode d'�chantillonage %s n'existe pas"
+msgstr "la méthode d'échantillonage %s n'existe pas"
#: parser/parse_clause.c:775
#, c-format
msgid "tablesample method %s requires %d argument, not %d"
msgid_plural "tablesample method %s requires %d arguments, not %d"
-msgstr[0] "la m�thode d'�chantillonage %s requiert %d argument, et non pas %d"
-msgstr[1] "la m�thode d'�chantillonage %s requiert %d arguments, et non pas %d"
+msgstr[0] "la méthode d'échantillonage %s requiert %d argument, et non pas %d"
+msgstr[1] "la méthode d'échantillonage %s requiert %d arguments, et non pas %d"
#: parser/parse_clause.c:809
#, c-format
msgid "tablesample method %s does not support REPEATABLE"
-msgstr "la m�thode d'�chantillonage %s ne supporte pas REPEATABLE"
+msgstr "la méthode d'échantillonage %s ne supporte pas REPEATABLE"
#: parser/parse_clause.c:940
#, c-format
msgid "TABLESAMPLE clause can only be applied to tables and materialized views"
-msgstr "la clause TABLESPACE est uniquement applicable pour les tables et les vues mat�rialis�es"
+msgstr "la clause TABLESAMPLE est uniquement applicable pour les tables et les vues matérialisées"
#: parser/parse_clause.c:1110
#, c-format
msgid "column name \"%s\" appears more than once in USING clause"
-msgstr "le nom de la colonne � %s � appara�t plus d'une fois dans la clause USING"
+msgstr "le nom de la colonne « %s » apparaît plus d'une fois dans la clause USING"
#: parser/parse_clause.c:1125
#, c-format
msgid "common column name \"%s\" appears more than once in left table"
msgstr ""
-"le nom commun de la colonne � %s � appara�t plus d'une fois dans la table de\n"
+"le nom commun de la colonne « %s » apparaît plus d'une fois dans la table de\n"
"gauche"
#: parser/parse_clause.c:1134
#, c-format
msgid "column \"%s\" specified in USING clause does not exist in left table"
msgstr ""
-"la colonne � %s � sp�cifi�e dans la clause USING n'existe pas dans la table\n"
+"la colonne « %s » spécifiée dans la clause USING n'existe pas dans la table\n"
"de gauche"
#: parser/parse_clause.c:1148
#, c-format
msgid "common column name \"%s\" appears more than once in right table"
msgstr ""
-"le nom commun de la colonne � %s � appara�t plus d'une fois dans la table de\n"
+"le nom commun de la colonne « %s » apparaît plus d'une fois dans la table de\n"
" droite"
#: parser/parse_clause.c:1157
#, c-format
msgid "column \"%s\" specified in USING clause does not exist in right table"
msgstr ""
-"la colonne � %s � sp�cifi�e dans la clause USING n'existe pas dans la table\n"
+"la colonne « %s » spécifiée dans la clause USING n'existe pas dans la table\n"
"de droite"
#: parser/parse_clause.c:1211
#, c-format
msgid "column alias list for \"%s\" has too many entries"
-msgstr "la liste d'alias de colonnes pour � %s � a beaucoup trop d'entr�es"
+msgstr "la liste d'alias de colonnes pour « %s » a beaucoup trop d'entrées"
#. translator: %s is name of a SQL construct, eg LIMIT
#: parser/parse_clause.c:1520
#, c-format
msgid "argument of %s must not contain variables"
-msgstr "l'argument de � %s � ne doit pas contenir de variables"
+msgstr "l'argument de « %s » ne doit pas contenir de variables"
#. translator: first %s is name of a SQL construct, eg ORDER BY
#: parser/parse_clause.c:1685
#, c-format
msgid "%s \"%s\" is ambiguous"
-msgstr "%s � %s � est ambigu"
+msgstr "%s « %s » est ambigu"
#. translator: %s is name of a SQL construct, eg ORDER BY
#: parser/parse_clause.c:1714
#, c-format
msgid "non-integer constant in %s"
-msgstr "constante non enti�re dans %s"
+msgstr "constante non entière dans %s"
#. translator: %s is name of a SQL construct, eg ORDER BY
#: parser/parse_clause.c:1736
#, c-format
msgid "%s position %d is not in select list"
-msgstr "%s, � la position %d, n'est pas dans la liste SELECT"
+msgstr "%s, à la position %d, n'est pas dans la liste SELECT"
#: parser/parse_clause.c:2178
#, c-format
msgid "CUBE is limited to 12 elements"
-msgstr "CUBE est limit� � 12 �l�ments"
+msgstr "CUBE est limité à 12 éléments"
#: parser/parse_clause.c:2384
#, c-format
msgid "window \"%s\" is already defined"
-msgstr "le window � %s � est d�j� d�finie"
+msgstr "le window « %s » est déjà définie"
#: parser/parse_clause.c:2446
#, c-format
msgid "cannot override PARTITION BY clause of window \"%s\""
-msgstr "n'a pas pu surcharger la clause PARTITION BY de window � %s �"
+msgstr "n'a pas pu surcharger la clause PARTITION BY de window « %s »"
#: parser/parse_clause.c:2458
#, c-format
msgid "cannot override ORDER BY clause of window \"%s\""
-msgstr "n'a pas pu surcharger la clause ORDER BY de window � %s �"
+msgstr "n'a pas pu surcharger la clause ORDER BY de window « %s »"
#: parser/parse_clause.c:2488 parser/parse_clause.c:2494
#, c-format
msgid "cannot copy window \"%s\" because it has a frame clause"
-msgstr "ne peut pas copier la fen�tre � %s � car il dispose d'une clause de port�e"
+msgstr "ne peut pas copier la fenêtre « %s » car il dispose d'une clause de portée"
#: parser/parse_clause.c:2496
#, c-format
msgid "Omit the parentheses in this OVER clause."
-msgstr "Omettre les parenth�ses dans cette clause OVER."
+msgstr "Omettre les parenthèses dans cette clause OVER."
#: parser/parse_clause.c:2562
#, c-format
msgid "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list"
msgstr ""
-"dans un agr�gat avec DISTINCT, les expressions ORDER BY doivent appara�tre\n"
+"dans un agrégat avec DISTINCT, les expressions ORDER BY doivent apparaître\n"
"dans la liste d'argument"
#: parser/parse_clause.c:2563
#, c-format
msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list"
msgstr ""
-"pour SELECT DISTINCT, ORDER BY, les expressions doivent appara�tre dans la\n"
+"pour SELECT DISTINCT, ORDER BY, les expressions doivent apparaître dans la\n"
"liste SELECT"
#: parser/parse_clause.c:2596
#, c-format
msgid "an aggregate with DISTINCT must have at least one argument"
-msgstr "un agr�gat avec DISTINCT doit avoir au moins un argument"
+msgstr "un agrégat avec DISTINCT doit avoir au moins un argument"
#: parser/parse_clause.c:2597
#, c-format
@@ -13162,17 +13177,17 @@ msgstr ""
#: parser/parse_clause.c:2774
#, c-format
msgid "ASC/DESC is not allowed in ON CONFLICT clause"
-msgstr "ASC/DESC n'est pas autoris� avec la clause ON CONFLICT"
+msgstr "ASC/DESC n'est pas autorisé avec la clause ON CONFLICT"
#: parser/parse_clause.c:2780
#, c-format
msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause"
-msgstr "NULLS FIRST/LAST n'est pas autoris� avec la clause ON CONFLICT"
+msgstr "NULLS FIRST/LAST n'est pas autorisé avec la clause ON CONFLICT"
#: parser/parse_clause.c:2860
#, c-format
msgid "ON CONFLICT DO UPDATE requires inference specification or constraint name"
-msgstr "ON CONFLICT DO UPDATE requiert une sp�cification d'inf�rence ou un nom de contrainte"
+msgstr "ON CONFLICT DO UPDATE requiert une spécification d'inférence ou un nom de contrainte"
#: parser/parse_clause.c:2861
#, c-format
@@ -13182,26 +13197,26 @@ msgstr "Par exemple, ON CONFLICT (nom_colonne)"
#: parser/parse_clause.c:2872
#, c-format
msgid "ON CONFLICT is not supported with system catalog tables"
-msgstr "ON CONFLICT n'est pas support� avec les catalogues syst�mes"
+msgstr "ON CONFLICT n'est pas supporté avec les catalogues systèmes"
#: parser/parse_clause.c:2880
#, c-format
msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table"
-msgstr "ON CONFLICT n'est pas support� sur la table � %s � utilis�e comme une table catalogue"
+msgstr "ON CONFLICT n'est pas supporté sur la table « %s » utilisée comme une table catalogue"
#: parser/parse_clause.c:3012
#, c-format
msgid "operator %s is not a valid ordering operator"
-msgstr "l'op�rateur %s n'est pas un op�rateur de tri valide"
+msgstr "l'opérateur %s n'est pas un opérateur de tri valide"
#: parser/parse_clause.c:3014
#, c-format
msgid "Ordering operators must be \"<\" or \">\" members of btree operator families."
msgstr ""
-"Les op�rateurs de tri doivent �tre les membres � < � ou � > � des familles\n"
-"d'op�rateurs btree."
+"Les opérateurs de tri doivent être les membres « < » ou « > » des familles\n"
+"d'opérateurs btree."
-#: parser/parse_coerce.c:971 parser/parse_coerce.c:1001 parser/parse_coerce.c:1019 parser/parse_coerce.c:1034 parser/parse_expr.c:2028 parser/parse_expr.c:2552 parser/parse_target.c:874
+#: parser/parse_coerce.c:971 parser/parse_coerce.c:1001 parser/parse_coerce.c:1019 parser/parse_coerce.c:1034 parser/parse_expr.c:2053 parser/parse_expr.c:2577 parser/parse_target.c:885
#, c-format
msgid "cannot cast type %s to %s"
msgstr "ne peut pas convertir le type %s en %s"
@@ -13209,7 +13224,7 @@ msgstr "ne peut pas convertir le type %s en %s"
#: parser/parse_coerce.c:1004
#, c-format
msgid "Input has too few columns."
-msgstr "L'entr�e n'a pas assez de colonnes."
+msgstr "L'entrée n'a pas assez de colonnes."
#: parser/parse_coerce.c:1022
#, c-format
@@ -13219,13 +13234,13 @@ msgstr "ne peut pas convertir le type %s en %s dans la colonne %d"
#: parser/parse_coerce.c:1037
#, c-format
msgid "Input has too many columns."
-msgstr "L'entr�e a trop de colonnes."
+msgstr "L'entrée a trop de colonnes."
#. translator: first %s is name of a SQL construct, eg WHERE
#: parser/parse_coerce.c:1080
#, c-format
msgid "argument of %s must be type boolean, not type %s"
-msgstr "l'argument de %s doit �tre de type bool�en, et non du type %s"
+msgstr "l'argument de %s doit être de type booléen, et non du type %s"
#. translator: %s is name of a SQL construct, eg WHERE
#. translator: %s is name of a SQL construct, eg LIMIT
@@ -13238,7 +13253,7 @@ msgstr "l'argument de %s ne doit pas renvoyer un ensemble"
#: parser/parse_coerce.c:1127
#, c-format
msgid "argument of %s must be type %s, not type %s"
-msgstr "l'argument de %s doit �tre de type %s, et non du type %s"
+msgstr "l'argument de %s doit être de type %s, et non du type %s"
#. translator: first %s is name of a SQL construct, eg CASE
#: parser/parse_coerce.c:1260
@@ -13255,441 +13270,441 @@ msgstr "%s n'a pas pu convertir le type %s en %s"
#: parser/parse_coerce.c:1629
#, c-format
msgid "arguments declared \"anyelement\" are not all alike"
-msgstr "les arguments d�clar�s � anyelement � ne sont pas tous identiques"
+msgstr "les arguments déclarés « anyelement » ne sont pas tous identiques"
#: parser/parse_coerce.c:1649
#, c-format
msgid "arguments declared \"anyarray\" are not all alike"
-msgstr "les arguments d�clar�s � anyarray � ne sont pas tous identiques"
+msgstr "les arguments déclarés « anyarray » ne sont pas tous identiques"
#: parser/parse_coerce.c:1669
#, c-format
msgid "arguments declared \"anyrange\" are not all alike"
-msgstr "les arguments d�clar�s � anyrange � ne sont pas tous identiques"
+msgstr "les arguments déclarés « anyrange » ne sont pas tous identiques"
#: parser/parse_coerce.c:1698 parser/parse_coerce.c:1909 parser/parse_coerce.c:1943
#, c-format
msgid "argument declared \"anyarray\" is not an array but type %s"
-msgstr "l'argument d�clar� � anyarray � n'est pas un tableau mais est du type %s"
+msgstr "l'argument déclaré « anyarray » n'est pas un tableau mais est du type %s"
#: parser/parse_coerce.c:1714
#, c-format
msgid "argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""
msgstr ""
-"l'argument d�clar� � anyarray � n'est pas coh�rent avec l'argument d�clar�\n"
-"� anyelement �"
+"l'argument déclaré « anyarray » n'est pas cohérent avec l'argument déclaré\n"
+"« anyelement »"
#: parser/parse_coerce.c:1735 parser/parse_coerce.c:1956
#, c-format
msgid "argument declared \"anyrange\" is not a range type but type %s"
-msgstr "l'argument d�clar� � anyrange � n'est pas un type d'intervalle mais est du type %s"
+msgstr "l'argument déclaré « anyrange » n'est pas un type d'intervalle mais est du type %s"
#: parser/parse_coerce.c:1751
#, c-format
msgid "argument declared \"anyrange\" is not consistent with argument declared \"anyelement\""
msgstr ""
-"l'argument d�clar� � anyrange � n'est pas coh�rent avec l'argument d�clar�\n"
-"� anyelement �"
+"l'argument déclaré « anyrange » n'est pas cohérent avec l'argument déclaré\n"
+"« anyelement »"
#: parser/parse_coerce.c:1771
#, c-format
msgid "could not determine polymorphic type because input has type \"unknown\""
msgstr ""
-"n'a pas pu d�terminer le type polymorphique car l'entr�e dispose du type\n"
-"� unknown �"
+"n'a pas pu déterminer le type polymorphique car l'entrée dispose du type\n"
+"« unknown »"
#: parser/parse_coerce.c:1781
#, c-format
msgid "type matched to anynonarray is an array type: %s"
-msgstr "le type d�clar� anynonarray est un type tableau : %s"
+msgstr "le type déclaré anynonarray est un type tableau : %s"
#: parser/parse_coerce.c:1791
#, c-format
msgid "type matched to anyenum is not an enum type: %s"
-msgstr "le type d�clar� anyenum n'est pas un type enum : %s"
+msgstr "le type déclaré anyenum n'est pas un type enum : %s"
#: parser/parse_coerce.c:1831 parser/parse_coerce.c:1861
#, c-format
msgid "could not find range type for data type %s"
-msgstr "n'a pas pu trouver le type range pour le type de donn�es %s"
+msgstr "n'a pas pu trouver le type range pour le type de données %s"
#: parser/parse_collate.c:228 parser/parse_collate.c:475 parser/parse_collate.c:986
#, c-format
msgid "collation mismatch between implicit collations \"%s\" and \"%s\""
-msgstr "le collationnement ne correspond pas aux collationnements implicites � %s � et � %s �"
+msgstr "le collationnement ne correspond pas aux collationnements implicites « %s » et « %s »"
#: parser/parse_collate.c:231 parser/parse_collate.c:478 parser/parse_collate.c:989
#, c-format
msgid "You can choose the collation by applying the COLLATE clause to one or both expressions."
-msgstr "Vous pouvez choisir le collationnement en appliquant la clause COLLATE � une ou aux deux expressions."
+msgstr "Vous pouvez choisir le collationnement en appliquant la clause COLLATE à une ou aux deux expressions."
#: parser/parse_collate.c:834
#, c-format
msgid "collation mismatch between explicit collations \"%s\" and \"%s\""
-msgstr "le collationnement ne correspond pas aux collationnements explicites � %s � et � %s �"
+msgstr "le collationnement ne correspond pas aux collationnements explicites « %s » et « %s »"
#: parser/parse_cte.c:42
#, c-format
msgid "recursive reference to query \"%s\" must not appear within its non-recursive term"
msgstr ""
-"la r�f�rence r�cursive � la requ�te � %s � ne doit pas appara�tre �\n"
-"l'int�rieur de son terme non r�cursif"
+"la référence récursive à la requête « %s » ne doit pas apparaître à\n"
+"l'intérieur de son terme non récursif"
#: parser/parse_cte.c:44
#, c-format
msgid "recursive reference to query \"%s\" must not appear within a subquery"
msgstr ""
-"la r�f�rence r�cursive � la requ�te � %s � ne doit pas appara�tre �\n"
-"l'int�rieur d'une sous-requ�te"
+"la référence récursive à la requête « %s » ne doit pas apparaître à\n"
+"l'intérieur d'une sous-requête"
#: parser/parse_cte.c:46
#, c-format
msgid "recursive reference to query \"%s\" must not appear within an outer join"
msgstr ""
-"la r�f�rence r�cursive � la requ�te � %s � ne doit pas appara�tre �\n"
-"l'int�rieur d'une jointure externe"
+"la référence récursive à la requête « %s » ne doit pas apparaître à\n"
+"l'intérieur d'une jointure externe"
#: parser/parse_cte.c:48
#, c-format
msgid "recursive reference to query \"%s\" must not appear within INTERSECT"
msgstr ""
-"la r�f�rence r�cursive � la requ�te � %s � ne doit pas appara�tre �\n"
-"l'int�rieur d'INTERSECT"
+"la référence récursive à la requête « %s » ne doit pas apparaître à\n"
+"l'intérieur d'INTERSECT"
#: parser/parse_cte.c:50
#, c-format
msgid "recursive reference to query \"%s\" must not appear within EXCEPT"
msgstr ""
-"la r�f�rence r�cursive � la requ�te � %s � ne doit pas appara�tre �\n"
-"l'int�rieur d'EXCEPT"
+"la référence récursive à la requête « %s » ne doit pas apparaître à\n"
+"l'intérieur d'EXCEPT"
#: parser/parse_cte.c:132
#, c-format
msgid "WITH query name \"%s\" specified more than once"
-msgstr "le nom de la requ�te WITH � %s � est sp�cifi� plus d'une fois"
+msgstr "le nom de la requête WITH « %s » est spécifié plus d'une fois"
#: parser/parse_cte.c:264
#, c-format
msgid "WITH clause containing a data-modifying statement must be at the top level"
msgstr ""
-"la clause WITH contenant une instruction de modification de donn�es doit �tre\n"
+"la clause WITH contenant une instruction de modification de données doit être\n"
"au plus haut niveau"
#: parser/parse_cte.c:313
#, c-format
msgid "recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall"
msgstr ""
-"dans la requ�te r�cursive � %s �, la colonne %d a le type %s dans le terme non\n"
-"r�cursif mais le type global %s"
+"dans la requête récursive « %s », la colonne %d a le type %s dans le terme non\n"
+"récursif mais le type global %s"
#: parser/parse_cte.c:319
#, c-format
msgid "Cast the output of the non-recursive term to the correct type."
-msgstr "Convertit la sortie du terme non r�cursif dans le bon type."
+msgstr "Convertit la sortie du terme non récursif dans le bon type."
#: parser/parse_cte.c:324
#, c-format
msgid "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall"
-msgstr "requ�te r�cursive � %s � : la colonne %d a le collationnement � %s � dans un terme non r�cursifet un collationnement � %s � global"
+msgstr "requête récursive « %s » : la colonne %d a le collationnement « %s » dans un terme non récursifet un collationnement « %s » global"
#: parser/parse_cte.c:328
#, c-format
msgid "Use the COLLATE clause to set the collation of the non-recursive term."
-msgstr "Utilisez la clause COLLATE pour configurer le collationnement du terme non r�cursif."
+msgstr "Utilisez la clause COLLATE pour configurer le collationnement du terme non récursif."
#: parser/parse_cte.c:419
#, c-format
msgid "WITH query \"%s\" has %d columns available but %d columns specified"
-msgstr "la requ�te WITH � %s � a %d colonnes disponibles mais %d colonnes sp�cifi�es"
+msgstr "la requête WITH « %s » a %d colonnes disponibles mais %d colonnes spécifiées"
#: parser/parse_cte.c:599
#, c-format
msgid "mutual recursion between WITH items is not implemented"
-msgstr "la r�cursion mutuelle entre des �l�ments WITH n'est pas implant�e"
+msgstr "la récursion mutuelle entre des éléments WITH n'est pas implantée"
#: parser/parse_cte.c:651
#, c-format
msgid "recursive query \"%s\" must not contain data-modifying statements"
-msgstr "la requ�te r�cursive � %s � ne doit pas contenir des instructions de modification de donn�es"
+msgstr "la requête récursive « %s » ne doit pas contenir des instructions de modification de données"
#: parser/parse_cte.c:659
#, c-format
msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term"
msgstr ""
-"la requ�te r�cursive � %s � n'a pas la forme terme-non-r�cursive UNION [ALL]\n"
-"terme-r�cursive"
+"la requête récursive « %s » n'a pas la forme terme-non-récursive UNION [ALL]\n"
+"terme-récursive"
#: parser/parse_cte.c:703
#, c-format
msgid "ORDER BY in a recursive query is not implemented"
-msgstr "ORDER BY dans une requ�te r�cursive n'est pas implant�"
+msgstr "ORDER BY dans une requête récursive n'est pas implanté"
#: parser/parse_cte.c:709
#, c-format
msgid "OFFSET in a recursive query is not implemented"
-msgstr "OFFSET dans une requ�te r�cursive n'est pas impl�ment�"
+msgstr "OFFSET dans une requête récursive n'est pas implémenté"
#: parser/parse_cte.c:715
#, c-format
msgid "LIMIT in a recursive query is not implemented"
-msgstr "LIMIT dans une requ�te r�cursive n'est pas impl�ment�"
+msgstr "LIMIT dans une requête récursive n'est pas implémenté"
#: parser/parse_cte.c:721
#, c-format
msgid "FOR UPDATE/SHARE in a recursive query is not implemented"
-msgstr "FOR UPDATE/SHARE dans une requ�te r�cursive n'est pas impl�ment�"
+msgstr "FOR UPDATE/SHARE dans une requête récursive n'est pas implémenté"
#: parser/parse_cte.c:778
#, c-format
msgid "recursive reference to query \"%s\" must not appear more than once"
-msgstr "la r�f�rence r�cursive � la requ�te � %s � ne doit pas appara�tre plus d'une fois"
+msgstr "la référence récursive à la requête « %s » ne doit pas apparaître plus d'une fois"
-#: parser/parse_expr.c:387 parser/parse_relation.c:3083 parser/parse_relation.c:3103
+#: parser/parse_expr.c:390 parser/parse_relation.c:3176 parser/parse_relation.c:3196
#, c-format
msgid "column %s.%s does not exist"
msgstr "la colonne %s.%s n'existe pas"
-#: parser/parse_expr.c:399
+#: parser/parse_expr.c:402
#, c-format
msgid "column \"%s\" not found in data type %s"
-msgstr "colonne � %s � introuvable pour le type de donn�es %s"
+msgstr "colonne « %s » introuvable pour le type de données %s"
-#: parser/parse_expr.c:405
+#: parser/parse_expr.c:408
#, c-format
msgid "could not identify column \"%s\" in record data type"
-msgstr "n'a pas pu identifier la colonne � %s � dans le type de donn�es de l'enregistrement"
+msgstr "n'a pas pu identifier la colonne « %s » dans le type de données de l'enregistrement"
-#: parser/parse_expr.c:411
+#: parser/parse_expr.c:414
#, c-format
msgid "column notation .%s applied to type %s, which is not a composite type"
-msgstr "notation d'attribut .%s appliqu� au type %s, qui n'est pas un type compos�"
+msgstr "notation d'attribut .%s appliqué au type %s, qui n'est pas un type composé"
-#: parser/parse_expr.c:441 parser/parse_target.c:660
+#: parser/parse_expr.c:444 parser/parse_target.c:671
#, c-format
msgid "row expansion via \"*\" is not supported here"
-msgstr "l'expansion de ligne via � * � n'est pas support� ici"
+msgstr "l'expansion de ligne via « * » n'est pas supporté ici"
-#: parser/parse_expr.c:767 parser/parse_relation.c:667 parser/parse_relation.c:767 parser/parse_target.c:1109
+#: parser/parse_expr.c:770 parser/parse_relation.c:668 parser/parse_relation.c:768 parser/parse_target.c:1120
#, c-format
msgid "column reference \"%s\" is ambiguous"
-msgstr "la r�f�rence � la colonne � %s � est ambigu"
+msgstr "la référence à la colonne « %s » est ambigu"
-#: parser/parse_expr.c:823 parser/parse_param.c:110 parser/parse_param.c:142 parser/parse_param.c:199 parser/parse_param.c:298
+#: parser/parse_expr.c:826 parser/parse_param.c:110 parser/parse_param.c:142 parser/parse_param.c:199 parser/parse_param.c:298
#, c-format
msgid "there is no parameter $%d"
-msgstr "Il n'existe pas de param�tres $%d"
+msgstr "Il n'existe pas de paramètres $%d"
-#: parser/parse_expr.c:1042
+#: parser/parse_expr.c:1067
#, c-format
msgid "NULLIF requires = operator to yield boolean"
-msgstr "NULLIF requiert l'op�rateur = pour comparer des boole�ns"
+msgstr "NULLIF requiert l'opérateur = pour comparer des booleéns"
-#: parser/parse_expr.c:1705
+#: parser/parse_expr.c:1730
msgid "cannot use subquery in check constraint"
-msgstr "ne peut pas utiliser une sous-requ�te dans la contrainte de v�rification"
+msgstr "ne peut pas utiliser une sous-requête dans la contrainte de vérification"
-#: parser/parse_expr.c:1709
+#: parser/parse_expr.c:1734
msgid "cannot use subquery in DEFAULT expression"
-msgstr "ne peut pas utiliser de sous-requ�te dans une expression DEFAULT"
+msgstr "ne peut pas utiliser de sous-requête dans une expression DEFAULT"
-#: parser/parse_expr.c:1712
+#: parser/parse_expr.c:1737
msgid "cannot use subquery in index expression"
-msgstr "ne peut pas utiliser la sous-requ�te dans l'expression de l'index"
+msgstr "ne peut pas utiliser la sous-requête dans l'expression de l'index"
-#: parser/parse_expr.c:1715
+#: parser/parse_expr.c:1740
msgid "cannot use subquery in index predicate"
-msgstr "ne peut pas utiliser une sous-requ�te dans un pr�dicat d'index"
+msgstr "ne peut pas utiliser une sous-requête dans un prédicat d'index"
-#: parser/parse_expr.c:1718
+#: parser/parse_expr.c:1743
msgid "cannot use subquery in transform expression"
-msgstr "ne peut pas utiliser une sous-requ�te dans l'expression de transformation"
+msgstr "ne peut pas utiliser une sous-requête dans l'expression de transformation"
-#: parser/parse_expr.c:1721
+#: parser/parse_expr.c:1746
msgid "cannot use subquery in EXECUTE parameter"
-msgstr "ne peut pas utiliser les sous-requ�tes dans le param�tre EXECUTE"
+msgstr "ne peut pas utiliser les sous-requêtes dans le paramètre EXECUTE"
-#: parser/parse_expr.c:1724
+#: parser/parse_expr.c:1749
msgid "cannot use subquery in trigger WHEN condition"
-msgstr "ne peut pas utiliser une sous-requ�te dans la condition WHEN d'un trigger"
+msgstr "ne peut pas utiliser une sous-requête dans la condition WHEN d'un trigger"
-#: parser/parse_expr.c:1778
+#: parser/parse_expr.c:1803
#, c-format
msgid "subquery must return only one column"
-msgstr "la sous-requ�te doit renvoyer une seule colonne"
+msgstr "la sous-requête doit renvoyer une seule colonne"
-#: parser/parse_expr.c:1862
+#: parser/parse_expr.c:1887
#, c-format
msgid "subquery has too many columns"
-msgstr "la sous-requ�te a trop de colonnes"
+msgstr "la sous-requête a trop de colonnes"
-#: parser/parse_expr.c:1867
+#: parser/parse_expr.c:1892
#, c-format
msgid "subquery has too few columns"
-msgstr "la sous-requ�te n'a pas assez de colonnes"
+msgstr "la sous-requête n'a pas assez de colonnes"
-#: parser/parse_expr.c:1968
+#: parser/parse_expr.c:1993
#, c-format
msgid "cannot determine type of empty array"
-msgstr "ne peut pas d�terminer le type d'un tableau vide"
+msgstr "ne peut pas déterminer le type d'un tableau vide"
-#: parser/parse_expr.c:1969
+#: parser/parse_expr.c:1994
#, c-format
msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]."
-msgstr "Convertit explicitement vers le type d�sir�, par exemple ARRAY[]::integer[]."
+msgstr "Convertit explicitement vers le type désiré, par exemple ARRAY[]::integer[]."
-#: parser/parse_expr.c:1983
+#: parser/parse_expr.c:2008
#, c-format
msgid "could not find element type for data type %s"
-msgstr "n'a pas pu trouver le type d'�l�ment pour le type de donn�es %s"
+msgstr "n'a pas pu trouver le type d'élément pour le type de données %s"
-#: parser/parse_expr.c:2206
+#: parser/parse_expr.c:2231
#, c-format
msgid "unnamed XML attribute value must be a column reference"
-msgstr "la valeur d'un attribut XML sans nom doit �tre une r�f�rence de colonne"
+msgstr "la valeur d'un attribut XML sans nom doit être une référence de colonne"
-#: parser/parse_expr.c:2207
+#: parser/parse_expr.c:2232
#, c-format
msgid "unnamed XML element value must be a column reference"
-msgstr "la valeur d'un �l�ment XML sans nom doit �tre une r�f�rence de colonne"
+msgstr "la valeur d'un élément XML sans nom doit être une référence de colonne"
-#: parser/parse_expr.c:2222
+#: parser/parse_expr.c:2247
#, c-format
msgid "XML attribute name \"%s\" appears more than once"
-msgstr "le nom de l'attribut XML � %s � appara�t plus d'une fois"
+msgstr "le nom de l'attribut XML « %s » apparaît plus d'une fois"
-#: parser/parse_expr.c:2329
+#: parser/parse_expr.c:2354
#, c-format
msgid "cannot cast XMLSERIALIZE result to %s"
-msgstr "ne peut pas convertir le r�sultat XMLSERIALIZE en %s"
+msgstr "ne peut pas convertir le résultat XMLSERIALIZE en %s"
-#: parser/parse_expr.c:2625 parser/parse_expr.c:2821
+#: parser/parse_expr.c:2650 parser/parse_expr.c:2846
#, c-format
msgid "unequal number of entries in row expressions"
-msgstr "nombre diff�rent d'entr�es dans les expressions de ligne"
+msgstr "nombre différent d'entrées dans les expressions de ligne"
-#: parser/parse_expr.c:2635
+#: parser/parse_expr.c:2660
#, c-format
msgid "cannot compare rows of zero length"
-msgstr "n'a pas pu comparer des lignes de taille z�ro"
+msgstr "n'a pas pu comparer des lignes de taille zéro"
-#: parser/parse_expr.c:2660
+#: parser/parse_expr.c:2685
#, c-format
msgid "row comparison operator must yield type boolean, not type %s"
msgstr ""
-"l'op�rateur de comparaison de ligne doit renvoyer le type bool�en, et non le\n"
+"l'opérateur de comparaison de ligne doit renvoyer le type booléen, et non le\n"
"type %s"
-#: parser/parse_expr.c:2667
+#: parser/parse_expr.c:2692
#, c-format
msgid "row comparison operator must not return a set"
-msgstr "l'op�rateur de comparaison de ligne ne doit pas renvoyer un ensemble"
+msgstr "l'opérateur de comparaison de ligne ne doit pas renvoyer un ensemble"
-#: parser/parse_expr.c:2726 parser/parse_expr.c:2767
+#: parser/parse_expr.c:2751 parser/parse_expr.c:2792
#, c-format
msgid "could not determine interpretation of row comparison operator %s"
-msgstr "n'a pas pu d�terminer l'interpr�tation de l'op�rateur de comparaison de ligne %s"
+msgstr "n'a pas pu déterminer l'interprétation de l'opérateur de comparaison de ligne %s"
-#: parser/parse_expr.c:2728
+#: parser/parse_expr.c:2753
#, c-format
msgid "Row comparison operators must be associated with btree operator families."
msgstr ""
-"Les op�rateurs de comparaison de lignes doivent �tre associ�s � des familles\n"
-"d'op�rateurs btree."
+"Les opérateurs de comparaison de lignes doivent être associés à des familles\n"
+"d'opérateurs btree."
-#: parser/parse_expr.c:2769
+#: parser/parse_expr.c:2794
#, c-format
msgid "There are multiple equally-plausible candidates."
-msgstr "Il existe de nombreus candidats �galement plausibles."
+msgstr "Il existe de nombreus candidats également plausibles."
-#: parser/parse_expr.c:2861
+#: parser/parse_expr.c:2886
#, c-format
msgid "IS DISTINCT FROM requires = operator to yield boolean"
-msgstr "IS DISTINCT FROM requiert l'op�rateur = pour comparer des bool�ens"
+msgstr "IS DISTINCT FROM requiert l'opérateur = pour comparer des booléens"
-#: parser/parse_expr.c:3151 parser/parse_expr.c:3169
+#: parser/parse_expr.c:3199 parser/parse_expr.c:3217
#, c-format
msgid "operator precedence change: %s is now lower precedence than %s"
-msgstr ""
+msgstr "la précédence d'opérateur change : %s a maintenant une précédence inférieure à %s"
#: parser/parse_func.c:174
#, c-format
msgid "argument name \"%s\" used more than once"
-msgstr "nom � %s � de l'argument sp�cifi� plus d'une fois"
+msgstr "nom « %s » de l'argument spécifié plus d'une fois"
#: parser/parse_func.c:185
#, c-format
msgid "positional argument cannot follow named argument"
-msgstr "l'argument positionn� ne doit pas suivre l'argument nomm�"
+msgstr "l'argument positionné ne doit pas suivre l'argument nommé"
#: parser/parse_func.c:270
#, c-format
msgid "%s(*) specified, but %s is not an aggregate function"
-msgstr "%s(*) sp�cifi�, mais %s n'est pas une fonction d'agr�gat"
+msgstr "%s(*) spécifié, mais %s n'est pas une fonction d'agrégat"
#: parser/parse_func.c:277
#, c-format
msgid "DISTINCT specified, but %s is not an aggregate function"
-msgstr "DISTINCT sp�cifi� mais %s n'est pas une fonction d'agr�gat"
+msgstr "DISTINCT spécifié mais %s n'est pas une fonction d'agrégat"
#: parser/parse_func.c:283
#, c-format
msgid "WITHIN GROUP specified, but %s is not an aggregate function"
-msgstr "WITHIN GROUP sp�cifi�, mais %s n'est pas une fonction d'agr�gat"
+msgstr "WITHIN GROUP spécifié, mais %s n'est pas une fonction d'agrégat"
#: parser/parse_func.c:289
#, c-format
msgid "ORDER BY specified, but %s is not an aggregate function"
-msgstr "ORDER BY sp�cifi�, mais %s n'est pas une fonction d'agr�gat"
+msgstr "ORDER BY spécifié, mais %s n'est pas une fonction d'agrégat"
#: parser/parse_func.c:295
#, c-format
msgid "FILTER specified, but %s is not an aggregate function"
-msgstr "FILTER sp�cifi� mais %s n'est pas une fonction d'agr�gat"
+msgstr "FILTER spécifié mais %s n'est pas une fonction d'agrégat"
#: parser/parse_func.c:301
#, c-format
msgid "OVER specified, but %s is not a window function nor an aggregate function"
-msgstr "OVER sp�cifi�, mais %s n'est pas une fonction window ou une fonction d'agr�gat"
+msgstr "OVER spécifié, mais %s n'est pas une fonction window ou une fonction d'agrégat"
#: parser/parse_func.c:331
#, c-format
msgid "WITHIN GROUP is required for ordered-set aggregate %s"
-msgstr "WITHIN GROUP est requis pour l'agr�gat � ensemble ordonn� %s"
+msgstr "WITHIN GROUP est requis pour l'agrégat à ensemble ordonné %s"
#: parser/parse_func.c:337
#, c-format
msgid "OVER is not supported for ordered-set aggregate %s"
-msgstr "OVER n'est pas support� pour l'agr�gat %s � ensemble tri�"
+msgstr "OVER n'est pas supporté pour l'agrégat %s à ensemble trié"
#: parser/parse_func.c:368 parser/parse_func.c:397
#, c-format
msgid "There is an ordered-set aggregate %s, but it requires %d direct arguments, not %d."
-msgstr "Il existe un agr�gat par ensemble tri� nomm� %s, mais il requiert au moins %d arguments directs, pas %d."
+msgstr "Il existe un agrégat par ensemble trié nommé %s, mais il requiert au moins %d arguments directs, pas %d."
#: parser/parse_func.c:422
#, c-format
msgid "To use the hypothetical-set aggregate %s, the number of hypothetical direct arguments (here %d) must match the number of ordering columns (here %d)."
-msgstr "Pour utiliser l'agr�gat � ensemble hypoth�tique %s, le nombre d'arguments directs hypoth�tiques (ici %d) doit correspondre au nombre de colonnes de tri (ici %d)."
+msgstr "Pour utiliser l'agrégat à ensemble hypothétique %s, le nombre d'arguments directs hypothétiques (ici %d) doit correspondre au nombre de colonnes de tri (ici %d)."
#: parser/parse_func.c:436
#, c-format
msgid "There is an ordered-set aggregate %s, but it requires at least %d direct arguments."
-msgstr "Il existe un agr�gat par ensemble tri� nomm� %s, mais il requiert au moins %d arguments directs."
+msgstr "Il existe un agrégat par ensemble trié nommé %s, mais il requiert au moins %d arguments directs."
#: parser/parse_func.c:455
#, c-format
msgid "%s is not an ordered-set aggregate, so it cannot have WITHIN GROUP"
-msgstr "%s n'est pas un agr�gat par ensemble tri�, donc il ne peut pas avoir WITHIN GROUP"
+msgstr "%s n'est pas un agrégat par ensemble trié, donc il ne peut pas avoir WITHIN GROUP"
#: parser/parse_func.c:468
#, c-format
msgid "window function %s requires an OVER clause"
-msgstr "la fonction de fen�trage %s n�cessite une clause OVER"
+msgstr "la fonction de fenêtrage %s nécessite une clause OVER"
#: parser/parse_func.c:475
#, c-format
msgid "window function %s cannot have WITHIN GROUP"
-msgstr "la fonction de fen�trage %s ne peut avoir WITHIN GROUP"
+msgstr "la fonction de fenêtrage %s ne peut avoir WITHIN GROUP"
#: parser/parse_func.c:496
#, c-format
@@ -13707,71 +13722,71 @@ msgstr ""
#, c-format
msgid "No aggregate function matches the given name and argument types. Perhaps you misplaced ORDER BY; ORDER BY must appear after all regular arguments of the aggregate."
msgstr ""
-"Aucune fonction d'agr�gat ne correspond au nom donn� et aux types d'arguments.\n"
-"Peut-�tre avez-vous mal plac� la clause ORDER BY.\n"
-"Cette derni�re doit appara�tre apr�s tous les arguments standards de l'agr�gat."
+"Aucune fonction d'agrégat ne correspond au nom donné et aux types d'arguments.\n"
+"Peut-être avez-vous mal placé la clause ORDER BY.\n"
+"Cette dernière doit apparaître après tous les arguments standards de l'agrégat."
#: parser/parse_func.c:521
#, c-format
msgid "No function matches the given name and argument types. You might need to add explicit type casts."
msgstr ""
-"Aucune fonction ne correspond au nom donn� et aux types d'arguments.\n"
+"Aucune fonction ne correspond au nom donné et aux types d'arguments.\n"
"Vous devez ajouter des conversions explicites de type."
#: parser/parse_func.c:623
#, c-format
msgid "VARIADIC argument must be an array"
-msgstr "l'argument VARIADIC doit �tre un tableau"
+msgstr "l'argument VARIADIC doit être un tableau"
-#: parser/parse_func.c:669 parser/parse_func.c:733
+#: parser/parse_func.c:671 parser/parse_func.c:735
#, c-format
msgid "%s(*) must be used to call a parameterless aggregate function"
-msgstr "%s(*) doit �tre utilis� pour appeler une fonction d'agr�gat sans param�tre"
+msgstr "%s(*) doit être utilisé pour appeler une fonction d'agrégat sans paramètre"
-#: parser/parse_func.c:676
+#: parser/parse_func.c:678
#, c-format
msgid "aggregates cannot return sets"
-msgstr "les agr�gats ne peuvent pas renvoyer des ensembles"
+msgstr "les agrégats ne peuvent pas renvoyer des ensembles"
-#: parser/parse_func.c:691
+#: parser/parse_func.c:693
#, c-format
msgid "aggregates cannot use named arguments"
-msgstr "les agr�gats ne peuvent pas utiliser des aguments nomm�s"
+msgstr "les agrégats ne peuvent pas utiliser des aguments nommés"
-#: parser/parse_func.c:723
+#: parser/parse_func.c:725
#, c-format
msgid "DISTINCT is not implemented for window functions"
-msgstr "DISTINCT n'est pas impl�ment� pour des fonctions window"
+msgstr "DISTINCT n'est pas implémenté pour des fonctions window"
-#: parser/parse_func.c:743
+#: parser/parse_func.c:745
#, c-format
msgid "aggregate ORDER BY is not implemented for window functions"
-msgstr "l'agr�gat ORDER BY n'est pas impl�ment� pour des fonctions window"
+msgstr "l'agrégat ORDER BY n'est pas implémenté pour des fonctions window"
-#: parser/parse_func.c:752
+#: parser/parse_func.c:754
#, c-format
msgid "FILTER is not implemented for non-aggregate window functions"
-msgstr "FILTER n'est pas impl�ment� pour des fonctions de fen�trage non agr�gats"
+msgstr "FILTER n'est pas implémenté pour des fonctions de fenêtrage non agrégats"
-#: parser/parse_func.c:758
+#: parser/parse_func.c:760
#, c-format
msgid "window functions cannot return sets"
msgstr "les fonctions window ne peuvent pas renvoyer des ensembles"
-#: parser/parse_func.c:2008
+#: parser/parse_func.c:2010
#, c-format
msgid "aggregate %s(*) does not exist"
-msgstr "l'agr�gat %s(*) n'existe pas"
+msgstr "l'agrégat %s(*) n'existe pas"
-#: parser/parse_func.c:2013
+#: parser/parse_func.c:2015
#, c-format
msgid "aggregate %s does not exist"
-msgstr "l'agr�gat %s n'existe pas"
+msgstr "l'agrégat %s n'existe pas"
-#: parser/parse_func.c:2032
+#: parser/parse_func.c:2034
#, c-format
msgid "function %s is not an aggregate"
-msgstr "la fonction %s n'est pas un agr�gat"
+msgstr "la fonction %s n'est pas un agrégat"
#: parser/parse_node.c:84
#, c-format
@@ -13786,7 +13801,7 @@ msgstr "ne peut pas indicer le type %s car il ne s'agit pas d'un tableau"
#: parser/parse_node.c:356 parser/parse_node.c:393
#, c-format
msgid "array subscript must have type integer"
-msgstr "l'indice d'un tableau doit �tre de type entier"
+msgstr "l'indice d'un tableau doit être de type entier"
#: parser/parse_node.c:424
#, c-format
@@ -13796,512 +13811,512 @@ msgstr "l'affectation de tableaux requiert le type %s mais l'expression est de t
#: parser/parse_oper.c:125 parser/parse_oper.c:722 utils/adt/regproc.c:583 utils/adt/regproc.c:603 utils/adt/regproc.c:787
#, c-format
msgid "operator does not exist: %s"
-msgstr "l'op�rateur n'existe pas : %s"
+msgstr "l'opérateur n'existe pas : %s"
#: parser/parse_oper.c:222
#, c-format
msgid "Use an explicit ordering operator or modify the query."
-msgstr "Utilisez un op�rateur explicite de tri ou modifiez la requ�te."
+msgstr "Utilisez un opérateur explicite de tri ou modifiez la requête."
-#: parser/parse_oper.c:226 utils/adt/array_userfuncs.c:782 utils/adt/array_userfuncs.c:920 utils/adt/arrayfuncs.c:3639 utils/adt/arrayfuncs.c:4077 utils/adt/arrayfuncs.c:6055 utils/adt/rowtypes.c:1167
+#: parser/parse_oper.c:226 utils/adt/array_userfuncs.c:794 utils/adt/array_userfuncs.c:933 utils/adt/arrayfuncs.c:3639 utils/adt/arrayfuncs.c:4077 utils/adt/arrayfuncs.c:6039 utils/adt/rowtypes.c:1167
#, c-format
msgid "could not identify an equality operator for type %s"
-msgstr "n'a pas pu identifier un op�rateur d'�galit� pour le type %s"
+msgstr "n'a pas pu identifier un opérateur d'égalité pour le type %s"
#: parser/parse_oper.c:478
#, c-format
msgid "operator requires run-time type coercion: %s"
-msgstr "l'op�rateur requiert la coercion du type � l'ex�cution : %s"
+msgstr "l'opérateur requiert la coercion du type à l'exécution : %s"
#: parser/parse_oper.c:714
#, c-format
msgid "operator is not unique: %s"
-msgstr "l'op�rateur n'est pas unique : %s"
+msgstr "l'opérateur n'est pas unique : %s"
#: parser/parse_oper.c:716
#, c-format
msgid "Could not choose a best candidate operator. You might need to add explicit type casts."
msgstr ""
-"N'a pas pu choisir un meilleur candidat pour l'op�rateur. Vous devez ajouter une\n"
+"N'a pas pu choisir un meilleur candidat pour l'opérateur. Vous devez ajouter une\n"
"conversion explicite de type."
#: parser/parse_oper.c:724
#, c-format
msgid "No operator matches the given name and argument type(s). You might need to add explicit type casts."
msgstr ""
-"Aucun op�rateur ne correspond au nom donn� et aux types d'arguments.\n"
+"Aucun opérateur ne correspond au nom donné et aux types d'arguments.\n"
"Vous devez ajouter des conversions explicites de type."
#: parser/parse_oper.c:783 parser/parse_oper.c:897
#, c-format
msgid "operator is only a shell: %s"
-msgstr "l'op�rateur est seulement un shell : %s"
+msgstr "l'opérateur est seulement un shell : %s"
#: parser/parse_oper.c:885
#, c-format
msgid "op ANY/ALL (array) requires array on right side"
-msgstr "op ANY/ALL (tableau) requiert un tableau sur le c�t� droit"
+msgstr "op ANY/ALL (tableau) requiert un tableau sur le côté droit"
#: parser/parse_oper.c:927
#, c-format
msgid "op ANY/ALL (array) requires operator to yield boolean"
-msgstr "op ANY/ALL (tableau) requiert un op�rateur pour comparer des bool�ens"
+msgstr "op ANY/ALL (tableau) requiert un opérateur pour comparer des booléens"
#: parser/parse_oper.c:932
#, c-format
msgid "op ANY/ALL (array) requires operator not to return a set"
-msgstr "op ANY/ALL (tableau) requiert que l'op�rateur ne renvoie pas un ensemble"
+msgstr "op ANY/ALL (tableau) requiert que l'opérateur ne renvoie pas un ensemble"
#: parser/parse_param.c:216
#, c-format
msgid "inconsistent types deduced for parameter $%d"
-msgstr "types incoh�rents d�duit pour le param�tre $%d"
+msgstr "types incohérents déduit pour le paramètre $%d"
-#: parser/parse_relation.c:174
+#: parser/parse_relation.c:175
#, c-format
msgid "table reference \"%s\" is ambiguous"
-msgstr "la r�f�rence � la table � %s � est ambigu"
+msgstr "la référence à la table « %s » est ambigu"
-#: parser/parse_relation.c:218
+#: parser/parse_relation.c:219
#, c-format
msgid "table reference %u is ambiguous"
-msgstr "la r�f�rence � la table %u est ambigu"
+msgstr "la référence à la table %u est ambigu"
-#: parser/parse_relation.c:397
+#: parser/parse_relation.c:398
#, c-format
msgid "table name \"%s\" specified more than once"
-msgstr "le nom de la table � %s � est sp�cifi� plus d'une fois"
+msgstr "le nom de la table « %s » est spécifié plus d'une fois"
-#: parser/parse_relation.c:424 parser/parse_relation.c:3023
+#: parser/parse_relation.c:425 parser/parse_relation.c:3116
#, c-format
msgid "invalid reference to FROM-clause entry for table \"%s\""
-msgstr "r�f�rence invalide d'une entr�e de la clause FROM pour la table � %s �"
+msgstr "référence invalide d'une entrée de la clause FROM pour la table « %s »"
-#: parser/parse_relation.c:427 parser/parse_relation.c:3028
+#: parser/parse_relation.c:428 parser/parse_relation.c:3121
#, c-format
msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query."
msgstr ""
-"Il existe une entr�e pour la table � %s � mais elle ne peut pas �tre\n"
-"r�f�renc�e de cette partie de la requ�te."
+"Il existe une entrée pour la table « %s » mais elle ne peut pas être\n"
+"référencée de cette partie de la requête."
-#: parser/parse_relation.c:429
+#: parser/parse_relation.c:430
#, c-format
msgid "The combining JOIN type must be INNER or LEFT for a LATERAL reference."
-msgstr "Le type JOIN combin� doit �tre INNER ou LEFT pour une r�f�rence LATERAL."
+msgstr "Le type JOIN combiné doit être INNER ou LEFT pour une référence LATERAL."
-#: parser/parse_relation.c:705
+#: parser/parse_relation.c:706
#, c-format
msgid "system column \"%s\" reference in check constraint is invalid"
-msgstr "la r�f�rence de la colonne syst�me � %s � dans la contrainte CHECK est invalide"
+msgstr "la référence de la colonne système « %s » dans la contrainte CHECK est invalide"
-#: parser/parse_relation.c:1065 parser/parse_relation.c:1345 parser/parse_relation.c:1847
+#: parser/parse_relation.c:1066 parser/parse_relation.c:1346 parser/parse_relation.c:1848
#, c-format
msgid "table \"%s\" has %d columns available but %d columns specified"
-msgstr "la table � %s � a %d colonnes disponibles mais %d colonnes sp�cifi�es"
+msgstr "la table « %s » a %d colonnes disponibles mais %d colonnes spécifiées"
-#: parser/parse_relation.c:1152
+#: parser/parse_relation.c:1153
#, c-format
msgid "There is a WITH item named \"%s\", but it cannot be referenced from this part of the query."
msgstr ""
-"Il existe un �l�ment WITH nomm� � %s � mais il ne peut pas �tre\n"
-"r�f�renc�e de cette partie de la requ�te."
+"Il existe un élément WITH nommé « %s » mais il ne peut pas être\n"
+"référencée de cette partie de la requête."
-#: parser/parse_relation.c:1154
+#: parser/parse_relation.c:1155
#, c-format
msgid "Use WITH RECURSIVE, or re-order the WITH items to remove forward references."
msgstr ""
-"Utilisez WITH RECURSIVE ou r�-ordonnez les �l�ments WITH pour supprimer\n"
-"les r�f�rences en avant."
+"Utilisez WITH RECURSIVE ou ré-ordonnez les éléments WITH pour supprimer\n"
+"les références en avant."
-#: parser/parse_relation.c:1465
+#: parser/parse_relation.c:1466
#, c-format
msgid "a column definition list is only allowed for functions returning \"record\""
msgstr ""
-"une liste de d�finition de colonnes est uniquement autoris�e pour les fonctions\n"
-"renvoyant un � record �"
+"une liste de définition de colonnes est uniquement autorisée pour les fonctions\n"
+"renvoyant un « record »"
-#: parser/parse_relation.c:1474
+#: parser/parse_relation.c:1475
#, c-format
msgid "a column definition list is required for functions returning \"record\""
msgstr ""
-"une liste de d�finition de colonnes est requise pour les fonctions renvoyant\n"
-"un � record �"
+"une liste de définition de colonnes est requise pour les fonctions renvoyant\n"
+"un « record »"
-#: parser/parse_relation.c:1553
+#: parser/parse_relation.c:1554
#, c-format
msgid "function \"%s\" in FROM has unsupported return type %s"
-msgstr "la fonction � %s � dans la clause FROM a un type de retour %s non support�"
+msgstr "la fonction « %s » dans la clause FROM a un type de retour %s non supporté"
-#: parser/parse_relation.c:1675
+#: parser/parse_relation.c:1676
#, c-format
msgid "VALUES lists \"%s\" have %d columns available but %d columns specified"
msgstr ""
-"les listes � %s � de VALUES ont %d colonnes disponibles mais %d colonnes\n"
-"sp�cifi�es"
+"les listes « %s » de VALUES ont %d colonnes disponibles mais %d colonnes\n"
+"spécifiées"
-#: parser/parse_relation.c:1730
+#: parser/parse_relation.c:1731
#, c-format
msgid "joins can have at most %d columns"
msgstr "les jointures peuvent avoir au plus %d colonnes"
-#: parser/parse_relation.c:1820
+#: parser/parse_relation.c:1821
#, c-format
msgid "WITH query \"%s\" does not have a RETURNING clause"
-msgstr "La requ�te WITH � %s � n'a pas de clause RETURNING"
+msgstr "La requête WITH « %s » n'a pas de clause RETURNING"
-#: parser/parse_relation.c:2652 parser/parse_relation.c:2807
+#: parser/parse_relation.c:2738 parser/parse_relation.c:2900
#, c-format
msgid "column %d of relation \"%s\" does not exist"
-msgstr "la colonne %d de la relation � %s � n'existe pas"
+msgstr "la colonne %d de la relation « %s » n'existe pas"
-#: parser/parse_relation.c:3026
+#: parser/parse_relation.c:3119
#, c-format
msgid "Perhaps you meant to reference the table alias \"%s\"."
-msgstr "Peut-�tre que vous souhaitiez r�f�rencer l'alias de la table � %s �."
+msgstr "Peut-être que vous souhaitiez référencer l'alias de la table « %s »."
-#: parser/parse_relation.c:3034
+#: parser/parse_relation.c:3127
#, c-format
msgid "missing FROM-clause entry for table \"%s\""
-msgstr "entr�e manquante de la clause FROM pour la table � %s �"
+msgstr "entrée manquante de la clause FROM pour la table « %s »"
-#: parser/parse_relation.c:3086
+#: parser/parse_relation.c:3179
#, c-format
msgid "Perhaps you meant to reference the column \"%s.%s\"."
-msgstr "Peut-�tre que vous souhaitiez r�f�rencer la colonne � %s.%s �."
+msgstr "Peut-être que vous souhaitiez référencer la colonne « %s.%s »."
-#: parser/parse_relation.c:3088
+#: parser/parse_relation.c:3181
#, c-format
msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query."
-msgstr "Il existe une colonne nomm�e � %s � pour la table � %s � mais elle ne peut pas �tre r�f�renc�e dans cette partie de la requ�te."
+msgstr "Il existe une colonne nommée « %s » pour la table « %s » mais elle ne peut pas être référencée dans cette partie de la requête."
-#: parser/parse_relation.c:3105
+#: parser/parse_relation.c:3198
#, c-format
msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"."
-msgstr "Peut-�tre que vous souhaitiez r�f�rencer la colonne � %s.%s � ou la colonne � %s.%s �."
+msgstr "Peut-être que vous souhaitiez référencer la colonne « %s.%s » ou la colonne « %s.%s »."
-#: parser/parse_target.c:421 parser/parse_target.c:713
+#: parser/parse_target.c:432 parser/parse_target.c:724
#, c-format
msgid "cannot assign to system column \"%s\""
-msgstr "ne peut pas affecter � une colonne syst�me � %s �"
+msgstr "ne peut pas affecter à une colonne système « %s »"
-#: parser/parse_target.c:449
+#: parser/parse_target.c:460
#, c-format
msgid "cannot set an array element to DEFAULT"
-msgstr "ne peut pas initialiser un �l�ment d'un tableau avec DEFAULT"
+msgstr "ne peut pas initialiser un élément d'un tableau avec DEFAULT"
-#: parser/parse_target.c:454
+#: parser/parse_target.c:465
#, c-format
msgid "cannot set a subfield to DEFAULT"
msgstr "ne peut pas initialiser un sous-champ avec DEFAULT"
-#: parser/parse_target.c:523
+#: parser/parse_target.c:534
#, c-format
msgid "column \"%s\" is of type %s but expression is of type %s"
-msgstr "la colonne � %s � est de type %s mais l'expression est de type %s"
+msgstr "la colonne « %s » est de type %s mais l'expression est de type %s"
-#: parser/parse_target.c:697
+#: parser/parse_target.c:708
#, c-format
msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type"
msgstr ""
-"ne peut pas l'affecter au champ � %s � de la colonne � %s � parce que son\n"
-"type %s n'est pas un type compos�"
+"ne peut pas l'affecter au champ « %s » de la colonne « %s » parce que son\n"
+"type %s n'est pas un type composé"
-#: parser/parse_target.c:706
+#: parser/parse_target.c:717
#, c-format
msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s"
msgstr ""
-"ne peut pas l'affecter au champ � %s � de la colonne � %s � parce qu'il n'existe\n"
-"pas une telle colonne dans le type de donn�es %s"
+"ne peut pas l'affecter au champ « %s » de la colonne « %s » parce qu'il n'existe\n"
+"pas une telle colonne dans le type de données %s"
-#: parser/parse_target.c:773
+#: parser/parse_target.c:784
#, c-format
msgid "array assignment to \"%s\" requires type %s but expression is of type %s"
msgstr ""
-"l'affectation d'un tableau avec � %s � requiert le type %s mais l'expression est\n"
+"l'affectation d'un tableau avec « %s » requiert le type %s mais l'expression est\n"
"de type %s"
-#: parser/parse_target.c:783
+#: parser/parse_target.c:794
#, c-format
msgid "subfield \"%s\" is of type %s but expression is of type %s"
-msgstr "le sous-champ � %s � est de type %s mais l'expression est de type %s"
+msgstr "le sous-champ « %s » est de type %s mais l'expression est de type %s"
-#: parser/parse_target.c:1199
+#: parser/parse_target.c:1210
#, c-format
msgid "SELECT * with no tables specified is not valid"
-msgstr "Un SELECT * sans table sp�cifi�e n'est pas valide"
+msgstr "Un SELECT * sans table spécifiée n'est pas valide"
#: parser/parse_type.c:83
#, c-format
msgid "improper %%TYPE reference (too few dotted names): %s"
-msgstr "r�f�rence %%TYPE invalide (trop peu de points entre les noms) : %s"
+msgstr "référence %%TYPE invalide (trop peu de points entre les noms) : %s"
#: parser/parse_type.c:105
#, c-format
msgid "improper %%TYPE reference (too many dotted names): %s"
-msgstr "r�f�rence %%TYPE invalide (trop de points entre les noms) : %s"
+msgstr "référence %%TYPE invalide (trop de points entre les noms) : %s"
#: parser/parse_type.c:140
#, c-format
msgid "type reference %s converted to %s"
-msgstr "r�f�rence de type %s convertie en %s"
+msgstr "référence de type %s convertie en %s"
#: parser/parse_type.c:261 parser/parse_type.c:805 utils/cache/typcache.c:239
#, c-format
msgid "type \"%s\" is only a shell"
-msgstr "le type � %s � est seulement un shell"
+msgstr "le type « %s » est seulement un shell"
#: parser/parse_type.c:346
#, c-format
msgid "type modifier is not allowed for type \"%s\""
-msgstr "le modificateur de type n'est pas autoris� pour le type � %s �"
+msgstr "le modificateur de type n'est pas autorisé pour le type « %s »"
#: parser/parse_type.c:388
#, c-format
msgid "type modifiers must be simple constants or identifiers"
-msgstr "les modificateurs de type doivent �tre des constantes ou des identifiants"
+msgstr "les modificateurs de type doivent être des constantes ou des identifiants"
#: parser/parse_type.c:671 parser/parse_type.c:770
#, c-format
msgid "invalid type name \"%s\""
-msgstr "nom de type � %s � invalide"
+msgstr "nom de type « %s » invalide"
-#: parser/parse_utilcmd.c:399
+#: parser/parse_utilcmd.c:384
#, c-format
msgid "array of serial is not implemented"
-msgstr "le tableau de type serial n'est pas implant�"
+msgstr "le tableau de type serial n'est pas implanté"
-#: parser/parse_utilcmd.c:447
+#: parser/parse_utilcmd.c:432
#, c-format
msgid "%s will create implicit sequence \"%s\" for serial column \"%s.%s\""
-msgstr "%s cr�era des s�quences implicites � %s � pour la colonne serial � %s.%s �"
+msgstr "%s créera des séquences implicites « %s » pour la colonne serial « %s.%s »"
-#: parser/parse_utilcmd.c:541 parser/parse_utilcmd.c:553
+#: parser/parse_utilcmd.c:526 parser/parse_utilcmd.c:538
#, c-format
msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\""
-msgstr "d�clarations NULL/NOT NULL en conflit pour la colonne � %s � de la table � %s �"
+msgstr "déclarations NULL/NOT NULL en conflit pour la colonne « %s » de la table « %s »"
-#: parser/parse_utilcmd.c:565
+#: parser/parse_utilcmd.c:550
#, c-format
msgid "multiple default values specified for column \"%s\" of table \"%s\""
msgstr ""
-"plusieurs valeurs par d�faut sont sp�cifi�es pour la colonne � %s � de la table\n"
-"� %s �"
+"plusieurs valeurs par défaut sont spécifiées pour la colonne « %s » de la table\n"
+"« %s »"
-#: parser/parse_utilcmd.c:582 parser/parse_utilcmd.c:673
+#: parser/parse_utilcmd.c:567 parser/parse_utilcmd.c:658
#, c-format
msgid "primary key constraints are not supported on foreign tables"
-msgstr "les cl�s primaires ne sont pas support�es par les tables distantes"
+msgstr "les clés primaires ne sont pas supportées par les tables distantes"
-#: parser/parse_utilcmd.c:591 parser/parse_utilcmd.c:683
+#: parser/parse_utilcmd.c:576 parser/parse_utilcmd.c:668
#, c-format
msgid "unique constraints are not supported on foreign tables"
-msgstr "les contraintes uniques ne sont pas support�es par les tables distantes"
+msgstr "les contraintes uniques ne sont pas supportées par les tables distantes"
-#: parser/parse_utilcmd.c:608 parser/parse_utilcmd.c:707
+#: parser/parse_utilcmd.c:593 parser/parse_utilcmd.c:692
#, c-format
msgid "foreign key constraints are not supported on foreign tables"
-msgstr "les cl�s �trang�res ne sont pas support�es par les tables distantes"
+msgstr "les clés étrangères ne sont pas supportées par les tables distantes"
-#: parser/parse_utilcmd.c:693
+#: parser/parse_utilcmd.c:678
#, c-format
msgid "exclusion constraints are not supported on foreign tables"
-msgstr "les contraintes d'exclusion ne sont pas support�es par les tables distantes"
+msgstr "les contraintes d'exclusion ne sont pas supportées par les tables distantes"
-#: parser/parse_utilcmd.c:757
+#: parser/parse_utilcmd.c:742
#, c-format
msgid "LIKE is not supported for creating foreign tables"
-msgstr "LIKE n'est pas support� pour la cr�ation de tables distantes"
+msgstr "LIKE n'est pas supporté pour la création de tables distantes"
-#: parser/parse_utilcmd.c:1288 parser/parse_utilcmd.c:1364
+#: parser/parse_utilcmd.c:1275 parser/parse_utilcmd.c:1351
#, c-format
msgid "Index \"%s\" contains a whole-row table reference."
-msgstr "l'index � %s � contient une r�f�rence de table de ligne compl�te"
+msgstr "l'index « %s » contient une référence de table de ligne complète"
-#: parser/parse_utilcmd.c:1634
+#: parser/parse_utilcmd.c:1621
#, c-format
msgid "cannot use an existing index in CREATE TABLE"
msgstr "ne peut pas utiliser un index existant dans CREATE TABLE"
-#: parser/parse_utilcmd.c:1654
+#: parser/parse_utilcmd.c:1641
#, c-format
msgid "index \"%s\" is already associated with a constraint"
-msgstr "l'index � %s � est d�j� associ� � une contrainte"
+msgstr "l'index « %s » est déjà associé à une contrainte"
-#: parser/parse_utilcmd.c:1662
+#: parser/parse_utilcmd.c:1649
#, c-format
msgid "index \"%s\" does not belong to table \"%s\""
-msgstr "l'index � %s � n'appartient pas � la table � %s �"
+msgstr "l'index « %s » n'appartient pas à la table « %s »"
-#: parser/parse_utilcmd.c:1669
+#: parser/parse_utilcmd.c:1656
#, c-format
msgid "index \"%s\" is not valid"
-msgstr "l'index � %s � n'est pas valide"
+msgstr "l'index « %s » n'est pas valide"
-#: parser/parse_utilcmd.c:1675
+#: parser/parse_utilcmd.c:1662
#, c-format
msgid "\"%s\" is not a unique index"
-msgstr "� %s � n'est pas un index unique"
+msgstr "« %s » n'est pas un index unique"
-#: parser/parse_utilcmd.c:1676 parser/parse_utilcmd.c:1683 parser/parse_utilcmd.c:1690 parser/parse_utilcmd.c:1760
+#: parser/parse_utilcmd.c:1663 parser/parse_utilcmd.c:1670 parser/parse_utilcmd.c:1677 parser/parse_utilcmd.c:1747
#, c-format
msgid "Cannot create a primary key or unique constraint using such an index."
-msgstr "Ne peut pas cr�er une cl� primaire ou une contrainte unique avec cet index."
+msgstr "Ne peut pas créer une clé primaire ou une contrainte unique avec cet index."
-#: parser/parse_utilcmd.c:1682
+#: parser/parse_utilcmd.c:1669
#, c-format
msgid "index \"%s\" contains expressions"
-msgstr "l'index � %s � contient des expressions"
+msgstr "l'index « %s » contient des expressions"
-#: parser/parse_utilcmd.c:1689
+#: parser/parse_utilcmd.c:1676
#, c-format
msgid "\"%s\" is a partial index"
-msgstr "� %s � est un index partiel"
+msgstr "« %s » est un index partiel"
-#: parser/parse_utilcmd.c:1701
+#: parser/parse_utilcmd.c:1688
#, c-format
msgid "\"%s\" is a deferrable index"
-msgstr "� %s � est un index d�ferrable"
+msgstr "« %s » est un index déferrable"
-#: parser/parse_utilcmd.c:1702
+#: parser/parse_utilcmd.c:1689
#, c-format
msgid "Cannot create a non-deferrable constraint using a deferrable index."
-msgstr "Ne peut pas cr�er une contrainte non-d�ferrable utilisant un index d�ferrable."
+msgstr "Ne peut pas créer une contrainte non-déferrable utilisant un index déferrable."
-#: parser/parse_utilcmd.c:1759
+#: parser/parse_utilcmd.c:1746
#, c-format
msgid "index \"%s\" does not have default sorting behavior"
-msgstr "l'index � %s � n'a pas de comportement de tri par d�faut"
+msgstr "l'index « %s » n'a pas de comportement de tri par défaut"
-#: parser/parse_utilcmd.c:1906
+#: parser/parse_utilcmd.c:1893
#, c-format
msgid "column \"%s\" appears twice in primary key constraint"
-msgstr "la colonne � %s � appara�t deux fois dans la contrainte de la cl� primaire"
+msgstr "la colonne « %s » apparaît deux fois dans la contrainte de la clé primaire"
-#: parser/parse_utilcmd.c:1912
+#: parser/parse_utilcmd.c:1899
#, c-format
msgid "column \"%s\" appears twice in unique constraint"
-msgstr "la colonne � %s � appara�t deux fois sur une contrainte unique"
+msgstr "la colonne « %s » apparaît deux fois sur une contrainte unique"
-#: parser/parse_utilcmd.c:2116
+#: parser/parse_utilcmd.c:2103
#, c-format
msgid "index expression cannot return a set"
msgstr "l'expression de l'index ne peut pas renvoyer un ensemble"
-#: parser/parse_utilcmd.c:2127
+#: parser/parse_utilcmd.c:2114
#, c-format
msgid "index expressions and predicates can refer only to the table being indexed"
-msgstr "les expressions et pr�dicats d'index peuvent seulement faire r�f�rence � la table en cours d'indexage"
+msgstr "les expressions et prédicats d'index peuvent seulement faire référence à la table en cours d'indexage"
-#: parser/parse_utilcmd.c:2173
+#: parser/parse_utilcmd.c:2160
#, c-format
msgid "rules on materialized views are not supported"
-msgstr "les r�gles ne sont pas support�s sur les vues mat�rialis�es"
+msgstr "les règles ne sont pas supportés sur les vues matérialisées"
-#: parser/parse_utilcmd.c:2234
+#: parser/parse_utilcmd.c:2221
#, c-format
msgid "rule WHERE condition cannot contain references to other relations"
msgstr ""
-"la condition WHERE d'une r�gle ne devrait pas contenir de r�f�rences � d'autres\n"
+"la condition WHERE d'une règle ne devrait pas contenir de références à d'autres\n"
"relations"
-#: parser/parse_utilcmd.c:2306
+#: parser/parse_utilcmd.c:2293
#, c-format
msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions"
msgstr ""
-"les r�gles avec des conditions WHERE ne peuvent contenir que des actions\n"
+"les règles avec des conditions WHERE ne peuvent contenir que des actions\n"
"SELECT, INSERT, UPDATE ou DELETE "
-#: parser/parse_utilcmd.c:2324 parser/parse_utilcmd.c:2423 rewrite/rewriteHandler.c:485 rewrite/rewriteManip.c:1015
+#: parser/parse_utilcmd.c:2311 parser/parse_utilcmd.c:2410 rewrite/rewriteHandler.c:485 rewrite/rewriteManip.c:1015
#, c-format
msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented"
msgstr ""
"les instructions conditionnelles UNION/INTERSECT/EXCEPT ne sont pas\n"
-"impl�ment�es"
+"implémentées"
-#: parser/parse_utilcmd.c:2342
+#: parser/parse_utilcmd.c:2329
#, c-format
msgid "ON SELECT rule cannot use OLD"
-msgstr "la r�gle ON SELECT ne peut pas utiliser OLD"
+msgstr "la règle ON SELECT ne peut pas utiliser OLD"
-#: parser/parse_utilcmd.c:2346
+#: parser/parse_utilcmd.c:2333
#, c-format
msgid "ON SELECT rule cannot use NEW"
-msgstr "la r�gle ON SELECT ne peut pas utiliser NEW"
+msgstr "la règle ON SELECT ne peut pas utiliser NEW"
-#: parser/parse_utilcmd.c:2355
+#: parser/parse_utilcmd.c:2342
#, c-format
msgid "ON INSERT rule cannot use OLD"
-msgstr "la r�gle ON INSERT ne peut pas utiliser OLD"
+msgstr "la règle ON INSERT ne peut pas utiliser OLD"
-#: parser/parse_utilcmd.c:2361
+#: parser/parse_utilcmd.c:2348
#, c-format
msgid "ON DELETE rule cannot use NEW"
-msgstr "la r�gle ON INSERT ne peut pas utiliser NEW"
+msgstr "la règle ON INSERT ne peut pas utiliser NEW"
-#: parser/parse_utilcmd.c:2389
+#: parser/parse_utilcmd.c:2376
#, c-format
msgid "cannot refer to OLD within WITH query"
-msgstr "ne peut r�f�rencer OLD dans une requ�te WITH"
+msgstr "ne peut référencer OLD dans une requête WITH"
-#: parser/parse_utilcmd.c:2396
+#: parser/parse_utilcmd.c:2383
#, c-format
msgid "cannot refer to NEW within WITH query"
-msgstr "ne peut r�f�rencer NEW dans une requ�te WITH"
+msgstr "ne peut référencer NEW dans une requête WITH"
-#: parser/parse_utilcmd.c:2599
+#: parser/parse_utilcmd.c:2586
#, c-format
msgid "transform expression must not return a set"
msgstr "l'expression de transformation ne doit pas renvoyer un ensemble"
-#: parser/parse_utilcmd.c:2713
+#: parser/parse_utilcmd.c:2700
#, c-format
msgid "misplaced DEFERRABLE clause"
-msgstr "clause DEFERRABLE mal plac�e"
+msgstr "clause DEFERRABLE mal placée"
-#: parser/parse_utilcmd.c:2718 parser/parse_utilcmd.c:2733
+#: parser/parse_utilcmd.c:2705 parser/parse_utilcmd.c:2720
#, c-format
msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"
-msgstr "clauses DEFERRABLE/NOT DEFERRABLE multiples non autoris�es"
+msgstr "clauses DEFERRABLE/NOT DEFERRABLE multiples non autorisées"
-#: parser/parse_utilcmd.c:2728
+#: parser/parse_utilcmd.c:2715
#, c-format
msgid "misplaced NOT DEFERRABLE clause"
-msgstr "clause NOT DEFERRABLE mal plac�e"
+msgstr "clause NOT DEFERRABLE mal placée"
-#: parser/parse_utilcmd.c:2749
+#: parser/parse_utilcmd.c:2736
#, c-format
msgid "misplaced INITIALLY DEFERRED clause"
-msgstr "clause INITIALLY DEFERRED mal plac�e"
+msgstr "clause INITIALLY DEFERRED mal placée"
-#: parser/parse_utilcmd.c:2754 parser/parse_utilcmd.c:2780
+#: parser/parse_utilcmd.c:2741 parser/parse_utilcmd.c:2767
#, c-format
msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"
-msgstr "clauses INITIALLY IMMEDIATE/DEFERRED multiples non autoris�es"
+msgstr "clauses INITIALLY IMMEDIATE/DEFERRED multiples non autorisées"
-#: parser/parse_utilcmd.c:2775
+#: parser/parse_utilcmd.c:2762
#, c-format
msgid "misplaced INITIALLY IMMEDIATE clause"
-msgstr "clause INITIALLY IMMEDIATE mal plac�e"
+msgstr "clause INITIALLY IMMEDIATE mal placée"
-#: parser/parse_utilcmd.c:2966
+#: parser/parse_utilcmd.c:2953
#, c-format
msgid "CREATE specifies a schema (%s) different from the one being created (%s)"
-msgstr "CREATE sp�cifie un sch�ma (%s) diff�rent de celui tout juste cr�� (%s)"
+msgstr "CREATE spécifie un schéma (%s) différent de celui tout juste créé (%s)"
#: parser/scansup.c:204
#, c-format
msgid "identifier \"%s\" will be truncated to \"%s\""
-msgstr "l'identifiant � %s � sera tronqu� en � %s �"
+msgstr "l'identifiant « %s » sera tronqué en « %s »"
#: port/pg_sema.c:113 port/sysv_sema.c:113
#, c-format
msgid "could not create semaphores: %m"
-msgstr "n'a pas pu cr�er des s�maphores : %m"
+msgstr "n'a pas pu créer des sémaphores : %m"
#: port/pg_sema.c:114 port/sysv_sema.c:114
#, c-format
msgid "Failed system call was semget(%lu, %d, 0%o)."
-msgstr "L'appel syst�me qui a �chou� �tait semget(%lu, %d, 0%o)."
+msgstr "L'appel système qui a échoué était semget(%lu, %d, 0%o)."
#: port/pg_sema.c:118 port/sysv_sema.c:118
#, c-format
@@ -14310,336 +14325,331 @@ msgid ""
"The PostgreSQL documentation contains more information about configuring your system for PostgreSQL."
msgstr ""
"Cette erreur ne signifie *pas* que vous manquez d'espace disque. Il arrive\n"
-"que soit la limite syst�me du nombre maximum d'ensembles de s�maphores\n"
-"(SEMMNI) ou le nombre maximum de s�maphores pour le syst�me (SEMMNS) soit\n"
-"d�pass�e. Vous avez besoin d'augmenter le param�tre noyau respectif.\n"
-"Autrement, r�duisez la consommation de s�maphores par PostgreSQL en r�duisant\n"
-"son param�tre max_connections.\n"
+"que soit la limite système du nombre maximum d'ensembles de sémaphores\n"
+"(SEMMNI) ou le nombre maximum de sémaphores pour le système (SEMMNS) soit\n"
+"dépassée. Vous avez besoin d'augmenter le paramètre noyau respectif.\n"
+"Autrement, réduisez la consommation de sémaphores par PostgreSQL en réduisant\n"
+"son paramètre max_connections.\n"
"La documentation de PostgreSQL contient plus d'informations sur la\n"
-"configuration de votre syst�me avec PostgreSQL."
+"configuration de votre système avec PostgreSQL."
#: port/pg_sema.c:148 port/sysv_sema.c:148
#, c-format
msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details."
msgstr ""
"Vous pouvez avoir besoin d'augmenter la valeur SEMVMX par noyau pour valoir\n"
-"au moins de %d. Regardez dans la documentation de PostgreSQL pour les d�tails."
+"au moins de %d. Regardez dans la documentation de PostgreSQL pour les détails."
-#: port/pg_shmem.c:141 port/sysv_shmem.c:141
+#: port/pg_shmem.c:175 port/sysv_shmem.c:175
#, c-format
msgid "could not create shared memory segment: %m"
-msgstr "n'a pas pu cr�er le segment de m�moire partag�e : %m"
+msgstr "n'a pas pu créer le segment de mémoire partagée : %m"
-#: port/pg_shmem.c:142 port/sysv_shmem.c:142
+#: port/pg_shmem.c:176 port/sysv_shmem.c:176
#, c-format
msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)."
-msgstr "L'appel syst�me qui a �chou� �tait shmget(cl�=%lu, taille=%zu, 0%o)."
+msgstr "L'appel système qui a échoué était shmget(clé=%lu, taille=%zu, 0%o)."
-#: port/pg_shmem.c:146 port/sysv_shmem.c:146
+#: port/pg_shmem.c:180 port/sysv_shmem.c:180
#, c-format
msgid ""
"This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter, or possibly that it is less than your kernel's SHMMIN parameter.\n"
"The PostgreSQL documentation contains more information about shared memory configuration."
msgstr ""
-"Cette erreur signifie habituellement que la demande de PostgreSQL pour un segment de m�moire partag�e d�passe la valeur du param�tre SHMMAX du noyau, ou est plus petite\n"
-"que votre param�tre SHMMIN du noyau. La documentation PostgreSQL contient plus d'information sur la configuration de la m�moire partag�e."
+"Cette erreur signifie habituellement que la demande de PostgreSQL pour un segment de mémoire partagée dépasse la valeur du paramètre SHMMAX du noyau, ou est plus petite\n"
+"que votre paramètre SHMMIN du noyau. La documentation PostgreSQL contient plus d'information sur la configuration de la mémoire partagée."
-#: port/pg_shmem.c:153 port/sysv_shmem.c:153
+#: port/pg_shmem.c:187 port/sysv_shmem.c:187
#, c-format
msgid ""
"This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMALL parameter. You might need to reconfigure the kernel with larger SHMALL.\n"
"The PostgreSQL documentation contains more information about shared memory configuration."
msgstr ""
-"Cette erreur signifie habituellement que la demande de PostgreSQL pour un segment de m�moire partag�e d�passe le param�tre SHMALL du noyau. Vous pourriez avoir besoin de reconfigurer\n"
-"le noyau avec un SHMALL plus important. La documentation PostgreSQL contient plus d'information sur la configuration de la m�moire partag�e."
+"Cette erreur signifie habituellement que la demande de PostgreSQL pour un segment de mémoire partagée dépasse le paramètre SHMALL du noyau. Vous pourriez avoir besoin de reconfigurer\n"
+"le noyau avec un SHMALL plus important. La documentation PostgreSQL contient plus d'information sur la configuration de la mémoire partagée."
-#: port/pg_shmem.c:159 port/sysv_shmem.c:159
+#: port/pg_shmem.c:193 port/sysv_shmem.c:193
#, c-format
msgid ""
"This error does *not* mean that you have run out of disk space. It occurs either if all available shared memory IDs have been taken, in which case you need to raise the SHMMNI parameter in your kernel, or because the system's overall limit for shared memory has been reached.\n"
"The PostgreSQL documentation contains more information about shared memory configuration."
msgstr ""
-"Cette erreur ne signifie *pas* que vous manquez d'espace disque. Elle survient si tous les identifiants de m�moire partag� disponibles ont �t� pris, auquel cas vous devez augmenter le param�tre SHMMNI de votre noyau, ou parce que la limite maximum de la m�moire partag�e\n"
-"de votre syst�me a �t� atteinte. La documentation de PostgreSQL contient plus d'informations sur la configuration de la m�moire partag�e."
+"Cette erreur ne signifie *pas* que vous manquez d'espace disque. Elle survient si tous les identifiants de mémoire partagé disponibles ont été pris, auquel cas vous devez augmenter le paramètre SHMMNI de votre noyau, ou parce que la limite maximum de la mémoire partagée\n"
+"de votre système a été atteinte. La documentation de PostgreSQL contient plus d'informations sur la configuration de la mémoire partagée."
-#: port/pg_shmem.c:340 port/sysv_shmem.c:340
-#, c-format
-msgid "huge TLB pages not supported on this platform"
-msgstr "Huge Pages TLB non support� sur cette plateforme."
-
-#: port/pg_shmem.c:390 port/sysv_shmem.c:390
+#: port/pg_shmem.c:483 port/sysv_shmem.c:483
#, c-format
msgid "could not map anonymous shared memory: %m"
-msgstr "n'a pas pu cr�er le segment de m�moire partag�e anonyme : %m"
+msgstr "n'a pas pu créer le segment de mémoire partagée anonyme : %m"
-#: port/pg_shmem.c:392 port/sysv_shmem.c:392
+#: port/pg_shmem.c:485 port/sysv_shmem.c:485
#, c-format
msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections."
msgstr ""
"Cette erreur signifie habituellement que la demande de PostgreSQL pour un\n"
-"segment de m�moire partag�e d�passe la m�moire disponible, l'espace swap ou\n"
-"les Huge Pages. Pour r�duire la taille demand�e (actuellement %zu octets),\n"
-"diminuez l'utilisation de la m�moire partag�e, par exemple en r�duisant la\n"
-"valeur du param�tre shared_buffers de PostgreSQL ou le param�tre\n"
+"segment de mémoire partagée dépasse la mémoire disponible, l'espace swap ou\n"
+"les Huge Pages. Pour réduire la taille demandée (actuellement %zu octets),\n"
+"diminuez l'utilisation de la mémoire partagée, par exemple en réduisant la\n"
+"valeur du paramètre shared_buffers de PostgreSQL ou le paramètre\n"
"max_connections."
-#: port/pg_shmem.c:439 port/sysv_shmem.c:439 port/win32_shmem.c:134
+#: port/pg_shmem.c:551 port/sysv_shmem.c:551 port/win32_shmem.c:134
#, c-format
msgid "huge pages not supported on this platform"
-msgstr "Huge Pages non support� sur cette plateforme"
+msgstr "Huge Pages non supporté sur cette plateforme"
-#: port/pg_shmem.c:553 port/sysv_shmem.c:553
+#: port/pg_shmem.c:646 port/sysv_shmem.c:646
#, c-format
msgid "could not stat data directory \"%s\": %m"
-msgstr "n'a pas pu lire les informations sur le r�pertoire des donn�es � %s � : %m"
+msgstr "n'a pas pu lire les informations sur le répertoire des données « %s » : %m"
#: port/win32/crashdump.c:122
#, c-format
msgid "could not load dbghelp.dll, cannot write crash dump\n"
-msgstr "n'a pas pu charger dbghelp.dll, ne peut pas �crire le � crashdump �\n"
+msgstr "n'a pas pu charger dbghelp.dll, ne peut pas écrire le « crashdump »\n"
#: port/win32/crashdump.c:130
#, c-format
msgid "could not load required functions in dbghelp.dll, cannot write crash dump\n"
-msgstr "n'a pas pu charger les fonctions requises dans dbghelp.dll, ne peut pas �crire le � crashdump �\n"
+msgstr "n'a pas pu charger les fonctions requises dans dbghelp.dll, ne peut pas écrire le « crashdump »\n"
#: port/win32/crashdump.c:161
#, c-format
msgid "could not open crash dump file \"%s\" for writing: error code %lu\n"
-msgstr "n'a pas pu ouvrir le fichier � crashdump � � %s � en �criture : code d'erreur %lu\n"
+msgstr "n'a pas pu ouvrir le fichier « crashdump » « %s » en écriture : code d'erreur %lu\n"
#: port/win32/crashdump.c:168
#, c-format
msgid "wrote crash dump to file \"%s\"\n"
-msgstr "a �crit le � crash dump � dans le fichier � %s �\n"
+msgstr "a écrit le « crash dump » dans le fichier « %s »\n"
#: port/win32/crashdump.c:170
#, c-format
msgid "could not write crash dump to file \"%s\": error code %lu\n"
-msgstr "n'a pas pu �crire le � crashdump � dans le fichier � %s � : code d'erreur %lu\n"
+msgstr "n'a pas pu écrire le « crashdump » dans le fichier « %s » : code d'erreur %lu\n"
#: port/win32/signal.c:194
#, c-format
msgid "could not create signal listener pipe for PID %d: error code %lu"
msgstr ""
-"n'a pas pu cr�er le tube d'�coute de signal pour l'identifiant de processus %d :\n"
+"n'a pas pu créer le tube d'écoute de signal pour l'identifiant de processus %d :\n"
"code d'erreur %lu"
#: port/win32/signal.c:274 port/win32/signal.c:306
#, c-format
msgid "could not create signal listener pipe: error code %lu; retrying\n"
-msgstr "n'a pas pu cr�er le tube d'�coute de signal : code d'erreur %lu ; nouvelle tentative\n"
+msgstr "n'a pas pu créer le tube d'écoute de signal : code d'erreur %lu ; nouvelle tentative\n"
#: port/win32/signal.c:317
#, c-format
msgid "could not create signal dispatch thread: error code %lu\n"
-msgstr "n'a pas pu cr�er le thread de r�partition des signaux : code d'erreur %lu\n"
+msgstr "n'a pas pu créer le thread de répartition des signaux : code d'erreur %lu\n"
#: port/win32_sema.c:94
#, c-format
msgid "could not create semaphore: error code %lu"
-msgstr "n'a pas pu cr�er la s�maphore : code d'erreur %lu"
+msgstr "n'a pas pu créer la sémaphore : code d'erreur %lu"
#: port/win32_sema.c:167
#, c-format
msgid "could not lock semaphore: error code %lu"
-msgstr "n'a pas pu verrouiller la s�maphore : code d'erreur %lu"
+msgstr "n'a pas pu verrouiller la sémaphore : code d'erreur %lu"
#: port/win32_sema.c:187
#, c-format
msgid "could not unlock semaphore: error code %lu"
-msgstr "n'a pas pu d�verrouiller la s�maphore : code d'erreur %lu"
+msgstr "n'a pas pu déverrouiller la sémaphore : code d'erreur %lu"
#: port/win32_sema.c:216
#, c-format
msgid "could not try-lock semaphore: error code %lu"
-msgstr "n'a pas pu tenter le verrouillage de la s�maphore : code d'erreur %lu"
+msgstr "n'a pas pu tenter le verrouillage de la sémaphore : code d'erreur %lu"
#: port/win32_shmem.c:173 port/win32_shmem.c:208 port/win32_shmem.c:226
#, c-format
msgid "could not create shared memory segment: error code %lu"
-msgstr "n'a pas pu cr�er le segment de m�moire partag�e : code d'erreur %lu"
+msgstr "n'a pas pu créer le segment de mémoire partagée : code d'erreur %lu"
#: port/win32_shmem.c:174
#, c-format
msgid "Failed system call was CreateFileMapping(size=%zu, name=%s)."
-msgstr "L'appel syst�me qui a �chou� �tait CreateFileMapping(taille=%zu, nom=%s)."
+msgstr "L'appel système qui a échoué était CreateFileMapping(taille=%zu, nom=%s)."
#: port/win32_shmem.c:198
#, c-format
msgid "pre-existing shared memory block is still in use"
-msgstr "le bloc de m�moire partag� pr�-existant est toujours en cours d'utilisation"
+msgstr "le bloc de mémoire partagé pré-existant est toujours en cours d'utilisation"
#: port/win32_shmem.c:199
#, c-format
msgid "Check if there are any old server processes still running, and terminate them."
msgstr ""
-"V�rifier s'il n'y a pas de vieux processus serveur en cours d'ex�cution. Si c'est le\n"
+"Vérifier s'il n'y a pas de vieux processus serveur en cours d'exécution. Si c'est le\n"
"cas, fermez-les."
#: port/win32_shmem.c:209
#, c-format
msgid "Failed system call was DuplicateHandle."
-msgstr "L'appel syst�me qui a �chou� �tait DuplicateHandle."
+msgstr "L'appel système qui a échoué était DuplicateHandle."
#: port/win32_shmem.c:227
#, c-format
msgid "Failed system call was MapViewOfFileEx."
-msgstr "L'appel syst�me qui a �chou� �tait MapViewOfFileEx."
+msgstr "L'appel système qui a échoué était MapViewOfFileEx."
-#: postmaster/autovacuum.c:377
+#: postmaster/autovacuum.c:380
#, c-format
msgid "could not fork autovacuum launcher process: %m"
-msgstr "n'a pas pu ex�cuter le processus autovacuum ma�tre : %m"
+msgstr "n'a pas pu exécuter le processus autovacuum maître : %m"
-#: postmaster/autovacuum.c:413
+#: postmaster/autovacuum.c:416
#, c-format
msgid "autovacuum launcher started"
msgstr "lancement du processus autovacuum"
-#: postmaster/autovacuum.c:775
+#: postmaster/autovacuum.c:779
#, c-format
msgid "autovacuum launcher shutting down"
-msgstr "arr�t du processus autovacuum"
+msgstr "arrêt du processus autovacuum"
-#: postmaster/autovacuum.c:1443
+#: postmaster/autovacuum.c:1441
#, c-format
msgid "could not fork autovacuum worker process: %m"
-msgstr "n'a pas pu ex�cuter le processus autovacuum worker : %m"
+msgstr "n'a pas pu exécuter le processus autovacuum worker : %m"
#: postmaster/autovacuum.c:1639
#, c-format
msgid "autovacuum: processing database \"%s\""
-msgstr "autovacuum : traitement de la base de donn�es � %s �"
+msgstr "autovacuum : traitement de la base de données « %s »"
-#: postmaster/autovacuum.c:2051
+#: postmaster/autovacuum.c:2052
#, c-format
msgid "autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\""
msgstr ""
-"autovacuum : suppression de la table temporaire orpheline � %s.%s � dans la\n"
-"base de donn�es � %s �"
+"autovacuum : suppression de la table temporaire orpheline « %s.%s » dans la\n"
+"base de données « %s »"
-#: postmaster/autovacuum.c:2063
+#: postmaster/autovacuum.c:2064
#, c-format
msgid "autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\""
msgstr ""
-"autovacuum : a trouv� la table temporaire orpheline � %s.%s � dans la base de\n"
-"donn�es � %s �"
+"autovacuum : a trouvé la table temporaire orpheline « %s.%s » dans la base de\n"
+"données « %s »"
-#: postmaster/autovacuum.c:2346
+#: postmaster/autovacuum.c:2347
#, c-format
msgid "automatic vacuum of table \"%s.%s.%s\""
-msgstr "VACUUM automatique de la table � %s.%s.%s �"
+msgstr "VACUUM automatique de la table « %s.%s.%s »"
-#: postmaster/autovacuum.c:2349
+#: postmaster/autovacuum.c:2350
#, c-format
msgid "automatic analyze of table \"%s.%s.%s\""
-msgstr "ANALYZE automatique de la table � %s.%s.%s �"
+msgstr "ANALYZE automatique de la table « %s.%s.%s »"
-#: postmaster/autovacuum.c:2877
+#: postmaster/autovacuum.c:2899
#, c-format
msgid "autovacuum not started because of misconfiguration"
-msgstr "autovacuum non ex�cut� � cause d'une mauvaise configuration"
+msgstr "autovacuum non exécuté à cause d'une mauvaise configuration"
-#: postmaster/autovacuum.c:2878
+#: postmaster/autovacuum.c:2900
#, c-format
msgid "Enable the \"track_counts\" option."
-msgstr "Activez l'option � track_counts �."
+msgstr "Activez l'option « track_counts »."
-#: postmaster/bgworker.c:346 postmaster/bgworker.c:746
+#: postmaster/bgworker.c:346 postmaster/bgworker.c:745
#, c-format
msgid "registering background worker \"%s\""
-msgstr "enregistrement du processus en t�che de fond � %s �"
+msgstr "enregistrement du processus en tâche de fond « %s »"
#: postmaster/bgworker.c:375
#, c-format
msgid "unregistering background worker \"%s\""
-msgstr "d�senregistrement du processus en t�che de fond � %s �"
+msgstr "désenregistrement du processus en tâche de fond « %s »"
#: postmaster/bgworker.c:484
#, c-format
msgid "background worker \"%s\": must attach to shared memory in order to request a database connection"
-msgstr "processus en t�che de fond � %s � : doit se lier � la m�moire partag�e pour �tre capable de demander une connexion � une base"
+msgstr "processus en tâche de fond « %s » : doit se lier à la mémoire partagée pour être capable de demander une connexion à une base"
#: postmaster/bgworker.c:493
#, c-format
msgid "background worker \"%s\": cannot request database access if starting at postmaster start"
-msgstr "processus en t�che de fond � %s � : ne peut pas r�clamer un acc�s � la base s'il s'ex�cute au lancement de postmaster"
+msgstr "processus en tâche de fond « %s » : ne peut pas réclamer un accès à la base s'il s'exécute au lancement de postmaster"
#: postmaster/bgworker.c:507
#, c-format
msgid "background worker \"%s\": invalid restart interval"
-msgstr "processus en t�che de fond � %s �: intervalle de red�marrage invalide"
+msgstr "processus en tâche de fond « %s »: intervalle de redémarrage invalide"
#: postmaster/bgworker.c:552
#, c-format
msgid "terminating background worker \"%s\" due to administrator command"
-msgstr "arr�t du processus en t�che de fond � %s � suite � la demande de l'administrateur"
+msgstr "arrêt du processus en tâche de fond « %s » suite à la demande de l'administrateur"
-#: postmaster/bgworker.c:753
+#: postmaster/bgworker.c:752
#, c-format
msgid "background worker \"%s\": must be registered in shared_preload_libraries"
-msgstr "processus en t�che de fond � %s � : doit �tre enregistr� dans shared_preload_libraries"
+msgstr "processus en tâche de fond « %s » : doit être enregistré dans shared_preload_libraries"
-#: postmaster/bgworker.c:765
+#: postmaster/bgworker.c:764
#, c-format
msgid "background worker \"%s\": only dynamic background workers can request notification"
-msgstr "processus en t�che de fond � %s � : seuls les processus utilisateurs en t�che de fond dynamiques peuvent r�clamer des notifications"
+msgstr "processus en tâche de fond « %s » : seuls les processus utilisateurs en tâche de fond dynamiques peuvent réclamer des notifications"
-#: postmaster/bgworker.c:780
+#: postmaster/bgworker.c:779
#, c-format
msgid "too many background workers"
-msgstr "trop de processus en t�che de fond"
+msgstr "trop de processus en tâche de fond"
-#: postmaster/bgworker.c:781
+#: postmaster/bgworker.c:780
#, c-format
msgid "Up to %d background worker can be registered with the current settings."
msgid_plural "Up to %d background workers can be registered with the current settings."
-msgstr[0] "Un maximum de %d processus en t�che de fond peut �tre enregistr� avec la configuration actuelle"
-msgstr[1] "Un maximum de %d processus en t�che de fond peut �tre enregistr� avec la configuration actuelle"
+msgstr[0] "Un maximum de %d processus en tâche de fond peut être enregistré avec la configuration actuelle"
+msgstr[1] "Un maximum de %d processus en tâche de fond peut être enregistré avec la configuration actuelle"
-#: postmaster/bgworker.c:785
+#: postmaster/bgworker.c:784
#, c-format
msgid "Consider increasing the configuration parameter \"max_worker_processes\"."
-msgstr "Consid�rez l'augmentation du param�tre � max_worker_processes �."
+msgstr "Considérez l'augmentation du paramètre « max_worker_processes »."
-#: postmaster/checkpointer.c:465
+#: postmaster/checkpointer.c:463
#, c-format
msgid "checkpoints are occurring too frequently (%d second apart)"
msgid_plural "checkpoints are occurring too frequently (%d seconds apart)"
msgstr[0] ""
-"les points de v�rification (checkpoints) arrivent trop fr�quemment\n"
+"les points de vérification (checkpoints) arrivent trop fréquemment\n"
"(toutes les %d seconde)"
msgstr[1] ""
-"les points de v�rification (checkpoints) arrivent trop fr�quemment\n"
+"les points de vérification (checkpoints) arrivent trop fréquemment\n"
"(toutes les %d secondes)"
-#: postmaster/checkpointer.c:469
+#: postmaster/checkpointer.c:467
#, c-format
msgid "Consider increasing the configuration parameter \"max_wal_size\"."
-msgstr "Consid�rez l'augmentation du param�tre � max_wal_size �."
+msgstr "Considérez l'augmentation du paramètre « max_wal_size »."
-#: postmaster/checkpointer.c:616
+#: postmaster/checkpointer.c:614
#, c-format
msgid "transaction log switch forced (archive_timeout=%d)"
-msgstr "changement forc� du journal de transaction (archive_timeout=%d)"
+msgstr "changement forcé du journal de transaction (archive_timeout=%d)"
-#: postmaster/checkpointer.c:1074
+#: postmaster/checkpointer.c:1072
#, c-format
msgid "checkpoint request failed"
-msgstr "�chec de la demande de point de v�rification"
+msgstr "échec de la demande de point de vérification"
-#: postmaster/checkpointer.c:1075
+#: postmaster/checkpointer.c:1073
#, c-format
msgid "Consult recent messages in the server log for details."
msgstr ""
-"Consultez les messages r�cents du serveur dans les journaux applicatifs pour\n"
-"plus de d�tails."
+"Consultez les messages récents du serveur dans les journaux applicatifs pour\n"
+"plus de détails."
-#: postmaster/checkpointer.c:1270
+#: postmaster/checkpointer.c:1268
#, c-format
msgid "compacted fsync request queue from %d entries to %d entries"
-msgstr "a compact� la queue de requ�tes fsync de %d entr�es � %d"
+msgstr "a compacté la queue de requêtes fsync de %d entrées à %d"
#: postmaster/pgarch.c:149
#, c-format
@@ -14649,748 +14659,747 @@ msgstr "n'a pas pu lancer le processus fils correspondant au processus d'archiva
#: postmaster/pgarch.c:456
#, c-format
msgid "archive_mode enabled, yet archive_command is not set"
-msgstr "archive_mode activ�, cependant archive_command n'est pas configur�"
+msgstr "archive_mode activé, cependant archive_command n'est pas configuré"
#: postmaster/pgarch.c:484
#, c-format
msgid "archiving transaction log file \"%s\" failed too many times, will try again later"
-msgstr "l'archivage du journal de transactions � %s � a �chou� trop de fois, nouvelle tentative repouss�e"
+msgstr "l'archivage du journal de transactions « %s » a échoué trop de fois, nouvelle tentative repoussée"
#: postmaster/pgarch.c:587
#, c-format
msgid "archive command failed with exit code %d"
-msgstr "�chec de la commande d'archivage avec un code de retour %d"
+msgstr "échec de la commande d'archivage avec un code de retour %d"
#: postmaster/pgarch.c:589 postmaster/pgarch.c:599 postmaster/pgarch.c:606 postmaster/pgarch.c:612 postmaster/pgarch.c:621
#, c-format
msgid "The failed archive command was: %s"
-msgstr "La commande d'archivage qui a �chou� �tait : %s"
+msgstr "La commande d'archivage qui a échoué était : %s"
#: postmaster/pgarch.c:596
#, c-format
msgid "archive command was terminated by exception 0x%X"
-msgstr "la commande d'archivage a �t� termin�e par l'exception 0x%X"
+msgstr "la commande d'archivage a été terminée par l'exception 0x%X"
-#: postmaster/pgarch.c:598 postmaster/postmaster.c:3478
+#: postmaster/pgarch.c:598 postmaster/postmaster.c:3491
#, c-format
msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value."
msgstr ""
-"Voir le fichier d'en-t�te C � ntstatus.h � pour une description de la valeur\n"
-"hexad�cimale."
+"Voir le fichier d'en-tête C « ntstatus.h » pour une description de la valeur\n"
+"hexadécimale."
#: postmaster/pgarch.c:603
#, c-format
msgid "archive command was terminated by signal %d: %s"
-msgstr "la commande d'archivage a �t� termin�e par le signal %d : %s"
+msgstr "la commande d'archivage a été terminée par le signal %d : %s"
#: postmaster/pgarch.c:610
#, c-format
msgid "archive command was terminated by signal %d"
-msgstr "la commande d'archivage a �t� termin�e par le signal %d"
+msgstr "la commande d'archivage a été terminée par le signal %d"
#: postmaster/pgarch.c:619
#, c-format
msgid "archive command exited with unrecognized status %d"
-msgstr "la commande d'archivage a quitt� avec le statut non reconnu %d"
+msgstr "la commande d'archivage a quitté avec le statut non reconnu %d"
#: postmaster/pgarch.c:631
#, c-format
msgid "archived transaction log file \"%s\""
-msgstr "journal des transactions archiv� � %s �"
+msgstr "journal des transactions archivé « %s »"
#: postmaster/pgarch.c:680
#, c-format
msgid "could not open archive status directory \"%s\": %m"
-msgstr "n'a pas pu acc�der au r�pertoire du statut des archives � %s � : %m"
+msgstr "n'a pas pu accéder au répertoire du statut des archives « %s » : %m"
-#: postmaster/pgstat.c:356
+#: postmaster/pgstat.c:355
#, c-format
msgid "could not resolve \"localhost\": %s"
-msgstr "n'a pas pu r�soudre � localhost � : %s"
+msgstr "n'a pas pu résoudre « localhost » : %s"
-#: postmaster/pgstat.c:379
+#: postmaster/pgstat.c:378
#, c-format
msgid "trying another address for the statistics collector"
-msgstr "nouvelle tentative avec une autre adresse pour le r�cup�rateur de statistiques"
+msgstr "nouvelle tentative avec une autre adresse pour le récupérateur de statistiques"
-#: postmaster/pgstat.c:388
+#: postmaster/pgstat.c:387
#, c-format
msgid "could not create socket for statistics collector: %m"
-msgstr "n'a pas pu cr�er la socket pour le r�cup�rateur de statistiques : %m"
+msgstr "n'a pas pu créer la socket pour le récupérateur de statistiques : %m"
-#: postmaster/pgstat.c:400
+#: postmaster/pgstat.c:399
#, c-format
msgid "could not bind socket for statistics collector: %m"
-msgstr "n'a pas pu lier la socket au r�cup�rateur de statistiques : %m"
+msgstr "n'a pas pu lier la socket au récupérateur de statistiques : %m"
-#: postmaster/pgstat.c:411
+#: postmaster/pgstat.c:410
#, c-format
msgid "could not get address of socket for statistics collector: %m"
-msgstr "n'a pas pu obtenir l'adresse de la socket du r�cup�rateur de statistiques : %m"
+msgstr "n'a pas pu obtenir l'adresse de la socket du récupérateur de statistiques : %m"
-#: postmaster/pgstat.c:427
+#: postmaster/pgstat.c:426
#, c-format
msgid "could not connect socket for statistics collector: %m"
-msgstr "n'a pas pu connecter la socket au r�cup�rateur de statistiques : %m"
+msgstr "n'a pas pu connecter la socket au récupérateur de statistiques : %m"
-#: postmaster/pgstat.c:448
+#: postmaster/pgstat.c:447
#, c-format
msgid "could not send test message on socket for statistics collector: %m"
msgstr ""
-"n'a pas pu envoyer le message de tests sur la socket du r�cup�rateur de\n"
+"n'a pas pu envoyer le message de tests sur la socket du récupérateur de\n"
"statistiques : %m"
-#: postmaster/pgstat.c:474
+#: postmaster/pgstat.c:473
#, c-format
msgid "select() failed in statistics collector: %m"
-msgstr "�chec du select() dans le r�cup�rateur de statistiques : %m"
+msgstr "échec du select() dans le récupérateur de statistiques : %m"
-#: postmaster/pgstat.c:489
+#: postmaster/pgstat.c:488
#, c-format
msgid "test message did not get through on socket for statistics collector"
msgstr ""
-"le message de test n'a pas pu arriver sur la socket du r�cup�rateur de\n"
+"le message de test n'a pas pu arriver sur la socket du récupérateur de\n"
"statistiques : %m"
-#: postmaster/pgstat.c:504
+#: postmaster/pgstat.c:503
#, c-format
msgid "could not receive test message on socket for statistics collector: %m"
msgstr ""
-"n'a pas pu recevoir le message de tests sur la socket du r�cup�rateur de\n"
+"n'a pas pu recevoir le message de tests sur la socket du récupérateur de\n"
"statistiques : %m"
-#: postmaster/pgstat.c:514
+#: postmaster/pgstat.c:513
#, c-format
msgid "incorrect test message transmission on socket for statistics collector"
msgstr ""
-"transmission incorrecte du message de tests sur la socket du r�cup�rateur de\n"
+"transmission incorrecte du message de tests sur la socket du récupérateur de\n"
"statistiques"
-#: postmaster/pgstat.c:537
+#: postmaster/pgstat.c:536
#, c-format
msgid "could not set statistics collector socket to nonblocking mode: %m"
msgstr ""
-"n'a pas pu initialiser la socket du r�cup�rateur de statistiques dans le mode\n"
+"n'a pas pu initialiser la socket du récupérateur de statistiques dans le mode\n"
"non bloquant : %m"
-#: postmaster/pgstat.c:547
+#: postmaster/pgstat.c:546
#, c-format
msgid "disabling statistics collector for lack of working socket"
msgstr ""
-"d�sactivation du r�cup�rateur de statistiques � cause du manque de socket\n"
+"désactivation du récupérateur de statistiques à cause du manque de socket\n"
"fonctionnel"
-#: postmaster/pgstat.c:694
+#: postmaster/pgstat.c:693
#, c-format
msgid "could not fork statistics collector: %m"
msgstr ""
-"n'a pas pu lancer le processus fils correspondant au r�cup�rateur de\n"
+"n'a pas pu lancer le processus fils correspondant au récupérateur de\n"
"statistiques : %m"
-#: postmaster/pgstat.c:1262
+#: postmaster/pgstat.c:1261
#, c-format
msgid "unrecognized reset target: \"%s\""
-msgstr "cible reset non reconnu : � %s �"
+msgstr "cible reset non reconnu : « %s »"
-#: postmaster/pgstat.c:1263
+#: postmaster/pgstat.c:1262
#, c-format
msgid "Target must be \"archiver\" or \"bgwriter\"."
-msgstr "La cible doit �tre � archiver � ou � bgwriter �."
+msgstr "La cible doit être « archiver » ou « bgwriter »."
-#: postmaster/pgstat.c:3578
+#: postmaster/pgstat.c:3587
#, c-format
msgid "could not read statistics message: %m"
msgstr "n'a pas pu lire le message des statistiques : %m"
-#: postmaster/pgstat.c:3909 postmaster/pgstat.c:4086
+#: postmaster/pgstat.c:3918 postmaster/pgstat.c:4075
#, c-format
msgid "could not open temporary statistics file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier temporaire des statistiques � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier temporaire des statistiques « %s » : %m"
-#: postmaster/pgstat.c:3977 postmaster/pgstat.c:4131
+#: postmaster/pgstat.c:3985 postmaster/pgstat.c:4120
#, c-format
msgid "could not write temporary statistics file \"%s\": %m"
-msgstr "n'a pas pu �crire le fichier temporaire des statistiques � %s � : %m"
+msgstr "n'a pas pu écrire le fichier temporaire des statistiques « %s » : %m"
-#: postmaster/pgstat.c:3986 postmaster/pgstat.c:4140
+#: postmaster/pgstat.c:3994 postmaster/pgstat.c:4129
#, c-format
msgid "could not close temporary statistics file \"%s\": %m"
-msgstr "n'a pas pu fermer le fichier temporaire des statistiques � %s � : %m"
+msgstr "n'a pas pu fermer le fichier temporaire des statistiques « %s » : %m"
-#: postmaster/pgstat.c:3994 postmaster/pgstat.c:4148
+#: postmaster/pgstat.c:4002 postmaster/pgstat.c:4137
#, c-format
msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m"
msgstr ""
-"n'a pas pu renommer le fichier temporaire des statistiques � %s � en\n"
-"� %s � : %m"
+"n'a pas pu renommer le fichier temporaire des statistiques « %s » en\n"
+"« %s » : %m"
-#: postmaster/pgstat.c:4230 postmaster/pgstat.c:4413 postmaster/pgstat.c:4568
+#: postmaster/pgstat.c:4226 postmaster/pgstat.c:4411 postmaster/pgstat.c:4564
#, c-format
msgid "could not open statistics file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier de statistiques � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier de statistiques « %s » : %m"
-#: postmaster/pgstat.c:4242 postmaster/pgstat.c:4252 postmaster/pgstat.c:4262 postmaster/pgstat.c:4283 postmaster/pgstat.c:4298 postmaster/pgstat.c:4354 postmaster/pgstat.c:4425 postmaster/pgstat.c:4445 postmaster/pgstat.c:4463 postmaster/pgstat.c:4479 postmaster/pgstat.c:4497 postmaster/pgstat.c:4513 postmaster/pgstat.c:4580 postmaster/pgstat.c:4592 postmaster/pgstat.c:4604 postmaster/pgstat.c:4629 postmaster/pgstat.c:4651
+#: postmaster/pgstat.c:4238 postmaster/pgstat.c:4248 postmaster/pgstat.c:4258 postmaster/pgstat.c:4279 postmaster/pgstat.c:4294 postmaster/pgstat.c:4348 postmaster/pgstat.c:4423 postmaster/pgstat.c:4443 postmaster/pgstat.c:4461 postmaster/pgstat.c:4477 postmaster/pgstat.c:4495 postmaster/pgstat.c:4511 postmaster/pgstat.c:4576 postmaster/pgstat.c:4588 postmaster/pgstat.c:4600 postmaster/pgstat.c:4625 postmaster/pgstat.c:4647
#, c-format
msgid "corrupted statistics file \"%s\""
-msgstr "fichier de statistiques � %s � corrompu"
+msgstr "fichier de statistiques « %s » corrompu"
-#: postmaster/pgstat.c:4768
+#: postmaster/pgstat.c:4776
#, c-format
msgid "using stale statistics instead of current ones because stats collector is not responding"
msgstr ""
-"utilise de vieilles statistiques � la place des actuelles car le collecteur de\n"
-"statistiques ne r�pond pas"
+"utilise de vieilles statistiques à la place des actuelles car le collecteur de\n"
+"statistiques ne répond pas"
-#: postmaster/pgstat.c:5086
+#: postmaster/pgstat.c:5103
#, c-format
msgid "database hash table corrupted during cleanup --- abort"
msgstr ""
-"corruption de la table hach�e de la base de donn�es lors du lancement\n"
+"corruption de la table hachée de la base de données lors du lancement\n"
"--- annulation"
-#: postmaster/postmaster.c:676
+#: postmaster/postmaster.c:684
#, c-format
msgid "%s: invalid argument for option -f: \"%s\"\n"
-msgstr "%s : argument invalide pour l'option -f : � %s �\n"
+msgstr "%s : argument invalide pour l'option -f : « %s »\n"
-#: postmaster/postmaster.c:762
+#: postmaster/postmaster.c:770
#, c-format
msgid "%s: invalid argument for option -t: \"%s\"\n"
-msgstr "%s : argument invalide pour l'option -t : � %s �\n"
+msgstr "%s : argument invalide pour l'option -t : « %s »\n"
-#: postmaster/postmaster.c:813
+#: postmaster/postmaster.c:821
#, c-format
msgid "%s: invalid argument: \"%s\"\n"
-msgstr "%s : argument invalide : � %s �\n"
+msgstr "%s : argument invalide : « %s »\n"
-#: postmaster/postmaster.c:848
+#: postmaster/postmaster.c:860
#, c-format
msgid "%s: superuser_reserved_connections must be less than max_connections\n"
-msgstr "%s : superuser_reserved_connections doit �tre inf�rieur � max_connections\n"
+msgstr "%s : superuser_reserved_connections doit être inférieur à max_connections\n"
-#: postmaster/postmaster.c:853
+#: postmaster/postmaster.c:865
#, c-format
msgid "%s: max_wal_senders must be less than max_connections\n"
-msgstr "%s : max_wal_senders doit �tre inf�rieur � max_connections\n"
+msgstr "%s : max_wal_senders doit être inférieur à max_connections\n"
-#: postmaster/postmaster.c:858
+#: postmaster/postmaster.c:870
#, c-format
msgid "WAL archival cannot be enabled when wal_level is \"minimal\""
-msgstr "L'archivage des journaux de transactions ne peut pas �tre activ� quand wal_level vaut � minimal �"
+msgstr "L'archivage des journaux de transactions ne peut pas être activé quand wal_level vaut « minimal »"
-#: postmaster/postmaster.c:861
-#, fuzzy, c-format
-#| msgid "WAL streaming (max_wal_senders > 0) requires wal_level \"archive\", \"hot_standby\", or \"logical\""
+#: postmaster/postmaster.c:873
+#, c-format
msgid "WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or \"logical\""
msgstr ""
-"l'envoi d'un flux de transactions (max_wal_senders > 0) n�cessite que\n"
-"le param�tre wal_level soit initialis� avec � archive �, � hot_standby � ou � logical �"
+"l'envoi d'un flux de transactions (max_wal_senders > 0) nécessite que\n"
+"le paramètre wal_level soit initialisé avec « replica » ou « logical »"
-#: postmaster/postmaster.c:869
+#: postmaster/postmaster.c:881
#, c-format
msgid "%s: invalid datetoken tables, please fix\n"
msgstr "%s : tables datetoken invalide, merci de corriger\n"
-#: postmaster/postmaster.c:961 postmaster/postmaster.c:1059 utils/init/miscinit.c:1429
+#: postmaster/postmaster.c:973 postmaster/postmaster.c:1071 utils/init/miscinit.c:1429
#, c-format
msgid "invalid list syntax in parameter \"%s\""
-msgstr "syntaxe de liste invalide pour le param�tre � %s �"
+msgstr "syntaxe de liste invalide pour le paramètre « %s »"
-#: postmaster/postmaster.c:992
+#: postmaster/postmaster.c:1004
#, c-format
msgid "could not create listen socket for \"%s\""
-msgstr "n'a pas pu cr�er le socket d'�coute pour � %s �"
+msgstr "n'a pas pu créer le socket d'écoute pour « %s »"
-#: postmaster/postmaster.c:998
+#: postmaster/postmaster.c:1010
#, c-format
msgid "could not create any TCP/IP sockets"
-msgstr "n'a pas pu cr�er de socket TCP/IP"
+msgstr "n'a pas pu créer de socket TCP/IP"
-#: postmaster/postmaster.c:1081
+#: postmaster/postmaster.c:1093
#, c-format
msgid "could not create Unix-domain socket in directory \"%s\""
-msgstr "n'a pas pu cr�er la socket de domaine Unix dans le r�pertoire � %s �"
+msgstr "n'a pas pu créer la socket de domaine Unix dans le répertoire « %s »"
-#: postmaster/postmaster.c:1087
+#: postmaster/postmaster.c:1099
#, c-format
msgid "could not create any Unix-domain sockets"
-msgstr "n'a pas pu cr�er les sockets de domaine Unix"
+msgstr "n'a pas pu créer les sockets de domaine Unix"
-#: postmaster/postmaster.c:1099
+#: postmaster/postmaster.c:1111
#, c-format
msgid "no socket created for listening"
-msgstr "pas de socket cr�� pour l'�coute"
+msgstr "pas de socket créé pour l'écoute"
-#: postmaster/postmaster.c:1139
+#: postmaster/postmaster.c:1151
#, c-format
msgid "could not create I/O completion port for child queue"
-msgstr "n'a pas pu cr�er un port de terminaison I/O pour la queue"
+msgstr "n'a pas pu créer un port de terminaison I/O pour la queue"
-#: postmaster/postmaster.c:1168
+#: postmaster/postmaster.c:1180
#, c-format
msgid "%s: could not change permissions of external PID file \"%s\": %s\n"
-msgstr "%s : n'a pas pu modifier les droits du fichier PID externe � %s � : %s\n"
+msgstr "%s : n'a pas pu modifier les droits du fichier PID externe « %s » : %s\n"
-#: postmaster/postmaster.c:1172
+#: postmaster/postmaster.c:1184
#, c-format
msgid "%s: could not write external PID file \"%s\": %s\n"
-msgstr "%s : n'a pas pu �crire le fichier PID externe � %s � : %s\n"
+msgstr "%s : n'a pas pu écrire le fichier PID externe « %s » : %s\n"
-#: postmaster/postmaster.c:1223
+#: postmaster/postmaster.c:1234
#, c-format
msgid "ending log output to stderr"
-msgstr "arr�t des traces sur stderr"
+msgstr "arrêt des traces sur stderr"
-#: postmaster/postmaster.c:1224
+#: postmaster/postmaster.c:1235
#, c-format
msgid "Future log output will go to log destination \"%s\"."
-msgstr "Les traces suivantes iront sur � %s �."
+msgstr "Les traces suivantes iront sur « %s »."
-#: postmaster/postmaster.c:1250 utils/init/postinit.c:214
+#: postmaster/postmaster.c:1261 utils/init/postinit.c:213
#, c-format
msgid "could not load pg_hba.conf"
msgstr "n'a pas pu charger pg_hba.conf"
-#: postmaster/postmaster.c:1276
+#: postmaster/postmaster.c:1287
#, c-format
msgid "postmaster became multithreaded during startup"
-msgstr "le postmaster est devenu multithread� lors du d�marrage"
+msgstr "le postmaster est devenu multithreadé lors du démarrage"
-#: postmaster/postmaster.c:1277
+#: postmaster/postmaster.c:1288
#, c-format
msgid "Set the LC_ALL environment variable to a valid locale."
msgstr "Configurez la variable d'environnement LC_ALL avec une locale valide."
-#: postmaster/postmaster.c:1374
+#: postmaster/postmaster.c:1385
#, c-format
msgid "%s: could not locate matching postgres executable"
-msgstr "%s : n'a pas pu localiser l'ex�cutable postgres correspondant"
+msgstr "%s : n'a pas pu localiser l'exécutable postgres correspondant"
-#: postmaster/postmaster.c:1397 utils/misc/tzparser.c:341
+#: postmaster/postmaster.c:1408 utils/misc/tzparser.c:341
#, c-format
msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location."
-msgstr "Ceci peut indiquer une installation PostgreSQL incompl�te, ou que le fichier � %s � a �t� d�plac�."
+msgstr "Ceci peut indiquer une installation PostgreSQL incomplète, ou que le fichier « %s » a été déplacé."
-#: postmaster/postmaster.c:1425
+#: postmaster/postmaster.c:1436
#, c-format
msgid "data directory \"%s\" does not exist"
-msgstr "le r�pertoire des donn�es � %s � n'existe pas"
+msgstr "le répertoire des données « %s » n'existe pas"
-#: postmaster/postmaster.c:1430
+#: postmaster/postmaster.c:1441
#, c-format
msgid "could not read permissions of directory \"%s\": %m"
-msgstr "n'a pas pu lire les droits du r�pertoire � %s � : %m"
+msgstr "n'a pas pu lire les droits du répertoire « %s » : %m"
-#: postmaster/postmaster.c:1438
+#: postmaster/postmaster.c:1449
#, c-format
msgid "specified data directory \"%s\" is not a directory"
-msgstr "le r�pertoire des donn�es � %s � n'est pas un r�pertoire"
+msgstr "le répertoire des données « %s » n'est pas un répertoire"
-#: postmaster/postmaster.c:1454
+#: postmaster/postmaster.c:1465
#, c-format
msgid "data directory \"%s\" has wrong ownership"
-msgstr "le r�pertoire des donn�es � %s � a un mauvais propri�taire"
+msgstr "le répertoire des données « %s » a un mauvais propriétaire"
-#: postmaster/postmaster.c:1456
+#: postmaster/postmaster.c:1467
#, c-format
msgid "The server must be started by the user that owns the data directory."
msgstr ""
-"Le serveur doit �tre en cours d'ex�cution par l'utilisateur qui poss�de le\n"
-"r�pertoire des donn�es."
+"Le serveur doit être en cours d'exécution par l'utilisateur qui possède le\n"
+"répertoire des données."
-#: postmaster/postmaster.c:1476
+#: postmaster/postmaster.c:1487
#, c-format
msgid "data directory \"%s\" has group or world access"
msgstr ""
-"le r�pertoire des donn�es � %s � est accessible par le groupe et/ou par les\n"
+"le répertoire des données « %s » est accessible par le groupe et/ou par les\n"
"autres"
-#: postmaster/postmaster.c:1478
+#: postmaster/postmaster.c:1489
#, c-format
msgid "Permissions should be u=rwx (0700)."
-msgstr "Les droits devraient �tre u=rwx (0700)."
+msgstr "Les droits devraient être u=rwx (0700)."
-#: postmaster/postmaster.c:1489
+#: postmaster/postmaster.c:1500
#, c-format
msgid ""
"%s: could not find the database system\n"
"Expected to find it in the directory \"%s\",\n"
"but could not open file \"%s\": %s\n"
msgstr ""
-"%s : n'a pas pu trouver le syst�me de bases de donn�es\n"
-"S'attendait � le trouver dans le r�pertoire � %s �,\n"
-"mais n'a pas r�ussi � ouvrir le fichier � %s �: %s\n"
+"%s : n'a pas pu trouver le système de bases de données\n"
+"S'attendait à le trouver dans le répertoire « %s »,\n"
+"mais n'a pas réussi à ouvrir le fichier « %s »: %s\n"
-#: postmaster/postmaster.c:1666
+#: postmaster/postmaster.c:1677
#, c-format
msgid "select() failed in postmaster: %m"
-msgstr "�chec de select() dans postmaster : %m"
+msgstr "échec de select() dans postmaster : %m"
-#: postmaster/postmaster.c:1816
+#: postmaster/postmaster.c:1828
#, c-format
msgid "performing immediate shutdown because data directory lock file is invalid"
-msgstr ""
+msgstr "forçage d'un arrêt immédiat car le fichier de verrou du répertoire de données est invalide"
-#: postmaster/postmaster.c:1894 postmaster/postmaster.c:1925
+#: postmaster/postmaster.c:1906 postmaster/postmaster.c:1937
#, c-format
msgid "incomplete startup packet"
-msgstr "paquet de d�marrage incomplet"
+msgstr "paquet de démarrage incomplet"
-#: postmaster/postmaster.c:1906
+#: postmaster/postmaster.c:1918
#, c-format
msgid "invalid length of startup packet"
-msgstr "longueur invalide du paquet de d�marrage"
+msgstr "longueur invalide du paquet de démarrage"
-#: postmaster/postmaster.c:1964
+#: postmaster/postmaster.c:1976
#, c-format
msgid "failed to send SSL negotiation response: %m"
-msgstr "�chec lors de l'envoi de la r�ponse de n�gotiation SSL : %m"
+msgstr "échec lors de l'envoi de la réponse de négotiation SSL : %m"
-#: postmaster/postmaster.c:1993
+#: postmaster/postmaster.c:2005
#, c-format
msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u"
msgstr ""
-"Protocole non support�e de l'interface %u.%u : le serveur supporte de %u.0 �\n"
+"Protocole non supportée de l'interface %u.%u : le serveur supporte de %u.0 à\n"
"%u.%u"
-#: postmaster/postmaster.c:2056 utils/misc/guc.c:5657 utils/misc/guc.c:5750 utils/misc/guc.c:7047 utils/misc/guc.c:9783 utils/misc/guc.c:9817
+#: postmaster/postmaster.c:2068 utils/misc/guc.c:5660 utils/misc/guc.c:5753 utils/misc/guc.c:7051 utils/misc/guc.c:9805 utils/misc/guc.c:9839
#, c-format
msgid "invalid value for parameter \"%s\": \"%s\""
-msgstr "valeur invalide pour le param�tre � %s � : � %s �"
+msgstr "valeur invalide pour le paramètre « %s » : « %s »"
-#: postmaster/postmaster.c:2059
+#: postmaster/postmaster.c:2071
#, c-format
msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"."
-msgstr "Les valeurs valides sont : � false �, � 0 �, � true �, � 1 �, � database �."
+msgstr "Les valeurs valides sont : « false », « 0 », « true », « 1 », « database »."
-#: postmaster/postmaster.c:2079
+#: postmaster/postmaster.c:2091
#, c-format
msgid "invalid startup packet layout: expected terminator as last byte"
msgstr ""
-"configuration invalide du paquet de d�marrage : terminaison attendue comme\n"
+"configuration invalide du paquet de démarrage : terminaison attendue comme\n"
"dernier octet"
-#: postmaster/postmaster.c:2107
+#: postmaster/postmaster.c:2119
#, c-format
msgid "no PostgreSQL user name specified in startup packet"
-msgstr "aucun nom d'utilisateur PostgreSQL n'a �t� sp�cifi� dans le paquet de d�marrage"
+msgstr "aucun nom d'utilisateur PostgreSQL n'a été spécifié dans le paquet de démarrage"
-#: postmaster/postmaster.c:2166
+#: postmaster/postmaster.c:2178
#, c-format
msgid "the database system is starting up"
-msgstr "le syst�me de bases de donn�es se lance"
+msgstr "le système de bases de données se lance"
-#: postmaster/postmaster.c:2171
+#: postmaster/postmaster.c:2183
#, c-format
msgid "the database system is shutting down"
-msgstr "le syst�me de base de donn�es s'arr�te"
+msgstr "le système de base de données s'arrête"
-#: postmaster/postmaster.c:2176
+#: postmaster/postmaster.c:2188
#, c-format
msgid "the database system is in recovery mode"
-msgstr "le syst�me de bases de donn�es est en cours de restauration"
+msgstr "le système de bases de données est en cours de restauration"
-#: postmaster/postmaster.c:2181 storage/ipc/procarray.c:297 storage/ipc/sinvaladt.c:298 storage/lmgr/proc.c:340
+#: postmaster/postmaster.c:2193 storage/ipc/procarray.c:297 storage/ipc/sinvaladt.c:298 storage/lmgr/proc.c:340
#, c-format
msgid "sorry, too many clients already"
-msgstr "d�sol�, trop de clients sont d�j� connect�s"
+msgstr "désolé, trop de clients sont déjà connectés"
-#: postmaster/postmaster.c:2243
+#: postmaster/postmaster.c:2255
#, c-format
msgid "wrong key in cancel request for process %d"
-msgstr "mauvaise cl� dans la demande d'annulation pour le processus %d"
+msgstr "mauvaise clé dans la demande d'annulation pour le processus %d"
-#: postmaster/postmaster.c:2251
+#: postmaster/postmaster.c:2263
#, c-format
msgid "PID %d in cancel request did not match any process"
-msgstr "le PID %d dans la demande d'annulation ne correspond � aucun processus"
+msgstr "le PID %d dans la demande d'annulation ne correspond à aucun processus"
-#: postmaster/postmaster.c:2471
+#: postmaster/postmaster.c:2483
#, c-format
msgid "received SIGHUP, reloading configuration files"
-msgstr "a re�u SIGHUP, rechargement des fichiers de configuration"
+msgstr "a reçu SIGHUP, rechargement des fichiers de configuration"
-#: postmaster/postmaster.c:2496
+#: postmaster/postmaster.c:2508
#, c-format
msgid "pg_hba.conf not reloaded"
msgstr "pg_hba.conf non lu"
-#: postmaster/postmaster.c:2500
+#: postmaster/postmaster.c:2512
#, c-format
msgid "pg_ident.conf not reloaded"
-msgstr "pg_ident.conf non recharg�"
+msgstr "pg_ident.conf non rechargé"
-#: postmaster/postmaster.c:2541
+#: postmaster/postmaster.c:2553
#, c-format
msgid "received smart shutdown request"
-msgstr "a re�u une demande d'arr�t intelligent"
+msgstr "a reçu une demande d'arrêt intelligent"
-#: postmaster/postmaster.c:2596
+#: postmaster/postmaster.c:2608
#, c-format
msgid "received fast shutdown request"
-msgstr "a re�u une demande d'arr�t rapide"
+msgstr "a reçu une demande d'arrêt rapide"
-#: postmaster/postmaster.c:2625
+#: postmaster/postmaster.c:2638
#, c-format
msgid "aborting any active transactions"
msgstr "annulation des transactions actives"
-#: postmaster/postmaster.c:2659
+#: postmaster/postmaster.c:2672
#, c-format
msgid "received immediate shutdown request"
-msgstr "a re�u une demande d'arr�t imm�diat"
+msgstr "a reçu une demande d'arrêt immédiat"
-#: postmaster/postmaster.c:2723
+#: postmaster/postmaster.c:2736
#, c-format
msgid "shutdown at recovery target"
-msgstr "arr�t sur la cible de restauration"
+msgstr "arrêt sur la cible de restauration"
-#: postmaster/postmaster.c:2739 postmaster/postmaster.c:2762
+#: postmaster/postmaster.c:2752 postmaster/postmaster.c:2775
msgid "startup process"
msgstr "processus de lancement"
-#: postmaster/postmaster.c:2742
+#: postmaster/postmaster.c:2755
#, c-format
msgid "aborting startup due to startup process failure"
-msgstr "annulation du d�marrage � cause d'un �chec dans le processus de lancement"
+msgstr "annulation du démarrage à cause d'un échec dans le processus de lancement"
-#: postmaster/postmaster.c:2803
+#: postmaster/postmaster.c:2816
#, c-format
msgid "database system is ready to accept connections"
-msgstr "le syst�me de bases de donn�es est pr�t pour accepter les connexions"
+msgstr "le système de bases de données est prêt pour accepter les connexions"
-#: postmaster/postmaster.c:2822
+#: postmaster/postmaster.c:2835
msgid "background writer process"
-msgstr "processus d'�criture en t�che de fond"
+msgstr "processus d'écriture en tâche de fond"
-#: postmaster/postmaster.c:2876
+#: postmaster/postmaster.c:2889
msgid "checkpointer process"
msgstr "processus checkpointer"
-#: postmaster/postmaster.c:2892
+#: postmaster/postmaster.c:2905
msgid "WAL writer process"
-msgstr "processus d'�criture des journaux de transaction"
+msgstr "processus d'écriture des journaux de transaction"
-#: postmaster/postmaster.c:2906
+#: postmaster/postmaster.c:2919
msgid "WAL receiver process"
-msgstr "processus de r�ception des journaux de transaction"
+msgstr "processus de réception des journaux de transaction"
-#: postmaster/postmaster.c:2921
+#: postmaster/postmaster.c:2934
msgid "autovacuum launcher process"
msgstr "processus de l'autovacuum"
-#: postmaster/postmaster.c:2936
+#: postmaster/postmaster.c:2949
msgid "archiver process"
msgstr "processus d'archivage"
-#: postmaster/postmaster.c:2952
+#: postmaster/postmaster.c:2965
msgid "statistics collector process"
-msgstr "processus de r�cup�ration des statistiques"
+msgstr "processus de récupération des statistiques"
-#: postmaster/postmaster.c:2966
+#: postmaster/postmaster.c:2979
msgid "system logger process"
msgstr "processus des journaux applicatifs"
-#: postmaster/postmaster.c:3028
+#: postmaster/postmaster.c:3041
msgid "worker process"
msgstr "processus de travail"
-#: postmaster/postmaster.c:3111 postmaster/postmaster.c:3131 postmaster/postmaster.c:3138 postmaster/postmaster.c:3156
+#: postmaster/postmaster.c:3124 postmaster/postmaster.c:3144 postmaster/postmaster.c:3151 postmaster/postmaster.c:3169
msgid "server process"
msgstr "processus serveur"
-#: postmaster/postmaster.c:3210
+#: postmaster/postmaster.c:3223
#, c-format
msgid "terminating any other active server processes"
-msgstr "arr�t des autres processus serveur actifs"
+msgstr "arrêt des autres processus serveur actifs"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3466
+#: postmaster/postmaster.c:3479
#, c-format
msgid "%s (PID %d) exited with exit code %d"
msgstr "%s (PID %d) quitte avec le code de sortie %d"
-#: postmaster/postmaster.c:3468 postmaster/postmaster.c:3479 postmaster/postmaster.c:3490 postmaster/postmaster.c:3499 postmaster/postmaster.c:3509
+#: postmaster/postmaster.c:3481 postmaster/postmaster.c:3492 postmaster/postmaster.c:3503 postmaster/postmaster.c:3512 postmaster/postmaster.c:3522
#, c-format
msgid "Failed process was running: %s"
-msgstr "Le processus qui a �chou� ex�cutait : %s"
+msgstr "Le processus qui a échoué exécutait : %s"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3476
+#: postmaster/postmaster.c:3489
#, c-format
msgid "%s (PID %d) was terminated by exception 0x%X"
-msgstr "%s (PID %d) a �t� arr�t� par l'exception 0x%X"
+msgstr "%s (PID %d) a été arrêté par l'exception 0x%X"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3486
+#: postmaster/postmaster.c:3499
#, c-format
msgid "%s (PID %d) was terminated by signal %d: %s"
-msgstr "%s (PID %d) a �t� arr�t� par le signal %d : %s"
+msgstr "%s (PID %d) a été arrêté par le signal %d : %s"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3497
+#: postmaster/postmaster.c:3510
#, c-format
msgid "%s (PID %d) was terminated by signal %d"
-msgstr "%s (PID %d) a �t� arr�t� par le signal %d"
+msgstr "%s (PID %d) a été arrêté par le signal %d"
#. translator: %s is a noun phrase describing a child process, such as
#. "server process"
-#: postmaster/postmaster.c:3507
+#: postmaster/postmaster.c:3520
#, c-format
msgid "%s (PID %d) exited with unrecognized status %d"
-msgstr "%s (PID %d) a quitt� avec le statut inattendu %d"
+msgstr "%s (PID %d) a quitté avec le statut inattendu %d"
-#: postmaster/postmaster.c:3694
+#: postmaster/postmaster.c:3707
#, c-format
msgid "abnormal database system shutdown"
-msgstr "le syst�me de base de donn�es a �t� arr�t� anormalement"
+msgstr "le système de base de données a été arrêté anormalement"
-#: postmaster/postmaster.c:3734
+#: postmaster/postmaster.c:3747
#, c-format
msgid "all server processes terminated; reinitializing"
-msgstr "tous les processus serveur se sont arr�t�s, r�initialisation"
+msgstr "tous les processus serveur se sont arrêtés, réinitialisation"
-#: postmaster/postmaster.c:3946
+#: postmaster/postmaster.c:3959
#, c-format
msgid "could not fork new process for connection: %m"
msgstr "n'a pas pu lancer le nouveau processus fils pour la connexion : %m"
-#: postmaster/postmaster.c:3988
+#: postmaster/postmaster.c:4001
msgid "could not fork new process for connection: "
msgstr "n'a pas pu lancer le nouveau processus fils pour la connexion : "
-#: postmaster/postmaster.c:4102
+#: postmaster/postmaster.c:4115
#, c-format
msgid "connection received: host=%s port=%s"
-msgstr "connexion re�ue : h�te=%s port=%s"
+msgstr "connexion reçue : hôte=%s port=%s"
-#: postmaster/postmaster.c:4107
+#: postmaster/postmaster.c:4120
#, c-format
msgid "connection received: host=%s"
-msgstr "connexion re�ue : h�te=%s"
+msgstr "connexion reçue : hôte=%s"
-#: postmaster/postmaster.c:4390
+#: postmaster/postmaster.c:4403
#, c-format
msgid "could not execute server process \"%s\": %m"
-msgstr "n'a pas pu ex�cuter le processus serveur � %s � : %m"
+msgstr "n'a pas pu exécuter le processus serveur « %s » : %m"
-#: postmaster/postmaster.c:4955
+#: postmaster/postmaster.c:4947
#, c-format
msgid "database system is ready to accept read only connections"
-msgstr "le syst�me de bases de donn�es est pr�t pour accepter les connexions en lecture seule"
+msgstr "le système de bases de données est prêt pour accepter les connexions en lecture seule"
-#: postmaster/postmaster.c:5242
+#: postmaster/postmaster.c:5238
#, c-format
msgid "could not fork startup process: %m"
-msgstr "n'a pas pu lancer le processus fils de d�marrage : %m"
+msgstr "n'a pas pu lancer le processus fils de démarrage : %m"
-#: postmaster/postmaster.c:5246
+#: postmaster/postmaster.c:5242
#, c-format
msgid "could not fork background writer process: %m"
msgstr ""
-"n'a pas pu cr�er un processus fils du processus d'�criture en t�che de\n"
+"n'a pas pu créer un processus fils du processus d'écriture en tâche de\n"
"fond : %m"
-#: postmaster/postmaster.c:5250
+#: postmaster/postmaster.c:5246
#, c-format
msgid "could not fork checkpointer process: %m"
-msgstr "n'a pas pu cr�er le processus checkpointer : %m"
+msgstr "n'a pas pu créer le processus checkpointer : %m"
-#: postmaster/postmaster.c:5254
+#: postmaster/postmaster.c:5250
#, c-format
msgid "could not fork WAL writer process: %m"
msgstr ""
-"n'a pas pu cr�er un processus fils du processus d'�criture des journaux de\n"
+"n'a pas pu créer un processus fils du processus d'écriture des journaux de\n"
"transaction : %m"
-#: postmaster/postmaster.c:5258
+#: postmaster/postmaster.c:5254
#, c-format
msgid "could not fork WAL receiver process: %m"
msgstr ""
-"n'a pas pu cr�er un processus fils de r�ception des journaux de\n"
+"n'a pas pu créer un processus fils de réception des journaux de\n"
"transactions : %m"
-#: postmaster/postmaster.c:5262
+#: postmaster/postmaster.c:5258
#, c-format
msgid "could not fork process: %m"
msgstr "n'a pas pu lancer le processus fils : %m"
-#: postmaster/postmaster.c:5424 postmaster/postmaster.c:5447
+#: postmaster/postmaster.c:5420 postmaster/postmaster.c:5443
#, c-format
msgid "database connection requirement not indicated during registration"
-msgstr "pr�-requis de la connexion � la base non indiqu� lors de l'enregistrement"
+msgstr "pré-requis de la connexion à la base non indiqué lors de l'enregistrement"
-#: postmaster/postmaster.c:5431 postmaster/postmaster.c:5454
+#: postmaster/postmaster.c:5427 postmaster/postmaster.c:5450
#, c-format
msgid "invalid processing mode in background worker"
-msgstr "mode de traitement invalide dans le processus en t�che de fond"
+msgstr "mode de traitement invalide dans le processus en tâche de fond"
-#: postmaster/postmaster.c:5506
+#: postmaster/postmaster.c:5502
#, c-format
msgid "starting background worker process \"%s\""
-msgstr "d�marrage du processus d'�criture en t�che de fond � %s �"
+msgstr "démarrage du processus d'écriture en tâche de fond « %s »"
-#: postmaster/postmaster.c:5517
+#: postmaster/postmaster.c:5513
#, c-format
msgid "could not fork worker process: %m"
-msgstr "n'a pas pu cr�er un processus fils du processus en t�che de fond : %m"
+msgstr "n'a pas pu créer un processus fils du processus en tâche de fond : %m"
-#: postmaster/postmaster.c:5895
+#: postmaster/postmaster.c:5901
#, c-format
msgid "could not duplicate socket %d for use in backend: error code %d"
msgstr "n'a pas pu dupliquer la socket %d pour le serveur : code d'erreur %d"
-#: postmaster/postmaster.c:5927
+#: postmaster/postmaster.c:5933
#, c-format
msgid "could not create inherited socket: error code %d\n"
-msgstr "n'a pas pu cr�er la socket h�rit�e : code d'erreur %d\n"
+msgstr "n'a pas pu créer la socket héritée : code d'erreur %d\n"
-#: postmaster/postmaster.c:5956
+#: postmaster/postmaster.c:5962
#, c-format
msgid "could not open backend variables file \"%s\": %s\n"
-msgstr "n'a pas pu ouvrir le fichier des variables moteurs � %s � : %s\n"
+msgstr "n'a pas pu ouvrir le fichier des variables moteurs « %s » : %s\n"
-#: postmaster/postmaster.c:5963
+#: postmaster/postmaster.c:5969
#, c-format
msgid "could not read from backend variables file \"%s\": %s\n"
-msgstr "n'a pas pu lire le fichier de configuration serveur � %s � : %s\n"
+msgstr "n'a pas pu lire le fichier de configuration serveur « %s » : %s\n"
-#: postmaster/postmaster.c:5972
+#: postmaster/postmaster.c:5978
#, c-format
msgid "could not remove file \"%s\": %s\n"
-msgstr "n'a pas pu supprimer le fichier � %s � : %s\n"
+msgstr "n'a pas pu supprimer le fichier « %s » : %s\n"
-#: postmaster/postmaster.c:5989
+#: postmaster/postmaster.c:5995
#, c-format
msgid "could not map view of backend variables: error code %lu\n"
msgstr ""
-"n'a pas pu ex�cuter \"map\" la vue des variables serveurs : code\n"
+"n'a pas pu exécuter \"map\" la vue des variables serveurs : code\n"
"d'erreur %lu\n"
-#: postmaster/postmaster.c:5998
+#: postmaster/postmaster.c:6004
#, c-format
msgid "could not unmap view of backend variables: error code %lu\n"
msgstr ""
-"n'a pas pu ex�cuter \"unmap\" sur la vue des variables serveurs : code\n"
+"n'a pas pu exécuter \"unmap\" sur la vue des variables serveurs : code\n"
"d'erreur %lu\n"
-#: postmaster/postmaster.c:6005
+#: postmaster/postmaster.c:6011
#, c-format
msgid "could not close handle to backend parameter variables: error code %lu\n"
msgstr ""
-"n'a pas pu fermer le lien vers les variables des param�tres du serveur :\n"
+"n'a pas pu fermer le lien vers les variables des paramètres du serveur :\n"
"code d'erreur %lu\n"
-#: postmaster/postmaster.c:6166
+#: postmaster/postmaster.c:6172
#, c-format
msgid "could not read exit code for process\n"
msgstr "n'a pas pu lire le code de sortie du processus\n"
-#: postmaster/postmaster.c:6171
+#: postmaster/postmaster.c:6177
#, c-format
msgid "could not post child completion status\n"
msgstr "n'a pas pu poster le statut de fin de l'enfant\n"
@@ -15398,17 +15407,17 @@ msgstr "n'a pas pu poster le statut de fin de l'enfant\n"
#: postmaster/syslogger.c:441 postmaster/syslogger.c:1041
#, c-format
msgid "could not read from logger pipe: %m"
-msgstr "n'a pas pu lire � partir du tube des journaux applicatifs : %m"
+msgstr "n'a pas pu lire à partir du tube des journaux applicatifs : %m"
#: postmaster/syslogger.c:490
#, c-format
msgid "logger shutting down"
-msgstr "arr�t en cours des journaux applicatifs"
+msgstr "arrêt en cours des journaux applicatifs"
#: postmaster/syslogger.c:534 postmaster/syslogger.c:548
#, c-format
msgid "could not create pipe for syslog: %m"
-msgstr "n'a pas pu cr�er un tube pour syslog : %m"
+msgstr "n'a pas pu créer un tube pour syslog : %m"
#: postmaster/syslogger.c:584
#, c-format
@@ -15418,12 +15427,12 @@ msgstr "n'a pas pu lancer le processus des journaux applicatifs : %m"
#: postmaster/syslogger.c:620
#, c-format
msgid "redirecting log output to logging collector process"
-msgstr "redirection des traces vers le processus de r�cup�ration des traces"
+msgstr "redirection des traces vers le processus de récupération des traces"
#: postmaster/syslogger.c:621
#, c-format
msgid "Future log output will appear in directory \"%s\"."
-msgstr "Les prochaines traces appara�tront dans le r�pertoire � %s �."
+msgstr "Les prochaines traces apparaîtront dans le répertoire « %s »."
#: postmaster/syslogger.c:629
#, c-format
@@ -15438,22 +15447,22 @@ msgstr "n'a pas pu rediriger la sortie des erreurs (stderr) : %m"
#: postmaster/syslogger.c:996
#, c-format
msgid "could not write to log file: %s\n"
-msgstr "n'a pas pu �crire dans le journal applicatif : %s\n"
+msgstr "n'a pas pu écrire dans le journal applicatif : %s\n"
#: postmaster/syslogger.c:1136
#, c-format
msgid "could not open log file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier applicatif � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier applicatif « %s » : %m"
#: postmaster/syslogger.c:1198 postmaster/syslogger.c:1242
#, c-format
msgid "disabling automatic rotation (use SIGHUP to re-enable)"
-msgstr "d�sactivation de la rotation automatique (utilisez SIGHUP pour la r�activer)"
+msgstr "désactivation de la rotation automatique (utilisez SIGHUP pour la réactiver)"
#: regex/regc_pg_locale.c:261
#, c-format
msgid "could not determine which collation to use for regular expression"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour une expression rationnelle"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour une expression rationnelle"
#: repl_gram.y:260 repl_gram.y:292
#, c-format
@@ -15462,233 +15471,238 @@ msgstr "timeline %u invalide"
#: repl_scanner.l:120
msgid "invalid streaming start location"
-msgstr "emplacement de d�marrage du flux de r�plication invalide"
+msgstr "emplacement de démarrage du flux de réplication invalide"
-#: repl_scanner.l:171 scan.l:671
+#: repl_scanner.l:171 scan.l:670
msgid "unterminated quoted string"
-msgstr "cha�ne entre guillemets non termin�e"
+msgstr "chaîne entre guillemets non terminée"
#: repl_scanner.l:181
#, c-format
msgid "syntax error: unexpected character \"%s\""
-msgstr "erreur de syntaxe : caract�re � %s � inattendu"
+msgstr "erreur de syntaxe : caractère « %s » inattendu"
-#: replication/basebackup.c:230
+#: replication/basebackup.c:232
#, c-format
msgid "could not stat control file \"%s\": %m"
-msgstr "n'a pas pu r�cup�rer des informations sur le fichier de contr�le � %s � : %m"
+msgstr "n'a pas pu récupérer des informations sur le fichier de contrôle « %s » : %m"
-#: replication/basebackup.c:339
+#: replication/basebackup.c:341
#, c-format
msgid "could not find any WAL files"
msgstr "n'a pas pu trouver un seul fichier WAL"
-#: replication/basebackup.c:352 replication/basebackup.c:366 replication/basebackup.c:375
+#: replication/basebackup.c:354 replication/basebackup.c:368 replication/basebackup.c:377
#, c-format
msgid "could not find WAL file \"%s\""
-msgstr "n'a pas pu trouver le fichier WAL � %s �"
+msgstr "n'a pas pu trouver le fichier WAL « %s »"
-#: replication/basebackup.c:414 replication/basebackup.c:440
+#: replication/basebackup.c:416 replication/basebackup.c:442
#, c-format
msgid "unexpected WAL file size \"%s\""
-msgstr "taille du fichier WAL � %s � inattendue"
+msgstr "taille du fichier WAL « %s » inattendue"
-#: replication/basebackup.c:426 replication/basebackup.c:1172
+#: replication/basebackup.c:428 replication/basebackup.c:1160
#, c-format
msgid "base backup could not send data, aborting backup"
-msgstr "la sauvegarde de base n'a pas pu envoyer les donn�es, annulation de la sauvegarde"
+msgstr "la sauvegarde de base n'a pas pu envoyer les données, annulation de la sauvegarde"
-#: replication/basebackup.c:528 replication/basebackup.c:537 replication/basebackup.c:546 replication/basebackup.c:555 replication/basebackup.c:564 replication/basebackup.c:575 replication/basebackup.c:592
+#: replication/basebackup.c:530 replication/basebackup.c:539 replication/basebackup.c:548 replication/basebackup.c:557 replication/basebackup.c:566 replication/basebackup.c:577 replication/basebackup.c:594
#, c-format
msgid "duplicate option \"%s\""
-msgstr "option � %s � dupliqu�e"
+msgstr "option « %s » dupliquée"
-#: replication/basebackup.c:581 utils/misc/guc.c:5667
+#: replication/basebackup.c:583 utils/misc/guc.c:5670
#, c-format
msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)"
-msgstr "%d est en dehors des limites valides pour le param�tre � %s � (%d .. %d)"
+msgstr "%d est en dehors des limites valides pour le paramètre « %s » (%d .. %d)"
-#: replication/basebackup.c:855 replication/basebackup.c:957
+#: replication/basebackup.c:857 replication/basebackup.c:959
#, c-format
msgid "could not stat file or directory \"%s\": %m"
msgstr ""
-"n'a pas pu r�cup�rer les informations sur le fichier ou r�pertoire\n"
-"� %s � : %m"
+"n'a pas pu récupérer les informations sur le fichier ou répertoire\n"
+"« %s » : %m"
-#: replication/basebackup.c:1124
+#: replication/basebackup.c:1112
#, c-format
msgid "skipping special file \"%s\""
-msgstr "ignore le fichier sp�cial � %s �"
+msgstr "ignore le fichier spécial « %s »"
-#: replication/basebackup.c:1235
+#: replication/basebackup.c:1223
#, c-format
msgid "file name too long for tar format: \"%s\""
-msgstr "nom du fichier trop long pour le format tar : � %s �"
+msgstr "nom du fichier trop long pour le format tar : « %s »"
-#: replication/basebackup.c:1240
+#: replication/basebackup.c:1228
#, c-format
msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\""
-msgstr "cible du lien symbolique trop long pour le format tar : nom de fichier � %s �, cible � %s �"
+msgstr "cible du lien symbolique trop long pour le format tar : nom de fichier « %s », cible « %s »"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:116
+#: replication/libpqwalreceiver/libpqwalreceiver.c:119
#, c-format
msgid "could not connect to the primary server: %s"
msgstr "n'a pas pu se connecter au serveur principal : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:140
+#: replication/libpqwalreceiver/libpqwalreceiver.c:142
+#, c-format
+msgid "could not parse connection string: %s"
+msgstr "n'a pas pu analyser la chaîne de connexion « %s »"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:192
#, c-format
msgid "could not receive database system identifier and timeline ID from the primary server: %s"
msgstr ""
-"n'a pas pu recevoir l'identifiant du syst�me de bases de donn�es et\n"
-"l'identifiant de la timeline � partir du serveur principal : %s"
+"n'a pas pu recevoir l'identifiant du système de bases de données et\n"
+"l'identifiant de la timeline à partir du serveur principal : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:151 replication/libpqwalreceiver/libpqwalreceiver.c:305
+#: replication/libpqwalreceiver/libpqwalreceiver.c:203 replication/libpqwalreceiver/libpqwalreceiver.c:357
#, c-format
msgid "invalid response from primary server"
-msgstr "r�ponse invalide du serveur principal"
+msgstr "réponse invalide du serveur principal"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:152
+#: replication/libpqwalreceiver/libpqwalreceiver.c:204
#, c-format
msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields."
msgstr ""
-"N'a pas pu identifier le syst�me : a r�cup�r� %d lignes et %d champs,\n"
+"N'a pas pu identifier le système : a récupéré %d lignes et %d champs,\n"
"attendait %d lignes et %d champs (ou plus)."
-#: replication/libpqwalreceiver/libpqwalreceiver.c:168
+#: replication/libpqwalreceiver/libpqwalreceiver.c:220
#, c-format
msgid "database system identifier differs between the primary and standby"
msgstr ""
-"l'identifiant du syst�me de bases de donn�es diff�re entre le serveur principal\n"
+"l'identifiant du système de bases de données diffère entre le serveur principal\n"
"et le serveur en attente"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:169
+#: replication/libpqwalreceiver/libpqwalreceiver.c:221
#, c-format
msgid "The primary's identifier is %s, the standby's identifier is %s."
msgstr ""
"L'identifiant du serveur principal est %s, l'identifiant du serveur en attente\n"
"est %s."
-#: replication/libpqwalreceiver/libpqwalreceiver.c:211
+#: replication/libpqwalreceiver/libpqwalreceiver.c:263
#, c-format
msgid "could not start WAL streaming: %s"
-msgstr "n'a pas pu d�marrer l'envoi des WAL : %s"
+msgstr "n'a pas pu démarrer l'envoi des WAL : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:229
+#: replication/libpqwalreceiver/libpqwalreceiver.c:281
#, c-format
msgid "could not send end-of-streaming message to primary: %s"
msgstr "n'a pas pu transmettre le message de fin d'envoi de flux au primaire : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:251
+#: replication/libpqwalreceiver/libpqwalreceiver.c:303
#, c-format
msgid "unexpected result set after end-of-streaming"
-msgstr "ensemble de r�sultats inattendu apr�s la fin du flux de r�plication"
+msgstr "ensemble de résultats inattendu après la fin du flux de réplication"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:263
+#: replication/libpqwalreceiver/libpqwalreceiver.c:315
#, c-format
msgid "error reading result of streaming command: %s"
msgstr "erreur lors de la lecture de la commande de flux : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:271
+#: replication/libpqwalreceiver/libpqwalreceiver.c:323
#, c-format
msgid "unexpected result after CommandComplete: %s"
-msgstr "r�sultat inattendu apr�s CommandComplete : %s"
+msgstr "résultat inattendu après CommandComplete : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:294
+#: replication/libpqwalreceiver/libpqwalreceiver.c:346
#, c-format
msgid "could not receive timeline history file from the primary server: %s"
-msgstr "n'a pas pu recevoir le fichier historique � partir du serveur principal : %s"
+msgstr "n'a pas pu recevoir le fichier historique à partir du serveur principal : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:306
+#: replication/libpqwalreceiver/libpqwalreceiver.c:358
#, c-format
msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields."
msgstr "Attendait 1 ligne avec 2 champs, a obtenu %d lignes avec %d champs."
-#: replication/libpqwalreceiver/libpqwalreceiver.c:334
+#: replication/libpqwalreceiver/libpqwalreceiver.c:386
#, c-format
msgid "invalid socket: %s"
msgstr "socket invalide : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:374 storage/ipc/latch.c:1271
+#: replication/libpqwalreceiver/libpqwalreceiver.c:426 storage/ipc/latch.c:1280
#, c-format
msgid "select() failed: %m"
-msgstr "�chec de select() : %m"
+msgstr "échec de select() : %m"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:497 replication/libpqwalreceiver/libpqwalreceiver.c:524 replication/libpqwalreceiver/libpqwalreceiver.c:530
+#: replication/libpqwalreceiver/libpqwalreceiver.c:549 replication/libpqwalreceiver/libpqwalreceiver.c:576 replication/libpqwalreceiver/libpqwalreceiver.c:582
#, c-format
msgid "could not receive data from WAL stream: %s"
-msgstr "n'a pas pu recevoir des donn�es du flux de WAL : %s"
+msgstr "n'a pas pu recevoir des données du flux de WAL : %s"
-#: replication/libpqwalreceiver/libpqwalreceiver.c:549
+#: replication/libpqwalreceiver/libpqwalreceiver.c:601
#, c-format
msgid "could not send data to WAL stream: %s"
-msgstr "n'a pas pu transmettre les donn�es au flux WAL : %s"
+msgstr "n'a pas pu transmettre les données au flux WAL : %s"
#: replication/logical/logical.c:83
#, c-format
msgid "logical decoding requires wal_level >= logical"
-msgstr "le d�codage logique requiert wal_level >= logical"
+msgstr "le décodage logique requiert wal_level >= logical"
#: replication/logical/logical.c:88
#, c-format
msgid "logical decoding requires a database connection"
-msgstr "le d�codage logique requiert une connexion � une base"
+msgstr "le décodage logique requiert une connexion à une base"
#: replication/logical/logical.c:106
#, c-format
msgid "logical decoding cannot be used while in recovery"
-msgstr "le d�codage logique ne peut pas �tre utilis� lors de la restauration"
+msgstr "le décodage logique ne peut pas être utilisé lors de la restauration"
-#: replication/logical/logical.c:238 replication/logical/logical.c:350
+#: replication/logical/logical.c:236 replication/logical/logical.c:348
#, c-format
msgid "cannot use physical replication slot for logical decoding"
-msgstr "ne peut pas utiliser un slot de r�plication physique pour le d�codage logique"
+msgstr "ne peut pas utiliser un slot de réplication physique pour le décodage logique"
-#: replication/logical/logical.c:243 replication/logical/logical.c:355
+#: replication/logical/logical.c:241 replication/logical/logical.c:353
#, c-format
msgid "replication slot \"%s\" was not created in this database"
-msgstr "le slot de r�plication � %s � n'a pas �t� cr�� dans cette base de donn�es"
+msgstr "le slot de réplication « %s » n'a pas été créé dans cette base de données"
-#: replication/logical/logical.c:250
+#: replication/logical/logical.c:248
#, c-format
msgid "cannot create logical replication slot in transaction that has performed writes"
-msgstr "ne peut pas cr�er un slot de r�plication logique dans une transaction qui a fait des �critures"
+msgstr "ne peut pas créer un slot de réplication logique dans une transaction qui a fait des écritures"
-#: replication/logical/logical.c:392
+#: replication/logical/logical.c:390
#, c-format
msgid "starting logical decoding for slot \"%s\""
-msgstr "d�but du d�codage logique pour le slot � %s �"
+msgstr "début du décodage logique pour le slot « %s »"
-#: replication/logical/logical.c:394
+#: replication/logical/logical.c:392
#, c-format
msgid "streaming transactions committing after %X/%X, reading WAL from %X/%X"
-msgstr "envoi des transactions valid�es apr�s %X/%X, lecture des journaux � partir de %X/%X"
+msgstr "envoi des transactions validées après %X/%X, lecture des journaux à partir de %X/%X"
-#: replication/logical/logical.c:529
+#: replication/logical/logical.c:527
#, c-format
msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X"
-msgstr "slot � %s �, plugin de sortie � %s �, dans la fonction d'appel %s, associ� au LSN %X/%X"
+msgstr "slot « %s », plugin de sortie « %s », dans la fonction d'appel %s, associé au LSN %X/%X"
-#: replication/logical/logical.c:536
+#: replication/logical/logical.c:534
#, c-format
msgid "slot \"%s\", output plugin \"%s\", in the %s callback"
-msgstr "slot � %s �, plugin de sortie � %s �, dans la fonction d'appel %s"
+msgstr "slot « %s », plugin de sortie « %s », dans la fonction d'appel %s"
#: replication/logical/logicalfuncs.c:113 replication/slotfuncs.c:32
#, c-format
msgid "must be superuser or replication role to use replication slots"
msgstr ""
-"doit �tre un superutilisateur ou un r�le ayant l'attribut de r�plication\n"
-"pour utiliser des slots de r�plication"
+"doit être un superutilisateur ou un rôle ayant l'attribut de réplication\n"
+"pour utiliser des slots de réplication"
#: replication/logical/logicalfuncs.c:152
#, c-format
msgid "slot name must not be null"
-msgstr "le nom du slot ne doit pas �tre NULL"
+msgstr "le nom du slot ne doit pas être NULL"
#: replication/logical/logicalfuncs.c:168
#, c-format
msgid "options array must not be null"
-msgstr "le tableau options ne doit pas �tre NULL"
+msgstr "le tableau options ne doit pas être NULL"
#: replication/logical/logicalfuncs.c:199
#, c-format
@@ -15703,74 +15717,69 @@ msgstr "le tableau ne doit pas contenir de valeurs NULL"
#: replication/logical/logicalfuncs.c:221 utils/adt/json.c:2277 utils/adt/jsonb.c:1356
#, c-format
msgid "array must have even number of elements"
-msgstr "le tableau doit avoir un nombre pair d'�l�ments"
+msgstr "le tableau doit avoir un nombre pair d'éléments"
#: replication/logical/logicalfuncs.c:264
#, c-format
msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data"
-msgstr "le plugin de sortie � %s � pour le d�codage logique produit une sortie binaire, mais la fonction � %s � attend des donn�es texte"
+msgstr "le plugin de sortie « %s » pour le décodage logique produit une sortie binaire, mais la fonction « %s » attend des données texte"
#: replication/logical/origin.c:181
#, c-format
msgid "only superusers can query or manipulate replication origins"
-msgstr "seuls les super-utilisateurs peuvent lire ou manipuler les origines de r�plication"
+msgstr "seuls les super-utilisateurs peuvent lire ou manipuler les origines de réplication"
#: replication/logical/origin.c:186
#, c-format
msgid "cannot query or manipulate replication origin when max_replication_slots = 0"
-msgstr "ne peut pas lire ou manipuler une originie de r�plication logique quand max_replication_slots = 0"
+msgstr "ne peut pas lire ou manipuler une originie de réplication logique quand max_replication_slots = 0"
#: replication/logical/origin.c:191
#, c-format
msgid "cannot manipulate replication origins during recovery"
-msgstr "ne peut pas manipuler les origines de r�plication lors d'une restauration"
+msgstr "ne peut pas manipuler les origines de réplication lors d'une restauration"
#: replication/logical/origin.c:316
-#, fuzzy, c-format
-#| msgid "could not find parent extension for %s\n"
+#, c-format
msgid "could not find free replication origin OID"
-msgstr "n'a pas pu trouver l'extension parent pour %s\n"
+msgstr "n'a pas pu trouver d'OID d'origine de réplication libre"
#: replication/logical/origin.c:353
#, c-format
msgid "could not drop replication origin with OID %d, in use by PID %d"
-msgstr "ne peut pas supprimer l'origine de r�plication d'OID %d, utilis�e par le PID %d"
+msgstr "ne peut pas supprimer l'origine de réplication d'OID %d, utilisée par le PID %d"
#: replication/logical/origin.c:671
#, c-format
msgid "replication checkpoint has wrong magic %u instead of %u"
-msgstr "le checkpoint de r�plication a le mauvais nombre magique (%u au lieu de %u)"
+msgstr "le checkpoint de réplication a le mauvais nombre magique (%u au lieu de %u)"
#: replication/logical/origin.c:703
#, c-format
msgid "could not read file \"%s\": read %d of %zu"
-msgstr "n'a pas pu lire le fichier � %s � : a lu %d sur %zu"
+msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu"
#: replication/logical/origin.c:712
-#, fuzzy, c-format
-#| msgid "Free one or increase max_replication_slots."
+#, c-format
msgid "could not find free replication state, increase max_replication_slots"
-msgstr "Lib�rez un slot ou augmentez max_replication_slots."
+msgstr "n'a pas pu trouver d'état de réplication libre, augmentez max_replication_slots"
#: replication/logical/origin.c:730
-#, fuzzy, c-format
-#| msgid "replication slot file \"%s\" has wrong magic %u instead of %u"
+#, c-format
msgid "replication slot checkpoint has wrong checksum %u, expected %u"
-msgstr "le fichier � %s � du slot de r�plication un le nombre magique %u au lieu de %u"
+msgstr "le point de contrôle du slot de réplication à la mauvaise somme de contrôle %u, %u attendu"
#: replication/logical/origin.c:854
-#, fuzzy, c-format
-#| msgid "replication slot \"%s\" is already active"
+#, c-format
msgid "replication origin with OID %d is already active for PID %d"
-msgstr "le slot de r�plication � %s � est d�j� actif"
+msgstr "l'origine de réplication d'OID %d est déjà active pour le PID %d"
#: replication/logical/origin.c:865 replication/logical/origin.c:1045
-#, fuzzy, c-format
-#| msgid "could not obtain lock on relation with OID %u"
+#, c-format
msgid "could not find free replication state slot for replication origin with OID %u"
-msgstr "n'a pas pu obtenir un verrou sur la relation d'OID � %u �"
+msgstr "n'a pas pu trouver de slot d'état de réplication libre pour l'origine de réplication d'OID %u"
-#: replication/logical/origin.c:867 replication/logical/origin.c:1047 replication/slot.c:1288
+#: replication/logical/origin.c:867 replication/logical/origin.c:1047 replication/slot.c:1299
#, c-format
msgid "Increase max_replication_slots and try again."
msgstr "Augmentez max_replication_slots et recommencez."
@@ -15778,307 +15787,306 @@ msgstr "Augmentez max_replication_slots et recommencez."
#: replication/logical/origin.c:1004
#, c-format
msgid "cannot setup replication origin when one is already setup"
-msgstr "ne peut pas configurer l'origine de r�plication si une origine existe d�j�"
+msgstr "ne peut pas configurer l'origine de réplication si une origine existe déjà"
#: replication/logical/origin.c:1033
#, c-format
msgid "replication identifier %d is already active for PID %d"
-msgstr "l'identificateur de r�plication %d est d�j� actif pour le PID %d"
+msgstr "l'identificateur de réplication %d est déjà actif pour le PID %d"
#: replication/logical/origin.c:1079 replication/logical/origin.c:1274 replication/logical/origin.c:1294
#, c-format
msgid "no replication origin is configured"
-msgstr "aucune origine de r�plication n'est configur�e"
+msgstr "aucune origine de réplication n'est configurée"
-#: replication/logical/reorderbuffer.c:2322
+#: replication/logical/reorderbuffer.c:2330
#, c-format
msgid "could not write to data file for XID %u: %m"
-msgstr "n'a pas pu �crire dans le fichier pour le XID %u : %m"
+msgstr "n'a pas pu écrire dans le fichier pour le XID %u : %m"
-#: replication/logical/reorderbuffer.c:2418 replication/logical/reorderbuffer.c:2438
+#: replication/logical/reorderbuffer.c:2426 replication/logical/reorderbuffer.c:2446
#, c-format
msgid "could not read from reorderbuffer spill file: %m"
-msgstr "n'a pas pu lire le fichier � reorderbuffer spill � : %m"
+msgstr "n'a pas pu lire le fichier « reorderbuffer spill » : %m"
-#: replication/logical/reorderbuffer.c:2422 replication/logical/reorderbuffer.c:2442
+#: replication/logical/reorderbuffer.c:2430 replication/logical/reorderbuffer.c:2450
#, c-format
msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes"
msgstr ""
-"n'a pas pu lire � partir du fichier � reorderbuffer spill � : a lu seulement %d octets\n"
+"n'a pas pu lire à partir du fichier « reorderbuffer spill » : a lu seulement %d octets\n"
"sur %u"
-#: replication/logical/reorderbuffer.c:3097
+#: replication/logical/reorderbuffer.c:3106
#, c-format
msgid "could not read from file \"%s\": read %d instead of %d bytes"
-msgstr "n'a pas pu lire � partir du fichier � %s � : lu %d octets au lieu de %d octets"
+msgstr "n'a pas pu lire à partir du fichier « %s » : lu %d octets au lieu de %d octets"
-#: replication/logical/snapbuild.c:600
+#: replication/logical/snapbuild.c:598
#, c-format
msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID"
msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs"
-msgstr[0] "snapshot export� pour le d�codage logique : � %s � avec %u identifiant de transaction"
-msgstr[1] "snapshot export� pour le d�codage logique : � %s � avec %u identifiants de transaction"
+msgstr[0] "snapshot exporté pour le décodage logique : « %s » avec %u identifiant de transaction"
+msgstr[1] "snapshot exporté pour le décodage logique : « %s » avec %u identifiants de transaction"
-#: replication/logical/snapbuild.c:919 replication/logical/snapbuild.c:1284 replication/logical/snapbuild.c:1815
+#: replication/logical/snapbuild.c:917 replication/logical/snapbuild.c:1282 replication/logical/snapbuild.c:1813
#, c-format
msgid "logical decoding found consistent point at %X/%X"
-msgstr "le d�codage logique a trouv� le point de coh�rence � %X/%X"
+msgstr "le décodage logique a trouvé le point de cohérence à %X/%X"
-#: replication/logical/snapbuild.c:921
+#: replication/logical/snapbuild.c:919
#, c-format
msgid "Transaction ID %u finished; no more running transactions."
-msgstr "Identifiant de transaction %u termin� ; plus de transactions en cours."
+msgstr "Identifiant de transaction %u terminé ; plus de transactions en cours."
-#: replication/logical/snapbuild.c:1286
+#: replication/logical/snapbuild.c:1284
#, c-format
msgid "There are no running transactions."
msgstr "Il n'existe pas de transactions en cours."
-#: replication/logical/snapbuild.c:1348
+#: replication/logical/snapbuild.c:1346
#, c-format
msgid "logical decoding found initial starting point at %X/%X"
-msgstr "le d�codage logique a trouv� le point de d�marrage � %X/%X"
+msgstr "le décodage logique a trouvé le point de démarrage à %X/%X"
-#: replication/logical/snapbuild.c:1350
+#: replication/logical/snapbuild.c:1348
#, c-format
msgid "%u transaction needs to finish."
msgid_plural "%u transactions need to finish."
msgstr[0] "La transaction %u doit se terminer."
msgstr[1] "Les transactions %u doivent se terminer."
-#: replication/logical/snapbuild.c:1689 replication/logical/snapbuild.c:1715 replication/logical/snapbuild.c:1729 replication/logical/snapbuild.c:1743
+#: replication/logical/snapbuild.c:1687 replication/logical/snapbuild.c:1713 replication/logical/snapbuild.c:1727 replication/logical/snapbuild.c:1741
#, c-format
msgid "could not read file \"%s\", read %d of %d: %m"
-msgstr "n'a pas pu lire le fichier � %s �, lu %d sur %d : %m"
+msgstr "n'a pas pu lire le fichier « %s », lu %d sur %d : %m"
-#: replication/logical/snapbuild.c:1695
-#, fuzzy, c-format
-#| msgid "snapbuild state file \"%s\" has wrong magic %u instead of %u"
+#: replication/logical/snapbuild.c:1693
+#, c-format
msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u"
-msgstr "le fichier d'�tat snapbuild � %s � a le nombre magique %u au lieu de %u"
+msgstr "le fichier d'état snapbuild « %s » a le nombre magique: %u au lieu de %u"
-#: replication/logical/snapbuild.c:1700
-#, fuzzy, c-format
-#| msgid "snapbuild state file \"%s\" has unsupported version %u instead of %u"
+#: replication/logical/snapbuild.c:1698
+#, c-format
msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u"
-msgstr "le fichier d'�tat snapbuild � %s � a une version %u non support�e au lieu de %u"
+msgstr "le fichier d'état snapbuild « %s » a une version non supportée : %u au lieu de %u"
-#: replication/logical/snapbuild.c:1756
-#, fuzzy, c-format
-#| msgid "snapbuild state file %s: checksum mismatch, is %u, should be %u"
+#: replication/logical/snapbuild.c:1754
+#, c-format
msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u"
msgstr ""
-"fichier d'�tat snapbuild %s : diff�rence de somme de contr�le,\n"
-"est %u, devrait �tre %u"
+"différence de somme de contrôle pour lefichier d'état snapbuild %s :\n"
+"est %u, devrait être %u"
-#: replication/logical/snapbuild.c:1817
+#: replication/logical/snapbuild.c:1815
#, c-format
msgid "Logical decoding will begin using saved snapshot."
-msgstr "Le d�codage logique commencera en utilisant un snapshot sauvegard�."
+msgstr "Le décodage logique commencera en utilisant un snapshot sauvegardé."
-#: replication/logical/snapbuild.c:1890
+#: replication/logical/snapbuild.c:1888
#, c-format
msgid "could not parse file name \"%s\""
-msgstr "n'a pas pu analyser le mode du fichier � %s �"
+msgstr "n'a pas pu analyser le mode du fichier « %s »"
#: replication/slot.c:183
#, c-format
msgid "replication slot name \"%s\" is too short"
-msgstr "le nom du slot de r�plication � %s � est trop court"
+msgstr "le nom du slot de réplication « %s » est trop court"
#: replication/slot.c:192
#, c-format
msgid "replication slot name \"%s\" is too long"
-msgstr "le nom du slot de r�plication � %s � est trop long"
+msgstr "le nom du slot de réplication « %s » est trop long"
#: replication/slot.c:205
#, c-format
msgid "replication slot name \"%s\" contains invalid character"
-msgstr "le nom du slot de r�plication � %s � contient un caract�re invalide"
+msgstr "le nom du slot de réplication « %s » contient un caractère invalide"
#: replication/slot.c:207
#, c-format
msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character."
-msgstr "Les noms des slots de r�plication peuvent seulement contenir des lettres, des nombres et des tirets bas."
+msgstr "Les noms des slots de réplication peuvent seulement contenir des lettres, des nombres et des tirets bas."
#: replication/slot.c:254
#, c-format
msgid "replication slot \"%s\" already exists"
-msgstr "le slot de r�plication � %s � existe d�j�"
+msgstr "le slot de réplication « %s » existe déjà"
#: replication/slot.c:264
#, c-format
msgid "all replication slots are in use"
-msgstr "tous les slots de r�plication sont utilis�s"
+msgstr "tous les slots de réplication sont utilisés"
#: replication/slot.c:265
#, c-format
msgid "Free one or increase max_replication_slots."
-msgstr "Lib�rez un slot ou augmentez max_replication_slots."
+msgstr "Libérez un slot ou augmentez max_replication_slots."
-#: replication/slot.c:351
+#: replication/slot.c:361
#, c-format
msgid "replication slot \"%s\" does not exist"
-msgstr "le slot de r�plication � %s � n'existe pas"
+msgstr "le slot de réplication « %s » n'existe pas"
-#: replication/slot.c:355
-#, fuzzy, c-format
-#| msgid "replication slot \"%s\" is already active for PID %d"
+#: replication/slot.c:365
+#, c-format
msgid "replication slot \"%s\" is active for PID %d"
-msgstr "le slot de r�plication � %s � est d�j� actif pour le PID %d"
+msgstr "le slot de réplication « %s » est actif pour le PID %d"
-#: replication/slot.c:501 replication/slot.c:912 replication/slot.c:1249
+#: replication/slot.c:511 replication/slot.c:923 replication/slot.c:1260
#, c-format
msgid "could not remove directory \"%s\""
-msgstr "n'a pas pu supprimer le r�pertoire � %s �"
+msgstr "n'a pas pu supprimer le répertoire « %s »"
-#: replication/slot.c:761
+#: replication/slot.c:772
#, c-format
msgid "replication slots can only be used if max_replication_slots > 0"
-msgstr "les slots de r�plications peuvent seulement �tre utilis�s si max_replication_slots > 0"
+msgstr "les slots de réplications peuvent seulement être utilisés si max_replication_slots > 0"
-#: replication/slot.c:766
-#, fuzzy, c-format
-#| msgid "replication slots can only be used if wal_level >= archive"
+#: replication/slot.c:777
+#, c-format
msgid "replication slots can only be used if wal_level >= replica"
-msgstr "les slots de r�plication peuvent seulement �tre utilis�s si wal_level >= archive"
+msgstr "les slots de réplication peuvent seulement être utilisés si wal_level >= replica"
-#: replication/slot.c:1181 replication/slot.c:1219
+#: replication/slot.c:1192 replication/slot.c:1230
#, c-format
msgid "could not read file \"%s\", read %d of %u: %m"
-msgstr "n'a pas pu lire le fichier � %s �, a lu %d sur %u : %m"
+msgstr "n'a pas pu lire le fichier « %s », a lu %d sur %u : %m"
-#: replication/slot.c:1190
+#: replication/slot.c:1201
#, c-format
msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u"
-msgstr "le fichier � %s � du slot de r�plication a le nombre magique %u au lieu de %u"
+msgstr "le fichier « %s » du slot de réplication a le nombre magique %u au lieu de %u"
-#: replication/slot.c:1197
+#: replication/slot.c:1208
#, c-format
msgid "replication slot file \"%s\" has unsupported version %u"
-msgstr "le fichier � %s � du slot de r�plication a une version %u non support�e"
+msgstr "le fichier « %s » du slot de réplication a une version %u non supportée"
-#: replication/slot.c:1204
+#: replication/slot.c:1215
#, c-format
msgid "replication slot file \"%s\" has corrupted length %u"
-msgstr "le slot de r�plication � %s � a une taille %u corrompue"
+msgstr "le slot de réplication « %s » a une taille %u corrompue"
-#: replication/slot.c:1234
+#: replication/slot.c:1245
#, c-format
msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u"
-msgstr "diff�rence de somme de contr�le pour le fichier de slot de r�plication � %s � : est %u, devrait �tre %u"
+msgstr "différence de somme de contrôle pour le fichier de slot de réplication « %s » : est %u, devrait être %u"
-#: replication/slot.c:1287
+#: replication/slot.c:1298
#, c-format
msgid "too many replication slots active before shutdown"
-msgstr "trop de slots de r�plication actifs avant l'arr�t"
+msgstr "trop de slots de réplication actifs avant l'arrêt"
-#: replication/syncrep.c:228
+#: replication/syncrep.c:221
#, c-format
msgid "canceling the wait for synchronous replication and terminating connection due to administrator command"
msgstr ""
-"annulation de l'attente pour la r�plication synchrone et arr�t des connexions\n"
-"suite � la demande de l'administrateur"
+"annulation de l'attente pour la réplication synchrone et arrêt des connexions\n"
+"suite à la demande de l'administrateur"
-#: replication/syncrep.c:229 replication/syncrep.c:246
+#: replication/syncrep.c:222 replication/syncrep.c:239
#, c-format
msgid "The transaction has already committed locally, but might not have been replicated to the standby."
msgstr ""
-"La transaction a d�j� enregistr� les donn�es localement, mais il se peut que\n"
-"cela n'ait pas �t� r�pliqu� sur le serveur en standby."
+"La transaction a déjà enregistré les données localement, mais il se peut que\n"
+"cela n'ait pas été répliqué sur le serveur en standby."
-#: replication/syncrep.c:245
+#: replication/syncrep.c:238
#, c-format
msgid "canceling wait for synchronous replication due to user request"
-msgstr "annulation de l'attente pour la r�plication synchrone � la demande de l'utilisateur"
+msgstr "annulation de l'attente pour la réplication synchrone à la demande de l'utilisateur"
-#: replication/syncrep.c:375
+#: replication/syncrep.c:368
#, c-format
msgid "standby \"%s\" now has synchronous standby priority %u"
msgstr ""
-"le serveur � %s � en standby a maintenant une priorit� %u en tant que standby\n"
+"le serveur « %s » en standby a maintenant une priorité %u en tant que standby\n"
"synchrone"
-#: replication/syncrep.c:435
-#, fuzzy, c-format
-#| msgid "standby \"%s\" is now the synchronous standby with priority %u"
+#: replication/syncrep.c:428
+#, c-format
msgid "standby \"%s\" is now a synchronous standby with priority %u"
-msgstr "le serveur � %s � en standby est maintenant le serveur standby synchrone de priorit� %u"
+msgstr "le serveur « %s » en standby est maintenant un serveur standby synchrone de priorité %u"
-#: replication/syncrep.c:928
+#: replication/syncrep.c:921
#, c-format
msgid "synchronous_standby_names parser failed"
-msgstr ""
+msgstr "l'analyseur du paramètre synchronous_standby_names a échoué"
+
+#: replication/syncrep.c:927
+#, c-format
+msgid "number of synchronous standbys (%d) must be greater than zero"
+msgstr "le nombre de standbys synchrones (%d) doit être supérieur à zéro"
-#: replication/walreceiver.c:172
+#: replication/walreceiver.c:173
#, c-format
msgid "terminating walreceiver process due to administrator command"
-msgstr "arr�t du processus walreceiver suite � la demande de l'administrateur"
+msgstr "arrêt du processus walreceiver suite à la demande de l'administrateur"
-#: replication/walreceiver.c:324
+#: replication/walreceiver.c:344
#, c-format
msgid "highest timeline %u of the primary is behind recovery timeline %u"
-msgstr "la plus grande timeline %u du serveur principal est derri�re la timeline de restauration %u"
+msgstr "la plus grande timeline %u du serveur principal est derrière la timeline de restauration %u"
-#: replication/walreceiver.c:357
+#: replication/walreceiver.c:377
#, c-format
msgid "started streaming WAL from primary at %X/%X on timeline %u"
-msgstr "Commence le flux des journaux depuis le principal � %X/%X sur la timeline %u"
+msgstr "Commence le flux des journaux depuis le principal à %X/%X sur la timeline %u"
-#: replication/walreceiver.c:362
+#: replication/walreceiver.c:382
#, c-format
msgid "restarted WAL streaming at %X/%X on timeline %u"
-msgstr "recommence le flux WAL � %X/%X sur la timeline %u"
+msgstr "recommence le flux WAL à %X/%X sur la timeline %u"
-#: replication/walreceiver.c:391
+#: replication/walreceiver.c:411
#, c-format
msgid "cannot continue WAL streaming, recovery has already ended"
-msgstr "ne peut pas continuer le flux de journaux de transactions, la r�cup�ration est d�j� termin�e"
+msgstr "ne peut pas continuer le flux de journaux de transactions, la récupération est déjà terminée"
-#: replication/walreceiver.c:428
+#: replication/walreceiver.c:448
#, c-format
msgid "replication terminated by primary server"
-msgstr "r�plication termin�e par le serveur primaire"
+msgstr "réplication terminée par le serveur primaire"
-#: replication/walreceiver.c:429
+#: replication/walreceiver.c:449
#, c-format
msgid "End of WAL reached on timeline %u at %X/%X."
-msgstr "Fin du WAL atteint sur la timeline %u � %X/%X"
+msgstr "Fin du WAL atteint sur la timeline %u à %X/%X"
-#: replication/walreceiver.c:523
+#: replication/walreceiver.c:543
#, c-format
msgid "terminating walreceiver due to timeout"
-msgstr "arr�t du processus walreceiver suite � l'expiration du d�lai de r�plication"
+msgstr "arrêt du processus walreceiver suite à l'expiration du délai de réplication"
-#: replication/walreceiver.c:563
+#: replication/walreceiver.c:583
#, c-format
msgid "primary server contains no more WAL on requested timeline %u"
-msgstr "le serveur principal ne contient plus de WAL sur la timeline %u demand�e"
+msgstr "le serveur principal ne contient plus de WAL sur la timeline %u demandée"
-#: replication/walreceiver.c:578 replication/walreceiver.c:936
+#: replication/walreceiver.c:598 replication/walreceiver.c:957
#, c-format
msgid "could not close log segment %s: %m"
msgstr "n'a pas pu fermer le journal de transactions %s : %m"
-#: replication/walreceiver.c:702
+#: replication/walreceiver.c:722
#, c-format
msgid "fetching timeline history file for timeline %u from primary server"
-msgstr "r�cup�ration du fichier historique pour la timeline %u � partir du serveur principal"
+msgstr "récupération du fichier historique pour la timeline %u à partir du serveur principal"
-#: replication/walreceiver.c:990
+#: replication/walreceiver.c:1011
#, c-format
msgid "could not write to log segment %s at offset %u, length %lu: %m"
-msgstr "n'a pas pu �crire le journal de transactions %s au d�calage %u, longueur %lu : %m"
+msgstr "n'a pas pu écrire le journal de transactions %s au décalage %u, longueur %lu : %m"
#: replication/walsender.c:485
#, c-format
msgid "could not seek to beginning of file \"%s\": %m"
-msgstr "n'a pas pu se d�placer au d�but du fichier � %s � : %m"
+msgstr "n'a pas pu se déplacer au début du fichier « %s » : %m"
#: replication/walsender.c:536
#, c-format
msgid "cannot use a logical replication slot for physical replication"
-msgstr "ne peut pas utiliser un slot de r�plication logique pour une r�plication physique"
+msgstr "ne peut pas utiliser un slot de réplication logique pour une réplication physique"
#: replication/walsender.c:599
#, c-format
@@ -16088,7 +16096,7 @@ msgstr "le point de reprise %X/%X de la timeline %u n'est pas dans l'historique
#: replication/walsender.c:603
#, c-format
msgid "This server's history forked from timeline %u at %X/%X."
-msgstr "L'historique du serveur a chang� � partir de la timeline %u � %X/%X."
+msgstr "L'historique du serveur a changé à partir de la timeline %u à %X/%X."
#: replication/walsender.c:648
#, c-format
@@ -16098,683 +16106,686 @@ msgstr "le point de reprise requis %X/%X est devant la position de vidage des WA
#: replication/walsender.c:974
#, c-format
msgid "terminating walsender process after promotion"
-msgstr "arr�t du processus walreceiver suite promotion"
+msgstr "arrêt du processus walreceiver suite promotion"
#: replication/walsender.c:1300
#, c-format
msgid "received replication command: %s"
-msgstr "commande de r�plication re�u : %s"
+msgstr "commande de réplication reçu : %s"
-#: replication/walsender.c:1393 replication/walsender.c:1409
+#: replication/walsender.c:1391 replication/walsender.c:1407
#, c-format
msgid "unexpected EOF on standby connection"
msgstr "fin de fichier (EOF) inattendue de la connexion du serveur en attente"
-#: replication/walsender.c:1423
+#: replication/walsender.c:1421
#, c-format
msgid "unexpected standby message type \"%c\", after receiving CopyDone"
-msgstr "type de message standby � %c � inattendu, apr�s avoir re�u CopyDone"
+msgstr "type de message standby « %c » inattendu, après avoir reçu CopyDone"
-#: replication/walsender.c:1461
+#: replication/walsender.c:1459
#, c-format
msgid "invalid standby message type \"%c\""
-msgstr "type de message � %c � invalide pour le serveur en standby"
+msgstr "type de message « %c » invalide pour le serveur en standby"
-#: replication/walsender.c:1502
+#: replication/walsender.c:1500
#, c-format
msgid "unexpected message type \"%c\""
-msgstr "type de message � %c � inattendu"
+msgstr "type de message « %c » inattendu"
-#: replication/walsender.c:1786
+#: replication/walsender.c:1784
#, c-format
msgid "terminating walsender process due to replication timeout"
-msgstr "arr�t du processus walreceiver suite � l'expiration du d�lai de r�plication"
+msgstr "arrêt du processus walreceiver suite à l'expiration du délai de réplication"
-#: replication/walsender.c:1879
+#: replication/walsender.c:1877
#, c-format
msgid "standby \"%s\" has now caught up with primary"
-msgstr "le serveur standby � %s � a maintenant rattrap� le serveur primaire"
+msgstr "le serveur standby « %s » a maintenant rattrapé le serveur primaire"
-#: replication/walsender.c:1982
+#: replication/walsender.c:1980
#, c-format
msgid "number of requested standby connections exceeds max_wal_senders (currently %d)"
msgstr ""
-"le nombre de connexions demand�es par le serveur en attente d�passe\n"
+"le nombre de connexions demandées par le serveur en attente dépasse\n"
"max_wal_senders (actuellement %d)"
#: rewrite/rewriteDefine.c:112 rewrite/rewriteDefine.c:973
#, c-format
msgid "rule \"%s\" for relation \"%s\" already exists"
-msgstr "la r�gle � %s � existe d�j� pour la relation � %s �"
+msgstr "la règle « %s » existe déjà pour la relation « %s »"
#: rewrite/rewriteDefine.c:297
#, c-format
msgid "rule actions on OLD are not implemented"
-msgstr "les actions de la r�gle sur OLD ne sont pas impl�ment�es"
+msgstr "les actions de la règle sur OLD ne sont pas implémentées"
#: rewrite/rewriteDefine.c:298
#, c-format
msgid "Use views or triggers instead."
-msgstr "Utilisez � la place des vues ou des triggers."
+msgstr "Utilisez à la place des vues ou des triggers."
#: rewrite/rewriteDefine.c:302
#, c-format
msgid "rule actions on NEW are not implemented"
-msgstr "les actions de la r�gle sur NEW ne sont pas impl�ment�es"
+msgstr "les actions de la règle sur NEW ne sont pas implémentées"
#: rewrite/rewriteDefine.c:303
#, c-format
msgid "Use triggers instead."
-msgstr "Utilisez des triggers � la place."
+msgstr "Utilisez des triggers à la place."
#: rewrite/rewriteDefine.c:316
#, c-format
msgid "INSTEAD NOTHING rules on SELECT are not implemented"
-msgstr "les r�gles INSTEAD NOTHING sur SELECT ne sont pas impl�ment�es"
+msgstr "les règles INSTEAD NOTHING sur SELECT ne sont pas implémentées"
#: rewrite/rewriteDefine.c:317
#, c-format
msgid "Use views instead."
-msgstr "Utilisez les vues � la place."
+msgstr "Utilisez les vues à la place."
#: rewrite/rewriteDefine.c:325
#, c-format
msgid "multiple actions for rules on SELECT are not implemented"
-msgstr "les actions multiples pour les r�gles sur SELECT ne sont pas impl�ment�es"
+msgstr "les actions multiples pour les règles sur SELECT ne sont pas implémentées"
#: rewrite/rewriteDefine.c:336
#, c-format
msgid "rules on SELECT must have action INSTEAD SELECT"
-msgstr "les r�gles sur SELECT doivent avoir une action INSTEAD SELECT"
+msgstr "les règles sur SELECT doivent avoir une action INSTEAD SELECT"
#: rewrite/rewriteDefine.c:344
#, c-format
msgid "rules on SELECT must not contain data-modifying statements in WITH"
msgstr ""
-"les r�gles sur SELECT ne doivent pas contenir d'instructions de modification\n"
-"de donn�es avec WITH"
+"les règles sur SELECT ne doivent pas contenir d'instructions de modification\n"
+"de données avec WITH"
#: rewrite/rewriteDefine.c:352
#, c-format
msgid "event qualifications are not implemented for rules on SELECT"
msgstr ""
-"les qualifications d'�v�nements ne sont pas impl�ment�es pour les r�gles sur\n"
+"les qualifications d'événements ne sont pas implémentées pour les règles sur\n"
"SELECT"
#: rewrite/rewriteDefine.c:379
#, c-format
msgid "\"%s\" is already a view"
-msgstr "� %s � est d�j� une vue"
+msgstr "« %s » est déjà une vue"
#: rewrite/rewriteDefine.c:403
#, c-format
msgid "view rule for \"%s\" must be named \"%s\""
-msgstr "la r�gle de la vue pour � %s � doit �tre nomm�e � %s �"
+msgstr "la règle de la vue pour « %s » doit être nommée « %s »"
#: rewrite/rewriteDefine.c:432
#, c-format
msgid "could not convert table \"%s\" to a view because it is not empty"
-msgstr "n'a pas pu convertir la table � %s � en une vue car elle n'est pas vide"
+msgstr "n'a pas pu convertir la table « %s » en une vue car elle n'est pas vide"
#: rewrite/rewriteDefine.c:440
#, c-format
msgid "could not convert table \"%s\" to a view because it has triggers"
-msgstr "n'a pas pu convertir la table � %s � en une vue parce qu'elle a des triggers"
+msgstr "n'a pas pu convertir la table « %s » en une vue parce qu'elle a des triggers"
#: rewrite/rewriteDefine.c:442
#, c-format
msgid "In particular, the table cannot be involved in any foreign key relationships."
msgstr ""
-"En particulier, la table ne peut pas �tre impliqu�e dans les relations des\n"
-"cl�s �trang�res."
+"En particulier, la table ne peut pas être impliquée dans les relations des\n"
+"clés étrangères."
#: rewrite/rewriteDefine.c:447
#, c-format
msgid "could not convert table \"%s\" to a view because it has indexes"
-msgstr "n'a pas pu convertir la table � %s � en une vue parce qu'elle a des index"
+msgstr "n'a pas pu convertir la table « %s » en une vue parce qu'elle a des index"
#: rewrite/rewriteDefine.c:453
#, c-format
msgid "could not convert table \"%s\" to a view because it has child tables"
-msgstr "n'a pas pu convertir la table � %s � en une vue parce qu'elle a des tables filles"
+msgstr "n'a pas pu convertir la table « %s » en une vue parce qu'elle a des tables filles"
#: rewrite/rewriteDefine.c:459
#, c-format
msgid "could not convert table \"%s\" to a view because it has row security enabled"
-msgstr "n'a pas pu convertir la table � %s � en une vue parce que le mode s�curit� des lignes est activ� pour elle"
+msgstr "n'a pas pu convertir la table « %s » en une vue parce que le mode sécurité des lignes est activé pour elle"
#: rewrite/rewriteDefine.c:465
#, c-format
msgid "could not convert table \"%s\" to a view because it has row security policies"
-msgstr "n'a pas pu convertir la table � %s � en une vue parce qu'elle a des politiques de s�curit�"
+msgstr "n'a pas pu convertir la table « %s » en une vue parce qu'elle a des politiques de sécurité"
#: rewrite/rewriteDefine.c:492
#, c-format
msgid "cannot have multiple RETURNING lists in a rule"
-msgstr "ne peut pas avoir plusieurs listes RETURNING dans une r�gle"
+msgstr "ne peut pas avoir plusieurs listes RETURNING dans une règle"
#: rewrite/rewriteDefine.c:497
#, c-format
msgid "RETURNING lists are not supported in conditional rules"
-msgstr "les listes RETURNING ne sont pas support�s dans des r�gles conditionnelles"
+msgstr "les listes RETURNING ne sont pas supportés dans des règles conditionnelles"
#: rewrite/rewriteDefine.c:501
#, c-format
msgid "RETURNING lists are not supported in non-INSTEAD rules"
-msgstr "les listes RETURNING ne sont pas support�s dans des r�gles autres que INSTEAD"
+msgstr "les listes RETURNING ne sont pas supportés dans des règles autres que INSTEAD"
#: rewrite/rewriteDefine.c:667
#, c-format
msgid "SELECT rule's target list has too many entries"
-msgstr "la liste cible de la r�gle SELECT a trop d'entr�es"
+msgstr "la liste cible de la règle SELECT a trop d'entrées"
#: rewrite/rewriteDefine.c:668
#, c-format
msgid "RETURNING list has too many entries"
-msgstr "la liste RETURNING a trop d'entr�es"
+msgstr "la liste RETURNING a trop d'entrées"
#: rewrite/rewriteDefine.c:695
#, c-format
msgid "cannot convert relation containing dropped columns to view"
-msgstr "ne peut pas convertir la relation contenant les colonnes supprim�es de la vue"
+msgstr "ne peut pas convertir la relation contenant les colonnes supprimées de la vue"
#: rewrite/rewriteDefine.c:696
-#, fuzzy, c-format
-#| msgid "cannot convert relation containing dropped columns to view"
+#, c-format
msgid "cannot create a RETURNING list for a relation containing dropped columns"
-msgstr "ne peut pas convertir la relation contenant les colonnes supprim�es de la vue"
+msgstr "ne peut pas créer une liste RETURNING pour une relation contenant des colonnes supprimées"
#: rewrite/rewriteDefine.c:702
#, c-format
msgid "SELECT rule's target entry %d has different column name from column \"%s\""
-msgstr "l'entr�e cible de la r�gle SELECT %d a un nom de colonne diff�rent pour la colonne � %s �"
+msgstr "l'entrée cible de la règle SELECT %d a un nom de colonne différent pour la colonne « %s »"
#: rewrite/rewriteDefine.c:704
#, c-format
msgid "SELECT target entry is named \"%s\"."
-msgstr "l'entr�e cible de la r�gle SELECT est nomm� � %s �."
+msgstr "l'entrée cible de la règle SELECT est nommé « %s »."
#: rewrite/rewriteDefine.c:713
#, c-format
msgid "SELECT rule's target entry %d has different type from column \"%s\""
-msgstr "l'entr�e cible de la r�gle SELECT %d a plusieurs types pour la colonne � %s �"
+msgstr "l'entrée cible de la règle SELECT %d a plusieurs types pour la colonne « %s »"
#: rewrite/rewriteDefine.c:715
#, c-format
msgid "RETURNING list's entry %d has different type from column \"%s\""
-msgstr "l'entr�e %d de la liste RETURNING a un type diff�rent de la colonne � %s �"
+msgstr "l'entrée %d de la liste RETURNING a un type différent de la colonne « %s »"
#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:742
#, c-format
msgid "SELECT target entry has type %s, but column has type %s."
-msgstr "l'entr�e de la liste SELECT a le type %s alors que la colonne a le type %s."
+msgstr "l'entrée de la liste SELECT a le type %s alors que la colonne a le type %s."
#: rewrite/rewriteDefine.c:721 rewrite/rewriteDefine.c:746
#, c-format
msgid "RETURNING list entry has type %s, but column has type %s."
-msgstr "l'entr�e de la liste RETURNING a le type %s alors que la colonne a le type %s."
+msgstr "l'entrée de la liste RETURNING a le type %s alors que la colonne a le type %s."
#: rewrite/rewriteDefine.c:737
#, c-format
msgid "SELECT rule's target entry %d has different size from column \"%s\""
-msgstr "l'entr�e cible de la r�gle SELECT %d a plusieurs tailles pour la colonne � %s �"
+msgstr "l'entrée cible de la règle SELECT %d a plusieurs tailles pour la colonne « %s »"
#: rewrite/rewriteDefine.c:739
#, c-format
msgid "RETURNING list's entry %d has different size from column \"%s\""
-msgstr "l'entr�e %d de la liste RETURNING a plusieurs tailles pour la colonne � %s �"
+msgstr "l'entrée %d de la liste RETURNING a plusieurs tailles pour la colonne « %s »"
#: rewrite/rewriteDefine.c:756
#, c-format
msgid "SELECT rule's target list has too few entries"
-msgstr "l'entr�e cible de la r�gle SELECT n'a pas assez d'entr�es"
+msgstr "l'entrée cible de la règle SELECT n'a pas assez d'entrées"
#: rewrite/rewriteDefine.c:757
#, c-format
msgid "RETURNING list has too few entries"
-msgstr "la liste RETURNING n'a pas assez d'entr�es"
+msgstr "la liste RETURNING n'a pas assez d'entrées"
#: rewrite/rewriteDefine.c:849 rewrite/rewriteDefine.c:964 rewrite/rewriteSupport.c:112
#, c-format
msgid "rule \"%s\" for relation \"%s\" does not exist"
-msgstr "la r�gle � %s � de la relation � %s � n'existe pas"
+msgstr "la règle « %s » de la relation « %s » n'existe pas"
#: rewrite/rewriteDefine.c:983
#, c-format
msgid "renaming an ON SELECT rule is not allowed"
-msgstr "le renommage d'une r�gle ON SELECT n'est pas autoris�"
+msgstr "le renommage d'une règle ON SELECT n'est pas autorisé"
#: rewrite/rewriteHandler.c:528
#, c-format
msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten"
msgstr ""
-"Le nom de la requ�te WITH �%s � appara�t � la fois dans l'action d'une r�gle\n"
-"et la requ�te en cours de r�-�criture."
+"Le nom de la requête WITH «%s » apparaît à la fois dans l'action d'une règle\n"
+"et la requête en cours de ré-écriture."
#: rewrite/rewriteHandler.c:588
#, c-format
msgid "cannot have RETURNING lists in multiple rules"
-msgstr "ne peut pas avoir des listes RETURNING dans plusieurs r�gles"
+msgstr "ne peut pas avoir des listes RETURNING dans plusieurs règles"
#: rewrite/rewriteHandler.c:928 rewrite/rewriteHandler.c:946
#, c-format
msgid "multiple assignments to same column \"%s\""
-msgstr "affectations multiples pour la m�me colonne � %s �"
+msgstr "affectations multiples pour la même colonne « %s »"
#: rewrite/rewriteHandler.c:1721 rewrite/rewriteHandler.c:3331
#, c-format
msgid "infinite recursion detected in rules for relation \"%s\""
-msgstr "r�cursion infinie d�tect�e dans les r�gles de la relation � %s �"
+msgstr "récursion infinie détectée dans les règles de la relation « %s »"
#: rewrite/rewriteHandler.c:1806
#, c-format
msgid "infinite recursion detected in policy for relation \"%s\""
-msgstr "r�cursion infinie d�tect�e dans la politique pour la relation � %s �"
+msgstr "récursion infinie détectée dans la politique pour la relation « %s »"
#: rewrite/rewriteHandler.c:2123
msgid "Junk view columns are not updatable."
-msgstr "Les colonnes � junk � des vues ne sont pas automatiquement disponibles en �criture."
+msgstr "Les colonnes « junk » des vues ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2128
msgid "View columns that are not columns of their base relation are not updatable."
-msgstr "Les colonnes des vues qui ne font pas r�f�rence � des colonnes de la relation de base ne sont pas automatiquement modifiables."
+msgstr "Les colonnes des vues qui ne font pas référence à des colonnes de la relation de base ne sont pas automatiquement modifiables."
#: rewrite/rewriteHandler.c:2131
msgid "View columns that refer to system columns are not updatable."
-msgstr "Les colonnes des vues qui font r�f�rence � des colonnes syst�mes ne sont pas automatiquement modifiables."
+msgstr "Les colonnes des vues qui font référence à des colonnes systèmes ne sont pas automatiquement modifiables."
#: rewrite/rewriteHandler.c:2134
msgid "View columns that return whole-row references are not updatable."
-msgstr "Les colonnes de vue qui font r�f�rences � des lignes compl�tes ne sont pas automatiquement modifiables."
+msgstr "Les colonnes de vue qui font références à des lignes complètes ne sont pas automatiquement modifiables."
#: rewrite/rewriteHandler.c:2192
msgid "Views containing DISTINCT are not automatically updatable."
-msgstr "Les vues contenant DISTINCT ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant DISTINCT ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2195
msgid "Views containing GROUP BY are not automatically updatable."
-msgstr "Les vues contenant GROUP BY ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant GROUP BY ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2198
msgid "Views containing HAVING are not automatically updatable."
-msgstr "Les vues contenant HAVING ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant HAVING ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2201
msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable."
-msgstr "Les vues contenant UNION, INTERSECT ou EXCEPT ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant UNION, INTERSECT ou EXCEPT ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2204
msgid "Views containing WITH are not automatically updatable."
-msgstr "Les vues contenant WITH ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant WITH ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2207
msgid "Views containing LIMIT or OFFSET are not automatically updatable."
-msgstr "Les vues contenant LIMIT ou OFFSET ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant LIMIT ou OFFSET ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2219
msgid "Views that return aggregate functions are not automatically updatable."
-msgstr "Les vues qui renvoient des fonctions d'agr�gat ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues qui renvoient des fonctions d'agrégat ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2222
msgid "Views that return window functions are not automatically updatable."
-msgstr "Les vues qui renvoient des fonctions de fen�trage ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues qui renvoient des fonctions de fenêtrage ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2225
msgid "Views that return set-returning functions are not automatically updatable."
-msgstr "Les vues qui renvoient des fonctions � plusieurs lignes ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues qui renvoient des fonctions à plusieurs lignes ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2232 rewrite/rewriteHandler.c:2236 rewrite/rewriteHandler.c:2243
msgid "Views that do not select from a single table or view are not automatically updatable."
-msgstr "Les vues qui lisent plusieurs tables ou vues ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues qui lisent plusieurs tables ou vues ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2246
msgid "Views containing TABLESAMPLE are not automatically updatable."
-msgstr "Les vues contenant TABLESAMPLE ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues contenant TABLESAMPLE ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2270
msgid "Views that have no updatable columns are not automatically updatable."
-msgstr "Les vues qui poss�dent des colonnes non modifiables ne sont pas automatiquement disponibles en �criture."
+msgstr "Les vues qui possèdent des colonnes non modifiables ne sont pas automatiquement disponibles en écriture."
#: rewrite/rewriteHandler.c:2724
#, c-format
msgid "cannot insert into column \"%s\" of view \"%s\""
-msgstr "ne peut pas ins�rer dans la colonne � %s � de la vue � %s �"
+msgstr "ne peut pas insérer dans la colonne « %s » de la vue « %s »"
#: rewrite/rewriteHandler.c:2732
#, c-format
msgid "cannot update column \"%s\" of view \"%s\""
-msgstr "ne peut pas mettre � jour la colonne � %s � de la vue � %s �"
+msgstr "ne peut pas mettre à jour la colonne « %s » de la vue « %s »"
#: rewrite/rewriteHandler.c:3130
#, c-format
msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH"
msgstr ""
-"les r�gles DO INSTEAD NOTHING ne sont pas support�es par les instructions\n"
-"de modification de donn�es dans WITH"
+"les règles DO INSTEAD NOTHING ne sont pas supportées par les instructions\n"
+"de modification de données dans WITH"
#: rewrite/rewriteHandler.c:3144
#, c-format
msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH"
msgstr ""
-"les r�gles DO INSTEAD conditionnelles ne sont pas support�es par les\n"
-"instructions de modification de donn�es dans WITH"
+"les règles DO INSTEAD conditionnelles ne sont pas supportées par les\n"
+"instructions de modification de données dans WITH"
#: rewrite/rewriteHandler.c:3148
#, c-format
msgid "DO ALSO rules are not supported for data-modifying statements in WITH"
msgstr ""
-"les r�gles DO ALSO ne sont pas support�es par les instructions de modification\n"
-"de donn�es dans WITH"
+"les règles DO ALSO ne sont pas supportées par les instructions de modification\n"
+"de données dans WITH"
#: rewrite/rewriteHandler.c:3153
#, c-format
msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH"
msgstr ""
-"les r�gles DO INSTEAD multi-instructions ne sont pas support�es pour les\n"
-"instructions de modification de donn�es dans WITH"
+"les règles DO INSTEAD multi-instructions ne sont pas supportées pour les\n"
+"instructions de modification de données dans WITH"
#: rewrite/rewriteHandler.c:3368
#, c-format
msgid "cannot perform INSERT RETURNING on relation \"%s\""
-msgstr "ne peut pas ex�cuter INSERT RETURNING sur la relation � %s �"
+msgstr "ne peut pas exécuter INSERT RETURNING sur la relation « %s »"
#: rewrite/rewriteHandler.c:3370
#, c-format
msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause."
msgstr ""
-"Vous avez besoin d'une r�gle ON INSERT DO INSTEAD sans condition avec une\n"
+"Vous avez besoin d'une règle ON INSERT DO INSTEAD sans condition avec une\n"
"clause RETURNING."
#: rewrite/rewriteHandler.c:3375
#, c-format
msgid "cannot perform UPDATE RETURNING on relation \"%s\""
-msgstr "ne peut pas ex�cuter UPDATE RETURNING sur la relation � %s �"
+msgstr "ne peut pas exécuter UPDATE RETURNING sur la relation « %s »"
#: rewrite/rewriteHandler.c:3377
#, c-format
msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause."
msgstr ""
-"Vous avez besoin d'une r�gle ON UPDATE DO INSTEAD sans condition avec une\n"
+"Vous avez besoin d'une règle ON UPDATE DO INSTEAD sans condition avec une\n"
"clause RETURNING."
#: rewrite/rewriteHandler.c:3382
#, c-format
msgid "cannot perform DELETE RETURNING on relation \"%s\""
-msgstr "ne peut pas ex�cuter DELETE RETURNING sur la relation � %s �"
+msgstr "ne peut pas exécuter DELETE RETURNING sur la relation « %s »"
#: rewrite/rewriteHandler.c:3384
#, c-format
msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause."
msgstr ""
-"Vous avez besoin d'une r�gle ON DELETE DO INSTEAD sans condition avec une\n"
+"Vous avez besoin d'une règle ON DELETE DO INSTEAD sans condition avec une\n"
"clause RETURNING."
#: rewrite/rewriteHandler.c:3402
#, c-format
msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules"
-msgstr "INSERT avec une clause ON CONFLICT ne peut pas �tre utilis�e avec une table qui a des r�gles pour INSERT ou UPDATE"
+msgstr "INSERT avec une clause ON CONFLICT ne peut pas être utilisée avec une table qui a des règles pour INSERT ou UPDATE"
#: rewrite/rewriteHandler.c:3459
#, c-format
msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries"
-msgstr "WITH ne peut pas �tre utilis� dans une requ�te r��crite par des r�gles en plusieurs requ�tes"
+msgstr "WITH ne peut pas être utilisé dans une requête réécrite par des règles en plusieurs requêtes"
#: rewrite/rewriteManip.c:1003
#, c-format
msgid "conditional utility statements are not implemented"
-msgstr "les instructions conditionnelles ne sont pas impl�ment�es"
+msgstr "les instructions conditionnelles ne sont pas implémentées"
#: rewrite/rewriteManip.c:1169
#, c-format
msgid "WHERE CURRENT OF on a view is not implemented"
-msgstr "WHERE CURRENT OF n'est pas impl�ment� sur une vue"
+msgstr "WHERE CURRENT OF n'est pas implémenté sur une vue"
#: rewrite/rewriteManip.c:1434
#, c-format
msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command"
-msgstr "les variables NEW des r�gles ON UPDATE ne peuvent pas r�f�rencer des colonnes faisant partie d'une affectation multiple dans une commande UPDATE"
+msgstr "les variables NEW des règles ON UPDATE ne peuvent pas référencer des colonnes faisant partie d'une affectation multiple dans une commande UPDATE"
#: rewrite/rewriteSupport.c:154
#, c-format
msgid "rule \"%s\" does not exist"
-msgstr "la r�gle � %s � n'existe pas"
+msgstr "la règle « %s » n'existe pas"
#: rewrite/rewriteSupport.c:167
#, c-format
msgid "there are multiple rules named \"%s\""
-msgstr "il existe de nombreuses r�gles nomm�es � %s �"
+msgstr "il existe de nombreuses règles nommées « %s »"
#: rewrite/rewriteSupport.c:168
#, c-format
msgid "Specify a relation name as well as a rule name."
-msgstr "Sp�cifier un nom de relation ainsi qu'un nom de r�gle."
+msgstr "Spécifier un nom de relation ainsi qu'un nom de règle."
-#: scan.l:433
+#: scan.l:432
msgid "unterminated /* comment"
-msgstr "commentaire /* non termin�"
+msgstr "commentaire /* non terminé"
-#: scan.l:462
+#: scan.l:461
msgid "unterminated bit string literal"
-msgstr "cha�ne litt�rale bit non termin�e"
+msgstr "chaîne littérale bit non terminée"
-#: scan.l:483
+#: scan.l:482
msgid "unterminated hexadecimal string literal"
-msgstr "cha�ne litt�rale hexad�cimale non termin�e"
+msgstr "chaîne littérale hexadécimale non terminée"
-#: scan.l:533
+#: scan.l:532
#, c-format
msgid "unsafe use of string constant with Unicode escapes"
-msgstr "utilisation non s�re de la constante de cha�ne avec des �chappements Unicode"
+msgstr "utilisation non sûre de la constante de chaîne avec des échappements Unicode"
-#: scan.l:534
+#: scan.l:533
#, c-format
msgid "String constants with Unicode escapes cannot be used when standard_conforming_strings is off."
msgstr ""
-"Les constantes de cha�ne avec des �chappements Unicode ne peuvent pas �tre\n"
-"utilis�es quand standard_conforming_strings est d�sactiv�."
+"Les constantes de chaîne avec des échappements Unicode ne peuvent pas être\n"
+"utilisées quand standard_conforming_strings est désactivé."
-#: scan.l:580 scan.l:779
+#: scan.l:579 scan.l:778
msgid "invalid Unicode escape character"
-msgstr "cha�ne d'�chappement Unicode invalide"
+msgstr "chaîne d'échappement Unicode invalide"
-#: scan.l:606 scan.l:614 scan.l:622 scan.l:623 scan.l:624 scan.l:1338 scan.l:1365 scan.l:1369 scan.l:1407 scan.l:1411 scan.l:1433
+#: scan.l:605 scan.l:613 scan.l:621 scan.l:622 scan.l:623 scan.l:1337 scan.l:1364 scan.l:1368 scan.l:1406 scan.l:1410 scan.l:1432 scan.l:1442
msgid "invalid Unicode surrogate pair"
msgstr "paire surrogate Unicode invalide"
-#: scan.l:628
+#: scan.l:627
#, c-format
msgid "invalid Unicode escape"
-msgstr "�chappement Unicode invalide"
+msgstr "échappement Unicode invalide"
-#: scan.l:629
+#: scan.l:628
#, c-format
msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX."
-msgstr "Les �chappements Unicode doivent �tre de la forme \\uXXXX ou \\UXXXXXXXX."
+msgstr "Les échappements Unicode doivent être de la forme \\uXXXX ou \\UXXXXXXXX."
-#: scan.l:640
+#: scan.l:639
#, c-format
msgid "unsafe use of \\' in a string literal"
-msgstr "utilisation non s�re de \\' dans une cha�ne litt�rale"
+msgstr "utilisation non sûre de \\' dans une chaîne littérale"
-#: scan.l:641
+#: scan.l:640
#, c-format
msgid "Use '' to write quotes in strings. \\' is insecure in client-only encodings."
msgstr ""
-"Utilisez '' pour �crire des guillemets dans une cha�ne. \\' n'est pas s�curis�\n"
+"Utilisez '' pour écrire des guillemets dans une chaîne. \\' n'est pas sécurisé\n"
"pour les encodages clients."
-#: scan.l:716
+#: scan.l:715
msgid "unterminated dollar-quoted string"
-msgstr "cha�ne entre guillemets dollars non termin�e"
+msgstr "chaîne entre guillemets dollars non terminée"
-#: scan.l:733 scan.l:759 scan.l:774
+#: scan.l:732 scan.l:758 scan.l:773
msgid "zero-length delimited identifier"
-msgstr "identifiant d�limit� de longueur nulle"
+msgstr "identifiant délimité de longueur nulle"
-#: scan.l:794 syncrep_scanner.l:84
+#: scan.l:793 syncrep_scanner.l:84
msgid "unterminated quoted identifier"
-msgstr "identifiant entre guillemets non termin�"
+msgstr "identifiant entre guillemets non terminé"
-#: scan.l:925
+#: scan.l:924
msgid "operator too long"
-msgstr "op�rateur trop long"
+msgstr "opérateur trop long"
#. translator: %s is typically the translation of "syntax error"
-#: scan.l:1078
+#: scan.l:1077
#, c-format
msgid "%s at end of input"
-msgstr "%s � la fin de l'entr�e"
+msgstr "%s à la fin de l'entrée"
#. translator: first %s is typically the translation of "syntax error"
-#: scan.l:1086
+#: scan.l:1085
#, c-format
msgid "%s at or near \"%s\""
-msgstr "%s sur ou pr�s de � %s �"
+msgstr "%s sur ou près de « %s »"
-#: scan.l:1252 scan.l:1284
+#: scan.l:1251 scan.l:1283
msgid "Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8"
msgstr ""
-"Les valeurs d'�chappement unicode ne peuvent pas �tre utilis�es pour les\n"
+"Les valeurs d'échappement unicode ne peuvent pas être utilisées pour les\n"
"valeurs de point de code au-dessus de 007F quand l'encodage serveur n'est\n"
"pas UTF8"
-#: scan.l:1280 scan.l:1425
+#: scan.l:1279 scan.l:1424
msgid "invalid Unicode escape value"
-msgstr "valeur d'�chappement Unicode invalide"
+msgstr "valeur d'échappement Unicode invalide"
-#: scan.l:1482
+#: scan.l:1488
#, c-format
msgid "nonstandard use of \\' in a string literal"
-msgstr "utilisation non standard de \\' dans une cha�ne litt�rale"
+msgstr "utilisation non standard de \\' dans une chaîne littérale"
-#: scan.l:1483
+#: scan.l:1489
#, c-format
msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')."
msgstr ""
-"Utilisez '' pour �crire des guillemets dans une cha�ne ou utilisez la syntaxe de\n"
-"cha�ne d'�chappement (E'...')."
+"Utilisez '' pour écrire des guillemets dans une chaîne ou utilisez la syntaxe de\n"
+"chaîne d'échappement (E'...')."
-#: scan.l:1492
+#: scan.l:1498
#, c-format
msgid "nonstandard use of \\\\ in a string literal"
-msgstr "utilisation non standard de \\\\ dans une cha�ne litt�rale"
+msgstr "utilisation non standard de \\\\ dans une chaîne littérale"
-#: scan.l:1493
+#: scan.l:1499
#, c-format
msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'."
-msgstr "Utilisez la syntaxe de cha�ne d'�chappement pour les antislashs, c'est-�-dire E'\\\\'."
+msgstr "Utilisez la syntaxe de chaîne d'échappement pour les antislashs, c'est-à-dire E'\\\\'."
-#: scan.l:1507
+#: scan.l:1513
#, c-format
msgid "nonstandard use of escape in a string literal"
-msgstr "utilisation non standard d'un �chappement dans une cha�ne litt�rale"
+msgstr "utilisation non standard d'un échappement dans une chaîne littérale"
-#: scan.l:1508
+#: scan.l:1514
#, c-format
msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'."
msgstr ""
-"Utilisez la syntaxe de la cha�ne d'�chappement pour les �chappements,\n"
-"c'est-�-dire E'\\r\\n'."
+"Utilisez la syntaxe de la chaîne d'échappement pour les échappements,\n"
+"c'est-à-dire E'\\r\\n'."
#: snowball/dict_snowball.c:177
#, c-format
msgid "no Snowball stemmer available for language \"%s\" and encoding \"%s\""
-msgstr "aucun stemmer Snowball disponible pour la langue � %s � et l'encodage � %s �"
+msgstr "aucun stemmer Snowball disponible pour la langue « %s » et l'encodage « %s »"
#: snowball/dict_snowball.c:200 tsearch/dict_ispell.c:73 tsearch/dict_simple.c:48
#, c-format
msgid "multiple StopWords parameters"
-msgstr "plusieurs param�tres StopWords"
+msgstr "plusieurs paramètres StopWords"
#: snowball/dict_snowball.c:209
#, c-format
msgid "multiple Language parameters"
-msgstr "multiples param�tres Language"
+msgstr "multiples paramètres Language"
#: snowball/dict_snowball.c:216
#, c-format
msgid "unrecognized Snowball parameter: \"%s\""
-msgstr "param�tre Snowball non reconnu : � %s �"
+msgstr "paramètre Snowball non reconnu : « %s »"
#: snowball/dict_snowball.c:224
#, c-format
msgid "missing Language parameter"
-msgstr "param�tre Language manquant"
+msgstr "paramètre Language manquant"
#: storage/buffer/bufmgr.c:544 storage/buffer/bufmgr.c:657
#, c-format
msgid "cannot access temporary tables of other sessions"
-msgstr "ne peut pas acc�der aux tables temporaires d'autres sessions"
+msgstr "ne peut pas accéder aux tables temporaires d'autres sessions"
#: storage/buffer/bufmgr.c:807
#, c-format
msgid "unexpected data beyond EOF in block %u of relation %s"
msgstr ""
-"donn�es inattendues apr�s la fin de fichier dans le bloc %u de la relation\n"
+"données inattendues après la fin de fichier dans le bloc %u de la relation\n"
"%s"
#: storage/buffer/bufmgr.c:809
#, c-format
msgid "This has been seen to occur with buggy kernels; consider updating your system."
msgstr ""
-"Ceci s'est d�j� vu avec des noyaux bugg�s ; pensez � mettre � jour votre\n"
-"syst�me."
+"Ceci s'est déjà vu avec des noyaux buggés ; pensez à mettre à jour votre\n"
+"système."
#: storage/buffer/bufmgr.c:907
#, c-format
msgid "invalid page in block %u of relation %s; zeroing out page"
-msgstr "page invalide dans le bloc %u de la relation %s ; remplacement de la page par des z�ros"
+msgstr "page invalide dans le bloc %u de la relation %s ; remplacement de la page par des zéros"
#: storage/buffer/bufmgr.c:3952
#, c-format
msgid "could not write block %u of %s"
-msgstr "n'a pas pu �crire le bloc %u de %s"
+msgstr "n'a pas pu écrire le bloc %u de %s"
#: storage/buffer/bufmgr.c:3954
#, c-format
msgid "Multiple failures --- write error might be permanent."
-msgstr "�checs multiples --- l'erreur d'�criture pourrait �tre permanent."
+msgstr "Échecs multiples --- l'erreur d'écriture pourrait être permanent."
#: storage/buffer/bufmgr.c:3975 storage/buffer/bufmgr.c:3994
#, c-format
msgid "writing block %u of relation %s"
-msgstr "�criture du bloc %u de la relation %s"
+msgstr "écriture du bloc %u de la relation %s"
-#: storage/buffer/bufmgr.c:4298
+#: storage/buffer/bufmgr.c:4295
#, c-format
msgid "snapshot too old"
msgstr "snapshot trop ancien"
-#: storage/buffer/localbuf.c:198
+#: storage/buffer/localbuf.c:199
#, c-format
msgid "no empty local buffer available"
msgstr "aucun tampon local vide disponible"
+#: storage/buffer/localbuf.c:427
+#, c-format
+msgid "cannot access temporary tables during a parallel operation"
+msgstr "ne peut pas accéder à des tables temporaires pendant une opération parallèle"
+
#: storage/file/fd.c:436 storage/file/fd.c:508 storage/file/fd.c:544
#, c-format
msgid "could not flush dirty data: %m"
-msgstr "n'a pas pu vider les donn�es modifi�es : %m"
+msgstr "n'a pas pu vider les données modifiées : %m"
#: storage/file/fd.c:466
#, c-format
msgid "could not determine dirty data size: %m"
-msgstr "n'a pas pu d�terminer la taille des donn�es modifi�es : %m"
+msgstr "n'a pas pu déterminer la taille des données modifiées : %m"
#: storage/file/fd.c:518
-#, fuzzy, c-format
-#| msgid "could not uncompress data: %s\n"
+#, c-format
msgid "could not munmap() while flushing data: %m"
-msgstr "n'a pas pu d�compresser les donn�es : %s\n"
+msgstr "n'a pas exécuter munmap() durant la synchronisation des données : %m"
#: storage/file/fd.c:682
#, c-format
msgid "could not link file \"%s\" to \"%s\": %m"
-msgstr "n'a pas pu lier le fichier � %s � � � %s � : %m"
+msgstr "n'a pas pu lier le fichier « %s » à « %s » : %m"
#: storage/file/fd.c:776
#, c-format
msgid "getrlimit failed: %m"
-msgstr "�chec de getrlimit : %m"
+msgstr "échec de getrlimit : %m"
#: storage/file/fd.c:866
#, c-format
@@ -16784,159 +16795,159 @@ msgstr "nombre de descripteurs de fichier insuffisants pour lancer le processus
#: storage/file/fd.c:867
#, c-format
msgid "System allows %d, we need at least %d."
-msgstr "Le syst�me autorise %d, nous avons besoin d'au moins %d."
+msgstr "Le système autorise %d, nous avons besoin d'au moins %d."
#: storage/file/fd.c:908 storage/file/fd.c:2001 storage/file/fd.c:2094 storage/file/fd.c:2242
#, c-format
msgid "out of file descriptors: %m; release and retry"
-msgstr "plus de descripteurs de fichiers : %m; quittez et r�-essayez"
+msgstr "plus de descripteurs de fichiers : %m; quittez et ré-essayez"
#: storage/file/fd.c:1482
#, c-format
msgid "temporary file: path \"%s\", size %lu"
-msgstr "fichier temporaire : chemin � %s �, taille %lu"
+msgstr "fichier temporaire : chemin « %s », taille %lu"
#: storage/file/fd.c:1656
#, c-format
msgid "temporary file size exceeds temp_file_limit (%dkB)"
-msgstr "la taille du fichier temporaire d�passe temp_file_limit (%d Ko)"
+msgstr "la taille du fichier temporaire dépasse temp_file_limit (%d Ko)"
#: storage/file/fd.c:1977 storage/file/fd.c:2027
#, c-format
msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\""
-msgstr "d�passement de maxAllocatedDescs (%d) lors de la tentative d'ouverture du fichier � %s �"
+msgstr "dépassement de maxAllocatedDescs (%d) lors de la tentative d'ouverture du fichier « %s »"
#: storage/file/fd.c:2067
#, c-format
msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\""
-msgstr "d�passement de maxAllocatedDescs (%d) lors de la tentative d'ex�cution de la commande � %s �"
+msgstr "dépassement de maxAllocatedDescs (%d) lors de la tentative d'exécution de la commande « %s »"
#: storage/file/fd.c:2218
#, c-format
msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\""
-msgstr "d�passement de maxAllocatedDescs (%d) lors de la tentative d'ouverture du r�pertoire � %s �"
+msgstr "dépassement de maxAllocatedDescs (%d) lors de la tentative d'ouverture du répertoire « %s »"
#: storage/file/fd.c:2304
#, c-format
msgid "could not read directory \"%s\": %m"
-msgstr "n'a pas pu lire le r�pertoire � %s � : %m"
+msgstr "n'a pas pu lire le répertoire « %s » : %m"
#: storage/ipc/dsm.c:363
#, c-format
msgid "dynamic shared memory control segment is corrupt"
-msgstr "le segment contr�le de m�moire partag�e dynamique est corrompu"
+msgstr "le segment contrôle de mémoire partagée dynamique est corrompu"
#: storage/ipc/dsm.c:410
#, c-format
msgid "dynamic shared memory is disabled"
-msgstr "la m�moire partag�e dynamique est d�sactiv�e"
+msgstr "la mémoire partagée dynamique est désactivée"
#: storage/ipc/dsm.c:411
#, c-format
msgid "Set dynamic_shared_memory_type to a value other than \"none\"."
-msgstr "Configurez dynamic_shared_memory_type � une valeur autre que � none �."
+msgstr "Configurez dynamic_shared_memory_type à une valeur autre que « none »."
#: storage/ipc/dsm.c:431
#, c-format
msgid "dynamic shared memory control segment is not valid"
-msgstr "le segment contr�le de m�moire partag�e dynamique n'est pas valide"
+msgstr "le segment contrôle de mémoire partagée dynamique n'est pas valide"
#: storage/ipc/dsm.c:516
#, c-format
msgid "too many dynamic shared memory segments"
-msgstr "trop de segments de m�moire partag�e dynamique"
+msgstr "trop de segments de mémoire partagée dynamique"
-#: storage/ipc/dsm_impl.c:261 storage/ipc/dsm_impl.c:361 storage/ipc/dsm_impl.c:533 storage/ipc/dsm_impl.c:648 storage/ipc/dsm_impl.c:811 storage/ipc/dsm_impl.c:953
+#: storage/ipc/dsm_impl.c:261 storage/ipc/dsm_impl.c:361 storage/ipc/dsm_impl.c:533 storage/ipc/dsm_impl.c:648 storage/ipc/dsm_impl.c:819 storage/ipc/dsm_impl.c:961
#, c-format
msgid "could not unmap shared memory segment \"%s\": %m"
-msgstr "n'a pas pu annuler le mappage du segment de m�moire partag�e � %s � : %m"
+msgstr "n'a pas pu annuler le mappage du segment de mémoire partagée « %s » : %m"
-#: storage/ipc/dsm_impl.c:271 storage/ipc/dsm_impl.c:543 storage/ipc/dsm_impl.c:658 storage/ipc/dsm_impl.c:821
+#: storage/ipc/dsm_impl.c:271 storage/ipc/dsm_impl.c:543 storage/ipc/dsm_impl.c:658 storage/ipc/dsm_impl.c:829
#, c-format
msgid "could not remove shared memory segment \"%s\": %m"
-msgstr "n'a pas pu supprimer le segment de m�moire partag�e � %s � : %m"
+msgstr "n'a pas pu supprimer le segment de mémoire partagée « %s » : %m"
-#: storage/ipc/dsm_impl.c:292 storage/ipc/dsm_impl.c:721 storage/ipc/dsm_impl.c:835
+#: storage/ipc/dsm_impl.c:292 storage/ipc/dsm_impl.c:729 storage/ipc/dsm_impl.c:843
#, c-format
msgid "could not open shared memory segment \"%s\": %m"
-msgstr "n'a pas pu ouvrir le segment de m�moire partag�e � %s � : %m"
+msgstr "n'a pas pu ouvrir le segment de mémoire partagée « %s » : %m"
-#: storage/ipc/dsm_impl.c:316 storage/ipc/dsm_impl.c:559 storage/ipc/dsm_impl.c:766 storage/ipc/dsm_impl.c:859
+#: storage/ipc/dsm_impl.c:316 storage/ipc/dsm_impl.c:559 storage/ipc/dsm_impl.c:774 storage/ipc/dsm_impl.c:867
#, c-format
msgid "could not stat shared memory segment \"%s\": %m"
-msgstr "n'a pas pu obtenir des informations sur le segment de m�moire partag�e � %s � : %m"
+msgstr "n'a pas pu obtenir des informations sur le segment de mémoire partagée « %s » : %m"
-#: storage/ipc/dsm_impl.c:335 storage/ipc/dsm_impl.c:878 storage/ipc/dsm_impl.c:926
+#: storage/ipc/dsm_impl.c:335 storage/ipc/dsm_impl.c:886 storage/ipc/dsm_impl.c:934
#, c-format
msgid "could not resize shared memory segment \"%s\" to %zu bytes: %m"
-msgstr "n'a pas pu retailler le segment de m�moire partag�e � %s � en %zu octets : %m"
+msgstr "n'a pas pu retailler le segment de mémoire partagée « %s » en %zu octets : %m"
-#: storage/ipc/dsm_impl.c:385 storage/ipc/dsm_impl.c:580 storage/ipc/dsm_impl.c:742 storage/ipc/dsm_impl.c:977
+#: storage/ipc/dsm_impl.c:385 storage/ipc/dsm_impl.c:580 storage/ipc/dsm_impl.c:750 storage/ipc/dsm_impl.c:985
#, c-format
msgid "could not map shared memory segment \"%s\": %m"
-msgstr "n'a pas pu mapper le segment de m�moire partag�e � %s � : %m"
+msgstr "n'a pas pu mapper le segment de mémoire partagée « %s » : %m"
#: storage/ipc/dsm_impl.c:515
#, c-format
msgid "could not get shared memory segment: %m"
-msgstr "n'a pas pu obtenir le segment de m�moire partag�e : %m"
+msgstr "n'a pas pu obtenir le segment de mémoire partagée : %m"
-#: storage/ipc/dsm_impl.c:694
+#: storage/ipc/dsm_impl.c:714
#, c-format
msgid "could not create shared memory segment \"%s\": %m"
-msgstr "n'a pas pu cr�er le segment de m�moire partag�e � %s � : %m"
+msgstr "n'a pas pu créer le segment de mémoire partagée « %s » : %m"
-#: storage/ipc/dsm_impl.c:1018
+#: storage/ipc/dsm_impl.c:1026
#, c-format
msgid "could not duplicate handle for \"%s\": %m"
-msgstr "n'a pas pu dupliquer le lien pour � %s � : %m"
+msgstr "n'a pas pu dupliquer le lien pour « %s » : %m"
-#: storage/ipc/latch.c:769
+#: storage/ipc/latch.c:778
#, c-format
msgid "epoll_ctl() failed: %m"
-msgstr "�chec de epoll_ctl() : %m"
+msgstr "échec de epoll_ctl() : %m"
-#: storage/ipc/latch.c:993
+#: storage/ipc/latch.c:1002
#, c-format
msgid "epoll_wait() failed: %m"
-msgstr "�chec de epoll_wait() : %m"
+msgstr "échec de epoll_wait() : %m"
-#: storage/ipc/latch.c:1113
+#: storage/ipc/latch.c:1122
#, c-format
msgid "poll() failed: %m"
-msgstr "�chec de poll() : %m"
+msgstr "échec de poll() : %m"
-#: storage/ipc/shm_toc.c:108 storage/ipc/shm_toc.c:189 storage/ipc/shmem.c:212 storage/lmgr/lock.c:883 storage/lmgr/lock.c:917 storage/lmgr/lock.c:2682 storage/lmgr/lock.c:4007 storage/lmgr/lock.c:4072 storage/lmgr/lock.c:4364 storage/lmgr/predicate.c:2329 storage/lmgr/predicate.c:2344 storage/lmgr/predicate.c:3736 storage/lmgr/predicate.c:4879 storage/lmgr/proc.c:203 utils/hash/dynahash.c:1045
+#: storage/ipc/shm_toc.c:108 storage/ipc/shm_toc.c:189 storage/ipc/shmem.c:212 storage/lmgr/lock.c:883 storage/lmgr/lock.c:917 storage/lmgr/lock.c:2682 storage/lmgr/lock.c:4007 storage/lmgr/lock.c:4072 storage/lmgr/lock.c:4364 storage/lmgr/predicate.c:2329 storage/lmgr/predicate.c:2344 storage/lmgr/predicate.c:3736 storage/lmgr/predicate.c:4879 storage/lmgr/proc.c:203 utils/hash/dynahash.c:1043
#, c-format
msgid "out of shared memory"
-msgstr "m�moire partag�e �puis�e"
+msgstr "mémoire partagée épuisée"
#: storage/ipc/shmem.c:370 storage/ipc/shmem.c:421
#, c-format
msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)"
-msgstr "pas assez de m�moire partag�e pour la structure de donn�es � %s � (%zu octets demand�s)"
+msgstr "pas assez de mémoire partagée pour la structure de données « %s » (%zu octets demandés)"
#: storage/ipc/shmem.c:389
#, c-format
msgid "could not create ShmemIndex entry for data structure \"%s\""
-msgstr "n'a pas pu cr�er l'entr�e ShmemIndex pour la structure de donn�es � %s �"
+msgstr "n'a pas pu créer l'entrée ShmemIndex pour la structure de données « %s »"
#: storage/ipc/shmem.c:404
#, c-format
msgid "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, actual %zu"
-msgstr "La taille de l'entr�e ShmemIndex est mauvaise pour la structure de donn�es � %s � : %zu attendu, %zu obtenu"
+msgstr "La taille de l'entrée ShmemIndex est mauvaise pour la structure de données « %s » : %zu attendu, %zu obtenu"
#: storage/ipc/shmem.c:452 storage/ipc/shmem.c:471
#, c-format
msgid "requested shared memory size overflows size_t"
-msgstr "la taille de la m�moire partag�e demand�e d�passe size_t"
+msgstr "la taille de la mémoire partagée demandée dépasse size_t"
-#: storage/ipc/standby.c:527 tcop/postgres.c:2963
+#: storage/ipc/standby.c:530 tcop/postgres.c:2976
#, c-format
msgid "canceling statement due to conflict with recovery"
-msgstr "annulation de la requ�te � cause d'un conflit avec la restauration"
+msgstr "annulation de la requête à cause d'un conflit avec la restauration"
-#: storage/ipc/standby.c:528 tcop/postgres.c:2265
+#: storage/ipc/standby.c:531 tcop/postgres.c:2263
#, c-format
msgid "User transaction caused buffer deadlock with recovery."
msgstr "La transaction de l'utilisateur causait un verrou mortel lors de la restauration."
@@ -16944,27 +16955,27 @@ msgstr "La transaction de l'utilisateur causait un verrou mortel lors de la rest
#: storage/large_object/inv_api.c:203
#, c-format
msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d"
-msgstr "l'entr�e du Large Object d'OID %u, en page %d, a une taille de champ de donn�es invalide, %d"
+msgstr "l'entrée du Large Object d'OID %u, en page %d, a une taille de champ de données invalide, %d"
#: storage/large_object/inv_api.c:284
#, c-format
msgid "invalid flags for opening a large object: %d"
-msgstr "drapeaux invalides pour l'ouverture d'un � Large Object � : %d"
+msgstr "drapeaux invalides pour l'ouverture d'un « Large Object » : %d"
#: storage/large_object/inv_api.c:436
#, c-format
msgid "invalid whence setting: %d"
-msgstr "param�trage de � whence � invalide : %d"
+msgstr "paramètrage de « whence » invalide : %d"
#: storage/large_object/inv_api.c:593
#, c-format
msgid "invalid large object write request size: %d"
-msgstr "taille de la requ�te d'�criture du � Large Object � invalide : %d"
+msgstr "taille de la requête d'écriture du « Large Object » invalide : %d"
#: storage/lmgr/deadlock.c:1109
#, c-format
msgid "Process %d waits for %s on %s; blocked by process %d."
-msgstr "Le processus %d attend %s sur %s ; bloqu� par le processus %d."
+msgstr "Le processus %d attend %s sur %s ; bloqué par le processus %d."
#: storage/lmgr/deadlock.c:1128
#, c-format
@@ -16974,72 +16985,72 @@ msgstr "Processus %d : %s"
#: storage/lmgr/deadlock.c:1137
#, c-format
msgid "deadlock detected"
-msgstr "Bloquage mortel d�tect�"
+msgstr "Bloquage mortel détecté"
#: storage/lmgr/deadlock.c:1140
#, c-format
msgid "See server log for query details."
-msgstr "Voir les journaux applicatifs du serveur pour les d�tails sur la requ�te."
+msgstr "Voir les journaux applicatifs du serveur pour les détails sur la requête."
#: storage/lmgr/lmgr.c:719
#, c-format
msgid "while updating tuple (%u,%u) in relation \"%s\""
-msgstr "lors de la mise � jour de la ligne (%u,%u) dans la relation � %s �"
+msgstr "lors de la mise à jour de la ligne (%u,%u) dans la relation « %s »"
#: storage/lmgr/lmgr.c:722
#, c-format
msgid "while deleting tuple (%u,%u) in relation \"%s\""
-msgstr "lors de la suppression de la ligne (%u,%u) dans la relation � %s �"
+msgstr "lors de la suppression de la ligne (%u,%u) dans la relation « %s »"
#: storage/lmgr/lmgr.c:725
#, c-format
msgid "while locking tuple (%u,%u) in relation \"%s\""
-msgstr "lors du verrouillage de la ligne (%u,%u) dans la relation � %s �"
+msgstr "lors du verrouillage de la ligne (%u,%u) dans la relation « %s »"
#: storage/lmgr/lmgr.c:728
#, c-format
msgid "while locking updated version (%u,%u) of tuple in relation \"%s\""
-msgstr "lors du verrou de la version mise � jour (%u, %u) de la ligne de la relation � %s �"
+msgstr "lors du verrou de la version mise à jour (%u, %u) de la ligne de la relation « %s »"
#: storage/lmgr/lmgr.c:731
#, c-format
msgid "while inserting index tuple (%u,%u) in relation \"%s\""
-msgstr "lors de l'insertion de l'enregistrement (%u, %u) de l'index dans la relation � %s �"
+msgstr "lors de l'insertion de l'enregistrement (%u, %u) de l'index dans la relation « %s »"
#: storage/lmgr/lmgr.c:734
#, c-format
msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\""
-msgstr "lors de la v�rification de l'unicit� de l'enregistrement (%u,%u) dans la relation � %s �"
+msgstr "lors de la vérification de l'unicité de l'enregistrement (%u,%u) dans la relation « %s »"
#: storage/lmgr/lmgr.c:737
#, c-format
msgid "while rechecking updated tuple (%u,%u) in relation \"%s\""
-msgstr "lors de la re-v�rification de l'enregistrement mis � jour (%u,%u) dans la relation � %s �"
+msgstr "lors de la re-vérification de l'enregistrement mis à jour (%u,%u) dans la relation « %s »"
#: storage/lmgr/lmgr.c:740
#, c-format
msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\""
-msgstr "lors de la v�rification de la contrainte d'exclusion sur l'enregistrement (%u,%u) dans la relation � %s �"
+msgstr "lors de la vérification de la contrainte d'exclusion sur l'enregistrement (%u,%u) dans la relation « %s »"
#: storage/lmgr/lmgr.c:960
#, c-format
msgid "relation %u of database %u"
-msgstr "relation %u de la base de donn�es %u"
+msgstr "relation %u de la base de données %u"
#: storage/lmgr/lmgr.c:966
#, c-format
msgid "extension of relation %u of database %u"
-msgstr "extension de la relation %u de la base de donn�es %u"
+msgstr "extension de la relation %u de la base de données %u"
#: storage/lmgr/lmgr.c:972
#, c-format
msgid "page %u of relation %u of database %u"
-msgstr "page %u de la relation %u de la base de donn�es %u"
+msgstr "page %u de la relation %u de la base de données %u"
#: storage/lmgr/lmgr.c:979
#, c-format
msgid "tuple (%u,%u) of relation %u of database %u"
-msgstr "ligne (%u,%u) de la relation %u de la base de donn�es %u"
+msgstr "ligne (%u,%u) de la relation %u de la base de données %u"
#: storage/lmgr/lmgr.c:987
#, c-format
@@ -17052,15 +17063,14 @@ msgid "virtual transaction %d/%u"
msgstr "transaction virtuelle %d/%u"
#: storage/lmgr/lmgr.c:998
-#, fuzzy, c-format
-#| msgid "could not access status of transaction %u"
+#, c-format
msgid "speculative token %u of transaction %u"
-msgstr "n'a pas pu acc�der au statut de la transaction %u"
+msgstr "jeton spéculatif %u de la transaction %u"
#: storage/lmgr/lmgr.c:1004
#, c-format
msgid "object %u of class %u of database %u"
-msgstr "objet %u de la classe %u de la base de donn�es %u"
+msgstr "objet %u de la classe %u de la base de données %u"
#: storage/lmgr/lmgr.c:1012
#, c-format
@@ -17081,14 +17091,14 @@ msgstr "type locktag non reconnu %d"
#, c-format
msgid "cannot acquire lock mode %s on database objects while recovery is in progress"
msgstr ""
-"ne peut pas acqu�rir le mode de verrou %s sur les objets de base de donn�es\n"
+"ne peut pas acquérir le mode de verrou %s sur les objets de base de données\n"
"alors que la restauration est en cours"
#: storage/lmgr/lock.c:734
#, c-format
msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery."
msgstr ""
-"Seuls RowExclusiveLock et les verrous inf�rieurs peuvent �tre acquis sur les\n"
+"Seuls RowExclusiveLock et les verrous inférieurs peuvent être acquis sur les\n"
"objets d'une base pendant une restauration."
#: storage/lmgr/lock.c:884 storage/lmgr/lock.c:918 storage/lmgr/lock.c:2683 storage/lmgr/lock.c:4008 storage/lmgr/lock.c:4073 storage/lmgr/lock.c:4365
@@ -17099,75 +17109,75 @@ msgstr "Vous pourriez avoir besoin d'augmenter max_locks_per_transaction."
#: storage/lmgr/lock.c:3124 storage/lmgr/lock.c:3240
#, c-format
msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object"
-msgstr "ne peut pas utiliser PREPARE lorsque des verrous de niveau session et deniveau transaction sont d�tenus sur le m�me objet"
+msgstr "ne peut pas utiliser PREPARE lorsque des verrous de niveau session et deniveau transaction sont détenus sur le même objet"
#: storage/lmgr/predicate.c:675
#, c-format
msgid "not enough elements in RWConflictPool to record a read/write conflict"
-msgstr "pas assez d'�l�ments dans RWConflictPool pour enregistrer un conflit en lecture/�criture"
+msgstr "pas assez d'éléments dans RWConflictPool pour enregistrer un conflit en lecture/écriture"
#: storage/lmgr/predicate.c:676 storage/lmgr/predicate.c:704
#, c-format
msgid "You might need to run fewer transactions at a time or increase max_connections."
msgstr ""
-"Il est possible que vous ayez � ex�cuter moins de transactions � la fois\n"
+"Il est possible que vous ayez à exécuter moins de transactions à la fois\n"
"ou d'augmenter max_connections."
#: storage/lmgr/predicate.c:703
#, c-format
msgid "not enough elements in RWConflictPool to record a potential read/write conflict"
-msgstr "pas assez d'�l�ments dans RWConflictPool pour enregistrer un conflit en lecture/�criture potentiel"
+msgstr "pas assez d'éléments dans RWConflictPool pour enregistrer un conflit en lecture/écriture potentiel"
#: storage/lmgr/predicate.c:909
#, c-format
msgid "memory for serializable conflict tracking is nearly exhausted"
-msgstr "la m�moire pour tracer les conflits s�rialisables est pratiquement pleine"
+msgstr "la mémoire pour tracer les conflits sérialisables est pratiquement pleine"
#: storage/lmgr/predicate.c:910
#, c-format
msgid "There might be an idle transaction or a forgotten prepared transaction causing this."
msgstr ""
-"Il pourait y avoir une transaction en attente ou une transaction pr�par�e\n"
-"oubli�e causant cela."
+"Il pourait y avoir une transaction en attente ou une transaction préparée\n"
+"oubliée causant cela."
#: storage/lmgr/predicate.c:1190 storage/lmgr/predicate.c:1261
#, c-format
msgid "not enough shared memory for elements of data structure \"%s\" (%zu bytes requested)"
msgstr ""
-"pas assez de m�moire partag�e pour les �l�ments de la structure de donn�es\n"
-"� %s � (%zu octets demand�s)"
+"pas assez de mémoire partagée pour les éléments de la structure de données\n"
+"« %s » (%zu octets demandés)"
#: storage/lmgr/predicate.c:1549
#, c-format
msgid "deferrable snapshot was unsafe; trying a new one"
-msgstr "l'image d�ferrable est non s�re ; tentative avec une nouvelle image"
+msgstr "l'image déferrable est non sûre ; tentative avec une nouvelle image"
#: storage/lmgr/predicate.c:1588
#, c-format
msgid "\"default_transaction_isolation\" is set to \"serializable\"."
-msgstr "� default_transaction_isolation � est configur� � � serializable �."
+msgstr "« default_transaction_isolation » est configuré à « serializable »."
#: storage/lmgr/predicate.c:1589
#, c-format
msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default."
msgstr ""
-"Vous pouvez utiliser � SET default_transaction_isolation = 'repeatable read' �\n"
-"pour modifier la valeur par d�faut."
+"Vous pouvez utiliser « SET default_transaction_isolation = 'repeatable read' »\n"
+"pour modifier la valeur par défaut."
#: storage/lmgr/predicate.c:1628
#, c-format
msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE"
-msgstr "une transaction important un snapshot ne doit pas �tre READ ONLY DEFERRABLE"
+msgstr "une transaction important un snapshot ne doit pas être READ ONLY DEFERRABLE"
-#: storage/lmgr/predicate.c:1706 utils/time/snapmgr.c:542 utils/time/snapmgr.c:548
+#: storage/lmgr/predicate.c:1706 utils/time/snapmgr.c:617 utils/time/snapmgr.c:623
#, c-format
msgid "could not import the requested snapshot"
-msgstr "n'a pas pu importer le snapshot demand�"
+msgstr "n'a pas pu importer le snapshot demandé"
-#: storage/lmgr/predicate.c:1707 utils/time/snapmgr.c:549
+#: storage/lmgr/predicate.c:1707 utils/time/snapmgr.c:624
#, c-format
msgid "The source transaction %u is not running anymore."
-msgstr "La transaction source %u n'est plus en cours d'ex�cution."
+msgstr "La transaction source %u n'est plus en cours d'exécution."
#: storage/lmgr/predicate.c:2330 storage/lmgr/predicate.c:2345 storage/lmgr/predicate.c:3737
#, c-format
@@ -17178,203 +17188,202 @@ msgstr "Vous pourriez avoir besoin d'augmenter max_pred_locks_per_transaction."
#, c-format
msgid "could not serialize access due to read/write dependencies among transactions"
msgstr ""
-"n'a pas pu s�rialiser un acc�s � cause des d�pendances de lecture/�criture\n"
+"n'a pas pu sérialiser un accès à cause des dépendances de lecture/écriture\n"
"parmi les transactions"
#: storage/lmgr/predicate.c:3893 storage/lmgr/predicate.c:3982 storage/lmgr/predicate.c:3990 storage/lmgr/predicate.c:4029 storage/lmgr/predicate.c:4268 storage/lmgr/predicate.c:4605 storage/lmgr/predicate.c:4617 storage/lmgr/predicate.c:4659 storage/lmgr/predicate.c:4697
#, c-format
msgid "The transaction might succeed if retried."
-msgstr "La transaction pourrait r�ussir apr�s une nouvelle tentative."
+msgstr "La transaction pourrait réussir après une nouvelle tentative."
-#: storage/lmgr/proc.c:1263
+#: storage/lmgr/proc.c:1265
#, c-format
msgid "Process %d waits for %s on %s."
msgstr "Le processus %d attend %s sur %s."
-#: storage/lmgr/proc.c:1274
+#: storage/lmgr/proc.c:1276
#, c-format
msgid "sending cancel to blocking autovacuum PID %d"
msgstr "envoi de l'annulation pour bloquer le PID %d de l'autovacuum"
-#: storage/lmgr/proc.c:1292 utils/adt/misc.c:270
+#: storage/lmgr/proc.c:1294 utils/adt/misc.c:270
#, c-format
msgid "could not send signal to process %d: %m"
msgstr "n'a pas pu envoyer le signal au processus %d : %m"
-#: storage/lmgr/proc.c:1394
+#: storage/lmgr/proc.c:1396
#, c-format
msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms"
msgstr ""
-"le processus %d a �vit� un verrou mortel pour %s sur %s en modifiant l'ordre\n"
-"de la queue apr�s %ld.%03d ms"
+"le processus %d a évité un verrou mortel pour %s sur %s en modifiant l'ordre\n"
+"de la queue après %ld.%03d ms"
-#: storage/lmgr/proc.c:1409
+#: storage/lmgr/proc.c:1411
#, c-format
msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms"
msgstr ""
-"le processus %d a d�tect� un verrou mortel alors qu'il �tait en attente de\n"
-"%s sur %s apr�s %ld.%03d ms"
+"le processus %d a détecté un verrou mortel alors qu'il était en attente de\n"
+"%s sur %s après %ld.%03d ms"
-#: storage/lmgr/proc.c:1418
+#: storage/lmgr/proc.c:1420
#, c-format
msgid "process %d still waiting for %s on %s after %ld.%03d ms"
-msgstr "le processus %d est toujours en attente de %s sur %s apr�s %ld.%03d ms"
+msgstr "le processus %d est toujours en attente de %s sur %s après %ld.%03d ms"
-#: storage/lmgr/proc.c:1425
+#: storage/lmgr/proc.c:1427
#, c-format
msgid "process %d acquired %s on %s after %ld.%03d ms"
-msgstr "le processus %d a acquis %s sur %s apr�s %ld.%03d ms"
+msgstr "le processus %d a acquis %s sur %s après %ld.%03d ms"
-#: storage/lmgr/proc.c:1441
+#: storage/lmgr/proc.c:1443
#, c-format
msgid "process %d failed to acquire %s on %s after %ld.%03d ms"
-msgstr "le processus %d a �chou� pour l'acquisition de %s sur %s apr�s %ld.%03d ms"
+msgstr "le processus %d a échoué pour l'acquisition de %s sur %s après %ld.%03d ms"
#: storage/page/bufpage.c:144
#, c-format
msgid "page verification failed, calculated checksum %u but expected %u"
-msgstr "�chec de la v�rification de la page, somme de contr�le calcul� %u, mais attendait %u"
+msgstr "échec de la vérification de la page, somme de contrôle calculé %u, mais attendait %u"
-#: storage/page/bufpage.c:200 storage/page/bufpage.c:490 storage/page/bufpage.c:705 storage/page/bufpage.c:836 storage/page/bufpage.c:936
+#: storage/page/bufpage.c:203 storage/page/bufpage.c:522 storage/page/bufpage.c:737 storage/page/bufpage.c:868 storage/page/bufpage.c:968
#, c-format
msgid "corrupted page pointers: lower = %u, upper = %u, special = %u"
-msgstr "pointeurs de page corrompus : le plus bas = %u, le plus haut = %u, sp�cial = %u"
+msgstr "pointeurs de page corrompus : le plus bas = %u, le plus haut = %u, spécial = %u"
-#: storage/page/bufpage.c:534
+#: storage/page/bufpage.c:566
#, c-format
msgid "corrupted item pointer: %u"
-msgstr "pointeur d'�l�ment corrompu : %u"
+msgstr "pointeur d'élément corrompu : %u"
-#: storage/page/bufpage.c:545 storage/page/bufpage.c:887 storage/page/bufpage.c:1042
+#: storage/page/bufpage.c:577 storage/page/bufpage.c:919 storage/page/bufpage.c:1074
#, c-format
msgid "corrupted item lengths: total %u, available space %u"
-msgstr "longueurs d'�l�ment corrompus : total %u, espace disponible %u"
+msgstr "longueurs d'élément corrompus : total %u, espace disponible %u"
-#: storage/page/bufpage.c:724 storage/page/bufpage.c:860
+#: storage/page/bufpage.c:756 storage/page/bufpage.c:892
#, c-format
msgid "corrupted item pointer: offset = %u, size = %u"
-msgstr "pointeur d'�l�ment corrompu : d�calage = %u, taille = %u"
+msgstr "pointeur d'élément corrompu : décalage = %u, taille = %u"
-#: storage/page/bufpage.c:965
+#: storage/page/bufpage.c:997
#, c-format
msgid "corrupted item pointer: offset = %u, length = %u"
-msgstr "pointeur d'�l�ment corrompu : d�calage = %u, longueur = %u"
+msgstr "pointeur d'élément corrompu : décalage = %u, longueur = %u"
-#: storage/smgr/md.c:453 storage/smgr/md.c:975
+#: storage/smgr/md.c:449 storage/smgr/md.c:971
#, c-format
msgid "could not truncate file \"%s\": %m"
-msgstr "n'a pas pu tronquer le fichier � %s � : %m"
+msgstr "n'a pas pu tronquer le fichier « %s » : %m"
-#: storage/smgr/md.c:520
+#: storage/smgr/md.c:516
#, c-format
msgid "cannot extend file \"%s\" beyond %u blocks"
-msgstr "ne peut pas �tendre le fichier � %s � de plus de %u blocs"
+msgstr "ne peut pas étendre le fichier « %s » de plus de %u blocs"
-#: storage/smgr/md.c:542 storage/smgr/md.c:755 storage/smgr/md.c:831
+#: storage/smgr/md.c:538 storage/smgr/md.c:751 storage/smgr/md.c:827
#, c-format
msgid "could not seek to block %u in file \"%s\": %m"
-msgstr "n'a pas pu trouver le bloc %u dans le fichier � %s � : %m"
+msgstr "n'a pas pu trouver le bloc %u dans le fichier « %s » : %m"
-#: storage/smgr/md.c:550
+#: storage/smgr/md.c:546
#, c-format
msgid "could not extend file \"%s\": %m"
-msgstr "n'a pas pu �tendre le fichier � %s � : %m"
+msgstr "n'a pas pu étendre le fichier « %s » : %m"
-#: storage/smgr/md.c:552 storage/smgr/md.c:559 storage/smgr/md.c:858
+#: storage/smgr/md.c:548 storage/smgr/md.c:555 storage/smgr/md.c:854
#, c-format
msgid "Check free disk space."
-msgstr "V�rifiez l'espace disque disponible."
+msgstr "Vérifiez l'espace disque disponible."
-#: storage/smgr/md.c:556
+#: storage/smgr/md.c:552
#, c-format
msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u"
msgstr ""
-"n'a pas pu �tendre le fichier � %s � : a �crit seulement %d octets sur %d\n"
+"n'a pas pu étendre le fichier « %s » : a écrit seulement %d octets sur %d\n"
"au bloc %u"
-#: storage/smgr/md.c:773
+#: storage/smgr/md.c:769
#, c-format
msgid "could not read block %u in file \"%s\": %m"
-msgstr "n'a pas pu lire le bloc %u dans le fichier � %s � : %m"
+msgstr "n'a pas pu lire le bloc %u dans le fichier « %s » : %m"
-#: storage/smgr/md.c:789
+#: storage/smgr/md.c:785
#, c-format
msgid "could not read block %u in file \"%s\": read only %d of %d bytes"
msgstr ""
-"n'a pas pu lire le bloc %u du fichier � %s � : a lu seulement %d octets\n"
+"n'a pas pu lire le bloc %u du fichier « %s » : a lu seulement %d octets\n"
"sur %d"
-#: storage/smgr/md.c:849
+#: storage/smgr/md.c:845
#, c-format
msgid "could not write block %u in file \"%s\": %m"
-msgstr "n'a pas pu �crire le bloc %u dans le fichier � %s � : %m"
+msgstr "n'a pas pu écrire le bloc %u dans le fichier « %s » : %m"
-#: storage/smgr/md.c:854
+#: storage/smgr/md.c:850
#, c-format
msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes"
msgstr ""
-"n'a pas pu �crire le bloc %u du fichier � %s � : a seulement �crit %d\n"
+"n'a pas pu écrire le bloc %u du fichier « %s » : a seulement écrit %d\n"
"octets sur %d"
-#: storage/smgr/md.c:951
+#: storage/smgr/md.c:947
#, c-format
msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now"
-msgstr "n'a pas pu tronquer le fichier � %s � en %u blocs : il y a seulement %u blocs"
+msgstr "n'a pas pu tronquer le fichier « %s » en %u blocs : il y a seulement %u blocs"
-#: storage/smgr/md.c:1000
+#: storage/smgr/md.c:997
#, c-format
msgid "could not truncate file \"%s\" to %u blocks: %m"
-msgstr "n'a pas pu tronquer le fichier � %s � en %u blocs : %m"
+msgstr "n'a pas pu tronquer le fichier « %s » en %u blocs : %m"
-#: storage/smgr/md.c:1282
+#: storage/smgr/md.c:1279
#, c-format
msgid "could not fsync file \"%s\" but retrying: %m"
msgstr ""
-"n'a pas pu synchroniser sur disque (fsync) le fichier � %s �, nouvelle\n"
+"n'a pas pu synchroniser sur disque (fsync) le fichier « %s », nouvelle\n"
"tentative : %m"
-#: storage/smgr/md.c:1445
+#: storage/smgr/md.c:1442
#, c-format
msgid "could not forward fsync request because request queue is full"
-msgstr "n'a pas pu envoyer la requ�te fsync car la queue des requ�tes est pleine"
+msgstr "n'a pas pu envoyer la requête fsync car la queue des requêtes est pleine"
-#: storage/smgr/md.c:1866
-#, fuzzy, c-format
-#| msgid "could not open file \"%s\" (target block %u): %m"
+#: storage/smgr/md.c:1863
+#, c-format
msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks"
-msgstr "n'a pas pu ouvrir le fichier � %s � (bloc cible %u) : %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » (bloc cible %u) : le segment précédent ne fait que %u blocs"
-#: storage/smgr/md.c:1880
+#: storage/smgr/md.c:1877
#, c-format
msgid "could not open file \"%s\" (target block %u): %m"
-msgstr "n'a pas pu ouvrir le fichier � %s � (bloc cible %u) : %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » (bloc cible %u) : %m"
#: tcop/fastpath.c:111 tcop/fastpath.c:475 tcop/fastpath.c:605
#, c-format
msgid "invalid argument size %d in function call message"
msgstr "taille de l'argument %d invalide dans le message d'appel de la fonction"
-#: tcop/fastpath.c:291 tcop/postgres.c:992 tcop/postgres.c:1303 tcop/postgres.c:1561 tcop/postgres.c:1966 tcop/postgres.c:2333 tcop/postgres.c:2408
+#: tcop/fastpath.c:291 tcop/postgres.c:992 tcop/postgres.c:1301 tcop/postgres.c:1559 tcop/postgres.c:1964 tcop/postgres.c:2331 tcop/postgres.c:2406
#, c-format
msgid "current transaction is aborted, commands ignored until end of transaction block"
msgstr ""
-"la transaction est annul�e, les commandes sont ignor�es jusqu'� la fin du bloc\n"
+"la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc\n"
"de la transaction"
#: tcop/fastpath.c:319
#, c-format
msgid "fastpath function call: \"%s\" (OID %u)"
-msgstr "appel de fonction fastpath : � %s � (OID %u)"
+msgstr "appel de fonction fastpath : « %s » (OID %u)"
-#: tcop/fastpath.c:401 tcop/postgres.c:1163 tcop/postgres.c:1428 tcop/postgres.c:1807 tcop/postgres.c:2024
+#: tcop/fastpath.c:401 tcop/postgres.c:1163 tcop/postgres.c:1426 tcop/postgres.c:1805 tcop/postgres.c:2022
#, c-format
msgid "duration: %s ms"
-msgstr "dur�e : %s ms"
+msgstr "durée : %s ms"
#: tcop/fastpath.c:405
#, c-format
msgid "duration: %s ms fastpath function call: \"%s\" (OID %u)"
-msgstr "dur�e : %s ms, appel de fonction fastpath : � %s � (OID %u)"
+msgstr "durée : %s ms, appel de fonction fastpath : « %s » (OID %u)"
#: tcop/fastpath.c:443 tcop/fastpath.c:570
#, c-format
@@ -17393,14 +17402,14 @@ msgstr ""
#: tcop/fastpath.c:538 tcop/fastpath.c:621
#, c-format
msgid "incorrect binary data format in function argument %d"
-msgstr "format des donn�es binaires incorrect dans l'argument de la fonction %d"
+msgstr "format des données binaires incorrect dans l'argument de la fonction %d"
#: tcop/postgres.c:352 tcop/postgres.c:388 tcop/postgres.c:415
#, c-format
msgid "unexpected EOF on client connection"
msgstr "fin de fichier (EOF) inattendue de la connexion du client"
-#: tcop/postgres.c:438 tcop/postgres.c:450 tcop/postgres.c:461 tcop/postgres.c:473 tcop/postgres.c:4297
+#: tcop/postgres.c:438 tcop/postgres.c:450 tcop/postgres.c:461 tcop/postgres.c:473 tcop/postgres.c:4314
#, c-format
msgid "invalid frontend message type %d"
msgstr "type %d du message de l'interface invalide"
@@ -17413,381 +17422,380 @@ msgstr "instruction : %s"
#: tcop/postgres.c:1168
#, c-format
msgid "duration: %s ms statement: %s"
-msgstr "dur�e : %s ms, instruction : %s"
+msgstr "durée : %s ms, instruction : %s"
#: tcop/postgres.c:1218
#, c-format
msgid "parse %s: %s"
msgstr "analyse %s : %s"
-#: tcop/postgres.c:1276
+#: tcop/postgres.c:1274
#, c-format
msgid "cannot insert multiple commands into a prepared statement"
-msgstr "ne peut pas ins�rer les commandes multiples dans une instruction pr�par�e"
+msgstr "ne peut pas insérer les commandes multiples dans une instruction préparée"
-#: tcop/postgres.c:1433
+#: tcop/postgres.c:1431
#, c-format
msgid "duration: %s ms parse %s: %s"
-msgstr "dur�e : %s ms, analyse %s : %s"
+msgstr "durée : %s ms, analyse %s : %s"
-#: tcop/postgres.c:1478
+#: tcop/postgres.c:1476
#, c-format
msgid "bind %s to %s"
-msgstr "lie %s � %s"
+msgstr "lie %s à %s"
-#: tcop/postgres.c:1497 tcop/postgres.c:2314
+#: tcop/postgres.c:1495 tcop/postgres.c:2312
#, c-format
msgid "unnamed prepared statement does not exist"
-msgstr "l'instruction pr�par�e non nomm�e n'existe pas"
+msgstr "l'instruction préparée non nommée n'existe pas"
-#: tcop/postgres.c:1539
+#: tcop/postgres.c:1537
#, c-format
msgid "bind message has %d parameter formats but %d parameters"
-msgstr "le message bind a %d formats de param�tres mais %d param�tres"
+msgstr "le message bind a %d formats de paramètres mais %d paramètres"
-#: tcop/postgres.c:1545
+#: tcop/postgres.c:1543
#, c-format
msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d"
msgstr ""
-"le message bind fournit %d param�tres, mais l'instruction pr�par�e � %s � en\n"
+"le message bind fournit %d paramètres, mais l'instruction préparée « %s » en\n"
"requiert %d"
-#: tcop/postgres.c:1714
+#: tcop/postgres.c:1712
#, c-format
msgid "incorrect binary data format in bind parameter %d"
-msgstr "format des donn�es binaires incorrect dans le param�tre bind %d"
+msgstr "format des données binaires incorrect dans le paramètre bind %d"
-#: tcop/postgres.c:1812
+#: tcop/postgres.c:1810
#, c-format
msgid "duration: %s ms bind %s%s%s: %s"
-msgstr "dur�e : %s ms, lien %s%s%s : %s"
+msgstr "durée : %s ms, lien %s%s%s : %s"
-#: tcop/postgres.c:1860 tcop/postgres.c:2394
+#: tcop/postgres.c:1858 tcop/postgres.c:2392
#, c-format
msgid "portal \"%s\" does not exist"
-msgstr "le portail � %s � n'existe pas"
+msgstr "le portail « %s » n'existe pas"
-#: tcop/postgres.c:1945
+#: tcop/postgres.c:1943
#, c-format
msgid "%s %s%s%s: %s"
msgstr "%s %s%s%s: %s"
-#: tcop/postgres.c:1947 tcop/postgres.c:2032
+#: tcop/postgres.c:1945 tcop/postgres.c:2030
msgid "execute fetch from"
-msgstr "ex�cute fetch � partir de"
+msgstr "exécute fetch à partir de"
-#: tcop/postgres.c:1948 tcop/postgres.c:2033
+#: tcop/postgres.c:1946 tcop/postgres.c:2031
msgid "execute"
-msgstr "ex�cute"
+msgstr "exécute"
-#: tcop/postgres.c:2029
+#: tcop/postgres.c:2027
#, c-format
msgid "duration: %s ms %s %s%s%s: %s"
-msgstr "dur�e : %s ms %s %s%s%s: %s"
+msgstr "durée : %s ms %s %s%s%s: %s"
-#: tcop/postgres.c:2155
+#: tcop/postgres.c:2153
#, c-format
msgid "prepare: %s"
-msgstr "pr�paration : %s"
+msgstr "préparation : %s"
-#: tcop/postgres.c:2218
+#: tcop/postgres.c:2216
#, c-format
msgid "parameters: %s"
-msgstr "param�tres : %s"
+msgstr "paramètres : %s"
-#: tcop/postgres.c:2237
+#: tcop/postgres.c:2235
#, c-format
msgid "abort reason: recovery conflict"
msgstr "raison de l'annulation : conflit de restauration"
-#: tcop/postgres.c:2253
+#: tcop/postgres.c:2251
#, c-format
msgid "User was holding shared buffer pin for too long."
-msgstr "L'utilisateur conservait des blocs disques en m�moire partag�e depuis trop longtemps."
+msgstr "L'utilisateur conservait des blocs disques en mémoire partagée depuis trop longtemps."
-#: tcop/postgres.c:2256
+#: tcop/postgres.c:2254
#, c-format
msgid "User was holding a relation lock for too long."
msgstr "L'utilisateur conservait un verrou sur une relation depuis trop longtemps."
-#: tcop/postgres.c:2259
+#: tcop/postgres.c:2257
#, c-format
msgid "User was or might have been using tablespace that must be dropped."
-msgstr "L'utilisateur utilisait ou pouvait utiliser un tablespace qui doit �tre supprim�."
+msgstr "L'utilisateur utilisait ou pouvait utiliser un tablespace qui doit être supprimé."
-#: tcop/postgres.c:2262
+#: tcop/postgres.c:2260
#, c-format
msgid "User query might have needed to see row versions that must be removed."
msgstr ""
-"La requ�te de l'utilisateur pourrait avoir eu besoin de voir des versions de\n"
-"lignes qui doivent �tre supprim�es."
+"La requête de l'utilisateur pourrait avoir eu besoin de voir des versions de\n"
+"lignes qui doivent être supprimées."
-#: tcop/postgres.c:2268
+#: tcop/postgres.c:2266
#, c-format
msgid "User was connected to a database that must be dropped."
-msgstr "L'utilisateur �tait connect� � une base de donn�e qui doit �tre supprim�."
+msgstr "L'utilisateur était connecté à une base de donnée qui doit être supprimé."
-#: tcop/postgres.c:2597
+#: tcop/postgres.c:2595
#, c-format
msgid "terminating connection because of crash of another server process"
-msgstr "arr�t de la connexion � cause de l'arr�t brutal d'un autre processus serveur"
+msgstr "arrêt de la connexion à cause de l'arrêt brutal d'un autre processus serveur"
-#: tcop/postgres.c:2598
+#: tcop/postgres.c:2596
#, c-format
msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory."
msgstr ""
-"Le postmaster a command� � ce processus serveur d'annuler la transaction\n"
-"courante et de quitter car un autre processus serveur a quitt� anormalement\n"
-"et qu'il existe probablement de la m�moire partag�e corrompue."
+"Le postmaster a commandé à ce processus serveur d'annuler la transaction\n"
+"courante et de quitter car un autre processus serveur a quitté anormalement\n"
+"et qu'il existe probablement de la mémoire partagée corrompue."
-#: tcop/postgres.c:2602 tcop/postgres.c:2906
+#: tcop/postgres.c:2600 tcop/postgres.c:2904
#, c-format
msgid "In a moment you should be able to reconnect to the database and repeat your command."
msgstr ""
-"Dans un moment, vous devriez �tre capable de vous reconnecter � la base de\n"
-"donn�es et de relancer votre commande."
+"Dans un moment, vous devriez être capable de vous reconnecter à la base de\n"
+"données et de relancer votre commande."
-#: tcop/postgres.c:2688
+#: tcop/postgres.c:2686
#, c-format
msgid "floating-point exception"
-msgstr "exception d� � une virgule flottante"
+msgstr "exception dû à une virgule flottante"
-#: tcop/postgres.c:2689
+#: tcop/postgres.c:2687
#, c-format
msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero."
msgstr ""
-"Une op�ration invalide sur les virgules flottantes a �t� signal�e.\n"
-"Ceci signifie probablement un r�sultat en dehors de l'�chelle ou une\n"
-"op�ration invalide telle qu'une division par z�ro."
+"Une opération invalide sur les virgules flottantes a été signalée.\n"
+"Ceci signifie probablement un résultat en dehors de l'échelle ou une\n"
+"opération invalide telle qu'une division par zéro."
-#: tcop/postgres.c:2851
+#: tcop/postgres.c:2849
#, c-format
msgid "canceling authentication due to timeout"
-msgstr "annulation de l'authentification � cause du d�lai �coul�"
+msgstr "annulation de l'authentification à cause du délai écoulé"
-#: tcop/postgres.c:2855
+#: tcop/postgres.c:2853
#, c-format
msgid "terminating autovacuum process due to administrator command"
-msgstr "arr�t du processus autovacuum suite � la demande de l'administrateur"
+msgstr "arrêt du processus autovacuum suite à la demande de l'administrateur"
-#: tcop/postgres.c:2861 tcop/postgres.c:2871 tcop/postgres.c:2904
+#: tcop/postgres.c:2859 tcop/postgres.c:2869 tcop/postgres.c:2902
#, c-format
msgid "terminating connection due to conflict with recovery"
-msgstr "arr�t de la connexion � cause d'un conflit avec la restauration"
+msgstr "arrêt de la connexion à cause d'un conflit avec la restauration"
-#: tcop/postgres.c:2877
+#: tcop/postgres.c:2875
#, c-format
msgid "terminating connection due to administrator command"
-msgstr "arr�t des connexions suite � la demande de l'administrateur"
+msgstr "arrêt des connexions suite à la demande de l'administrateur"
-#: tcop/postgres.c:2887
+#: tcop/postgres.c:2885
#, c-format
msgid "connection to client lost"
msgstr "connexion au client perdue"
-#: tcop/postgres.c:2940
+#: tcop/postgres.c:2953
#, c-format
msgid "canceling statement due to lock timeout"
-msgstr "annulation de la requ�te � cause du d�lai �coul� pour l'obtention des verrous"
+msgstr "annulation de la requête à cause du délai écoulé pour l'obtention des verrous"
-#: tcop/postgres.c:2947
+#: tcop/postgres.c:2960
#, c-format
msgid "canceling statement due to statement timeout"
-msgstr "annulation de la requ�te � cause du d�lai �coul� pour l'ex�cution de l'instruction"
+msgstr "annulation de la requête à cause du délai écoulé pour l'exécution de l'instruction"
-#: tcop/postgres.c:2954
+#: tcop/postgres.c:2967
#, c-format
msgid "canceling autovacuum task"
-msgstr "annulation de la t�che d'autovacuum"
+msgstr "annulation de la tâche d'autovacuum"
-#: tcop/postgres.c:2977
+#: tcop/postgres.c:2990
#, c-format
msgid "canceling statement due to user request"
-msgstr "annulation de la requ�te � la demande de l'utilisateur"
+msgstr "annulation de la requête à la demande de l'utilisateur"
-#: tcop/postgres.c:2987
-#, fuzzy, c-format
-#| msgid "terminating connection due to administrator command"
+#: tcop/postgres.c:3000
+#, c-format
msgid "terminating connection due to idle-in-transaction timeout"
-msgstr "arr�t des connexions suite � la demande de l'administrateur"
+msgstr "arrêt des connexions suite à l'expiration du délai d'inactivité en transaction"
-#: tcop/postgres.c:3101
+#: tcop/postgres.c:3114
#, c-format
msgid "stack depth limit exceeded"
-msgstr "d�passement de limite (en profondeur) de la pile"
+msgstr "dépassement de limite (en profondeur) de la pile"
-#: tcop/postgres.c:3102
+#: tcop/postgres.c:3115
#, c-format
msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate."
msgstr ""
-"Augmenter le param�tre � max_stack_depth � (actuellement %d Ko) apr�s vous\n"
-"�tre assur� que la limite de profondeur de la pile de la plateforme est\n"
-"ad�quate."
+"Augmenter le paramètre « max_stack_depth » (actuellement %d Ko) après vous\n"
+"être assuré que la limite de profondeur de la pile de la plateforme est\n"
+"adéquate."
-#: tcop/postgres.c:3165
+#: tcop/postgres.c:3178
#, c-format
msgid "\"max_stack_depth\" must not exceed %ldkB."
-msgstr "� max_stack_depth � ne doit pas d�passer %ld Ko."
+msgstr "« max_stack_depth » ne doit pas dépasser %ld Ko."
-#: tcop/postgres.c:3167
+#: tcop/postgres.c:3180
#, c-format
msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent."
msgstr ""
"Augmenter la limite de profondeur de la pile sur votre plateforme via\n"
-"� ulimit -s � ou l'�quivalent local."
+"« ulimit -s » ou l'équivalent local."
-#: tcop/postgres.c:3527
+#: tcop/postgres.c:3540
#, c-format
msgid "invalid command-line argument for server process: %s"
msgstr "argument invalide en ligne de commande pour le processus serveur : %s"
-#: tcop/postgres.c:3528 tcop/postgres.c:3534
+#: tcop/postgres.c:3541 tcop/postgres.c:3547
#, c-format
msgid "Try \"%s --help\" for more information."
-msgstr "Essayez � %s --help � pour plus d'informations."
+msgstr "Essayez « %s --help » pour plus d'informations."
-#: tcop/postgres.c:3532
+#: tcop/postgres.c:3545
#, c-format
msgid "%s: invalid command-line argument: %s"
msgstr "%s : argument invalide en ligne de commande : %s"
-#: tcop/postgres.c:3594
+#: tcop/postgres.c:3607
#, c-format
msgid "%s: no database nor user name specified"
-msgstr "%s : aucune base de donn�es et aucun utilisateur sp�cifi�s"
+msgstr "%s : aucune base de données et aucun utilisateur spécifiés"
-#: tcop/postgres.c:4205
+#: tcop/postgres.c:4222
#, c-format
msgid "invalid CLOSE message subtype %d"
msgstr "sous-type %d du message CLOSE invalide"
-#: tcop/postgres.c:4240
+#: tcop/postgres.c:4257
#, c-format
msgid "invalid DESCRIBE message subtype %d"
msgstr "sous-type %d du message DESCRIBE invalide"
-#: tcop/postgres.c:4318
+#: tcop/postgres.c:4335
#, c-format
msgid "fastpath function calls not supported in a replication connection"
-msgstr "appels � la fonction fastpath non support�s dans une connexion de r�plication"
+msgstr "appels à la fonction fastpath non supportés dans une connexion de réplication"
-#: tcop/postgres.c:4322
+#: tcop/postgres.c:4339
#, c-format
msgid "extended query protocol not supported in a replication connection"
-msgstr "protocole �tendu de requ�tes non support� dans une connexion de r�plication"
+msgstr "protocole étendu de requêtes non supporté dans une connexion de réplication"
-#: tcop/postgres.c:4492
+#: tcop/postgres.c:4509
#, c-format
msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s"
msgstr ""
-"d�connexion : dur�e de la session : %d:%02d:%02d.%03d\n"
-"utilisateur=%s base=%s h�te=%s%s%s"
+"déconnexion : durée de la session : %d:%02d:%02d.%03d\n"
+"utilisateur=%s base=%s hôte=%s%s%s"
-#: tcop/pquery.c:663
+#: tcop/pquery.c:665
#, c-format
msgid "bind message has %d result formats but query has %d columns"
-msgstr "le message bind a %d formats de r�sultat mais la requ�te a %d colonnes"
+msgstr "le message bind a %d formats de résultat mais la requête a %d colonnes"
-#: tcop/pquery.c:965
+#: tcop/pquery.c:967
#, c-format
msgid "cursor can only scan forward"
msgstr "le curseur peut seulement parcourir en avant"
-#: tcop/pquery.c:966
+#: tcop/pquery.c:968
#, c-format
msgid "Declare it with SCROLL option to enable backward scan."
-msgstr "D�clarez-le avec l'option SCROLL pour activer le parcours inverse."
+msgstr "Déclarez-le avec l'option SCROLL pour activer le parcours inverse."
#. translator: %s is name of a SQL command, eg CREATE
#: tcop/utility.c:235
#, c-format
msgid "cannot execute %s in a read-only transaction"
-msgstr "ne peut pas ex�cuter %s dans une transaction en lecture seule"
+msgstr "ne peut pas exécuter %s dans une transaction en lecture seule"
#. translator: %s is name of a SQL command, eg CREATE
#: tcop/utility.c:253
#, c-format
msgid "cannot execute %s during a parallel operation"
-msgstr "ne peut pas ex�cut� %s lors d'une op�ration parall�le"
+msgstr "ne peut pas exécuté %s lors d'une opération parallèle"
#. translator: %s is name of a SQL command, eg CREATE
#: tcop/utility.c:272
#, c-format
msgid "cannot execute %s during recovery"
-msgstr "ne peut pas ex�cut� %s lors de la restauration"
+msgstr "ne peut pas exécuté %s lors de la restauration"
#. translator: %s is name of a SQL command, eg PREPARE
#: tcop/utility.c:290
#, c-format
msgid "cannot execute %s within security-restricted operation"
msgstr ""
-"ne peut pas ex�cuter %s � l'int�rieur d'une fonction restreinte\n"
-"pour s�curit�"
+"ne peut pas exécuter %s à l'intérieur d'une fonction restreinte\n"
+"pour sécurité"
#: tcop/utility.c:744
#, c-format
msgid "must be superuser to do CHECKPOINT"
-msgstr "doit �tre super-utilisateur pour ex�cuter un point de v�rification (CHECKPOINT)"
+msgstr "doit être super-utilisateur pour exécuter un point de vérification (CHECKPOINT)"
#: tsearch/dict_ispell.c:51 tsearch/dict_thesaurus.c:623
#, c-format
msgid "multiple DictFile parameters"
-msgstr "multiples param�tres DictFile"
+msgstr "multiples paramètres DictFile"
#: tsearch/dict_ispell.c:62
#, c-format
msgid "multiple AffFile parameters"
-msgstr "multiples param�tres AffFile"
+msgstr "multiples paramètres AffFile"
#: tsearch/dict_ispell.c:81
#, c-format
msgid "unrecognized Ispell parameter: \"%s\""
-msgstr "param�tre Ispell non reconnu : � %s �"
+msgstr "paramètre Ispell non reconnu : « %s »"
#: tsearch/dict_ispell.c:95
#, c-format
msgid "missing AffFile parameter"
-msgstr "param�tre AffFile manquant"
+msgstr "paramètre AffFile manquant"
#: tsearch/dict_ispell.c:101 tsearch/dict_thesaurus.c:647
#, c-format
msgid "missing DictFile parameter"
-msgstr "param�tre DictFile manquant"
+msgstr "paramètre DictFile manquant"
#: tsearch/dict_simple.c:57
#, c-format
msgid "multiple Accept parameters"
-msgstr "multiples param�tres Accept"
+msgstr "multiples paramètres Accept"
#: tsearch/dict_simple.c:65
#, c-format
msgid "unrecognized simple dictionary parameter: \"%s\""
-msgstr "param�tre de dictionnaire simple non reconnu : � %s �"
+msgstr "paramètre de dictionnaire simple non reconnu : « %s »"
#: tsearch/dict_synonym.c:117
#, c-format
msgid "unrecognized synonym parameter: \"%s\""
-msgstr "param�tre synonyme non reconnu : � %s �"
+msgstr "paramètre synonyme non reconnu : « %s »"
#: tsearch/dict_synonym.c:124
#, c-format
msgid "missing Synonyms parameter"
-msgstr "param�tre Synonyms manquant"
+msgstr "paramètre Synonyms manquant"
#: tsearch/dict_synonym.c:131
#, c-format
msgid "could not open synonym file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier synonyme � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier synonyme « %s » : %m"
#: tsearch/dict_thesaurus.c:178
#, c-format
msgid "could not open thesaurus file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le th�saurus � %s � : %m"
+msgstr "n'a pas pu ouvrir le thésaurus « %s » : %m"
#: tsearch/dict_thesaurus.c:211
#, c-format
msgid "unexpected delimiter"
-msgstr "d�limiteur inattendu"
+msgstr "délimiteur inattendu"
#: tsearch/dict_thesaurus.c:261 tsearch/dict_thesaurus.c:277
#, c-format
@@ -17802,152 +17810,146 @@ msgstr "fin de ligne inattendue"
#: tsearch/dict_thesaurus.c:296
#, c-format
msgid "too many lexemes in thesaurus entry"
-msgstr "trop de lex�mes dans l'entre du th�saurus"
+msgstr "trop de lexèmes dans l'entre du thésaurus"
#: tsearch/dict_thesaurus.c:420
#, c-format
msgid "thesaurus sample word \"%s\" isn't recognized by subdictionary (rule %d)"
msgstr ""
-"le mot d'exemple � %s � du th�saurus n'est pas reconnu par le\n"
-"sous-dictionnaire (r�gle %d)"
+"le mot d'exemple « %s » du thésaurus n'est pas reconnu par le\n"
+"sous-dictionnaire (règle %d)"
#: tsearch/dict_thesaurus.c:426
#, c-format
msgid "thesaurus sample word \"%s\" is a stop word (rule %d)"
-msgstr "le mot d'exemple � %s � du th�saurus est un terme courant (r�gle %d)"
+msgstr "le mot d'exemple « %s » du thésaurus est un terme courant (règle %d)"
#: tsearch/dict_thesaurus.c:429
#, c-format
msgid "Use \"?\" to represent a stop word within a sample phrase."
-msgstr "Utilisez � ? � pour repr�senter un terme courant dans une phrase."
+msgstr "Utilisez « ? » pour représenter un terme courant dans une phrase."
#: tsearch/dict_thesaurus.c:575
#, c-format
msgid "thesaurus substitute word \"%s\" is a stop word (rule %d)"
-msgstr "le mot substitut � %s � du th�saurus est un terme courant (r�gle %d)"
+msgstr "le mot substitut « %s » du thésaurus est un terme courant (règle %d)"
#: tsearch/dict_thesaurus.c:582
#, c-format
msgid "thesaurus substitute word \"%s\" isn't recognized by subdictionary (rule %d)"
msgstr ""
-"le mot substitut � %s � du th�saurus n'est pas reconnu par le\n"
-"sous-dictionnaire (r�gle %d)"
+"le mot substitut « %s » du thésaurus n'est pas reconnu par le\n"
+"sous-dictionnaire (règle %d)"
#: tsearch/dict_thesaurus.c:594
#, c-format
msgid "thesaurus substitute phrase is empty (rule %d)"
-msgstr "la phrase substitut du th�saurus est vide (r�gle %d)"
+msgstr "la phrase substitut du thésaurus est vide (règle %d)"
#: tsearch/dict_thesaurus.c:632
#, c-format
msgid "multiple Dictionary parameters"
-msgstr "multiples param�tres Dictionary"
+msgstr "multiples paramètres Dictionary"
#: tsearch/dict_thesaurus.c:639
#, c-format
msgid "unrecognized Thesaurus parameter: \"%s\""
-msgstr "param�tre Thesaurus non reconnu : � %s �"
+msgstr "paramètre Thesaurus non reconnu : « %s »"
#: tsearch/dict_thesaurus.c:651
#, c-format
msgid "missing Dictionary parameter"
-msgstr "param�tre Dictionary manquant"
+msgstr "paramètre Dictionary manquant"
-#: tsearch/spell.c:382 tsearch/spell.c:399 tsearch/spell.c:408 tsearch/spell.c:1034
-#, fuzzy, c-format
-#| msgid "invalid data in file \"%s\""
+#: tsearch/spell.c:380 tsearch/spell.c:397 tsearch/spell.c:406 tsearch/spell.c:1034
+#, c-format
msgid "invalid affix flag \"%s\""
-msgstr "donn�es invalides dans le fichier � %s �"
+msgstr "drapeau d'affixe invalide « %s »"
-#: tsearch/spell.c:386 tsearch/spell.c:1038
-#, fuzzy, c-format
-#| msgid "%s: transfer rate \"%s\" is out of range\n"
+#: tsearch/spell.c:384 tsearch/spell.c:1038
+#, c-format
msgid "affix flag \"%s\" is out of range"
-msgstr "%s : le taux de transfert � %s � est en dehors des limites\n"
+msgstr "le drapeau d'affixe « %s » est en dehors des limites"
-#: tsearch/spell.c:416
-#, fuzzy, c-format
-#| msgid "invalid data in file \"%s\""
+#: tsearch/spell.c:414
+#, c-format
msgid "invalid character in affix flag \"%s\""
-msgstr "donn�es invalides dans le fichier � %s �"
+msgstr "données invalides dans le drapeau d'affixe « %s »"
-#: tsearch/spell.c:436
+#: tsearch/spell.c:434
#, c-format
-msgid "invalid affix flag \"%s\" with long flag value"
-msgstr ""
+msgid "invalid affix flag \"%s\" with \"long\" flag value"
+msgstr "drapeau d'affixe invalide « %s » avec la valeur de drapeau « long »"
-#: tsearch/spell.c:523
+#: tsearch/spell.c:522
#, c-format
msgid "could not open dictionary file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier dictionnaire � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier dictionnaire « %s » : %m"
#: tsearch/spell.c:740 utils/adt/regexp.c:204
#, c-format
msgid "invalid regular expression: %s"
msgstr "expression rationnelle invalide : %s"
-#: tsearch/spell.c:1161 tsearch/spell.c:1718
-#, fuzzy, c-format
-#| msgid "invalid cidr value: \"%s\""
+#: tsearch/spell.c:1161 tsearch/spell.c:1721
+#, c-format
msgid "invalid affix alias \"%s\""
-msgstr "valeur cidr invalide : � %s �"
+msgstr "alias d'affixe invalide « %s »"
-#: tsearch/spell.c:1210 tsearch/spell.c:1280 tsearch/spell.c:1424
+#: tsearch/spell.c:1211 tsearch/spell.c:1282 tsearch/spell.c:1426
#, c-format
msgid "could not open affix file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier affixe � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier affixe « %s » : %m"
-#: tsearch/spell.c:1264
-#, fuzzy, c-format
-#| msgid "Ispell dictionary supports only default flag value"
-msgid "Ispell dictionary supports only default, long and num flag value"
-msgstr "le dictionnaire Ispell supporte seulement la valeur par d�faut du drapeau"
+#: tsearch/spell.c:1265
+#, c-format
+msgid "Ispell dictionary supports only \"default\", \"long\", and \"num\" flag values"
+msgstr "le dictionnaire Ispell supporte seulement les valeurs de drapeau « default », « long »et « num »"
-#: tsearch/spell.c:1307
-#, fuzzy, c-format
-#| msgid "%s: invalid number of parallel jobs\n"
+#: tsearch/spell.c:1309
+#, c-format
msgid "invalid number of flag vector aliases"
-msgstr "%s : nombre de jobs en parall�le invalide\n"
+msgstr "nombre d'alias de vecteur de drapeau invalide"
-#: tsearch/spell.c:1540
+#: tsearch/spell.c:1542
#, c-format
msgid "affix file contains both old-style and new-style commands"
msgstr "le fichier d'affixes contient des commandes ancien et nouveau style"
-#: tsearch/to_tsany.c:170 utils/adt/tsvector.c:270 utils/adt/tsvector_op.c:1066
+#: tsearch/to_tsany.c:170 utils/adt/tsvector.c:270 utils/adt/tsvector_op.c:1133
#, c-format
msgid "string is too long for tsvector (%d bytes, max %d bytes)"
-msgstr "la cha�ne est trop longue (%d octets, max %d octets)"
+msgstr "la chaîne est trop longue (%d octets, max %d octets)"
#: tsearch/ts_locale.c:177
#, c-format
msgid "line %d of configuration file \"%s\": \"%s\""
-msgstr "ligne %d du fichier de configuration � %s � : � %s �"
+msgstr "ligne %d du fichier de configuration « %s » : « %s »"
#: tsearch/ts_locale.c:299
#, c-format
msgid "conversion from wchar_t to server encoding failed: %m"
-msgstr "�chec de l'encodage de wchar_t vers l'encodage du serveur : %m"
+msgstr "échec de l'encodage de wchar_t vers l'encodage du serveur : %m"
#: tsearch/ts_parse.c:390 tsearch/ts_parse.c:397 tsearch/ts_parse.c:566 tsearch/ts_parse.c:573
#, c-format
msgid "word is too long to be indexed"
-msgstr "le mot est trop long pour �tre index�"
+msgstr "le mot est trop long pour être indexé"
#: tsearch/ts_parse.c:391 tsearch/ts_parse.c:398 tsearch/ts_parse.c:567 tsearch/ts_parse.c:574
#, c-format
msgid "Words longer than %d characters are ignored."
-msgstr "Les mots de plus de %d caract�res sont ignor�s."
+msgstr "Les mots de plus de %d caractères sont ignorés."
#: tsearch/ts_utils.c:51
#, c-format
msgid "invalid text search configuration file name \"%s\""
-msgstr "nom du fichier de configuration de la recherche plein texte invalide : � %s �"
+msgstr "nom du fichier de configuration de la recherche plein texte invalide : « %s »"
#: tsearch/ts_utils.c:83
#, c-format
msgid "could not open stop-word file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier des termes courants � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier des termes courants « %s » : %m"
#: tsearch/wparser.c:306
#, c-format
@@ -17957,7 +17959,7 @@ msgstr "l'analyseur de recherche plein texte ne supporte pas headline"
#: tsearch/wparser_def.c:2583
#, c-format
msgid "unrecognized headline parameter: \"%s\""
-msgstr "param�tre headline � %s � non reconnu"
+msgstr "paramètre headline « %s » non reconnu"
#: tsearch/wparser_def.c:2592
#, c-format
@@ -17967,17 +17969,17 @@ msgstr "MinWords doit avoir une valeur plus petite que celle de MaxWords"
#: tsearch/wparser_def.c:2596
#, c-format
msgid "MinWords should be positive"
-msgstr "MinWords doit �tre positif"
+msgstr "MinWords doit être positif"
#: tsearch/wparser_def.c:2600
#, c-format
msgid "ShortWord should be >= 0"
-msgstr "ShortWord devrait �tre positif ou nul"
+msgstr "ShortWord devrait être positif ou nul"
#: tsearch/wparser_def.c:2604
#, c-format
msgid "MaxFragments should be >= 0"
-msgstr "MaxFragments devrait �tre positif ou nul"
+msgstr "MaxFragments devrait être positif ou nul"
#: utils/adt/acl.c:170 utils/adt/name.c:91
#, c-format
@@ -17987,17 +17989,17 @@ msgstr "identifiant trop long"
#: utils/adt/acl.c:171 utils/adt/name.c:92
#, c-format
msgid "Identifier must be less than %d characters."
-msgstr "L'identifiant doit faire moins de %d caract�res."
+msgstr "L'identifiant doit faire moins de %d caractères."
#: utils/adt/acl.c:257
#, c-format
msgid "unrecognized key word: \"%s\""
-msgstr "mot cl� non reconnu : � %s �"
+msgstr "mot clé non reconnu : « %s »"
#: utils/adt/acl.c:258
#, c-format
msgid "ACL key word must be \"group\" or \"user\"."
-msgstr "le mot cl� ACL doit �tre soit � group � soit � user �."
+msgstr "le mot clé ACL doit être soit « group » soit « user »."
#: utils/adt/acl.c:263
#, c-format
@@ -18007,32 +18009,32 @@ msgstr "nom manquant"
#: utils/adt/acl.c:264
#, c-format
msgid "A name must follow the \"group\" or \"user\" key word."
-msgstr "Un nom doit suivre le mot cl� � group � ou � user �."
+msgstr "Un nom doit suivre le mot clé « group » ou « user »."
#: utils/adt/acl.c:270
#, c-format
msgid "missing \"=\" sign"
-msgstr "signe � = � manquant"
+msgstr "signe « = » manquant"
#: utils/adt/acl.c:323
#, c-format
msgid "invalid mode character: must be one of \"%s\""
-msgstr "mode caract�re invalide : doit faire partie de � %s �"
+msgstr "mode caractère invalide : doit faire partie de « %s »"
#: utils/adt/acl.c:345
#, c-format
msgid "a name must follow the \"/\" sign"
-msgstr "un nom doit suivre le signe � / �"
+msgstr "un nom doit suivre le signe « / »"
#: utils/adt/acl.c:353
#, c-format
msgid "defaulting grantor to user ID %u"
-msgstr "par d�faut, le � donneur de droits � devient l'utilisateur d'identifiant %u"
+msgstr "par défaut, le « donneur de droits » devient l'utilisateur d'identifiant %u"
#: utils/adt/acl.c:544
#, c-format
msgid "ACL array contains wrong data type"
-msgstr "le tableau ACL contient un type de donn�es incorrect"
+msgstr "le tableau ACL contient un type de données incorrect"
#: utils/adt/acl.c:548
#, c-format
@@ -18047,138 +18049,132 @@ msgstr "les tableaux d'ACL ne doivent pas contenir de valeurs NULL"
#: utils/adt/acl.c:576
#, c-format
msgid "extra garbage at the end of the ACL specification"
-msgstr "donn�es superflues � la fin de la sp�cification de l'ACL"
+msgstr "données superflues à la fin de la spécification de l'ACL"
#: utils/adt/acl.c:1196
#, c-format
msgid "grant options cannot be granted back to your own grantor"
-msgstr "les options grant ne peuvent pas �tre rendues � votre propre donateur"
+msgstr "les options grant ne peuvent pas être rendues à votre propre donateur"
#: utils/adt/acl.c:1257
#, c-format
msgid "dependent privileges exist"
-msgstr "des privil�ges d�pendants existent"
+msgstr "des privilèges dépendants existent"
#: utils/adt/acl.c:1258
#, c-format
msgid "Use CASCADE to revoke them too."
-msgstr "Utilisez CASCADE pour les r�voquer aussi."
+msgstr "Utilisez CASCADE pour les révoquer aussi."
#: utils/adt/acl.c:1537
#, c-format
msgid "aclinsert is no longer supported"
-msgstr "aclinsert n'est plus support�"
+msgstr "aclinsert n'est plus supporté"
#: utils/adt/acl.c:1547
#, c-format
msgid "aclremove is no longer supported"
-msgstr "aclremove n'est plus support�"
+msgstr "aclremove n'est plus supporté"
#: utils/adt/acl.c:1633 utils/adt/acl.c:1687
#, c-format
msgid "unrecognized privilege type: \"%s\""
-msgstr "type de droit non reconnu : � %s �"
+msgstr "type de droit non reconnu : « %s »"
#: utils/adt/acl.c:3427 utils/adt/regproc.c:123 utils/adt/regproc.c:144 utils/adt/regproc.c:319
#, c-format
msgid "function \"%s\" does not exist"
-msgstr "la fonction � %s � n'existe pas"
+msgstr "la fonction « %s » n'existe pas"
#: utils/adt/acl.c:4881
#, c-format
msgid "must be member of role \"%s\""
-msgstr "doit �tre un membre du r�le � %s �"
-
-#: utils/adt/acl.c:5279 utils/adt/acl.c:5285
-#, c-format
-msgid "role \"%s\" is reserved"
-msgstr "le r�le � %s � est r�serv�"
+msgstr "doit être un membre du rôle « %s »"
-#: utils/adt/array_expanded.c:276 utils/adt/arrayfuncs.c:931 utils/adt/arrayfuncs.c:1519 utils/adt/arrayfuncs.c:3251 utils/adt/arrayfuncs.c:3389 utils/adt/arrayfuncs.c:5864 utils/adt/arrayfuncs.c:6175 utils/adt/arrayutils.c:93 utils/adt/arrayutils.c:102 utils/adt/arrayutils.c:109
+#: utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:931 utils/adt/arrayfuncs.c:1519 utils/adt/arrayfuncs.c:3251 utils/adt/arrayfuncs.c:3389 utils/adt/arrayfuncs.c:5848 utils/adt/arrayfuncs.c:6159 utils/adt/arrayutils.c:93 utils/adt/arrayutils.c:102 utils/adt/arrayutils.c:109
#, c-format
msgid "array size exceeds the maximum allowed (%d)"
-msgstr "la taille du tableau d�passe le maximum permis (%d)"
+msgstr "la taille du tableau dépasse le maximum permis (%d)"
-#: utils/adt/array_userfuncs.c:67 utils/adt/array_userfuncs.c:529 utils/adt/array_userfuncs.c:609 utils/adt/json.c:1759 utils/adt/json.c:1854 utils/adt/json.c:1892 utils/adt/jsonb.c:1126 utils/adt/jsonb.c:1155 utils/adt/jsonb.c:1591 utils/adt/jsonb.c:1755 utils/adt/jsonb.c:1765
+#: utils/adt/array_userfuncs.c:79 utils/adt/array_userfuncs.c:541 utils/adt/array_userfuncs.c:621 utils/adt/json.c:1759 utils/adt/json.c:1854 utils/adt/json.c:1892 utils/adt/jsonb.c:1126 utils/adt/jsonb.c:1155 utils/adt/jsonb.c:1591 utils/adt/jsonb.c:1755 utils/adt/jsonb.c:1765
#, c-format
msgid "could not determine input data type"
-msgstr "n'a pas pu d�terminer le type de donn�es date en entr�e"
+msgstr "n'a pas pu déterminer le type de données date en entrée"
-#: utils/adt/array_userfuncs.c:72
+#: utils/adt/array_userfuncs.c:84
#, c-format
msgid "input data type is not an array"
-msgstr "le type de donn�es en entr�e n'est pas un tableau"
+msgstr "le type de données en entrée n'est pas un tableau"
-#: utils/adt/array_userfuncs.c:120 utils/adt/array_userfuncs.c:174 utils/adt/arrayfuncs.c:1322 utils/adt/float.c:1230 utils/adt/float.c:1289 utils/adt/float.c:3558 utils/adt/float.c:3574 utils/adt/int.c:623 utils/adt/int.c:652 utils/adt/int.c:673 utils/adt/int.c:704 utils/adt/int.c:737 utils/adt/int.c:759 utils/adt/int.c:907 utils/adt/int.c:928 utils/adt/int.c:955 utils/adt/int.c:995 utils/adt/int.c:1016 utils/adt/int.c:1043
-#: utils/adt/int.c:1076 utils/adt/int.c:1159 utils/adt/int8.c:1298 utils/adt/numeric.c:2907 utils/adt/numeric.c:2916 utils/adt/varbit.c:1173 utils/adt/varbit.c:1565 utils/adt/varlena.c:1055 utils/adt/varlena.c:2807
+#: utils/adt/array_userfuncs.c:132 utils/adt/array_userfuncs.c:186 utils/adt/arrayfuncs.c:1322 utils/adt/float.c:1228 utils/adt/float.c:1287 utils/adt/float.c:3556 utils/adt/float.c:3572 utils/adt/int.c:623 utils/adt/int.c:652 utils/adt/int.c:673 utils/adt/int.c:704 utils/adt/int.c:737 utils/adt/int.c:759 utils/adt/int.c:907 utils/adt/int.c:928 utils/adt/int.c:955 utils/adt/int.c:995 utils/adt/int.c:1016 utils/adt/int.c:1043
+#: utils/adt/int.c:1076 utils/adt/int.c:1159 utils/adt/int8.c:1298 utils/adt/numeric.c:2903 utils/adt/numeric.c:2912 utils/adt/varbit.c:1173 utils/adt/varbit.c:1575 utils/adt/varlena.c:1055 utils/adt/varlena.c:2807
#, c-format
msgid "integer out of range"
msgstr "entier en dehors des limites"
-#: utils/adt/array_userfuncs.c:127 utils/adt/array_userfuncs.c:184
+#: utils/adt/array_userfuncs.c:139 utils/adt/array_userfuncs.c:196
#, c-format
msgid "argument must be empty or one-dimensional array"
-msgstr "l'argument doit �tre vide ou doit �tre un tableau � une dimension"
+msgstr "l'argument doit être vide ou doit être un tableau à une dimension"
-#: utils/adt/array_userfuncs.c:266 utils/adt/array_userfuncs.c:305 utils/adt/array_userfuncs.c:342 utils/adt/array_userfuncs.c:371 utils/adt/array_userfuncs.c:399
+#: utils/adt/array_userfuncs.c:278 utils/adt/array_userfuncs.c:317 utils/adt/array_userfuncs.c:354 utils/adt/array_userfuncs.c:383 utils/adt/array_userfuncs.c:411
#, c-format
msgid "cannot concatenate incompatible arrays"
-msgstr "ne peut pas concat�ner des tableaux non compatibles"
+msgstr "ne peut pas concaténer des tableaux non compatibles"
-#: utils/adt/array_userfuncs.c:267
+#: utils/adt/array_userfuncs.c:279
#, c-format
msgid "Arrays with element types %s and %s are not compatible for concatenation."
msgstr ""
-"Les tableaux avec les types d'�l�ment %s et %s ne sont pas compatibles\n"
-"pour la concat�nation."
+"Les tableaux avec les types d'élément %s et %s ne sont pas compatibles\n"
+"pour la concaténation."
-#: utils/adt/array_userfuncs.c:306
+#: utils/adt/array_userfuncs.c:318
#, c-format
msgid "Arrays of %d and %d dimensions are not compatible for concatenation."
msgstr ""
"Les tableaux de dimensions %d et %d ne sont pas compatiblee pour la\n"
-"concat�nation."
+"concaténation."
-#: utils/adt/array_userfuncs.c:343
+#: utils/adt/array_userfuncs.c:355
#, c-format
msgid "Arrays with differing element dimensions are not compatible for concatenation."
msgstr ""
-"Les tableaux de dimensions diff�rentes ne sont pas compatibles pour\n"
-"une concat�nation."
+"Les tableaux de dimensions différentes ne sont pas compatibles pour\n"
+"une concaténation."
-#: utils/adt/array_userfuncs.c:372 utils/adt/array_userfuncs.c:400
+#: utils/adt/array_userfuncs.c:384 utils/adt/array_userfuncs.c:412
#, c-format
msgid "Arrays with differing dimensions are not compatible for concatenation."
msgstr ""
-"Les tableaux de dimensions diff�rentes ne sont pas compatibles pour\n"
-"une concat�nation."
+"Les tableaux de dimensions différentes ne sont pas compatibles pour\n"
+"une concaténation."
-#: utils/adt/array_userfuncs.c:468 utils/adt/arrayfuncs.c:1284 utils/adt/arrayfuncs.c:3357 utils/adt/arrayfuncs.c:5764
+#: utils/adt/array_userfuncs.c:480 utils/adt/arrayfuncs.c:1284 utils/adt/arrayfuncs.c:3357 utils/adt/arrayfuncs.c:5754
#, c-format
msgid "invalid number of dimensions: %d"
msgstr "nombre de dimensions invalides : %d"
-#: utils/adt/array_userfuncs.c:725 utils/adt/array_userfuncs.c:876
-#, fuzzy, c-format
-#| msgid "removing elements from multidimensional arrays is not supported"
+#: utils/adt/array_userfuncs.c:737 utils/adt/array_userfuncs.c:889
+#, c-format
msgid "searching for elements in multidimensional arrays is not supported"
-msgstr "la suppression d'�l�ments de tableaux multidimensionnels n'est pas support�e"
+msgstr "la recherche d'éléments dans des tableaux multidimensionnels n'est pas supportée"
-#: utils/adt/array_userfuncs.c:749
+#: utils/adt/array_userfuncs.c:761
#, c-format
msgid "initial position must not be null"
-msgstr "la position initiale ne doit pas �tre NULL"
+msgstr "la position initiale ne doit pas être NULL"
#: utils/adt/arrayfuncs.c:268 utils/adt/arrayfuncs.c:282 utils/adt/arrayfuncs.c:293 utils/adt/arrayfuncs.c:315 utils/adt/arrayfuncs.c:330 utils/adt/arrayfuncs.c:344 utils/adt/arrayfuncs.c:350 utils/adt/arrayfuncs.c:357 utils/adt/arrayfuncs.c:488 utils/adt/arrayfuncs.c:504 utils/adt/arrayfuncs.c:515 utils/adt/arrayfuncs.c:530 utils/adt/arrayfuncs.c:551 utils/adt/arrayfuncs.c:581 utils/adt/arrayfuncs.c:588 utils/adt/arrayfuncs.c:596
#: utils/adt/arrayfuncs.c:630 utils/adt/arrayfuncs.c:653 utils/adt/arrayfuncs.c:673 utils/adt/arrayfuncs.c:785 utils/adt/arrayfuncs.c:794 utils/adt/arrayfuncs.c:824 utils/adt/arrayfuncs.c:839 utils/adt/arrayfuncs.c:892
#, c-format
msgid "malformed array literal: \"%s\""
-msgstr "tableau lit�ral mal form� : � %s �"
+msgstr "tableau litéral mal formé : « %s »"
#: utils/adt/arrayfuncs.c:269
#, c-format
msgid "\"[\" must introduce explicitly-specified array dimensions."
-msgstr "� [ � doit introduire les dimensions explicites du tableau"
+msgstr "« [ » doit introduire les dimensions explicites du tableau"
#: utils/adt/arrayfuncs.c:283
#, c-format
@@ -18188,49 +18184,49 @@ msgstr "Valeur manquante de la dimension du tableau."
#: utils/adt/arrayfuncs.c:294 utils/adt/arrayfuncs.c:331
#, c-format
msgid "Missing \"%s\" after array dimensions."
-msgstr "� %s � manquant apr�s les dimensions du tableau."
+msgstr "« %s » manquant après les dimensions du tableau."
#: utils/adt/arrayfuncs.c:303 utils/adt/arrayfuncs.c:2870 utils/adt/arrayfuncs.c:2902 utils/adt/arrayfuncs.c:2917
#, c-format
msgid "upper bound cannot be less than lower bound"
-msgstr "la limite sup�rieure ne peut pas �tre plus petite que la limite inf�rieure"
+msgstr "la limite supérieure ne peut pas être plus petite que la limite inférieure"
#: utils/adt/arrayfuncs.c:316
#, c-format
msgid "Array value must start with \"{\" or dimension information."
msgstr ""
-"La valeur du tableau doit commencer avec � { � ou avec l'information de la\n"
+"La valeur du tableau doit commencer avec « { » ou avec l'information de la\n"
"dimension."
#: utils/adt/arrayfuncs.c:345
#, c-format
msgid "Array contents must start with \"{\"."
-msgstr "Le contenu du tableau doit commencer avec � { �."
+msgstr "Le contenu du tableau doit commencer avec « { »."
#: utils/adt/arrayfuncs.c:351 utils/adt/arrayfuncs.c:358
#, c-format
msgid "Specified array dimensions do not match array contents."
-msgstr "Les dimensions sp�cifi�es du tableau ne correspondent pas au contenu du tableau."
+msgstr "Les dimensions spécifiées du tableau ne correspondent pas au contenu du tableau."
#: utils/adt/arrayfuncs.c:489 utils/adt/arrayfuncs.c:516 utils/adt/rangetypes.c:2124 utils/adt/rangetypes.c:2132 utils/adt/rowtypes.c:208 utils/adt/rowtypes.c:216
#, c-format
msgid "Unexpected end of input."
-msgstr "Fin de l'entr�e inattendue."
+msgstr "Fin de l'entrée inattendue."
#: utils/adt/arrayfuncs.c:505 utils/adt/arrayfuncs.c:552 utils/adt/arrayfuncs.c:582 utils/adt/arrayfuncs.c:631
#, c-format
msgid "Unexpected \"%c\" character."
-msgstr "Caract�re � %c � inattendu."
+msgstr "Caractère « %c » inattendu."
#: utils/adt/arrayfuncs.c:531 utils/adt/arrayfuncs.c:654
#, c-format
msgid "Unexpected array element."
-msgstr "�l�ment de tableau inattendu."
+msgstr "Élément de tableau inattendu."
#: utils/adt/arrayfuncs.c:589
#, c-format
msgid "Unmatched \"%c\" character."
-msgstr "Caract�re � %c � sans correspondance."
+msgstr "Caractère « %c » sans correspondance."
#: utils/adt/arrayfuncs.c:597
#, c-format
@@ -18242,7 +18238,7 @@ msgstr ""
#: utils/adt/arrayfuncs.c:674
#, c-format
msgid "Junk after closing right brace."
-msgstr "Probl�me apr�s la parenth�se droite fermante."
+msgstr "Problème après la parenthèse droite fermante."
#: utils/adt/arrayfuncs.c:1295
#, c-format
@@ -18252,17 +18248,17 @@ msgstr "drapeaux de tableau invalides"
#: utils/adt/arrayfuncs.c:1303
#, c-format
msgid "wrong element type"
-msgstr "mauvais type d'�l�ment"
+msgstr "mauvais type d'élément"
#: utils/adt/arrayfuncs.c:1353 utils/adt/rangetypes.c:334 utils/cache/lsyscache.c:2651
#, c-format
msgid "no binary input function available for type %s"
-msgstr "aucune fonction d'entr�e binaire disponible pour le type %s"
+msgstr "aucune fonction d'entrée binaire disponible pour le type %s"
#: utils/adt/arrayfuncs.c:1493
#, c-format
msgid "improper binary format in array element %d"
-msgstr "format binaire mal con�u dans l'�l�ment du tableau %d"
+msgstr "format binaire mal conçu dans l'élément du tableau %d"
#: utils/adt/arrayfuncs.c:1574 utils/adt/rangetypes.c:339 utils/cache/lsyscache.c:2684
#, c-format
@@ -18272,9 +18268,9 @@ msgstr "aucune fonction de sortie binaire disponible pour le type %s"
#: utils/adt/arrayfuncs.c:2052
#, c-format
msgid "slices of fixed-length arrays not implemented"
-msgstr "les morceaux des tableaux � longueur fixe ne sont pas impl�ment�s"
+msgstr "les morceaux des tableaux à longueur fixe ne sont pas implémentés"
-#: utils/adt/arrayfuncs.c:2230 utils/adt/arrayfuncs.c:2252 utils/adt/arrayfuncs.c:2301 utils/adt/arrayfuncs.c:2537 utils/adt/arrayfuncs.c:2848 utils/adt/arrayfuncs.c:5744 utils/adt/arrayfuncs.c:5776 utils/adt/arrayfuncs.c:5793 utils/adt/json.c:2290 utils/adt/json.c:2365 utils/adt/jsonb.c:1369 utils/adt/jsonb.c:1455 utils/adt/jsonfuncs.c:3537 utils/adt/jsonfuncs.c:3582 utils/adt/jsonfuncs.c:3629
+#: utils/adt/arrayfuncs.c:2230 utils/adt/arrayfuncs.c:2252 utils/adt/arrayfuncs.c:2301 utils/adt/arrayfuncs.c:2537 utils/adt/arrayfuncs.c:2848 utils/adt/arrayfuncs.c:5740 utils/adt/arrayfuncs.c:5766 utils/adt/arrayfuncs.c:5777 utils/adt/json.c:2290 utils/adt/json.c:2365 utils/adt/jsonb.c:1369 utils/adt/jsonb.c:1455 utils/adt/jsonfuncs.c:3529 utils/adt/jsonfuncs.c:3574 utils/adt/jsonfuncs.c:3621
#, c-format
msgid "wrong number of array subscripts"
msgstr "mauvais nombre d'indices du tableau"
@@ -18282,30 +18278,29 @@ msgstr "mauvais nombre d'indices du tableau"
#: utils/adt/arrayfuncs.c:2235 utils/adt/arrayfuncs.c:2343 utils/adt/arrayfuncs.c:2601 utils/adt/arrayfuncs.c:2907
#, c-format
msgid "array subscript out of range"
-msgstr "indice du tableau en dehors de l'�chelle"
+msgstr "indice du tableau en dehors de l'échelle"
#: utils/adt/arrayfuncs.c:2240
#, c-format
msgid "cannot assign null value to an element of a fixed-length array"
-msgstr "ne peut pas affecter une valeur NULL � un �l�ment d'un tableau � longueur fixe"
+msgstr "ne peut pas affecter une valeur NULL à un élément d'un tableau à longueur fixe"
#: utils/adt/arrayfuncs.c:2795
#, c-format
msgid "updates on slices of fixed-length arrays not implemented"
msgstr ""
-"les mises � jour de morceaux des tableaux � longueur fixe ne sont pas\n"
-"impl�ment�es"
+"les mises à jour de morceaux des tableaux à longueur fixe ne sont pas\n"
+"implémentées"
#: utils/adt/arrayfuncs.c:2826
-#, fuzzy, c-format
-#| msgid "array subscript must have type integer"
+#, c-format
msgid "array slice subscript must provide both boundaries"
-msgstr "l'indice d'un tableau doit �tre de type entier"
+msgstr "la tranche d'indice de tableau doit être fournir les deux limites"
#: utils/adt/arrayfuncs.c:2827
#, c-format
msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified."
-msgstr ""
+msgstr "Les limites de tranches doivent être entièrement spécifiées lors de l'assignation d'une valeur d'un tableau vide à une tranche"
#: utils/adt/arrayfuncs.c:2838 utils/adt/arrayfuncs.c:2933
#, c-format
@@ -18315,79 +18310,69 @@ msgstr "tableau source trop petit"
#: utils/adt/arrayfuncs.c:3513
#, c-format
msgid "null array element not allowed in this context"
-msgstr "�l�ment NULL de tableau interdit dans ce contexte"
+msgstr "élément NULL de tableau interdit dans ce contexte"
#: utils/adt/arrayfuncs.c:3615 utils/adt/arrayfuncs.c:3786 utils/adt/arrayfuncs.c:4060
#, c-format
msgid "cannot compare arrays of different element types"
-msgstr "ne peut pas comparer des tableaux ayant des types d'�l�ments diff�rents"
+msgstr "ne peut pas comparer des tableaux ayant des types d'éléments différents"
#: utils/adt/arrayfuncs.c:3962 utils/adt/rangetypes.c:1253
#, c-format
msgid "could not identify a hash function for type %s"
msgstr "n'a pas pu identifier une fonction de hachage pour le type %s"
-#: utils/adt/arrayfuncs.c:5156
+#: utils/adt/arrayfuncs.c:5154
#, c-format
msgid "data type %s is not an array type"
-msgstr "le type de donn�es %s n'est pas un type tableau"
+msgstr "le type de données %s n'est pas un type tableau"
-#: utils/adt/arrayfuncs.c:5213
+#: utils/adt/arrayfuncs.c:5209
#, c-format
msgid "cannot accumulate null arrays"
msgstr "ne peut pas accumuler des tableaux NULL"
-#: utils/adt/arrayfuncs.c:5241
+#: utils/adt/arrayfuncs.c:5237
#, c-format
msgid "cannot accumulate empty arrays"
-msgstr "ne peut pas concat�ner des tableaux vides"
+msgstr "ne peut pas concaténer des tableaux vides"
-#: utils/adt/arrayfuncs.c:5270 utils/adt/arrayfuncs.c:5276
+#: utils/adt/arrayfuncs.c:5266 utils/adt/arrayfuncs.c:5272
#, c-format
msgid "cannot accumulate arrays of different dimensionality"
-msgstr "ne peut pas accumuler des tableaux de dimensions diff�rentes"
+msgstr "ne peut pas accumuler des tableaux de dimensions différentes"
-#: utils/adt/arrayfuncs.c:5642 utils/adt/arrayfuncs.c:5682
+#: utils/adt/arrayfuncs.c:5638 utils/adt/arrayfuncs.c:5678
#, c-format
msgid "dimension array or low bound array cannot be null"
-msgstr "la dimension ou la limite basse du tableau ne peut pas �tre NULL"
+msgstr "la dimension ou la limite basse du tableau ne peut pas être NULL"
-#: utils/adt/arrayfuncs.c:5745 utils/adt/arrayfuncs.c:5777
+#: utils/adt/arrayfuncs.c:5741 utils/adt/arrayfuncs.c:5767
#, c-format
msgid "Dimension array must be one dimensional."
msgstr "le tableau doit avoir une seule dimension"
-#: utils/adt/arrayfuncs.c:5750 utils/adt/arrayfuncs.c:5782
-#, c-format
-msgid "wrong range of array subscripts"
-msgstr "mauvais �chelle des indices du tableau"
-
-#: utils/adt/arrayfuncs.c:5751 utils/adt/arrayfuncs.c:5783
-#, c-format
-msgid "Lower bound of dimension array must be one."
-msgstr "La limite inf�rieure du tableau doit valoir un."
-
-#: utils/adt/arrayfuncs.c:5756 utils/adt/arrayfuncs.c:5788
+#: utils/adt/arrayfuncs.c:5746 utils/adt/arrayfuncs.c:5772
#, c-format
msgid "dimension values cannot be null"
-msgstr "les valeurs de dimension ne peuvent pas �tre NULL"
+msgstr "les valeurs de dimension ne peuvent pas être NULL"
-#: utils/adt/arrayfuncs.c:5794
+#: utils/adt/arrayfuncs.c:5778
#, c-format
msgid "Low bound array has different size than dimensions array."
-msgstr "La limite basse du tableau a une taille diff�rentes des dimensions du tableau."
+msgstr "La limite basse du tableau a une taille différentes des dimensions du tableau."
-#: utils/adt/arrayfuncs.c:6040
+#: utils/adt/arrayfuncs.c:6024
#, c-format
msgid "removing elements from multidimensional arrays is not supported"
-msgstr "la suppression d'�l�ments de tableaux multidimensionnels n'est pas support�e"
+msgstr "la suppression d'éléments de tableaux multidimensionnels n'est pas supportée"
-#: utils/adt/arrayfuncs.c:6317
+#: utils/adt/arrayfuncs.c:6301
#, c-format
msgid "thresholds must be one-dimensional array"
-msgstr "les limites doivent �tre un tableau � une dimension"
+msgstr "les limites doivent être un tableau à une dimension"
-#: utils/adt/arrayfuncs.c:6322
+#: utils/adt/arrayfuncs.c:6306
#, c-format
msgid "thresholds array must not contain NULLs"
msgstr "le tableau de limites ne doit pas contenir de valeurs NULL"
@@ -18395,7 +18380,7 @@ msgstr "le tableau de limites ne doit pas contenir de valeurs NULL"
#: utils/adt/arrayutils.c:209
#, c-format
msgid "typmod array must be type cstring[]"
-msgstr "le tableau typmod doit �tre de type cstring[]"
+msgstr "le tableau typmod doit être de type cstring[]"
#: utils/adt/arrayutils.c:214
#, c-format
@@ -18410,28 +18395,28 @@ msgstr "le tableau typmod ne doit pas contenir de valeurs NULL"
#: utils/adt/ascii.c:75
#, c-format
msgid "encoding conversion from %s to ASCII not supported"
-msgstr "la conversion de l'encodage de %s vers l'ASCII n'est pas support�e"
+msgstr "la conversion de l'encodage de %s vers l'ASCII n'est pas supportée"
#: utils/adt/bool.c:153
#, c-format
msgid "invalid input syntax for type boolean: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type bool�en : � %s �"
+msgstr "syntaxe en entrée invalide pour le type booléen : « %s »"
#: utils/adt/cash.c:246
#, c-format
msgid "invalid input syntax for type money: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type money : � %s �"
+msgstr "syntaxe en entrée invalide pour le type money : « %s »"
-#: utils/adt/cash.c:607 utils/adt/cash.c:657 utils/adt/cash.c:708 utils/adt/cash.c:757 utils/adt/cash.c:809 utils/adt/cash.c:859 utils/adt/float.c:857 utils/adt/float.c:921 utils/adt/float.c:3317 utils/adt/float.c:3380 utils/adt/geo_ops.c:4085 utils/adt/int.c:719 utils/adt/int.c:861 utils/adt/int.c:969 utils/adt/int.c:1058 utils/adt/int.c:1097 utils/adt/int.c:1125 utils/adt/int8.c:597 utils/adt/int8.c:657 utils/adt/int8.c:897
-#: utils/adt/int8.c:1005 utils/adt/int8.c:1094 utils/adt/int8.c:1202 utils/adt/numeric.c:6800 utils/adt/numeric.c:7089 utils/adt/numeric.c:8102 utils/adt/timestamp.c:3446
+#: utils/adt/cash.c:607 utils/adt/cash.c:657 utils/adt/cash.c:708 utils/adt/cash.c:757 utils/adt/cash.c:809 utils/adt/cash.c:859 utils/adt/float.c:855 utils/adt/float.c:919 utils/adt/float.c:3315 utils/adt/float.c:3378 utils/adt/geo_ops.c:4093 utils/adt/int.c:719 utils/adt/int.c:861 utils/adt/int.c:969 utils/adt/int.c:1058 utils/adt/int.c:1097 utils/adt/int.c:1125 utils/adt/int8.c:597 utils/adt/int8.c:657 utils/adt/int8.c:897
+#: utils/adt/int8.c:1005 utils/adt/int8.c:1094 utils/adt/int8.c:1202 utils/adt/numeric.c:6818 utils/adt/numeric.c:7107 utils/adt/numeric.c:8120 utils/adt/timestamp.c:3499
#, c-format
msgid "division by zero"
-msgstr "division par z�ro"
+msgstr "division par zéro"
#: utils/adt/char.c:169
#, c-format
msgid "\"char\" out of range"
-msgstr "� char � hors des limites"
+msgstr "« char » hors des limites"
#: utils/adt/date.c:67 utils/adt/timestamp.c:94 utils/adt/varbit.c:52 utils/adt/varchar.c:45
#, c-format
@@ -18441,24 +18426,24 @@ msgstr "modifieur de type invalide"
#: utils/adt/date.c:72
#, c-format
msgid "TIME(%d)%s precision must not be negative"
-msgstr "la pr�cision de TIME(%d)%s ne doit pas �tre n�gative"
+msgstr "la précision de TIME(%d)%s ne doit pas être négative"
#: utils/adt/date.c:78
#, c-format
msgid "TIME(%d)%s precision reduced to maximum allowed, %d"
-msgstr "la pr�cision de TIME(%d)%s a �t� r�duit au maximum autoris�e, %d"
+msgstr "la précision de TIME(%d)%s a été réduit au maximum autorisée, %d"
-#: utils/adt/date.c:141 utils/adt/datetime.c:1277 utils/adt/datetime.c:2148
+#: utils/adt/date.c:141 utils/adt/datetime.c:1278 utils/adt/datetime.c:2191
#, c-format
msgid "date/time value \"current\" is no longer supported"
-msgstr "la valeur � current � pour la date et heure n'est plus support�e"
+msgstr "la valeur « current » pour la date et heure n'est plus supportée"
#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:3529 utils/adt/formatting.c:3538
#, c-format
msgid "date out of range: \"%s\""
-msgstr "date en dehors des limites : � %s �"
+msgstr "date en dehors des limites : « %s »"
-#: utils/adt/date.c:222 utils/adt/date.c:456 utils/adt/date.c:480 utils/adt/xml.c:2029
+#: utils/adt/date.c:222 utils/adt/date.c:456 utils/adt/date.c:480 utils/adt/xml.c:2027
#, c-format
msgid "date out of range"
msgstr "date en dehors des limites"
@@ -18483,10 +18468,10 @@ msgstr "ne peut pas soustraire les valeurs dates infinies"
msgid "date out of range for timestamp"
msgstr "date en dehors des limites pour un timestamp"
-#: utils/adt/date.c:1022 utils/adt/date.c:1068 utils/adt/date.c:1678 utils/adt/date.c:1714 utils/adt/date.c:1748 utils/adt/date.c:2592 utils/adt/formatting.c:3404 utils/adt/formatting.c:3436 utils/adt/formatting.c:3504 utils/adt/json.c:1534 utils/adt/json.c:1556 utils/adt/jsonb.c:823 utils/adt/jsonb.c:847 utils/adt/nabstime.c:455 utils/adt/nabstime.c:498 utils/adt/nabstime.c:528 utils/adt/nabstime.c:571 utils/adt/timestamp.c:224
-#: utils/adt/timestamp.c:268 utils/adt/timestamp.c:726 utils/adt/timestamp.c:735 utils/adt/timestamp.c:820 utils/adt/timestamp.c:860 utils/adt/timestamp.c:3021 utils/adt/timestamp.c:3042 utils/adt/timestamp.c:3055 utils/adt/timestamp.c:3064 utils/adt/timestamp.c:3072 utils/adt/timestamp.c:3127 utils/adt/timestamp.c:3150 utils/adt/timestamp.c:3163 utils/adt/timestamp.c:3174 utils/adt/timestamp.c:3182 utils/adt/timestamp.c:3756
-#: utils/adt/timestamp.c:3885 utils/adt/timestamp.c:3926 utils/adt/timestamp.c:4014 utils/adt/timestamp.c:4060 utils/adt/timestamp.c:4171 utils/adt/timestamp.c:4578 utils/adt/timestamp.c:4694 utils/adt/timestamp.c:4704 utils/adt/timestamp.c:4800 utils/adt/timestamp.c:4919 utils/adt/timestamp.c:4929 utils/adt/timestamp.c:5250 utils/adt/timestamp.c:5264 utils/adt/timestamp.c:5269 utils/adt/timestamp.c:5283 utils/adt/timestamp.c:5366
-#: utils/adt/timestamp.c:5398 utils/adt/timestamp.c:5405 utils/adt/timestamp.c:5431 utils/adt/timestamp.c:5435 utils/adt/timestamp.c:5504 utils/adt/timestamp.c:5508 utils/adt/timestamp.c:5522 utils/adt/timestamp.c:5560 utils/adt/xml.c:2051 utils/adt/xml.c:2058 utils/adt/xml.c:2078 utils/adt/xml.c:2085
+#: utils/adt/date.c:1022 utils/adt/date.c:1068 utils/adt/date.c:1678 utils/adt/date.c:1714 utils/adt/date.c:1748 utils/adt/date.c:2592 utils/adt/datetime.c:1759 utils/adt/formatting.c:3404 utils/adt/formatting.c:3436 utils/adt/formatting.c:3504 utils/adt/json.c:1534 utils/adt/json.c:1556 utils/adt/jsonb.c:823 utils/adt/jsonb.c:847 utils/adt/nabstime.c:455 utils/adt/nabstime.c:498 utils/adt/nabstime.c:528 utils/adt/nabstime.c:571
+#: utils/adt/timestamp.c:224 utils/adt/timestamp.c:268 utils/adt/timestamp.c:726 utils/adt/timestamp.c:735 utils/adt/timestamp.c:820 utils/adt/timestamp.c:860 utils/adt/timestamp.c:3074 utils/adt/timestamp.c:3095 utils/adt/timestamp.c:3108 utils/adt/timestamp.c:3117 utils/adt/timestamp.c:3125 utils/adt/timestamp.c:3180 utils/adt/timestamp.c:3203 utils/adt/timestamp.c:3216 utils/adt/timestamp.c:3227 utils/adt/timestamp.c:3235
+#: utils/adt/timestamp.c:3809 utils/adt/timestamp.c:3938 utils/adt/timestamp.c:3979 utils/adt/timestamp.c:4067 utils/adt/timestamp.c:4113 utils/adt/timestamp.c:4224 utils/adt/timestamp.c:4631 utils/adt/timestamp.c:4747 utils/adt/timestamp.c:4757 utils/adt/timestamp.c:4853 utils/adt/timestamp.c:4972 utils/adt/timestamp.c:4982 utils/adt/timestamp.c:5234 utils/adt/timestamp.c:5248 utils/adt/timestamp.c:5253 utils/adt/timestamp.c:5267
+#: utils/adt/timestamp.c:5316 utils/adt/timestamp.c:5348 utils/adt/timestamp.c:5355 utils/adt/timestamp.c:5381 utils/adt/timestamp.c:5385 utils/adt/timestamp.c:5454 utils/adt/timestamp.c:5458 utils/adt/timestamp.c:5472 utils/adt/timestamp.c:5510 utils/adt/xml.c:2049 utils/adt/xml.c:2056 utils/adt/xml.c:2076 utils/adt/xml.c:2083
#, c-format
msgid "timestamp out of range"
msgstr "timestamp en dehors des limites"
@@ -18494,13 +18479,12 @@ msgstr "timestamp en dehors des limites"
#: utils/adt/date.c:1094
#, c-format
msgid "cannot convert reserved abstime value to date"
-msgstr "ne peut pas convertir la valeur r�serv�e abstime en date"
+msgstr "ne peut pas convertir la valeur réservée abstime en date"
#: utils/adt/date.c:1112 utils/adt/date.c:1118
-#, fuzzy, c-format
-#| msgid "date out of range for timestamp"
+#, c-format
msgid "abstime out of range for date"
-msgstr "date en dehors des limites pour un timestamp"
+msgstr "abstime en dehors des limites pour une date"
#: utils/adt/date.c:1258 utils/adt/date.c:1265 utils/adt/date.c:2082 utils/adt/date.c:2089
#, c-format
@@ -18515,64 +18499,59 @@ msgstr "valeur du champ time en dehors des limites : %d:%02d:%02g"
#: utils/adt/date.c:1960 utils/adt/date.c:1977
#, c-format
msgid "\"time\" units \"%s\" not recognized"
-msgstr "l'unit� � %s � n'est pas reconnu pour le type � time �"
+msgstr "l'unité « %s » n'est pas reconnu pour le type « time »"
#: utils/adt/date.c:2098
#, c-format
msgid "time zone displacement out of range"
-msgstr "d�placement du fuseau horaire en dehors des limites"
+msgstr "déplacement du fuseau horaire en dehors des limites"
#: utils/adt/date.c:2740 utils/adt/date.c:2757
#, c-format
msgid "\"time with time zone\" units \"%s\" not recognized"
-msgstr "L'unit� � %s � n'est pas reconnu pour le type � time with time zone �"
+msgstr "L'unité « %s » n'est pas reconnu pour le type « time with time zone »"
-#: utils/adt/date.c:2830 utils/adt/datetime.c:994 utils/adt/datetime.c:1874 utils/adt/datetime.c:4700 utils/adt/timestamp.c:532 utils/adt/timestamp.c:559 utils/adt/timestamp.c:5275 utils/adt/timestamp.c:5514
+#: utils/adt/date.c:2830 utils/adt/datetime.c:995 utils/adt/datetime.c:1917 utils/adt/datetime.c:4743 utils/adt/timestamp.c:532 utils/adt/timestamp.c:559 utils/adt/timestamp.c:5259 utils/adt/timestamp.c:5464
#, c-format
msgid "time zone \"%s\" not recognized"
-msgstr "le fuseau horaire � %s � n'est pas reconnu"
+msgstr "le fuseau horaire « %s » n'est pas reconnu"
-#: utils/adt/date.c:2870 utils/adt/timestamp.c:5351 utils/adt/timestamp.c:5545
+#: utils/adt/date.c:2870 utils/adt/timestamp.c:5301 utils/adt/timestamp.c:5495
#, c-format
msgid "interval time zone \"%s\" must not include months or days"
-msgstr "l'intervalle de fuseau horaire � %s � ne doit pas sp�cifier de mois ou de jours"
+msgstr "l'intervalle de fuseau horaire « %s » ne doit pas spécifier de mois ou de jours"
-#: utils/adt/datetime.c:1749
-#, c-format
-msgid "time zone abbreviation \"%s\" is not used in time zone \"%s\""
-msgstr "l'abr�viation � %s � du fuseau horaire n'est pas utilis�e dans le fuseau horaire � %s �"
-
-#: utils/adt/datetime.c:3835 utils/adt/datetime.c:3842
+#: utils/adt/datetime.c:3878 utils/adt/datetime.c:3885
#, c-format
msgid "date/time field value out of range: \"%s\""
-msgstr "valeur du champ date/time en dehors des limites : � %s �"
+msgstr "valeur du champ date/time en dehors des limites : « %s »"
-#: utils/adt/datetime.c:3844
+#: utils/adt/datetime.c:3887
#, c-format
msgid "Perhaps you need a different \"datestyle\" setting."
-msgstr "Peut-�tre avez-vous besoin d'un param�trage � datestyle � diff�rent."
+msgstr "Peut-être avez-vous besoin d'un paramètrage « datestyle » différent."
-#: utils/adt/datetime.c:3849
+#: utils/adt/datetime.c:3892
#, c-format
msgid "interval field value out of range: \"%s\""
-msgstr "valeur du champ interval en dehors des limites : � %s �"
+msgstr "valeur du champ interval en dehors des limites : « %s »"
-#: utils/adt/datetime.c:3855
+#: utils/adt/datetime.c:3898
#, c-format
msgid "time zone displacement out of range: \"%s\""
-msgstr "d�placement du fuseau horaire en dehors des limites : � %s �"
+msgstr "déplacement du fuseau horaire en dehors des limites : « %s »"
#. translator: first %s is inet or cidr
-#: utils/adt/datetime.c:3862 utils/adt/float.c:463 utils/adt/float.c:546 utils/adt/float.c:572 utils/adt/geo_ops.c:156 utils/adt/geo_ops.c:166 utils/adt/geo_ops.c:178 utils/adt/geo_ops.c:210 utils/adt/geo_ops.c:255 utils/adt/geo_ops.c:265 utils/adt/geo_ops.c:935 utils/adt/geo_ops.c:1321 utils/adt/geo_ops.c:1356 utils/adt/geo_ops.c:1364 utils/adt/geo_ops.c:3422 utils/adt/geo_ops.c:4555 utils/adt/geo_ops.c:4571 utils/adt/geo_ops.c:4578
+#: utils/adt/datetime.c:3905 utils/adt/float.c:461 utils/adt/float.c:544 utils/adt/float.c:570 utils/adt/geo_ops.c:156 utils/adt/geo_ops.c:166 utils/adt/geo_ops.c:178 utils/adt/geo_ops.c:210 utils/adt/geo_ops.c:255 utils/adt/geo_ops.c:265 utils/adt/geo_ops.c:935 utils/adt/geo_ops.c:1321 utils/adt/geo_ops.c:1356 utils/adt/geo_ops.c:1364 utils/adt/geo_ops.c:3430 utils/adt/geo_ops.c:4563 utils/adt/geo_ops.c:4579 utils/adt/geo_ops.c:4586
#: utils/adt/network.c:58
#, c-format
msgid "invalid input syntax for type %s: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type %s : � %s �"
+msgstr "syntaxe en entrée invalide pour le type %s : « %s »"
-#: utils/adt/datetime.c:4702
+#: utils/adt/datetime.c:4745
#, c-format
msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"."
-msgstr "Ce nom du fuseau horaire appara�t dans le fichier de configuration des abr�viations de fuseaux horaires � %s �."
+msgstr "Ce nom du fuseau horaire apparaît dans le fichier de configuration des abréviations de fuseaux horaires « %s »."
#: utils/adt/datum.c:86 utils/adt/datum.c:98
#, c-format
@@ -18582,24 +18561,24 @@ msgstr "pointeur Datum invalide"
#: utils/adt/dbsize.c:110
#, c-format
msgid "could not open tablespace directory \"%s\": %m"
-msgstr "n'a pas pu ouvrir le r�pertoire du tablespace � %s � : %m"
+msgstr "n'a pas pu ouvrir le répertoire du tablespace « %s » : %m"
-#: utils/adt/dbsize.c:757 utils/adt/dbsize.c:776 utils/adt/dbsize.c:831
+#: utils/adt/dbsize.c:757 utils/adt/dbsize.c:825
#, c-format
msgid "invalid size: \"%s\""
-msgstr "taille invalide : � %s �"
+msgstr "taille invalide : « %s »"
-#: utils/adt/dbsize.c:832
+#: utils/adt/dbsize.c:826
#, c-format
msgid "Invalid size unit: \"%s\"."
-msgstr "Unit� invalide pour une taille : � %s �."
+msgstr "Unité invalide pour une taille : « %s »."
-#: utils/adt/dbsize.c:833
+#: utils/adt/dbsize.c:827
#, c-format
msgid "Valid units are \"bytes\", \"kB\", \"MB\", \"GB\", and \"TB\"."
-msgstr "Les unit�s valides pour ce param�tre sont � bytes �, � kB �, � MB �, � GB � et � TB �."
+msgstr "Les unités valides pour ce paramètre sont « bytes », « kB », « MB », « GB » et « TB »."
-#: utils/adt/domains.c:85
+#: utils/adt/domains.c:86
#, c-format
msgid "type %s is not a domain"
msgstr "le type %s n'est pas un domaine"
@@ -18607,47 +18586,47 @@ msgstr "le type %s n'est pas un domaine"
#: utils/adt/encode.c:55 utils/adt/encode.c:91
#, c-format
msgid "unrecognized encoding: \"%s\""
-msgstr "encodage non reconnu : � %s �"
+msgstr "encodage non reconnu : « %s »"
#: utils/adt/encode.c:150
#, c-format
msgid "invalid hexadecimal digit: \"%c\""
-msgstr "chiffre hexad�cimal invalide : � %c �"
+msgstr "chiffre hexadécimal invalide : « %c »"
#: utils/adt/encode.c:178
#, c-format
msgid "invalid hexadecimal data: odd number of digits"
-msgstr "donn�e hexad�cimale invalide : nombre pair de chiffres"
+msgstr "donnée hexadécimale invalide : nombre pair de chiffres"
#: utils/adt/encode.c:295
#, c-format
msgid "unexpected \"=\" while decoding base64 sequence"
-msgstr "� = � inattendu lors du d�codage de la s�quence en base64"
+msgstr "« = » inattendu lors du décodage de la séquence en base64"
#: utils/adt/encode.c:307
#, c-format
msgid "invalid symbol \"%c\" while decoding base64 sequence"
-msgstr "symbole � %c � invalide invalide lors du d�codage de la s�quence en base64"
+msgstr "symbole « %c » invalide invalide lors du décodage de la séquence en base64"
#: utils/adt/encode.c:327
#, c-format
msgid "invalid base64 end sequence"
-msgstr "s�quence base64 de fin invalide"
+msgstr "séquence base64 de fin invalide"
#: utils/adt/encode.c:328
#, c-format
msgid "Input data is missing padding, is truncated, or is otherwise corrupted."
-msgstr "Les donn�es en entr�e manquent un alignement, sont tronqu�es ou ont une corruption autre."
+msgstr "Les données en entrée manquent un alignement, sont tronquées ou ont une corruption autre."
#: utils/adt/encode.c:442 utils/adt/encode.c:507 utils/adt/varlena.c:297 utils/adt/varlena.c:338
#, c-format
msgid "invalid input syntax for type bytea"
-msgstr "syntaxe en entr�e invalide pour le type bytea"
+msgstr "syntaxe en entrée invalide pour le type bytea"
#: utils/adt/enum.c:48 utils/adt/enum.c:58 utils/adt/enum.c:113 utils/adt/enum.c:123
#, c-format
msgid "invalid input value for enum %s: \"%s\""
-msgstr "valeur en entr�e invalide pour le enum %s : � %s �"
+msgstr "valeur en entrée invalide pour le enum %s : « %s »"
#: utils/adt/enum.c:85 utils/adt/enum.c:148 utils/adt/enum.c:198
#, c-format
@@ -18657,192 +18636,192 @@ msgstr "valeur interne invalide pour le enum : %u"
#: utils/adt/enum.c:356 utils/adt/enum.c:385 utils/adt/enum.c:425 utils/adt/enum.c:445
#, c-format
msgid "could not determine actual enum type"
-msgstr "n'a pas pu d�terminer le type enum actuel"
+msgstr "n'a pas pu déterminer le type enum actuel"
#: utils/adt/enum.c:364 utils/adt/enum.c:393
#, c-format
msgid "enum %s contains no values"
-msgstr "l'�num�ration � %s � ne contient aucune valeur"
+msgstr "l'énumération « %s » ne contient aucune valeur"
#: utils/adt/float.c:58
#, c-format
msgid "value out of range: overflow"
-msgstr "valeur en dehors des limites : d�passement"
+msgstr "valeur en dehors des limites : dépassement"
#: utils/adt/float.c:63
#, c-format
msgid "value out of range: underflow"
msgstr "valeur en dehors des limites : trop petit"
-#: utils/adt/float.c:246 utils/adt/float.c:320 utils/adt/float.c:344
+#: utils/adt/float.c:244 utils/adt/float.c:318 utils/adt/float.c:342
#, c-format
msgid "invalid input syntax for type real: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type real : � %s �"
+msgstr "syntaxe en entrée invalide pour le type real : « %s »"
-#: utils/adt/float.c:314
+#: utils/adt/float.c:312
#, c-format
msgid "\"%s\" is out of range for type real"
-msgstr "� %s � est hors des limites du type real"
+msgstr "« %s » est hors des limites du type real"
-#: utils/adt/float.c:539
+#: utils/adt/float.c:537
#, c-format
msgid "\"%s\" is out of range for type double precision"
-msgstr "� %s � est en dehors des limites du type double precision"
+msgstr "« %s » est en dehors des limites du type double precision"
-#: utils/adt/float.c:1248 utils/adt/float.c:1306 utils/adt/int.c:349 utils/adt/int.c:775 utils/adt/int.c:804 utils/adt/int.c:825 utils/adt/int.c:845 utils/adt/int.c:879 utils/adt/int.c:1174 utils/adt/int8.c:1323 utils/adt/numeric.c:3004 utils/adt/numeric.c:3013
+#: utils/adt/float.c:1246 utils/adt/float.c:1304 utils/adt/int.c:349 utils/adt/int.c:775 utils/adt/int.c:804 utils/adt/int.c:825 utils/adt/int.c:845 utils/adt/int.c:879 utils/adt/int.c:1174 utils/adt/int8.c:1323 utils/adt/numeric.c:3000 utils/adt/numeric.c:3009
#, c-format
msgid "smallint out of range"
msgstr "smallint en dehors des limites"
-#: utils/adt/float.c:1432 utils/adt/numeric.c:7522
+#: utils/adt/float.c:1430 utils/adt/numeric.c:7540
#, c-format
msgid "cannot take square root of a negative number"
-msgstr "ne peut pas calculer la racine carr� d'un nombre n�gatif"
+msgstr "ne peut pas calculer la racine carré d'un nombre négatif"
-#: utils/adt/float.c:1474 utils/adt/numeric.c:2807
+#: utils/adt/float.c:1472 utils/adt/numeric.c:2803
#, c-format
msgid "zero raised to a negative power is undefined"
-msgstr "z�ro � une puissance n�gative est ind�fini"
+msgstr "zéro à une puissance négative est indéfini"
-#: utils/adt/float.c:1478 utils/adt/numeric.c:2813
+#: utils/adt/float.c:1476 utils/adt/numeric.c:2809
#, c-format
msgid "a negative number raised to a non-integer power yields a complex result"
-msgstr "un nombre n�gatif �lev� � une puissance non enti�re donne un r�sultat complexe"
+msgstr "un nombre négatif élevé à une puissance non entière donne un résultat complexe"
-#: utils/adt/float.c:1544 utils/adt/float.c:1574 utils/adt/numeric.c:7788
+#: utils/adt/float.c:1542 utils/adt/float.c:1572 utils/adt/numeric.c:7806
#, c-format
msgid "cannot take logarithm of zero"
-msgstr "ne peut pas calculer le logarithme de z�ro"
+msgstr "ne peut pas calculer le logarithme de zéro"
-#: utils/adt/float.c:1548 utils/adt/float.c:1578 utils/adt/numeric.c:7792
+#: utils/adt/float.c:1546 utils/adt/float.c:1576 utils/adt/numeric.c:7810
#, c-format
msgid "cannot take logarithm of a negative number"
-msgstr "ne peut pas calculer le logarithme sur un nombre n�gatif"
+msgstr "ne peut pas calculer le logarithme sur un nombre négatif"
-#: utils/adt/float.c:1608 utils/adt/float.c:1638 utils/adt/float.c:1730 utils/adt/float.c:1756 utils/adt/float.c:1783 utils/adt/float.c:1809 utils/adt/float.c:1956 utils/adt/float.c:1991 utils/adt/float.c:2155 utils/adt/float.c:2209 utils/adt/float.c:2273 utils/adt/float.c:2328
+#: utils/adt/float.c:1606 utils/adt/float.c:1636 utils/adt/float.c:1728 utils/adt/float.c:1754 utils/adt/float.c:1781 utils/adt/float.c:1807 utils/adt/float.c:1954 utils/adt/float.c:1989 utils/adt/float.c:2153 utils/adt/float.c:2207 utils/adt/float.c:2271 utils/adt/float.c:2326
#, c-format
msgid "input is out of range"
-msgstr "l'entr�e est en dehors des limites"
+msgstr "l'entrée est en dehors des limites"
-#: utils/adt/float.c:3534 utils/adt/numeric.c:1447
+#: utils/adt/float.c:3532 utils/adt/numeric.c:1443
#, c-format
msgid "count must be greater than zero"
-msgstr "le total doit �tre sup�rieur � z�ro"
+msgstr "le total doit être supérieur à zéro"
-#: utils/adt/float.c:3539 utils/adt/numeric.c:1454
+#: utils/adt/float.c:3537 utils/adt/numeric.c:1450
#, c-format
msgid "operand, lower bound, and upper bound cannot be NaN"
-msgstr "la limite inf�rieure et sup�rieure de l'op�rande ne peuvent pas �tre NaN"
+msgstr "la limite inférieure et supérieure de l'opérande ne peuvent pas être NaN"
-#: utils/adt/float.c:3545
+#: utils/adt/float.c:3543
#, c-format
msgid "lower and upper bounds must be finite"
-msgstr "les limites basse et haute doivent �tre finies"
+msgstr "les limites basse et haute doivent être finies"
-#: utils/adt/float.c:3583 utils/adt/numeric.c:1467
+#: utils/adt/float.c:3581 utils/adt/numeric.c:1463
#, c-format
msgid "lower bound cannot equal upper bound"
-msgstr "la limite inf�rieure ne peut pas �tre plus �gale � la limite sup�rieure"
+msgstr "la limite inférieure ne peut pas être plus égale à la limite supérieure"
#: utils/adt/formatting.c:485
#, c-format
msgid "invalid format specification for an interval value"
-msgstr "format de sp�cification invalide pour une valeur intervalle"
+msgstr "format de spécification invalide pour une valeur intervalle"
#: utils/adt/formatting.c:486
#, c-format
msgid "Intervals are not tied to specific calendar dates."
-msgstr "Les intervalles ne sont pas li�s aux dates de calendriers sp�cifiques."
+msgstr "Les intervalles ne sont pas liés aux dates de calendriers spécifiques."
#: utils/adt/formatting.c:1058
#, c-format
msgid "\"EEEE\" must be the last pattern used"
-msgstr "� EEEE � doit �tre le dernier motif utilis�"
+msgstr "« EEEE » doit être le dernier motif utilisé"
#: utils/adt/formatting.c:1066
#, c-format
msgid "\"9\" must be ahead of \"PR\""
-msgstr "� 9 � doit �tre avant � PR �"
+msgstr "« 9 » doit être avant « PR »"
#: utils/adt/formatting.c:1082
#, c-format
msgid "\"0\" must be ahead of \"PR\""
-msgstr "� 0 � doit �tre avant � PR �"
+msgstr "« 0 » doit être avant « PR »"
#: utils/adt/formatting.c:1109
#, c-format
msgid "multiple decimal points"
-msgstr "multiples points d�cimaux"
+msgstr "multiples points décimaux"
#: utils/adt/formatting.c:1113 utils/adt/formatting.c:1196
#, c-format
msgid "cannot use \"V\" and decimal point together"
-msgstr "ne peut pas utiliser � V � et le point d�cimal ensemble"
+msgstr "ne peut pas utiliser « V » et le point décimal ensemble"
#: utils/adt/formatting.c:1125
#, c-format
msgid "cannot use \"S\" twice"
-msgstr "ne peut pas utiliser � S � deux fois"
+msgstr "ne peut pas utiliser « S » deux fois"
#: utils/adt/formatting.c:1129
#, c-format
msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together"
-msgstr "ne peut pas utiliser � S � et � PL �/� MI �/� SG �/� PR � ensemble"
+msgstr "ne peut pas utiliser « S » et « PL »/« MI »/« SG »/« PR » ensemble"
#: utils/adt/formatting.c:1149
#, c-format
msgid "cannot use \"S\" and \"MI\" together"
-msgstr "ne peut pas utiliser � S � et � MI � ensemble"
+msgstr "ne peut pas utiliser « S » et « MI » ensemble"
#: utils/adt/formatting.c:1159
#, c-format
msgid "cannot use \"S\" and \"PL\" together"
-msgstr "ne peut pas utiliser � S � et � PL � ensemble"
+msgstr "ne peut pas utiliser « S » et « PL » ensemble"
#: utils/adt/formatting.c:1169
#, c-format
msgid "cannot use \"S\" and \"SG\" together"
-msgstr "ne peut pas utiliser � S � et � SG � ensemble"
+msgstr "ne peut pas utiliser « S » et « SG » ensemble"
#: utils/adt/formatting.c:1178
#, c-format
msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together"
-msgstr "ne peut pas utiliser � PR � et � S �/� PL �/� MI �/� SG � ensemble"
+msgstr "ne peut pas utiliser « PR » et « S »/« PL »/« MI »/« SG » ensemble"
#: utils/adt/formatting.c:1204
#, c-format
msgid "cannot use \"EEEE\" twice"
-msgstr "ne peut pas utiliser � EEEE � deux fois"
+msgstr "ne peut pas utiliser « EEEE » deux fois"
#: utils/adt/formatting.c:1210
#, c-format
msgid "\"EEEE\" is incompatible with other formats"
-msgstr "� EEEE � est incompatible avec les autres formats"
+msgstr "« EEEE » est incompatible avec les autres formats"
#: utils/adt/formatting.c:1211
#, c-format
msgid "\"EEEE\" may only be used together with digit and decimal point patterns."
-msgstr "� EEEE � peut seulement �tre utilis� avec les motifs de chiffres et de points d�cimaux."
+msgstr "« EEEE » peut seulement être utilisé avec les motifs de chiffres et de points décimaux."
#: utils/adt/formatting.c:1411
#, c-format
msgid "\"%s\" is not a number"
-msgstr "� %s � n'est pas un nombre"
+msgstr "« %s » n'est pas un nombre"
#: utils/adt/formatting.c:1512 utils/adt/formatting.c:1564
#, c-format
msgid "could not determine which collation to use for lower() function"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour la fonction lower()"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour la fonction lower()"
#: utils/adt/formatting.c:1632 utils/adt/formatting.c:1684
#, c-format
msgid "could not determine which collation to use for upper() function"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour la fonction upper()"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour la fonction upper()"
#: utils/adt/formatting.c:1753 utils/adt/formatting.c:1817
#, c-format
msgid "could not determine which collation to use for initcap() function"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour la fonction initcap()"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour la fonction initcap()"
#: utils/adt/formatting.c:2114
#, c-format
@@ -18853,85 +18832,85 @@ msgstr "combinaison invalide des conventions de date"
#, c-format
msgid "Do not mix Gregorian and ISO week date conventions in a formatting template."
msgstr ""
-"Ne pas mixer les conventions de jour de semaine gr�gorien et ISO dans un\n"
-"mod�le de formatage."
+"Ne pas mixer les conventions de jour de semaine grégorien et ISO dans un\n"
+"modèle de formatage."
#: utils/adt/formatting.c:2132
#, c-format
msgid "conflicting values for \"%s\" field in formatting string"
-msgstr "valeur conflictuelle pour le champ � %s � dans la cha�ne de formatage"
+msgstr "valeur conflictuelle pour le champ « %s » dans la chaîne de formatage"
#: utils/adt/formatting.c:2134
#, c-format
msgid "This value contradicts a previous setting for the same field type."
-msgstr "Cette valeur contredit une configuration pr�c�dente pour le m�me type de champ."
+msgstr "Cette valeur contredit une configuration précédente pour le même type de champ."
#: utils/adt/formatting.c:2195
#, c-format
msgid "source string too short for \"%s\" formatting field"
-msgstr "cha�ne source trop petite pour le champ de formatage � %s �"
+msgstr "chaîne source trop petite pour le champ de formatage « %s »"
#: utils/adt/formatting.c:2197
#, c-format
msgid "Field requires %d characters, but only %d remain."
-msgstr "Le champ requiert %d caract�res, mais seuls %d restent."
+msgstr "Le champ requiert %d caractères, mais seuls %d restent."
#: utils/adt/formatting.c:2200 utils/adt/formatting.c:2214
#, c-format
msgid "If your source string is not fixed-width, try using the \"FM\" modifier."
msgstr ""
-"Si votre cha�ne source n'a pas une taille fixe, essayez d'utiliser le\n"
-"modifieur � FM �."
+"Si votre chaîne source n'a pas une taille fixe, essayez d'utiliser le\n"
+"modifieur « FM »."
#: utils/adt/formatting.c:2210 utils/adt/formatting.c:2223 utils/adt/formatting.c:2353
#, c-format
msgid "invalid value \"%s\" for \"%s\""
-msgstr "valeur � %s � invalide pour � %s �"
+msgstr "valeur « %s » invalide pour « %s »"
#: utils/adt/formatting.c:2212
#, c-format
msgid "Field requires %d characters, but only %d could be parsed."
-msgstr "Le champ n�cessite %d caract�res, mais seulement %d ont pu �tre analys�s."
+msgstr "Le champ nécessite %d caractères, mais seulement %d ont pu être analysés."
#: utils/adt/formatting.c:2225
#, c-format
msgid "Value must be an integer."
-msgstr "La valeur doit �tre un entier"
+msgstr "La valeur doit être un entier"
#: utils/adt/formatting.c:2230
#, c-format
msgid "value for \"%s\" in source string is out of range"
-msgstr "la valeur pour � %s � dans la cha�ne source est en dehors des limites"
+msgstr "la valeur pour « %s » dans la chaîne source est en dehors des limites"
#: utils/adt/formatting.c:2232
#, c-format
msgid "Value must be in the range %d to %d."
-msgstr "La valeur doit �tre compris entre %d et %d"
+msgstr "La valeur doit être compris entre %d et %d"
#: utils/adt/formatting.c:2355
#, c-format
msgid "The given value did not match any of the allowed values for this field."
-msgstr "La valeur donn�e ne correspond pas aux valeurs autoris�es pour ce champ."
+msgstr "La valeur donnée ne correspond pas aux valeurs autorisées pour ce champ."
#: utils/adt/formatting.c:2550 utils/adt/formatting.c:2570 utils/adt/formatting.c:2590 utils/adt/formatting.c:2610 utils/adt/formatting.c:2629 utils/adt/formatting.c:2648 utils/adt/formatting.c:2672 utils/adt/formatting.c:2690 utils/adt/formatting.c:2708 utils/adt/formatting.c:2726 utils/adt/formatting.c:2743 utils/adt/formatting.c:2760
#, c-format
msgid "localized string format value too long"
-msgstr "cha�ne localis�e trop longue"
+msgstr "chaîne localisée trop longue"
#: utils/adt/formatting.c:3047
#, c-format
msgid "\"TZ\"/\"tz\"/\"OF\" format patterns are not supported in to_date"
-msgstr "les motifs de format � TZ �/� tz �/� OF � ne sont pas support�s dans to_date"
+msgstr "les motifs de format « TZ »/« tz »/« OF » ne sont pas supportés dans to_date"
#: utils/adt/formatting.c:3156
#, c-format
msgid "invalid input string for \"Y,YYY\""
-msgstr "cha�ne invalide en entr�e pour � Y,YYY �"
+msgstr "chaîne invalide en entrée pour « Y,YYY »"
#: utils/adt/formatting.c:3668
#, c-format
msgid "hour \"%d\" is invalid for the 12-hour clock"
-msgstr "l'heure � %d � est invalide pour une horloge sur 12 heures"
+msgstr "l'heure « %d » est invalide pour une horloge sur 12 heures"
#: utils/adt/formatting.c:3670
#, c-format
@@ -18941,170 +18920,170 @@ msgstr "Utilisez une horloge sur 24 heures ou donnez une heure entre 1 et 12."
#: utils/adt/formatting.c:3765
#, c-format
msgid "cannot calculate day of year without year information"
-msgstr "ne peut pas calculer le jour de l'ann�e sans information sur l'ann�e"
+msgstr "ne peut pas calculer le jour de l'année sans information sur l'année"
#: utils/adt/formatting.c:4614
#, c-format
msgid "\"EEEE\" not supported for input"
-msgstr "� EEEE � non support� en entr�e"
+msgstr "« EEEE » non supporté en entrée"
#: utils/adt/formatting.c:4626
#, c-format
msgid "\"RN\" not supported for input"
-msgstr "� RN � non support� en entr�e"
+msgstr "« RN » non supporté en entrée"
#: utils/adt/genfile.c:62
#, c-format
msgid "reference to parent directory (\"..\") not allowed"
-msgstr "r�f�rence non autoris�e au r�pertoire parent (� .. �)"
+msgstr "référence non autorisée au répertoire parent (« .. »)"
#: utils/adt/genfile.c:73
#, c-format
msgid "absolute path not allowed"
-msgstr "chemin absolu non autoris�"
+msgstr "chemin absolu non autorisé"
#: utils/adt/genfile.c:78
#, c-format
msgid "path must be in or below the current directory"
-msgstr "le chemin doit �tre dans ou en-dessous du r�pertoire courant"
+msgstr "le chemin doit être dans ou en-dessous du répertoire courant"
#: utils/adt/genfile.c:125 utils/adt/oracle_compat.c:184 utils/adt/oracle_compat.c:282 utils/adt/oracle_compat.c:758 utils/adt/oracle_compat.c:1059
#, c-format
msgid "requested length too large"
-msgstr "longueur demand�e trop importante"
+msgstr "longueur demandée trop importante"
#: utils/adt/genfile.c:142
#, c-format
msgid "could not seek in file \"%s\": %m"
-msgstr "n'a pas pu parcourir le fichier � %s � : %m"
+msgstr "n'a pas pu parcourir le fichier « %s » : %m"
#: utils/adt/genfile.c:200 utils/adt/genfile.c:241
#, c-format
msgid "must be superuser to read files"
-msgstr "doit �tre super-utilisateur pour lire des fichiers"
+msgstr "doit être super-utilisateur pour lire des fichiers"
#: utils/adt/genfile.c:318
#, c-format
msgid "must be superuser to get file information"
-msgstr "doit �tre super-utilisateur pour obtenir des informations sur le fichier"
+msgstr "doit être super-utilisateur pour obtenir des informations sur le fichier"
#: utils/adt/genfile.c:404
#, c-format
msgid "must be superuser to get directory listings"
-msgstr "doit �tre super-utilisateur pour obtenir le contenu du r�pertoire"
+msgstr "doit être super-utilisateur pour obtenir le contenu du répertoire"
#: utils/adt/geo_ops.c:940
#, c-format
msgid "invalid line specification: A and B cannot both be zero"
-msgstr "sp�cification invalide de ligne : A et B ne peuvent pas �tre � z�ro tous les deux"
+msgstr "spécification invalide de ligne : A et B ne peuvent pas être à zéro tous les deux"
#: utils/adt/geo_ops.c:948
#, c-format
msgid "invalid line specification: must be two distinct points"
-msgstr "sp�cification de ligne invalide : doit �tre deux points distincts"
+msgstr "spécification de ligne invalide : doit être deux points distincts"
-#: utils/adt/geo_ops.c:1342 utils/adt/geo_ops.c:3432 utils/adt/geo_ops.c:4245 utils/adt/geo_ops.c:5173
+#: utils/adt/geo_ops.c:1342 utils/adt/geo_ops.c:3440 utils/adt/geo_ops.c:4253 utils/adt/geo_ops.c:5181
#, c-format
msgid "too many points requested"
-msgstr "trop de points demand�"
+msgstr "trop de points demandé"
#: utils/adt/geo_ops.c:1404
#, c-format
msgid "invalid number of points in external \"path\" value"
-msgstr "nombre de points invalide dans la valeur externe de � path �"
+msgstr "nombre de points invalide dans la valeur externe de « path »"
#: utils/adt/geo_ops.c:2555
#, c-format
msgid "function \"dist_lb\" not implemented"
-msgstr "la fonction � dist_lb � n'est pas impl�ment�e"
+msgstr "la fonction « dist_lb » n'est pas implémentée"
-#: utils/adt/geo_ops.c:3007
+#: utils/adt/geo_ops.c:3015
#, c-format
msgid "function \"close_sl\" not implemented"
-msgstr "la fonction � close_sl � n'est pas impl�ment�e"
+msgstr "la fonction « close_sl » n'est pas implémentée"
-#: utils/adt/geo_ops.c:3109
+#: utils/adt/geo_ops.c:3117
#, c-format
msgid "function \"close_lb\" not implemented"
-msgstr "la fonction � close_lb � n'est pas impl�ment�e"
+msgstr "la fonction « close_lb » n'est pas implémentée"
-#: utils/adt/geo_ops.c:3398
+#: utils/adt/geo_ops.c:3406
#, c-format
msgid "cannot create bounding box for empty polygon"
-msgstr "ne peut pas cr�er une bo�te entour�e pour un polyg�ne vide"
+msgstr "ne peut pas créer une boîte entourée pour un polygône vide"
-#: utils/adt/geo_ops.c:3479
+#: utils/adt/geo_ops.c:3487
#, c-format
msgid "invalid number of points in external \"polygon\" value"
-msgstr "nombre de points invalide dans la valeur externe de � polygon �"
+msgstr "nombre de points invalide dans la valeur externe de « polygon »"
-#: utils/adt/geo_ops.c:4004
+#: utils/adt/geo_ops.c:4012
#, c-format
msgid "function \"poly_distance\" not implemented"
-msgstr "la fonction � poly_distance � n'est pas impl�ment�e"
+msgstr "la fonction « poly_distance » n'est pas implémentée"
-#: utils/adt/geo_ops.c:4357
+#: utils/adt/geo_ops.c:4365
#, c-format
msgid "function \"path_center\" not implemented"
-msgstr "la fonction � path_center � n'est pas impl�ment�e"
+msgstr "la fonction « path_center » n'est pas implémentée"
-#: utils/adt/geo_ops.c:4374
+#: utils/adt/geo_ops.c:4382
#, c-format
msgid "open path cannot be converted to polygon"
-msgstr "le chemin ouvert ne peut �tre converti en polyg�ne"
+msgstr "le chemin ouvert ne peut être converti en polygône"
-#: utils/adt/geo_ops.c:4623
+#: utils/adt/geo_ops.c:4631
#, c-format
msgid "invalid radius in external \"circle\" value"
-msgstr "diam�tre invalide pour la valeur externe de � circle �"
+msgstr "diamètre invalide pour la valeur externe de « circle »"
-#: utils/adt/geo_ops.c:5159
+#: utils/adt/geo_ops.c:5167
#, c-format
msgid "cannot convert circle with radius zero to polygon"
-msgstr "ne peut pas convertir le cercle avec un diam�tre z�ro en un polyg�ne"
+msgstr "ne peut pas convertir le cercle avec un diamètre zéro en un polygône"
-#: utils/adt/geo_ops.c:5164
+#: utils/adt/geo_ops.c:5172
#, c-format
msgid "must request at least 2 points"
msgstr "doit demander au moins deux points"
-#: utils/adt/geo_ops.c:5208
+#: utils/adt/geo_ops.c:5216
#, c-format
msgid "cannot convert empty polygon to circle"
-msgstr "ne peut pas convertir un polyg�ne vide en cercle"
+msgstr "ne peut pas convertir un polygône vide en cercle"
#: utils/adt/int.c:162
#, c-format
msgid "int2vector has too many elements"
-msgstr "int2vector a trop d'�l�ments"
+msgstr "int2vector a trop d'éléments"
#: utils/adt/int.c:237
#, c-format
msgid "invalid int2vector data"
-msgstr "donn�es int2vector invalide"
+msgstr "données int2vector invalide"
#: utils/adt/int.c:243 utils/adt/oid.c:212 utils/adt/oid.c:293
#, c-format
msgid "oidvector has too many elements"
-msgstr "oidvector a trop d'�l�ments"
+msgstr "oidvector a trop d'éléments"
-#: utils/adt/int.c:1362 utils/adt/int8.c:1460 utils/adt/numeric.c:1355 utils/adt/timestamp.c:5611 utils/adt/timestamp.c:5692
+#: utils/adt/int.c:1362 utils/adt/int8.c:1460 utils/adt/numeric.c:1351 utils/adt/timestamp.c:5561 utils/adt/timestamp.c:5642
#, c-format
msgid "step size cannot equal zero"
-msgstr "la taille du pas ne peut pas valoir z�ro"
+msgstr "la taille du pas ne peut pas valoir zéro"
#: utils/adt/int8.c:98 utils/adt/int8.c:133 utils/adt/numutils.c:51 utils/adt/numutils.c:61 utils/adt/numutils.c:103
#, c-format
msgid "invalid input syntax for integer: \"%s\""
-msgstr "syntaxe en entr�e invalide pour l'entier : � %s �"
+msgstr "syntaxe en entrée invalide pour l'entier : « %s »"
#: utils/adt/int8.c:114
#, c-format
msgid "value \"%s\" is out of range for type bigint"
-msgstr "la valeur � %s � est en dehors des limites du type bigint"
+msgstr "la valeur « %s » est en dehors des limites du type bigint"
#: utils/adt/int8.c:500 utils/adt/int8.c:529 utils/adt/int8.c:550 utils/adt/int8.c:581 utils/adt/int8.c:615 utils/adt/int8.c:640 utils/adt/int8.c:697 utils/adt/int8.c:714 utils/adt/int8.c:741 utils/adt/int8.c:758 utils/adt/int8.c:834 utils/adt/int8.c:855 utils/adt/int8.c:882 utils/adt/int8.c:915 utils/adt/int8.c:943 utils/adt/int8.c:964 utils/adt/int8.c:991 utils/adt/int8.c:1031 utils/adt/int8.c:1052 utils/adt/int8.c:1079
-#: utils/adt/int8.c:1112 utils/adt/int8.c:1140 utils/adt/int8.c:1161 utils/adt/int8.c:1188 utils/adt/int8.c:1361 utils/adt/int8.c:1400 utils/adt/numeric.c:2959 utils/adt/varbit.c:1645
+#: utils/adt/int8.c:1112 utils/adt/int8.c:1140 utils/adt/int8.c:1161 utils/adt/int8.c:1188 utils/adt/int8.c:1361 utils/adt/int8.c:1400 utils/adt/numeric.c:2955 utils/adt/varbit.c:1655
#, c-format
msgid "bigint out of range"
msgstr "bigint en dehors des limites"
@@ -19118,17 +19097,17 @@ msgstr "OID en dehors des limites"
#: utils/adt/json.c:1241
#, c-format
msgid "invalid input syntax for type json"
-msgstr "syntaxe en entr�e invalide pour le type json"
+msgstr "syntaxe en entrée invalide pour le type json"
#: utils/adt/json.c:786
#, c-format
msgid "Character with value 0x%02x must be escaped."
-msgstr "Le caract�re de valeur 0x%02x doit �tre �chapp�."
+msgstr "Le caractère de valeur 0x%02x doit être échappé."
#: utils/adt/json.c:826
#, c-format
msgid "\"\\u\" must be followed by four hexadecimal digits."
-msgstr "� \\u � doit �tre suivi par quatre chiffres hexad�cimaux."
+msgstr "« \\u » doit être suivi par quatre chiffres hexadécimaux."
#: utils/adt/json.c:841
#, c-format
@@ -19143,124 +19122,124 @@ msgstr "Une substitution unicode basse ne doit pas suivre une substitution haute
#: utils/adt/json.c:877 utils/adt/json.c:900
#, c-format
msgid "unsupported Unicode escape sequence"
-msgstr "s�quence d'�chappement Unicode non support�e"
+msgstr "séquence d'échappement Unicode non supportée"
#: utils/adt/json.c:878
#, c-format
msgid "\\u0000 cannot be converted to text."
-msgstr "\\u0000 ne peut pas �tre converti en texte."
+msgstr "\\u0000 ne peut pas être converti en texte."
#: utils/adt/json.c:901
#, c-format
msgid "Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."
msgstr ""
-"Les valeurs d'�chappement unicode ne peuvent pas �tre utilis�es pour les valeurs de point de code\n"
+"Les valeurs d'échappement unicode ne peuvent pas être utilisées pour les valeurs de point de code\n"
"au-dessus de 007F quand l'encodage serveur n'est pas UTF8."
#: utils/adt/json.c:944 utils/adt/json.c:962
#, c-format
msgid "Escape sequence \"\\%s\" is invalid."
-msgstr "La s�quence d'�chappement � \\%s � est invalide."
+msgstr "La séquence d'échappement « \\%s » est invalide."
#: utils/adt/json.c:1131
#, c-format
msgid "The input string ended unexpectedly."
-msgstr "La cha�ne en entr�e se ferme de mani�re inattendue."
+msgstr "La chaîne en entrée se ferme de manière inattendue."
#: utils/adt/json.c:1145
#, c-format
msgid "Expected end of input, but found \"%s\"."
-msgstr "Attendait une fin de l'entr�e, mais ait trouv� � %s �."
+msgstr "Attendait une fin de l'entrée, mais ait trouvé « %s »."
#: utils/adt/json.c:1156
#, c-format
msgid "Expected JSON value, but found \"%s\"."
-msgstr "Valeur JSON attendue, mais � %s � trouv�."
+msgstr "Valeur JSON attendue, mais « %s » trouvé."
#: utils/adt/json.c:1164 utils/adt/json.c:1212
#, c-format
msgid "Expected string, but found \"%s\"."
-msgstr "Cha�ne attendue, mais � %s � trouv�."
+msgstr "Chaîne attendue, mais « %s » trouvé."
#: utils/adt/json.c:1172
#, c-format
msgid "Expected array element or \"]\", but found \"%s\"."
-msgstr "�l�ment de tableau ou � ] � attendu, mais � %s � trouv�"
+msgstr "Élément de tableau ou « ] » attendu, mais « %s » trouvé"
#: utils/adt/json.c:1180
#, c-format
msgid "Expected \",\" or \"]\", but found \"%s\"."
-msgstr "� , � ou � ] � attendu, mais � %s � trouv�"
+msgstr "« , » ou « ] » attendu, mais « %s » trouvé"
#: utils/adt/json.c:1188
#, c-format
msgid "Expected string or \"}\", but found \"%s\"."
-msgstr "Cha�ne ou � } � attendu, mais � %s � trouv�"
+msgstr "Chaîne ou « } » attendu, mais « %s » trouvé"
#: utils/adt/json.c:1196
#, c-format
msgid "Expected \":\", but found \"%s\"."
-msgstr "� : � attendu, mais � %s � trouv�"
+msgstr "« : » attendu, mais « %s » trouvé"
#: utils/adt/json.c:1204
#, c-format
msgid "Expected \",\" or \"}\", but found \"%s\"."
-msgstr "� , � ou � } � attendu, mais � %s � trouv�"
+msgstr "« , » ou « } » attendu, mais « %s » trouvé"
#: utils/adt/json.c:1242
#, c-format
msgid "Token \"%s\" is invalid."
-msgstr "le jeton � %s � n'est pas valide"
+msgstr "le jeton « %s » n'est pas valide"
#: utils/adt/json.c:1314
#, c-format
msgid "JSON data, line %d: %s%s%s"
-msgstr "donn�es JSON, ligne %d : %s%s%s"
+msgstr "données JSON, ligne %d : %s%s%s"
#: utils/adt/json.c:1469 utils/adt/jsonb.c:724
#, c-format
msgid "key value must be scalar, not array, composite, or json"
-msgstr "la valeur cl� doit �tre scalaire, et non pas un tableau ou une valeur composite ou un json"
+msgstr "la valeur clé doit être scalaire, et non pas un tableau ou une valeur composite ou un json"
#: utils/adt/json.c:2006
#, c-format
msgid "could not determine data type for argument 1"
-msgstr "n'a pas pu d�terminer le type de donn�es pour l'argument 1"
+msgstr "n'a pas pu déterminer le type de données pour l'argument 1"
#: utils/adt/json.c:2016
#, c-format
msgid "could not determine data type for argument 2"
-msgstr "n'a pas pu d�terminer le type de donn�es pour l'argument 2"
+msgstr "n'a pas pu déterminer le type de données pour l'argument 2"
#: utils/adt/json.c:2040 utils/adt/jsonb.c:1781
#, c-format
msgid "field name must not be null"
-msgstr "le nom du champ ne doit pas �tre NULL"
+msgstr "le nom du champ ne doit pas être NULL"
#: utils/adt/json.c:2117
#, c-format
msgid "argument list must have even number of elements"
-msgstr "la liste d'arguments doit avoir un nombre pair d'�l�ments"
+msgstr "la liste d'arguments doit avoir un nombre pair d'éléments"
#: utils/adt/json.c:2118
#, c-format
msgid "The arguments of json_build_object() must consist of alternating keys and values."
-msgstr "Les arguments de json_build_object() doivent consister en des cl�s et valeurs altern�es"
+msgstr "Les arguments de json_build_object() doivent consister en des clés et valeurs alternées"
#: utils/adt/json.c:2142 utils/adt/json.c:2163 utils/adt/json.c:2222
#, c-format
msgid "could not determine data type for argument %d"
-msgstr "n'a pas pu d�terminer le type de donn�es pour l'argument %d"
+msgstr "n'a pas pu déterminer le type de données pour l'argument %d"
#: utils/adt/json.c:2148
#, c-format
msgid "argument %d cannot be null"
-msgstr "l'argument %d ne peut pas �tre NULL"
+msgstr "l'argument %d ne peut pas être NULL"
#: utils/adt/json.c:2149
#, c-format
msgid "Object keys should be text."
-msgstr "Les cl�s de l'objet doivent �tre du texte."
+msgstr "Les clés de l'objet doivent être du texte."
#: utils/adt/json.c:2284 utils/adt/jsonb.c:1363
#, c-format
@@ -19270,7 +19249,7 @@ msgstr "le tableau doit avoir deux colonnes"
#: utils/adt/json.c:2308 utils/adt/json.c:2392 utils/adt/jsonb.c:1387 utils/adt/jsonb.c:1482
#, c-format
msgid "null value not allowed for object key"
-msgstr "valeur NULL non autoris�e pour une cl� d'objet"
+msgstr "valeur NULL non autorisée pour une clé d'objet"
#: utils/adt/json.c:2381 utils/adt/jsonb.c:1471
#, c-format
@@ -19280,59 +19259,59 @@ msgstr "dimensions du tableau non correspondantes"
#: utils/adt/jsonb.c:257
#, c-format
msgid "string too long to represent as jsonb string"
-msgstr "cha�ne trop longue pour �tre repr�sent�e en tant que cha�ne jsonb"
+msgstr "chaîne trop longue pour être représentée en tant que chaîne jsonb"
#: utils/adt/jsonb.c:258
#, c-format
msgid "Due to an implementation restriction, jsonb strings cannot exceed %d bytes."
-msgstr "D� � l'impl�mentation, les cha�nes jsonb ne peuvent exc�der %d octets."
+msgstr "Dû à l'implémentation, les chaînes jsonb ne peuvent excéder %d octets."
#: utils/adt/jsonb.c:1182
#, c-format
msgid "invalid number of arguments: object must be matched key value pairs"
-msgstr "nombre d'arguments invalide : l'objet doit correspond aux paires cl�/valeur"
+msgstr "nombre d'arguments invalide : l'objet doit correspond aux paires clé/valeur"
#: utils/adt/jsonb.c:1195
#, c-format
msgid "argument %d: key must not be null"
-msgstr "argument %d : la cl� ne doit pas �tre NULL"
+msgstr "argument %d : la clé ne doit pas être NULL"
#: utils/adt/jsonb.c:1214 utils/adt/jsonb.c:1237 utils/adt/jsonb.c:1297
#, c-format
msgid "argument %d: could not determine data type"
-msgstr "argument %d : n'a pas pu d�terminer le type de donn�es"
+msgstr "argument %d : n'a pas pu déterminer le type de données"
#: utils/adt/jsonb.c:1834
#, c-format
msgid "object keys must be strings"
-msgstr "les cl�s de l'objet doivent �tre du texte"
+msgstr "les clés de l'objet doivent être du texte"
#: utils/adt/jsonb_util.c:656
#, c-format
msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)"
-msgstr "le nombre de paires d'objets jsonb d�passe le maximum autoris� (%zu)"
+msgstr "le nombre de paires d'objets jsonb dépasse le maximum autorisé (%zu)"
#: utils/adt/jsonb_util.c:697
#, c-format
msgid "number of jsonb array elements exceeds the maximum allowed (%zu)"
-msgstr "le nombre d'�l�ments du tableau jsonb d�passe le maximum autoris� (%zu)"
+msgstr "le nombre d'éléments du tableau jsonb dépasse le maximum autorisé (%zu)"
#: utils/adt/jsonb_util.c:1525 utils/adt/jsonb_util.c:1545
#, c-format
msgid "total size of jsonb array elements exceeds the maximum of %u bytes"
-msgstr "la taille totale des �l�ments du tableau jsonb d�passe le maximum de %u octets"
+msgstr "la taille totale des éléments du tableau jsonb dépasse le maximum de %u octets"
#: utils/adt/jsonb_util.c:1606 utils/adt/jsonb_util.c:1641 utils/adt/jsonb_util.c:1661
#, c-format
msgid "total size of jsonb object elements exceeds the maximum of %u bytes"
-msgstr "la taille totale des �l�ments de l'objet JSON d�passe le maximum de %u octets"
+msgstr "la taille totale des éléments de l'objet JSON dépasse le maximum de %u octets"
-#: utils/adt/jsonfuncs.c:305 utils/adt/jsonfuncs.c:470 utils/adt/jsonfuncs.c:2065 utils/adt/jsonfuncs.c:2506 utils/adt/jsonfuncs.c:3012
+#: utils/adt/jsonfuncs.c:305 utils/adt/jsonfuncs.c:470 utils/adt/jsonfuncs.c:2057 utils/adt/jsonfuncs.c:2498 utils/adt/jsonfuncs.c:3004
#, c-format
msgid "cannot call %s on a scalar"
msgstr "ne peut pas appeler %s sur un scalaire"
-#: utils/adt/jsonfuncs.c:310 utils/adt/jsonfuncs.c:457 utils/adt/jsonfuncs.c:2495
+#: utils/adt/jsonfuncs.c:310 utils/adt/jsonfuncs.c:457 utils/adt/jsonfuncs.c:2487
#, c-format
msgid "cannot call %s on an array"
msgstr "ne peut pas appeler %s sur un tableau"
@@ -19352,143 +19331,142 @@ msgstr "ne peut pas obtenir la longueur du tableau d'un objet qui n'est pas un t
msgid "cannot call %s on a non-object"
msgstr "ne peut pas appeler %s sur un non objet"
-#: utils/adt/jsonfuncs.c:1491 utils/adt/jsonfuncs.c:2178 utils/adt/jsonfuncs.c:2715
+#: utils/adt/jsonfuncs.c:1491 utils/adt/jsonfuncs.c:2170 utils/adt/jsonfuncs.c:2707
#, c-format
msgid "function returning record called in context that cannot accept type record"
msgstr ""
-"fonction renvoyant le type record appel�e dans un contexte qui ne peut pas\n"
+"fonction renvoyant le type record appelée dans un contexte qui ne peut pas\n"
"accepter le type record"
-#: utils/adt/jsonfuncs.c:1734
+#: utils/adt/jsonfuncs.c:1730
#, c-format
msgid "cannot deconstruct an array as an object"
-msgstr "ne peut pas d�construire un tableau sous la forme d'un objet"
+msgstr "ne peut pas déconstruire un tableau sous la forme d'un objet"
-#: utils/adt/jsonfuncs.c:1746
+#: utils/adt/jsonfuncs.c:1742
#, c-format
msgid "cannot deconstruct a scalar"
-msgstr "ne peut pas d�composer un scalaire"
+msgstr "ne peut pas décomposer un scalaire"
-#: utils/adt/jsonfuncs.c:1792
+#: utils/adt/jsonfuncs.c:1788
#, c-format
msgid "cannot extract elements from a scalar"
-msgstr "ne peut pas extraire des �l�ments d'un scalaire"
+msgstr "ne peut pas extraire des éléments d'un scalaire"
-#: utils/adt/jsonfuncs.c:1796
+#: utils/adt/jsonfuncs.c:1792
#, c-format
msgid "cannot extract elements from an object"
-msgstr "ne peut pas extraire des �l�ments d'un objet"
+msgstr "ne peut pas extraire des éléments d'un objet"
-#: utils/adt/jsonfuncs.c:2052 utils/adt/jsonfuncs.c:2811
+#: utils/adt/jsonfuncs.c:2044 utils/adt/jsonfuncs.c:2803
#, c-format
msgid "cannot call %s on a non-array"
msgstr "ne peut pas appeler %s sur un type non tableau"
-#: utils/adt/jsonfuncs.c:2139 utils/adt/jsonfuncs.c:2691
+#: utils/adt/jsonfuncs.c:2131 utils/adt/jsonfuncs.c:2683
#, c-format
msgid "first argument of %s must be a row type"
-msgstr "le premier argument de %s doit �tre un type row"
+msgstr "le premier argument de %s doit être un type row"
-#: utils/adt/jsonfuncs.c:2180
+#: utils/adt/jsonfuncs.c:2172
#, c-format
msgid "Try calling the function in the FROM clause using a column definition list."
-msgstr "Essayez d'appeler la fonction dans la clause FROM en utilisant une liste de d�finition de colonnes."
+msgstr "Essayez d'appeler la fonction dans la clause FROM en utilisant une liste de définition de colonnes."
-#: utils/adt/jsonfuncs.c:2827 utils/adt/jsonfuncs.c:2994
+#: utils/adt/jsonfuncs.c:2819 utils/adt/jsonfuncs.c:2986
#, c-format
msgid "argument of %s must be an array of objects"
-msgstr "l'argument de %s doit �tre un tableau d'objets"
+msgstr "l'argument de %s doit être un tableau d'objets"
-#: utils/adt/jsonfuncs.c:2851
+#: utils/adt/jsonfuncs.c:2843
#, c-format
msgid "cannot call %s on an object"
msgstr "ne peut pas appeler %s sur un objet"
-#: utils/adt/jsonfuncs.c:3418 utils/adt/jsonfuncs.c:3471
+#: utils/adt/jsonfuncs.c:3410 utils/adt/jsonfuncs.c:3463
#, c-format
msgid "cannot delete from scalar"
-msgstr "ne peut pas supprimer � partir du scalaire"
+msgstr "ne peut pas supprimer à partir du scalaire"
-#: utils/adt/jsonfuncs.c:3476
+#: utils/adt/jsonfuncs.c:3468
#, c-format
msgid "cannot delete from object using integer index"
-msgstr "ne peut pas supprimer � partir de l'objet en utilisant l'index de l'entier"
+msgstr "ne peut pas supprimer à partir de l'objet en utilisant l'index de l'entier"
-#: utils/adt/jsonfuncs.c:3542 utils/adt/jsonfuncs.c:3634
+#: utils/adt/jsonfuncs.c:3534 utils/adt/jsonfuncs.c:3626
#, c-format
msgid "cannot set path in scalar"
msgstr "ne peut pas initialiser le chemin dans le scalaire"
-#: utils/adt/jsonfuncs.c:3587
+#: utils/adt/jsonfuncs.c:3579
#, c-format
msgid "cannot delete path in scalar"
msgstr "ne peut pas supprimer un chemin dans le scalaire"
-#: utils/adt/jsonfuncs.c:3757
+#: utils/adt/jsonfuncs.c:3749
#, c-format
msgid "invalid concatenation of jsonb objects"
-msgstr "concat�nation invalide d'objets jsonb"
+msgstr "concaténation invalide d'objets jsonb"
-#: utils/adt/jsonfuncs.c:3791
+#: utils/adt/jsonfuncs.c:3783
#, c-format
msgid "path element at position %d is null"
-msgstr ""
+msgstr "l'élément de chemin à la position %d est nul"
-#: utils/adt/jsonfuncs.c:3877
+#: utils/adt/jsonfuncs.c:3869
#, c-format
msgid "cannot replace existing key"
-msgstr "ne peut pas remplacer une cl� existante"
+msgstr "ne peut pas remplacer une clé existante"
-#: utils/adt/jsonfuncs.c:3878
+#: utils/adt/jsonfuncs.c:3870
#, c-format
msgid "Try using the function jsonb_set to replace key value."
-msgstr ""
+msgstr "Essayez d'utiliser la fonction jsonb_set pour remplacer la valeur de la clé."
-#: utils/adt/jsonfuncs.c:3960
-#, fuzzy, c-format
-#| msgid "plpy.prepare: type name at ordinal position %d is not a string"
+#: utils/adt/jsonfuncs.c:3952
+#, c-format
msgid "path element at position %d is not an integer: \"%s\""
-msgstr "plpy.prepare : le nom du type sur la position ordinale %d n'est pas une cha�ne"
+msgstr "l'élément du chemin à la position %d n'est pas un entier : « %s »"
#: utils/adt/levenshtein.c:133
#, c-format
msgid "levenshtein argument exceeds maximum length of %d characters"
-msgstr "l'argument levenshtein d�passe la longueur maximale de %d caract�res"
+msgstr "l'argument levenshtein dépasse la longueur maximale de %d caractères"
-#: utils/adt/like.c:212 utils/adt/selfuncs.c:5329
+#: utils/adt/like.c:212 utils/adt/selfuncs.c:5333
#, c-format
msgid "could not determine which collation to use for ILIKE"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour ILIKE"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour ILIKE"
#: utils/adt/like_match.c:107 utils/adt/like_match.c:167
#, c-format
msgid "LIKE pattern must not end with escape character"
-msgstr "le motif LIKE ne se termine pas de caract�res d'�chappement"
+msgstr "le motif LIKE ne se termine pas de caractères d'échappement"
#: utils/adt/like_match.c:292 utils/adt/regexp.c:698
#, c-format
msgid "invalid escape string"
-msgstr "cha�ne d'�chappement invalide"
+msgstr "chaîne d'échappement invalide"
#: utils/adt/like_match.c:293 utils/adt/regexp.c:699
#, c-format
msgid "Escape string must be empty or one character."
-msgstr "La cha�ne d'�chappement doit �tre vide ou ne contenir qu'un caract�re."
+msgstr "La chaîne d'échappement doit être vide ou ne contenir qu'un caractère."
#: utils/adt/lockfuncs.c:545
#, c-format
msgid "cannot use advisory locks during a parallel operation"
-msgstr "ne peut pas utiliser les verrous informatifs lors d'une op�ration parall�le"
+msgstr "ne peut pas utiliser les verrous informatifs lors d'une opération parallèle"
#: utils/adt/mac.c:68
#, c-format
msgid "invalid input syntax for type macaddr: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type macaddr : � %s �"
+msgstr "syntaxe en entrée invalide pour le type macaddr : « %s »"
#: utils/adt/mac.c:75
#, c-format
msgid "invalid octet value in \"macaddr\" value: \"%s\""
-msgstr "valeur d'un octet invalide dans la valeur de � macaddr � : � %s �"
+msgstr "valeur d'un octet invalide dans la valeur de « macaddr » : « %s »"
#: utils/adt/misc.c:239
#, c-format
@@ -19498,24 +19476,22 @@ msgstr "le PID %d n'est pas un processus du serveur PostgreSQL"
#: utils/adt/misc.c:290
#, c-format
msgid "must be a superuser to cancel superuser query"
-msgstr "doit �tre super-utilisateur pour annuler la requ�te d'un super-utilisateur"
+msgstr "doit être super-utilisateur pour annuler la requête d'un super-utilisateur"
#: utils/adt/misc.c:295
-#, fuzzy, c-format
-#| msgid "must be a member of the role whose query is being canceled"
+#, c-format
msgid "must be a member of the role whose query is being canceled or member of pg_signal_backend"
-msgstr "doit �tre un membre du r�le dont la requ�te est en cours d'annulation"
+msgstr "doit être un membre du rôle dont la requête est en cours d'annulation ou membre de pg_signal_backend"
#: utils/adt/misc.c:314
#, c-format
msgid "must be a superuser to terminate superuser process"
-msgstr "doit �tre super-utilisateur pour terminer le processus d'un super-utilisateur"
+msgstr "doit être super-utilisateur pour terminer le processus d'un super-utilisateur"
#: utils/adt/misc.c:319
-#, fuzzy, c-format
-#| msgid "must be a member of the role whose process is being terminated"
+#, c-format
msgid "must be a member of the role whose process is being terminated or member of pg_signal_backend"
-msgstr "doit �tre un membre du r�le dont le processus est en cours d'arr�t"
+msgstr "doit être un membre du rôle dont le processus est en cours d'arrêt ou membre de pg_signal_backend"
#: utils/adt/misc.c:336
#, c-format
@@ -19525,12 +19501,12 @@ msgstr "n'a pas pu envoyer le signal au postmaster : %m"
#: utils/adt/misc.c:356
#, c-format
msgid "rotation not possible because log collection not active"
-msgstr "rotation impossible car la r�cup�ration des journaux applicatifs n'est pas activ�e"
+msgstr "rotation impossible car la récupération des journaux applicatifs n'est pas activée"
#: utils/adt/misc.c:393
#, c-format
msgid "global tablespace never has databases"
-msgstr "le tablespace global n'a jamais de bases de donn�es"
+msgstr "le tablespace global n'a jamais de bases de données"
#: utils/adt/misc.c:414
#, c-format
@@ -19539,79 +19515,79 @@ msgstr "%u n'est pas un OID de tablespace"
#: utils/adt/misc.c:611
msgid "unreserved"
-msgstr "non r�serv�"
+msgstr "non réservé"
#: utils/adt/misc.c:615
msgid "unreserved (cannot be function or type name)"
-msgstr "non r�serv� (ne peut pas �tre un nom de fonction ou de type)"
+msgstr "non réservé (ne peut pas être un nom de fonction ou de type)"
#: utils/adt/misc.c:619
msgid "reserved (can be function or type name)"
-msgstr "r�serv� (peut �tre un nom de fonction ou de type)"
+msgstr "réservé (peut être un nom de fonction ou de type)"
#: utils/adt/misc.c:623
msgid "reserved"
-msgstr "r�serv�"
+msgstr "réservé"
#: utils/adt/misc.c:797 utils/adt/misc.c:811 utils/adt/misc.c:850 utils/adt/misc.c:856 utils/adt/misc.c:862 utils/adt/misc.c:885
#, c-format
msgid "string is not a valid identifier: \"%s\""
-msgstr "la cha�ne n'est pas un identifiant valide : � %s �"
+msgstr "la chaîne n'est pas un identifiant valide : « %s »"
#: utils/adt/misc.c:799
#, c-format
msgid "String has unclosed double quotes."
-msgstr ""
+msgstr "La chaîne des des guillements doubles non fermés."
#: utils/adt/misc.c:813
#, c-format
msgid "Quoted identifier must not be empty."
-msgstr "L'identifiant entre guillemets ne doit pas �tre vide."
+msgstr "L'identifiant entre guillemets ne doit pas être vide."
#: utils/adt/misc.c:852
#, c-format
-msgid "No valid identifier before \".\" symbol."
-msgstr ""
+msgid "No valid identifier before \".\"."
+msgstr "Pas d'identifiant valide avant « . »."
#: utils/adt/misc.c:858
#, c-format
-msgid "No valid identifier after \".\" symbol."
-msgstr ""
+msgid "No valid identifier after \".\"."
+msgstr "Pas d'identifiant valide après « . »."
#: utils/adt/nabstime.c:136
#, c-format
msgid "invalid time zone name: \"%s\""
-msgstr "nom du fuseau horaire invalide : � %s �"
+msgstr "nom du fuseau horaire invalide : « %s »"
#: utils/adt/nabstime.c:481 utils/adt/nabstime.c:554
#, c-format
msgid "cannot convert abstime \"invalid\" to timestamp"
-msgstr "ne peut pas convertir un abstime � invalid � en timestamp"
+msgstr "ne peut pas convertir un abstime « invalid » en timestamp"
#: utils/adt/nabstime.c:781
#, c-format
msgid "invalid status in external \"tinterval\" value"
-msgstr "statut invalide dans la valeur externe � tinterval �"
+msgstr "statut invalide dans la valeur externe « tinterval »"
#: utils/adt/nabstime.c:855
#, c-format
msgid "cannot convert reltime \"invalid\" to interval"
-msgstr "ne peut pas convertir reltime � invalid � en interval"
+msgstr "ne peut pas convertir reltime « invalid » en interval"
#: utils/adt/nabstime.c:1550
#, c-format
msgid "invalid input syntax for type tinterval: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type tinterval : � %s �"
+msgstr "syntaxe en entrée invalide pour le type tinterval : « %s »"
#: utils/adt/network.c:69
#, c-format
msgid "invalid cidr value: \"%s\""
-msgstr "valeur cidr invalide : � %s �"
+msgstr "valeur cidr invalide : « %s »"
#: utils/adt/network.c:70 utils/adt/network.c:200
#, c-format
msgid "Value has bits set to right of mask."
-msgstr "La valeur a des bits positionn�s � la droite du masque."
+msgstr "La valeur a des bits positionnés à la droite du masque."
#: utils/adt/network.c:111 utils/adt/network.c:607 utils/adt/network.c:632 utils/adt/network.c:657
#, c-format
@@ -19622,24 +19598,24 @@ msgstr "n'a pas pu formater la valeur inet : %m"
#: utils/adt/network.c:168
#, c-format
msgid "invalid address family in external \"%s\" value"
-msgstr "famille d'adresses invalide dans la valeur externe � %s �"
+msgstr "famille d'adresses invalide dans la valeur externe « %s »"
#. translator: %s is inet or cidr
#: utils/adt/network.c:175
#, c-format
msgid "invalid bits in external \"%s\" value"
-msgstr "bits invalides dans la valeur externe � %s �"
+msgstr "bits invalides dans la valeur externe « %s »"
#. translator: %s is inet or cidr
#: utils/adt/network.c:184
#, c-format
msgid "invalid length in external \"%s\" value"
-msgstr "longueur invalide dans la valeur externe � %s �"
+msgstr "longueur invalide dans la valeur externe « %s »"
#: utils/adt/network.c:199
#, c-format
msgid "invalid external \"cidr\" value"
-msgstr "valeur externe � cidr � invalide"
+msgstr "valeur externe « cidr » invalide"
#: utils/adt/network.c:321 utils/adt/network.c:348
#, c-format
@@ -19654,232 +19630,227 @@ msgstr "n'a pas pu formater la valeur cidr : %m"
#: utils/adt/network.c:917
#, c-format
msgid "cannot merge addresses from different families"
-msgstr "ne peut pas assembler les adresses de familles diff�rentes"
+msgstr "ne peut pas assembler les adresses de familles différentes"
#: utils/adt/network.c:1343
#, c-format
msgid "cannot AND inet values of different sizes"
msgstr ""
-"ne peut pas utiliser l'op�rateur AND sur des champs de type inet de tailles\n"
-"diff�rentes"
+"ne peut pas utiliser l'opérateur AND sur des champs de type inet de tailles\n"
+"différentes"
#: utils/adt/network.c:1375
#, c-format
msgid "cannot OR inet values of different sizes"
msgstr ""
-"ne peut pas utiliser l'op�rateur OR sur des champs de type inet de tailles\n"
-"diff�rentes"
+"ne peut pas utiliser l'opérateur OR sur des champs de type inet de tailles\n"
+"différentes"
#: utils/adt/network.c:1436 utils/adt/network.c:1512
#, c-format
msgid "result is out of range"
-msgstr "le r�sultat est en dehors des limites"
+msgstr "le résultat est en dehors des limites"
#: utils/adt/network.c:1477
#, c-format
msgid "cannot subtract inet values of different sizes"
-msgstr "ne peut pas soustraire des valeurs inet de tailles diff�rentes"
+msgstr "ne peut pas soustraire des valeurs inet de tailles différentes"
-#: utils/adt/numeric.c:542 utils/adt/numeric.c:569 utils/adt/numeric.c:5394 utils/adt/numeric.c:5417 utils/adt/numeric.c:5441 utils/adt/numeric.c:5448
+#: utils/adt/numeric.c:542 utils/adt/numeric.c:569 utils/adt/numeric.c:5405 utils/adt/numeric.c:5428 utils/adt/numeric.c:5452
#, c-format
msgid "invalid input syntax for type numeric: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type numeric : � %s �"
+msgstr "syntaxe en entrée invalide pour le type numeric : « %s »"
-#: utils/adt/numeric.c:759
-#, c-format
-msgid "invalid length in external \"numeric\" value"
-msgstr "longueur invalide dans la valeur externe � numeric �"
-
-#: utils/adt/numeric.c:772
+#: utils/adt/numeric.c:768
#, c-format
msgid "invalid sign in external \"numeric\" value"
-msgstr "signe invalide dans la valeur externe � numeric �"
+msgstr "signe invalide dans la valeur externe « numeric »"
-#: utils/adt/numeric.c:778
+#: utils/adt/numeric.c:774
#, c-format
msgid "invalid scale in external \"numeric\" value"
-msgstr "�chelle invalide dans la valeur externe � numeric �"
+msgstr "échelle invalide dans la valeur externe « numeric »"
-#: utils/adt/numeric.c:787
+#: utils/adt/numeric.c:783
#, c-format
msgid "invalid digit in external \"numeric\" value"
-msgstr "chiffre invalide dans la valeur externe � numeric �"
+msgstr "chiffre invalide dans la valeur externe « numeric »"
-#: utils/adt/numeric.c:978 utils/adt/numeric.c:992
+#: utils/adt/numeric.c:974 utils/adt/numeric.c:988
#, c-format
msgid "NUMERIC precision %d must be between 1 and %d"
-msgstr "la pr�cision NUMERIC %d doit �tre comprise entre 1 et %d"
+msgstr "la précision NUMERIC %d doit être comprise entre 1 et %d"
-#: utils/adt/numeric.c:983
+#: utils/adt/numeric.c:979
#, c-format
msgid "NUMERIC scale %d must be between 0 and precision %d"
-msgstr "l'�chelle NUMERIC %d doit �tre comprise entre 0 et %d"
+msgstr "l'échelle NUMERIC %d doit être comprise entre 0 et %d"
-#: utils/adt/numeric.c:1001
+#: utils/adt/numeric.c:997
#, c-format
msgid "invalid NUMERIC type modifier"
msgstr "modificateur de type NUMERIC invalide"
-#: utils/adt/numeric.c:1333
+#: utils/adt/numeric.c:1329
#, c-format
msgid "start value cannot be NaN"
-msgstr "la valeur de d�marrage ne peut pas �tre NaN"
+msgstr "la valeur de démarrage ne peut pas être NaN"
-#: utils/adt/numeric.c:1338
+#: utils/adt/numeric.c:1334
#, c-format
msgid "stop value cannot be NaN"
-msgstr "la valeur d'arr�t ne peut pas �tre NaN"
+msgstr "la valeur d'arrêt ne peut pas être NaN"
-#: utils/adt/numeric.c:1348
+#: utils/adt/numeric.c:1344
#, c-format
msgid "step size cannot be NaN"
-msgstr "la taille du pas ne peut pas �tre NaN"
+msgstr "la taille du pas ne peut pas être NaN"
-#: utils/adt/numeric.c:2543 utils/adt/numeric.c:5894 utils/adt/numeric.c:7598 utils/adt/numeric.c:8023 utils/adt/numeric.c:8138 utils/adt/numeric.c:8211
+#: utils/adt/numeric.c:2539 utils/adt/numeric.c:5467 utils/adt/numeric.c:5912 utils/adt/numeric.c:7616 utils/adt/numeric.c:8041 utils/adt/numeric.c:8156 utils/adt/numeric.c:8229
#, c-format
msgid "value overflows numeric format"
-msgstr "la valeur d�passe le format numeric"
+msgstr "la valeur dépasse le format numeric"
-#: utils/adt/numeric.c:2885
+#: utils/adt/numeric.c:2881
#, c-format
msgid "cannot convert NaN to integer"
msgstr "ne peut pas convertir NaN en un entier"
-#: utils/adt/numeric.c:2951
+#: utils/adt/numeric.c:2947
#, c-format
msgid "cannot convert NaN to bigint"
msgstr "ne peut pas convertir NaN en un entier de type bigint"
-#: utils/adt/numeric.c:2996
+#: utils/adt/numeric.c:2992
#, c-format
msgid "cannot convert NaN to smallint"
msgstr "ne peut pas convertir NaN en un entier de type smallint"
-#: utils/adt/numeric.c:5964
+#: utils/adt/numeric.c:5982
#, c-format
msgid "numeric field overflow"
-msgstr "champ num�rique en dehors des limites"
+msgstr "champ numérique en dehors des limites"
-#: utils/adt/numeric.c:5965
+#: utils/adt/numeric.c:5983
#, c-format
msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d."
msgstr ""
-"Un champ de pr�cision %d et d'�chelle %d doit �tre arrondi � une valeur\n"
-"absolue inf�rieure � %s%d."
+"Un champ de précision %d et d'échelle %d doit être arrondi à une valeur\n"
+"absolue inférieure à %s%d."
-#: utils/adt/numeric.c:6236 utils/adt/numeric.c:6262
+#: utils/adt/numeric.c:6254 utils/adt/numeric.c:6280
#, c-format
msgid "invalid input syntax for type double precision: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type double precision : � %s �"
+msgstr "syntaxe en entrée invalide pour le type double precision : « %s »"
#: utils/adt/numutils.c:75
#, c-format
msgid "value \"%s\" is out of range for type integer"
-msgstr "la valeur � %s � est en dehors des limites du type integer"
+msgstr "la valeur « %s » est en dehors des limites du type integer"
#: utils/adt/numutils.c:81
#, c-format
msgid "value \"%s\" is out of range for type smallint"
-msgstr "la valeur � %s � est en dehors des limites du type smallint"
+msgstr "la valeur « %s » est en dehors des limites du type smallint"
#: utils/adt/numutils.c:87
#, c-format
msgid "value \"%s\" is out of range for 8-bit integer"
-msgstr "la valeur � %s � est en dehors des limites des entiers sur 8 bits"
+msgstr "la valeur « %s » est en dehors des limites des entiers sur 8 bits"
#: utils/adt/oid.c:43 utils/adt/oid.c:57 utils/adt/oid.c:63 utils/adt/oid.c:84
#, c-format
msgid "invalid input syntax for type oid: \"%s\""
-msgstr "syntaxe invalide en entr�e pour le type oid : � %s �"
+msgstr "syntaxe invalide en entrée pour le type oid : « %s »"
#: utils/adt/oid.c:69 utils/adt/oid.c:107
#, c-format
msgid "value \"%s\" is out of range for type oid"
-msgstr "la valeur � %s � est en dehors des limites pour le type oid"
+msgstr "la valeur « %s » est en dehors des limites pour le type oid"
#: utils/adt/oid.c:287
#, c-format
msgid "invalid oidvector data"
-msgstr "donn�e oidvector invalide"
+msgstr "donnée oidvector invalide"
#: utils/adt/oracle_compat.c:895
#, c-format
msgid "requested character too large"
-msgstr "caract�re demand� trop long"
+msgstr "caractère demandé trop long"
#: utils/adt/oracle_compat.c:945 utils/adt/oracle_compat.c:1007
#, c-format
msgid "requested character too large for encoding: %d"
-msgstr "caract�re demand� trop long pour l'encodage : %d"
+msgstr "caractère demandé trop long pour l'encodage : %d"
#: utils/adt/oracle_compat.c:986
#, c-format
msgid "requested character not valid for encoding: %d"
-msgstr "caract�re demand� invalide pour l'encodage : %d"
+msgstr "caractère demandé invalide pour l'encodage : %d"
#: utils/adt/oracle_compat.c:1000
#, c-format
msgid "null character not permitted"
-msgstr "caract�re nul interdit"
+msgstr "caractère nul interdit"
#: utils/adt/orderedsetaggs.c:425 utils/adt/orderedsetaggs.c:530 utils/adt/orderedsetaggs.c:669
#, c-format
msgid "percentile value %g is not between 0 and 1"
msgstr "la valeur centile %g n'est pas entre 0 et 1"
-#: utils/adt/pg_locale.c:917
+#: utils/adt/pg_locale.c:1029
#, c-format
msgid "Apply system library package updates."
-msgstr "Applique les mises � jour du paquet de biblioth�que syst�me."
+msgstr "Applique les mises à jour du paquet de bibliothèque système."
-#: utils/adt/pg_locale.c:1122
+#: utils/adt/pg_locale.c:1234
#, c-format
msgid "could not create locale \"%s\": %m"
-msgstr "n'a pas pu cr�er la locale � %s � : %m"
+msgstr "n'a pas pu créer la locale « %s » : %m"
-#: utils/adt/pg_locale.c:1125
+#: utils/adt/pg_locale.c:1237
#, c-format
msgid "The operating system could not find any locale data for the locale name \"%s\"."
-msgstr "Le syst�me d'exploitation n'a pas pu trouver des donn�es de locale pour la locale � %s �."
+msgstr "Le système d'exploitation n'a pas pu trouver des données de locale pour la locale « %s »."
-#: utils/adt/pg_locale.c:1212
+#: utils/adt/pg_locale.c:1324
#, c-format
msgid "collations with different collate and ctype values are not supported on this platform"
msgstr ""
-"les collationnements avec des valeurs diff�rents pour le tri et le jeu de\n"
-"caract�res ne sont pas support�s sur cette plateforme"
+"les collationnements avec des valeurs différents pour le tri et le jeu de\n"
+"caractères ne sont pas supportés sur cette plateforme"
-#: utils/adt/pg_locale.c:1227
+#: utils/adt/pg_locale.c:1339
#, c-format
msgid "nondefault collations are not supported on this platform"
-msgstr "les collationnements autres que par d�faut ne sont pas support�s sur cette plateforme"
+msgstr "les collationnements autres que par défaut ne sont pas supportés sur cette plateforme"
-#: utils/adt/pg_locale.c:1398
+#: utils/adt/pg_locale.c:1510
#, c-format
msgid "invalid multibyte character for locale"
-msgstr "caract�re multi-octets invalide pour la locale"
+msgstr "caractère multi-octets invalide pour la locale"
-#: utils/adt/pg_locale.c:1399
+#: utils/adt/pg_locale.c:1511
#, c-format
msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding."
msgstr ""
"La locale LC_CTYPE du serveur est probablement incompatible avec l'encodage\n"
-"de la base de donn�es."
+"de la base de données."
#: utils/adt/pg_lsn.c:44 utils/adt/pg_lsn.c:49
#, c-format
msgid "invalid input syntax for type pg_lsn: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type pg_lsn : � %s �"
+msgstr "syntaxe en entrée invalide pour le type pg_lsn : « %s »"
#: utils/adt/pg_upgrade_support.c:40
#, c-format
msgid "function can only be called when server is in binary upgrade mode"
-msgstr "la fonction peut seulement �tre appel�e quand le serveur est en mode de mise � jour binaire"
+msgstr "la fonction peut seulement être appelée quand le serveur est en mode de mise à jour binaire"
#: utils/adt/pgstatfuncs.c:571
#, c-format
msgid "invalid command name: \"%s\""
-msgstr "nom de commande invalide : � %s �"
+msgstr "nom de commande invalide : « %s »"
#: utils/adt/pseudotypes.c:95
#, c-format
@@ -20029,24 +20000,24 @@ msgstr "ne peut pas afficher une valeur de type %s"
#: utils/adt/rangetypes.c:405
#, c-format
msgid "range constructor flags argument must not be null"
-msgstr "l'argument flags du contructeur d'intervalle ne doit pas �tre NULL"
+msgstr "l'argument flags du contructeur d'intervalle ne doit pas être NULL"
#: utils/adt/rangetypes.c:992
#, c-format
msgid "result of range difference would not be contiguous"
-msgstr "le r�sultat de la diff�rence d'intervalle de valeur ne sera pas contigu"
+msgstr "le résultat de la différence d'intervalle de valeur ne sera pas contigu"
#: utils/adt/rangetypes.c:1053
#, c-format
msgid "result of range union would not be contiguous"
-msgstr "le r�sultat de l'union d'intervalle pourrait ne pas �tre contig�"
+msgstr "le résultat de l'union d'intervalle pourrait ne pas être contigü"
#: utils/adt/rangetypes.c:1543
#, c-format
msgid "range lower bound must be less than or equal to range upper bound"
msgstr ""
-"la limite inf�rieure de l'intervalle de valeurs doit �tre inf�rieure ou �gale\n"
-"� la limite sup�rieure de l'intervalle de valeurs"
+"la limite inférieure de l'intervalle de valeurs doit être inférieure ou égale\n"
+"à la limite supérieure de l'intervalle de valeurs"
#: utils/adt/rangetypes.c:1926 utils/adt/rangetypes.c:1939 utils/adt/rangetypes.c:1953
#, c-format
@@ -20056,27 +20027,27 @@ msgstr "drapeaux de limite de l'intervalle invalides"
#: utils/adt/rangetypes.c:1927 utils/adt/rangetypes.c:1940 utils/adt/rangetypes.c:1954
#, c-format
msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"."
-msgstr "Les valeurs valides sont entre � [] �, � [) �, � (] � et � () �."
+msgstr "Les valeurs valides sont entre « [] », « [) », « (] » et « () »."
#: utils/adt/rangetypes.c:2019 utils/adt/rangetypes.c:2036 utils/adt/rangetypes.c:2049 utils/adt/rangetypes.c:2067 utils/adt/rangetypes.c:2078 utils/adt/rangetypes.c:2122 utils/adt/rangetypes.c:2130
#, c-format
msgid "malformed range literal: \"%s\""
-msgstr "intervalle lit�ral mal form� : � %s �"
+msgstr "intervalle litéral mal formé : « %s »"
#: utils/adt/rangetypes.c:2021
#, c-format
msgid "Junk after \"empty\" key word."
-msgstr "Cochonnerie apr�s le mot cl� � empty �"
+msgstr "Cochonnerie après le mot clé « empty »"
#: utils/adt/rangetypes.c:2038
#, c-format
msgid "Missing left parenthesis or bracket."
-msgstr "Parenth�se gauche ou crochet manquant"
+msgstr "Parenthèse gauche ou crochet manquant"
#: utils/adt/rangetypes.c:2051
#, c-format
msgid "Missing comma after lower bound."
-msgstr "Virgule manquante apr�s une limite basse."
+msgstr "Virgule manquante après une limite basse."
#: utils/adt/rangetypes.c:2069
#, c-format
@@ -20086,17 +20057,17 @@ msgstr "Trop de virgules."
#: utils/adt/rangetypes.c:2080
#, c-format
msgid "Junk after right parenthesis or bracket."
-msgstr "Probl�me apr�s la parenth�se droite ou le crochet droit."
+msgstr "Problème après la parenthèse droite ou le crochet droit."
#: utils/adt/regexp.c:285 utils/adt/regexp.c:1288 utils/adt/varlena.c:3829
#, c-format
msgid "regular expression failed: %s"
-msgstr "l'expression rationnelle a �chou� : %s"
+msgstr "l'expression rationnelle a échoué : %s"
#: utils/adt/regexp.c:422
#, c-format
msgid "invalid regexp option: \"%c\""
-msgstr "option invalide de l'expression rationnelle : � %c �"
+msgstr "option invalide de l'expression rationnelle : « %c »"
#: utils/adt/regexp.c:948
#, c-format
@@ -20106,14 +20077,14 @@ msgstr "regexp_split ne supporte pas l'option globale"
#: utils/adt/regproc.c:128 utils/adt/regproc.c:148
#, c-format
msgid "more than one function named \"%s\""
-msgstr "il existe plus d'une fonction nomm�e � %s �"
+msgstr "il existe plus d'une fonction nommée « %s »"
#: utils/adt/regproc.c:587 utils/adt/regproc.c:607
#, c-format
msgid "more than one operator named %s"
-msgstr "il existe plus d'un op�rateur nomm�%s"
+msgstr "il existe plus d'un opérateur nommé%s"
-#: utils/adt/regproc.c:779 utils/adt/regproc.c:820 utils/adt/regproc.c:2006 utils/adt/ruleutils.c:8235 utils/adt/ruleutils.c:8401
+#: utils/adt/regproc.c:779 utils/adt/regproc.c:820 utils/adt/regproc.c:2006 utils/adt/ruleutils.c:8367 utils/adt/ruleutils.c:8536
#, c-format
msgid "too many arguments"
msgstr "trop d'arguments"
@@ -20121,7 +20092,7 @@ msgstr "trop d'arguments"
#: utils/adt/regproc.c:780 utils/adt/regproc.c:821
#, c-format
msgid "Provide two argument types for operator."
-msgstr "Fournit deux types d'argument pour l'op�rateur."
+msgstr "Fournit deux types d'argument pour l'opérateur."
#: utils/adt/regproc.c:1594 utils/adt/regproc.c:1618 utils/adt/regproc.c:1715 utils/adt/regproc.c:1739 utils/adt/regproc.c:1841 utils/adt/regproc.c:1846 utils/adt/varlena.c:3084 utils/adt/varlena.c:3089
#, c-format
@@ -20131,12 +20102,12 @@ msgstr "syntaxe du nom invalide"
#: utils/adt/regproc.c:1904
#, c-format
msgid "expected a left parenthesis"
-msgstr "attendait une parenth�se gauche"
+msgstr "attendait une parenthèse gauche"
#: utils/adt/regproc.c:1920
#, c-format
msgid "expected a right parenthesis"
-msgstr "attendait une parenth�se droite"
+msgstr "attendait une parenthèse droite"
#: utils/adt/regproc.c:1939
#, c-format
@@ -20148,98 +20119,98 @@ msgstr "attendait un nom de type"
msgid "improper type name"
msgstr "nom du type invalide"
-#: utils/adt/ri_triggers.c:345 utils/adt/ri_triggers.c:2492 utils/adt/ri_triggers.c:3317
+#: utils/adt/ri_triggers.c:343 utils/adt/ri_triggers.c:2490 utils/adt/ri_triggers.c:3315
#, c-format
msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\""
msgstr ""
-"une instruction insert ou update sur la table � %s � viole la contrainte de cl�\n"
-"�trang�re � %s �"
+"une instruction insert ou update sur la table « %s » viole la contrainte de clé\n"
+"étrangère « %s »"
-#: utils/adt/ri_triggers.c:348 utils/adt/ri_triggers.c:2495
+#: utils/adt/ri_triggers.c:346 utils/adt/ri_triggers.c:2493
#, c-format
msgid "MATCH FULL does not allow mixing of null and nonnull key values."
-msgstr "MATCH FULL n'autorise pas le mixage de valeurs cl�s NULL et non NULL."
+msgstr "MATCH FULL n'autorise pas le mixage de valeurs clés NULL et non NULL."
-#: utils/adt/ri_triggers.c:2734
+#: utils/adt/ri_triggers.c:2732
#, c-format
msgid "function \"%s\" must be fired for INSERT"
-msgstr "la fonction � %s � doit �tre ex�cut�e pour l'instruction INSERT"
+msgstr "la fonction « %s » doit être exécutée pour l'instruction INSERT"
-#: utils/adt/ri_triggers.c:2740
+#: utils/adt/ri_triggers.c:2738
#, c-format
msgid "function \"%s\" must be fired for UPDATE"
-msgstr "la fonction � %s � doit �tre ex�cut�e pour l'instruction UPDATE"
+msgstr "la fonction « %s » doit être exécutée pour l'instruction UPDATE"
-#: utils/adt/ri_triggers.c:2746
+#: utils/adt/ri_triggers.c:2744
#, c-format
msgid "function \"%s\" must be fired for DELETE"
-msgstr "la fonction � %s � doit �tre ex�cut�e pour l'instruction DELETE"
+msgstr "la fonction « %s » doit être exécutée pour l'instruction DELETE"
-#: utils/adt/ri_triggers.c:2769
+#: utils/adt/ri_triggers.c:2767
#, c-format
msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\""
-msgstr "aucune entr�e pg_constraint pour le trigger � %s � sur la table � %s �"
+msgstr "aucune entrée pg_constraint pour le trigger « %s » sur la table « %s »"
-#: utils/adt/ri_triggers.c:2771
+#: utils/adt/ri_triggers.c:2769
#, c-format
msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT."
msgstr ""
-"Supprimez ce trigger sur une int�grit� r�f�rentielle et ses enfants,\n"
+"Supprimez ce trigger sur une intégrité référentielle et ses enfants,\n"
"puis faites un ALTER TABLE ADD CONSTRAINT."
-#: utils/adt/ri_triggers.c:3227
+#: utils/adt/ri_triggers.c:3225
#, c-format
msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result"
msgstr ""
-"la requ�te d'int�grit� r�f�rentielle sur � %s � � partir de la contrainte � %s �\n"
-"sur � %s � donne des r�sultats inattendus"
+"la requête d'intégrité référentielle sur « %s » à partir de la contrainte « %s »\n"
+"sur « %s » donne des résultats inattendus"
-#: utils/adt/ri_triggers.c:3231
+#: utils/adt/ri_triggers.c:3229
#, c-format
msgid "This is most likely due to a rule having rewritten the query."
-msgstr "Ceci est certainement d� � une r�gle qui a r�-�crit la requ�te."
+msgstr "Ceci est certainement dû à une règle qui a ré-écrit la requête."
-#: utils/adt/ri_triggers.c:3321
+#: utils/adt/ri_triggers.c:3319
#, c-format
msgid "Key (%s)=(%s) is not present in table \"%s\"."
-msgstr "La cl� (%s)=(%s) n'est pas pr�sente dans la table � %s �."
+msgstr "La clé (%s)=(%s) n'est pas présente dans la table « %s »."
-#: utils/adt/ri_triggers.c:3324
+#: utils/adt/ri_triggers.c:3322
#, c-format
msgid "Key is not present in table \"%s\"."
-msgstr "La cl� n'est pas pr�sente dans la table � %s �."
+msgstr "La clé n'est pas présente dans la table « %s »."
-#: utils/adt/ri_triggers.c:3330
+#: utils/adt/ri_triggers.c:3328
#, c-format
msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\""
msgstr ""
-"UPDATE ou DELETE sur la table � %s � viole la contrainte de cl� �trang�re\n"
-"� %s � de la table � %s �"
+"UPDATE ou DELETE sur la table « %s » viole la contrainte de clé étrangère\n"
+"« %s » de la table « %s »"
-#: utils/adt/ri_triggers.c:3335
+#: utils/adt/ri_triggers.c:3333
#, c-format
msgid "Key (%s)=(%s) is still referenced from table \"%s\"."
-msgstr "La cl� (%s)=(%s) est toujours r�f�renc�e � partir de la table � %s �."
+msgstr "La clé (%s)=(%s) est toujours référencée à partir de la table « %s »."
-#: utils/adt/ri_triggers.c:3338
+#: utils/adt/ri_triggers.c:3336
#, c-format
msgid "Key is still referenced from table \"%s\"."
-msgstr "La cl� est toujours r�f�renc�e � partir de la table � %s �."
+msgstr "La clé est toujours référencée à partir de la table « %s »."
#: utils/adt/rowtypes.c:103 utils/adt/rowtypes.c:479
#, c-format
msgid "input of anonymous composite types is not implemented"
-msgstr "l'ajout de colonnes ayant un type compos� n'est pas impl�ment�"
+msgstr "l'ajout de colonnes ayant un type composé n'est pas implémenté"
#: utils/adt/rowtypes.c:155 utils/adt/rowtypes.c:183 utils/adt/rowtypes.c:206 utils/adt/rowtypes.c:214 utils/adt/rowtypes.c:266 utils/adt/rowtypes.c:274
#, c-format
msgid "malformed record literal: \"%s\""
-msgstr "enregistrement lit�ral invalide : � %s �"
+msgstr "enregistrement litéral invalide : « %s »"
#: utils/adt/rowtypes.c:156
#, c-format
msgid "Missing left parenthesis."
-msgstr "Parenth�se gauche manquante"
+msgstr "Parenthèse gauche manquante"
#: utils/adt/rowtypes.c:184
#, c-format
@@ -20254,7 +20225,7 @@ msgstr "Trop de colonnes."
#: utils/adt/rowtypes.c:275
#, c-format
msgid "Junk after right parenthesis."
-msgstr "Probl�me apr�s la parenth�se droite."
+msgstr "Problème après la parenthèse droite."
#: utils/adt/rowtypes.c:528
#, c-format
@@ -20264,7 +20235,7 @@ msgstr "mauvais nombre de colonnes : %d, alors que %d attendu"
#: utils/adt/rowtypes.c:555
#, c-format
msgid "wrong data type: %u, expected %u"
-msgstr "mauvais type de donn�es : %u, alors que %u attendu"
+msgstr "mauvais type de données : %u, alors que %u attendu"
#: utils/adt/rowtypes.c:616
#, c-format
@@ -20282,48 +20253,48 @@ msgstr ""
#, c-format
msgid "cannot compare record types with different numbers of columns"
msgstr ""
-"ne peut pas comparer les types d'enregistrement avec des num�ros diff�rents\n"
+"ne peut pas comparer les types d'enregistrement avec des numéros différents\n"
"des colonnes"
-#: utils/adt/ruleutils.c:4174
+#: utils/adt/ruleutils.c:4289
#, c-format
msgid "rule \"%s\" has unsupported event type %d"
-msgstr "la r�gle � %s � a un type d'�v�nement %d non support�"
+msgstr "la règle « %s » a un type d'événement %d non supporté"
-#: utils/adt/selfuncs.c:5314
+#: utils/adt/selfuncs.c:5318
#, c-format
msgid "case insensitive matching not supported on type bytea"
-msgstr "la recherche insensible � la casse n'est pas support�e avec le type bytea"
+msgstr "la recherche insensible à la casse n'est pas supportée avec le type bytea"
-#: utils/adt/selfuncs.c:5417
+#: utils/adt/selfuncs.c:5421
#, c-format
msgid "regular-expression matching not supported on type bytea"
-msgstr "la recherche par expression rationnelle n'est pas support�e sur le type bytea"
+msgstr "la recherche par expression rationnelle n'est pas supportée sur le type bytea"
#: utils/adt/tid.c:71 utils/adt/tid.c:79 utils/adt/tid.c:87
#, c-format
msgid "invalid input syntax for type tid: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type tid : � %s �"
+msgstr "syntaxe en entrée invalide pour le type tid : « %s »"
#: utils/adt/timestamp.c:99
#, c-format
msgid "TIMESTAMP(%d)%s precision must not be negative"
-msgstr "la pr�cision de TIMESTAMP(%d)%s ne doit pas �tre n�gative"
+msgstr "la précision de TIMESTAMP(%d)%s ne doit pas être négative"
#: utils/adt/timestamp.c:105
#, c-format
msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d"
-msgstr "la pr�cision de TIMESTAMP(%d)%s est r�duit au maximum autoris�, %d"
+msgstr "la précision de TIMESTAMP(%d)%s est réduit au maximum autorisé, %d"
#: utils/adt/timestamp.c:170 utils/adt/timestamp.c:445
#, c-format
msgid "timestamp out of range: \"%s\""
-msgstr "timestamp en dehors de limites : � %s �"
+msgstr "timestamp en dehors de limites : « %s »"
#: utils/adt/timestamp.c:188 utils/adt/timestamp.c:463 utils/adt/timestamp.c:993
#, c-format
msgid "date/time value \"%s\" is no longer supported"
-msgstr "la valeur date/time � %s � n'est plus support�e"
+msgstr "la valeur date/time « %s » n'est plus supportée"
#: utils/adt/timestamp.c:258 utils/adt/timestamp.c:754
#, c-format
@@ -20333,22 +20304,22 @@ msgstr "timestamp ne peut pas valoir NaN"
#: utils/adt/timestamp.c:380
#, c-format
msgid "timestamp(%d) precision must be between %d and %d"
-msgstr "la pr�cision de timestamp(%d) doit �tre comprise entre %d et %d"
+msgstr "la précision de timestamp(%d) doit être comprise entre %d et %d"
#: utils/adt/timestamp.c:513
#, c-format
msgid "invalid input syntax for numeric time zone: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le fuseau horaire num�rique : � %s �"
+msgstr "syntaxe en entrée invalide pour le fuseau horaire numérique : « %s »"
#: utils/adt/timestamp.c:515
#, c-format
msgid "Numeric time zones must have \"-\" or \"+\" as first character."
-msgstr "Les fuseaux horaires num�riques doivent avoir � - � ou � + � comme premier caract�re."
+msgstr "Les fuseaux horaires numériques doivent avoir « - » ou « + » comme premier caractère."
#: utils/adt/timestamp.c:528
#, c-format
msgid "numeric time zone \"%s\" out of range"
-msgstr "le fuseau horaire num�rique � %s � est en dehors des limites"
+msgstr "le fuseau horaire numérique « %s » est en dehors des limites"
#: utils/adt/timestamp.c:631 utils/adt/timestamp.c:641 utils/adt/timestamp.c:653
#, c-format
@@ -20358,10 +20329,10 @@ msgstr "timestamp en dehors de limites : %d-%02d-%02d %d:%02d:%02g"
#: utils/adt/timestamp.c:770 utils/adt/timestamp.c:776 utils/adt/timestamp.c:791
#, c-format
msgid "timestamp out of range: \"%g\""
-msgstr "timestamp en dehors de limites : � %g �"
+msgstr "timestamp en dehors de limites : « %g »"
-#: utils/adt/timestamp.c:987 utils/adt/timestamp.c:1558 utils/adt/timestamp.c:2068 utils/adt/timestamp.c:3220 utils/adt/timestamp.c:3225 utils/adt/timestamp.c:3230 utils/adt/timestamp.c:3280 utils/adt/timestamp.c:3287 utils/adt/timestamp.c:3294 utils/adt/timestamp.c:3314 utils/adt/timestamp.c:3321 utils/adt/timestamp.c:3328 utils/adt/timestamp.c:3358 utils/adt/timestamp.c:3366 utils/adt/timestamp.c:3411 utils/adt/timestamp.c:3751
-#: utils/adt/timestamp.c:3880 utils/adt/timestamp.c:4271
+#: utils/adt/timestamp.c:987 utils/adt/timestamp.c:1611 utils/adt/timestamp.c:2121 utils/adt/timestamp.c:3273 utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3283 utils/adt/timestamp.c:3333 utils/adt/timestamp.c:3340 utils/adt/timestamp.c:3347 utils/adt/timestamp.c:3367 utils/adt/timestamp.c:3374 utils/adt/timestamp.c:3381 utils/adt/timestamp.c:3411 utils/adt/timestamp.c:3419 utils/adt/timestamp.c:3464 utils/adt/timestamp.c:3804
+#: utils/adt/timestamp.c:3933 utils/adt/timestamp.c:4324
#, c-format
msgid "interval out of range"
msgstr "intervalle en dehors des limites"
@@ -20374,148 +20345,148 @@ msgstr "modificateur de type INTERVAL invalide"
#: utils/adt/timestamp.c:1144
#, c-format
msgid "INTERVAL(%d) precision must not be negative"
-msgstr "la pr�cision de l'intervalle INTERVAL(%d) ne doit pas �tre n�gative"
+msgstr "la précision de l'intervalle INTERVAL(%d) ne doit pas être négative"
#: utils/adt/timestamp.c:1150
#, c-format
msgid "INTERVAL(%d) precision reduced to maximum allowed, %d"
-msgstr "La pr�cision de l'intervalle INTERVAL(%d) doit �tre r�duit au maximum permis, %d"
+msgstr "La précision de l'intervalle INTERVAL(%d) doit être réduit au maximum permis, %d"
-#: utils/adt/timestamp.c:1502
+#: utils/adt/timestamp.c:1555
#, c-format
msgid "interval(%d) precision must be between %d and %d"
-msgstr "La pr�cision de interval(%d) doit �tre comprise entre %d et %d"
+msgstr "La précision de interval(%d) doit être comprise entre %d et %d"
-#: utils/adt/timestamp.c:2797
+#: utils/adt/timestamp.c:2850
#, c-format
msgid "cannot subtract infinite timestamps"
msgstr "ne peut pas soustraire les valeurs timestamps infinies"
-#: utils/adt/timestamp.c:4006 utils/adt/timestamp.c:4531 utils/adt/timestamp.c:4715 utils/adt/timestamp.c:4740
+#: utils/adt/timestamp.c:4059 utils/adt/timestamp.c:4584 utils/adt/timestamp.c:4768 utils/adt/timestamp.c:4793
#, c-format
msgid "timestamp units \"%s\" not supported"
-msgstr "les unit�s timestamp � %s � ne sont pas support�es"
+msgstr "les unités timestamp « %s » ne sont pas supportées"
-#: utils/adt/timestamp.c:4020 utils/adt/timestamp.c:4485 utils/adt/timestamp.c:4750
+#: utils/adt/timestamp.c:4073 utils/adt/timestamp.c:4538 utils/adt/timestamp.c:4803
#, c-format
msgid "timestamp units \"%s\" not recognized"
-msgstr "les unit� � %s � ne sont pas reconnues pour le type timestamp"
+msgstr "les unité « %s » ne sont pas reconnues pour le type timestamp"
-#: utils/adt/timestamp.c:4160 utils/adt/timestamp.c:4526 utils/adt/timestamp.c:4937 utils/adt/timestamp.c:4963
+#: utils/adt/timestamp.c:4213 utils/adt/timestamp.c:4579 utils/adt/timestamp.c:4990 utils/adt/timestamp.c:5016
#, c-format
msgid "timestamp with time zone units \"%s\" not supported"
msgstr ""
-"les unit�s � %s � ne sont pas support�es pour le type � timestamp with time\n"
-"zone �"
+"les unités « %s » ne sont pas supportées pour le type « timestamp with time\n"
+"zone »"
-#: utils/adt/timestamp.c:4177 utils/adt/timestamp.c:4480 utils/adt/timestamp.c:4972
+#: utils/adt/timestamp.c:4230 utils/adt/timestamp.c:4533 utils/adt/timestamp.c:5025
#, c-format
msgid "timestamp with time zone units \"%s\" not recognized"
msgstr ""
-"Les unit�s � %s � ne sont pas reconnues pour le type � timestamp with time\n"
-"zone �"
+"Les unités « %s » ne sont pas reconnues pour le type « timestamp with time\n"
+"zone »"
-#: utils/adt/timestamp.c:4258
+#: utils/adt/timestamp.c:4311
#, c-format
msgid "interval units \"%s\" not supported because months usually have fractional weeks"
-msgstr "unit�s d'intervalle � %s � non support� car les mois ont g�n�ralement des semaines fractionnaires"
+msgstr "unités d'intervalle « %s » non supporté car les mois ont généralement des semaines fractionnaires"
-#: utils/adt/timestamp.c:4264 utils/adt/timestamp.c:5078
+#: utils/adt/timestamp.c:4317 utils/adt/timestamp.c:5131
#, c-format
msgid "interval units \"%s\" not supported"
-msgstr "Les unit�s � %s � ne sont pas support�es pour le type interval"
+msgstr "Les unités « %s » ne sont pas supportées pour le type interval"
-#: utils/adt/timestamp.c:4280 utils/adt/timestamp.c:5105
+#: utils/adt/timestamp.c:4333 utils/adt/timestamp.c:5158
#, c-format
msgid "interval units \"%s\" not recognized"
-msgstr "Les unit�s � %s � ne sont pas reconnues pour le type interval"
+msgstr "Les unités « %s » ne sont pas reconnues pour le type interval"
#: utils/adt/trigfuncs.c:42
#, c-format
msgid "suppress_redundant_updates_trigger: must be called as trigger"
-msgstr "suppress_redundant_updates_trigger : doit �tre appel� par un trigger"
+msgstr "suppress_redundant_updates_trigger : doit être appelé par un trigger"
#: utils/adt/trigfuncs.c:48
#, c-format
msgid "suppress_redundant_updates_trigger: must be called on update"
-msgstr "suppress_redundant_updates_trigger : doit �tre appel� sur une mise � jour"
+msgstr "suppress_redundant_updates_trigger : doit être appelé sur une mise à jour"
#: utils/adt/trigfuncs.c:54
#, c-format
msgid "suppress_redundant_updates_trigger: must be called before update"
-msgstr "suppress_redundant_updates_trigger : doit �tre appel� avant une mise � jour"
+msgstr "suppress_redundant_updates_trigger : doit être appelé avant une mise à jour"
#: utils/adt/trigfuncs.c:60
#, c-format
msgid "suppress_redundant_updates_trigger: must be called for each row"
-msgstr "suppress_redundant_updates_trigger : doit �tre appel� pour chaque ligne"
+msgstr "suppress_redundant_updates_trigger : doit être appelé pour chaque ligne"
#: utils/adt/tsgistidx.c:99
#, c-format
msgid "gtsvector_in not implemented"
-msgstr "gtsvector_in n'est pas encore impl�ment�"
+msgstr "gtsvector_in n'est pas encore implémenté"
#: utils/adt/tsquery.c:166
#, c-format
msgid "distance in phrase operator should not be greater than %d"
-msgstr ""
+msgstr "la distance dans l'opérateur de phrase ne devrait pas être plus que %d"
#: utils/adt/tsquery.c:254 utils/adt/tsquery.c:513 utils/adt/tsvector_parser.c:141
#, c-format
msgid "syntax error in tsquery: \"%s\""
-msgstr "erreur de syntaxe dans tsquery : � %s �"
+msgstr "erreur de syntaxe dans tsquery : « %s »"
#: utils/adt/tsquery.c:275
#, c-format
msgid "no operand in tsquery: \"%s\""
-msgstr "aucun op�rande dans tsquery : � %s �"
+msgstr "aucun opérande dans tsquery : « %s »"
#: utils/adt/tsquery.c:358
#, c-format
msgid "value is too big in tsquery: \"%s\""
-msgstr "valeur trop importante dans tsquery : � %s �"
+msgstr "valeur trop importante dans tsquery : « %s »"
#: utils/adt/tsquery.c:363
#, c-format
msgid "operand is too long in tsquery: \"%s\""
-msgstr "l'op�rande est trop long dans tsquery : � %s �"
+msgstr "l'opérande est trop long dans tsquery : « %s »"
#: utils/adt/tsquery.c:391
#, c-format
msgid "word is too long in tsquery: \"%s\""
-msgstr "le mot est trop long dans tsquery : � %s �"
+msgstr "le mot est trop long dans tsquery : « %s »"
-#: utils/adt/tsquery.c:648
+#: utils/adt/tsquery.c:642
#, c-format
msgid "text-search query doesn't contain lexemes: \"%s\""
-msgstr "la requ�te de recherche plein texte ne contient pas de lexemes : � %s �"
+msgstr "la requête de recherche plein texte ne contient pas de lexemes : « %s »"
-#: utils/adt/tsquery.c:659 utils/adt/tsquery_util.c:347
+#: utils/adt/tsquery.c:653 utils/adt/tsquery_util.c:375
#, c-format
msgid "tsquery is too large"
msgstr "le champ tsquery est trop gros"
-#: utils/adt/tsquery_cleanup.c:580
+#: utils/adt/tsquery_cleanup.c:407
#, c-format
msgid "text-search query contains only stop words or doesn't contain lexemes, ignored"
msgstr ""
-"la requ�te de recherche plein texte ne contient que des termes courants\n"
-"ou ne contient pas de lexemes, ignor�"
+"la requête de recherche plein texte ne contient que des termes courants\n"
+"ou ne contient pas de lexemes, ignoré"
#: utils/adt/tsquery_op.c:122
#, c-format
msgid "distance in phrase operator should be non-negative and less than %d"
-msgstr ""
+msgstr "la distance dans l'opérateur de phrase devrait pas positif et inférieur à %d"
-#: utils/adt/tsquery_rewrite.c:292
+#: utils/adt/tsquery_rewrite.c:321
#, c-format
msgid "ts_rewrite query must return two tsquery columns"
-msgstr "la requ�te ts_rewrite doit renvoyer deux colonnes tsquery"
+msgstr "la requête ts_rewrite doit renvoyer deux colonnes tsquery"
#: utils/adt/tsrank.c:412
#, c-format
msgid "array of weight must be one-dimensional"
-msgstr "le tableau de poids doit �tre sur une seule dimension"
+msgstr "le tableau de poids doit être sur une seule dimension"
#: utils/adt/tsrank.c:417
#, c-format
@@ -20527,7 +20498,7 @@ msgstr "le tableau de poids est trop court"
msgid "array of weight must not contain nulls"
msgstr "le tableau de poids ne doit pas contenir de valeurs NULL"
-#: utils/adt/tsrank.c:431 utils/adt/tsrank.c:862
+#: utils/adt/tsrank.c:431 utils/adt/tsrank.c:868
#, c-format
msgid "weight out of range"
msgstr "poids en dehors des limites"
@@ -20540,163 +20511,161 @@ msgstr "le mot est trop long (%ld octets, max %ld octets)"
#: utils/adt/tsvector.c:220
#, c-format
msgid "string is too long for tsvector (%ld bytes, max %ld bytes)"
-msgstr "la cha�ne est trop longue pour tsvector (%ld octets, max %ld octets)"
+msgstr "la chaîne est trop longue pour tsvector (%ld octets, max %ld octets)"
-#: utils/adt/tsvector_op.c:317 utils/adt/tsvector_op.c:565 utils/adt/tsvector_op.c:731
-#, fuzzy, c-format
-#| msgid "array must not contain nulls"
+#: utils/adt/tsvector_op.c:322 utils/adt/tsvector_op.c:609 utils/adt/tsvector_op.c:777
+#, c-format
msgid "lexeme array may not contain nulls"
-msgstr "le tableau ne doit pas contenir de valeurs NULL"
+msgstr "le tableau de lexème ne doit pas contenir de valeurs NULL"
-#: utils/adt/tsvector_op.c:789
-#, fuzzy, c-format
-#| msgid "array must not contain nulls"
+#: utils/adt/tsvector_op.c:852
+#, c-format
msgid "weight array may not contain nulls"
-msgstr "le tableau ne doit pas contenir de valeurs NULL"
+msgstr "le tableau de poids ne doit pas contenir de valeurs NULL"
-#: utils/adt/tsvector_op.c:809
+#: utils/adt/tsvector_op.c:876
#, c-format
msgid "unrecognized weight: \"%c\""
-msgstr "poids non reconnu : � %c �"
+msgstr "poids non reconnu : « %c »"
-#: utils/adt/tsvector_op.c:1978
+#: utils/adt/tsvector_op.c:2313
#, c-format
msgid "ts_stat query must return one tsvector column"
-msgstr "la requ�te ts_stat doit renvoyer une colonne tsvector"
+msgstr "la requête ts_stat doit renvoyer une colonne tsvector"
-#: utils/adt/tsvector_op.c:2160
+#: utils/adt/tsvector_op.c:2495
#, c-format
msgid "tsvector column \"%s\" does not exist"
-msgstr "la colonne tsvector � %s � n'existe pas"
+msgstr "la colonne tsvector « %s » n'existe pas"
-#: utils/adt/tsvector_op.c:2166
+#: utils/adt/tsvector_op.c:2501
#, c-format
msgid "column \"%s\" is not of tsvector type"
-msgstr "la colonne � %s � n'est pas de type tsvector"
+msgstr "la colonne « %s » n'est pas de type tsvector"
-#: utils/adt/tsvector_op.c:2178
+#: utils/adt/tsvector_op.c:2513
#, c-format
msgid "configuration column \"%s\" does not exist"
-msgstr "la colonne de configuration � %s � n'existe pas"
+msgstr "la colonne de configuration « %s » n'existe pas"
-#: utils/adt/tsvector_op.c:2184
+#: utils/adt/tsvector_op.c:2519
#, c-format
msgid "column \"%s\" is not of regconfig type"
-msgstr "la colonne � %s � n'est pas de type regconfig"
+msgstr "la colonne « %s » n'est pas de type regconfig"
-#: utils/adt/tsvector_op.c:2191
+#: utils/adt/tsvector_op.c:2526
#, c-format
msgid "configuration column \"%s\" must not be null"
-msgstr "la colonne de configuration � %s � ne doit pas �tre NULL"
+msgstr "la colonne de configuration « %s » ne doit pas être NULL"
-#: utils/adt/tsvector_op.c:2204
+#: utils/adt/tsvector_op.c:2539
#, c-format
msgid "text search configuration name \"%s\" must be schema-qualified"
msgstr ""
-"le nom de la configuration de la recherche plein texte � %s � doit �tre\n"
-"qualifi� par son sch�ma"
+"le nom de la configuration de la recherche plein texte « %s » doit être\n"
+"qualifié par son schéma"
-#: utils/adt/tsvector_op.c:2229
+#: utils/adt/tsvector_op.c:2564
#, c-format
msgid "column \"%s\" is not of a character type"
-msgstr "la colonne � %s � n'est pas de type caract�re"
+msgstr "la colonne « %s » n'est pas de type caractère"
#: utils/adt/tsvector_parser.c:142
#, c-format
msgid "syntax error in tsvector: \"%s\""
-msgstr "erreur de syntaxe dans tsvector : � %s �"
+msgstr "erreur de syntaxe dans tsvector : « %s »"
#: utils/adt/tsvector_parser.c:207
#, c-format
msgid "there is no escaped character: \"%s\""
-msgstr "il n'existe pas de caract�res d'�chappement : � %s �"
+msgstr "il n'existe pas de caractères d'échappement : « %s »"
#: utils/adt/tsvector_parser.c:324
#, c-format
msgid "wrong position info in tsvector: \"%s\""
-msgstr "mauvaise information de position dans tsvector : � %s �"
+msgstr "mauvaise information de position dans tsvector : « %s »"
#: utils/adt/txid.c:339
#, c-format
msgid "invalid input syntax for type txid_snapshot: \"%s\""
-msgstr "syntaxe en entr�e invalide pour le type txid_snapshot : � %s �"
+msgstr "syntaxe en entrée invalide pour le type txid_snapshot : « %s »"
#: utils/adt/txid.c:534
#, c-format
msgid "invalid external txid_snapshot data"
-msgstr "valeur externe � txid_snapshot � invalide"
+msgstr "valeur externe « txid_snapshot » invalide"
#: utils/adt/uuid.c:145
#, c-format
msgid "invalid input syntax for uuid: \"%s\""
-msgstr "syntaxe invalide en entr�e pour l'uuid : � %s �"
+msgstr "syntaxe invalide en entrée pour l'uuid : « %s »"
#: utils/adt/varbit.c:57 utils/adt/varchar.c:50
#, c-format
msgid "length for type %s must be at least 1"
-msgstr "la longueur du type %s doit �tre d'au moins 1"
+msgstr "la longueur du type %s doit être d'au moins 1"
#: utils/adt/varbit.c:62 utils/adt/varchar.c:54
#, c-format
msgid "length for type %s cannot exceed %d"
-msgstr "la longueur du type %s ne peut pas exc�der %d"
+msgstr "la longueur du type %s ne peut pas excéder %d"
#: utils/adt/varbit.c:163 utils/adt/varbit.c:475 utils/adt/varbit.c:973
#, c-format
msgid "bit string length exceeds the maximum allowed (%d)"
-msgstr "la taille du tableau de bits d�passe le maximum permis (%d)"
+msgstr "la taille du tableau de bits dépasse le maximum permis (%d)"
#: utils/adt/varbit.c:177 utils/adt/varbit.c:320 utils/adt/varbit.c:377
#, c-format
msgid "bit string length %d does not match type bit(%d)"
-msgstr "la longueur (en bits) de la cha�ne %d ne doit pas correspondre au type bit(%d)"
+msgstr "la longueur (en bits) de la chaîne %d ne doit pas correspondre au type bit(%d)"
#: utils/adt/varbit.c:199 utils/adt/varbit.c:511
#, c-format
msgid "\"%c\" is not a valid binary digit"
-msgstr "� %c � n'est pas un chiffre binaire valide"
+msgstr "« %c » n'est pas un chiffre binaire valide"
#: utils/adt/varbit.c:224 utils/adt/varbit.c:536
#, c-format
msgid "\"%c\" is not a valid hexadecimal digit"
-msgstr "� %c � n'est pas un chiffre hexad�cimal valide"
+msgstr "« %c » n'est pas un chiffre hexadécimal valide"
#: utils/adt/varbit.c:311 utils/adt/varbit.c:627
#, c-format
msgid "invalid length in external bit string"
-msgstr "longueur invalide dans la cha�ne bit externe"
+msgstr "longueur invalide dans la chaîne bit externe"
#: utils/adt/varbit.c:489 utils/adt/varbit.c:636 utils/adt/varbit.c:731
#, c-format
msgid "bit string too long for type bit varying(%d)"
-msgstr "la cha�ne bit est trop longue pour le type bit varying(%d)"
+msgstr "la chaîne bit est trop longue pour le type bit varying(%d)"
#: utils/adt/varbit.c:1066 utils/adt/varbit.c:1168 utils/adt/varlena.c:842 utils/adt/varlena.c:906 utils/adt/varlena.c:1050 utils/adt/varlena.c:2735 utils/adt/varlena.c:2802
#, c-format
msgid "negative substring length not allowed"
-msgstr "longueur de sous-cha�ne n�gative non autoris�e"
+msgstr "longueur de sous-chaîne négative non autorisée"
#: utils/adt/varbit.c:1226
#, c-format
msgid "cannot AND bit strings of different sizes"
-msgstr "ne peut pas utiliser l'op�rateur AND sur des cha�nes bit de tailles diff�rentes"
+msgstr "ne peut pas utiliser l'opérateur AND sur des chaînes bit de tailles différentes"
#: utils/adt/varbit.c:1268
#, c-format
msgid "cannot OR bit strings of different sizes"
-msgstr "ne peut pas utiliser l'op�rateur OR sur des cha�nes bit de tailles diff�rentes"
+msgstr "ne peut pas utiliser l'opérateur OR sur des chaînes bit de tailles différentes"
#: utils/adt/varbit.c:1315
#, c-format
msgid "cannot XOR bit strings of different sizes"
-msgstr "ne peut pas utiliser l'op�rateur XOR sur des cha�nes bit de tailles diff�rentes"
+msgstr "ne peut pas utiliser l'opérateur XOR sur des chaînes bit de tailles différentes"
-#: utils/adt/varbit.c:1793 utils/adt/varbit.c:1851
+#: utils/adt/varbit.c:1803 utils/adt/varbit.c:1861
#, c-format
msgid "bit index %d out of valid range (0..%d)"
msgstr "index de bit %d en dehors des limites valides (0..%d)"
-#: utils/adt/varbit.c:1802 utils/adt/varlena.c:3002
+#: utils/adt/varbit.c:1812 utils/adt/varlena.c:3002
#, c-format
msgid "new bit must be 0 or 1"
msgstr "le nouveau bit doit valoir soit 0 soit 1"
@@ -20714,17 +20683,17 @@ msgstr "valeur trop longue pour le type character varying(%d)"
#: utils/adt/varlena.c:1420 utils/adt/varlena.c:1825
#, c-format
msgid "could not determine which collation to use for string comparison"
-msgstr "n'a pas pu d�terminer le collationnement � utiliser pour la comparaison de cha�ne"
+msgstr "n'a pas pu déterminer le collationnement à utiliser pour la comparaison de chaîne"
#: utils/adt/varlena.c:1478 utils/adt/varlena.c:1491
#, c-format
msgid "could not convert string to UTF-16: error code %lu"
-msgstr "n'a pas pu convertir la cha�ne en UTF-16 : erreur %lu"
+msgstr "n'a pas pu convertir la chaîne en UTF-16 : erreur %lu"
#: utils/adt/varlena.c:1506
#, c-format
msgid "could not compare Unicode strings: %m"
-msgstr "n'a pas pu comparer les cha�nes unicode : %m"
+msgstr "n'a pas pu comparer les chaînes unicode : %m"
#: utils/adt/varlena.c:2880 utils/adt/varlena.c:2911 utils/adt/varlena.c:2947 utils/adt/varlena.c:2990
#, c-format
@@ -20734,33 +20703,28 @@ msgstr "index %d en dehors des limites valides, 0..%d"
#: utils/adt/varlena.c:3925
#, c-format
msgid "field position must be greater than zero"
-msgstr "la position du champ doit �tre plus grand que z�ro"
+msgstr "la position du champ doit être plus grand que zéro"
#: utils/adt/varlena.c:4804
#, c-format
msgid "unterminated format() type specifier"
-msgstr "sp�cificateur de type pour format() non termin�"
+msgstr "spécificateur de type pour format() non terminé"
#: utils/adt/varlena.c:4805 utils/adt/varlena.c:4939 utils/adt/varlena.c:5060
#, c-format
msgid "For a single \"%%\" use \"%%%%\"."
-msgstr ""
+msgstr "Pour un unique \"%%\" utilisez \"%%%%\"."
#: utils/adt/varlena.c:4937 utils/adt/varlena.c:5058
#, c-format
msgid "unrecognized format() type specifier \"%c\""
-msgstr "sp�cificateur de type � %c � pour format() non reconnu"
+msgstr "spécificateur de type « %c » pour format() non reconnu"
-#: utils/adt/varlena.c:4950
+#: utils/adt/varlena.c:4950 utils/adt/varlena.c:5007
#, c-format
msgid "too few arguments for format()"
msgstr "trop peu d'arguments pour format()"
-#: utils/adt/varlena.c:5007
-#, c-format
-msgid "too few arguments for format"
-msgstr "trop peu d'arguments pour le format"
-
#: utils/adt/varlena.c:5102 utils/adt/varlena.c:5285
#, c-format
msgid "number is out of range"
@@ -20769,37 +20733,37 @@ msgstr "le nombre est en dehors des limites"
#: utils/adt/varlena.c:5166 utils/adt/varlena.c:5194
#, c-format
msgid "format specifies argument 0, but arguments are numbered from 1"
-msgstr "le format indique l'argument 0 mais les arguments sont num�rot�s � partir de 1"
+msgstr "le format indique l'argument 0 mais les arguments sont numérotés à partir de 1"
#: utils/adt/varlena.c:5187
#, c-format
msgid "width argument position must be ended by \"$\""
-msgstr "la position de l'argument width doit se terminer par � $ �"
+msgstr "la position de l'argument width doit se terminer par « $ »"
#: utils/adt/varlena.c:5232
#, c-format
msgid "null values cannot be formatted as an SQL identifier"
-msgstr "les valeurs NULL ne peuvent pas �tre format�s comme un identifiant SQL"
+msgstr "les valeurs NULL ne peuvent pas être formatés comme un identifiant SQL"
#: utils/adt/windowfuncs.c:243
#, c-format
msgid "argument of ntile must be greater than zero"
-msgstr "l'argument de ntile doit �tre sup�rieur � z�ro"
+msgstr "l'argument de ntile doit être supérieur à zéro"
#: utils/adt/windowfuncs.c:465
#, c-format
msgid "argument of nth_value must be greater than zero"
-msgstr "l'argument de nth_value doit �tre sup�rieur � z�ro"
+msgstr "l'argument de nth_value doit être supérieur à zéro"
#: utils/adt/xml.c:171
#, c-format
msgid "unsupported XML feature"
-msgstr "fonctionnalit� XML non support�e"
+msgstr "fonctionnalité XML non supportée"
#: utils/adt/xml.c:172
#, c-format
msgid "This functionality requires the server to be built with libxml support."
-msgstr "Cette fonctionnalit� n�cessite que le serveur dispose du support de libxml."
+msgstr "Cette fonctionnalité nécessite que le serveur dispose du support de libxml."
#: utils/adt/xml.c:173
#, c-format
@@ -20809,7 +20773,7 @@ msgstr "Vous devez recompiler PostgreSQL en utilisant --with-libxml."
#: utils/adt/xml.c:192 utils/mb/mbutils.c:523
#, c-format
msgid "invalid encoding name \"%s\""
-msgstr "nom d'encodage � %s � invalide"
+msgstr "nom d'encodage « %s » invalide"
#: utils/adt/xml.c:435 utils/adt/xml.c:440
#, c-format
@@ -20829,28 +20793,28 @@ msgstr "instruction de traitement XML invalide"
#: utils/adt/xml.c:729
#, c-format
msgid "XML processing instruction target name cannot be \"%s\"."
-msgstr "le nom de cible de l'instruction de traitement XML ne peut pas �tre � %s �."
+msgstr "le nom de cible de l'instruction de traitement XML ne peut pas être « %s »."
#: utils/adt/xml.c:752
#, c-format
msgid "XML processing instruction cannot contain \"?>\"."
-msgstr "l'instruction de traitement XML ne peut pas contenir � ?> �."
+msgstr "l'instruction de traitement XML ne peut pas contenir « ?> »."
#: utils/adt/xml.c:831
#, c-format
msgid "xmlvalidate is not implemented"
-msgstr "xmlvalidate n'est pas impl�ment�"
+msgstr "xmlvalidate n'est pas implémenté"
#: utils/adt/xml.c:910
#, c-format
msgid "could not initialize XML library"
-msgstr "n'a pas pu initialiser la biblioth�que XML"
+msgstr "n'a pas pu initialiser la bibliothèque XML"
#: utils/adt/xml.c:911
#, c-format
msgid "libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u."
msgstr ""
-"libxml2 a un type de caract�re incompatible : sizeof(char)=%u,\n"
+"libxml2 a un type de caractère incompatible : sizeof(char)=%u,\n"
"sizeof(xmlChar)=%u."
#: utils/adt/xml.c:997
@@ -20863,79 +20827,79 @@ msgstr "n'a pas pu configurer le gestionnaire d'erreurs XML"
msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with."
msgstr ""
"Ceci indique probablement que la version de libxml2 en cours d'utilisation\n"
-"n'est pas compatible avec les fichiers d'en-t�te de libxml2 avec lesquels\n"
-"PostgreSQL a �t� construit."
+"n'est pas compatible avec les fichiers d'en-tête de libxml2 avec lesquels\n"
+"PostgreSQL a été construit."
-#: utils/adt/xml.c:1737
+#: utils/adt/xml.c:1735
msgid "Invalid character value."
-msgstr "Valeur invalide pour le caract�re."
+msgstr "Valeur invalide pour le caractère."
-#: utils/adt/xml.c:1740
+#: utils/adt/xml.c:1738
msgid "Space required."
msgstr "Espace requis."
-#: utils/adt/xml.c:1743
+#: utils/adt/xml.c:1741
msgid "standalone accepts only 'yes' or 'no'."
msgstr "la version autonome accepte seulement 'yes' et 'no'."
-#: utils/adt/xml.c:1746
+#: utils/adt/xml.c:1744
msgid "Malformed declaration: missing version."
-msgstr "D�claration mal form�e : version manquante."
+msgstr "Déclaration mal formée : version manquante."
-#: utils/adt/xml.c:1749
+#: utils/adt/xml.c:1747
msgid "Missing encoding in text declaration."
-msgstr "Encodage manquant dans la d�claration du texte."
+msgstr "Encodage manquant dans la déclaration du texte."
-#: utils/adt/xml.c:1752
+#: utils/adt/xml.c:1750
msgid "Parsing XML declaration: '?>' expected."
-msgstr "Analyse de la d�claration XML : � ?> � attendu."
+msgstr "Analyse de la déclaration XML : « ?> » attendu."
-#: utils/adt/xml.c:1755
+#: utils/adt/xml.c:1753
#, c-format
msgid "Unrecognized libxml error code: %d."
msgstr "code d'erreur libxml inconnu : %d"
-#: utils/adt/xml.c:2030
+#: utils/adt/xml.c:2028
#, c-format
msgid "XML does not support infinite date values."
msgstr "XML ne supporte pas les valeurs infinies de date."
-#: utils/adt/xml.c:2052 utils/adt/xml.c:2079
+#: utils/adt/xml.c:2050 utils/adt/xml.c:2077
#, c-format
msgid "XML does not support infinite timestamp values."
msgstr "XML ne supporte pas les valeurs infinies de timestamp."
-#: utils/adt/xml.c:2470
+#: utils/adt/xml.c:2468
#, c-format
msgid "invalid query"
-msgstr "requ�te invalide"
+msgstr "requête invalide"
-#: utils/adt/xml.c:3795
+#: utils/adt/xml.c:3793
#, c-format
msgid "invalid array for XML namespace mapping"
msgstr "tableau invalide pour la correspondance de l'espace de nom XML"
-#: utils/adt/xml.c:3796
+#: utils/adt/xml.c:3794
#, c-format
msgid "The array must be two-dimensional with length of the second axis equal to 2."
msgstr ""
"Le tableau doit avoir deux dimensions avec une longueur de 2 pour le\n"
-"deuxi�me axe."
+"deuxième axe."
-#: utils/adt/xml.c:3820
+#: utils/adt/xml.c:3818
#, c-format
msgid "empty XPath expression"
msgstr "expression XPath vide"
-#: utils/adt/xml.c:3869
+#: utils/adt/xml.c:3867
#, c-format
msgid "neither namespace name nor URI may be null"
-msgstr "ni le nom de l'espace de noms ni l'URI ne peuvent �tre NULL"
+msgstr "ni le nom de l'espace de noms ni l'URI ne peuvent être NULL"
-#: utils/adt/xml.c:3876
+#: utils/adt/xml.c:3874
#, c-format
msgid "could not register XML namespace with name \"%s\" and URI \"%s\""
-msgstr "n'a pas pu enregistrer l'espace de noms XML de nom � %s � et d'URI � %s �"
+msgstr "n'a pas pu enregistrer l'espace de noms XML de nom « %s » et d'URI « %s »"
#: utils/cache/lsyscache.c:2580 utils/cache/lsyscache.c:2613 utils/cache/lsyscache.c:2646 utils/cache/lsyscache.c:2679
#, c-format
@@ -20945,86 +20909,86 @@ msgstr "le type %s est seulement un shell"
#: utils/cache/lsyscache.c:2585
#, c-format
msgid "no input function available for type %s"
-msgstr "aucune fonction en entr�e disponible pour le type %s"
+msgstr "aucune fonction en entrée disponible pour le type %s"
#: utils/cache/lsyscache.c:2618
#, c-format
msgid "no output function available for type %s"
msgstr "aucune fonction en sortie disponible pour le type %s"
-#: utils/cache/plancache.c:745
+#: utils/cache/plancache.c:718
#, c-format
msgid "cached plan must not change result type"
-msgstr "le plan en cache ne doit pas modifier le type en r�sultat"
+msgstr "le plan en cache ne doit pas modifier le type en résultat"
-#: utils/cache/relcache.c:5135
+#: utils/cache/relcache.c:5199
#, c-format
msgid "could not create relation-cache initialization file \"%s\": %m"
-msgstr "n'a pas pu cr�er le fichier d'initialisation relation-cache � %s � : %m"
+msgstr "n'a pas pu créer le fichier d'initialisation relation-cache « %s » : %m"
-#: utils/cache/relcache.c:5137
+#: utils/cache/relcache.c:5201
#, c-format
msgid "Continuing anyway, but there's something wrong."
-msgstr "Continue malgr� tout, mais quelque chose s'est mal pass�."
+msgstr "Continue malgré tout, mais quelque chose s'est mal passé."
-#: utils/cache/relcache.c:5411
+#: utils/cache/relcache.c:5475
#, c-format
msgid "could not remove cache file \"%s\": %m"
-msgstr "n'a pas pu supprimer le fichier cache � %s � : %m"
+msgstr "n'a pas pu supprimer le fichier cache « %s » : %m"
#: utils/cache/relmapper.c:508
#, c-format
msgid "cannot PREPARE a transaction that modified relation mapping"
msgstr ""
-"ne peut pas pr�parer (PREPARE) une transaction qui a modifi� la correspondance\n"
+"ne peut pas préparer (PREPARE) une transaction qui a modifié la correspondance\n"
"de relation"
#: utils/cache/relmapper.c:651 utils/cache/relmapper.c:751
#, c-format
msgid "could not open relation mapping file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier de correspondance des relations � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier de correspondance des relations « %s » : %m"
#: utils/cache/relmapper.c:664
#, c-format
msgid "could not read relation mapping file \"%s\": %m"
-msgstr "n'a pas pu lire le fichier de correspondance des relations � %s � : %m"
+msgstr "n'a pas pu lire le fichier de correspondance des relations « %s » : %m"
#: utils/cache/relmapper.c:674
#, c-format
msgid "relation mapping file \"%s\" contains invalid data"
-msgstr "le fichier de correspondance des relations � %s � contient des donn�es invalides"
+msgstr "le fichier de correspondance des relations « %s » contient des données invalides"
#: utils/cache/relmapper.c:684
#, c-format
msgid "relation mapping file \"%s\" contains incorrect checksum"
msgstr ""
-"le fichier de correspondance des relations � %s � contient une somme de\n"
-"contr�le incorrecte"
+"le fichier de correspondance des relations « %s » contient une somme de\n"
+"contrôle incorrecte"
#: utils/cache/relmapper.c:784
#, c-format
msgid "could not write to relation mapping file \"%s\": %m"
-msgstr "n'a pas pu �crire le fichier de correspondance des relations � %s � : %m"
+msgstr "n'a pas pu écrire le fichier de correspondance des relations « %s » : %m"
#: utils/cache/relmapper.c:797
#, c-format
msgid "could not fsync relation mapping file \"%s\": %m"
-msgstr "n'a pas pu synchroniser (fsync) le fichier de correspondance des relations � %s � : %m"
+msgstr "n'a pas pu synchroniser (fsync) le fichier de correspondance des relations « %s » : %m"
#: utils/cache/relmapper.c:803
#, c-format
msgid "could not close relation mapping file \"%s\": %m"
-msgstr "n'a pas pu fermer le fichier de correspondance des relations � %s � : %m"
+msgstr "n'a pas pu fermer le fichier de correspondance des relations « %s » : %m"
-#: utils/cache/typcache.c:1211
+#: utils/cache/typcache.c:1207
#, c-format
msgid "type %s is not composite"
msgstr "le type %s n'est pas un type composite"
-#: utils/cache/typcache.c:1225
+#: utils/cache/typcache.c:1221
#, c-format
msgid "record type has not been registered"
-msgstr "le type d'enregistrement n'a pas �t� enregistr�"
+msgstr "le type d'enregistrement n'a pas été enregistré"
#: utils/error/assert.c:34
#, c-format
@@ -21034,578 +20998,578 @@ msgstr "TRAP : ExceptionalCondition : mauvais arguments\n"
#: utils/error/assert.c:37
#, c-format
msgid "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n"
-msgstr "TRAP : %s(� %s �, fichier : � %s �, ligne : %d)\n"
+msgstr "TRAP : %s(« %s », fichier : « %s », ligne : %d)\n"
#: utils/error/elog.c:322 utils/error/elog.c:1306
#, c-format
msgid "error occurred at %s:%d before error message processing is available\n"
msgstr ""
-"erreur survenue � %s:%d avant que le traitement des messages d'erreurs ne\n"
+"erreur survenue à %s:%d avant que le traitement des messages d'erreurs ne\n"
"soit disponible\n"
-#: utils/error/elog.c:1880
+#: utils/error/elog.c:1889
#, c-format
msgid "could not reopen file \"%s\" as stderr: %m"
-msgstr "n'a pas pu r�-ouvrir le fichier � %s � comme stderr : %m"
+msgstr "n'a pas pu ré-ouvrir le fichier « %s » comme stderr : %m"
-#: utils/error/elog.c:1893
+#: utils/error/elog.c:1902
#, c-format
msgid "could not reopen file \"%s\" as stdout: %m"
-msgstr "n'a pas pu r�-ouvrir le fichier � %s � comme stdout : %m"
+msgstr "n'a pas pu ré-ouvrir le fichier « %s » comme stdout : %m"
-#: utils/error/elog.c:2380 utils/error/elog.c:2397 utils/error/elog.c:2413
+#: utils/error/elog.c:2389 utils/error/elog.c:2406 utils/error/elog.c:2422
msgid "[unknown]"
msgstr "[inconnu]"
-#: utils/error/elog.c:2872 utils/error/elog.c:3171 utils/error/elog.c:3279
+#: utils/error/elog.c:2882 utils/error/elog.c:3185 utils/error/elog.c:3293
msgid "missing error text"
msgstr "texte d'erreur manquant"
-#: utils/error/elog.c:2875 utils/error/elog.c:2878 utils/error/elog.c:3282 utils/error/elog.c:3285
+#: utils/error/elog.c:2885 utils/error/elog.c:2888 utils/error/elog.c:3296 utils/error/elog.c:3299
#, c-format
msgid " at character %d"
-msgstr " au caract�re %d"
+msgstr " au caractère %d"
-#: utils/error/elog.c:2888 utils/error/elog.c:2895
+#: utils/error/elog.c:2898 utils/error/elog.c:2905
msgid "DETAIL: "
-msgstr "D�TAIL: "
+msgstr "DÉTAIL: "
-#: utils/error/elog.c:2902
+#: utils/error/elog.c:2912
msgid "HINT: "
msgstr "ASTUCE : "
-#: utils/error/elog.c:2909
+#: utils/error/elog.c:2919
msgid "QUERY: "
-msgstr "REQU�TE : "
+msgstr "REQUÊTE : "
-#: utils/error/elog.c:2916
+#: utils/error/elog.c:2926
msgid "CONTEXT: "
msgstr "CONTEXTE : "
-#: utils/error/elog.c:2926
+#: utils/error/elog.c:2936
#, c-format
msgid "LOCATION: %s, %s:%d\n"
msgstr "EMPLACEMENT : %s, %s:%d\n"
-#: utils/error/elog.c:2933
+#: utils/error/elog.c:2943
#, c-format
msgid "LOCATION: %s:%d\n"
msgstr "EMPLACEMENT : %s:%d\n"
-#: utils/error/elog.c:2947
+#: utils/error/elog.c:2957
msgid "STATEMENT: "
msgstr "INSTRUCTION : "
#. translator: This string will be truncated at 47
#. characters expanded.
-#: utils/error/elog.c:3400
+#: utils/error/elog.c:3414
#, c-format
msgid "operating system error %d"
-msgstr "erreur %d du syst�me d'exploitation"
+msgstr "erreur %d du système d'exploitation"
-#: utils/error/elog.c:3595
+#: utils/error/elog.c:3612
msgid "DEBUG"
msgstr "DEBUG"
-#: utils/error/elog.c:3599
+#: utils/error/elog.c:3616
msgid "LOG"
msgstr "LOG"
-#: utils/error/elog.c:3602
+#: utils/error/elog.c:3619
msgid "INFO"
msgstr "INFO"
-#: utils/error/elog.c:3605
+#: utils/error/elog.c:3622
msgid "NOTICE"
msgstr "NOTICE"
-#: utils/error/elog.c:3608
+#: utils/error/elog.c:3625
msgid "WARNING"
msgstr "ATTENTION"
-#: utils/error/elog.c:3611
+#: utils/error/elog.c:3628
msgid "ERROR"
msgstr "ERREUR"
-#: utils/error/elog.c:3614
+#: utils/error/elog.c:3631
msgid "FATAL"
msgstr "FATAL"
-#: utils/error/elog.c:3617
+#: utils/error/elog.c:3634
msgid "PANIC"
msgstr "PANIC"
#: utils/fmgr/dfmgr.c:117
#, c-format
msgid "could not find function \"%s\" in file \"%s\""
-msgstr "n'a pas pu trouver la fonction � %s � dans le fichier � %s �"
+msgstr "n'a pas pu trouver la fonction « %s » dans le fichier « %s »"
#: utils/fmgr/dfmgr.c:196 utils/fmgr/dfmgr.c:405 utils/fmgr/dfmgr.c:453
#, c-format
msgid "could not access file \"%s\": %m"
-msgstr "n'a pas pu acc�der au fichier � %s � : %m"
+msgstr "n'a pas pu accéder au fichier « %s » : %m"
#: utils/fmgr/dfmgr.c:234
#, c-format
msgid "could not load library \"%s\": %s"
-msgstr "n'a pas pu charger la biblioth�que � %s � : %s"
+msgstr "n'a pas pu charger la bibliothèque « %s » : %s"
#: utils/fmgr/dfmgr.c:266
#, c-format
msgid "incompatible library \"%s\": missing magic block"
-msgstr "biblioth�que � %s � incompatible : bloc magique manquant"
+msgstr "bibliothèque « %s » incompatible : bloc magique manquant"
#: utils/fmgr/dfmgr.c:268
#, c-format
msgid "Extension libraries are required to use the PG_MODULE_MAGIC macro."
msgstr ""
-"Les biblioth�ques �tendues n�cessitent l'utilisation de la macro\n"
+"Les bibliothèques étendues nécessitent l'utilisation de la macro\n"
"PG_MODULE_MAGIC."
#: utils/fmgr/dfmgr.c:304
#, c-format
msgid "incompatible library \"%s\": version mismatch"
-msgstr "biblioth�que � %s � incompatible : versions diff�rentes"
+msgstr "bibliothèque « %s » incompatible : versions différentes"
#: utils/fmgr/dfmgr.c:306
#, c-format
msgid "Server is version %d.%d, library is version %d.%d."
-msgstr "La version du serveur est %d.%d, celle de la biblioth�que est %d.%d."
+msgstr "La version du serveur est %d.%d, celle de la bibliothèque est %d.%d."
#: utils/fmgr/dfmgr.c:325
#, c-format
msgid "Server has FUNC_MAX_ARGS = %d, library has %d."
-msgstr "Le serveur a FUNC_MAX_ARGS = %d, la biblioth�que a %d."
+msgstr "Le serveur a FUNC_MAX_ARGS = %d, la bibliothèque a %d."
#: utils/fmgr/dfmgr.c:334
#, c-format
msgid "Server has INDEX_MAX_KEYS = %d, library has %d."
-msgstr "Le serveur a INDEX_MAX_KEYS = %d, la biblioth�que a %d."
+msgstr "Le serveur a INDEX_MAX_KEYS = %d, la bibliothèque a %d."
#: utils/fmgr/dfmgr.c:343
#, c-format
msgid "Server has NAMEDATALEN = %d, library has %d."
-msgstr "Le serveur a NAMEDATALEN = %d, la biblioth�que a %d."
+msgstr "Le serveur a NAMEDATALEN = %d, la bibliothèque a %d."
#: utils/fmgr/dfmgr.c:352
#, c-format
msgid "Server has FLOAT4PASSBYVAL = %s, library has %s."
-msgstr "Le serveur a FLOAT4PASSBYVAL = %s, la biblioth�que a %s."
+msgstr "Le serveur a FLOAT4PASSBYVAL = %s, la bibliothèque a %s."
#: utils/fmgr/dfmgr.c:361
#, c-format
msgid "Server has FLOAT8PASSBYVAL = %s, library has %s."
-msgstr "Le serveur a FLOAT8PASSBYVAL = %s, la biblioth�que a %s."
+msgstr "Le serveur a FLOAT8PASSBYVAL = %s, la bibliothèque a %s."
#: utils/fmgr/dfmgr.c:368
msgid "Magic block has unexpected length or padding difference."
-msgstr "Le bloc magique a une longueur inattendue ou une diff�rence de padding."
+msgstr "Le bloc magique a une longueur inattendue ou une différence de padding."
#: utils/fmgr/dfmgr.c:371
#, c-format
msgid "incompatible library \"%s\": magic block mismatch"
-msgstr "biblioth�que � %s � incompatible : diff�rences dans le bloc magique"
+msgstr "bibliothèque « %s » incompatible : différences dans le bloc magique"
#: utils/fmgr/dfmgr.c:535
#, c-format
msgid "access to library \"%s\" is not allowed"
-msgstr "l'acc�s � la biblioth�que � %s � n'est pas autoris�"
+msgstr "l'accès à la bibliothèque « %s » n'est pas autorisé"
#: utils/fmgr/dfmgr.c:561
#, c-format
msgid "invalid macro name in dynamic library path: %s"
-msgstr "nom de macro invalide dans le chemin des biblioth�ques partag�es : %s"
+msgstr "nom de macro invalide dans le chemin des bibliothèques partagées : %s"
#: utils/fmgr/dfmgr.c:601
#, c-format
msgid "zero-length component in parameter \"dynamic_library_path\""
-msgstr "composant de longueur z�ro dans le param�tre � dynamic_library_path �"
+msgstr "composant de longueur zéro dans le paramètre « dynamic_library_path »"
#: utils/fmgr/dfmgr.c:620
#, c-format
msgid "component in parameter \"dynamic_library_path\" is not an absolute path"
-msgstr "Un composant du param�tre � dynamic_library_path � n'est pas un chemin absolu"
+msgstr "Un composant du paramètre « dynamic_library_path » n'est pas un chemin absolu"
#: utils/fmgr/fmgr.c:272
#, c-format
msgid "internal function \"%s\" is not in internal lookup table"
-msgstr "la fonction interne � %s � n'est pas dans une table de recherche interne"
+msgstr "la fonction interne « %s » n'est pas dans une table de recherche interne"
#: utils/fmgr/fmgr.c:479
#, c-format
msgid "unrecognized API version %d reported by info function \"%s\""
-msgstr "version API %d non reconnue mais rapport�e par la fonction info � %s �"
+msgstr "version API %d non reconnue mais rapportée par la fonction info « %s »"
-#: utils/fmgr/fmgr.c:849 utils/fmgr/fmgr.c:2110
+#: utils/fmgr/fmgr.c:849 utils/fmgr/fmgr.c:2106
#, c-format
msgid "function %u has too many arguments (%d, maximum is %d)"
-msgstr "la fonction %u a trop d'arguments (%d, le maximum �tant %d)"
+msgstr "la fonction %u a trop d'arguments (%d, le maximum étant %d)"
-#: utils/fmgr/fmgr.c:2531
+#: utils/fmgr/fmgr.c:2527
#, c-format
msgid "language validation function %u called for language %u instead of %u"
-msgstr "fonction %u de validation du langage appel�e pour le langage %u au lieu de %u"
+msgstr "fonction %u de validation du langage appelée pour le langage %u au lieu de %u"
-#: utils/fmgr/funcapi.c:355
+#: utils/fmgr/funcapi.c:353
#, c-format
msgid "could not determine actual result type for function \"%s\" declared to return type %s"
msgstr ""
-"n'a pas pu d�terminer le type du r�sultat actuel pour la fonction � %s �\n"
-"d�clarant retourner le type %s"
+"n'a pas pu déterminer le type du résultat actuel pour la fonction « %s »\n"
+"déclarant retourner le type %s"
-#: utils/fmgr/funcapi.c:1342 utils/fmgr/funcapi.c:1373
+#: utils/fmgr/funcapi.c:1340 utils/fmgr/funcapi.c:1371
#, c-format
msgid "number of aliases does not match number of columns"
msgstr "le nombre d'alias ne correspond pas au nombre de colonnes"
-#: utils/fmgr/funcapi.c:1367
+#: utils/fmgr/funcapi.c:1365
#, c-format
msgid "no column alias was provided"
-msgstr "aucun alias de colonne n'a �t� fourni"
+msgstr "aucun alias de colonne n'a été fourni"
-#: utils/fmgr/funcapi.c:1391
+#: utils/fmgr/funcapi.c:1389
#, c-format
msgid "could not determine row description for function returning record"
msgstr ""
-"n'a pas pu d�terminer la description de la ligne pour la fonction renvoyant\n"
+"n'a pas pu déterminer la description de la ligne pour la fonction renvoyant\n"
"l'enregistrement"
#: utils/init/miscinit.c:121
#, c-format
msgid "could not change directory to \"%s\": %m"
-msgstr "n'a pas pu modifier le r�pertoire par � %s � : %m"
+msgstr "n'a pas pu modifier le répertoire par « %s » : %m"
-#: utils/init/miscinit.c:449 utils/misc/guc.c:6012
+#: utils/init/miscinit.c:449 utils/misc/guc.c:6016
#, c-format
msgid "cannot set parameter \"%s\" within security-restricted operation"
msgstr ""
-"ne peut pas configurer le param�tre � %s � � l'int�rieur d'une fonction\n"
-"restreinte pour s�curit�"
+"ne peut pas configurer le paramètre « %s » à l'intérieur d'une fonction\n"
+"restreinte pour sécurité"
#: utils/init/miscinit.c:510
#, c-format
msgid "role with OID %u does not exist"
-msgstr "le r�le d'OID %u n'existe pas"
+msgstr "le rôle d'OID %u n'existe pas"
#: utils/init/miscinit.c:540
#, c-format
msgid "role \"%s\" is not permitted to log in"
-msgstr "le r�le � %s � n'est pas autoris� � se connecter"
+msgstr "le rôle « %s » n'est pas autorisé à se connecter"
#: utils/init/miscinit.c:558
#, c-format
msgid "too many connections for role \"%s\""
-msgstr "trop de connexions pour le r�le � %s �"
+msgstr "trop de connexions pour le rôle « %s »"
#: utils/init/miscinit.c:618
#, c-format
msgid "permission denied to set session authorization"
-msgstr "droit refus� pour initialiser une autorisation de session"
+msgstr "droit refusé pour initialiser une autorisation de session"
#: utils/init/miscinit.c:701
#, c-format
msgid "invalid role OID: %u"
-msgstr "OID du r�le invalide : %u"
+msgstr "OID du rôle invalide : %u"
#: utils/init/miscinit.c:755
#, c-format
msgid "database system is shut down"
-msgstr "le syst�me de base de donn�es est arr�t�"
+msgstr "le système de base de données est arrêté"
#: utils/init/miscinit.c:842
#, c-format
msgid "could not create lock file \"%s\": %m"
-msgstr "n'a pas pu cr�er le fichier verrou � %s � : %m"
+msgstr "n'a pas pu créer le fichier verrou « %s » : %m"
#: utils/init/miscinit.c:856
#, c-format
msgid "could not open lock file \"%s\": %m"
-msgstr "n'a pas pu ouvrir le fichier verrou � %s � : %m"
+msgstr "n'a pas pu ouvrir le fichier verrou « %s » : %m"
#: utils/init/miscinit.c:862
#, c-format
msgid "could not read lock file \"%s\": %m"
-msgstr "n'a pas pu lire le fichier verrou � %s � : %m"
+msgstr "n'a pas pu lire le fichier verrou « %s » : %m"
#: utils/init/miscinit.c:870
#, c-format
msgid "lock file \"%s\" is empty"
-msgstr "le fichier verrou � %s � est vide"
+msgstr "le fichier verrou « %s » est vide"
#: utils/init/miscinit.c:871
#, c-format
msgid "Either another server is starting, or the lock file is the remnant of a previous server startup crash."
-msgstr "Soit un autre serveur est en cours de d�marrage, soit le fichier verrou est un reste d'un pr�c�dent crash au d�marrage du serveur"
+msgstr "Soit un autre serveur est en cours de démarrage, soit le fichier verrou est un reste d'un précédent crash au démarrage du serveur"
#: utils/init/miscinit.c:918
#, c-format
msgid "lock file \"%s\" already exists"
-msgstr "le fichier verrou � %s � existe d�j�"
+msgstr "le fichier verrou « %s » existe déjà"
#: utils/init/miscinit.c:922
#, c-format
msgid "Is another postgres (PID %d) running in data directory \"%s\"?"
msgstr ""
-"Un autre postgres (de PID %d) est-il d�j� lanc� avec comme r�pertoire de\n"
-"donn�es � %s � ?"
+"Un autre postgres (de PID %d) est-il déjà lancé avec comme répertoire de\n"
+"données « %s » ?"
#: utils/init/miscinit.c:924
#, c-format
msgid "Is another postmaster (PID %d) running in data directory \"%s\"?"
msgstr ""
-"Un autre postmaster (de PID %d) est-il d�j� lanc� avec comme r�pertoire de\n"
-"donn�es � %s � ?"
+"Un autre postmaster (de PID %d) est-il déjà lancé avec comme répertoire de\n"
+"données « %s » ?"
#: utils/init/miscinit.c:927
#, c-format
msgid "Is another postgres (PID %d) using socket file \"%s\"?"
-msgstr "Un autre postgres (de PID %d) est-il d�j� lanc� en utilisant la socket � %s � ?"
+msgstr "Un autre postgres (de PID %d) est-il déjà lancé en utilisant la socket « %s » ?"
#: utils/init/miscinit.c:929
#, c-format
msgid "Is another postmaster (PID %d) using socket file \"%s\"?"
-msgstr "Un autre postmaster (de PID %d) est-il d�j� lanc� en utilisant la socket � %s � ?"
+msgstr "Un autre postmaster (de PID %d) est-il déjà lancé en utilisant la socket « %s » ?"
#: utils/init/miscinit.c:965
#, c-format
msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use"
msgstr ""
-"le bloc de m�moire partag� pr�-existant (cl� %lu, ID %lu) est en cours\n"
+"le bloc de mémoire partagé pré-existant (clé %lu, ID %lu) est en cours\n"
"d'utilisation"
#: utils/init/miscinit.c:968
#, c-format
msgid "If you're sure there are no old server processes still running, remove the shared memory block or just delete the file \"%s\"."
msgstr ""
-"Si vous �tes s�r qu'aucun processus serveur n'est toujours en cours\n"
-"d'ex�cution, supprimez le bloc de m�moire partag�e\n"
-"ou supprimez simplement le fichier � %s �."
+"Si vous êtes sûr qu'aucun processus serveur n'est toujours en cours\n"
+"d'exécution, supprimez le bloc de mémoire partagée\n"
+"ou supprimez simplement le fichier « %s »."
#: utils/init/miscinit.c:984
#, c-format
msgid "could not remove old lock file \"%s\": %m"
-msgstr "n'a pas pu supprimer le vieux fichier verrou � %s � : %m"
+msgstr "n'a pas pu supprimer le vieux fichier verrou « %s » : %m"
#: utils/init/miscinit.c:986
#, c-format
msgid "The file seems accidentally left over, but it could not be removed. Please remove the file by hand and try again."
msgstr ""
-"Le fichier semble avoir �t� oubli� accidentellement mais il ne peut pas �tre\n"
-"supprim�. Merci de supprimer ce fichier manuellement et de r�-essayer."
+"Le fichier semble avoir été oublié accidentellement mais il ne peut pas être\n"
+"supprimé. Merci de supprimer ce fichier manuellement et de ré-essayer."
#: utils/init/miscinit.c:1022 utils/init/miscinit.c:1033 utils/init/miscinit.c:1043
#, c-format
msgid "could not write lock file \"%s\": %m"
-msgstr "n'a pas pu �crire le fichier verrou � %s � : %m"
+msgstr "n'a pas pu écrire le fichier verrou « %s » : %m"
-#: utils/init/miscinit.c:1172 utils/init/miscinit.c:1301 utils/misc/guc.c:8806
+#: utils/init/miscinit.c:1172 utils/init/miscinit.c:1301 utils/misc/guc.c:8818
#, c-format
msgid "could not read from file \"%s\": %m"
-msgstr "n'a pas pu lire � partir du fichier � %s � : %m"
+msgstr "n'a pas pu lire à partir du fichier « %s » : %m"
#: utils/init/miscinit.c:1291
#, c-format
msgid "could not open file \"%s\": %m; continuing anyway"
-msgstr "n'a pas pu ouvrir le fichier � %s � : %m ; poursuite du traitement"
+msgstr "n'a pas pu ouvrir le fichier « %s » : %m ; poursuite du traitement"
#: utils/init/miscinit.c:1314
#, c-format
msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld"
-msgstr "le fichier de verrou � %s � contient le mauvais PID : %ld au lieu de %ld"
+msgstr "le fichier de verrou « %s » contient le mauvais PID : %ld au lieu de %ld"
#: utils/init/miscinit.c:1356 utils/init/miscinit.c:1369
#, c-format
msgid "\"%s\" is not a valid data directory"
-msgstr "� %s � n'est pas un r�pertoire de donn�es valide"
+msgstr "« %s » n'est pas un répertoire de données valide"
#: utils/init/miscinit.c:1358
#, c-format
msgid "File \"%s\" is missing."
-msgstr "le fichier � %s � est manquant."
+msgstr "le fichier « %s » est manquant."
#: utils/init/miscinit.c:1371
#, c-format
msgid "File \"%s\" does not contain valid data."
-msgstr "le fichier � %s � ne contient aucune donn�es valides."
+msgstr "le fichier « %s » ne contient aucune données valides."
#: utils/init/miscinit.c:1373
#, c-format
msgid "You might need to initdb."
-msgstr "Vous pouvez avoir besoin d'ex�cuter initdb."
+msgstr "Vous pouvez avoir besoin d'exécuter initdb."
#: utils/init/miscinit.c:1381
#, c-format
msgid "The data directory was initialized by PostgreSQL version %ld.%ld, which is not compatible with this version %s."
msgstr ""
-"Le r�pertoire des donn�es a �t� initialis� avec PostgreSQL version %ld.%ld,\n"
+"Le répertoire des données a été initialisé avec PostgreSQL version %ld.%ld,\n"
"qui est non compatible avec cette version %s."
#: utils/init/miscinit.c:1452
#, c-format
msgid "loaded library \"%s\""
-msgstr "biblioth�que � %s � charg�e"
+msgstr "bibliothèque « %s » chargée"
-#: utils/init/postinit.c:252
+#: utils/init/postinit.c:251
#, c-format
msgid "replication connection authorized: user=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)"
-msgstr "connexion autoris�e : utilisateur=%s, SSL activ� (protocole=%s, chiffrement=%s, compression=%s)"
+msgstr "connexion autorisée : utilisateur=%s, SSL activé (protocole=%s, chiffrement=%s, compression=%s)"
-#: utils/init/postinit.c:254 utils/init/postinit.c:268
+#: utils/init/postinit.c:253 utils/init/postinit.c:267
msgid "off"
-msgstr "d�sactiv�"
+msgstr "désactivé"
-#: utils/init/postinit.c:254 utils/init/postinit.c:268
+#: utils/init/postinit.c:253 utils/init/postinit.c:267
msgid "on"
-msgstr "activ�"
+msgstr "activé"
-#: utils/init/postinit.c:258
+#: utils/init/postinit.c:257
#, c-format
msgid "replication connection authorized: user=%s"
-msgstr "connexion de r�plication autoris�e : utilisateur=%s"
+msgstr "connexion de réplication autorisée : utilisateur=%s"
-#: utils/init/postinit.c:266
+#: utils/init/postinit.c:265
#, c-format
msgid "connection authorized: user=%s database=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)"
-msgstr "connexion autoris�e : utilisateur=%s, base de donn�es=%s, SSL activ� (protocole=%s, chiffrement=%s, compression=%s)"
+msgstr "connexion autorisée : utilisateur=%s, base de données=%s, SSL activé (protocole=%s, chiffrement=%s, compression=%s)"
-#: utils/init/postinit.c:272
+#: utils/init/postinit.c:271
#, c-format
msgid "connection authorized: user=%s database=%s"
-msgstr "connexion autoris�e : utilisateur=%s, base de donn�es=%s"
+msgstr "connexion autorisée : utilisateur=%s, base de données=%s"
-#: utils/init/postinit.c:304
+#: utils/init/postinit.c:303
#, c-format
msgid "database \"%s\" has disappeared from pg_database"
-msgstr "la base de donn�es � %s � a disparu de pg_database"
+msgstr "la base de données « %s » a disparu de pg_database"
-#: utils/init/postinit.c:306
+#: utils/init/postinit.c:305
#, c-format
msgid "Database OID %u now seems to belong to \"%s\"."
-msgstr "La base de donn�es d'OID %u semble maintenant appartenir � � %s �."
+msgstr "La base de données d'OID %u semble maintenant appartenir à « %s »."
-#: utils/init/postinit.c:326
+#: utils/init/postinit.c:325
#, c-format
msgid "database \"%s\" is not currently accepting connections"
-msgstr "la base de donn�es � %s � n'accepte plus les connexions"
+msgstr "la base de données « %s » n'accepte plus les connexions"
-#: utils/init/postinit.c:339
+#: utils/init/postinit.c:338
#, c-format
msgid "permission denied for database \"%s\""
-msgstr "droit refus� pour la base de donn�es � %s �"
+msgstr "droit refusé pour la base de données « %s »"
-#: utils/init/postinit.c:340
+#: utils/init/postinit.c:339
#, c-format
msgid "User does not have CONNECT privilege."
msgstr "L'utilisateur n'a pas le droit CONNECT."
-#: utils/init/postinit.c:357
+#: utils/init/postinit.c:356
#, c-format
msgid "too many connections for database \"%s\""
-msgstr "trop de connexions pour la base de donn�es � %s �"
+msgstr "trop de connexions pour la base de données « %s »"
-#: utils/init/postinit.c:379 utils/init/postinit.c:386
+#: utils/init/postinit.c:378 utils/init/postinit.c:385
#, c-format
msgid "database locale is incompatible with operating system"
-msgstr "la locale de la base de donn�es est incompatible avec le syst�me d'exploitation"
+msgstr "la locale de la base de données est incompatible avec le système d'exploitation"
-#: utils/init/postinit.c:380
+#: utils/init/postinit.c:379
#, c-format
msgid "The database was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()."
msgstr ""
-"La base de donn�es a �t� initialis�e avec un LC_COLLATE � � %s �,\n"
+"La base de données a été initialisée avec un LC_COLLATE à « %s »,\n"
"qui n'est pas reconnu par setlocale()."
-#: utils/init/postinit.c:382 utils/init/postinit.c:389
+#: utils/init/postinit.c:381 utils/init/postinit.c:388
#, c-format
msgid "Recreate the database with another locale or install the missing locale."
msgstr ""
-"Recr�ez la base de donn�es avec une autre locale ou installez la locale\n"
+"Recréez la base de données avec une autre locale ou installez la locale\n"
"manquante."
-#: utils/init/postinit.c:387
+#: utils/init/postinit.c:386
#, c-format
msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()."
msgstr ""
-"La base de donn�es a �t� initialis�e avec un LC_CTYPE � � %s �,\n"
+"La base de données a été initialisée avec un LC_CTYPE à « %s »,\n"
"qui n'est pas reconnu par setlocale()."
-#: utils/init/postinit.c:715
+#: utils/init/postinit.c:714
#, c-format
msgid "no roles are defined in this database system"
-msgstr "aucun r�le n'est d�fini dans le syst�me de bases de donn�es"
+msgstr "aucun rôle n'est défini dans le système de bases de données"
-#: utils/init/postinit.c:716
+#: utils/init/postinit.c:715
#, c-format
msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;."
-msgstr "Vous devez imm�diatement ex�cuter � CREATE USER \"%s\" CREATEUSER; �."
+msgstr "Vous devez immédiatement exécuter « CREATE USER \"%s\" CREATEUSER; »."
-#: utils/init/postinit.c:752
+#: utils/init/postinit.c:751
#, c-format
msgid "new replication connections are not allowed during database shutdown"
msgstr ""
-"les nouvelles connexions pour la r�plication ne sont pas autoris�es pendant\n"
-"l'arr�t du serveur de base de donn�es"
+"les nouvelles connexions pour la réplication ne sont pas autorisées pendant\n"
+"l'arrêt du serveur de base de données"
-#: utils/init/postinit.c:756
+#: utils/init/postinit.c:755
#, c-format
msgid "must be superuser to connect during database shutdown"
msgstr ""
-"doit �tre super-utilisateur pour se connecter pendant un arr�t de la base de\n"
-"donn�es"
+"doit être super-utilisateur pour se connecter pendant un arrêt de la base de\n"
+"données"
-#: utils/init/postinit.c:766
+#: utils/init/postinit.c:765
#, c-format
msgid "must be superuser to connect in binary upgrade mode"
-msgstr "doit �tre super-utilisateur pour se connecter en mode de mise � jour binaire"
+msgstr "doit être super-utilisateur pour se connecter en mode de mise à jour binaire"
-#: utils/init/postinit.c:780
+#: utils/init/postinit.c:779
#, c-format
msgid "remaining connection slots are reserved for non-replication superuser connections"
msgstr ""
-"les emplacements de connexions restants sont r�serv�s pour les connexions\n"
-"superutilisateur non relatif � la r�plication"
+"les emplacements de connexions restants sont réservés pour les connexions\n"
+"superutilisateur non relatif à la réplication"
-#: utils/init/postinit.c:790
+#: utils/init/postinit.c:789
#, c-format
msgid "must be superuser or replication role to start walsender"
msgstr ""
-"doit �tre un superutilisateur ou un r�le ayant l'attribut de r�plication\n"
-"pour ex�cuter walsender"
+"doit être un superutilisateur ou un rôle ayant l'attribut de réplication\n"
+"pour exécuter walsender"
-#: utils/init/postinit.c:859
+#: utils/init/postinit.c:858
#, c-format
msgid "database %u does not exist"
-msgstr "la base de donn�es � %u � n'existe pas"
+msgstr "la base de données « %u » n'existe pas"
-#: utils/init/postinit.c:945
+#: utils/init/postinit.c:944
#, c-format
msgid "It seems to have just been dropped or renamed."
-msgstr "Cet objet semble avoir �t� tout juste supprim� ou renomm�."
+msgstr "Cet objet semble avoir été tout juste supprimé ou renommé."
-#: utils/init/postinit.c:963
+#: utils/init/postinit.c:962
#, c-format
msgid "The database subdirectory \"%s\" is missing."
-msgstr "Le sous-r�pertoire de la base de donn�es � %s � est manquant."
+msgstr "Le sous-répertoire de la base de données « %s » est manquant."
-#: utils/init/postinit.c:968
+#: utils/init/postinit.c:967
#, c-format
msgid "could not access directory \"%s\": %m"
-msgstr "n'a pas pu acc�der au r�pertoire � %s � : %m"
+msgstr "n'a pas pu accéder au répertoire « %s » : %m"
#: utils/mb/conv.c:405 utils/mb/conv.c:591
#, c-format
msgid "invalid encoding number: %d"
-msgstr "num�ro d'encodage invalide : %d"
+msgstr "numéro d'encodage invalide : %d"
#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:137 utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:169
#, c-format
msgid "unexpected encoding ID %d for ISO 8859 character sets"
-msgstr "identifiant d'encodage %d inattendu pour les jeux de caract�res ISO-8859"
+msgstr "identifiant d'encodage %d inattendu pour les jeux de caractères ISO-8859"
#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:127 utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:159
#, c-format
msgid "unexpected encoding ID %d for WIN character sets"
-msgstr "identifiant d'encodage %d inattendu pour les jeux de caract�res WIN"
+msgstr "identifiant d'encodage %d inattendu pour les jeux de caractères WIN"
#: utils/mb/encnames.c:496
#, c-format
@@ -21615,55 +21579,55 @@ msgstr "nom d'encodage trop long"
#: utils/mb/mbutils.c:307
#, c-format
msgid "conversion between %s and %s is not supported"
-msgstr "la conversion entre %s et %s n'est pas support�e"
+msgstr "la conversion entre %s et %s n'est pas supportée"
#: utils/mb/mbutils.c:366
#, c-format
msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist"
msgstr ""
-"la fonction de conversion par d�faut pour l'encodage de � %s � en � %s �\n"
+"la fonction de conversion par défaut pour l'encodage de « %s » en « %s »\n"
"n'existe pas"
#: utils/mb/mbutils.c:377 utils/mb/mbutils.c:710
#, c-format
msgid "String of %d bytes is too long for encoding conversion."
-msgstr "Une cha�ne de %d octets est trop longue pour la conversion d'encodage."
+msgstr "Une chaîne de %d octets est trop longue pour la conversion d'encodage."
#: utils/mb/mbutils.c:464
#, c-format
msgid "invalid source encoding name \"%s\""
-msgstr "nom de l'encodage source � %s � invalide"
+msgstr "nom de l'encodage source « %s » invalide"
#: utils/mb/mbutils.c:469
#, c-format
msgid "invalid destination encoding name \"%s\""
-msgstr "nom de l'encodage destination � %s � invalide"
+msgstr "nom de l'encodage destination « %s » invalide"
#: utils/mb/mbutils.c:609
#, c-format
msgid "invalid byte value for encoding \"%s\": 0x%02x"
-msgstr "valeur d'octet invalide pour l'encodage � %s � : 0x%02x"
+msgstr "valeur d'octet invalide pour l'encodage « %s » : 0x%02x"
#: utils/mb/mbutils.c:951
#, c-format
msgid "bind_textdomain_codeset failed"
-msgstr "�chec de bind_textdomain_codeset"
+msgstr "échec de bind_textdomain_codeset"
#: utils/mb/wchar.c:2015
#, c-format
msgid "invalid byte sequence for encoding \"%s\": %s"
-msgstr "s�quence d'octets invalide pour l'encodage � %s � : %s"
+msgstr "séquence d'octets invalide pour l'encodage « %s » : %s"
#: utils/mb/wchar.c:2048
#, c-format
msgid "character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\""
msgstr ""
-"le caract�re dont la s�quence d'octets est %s dans l'encodage � %s � n'a pas\n"
-"d'�quivalent dans l'encodage � %s �"
+"le caractère dont la séquence d'octets est %s dans l'encodage « %s » n'a pas\n"
+"d'équivalent dans l'encodage « %s »"
#: utils/misc/guc.c:548
msgid "Ungrouped"
-msgstr "D�group�"
+msgstr "Dégroupé"
#: utils/misc/guc.c:550
msgid "File Locations"
@@ -21675,11 +21639,11 @@ msgstr "Connexions et authentification"
#: utils/misc/guc.c:554
msgid "Connections and Authentication / Connection Settings"
-msgstr "Connexions et authentification / Param�trages de connexion"
+msgstr "Connexions et authentification / Paramètrages de connexion"
#: utils/misc/guc.c:556
msgid "Connections and Authentication / Security and Authentication"
-msgstr "Connexions et authentification / S�curit� et authentification"
+msgstr "Connexions et authentification / Sécurité et authentification"
#: utils/misc/guc.c:558
msgid "Resource Usage"
@@ -21687,7 +21651,7 @@ msgstr "Utilisation des ressources"
#: utils/misc/guc.c:560
msgid "Resource Usage / Memory"
-msgstr "Utilisation des ressources / M�moire"
+msgstr "Utilisation des ressources / Mémoire"
#: utils/misc/guc.c:562
msgid "Resource Usage / Disk"
@@ -21699,11 +21663,11 @@ msgstr "Utilisation des ressources / Ressources noyau"
#: utils/misc/guc.c:566
msgid "Resource Usage / Cost-Based Vacuum Delay"
-msgstr "Utilisation des ressources / D�lai du VACUUM bas� sur le co�t"
+msgstr "Utilisation des ressources / Délai du VACUUM basé sur le coût"
#: utils/misc/guc.c:568
msgid "Resource Usage / Background Writer"
-msgstr "Utilisation des ressources / Processus d'�criture en t�che de fond"
+msgstr "Utilisation des ressources / Processus d'écriture en tâche de fond"
#: utils/misc/guc.c:570
msgid "Resource Usage / Asynchronous Behavior"
@@ -21715,11 +21679,11 @@ msgstr "Write-Ahead Log"
#: utils/misc/guc.c:574
msgid "Write-Ahead Log / Settings"
-msgstr "Write-Ahead Log / Param�trages"
+msgstr "Write-Ahead Log / Paramètrages"
#: utils/misc/guc.c:576
msgid "Write-Ahead Log / Checkpoints"
-msgstr "Write-Ahead Log / Points de v�rification (Checkpoints)"
+msgstr "Write-Ahead Log / Points de vérification (Checkpoints)"
#: utils/misc/guc.c:578
msgid "Write-Ahead Log / Archiving"
@@ -21727,39 +21691,39 @@ msgstr "Write-Ahead Log / Archivage"
#: utils/misc/guc.c:580
msgid "Replication"
-msgstr "R�plication"
+msgstr "Réplication"
#: utils/misc/guc.c:582
msgid "Replication / Sending Servers"
-msgstr "R�plication / Serveurs d'envoi"
+msgstr "Réplication / Serveurs d'envoi"
#: utils/misc/guc.c:584
msgid "Replication / Master Server"
-msgstr "R�plication / Serveur ma�tre"
+msgstr "Réplication / Serveur maître"
#: utils/misc/guc.c:586
msgid "Replication / Standby Servers"
-msgstr "R�plication / Serveurs en attente"
+msgstr "Réplication / Serveurs en attente"
#: utils/misc/guc.c:588
msgid "Query Tuning"
-msgstr "Optimisation des requ�tes"
+msgstr "Optimisation des requêtes"
#: utils/misc/guc.c:590
msgid "Query Tuning / Planner Method Configuration"
-msgstr "Optimisation des requ�tes / Configuration de la m�thode du planificateur"
+msgstr "Optimisation des requêtes / Configuration de la méthode du planificateur"
#: utils/misc/guc.c:592
msgid "Query Tuning / Planner Cost Constants"
-msgstr "Optimisation des requ�tes / Constantes des co�ts du planificateur"
+msgstr "Optimisation des requêtes / Constantes des coûts du planificateur"
#: utils/misc/guc.c:594
msgid "Query Tuning / Genetic Query Optimizer"
-msgstr "Optimisation des requ�tes / Optimiseur g�n�tique de requ�tes"
+msgstr "Optimisation des requêtes / Optimiseur génétique de requêtes"
#: utils/misc/guc.c:596
msgid "Query Tuning / Other Planner Options"
-msgstr "Optimisation des requ�tes / Autres options du planificateur"
+msgstr "Optimisation des requêtes / Autres options du planificateur"
#: utils/misc/guc.c:598
msgid "Reporting and Logging"
@@ -21767,7 +21731,7 @@ msgstr "Rapports et traces"
#: utils/misc/guc.c:600
msgid "Reporting and Logging / Where to Log"
-msgstr "Rapports et traces / O� tracer"
+msgstr "Rapports et traces / Où tracer"
#: utils/misc/guc.c:602
msgid "Reporting and Logging / When to Log"
@@ -21791,7 +21755,7 @@ msgstr "Statistiques / Surveillance"
#: utils/misc/guc.c:612
msgid "Statistics / Query and Index Statistics Collector"
-msgstr "Statistiques / R�cup�rateur des statistiques sur les requ�tes et sur les index"
+msgstr "Statistiques / Récupérateur des statistiques sur les requêtes et sur les index"
#: utils/misc/guc.c:614
msgid "Autovacuum"
@@ -21799,23 +21763,23 @@ msgstr "Autovacuum"
#: utils/misc/guc.c:616
msgid "Client Connection Defaults"
-msgstr "Valeurs par d�faut pour les connexions client"
+msgstr "Valeurs par défaut pour les connexions client"
#: utils/misc/guc.c:618
msgid "Client Connection Defaults / Statement Behavior"
-msgstr "Valeurs par d�faut pour les connexions client / Comportement des instructions"
+msgstr "Valeurs par défaut pour les connexions client / Comportement des instructions"
#: utils/misc/guc.c:620
msgid "Client Connection Defaults / Locale and Formatting"
-msgstr "Valeurs par d�faut pour les connexions client / Locale et formattage"
+msgstr "Valeurs par défaut pour les connexions client / Locale et formattage"
#: utils/misc/guc.c:622
msgid "Client Connection Defaults / Shared Library Preloading"
-msgstr "Valeurs par d�faut pour les connexions des clients / Pr�chargement des biblioth�ques partag�es"
+msgstr "Valeurs par défaut pour les connexions des clients / Préchargement des bibliothèques partagées"
#: utils/misc/guc.c:624
msgid "Client Connection Defaults / Other Defaults"
-msgstr "Valeurs par d�faut pour les connexions client / Autres valeurs par d�faut"
+msgstr "Valeurs par défaut pour les connexions client / Autres valeurs par défaut"
#: utils/misc/guc.c:626
msgid "Lock Management"
@@ -21823,15 +21787,15 @@ msgstr "Gestion des verrous"
#: utils/misc/guc.c:628
msgid "Version and Platform Compatibility"
-msgstr "Compatibilit� des versions et des plateformes"
+msgstr "Compatibilité des versions et des plateformes"
#: utils/misc/guc.c:630
msgid "Version and Platform Compatibility / Previous PostgreSQL Versions"
-msgstr "Compatibilit� des versions et des plateformes / Anciennes versions de PostgreSQL"
+msgstr "Compatibilité des versions et des plateformes / Anciennes versions de PostgreSQL"
#: utils/misc/guc.c:632
msgid "Version and Platform Compatibility / Other Platforms and Clients"
-msgstr "Compatibilit� des versions et des plateformes / Anciennes plateformes et anciens clients"
+msgstr "Compatibilité des versions et des plateformes / Anciennes plateformes et anciens clients"
#: utils/misc/guc.c:634
msgid "Error Handling"
@@ -21839,29 +21803,29 @@ msgstr "Gestion des erreurs"
#: utils/misc/guc.c:636
msgid "Preset Options"
-msgstr "Options pr�-configur�es"
+msgstr "Options pré-configurées"
#: utils/misc/guc.c:638
msgid "Customized Options"
-msgstr "Options personnalis�es"
+msgstr "Options personnalisées"
#: utils/misc/guc.c:640
msgid "Developer Options"
-msgstr "Options pour le d�veloppeur"
+msgstr "Options pour le développeur"
#: utils/misc/guc.c:697
msgid "Valid units for this parameter are \"kB\", \"MB\", \"GB\", and \"TB\"."
-msgstr "Les unit�s valides pour ce param�tre sont � kB �, � MB �, � GB � et � TB �."
+msgstr "Les unités valides pour ce paramètre sont « kB », « MB », « GB » et « TB »."
#: utils/misc/guc.c:724
msgid "Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\"."
msgstr ""
-"Les unit�s valides pour ce param�tre sont � ms �, � s �, � min �, � h � et\n"
-"� d �."
+"Les unités valides pour ce paramètre sont « ms », « s », « min », « h » et\n"
+"« d »."
#: utils/misc/guc.c:783
msgid "Enables the planner's use of sequential-scan plans."
-msgstr "Active l'utilisation des parcours s�quentiels par le planificateur."
+msgstr "Active l'utilisation des parcours séquentiels par le planificateur."
#: utils/misc/guc.c:792
msgid "Enables the planner's use of index-scan plans."
@@ -21881,19 +21845,19 @@ msgstr "Active l'utilisation de plans de parcours TID par le planificateur."
#: utils/misc/guc.c:828
msgid "Enables the planner's use of explicit sort steps."
-msgstr "Active l'utilisation des �tapes de tris explicites par le planificateur."
+msgstr "Active l'utilisation des étapes de tris explicites par le planificateur."
#: utils/misc/guc.c:837
msgid "Enables the planner's use of hashed aggregation plans."
-msgstr "Active l'utilisation de plans d'agr�gats h�ch�s par le planificateur."
+msgstr "Active l'utilisation de plans d'agrégats hâchés par le planificateur."
#: utils/misc/guc.c:846
msgid "Enables the planner's use of materialization."
-msgstr "Active l'utilisation de la mat�rialisation par le planificateur."
+msgstr "Active l'utilisation de la matérialisation par le planificateur."
#: utils/misc/guc.c:855
msgid "Enables the planner's use of nested-loop join plans."
-msgstr "Active l'utilisation de plans avec des jointures imbriqu�es par le planificateur."
+msgstr "Active l'utilisation de plans avec des jointures imbriquées par le planificateur."
#: utils/misc/guc.c:864
msgid "Enables the planner's use of merge join plans."
@@ -21901,1674 +21865,1666 @@ msgstr "Active l'utilisation de plans de jointures MERGE par le planificateur."
#: utils/misc/guc.c:873
msgid "Enables the planner's use of hash join plans."
-msgstr "Active l'utilisation de plans de jointures h�ch�es par le planificateur."
+msgstr "Active l'utilisation de plans de jointures hâchées par le planificateur."
-#: utils/misc/guc.c:882
-msgid "Enables use of foreign keys for estimating joins."
-msgstr ""
-
-#: utils/misc/guc.c:892
+#: utils/misc/guc.c:883
msgid "Enables genetic query optimization."
-msgstr "Active l'optimisation g�n�tique des requ�tes."
+msgstr "Active l'optimisation génétique des requêtes."
-#: utils/misc/guc.c:893
+#: utils/misc/guc.c:884
msgid "This algorithm attempts to do planning without exhaustive searching."
msgstr "Cet algorithme essaie de faire une planification sans recherche exhaustive."
-#: utils/misc/guc.c:903
+#: utils/misc/guc.c:894
msgid "Shows whether the current user is a superuser."
msgstr "Affiche si l'utilisateur actuel est un super-utilisateur."
-#: utils/misc/guc.c:913
+#: utils/misc/guc.c:904
msgid "Enables advertising the server via Bonjour."
msgstr "Active la publication du serveur via Bonjour."
-#: utils/misc/guc.c:922
+#: utils/misc/guc.c:913
msgid "Collects transaction commit time."
-msgstr "R�cup�re l'horodatage de la validation de la transaction."
+msgstr "Récupère l'horodatage de la validation de la transaction."
-#: utils/misc/guc.c:931
+#: utils/misc/guc.c:922
msgid "Enables SSL connections."
msgstr "Active les connexions SSL."
-#: utils/misc/guc.c:940
+#: utils/misc/guc.c:931
msgid "Give priority to server ciphersuite order."
-msgstr "Donne la priorit� � l'ordre des chiffrements du serveur."
+msgstr "Donne la priorité à l'ordre des chiffrements du serveur."
-#: utils/misc/guc.c:949
+#: utils/misc/guc.c:940
msgid "Forces synchronization of updates to disk."
-msgstr "Force la synchronisation des mises � jour sur le disque."
+msgstr "Force la synchronisation des mises à jour sur le disque."
-#: utils/misc/guc.c:950
+#: utils/misc/guc.c:941
msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This insures that a database cluster will recover to a consistent state after an operating system or hardware crash."
msgstr ""
-"Le serveur utilisera l'appel syst�me fsync() � diff�rents endroits pour\n"
-"s'assurer que les mises � jour sont �crites physiquement sur le disque. Ceci\n"
-"nous assure qu'un groupe de bases de donn�es se retrouvera dans un �tat\n"
-"coh�rent apr�s un arr�t brutal d� au syst�me d'exploitation ou au mat�riel."
+"Le serveur utilisera l'appel système fsync() à différents endroits pour\n"
+"s'assurer que les mises à jour sont écrites physiquement sur le disque. Ceci\n"
+"nous assure qu'un groupe de bases de données se retrouvera dans un état\n"
+"cohérent après un arrêt brutal dû au système d'exploitation ou au matériel."
-#: utils/misc/guc.c:961
+#: utils/misc/guc.c:952
msgid "Continues processing after a checksum failure."
-msgstr "Continue le traitement apr�s un �chec de la somme de contr�le."
+msgstr "Continue le traitement après un échec de la somme de contrôle."
-#: utils/misc/guc.c:962
+#: utils/misc/guc.c:953
msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled."
-msgstr "La d�tection d'une erreur de somme de contr�le a normalement pour effet de rapporter une erreur, annulant la transaction en cours. R�gler ignore_checksum_failure � true permet au syst�me d'ignorer cette erreur (mais rapporte toujours un avertissement), et continue le traitement. Ce comportement pourrait causer un arr�t brutal ou d'autres probl�mes s�rieux. Cela a un effet seulement si les sommes de contr�les (checksums) sont activ�s."
+msgstr "La détection d'une erreur de somme de contrôle a normalement pour effet de rapporter une erreur, annulant la transaction en cours. Régler ignore_checksum_failure à true permet au système d'ignorer cette erreur (mais rapporte toujours un avertissement), et continue le traitement. Ce comportement pourrait causer un arrêt brutal ou d'autres problèmes sérieux. Cela a un effet seulement si les sommes de contrôles (checksums) sont activés."
-#: utils/misc/guc.c:976
+#: utils/misc/guc.c:967
msgid "Continues processing past damaged page headers."
-msgstr "Continue le travail apr�s les en-t�tes de page endommag�s."
+msgstr "Continue le travail après les en-têtes de page endommagés."
-#: utils/misc/guc.c:977
+#: utils/misc/guc.c:968
msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting zero_damaged_pages to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page."
msgstr ""
-"La d�tection d'une en-t�te de page endommag�e cause normalement le rapport\n"
+"La détection d'une en-tête de page endommagée cause normalement le rapport\n"
"d'une erreur par PostgreSQL, l'annulation de la transaction en cours.\n"
-"Initialiser zero_damaged_pages � true fait que le syst�me ne rapporte qu'un\n"
-"message d'attention et continue � travailler. Ce comportement d�truira des\n"
-"donn�es, notamment toutes les lignes de la page endommag�e."
+"Initialiser zero_damaged_pages à true fait que le système ne rapporte qu'un\n"
+"message d'attention et continue à travailler. Ce comportement détruira des\n"
+"données, notamment toutes les lignes de la page endommagée."
-#: utils/misc/guc.c:990
+#: utils/misc/guc.c:981
msgid "Writes full pages to WAL when first modified after a checkpoint."
msgstr ""
-"�crit des pages compl�tes dans les WAL lors d'une premi�re modification apr�s\n"
-"un point de v�rification."
+"Écrit des pages complètes dans les WAL lors d'une première modification après\n"
+"un point de vérification."
-#: utils/misc/guc.c:991
+#: utils/misc/guc.c:982
msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible."
msgstr ""
-"Une page �crite au moment d'un arr�t brutal du syst�me d'exploitation\n"
-"pourrait �tre seulement partiellement �crite sur le disque. Lors de la\n"
-"r�cup�ration, les modifications de la ligne, stock�es dans le journal de\n"
-"transaction, ne seront pas suffisantes pour terminer la r�cup�ration. Cette\n"
-"option �crit les pages lors de la premi�re modification apr�s un point de\n"
-"v�rification des journaux de transaction pour que la r�cup�ration compl�te\n"
+"Une page écrite au moment d'un arrêt brutal du système d'exploitation\n"
+"pourrait être seulement partiellement écrite sur le disque. Lors de la\n"
+"récupération, les modifications de la ligne, stockées dans le journal de\n"
+"transaction, ne seront pas suffisantes pour terminer la récupération. Cette\n"
+"option écrit les pages lors de la première modification après un point de\n"
+"vérification des journaux de transaction pour que la récupération complète\n"
"soit possible."
-#: utils/misc/guc.c:1004
+#: utils/misc/guc.c:995
msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modifications."
msgstr ""
-"�crit des pages compl�tes dans les WAL lors d'une premi�re modification apr�s\n"
-"un point de v�rification, y compris pour des modifications non critiques."
+"Écrit des pages complètes dans les WAL lors d'une première modification après\n"
+"un point de vérification, y compris pour des modifications non critiques."
-#: utils/misc/guc.c:1014
+#: utils/misc/guc.c:1005
msgid "Compresses full-page writes written in WAL file."
-msgstr "Compresse les blocs complets �crits dans les journaux de transactions."
+msgstr "Compresse les blocs complets écrits dans les journaux de transactions."
-#: utils/misc/guc.c:1024
+#: utils/misc/guc.c:1015
msgid "Logs each checkpoint."
-msgstr "Trace tous les points de v�rification."
+msgstr "Trace tous les points de vérification."
-#: utils/misc/guc.c:1033
+#: utils/misc/guc.c:1024
msgid "Logs each successful connection."
-msgstr "Trace toutes les connexions r�ussies."
+msgstr "Trace toutes les connexions réussies."
-#: utils/misc/guc.c:1042
+#: utils/misc/guc.c:1033
msgid "Logs end of a session, including duration."
-msgstr "Trace la fin d'une session, avec sa dur�e."
+msgstr "Trace la fin d'une session, avec sa durée."
-#: utils/misc/guc.c:1051
+#: utils/misc/guc.c:1042
msgid "Logs each replication command."
-msgstr "Trace chaque commande de r�plication."
+msgstr "Trace chaque commande de réplication."
-#: utils/misc/guc.c:1060
+#: utils/misc/guc.c:1051
msgid "Shows whether the running server has assertion checks enabled."
-msgstr "Affiche si le serveur en cours d'ex�cution a les v�rifications d'assertion activ�es."
+msgstr "Affiche si le serveur en cours d'exécution a les vérifications d'assertion activées."
-#: utils/misc/guc.c:1075
+#: utils/misc/guc.c:1066
msgid "Terminate session on any error."
msgstr "Termine la session sans erreur."
-#: utils/misc/guc.c:1084
+#: utils/misc/guc.c:1075
msgid "Reinitialize server after backend crash."
-msgstr "R�initialisation du serveur apr�s un arr�t brutal d'un processus serveur."
+msgstr "Réinitialisation du serveur après un arrêt brutal d'un processus serveur."
-#: utils/misc/guc.c:1094
+#: utils/misc/guc.c:1085
msgid "Logs the duration of each completed SQL statement."
-msgstr "Trace la dur�e de chaque instruction SQL termin�e."
+msgstr "Trace la durée de chaque instruction SQL terminée."
-#: utils/misc/guc.c:1103
+#: utils/misc/guc.c:1094
msgid "Logs each query's parse tree."
-msgstr "Trace l'arbre d'analyse de chaque requ�te."
+msgstr "Trace l'arbre d'analyse de chaque requête."
-#: utils/misc/guc.c:1112
+#: utils/misc/guc.c:1103
msgid "Logs each query's rewritten parse tree."
-msgstr "Trace l'arbre d'analyse r��crit de chaque requ�te."
+msgstr "Trace l'arbre d'analyse réécrit de chaque requête."
-#: utils/misc/guc.c:1121
+#: utils/misc/guc.c:1112
msgid "Logs each query's execution plan."
-msgstr "Trace le plan d'ex�cution de chaque requ�te."
+msgstr "Trace le plan d'exécution de chaque requête."
-#: utils/misc/guc.c:1130
+#: utils/misc/guc.c:1121
msgid "Indents parse and plan tree displays."
msgstr "Indente l'affichage des arbres d'analyse et de planification."
-#: utils/misc/guc.c:1139
+#: utils/misc/guc.c:1130
msgid "Writes parser performance statistics to the server log."
msgstr ""
-"�crit les statistiques de performance de l'analyseur dans les journaux applicatifs\n"
+"Écrit les statistiques de performance de l'analyseur dans les journaux applicatifs\n"
"du serveur."
-#: utils/misc/guc.c:1148
+#: utils/misc/guc.c:1139
msgid "Writes planner performance statistics to the server log."
msgstr ""
-"�crit les statistiques de performance de planification dans les journaux\n"
+"Écrit les statistiques de performance de planification dans les journaux\n"
"applicatifs du serveur."
-#: utils/misc/guc.c:1157
+#: utils/misc/guc.c:1148
msgid "Writes executor performance statistics to the server log."
msgstr ""
-"�crit les statistiques de performance de l'ex�cuteur dans les journaux applicatifs\n"
+"Écrit les statistiques de performance de l'exécuteur dans les journaux applicatifs\n"
"du serveur."
-#: utils/misc/guc.c:1166
+#: utils/misc/guc.c:1157
msgid "Writes cumulative performance statistics to the server log."
msgstr ""
-"�crit les statistiques de performance cumulatives dans les journaux applicatifs\n"
+"Écrit les statistiques de performance cumulatives dans les journaux applicatifs\n"
"du serveur."
-#: utils/misc/guc.c:1176
+#: utils/misc/guc.c:1167
msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations."
-msgstr "Trace les statistiques d'utilisation des ressources syst�mes (m�moire et CPU) sur les diff�rentes op�rations B-tree."
+msgstr "Trace les statistiques d'utilisation des ressources systèmes (mémoire et CPU) sur les différentes opérations B-tree."
-#: utils/misc/guc.c:1188
+#: utils/misc/guc.c:1179
msgid "Collects information about executing commands."
-msgstr "R�cup�re les statistiques sur les commandes en ex�cution."
+msgstr "Récupère les statistiques sur les commandes en exécution."
-#: utils/misc/guc.c:1189
+#: utils/misc/guc.c:1180
msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution."
msgstr ""
-"Active la r�cup�ration d'informations sur la commande en cours d'ex�cution\n"
-"pour chaque session, avec l'heure de d�but de l'ex�cution de la commande."
+"Active la récupération d'informations sur la commande en cours d'exécution\n"
+"pour chaque session, avec l'heure de début de l'exécution de la commande."
-#: utils/misc/guc.c:1199
+#: utils/misc/guc.c:1190
msgid "Collects statistics on database activity."
-msgstr "R�cup�re les statistiques sur l'activit� de la base de donn�es."
+msgstr "Récupère les statistiques sur l'activité de la base de données."
-#: utils/misc/guc.c:1208
+#: utils/misc/guc.c:1199
msgid "Collects timing statistics for database I/O activity."
-msgstr "R�cup�re les statistiques d'horodatage sur l'activit� en entr�es/sorties de la base de donn�es."
+msgstr "Récupère les statistiques d'horodatage sur l'activité en entrées/sorties de la base de données."
-#: utils/misc/guc.c:1218
+#: utils/misc/guc.c:1209
msgid "Updates the process title to show the active SQL command."
msgstr ""
-"Met � jour le titre du processus pour indiquer la commande SQL en cours\n"
-"d'ex�cution."
+"Met à jour le titre du processus pour indiquer la commande SQL en cours\n"
+"d'exécution."
-#: utils/misc/guc.c:1219
+#: utils/misc/guc.c:1210
msgid "Enables updating of the process title every time a new SQL command is received by the server."
msgstr ""
-"Active la mise � jour du titre du processus chaque fois qu'une nouvelle\n"
-"commande SQL est re�ue par le serveur."
+"Active la mise à jour du titre du processus chaque fois qu'une nouvelle\n"
+"commande SQL est reçue par le serveur."
-#: utils/misc/guc.c:1228
+#: utils/misc/guc.c:1223
msgid "Starts the autovacuum subprocess."
-msgstr "Ex�cute le sous-processus de l'autovacuum."
+msgstr "Exécute le sous-processus de l'autovacuum."
-#: utils/misc/guc.c:1238
+#: utils/misc/guc.c:1233
msgid "Generates debugging output for LISTEN and NOTIFY."
-msgstr "G�n�re une sortie de d�bogage pour LISTEN et NOTIFY."
+msgstr "Génère une sortie de débogage pour LISTEN et NOTIFY."
-#: utils/misc/guc.c:1250
+#: utils/misc/guc.c:1245
msgid "Emits information about lock usage."
-msgstr "�met des informations sur l'utilisation des verrous."
+msgstr "Émet des informations sur l'utilisation des verrous."
-#: utils/misc/guc.c:1260
+#: utils/misc/guc.c:1255
msgid "Emits information about user lock usage."
-msgstr "�met des informations sur l'utilisation des verrous utilisateurs."
+msgstr "Émet des informations sur l'utilisation des verrous utilisateurs."
-#: utils/misc/guc.c:1270
+#: utils/misc/guc.c:1265
msgid "Emits information about lightweight lock usage."
-msgstr "�met des informations sur l'utilisation des verrous l�gers."
+msgstr "Émet des informations sur l'utilisation des verrous légers."
-#: utils/misc/guc.c:1280
+#: utils/misc/guc.c:1275
msgid "Dumps information about all current locks when a deadlock timeout occurs."
-msgstr "Trace les informations sur les verrous actuels lorsqu'un d�lai sur le deadlock est d�pass�."
+msgstr "Trace les informations sur les verrous actuels lorsqu'un délai sur le deadlock est dépassé."
-#: utils/misc/guc.c:1292
+#: utils/misc/guc.c:1287
msgid "Logs long lock waits."
msgstr "Trace les attentes longues de verrou."
-#: utils/misc/guc.c:1302
+#: utils/misc/guc.c:1297
msgid "Logs the host name in the connection logs."
-msgstr "Trace le nom d'h�te dans les traces de connexion."
+msgstr "Trace le nom d'hôte dans les traces de connexion."
-#: utils/misc/guc.c:1303
+#: utils/misc/guc.c:1298
msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty."
msgstr ""
-"Par d�faut, les traces de connexion n'affichent que l'adresse IP de l'h�te\n"
-"se connectant. Si vous voulez que s'affiche le nom de l'h�te, vous devez\n"
-"activer cette option mais suivant la configuration de la r�solution de noms\n"
-"pour votre h�te, cela pourrait imposer des d�gradations de performances non\n"
-"n�gligeables."
+"Par défaut, les traces de connexion n'affichent que l'adresse IP de l'hôte\n"
+"se connectant. Si vous voulez que s'affiche le nom de l'hôte, vous devez\n"
+"activer cette option mais suivant la configuration de la résolution de noms\n"
+"pour votre hôte, cela pourrait imposer des dégradations de performances non\n"
+"négligeables."
-#: utils/misc/guc.c:1314
+#: utils/misc/guc.c:1309
msgid "Causes subtables to be included by default in various commands."
msgstr ""
-"Fait que les sous-tables soient incluses par d�faut dans les diff�rentes\n"
+"Fait que les sous-tables soient incluses par défaut dans les différentes\n"
"commandes."
-#: utils/misc/guc.c:1323
+#: utils/misc/guc.c:1318
msgid "Encrypt passwords."
msgstr "Chiffre les mots de passe."
-#: utils/misc/guc.c:1324
+#: utils/misc/guc.c:1319
msgid "When a password is specified in CREATE USER or ALTER USER without writing either ENCRYPTED or UNENCRYPTED, this parameter determines whether the password is to be encrypted."
msgstr ""
-"Lorsqu'un mot de passe est sp�cifi� dans CREATE USER ou ALTER USER sans\n"
-"indiquer ENCRYPTED ou UNENCRYPTED, ce param�tre d�termine si le mot de passe\n"
-"doit �tre chiffr�."
+"Lorsqu'un mot de passe est spécifié dans CREATE USER ou ALTER USER sans\n"
+"indiquer ENCRYPTED ou UNENCRYPTED, ce paramètre détermine si le mot de passe\n"
+"doit être chiffré."
-#: utils/misc/guc.c:1334
+#: utils/misc/guc.c:1329
msgid "Treats \"expr=NULL\" as \"expr IS NULL\"."
-msgstr "Traite � expr=NULL � comme � expr IS NULL �."
+msgstr "Traite « expr=NULL » comme « expr IS NULL »."
-#: utils/misc/guc.c:1335
+#: utils/misc/guc.c:1330
msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)."
msgstr ""
-"Une fois activ�, les expressions de la forme expr = NULL (ou NULL = expr)\n"
-"sont trait�es comme expr IS NULL, c'est-�-dire qu'elles renvoient true si\n"
-"l'expression est �valu�e comme �tant NULL et false sinon. Le comportement\n"
+"Une fois activé, les expressions de la forme expr = NULL (ou NULL = expr)\n"
+"sont traitées comme expr IS NULL, c'est-à-dire qu'elles renvoient true si\n"
+"l'expression est évaluée comme étant NULL et false sinon. Le comportement\n"
"correct de expr = NULL est de toujours renvoyer NULL (inconnu)."
-#: utils/misc/guc.c:1347
+#: utils/misc/guc.c:1342
msgid "Enables per-database user names."
-msgstr "Active les noms d'utilisateur par base de donn�es."
+msgstr "Active les noms d'utilisateur par base de données."
-#: utils/misc/guc.c:1356
+#: utils/misc/guc.c:1351
msgid "Sets the default read-only status of new transactions."
-msgstr "Initialise le statut de lecture seule par d�faut des nouvelles transactions."
+msgstr "Initialise le statut de lecture seule par défaut des nouvelles transactions."
-#: utils/misc/guc.c:1365
+#: utils/misc/guc.c:1360
msgid "Sets the current transaction's read-only status."
msgstr "Affiche le statut de lecture seule de la transaction actuelle."
-#: utils/misc/guc.c:1375
+#: utils/misc/guc.c:1370
msgid "Sets the default deferrable status of new transactions."
-msgstr "Initialise le statut d�ferrable par d�faut des nouvelles transactions."
+msgstr "Initialise le statut déferrable par défaut des nouvelles transactions."
-#: utils/misc/guc.c:1384
+#: utils/misc/guc.c:1379
msgid "Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."
msgstr ""
-"S'il faut repousser une transaction s�rialisable en lecture seule jusqu'� ce qu'elle\n"
-"puisse �tre ex�cut�e sans �checs possibles de s�rialisation."
+"S'il faut repousser une transaction sérialisable en lecture seule jusqu'à ce qu'elle\n"
+"puisse être exécutée sans échecs possibles de sérialisation."
-#: utils/misc/guc.c:1394
+#: utils/misc/guc.c:1389
msgid "Enable row security."
-msgstr "Active la s�curit� niveau ligne."
+msgstr "Active la sécurité niveau ligne."
-#: utils/misc/guc.c:1395
+#: utils/misc/guc.c:1390
msgid "When enabled, row security will be applied to all users."
-msgstr "Lorsqu'il est activ�, le mode de s�curit� niveau ligne sera appliqu� � tous les utilisateurs."
+msgstr "Lorsqu'il est activé, le mode de sécurité niveau ligne sera appliqué à tous les utilisateurs."
-#: utils/misc/guc.c:1403
+#: utils/misc/guc.c:1398
msgid "Check function bodies during CREATE FUNCTION."
-msgstr "V�rifie les corps de fonction lors du CREATE FUNCTION."
+msgstr "Vérifie les corps de fonction lors du CREATE FUNCTION."
-#: utils/misc/guc.c:1412
+#: utils/misc/guc.c:1407
msgid "Enable input of NULL elements in arrays."
-msgstr "Active la saisie d'�l�ments NULL dans les tableaux."
+msgstr "Active la saisie d'éléments NULL dans les tableaux."
-#: utils/misc/guc.c:1413
+#: utils/misc/guc.c:1408
msgid "When turned on, unquoted NULL in an array input value means a null value; otherwise it is taken literally."
msgstr ""
-"Si activ�, un NULL sans guillemets en tant que valeur d'entr�e dans un\n"
-"tableau signifie une valeur NULL ; sinon, il sera pris litt�ralement."
+"Si activé, un NULL sans guillemets en tant que valeur d'entrée dans un\n"
+"tableau signifie une valeur NULL ; sinon, il sera pris littéralement."
-#: utils/misc/guc.c:1423
+#: utils/misc/guc.c:1418
msgid "Create new tables with OIDs by default."
-msgstr "Cr�e des nouvelles tables avec des OID par d�faut."
+msgstr "Crée des nouvelles tables avec des OID par défaut."
-#: utils/misc/guc.c:1432
+#: utils/misc/guc.c:1427
msgid "Start a subprocess to capture stderr output and/or csvlogs into log files."
msgstr ""
"Lance un sous-processus pour capturer la sortie d'erreurs (stderr) et/ou\n"
"csvlogs dans des journaux applicatifs."
-#: utils/misc/guc.c:1441
+#: utils/misc/guc.c:1436
msgid "Truncate existing log files of same name during log rotation."
msgstr ""
-"Tronque les journaux applicatifs existants du m�me nom lors de la rotation\n"
+"Tronque les journaux applicatifs existants du même nom lors de la rotation\n"
"des journaux applicatifs."
-#: utils/misc/guc.c:1452
+#: utils/misc/guc.c:1447
msgid "Emit information about resource usage in sorting."
-msgstr "�met des informations sur l'utilisation des ressources lors d'un tri."
+msgstr "Émet des informations sur l'utilisation des ressources lors d'un tri."
-#: utils/misc/guc.c:1466
+#: utils/misc/guc.c:1461
msgid "Generate debugging output for synchronized scanning."
-msgstr "G�n�re une sortie de d�bogage pour les parcours synchronis�s."
+msgstr "Génère une sortie de débogage pour les parcours synchronisés."
-#: utils/misc/guc.c:1481
+#: utils/misc/guc.c:1476
msgid "Enable bounded sorting using heap sort."
-msgstr "Active le tri limit� en utilisant le tri de heap."
+msgstr "Active le tri limité en utilisant le tri de heap."
-#: utils/misc/guc.c:1494
+#: utils/misc/guc.c:1489
msgid "Emit WAL-related debugging output."
-msgstr "�met une sortie de d�bogage concernant les journaux de transactions."
+msgstr "Émet une sortie de débogage concernant les journaux de transactions."
-#: utils/misc/guc.c:1506
+#: utils/misc/guc.c:1501
msgid "Datetimes are integer based."
-msgstr "Les types datetime sont bas�s sur des entiers"
+msgstr "Les types datetime sont basés sur des entiers"
-#: utils/misc/guc.c:1521
+#: utils/misc/guc.c:1516
msgid "Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."
msgstr ""
-"Indique si les noms d'utilisateurs Kerberos et GSSAPI devraient �tre trait�s\n"
+"Indique si les noms d'utilisateurs Kerberos et GSSAPI devraient être traités\n"
"sans se soucier de la casse."
-#: utils/misc/guc.c:1531
+#: utils/misc/guc.c:1526
msgid "Warn about backslash escapes in ordinary string literals."
-msgstr "Avertie sur les �chappements par antislash dans les cha�nes ordinaires."
+msgstr "Avertie sur les échappements par antislash dans les chaînes ordinaires."
-#: utils/misc/guc.c:1541
+#: utils/misc/guc.c:1536
msgid "Causes '...' strings to treat backslashes literally."
-msgstr "Fait que les cha�nes '...' traitent les antislashs litt�ralement."
+msgstr "Fait que les chaînes '...' traitent les antislashs littéralement."
-#: utils/misc/guc.c:1552
+#: utils/misc/guc.c:1547
msgid "Enable synchronized sequential scans."
-msgstr "Active l'utilisation des parcours s�quentiels synchronis�s."
+msgstr "Active l'utilisation des parcours séquentiels synchronisés."
-#: utils/misc/guc.c:1562
+#: utils/misc/guc.c:1557
msgid "Allows connections and queries during recovery."
-msgstr "Autorise les connexions et les requ�tes pendant la restauration."
+msgstr "Autorise les connexions et les requêtes pendant la restauration."
-#: utils/misc/guc.c:1572
+#: utils/misc/guc.c:1567
msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts."
msgstr ""
"Permet l'envoi d'informations d'un serveur Hot Standby vers le serveur\n"
-"principal pour �viter les conflits de requ�tes."
+"principal pour éviter les conflits de requêtes."
-#: utils/misc/guc.c:1582
+#: utils/misc/guc.c:1577
msgid "Allows modifications of the structure of system tables."
-msgstr "Permet les modifications de la structure des tables syst�mes."
+msgstr "Permet les modifications de la structure des tables systèmes."
-#: utils/misc/guc.c:1593
+#: utils/misc/guc.c:1588
msgid "Disables reading from system indexes."
-msgstr "D�sactive la lecture des index syst�me."
+msgstr "Désactive la lecture des index système."
-#: utils/misc/guc.c:1594
+#: utils/misc/guc.c:1589
msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness."
msgstr ""
-"Cela n'emp�che pas la mise � jour des index, donc vous pouvez l'utiliser en\n"
-"toute s�curit�. La pire cons�quence est la lenteur."
+"Cela n'empêche pas la mise à jour des index, donc vous pouvez l'utiliser en\n"
+"toute sécurité. La pire conséquence est la lenteur."
-#: utils/misc/guc.c:1605
+#: utils/misc/guc.c:1600
msgid "Enables backward compatibility mode for privilege checks on large objects."
msgstr ""
-"Active la compatibilit� ascendante pour la v�rification des droits sur les\n"
+"Active la compatibilité ascendante pour la vérification des droits sur les\n"
"Large Objects."
-#: utils/misc/guc.c:1606
+#: utils/misc/guc.c:1601
msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0."
msgstr ""
-"Ignore la v�rification des droits lors de la lecture et de la modification\n"
-"des Larges Objects, pour la compatibilit� avec les versions ant�rieures � la\n"
+"Ignore la vérification des droits lors de la lecture et de la modification\n"
+"des Larges Objects, pour la compatibilité avec les versions antérieures à la\n"
"9.0."
-#: utils/misc/guc.c:1616
+#: utils/misc/guc.c:1611
msgid "Emit a warning for constructs that changed meaning since PostgreSQL 9.4."
-msgstr "�met un avertissement pour les constructions dont la signification a chang� depuis PostgreSQL 9.4."
+msgstr "Émet un avertissement pour les constructions dont la signification a changé depuis PostgreSQL 9.4."
-#: utils/misc/guc.c:1626
+#: utils/misc/guc.c:1621
msgid "When generating SQL fragments, quote all identifiers."
-msgstr "Lors de la g�n�ration des rragments SQL, mettre entre guillemets tous les identifiants."
+msgstr "Lors de la génération des rragments SQL, mettre entre guillemets tous les identifiants."
-#: utils/misc/guc.c:1636
+#: utils/misc/guc.c:1631
msgid "Shows whether data checksums are turned on for this cluster."
-msgstr "Affiche si les sommes de contr�le sont activ�es sur les donn�es pour cette instance."
+msgstr "Affiche si les sommes de contrôle sont activées sur les données pour cette instance."
-#: utils/misc/guc.c:1647
+#: utils/misc/guc.c:1642
msgid "Add sequence number to syslog messages to avoid duplicate suppression."
-msgstr ""
+msgstr "Ajoute un numéro de séquence aux messages syslog pour éviter des suppressions de doublons."
-#: utils/misc/guc.c:1657
+#: utils/misc/guc.c:1652
msgid "Split messages sent to syslog by lines and to fit into 1024 bytes."
-msgstr ""
+msgstr "Sépare les messages envoyés à syslog par lignes afin de les faire tenir dans 1024 octets."
-#: utils/misc/guc.c:1676
+#: utils/misc/guc.c:1671
msgid "Forces a switch to the next xlog file if a new file has not been started within N seconds."
msgstr ""
"Force un changement du journal de transaction si un nouveau fichier n'a pas\n"
-"�t� cr�� depuis N secondes."
+"été créé depuis N secondes."
-#: utils/misc/guc.c:1687
+#: utils/misc/guc.c:1682
msgid "Waits N seconds on connection startup after authentication."
-msgstr "Attends N secondes apr�s l'authentification."
+msgstr "Attends N secondes après l'authentification."
-#: utils/misc/guc.c:1688 utils/misc/guc.c:2211
+#: utils/misc/guc.c:1683 utils/misc/guc.c:2206
msgid "This allows attaching a debugger to the process."
-msgstr "Ceci permet d'attacher un d�bogueur au processus."
+msgstr "Ceci permet d'attacher un débogueur au processus."
-#: utils/misc/guc.c:1697
+#: utils/misc/guc.c:1692
msgid "Sets the default statistics target."
-msgstr "Initialise la cible par d�faut des statistiques."
+msgstr "Initialise la cible par défaut des statistiques."
-#: utils/misc/guc.c:1698
+#: utils/misc/guc.c:1693
msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS."
msgstr ""
-"Ceci s'applique aux colonnes de tables qui n'ont pas de cible sp�cifique\n"
-"pour la colonne initialis�e via ALTER TABLE SET STATISTICS."
+"Ceci s'applique aux colonnes de tables qui n'ont pas de cible spécifique\n"
+"pour la colonne initialisée via ALTER TABLE SET STATISTICS."
-#: utils/misc/guc.c:1707
+#: utils/misc/guc.c:1702
msgid "Sets the FROM-list size beyond which subqueries are not collapsed."
msgstr ""
"Initialise la taille de la liste FROM en dehors de laquelle les\n"
-"sous-requ�tes ne sont pas rassembl�es."
+"sous-requêtes ne sont pas rassemblées."
-#: utils/misc/guc.c:1709
+#: utils/misc/guc.c:1704
msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items."
msgstr ""
-"Le planificateur fusionne les sous-requ�tes dans des requ�tes sup�rieures\n"
-"si la liste FROM r�sultante n'a pas plus de ce nombre d'�l�ments."
+"Le planificateur fusionne les sous-requêtes dans des requêtes supérieures\n"
+"si la liste FROM résultante n'a pas plus de ce nombre d'éléments."
-#: utils/misc/guc.c:1719
+#: utils/misc/guc.c:1714
msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened."
msgstr ""
"Initialise la taille de la liste FROM en dehors de laquelle les contructions\n"
"JOIN ne sont pas aplanies."
-#: utils/misc/guc.c:1721
+#: utils/misc/guc.c:1716
msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result."
msgstr ""
"La planificateur applanira les constructions JOIN explicites dans des listes\n"
-"d'�l�ments FROM lorsqu'une liste d'au plus ce nombre d'�l�ments en\n"
-"r�sulterait."
+"d'éléments FROM lorsqu'une liste d'au plus ce nombre d'éléments en\n"
+"résulterait."
-#: utils/misc/guc.c:1731
+#: utils/misc/guc.c:1726
msgid "Sets the threshold of FROM items beyond which GEQO is used."
-msgstr "Initialise la limite des �l�ments FROM en dehors de laquelle GEQO est utilis�."
+msgstr "Initialise la limite des éléments FROM en dehors de laquelle GEQO est utilisé."
-#: utils/misc/guc.c:1740
+#: utils/misc/guc.c:1735
msgid "GEQO: effort is used to set the default for other GEQO parameters."
msgstr ""
-"GEQO : l'effort est utilis� pour initialiser une valeur par d�faut pour les\n"
-"autres param�tres GEQO."
+"GEQO : l'effort est utilisé pour initialiser une valeur par défaut pour les\n"
+"autres paramètres GEQO."
-#: utils/misc/guc.c:1749
+#: utils/misc/guc.c:1744
msgid "GEQO: number of individuals in the population."
msgstr "GEQO : nombre d'individus dans une population."
-#: utils/misc/guc.c:1750 utils/misc/guc.c:1759
+#: utils/misc/guc.c:1745 utils/misc/guc.c:1754
msgid "Zero selects a suitable default value."
-msgstr "Z�ro s�lectionne une valeur par d�faut convenable."
+msgstr "Zéro sélectionne une valeur par défaut convenable."
-#: utils/misc/guc.c:1758
+#: utils/misc/guc.c:1753
msgid "GEQO: number of iterations of the algorithm."
-msgstr "GEQO : nombre d'it�rations dans l'algorithme."
+msgstr "GEQO : nombre d'itérations dans l'algorithme."
-#: utils/misc/guc.c:1769
+#: utils/misc/guc.c:1764
msgid "Sets the time to wait on a lock before checking for deadlock."
-msgstr "Temps d'attente du verrou avant de v�rifier les verrous bloqu�s."
+msgstr "Temps d'attente du verrou avant de vérifier les verrous bloqués."
-#: utils/misc/guc.c:1780
+#: utils/misc/guc.c:1775
msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."
msgstr ""
-"Initialise le d�lai maximum avant d'annuler les requ�tes lorsqu'un serveur en\n"
-"hotstandby traite les donn�es des journaux de transactions archiv�s"
+"Initialise le délai maximum avant d'annuler les requêtes lorsqu'un serveur en\n"
+"hotstandby traite les données des journaux de transactions archivés"
-#: utils/misc/guc.c:1791
+#: utils/misc/guc.c:1786
msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."
msgstr ""
-"Initialise le d�lai maximum avant d'annuler les requ�tes lorsqu'un serveur en\n"
-"hotstandby traite les donn�es des journaux de transactions envoy�s en flux."
+"Initialise le délai maximum avant d'annuler les requêtes lorsqu'un serveur en\n"
+"hotstandby traite les données des journaux de transactions envoyés en flux."
-#: utils/misc/guc.c:1802
+#: utils/misc/guc.c:1797
msgid "Sets the maximum interval between WAL receiver status reports to the primary."
-msgstr "Configure l'intervalle maximum entre chaque envoi d'un rapport de statut du walreceiver vers le serveur ma�tre."
+msgstr "Configure l'intervalle maximum entre chaque envoi d'un rapport de statut du walreceiver vers le serveur maître."
-#: utils/misc/guc.c:1813
+#: utils/misc/guc.c:1808
msgid "Sets the maximum wait time to receive data from the primary."
-msgstr "Configure la dur�e maximale de l'attente de la r�ception de donn�es depuis le serveur ma�tre."
+msgstr "Configure la durée maximale de l'attente de la réception de données depuis le serveur maître."
-#: utils/misc/guc.c:1824
+#: utils/misc/guc.c:1819
msgid "Sets the maximum number of concurrent connections."
-msgstr "Nombre maximum de connexions simultan�es."
+msgstr "Nombre maximum de connexions simultanées."
-#: utils/misc/guc.c:1834
+#: utils/misc/guc.c:1829
msgid "Sets the number of connection slots reserved for superusers."
-msgstr "Nombre de connexions r�serv�es aux super-utilisateurs."
+msgstr "Nombre de connexions réservées aux super-utilisateurs."
-#: utils/misc/guc.c:1848
+#: utils/misc/guc.c:1843
msgid "Sets the number of shared memory buffers used by the server."
-msgstr "Nombre de tampons en m�moire partag�e utilis� par le serveur."
+msgstr "Nombre de tampons en mémoire partagée utilisé par le serveur."
-#: utils/misc/guc.c:1859
+#: utils/misc/guc.c:1854
msgid "Sets the maximum number of temporary buffers used by each session."
-msgstr "Nombre maximum de tampons en m�moire partag�e utilis�s par chaque session."
+msgstr "Nombre maximum de tampons en mémoire partagée utilisés par chaque session."
-#: utils/misc/guc.c:1870
+#: utils/misc/guc.c:1865
msgid "Sets the TCP port the server listens on."
-msgstr "Port TCP sur lequel le serveur �coutera."
+msgstr "Port TCP sur lequel le serveur écoutera."
-#: utils/misc/guc.c:1880
+#: utils/misc/guc.c:1875
msgid "Sets the access permissions of the Unix-domain socket."
-msgstr "Droits d'acc�s au socket domaine Unix."
+msgstr "Droits d'accès au socket domaine Unix."
-#: utils/misc/guc.c:1881
+#: utils/misc/guc.c:1876
msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)"
msgstr ""
-"Les sockets de domaine Unix utilise l'ensemble des droits habituels du syst�me\n"
-"de fichiers Unix. La valeur de ce param�tre doit �tre une sp�cification en\n"
-"mode num�rique de la forme accept�e par les appels syst�me chmod et umask\n"
-"(pour utiliser le format octal, le nombre doit commencer avec un z�ro)."
+"Les sockets de domaine Unix utilise l'ensemble des droits habituels du système\n"
+"de fichiers Unix. La valeur de ce paramètre doit être une spécification en\n"
+"mode numérique de la forme acceptée par les appels système chmod et umask\n"
+"(pour utiliser le format octal, le nombre doit commencer avec un zéro)."
-#: utils/misc/guc.c:1895
+#: utils/misc/guc.c:1890
msgid "Sets the file permissions for log files."
msgstr "Initialise les droits des fichiers de trace."
-#: utils/misc/guc.c:1896
+#: utils/misc/guc.c:1891
msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)"
msgstr ""
-"La valeur du param�tre est attendue dans le format num�rique du mode accept�\n"
-"par les appels syst�me chmod et umask (pour utiliser le format octal\n"
-"personnalis�, le num�ro doit commencer avec un z�ro)."
+"La valeur du paramètre est attendue dans le format numérique du mode accepté\n"
+"par les appels système chmod et umask (pour utiliser le format octal\n"
+"personnalisé, le numéro doit commencer avec un zéro)."
-#: utils/misc/guc.c:1909
+#: utils/misc/guc.c:1904
msgid "Sets the maximum memory to be used for query workspaces."
-msgstr "Initialise la m�moire maximum utilis�e pour les espaces de travail des requ�tes."
+msgstr "Initialise la mémoire maximum utilisée pour les espaces de travail des requêtes."
-#: utils/misc/guc.c:1910
+#: utils/misc/guc.c:1905
msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files."
msgstr ""
-"Sp�cifie la m�moire � utiliser par les op�rations de tris internes et par\n"
+"Spécifie la mémoire à utiliser par les opérations de tris internes et par\n"
"les tables de hachage avant de passer sur des fichiers temporaires sur disque."
-#: utils/misc/guc.c:1922
+#: utils/misc/guc.c:1917
msgid "Sets the maximum memory to be used for maintenance operations."
-msgstr "Initialise la m�moire maximum utilis�e pour les op�rations de maintenance."
+msgstr "Initialise la mémoire maximum utilisée pour les opérations de maintenance."
-#: utils/misc/guc.c:1923
+#: utils/misc/guc.c:1918
msgid "This includes operations such as VACUUM and CREATE INDEX."
-msgstr "Ceci inclut les op�rations comme VACUUM et CREATE INDEX."
+msgstr "Ceci inclut les opérations comme VACUUM et CREATE INDEX."
-#: utils/misc/guc.c:1933
+#: utils/misc/guc.c:1928
msgid "Sets the maximum number of tuples to be sorted using replacement selection."
-msgstr "Configure le nombre maximum de lignes � trier en utilisant la s�lection de remplacement."
+msgstr "Configure le nombre maximum de lignes à trier en utilisant la sélection de remplacement."
-#: utils/misc/guc.c:1934
+#: utils/misc/guc.c:1929
msgid "When more tuples than this are present, quicksort will be used."
-msgstr ""
+msgstr "Quand plus de lignes que ça sont présentes, quicksort sera utilisé."
-#: utils/misc/guc.c:1948
+#: utils/misc/guc.c:1943
msgid "Sets the maximum stack depth, in kilobytes."
msgstr "Initialise la profondeur maximale de la pile, en Ko."
-#: utils/misc/guc.c:1959
-msgid "Limits the total size of all temporary files used by each session."
-msgstr "Limite la taille totale de tous les fichiers temporaires utilis�s par chaque session."
+#: utils/misc/guc.c:1954
+msgid "Limits the total size of all temporary files used by each process."
+msgstr "Limite la taille totale de tous les fichiers temporaires utilisés par chaque processus."
-#: utils/misc/guc.c:1960
+#: utils/misc/guc.c:1955
msgid "-1 means no limit."
msgstr "-1 signifie sans limite."
-#: utils/misc/guc.c:1970
+#: utils/misc/guc.c:1965
msgid "Vacuum cost for a page found in the buffer cache."
-msgstr "Co�t d'un VACUUM pour une page trouv�e dans le cache du tampon."
+msgstr "Coût d'un VACUUM pour une page trouvée dans le cache du tampon."
-#: utils/misc/guc.c:1980
+#: utils/misc/guc.c:1975
msgid "Vacuum cost for a page not found in the buffer cache."
-msgstr "Co�t d'un VACUUM pour une page introuvable dans le cache du tampon."
+msgstr "Coût d'un VACUUM pour une page introuvable dans le cache du tampon."
-#: utils/misc/guc.c:1990
+#: utils/misc/guc.c:1985
msgid "Vacuum cost for a page dirtied by vacuum."
-msgstr "Co�t d'un VACUUM pour une page modifi�e par VACUUM."
+msgstr "Coût d'un VACUUM pour une page modifiée par VACUUM."
-#: utils/misc/guc.c:2000
+#: utils/misc/guc.c:1995
msgid "Vacuum cost amount available before napping."
-msgstr "Co�t du VACUUM disponible avant un repos."
+msgstr "Coût du VACUUM disponible avant un repos."
-#: utils/misc/guc.c:2010
+#: utils/misc/guc.c:2005
msgid "Vacuum cost delay in milliseconds."
-msgstr "D�lai d'un co�t de VACUUM en millisecondes."
+msgstr "Délai d'un coût de VACUUM en millisecondes."
-#: utils/misc/guc.c:2021
+#: utils/misc/guc.c:2016
msgid "Vacuum cost delay in milliseconds, for autovacuum."
-msgstr "D�lai d'un co�t de VACUUM en millisecondes, pour autovacuum."
+msgstr "Délai d'un coût de VACUUM en millisecondes, pour autovacuum."
-#: utils/misc/guc.c:2032
+#: utils/misc/guc.c:2027
msgid "Vacuum cost amount available before napping, for autovacuum."
-msgstr "Co�t du VACUUM disponible avant un repos, pour autovacuum."
+msgstr "Coût du VACUUM disponible avant un repos, pour autovacuum."
-#: utils/misc/guc.c:2042
+#: utils/misc/guc.c:2037
msgid "Sets the maximum number of simultaneously open files for each server process."
msgstr ""
-"Initialise le nombre maximum de fichiers ouverts simultan�ment pour chaque\n"
+"Initialise le nombre maximum de fichiers ouverts simultanément pour chaque\n"
"processus serveur."
-#: utils/misc/guc.c:2055
+#: utils/misc/guc.c:2050
msgid "Sets the maximum number of simultaneously prepared transactions."
-msgstr "Initialise le nombre maximum de transactions pr�par�es simultan�ment."
+msgstr "Initialise le nombre maximum de transactions préparées simultanément."
-#: utils/misc/guc.c:2066
+#: utils/misc/guc.c:2061
msgid "Sets the minimum OID of tables for tracking locks."
msgstr "Initialise l'OID minimum des tables pour tracer les verrous."
-#: utils/misc/guc.c:2067
+#: utils/misc/guc.c:2062
msgid "Is used to avoid output on system tables."
-msgstr "Est utilis� pour �viter la sortie sur des tables syst�mes."
+msgstr "Est utilisé pour éviter la sortie sur des tables systèmes."
-#: utils/misc/guc.c:2076
+#: utils/misc/guc.c:2071
msgid "Sets the OID of the table with unconditionally lock tracing."
msgstr "Configure l'OID de la table avec une trace des verrous sans condition."
-#: utils/misc/guc.c:2088
+#: utils/misc/guc.c:2083
msgid "Sets the maximum allowed duration of any statement."
-msgstr "Initialise la dur�e maximum permise pour toute instruction."
+msgstr "Initialise la durée maximum permise pour toute instruction."
-#: utils/misc/guc.c:2089 utils/misc/guc.c:2100 utils/misc/guc.c:2111
+#: utils/misc/guc.c:2084 utils/misc/guc.c:2095 utils/misc/guc.c:2106
msgid "A value of 0 turns off the timeout."
-msgstr "Une valeur de 0 d�sactive le timeout."
+msgstr "Une valeur de 0 désactive le timeout."
-#: utils/misc/guc.c:2099
+#: utils/misc/guc.c:2094
msgid "Sets the maximum allowed duration of any wait for a lock."
-msgstr "Initialise la dur�e maximum permise pour toute attente d'un verrou."
+msgstr "Initialise la durée maximum permise pour toute attente d'un verrou."
-#: utils/misc/guc.c:2110
+#: utils/misc/guc.c:2105
msgid "Sets the maximum allowed duration of any idling transaction."
-msgstr "Initialise la dur�e maximale autoris�e pour toute transaction en attente."
+msgstr "Initialise la durée maximale autorisée pour toute transaction en attente."
-#: utils/misc/guc.c:2121
+#: utils/misc/guc.c:2116
msgid "Minimum age at which VACUUM should freeze a table row."
-msgstr "�ge minimum � partir duquel VACUUM devra geler une ligne de table."
+msgstr "Âge minimum à partir duquel VACUUM devra geler une ligne de table."
-#: utils/misc/guc.c:2131
+#: utils/misc/guc.c:2126
msgid "Age at which VACUUM should scan whole table to freeze tuples."
msgstr ""
-"�ge � partir duquel VACUUM devra parcourir une table compl�te pour geler les\n"
+"Âge à partir duquel VACUUM devra parcourir une table complète pour geler les\n"
"lignes."
-#: utils/misc/guc.c:2141
+#: utils/misc/guc.c:2136
msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row."
-msgstr "�ge minimum � partir duquel VACUUM devra geler un MultiXactId dans une ligne de table."
+msgstr "Âge minimum à partir duquel VACUUM devra geler un MultiXactId dans une ligne de table."
-#: utils/misc/guc.c:2151
+#: utils/misc/guc.c:2146
msgid "Multixact age at which VACUUM should scan whole table to freeze tuples."
msgstr ""
-"�ge Multixact � partir duquel VACUUM devra parcourir une table compl�te pour geler les\n"
+"Âge Multixact à partir duquel VACUUM devra parcourir une table complète pour geler les\n"
"lignes."
-#: utils/misc/guc.c:2161
+#: utils/misc/guc.c:2156
msgid "Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."
-msgstr "Nombre de transactions � partir duquel les nettoyages VACUUM et HOT doivent �tre d�ferr�s."
+msgstr "Nombre de transactions à partir duquel les nettoyages VACUUM et HOT doivent être déferrés."
-#: utils/misc/guc.c:2174
+#: utils/misc/guc.c:2169
msgid "Sets the maximum number of locks per transaction."
msgstr "Initialise le nombre maximum de verrous par transaction."
-#: utils/misc/guc.c:2175
+#: utils/misc/guc.c:2170
msgid "The shared lock table is sized on the assumption that at most max_locks_per_transaction * max_connections distinct objects will need to be locked at any one time."
msgstr ""
-"La table des verrous partag�s est dimensionn�e sur l'id�e qu'au plus\n"
+"La table des verrous partagés est dimensionnée sur l'idée qu'au plus\n"
"max_locks_per_transaction * max_connections objets distincts auront besoin\n"
-"d'�tre verrouill�s � tout moment."
+"d'être verrouillés à tout moment."
-#: utils/misc/guc.c:2186
+#: utils/misc/guc.c:2181
msgid "Sets the maximum number of predicate locks per transaction."
-msgstr "Initialise le nombre maximum de verrous pr�dicats par transaction."
+msgstr "Initialise le nombre maximum de verrous prédicats par transaction."
-#: utils/misc/guc.c:2187
+#: utils/misc/guc.c:2182
msgid "The shared predicate lock table is sized on the assumption that at most max_pred_locks_per_transaction * max_connections distinct objects will need to be locked at any one time."
msgstr ""
-"La table des verrous de pr�dicat partag�s est dimensionn�e sur l'id�e qu'au plus\n"
+"La table des verrous de prédicat partagés est dimensionnée sur l'idée qu'au plus\n"
"max_pred_locks_per_transaction * max_connections objets distincts auront besoin\n"
-"d'�tre verrouill�s � tout moment."
+"d'être verrouillés à tout moment."
-#: utils/misc/guc.c:2198
+#: utils/misc/guc.c:2193
msgid "Sets the maximum allowed time to complete client authentication."
msgstr ""
"Initialise le temps maximum en secondes pour terminer l'authentification du\n"
"client."
-#: utils/misc/guc.c:2210
+#: utils/misc/guc.c:2205
msgid "Waits N seconds on connection startup before authentication."
msgstr "Attends N secondes au lancement de la connexion avant l'authentification."
-#: utils/misc/guc.c:2221
+#: utils/misc/guc.c:2216
msgid "Sets the number of WAL files held for standby servers."
-msgstr "Initialise le nombre de journaux de transactions conserv�s tenus par les seveurs en attente."
+msgstr "Initialise le nombre de journaux de transactions conservés tenus par les seveurs en attente."
-#: utils/misc/guc.c:2231
-#, fuzzy
-#| msgid "Sets the maximum time to wait for WAL replication."
+#: utils/misc/guc.c:2226
msgid "Sets the minimum size to shrink the WAL to."
-msgstr "Initialise le temps maximum � attendre pour la r�plication des WAL."
+msgstr "Initialise la taille minimale à laquelle réduire l'espace des journaux de transaction."
-#: utils/misc/guc.c:2242
-#, fuzzy
-#| msgid "Sets the maximum time between automatic WAL checkpoints."
+#: utils/misc/guc.c:2237
msgid "Sets the WAL size that triggers a checkpoint."
-msgstr ""
-"Initialise le temps maximum entre des points de v�rification (checkpoints)\n"
-"pour les journaux de transactions."
+msgstr "Initialise la volumétrie de journaux de transaction qui déclenche un checkpoint."
-#: utils/misc/guc.c:2253
+#: utils/misc/guc.c:2248
msgid "Sets the maximum time between automatic WAL checkpoints."
msgstr ""
-"Initialise le temps maximum entre des points de v�rification (checkpoints)\n"
+"Initialise le temps maximum entre des points de vérification (checkpoints)\n"
"pour les journaux de transactions."
-#: utils/misc/guc.c:2264
+#: utils/misc/guc.c:2259
msgid "Enables warnings if checkpoint segments are filled more frequently than this."
msgstr ""
"Active des messages d'avertissement si les segments des points de\n"
-"v�rifications se remplissent plus fr�quemment que cette dur�e."
+"vérifications se remplissent plus fréquemment que cette durée."
-#: utils/misc/guc.c:2266
+#: utils/misc/guc.c:2261
msgid "Write a message to the server log if checkpoints caused by the filling of checkpoint segment files happens more frequently than this number of seconds. Zero turns off the warning."
msgstr ""
-"�crit un message dans les journaux applicatifs du serveur si les points de\n"
-"v�rifications caus�es par le remplissage des journaux de transaction avec\n"
-"des points de v�rification qui arrivent plus fr�quemment que ce nombre de\n"
-"secondes. Une valeur 0 d�sactive l'avertissement."
+"Écrit un message dans les journaux applicatifs du serveur si les points de\n"
+"vérifications causées par le remplissage des journaux de transaction avec\n"
+"des points de vérification qui arrivent plus fréquemment que ce nombre de\n"
+"secondes. Une valeur 0 désactive l'avertissement."
-#: utils/misc/guc.c:2278 utils/misc/guc.c:2436 utils/misc/guc.c:2464
+#: utils/misc/guc.c:2273 utils/misc/guc.c:2430 utils/misc/guc.c:2457
msgid "Number of pages after which previously performed writes are flushed to disk."
-msgstr ""
+msgstr "Nombre de pages après lequel les précédentes écritures seront synchronisées sur disque."
-#: utils/misc/guc.c:2290
+#: utils/misc/guc.c:2284
msgid "Sets the number of disk-page buffers in shared memory for WAL."
msgstr ""
-"Initialise le nombre de tampons de pages disque dans la m�moire partag�e\n"
+"Initialise le nombre de tampons de pages disque dans la mémoire partagée\n"
"pour les journaux de transactions."
-#: utils/misc/guc.c:2301
+#: utils/misc/guc.c:2295
msgid "Time between WAL flushes performed in the WAL writer."
-msgstr ""
+msgstr "Temps entre les synchronisations des WAL sur disques effectuées par le processus d'écriture des journaux de transaction"
-#: utils/misc/guc.c:2312
-msgid "Amount of WAL written out by WAL writer triggering a flush."
-msgstr ""
+#: utils/misc/guc.c:2306
+msgid "Amount of WAL written out by WAL writer that triggers a flush."
+msgstr "Quantité de WAL écrits par le processus d'écriture des journaux de transaction devant déclencher une synchronisation sur disque."
-#: utils/misc/guc.c:2324
+#: utils/misc/guc.c:2318
msgid "Sets the maximum number of simultaneously running WAL sender processes."
msgstr ""
"Initialise le nombre maximum de processus d'envoi des journaux de transactions\n"
-"ex�cut�s simultan�ment."
+"exécutés simultanément."
-#: utils/misc/guc.c:2335
+#: utils/misc/guc.c:2329
msgid "Sets the maximum number of simultaneously defined replication slots."
-msgstr "Initialise le nombre maximum de slots de r�plication d�finis simultan�ment."
+msgstr "Initialise le nombre maximum de slots de réplication définis simultanément."
-#: utils/misc/guc.c:2345
+#: utils/misc/guc.c:2339
msgid "Sets the maximum time to wait for WAL replication."
-msgstr "Initialise le temps maximum � attendre pour la r�plication des WAL."
+msgstr "Initialise le temps maximum à attendre pour la réplication des WAL."
-#: utils/misc/guc.c:2356
+#: utils/misc/guc.c:2350
msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk."
msgstr ""
-"Initialise le d�lai en microsecondes entre l'acceptation de la transaction\n"
+"Initialise le délai en microsecondes entre l'acceptation de la transaction\n"
"et le vidage du journal de transaction sur disque."
-#: utils/misc/guc.c:2368
+#: utils/misc/guc.c:2362
msgid "Sets the minimum concurrent open transactions before performing commit_delay."
msgstr ""
-"Initialise le nombre minimum de transactions ouvertes simultan�ment avant le\n"
+"Initialise le nombre minimum de transactions ouvertes simultanément avant le\n"
"commit_delay."
-#: utils/misc/guc.c:2379
+#: utils/misc/guc.c:2373
msgid "Sets the number of digits displayed for floating-point values."
-msgstr "Initialise le nombre de chiffres affich�s pour les valeurs � virgule flottante."
+msgstr "Initialise le nombre de chiffres affichés pour les valeurs à virgule flottante."
-#: utils/misc/guc.c:2380
+#: utils/misc/guc.c:2374
msgid "This affects real, double precision, and geometric data types. The parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate)."
msgstr ""
-"Ceci affecte les types de donn�es real, double precision et g�om�triques.\n"
-"La valeur du param�tre est ajout�e au nombre standard de chiffres (FLT_DIG\n"
-"ou DBL_DIG comme appropri�)."
+"Ceci affecte les types de données real, double precision et géométriques.\n"
+"La valeur du paramètre est ajoutée au nombre standard de chiffres (FLT_DIG\n"
+"ou DBL_DIG comme approprié)."
-#: utils/misc/guc.c:2391
+#: utils/misc/guc.c:2385
msgid "Sets the minimum execution time above which statements will be logged."
msgstr ""
-"Initialise le temps d'ex�cution minimum au-dessus de lequel les instructions\n"
-"seront trac�es."
+"Initialise le temps d'exécution minimum au-dessus de lequel les instructions\n"
+"seront tracées."
-#: utils/misc/guc.c:2393
+#: utils/misc/guc.c:2387
msgid "Zero prints all queries. -1 turns this feature off."
-msgstr "Z�ro affiche toutes les requ�tes. -1 d�sactive cette fonctionnalit�."
+msgstr "Zéro affiche toutes les requêtes. -1 désactive cette fonctionnalité."
-#: utils/misc/guc.c:2403
+#: utils/misc/guc.c:2397
msgid "Sets the minimum execution time above which autovacuum actions will be logged."
msgstr ""
-"Initialise le temps d'ex�cution minimum au-dessus duquel les actions\n"
-"autovacuum seront trac�es."
+"Initialise le temps d'exécution minimum au-dessus duquel les actions\n"
+"autovacuum seront tracées."
-#: utils/misc/guc.c:2405
+#: utils/misc/guc.c:2399
msgid "Zero prints all actions. -1 turns autovacuum logging off."
-msgstr "Z�ro affiche toutes les requ�tes. -1 d�sactive cette fonctionnalit�."
+msgstr "Zéro affiche toutes les requêtes. -1 désactive cette fonctionnalité."
-#: utils/misc/guc.c:2415
+#: utils/misc/guc.c:2409
msgid "Background writer sleep time between rounds."
msgstr ""
-"Temps d'endormissement du processus d'�criture en t�che de fond en\n"
+"Temps d'endormissement du processus d'écriture en tâche de fond en\n"
"millisecondes."
-#: utils/misc/guc.c:2426
+#: utils/misc/guc.c:2420
msgid "Background writer maximum number of LRU pages to flush per round."
msgstr ""
-"Nombre de pages LRU maximum � nettoyer par le processus d'�criture en\n"
-"t�che de fond."
+"Nombre de pages LRU maximum à nettoyer par le processus d'écriture en\n"
+"tâche de fond."
-#: utils/misc/guc.c:2450
+#: utils/misc/guc.c:2443
msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem."
-msgstr "Nombre de requ�tes simultan�es pouvant �tre g�r�es efficacement par le sous-syst�me disque."
+msgstr "Nombre de requêtes simultanées pouvant être gérées efficacement par le sous-système disque."
-#: utils/misc/guc.c:2451
+#: utils/misc/guc.c:2444
msgid "For RAID arrays, this should be approximately the number of drive spindles in the array."
msgstr ""
-"Pour les syst�mes RAID, cela devrait �tre approximativement le nombre de\n"
-"t�tes de lecture du syst�me."
+"Pour les systèmes RAID, cela devrait être approximativement le nombre de\n"
+"têtes de lecture du système."
-#: utils/misc/guc.c:2478
+#: utils/misc/guc.c:2470
msgid "Maximum number of concurrent worker processes."
-msgstr "Nombre maximum de background workers simultan�s."
+msgstr "Nombre maximum de background workers simultanés."
-#: utils/misc/guc.c:2488
+#: utils/misc/guc.c:2480
msgid "Automatic log file rotation will occur after N minutes."
msgstr ""
"La rotation automatique des journaux applicatifs s'effectue toutes les N\n"
"minutes."
-#: utils/misc/guc.c:2499
+#: utils/misc/guc.c:2491
msgid "Automatic log file rotation will occur after N kilobytes."
-msgstr "La rotation automatique des journaux applicatifs s'effectue apr�s N Ko."
+msgstr "La rotation automatique des journaux applicatifs s'effectue après N Ko."
-#: utils/misc/guc.c:2510
+#: utils/misc/guc.c:2502
msgid "Shows the maximum number of function arguments."
msgstr "Affiche le nombre maximum d'arguments de fonction."
-#: utils/misc/guc.c:2521
+#: utils/misc/guc.c:2513
msgid "Shows the maximum number of index keys."
-msgstr "Affiche le nombre maximum de cl�s d'index."
+msgstr "Affiche le nombre maximum de clés d'index."
-#: utils/misc/guc.c:2532
+#: utils/misc/guc.c:2524
msgid "Shows the maximum identifier length."
msgstr "Affiche la longueur maximum d'un identifiant"
-#: utils/misc/guc.c:2543
+#: utils/misc/guc.c:2535
msgid "Shows the size of a disk block."
msgstr "Affiche la taille d'un bloc de disque."
-#: utils/misc/guc.c:2554
+#: utils/misc/guc.c:2546
msgid "Shows the number of pages per disk file."
msgstr "Affiche le nombre de pages par fichier."
-#: utils/misc/guc.c:2565
+#: utils/misc/guc.c:2557
msgid "Shows the block size in the write ahead log."
msgstr "Affiche la taille du bloc dans les journaux de transactions."
-#: utils/misc/guc.c:2576
+#: utils/misc/guc.c:2568
msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt."
-msgstr ""
+msgstr "Initalise le temps à attendre avant de retenter de récupérer un WAL après une tentative infructueuse."
-#: utils/misc/guc.c:2588
+#: utils/misc/guc.c:2580
msgid "Shows the number of pages per write ahead log segment."
msgstr "Affiche le nombre de pages par journal de transactions."
-#: utils/misc/guc.c:2601
+#: utils/misc/guc.c:2593
msgid "Time to sleep between autovacuum runs."
-msgstr "Dur�e d'endormissement entre deux ex�cutions d'autovacuum."
+msgstr "Durée d'endormissement entre deux exécutions d'autovacuum."
-#: utils/misc/guc.c:2611
+#: utils/misc/guc.c:2603
msgid "Minimum number of tuple updates or deletes prior to vacuum."
-msgstr "Nombre minimum de lignes mises � jour ou supprim�es avant le VACUUM."
+msgstr "Nombre minimum de lignes mises à jour ou supprimées avant le VACUUM."
-#: utils/misc/guc.c:2620
+#: utils/misc/guc.c:2612
msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze."
-msgstr "Nombre minimum de lignes ins�r�es, mises � jour ou supprim�es avant un ANALYZE."
+msgstr "Nombre minimum de lignes insérées, mises à jour ou supprimées avant un ANALYZE."
-#: utils/misc/guc.c:2630
+#: utils/misc/guc.c:2622
msgid "Age at which to autovacuum a table to prevent transaction ID wraparound."
msgstr ""
-"�ge � partir duquel l'autovacuum se d�clenche sur une table pour emp�cher la\n"
-"r�initialisation de l'identifiant de transaction"
+"Âge à partir duquel l'autovacuum se déclenche sur une table pour empêcher la\n"
+"réinitialisation de l'identifiant de transaction"
-#: utils/misc/guc.c:2641
+#: utils/misc/guc.c:2633
msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound."
msgstr ""
-"�ge multixact � partir duquel l'autovacuum se d�clenche sur une table pour emp�cher la\n"
-"r�initialisation du multixact"
+"Âge multixact à partir duquel l'autovacuum se déclenche sur une table pour empêcher la\n"
+"réinitialisation du multixact"
-#: utils/misc/guc.c:2651
+#: utils/misc/guc.c:2643
msgid "Sets the maximum number of simultaneously running autovacuum worker processes."
-msgstr "Initialise le nombre maximum de processus autovacuum ex�cut�s simultan�ment."
+msgstr "Initialise le nombre maximum de processus autovacuum exécutés simultanément."
-#: utils/misc/guc.c:2661
+#: utils/misc/guc.c:2653
msgid "Sets the maximum number of parallel processes per executor node."
-msgstr "Initialise le nombre maximum de processus parall�les par n�ud d'ex�cution."
+msgstr "Initialise le nombre maximum de processus parallèles par nœud d'exécution."
-#: utils/misc/guc.c:2671
+#: utils/misc/guc.c:2663
msgid "Sets the maximum memory to be used by each autovacuum worker process."
-msgstr "Initialise la m�moire maximum utilis�e par chaque processus autovacuum worker."
+msgstr "Initialise la mémoire maximum utilisée par chaque processus autovacuum worker."
-#: utils/misc/guc.c:2682
+#: utils/misc/guc.c:2674
msgid "Time before a snapshot is too old to read pages changed after the snapshot was taken."
-msgstr ""
+msgstr "Temps à partir duquel un snapshot est trop ancien pour lire des pages ayant changées après que le snapshot ait été effectué."
-#: utils/misc/guc.c:2683
+#: utils/misc/guc.c:2675
msgid "A value of -1 disables this feature."
-msgstr "Une valeur de -1 d�sactive cette fonctionnalit�."
+msgstr "Une valeur de -1 désactive cette fonctionnalité."
-#: utils/misc/guc.c:2693
+#: utils/misc/guc.c:2685
msgid "Time between issuing TCP keepalives."
-msgstr "Secondes entre l'ex�cution de � TCP keepalives �."
+msgstr "Secondes entre l'exécution de « TCP keepalives »."
-#: utils/misc/guc.c:2694 utils/misc/guc.c:2705
+#: utils/misc/guc.c:2686 utils/misc/guc.c:2697
msgid "A value of 0 uses the system default."
-msgstr "Une valeur de 0 d�sactive la valeur syst�me par d�faut."
+msgstr "Une valeur de 0 désactive la valeur système par défaut."
-#: utils/misc/guc.c:2704
+#: utils/misc/guc.c:2696
msgid "Time between TCP keepalive retransmits."
-msgstr "Secondes entre les retransmissions de � TCP keepalive �."
+msgstr "Secondes entre les retransmissions de « TCP keepalive »."
-#: utils/misc/guc.c:2715
+#: utils/misc/guc.c:2707
msgid "SSL renegotiation is no longer supported; this can only be 0."
-msgstr ""
+msgstr "La renégociation SSL n'est plus supportée; ce paramètre ne peut être positionné qu'à 0."
-#: utils/misc/guc.c:2726
+#: utils/misc/guc.c:2718
msgid "Maximum number of TCP keepalive retransmits."
-msgstr "Nombre maximum de retransmissions de � TCP keepalive �."
+msgstr "Nombre maximum de retransmissions de « TCP keepalive »."
-#: utils/misc/guc.c:2727
+#: utils/misc/guc.c:2719
msgid "This controls the number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default."
msgstr ""
-"Ceci contr�le le nombre de retransmissions keepalive cons�cutives qui\n"
-"peuvent �tre perdues avant qu'une connexion ne soit consid�r�e morte. Une\n"
-"valeur de 0 utilise la valeur par d�faut du syst�me."
+"Ceci contrôle le nombre de retransmissions keepalive consécutives qui\n"
+"peuvent être perdues avant qu'une connexion ne soit considérée morte. Une\n"
+"valeur de 0 utilise la valeur par défaut du système."
-#: utils/misc/guc.c:2738
+#: utils/misc/guc.c:2730
msgid "Sets the maximum allowed result for exact search by GIN."
-msgstr "Configure le nombre maximum de r�sultats lors d'une recherche par GIN."
+msgstr "Configure le nombre maximum de résultats lors d'une recherche par GIN."
-#: utils/misc/guc.c:2749
+#: utils/misc/guc.c:2741
msgid "Sets the planner's assumption about the size of the disk cache."
msgstr "Initialise le sentiment du planificateur sur la taille du cache disque."
-#: utils/misc/guc.c:2750
+#: utils/misc/guc.c:2742
msgid "That is, the portion of the kernel's disk cache that will be used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each."
msgstr ""
-"C'est-�-dire, la portion du cache disque du noyau qui sera utilis� pour les\n"
-"fichiers de donn�es de PostgreSQL. C'est mesur� en pages disque, qui font\n"
+"C'est-à-dire, la portion du cache disque du noyau qui sera utilisé pour les\n"
+"fichiers de données de PostgreSQL. C'est mesuré en pages disque, qui font\n"
"normalement 8 Ko chaque."
-#: utils/misc/guc.c:2763
+#: utils/misc/guc.c:2754
+msgid "Sets the minimum size of relations to be considered for parallel scan."
+msgstr "Initialise la taille mininmum d'une relation pour qu'elle soit considérée pour un parcours parallèle."
+
+#: utils/misc/guc.c:2766
msgid "Shows the server version as an integer."
msgstr "Affiche la version du serveur sous la forme d'un entier."
-#: utils/misc/guc.c:2774
+#: utils/misc/guc.c:2777
msgid "Log the use of temporary files larger than this number of kilobytes."
msgstr ""
"Trace l'utilisation de fichiers temporaires plus gros que ce nombre de\n"
"kilooctets."
-#: utils/misc/guc.c:2775
+#: utils/misc/guc.c:2778
msgid "Zero logs all files. The default is -1 (turning this feature off)."
msgstr ""
-"Z�ro trace toutes les requ�tes. La valeur par d�faut est -1 (d�sactivant\n"
-"cette fonctionnalit�)."
+"Zéro trace toutes les requêtes. La valeur par défaut est -1 (désactivant\n"
+"cette fonctionnalité)."
-#: utils/misc/guc.c:2785
+#: utils/misc/guc.c:2788
msgid "Sets the size reserved for pg_stat_activity.query, in bytes."
-msgstr "Configure la taille r�serv�e pour pg_stat_activity.query, en octets."
+msgstr "Configure la taille réservée pour pg_stat_activity.query, en octets."
-#: utils/misc/guc.c:2800
-#, fuzzy
-#| msgid "Sets the maximum time to wait for WAL replication."
+#: utils/misc/guc.c:2803
msgid "Sets the maximum size of the pending list for GIN index."
-msgstr "Initialise le temps maximum � attendre pour la r�plication des WAL."
+msgstr "Configure la taille maximale de la pending list d'un index GIN"
-#: utils/misc/guc.c:2820
+#: utils/misc/guc.c:2823
msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page."
msgstr ""
-"Initialise l'estimation du planificateur pour le co�t d'une page disque\n"
-"r�cup�r�e s�quentiellement."
+"Initialise l'estimation du planificateur pour le coût d'une page disque\n"
+"récupérée séquentiellement."
-#: utils/misc/guc.c:2830
+#: utils/misc/guc.c:2833
msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page."
msgstr ""
-"Initialise l'estimation du plnnificateur pour le co�t d'une page disque\n"
-"r�cup�r�e non s�quentiellement."
+"Initialise l'estimation du plnnificateur pour le coût d'une page disque\n"
+"récupérée non séquentiellement."
-#: utils/misc/guc.c:2840
+#: utils/misc/guc.c:2843
msgid "Sets the planner's estimate of the cost of processing each tuple (row)."
msgstr ""
-"Initialise l'estimation du planificateur pour le co�t d'ex�cution sur chaque\n"
+"Initialise l'estimation du planificateur pour le coût d'exécution sur chaque\n"
"ligne."
-#: utils/misc/guc.c:2850
+#: utils/misc/guc.c:2853
msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan."
msgstr ""
-"Initialise l'estimation du planificateur pour le co�t de traitement de\n"
-"chaque ligne index�e lors d'un parcours d'index."
+"Initialise l'estimation du planificateur pour le coût de traitement de\n"
+"chaque ligne indexée lors d'un parcours d'index."
-#: utils/misc/guc.c:2860
+#: utils/misc/guc.c:2863
msgid "Sets the planner's estimate of the cost of processing each operator or function call."
msgstr ""
-"Initialise l'estimation du planificateur pour le co�t de traitement de\n"
-"chaque op�rateur ou appel de fonction."
+"Initialise l'estimation du planificateur pour le coût de traitement de\n"
+"chaque opérateur ou appel de fonction."
-#: utils/misc/guc.c:2870
+#: utils/misc/guc.c:2873
msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to master backend."
-msgstr "Initialise l'estimation du planificateur pour le co�t de passage de chaque ligne d'un processus fils vers le processus ma�tre."
+msgstr "Initialise l'estimation du planificateur pour le coût de passage de chaque ligne d'un processus fils vers le processus maître."
-#: utils/misc/guc.c:2880
+#: utils/misc/guc.c:2883
msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query."
-msgstr "Initialise l'estimation du planificateur pour le co�t de d�marrage des processus d'ex�cution de requ�tes parall�les."
+msgstr "Initialise l'estimation du planificateur pour le coût de démarrage des processus d'exécution de requêtes parallèles."
-#: utils/misc/guc.c:2891
+#: utils/misc/guc.c:2894
msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved."
-msgstr "Initialise l'estimation du planificateur de la fraction des lignes d'un curseur � r�cup�rer."
+msgstr "Initialise l'estimation du planificateur de la fraction des lignes d'un curseur à récupérer."
-#: utils/misc/guc.c:2902
+#: utils/misc/guc.c:2905
msgid "GEQO: selective pressure within the population."
-msgstr "GEQO : pression s�lective dans la population."
+msgstr "GEQO : pression sélective dans la population."
-#: utils/misc/guc.c:2912
+#: utils/misc/guc.c:2915
msgid "GEQO: seed for random path selection."
-msgstr "GEQO : graine pour la s�lection du chemin al�atoire."
+msgstr "GEQO : graine pour la sélection du chemin aléatoire."
-#: utils/misc/guc.c:2922
+#: utils/misc/guc.c:2925
msgid "Multiple of the average buffer usage to free per round."
-msgstr "Multiplede l'utilisation moyenne des tampons � lib�rer � chaque tour."
+msgstr "Multiplede l'utilisation moyenne des tampons à libérer à chaque tour."
-#: utils/misc/guc.c:2932
+#: utils/misc/guc.c:2935
msgid "Sets the seed for random-number generation."
-msgstr "Initialise la cl� pour la g�n�ration de nombres al�atoires."
+msgstr "Initialise la clé pour la génération de nombres aléatoires."
-#: utils/misc/guc.c:2943
+#: utils/misc/guc.c:2946
msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."
msgstr ""
-"Nombre de lignes modifi�es ou supprim�es avant d'ex�cuter un VACUUM\n"
+"Nombre de lignes modifiées ou supprimées avant d'exécuter un VACUUM\n"
"(fraction de reltuples)."
-#: utils/misc/guc.c:2952
+#: utils/misc/guc.c:2955
msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."
msgstr ""
-"Nombre de lignes ins�r�es, mises � jour ou supprim�es avant d'analyser\n"
+"Nombre de lignes insérées, mises à jour ou supprimées avant d'analyser\n"
"une fraction de reltuples."
-#: utils/misc/guc.c:2962
+#: utils/misc/guc.c:2965
msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."
msgstr ""
-"Temps pass� � vider les tampons lors du point de v�rification, en tant que\n"
-"fraction de l'intervalle du point de v�rification."
+"Temps passé à vider les tampons lors du point de vérification, en tant que\n"
+"fraction de l'intervalle du point de vérification."
-#: utils/misc/guc.c:2981
+#: utils/misc/guc.c:2984
msgid "Sets the shell command that will be called to archive a WAL file."
-msgstr "La commande shell qui sera appel�e pour archiver un journal de transaction."
+msgstr "La commande shell qui sera appelée pour archiver un journal de transaction."
-#: utils/misc/guc.c:2991
+#: utils/misc/guc.c:2994
msgid "Sets the client's character set encoding."
msgstr "Initialise l'encodage du client."
-#: utils/misc/guc.c:3002
+#: utils/misc/guc.c:3005
msgid "Controls information prefixed to each log line."
-msgstr "Contr�le l'information pr�fix�e sur chaque ligne de trace."
+msgstr "Contrôle l'information préfixée sur chaque ligne de trace."
-#: utils/misc/guc.c:3003
+#: utils/misc/guc.c:3006
msgid "If blank, no prefix is used."
-msgstr "Si vide, aucun pr�fixe n'est utilis�."
+msgstr "Si vide, aucun préfixe n'est utilisé."
-#: utils/misc/guc.c:3012
+#: utils/misc/guc.c:3015
msgid "Sets the time zone to use in log messages."
-msgstr "Initialise le fuseau horaire � utiliser pour les journaux applicatifs."
+msgstr "Initialise le fuseau horaire à utiliser pour les journaux applicatifs."
-#: utils/misc/guc.c:3022
+#: utils/misc/guc.c:3025
msgid "Sets the display format for date and time values."
msgstr "Initialise le format d'affichage des valeurs date et time."
-#: utils/misc/guc.c:3023
+#: utils/misc/guc.c:3026
msgid "Also controls interpretation of ambiguous date inputs."
-msgstr "Contr�le aussi l'interpr�tation des dates ambigues en entr�e."
+msgstr "Contrôle aussi l'interprétation des dates ambigues en entrée."
-#: utils/misc/guc.c:3034
+#: utils/misc/guc.c:3037
msgid "Sets the default tablespace to create tables and indexes in."
-msgstr "Initialise le tablespace par d�faut pour cr�er les tables et index."
+msgstr "Initialise le tablespace par défaut pour créer les tables et index."
-#: utils/misc/guc.c:3035
+#: utils/misc/guc.c:3038
msgid "An empty string selects the database's default tablespace."
-msgstr "Une cha�ne vide s�lectionne le tablespace par d�faut de la base de donn�es."
+msgstr "Une chaîne vide sélectionne le tablespace par défaut de la base de données."
-#: utils/misc/guc.c:3045
+#: utils/misc/guc.c:3048
msgid "Sets the tablespace(s) to use for temporary tables and sort files."
msgstr ""
-"Initialise le(s) tablespace(s) � utiliser pour les tables temporaires et les\n"
+"Initialise le(s) tablespace(s) à utiliser pour les tables temporaires et les\n"
"fichiers de tri."
-#: utils/misc/guc.c:3056
+#: utils/misc/guc.c:3059
msgid "Sets the path for dynamically loadable modules."
msgstr "Initialise le chemin des modules chargeables dynamiquement."
-#: utils/misc/guc.c:3057
+#: utils/misc/guc.c:3060
msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file."
msgstr ""
-"Si un module chargeable dynamiquement a besoin d'�tre ouvert et que le nom\n"
-"sp�cifi� n'a pas une composante r�pertoire (c'est-�-dire que le nom ne\n"
-"contient pas un '/'), le syst�me cherche le fichier sp�cifi� sur ce chemin."
+"Si un module chargeable dynamiquement a besoin d'être ouvert et que le nom\n"
+"spécifié n'a pas une composante répertoire (c'est-à-dire que le nom ne\n"
+"contient pas un '/'), le système cherche le fichier spécifié sur ce chemin."
-#: utils/misc/guc.c:3070
+#: utils/misc/guc.c:3073
msgid "Sets the location of the Kerberos server key file."
-msgstr "Initalise l'emplacement du fichier de la cl� serveur pour Kerberos."
+msgstr "Initalise l'emplacement du fichier de la clé serveur pour Kerberos."
-#: utils/misc/guc.c:3081
+#: utils/misc/guc.c:3084
msgid "Sets the Bonjour service name."
msgstr "Initialise le nom du service Bonjour."
-#: utils/misc/guc.c:3093
+#: utils/misc/guc.c:3096
msgid "Shows the collation order locale."
msgstr "Affiche la locale de tri et de groupement."
-#: utils/misc/guc.c:3104
+#: utils/misc/guc.c:3107
msgid "Shows the character classification and case conversion locale."
-msgstr "Affiche la classification des caract�res et la locale de conversions."
+msgstr "Affiche la classification des caractères et la locale de conversions."
-#: utils/misc/guc.c:3115
+#: utils/misc/guc.c:3118
msgid "Sets the language in which messages are displayed."
-msgstr "Initialise le langage dans lequel les messages sont affich�s."
+msgstr "Initialise le langage dans lequel les messages sont affichés."
-#: utils/misc/guc.c:3125
+#: utils/misc/guc.c:3128
msgid "Sets the locale for formatting monetary amounts."
-msgstr "Initialise la locale pour le formattage des montants mon�taires."
+msgstr "Initialise la locale pour le formattage des montants monétaires."
-#: utils/misc/guc.c:3135
+#: utils/misc/guc.c:3138
msgid "Sets the locale for formatting numbers."
msgstr "Initialise la locale pour formater les nombres."
-#: utils/misc/guc.c:3145
+#: utils/misc/guc.c:3148
msgid "Sets the locale for formatting date and time values."
msgstr "Initialise la locale pour formater les valeurs date et time."
-#: utils/misc/guc.c:3155
+#: utils/misc/guc.c:3158
msgid "Lists shared libraries to preload into each backend."
-msgstr "Liste les biblioth�ques partag�es � pr�charger dans chaque processus serveur."
+msgstr "Liste les bibliothèques partagées à précharger dans chaque processus serveur."
-#: utils/misc/guc.c:3166
+#: utils/misc/guc.c:3169
msgid "Lists shared libraries to preload into server."
-msgstr "Liste les biblioth�ques partag�es � pr�charger dans le serveur."
+msgstr "Liste les bibliothèques partagées à précharger dans le serveur."
-#: utils/misc/guc.c:3177
+#: utils/misc/guc.c:3180
msgid "Lists unprivileged shared libraries to preload into each backend."
-msgstr "Liste les biblioth�ques partag�es non privil�gi�es � pr�charger dans chaque processus serveur."
+msgstr "Liste les bibliothèques partagées non privilégiées à précharger dans chaque processus serveur."
-#: utils/misc/guc.c:3188
+#: utils/misc/guc.c:3191
msgid "Sets the schema search order for names that are not schema-qualified."
msgstr ""
-"Initialise l'ordre de recherche des sch�mas pour les noms qui ne pr�cisent\n"
-"pas le sch�ma."
+"Initialise l'ordre de recherche des schémas pour les noms qui ne précisent\n"
+"pas le schéma."
-#: utils/misc/guc.c:3200
+#: utils/misc/guc.c:3203
msgid "Sets the server (database) character set encoding."
-msgstr "Initialise le codage des caract�res pour le serveur (base de donn�es)."
+msgstr "Initialise le codage des caractères pour le serveur (base de données)."
-#: utils/misc/guc.c:3212
+#: utils/misc/guc.c:3215
msgid "Shows the server version."
msgstr "Affiche la version du serveur."
-#: utils/misc/guc.c:3224
+#: utils/misc/guc.c:3227
msgid "Sets the current role."
-msgstr "Initialise le r�le courant."
+msgstr "Initialise le rôle courant."
-#: utils/misc/guc.c:3236
+#: utils/misc/guc.c:3239
msgid "Sets the session user name."
msgstr "Initialise le nom de l'utilisateur de la session."
-#: utils/misc/guc.c:3247
+#: utils/misc/guc.c:3250
msgid "Sets the destination for server log output."
msgstr "Initialise la destination des journaux applicatifs du serveur."
-#: utils/misc/guc.c:3248
+#: utils/misc/guc.c:3251
msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", and \"eventlog\", depending on the platform."
msgstr ""
-"Les valeurs valides sont une combinaison de � stderr �, � syslog �,\n"
-"� csvlog � et � eventlog �, suivant la plateforme."
+"Les valeurs valides sont une combinaison de « stderr », « syslog »,\n"
+"« csvlog » et « eventlog », suivant la plateforme."
-#: utils/misc/guc.c:3259
+#: utils/misc/guc.c:3262
msgid "Sets the destination directory for log files."
-msgstr "Initialise le r�pertoire de destination pour les journaux applicatifs."
+msgstr "Initialise le répertoire de destination pour les journaux applicatifs."
-#: utils/misc/guc.c:3260
+#: utils/misc/guc.c:3263
msgid "Can be specified as relative to the data directory or as absolute path."
-msgstr "Accepte un chemin relatif ou absolu pour le r�pertoire des donn�es."
+msgstr "Accepte un chemin relatif ou absolu pour le répertoire des données."
-#: utils/misc/guc.c:3270
+#: utils/misc/guc.c:3273
msgid "Sets the file name pattern for log files."
-msgstr "Initialise le mod�le de nom de fichiers pour les journaux applicatifs."
+msgstr "Initialise le modèle de nom de fichiers pour les journaux applicatifs."
-#: utils/misc/guc.c:3281
+#: utils/misc/guc.c:3284
msgid "Sets the program name used to identify PostgreSQL messages in syslog."
msgstr ""
-"Initialise le nom du programme utilis� pour identifier les messages de\n"
+"Initialise le nom du programme utilisé pour identifier les messages de\n"
"PostgreSQL dans syslog."
-#: utils/misc/guc.c:3292
+#: utils/misc/guc.c:3295
msgid "Sets the application name used to identify PostgreSQL messages in the event log."
msgstr ""
-"Initialise le nom de l'application, utilis� pour identifier les messages de\n"
+"Initialise le nom de l'application, utilisé pour identifier les messages de\n"
"PostgreSQL dans eventlog."
-#: utils/misc/guc.c:3303
+#: utils/misc/guc.c:3306
msgid "Sets the time zone for displaying and interpreting time stamps."
-msgstr "Initialise la zone horaire pour afficher et interpr�ter les dates/heures."
+msgstr "Initialise la zone horaire pour afficher et interpréter les dates/heures."
-#: utils/misc/guc.c:3313
+#: utils/misc/guc.c:3316
msgid "Selects a file of time zone abbreviations."
-msgstr "S�lectionne un fichier contenant les abr�viations des fuseaux horaires."
+msgstr "Sélectionne un fichier contenant les abréviations des fuseaux horaires."
-#: utils/misc/guc.c:3323
+#: utils/misc/guc.c:3326
msgid "Sets the current transaction's isolation level."
msgstr "Initialise le niveau d'isolation de la transaction courante."
-#: utils/misc/guc.c:3334
+#: utils/misc/guc.c:3337
msgid "Sets the owning group of the Unix-domain socket."
msgstr "Initialise le groupe d'appartenance du socket domaine Unix."
-#: utils/misc/guc.c:3335
+#: utils/misc/guc.c:3338
msgid "The owning user of the socket is always the user that starts the server."
-msgstr "Le propri�taire du socket est toujours l'utilisateur qui a lanc� le serveur."
+msgstr "Le propriétaire du socket est toujours l'utilisateur qui a lancé le serveur."
-#: utils/misc/guc.c:3345
+#: utils/misc/guc.c:3348
msgid "Sets the directories where Unix-domain sockets will be created."
-msgstr "Initialise les r�pertoires o� les sockets de domaine Unix seront cr��s."
+msgstr "Initialise les répertoires où les sockets de domaine Unix seront créés."
-#: utils/misc/guc.c:3360
+#: utils/misc/guc.c:3363
msgid "Sets the host name or IP address(es) to listen to."
-msgstr "Initialise le nom de l'h�te ou l'adresse IP � �couter."
+msgstr "Initialise le nom de l'hôte ou l'adresse IP à écouter."
-#: utils/misc/guc.c:3375
+#: utils/misc/guc.c:3378
msgid "Sets the server's data directory."
-msgstr "Initialise le r�pertoire des donn�es du serveur."
+msgstr "Initialise le répertoire des données du serveur."
-#: utils/misc/guc.c:3386
+#: utils/misc/guc.c:3389
msgid "Sets the server's main configuration file."
msgstr "Voir le fichier de configuration principal du serveur."
-#: utils/misc/guc.c:3397
+#: utils/misc/guc.c:3400
msgid "Sets the server's \"hba\" configuration file."
-msgstr "Initialise le fichier de configuration � hba � du serveur."
+msgstr "Initialise le fichier de configuration « hba » du serveur."
-#: utils/misc/guc.c:3408
+#: utils/misc/guc.c:3411
msgid "Sets the server's \"ident\" configuration file."
-msgstr "Initialise le fichier de configuration � ident � du serveur."
+msgstr "Initialise le fichier de configuration « ident » du serveur."
-#: utils/misc/guc.c:3419
+#: utils/misc/guc.c:3422
msgid "Writes the postmaster PID to the specified file."
-msgstr "�crit le PID du postmaster PID dans le fichier sp�cifi�."
+msgstr "Écrit le PID du postmaster PID dans le fichier spécifié."
-#: utils/misc/guc.c:3430
+#: utils/misc/guc.c:3433
msgid "Location of the SSL server certificate file."
msgstr "Emplacement du fichier du certificat serveur SSL."
-#: utils/misc/guc.c:3440
+#: utils/misc/guc.c:3443
msgid "Location of the SSL server private key file."
-msgstr "Emplacement du fichier de la cl� priv�e SSL du serveur."
+msgstr "Emplacement du fichier de la clé privée SSL du serveur."
-#: utils/misc/guc.c:3450
+#: utils/misc/guc.c:3453
msgid "Location of the SSL certificate authority file."
-msgstr "Emplacement du fichier du certificat autorit� SSL."
+msgstr "Emplacement du fichier du certificat autorité SSL."
-#: utils/misc/guc.c:3460
+#: utils/misc/guc.c:3463
msgid "Location of the SSL certificate revocation list file."
-msgstr "Emplacement du fichier de liste de r�vocation des certificats SSL."
+msgstr "Emplacement du fichier de liste de révocation des certificats SSL."
-#: utils/misc/guc.c:3470
+#: utils/misc/guc.c:3473
msgid "Writes temporary statistics files to the specified directory."
-msgstr "�crit les fichiers statistiques temporaires dans le r�pertoire indiqu�."
+msgstr "Écrit les fichiers statistiques temporaires dans le répertoire indiqué."
-#: utils/misc/guc.c:3481
+#: utils/misc/guc.c:3484
msgid "Number of synchronous standbys and list of names of potential synchronous ones."
msgstr "Nombre de standbys synchrones et liste des noms des synchrones potentiels."
-#: utils/misc/guc.c:3492
+#: utils/misc/guc.c:3495
msgid "Sets default text search configuration."
-msgstr "Initialise le configuration par d�faut de la recherche plein texte"
+msgstr "Initialise le configuration par défaut de la recherche plein texte"
-#: utils/misc/guc.c:3502
+#: utils/misc/guc.c:3505
msgid "Sets the list of allowed SSL ciphers."
-msgstr "Initialise la liste des chiffrements SSL autoris�s."
+msgstr "Initialise la liste des chiffrements SSL autorisés."
-#: utils/misc/guc.c:3517
+#: utils/misc/guc.c:3520
msgid "Sets the curve to use for ECDH."
-msgstr "Initialise la courbe � utiliser pour ECDH."
+msgstr "Initialise la courbe à utiliser pour ECDH."
-#: utils/misc/guc.c:3532
+#: utils/misc/guc.c:3535
msgid "Sets the application name to be reported in statistics and logs."
-msgstr "Configure le nom de l'application � indiquer dans les statistiques et les journaux."
+msgstr "Configure le nom de l'application à indiquer dans les statistiques et les journaux."
-#: utils/misc/guc.c:3543
+#: utils/misc/guc.c:3546
msgid "Sets the name of the cluster, which is included in the process title."
-msgstr ""
+msgstr "Configure le nom du cluster, qui est inclus dans le titre du processus."
-#: utils/misc/guc.c:3563
+#: utils/misc/guc.c:3566
msgid "Sets whether \"\\'\" is allowed in string literals."
-msgstr "Indique si � \\' � est autoris� dans une constante de cha�ne."
+msgstr "Indique si « \\' » est autorisé dans une constante de chaîne."
-#: utils/misc/guc.c:3573
+#: utils/misc/guc.c:3576
msgid "Sets the output format for bytea."
msgstr "Initialise le format de sortie pour bytea."
-#: utils/misc/guc.c:3583
+#: utils/misc/guc.c:3586
msgid "Sets the message levels that are sent to the client."
-msgstr "Initialise les niveaux de message envoy�s au client."
+msgstr "Initialise les niveaux de message envoyés au client."
-#: utils/misc/guc.c:3584 utils/misc/guc.c:3637 utils/misc/guc.c:3648 utils/misc/guc.c:3714
+#: utils/misc/guc.c:3587 utils/misc/guc.c:3640 utils/misc/guc.c:3651 utils/misc/guc.c:3717
msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent."
msgstr ""
"Chaque niveau inclut les niveaux qui suivent. Plus loin sera le niveau,\n"
-"moindre sera le nombre de messages envoy�s."
+"moindre sera le nombre de messages envoyés."
-#: utils/misc/guc.c:3594
+#: utils/misc/guc.c:3597
msgid "Enables the planner to use constraints to optimize queries."
-msgstr "Active l'utilisation des contraintes par le planificateur pour optimiser les requ�tes."
+msgstr "Active l'utilisation des contraintes par le planificateur pour optimiser les requêtes."
-#: utils/misc/guc.c:3595
+#: utils/misc/guc.c:3598
msgid "Table scans will be skipped if their constraints guarantee that no rows match the query."
msgstr ""
-"Les parcours de tables seront ignor�s si leur contraintes garantissent\n"
-"qu'aucune ligne ne correspond � la requ�te."
+"Les parcours de tables seront ignorés si leur contraintes garantissent\n"
+"qu'aucune ligne ne correspond à la requête."
-#: utils/misc/guc.c:3605
+#: utils/misc/guc.c:3608
msgid "Sets the transaction isolation level of each new transaction."
msgstr "Initialise le niveau d'isolation des transactions pour chaque nouvelle transaction."
-#: utils/misc/guc.c:3615
+#: utils/misc/guc.c:3618
msgid "Sets the display format for interval values."
msgstr "Initialise le format d'affichage des valeurs interval."
-#: utils/misc/guc.c:3626
+#: utils/misc/guc.c:3629
msgid "Sets the verbosity of logged messages."
-msgstr "Initialise la verbosit� des messages trac�s."
+msgstr "Initialise la verbosité des messages tracés."
-#: utils/misc/guc.c:3636
+#: utils/misc/guc.c:3639
msgid "Sets the message levels that are logged."
-msgstr "Initialise les niveaux de messages trac�s."
+msgstr "Initialise les niveaux de messages tracés."
-#: utils/misc/guc.c:3647
+#: utils/misc/guc.c:3650
msgid "Causes all statements generating error at or above this level to be logged."
msgstr ""
-"G�n�re une trace pour toutes les instructions qui produisent une erreur de\n"
+"Génère une trace pour toutes les instructions qui produisent une erreur de\n"
"ce niveau ou de niveaux plus importants."
-#: utils/misc/guc.c:3658
+#: utils/misc/guc.c:3661
msgid "Sets the type of statements logged."
-msgstr "Initialise le type d'instructions trac�es."
+msgstr "Initialise le type d'instructions tracées."
-#: utils/misc/guc.c:3668
+#: utils/misc/guc.c:3671
msgid "Sets the syslog \"facility\" to be used when syslog enabled."
msgstr ""
-"Initialise le niveau (� facility �) de syslog � utilis� lors de l'activation\n"
+"Initialise le niveau (« facility ») de syslog à utilisé lors de l'activation\n"
"de syslog."
-#: utils/misc/guc.c:3683
+#: utils/misc/guc.c:3686
msgid "Sets the session's behavior for triggers and rewrite rules."
msgstr ""
-"Configure le comportement des sessions pour les triggers et les r�gles de\n"
-"r�-�criture."
+"Configure le comportement des sessions pour les triggers et les règles de\n"
+"ré-écriture."
-#: utils/misc/guc.c:3693
+#: utils/misc/guc.c:3696
msgid "Sets the current transaction's synchronization level."
msgstr "Initialise le niveau d'isolation de la transaction courante."
-#: utils/misc/guc.c:3703
+#: utils/misc/guc.c:3706
msgid "Allows archiving of WAL files using archive_command."
msgstr "Autorise l'archivage des journaux de transactions en utilisant archive_command."
-#: utils/misc/guc.c:3713
+#: utils/misc/guc.c:3716
msgid "Enables logging of recovery-related debugging information."
-msgstr "Active les traces sur les informations de d�bogage relatives � la restauration."
+msgstr "Active les traces sur les informations de débogage relatives à la restauration."
-#: utils/misc/guc.c:3729
+#: utils/misc/guc.c:3732
msgid "Collects function-level statistics on database activity."
-msgstr "R�cup�re les statistiques niveau fonction sur l'activit� de la base de donn�es."
+msgstr "Récupère les statistiques niveau fonction sur l'activité de la base de données."
-#: utils/misc/guc.c:3739
+#: utils/misc/guc.c:3742
msgid "Set the level of information written to the WAL."
-msgstr "Configure le niveau des informations �crites dans les journaux de transactions."
+msgstr "Configure le niveau des informations écrites dans les journaux de transactions."
-#: utils/misc/guc.c:3749
+#: utils/misc/guc.c:3752
msgid "Selects the dynamic shared memory implementation used."
-msgstr "S�lectionne l'impl�mentation de la m�moire partag�e dynamique."
+msgstr "Sélectionne l'implémentation de la mémoire partagée dynamique."
-#: utils/misc/guc.c:3759
+#: utils/misc/guc.c:3762
msgid "Selects the method used for forcing WAL updates to disk."
msgstr ""
-"S�lectionne la m�thode utilis�e pour forcer la mise � jour des journaux de\n"
+"Sélectionne la méthode utilisée pour forcer la mise à jour des journaux de\n"
"transactions sur le disque."
-#: utils/misc/guc.c:3769
+#: utils/misc/guc.c:3772
msgid "Sets how binary values are to be encoded in XML."
-msgstr "Configure comment les valeurs binaires seront cod�es en XML."
+msgstr "Configure comment les valeurs binaires seront codées en XML."
-#: utils/misc/guc.c:3779
+#: utils/misc/guc.c:3782
msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments."
msgstr ""
-"Configure si les donn�es XML dans des op�rations d'analyse et de\n"
-"s�rialisation implicite doivent �tre consid�r�es comme des documents\n"
+"Configure si les données XML dans des opérations d'analyse et de\n"
+"sérialisation implicite doivent être considérées comme des documents\n"
"ou des fragments de contenu."
-#: utils/misc/guc.c:3790
+#: utils/misc/guc.c:3793
msgid "Use of huge pages on Linux."
msgstr "Utilisation des HugePages sur Linux."
-#: utils/misc/guc.c:3800
+#: utils/misc/guc.c:3803
msgid "Forces use of parallel query facilities."
-msgstr ""
+msgstr "Force l'utilisation des fonctionnalités de requête parallèle."
-#: utils/misc/guc.c:3801
+#: utils/misc/guc.c:3804
msgid "If possible, run query using a parallel worker and with parallel restrictions."
-msgstr ""
+msgstr "Si possible, exécute des requêtes utilisant des processus parallèles et avec les restrictions parallèles."
-#: utils/misc/guc.c:4601
+#: utils/misc/guc.c:4604
#, c-format
msgid "%s: could not access directory \"%s\": %s\n"
-msgstr "%s : n'a pas pu acc�der au r�pertoire � %s � : %s\n"
+msgstr "%s : n'a pas pu accéder au répertoire « %s » : %s\n"
-#: utils/misc/guc.c:4606
+#: utils/misc/guc.c:4609
#, c-format
msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n"
-msgstr "Lancer initdb ou pg_basebackup pour initialiser un r�pertoire de donn�es PostgreSQL.\n"
+msgstr "Lancer initdb ou pg_basebackup pour initialiser un répertoire de données PostgreSQL.\n"
-#: utils/misc/guc.c:4626
+#: utils/misc/guc.c:4629
#, c-format
msgid ""
"%s does not know where to find the server configuration file.\n"
"You must specify the --config-file or -D invocation option or set the PGDATA environment variable.\n"
msgstr ""
-"%s ne sait pas o� trouver le fichier de configuration du serveur.\n"
-"Vous devez soit sp�cifier l'option --config-file soit sp�cifier l'option -D\n"
+"%s ne sait pas où trouver le fichier de configuration du serveur.\n"
+"Vous devez soit spécifier l'option --config-file soit spécifier l'option -D\n"
"soit initialiser la variable d'environnement.\n"
-#: utils/misc/guc.c:4645
+#: utils/misc/guc.c:4648
#, c-format
msgid "%s: could not access the server configuration file \"%s\": %s\n"
-msgstr "%s : n'a pas pu acc�der au fichier de configuration � %s � : %s\n"
+msgstr "%s : n'a pas pu accéder au fichier de configuration « %s » : %s\n"
-#: utils/misc/guc.c:4671
+#: utils/misc/guc.c:4674
#, c-format
msgid ""
"%s does not know where to find the database system data.\n"
"This can be specified as \"data_directory\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n"
msgstr ""
-"%s ne sait pas o� trouver les donn�es du syst�me de bases de donn�es.\n"
-"Il est configurable avec � data_directory � dans � %s � ou avec l'option -D\n"
+"%s ne sait pas où trouver les données du système de bases de données.\n"
+"Il est configurable avec « data_directory » dans « %s » ou avec l'option -D\n"
"ou encore avec la variable d'environnement PGDATA.\n"
-#: utils/misc/guc.c:4719
+#: utils/misc/guc.c:4722
#, c-format
msgid ""
"%s does not know where to find the \"hba\" configuration file.\n"
"This can be specified as \"hba_file\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n"
msgstr ""
-"%s ne sait pas o� trouver le fichier de configuration � hba �.\n"
-"Il est configurable avec � hba_file � dans � %s � ou avec l'option -D ou\n"
+"%s ne sait pas où trouver le fichier de configuration « hba ».\n"
+"Il est configurable avec « hba_file » dans « %s » ou avec l'option -D ou\n"
"encore avec la variable d'environnement PGDATA.\n"
-#: utils/misc/guc.c:4742
+#: utils/misc/guc.c:4745
#, c-format
msgid ""
"%s does not know where to find the \"ident\" configuration file.\n"
"This can be specified as \"ident_file\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n"
msgstr ""
-"%s ne sait pas o� trouver le fichier de configuration � hba �.\n"
-"Il est configurable avec � ident_file � dans � %s � ou avec l'option -D ou\n"
+"%s ne sait pas où trouver le fichier de configuration « hba ».\n"
+"Il est configurable avec « ident_file » dans « %s » ou avec l'option -D ou\n"
"encore avec la variable d'environnement PGDATA.\n"
-#: utils/misc/guc.c:5416 utils/misc/guc.c:5463
+#: utils/misc/guc.c:5419 utils/misc/guc.c:5466
msgid "Value exceeds integer range."
-msgstr "La valeur d�passe l'�chelle des entiers."
+msgstr "La valeur dépasse l'échelle des entiers."
-#: utils/misc/guc.c:5686
+#: utils/misc/guc.c:5689
#, c-format
msgid "parameter \"%s\" requires a numeric value"
-msgstr "le param�tre � %s � requiert une valeur num�rique"
+msgstr "le paramètre « %s » requiert une valeur numérique"
-#: utils/misc/guc.c:5695
+#: utils/misc/guc.c:5698
#, c-format
msgid "%g is outside the valid range for parameter \"%s\" (%g .. %g)"
-msgstr "%g est en dehors des limites valides pour le param�tre � %s � (%g .. %g)"
+msgstr "%g est en dehors des limites valides pour le paramètre « %s » (%g .. %g)"
-#: utils/misc/guc.c:5848 utils/misc/guc.c:7190
+#: utils/misc/guc.c:5851 utils/misc/guc.c:7194
#, c-format
msgid "cannot set parameters during a parallel operation"
-msgstr "ne peut pas configurer les param�tres lors d'une op�ration parall�le"
+msgstr "ne peut pas configurer les paramètres lors d'une opération parallèle"
-#: utils/misc/guc.c:5855 utils/misc/guc.c:6605 utils/misc/guc.c:6657 utils/misc/guc.c:7018 utils/misc/guc.c:7778 utils/misc/guc.c:7946 utils/misc/guc.c:9603
+#: utils/misc/guc.c:5858 utils/misc/guc.c:6609 utils/misc/guc.c:6661 utils/misc/guc.c:7022 utils/misc/guc.c:7782 utils/misc/guc.c:7950 utils/misc/guc.c:9625
#, c-format
msgid "unrecognized configuration parameter \"%s\""
-msgstr "param�tre de configuration � %s � non reconnu"
+msgstr "paramètre de configuration « %s » non reconnu"
-#: utils/misc/guc.c:5870 utils/misc/guc.c:7030
+#: utils/misc/guc.c:5873 utils/misc/guc.c:7034
#, c-format
msgid "parameter \"%s\" cannot be changed"
-msgstr "le param�tre � %s � ne peut pas �tre chang�"
+msgstr "le paramètre « %s » ne peut pas être changé"
-#: utils/misc/guc.c:5903
+#: utils/misc/guc.c:5906
#, c-format
msgid "parameter \"%s\" cannot be changed now"
-msgstr "le param�tre � %s � ne peut pas �tre modifi� maintenant"
+msgstr "le paramètre « %s » ne peut pas être modifié maintenant"
-#: utils/misc/guc.c:5921 utils/misc/guc.c:5966 utils/misc/guc.c:9619
+#: utils/misc/guc.c:5924 utils/misc/guc.c:5970 utils/misc/guc.c:9641
#, c-format
msgid "permission denied to set parameter \"%s\""
-msgstr "droit refus� pour initialiser le param�tre � %s �"
+msgstr "droit refusé pour initialiser le paramètre « %s »"
-#: utils/misc/guc.c:5956
+#: utils/misc/guc.c:5960
#, c-format
msgid "parameter \"%s\" cannot be set after connection start"
-msgstr "le param�tre � %s � ne peut pas �tre initialis� apr�s le lancement du serveur"
+msgstr "le paramètre « %s » ne peut pas être initialisé après le lancement du serveur"
-#: utils/misc/guc.c:6004
+#: utils/misc/guc.c:6008
#, c-format
msgid "cannot set parameter \"%s\" within security-definer function"
msgstr ""
-"ne peut pas configurer le param�tre � %s � � l'int�rieur d'une fonction\n"
+"ne peut pas configurer le paramètre « %s » à l'intérieur d'une fonction\n"
"SECURITY DEFINER"
-#: utils/misc/guc.c:6613 utils/misc/guc.c:6661 utils/misc/guc.c:7952
+#: utils/misc/guc.c:6617 utils/misc/guc.c:6665 utils/misc/guc.c:7956
#, c-format
msgid "must be superuser to examine \"%s\""
-msgstr "doit �tre super-utilisateur pour examiner � %s �"
+msgstr "doit être super-utilisateur pour examiner « %s »"
-#: utils/misc/guc.c:6727
+#: utils/misc/guc.c:6731
#, c-format
msgid "SET %s takes only one argument"
msgstr "SET %s prend un seul argument"
-#: utils/misc/guc.c:6978
+#: utils/misc/guc.c:6982
#, c-format
msgid "must be superuser to execute ALTER SYSTEM command"
-msgstr "doit �tre super-utilisateur pour ex�cuter la commande ALTER SYSTEM"
+msgstr "doit être super-utilisateur pour exécuter la commande ALTER SYSTEM"
-#: utils/misc/guc.c:7063
+#: utils/misc/guc.c:7067
#, c-format
msgid "parameter value for ALTER SYSTEM must not contain a newline"
-msgstr ""
+msgstr "la valeur du paramètre pour ALTER SYSTEM ne doit pas contenir de caractère de retour à la ligne"
-#: utils/misc/guc.c:7108
+#: utils/misc/guc.c:7112
#, c-format
msgid "could not parse contents of file \"%s\""
-msgstr "n'a pas pu analyser le contenu du fichier � %s �"
+msgstr "n'a pas pu analyser le contenu du fichier « %s »"
-#: utils/misc/guc.c:7266
+#: utils/misc/guc.c:7270
#, c-format
msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented"
-msgstr "SET LOCAL TRANSACTION SNAPSHOT n'est pas impl�ment�"
+msgstr "SET LOCAL TRANSACTION SNAPSHOT n'est pas implémenté"
-#: utils/misc/guc.c:7351
+#: utils/misc/guc.c:7355
#, c-format
msgid "SET requires parameter name"
-msgstr "SET requiert le nom du param�tre"
+msgstr "SET requiert le nom du paramètre"
-#: utils/misc/guc.c:7475
+#: utils/misc/guc.c:7479
#, c-format
msgid "attempt to redefine parameter \"%s\""
-msgstr "tentative de red�finition du param�tre � %s �"
+msgstr "tentative de redéfinition du paramètre « %s »"
-#: utils/misc/guc.c:9236
+#: utils/misc/guc.c:9258
#, c-format
msgid "parameter \"%s\" could not be set"
-msgstr "le param�tre � %s � n'a pas pu �tre configur�"
+msgstr "le paramètre « %s » n'a pas pu être configuré"
-#: utils/misc/guc.c:9323
+#: utils/misc/guc.c:9345
#, c-format
msgid "could not parse setting for parameter \"%s\""
-msgstr "n'a pas pu analyser la configuration du param�tre � %s �"
+msgstr "n'a pas pu analyser la configuration du paramètre « %s »"
-#: utils/misc/guc.c:9681 utils/misc/guc.c:9715
+#: utils/misc/guc.c:9703 utils/misc/guc.c:9737
#, c-format
msgid "invalid value for parameter \"%s\": %d"
-msgstr "valeur invalide pour le param�tre � %s � : %d"
+msgstr "valeur invalide pour le paramètre « %s » : %d"
-#: utils/misc/guc.c:9749
+#: utils/misc/guc.c:9771
#, c-format
msgid "invalid value for parameter \"%s\": %g"
-msgstr "valeur invalide pour le param�tre � %s � : %g"
+msgstr "valeur invalide pour le paramètre « %s » : %g"
-#: utils/misc/guc.c:9939
+#: utils/misc/guc.c:9961
#, c-format
msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session."
-msgstr "� temp_buffers � ne peut pas �tre modifi� apr�s que des tables temporaires aient �t� utilis�es dans la session."
+msgstr "« temp_buffers » ne peut pas être modifié après que des tables temporaires aient été utilisées dans la session."
-#: utils/misc/guc.c:9951
+#: utils/misc/guc.c:9973
#, c-format
msgid "Bonjour is not supported by this build"
-msgstr "Bonjour n'est pas support� dans cette installation"
+msgstr "Bonjour n'est pas supporté dans cette installation"
-#: utils/misc/guc.c:9964
+#: utils/misc/guc.c:9986
#, c-format
msgid "SSL is not supported by this build"
-msgstr "SSL n'est pas support� dans cette installation"
+msgstr "SSL n'est pas supporté dans cette installation"
-#: utils/misc/guc.c:9976
+#: utils/misc/guc.c:9998
#, c-format
msgid "Cannot enable parameter when \"log_statement_stats\" is true."
-msgstr "Ne peut pas activer le param�tre avec � log_statement_stats � � true."
+msgstr "Ne peut pas activer le paramètre avec « log_statement_stats » à true."
-#: utils/misc/guc.c:9988
+#: utils/misc/guc.c:10010
#, c-format
msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true."
msgstr ""
-"Ne peut pas activer � log_statement_stats � lorsque � log_parser_stats �,\n"
-"� log_planner_stats � ou � log_executor_stats � est true."
+"Ne peut pas activer « log_statement_stats » lorsque « log_parser_stats »,\n"
+"« log_planner_stats » ou « log_executor_stats » est true."
#: utils/misc/help_config.c:131
#, c-format
msgid "internal error: unrecognized run-time parameter type\n"
-msgstr "erreur interne : type de param�tre d'ex�cution non reconnu\n"
+msgstr "erreur interne : type de paramètre d'exécution non reconnu\n"
#: utils/misc/pg_config.c:61
#, c-format
msgid "query-specified return tuple and function return type are not compatible"
-msgstr ""
+msgstr "une ligne de sortie spécifiée à la requête et un type de sortie de fonction ne sont pas compatibles"
#: utils/misc/rls.c:127
#, c-format
msgid "query would be affected by row-level security policy for table \"%s\""
-msgstr "la requ�te pourrait �tre affect�e par une politique de s�curit� au niveau ligne pour la table � %s �"
+msgstr "la requête pourrait être affectée par une politique de sécurité au niveau ligne pour la table « %s »"
#: utils/misc/rls.c:129
#, c-format
msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY."
-msgstr "Pour d�sactiver la politique pour le propri�taire de la table, utilisez ALTER TABLE NO FORCE ROW LEVEL SECURITY."
+msgstr "Pour désactiver la politique pour le propriétaire de la table, utilisez ALTER TABLE NO FORCE ROW LEVEL SECURITY."
#: utils/misc/timeout.c:388
#, c-format
@@ -23579,145 +23535,145 @@ msgstr "ne peut pas ajouter plus de raisons de timeout"
#, c-format
msgid "time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d"
msgstr ""
-"l'abr�viation � %s � du fuseau horaire est trop long (maximum %d caract�res)\n"
-"dans le fichier de fuseaux horaires � %s �, ligne %d"
+"l'abréviation « %s » du fuseau horaire est trop long (maximum %d caractères)\n"
+"dans le fichier de fuseaux horaires « %s », ligne %d"
#: utils/misc/tzparser.c:73
#, c-format
msgid "time zone offset %d is out of range in time zone file \"%s\", line %d"
msgstr ""
-"le d�calage %d du fuseau horaire est en dehors des limites dans le fichier\n"
-"des fuseaux horaires � %s �, ligne %d"
+"le décalage %d du fuseau horaire est en dehors des limites dans le fichier\n"
+"des fuseaux horaires « %s », ligne %d"
#: utils/misc/tzparser.c:112
#, c-format
msgid "missing time zone abbreviation in time zone file \"%s\", line %d"
-msgstr "abr�viation du fuseau horaire manquant dans le fichier � %s �, ligne %d"
+msgstr "abréviation du fuseau horaire manquant dans le fichier « %s », ligne %d"
#: utils/misc/tzparser.c:121
#, c-format
msgid "missing time zone offset in time zone file \"%s\", line %d"
-msgstr "d�calage du fuseau horaire manquant dans le fichier � %s �, ligne %d"
+msgstr "décalage du fuseau horaire manquant dans le fichier « %s », ligne %d"
#: utils/misc/tzparser.c:133
#, c-format
msgid "invalid number for time zone offset in time zone file \"%s\", line %d"
msgstr ""
-"nombre invalide pour le d�calage du fuseau horaire dans le fichier des\n"
-"fuseaux horaires � %s �, ligne %d"
+"nombre invalide pour le décalage du fuseau horaire dans le fichier des\n"
+"fuseaux horaires « %s », ligne %d"
#: utils/misc/tzparser.c:169
#, c-format
msgid "invalid syntax in time zone file \"%s\", line %d"
-msgstr "syntaxe invalide dans le fichier des fuseaux horaires � %s �, ligne %d"
+msgstr "syntaxe invalide dans le fichier des fuseaux horaires « %s », ligne %d"
#: utils/misc/tzparser.c:237
#, c-format
msgid "time zone abbreviation \"%s\" is multiply defined"
-msgstr "l'abr�viation � %s � du fuseau horaire est d�finie plusieurs fois"
+msgstr "l'abréviation « %s » du fuseau horaire est définie plusieurs fois"
#: utils/misc/tzparser.c:239
#, c-format
msgid "Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d."
msgstr ""
-"L'entr�e dans le fichier des fuseaux horaires � %s �, ligne %d, est en\n"
-"conflit avec l'entr�e du fichier � %s �, ligne %d."
+"L'entrée dans le fichier des fuseaux horaires « %s », ligne %d, est en\n"
+"conflit avec l'entrée du fichier « %s », ligne %d."
#: utils/misc/tzparser.c:301
#, c-format
msgid "invalid time zone file name \"%s\""
-msgstr "nom du fichier de fuseaux horaires invalide : � %s �"
+msgstr "nom du fichier de fuseaux horaires invalide : « %s »"
#: utils/misc/tzparser.c:314
#, c-format
msgid "time zone file recursion limit exceeded in file \"%s\""
msgstr ""
-"limite de r�cursion d�pass�e dans le fichier � %s � (fichier des fuseaux\n"
+"limite de récursion dépassée dans le fichier « %s » (fichier des fuseaux\n"
"horaires)"
#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366
#, c-format
msgid "could not read time zone file \"%s\": %m"
-msgstr "n'a pas pu lire le fichier des fuseaux horaires � %s � : %m"
+msgstr "n'a pas pu lire le fichier des fuseaux horaires « %s » : %m"
#: utils/misc/tzparser.c:376
#, c-format
msgid "line is too long in time zone file \"%s\", line %d"
msgstr ""
-"une ligne est trop longue dans le fichier des fuseaux horaires � %s �,\n"
+"une ligne est trop longue dans le fichier des fuseaux horaires « %s »,\n"
"ligne %d"
#: utils/misc/tzparser.c:399
#, c-format
msgid "@INCLUDE without file name in time zone file \"%s\", line %d"
msgstr ""
-"@INCLUDE sans nom de fichier dans le fichier des fuseaux horaires � %s �,\n"
+"@INCLUDE sans nom de fichier dans le fichier des fuseaux horaires « %s »,\n"
"ligne %d"
-#: utils/mmgr/aset.c:506
+#: utils/mmgr/aset.c:510
#, c-format
msgid "Failed while creating memory context \"%s\"."
-msgstr "�chec lors de la cr�ation du contexte m�moire � %s �."
+msgstr "Échec lors de la création du contexte mémoire « %s »."
-#: utils/mmgr/mcxt.c:771 utils/mmgr/mcxt.c:806 utils/mmgr/mcxt.c:843 utils/mmgr/mcxt.c:880 utils/mmgr/mcxt.c:914 utils/mmgr/mcxt.c:943 utils/mmgr/mcxt.c:977 utils/mmgr/mcxt.c:1059 utils/mmgr/mcxt.c:1093 utils/mmgr/mcxt.c:1142
+#: utils/mmgr/mcxt.c:768 utils/mmgr/mcxt.c:803 utils/mmgr/mcxt.c:840 utils/mmgr/mcxt.c:877 utils/mmgr/mcxt.c:911 utils/mmgr/mcxt.c:940 utils/mmgr/mcxt.c:974 utils/mmgr/mcxt.c:1056 utils/mmgr/mcxt.c:1090 utils/mmgr/mcxt.c:1139
#, c-format
msgid "Failed on request of size %zu."
-msgstr "�chec d'une requ�te de taille %zu."
+msgstr "Échec d'une requête de taille %zu."
-#: utils/mmgr/portalmem.c:208
+#: utils/mmgr/portalmem.c:207
#, c-format
msgid "cursor \"%s\" already exists"
-msgstr "le curseur � %s � existe d�j�"
+msgstr "le curseur « %s » existe déjà"
-#: utils/mmgr/portalmem.c:212
+#: utils/mmgr/portalmem.c:211
#, c-format
msgid "closing existing cursor \"%s\""
-msgstr "fermeture du curseur existant � %s �"
+msgstr "fermeture du curseur existant « %s »"
-#: utils/mmgr/portalmem.c:419
+#: utils/mmgr/portalmem.c:415
#, c-format
msgid "portal \"%s\" cannot be run"
-msgstr "le portail � %s � ne peut pas �tre ex�cut� de nouveau"
+msgstr "le portail « %s » ne peut pas être exécuté de nouveau"
-#: utils/mmgr/portalmem.c:499
+#: utils/mmgr/portalmem.c:495
#, c-format
msgid "cannot drop active portal \"%s\""
-msgstr "ne peut pas supprimer le portail actif � %s �"
+msgstr "ne peut pas supprimer le portail actif « %s »"
-#: utils/mmgr/portalmem.c:689
+#: utils/mmgr/portalmem.c:699
#, c-format
msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD"
-msgstr "ne peut pas pr�parer une transaction qui a cr�� un curseur WITH HOLD"
+msgstr "ne peut pas préparer une transaction qui a créé un curseur WITH HOLD"
#: utils/sort/logtape.c:226
#, c-format
msgid "could not read block %ld of temporary file: %m"
msgstr "n'a pas pu lire le bloc %ld du fichier temporaire : %m"
-#: utils/sort/tuplesort.c:3360
+#: utils/sort/tuplesort.c:3402
#, c-format
msgid "cannot have more than %d runs for an external sort"
-msgstr "ne peut pas avoir plus de %d ex�cutions pour un tri externe"
+msgstr "ne peut pas avoir plus de %d exécutions pour un tri externe"
-#: utils/sort/tuplesort.c:4416
+#: utils/sort/tuplesort.c:4474
#, c-format
msgid "could not create unique index \"%s\""
-msgstr "n'a pas pu cr�er l'index unique � %s �"
+msgstr "n'a pas pu créer l'index unique « %s »"
-#: utils/sort/tuplesort.c:4418
+#: utils/sort/tuplesort.c:4476
#, c-format
msgid "Key %s is duplicated."
-msgstr "La cl� %s est dupliqu�e."
+msgstr "La clé %s est dupliquée."
-#: utils/sort/tuplesort.c:4419
+#: utils/sort/tuplesort.c:4477
#, c-format
msgid "Duplicate keys exist."
-msgstr "Des cl�s dupliqu�es existent."
+msgstr "Des clés dupliquées existent."
#: utils/sort/tuplestore.c:515 utils/sort/tuplestore.c:525 utils/sort/tuplestore.c:852 utils/sort/tuplestore.c:956 utils/sort/tuplestore.c:1020 utils/sort/tuplestore.c:1037 utils/sort/tuplestore.c:1239 utils/sort/tuplestore.c:1304 utils/sort/tuplestore.c:1313
#, c-format
msgid "could not seek in tuplestore temporary file: %m"
-msgstr "n'a pas pu se d�placer dans le fichier temporaire tuplestore : %m"
+msgstr "n'a pas pu se déplacer dans le fichier temporaire tuplestore : %m"
#: utils/sort/tuplestore.c:1460 utils/sort/tuplestore.c:1533 utils/sort/tuplestore.c:1539
#, c-format
@@ -23727,1760 +23683,1783 @@ msgstr "n'a pas pu lire le fichier temporaire tuplestore : %m"
#: utils/sort/tuplestore.c:1501 utils/sort/tuplestore.c:1506 utils/sort/tuplestore.c:1512
#, c-format
msgid "could not write to tuplestore temporary file: %m"
-msgstr "n'a pas pu �crire le fichier temporaire tuplestore : %m"
+msgstr "n'a pas pu écrire le fichier temporaire tuplestore : %m"
-#: utils/time/snapmgr.c:543
+#: utils/time/snapmgr.c:618
#, c-format
msgid "The source transaction is not running anymore."
-msgstr "La transaction source n'est plus en cours d'ex�cution."
+msgstr "La transaction source n'est plus en cours d'exécution."
-#: utils/time/snapmgr.c:1097
+#: utils/time/snapmgr.c:1190
#, c-format
msgid "cannot export a snapshot from a subtransaction"
msgstr "ne peut pas exporter un snapshot dans un sous-transaction"
-#: utils/time/snapmgr.c:1246 utils/time/snapmgr.c:1251 utils/time/snapmgr.c:1256 utils/time/snapmgr.c:1271 utils/time/snapmgr.c:1276 utils/time/snapmgr.c:1281 utils/time/snapmgr.c:1380 utils/time/snapmgr.c:1396 utils/time/snapmgr.c:1421
+#: utils/time/snapmgr.c:1339 utils/time/snapmgr.c:1344 utils/time/snapmgr.c:1349 utils/time/snapmgr.c:1364 utils/time/snapmgr.c:1369 utils/time/snapmgr.c:1374 utils/time/snapmgr.c:1473 utils/time/snapmgr.c:1489 utils/time/snapmgr.c:1514
#, c-format
msgid "invalid snapshot data in file \"%s\""
-msgstr "donn�es invalides du snapshot dans le fichier � %s �"
+msgstr "données invalides du snapshot dans le fichier « %s »"
-#: utils/time/snapmgr.c:1318
+#: utils/time/snapmgr.c:1411
#, c-format
msgid "SET TRANSACTION SNAPSHOT must be called before any query"
-msgstr "SET TRANSACTION SNAPSHOT doit �tre appel� avant toute requ�te"
+msgstr "SET TRANSACTION SNAPSHOT doit être appelé avant toute requête"
-#: utils/time/snapmgr.c:1327
+#: utils/time/snapmgr.c:1420
#, c-format
msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ"
msgstr "une transaction important un snapshot doit avoir le niveau d'isolation SERIALIZABLE ou REPEATABLE READ."
-#: utils/time/snapmgr.c:1336 utils/time/snapmgr.c:1345
+#: utils/time/snapmgr.c:1429 utils/time/snapmgr.c:1438
#, c-format
msgid "invalid snapshot identifier: \"%s\""
-msgstr "identifiant invalide du snapshot : � %s �"
+msgstr "identifiant invalide du snapshot : « %s »"
-#: utils/time/snapmgr.c:1434
+#: utils/time/snapmgr.c:1527
#, c-format
msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction"
-msgstr "une transaction s�rialisable ne peut pas importer un snapshot provenant d'une transaction non s�rialisable"
+msgstr "une transaction sérialisable ne peut pas importer un snapshot provenant d'une transaction non sérialisable"
-#: utils/time/snapmgr.c:1438
+#: utils/time/snapmgr.c:1531
#, c-format
msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction"
msgstr ""
-"une transaction s�rialisable en �criture ne peut pas importer un snapshot\n"
+"une transaction sérialisable en écriture ne peut pas importer un snapshot\n"
"provenant d'une transaction en lecture seule"
-#: utils/time/snapmgr.c:1453
+#: utils/time/snapmgr.c:1546
#, c-format
msgid "cannot import a snapshot from a different database"
-msgstr "ne peut pas importer un snapshot � partir d'une base de donn�es diff�rente"
-
-#~ msgid "mapped win32 error code %lu to %d"
-#~ msgstr "correspondance du code d'erreur win32 %lu en %d"
-
-#~ msgid "unrecognized win32 error code: %lu"
-#~ msgstr "code d'erreur win32 non reconnu : %lu"
+msgstr "ne peut pas importer un snapshot à partir d'une base de données différente"
-#~ msgid "invalid value for recovery parameter \"recovery_target\""
-#~ msgstr "valeur invalide pour le param�tre de restauration � recovery_target �"
+#~ msgid "could not create two-phase state file \"%s\": %m"
+#~ msgstr ""
+#~ "n'a pas pu créer le fichier de statut de la validation en deux phases nommé\n"
+#~ "« %s » : %m"
-#~ msgid "redo record is at %X/%X; shutdown %s"
-#~ msgstr "l'enregistrement � r�-ex�cuter se trouve � %X/%X ; arr�t %s"
+#~ msgid "could not seek in two-phase state file: %m"
+#~ msgstr ""
+#~ "n'a pas pu se déplacer dans le fichier de statut de la validation en deux\n"
+#~ "phases : %m"
-#~ msgid "next transaction ID: %u/%u; next OID: %u"
-#~ msgstr "prochain identifiant de transaction : %u/%u ; prochain OID : %u"
+#~ msgid "two-phase state file for transaction %u is corrupt"
+#~ msgstr ""
+#~ "le fichier d'état de la validation en deux phases est corrompu pour la\n"
+#~ "transaction %u"
-#~ msgid "next MultiXactId: %u; next MultiXactOffset: %u"
-#~ msgstr "prochain MultiXactId : %u ; prochain MultiXactOffset : %u"
+#~ msgid "could not fsync two-phase state file \"%s\": %m"
+#~ msgstr ""
+#~ "n'a pas pu synchroniser sur disque (fsync) le fichier d'état de la\n"
+#~ "validation en deux phases nommé « %s » : %m"
-#~ msgid "oldest unfrozen transaction ID: %u, in database %u"
+#~ msgid "could not close two-phase state file \"%s\": %m"
#~ msgstr ""
-#~ "identifiant de transaction non gel� le plus ancien : %u, dans la base de\n"
-#~ "donn�es %u"
+#~ "n'a pas pu fermer le fichier d'état de la validation en deux phases nommé\n"
+#~ "« %s » : %m"
-#~ msgid "invalid xlog switch record at %X/%X"
-#~ msgstr "enregistrement de basculement du journal de transaction invalide � %X/%X"
+#~ msgid "could not link file \"%s\" to \"%s\" (initialization of log file): %m"
+#~ msgstr "n'a pas pu lier le fichier « %s » à « %s » (initialisation du journal de transactions) : %m"
-#~ msgid "record with zero length at %X/%X"
-#~ msgstr "enregistrement de longueur nulle � %X/%X"
+#~ msgid "could not rename file \"%s\" to \"%s\" (initialization of log file): %m"
+#~ msgstr "n'a pas pu renommer le fichier « %s » en « %s » (initialisation du journal de transactions) : %m"
-#~ msgid "invalid backup block size in record at %X/%X"
-#~ msgstr "taille du bloc de sauvegarde invalide dans l'enregistrement � %X/%X"
+#~ msgid "ignoring \"%s\" file because no \"%s\" file exists"
+#~ msgstr "ignore le fichier « %s » parce que le fichier « %s » n'existe pas"
-#~ msgid "incorrect hole size in record at %X/%X"
-#~ msgstr "taille du trou incorrect � l'enregistrement %X/%X"
+#~ msgid "must be superuser or replication role to run a backup"
+#~ msgstr "doit être super-utilisateur ou avoir l'attribut de réplication pour exécuter une sauvegarde"
-#~ msgid "incorrect total length in record at %X/%X"
-#~ msgstr "longueur totale incorrecte � l'enregistrement %X/%X"
+#~ msgid "must be superuser to switch transaction log files"
+#~ msgstr "doit être super-utilisateur pour changer de journal de transactions"
-#~ msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s."
-#~ msgstr ""
-#~ "L'identifiant du journal de transactions du syst�me de base de donn�es est %s,\n"
-#~ "l'identifiant pg_control du syst�me de base de donn�es dans pg_control est %s."
+#~ msgid "must be superuser to create a restore point"
+#~ msgstr "doit être super-utilisateur pour créer un point de restauration"
-#~ msgid "WAL file is from different database system: Incorrect XLOG_SEG_SIZE in page header."
-#~ msgstr ""
-#~ "le journal de transactions provient d'un syst�me de bases de donn�es diff�rent :\n"
-#~ "XLOG_SEG_SIZE incorrect dans l'en-t�te de page."
+#~ msgid "must be superuser to control recovery"
+#~ msgstr "doit être super-utilisateur pour contrôler la restauration"
-#~ msgid "WAL file is from different database system: Incorrect XLOG_BLCKSZ in page header."
-#~ msgstr ""
-#~ "le journal de transactions provient d'un syst�me de bases de donn�es diff�rent :\n"
-#~ "XLOG_BLCKSZ incorrect dans l'en-t�te de page."
+#~ msgid "invalid record length at %X/%X"
+#~ msgstr "longueur invalide de l'enregistrement à %X/%X"
-#~ msgid "=> is deprecated as an operator name"
-#~ msgstr "=> est un nom d'op�rateur obsol�te"
+#~ msgid "%s is already in schema \"%s\""
+#~ msgstr "%s existe déjà dans le schéma « %s »"
-#~ msgid "This name may be disallowed altogether in future versions of PostgreSQL."
-#~ msgstr "Ce nom pourrait �tre interdit dans les prochaines versions de PostgreSQL."
+#~ msgid "function \"%s\" must return type \"event_trigger\""
+#~ msgstr "la fonction « %s » doit renvoyer le type « event_trigger »"
-#~ msgid "inherited relation \"%s\" is not a table"
-#~ msgstr "la relation h�rit�e � %s � n'est pas une table"
+#~ msgid "function %s must return type \"fdw_handler\""
+#~ msgstr "la fonction %s doit renvoyer le type « fdw_handler »"
-#~ msgid "\"%s\" is not a table, materialized view, composite type, or foreign table"
-#~ msgstr "� %s � n'est ni une table, ni une vue mat�rialis�e, ni un type composite, ni une table distante"
+#~ msgid "could not reposition held cursor"
+#~ msgstr "n'a pas pu repositionner le curseur détenu"
-#~ msgid "Specify a USING expression to perform the conversion."
-#~ msgstr "Donnez une expression USING pour r�aliser la conversion."
+#~ msgid "function %s must return type \"language_handler\""
+#~ msgstr "la fonction %s doit renvoyer le type « language_handler »"
-#~ msgid ""
-#~ "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"
-#~ "pages: %d removed, %d remain\n"
-#~ "tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"
-#~ "buffer usage: %d hits, %d misses, %d dirtied\n"
-#~ "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"
-#~ "system usage: %s"
-#~ msgstr ""
-#~ "VACUUM automatique de la table � %s.%s.%s � : parcours d'index : %d\n"
-#~ "pages : %d supprim�es, %d restantes\n"
-#~ "lignes : %.0f supprim�es, %.0f restantes, %.0f sont mortes mais non supprimables\n"
-#~ "utilisation des tampons : %d lus dans le cache, %d lus hors du cache, %d modifi�s\n"
-#~ "taux moyen de lecture : %.3f Mo/s, taux moyen d'�criture : %.3f Mo/s\n"
-#~ "utilisation syst�me : %s"
+#~ msgid "function %s must return type \"trigger\""
+#~ msgstr "la fonction %s doit renvoyer le type « trigger »"
-#~ msgid ""
-#~ "%.0f dead row versions cannot be removed yet.\n"
-#~ "There were %.0f unused item pointers.\n"
-#~ "%u pages are entirely empty.\n"
-#~ "%s."
-#~ msgstr ""
-#~ "%.0f versions de lignes mortes ne peuvent pas encore �tre supprim�es.\n"
-#~ "Il y avait %.0f pointeurs d'�l�ments inutilis�s.\n"
-#~ "%u pages sont enti�rement vides.\n"
-#~ "%s."
+#~ msgid "changing return type of function %s from \"opaque\" to \"cstring\""
+#~ msgstr "changement du type de retour de la fonction %s d'« opaque » vers « cstring »"
-#~ msgid "interval precision specified twice"
-#~ msgstr "pr�cision d'intervalle sp�cifi�e deux fois"
+#~ msgid "type output function %s must return type \"cstring\""
+#~ msgstr "le type de sortie de la fonction %s doit être « cstring »"
-#~ msgid "received password packet"
-#~ msgstr "paquet du mot de passe re�u"
+#~ msgid "type send function %s must return type \"bytea\""
+#~ msgstr "la fonction send du type %s doit renvoyer le type « bytea »"
-#~ msgid "SSL failure during renegotiation start"
-#~ msgstr "�chec SSL au d�but de la re-n�gotiation"
+#~ msgid "typmod_in function %s must return type \"integer\""
+#~ msgstr "la fonction typmod_in %s doit renvoyer le type « entier »"
-#~ msgid "SSL handshake failure on renegotiation, retrying"
-#~ msgstr "�chec du handshake SSL lors de la ren�gotiation, nouvelle tentative"
+#~ msgid "Permissions should be u=rw (0600) or less."
+#~ msgstr "Les droits devraient être u=rwx (0600) ou inférieures."
-#~ msgid "could not complete SSL handshake on renegotiation, too many failures"
-#~ msgstr "n'a pas pu terminer la poign�e de main de ren�gotiation, trop d'�checs"
+#~ msgid "function %s must return type \"tsm_handler\""
+#~ msgstr "la fonction %s doit renvoyer le type « tsm_handler »"
-#~ msgid "SSL failed to renegotiate connection before limit expired"
-#~ msgstr "SSL a �chou� � ren�gotier la connexion avant l'expiration du d�lai"
+#~ msgid "must be superuser to reset statistics counters"
+#~ msgstr "doit être super-utilisateur pour réinitialiser les compteurs statistiques"
-#~ msgid "could not set socket to blocking mode: %m"
-#~ msgstr "n'a pas pu activer le mode bloquant pour la socket : %m"
+#~ msgid "socket not open"
+#~ msgstr "socket non ouvert"
-#~ msgid "%s: setsysinfo failed: %s\n"
-#~ msgstr "%s : setsysinfo a �chou� : %s\n"
+#~ msgid "multibyte flag character is not allowed"
+#~ msgstr "un caractère drapeau multi-octet n'est pas autorisé"
-#~ msgid " -A 1|0 enable/disable run-time assert checking\n"
-#~ msgstr ""
-#~ " -A 1|0 active/d�sactive la v�rification des limites (assert) �\n"
-#~ " l'ex�cution\n"
+#~ msgid "could not format \"path\" value"
+#~ msgstr "n'a pas pu formater la valeur « path »"
-#~ msgid "subquery must return a column"
-#~ msgstr "la sous-requ�te doit renvoyer une colonne"
+#~ msgid "invalid input syntax for type box: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type box : « %s »"
-#~ msgid "Consider increasing the configuration parameter \"checkpoint_segments\"."
-#~ msgstr "Consid�rez l'augmentation du param�tre � checkpoint_segments �."
+#~ msgid "invalid input syntax for type line: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type line: « %s »"
-#~ msgid "WAL archival (archive_mode=on) requires wal_level \"archive\", \"hot_standby\", or \"logical\""
-#~ msgstr ""
-#~ "l'archivage des journaux de transactions (archive_mode=on) n�cessite que\n"
-#~ "le param�tre wal_level soit initialis� avec � archive �, � hot_standby � ou � logical �"
+#~ msgid "invalid input syntax for type path: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type path : « %s »"
-#~ msgid "invalid value for parameter \"replication\""
-#~ msgstr "valeur invalide pour le param�tre � replication �"
+#~ msgid "invalid input syntax for type point: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type point : « %s »"
-#~ msgid "postmaster became multithreaded"
-#~ msgstr "le postmaster est devenu multithread�"
+#~ msgid "invalid input syntax for type lseg: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type lseg : « %s »"
-#~ msgid "archive member \"%s\" too large for tar format"
-#~ msgstr "membre � %s � de l'archive trop volumineux pour le format tar"
+#~ msgid "invalid input syntax for type polygon: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type polygon : « %s »"
-#~ msgid "could not determine input data types"
-#~ msgstr "n'a pas pu d�terminer les types de donn�es en entr�e"
+#~ msgid "invalid input syntax for type circle: \"%s\""
+#~ msgstr "syntaxe en entrée invalide pour le type circle : « %s »"
-#~ msgid "neither input type is an array"
-#~ msgstr "aucun type de donn�es n'est un tableau"
+#~ msgid "could not format \"circle\" value"
+#~ msgstr "n'a pas pu formater la valeur « circle »"
-#~ msgid "unexpected \"=\""
-#~ msgstr "� = � inattendu"
+#~ msgid "must be superuser to signal the postmaster"
+#~ msgstr "doit être super-utilisateur pour envoyer un signal au postmaster"
-#~ msgid "invalid symbol"
-#~ msgstr "symbole invalide"
+#~ msgid "must be superuser to rotate log files"
+#~ msgstr "doit être super-utilisateur pour exécuter la rotation des journaux applicatifs"
-#~ msgid "must be superuser or have the same role to cancel queries running in other server processes"
-#~ msgstr ""
-#~ "doit �tre super-utilisateur ou avoir le m�me r�le pour annuler des requ�tes\n"
-#~ "ex�cut�es dans les autres processus serveur"
+#~ msgid "argument for function \"exp\" too big"
+#~ msgstr "l'argument de la fonction « exp » est trop gros"
-#~ msgid "must be superuser or have the same role to terminate other server processes"
+#~ msgid "could not convert to time zone \"%s\""
+#~ msgstr "n'a pas pu convertir vers le fuseau horaire « %s »"
+
+#~ msgid "WAL writer sleep time between WAL flushes."
#~ msgstr ""
-#~ "doit �tre super-utilisateur ou avoir le m�me r�le pour fermer les connexions\n"
-#~ "ex�cut�es dans les autres processus serveur"
+#~ "Temps d'endormissement du processus d'écriture pendant le vidage des\n"
+#~ "journaux de transactions en millisecondes."
-#~ msgid "cannot accept a value of type pg_node_tree"
-#~ msgstr "ne peut pas accepter une valeur de type pg_node_tree"
+#~ msgid "JSON does not support infinite date values."
+#~ msgstr "JSON ne supporte pas les valeurs infinies de date."
-#~ msgid "Turns on various assertion checks."
-#~ msgstr "Active les diff�rentes v�rifications des assertions."
+#~ msgid "JSON does not support infinite timestamp values."
+#~ msgstr "JSON ne supporte pas les valeurs infinies de timestamp."
-#~ msgid "This is a debugging aid."
-#~ msgstr "C'est une aide de d�bogage."
+#~ msgid "cannot override frame clause of window \"%s\""
+#~ msgstr "ne peut pas surcharger la frame clause du window « %s »"
-#~ msgid "This parameter doesn't do anything."
-#~ msgstr "Ce param�tre ne fait rien."
+#~ msgid "window functions cannot use named arguments"
+#~ msgstr "les fonctions window ne peuvent pas renvoyer des arguments nommés"
-#~ msgid "It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."
-#~ msgstr ""
-#~ "C'est ici uniquement pour ne pas avoir de probl�mes avec le SET AUTOCOMMIT\n"
-#~ "TO ON des clients 7.3."
+#~ msgid "invalid list syntax for \"listen_addresses\""
+#~ msgstr "syntaxe de liste invalide pour le paramètre « listen_addresses »"
-#~ msgid "Sets the maximum distance in log segments between automatic WAL checkpoints."
-#~ msgstr ""
-#~ "Initialise la distance maximale dans les journaux de transaction entre chaque\n"
-#~ "point de v�rification (checkpoints) des journaux."
+#~ msgid "invalid list syntax for \"unix_socket_directories\""
+#~ msgstr "syntaxe de liste invalide pour le paramètre « unix_socket_directories »"
-#~ msgid "Set the amount of traffic to send and receive before renegotiating the encryption keys."
-#~ msgstr ""
-#~ "Configure la quantit� de trafic � envoyer et recevoir avant la ren�gotiation\n"
-#~ "des cl�s d'enchiffrement."
+#~ msgid "Valid values are '[]', '[)', '(]', and '()'."
+#~ msgstr "Les valeurs valides sont « [] », « [) », « (] » et « () »."
-#~ msgid "SET AUTOCOMMIT TO OFF is no longer supported"
-#~ msgstr "SET AUTOCOMMIT TO OFF n'est plus support�"
+#~ msgid "poll() failed in statistics collector: %m"
+#~ msgstr "échec du poll() dans le récupérateur de statistiques : %m"
-#~ msgid "assertion checking is not supported by this build"
-#~ msgstr "la v�rification de l'assertion n'a pas �t� int�gr�e lors de la compilation"
+#~ msgid "select() failed in logger process: %m"
+#~ msgstr "échec de select() dans le processus des journaux applicatifs : %m"
-#~ msgid "%s \"%s\": return code %d"
-#~ msgstr "%s � %s � : code de retour %d"
+#~ msgid "%s: could not open file \"%s\": %s\n"
+#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %s\n"
-#~ msgid "could not parse transaction log location \"%s\""
-#~ msgstr "n'a pas pu analyser l'emplacement du journal des transactions � %s �"
+#~ msgid "%s: could not open log file \"%s/%s\": %s\n"
+#~ msgstr "%s : n'a pas pu ouvrir le journal applicatif « %s/%s » : %s\n"
-#~ msgid "invalid input syntax for transaction log location: \"%s\""
-#~ msgstr "syntaxe invalide en entr�e pour l'emplacement du journal de transactions : � %s �"
+#~ msgid "%s: could not fork background process: %s\n"
+#~ msgstr "%s : n'a pas pu créer un processus fils : %s\n"
-#~ msgid "trigger \"%s\" for table \"%s\" does not exist, skipping"
-#~ msgstr "le trigger � %s � pour la table � %s � n'existe pas, poursuite du traitement"
+#~ msgid "%s: could not dissociate from controlling TTY: %s\n"
+#~ msgstr "%s : n'a pas pu se dissocier du TTY contrôlant : %s\n"
-#~ msgid "Kerberos 5 authentication failed for user \"%s\""
-#~ msgstr "authentification Kerberos 5 �chou�e pour l'utilisateur � %s �"
+#~ msgid "Runs the server silently."
+#~ msgstr "Lance le serveur de manière silencieuse."
-#~ msgid "Kerberos initialization returned error %d"
-#~ msgstr "l'initialisation de Kerberos a retourn� l'erreur %d"
+#~ msgid "If this parameter is set, the server will automatically run in the background and any controlling terminals are dissociated."
+#~ msgstr ""
+#~ "Si ce paramètre est initialisé, le serveur sera exécuté automatiquement en\n"
+#~ "tâche de fond et les terminaux de contrôles seront dés-associés."
-#~ msgid "Kerberos keytab resolving returned error %d"
-#~ msgstr "la r�solution keytab de Kerberos a renvoy� l'erreur %d"
+#~ msgid "WAL sender sleep time between WAL replications."
+#~ msgstr ""
+#~ "Temps d'endormissement du processus d'envoi des journaux de transactions entre\n"
+#~ "les réplications des journaux de transactions."
-#~ msgid "Kerberos sname_to_principal(\"%s\", \"%s\") returned error %d"
-#~ msgstr "sname_to_principal(� %s �, � %s �) de Kerberos a renvoy� l'erreur %d"
+#~ msgid "Sets the list of known custom variable classes."
+#~ msgstr "Initialise la liste des classes variables personnalisées connues."
-#~ msgid "Kerberos recvauth returned error %d"
-#~ msgstr "recvauth de Kerberos a renvoy� l'erreur %d"
+#~ msgid "foreign key constraint \"%s\" of relation \"%s\" does not exist"
+#~ msgstr "la clé étrangère « %s » de la relation « %s » n'existe pas"
-#~ msgid "Kerberos unparse_name returned error %d"
-#~ msgstr "unparse_name de Kerberos a renvoy� l'erreur %d"
+#~ msgid "removing built-in function \"%s\""
+#~ msgstr "suppression de la fonction interne « %s »"
-#~ msgid "local user with ID %d does not exist"
-#~ msgstr "l'utilisateur local dont l'identifiant est %d n'existe pas"
+#~ msgid "permission denied to drop foreign-data wrapper \"%s\""
+#~ msgstr "droit refusé pour supprimer le wrapper de données distantes « %s »"
-#~ msgid "SSL renegotiation failure"
-#~ msgstr "�chec lors de la re-n�gotiation SSL"
+#~ msgid "Must be superuser to drop a foreign-data wrapper."
+#~ msgstr "Doit être super-utilisateur pour supprimer un wrapper de données distantes."
-#~ msgid "krb5 authentication is not supported on local sockets"
+#~ msgid "must be superuser to drop text search parsers"
#~ msgstr ""
-#~ "l'authentification krb5 n'est pas support�e sur les connexions locales par\n"
-#~ "socket"
+#~ "doit être super-utilisateur pour supprimer des analyseurs de recherche plein\n"
+#~ "texte"
-#~ msgid "%s: invalid effective UID: %d\n"
-#~ msgstr "%s : UID effectif invalide : %d\n"
+#~ msgid "must be superuser to drop text search templates"
+#~ msgstr "doit être super-utilisateur pour supprimer des modèles de recherche plein texte"
-#~ msgid "%s: could not determine user name (GetUserName failed)\n"
-#~ msgstr "%s : n'a pas pu d�terminer le nom de l'utilisateur (GetUserName a �chou�)\n"
+#~ msgid "recovery is still in progress, can't accept WAL streaming connections"
+#~ msgstr "la restauration est en cours, ne peut pas accepter les connexions de flux WAL"
-#~ msgid "too many column aliases specified for function %s"
-#~ msgstr "trop d'alias de colonnes sp�cifi�es pour la fonction %s"
+#~ msgid "standby connections not allowed because wal_level=minimal"
+#~ msgstr "connexions standby non autorisées car wal_level=minimal"
-#~ msgid "Expected 1 tuple with 3 fields, got %d tuples with %d fields."
-#~ msgstr "Attendait 1 ligne avec 3 champs, a obtenu %d lignes avec %d champs."
+#~ msgid "could not open directory \"pg_tblspc\": %m"
+#~ msgstr "n'a pas pu ouvrir le répertoire « pg_tblspc » : %m"
-#~ msgid "Security-barrier views are not automatically updatable."
-#~ msgstr "Les vues avec barri�re de s�curit� ne sont pas automatiquement disponibles en �criture."
+#~ msgid "could not access root certificate file \"%s\": %m"
+#~ msgstr "n'a pas pu accéder au fichier du certificat racine « %s » : %m"
-#~ msgid "Views that return the same column more than once are not automatically updatable."
-#~ msgstr "Les vues qui renvoient la m�me colonne plus d'une fois ne sont pas automatiquement disponibles en �criture."
+#~ msgid "SSL certificate revocation list file \"%s\" not found, skipping: %s"
+#~ msgstr "liste de révocation des certificats SSL « %s » introuvable, continue : %s"
-#~ msgid "wrong affix file format for flag"
-#~ msgstr "mauvais format de fichier affixe pour le drapeau"
+#~ msgid "Certificates will not be checked against revocation list."
+#~ msgstr "Les certificats ne seront pas vérifiés avec la liste de révocation."
-#~ msgid "missing assignment operator"
-#~ msgstr "op�rateur d'affectation manquant"
+#~ msgid "missing or erroneous pg_hba.conf file"
+#~ msgstr "fichier pg_hba.conf manquant ou erroné"
-#~ msgid "cannot call json_object_keys on an array"
-#~ msgstr "ne peut pas appeler json_object_keys sur un tableau"
+#~ msgid "See server log for details."
+#~ msgstr "Voir les journaux applicatifs du serveur pour plus de détails."
-#~ msgid "cannot call json_object_keys on a scalar"
-#~ msgstr "ne peut pas appeler json_object_keys sur un scalaire"
+#~ msgid "Make sure the root.crt file is present and readable."
+#~ msgstr "Assurez-vous que le certificat racine (root.crt) est présent et lisible"
-#~ msgid "cannot call function with null path elements"
-#~ msgstr "ne peut pas appeler une fonction avec des �l�ments chemins NULL"
+#~ msgid " --help show this help, then exit\n"
+#~ msgstr " --help affiche cette aide, puis quitte\n"
-#~ msgid "cannot call function with empty path elements"
-#~ msgstr "ne peut pas appeler une fonction avec des �l�ments chemins vides"
+#~ msgid " --version output version information, then exit\n"
+#~ msgstr " --version affiche la version, puis quitte\n"
-#~ msgid "cannot extract array element from a non-array"
-#~ msgstr "ne peut pas extraire un �l�ment du tableau � partir d'un objet qui n'est pas un tableau"
+#~ msgid "CREATE TABLE AS cannot specify INTO"
+#~ msgstr "CREATE TABLE AS ne peut pas spécifier INTO"
-#~ msgid "cannot extract field from a non-object"
-#~ msgstr "ne peut pas extraire le chemin � partir d'un non-objet"
+#~ msgid "column name list not allowed in CREATE TABLE / AS EXECUTE"
+#~ msgstr "la liste de noms de colonnes n'est pas autorisée dans CREATE TABLE / AS EXECUTE"
-#~ msgid "cannot call json_array_elements on a non-array"
-#~ msgstr "ne peut pas appeler json_array_elements sur un objet qui n'est pas un tableau"
+#~ msgid "INSERT ... SELECT cannot specify INTO"
+#~ msgstr "INSERT ... SELECT ne peut pas avoir INTO"
-#~ msgid "cannot call json_array_elements on a scalar"
-#~ msgstr "ne peut pas appeler json_array_elements sur un scalaire"
+#~ msgid "DECLARE CURSOR cannot specify INTO"
+#~ msgstr "DECLARE CURSOR ne peut pas spécifier INTO"
-#~ msgid "first argument of json_populate_record must be a row type"
-#~ msgstr "le premier argument de json_populate_record doit �tre un type ROW"
+#~ msgid "subquery in FROM cannot have SELECT INTO"
+#~ msgstr "la sous-requête du FROM ne peut pas avoir de SELECT INTO"
-#~ msgid "first argument of json_populate_recordset must be a row type"
-#~ msgstr "le premier argument de json_populate_recordset doit �tre un type ROW"
+#~ msgid "subquery cannot have SELECT INTO"
+#~ msgstr "la sous-requête ne peut pas avoir de SELECT INTO"
-#~ msgid "cannot call json_populate_recordset on an object"
-#~ msgstr "ne peut pas appeler json_populate_recordset sur un objet"
+#~ msgid "subquery in WITH cannot have SELECT INTO"
+#~ msgstr "la sous-requête du WITH ne peut pas avoir de SELECT INTO"
-#~ msgid "cannot call json_populate_recordset with nested objects"
-#~ msgstr "ne peut pas appeler json_populate_recordset sur des objets imbriqu�s"
+#~ msgid "tablespace %u is not empty"
+#~ msgstr "le tablespace %u n'est pas vide"
-#~ msgid "must call json_populate_recordset on an array of objects"
-#~ msgstr "doit appeler json_populate_recordset sur un tableau d'objets"
+#~ msgid "consistent state delayed because recovery snapshot incomplete"
+#~ msgstr "état de cohérence pas encore atteint à cause d'un snapshot de restauration incomplet"
-#~ msgid "cannot call json_populate_recordset with nested arrays"
-#~ msgstr "ne peut pas appeler json_populate_recordset avec des tableaux imbriqu�s"
+#~ msgid "SSPI error %x"
+#~ msgstr "erreur SSPI : %x"
-#~ msgid "cannot call json_populate_recordset on a scalar"
-#~ msgstr "ne peut pas appeler json_populate_recordset sur un scalaire"
+#~ msgid "%s (%x)"
+#~ msgstr "%s (%x)"
-#~ msgid "cannot call json_populate_recordset on a nested object"
-#~ msgstr "ne peut pas appeler json_populate_recordset sur un objet imbriqu�"
+#~ msgid "resetting unlogged relations: cleanup %d init %d"
+#~ msgstr "réinitialisation des relations non tracées : nettoyage %d initialisation %d"
-#~ msgid "No description available."
-#~ msgstr "Aucune description disponible."
+#~ msgid "ALTER TYPE USING is only supported on plain tables"
+#~ msgstr "ALTER TYPE USING est seulement supportés sur les tables standards"
-#~ msgid "Sets the name of the Kerberos service."
-#~ msgstr "Initialise le nom du service Kerberos."
+#~ msgid "index \"%s\" is not a b-tree"
+#~ msgstr "l'index « %s » n'est pas un btree"
-#~ msgid "time zone offset %d is not a multiple of 900 sec (15 min) in time zone file \"%s\", line %d"
-#~ msgstr ""
-#~ "le d�calage %d du fuseau horaire n'est pas un multiples de 900 secondes\n"
-#~ "(15 minutes) dans le fichier des fuseaux horaires � %s �, ligne %d"
+#~ msgid "unable to read symbolic link %s: %m"
+#~ msgstr "incapable de lire le lien symbolique %s : %m"
-#~ msgid "Perhaps out of disk space?"
-#~ msgstr "Peut-�tre manquez-vous de place disque ?"
+#~ msgid "unable to open directory pg_tblspc: %m"
+#~ msgstr "impossible d'ouvrir le répertoire p_tblspc : %m"
-#~ msgid "could not change directory to \"%s\""
-#~ msgstr "n'a pas pu acc�der au r�pertoire � %s �"
+#~ msgid "Write-Ahead Log / Streaming Replication"
+#~ msgstr "Write-Ahead Log / Réplication en flux"
-#~ msgid "unlogged GiST indexes are not supported"
-#~ msgstr "les index GiST non trac�s ne sont pas support�s"
+#~ msgid "syntax error in recovery command file: %s"
+#~ msgstr "erreur de syntaxe dans le fichier de restauration : %s"
-#~ msgid "could not open file \"%s\" (log file %u, segment %u): %m"
-#~ msgstr "n'a pas pu ouvrir le fichier � %s � (journal de transactions %u, segment %u) : %m"
+#~ msgid "Lines should have the format parameter = 'value'."
+#~ msgstr "Les lignes devraient avoir le format paramètre = 'valeur'"
-#~ msgid "there is no contrecord flag in log file %u, segment %u, offset %u"
+#~ msgid "index %u/%u/%u needs VACUUM FULL or REINDEX to finish crash recovery"
#~ msgstr ""
-#~ "il n'y a pas de drapeaux � contrecord � dans le journal de transactions %u,\n"
-#~ "segment %u, d�calage %u"
+#~ "l'index %u/%u/%u a besoin d'un VACUUM FULL ou d'un REINDEX pour terminer la\n"
+#~ "récupération suite à un arrêt brutal"
-#~ msgid "invalid contrecord length %u in log file %u, segment %u, offset %u"
+#~ msgid "Incomplete insertion detected during crash replay."
#~ msgstr ""
-#~ "longueur invalide du � contrecord � %u dans le journal de tranasctions %u,\n"
-#~ "segment %u, d�calage %u"
-
-#~ msgid "Incorrect XLOG_SEG_SIZE in page header."
-#~ msgstr "XLOG_SEG_SIZE incorrecte dans l'en-t�te de page."
+#~ "Insertion incomplète détectée lors de la ré-exécution des requêtes suite à\n"
+#~ "l'arrêt brutal."
-#~ msgid "Incorrect XLOG_BLCKSZ in page header."
-#~ msgstr "XLOG_BLCKSZ incorrect dans l'en-t�te de page."
+#~ msgid "index \"%s\" needs VACUUM or REINDEX to finish crash recovery"
+#~ msgstr ""
+#~ "l'index « %s » a besoin d'un VACUUM ou d'un REINDEX pour terminer la\n"
+#~ "récupération suite à un arrêt brutal"
-#~ msgid "xrecoff \"%X\" is out of valid range, 0..%X"
-#~ msgstr "xrecoff � %X � en dehors des limites valides, 0..%X"
+#~ msgid "index \"%s\" needs VACUUM FULL or REINDEX to finish crash recovery"
+#~ msgstr ""
+#~ "l'index « %s » a besoin d'un VACUUM FULL ou d'un REINDEX pour terminer la\n"
+#~ "récupération suite à un arrêt brutal"
-#~ msgid "uncataloged table %s"
-#~ msgstr "table %s sans catalogue"
+#~ msgid "EnumValuesCreate() can only set a single OID"
+#~ msgstr "EnumValuesCreate() peut seulement initialiser un seul OID"
-#~ msgid "cannot use subquery in default expression"
-#~ msgstr "ne peut pas utiliser une sous-requ�te dans l'expression par d�faut"
+#~ msgid "clustering \"%s.%s\""
+#~ msgstr "exécution de CLUSTER sur « %s.%s »"
-#~ msgid "cannot use aggregate function in default expression"
-#~ msgstr "ne peut pas utiliser une fonction d'agr�gat dans une expression par d�faut"
+#~ msgid "cannot cluster on index \"%s\" because access method does not handle null values"
+#~ msgstr ""
+#~ "ne peut pas créer un cluster sur l'index « %s » car la méthode d'accès de\n"
+#~ "l'index ne gère pas les valeurs NULL"
-#~ msgid "cannot use window function in default expression"
-#~ msgstr "ne peut pas utiliser une fonction window dans une expression par d�faut"
+#~ msgid "You might be able to work around this by marking column \"%s\" NOT NULL, or use ALTER TABLE ... SET WITHOUT CLUSTER to remove the cluster specification from the table."
+#~ msgstr ""
+#~ "Vous pourriez contourner ceci en marquant la colonne « %s » avec la\n"
+#~ "contrainte NOT NULL ou en utilisant ALTER TABLE ... SET WITHOUT CLUSTER pour\n"
+#~ "supprimer la spécification CLUSTER de la table."
-#~ msgid "cannot use window function in check constraint"
-#~ msgstr "ne peut pas utiliser une fonction window dans une contrainte de v�rification"
+#~ msgid "You might be able to work around this by marking column \"%s\" NOT NULL."
+#~ msgstr "Vous pouvez contourner ceci en marquant la colonne « %s » comme NOT NULL."
-#~ msgid "A function returning ANYRANGE must have at least one ANYRANGE argument."
+#~ msgid "cannot cluster on expressional index \"%s\" because its index access method does not handle null values"
#~ msgstr ""
-#~ "Une fonction renvoyant ANYRANGE doit avoir au moins un argument du type\n"
-#~ "ANYRANGE."
+#~ "ne peut pas exécuter CLUSTER sur l'index à expression « %s » car sa méthode\n"
+#~ "d'accès ne gère pas les valeurs NULL"
-#~ msgid "%s already exists in schema \"%s\""
-#~ msgstr "%s existe d�j� dans le sch�ma � %s �"
+#~ msgid "\"%s\" is not a table, view, or composite type"
+#~ msgstr "« %s » n'est pas une table, une vue ou un type composite"
-#~ msgid "CREATE TABLE AS specifies too many column names"
-#~ msgstr "CREATE TABLE AS sp�cifie trop de noms de colonnes"
+#~ msgid "must be superuser to comment on procedural language"
+#~ msgstr ""
+#~ "doit être super-utilisateur pour ajouter un commentaire sur un langage de\n"
+#~ "procédures"
-#~ msgid "cannot use subquery in parameter default value"
-#~ msgstr "ne peut pas utiliser une sous-requ�te dans une valeur par d�faut d'un param�tre"
+#~ msgid "must be superuser to comment on text search parser"
+#~ msgstr ""
+#~ "doit être super-utilisateur pour ajouter un commentaire sur l'analyseur de\n"
+#~ "recherche plein texte"
-#~ msgid "cannot use aggregate function in parameter default value"
+#~ msgid "must be superuser to comment on text search template"
#~ msgstr ""
-#~ "ne peut pas utiliser une fonction d'agr�gat dans la valeur par d�faut d'un\n"
-#~ "param�tre"
+#~ "doit être super-utilisateur pour ajouter un commentaire sur un modèle de\n"
+#~ "recherche plein texte"
-#~ msgid "cannot use window function in parameter default value"
-#~ msgstr "ne peut pas utiliser la fonction window dans la valeur par d�faut d'un param�tre"
+#~ msgid "function \"%s\" is already in schema \"%s\""
+#~ msgstr "la fonction « %s » existe déjà dans le schéma « %s »"
-#~ msgid "Use ALTER AGGREGATE to rename aggregate functions."
-#~ msgstr "Utiliser ALTER AGGREGATE pour renommer les fonctions d'agr�gat."
+#~ msgid "cannot reference temporary table from permanent table constraint"
+#~ msgstr ""
+#~ "ne peut pas référencer une table temporaire à partir d'une contrainte de\n"
+#~ "table permanente"
-#~ msgid "Use ALTER AGGREGATE to change owner of aggregate functions."
-#~ msgstr "Utiliser ALTER AGGREGATE pour changer le propri�taire des fonctions d'agr�gat."
+#~ msgid "cannot reference permanent table from temporary table constraint"
+#~ msgstr ""
+#~ "ne peut pas référencer une table permanente à partir de la contrainte de\n"
+#~ "table temporaire"
-#~ msgid "function \"%s\" already exists in schema \"%s\""
-#~ msgstr "la fonction � %s � existe d�j� dans le sch�ma � %s �"
+#~ msgid "composite type must have at least one attribute"
+#~ msgstr "le type composite doit avoir au moins un attribut"
-#~ msgid "cannot use aggregate in index predicate"
-#~ msgstr "ne peut pas utiliser un agr�gat dans un pr�dicat d'index"
+#~ msgid "database \"%s\" not found"
+#~ msgstr "base de données « %s » non trouvée"
-#~ msgid "cannot use window function in EXECUTE parameter"
-#~ msgstr "ne peut pas utiliser une fonction window dans le param�tre EXECUTE"
+#~ msgid "invalid list syntax for parameter \"datestyle\""
+#~ msgstr "syntaxe de liste invalide pour le paramètre « datestyle »"
-#~ msgid "constraints on foreign tables are not supported"
-#~ msgstr "les contraintes sur les tables distantes ne sont pas support�es"
+#~ msgid "unrecognized \"datestyle\" key word: \"%s\""
+#~ msgstr "mot clé « datestyle » non reconnu : « %s »"
-#~ msgid "default values on foreign tables are not supported"
-#~ msgstr "les valeurs par d�faut ne sont pas support�es sur les tables distantes"
+#~ msgid "invalid interval value for time zone: month not allowed"
+#~ msgstr "valeur d'intervalle invalide pour le fuseau horaire : les mois ne sont pas autorisés"
-#~ msgid "cannot use window function in transform expression"
-#~ msgstr "ne peut pas utiliser la fonction window dans l'expression de la transformation"
+#~ msgid "invalid interval value for time zone: day not allowed"
+#~ msgstr "valeur d'intervalle invalide pour le fuseau horaire : jour non autorisé"
-#~ msgid "Use ALTER FOREIGN TABLE instead."
-#~ msgstr "Utilisez ALTER FOREIGN TABLE � la place."
+#~ msgid "argument to pg_get_expr() must come from system catalogs"
+#~ msgstr "l'argument de pg_get_expr() doit provenir des catalogues systèmes"
-#~ msgid "cannot use window function in trigger WHEN condition"
-#~ msgstr "ne peut pas utiliser la fonction window dans la condition WHEN d'un trigger"
+#~ msgid "could not enable credential reception: %m"
+#~ msgstr "n'a pas pu activer la réception de lettres de créance : %m"
-#~ msgid "must be superuser to rename text search parsers"
-#~ msgstr ""
-#~ "doit �tre super-utilisateur pour renommer les analyseurs de recherche plein\n"
-#~ "texte"
+#~ msgid "could not get effective UID from peer credentials: %m"
+#~ msgstr "n'a pas pu obtenir l'UID réel à partir des pièces d'identité de l'autre : %m"
-#~ msgid "must be superuser to rename text search templates"
-#~ msgstr "doit �tre super-utilisateur pour renommer les mod�les de recherche plein texte"
+#~ msgid "Ident authentication is not supported on local connections on this platform"
+#~ msgstr "l'authentification Ident n'est pas supportée sur les connexions locales sur cette plateforme"
-#~ msgid "automatic vacuum of table \"%s.%s.%s\": cannot (re)acquire exclusive lock for truncate scan"
-#~ msgstr "vacuum automatique de la table � %s.%s.%s � : ne peut pas acqu�rir le verrou exclusif pour la tronquer"
+#~ msgid "could not create log file \"%s\": %m"
+#~ msgstr "n'a pas pu créer le journal applicatif « %s » : %m"
-#~ msgid "You need an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger."
-#~ msgstr "Vous avez besoin d'une r�gle ON INSERT DO INSTEAD sans condition ou d'un trigger INSTEAD OF INSERT."
+#~ msgid "could not open new log file \"%s\": %m"
+#~ msgstr "n'a pas pu ouvrir le nouveau journal applicatif « %s » : %m"
-#~ msgid "You need an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger."
-#~ msgstr "Vous avez besoin d'une r�gle non conditionnelle ON UPDATE DO INSTEAD ou d'un trigger INSTEAD OF UPDATE."
+#~ msgid "Sets immediate fsync at commit."
+#~ msgstr "Configure un fsync immédiat lors du commit."
-#~ msgid "You need an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger."
-#~ msgstr "Vous avez besoin d'une r�gle inconditionnelle ON DELETE DO INSTEAD ou d'un trigger INSTEAD OF DELETE."
+#~ msgid "invalid list syntax for parameter \"log_destination\""
+#~ msgstr "syntaxe de liste invalide pour le paramètre « log_destination »"
-#~ msgid "LDAP search failed for filter \"%s\" on server \"%s\": user is not unique (%ld matches)"
-#~ msgstr ""
-#~ "�chec de la recherche LDAP pour le filtre � %s � sur le serveur � %s � :\n"
-#~ "utilisateur non unique (%ld correspondances)"
+#~ msgid "unrecognized \"log_destination\" key word: \"%s\""
+#~ msgstr "mot clé « log_destination » non reconnu : « %s »"
-#~ msgid "VALUES must not contain table references"
-#~ msgstr "VALUES ne doit pas contenir de r�f�rences de table"
+#~ msgid "cannot drop \"%s\" because it is being used by active queries in this session"
+#~ msgstr ""
+#~ "ne peut pas supprimer « %s » car cet objet est en cours d'utilisation par\n"
+#~ "des requêtes actives dans cette session"
-#~ msgid "VALUES must not contain OLD or NEW references"
-#~ msgstr "VALUES ne doit pas contenir des r�f�rences � OLD et NEW"
+#~ msgid "parameter \"recovery_target_inclusive\" requires a Boolean value"
+#~ msgstr "le paramètre « recovery_target_inclusive » requiert une valeur booléenne"
-#~ msgid "Use SELECT ... UNION ALL ... instead."
-#~ msgstr "Utilisez � la place SELECT ... UNION ALL ..."
+#~ msgid "parameter \"standby_mode\" requires a Boolean value"
+#~ msgstr "le paramètre « standby_mode » requiert une valeur booléenne"
-#~ msgid "cannot use aggregate function in VALUES"
-#~ msgstr "ne peut pas utiliser la fonction d'agr�gat dans un VALUES"
+#~ msgid "Sets the message levels that are logged during recovery."
+#~ msgstr "Initialise les niveaux de messages qui sont tracés lors de la restauration."
-#~ msgid "cannot use window function in VALUES"
-#~ msgstr "ne peut pas utiliser la fonction window dans un VALUES"
+#~ msgid "Not safe to send CSV data\n"
+#~ msgstr "Envoi non sûr des données CSV\n"
-#~ msgid "cannot use aggregate function in UPDATE"
-#~ msgstr "ne peut pas utiliser une fonction d'agr�gat dans un UPDATE"
+#~ msgid "recovery restart point at %X/%X with latest known log time %s"
+#~ msgstr ""
+#~ "point de relancement de la restauration sur %X/%X avec %s comme dernière\n"
+#~ "date connue du journal"
-#~ msgid "cannot use window function in UPDATE"
-#~ msgstr "ne peut pas utiliser une fonction window dans un UPDATE"
+#~ msgid "restartpoint_command = '%s'"
+#~ msgstr "restartpoint_command = '%s'"
-#~ msgid "cannot use aggregate function in RETURNING"
-#~ msgstr "ne peut pas utiliser une fonction d'agr�gat dans RETURNING"
+#~ msgid "usermap \"%s\""
+#~ msgstr "correspondance utilisateur « %s »"
-#~ msgid "cannot use window function in RETURNING"
-#~ msgstr "ne peut pas utiliser une fonction window dans RETURNING"
+#~ msgid "WAL archiving is not active"
+#~ msgstr "l'archivage des journaux de transactions n'est pas actif"
-#~ msgid "RETURNING cannot contain references to other relations"
-#~ msgstr "RETURNING ne doit pas contenir de r�f�rences � d'autres relations"
+#~ msgid "archive_mode must be enabled at server start."
+#~ msgstr "archive_mode doit être activé au lancement du serveur."
-#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with GROUP BY clause"
-#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autoris� avec la clause GROUP BY"
+#~ msgid "archive_command must be defined before online backups can be made safely."
+#~ msgstr ""
+#~ "archive_command doit être défini avant que les sauvegardes à chaud puissent\n"
+#~ "s'effectuer correctement."
-#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with HAVING clause"
-#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autoris� avec la clause HAVING"
+#~ msgid "During recovery, allows connections and queries. During normal running, causes additional info to be written to WAL to enable hot standby mode on WAL standby nodes."
+#~ msgstr ""
+#~ "Lors de la restauration, autorise les connexions et les requêtes. Lors d'une\n"
+#~ "exécution normale, fait que des informations supplémentaires sont écrites dans\n"
+#~ "les journaux de transactions pour activer le mode Hot Standby sur les nœuds\n"
+#~ "en attente."
-#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with aggregate functions"
-#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autoris� avec les fonctions d'agr�gats"
+#~ msgid "unlogged operation performed, data may be missing"
+#~ msgstr "opération réalisée non tracée, les données pourraient manquer"
-#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with window functions"
-#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autoris� avec les fonctions window"
+#~ msgid "not enough shared memory for walsender"
+#~ msgstr "pas assez de mémoire partagée pour le processus d'envoi des journaux de transactions"
-#~ msgid "SELECT FOR UPDATE/SHARE cannot be used with foreign table \"%s\""
-#~ msgstr "SELECT FOR UPDATE/SHARE ne peut pas �tre utilis� avec une table distante � %s �"
+#~ msgid "not enough shared memory for walreceiver"
+#~ msgstr ""
+#~ "pas assez de mémoire partagée pour le processus de réception des journaux de\n"
+#~ "transactions"
-#~ msgid "aggregates not allowed in WHERE clause"
-#~ msgstr "agr�gats non autoris�s dans une clause WHERE"
+#~ msgid "connection limit exceeded for non-superusers"
+#~ msgstr "limite de connexions dépassée pour les utilisateurs standards"
-#~ msgid "window functions not allowed in GROUP BY clause"
-#~ msgstr "fonctions window non autoris�es dans une clause GROUP BY"
+#~ msgid "not enough shared memory for background writer"
+#~ msgstr "pas assez de mémoire partagée pour le processus d'écriture en tâche de fond"
-#~ msgid "JOIN/ON clause refers to \"%s\", which is not part of JOIN"
-#~ msgstr "la clause JOIN/ON se r�f�re � � %s �, qui ne fait pas partie du JOIN"
+#, fuzzy
+#~ msgid "couldn't put socket to non-blocking mode: %m"
+#~ msgstr "n'a pas pu activer le mode non-bloquant pour la socket : %s\n"
-#~ msgid "subquery in FROM cannot refer to other relations of same query level"
-#~ msgstr ""
-#~ "la sous-requ�te du FROM ne peut pas faire r�f�rence � d'autres relations\n"
-#~ "dans le m�me niveau de la requ�te"
+#, fuzzy
+#~ msgid "couldn't put socket to blocking mode: %m"
+#~ msgstr "n'a pas pu activer le mode bloquant pour la socket : %s\n"
-#~ msgid "function expression in FROM cannot refer to other relations of same query level"
-#~ msgstr ""
-#~ "l'expression de la fonction du FROM ne peut pas faire r�f�rence � d'autres\n"
-#~ "relations sur le m�me niveau de la requ�te"
+#~ msgid "WAL file SYSID is %s, pg_control SYSID is %s"
+#~ msgstr "le SYSID du journal de transactions WAL est %s, celui de pg_control est %s"
-#~ msgid "cannot use window function in function expression in FROM"
-#~ msgstr ""
-#~ "ne peut pas utiliser la fonction window dans l'expression de la fonction\n"
-#~ "du FROM"
+#, fuzzy
+#~ msgid "sorry, too many standbys already"
+#~ msgstr "désolé, trop de clients sont déjà connectés"
-#~ msgid "argument of %s must not contain aggregate functions"
-#~ msgstr "l'argument de %s ne doit pas contenir de fonctions d'agr�gats"
+#, fuzzy
+#~ msgid "invalid WAL message received from primary"
+#~ msgstr "format du message invalide"
-#~ msgid "argument of %s must not contain window functions"
-#~ msgstr "l'argument de %s ne doit pas contenir des fonctions window"
+#~ msgid "PID %d is among the slowest backends."
+#~ msgstr "Le PID %d est parmi les processus serveur les plus lents."
-#~ msgid "arguments of row IN must all be row expressions"
-#~ msgstr "les arguments de la ligne IN doivent tous �tre des expressions de ligne"
+#~ msgid "transaction is read-only"
+#~ msgstr "la transaction est en lecture seule"
-#~ msgid "cannot use aggregate function in rule WHERE condition"
-#~ msgstr "ne peut pas utiliser la fonction d'agr�gat dans la condition d'une r�gle WHERE"
+#~ msgid "binary value is out of range for type bigint"
+#~ msgstr "la valeur binaire est en dehors des limites du type bigint"
-#~ msgid "cannot use window function in rule WHERE condition"
-#~ msgstr "ne peut pas utiliser la fonction window dans la condition d'une r�gle WHERE"
+#~ msgid "redo starts at %X/%X, consistency will be reached at %X/%X"
+#~ msgstr "la restauration comme à %X/%X, la cohérence sera atteinte à %X/%X"
-#~ msgid ""
-#~ "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently %lu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.\n"
-#~ "If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter, in which case raising the request size or reconfiguring SHMMIN is called for.\n"
-#~ "The PostgreSQL documentation contains more information about shared memory configuration."
+#~ msgid "This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by \"client_encoding\"."
#~ msgstr ""
-#~ "Cette erreur signifie habituellement que la demande de PostgreSQL pour un\n"
-#~ "segment de m�moire partag�e a d�pass� le param�tre SHMMAX de votre noyau.\n"
-#~ "Vous pouvez soit r�duire la taille de la requ�te soit reconfigurer le noyau\n"
-#~ "avec un SHMMAX plus important. Pour r�duire la taille de la requ�te\n"
-#~ "(actuellement %lu octets), r�duisez l'utilisation de la m�moire partag�e par PostgreSQL,par exemple en r�duisant shared_buffers ou max_connections\n"
-#~ "Si la taille de la requ�te est d�j� petite, il est possible qu'elle soit\n"
-#~ "moindre que le param�tre SHMMIN de votre noyau, auquel cas, augmentez la\n"
-#~ "taille de la requ�te ou reconfigurez SHMMIN.\n"
-#~ "La documentation de PostgreSQL contient plus d'informations sur la\n"
-#~ "configuration de la m�moire partag�e."
+#~ "Cette erreur peut aussi survenir si la séquence d'octets ne correspond pas\n"
+#~ "au jeu de caractères attendu par le serveur, le jeu étant contrôlé par\n"
+#~ "« client_encoding »."
-#~ msgid "terminating all walsender processes to force cascaded standby(s) to update timeline and reconnect"
+#~ msgid "Sets the language used in DO statement if LANGUAGE is not specified."
#~ msgstr ""
-#~ "arr�t de tous les processus walsender pour forcer les serveurs standby en\n"
-#~ "cascade � mettre � jour la timeline et � se reconnecter"
+#~ "Configure le langage utilisé dans une instruction DO si la clause LANGUAGE n'est\n"
+#~ "pas spécifiée."
-#~ msgid "shutdown requested, aborting active base backup"
-#~ msgstr "arr�t demand�, annulation de la sauvegarde active de base"
-
-#~ msgid "streaming replication successfully connected to primary"
-#~ msgstr "r�plication de flux connect� avec succ�s au serveur principal"
+#~ msgid "shared index \"%s\" can only be reindexed in stand-alone mode"
+#~ msgstr "un index partagé « %s » peut seulement être réindexé en mode autonome"
-#~ msgid "invalid standby handshake message type %d"
-#~ msgstr "type %d du message de handshake du serveur en attente invalide"
+#~ msgid "\"%s\" is a system catalog"
+#~ msgstr "« %s » est un catalogue système"
-#~ msgid "terminating walsender process to force cascaded standby to update timeline and reconnect"
-#~ msgstr ""
-#~ "arr�t du processus walreceiver pour forcer le serveur standby en cascade �\n"
-#~ "mettre � jour la timeline et � se reconnecter"
+#~ msgid "shared table \"%s\" can only be reindexed in stand-alone mode"
+#~ msgstr "la table partagée « %s » peut seulement être réindexé en mode autonome"
-#~ msgid "invalid standby query string: %s"
-#~ msgstr "cha�ne de requ�te invalide sur le serveur en attente : %s"
+#~ msgid "cannot truncate system relation \"%s\""
+#~ msgstr "ne peut pas tronquer la relation système « %s »"
-#~ msgid "large object %u was not opened for writing"
-#~ msgstr "le � Large Object � %u n'a pas �t� ouvert en �criture"
+#~ msgid "number of distinct values %g is too low"
+#~ msgstr "le nombre de valeurs distinctes %g est trop basse"
-#~ msgid "large object %u was already dropped"
-#~ msgstr "le � Large Object � %u a d�j� �t� supprim�"
+#~ msgid "directory \"%s\" is not empty"
+#~ msgstr "le répertoire « %s » n'est pas vide"
-#~ msgid "Not enough memory for reassigning the prepared transaction's locks."
-#~ msgstr "Pas assez de m�moire pour r�affecter les verrous des transactions pr�par�es."
+#~ msgid "relation \"%s\" TID %u/%u: XMIN_COMMITTED not set for transaction %u --- cannot shrink relation"
+#~ msgstr ""
+#~ "relation « %s », TID %u/%u : XMIN_COMMITTED non configuré pour la\n"
+#~ "transaction %u --- n'a pas pu diminuer la taille de la relation"
-#~ msgid "\"interval\" time zone \"%s\" not valid"
-#~ msgstr "le fuseau horaire � %s � n'est pas valide pour le type � interval �"
+#~ msgid "relation \"%s\" TID %u/%u: dead HOT-updated tuple --- cannot shrink relation"
+#~ msgstr ""
+#~ "relation « %s », TID %u/%u : ligne morte mise à jour par HOT --- n'a pas pu\n"
+#~ "diminuer la taille de la relation"
-#~ msgid "inconsistent use of year %04d and \"BC\""
-#~ msgstr "utilisation non coh�rente de l'ann�e %04d et de � BC �"
+#~ msgid "relation \"%s\" TID %u/%u: InsertTransactionInProgress %u --- cannot shrink relation"
+#~ msgstr ""
+#~ "relation « %s », TID %u/%u : InsertTransactionInProgress %u --- n'a pas pu\n"
+#~ "diminuer la taille de la relation"
-#~ msgid "No rows were found in \"%s\"."
-#~ msgstr "Aucune ligne trouv�e dans � %s �."
+#~ msgid "relation \"%s\" TID %u/%u: DeleteTransactionInProgress %u --- cannot shrink relation"
+#~ msgstr ""
+#~ "relation « %s », TID %u/%u : DeleteTransactionInProgress %u --- n'a pas pu\n"
+#~ "diminuer la taille de la relation"
-#~ msgid "argument number is out of range"
-#~ msgstr "le nombre en argument est en dehors des limites"
+#~ msgid ""
+#~ "%.0f dead row versions cannot be removed yet.\n"
+#~ "Nonremovable row versions range from %lu to %lu bytes long.\n"
+#~ "There were %.0f unused item pointers.\n"
+#~ "Total free space (including removable row versions) is %.0f bytes.\n"
+#~ "%u pages are or will become empty, including %u at the end of the table.\n"
+#~ "%u pages containing %.0f free bytes are potential move destinations.\n"
+#~ "%s."
+#~ msgstr ""
+#~ "%.0f versions de lignes mortes ne peuvent pas encore être supprimées.\n"
+#~ "Les versions non supprimables de ligne vont de %lu to %lu octets.\n"
+#~ "Il existait %.0f pointeurs d'éléments inutilisés.\n"
+#~ "L'espace libre total (incluant les versions supprimables de ligne) est de\n"
+#~ "%.0f octets.\n"
+#~ "%u pages sont ou deviendront vides, ceci incluant %u pages en fin de la\n"
+#~ "table.\n"
+#~ "%u pages contenant %.0f octets libres sont des destinations de déplacement\n"
+#~ "disponibles.\n"
+#~ "%s."
-#~ msgid "index \"%s\" is not ready"
-#~ msgstr "l'index � %s � n'est pas pr�t"
+#~ msgid "\"%s\": moved %u row versions, truncated %u to %u pages"
+#~ msgstr "« %s » : %u versions de ligne déplacées, %u pages tronquées sur %u"
-#~ msgid "could not remove database directory \"%s\""
-#~ msgstr "n'a pas pu supprimer le r�pertoire de bases de donn�es � %s �"
+#~ msgid ""
+#~ "%u index pages have been deleted, %u are currently reusable.\n"
+#~ "%s."
+#~ msgstr ""
+#~ "%u pages d'index ont été supprimées, %u sont actuellement réutilisables.\n"
+#~ "%s."
-#~ msgid "unexpected end of line at line %d of thesaurus file \"%s\""
-#~ msgstr "fin de ligne inattendue � la ligne %d du th�saurus � %s �"
+#~ msgid "index \"%s\" contains %.0f row versions, but table contains %.0f row versions"
+#~ msgstr ""
+#~ "l'index « %s » contient %.0f versions de ligne, mais la table contient %.0f\n"
+#~ "versions de ligne"
-#~ msgid "unexpected end of line or lexeme at line %d of thesaurus file \"%s\""
-#~ msgstr "fin de ligne ou de lexeme inattendu sur la ligne %d du thesaurus � %s �"
+#~ msgid "Rebuild the index with REINDEX."
+#~ msgstr "Reconstruisez l'index avec REINDEX."
-#~ msgid "unexpected delimiter at line %d of thesaurus file \"%s\""
-#~ msgstr "d�limiteur inattendu sur la ligne %d du thesaurus � %s �"
+#~ msgid "frame start at CURRENT ROW is not implemented"
+#~ msgstr "début du frame à CURRENT ROW n'est pas implémenté"
-#~ msgid "Use the @@@ operator instead."
-#~ msgstr "Utilisez � la place l'op�rateur @@@."
+#~ msgid "database system is in consistent recovery mode"
+#~ msgstr "le système de bases de données est dans un mode de restauration cohérent"
-#~ msgid "@@ operator does not support lexeme weight restrictions in GIN index searches"
-#~ msgstr ""
-#~ "l'op�rateur @@ ne supporte pas les restrictions de poids de lexeme dans les\n"
-#~ "recherches par index GIN"
+#~ msgid "DISTINCT is supported only for single-argument aggregates"
+#~ msgstr "DISTINCT est seulement supporté pour les agrégats à un seul argument"
-#~ msgid "query requires full scan, which is not supported by GIN indexes"
-#~ msgstr ""
-#~ "la requ�te n�cessite un parcours complet, ce qui n'est pas support� par les\n"
-#~ "index GIN"
+#~ msgid "index row size %lu exceeds btree maximum, %lu"
+#~ msgstr "la taille de la ligne index %lu dépasse le maximum de btree, %lu"
-#~ msgid "cannot calculate week number without year information"
-#~ msgstr "ne peut pas calculer le num�ro de la semaine sans informations sur l'ann�e"
+#~ msgid "Table contains duplicated values."
+#~ msgstr "La table contient des valeurs dupliquées."
-#~ msgid "UTF-16 to UTF-8 translation failed: %lu"
-#~ msgstr "�chec de la conversion d'UTF16 vers UTF8 : %lu"
+#~ msgid "Automatically adds missing table references to FROM clauses."
+#~ msgstr ""
+#~ "Ajoute automatiquement les références à la table manquant dans les clauses\n"
+#~ "FROM."
-#~ msgid "AM/PM hour must be between 1 and 12"
-#~ msgstr "l'heure AM/PM doit �tre compris entre 1 et 12"
+#~ msgid "Sets the regular expression \"flavor\"."
+#~ msgstr "Initialise l'expression rationnelle « flavor »."
-#~ msgid "Sat"
-#~ msgstr "Sam"
+#~ msgid "attempted change of parameter \"%s\" ignored"
+#~ msgstr "tentative de modification du paramètre « %s » ignoré"
-#~ msgid "Fri"
-#~ msgstr "Ven"
+#~ msgid "This parameter cannot be changed after server start."
+#~ msgstr "Ce paramètre ne peut pas être modifié après le lancement du serveur"
-#~ msgid "Thu"
-#~ msgstr "Jeu"
+#~ msgid "invalid database name \"%s\""
+#~ msgstr "nom de base de données « %s » invalide"
-#~ msgid "Wed"
-#~ msgstr "Mer"
+#~ msgid "invalid role name \"%s\""
+#~ msgstr "nom de rôle « %s » invalide"
-#~ msgid "Tue"
-#~ msgstr "Mar"
+#~ msgid "invalid role password \"%s\""
+#~ msgstr "mot de passe « %s » de l'utilisateur invalide"
-#~ msgid "Mon"
-#~ msgstr "Lun"
+#~ msgid "cannot specify CSV in BINARY mode"
+#~ msgstr "ne peut pas spécifier CSV en mode binaire (BINARY)"
-#~ msgid "Sun"
-#~ msgstr "Dim"
+#~ msgid "cannot set session authorization within security-definer function"
+#~ msgstr "ne peut pas exécuter SESSION AUTHORIZATION sur la fonction SECURITY DEFINER"
-#~ msgid "Saturday"
-#~ msgstr "Samedi"
+#~ msgid "SELECT FOR UPDATE/SHARE is not supported within a query with multiple result relations"
+#~ msgstr ""
+#~ "SELECT FOR UPDATE/SHARE n'est pas supporté dans une requête avec plusieurs\n"
+#~ "relations"
-#~ msgid "Friday"
-#~ msgstr "Vendredi"
+#~ msgid "could not remove relation %s: %m"
+#~ msgstr "n'a pas pu supprimer la relation %s : %m"
-#~ msgid "Thursday"
-#~ msgstr "Jeudi"
+#~ msgid "could not remove segment %u of relation %s: %m"
+#~ msgstr "n'a pas pu supprimer le segment %u de la relation %s : %m"
-#~ msgid "Wednesday"
-#~ msgstr "Mercredi"
+#~ msgid "could not seek to block %u of relation %s: %m"
+#~ msgstr "n'a pas pu se positionner sur le bloc %u de la relation %s : %m"
-#~ msgid "Tuesday"
-#~ msgstr "Mardi"
+#~ msgid "could not extend relation %s: %m"
+#~ msgstr "n'a pas pu étendre la relation %s : %m"
-#~ msgid "Monday"
-#~ msgstr "Lundi"
+#~ msgid "could not open relation %s: %m"
+#~ msgstr "n'a pas pu ouvrir la relation %s : %m"
-#~ msgid "Sunday"
-#~ msgstr "Dimanche"
+#~ msgid "could not read block %u of relation %s: %m"
+#~ msgstr "n'a pas pu lire le bloc %u de la relation %s : %m"
-#~ msgid "Dec"
-#~ msgstr "D�c"
+#~ msgid "could not write block %u of relation %s: %m"
+#~ msgstr "n'a pas pu écrire le bloc %u de la relation %s : %m"
-#~ msgid "Nov"
-#~ msgstr "Nov"
+#~ msgid "could not open segment %u of relation %s: %m"
+#~ msgstr "n'a pas pu ouvrir le segment %u de la relation %s : %m"
-#~ msgid "Oct"
-#~ msgstr "Oct"
+#~ msgid "could not fsync segment %u of relation %s: %m"
+#~ msgstr ""
+#~ "n'a pas pu synchroniser sur disque (fsync) le segment %u de la relation\n"
+#~ "%s : %m"
-#~ msgid "Sep"
-#~ msgstr "Sep"
+#~ msgid "could not fsync segment %u of relation %s but retrying: %m"
+#~ msgstr ""
+#~ "n'a pas pu synchroniser sur disque (fsync) le segment %u de la relation\n"
+#~ "%s, nouvelle tentative : %m"
-#~ msgid "Aug"
-#~ msgstr "Ao�"
+#~ msgid "could not seek to end of segment %u of relation %s: %m"
+#~ msgstr "n'a pas pu se déplacer à la fin du segment %u de la relation %s : %m"
-#~ msgid "Jul"
-#~ msgstr "Juil"
+#~ msgid "unsupported PAM conversation %d/%s"
+#~ msgstr "conversation PAM %d/%s non supportée"
-#~ msgid "Jun"
-#~ msgstr "Juin"
+#~ msgid "SELECT FOR UPDATE/SHARE is not allowed in subqueries"
+#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autorisé dans les sous-requêtes"
-#~ msgid "S:May"
-#~ msgstr "S:Mai"
+#~ msgid "adding missing FROM-clause entry for table \"%s\""
+#~ msgstr "ajout d'une entrée manquante dans FROM (table « %s »)"
-#~ msgid "Apr"
-#~ msgstr "Avr"
+#~ msgid "OLD used in query that is not in a rule"
+#~ msgstr "OLD utilisé dans une requête qui n'est pas une règle"
-#~ msgid "Mar"
-#~ msgstr "Mar"
+#~ msgid "NEW used in query that is not in a rule"
+#~ msgstr "NEW utilisé dans une requête qui ne fait pas partie d'une règle"
-#~ msgid "Feb"
-#~ msgstr "F�v"
+#~ msgid "hurrying in-progress restartpoint"
+#~ msgstr "accélération du restartpoint en cours"
-#~ msgid "Jan"
-#~ msgstr "Jan"
+#~ msgid "multiple DELETE events specified"
+#~ msgstr "multiples événements DELETE spécifiés"
-#~ msgid "December"
-#~ msgstr "D�cembre"
+#~ msgid "multiple UPDATE events specified"
+#~ msgstr "multiples événements UPDATE spécifiés"
-#~ msgid "November"
-#~ msgstr "Novembre"
+#~ msgid "multiple TRUNCATE events specified"
+#~ msgstr "multiples événements TRUNCATE spécifiés"
-#~ msgid "October"
-#~ msgstr "Octobre"
+#~ msgid "could not create XPath object"
+#~ msgstr "n'a pas pu créer l'objet XPath"
-#~ msgid "September"
-#~ msgstr "Septembre"
+#, fuzzy
+#~ msgid "wrong number of array_subscripts"
+#~ msgstr "mauvais nombre d'indices du tableau"
-#~ msgid "August"
-#~ msgstr "Ao�t"
+#~ msgid "fillfactor=%d is out of range (should be between %d and 100)"
+#~ msgstr "le facteur de remplissage (%d) est en dehors des limites (il devrait être entre %d et 100)"
-#~ msgid "July"
-#~ msgstr "Juillet"
+#~ msgid "GIN index does not support search with void query"
+#~ msgstr "les index GIN ne supportent pas la recherche avec des requêtes vides"
-#~ msgid "June"
-#~ msgstr "Juin"
+#~ msgid "invalid LC_COLLATE setting"
+#~ msgstr "paramètre LC_COLLATE invalide"
-#~ msgid "May"
-#~ msgstr "Mai"
+#~ msgid "invalid LC_CTYPE setting"
+#~ msgstr "paramètre LC_CTYPE invalide"
-#~ msgid "April"
-#~ msgstr "Avril"
+#~ msgid "The database cluster was initialized with LOCALE_NAME_BUFLEN %d, but the server was compiled with LOCALE_NAME_BUFLEN %d."
+#~ msgstr ""
+#~ "Le cluster de bases de données a été initialisé avec un LOCALE_NAME_BUFLEN\n"
+#~ "à %d alors que le serveur a été compilé avec un LOCALE_NAME_BUFLEN à %d."
-#~ msgid "March"
-#~ msgstr "Mars"
+#~ msgid "It looks like you need to initdb or install locale support."
+#~ msgstr ""
+#~ "Il semble que vous avez besoin d'exécuter initdb ou d'installer le support\n"
+#~ "des locales."
-#~ msgid "February"
-#~ msgstr "F�vrier"
+#~ msgid "log_restartpoints = %s"
+#~ msgstr "log_restartpoints = %s"
-#~ msgid "January"
-#~ msgstr "Janvier"
+#~ msgid "syntax error: cannot back up"
+#~ msgstr "erreur de syntaxe : n'a pas pu revenir"
-#~ msgid "\"TZ\"/\"tz\" not supported"
-#~ msgstr "� TZ �/� tz � non support�"
+#~ msgid "syntax error; also virtual memory exhausted"
+#~ msgstr "erreur de syntaxe ; de plus, mémoire virtuelle saturée"
-#~ msgid "invalid AM/PM string"
-#~ msgstr "cha�ne AM/PM invalide"
+#~ msgid "parser stack overflow"
+#~ msgstr "saturation de la pile de l'analyseur"
-#~ msgid "not unique \"S\""
-#~ msgstr "� S � non unique"
+#~ msgid "failed to drop all objects depending on %s"
+#~ msgstr "échec lors de la suppression de tous les objets dépendant de %s"
-#~ msgid "invalid argument for power function"
-#~ msgstr "argument invalide pour la fonction puissance (power)"
+#~ msgid "there are objects dependent on %s"
+#~ msgstr "des objets dépendent de %s"
-#~ msgid "Valid values are DOCUMENT and CONTENT."
-#~ msgstr "Les valeurs valides sont DOCUMENT et CONTENT."
+#~ msgid "multiple constraints named \"%s\" were dropped"
+#~ msgstr "les contraintes multiples nommées « %s » ont été supprimées"
-#~ msgid "Valid values are LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7."
+#~ msgid "constraint definition for check constraint \"%s\" does not match"
#~ msgstr ""
-#~ "Les valeurs valides sont LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5,\n"
-#~ "LOCAL6, LOCAL7."
+#~ "la définition de la contrainte « %s » pour la contrainte de vérification ne\n"
+#~ "correspond pas"
-#~ msgid "This can be set to advanced, extended, or basic."
+#~ msgid "relation \"%s.%s\" contains more than \"max_fsm_pages\" pages with useful free space"
#~ msgstr ""
-#~ "Ceci peut �tre initialis� avec advanced (avanc�), extended (�tendu) ou\n"
-#~ "basic (basique)."
-
-#~ msgid "Sets the hostname of the Kerberos server."
-#~ msgstr "Initalise le nom d'h�te du serveur Kerberos."
+#~ "la relation « %s.%s » contient plus de « max_fsm_pages » pages d'espace\n"
+#~ "libre utile"
-#~ msgid "Sets realm to match Kerberos and GSSAPI users against."
+#~ msgid "Consider using VACUUM FULL on this relation or increasing the configuration parameter \"max_fsm_pages\"."
#~ msgstr ""
-#~ "Indique le royaume pour l'authentification des utilisateurs via Kerberos et\n"
-#~ "GSSAPI."
+#~ "Pensez à compacter cette relation en utilisant VACUUM FULL ou à augmenter le\n"
+#~ "paramètre de configuration « max_fsm_pages »."
-#~ msgid "Each session can be either \"origin\", \"replica\", or \"local\"."
-#~ msgstr "Chaque session peut valoir soit � origin � soit � replica � soit � local �."
+#~ msgid "cannot change number of columns in view"
+#~ msgstr "ne peut pas modifier le nombre de colonnes dans la vue"
-#~ msgid "Each SQL transaction has an isolation level, which can be either \"read uncommitted\", \"read committed\", \"repeatable read\", or \"serializable\"."
+#~ msgid "unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")"
#~ msgstr ""
-#~ "Chaque transaction SQL a un niveau d'isolation qui peut �tre soit � read\n"
-#~ "uncommitted �, soit � read committed �, soit � repeatable read �, soit\n"
-#~ "� serializable �."
+#~ "nom d'utilisateur Kerberos inattendu reçu à partir du client (reçu « %s »,\n"
+#~ "attendu « %s »)"
-#~ msgid "All SQL statements that cause an error of the specified level or a higher level are logged."
-#~ msgstr ""
-#~ "Toutes les instructions SQL causant une erreur du niveau sp�cifi� ou d'un\n"
-#~ "niveau sup�rieur sont trac�es."
+#~ msgid "Kerberos 5 not implemented on this server"
+#~ msgstr "Kerberos 5 non implémenté sur ce serveur"
-#~ msgid "Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. Each level includes all the levels that follow it."
-#~ msgstr ""
-#~ "Les valeurs valides sont DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO,\n"
-#~ "NOTICE, WARNING, ERROR, LOG, FATAL et PANIC. Chaque niveau incut tous les\n"
-#~ "niveaux qui le suit."
+#~ msgid "GSSAPI not implemented on this server"
+#~ msgstr "GSSAPI non implémenté sur ce serveur"
-#~ msgid "Valid values are ON, OFF, and SAFE_ENCODING."
-#~ msgstr "Les valeurs valides sont ON, OFF et SAFE_ENCODING."
+#~ msgid "could not get security token from context"
+#~ msgstr "n'a pas pu récupérer le jeton de sécurité à partir du contexte"
-#~ msgid "Sets the maximum number of disk pages for which free space is tracked."
+#~ msgid "unsafe permissions on private key file \"%s\""
+#~ msgstr "droits non sûrs sur le fichier de la clé privée « %s »"
+
+#~ msgid "File must be owned by the database user and must have no permissions for \"group\" or \"other\"."
#~ msgstr ""
-#~ "Initialise le nombre maximum de pages disque pour lesquelles l'espace libre\n"
-#~ "est trac�."
+#~ "Le fichier doit appartenir au propriétaire de la base de données et ne doit\n"
+#~ "pas avoir de droits pour un groupe ou pour les autres."
-#~ msgid "Sets the maximum number of tables and indexes for which free space is tracked."
+#~ msgid "cannot use authentication method \"crypt\" because password is MD5-encrypted"
#~ msgstr ""
-#~ "Initialise le nombre maximum de tables et index pour lesquels l'espace libre\n"
-#~ "est trac�."
+#~ "n'a pas pu utiliser la méthode d'authentification « crypt » car le mot de\n"
+#~ "passe est chiffré avec MD5"
-#~ msgid "Uses the indented output format for EXPLAIN VERBOSE."
-#~ msgstr "Utilise le format de sortie indent� pour EXPLAIN VERBOSE."
+#~ msgid "invalid entry in file \"%s\" at line %d, token \"%s\""
+#~ msgstr "entrée invalide dans le fichier « %s » à la ligne %d, jeton « %s »"
-#~ msgid "Prints the execution plan to server log."
-#~ msgstr "Affiche le plan d'ex�cution dans les journaux applicatifs du serveur."
+#~ msgid "missing field in file \"%s\" at end of line %d"
+#~ msgstr "champ manquant dans le fichier « %s » à la fin de la ligne %d"
-#~ msgid "Prints the parse tree after rewriting to server log."
-#~ msgstr "Affiche l'arbre d'analyse apr�s r�-�criture dans les journaux applicatifs du serveur."
+#~ msgid "cannot use Ident authentication without usermap field"
+#~ msgstr "n'a pas pu utiliser l'authentication Ident sans le champ usermap"
-#~ msgid "Prints the parse tree to the server log."
-#~ msgstr "Affiche l'arbre d'analyse dans les journaux applicatifs du serveur."
+#~ msgid "Ident protocol identifies remote user as \"%s\""
+#~ msgstr "le protocole Ident identifie l'utilisateur distant comme « %s »"
-#~ msgid "string is too long for tsvector"
-#~ msgstr "la cha�ne est trop longue pour un tsvector"
+#~ msgid "SELECT FOR UPDATE/SHARE is not supported for inheritance queries"
+#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas supporté pour les requêtes d'héritage"
-#~ msgid "Consider increasing the configuration parameter \"max_fsm_pages\" to a value over %.0f."
-#~ msgstr ""
-#~ "Consid�rez l'augmentation du param�tre de configuration � max_fsm_pages �\n"
-#~ "� une valeur sup�rieure � %.0f."
+#~ msgid "missing FROM-clause entry in subquery for table \"%s\""
+#~ msgstr "entrée manquante de la clause FROM dans la sous-requête de la table « %s »"
-#~ msgid "number of page slots needed (%.0f) exceeds max_fsm_pages (%d)"
-#~ msgstr "le nombre d'emplacements de pages n�cessaires (%.0f) d�passe max_fsm_pages (%d)"
+#~ msgid "adding missing FROM-clause entry in subquery for table \"%s\""
+#~ msgstr "entrée manquante de la clause FROM dans la sous-requête pour la table « %s »"
-#~ msgid "You have at least %d relations. Consider increasing the configuration parameter \"max_fsm_relations\"."
+#~ msgid "%s: the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16\n"
#~ msgstr ""
-#~ "Vous avez au moins %d relations.Consid�rez l'augmentation du param�tre de\n"
-#~ "configuration � max_fsm_relations �."
+#~ "%s : le nombre de tampons (-B) doit être au moins deux fois le nombre de\n"
+#~ "connexions disponibles (-N) et au moins 16\n"
-#~ msgid "max_fsm_relations(%d) equals the number of relations checked"
-#~ msgstr "max_fsm_relations(%d) �quivaut au nombre de relations trac�es"
+#~ msgid "could not set statistics collector timer: %m"
+#~ msgstr "n'a pas pu configurer le timer du récupérateur de statistiques : %m"
+
+#~ msgid "insufficient shared memory for free space map"
+#~ msgstr "mémoire partagée insuffisante pour la structure FSM"
+
+#~ msgid "max_fsm_pages must exceed max_fsm_relations * %d"
+#~ msgstr "max_fsm_pages doit excéder max_fsm_relations * %d"
+
+#~ msgid "free space map contains %d pages in %d relations"
+#~ msgstr "la structure FSM contient %d pages dans %d relations"
#~ msgid ""
#~ "A total of %.0f page slots are in use (including overhead).\n"
#~ "%.0f page slots are required to track all free space.\n"
#~ "Current limits are: %d page slots, %d relations, using %.0f kB."
#~ msgstr ""
-#~ "Un total de %.0f emplacements de pages est utilis� (ceci incluant la\n"
+#~ "Un total de %.0f emplacements de pages est utilisé (ceci incluant la\n"
#~ "surcharge).\n"
#~ "%.0f emplacements de pages sont requis pour tracer tout l'espace libre.\n"
#~ "Les limites actuelles sont : %d emplacements de pages, %d relations,\n"
#~ "utilisant %.0f Ko."
-#~ msgid "free space map contains %d pages in %d relations"
-#~ msgstr "la structure FSM contient %d pages dans %d relations"
-
-#~ msgid "max_fsm_pages must exceed max_fsm_relations * %d"
-#~ msgstr "max_fsm_pages doit exc�der max_fsm_relations * %d"
-
-#~ msgid "insufficient shared memory for free space map"
-#~ msgstr "m�moire partag�e insuffisante pour la structure FSM"
-
-#~ msgid "could not set statistics collector timer: %m"
-#~ msgstr "n'a pas pu configurer le timer du r�cup�rateur de statistiques : %m"
+#~ msgid "max_fsm_relations(%d) equals the number of relations checked"
+#~ msgstr "max_fsm_relations(%d) équivaut au nombre de relations tracées"
-#~ msgid "%s: the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16\n"
+#~ msgid "You have at least %d relations. Consider increasing the configuration parameter \"max_fsm_relations\"."
#~ msgstr ""
-#~ "%s : le nombre de tampons (-B) doit �tre au moins deux fois le nombre de\n"
-#~ "connexions disponibles (-N) et au moins 16\n"
+#~ "Vous avez au moins %d relations.Considèrez l'augmentation du paramètre de\n"
+#~ "configuration « max_fsm_relations »."
-#~ msgid "adding missing FROM-clause entry in subquery for table \"%s\""
-#~ msgstr "entr�e manquante de la clause FROM dans la sous-requ�te pour la table � %s �"
+#~ msgid "number of page slots needed (%.0f) exceeds max_fsm_pages (%d)"
+#~ msgstr "le nombre d'emplacements de pages nécessaires (%.0f) dépasse max_fsm_pages (%d)"
-#~ msgid "missing FROM-clause entry in subquery for table \"%s\""
-#~ msgstr "entr�e manquante de la clause FROM dans la sous-requ�te de la table � %s �"
+#~ msgid "Consider increasing the configuration parameter \"max_fsm_pages\" to a value over %.0f."
+#~ msgstr ""
+#~ "Considérez l'augmentation du paramètre de configuration « max_fsm_pages »\n"
+#~ "à une valeur supérieure à %.0f."
-#~ msgid "SELECT FOR UPDATE/SHARE is not supported for inheritance queries"
-#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas support� pour les requ�tes d'h�ritage"
+#~ msgid "string is too long for tsvector"
+#~ msgstr "la chaîne est trop longue pour un tsvector"
-#~ msgid "Ident protocol identifies remote user as \"%s\""
-#~ msgstr "le protocole Ident identifie l'utilisateur distant comme � %s �"
+#~ msgid "Prints the parse tree to the server log."
+#~ msgstr "Affiche l'arbre d'analyse dans les journaux applicatifs du serveur."
-#~ msgid "cannot use Ident authentication without usermap field"
-#~ msgstr "n'a pas pu utiliser l'authentication Ident sans le champ usermap"
+#~ msgid "Prints the parse tree after rewriting to server log."
+#~ msgstr "Affiche l'arbre d'analyse après ré-écriture dans les journaux applicatifs du serveur."
-#~ msgid "missing field in file \"%s\" at end of line %d"
-#~ msgstr "champ manquant dans le fichier � %s � � la fin de la ligne %d"
+#~ msgid "Prints the execution plan to server log."
+#~ msgstr "Affiche le plan d'exécution dans les journaux applicatifs du serveur."
-#~ msgid "invalid entry in file \"%s\" at line %d, token \"%s\""
-#~ msgstr "entr�e invalide dans le fichier � %s � � la ligne %d, jeton � %s �"
+#~ msgid "Uses the indented output format for EXPLAIN VERBOSE."
+#~ msgstr "Utilise le format de sortie indenté pour EXPLAIN VERBOSE."
-#~ msgid "cannot use authentication method \"crypt\" because password is MD5-encrypted"
+#~ msgid "Sets the maximum number of tables and indexes for which free space is tracked."
#~ msgstr ""
-#~ "n'a pas pu utiliser la m�thode d'authentification � crypt � car le mot de\n"
-#~ "passe est chiffr� avec MD5"
+#~ "Initialise le nombre maximum de tables et index pour lesquels l'espace libre\n"
+#~ "est tracé."
-#~ msgid "File must be owned by the database user and must have no permissions for \"group\" or \"other\"."
+#~ msgid "Sets the maximum number of disk pages for which free space is tracked."
#~ msgstr ""
-#~ "Le fichier doit appartenir au propri�taire de la base de donn�es et ne doit\n"
-#~ "pas avoir de droits pour un groupe ou pour les autres."
-
-#~ msgid "unsafe permissions on private key file \"%s\""
-#~ msgstr "droits non s�rs sur le fichier de la cl� priv�e � %s �"
+#~ "Initialise le nombre maximum de pages disque pour lesquelles l'espace libre\n"
+#~ "est tracé."
-#~ msgid "could not get security token from context"
-#~ msgstr "n'a pas pu r�cup�rer le jeton de s�curit� � partir du contexte"
+#~ msgid "Valid values are ON, OFF, and SAFE_ENCODING."
+#~ msgstr "Les valeurs valides sont ON, OFF et SAFE_ENCODING."
-#~ msgid "GSSAPI not implemented on this server"
-#~ msgstr "GSSAPI non impl�ment� sur ce serveur"
+#~ msgid "Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. Each level includes all the levels that follow it."
+#~ msgstr ""
+#~ "Les valeurs valides sont DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO,\n"
+#~ "NOTICE, WARNING, ERROR, LOG, FATAL et PANIC. Chaque niveau incut tous les\n"
+#~ "niveaux qui le suit."
-#~ msgid "Kerberos 5 not implemented on this server"
-#~ msgstr "Kerberos 5 non impl�ment� sur ce serveur"
+#~ msgid "All SQL statements that cause an error of the specified level or a higher level are logged."
+#~ msgstr ""
+#~ "Toutes les instructions SQL causant une erreur du niveau spécifié ou d'un\n"
+#~ "niveau supérieur sont tracées."
-#~ msgid "unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")"
+#~ msgid "Each SQL transaction has an isolation level, which can be either \"read uncommitted\", \"read committed\", \"repeatable read\", or \"serializable\"."
#~ msgstr ""
-#~ "nom d'utilisateur Kerberos inattendu re�u � partir du client (re�u � %s �,\n"
-#~ "attendu � %s �)"
+#~ "Chaque transaction SQL a un niveau d'isolation qui peut être soit « read\n"
+#~ "uncommitted », soit « read committed », soit « repeatable read », soit\n"
+#~ "« serializable »."
-#~ msgid "cannot change number of columns in view"
-#~ msgstr "ne peut pas modifier le nombre de colonnes dans la vue"
+#~ msgid "Each session can be either \"origin\", \"replica\", or \"local\"."
+#~ msgstr "Chaque session peut valoir soit « origin » soit « replica » soit « local »."
-#~ msgid "Consider using VACUUM FULL on this relation or increasing the configuration parameter \"max_fsm_pages\"."
+#~ msgid "Sets realm to match Kerberos and GSSAPI users against."
#~ msgstr ""
-#~ "Pensez � compacter cette relation en utilisant VACUUM FULL ou � augmenter le\n"
-#~ "param�tre de configuration � max_fsm_pages �."
+#~ "Indique le royaume pour l'authentification des utilisateurs via Kerberos et\n"
+#~ "GSSAPI."
-#~ msgid "relation \"%s.%s\" contains more than \"max_fsm_pages\" pages with useful free space"
+#~ msgid "Sets the hostname of the Kerberos server."
+#~ msgstr "Initalise le nom d'hôte du serveur Kerberos."
+
+#~ msgid "This can be set to advanced, extended, or basic."
#~ msgstr ""
-#~ "la relation � %s.%s � contient plus de � max_fsm_pages � pages d'espace\n"
-#~ "libre utile"
+#~ "Ceci peut être initialisé avec advanced (avancé), extended (étendu) ou\n"
+#~ "basic (basique)."
-#~ msgid "constraint definition for check constraint \"%s\" does not match"
+#~ msgid "Valid values are LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7."
#~ msgstr ""
-#~ "la d�finition de la contrainte � %s � pour la contrainte de v�rification ne\n"
-#~ "correspond pas"
+#~ "Les valeurs valides sont LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5,\n"
+#~ "LOCAL6, LOCAL7."
-#~ msgid "multiple constraints named \"%s\" were dropped"
-#~ msgstr "les contraintes multiples nomm�es � %s � ont �t� supprim�es"
+#~ msgid "Valid values are DOCUMENT and CONTENT."
+#~ msgstr "Les valeurs valides sont DOCUMENT et CONTENT."
-#~ msgid "there are objects dependent on %s"
-#~ msgstr "des objets d�pendent de %s"
+#~ msgid "invalid argument for power function"
+#~ msgstr "argument invalide pour la fonction puissance (power)"
-#~ msgid "failed to drop all objects depending on %s"
-#~ msgstr "�chec lors de la suppression de tous les objets d�pendant de %s"
+#~ msgid "not unique \"S\""
+#~ msgstr "« S » non unique"
-#~ msgid "parser stack overflow"
-#~ msgstr "saturation de la pile de l'analyseur"
+#~ msgid "invalid AM/PM string"
+#~ msgstr "chaîne AM/PM invalide"
-#~ msgid "syntax error; also virtual memory exhausted"
-#~ msgstr "erreur de syntaxe ; de plus, m�moire virtuelle satur�e"
+#~ msgid "\"TZ\"/\"tz\" not supported"
+#~ msgstr "« TZ »/« tz » non supporté"
-#~ msgid "syntax error: cannot back up"
-#~ msgstr "erreur de syntaxe : n'a pas pu revenir"
+#~ msgid "January"
+#~ msgstr "Janvier"
-#~ msgid "log_restartpoints = %s"
-#~ msgstr "log_restartpoints = %s"
+#~ msgid "February"
+#~ msgstr "Février"
-#~ msgid "It looks like you need to initdb or install locale support."
-#~ msgstr ""
-#~ "Il semble que vous avez besoin d'ex�cuter initdb ou d'installer le support\n"
-#~ "des locales."
+#~ msgid "March"
+#~ msgstr "Mars"
-#~ msgid "The database cluster was initialized with LOCALE_NAME_BUFLEN %d, but the server was compiled with LOCALE_NAME_BUFLEN %d."
-#~ msgstr ""
-#~ "Le cluster de bases de donn�es a �t� initialis� avec un LOCALE_NAME_BUFLEN\n"
-#~ "� %d alors que le serveur a �t� compil� avec un LOCALE_NAME_BUFLEN � %d."
+#~ msgid "April"
+#~ msgstr "Avril"
-#~ msgid "invalid LC_CTYPE setting"
-#~ msgstr "param�tre LC_CTYPE invalide"
+#~ msgid "May"
+#~ msgstr "Mai"
-#~ msgid "invalid LC_COLLATE setting"
-#~ msgstr "param�tre LC_COLLATE invalide"
+#~ msgid "June"
+#~ msgstr "Juin"
-#~ msgid "GIN index does not support search with void query"
-#~ msgstr "les index GIN ne supportent pas la recherche avec des requ�tes vides"
+#~ msgid "July"
+#~ msgstr "Juillet"
-#~ msgid "fillfactor=%d is out of range (should be between %d and 100)"
-#~ msgstr "le facteur de remplissage (%d) est en dehors des limites (il devrait �tre entre %d et 100)"
+#~ msgid "August"
+#~ msgstr "Août"
-#, fuzzy
-#~ msgid "wrong number of array_subscripts"
-#~ msgstr "mauvais nombre d'indices du tableau"
+#~ msgid "September"
+#~ msgstr "Septembre"
-#~ msgid "could not create XPath object"
-#~ msgstr "n'a pas pu cr�er l'objet XPath"
+#~ msgid "October"
+#~ msgstr "Octobre"
-#~ msgid "multiple TRUNCATE events specified"
-#~ msgstr "multiples �v�nements TRUNCATE sp�cifi�s"
+#~ msgid "November"
+#~ msgstr "Novembre"
-#~ msgid "multiple UPDATE events specified"
-#~ msgstr "multiples �v�nements UPDATE sp�cifi�s"
+#~ msgid "December"
+#~ msgstr "Décembre"
-#~ msgid "multiple DELETE events specified"
-#~ msgstr "multiples �v�nements DELETE sp�cifi�s"
+#~ msgid "Jan"
+#~ msgstr "Jan"
-#~ msgid "hurrying in-progress restartpoint"
-#~ msgstr "acc�l�ration du restartpoint en cours"
+#~ msgid "Feb"
+#~ msgstr "Fév"
-#~ msgid "NEW used in query that is not in a rule"
-#~ msgstr "NEW utilis� dans une requ�te qui ne fait pas partie d'une r�gle"
+#~ msgid "Mar"
+#~ msgstr "Mar"
-#~ msgid "OLD used in query that is not in a rule"
-#~ msgstr "OLD utilis� dans une requ�te qui n'est pas une r�gle"
+#~ msgid "Apr"
+#~ msgstr "Avr"
-#~ msgid "adding missing FROM-clause entry for table \"%s\""
-#~ msgstr "ajout d'une entr�e manquante dans FROM (table � %s �)"
+#~ msgid "S:May"
+#~ msgstr "S:Mai"
-#~ msgid "SELECT FOR UPDATE/SHARE is not allowed in subqueries"
-#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autoris� dans les sous-requ�tes"
+#~ msgid "Jun"
+#~ msgstr "Juin"
-#~ msgid "unsupported PAM conversation %d/%s"
-#~ msgstr "conversation PAM %d/%s non support�e"
+#~ msgid "Jul"
+#~ msgstr "Juil"
-#~ msgid "could not seek to end of segment %u of relation %s: %m"
-#~ msgstr "n'a pas pu se d�placer � la fin du segment %u de la relation %s : %m"
+#~ msgid "Aug"
+#~ msgstr "Aoû"
-#~ msgid "could not fsync segment %u of relation %s but retrying: %m"
-#~ msgstr ""
-#~ "n'a pas pu synchroniser sur disque (fsync) le segment %u de la relation\n"
-#~ "%s, nouvelle tentative : %m"
+#~ msgid "Sep"
+#~ msgstr "Sep"
-#~ msgid "could not fsync segment %u of relation %s: %m"
-#~ msgstr ""
-#~ "n'a pas pu synchroniser sur disque (fsync) le segment %u de la relation\n"
-#~ "%s : %m"
+#~ msgid "Oct"
+#~ msgstr "Oct"
-#~ msgid "could not open segment %u of relation %s: %m"
-#~ msgstr "n'a pas pu ouvrir le segment %u de la relation %s : %m"
+#~ msgid "Nov"
+#~ msgstr "Nov"
-#~ msgid "could not write block %u of relation %s: %m"
-#~ msgstr "n'a pas pu �crire le bloc %u de la relation %s : %m"
+#~ msgid "Dec"
+#~ msgstr "Déc"
-#~ msgid "could not read block %u of relation %s: %m"
-#~ msgstr "n'a pas pu lire le bloc %u de la relation %s : %m"
+#~ msgid "Sunday"
+#~ msgstr "Dimanche"
-#~ msgid "could not open relation %s: %m"
-#~ msgstr "n'a pas pu ouvrir la relation %s : %m"
+#~ msgid "Monday"
+#~ msgstr "Lundi"
-#~ msgid "could not extend relation %s: %m"
-#~ msgstr "n'a pas pu �tendre la relation %s : %m"
+#~ msgid "Tuesday"
+#~ msgstr "Mardi"
-#~ msgid "could not seek to block %u of relation %s: %m"
-#~ msgstr "n'a pas pu se positionner sur le bloc %u de la relation %s : %m"
+#~ msgid "Wednesday"
+#~ msgstr "Mercredi"
-#~ msgid "could not remove segment %u of relation %s: %m"
-#~ msgstr "n'a pas pu supprimer le segment %u de la relation %s : %m"
+#~ msgid "Thursday"
+#~ msgstr "Jeudi"
-#~ msgid "could not remove relation %s: %m"
-#~ msgstr "n'a pas pu supprimer la relation %s : %m"
+#~ msgid "Friday"
+#~ msgstr "Vendredi"
-#~ msgid "SELECT FOR UPDATE/SHARE is not supported within a query with multiple result relations"
-#~ msgstr ""
-#~ "SELECT FOR UPDATE/SHARE n'est pas support� dans une requ�te avec plusieurs\n"
-#~ "relations"
+#~ msgid "Saturday"
+#~ msgstr "Samedi"
-#~ msgid "cannot set session authorization within security-definer function"
-#~ msgstr "ne peut pas ex�cuter SESSION AUTHORIZATION sur la fonction SECURITY DEFINER"
+#~ msgid "Sun"
+#~ msgstr "Dim"
-#~ msgid "cannot specify CSV in BINARY mode"
-#~ msgstr "ne peut pas sp�cifier CSV en mode binaire (BINARY)"
+#~ msgid "Mon"
+#~ msgstr "Lun"
-#~ msgid "invalid role password \"%s\""
-#~ msgstr "mot de passe � %s � de l'utilisateur invalide"
+#~ msgid "Tue"
+#~ msgstr "Mar"
-#~ msgid "invalid role name \"%s\""
-#~ msgstr "nom de r�le � %s � invalide"
+#~ msgid "Wed"
+#~ msgstr "Mer"
-#~ msgid "invalid database name \"%s\""
-#~ msgstr "nom de base de donn�es � %s � invalide"
+#~ msgid "Thu"
+#~ msgstr "Jeu"
-#~ msgid "This parameter cannot be changed after server start."
-#~ msgstr "Ce param�tre ne peut pas �tre modifi� apr�s le lancement du serveur"
+#~ msgid "Fri"
+#~ msgstr "Ven"
-#~ msgid "attempted change of parameter \"%s\" ignored"
-#~ msgstr "tentative de modification du param�tre � %s � ignor�"
+#~ msgid "Sat"
+#~ msgstr "Sam"
-#~ msgid "Sets the regular expression \"flavor\"."
-#~ msgstr "Initialise l'expression rationnelle � flavor �."
+#~ msgid "AM/PM hour must be between 1 and 12"
+#~ msgstr "l'heure AM/PM doit être compris entre 1 et 12"
-#~ msgid "Automatically adds missing table references to FROM clauses."
+#~ msgid "UTF-16 to UTF-8 translation failed: %lu"
+#~ msgstr "échec de la conversion d'UTF16 vers UTF8 : %lu"
+
+#~ msgid "cannot calculate week number without year information"
+#~ msgstr "ne peut pas calculer le numéro de la semaine sans informations sur l'année"
+
+#~ msgid "query requires full scan, which is not supported by GIN indexes"
#~ msgstr ""
-#~ "Ajoute automatiquement les r�f�rences � la table manquant dans les clauses\n"
-#~ "FROM."
+#~ "la requête nécessite un parcours complet, ce qui n'est pas supporté par les\n"
+#~ "index GIN"
-#~ msgid "Table contains duplicated values."
-#~ msgstr "La table contient des valeurs dupliqu�es."
+#~ msgid "@@ operator does not support lexeme weight restrictions in GIN index searches"
+#~ msgstr ""
+#~ "l'opérateur @@ ne supporte pas les restrictions de poids de lexeme dans les\n"
+#~ "recherches par index GIN"
-#~ msgid "index row size %lu exceeds btree maximum, %lu"
-#~ msgstr "la taille de la ligne index %lu d�passe le maximum de btree, %lu"
+#~ msgid "Use the @@@ operator instead."
+#~ msgstr "Utilisez à la place l'opérateur @@@."
-#~ msgid "DISTINCT is supported only for single-argument aggregates"
-#~ msgstr "DISTINCT est seulement support� pour les agr�gats � un seul argument"
+#~ msgid "unexpected delimiter at line %d of thesaurus file \"%s\""
+#~ msgstr "délimiteur inattendu sur la ligne %d du thesaurus « %s »"
-#~ msgid "database system is in consistent recovery mode"
-#~ msgstr "le syst�me de bases de donn�es est dans un mode de restauration coh�rent"
+#~ msgid "unexpected end of line or lexeme at line %d of thesaurus file \"%s\""
+#~ msgstr "fin de ligne ou de lexeme inattendu sur la ligne %d du thesaurus « %s »"
-#~ msgid "frame start at CURRENT ROW is not implemented"
-#~ msgstr "d�but du frame � CURRENT ROW n'est pas impl�ment�"
+#~ msgid "unexpected end of line at line %d of thesaurus file \"%s\""
+#~ msgstr "fin de ligne inattendue à la ligne %d du thésaurus « %s »"
-#~ msgid "Rebuild the index with REINDEX."
-#~ msgstr "Reconstruisez l'index avec REINDEX."
+#~ msgid "could not remove database directory \"%s\""
+#~ msgstr "n'a pas pu supprimer le répertoire de bases de données « %s »"
-#~ msgid "index \"%s\" contains %.0f row versions, but table contains %.0f row versions"
-#~ msgstr ""
-#~ "l'index � %s � contient %.0f versions de ligne, mais la table contient %.0f\n"
-#~ "versions de ligne"
+#~ msgid "index \"%s\" is not ready"
+#~ msgstr "l'index « %s » n'est pas prêt"
-#~ msgid ""
-#~ "%u index pages have been deleted, %u are currently reusable.\n"
-#~ "%s."
-#~ msgstr ""
-#~ "%u pages d'index ont �t� supprim�es, %u sont actuellement r�utilisables.\n"
-#~ "%s."
+#~ msgid "argument number is out of range"
+#~ msgstr "le nombre en argument est en dehors des limites"
-#~ msgid "\"%s\": moved %u row versions, truncated %u to %u pages"
-#~ msgstr "� %s � : %u versions de ligne d�plac�es, %u pages tronqu�es sur %u"
+#~ msgid "No rows were found in \"%s\"."
+#~ msgstr "Aucune ligne trouvée dans « %s »."
-#~ msgid ""
-#~ "%.0f dead row versions cannot be removed yet.\n"
-#~ "Nonremovable row versions range from %lu to %lu bytes long.\n"
-#~ "There were %.0f unused item pointers.\n"
-#~ "Total free space (including removable row versions) is %.0f bytes.\n"
-#~ "%u pages are or will become empty, including %u at the end of the table.\n"
-#~ "%u pages containing %.0f free bytes are potential move destinations.\n"
-#~ "%s."
-#~ msgstr ""
-#~ "%.0f versions de lignes mortes ne peuvent pas encore �tre supprim�es.\n"
-#~ "Les versions non supprimables de ligne vont de %lu to %lu octets.\n"
-#~ "Il existait %.0f pointeurs d'�l�ments inutilis�s.\n"
-#~ "L'espace libre total (incluant les versions supprimables de ligne) est de\n"
-#~ "%.0f octets.\n"
-#~ "%u pages sont ou deviendront vides, ceci incluant %u pages en fin de la\n"
-#~ "table.\n"
-#~ "%u pages contenant %.0f octets libres sont des destinations de d�placement\n"
-#~ "disponibles.\n"
-#~ "%s."
+#~ msgid "inconsistent use of year %04d and \"BC\""
+#~ msgstr "utilisation non cohérente de l'année %04d et de « BC »"
-#~ msgid "relation \"%s\" TID %u/%u: DeleteTransactionInProgress %u --- cannot shrink relation"
-#~ msgstr ""
-#~ "relation � %s �, TID %u/%u : DeleteTransactionInProgress %u --- n'a pas pu\n"
-#~ "diminuer la taille de la relation"
+#~ msgid "\"interval\" time zone \"%s\" not valid"
+#~ msgstr "le fuseau horaire « %s » n'est pas valide pour le type « interval »"
-#~ msgid "relation \"%s\" TID %u/%u: InsertTransactionInProgress %u --- cannot shrink relation"
-#~ msgstr ""
-#~ "relation � %s �, TID %u/%u : InsertTransactionInProgress %u --- n'a pas pu\n"
-#~ "diminuer la taille de la relation"
+#~ msgid "Not enough memory for reassigning the prepared transaction's locks."
+#~ msgstr "Pas assez de mémoire pour réaffecter les verrous des transactions préparées."
-#~ msgid "relation \"%s\" TID %u/%u: dead HOT-updated tuple --- cannot shrink relation"
+#~ msgid "large object %u was already dropped"
+#~ msgstr "le « Large Object » %u a déjà été supprimé"
+
+#~ msgid "large object %u was not opened for writing"
+#~ msgstr "le « Large Object » %u n'a pas été ouvert en écriture"
+
+#~ msgid "invalid standby query string: %s"
+#~ msgstr "chaîne de requête invalide sur le serveur en attente : %s"
+
+#~ msgid "terminating walsender process to force cascaded standby to update timeline and reconnect"
#~ msgstr ""
-#~ "relation � %s �, TID %u/%u : ligne morte mise � jour par HOT --- n'a pas pu\n"
-#~ "diminuer la taille de la relation"
+#~ "arrêt du processus walreceiver pour forcer le serveur standby en cascade à\n"
+#~ "mettre à jour la timeline et à se reconnecter"
-#~ msgid "relation \"%s\" TID %u/%u: XMIN_COMMITTED not set for transaction %u --- cannot shrink relation"
+#~ msgid "invalid standby handshake message type %d"
+#~ msgstr "type %d du message de handshake du serveur en attente invalide"
+
+#~ msgid "streaming replication successfully connected to primary"
+#~ msgstr "réplication de flux connecté avec succès au serveur principal"
+
+#~ msgid "shutdown requested, aborting active base backup"
+#~ msgstr "arrêt demandé, annulation de la sauvegarde active de base"
+
+#~ msgid "terminating all walsender processes to force cascaded standby(s) to update timeline and reconnect"
#~ msgstr ""
-#~ "relation � %s �, TID %u/%u : XMIN_COMMITTED non configur� pour la\n"
-#~ "transaction %u --- n'a pas pu diminuer la taille de la relation"
+#~ "arrêt de tous les processus walsender pour forcer les serveurs standby en\n"
+#~ "cascade à mettre à jour la timeline et à se reconnecter"
-#~ msgid "directory \"%s\" is not empty"
-#~ msgstr "le r�pertoire � %s � n'est pas vide"
+#~ msgid ""
+#~ "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently %lu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.\n"
+#~ "If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter, in which case raising the request size or reconfiguring SHMMIN is called for.\n"
+#~ "The PostgreSQL documentation contains more information about shared memory configuration."
+#~ msgstr ""
+#~ "Cette erreur signifie habituellement que la demande de PostgreSQL pour un\n"
+#~ "segment de mémoire partagée a dépassé le paramètre SHMMAX de votre noyau.\n"
+#~ "Vous pouvez soit réduire la taille de la requête soit reconfigurer le noyau\n"
+#~ "avec un SHMMAX plus important. Pour réduire la taille de la requête\n"
+#~ "(actuellement %lu octets), réduisez l'utilisation de la mémoire partagée par PostgreSQL,par exemple en réduisant shared_buffers ou max_connections\n"
+#~ "Si la taille de la requête est déjà petite, il est possible qu'elle soit\n"
+#~ "moindre que le paramètre SHMMIN de votre noyau, auquel cas, augmentez la\n"
+#~ "taille de la requête ou reconfigurez SHMMIN.\n"
+#~ "La documentation de PostgreSQL contient plus d'informations sur la\n"
+#~ "configuration de la mémoire partagée."
-#~ msgid "number of distinct values %g is too low"
-#~ msgstr "le nombre de valeurs distinctes %g est trop basse"
+#~ msgid "cannot use window function in rule WHERE condition"
+#~ msgstr "ne peut pas utiliser la fonction window dans la condition d'une règle WHERE"
-#~ msgid "cannot truncate system relation \"%s\""
-#~ msgstr "ne peut pas tronquer la relation syst�me � %s �"
+#~ msgid "cannot use aggregate function in rule WHERE condition"
+#~ msgstr "ne peut pas utiliser la fonction d'agrégat dans la condition d'une règle WHERE"
-#~ msgid "shared table \"%s\" can only be reindexed in stand-alone mode"
-#~ msgstr "la table partag�e � %s � peut seulement �tre r�index� en mode autonome"
+#~ msgid "arguments of row IN must all be row expressions"
+#~ msgstr "les arguments de la ligne IN doivent tous être des expressions de ligne"
-#~ msgid "\"%s\" is a system catalog"
-#~ msgstr "� %s � est un catalogue syst�me"
+#~ msgid "argument of %s must not contain window functions"
+#~ msgstr "l'argument de %s ne doit pas contenir des fonctions window"
-#~ msgid "shared index \"%s\" can only be reindexed in stand-alone mode"
-#~ msgstr "un index partag� � %s � peut seulement �tre r�index� en mode autonome"
+#~ msgid "argument of %s must not contain aggregate functions"
+#~ msgstr "l'argument de %s ne doit pas contenir de fonctions d'agrégats"
-#~ msgid "Sets the language used in DO statement if LANGUAGE is not specified."
+#~ msgid "cannot use window function in function expression in FROM"
#~ msgstr ""
-#~ "Configure le langage utilis� dans une instruction DO si la clause LANGUAGE n'est\n"
-#~ "pas sp�cifi�e."
+#~ "ne peut pas utiliser la fonction window dans l'expression de la fonction\n"
+#~ "du FROM"
-#~ msgid "This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by \"client_encoding\"."
+#~ msgid "function expression in FROM cannot refer to other relations of same query level"
#~ msgstr ""
-#~ "Cette erreur peut aussi survenir si la s�quence d'octets ne correspond pas\n"
-#~ "au jeu de caract�res attendu par le serveur, le jeu �tant contr�l� par\n"
-#~ "� client_encoding �."
-
-#~ msgid "redo starts at %X/%X, consistency will be reached at %X/%X"
-#~ msgstr "la restauration comme � %X/%X, la coh�rence sera atteinte � %X/%X"
+#~ "l'expression de la fonction du FROM ne peut pas faire référence à d'autres\n"
+#~ "relations sur le même niveau de la requête"
-#~ msgid "binary value is out of range for type bigint"
-#~ msgstr "la valeur binaire est en dehors des limites du type bigint"
+#~ msgid "subquery in FROM cannot refer to other relations of same query level"
+#~ msgstr ""
+#~ "la sous-requête du FROM ne peut pas faire référence à d'autres relations\n"
+#~ "dans le même niveau de la requête"
-#~ msgid "transaction is read-only"
-#~ msgstr "la transaction est en lecture seule"
+#~ msgid "JOIN/ON clause refers to \"%s\", which is not part of JOIN"
+#~ msgstr "la clause JOIN/ON se réfère à « %s », qui ne fait pas partie du JOIN"
-#~ msgid "PID %d is among the slowest backends."
-#~ msgstr "Le PID %d est parmi les processus serveur les plus lents."
+#~ msgid "window functions not allowed in GROUP BY clause"
+#~ msgstr "fonctions window non autorisées dans une clause GROUP BY"
-#, fuzzy
-#~ msgid "invalid WAL message received from primary"
-#~ msgstr "format du message invalide"
+#~ msgid "aggregates not allowed in WHERE clause"
+#~ msgstr "agrégats non autorisés dans une clause WHERE"
-#, fuzzy
-#~ msgid "sorry, too many standbys already"
-#~ msgstr "d�sol�, trop de clients sont d�j� connect�s"
+#~ msgid "SELECT FOR UPDATE/SHARE cannot be used with foreign table \"%s\""
+#~ msgstr "SELECT FOR UPDATE/SHARE ne peut pas être utilisé avec une table distante « %s »"
-#~ msgid "WAL file SYSID is %s, pg_control SYSID is %s"
-#~ msgstr "le SYSID du journal de transactions WAL est %s, celui de pg_control est %s"
+#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with window functions"
+#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autorisé avec les fonctions window"
-#, fuzzy
-#~ msgid "couldn't put socket to blocking mode: %m"
-#~ msgstr "n'a pas pu activer le mode bloquant pour la socket : %s\n"
+#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with aggregate functions"
+#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autorisé avec les fonctions d'agrégats"
-#, fuzzy
-#~ msgid "couldn't put socket to non-blocking mode: %m"
-#~ msgstr "n'a pas pu activer le mode non-bloquant pour la socket : %s\n"
+#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with HAVING clause"
+#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autorisé avec la clause HAVING"
-#~ msgid "not enough shared memory for background writer"
-#~ msgstr "pas assez de m�moire partag�e pour le processus d'�criture en t�che de fond"
+#~ msgid "SELECT FOR UPDATE/SHARE is not allowed with GROUP BY clause"
+#~ msgstr "SELECT FOR UPDATE/SHARE n'est pas autorisé avec la clause GROUP BY"
-#~ msgid "connection limit exceeded for non-superusers"
-#~ msgstr "limite de connexions d�pass�e pour les utilisateurs standards"
+#~ msgid "RETURNING cannot contain references to other relations"
+#~ msgstr "RETURNING ne doit pas contenir de références à d'autres relations"
-#~ msgid "not enough shared memory for walreceiver"
-#~ msgstr ""
-#~ "pas assez de m�moire partag�e pour le processus de r�ception des journaux de\n"
-#~ "transactions"
+#~ msgid "cannot use window function in RETURNING"
+#~ msgstr "ne peut pas utiliser une fonction window dans RETURNING"
-#~ msgid "not enough shared memory for walsender"
-#~ msgstr "pas assez de m�moire partag�e pour le processus d'envoi des journaux de transactions"
+#~ msgid "cannot use aggregate function in RETURNING"
+#~ msgstr "ne peut pas utiliser une fonction d'agrégat dans RETURNING"
-#~ msgid "unlogged operation performed, data may be missing"
-#~ msgstr "op�ration r�alis�e non trac�e, les donn�es pourraient manquer"
+#~ msgid "cannot use window function in UPDATE"
+#~ msgstr "ne peut pas utiliser une fonction window dans un UPDATE"
-#~ msgid "During recovery, allows connections and queries. During normal running, causes additional info to be written to WAL to enable hot standby mode on WAL standby nodes."
-#~ msgstr ""
-#~ "Lors de la restauration, autorise les connexions et les requ�tes. Lors d'une\n"
-#~ "ex�cution normale, fait que des informations suppl�mentaires sont �crites dans\n"
-#~ "les journaux de transactions pour activer le mode Hot Standby sur les n�uds\n"
-#~ "en attente."
+#~ msgid "cannot use aggregate function in UPDATE"
+#~ msgstr "ne peut pas utiliser une fonction d'agrégat dans un UPDATE"
-#~ msgid "archive_command must be defined before online backups can be made safely."
-#~ msgstr ""
-#~ "archive_command doit �tre d�fini avant que les sauvegardes � chaud puissent\n"
-#~ "s'effectuer correctement."
+#~ msgid "cannot use window function in VALUES"
+#~ msgstr "ne peut pas utiliser la fonction window dans un VALUES"
-#~ msgid "archive_mode must be enabled at server start."
-#~ msgstr "archive_mode doit �tre activ� au lancement du serveur."
+#~ msgid "cannot use aggregate function in VALUES"
+#~ msgstr "ne peut pas utiliser la fonction d'agrégat dans un VALUES"
-#~ msgid "WAL archiving is not active"
-#~ msgstr "l'archivage des journaux de transactions n'est pas actif"
+#~ msgid "Use SELECT ... UNION ALL ... instead."
+#~ msgstr "Utilisez à la place SELECT ... UNION ALL ..."
-#~ msgid "usermap \"%s\""
-#~ msgstr "correspondance utilisateur � %s �"
+#~ msgid "VALUES must not contain OLD or NEW references"
+#~ msgstr "VALUES ne doit pas contenir des références à OLD et NEW"
-#~ msgid "restartpoint_command = '%s'"
-#~ msgstr "restartpoint_command = '%s'"
+#~ msgid "VALUES must not contain table references"
+#~ msgstr "VALUES ne doit pas contenir de références de table"
-#~ msgid "recovery restart point at %X/%X with latest known log time %s"
+#~ msgid "LDAP search failed for filter \"%s\" on server \"%s\": user is not unique (%ld matches)"
#~ msgstr ""
-#~ "point de relancement de la restauration sur %X/%X avec %s comme derni�re\n"
-#~ "date connue du journal"
+#~ "échec de la recherche LDAP pour le filtre « %s » sur le serveur « %s » :\n"
+#~ "utilisateur non unique (%ld correspondances)"
-#~ msgid "Not safe to send CSV data\n"
-#~ msgstr "Envoi non s�r des donn�es CSV\n"
+#~ msgid "You need an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger."
+#~ msgstr "Vous avez besoin d'une règle inconditionnelle ON DELETE DO INSTEAD ou d'un trigger INSTEAD OF DELETE."
-#~ msgid "Sets the message levels that are logged during recovery."
-#~ msgstr "Initialise les niveaux de messages qui sont trac�s lors de la restauration."
+#~ msgid "You need an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger."
+#~ msgstr "Vous avez besoin d'une règle non conditionnelle ON UPDATE DO INSTEAD ou d'un trigger INSTEAD OF UPDATE."
-#~ msgid "parameter \"standby_mode\" requires a Boolean value"
-#~ msgstr "le param�tre � standby_mode � requiert une valeur bool�enne"
+#~ msgid "You need an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger."
+#~ msgstr "Vous avez besoin d'une règle ON INSERT DO INSTEAD sans condition ou d'un trigger INSTEAD OF INSERT."
-#~ msgid "parameter \"recovery_target_inclusive\" requires a Boolean value"
-#~ msgstr "le param�tre � recovery_target_inclusive � requiert une valeur bool�enne"
+#~ msgid "automatic vacuum of table \"%s.%s.%s\": cannot (re)acquire exclusive lock for truncate scan"
+#~ msgstr "vacuum automatique de la table « %s.%s.%s » : ne peut pas acquérir le verrou exclusif pour la tronquer"
-#~ msgid "cannot drop \"%s\" because it is being used by active queries in this session"
+#~ msgid "must be superuser to rename text search templates"
+#~ msgstr "doit être super-utilisateur pour renommer les modèles de recherche plein texte"
+
+#~ msgid "must be superuser to rename text search parsers"
#~ msgstr ""
-#~ "ne peut pas supprimer � %s � car cet objet est en cours d'utilisation par\n"
-#~ "des requ�tes actives dans cette session"
+#~ "doit être super-utilisateur pour renommer les analyseurs de recherche plein\n"
+#~ "texte"
-#~ msgid "unrecognized \"log_destination\" key word: \"%s\""
-#~ msgstr "mot cl� � log_destination � non reconnu : � %s �"
+#~ msgid "cannot use window function in trigger WHEN condition"
+#~ msgstr "ne peut pas utiliser la fonction window dans la condition WHEN d'un trigger"
-#~ msgid "invalid list syntax for parameter \"log_destination\""
-#~ msgstr "syntaxe de liste invalide pour le param�tre � log_destination �"
+#~ msgid "Use ALTER FOREIGN TABLE instead."
+#~ msgstr "Utilisez ALTER FOREIGN TABLE à la place."
-#~ msgid "Sets immediate fsync at commit."
-#~ msgstr "Configure un fsync imm�diat lors du commit."
+#~ msgid "cannot use window function in transform expression"
+#~ msgstr "ne peut pas utiliser la fonction window dans l'expression de la transformation"
-#~ msgid "could not open new log file \"%s\": %m"
-#~ msgstr "n'a pas pu ouvrir le nouveau journal applicatif � %s � : %m"
+#~ msgid "default values on foreign tables are not supported"
+#~ msgstr "les valeurs par défaut ne sont pas supportées sur les tables distantes"
-#~ msgid "could not create log file \"%s\": %m"
-#~ msgstr "n'a pas pu cr�er le journal applicatif � %s � : %m"
+#~ msgid "constraints on foreign tables are not supported"
+#~ msgstr "les contraintes sur les tables distantes ne sont pas supportées"
-#~ msgid "Ident authentication is not supported on local connections on this platform"
-#~ msgstr "l'authentification Ident n'est pas support�e sur les connexions locales sur cette plateforme"
+#~ msgid "cannot use window function in EXECUTE parameter"
+#~ msgstr "ne peut pas utiliser une fonction window dans le paramètre EXECUTE"
-#~ msgid "could not get effective UID from peer credentials: %m"
-#~ msgstr "n'a pas pu obtenir l'UID r�el � partir des pi�ces d'identit� de l'autre : %m"
+#~ msgid "cannot use aggregate in index predicate"
+#~ msgstr "ne peut pas utiliser un agrégat dans un prédicat d'index"
-#~ msgid "could not enable credential reception: %m"
-#~ msgstr "n'a pas pu activer la r�ception de lettres de cr�ance : %m"
+#~ msgid "function \"%s\" already exists in schema \"%s\""
+#~ msgstr "la fonction « %s » existe déjà dans le schéma « %s »"
-#~ msgid "argument to pg_get_expr() must come from system catalogs"
-#~ msgstr "l'argument de pg_get_expr() doit provenir des catalogues syst�mes"
+#~ msgid "Use ALTER AGGREGATE to change owner of aggregate functions."
+#~ msgstr "Utiliser ALTER AGGREGATE pour changer le propriétaire des fonctions d'agrégat."
-#~ msgid "invalid interval value for time zone: day not allowed"
-#~ msgstr "valeur d'intervalle invalide pour le fuseau horaire : jour non autoris�"
+#~ msgid "Use ALTER AGGREGATE to rename aggregate functions."
+#~ msgstr "Utiliser ALTER AGGREGATE pour renommer les fonctions d'agrégat."
-#~ msgid "invalid interval value for time zone: month not allowed"
-#~ msgstr "valeur d'intervalle invalide pour le fuseau horaire : les mois ne sont pas autoris�s"
+#~ msgid "cannot use window function in parameter default value"
+#~ msgstr "ne peut pas utiliser la fonction window dans la valeur par défaut d'un paramètre"
-#~ msgid "unrecognized \"datestyle\" key word: \"%s\""
-#~ msgstr "mot cl� � datestyle � non reconnu : � %s �"
+#~ msgid "cannot use aggregate function in parameter default value"
+#~ msgstr ""
+#~ "ne peut pas utiliser une fonction d'agrégat dans la valeur par défaut d'un\n"
+#~ "paramètre"
-#~ msgid "invalid list syntax for parameter \"datestyle\""
-#~ msgstr "syntaxe de liste invalide pour le param�tre � datestyle �"
+#~ msgid "cannot use subquery in parameter default value"
+#~ msgstr "ne peut pas utiliser une sous-requête dans une valeur par défaut d'un paramètre"
-#~ msgid "database \"%s\" not found"
-#~ msgstr "base de donn�es � %s � non trouv�e"
+#~ msgid "CREATE TABLE AS specifies too many column names"
+#~ msgstr "CREATE TABLE AS spécifie trop de noms de colonnes"
-#~ msgid "composite type must have at least one attribute"
-#~ msgstr "le type composite doit avoir au moins un attribut"
+#~ msgid "%s already exists in schema \"%s\""
+#~ msgstr "%s existe déjà dans le schéma « %s »"
-#~ msgid "cannot reference permanent table from temporary table constraint"
+#~ msgid "A function returning ANYRANGE must have at least one ANYRANGE argument."
#~ msgstr ""
-#~ "ne peut pas r�f�rencer une table permanente � partir de la contrainte de\n"
-#~ "table temporaire"
+#~ "Une fonction renvoyant ANYRANGE doit avoir au moins un argument du type\n"
+#~ "ANYRANGE."
-#~ msgid "cannot reference temporary table from permanent table constraint"
-#~ msgstr ""
-#~ "ne peut pas r�f�rencer une table temporaire � partir d'une contrainte de\n"
-#~ "table permanente"
+#~ msgid "cannot use window function in check constraint"
+#~ msgstr "ne peut pas utiliser une fonction window dans une contrainte de vérification"
-#~ msgid "function \"%s\" is already in schema \"%s\""
-#~ msgstr "la fonction � %s � existe d�j� dans le sch�ma � %s �"
+#~ msgid "cannot use window function in default expression"
+#~ msgstr "ne peut pas utiliser une fonction window dans une expression par défaut"
-#~ msgid "must be superuser to comment on text search template"
-#~ msgstr ""
-#~ "doit �tre super-utilisateur pour ajouter un commentaire sur un mod�le de\n"
-#~ "recherche plein texte"
+#~ msgid "cannot use aggregate function in default expression"
+#~ msgstr "ne peut pas utiliser une fonction d'agrégat dans une expression par défaut"
-#~ msgid "must be superuser to comment on text search parser"
-#~ msgstr ""
-#~ "doit �tre super-utilisateur pour ajouter un commentaire sur l'analyseur de\n"
-#~ "recherche plein texte"
+#~ msgid "cannot use subquery in default expression"
+#~ msgstr "ne peut pas utiliser une sous-requête dans l'expression par défaut"
-#~ msgid "must be superuser to comment on procedural language"
-#~ msgstr ""
-#~ "doit �tre super-utilisateur pour ajouter un commentaire sur un langage de\n"
-#~ "proc�dures"
+#~ msgid "uncataloged table %s"
+#~ msgstr "table %s sans catalogue"
-#~ msgid "\"%s\" is not a table, view, or composite type"
-#~ msgstr "� %s � n'est pas une table, une vue ou un type composite"
+#~ msgid "xrecoff \"%X\" is out of valid range, 0..%X"
+#~ msgstr "xrecoff « %X » en dehors des limites valides, 0..%X"
-#~ msgid "cannot cluster on expressional index \"%s\" because its index access method does not handle null values"
-#~ msgstr ""
-#~ "ne peut pas ex�cuter CLUSTER sur l'index � expression � %s � car sa m�thode\n"
-#~ "d'acc�s ne g�re pas les valeurs NULL"
+#~ msgid "Incorrect XLOG_BLCKSZ in page header."
+#~ msgstr "XLOG_BLCKSZ incorrect dans l'en-tête de page."
-#~ msgid "You might be able to work around this by marking column \"%s\" NOT NULL."
-#~ msgstr "Vous pouvez contourner ceci en marquant la colonne � %s � comme NOT NULL."
+#~ msgid "Incorrect XLOG_SEG_SIZE in page header."
+#~ msgstr "XLOG_SEG_SIZE incorrecte dans l'en-tête de page."
-#~ msgid "You might be able to work around this by marking column \"%s\" NOT NULL, or use ALTER TABLE ... SET WITHOUT CLUSTER to remove the cluster specification from the table."
+#~ msgid "invalid contrecord length %u in log file %u, segment %u, offset %u"
#~ msgstr ""
-#~ "Vous pourriez contourner ceci en marquant la colonne � %s � avec la\n"
-#~ "contrainte NOT NULL ou en utilisant ALTER TABLE ... SET WITHOUT CLUSTER pour\n"
-#~ "supprimer la sp�cification CLUSTER de la table."
+#~ "longueur invalide du « contrecord » %u dans le journal de tranasctions %u,\n"
+#~ "segment %u, décalage %u"
-#~ msgid "cannot cluster on index \"%s\" because access method does not handle null values"
+#~ msgid "there is no contrecord flag in log file %u, segment %u, offset %u"
#~ msgstr ""
-#~ "ne peut pas cr�er un cluster sur l'index � %s � car la m�thode d'acc�s de\n"
-#~ "l'index ne g�re pas les valeurs NULL"
+#~ "il n'y a pas de drapeaux « contrecord » dans le journal de transactions %u,\n"
+#~ "segment %u, décalage %u"
-#~ msgid "clustering \"%s.%s\""
-#~ msgstr "ex�cution de CLUSTER sur � %s.%s �"
+#~ msgid "could not open file \"%s\" (log file %u, segment %u): %m"
+#~ msgstr "n'a pas pu ouvrir le fichier « %s » (journal de transactions %u, segment %u) : %m"
-#~ msgid "EnumValuesCreate() can only set a single OID"
-#~ msgstr "EnumValuesCreate() peut seulement initialiser un seul OID"
+#~ msgid "unlogged GiST indexes are not supported"
+#~ msgstr "les index GiST non tracés ne sont pas supportés"
-#~ msgid "index \"%s\" needs VACUUM FULL or REINDEX to finish crash recovery"
-#~ msgstr ""
-#~ "l'index � %s � a besoin d'un VACUUM FULL ou d'un REINDEX pour terminer la\n"
-#~ "r�cup�ration suite � un arr�t brutal"
+#~ msgid "could not change directory to \"%s\""
+#~ msgstr "n'a pas pu accéder au répertoire « %s »"
-#~ msgid "index \"%s\" needs VACUUM or REINDEX to finish crash recovery"
-#~ msgstr ""
-#~ "l'index � %s � a besoin d'un VACUUM ou d'un REINDEX pour terminer la\n"
-#~ "r�cup�ration suite � un arr�t brutal"
+#~ msgid "Perhaps out of disk space?"
+#~ msgstr "Peut-être manquez-vous de place disque ?"
-#~ msgid "Incomplete insertion detected during crash replay."
+#~ msgid "time zone offset %d is not a multiple of 900 sec (15 min) in time zone file \"%s\", line %d"
#~ msgstr ""
-#~ "Insertion incompl�te d�tect�e lors de la r�-ex�cution des requ�tes suite �\n"
-#~ "l'arr�t brutal."
+#~ "le décalage %d du fuseau horaire n'est pas un multiples de 900 secondes\n"
+#~ "(15 minutes) dans le fichier des fuseaux horaires « %s », ligne %d"
-#~ msgid "index %u/%u/%u needs VACUUM FULL or REINDEX to finish crash recovery"
-#~ msgstr ""
-#~ "l'index %u/%u/%u a besoin d'un VACUUM FULL ou d'un REINDEX pour terminer la\n"
-#~ "r�cup�ration suite � un arr�t brutal"
+#~ msgid "Sets the name of the Kerberos service."
+#~ msgstr "Initialise le nom du service Kerberos."
-#~ msgid "Lines should have the format parameter = 'value'."
-#~ msgstr "Les lignes devraient avoir le format param�tre = 'valeur'"
+#~ msgid "No description available."
+#~ msgstr "Aucune description disponible."
-#~ msgid "syntax error in recovery command file: %s"
-#~ msgstr "erreur de syntaxe dans le fichier de restauration : %s"
+#~ msgid "cannot call json_populate_recordset on a nested object"
+#~ msgstr "ne peut pas appeler json_populate_recordset sur un objet imbriqué"
-#~ msgid "Write-Ahead Log / Streaming Replication"
-#~ msgstr "Write-Ahead Log / R�plication en flux"
+#~ msgid "cannot call json_populate_recordset on a scalar"
+#~ msgstr "ne peut pas appeler json_populate_recordset sur un scalaire"
-#~ msgid "unable to open directory pg_tblspc: %m"
-#~ msgstr "impossible d'ouvrir le r�pertoire p_tblspc : %m"
+#~ msgid "cannot call json_populate_recordset with nested arrays"
+#~ msgstr "ne peut pas appeler json_populate_recordset avec des tableaux imbriqués"
-#~ msgid "unable to read symbolic link %s: %m"
-#~ msgstr "incapable de lire le lien symbolique %s : %m"
+#~ msgid "must call json_populate_recordset on an array of objects"
+#~ msgstr "doit appeler json_populate_recordset sur un tableau d'objets"
-#~ msgid "index \"%s\" is not a b-tree"
-#~ msgstr "l'index � %s � n'est pas un btree"
+#~ msgid "cannot call json_populate_recordset with nested objects"
+#~ msgstr "ne peut pas appeler json_populate_recordset sur des objets imbriqués"
-#~ msgid "ALTER TYPE USING is only supported on plain tables"
-#~ msgstr "ALTER TYPE USING est seulement support�s sur les tables standards"
+#~ msgid "cannot call json_populate_recordset on an object"
+#~ msgstr "ne peut pas appeler json_populate_recordset sur un objet"
-#~ msgid "resetting unlogged relations: cleanup %d init %d"
-#~ msgstr "r�initialisation des relations non trac�es : nettoyage %d initialisation %d"
+#~ msgid "first argument of json_populate_recordset must be a row type"
+#~ msgstr "le premier argument de json_populate_recordset doit être un type ROW"
-#~ msgid "%s (%x)"
-#~ msgstr "%s (%x)"
+#~ msgid "first argument of json_populate_record must be a row type"
+#~ msgstr "le premier argument de json_populate_record doit être un type ROW"
-#~ msgid "SSPI error %x"
-#~ msgstr "erreur SSPI : %x"
+#~ msgid "cannot call json_array_elements on a scalar"
+#~ msgstr "ne peut pas appeler json_array_elements sur un scalaire"
-#~ msgid "consistent state delayed because recovery snapshot incomplete"
-#~ msgstr "�tat de coh�rence pas encore atteint � cause d'un snapshot de restauration incomplet"
+#~ msgid "cannot call json_array_elements on a non-array"
+#~ msgstr "ne peut pas appeler json_array_elements sur un objet qui n'est pas un tableau"
-#~ msgid "tablespace %u is not empty"
-#~ msgstr "le tablespace %u n'est pas vide"
+#~ msgid "cannot extract field from a non-object"
+#~ msgstr "ne peut pas extraire le chemin à partir d'un non-objet"
-#~ msgid "subquery in WITH cannot have SELECT INTO"
-#~ msgstr "la sous-requ�te du WITH ne peut pas avoir de SELECT INTO"
+#~ msgid "cannot extract array element from a non-array"
+#~ msgstr "ne peut pas extraire un élément du tableau à partir d'un objet qui n'est pas un tableau"
-#~ msgid "subquery cannot have SELECT INTO"
-#~ msgstr "la sous-requ�te ne peut pas avoir de SELECT INTO"
+#~ msgid "cannot call function with empty path elements"
+#~ msgstr "ne peut pas appeler une fonction avec des éléments chemins vides"
-#~ msgid "subquery in FROM cannot have SELECT INTO"
-#~ msgstr "la sous-requ�te du FROM ne peut pas avoir de SELECT INTO"
+#~ msgid "cannot call function with null path elements"
+#~ msgstr "ne peut pas appeler une fonction avec des éléments chemins NULL"
-#~ msgid "DECLARE CURSOR cannot specify INTO"
-#~ msgstr "DECLARE CURSOR ne peut pas sp�cifier INTO"
+#~ msgid "cannot call json_object_keys on a scalar"
+#~ msgstr "ne peut pas appeler json_object_keys sur un scalaire"
-#~ msgid "INSERT ... SELECT cannot specify INTO"
-#~ msgstr "INSERT ... SELECT ne peut pas avoir INTO"
+#~ msgid "cannot call json_object_keys on an array"
+#~ msgstr "ne peut pas appeler json_object_keys sur un tableau"
-#~ msgid "column name list not allowed in CREATE TABLE / AS EXECUTE"
-#~ msgstr "la liste de noms de colonnes n'est pas autoris�e dans CREATE TABLE / AS EXECUTE"
+#~ msgid "missing assignment operator"
+#~ msgstr "opérateur d'affectation manquant"
-#~ msgid "CREATE TABLE AS cannot specify INTO"
-#~ msgstr "CREATE TABLE AS ne peut pas sp�cifier INTO"
+#~ msgid "wrong affix file format for flag"
+#~ msgstr "mauvais format de fichier affixe pour le drapeau"
-#~ msgid " --version output version information, then exit\n"
-#~ msgstr " --version affiche la version, puis quitte\n"
+#~ msgid "Views that return the same column more than once are not automatically updatable."
+#~ msgstr "Les vues qui renvoient la même colonne plus d'une fois ne sont pas automatiquement disponibles en écriture."
-#~ msgid " --help show this help, then exit\n"
-#~ msgstr " --help affiche cette aide, puis quitte\n"
+#~ msgid "Security-barrier views are not automatically updatable."
+#~ msgstr "Les vues avec barrière de sécurité ne sont pas automatiquement disponibles en écriture."
-#~ msgid "Make sure the root.crt file is present and readable."
-#~ msgstr "Assurez-vous que le certificat racine (root.crt) est pr�sent et lisible"
+#~ msgid "Expected 1 tuple with 3 fields, got %d tuples with %d fields."
+#~ msgstr "Attendait 1 ligne avec 3 champs, a obtenu %d lignes avec %d champs."
-#~ msgid "See server log for details."
-#~ msgstr "Voir les journaux applicatifs du serveur pour plus de d�tails."
+#~ msgid "too many column aliases specified for function %s"
+#~ msgstr "trop d'alias de colonnes spécifiées pour la fonction %s"
-#~ msgid "missing or erroneous pg_hba.conf file"
-#~ msgstr "fichier pg_hba.conf manquant ou erron�"
+#~ msgid "%s: could not determine user name (GetUserName failed)\n"
+#~ msgstr "%s : n'a pas pu déterminer le nom de l'utilisateur (GetUserName a échoué)\n"
-#~ msgid "Certificates will not be checked against revocation list."
-#~ msgstr "Les certificats ne seront pas v�rifi�s avec la liste de r�vocation."
+#~ msgid "%s: invalid effective UID: %d\n"
+#~ msgstr "%s : UID effectif invalide : %d\n"
-#~ msgid "SSL certificate revocation list file \"%s\" not found, skipping: %s"
-#~ msgstr "liste de r�vocation des certificats SSL � %s � introuvable, continue : %s"
+#~ msgid "krb5 authentication is not supported on local sockets"
+#~ msgstr ""
+#~ "l'authentification krb5 n'est pas supportée sur les connexions locales par\n"
+#~ "socket"
-#~ msgid "could not access root certificate file \"%s\": %m"
-#~ msgstr "n'a pas pu acc�der au fichier du certificat racine � %s � : %m"
+#~ msgid "SSL renegotiation failure"
+#~ msgstr "échec lors de la re-négotiation SSL"
-#~ msgid "could not open directory \"pg_tblspc\": %m"
-#~ msgstr "n'a pas pu ouvrir le r�pertoire � pg_tblspc � : %m"
+#~ msgid "local user with ID %d does not exist"
+#~ msgstr "l'utilisateur local dont l'identifiant est %d n'existe pas"
-#~ msgid "standby connections not allowed because wal_level=minimal"
-#~ msgstr "connexions standby non autoris�es car wal_level=minimal"
+#~ msgid "Kerberos unparse_name returned error %d"
+#~ msgstr "unparse_name de Kerberos a renvoyé l'erreur %d"
-#~ msgid "recovery is still in progress, can't accept WAL streaming connections"
-#~ msgstr "la restauration est en cours, ne peut pas accepter les connexions de flux WAL"
+#~ msgid "Kerberos recvauth returned error %d"
+#~ msgstr "recvauth de Kerberos a renvoyé l'erreur %d"
-#~ msgid "must be superuser to drop text search templates"
-#~ msgstr "doit �tre super-utilisateur pour supprimer des mod�les de recherche plein texte"
+#~ msgid "Kerberos sname_to_principal(\"%s\", \"%s\") returned error %d"
+#~ msgstr "sname_to_principal(« %s », « %s ») de Kerberos a renvoyé l'erreur %d"
-#~ msgid "must be superuser to drop text search parsers"
-#~ msgstr ""
-#~ "doit �tre super-utilisateur pour supprimer des analyseurs de recherche plein\n"
-#~ "texte"
+#~ msgid "Kerberos keytab resolving returned error %d"
+#~ msgstr "la résolution keytab de Kerberos a renvoyé l'erreur %d"
-#~ msgid "Must be superuser to drop a foreign-data wrapper."
-#~ msgstr "Doit �tre super-utilisateur pour supprimer un wrapper de donn�es distantes."
+#~ msgid "Kerberos initialization returned error %d"
+#~ msgstr "l'initialisation de Kerberos a retourné l'erreur %d"
-#~ msgid "permission denied to drop foreign-data wrapper \"%s\""
-#~ msgstr "droit refus� pour supprimer le wrapper de donn�es distantes � %s �"
+#~ msgid "Kerberos 5 authentication failed for user \"%s\""
+#~ msgstr "authentification Kerberos 5 échouée pour l'utilisateur « %s »"
-#~ msgid "removing built-in function \"%s\""
-#~ msgstr "suppression de la fonction interne � %s �"
+#~ msgid "trigger \"%s\" for table \"%s\" does not exist, skipping"
+#~ msgstr "le trigger « %s » pour la table « %s » n'existe pas, poursuite du traitement"
-#~ msgid "foreign key constraint \"%s\" of relation \"%s\" does not exist"
-#~ msgstr "la cl� �trang�re � %s � de la relation � %s � n'existe pas"
+#~ msgid "invalid input syntax for transaction log location: \"%s\""
+#~ msgstr "syntaxe invalide en entrée pour l'emplacement du journal de transactions : « %s »"
-#~ msgid "Sets the list of known custom variable classes."
-#~ msgstr "Initialise la liste des classes variables personnalis�es connues."
+#~ msgid "could not parse transaction log location \"%s\""
+#~ msgstr "n'a pas pu analyser l'emplacement du journal des transactions « %s »"
-#~ msgid "WAL sender sleep time between WAL replications."
+#~ msgid "%s \"%s\": return code %d"
+#~ msgstr "%s « %s » : code de retour %d"
+
+#~ msgid "assertion checking is not supported by this build"
+#~ msgstr "la vérification de l'assertion n'a pas été intégrée lors de la compilation"
+
+#~ msgid "SET AUTOCOMMIT TO OFF is no longer supported"
+#~ msgstr "SET AUTOCOMMIT TO OFF n'est plus supporté"
+
+#~ msgid "Set the amount of traffic to send and receive before renegotiating the encryption keys."
#~ msgstr ""
-#~ "Temps d'endormissement du processus d'envoi des journaux de transactions entre\n"
-#~ "les r�plications des journaux de transactions."
+#~ "Configure la quantité de trafic à envoyer et recevoir avant la renégotiation\n"
+#~ "des clés d'enchiffrement."
-#~ msgid "If this parameter is set, the server will automatically run in the background and any controlling terminals are dissociated."
+#~ msgid "Sets the maximum distance in log segments between automatic WAL checkpoints."
#~ msgstr ""
-#~ "Si ce param�tre est initialis�, le serveur sera ex�cut� automatiquement en\n"
-#~ "t�che de fond et les terminaux de contr�les seront d�s-associ�s."
+#~ "Initialise la distance maximale dans les journaux de transaction entre chaque\n"
+#~ "point de vérification (checkpoints) des journaux."
-#~ msgid "Runs the server silently."
-#~ msgstr "Lance le serveur de mani�re silencieuse."
+#~ msgid "It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."
+#~ msgstr ""
+#~ "C'est ici uniquement pour ne pas avoir de problèmes avec le SET AUTOCOMMIT\n"
+#~ "TO ON des clients 7.3."
-#~ msgid "%s: could not dissociate from controlling TTY: %s\n"
-#~ msgstr "%s : n'a pas pu se dissocier du TTY contr�lant : %s\n"
+#~ msgid "This parameter doesn't do anything."
+#~ msgstr "Ce paramètre ne fait rien."
-#~ msgid "%s: could not fork background process: %s\n"
-#~ msgstr "%s : n'a pas pu cr�er un processus fils : %s\n"
+#~ msgid "This is a debugging aid."
+#~ msgstr "C'est une aide de débogage."
-#~ msgid "%s: could not open log file \"%s/%s\": %s\n"
-#~ msgstr "%s : n'a pas pu ouvrir le journal applicatif � %s/%s � : %s\n"
+#~ msgid "Turns on various assertion checks."
+#~ msgstr "Active les différentes vérifications des assertions."
-#~ msgid "%s: could not open file \"%s\": %s\n"
-#~ msgstr "%s : n'a pas pu ouvrir le fichier � %s � : %s\n"
+#~ msgid "cannot accept a value of type pg_node_tree"
+#~ msgstr "ne peut pas accepter une valeur de type pg_node_tree"
-#~ msgid "select() failed in logger process: %m"
-#~ msgstr "�chec de select() dans le processus des journaux applicatifs : %m"
+#~ msgid "must be superuser or have the same role to terminate other server processes"
+#~ msgstr ""
+#~ "doit être super-utilisateur ou avoir le même rôle pour fermer les connexions\n"
+#~ "exécutées dans les autres processus serveur"
-#~ msgid "poll() failed in statistics collector: %m"
-#~ msgstr "�chec du poll() dans le r�cup�rateur de statistiques : %m"
+#~ msgid "must be superuser or have the same role to cancel queries running in other server processes"
+#~ msgstr ""
+#~ "doit être super-utilisateur ou avoir le même rôle pour annuler des requêtes\n"
+#~ "exécutées dans les autres processus serveur"
-#~ msgid "Valid values are '[]', '[)', '(]', and '()'."
-#~ msgstr "Les valeurs valides sont � [] �, � [) �, � (] � et � () �."
+#~ msgid "invalid symbol"
+#~ msgstr "symbole invalide"
-#~ msgid "invalid list syntax for \"unix_socket_directories\""
-#~ msgstr "syntaxe de liste invalide pour le param�tre � unix_socket_directories �"
+#~ msgid "unexpected \"=\""
+#~ msgstr "« = » inattendu"
-#~ msgid "invalid list syntax for \"listen_addresses\""
-#~ msgstr "syntaxe de liste invalide pour le param�tre � listen_addresses �"
+#~ msgid "neither input type is an array"
+#~ msgstr "aucun type de données n'est un tableau"
-#~ msgid "window functions cannot use named arguments"
-#~ msgstr "les fonctions window ne peuvent pas renvoyer des arguments nomm�s"
+#~ msgid "could not determine input data types"
+#~ msgstr "n'a pas pu déterminer les types de données en entrée"
-#~ msgid "cannot override frame clause of window \"%s\""
-#~ msgstr "ne peut pas surcharger la frame clause du window � %s �"
+#~ msgid "archive member \"%s\" too large for tar format"
+#~ msgstr "membre « %s » de l'archive trop volumineux pour le format tar"
-#~ msgid "JSON does not support infinite timestamp values."
-#~ msgstr "JSON ne supporte pas les valeurs infinies de timestamp."
+#~ msgid "postmaster became multithreaded"
+#~ msgstr "le postmaster est devenu multithreadé"
-#~ msgid "JSON does not support infinite date values."
-#~ msgstr "JSON ne supporte pas les valeurs infinies de date."
+#~ msgid "invalid value for parameter \"replication\""
+#~ msgstr "valeur invalide pour le paramètre « replication »"
-#~ msgid "WAL writer sleep time between WAL flushes."
+#~ msgid "WAL archival (archive_mode=on) requires wal_level \"archive\", \"hot_standby\", or \"logical\""
#~ msgstr ""
-#~ "Temps d'endormissement du processus d'�criture pendant le vidage des\n"
-#~ "journaux de transactions en millisecondes."
-
-#~ msgid "could not convert to time zone \"%s\""
-#~ msgstr "n'a pas pu convertir vers le fuseau horaire � %s �"
+#~ "l'archivage des journaux de transactions (archive_mode=on) nécessite que\n"
+#~ "le paramètre wal_level soit initialisé avec « archive », « hot_standby » ou « logical »"
-#~ msgid "argument for function \"exp\" too big"
-#~ msgstr "l'argument de la fonction � exp � est trop gros"
+#~ msgid "Consider increasing the configuration parameter \"checkpoint_segments\"."
+#~ msgstr "Considèrez l'augmentation du paramètre « checkpoint_segments »."
-#~ msgid "must be superuser to rotate log files"
-#~ msgstr "doit �tre super-utilisateur pour ex�cuter la rotation des journaux applicatifs"
+#~ msgid "subquery must return a column"
+#~ msgstr "la sous-requête doit renvoyer une colonne"
-#~ msgid "must be superuser to signal the postmaster"
-#~ msgstr "doit �tre super-utilisateur pour envoyer un signal au postmaster"
+#~ msgid " -A 1|0 enable/disable run-time assert checking\n"
+#~ msgstr ""
+#~ " -A 1|0 active/désactive la vérification des limites (assert) à\n"
+#~ " l'exécution\n"
-#~ msgid "could not format \"circle\" value"
-#~ msgstr "n'a pas pu formater la valeur � circle �"
+#~ msgid "%s: setsysinfo failed: %s\n"
+#~ msgstr "%s : setsysinfo a échoué : %s\n"
-#~ msgid "invalid input syntax for type circle: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type circle : � %s �"
+#~ msgid "could not set socket to blocking mode: %m"
+#~ msgstr "n'a pas pu activer le mode bloquant pour la socket : %m"
-#~ msgid "invalid input syntax for type polygon: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type polygon : � %s �"
+#~ msgid "SSL failed to renegotiate connection before limit expired"
+#~ msgstr "SSL a échoué à renégotier la connexion avant l'expiration du délai"
-#~ msgid "invalid input syntax for type lseg: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type lseg : � %s �"
+#~ msgid "could not complete SSL handshake on renegotiation, too many failures"
+#~ msgstr "n'a pas pu terminer la poignée de main de renégotiation, trop d'échecs"
-#~ msgid "invalid input syntax for type point: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type point : � %s �"
+#~ msgid "SSL handshake failure on renegotiation, retrying"
+#~ msgstr "échec du handshake SSL lors de la renégotiation, nouvelle tentative"
-#~ msgid "invalid input syntax for type path: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type path : � %s �"
+#~ msgid "SSL failure during renegotiation start"
+#~ msgstr "échec SSL au début de la re-négotiation"
-#~ msgid "invalid input syntax for type line: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type line: � %s �"
+#~ msgid "received password packet"
+#~ msgstr "paquet du mot de passe reçu"
-#~ msgid "invalid input syntax for type box: \"%s\""
-#~ msgstr "syntaxe en entr�e invalide pour le type box : � %s �"
+#~ msgid "interval precision specified twice"
+#~ msgstr "précision d'intervalle spécifiée deux fois"
-#~ msgid "could not format \"path\" value"
-#~ msgstr "n'a pas pu formater la valeur � path �"
+#~ msgid ""
+#~ "%.0f dead row versions cannot be removed yet.\n"
+#~ "There were %.0f unused item pointers.\n"
+#~ "%u pages are entirely empty.\n"
+#~ "%s."
+#~ msgstr ""
+#~ "%.0f versions de lignes mortes ne peuvent pas encore être supprimées.\n"
+#~ "Il y avait %.0f pointeurs d'éléments inutilisés.\n"
+#~ "%u pages sont entièrement vides.\n"
+#~ "%s."
-#~ msgid "multibyte flag character is not allowed"
-#~ msgstr "un caract�re drapeau multi-octet n'est pas autoris�"
+#~ msgid ""
+#~ "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"
+#~ "pages: %d removed, %d remain\n"
+#~ "tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"
+#~ "buffer usage: %d hits, %d misses, %d dirtied\n"
+#~ "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"
+#~ "system usage: %s"
+#~ msgstr ""
+#~ "VACUUM automatique de la table « %s.%s.%s » : parcours d'index : %d\n"
+#~ "pages : %d supprimées, %d restantes\n"
+#~ "lignes : %.0f supprimées, %.0f restantes, %.0f sont mortes mais non supprimables\n"
+#~ "utilisation des tampons : %d lus dans le cache, %d lus hors du cache, %d modifiés\n"
+#~ "taux moyen de lecture : %.3f Mo/s, taux moyen d'écriture : %.3f Mo/s\n"
+#~ "utilisation système : %s"
-#~ msgid "socket not open"
-#~ msgstr "socket non ouvert"
+#~ msgid "Specify a USING expression to perform the conversion."
+#~ msgstr "Donnez une expression USING pour réaliser la conversion."
-#~ msgid "must be superuser to reset statistics counters"
-#~ msgstr "doit �tre super-utilisateur pour r�initialiser les compteurs statistiques"
+#~ msgid "\"%s\" is not a table, materialized view, composite type, or foreign table"
+#~ msgstr "« %s » n'est ni une table, ni une vue matérialisée, ni un type composite, ni une table distante"
-#~ msgid "could not get SID for PowerUsers group: error code %lu\n"
-#~ msgstr ""
-#~ "n'a pas pu obtenir le SID du groupe des utilisateurs avec pouvoir :\n"
-#~ "code d'erreur %lu\n"
+#~ msgid "inherited relation \"%s\" is not a table"
+#~ msgstr "la relation héritée « %s » n'est pas une table"
-#~ msgid "could not get SID for Administrators group: error code %lu\n"
-#~ msgstr "n'a pas pu obtenir le SID du groupe d'administrateurs : code d'erreur %lu\n"
+#~ msgid "This name may be disallowed altogether in future versions of PostgreSQL."
+#~ msgstr "Ce nom pourrait être interdit dans les prochaines versions de PostgreSQL."
-#~ msgid "could not open process token: error code %lu\n"
-#~ msgstr "n'a pas pu ouvrir le jeton du processus : code d'erreur %lu\n"
+#~ msgid "=> is deprecated as an operator name"
+#~ msgstr "=> est un nom d'opérateur obsolète"
-#~ msgid "function %s must return type \"tsm_handler\""
-#~ msgstr "la fonction %s doit renvoyer le type � tsm_handler �"
+#~ msgid "WAL file is from different database system: Incorrect XLOG_BLCKSZ in page header."
+#~ msgstr ""
+#~ "le journal de transactions provient d'un système de bases de données différent :\n"
+#~ "XLOG_BLCKSZ incorrect dans l'en-tête de page."
-#~ msgid "Permissions should be u=rw (0600) or less."
-#~ msgstr "Les droits devraient �tre u=rwx (0600) ou inf�rieures."
+#~ msgid "WAL file is from different database system: Incorrect XLOG_SEG_SIZE in page header."
+#~ msgstr ""
+#~ "le journal de transactions provient d'un système de bases de données différent :\n"
+#~ "XLOG_SEG_SIZE incorrect dans l'en-tête de page."
-#~ msgid "typmod_in function %s must return type \"integer\""
-#~ msgstr "la fonction typmod_in %s doit renvoyer le type � entier �"
+#~ msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s."
+#~ msgstr ""
+#~ "L'identifiant du journal de transactions du système de base de données est %s,\n"
+#~ "l'identifiant pg_control du système de base de données dans pg_control est %s."
-#~ msgid "type send function %s must return type \"bytea\""
-#~ msgstr "la fonction send du type %s doit renvoyer le type � bytea �"
+#~ msgid "incorrect total length in record at %X/%X"
+#~ msgstr "longueur totale incorrecte à l'enregistrement %X/%X"
-#~ msgid "type output function %s must return type \"cstring\""
-#~ msgstr "le type de sortie de la fonction %s doit �tre � cstring �"
+#~ msgid "incorrect hole size in record at %X/%X"
+#~ msgstr "taille du trou incorrect à l'enregistrement %X/%X"
-#~ msgid "changing return type of function %s from \"opaque\" to \"cstring\""
-#~ msgstr "changement du type de retour de la fonction %s d'� opaque � vers � cstring �"
+#~ msgid "invalid backup block size in record at %X/%X"
+#~ msgstr "taille du bloc de sauvegarde invalide dans l'enregistrement à %X/%X"
-#~ msgid "function %s must return type \"trigger\""
-#~ msgstr "la fonction %s doit renvoyer le type � trigger �"
+#~ msgid "record with zero length at %X/%X"
+#~ msgstr "enregistrement de longueur nulle à %X/%X"
-#~ msgid "function %s must return type \"language_handler\""
-#~ msgstr "la fonction %s doit renvoyer le type � language_handler �"
+#~ msgid "invalid xlog switch record at %X/%X"
+#~ msgstr "enregistrement de basculement du journal de transaction invalide à %X/%X"
-#~ msgid "could not reposition held cursor"
-#~ msgstr "n'a pas pu repositionner le curseur d�tenu"
+#~ msgid "oldest unfrozen transaction ID: %u, in database %u"
+#~ msgstr ""
+#~ "identifiant de transaction non gelé le plus ancien : %u, dans la base de\n"
+#~ "données %u"
-#~ msgid "function %s must return type \"fdw_handler\""
-#~ msgstr "la fonction %s doit renvoyer le type � fdw_handler �"
+#~ msgid "next MultiXactId: %u; next MultiXactOffset: %u"
+#~ msgstr "prochain MultiXactId : %u ; prochain MultiXactOffset : %u"
-#~ msgid "function \"%s\" must return type \"event_trigger\""
-#~ msgstr "la fonction � %s � doit renvoyer le type � event_trigger �"
+#~ msgid "next transaction ID: %u/%u; next OID: %u"
+#~ msgstr "prochain identifiant de transaction : %u/%u ; prochain OID : %u"
-#~ msgid "%s is already in schema \"%s\""
-#~ msgstr "%s existe d�j� dans le sch�ma � %s �"
+#~ msgid "redo record is at %X/%X; shutdown %s"
+#~ msgstr "l'enregistrement à ré-exécuter se trouve à %X/%X ; arrêt %s"
-#~ msgid "invalid record length at %X/%X"
-#~ msgstr "longueur invalide de l'enregistrement � %X/%X"
+#~ msgid "invalid value for recovery parameter \"recovery_target\""
+#~ msgstr "valeur invalide pour le paramètre de restauration « recovery_target »"
-#~ msgid "must be superuser to control recovery"
-#~ msgstr "doit �tre super-utilisateur pour contr�ler la restauration"
+#~ msgid "unrecognized win32 error code: %lu"
+#~ msgstr "code d'erreur win32 non reconnu : %lu"
-#~ msgid "must be superuser to create a restore point"
-#~ msgstr "doit �tre super-utilisateur pour cr�er un point de restauration"
+#~ msgid "mapped win32 error code %lu to %d"
+#~ msgstr "correspondance du code d'erreur win32 %lu en %d"
-#~ msgid "must be superuser to switch transaction log files"
-#~ msgstr "doit �tre super-utilisateur pour changer de journal de transactions"
+#~ msgid "too few arguments for format"
+#~ msgstr "trop peu d'arguments pour le format"
-#~ msgid "must be superuser or replication role to run a backup"
-#~ msgstr "doit �tre super-utilisateur ou avoir l'attribut de r�plication pour ex�cuter une sauvegarde"
+#~ msgid "invalid length in external \"numeric\" value"
+#~ msgstr "longueur invalide dans la valeur externe « numeric »"
-#~ msgid "ignoring \"%s\" file because no \"%s\" file exists"
-#~ msgstr "ignore le fichier � %s � parce que le fichier � %s � n'existe pas"
+#~ msgid "time zone abbreviation \"%s\" is not used in time zone \"%s\""
+#~ msgstr "l'abréviation « %s » du fuseau horaire n'est pas utilisée dans le fuseau horaire « %s »"
-#~ msgid "could not rename file \"%s\" to \"%s\" (initialization of log file): %m"
-#~ msgstr "n'a pas pu renommer le fichier � %s � en � %s � (initialisation du journal de transactions) : %m"
+#~ msgid "role \"%s\" is reserved"
+#~ msgstr "le rôle « %s » est réservé"
-#~ msgid "could not link file \"%s\" to \"%s\" (initialization of log file): %m"
-#~ msgstr "n'a pas pu lier le fichier � %s � � � %s � (initialisation du journal de transactions) : %m"
+#~ msgid "system columns cannot be used in an ON CONFLICT clause"
+#~ msgstr "les colonnes systèmes ne peuvent pas être utilisées dans une clause ON CONFLICT"
-#~ msgid "could not close two-phase state file \"%s\": %m"
+#~ msgid "function returning set of rows cannot return null value"
#~ msgstr ""
-#~ "n'a pas pu fermer le fichier d'�tat de la validation en deux phases nomm�\n"
-#~ "� %s � : %m"
+#~ "la fonction renvoyant un ensemble de lignes ne peut pas renvoyer une valeur\n"
+#~ "NULL"
-#~ msgid "could not fsync two-phase state file \"%s\": %m"
+#~ msgid "Only superusers can use untrusted languages."
#~ msgstr ""
-#~ "n'a pas pu synchroniser sur disque (fsync) le fichier d'�tat de la\n"
-#~ "validation en deux phases nomm� � %s � : %m"
+#~ "Seuls les super-utilisateurs peuvent utiliser des langages qui ne sont pas\n"
+#~ "de confiance."
-#~ msgid "two-phase state file for transaction %u is corrupt"
-#~ msgstr ""
-#~ "le fichier d'�tat de la validation en deux phases est corrompu pour la\n"
-#~ "transaction %u"
+#~ msgid "huge TLB pages not supported on this platform"
+#~ msgstr "Huge Pages TLB non supporté sur cette plateforme."
-#~ msgid "could not seek in two-phase state file: %m"
-#~ msgstr ""
-#~ "n'a pas pu se d�placer dans le fichier de statut de la validation en deux\n"
-#~ "phases : %m"
+#~ msgid "Lower bound of dimension array must be one."
+#~ msgstr "La limite inférieure du tableau doit valoir un."
-#~ msgid "could not create two-phase state file \"%s\": %m"
-#~ msgstr ""
-#~ "n'a pas pu cr�er le fichier de statut de la validation en deux phases nomm�\n"
-#~ "� %s � : %m"
+#~ msgid "wrong range of array subscripts"
+#~ msgstr "mauvais échelle des indices du tableau"
diff --git a/src/backend/po/ko.po b/src/backend/po/ko.po
new file mode 100644
index 0000000000..c5225ffa19
--- /dev/null
+++ b/src/backend/po/ko.po
@@ -0,0 +1,24982 @@
+# Korean message translation file for PostgreSQL server
+# Ioseph Kim <[email protected]>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PostgreSQL 9.6\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2017-03-02 11:23+0900\n"
+"PO-Revision-Date: 2017-03-02 11:28:26+0900\n"
+"Last-Translator: Ioseph Kim <[email protected]>\n"
+"Language-Team: Korean Team <[email protected]>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../common/config_info.c:131 ../common/config_info.c:139
+#: ../common/config_info.c:147 ../common/config_info.c:155
+#: ../common/config_info.c:163 ../common/config_info.c:171
+#: ../common/config_info.c:179 ../common/config_info.c:187
+#: ../common/config_info.c:195
+msgid "not recorded"
+msgstr "기록되어 있지 않음"
+
+#: ../common/controldata_utils.c:52 commands/copy.c:2833
+#: commands/extension.c:3141 utils/adt/genfile.c:134
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m"
+
+#: ../common/controldata_utils.c:56
+#, c-format
+msgid "%s: could not open file \"%s\" for reading: %s\n"
+msgstr "%s: \"%s\" 파일 읽기 모드로 열기 실패: %s\n"
+
+#: ../common/controldata_utils.c:66 access/transam/timeline.c:346
+#: access/transam/xlog.c:3220 access/transam/xlog.c:10423
+#: access/transam/xlog.c:10436 access/transam/xlog.c:10828
+#: access/transam/xlog.c:10871 access/transam/xlog.c:10910
+#: access/transam/xlog.c:10953 access/transam/xlogfuncs.c:665
+#: access/transam/xlogfuncs.c:684 commands/extension.c:3151
+#: replication/logical/origin.c:665 replication/logical/origin.c:695
+#: replication/logical/reorderbuffer.c:3099 replication/walsender.c:499
+#: storage/file/copydir.c:176 utils/adt/genfile.c:151
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "\"%s\" 파일을 읽을 수 없음: %m"
+
+#: ../common/controldata_utils.c:69
+#, c-format
+msgid "%s: could not read file \"%s\": %s\n"
+msgstr "%s: \"%s\" 파일을 읽을 수 없습니다: %s\n"
+
+#: ../common/controldata_utils.c:86
+msgid "calculated CRC checksum does not match value stored in file"
+msgstr "계산된 CRC 체크섬 값이 파일에 저장된 값과 다름"
+
+#: ../common/controldata_utils.c:88
+#, c-format
+msgid ""
+"WARNING: Calculated CRC checksum does not match value stored in file.\n"
+"Either the file is corrupt, or it has a different layout than this program\n"
+"is expecting. The results below are untrustworthy.\n"
+"\n"
+msgstr ""
+"경고: 계산된 CRC 체크섬값이 파일에 있는 값과 틀립니다.\n"
+"이 경우는 파일이 손상되었거나, 이 프로그램과 컨트롤 파일의 버전이 틀린\n"
+"경우입니다. 결과값들은 믿지 못할 값들이 출력될 수 있습니다.\n"
+"\n"
+
+#: ../common/controldata_utils.c:97
+msgid "byte ordering mismatch"
+msgstr "바이트 순서 불일치"
+
+#: ../common/controldata_utils.c:99
+#, c-format
+msgid ""
+"WARNING: possible byte ordering mismatch\n"
+"The byte ordering used to store the pg_control file might not match the one\n"
+"used by this program. In that case the results below would be incorrect, "
+"and\n"
+"the PostgreSQL installation would be incompatible with this data directory.\n"
+msgstr ""
+"경고: 바이트 순서가 일치하지 않습니다.\n"
+"pg_control 파일을 저장하는 데 사용된 바이트 순서는 \n"
+"이 프로그램에서 사용하는 순서와 일치해야 합니다. 이 경우 아래 결과는 올바르"
+"지 않으며\n"
+"이 데이터 디렉터리에 PostgreSQL을 설치할 수 없습니다.\n"
+
+#: ../common/exec.c:127 ../common/exec.c:241 ../common/exec.c:284
+#, c-format
+msgid "could not identify current directory: %s"
+msgstr "현재 디렉터리를 파악할 수 없음: %s"
+
+#: ../common/exec.c:146
+#, c-format
+msgid "invalid binary \"%s\""
+msgstr "잘못된 바이너리 파일 \"%s\""
+
+#: ../common/exec.c:195
+#, c-format
+msgid "could not read binary \"%s\""
+msgstr "\"%s\" 바이너리 파일을 읽을 수 없음"
+
+# translator: %s is IPv4, IPv6, or Unix
+#: ../common/exec.c:202
+#, c-format
+msgid "could not find a \"%s\" to execute"
+msgstr "\"%s\" 실행 파일을 찾을 수 없음"
+
+#: ../common/exec.c:257 ../common/exec.c:293
+#, c-format
+msgid "could not change directory to \"%s\": %s"
+msgstr "\"%s\" 디렉터리로 바꿀 수 없음: %s"
+
+#: ../common/exec.c:272
+#, c-format
+msgid "could not read symbolic link \"%s\""
+msgstr "\"%s\" 심벌릭 링크를 읽을 수 없음"
+
+#: ../common/exec.c:523
+#, c-format
+msgid "pclose failed: %s"
+msgstr "pclose 실패: %s"
+
+#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75
+#: ../common/fe_memutils.c:98 ../common/psprintf.c:181 ../port/path.c:632
+#: ../port/path.c:670 ../port/path.c:687
+#, c-format
+msgid "out of memory\n"
+msgstr "메모리 부족\n"
+
+#: ../common/fe_memutils.c:92
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n"
+
+#: ../common/pgfnames.c:45
+#, c-format
+msgid "could not open directory \"%s\": %s\n"
+msgstr "\"%s\" 디렉터리 열 수 없음: %s\n"
+
+#: ../common/pgfnames.c:72
+#, c-format
+msgid "could not read directory \"%s\": %s\n"
+msgstr "\"%s\" 디렉터리를 읽을 수 없음: %s\n"
+
+#: ../common/pgfnames.c:84
+#, c-format
+msgid "could not close directory \"%s\": %s\n"
+msgstr "\"%s\" 디렉터리를 닫을 수 없음: %s\n"
+
+#: ../common/psprintf.c:179 ../port/path.c:630 ../port/path.c:668
+#: ../port/path.c:685 access/transam/twophase.c:1262
+#: access/transam/xlog.c:6108 lib/stringinfo.c:258 libpq/auth.c:850
+#: libpq/auth.c:1213 libpq/auth.c:1281 libpq/auth.c:1797
+#: postmaster/bgworker.c:289 postmaster/bgworker.c:796
+#: postmaster/postmaster.c:2335 postmaster/postmaster.c:2366
+#: postmaster/postmaster.c:3899 postmaster/postmaster.c:4589
+#: postmaster/postmaster.c:4664 postmaster/postmaster.c:5339
+#: postmaster/postmaster.c:5603
+#: replication/libpqwalreceiver/libpqwalreceiver.c:143
+#: replication/logical/logical.c:168 storage/buffer/localbuf.c:436
+#: storage/file/fd.c:736 storage/file/fd.c:1164 storage/file/fd.c:1282
+#: storage/file/fd.c:1993 storage/ipc/procarray.c:1061
+#: storage/ipc/procarray.c:1547 storage/ipc/procarray.c:1554
+#: storage/ipc/procarray.c:1968 storage/ipc/procarray.c:2571
+#: utils/adt/formatting.c:1522 utils/adt/formatting.c:1642
+#: utils/adt/formatting.c:1763 utils/adt/pg_locale.c:463
+#: utils/adt/pg_locale.c:647 utils/adt/regexp.c:219 utils/adt/varlena.c:4440
+#: utils/adt/varlena.c:4461 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:429
+#: utils/hash/dynahash.c:535 utils/hash/dynahash.c:1047 utils/mb/mbutils.c:376
+#: utils/mb/mbutils.c:709 utils/misc/guc.c:3888 utils/misc/guc.c:3904
+#: utils/misc/guc.c:3917 utils/misc/guc.c:6863 utils/misc/tzparser.c:468
+#: utils/mmgr/aset.c:509 utils/mmgr/mcxt.c:767 utils/mmgr/mcxt.c:802
+#: utils/mmgr/mcxt.c:839 utils/mmgr/mcxt.c:876 utils/mmgr/mcxt.c:910
+#: utils/mmgr/mcxt.c:939 utils/mmgr/mcxt.c:973 utils/mmgr/mcxt.c:1055
+#: utils/mmgr/mcxt.c:1089 utils/mmgr/mcxt.c:1138
+#, c-format
+msgid "out of memory"
+msgstr "메모리 부족"
+
+#: ../common/relpath.c:59
+#, c-format
+msgid "invalid fork name"
+msgstr "잘못된 포크 이름"
+
+#: ../common/relpath.c:60
+#, c-format
+msgid "Valid fork names are \"main\", \"fsm\", \"vm\", and \"init\"."
+msgstr "유효한 포크 이름은 \"main\", \"fsm\" 및 \"vm\"입니다."
+
+#: ../common/restricted_token.c:68
+#, c-format
+msgid "%s: WARNING: cannot create restricted tokens on this platform\n"
+msgstr "%s: 경고: 이 운영체제에서 restricted token을 만들 수 없음\n"
+
+#: ../common/restricted_token.c:77
+#, c-format
+msgid "%s: could not open process token: error code %lu\n"
+msgstr "%s: 프로세스 토큰을 열 수 없음: 오류 코드 %lu\n"
+
+#: ../common/restricted_token.c:90
+#, c-format
+msgid "%s: could not allocate SIDs: error code %lu\n"
+msgstr "%s: SID를 할당할 수 없음: 오류 코드 %lu\n"
+
+#: ../common/restricted_token.c:110
+#, c-format
+msgid "%s: could not create restricted token: error code %lu\n"
+msgstr "%s: 상속된 토큰을 만들 수 없음: 오류 코드 %lu\n"
+
+#: ../common/restricted_token.c:132
+#, c-format
+msgid "%s: could not start process for command \"%s\": error code %lu\n"
+msgstr "%s: \"%s\" 명령용 프로세스를 시작할 수 없음: 오류 코드 %lu\n"
+
+#: ../common/restricted_token.c:170
+#, c-format
+msgid "%s: could not re-execute with restricted token: error code %lu\n"
+msgstr "%s: 상속된 토큰으로 재실행할 수 없음: 오류 코드 %lu\n"
+
+#: ../common/restricted_token.c:186
+#, c-format
+msgid "%s: could not get exit code from subprocess: error code %lu\n"
+msgstr "%s: 하위 프로세스의 종료 코드를 구할 수 없음: 오류 코드 %lu\n"
+
+#: ../common/rmtree.c:77
+#, c-format
+msgid "could not stat file or directory \"%s\": %s\n"
+msgstr "\"%s\" 파일이나 디렉터리 상태를 확인할 수 없음: %s\n"
+
+#: ../common/rmtree.c:104 ../common/rmtree.c:121
+#, c-format
+msgid "could not remove file or directory \"%s\": %s\n"
+msgstr "\"%s\" 디렉터리를 삭제할 수 없음: %s\n"
+
+#: ../common/username.c:45
+#, c-format
+msgid "could not look up effective user ID %ld: %s"
+msgstr "%ld UID를 찾을 수 없음: %s"
+
+#: ../common/username.c:47 libpq/auth.c:1744
+msgid "user does not exist"
+msgstr "사용자 없음"
+
+#: ../common/username.c:62
+#, c-format
+msgid "user name lookup failure: error code %lu"
+msgstr "사용자 이름 찾기 실패: 오류 코드 %lu"
+
+#: ../common/wait_error.c:47
+#, c-format
+msgid "command not executable"
+msgstr "명령을 실행할 수 없음"
+
+#: ../common/wait_error.c:51
+#, c-format
+msgid "command not found"
+msgstr "해당 명령어 없음"
+
+#: ../common/wait_error.c:56
+#, c-format
+msgid "child process exited with exit code %d"
+msgstr "하위 프로그램은 %d 코드로 마쳤습니다"
+
+#: ../common/wait_error.c:63
+#, c-format
+msgid "child process was terminated by exception 0x%X"
+msgstr "0x%X 예외처리로 하위 프로세스가 종료되었습니다"
+
+#: ../common/wait_error.c:73
+#, c-format
+msgid "child process was terminated by signal %s"
+msgstr "%s 시그널이 감지되어 하위 프로세스가 종료되었습니다"
+
+#: ../common/wait_error.c:77
+#, c-format
+msgid "child process was terminated by signal %d"
+msgstr "하위 프로그램은 %d 신호에 의해서 종료되었습니다"
+
+#: ../common/wait_error.c:82
+#, c-format
+msgid "child process exited with unrecognized status %d"
+msgstr "하위 프로그램 프로그램은 예상치 못한 %d 상태값으로 종료되었습니다"
+
+#: ../port/chklocale.c:293
+#, c-format
+msgid "could not determine encoding for codeset \"%s\""
+msgstr "\"%s\" 코드 세트 환경에 사용할 인코딩을 결정할 수 없습니다"
+
+#: ../port/chklocale.c:294 ../port/chklocale.c:423
+#: postmaster/postmaster.c:4868
+#, c-format
+msgid "Please report this to <[email protected]>."
+msgstr "이 내용을 <[email protected]> 주소로 보고하십시오."
+
+#: ../port/chklocale.c:415 ../port/chklocale.c:421
+#, c-format
+msgid "could not determine encoding for locale \"%s\": codeset is \"%s\""
+msgstr ""
+"\"%s\" 로케일 환경에서 사용할 인코딩을 결정할 수 없습니다. 코드 세트: \"%s\""
+
+#: ../port/dirmod.c:218
+#, c-format
+msgid "could not set junction for \"%s\": %s"
+msgstr "\"%s\" 디렉터리 연결을 할 수 없음: %s"
+
+#: ../port/dirmod.c:221
+#, c-format
+msgid "could not set junction for \"%s\": %s\n"
+msgstr "\"%s\" 디렉터리 연결을 할 수 없음: %s\n"
+
+#: ../port/dirmod.c:295
+#, c-format
+msgid "could not get junction for \"%s\": %s"
+msgstr "\"%s\" 파일의 정션을 구할 수 없음: %s"
+
+#: ../port/dirmod.c:298
+#, c-format
+msgid "could not get junction for \"%s\": %s\n"
+msgstr "\"%s\" 파일의 정션을 구할 수 없음: %s\n"
+
+#: ../port/open.c:112
+#, c-format
+msgid "could not open file \"%s\": %s"
+msgstr "\"%s\" 파일을 열 수 없음: %s"
+
+#: ../port/open.c:113
+msgid "lock violation"
+msgstr "잠금 위반"
+
+#: ../port/open.c:113
+msgid "sharing violation"
+msgstr "공유 위반"
+
+#: ../port/open.c:114
+#, c-format
+msgid "Continuing to retry for 30 seconds."
+msgstr "30초 동안 계속해서 다시 시도합니다."
+
+#: ../port/open.c:115
+#, c-format
+msgid ""
+"You might have antivirus, backup, or similar software interfering with the "
+"database system."
+msgstr ""
+"바이러스 백신 프로그램, 백업 또는 유사한 소프트웨어가 데이터베이스 시스템을 "
+"방해할 수 있습니다."
+
+#: ../port/path.c:654
+#, c-format
+msgid "could not get current working directory: %s\n"
+msgstr "현재 작업 디렉터리를 알 수 없음: %s\n"
+
+#: ../port/strerror.c:25
+#, c-format
+msgid "unrecognized error %d"
+msgstr "알 수 없는 오류 %d"
+
+#: ../port/win32security.c:68
+#, c-format
+msgid "could not open process token: error code %lu\n"
+msgstr "프로세스 토큰을 열 수 없음: 오류 코드 %lu\n"
+
+#: ../port/win32security.c:89
+#, c-format
+msgid "could not get SID for Administrators group: error code %lu\n"
+msgstr "Administrators 그룹의 SID를 가져올 수 없음: 오류 코드 %lu\n"
+
+#: ../port/win32security.c:99
+#, c-format
+msgid "could not get SID for PowerUsers group: error code %lu\n"
+msgstr "PowerUsers 그룹의 SID를 가져올 수 없음: 오류 코드 %lu\n"
+
+#: access/brin/brin.c:810
+#, c-format
+msgid "\"%s\" is not a BRIN index"
+msgstr "\"%s\" 객체는 BRIN 인덱스가 아닙니다"
+
+#: access/brin/brin.c:826
+#, c-format
+msgid "could not open parent table of index %s"
+msgstr "%s 인덱스에 대한 상위 테이블을 열 수 없음"
+
+#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362
+#: access/brin/brin_pageops.c:828
+#, c-format
+msgid "index row size %lu exceeds maximum %lu for index \"%s\""
+msgstr "인덱스 행 크기 %lu이(가) 최대값 %lu(\"%s\" 인덱스)을(를) 초과함"
+
+#: access/brin/brin_revmap.c:459
+#, c-format
+msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u"
+msgstr "예상치 못한 0x%04X 페이지 타입: \"%s\" BRIN 인덱스 %u 블록"
+
+#: access/brin/brin_validate.c:115
+#, c-format
+msgid ""
+"brin operator family \"%s\" contains function %s with invalid support number "
+"%d"
+msgstr ""
+"\"%s\" brin 연산자 패밀리에 %s 함수가 잘못된 지원 번호(%d)로 지정되었습니다."
+
+#: access/brin/brin_validate.c:131
+#, c-format
+msgid ""
+"brin operator family \"%s\" contains function %s with wrong signature for "
+"support number %d"
+msgstr ""
+"\"%s\" brin 연산자 패밀리에 %s 함수가 잘못된 signature 번호(%d)로 지정되었습"
+"니다."
+
+#: access/brin/brin_validate.c:153
+#, c-format
+msgid ""
+"brin operator family \"%s\" contains operator %s with invalid strategy "
+"number %d"
+msgstr ""
+"\"%s\" brin 연산자 패밀리에 %s 연산자가 잘못된 전략 번호(%d)로 지정되었습니"
+"다."
+
+#: access/brin/brin_validate.c:182
+#, c-format
+msgid ""
+"brin operator family \"%s\" contains invalid ORDER BY specification for "
+"operator %s"
+msgstr ""
+"\"%s\" brin 연산자 패밀리에 %s 연산자가 잘못된 ORDER BY 명세를 사용합니다."
+
+#: access/brin/brin_validate.c:195
+#, c-format
+msgid "brin operator family \"%s\" contains operator %s with wrong signature"
+msgstr "\"%s\" brin 연산자 패밀리에 %s 연산자가 잘못된 signature를 사용합니다."
+
+#: access/brin/brin_validate.c:233
+#, c-format
+msgid "brin operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr "\"%s\" brin 연산자 패밀리에는 %s, %s 자료형용 연산자가 없습니다"
+
+#: access/brin/brin_validate.c:243
+#, c-format
+msgid ""
+"brin operator family \"%s\" is missing support function(s) for types %s and "
+"%s"
+msgstr "\"%s\" brin 연산자 패밀리에는 %s, %s 자료형용으로 쓸 함수가 없습니다"
+
+#: access/brin/brin_validate.c:256
+#, c-format
+msgid "brin operator class \"%s\" is missing operator(s)"
+msgstr "\"%s\" brin 연산자 클래스에 연산자가 빠졌습니다"
+
+#: access/brin/brin_validate.c:267
+#, c-format
+msgid "brin operator class \"%s\" is missing support function %d"
+msgstr "\"%s\" brin 연산자 클래스에 %d 지원 함수가 없음"
+
+#: access/common/heaptuple.c:708 access/common/heaptuple.c:1339
+#, c-format
+msgid "number of columns (%d) exceeds limit (%d)"
+msgstr "열 수(%d)가 최대값(%d)을 초과했습니다"
+
+#: access/common/indextuple.c:60
+#, c-format
+msgid "number of index columns (%d) exceeds limit (%d)"
+msgstr "인덱스 열 수(%d)가 최대값(%d)을 초과했습니다"
+
+#: access/common/indextuple.c:176 access/spgist/spgutils.c:642
+#, c-format
+msgid "index row requires %zu bytes, maximum size is %zu"
+msgstr "인덱스 행(row)은 %zu 바이트를 필요로 함, 최대 크기는 %zu"
+
+#: access/common/printtup.c:292 tcop/fastpath.c:182 tcop/fastpath.c:544
+#: tcop/postgres.c:1719
+#, c-format
+msgid "unsupported format code: %d"
+msgstr "지원하지 않는 포맷 코드: %d"
+
+#: access/common/reloptions.c:493
+#, c-format
+msgid "user-defined relation parameter types limit exceeded"
+msgstr "사용자 정의 관계 매개 변수 형식 제한을 초과함"
+
+#: access/common/reloptions.c:775
+#, c-format
+msgid "RESET must not include values for parameters"
+msgstr "매개 변수의 값으로 RESET은 올 수 없음"
+
+#: access/common/reloptions.c:808
+#, c-format
+msgid "unrecognized parameter namespace \"%s\""
+msgstr "\"%s\" 매개 변수 네임스페이스를 인식할 수 없음"
+
+#: access/common/reloptions.c:1050 parser/parse_clause.c:281
+#, c-format
+msgid "unrecognized parameter \"%s\""
+msgstr "알 수 없는 환경 설정 이름입니다 \"%s\""
+
+#: access/common/reloptions.c:1080
+#, c-format
+msgid "parameter \"%s\" specified more than once"
+msgstr "\"%s\" 매개 변수가 여러 번 지정됨"
+
+#: access/common/reloptions.c:1096
+#, c-format
+msgid "invalid value for boolean option \"%s\": %s"
+msgstr "\"%s\" 부울 옵션 값이 잘못됨: %s"
+
+#: access/common/reloptions.c:1108
+#, c-format
+msgid "invalid value for integer option \"%s\": %s"
+msgstr "\"%s\" 정수 옵션 값이 잘못됨: %s"
+
+#: access/common/reloptions.c:1114 access/common/reloptions.c:1134
+#, c-format
+msgid "value %s out of bounds for option \"%s\""
+msgstr "값 %s은(는) \"%s\" 옵션 범위를 벗어남"
+
+#: access/common/reloptions.c:1116
+#, c-format
+msgid "Valid values are between \"%d\" and \"%d\"."
+msgstr "유효한 값은 \"%d\"에서 \"%d\" 사이입니다."
+
+#: access/common/reloptions.c:1128
+#, c-format
+msgid "invalid value for floating point option \"%s\": %s"
+msgstr "\"%s\" 부동 소수점 옵션 값이 잘못됨: %s"
+
+#: access/common/reloptions.c:1136
+#, c-format
+msgid "Valid values are between \"%f\" and \"%f\"."
+msgstr "유효한 값은 \"%f\"에서 \"%f\" 사이입니다."
+
+#: access/common/tupconvert.c:108
+#, c-format
+msgid "Returned type %s does not match expected type %s in column %d."
+msgstr ""
+"반환 자료형으로 %s 형을 지정했지만, 칼럼은 %s 자료형입니다. 해당 칼럼: %d 번"
+"째 칼럼"
+
+#: access/common/tupconvert.c:136
+#, c-format
+msgid ""
+"Number of returned columns (%d) does not match expected column count (%d)."
+msgstr "반환할 칼럼 수(%d)와 예상되는 칼럼수(%d)가 다릅니다."
+
+#: access/common/tupconvert.c:314
+#, c-format
+msgid ""
+"Attribute \"%s\" of type %s does not match corresponding attribute of type "
+"%s."
+msgstr ""
+" \"%s\" 속성(대상 자료형 %s)이 %s 자료형의 속성 가운데 관련된 것이 없습니다"
+
+#: access/common/tupconvert.c:326
+#, c-format
+msgid "Attribute \"%s\" of type %s does not exist in type %s."
+msgstr "\"%s\" 속성(대상 자료형 %s)이 %s 자료형에는 없습니다."
+
+#: access/common/tupdesc.c:635 parser/parse_relation.c:1518
+#, c-format
+msgid "column \"%s\" cannot be declared SETOF"
+msgstr "\"%s\" 열은 SETOF를 지정할 수 없습니다"
+
+#: access/gin/ginbulk.c:44
+#, c-format
+msgid "posting list is too long"
+msgstr "포스팅 목록이 너무 깁니다"
+
+#: access/gin/ginbulk.c:45
+#, c-format
+msgid "Reduce maintenance_work_mem."
+msgstr "maintenance_work_mem 설정값을 줄이세요."
+
+#: access/gin/ginentrypage.c:109 access/gist/gist.c:1337
+#: access/nbtree/nbtinsert.c:576 access/nbtree/nbtsort.c:488
+#: access/spgist/spgdoinsert.c:1907
+#, c-format
+msgid "index row size %zu exceeds maximum %zu for index \"%s\""
+msgstr "인덱스 행 크기 %zu이(가) 최대값 %zu(\"%s\" 인덱스)을(를) 초과함"
+
+#: access/gin/ginfast.c:989 access/transam/xlog.c:9858
+#: access/transam/xlog.c:10362 access/transam/xlogfuncs.c:293
+#: access/transam/xlogfuncs.c:320 access/transam/xlogfuncs.c:359
+#: access/transam/xlogfuncs.c:380 access/transam/xlogfuncs.c:401
+#: access/transam/xlogfuncs.c:471 access/transam/xlogfuncs.c:527
+#, c-format
+msgid "recovery is in progress"
+msgstr "복구 작업 진행 중"
+
+#: access/gin/ginfast.c:990
+#, c-format
+msgid "GIN pending list cannot be cleaned up during recovery."
+msgstr "GIN 팬딩 목록은 복구 작업 중에는 정리될 수 없습니다."
+
+#: access/gin/ginfast.c:997
+#, c-format
+msgid "\"%s\" is not a GIN index"
+msgstr "\"%s\" 객체는 GIN 인덱스가 아닙니다"
+
+#: access/gin/ginfast.c:1008
+#, c-format
+msgid "cannot access temporary indexes of other sessions"
+msgstr "다른 세션의 임시 인덱스는 접근할 수 없음"
+
+#: access/gin/ginscan.c:405
+#, c-format
+msgid "old GIN indexes do not support whole-index scans nor searches for nulls"
+msgstr ""
+"GIN 인덱스가 옛날 버전이어서 인덱스 전체 탐색, null 탐색 기능을 사용할 수 없"
+"습니다."
+
+#: access/gin/ginscan.c:406
+#, c-format
+msgid "To fix this, do REINDEX INDEX \"%s\"."
+msgstr "이 문제를 고치려면, 다음 명령을 수행하세요: REINDEX INDEX \"%s\""
+
+#: access/gin/ginvalidate.c:92
+#, c-format
+msgid ""
+"gin operator family \"%s\" contains support procedure %s with cross-type "
+"registration"
+msgstr ""
+"\"%s\" gin 연산자 패밀리에 cross-type registration 으로 %s 지원 프로시져가 포"
+"함되어 있습니다."
+
+#: access/gin/ginvalidate.c:148
+#, c-format
+msgid ""
+"gin operator family \"%s\" contains function %s with invalid support number "
+"%d"
+msgstr ""
+"\"%s\" gin 연산자 패밀리에 포함된 %s 함수가 잘못된 지원 번호 %d 로 지정되었습"
+"니다."
+
+#: access/gin/ginvalidate.c:160
+#, c-format
+msgid ""
+"gin operator family \"%s\" contains function %s with wrong signature for "
+"support number %d"
+msgstr ""
+"\"%s\" gin 연산자 패밀리에 포함된 %s 함수가 잘못된 signature 지원 번호 %d 로 "
+"지정되었습니다."
+
+#: access/gin/ginvalidate.c:179
+#, c-format
+msgid ""
+"gin operator family \"%s\" contains operator %s with invalid strategy number "
+"%d"
+msgstr ""
+"\"%s\" gin 연산자 패밀리에 포함된 %s 연산자의 %d 번 전략 번호가 잘못되었습니"
+"다."
+
+#: access/gin/ginvalidate.c:192
+#, c-format
+msgid ""
+"gin operator family \"%s\" contains invalid ORDER BY specification for "
+"operator %s"
+msgstr ""
+"\"%s\" gin 연산자 패밀리에 %s 연산자가 잘못된 ORDER BY 명세를 사용합니다."
+
+#: access/gin/ginvalidate.c:205
+#, c-format
+msgid "gin operator family \"%s\" contains operator %s with wrong signature"
+msgstr "\"%s\" gin 연산자 패밀리에 %s 연산자가 잘못된 기호를 사용합니다."
+
+#: access/gin/ginvalidate.c:246
+#, c-format
+msgid "gin operator class \"%s\" is missing support function %d"
+msgstr "\"%s\" gin 연산자 클래스에 %d 지원 함수가 빠졌습니다."
+
+#: access/gin/ginvalidate.c:256
+#, c-format
+msgid "gin operator class \"%s\" is missing support function %d or %d"
+msgstr "\"%s\" gin 연산자 클래스에는 %d 또는 %d 지원 함수가 빠졌습니다"
+
+#: access/gist/gist.c:680 access/gist/gistvacuum.c:258
+#, c-format
+msgid "index \"%s\" contains an inner tuple marked as invalid"
+msgstr "\"%s\" 인덱스에 잘못된 내부 튜플이 있다고 확인되었습니다."
+
+#: access/gist/gist.c:682 access/gist/gistvacuum.c:260
+#, c-format
+msgid ""
+"This is caused by an incomplete page split at crash recovery before "
+"upgrading to PostgreSQL 9.1."
+msgstr ""
+"이 문제는 PostgreSQL 9.1 버전으로 업그레이드 하기 전에 장애 복구 처리에서 잘"
+"못된 페이지 분리 때문에 발생했습니다."
+
+#: access/gist/gist.c:683 access/gist/gistutil.c:738
+#: access/gist/gistutil.c:749 access/gist/gistvacuum.c:261
+#: access/hash/hashutil.c:172 access/hash/hashutil.c:183
+#: access/hash/hashutil.c:195 access/hash/hashutil.c:216
+#: access/nbtree/nbtpage.c:518 access/nbtree/nbtpage.c:529
+#, c-format
+msgid "Please REINDEX it."
+msgstr "REINDEX 명령으로 다시 인덱스를 만드세요"
+
+#: access/gist/gistbuild.c:249
+#, c-format
+msgid "invalid value for \"buffering\" option"
+msgstr "\"buffering\" 옵션 값이 올바르지 않습니다"
+
+#: access/gist/gistbuild.c:250
+#, c-format
+msgid "Valid values are \"on\", \"off\", and \"auto\"."
+msgstr "유효한 값: \"on\", \"off\", \"auto\""
+
+#: access/gist/gistbuildbuffers.c:778 utils/sort/logtape.c:209
+#, c-format
+msgid "could not write block %ld of temporary file: %m"
+msgstr "임시파일의 %ld 블럭을 쓸 수 없음: %m"
+
+#: access/gist/gistsplit.c:446
+#, c-format
+msgid "picksplit method for column %d of index \"%s\" failed"
+msgstr "%d 열(\"%s\" 인덱스)에 대한 picksplit 메서드 실패"
+
+#: access/gist/gistsplit.c:448
+#, c-format
+msgid ""
+"The index is not optimal. To optimize it, contact a developer, or try to use "
+"the column as the second one in the CREATE INDEX command."
+msgstr ""
+"인덱스가 최적화되지 않았습니다. 최적화하려면 개발자에게 문의하거나, CREATE "
+"INDEX 명령에서 해당 열을 두 번째 인덱스로 사용하십시오."
+
+#: access/gist/gistutil.c:735 access/hash/hashutil.c:169
+#: access/nbtree/nbtpage.c:515
+#, c-format
+msgid "index \"%s\" contains unexpected zero page at block %u"
+msgstr "\"%s\" 인덱스의 %u번째 블럭에서 예상치 않은 zero page가 있습니다"
+
+#: access/gist/gistutil.c:746 access/hash/hashutil.c:180
+#: access/hash/hashutil.c:192 access/nbtree/nbtpage.c:526
+#, c-format
+msgid "index \"%s\" contains corrupted page at block %u"
+msgstr "\"%s\" 인덱스트 %u번째 블럭이 속상되었습니다"
+
+#: access/gist/gistvalidate.c:92
+#, c-format
+msgid ""
+"gist operator family \"%s\" contains support procedure %s with cross-type "
+"registration"
+msgstr ""
+"\"%s\" gist 연산자 패밀리에 cross-type registration 으로 %s 지원 프로시져가 "
+"포함되어 있습니다."
+
+#: access/gist/gistvalidate.c:145
+#, c-format
+msgid ""
+"gist operator family \"%s\" contains function %s with invalid support number "
+"%d"
+msgstr ""
+"\"%s\" gist 연산자 패밀리에 포함된 %s 함수가 잘못된 지원 번호 %d 로 지정되었"
+"습니다."
+
+#: access/gist/gistvalidate.c:157
+#, c-format
+msgid ""
+"gist operator family \"%s\" contains function %s with wrong signature for "
+"support number %d"
+msgstr ""
+"\"%s\" gist 연산자 패밀리에 포함된 %s 함수가 잘못된 signature 지원 번호 %d "
+"로 지정되었습니다."
+
+#: access/gist/gistvalidate.c:177
+#, c-format
+msgid ""
+"gist operator family \"%s\" contains operator %s with invalid strategy "
+"number %d"
+msgstr ""
+"\"%s\" gist 연산자 패밀리에 포함된 %s 연산자의 %d 번 전략 번호가 잘못되었습니"
+"다."
+
+#: access/gist/gistvalidate.c:195
+#, c-format
+msgid ""
+"gist operator family \"%s\" contains unsupported ORDER BY specification for "
+"operator %s"
+msgstr ""
+"\"%s\" gist 연산자 패밀리에 %s 연산자가 지원하지 않는 ORDER BY 명세를 사용합"
+"니다."
+
+#: access/gist/gistvalidate.c:206
+#, c-format
+msgid ""
+"gist operator family \"%s\" contains incorrect ORDER BY opfamily "
+"specification for operator %s"
+msgstr ""
+"\"%s\" gist 연산자 패밀리에 %s 연산자가 잘못된 ORDER BY 명세를 사용합니다."
+
+#: access/gist/gistvalidate.c:225
+#, c-format
+msgid "gist operator family \"%s\" contains operator %s with wrong signature"
+msgstr "\"%s\" gist 연산자 패밀리에 %s 연산자가 잘못된 기호를 사용합니다."
+
+#: access/gist/gistvalidate.c:264
+#, c-format
+msgid "gist operator class \"%s\" is missing support function %d"
+msgstr "\"%s\" gist 연산자 클래스에 %d 지원 함수가 빠졌습니다."
+
+#: access/hash/hashinsert.c:70
+#, c-format
+msgid "index row size %zu exceeds hash maximum %zu"
+msgstr "인덱스 행 크기가 초과됨: 현재값 %zu, 최대값 %zu"
+
+#: access/hash/hashinsert.c:72 access/spgist/spgdoinsert.c:1911
+#: access/spgist/spgutils.c:703
+#, c-format
+msgid "Values larger than a buffer page cannot be indexed."
+msgstr "버퍼 페이지보다 큰 값은 인덱싱할 수 없습니다."
+
+#: access/hash/hashovfl.c:546
+#, c-format
+msgid "out of overflow pages in hash index \"%s\""
+msgstr "\"%s\" 해시 인덱스에서 오버플로우 페이지 초과"
+
+#: access/hash/hashsearch.c:153
+#, c-format
+msgid "hash indexes do not support whole-index scans"
+msgstr "해시 인덱스는 whole-index scan을 지원하지 않음"
+
+#: access/hash/hashutil.c:208
+#, c-format
+msgid "index \"%s\" is not a hash index"
+msgstr "\"%s\" 인덱스는 해시 인덱스가 아님"
+
+#: access/hash/hashutil.c:214
+#, c-format
+msgid "index \"%s\" has wrong hash version"
+msgstr "\"%s\" 인덱스는 잘못된 해시 버전임"
+
+#: access/hash/hashvalidate.c:98
+#, c-format
+msgid ""
+"hash operator family \"%s\" contains support procedure %s with cross-type "
+"registration"
+msgstr ""
+"\"%s\" hash 연산자 패밀리에 cross-type registration 으로 %s 지원 프로시져가 "
+"포함되어 있습니다."
+
+#: access/hash/hashvalidate.c:113
+#, c-format
+msgid ""
+"hash operator family \"%s\" contains function %s with wrong signature for "
+"support number %d"
+msgstr ""
+"\"%s\" hash 연산자 패밀리에 포함된 %s 함수가 잘못된 signature 지원 번호 %d "
+"로 지정되었습니다."
+
+#: access/hash/hashvalidate.c:130
+#, c-format
+msgid ""
+"hash operator family \"%s\" contains function %s with invalid support number "
+"%d"
+msgstr ""
+"\"%s\" hash 연산자 패밀리에 포함된 %s 함수가 잘못된 지원 번호 %d 로 지정되었"
+"습니다."
+
+#: access/hash/hashvalidate.c:151
+#, c-format
+msgid ""
+"hash operator family \"%s\" contains operator %s with invalid strategy "
+"number %d"
+msgstr ""
+"\"%s\" hash 연산자 패밀리에 포함된 %s 연산자의 %d 번 전략 번호가 잘못되었습니"
+"다."
+
+#: access/hash/hashvalidate.c:164
+#, c-format
+msgid ""
+"hash operator family \"%s\" contains invalid ORDER BY specification for "
+"operator %s"
+msgstr ""
+"\"%s\" hash 연산자 패밀리에 %s 연산자가 잘못된 ORDER BY 명세를 사용합니다."
+
+#: access/hash/hashvalidate.c:177
+#, c-format
+msgid "hash operator family \"%s\" contains operator %s with wrong signature"
+msgstr "\"%s\" hash 연산자 패밀리에 %s 연산자가 잘못된 기호를 사용합니다."
+
+#: access/hash/hashvalidate.c:189
+#, c-format
+msgid "hash operator family \"%s\" lacks support function for operator %s"
+msgstr "\"%s\" hash 연산자 패밀리에 %s 연산자용 지원 함수가 없음"
+
+#: access/hash/hashvalidate.c:217
+#, c-format
+msgid "hash operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr ""
+"\"%s\" hash 연산자 패밀리에 %s 자료형과 %s 자료형을 다루는 연산자가 없음"
+
+#: access/hash/hashvalidate.c:231
+#, c-format
+msgid "hash operator class \"%s\" is missing operator(s)"
+msgstr "%s hash 연산자 클래스에 연산자가 빠졌음"
+
+#: access/hash/hashvalidate.c:247
+#, c-format
+msgid "hash operator family \"%s\" is missing cross-type operator(s)"
+msgstr "%s hash 연산자 클래스에 cross-type 연산자가 빠졌음"
+
+#: access/heap/heapam.c:1295 access/heap/heapam.c:1323
+#: access/heap/heapam.c:1355 catalog/aclchk.c:1756
+#, c-format
+msgid "\"%s\" is an index"
+msgstr "\"%s\" 객체는 인덱스임"
+
+#: access/heap/heapam.c:1300 access/heap/heapam.c:1328
+#: access/heap/heapam.c:1360 catalog/aclchk.c:1763 commands/tablecmds.c:9081
+#: commands/tablecmds.c:12189
+#, c-format
+msgid "\"%s\" is a composite type"
+msgstr "\"%s\" 객체는 복합 자료형입니다"
+
+#: access/heap/heapam.c:2567
+#, c-format
+msgid "cannot insert tuples during a parallel operation"
+msgstr "병렬 작업 중에는 튜플을 추가 할 수 없음"
+
+#: access/heap/heapam.c:3017
+#, c-format
+msgid "cannot delete tuples during a parallel operation"
+msgstr "병렬 작업 중에는 튜플을 지울 수 없음"
+
+#: access/heap/heapam.c:3063
+#, c-format
+msgid "attempted to delete invisible tuple"
+msgstr "볼 수 없는 튜플을 삭제 하려고 함"
+
+#: access/heap/heapam.c:3489 access/heap/heapam.c:6240
+#, c-format
+msgid "cannot update tuples during a parallel operation"
+msgstr "병렬 작업 중에 튜플 갱신은 할 수 없음"
+
+#: access/heap/heapam.c:3611
+#, c-format
+msgid "attempted to update invisible tuple"
+msgstr "볼 수 없는 튜플을 변경하려고 함"
+
+#: access/heap/heapam.c:4963 access/heap/heapam.c:5001
+#: access/heap/heapam.c:5253 executor/execMain.c:2314
+#, c-format
+msgid "could not obtain lock on row in relation \"%s\""
+msgstr "\"%s\" 릴레이션의 잠금 정보를 구할 수 없음"
+
+#: access/heap/hio.c:322 access/heap/rewriteheap.c:664
+#, c-format
+msgid "row is too big: size %zu, maximum size %zu"
+msgstr "열(row)이 너무 큽니다: 크기 %zu, 최대값 %zu"
+
+#: access/heap/rewriteheap.c:923
+#, c-format
+msgid "could not write to file \"%s\", wrote %d of %d: %m"
+msgstr "\"%s\" 파일 쓰기 실패, %d / %d 기록함: %m."
+
+#: access/heap/rewriteheap.c:963 access/heap/rewriteheap.c:1175
+#: access/heap/rewriteheap.c:1272 access/transam/timeline.c:407
+#: access/transam/timeline.c:483 access/transam/xlog.c:3087
+#: access/transam/xlog.c:3249 replication/logical/snapbuild.c:1605
+#: replication/slot.c:1088 replication/slot.c:1173 storage/file/fd.c:631
+#: storage/file/fd.c:3129 storage/smgr/md.c:1041 storage/smgr/md.c:1274
+#: storage/smgr/md.c:1447 utils/misc/guc.c:6885
+#, c-format
+msgid "could not fsync file \"%s\": %m"
+msgstr "\"%s\" 파일 fsync 실패: %m"
+
+#: access/heap/rewriteheap.c:1018 access/heap/rewriteheap.c:1138
+#: access/transam/timeline.c:315 access/transam/timeline.c:461
+#: access/transam/xlog.c:3043 access/transam/xlog.c:3192
+#: access/transam/xlog.c:10192 access/transam/xlog.c:10230
+#: access/transam/xlog.c:10603 postmaster/postmaster.c:4364
+#: replication/logical/origin.c:542 replication/slot.c:1045
+#: storage/file/copydir.c:162 storage/smgr/md.c:327 utils/time/snapmgr.c:1275
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "\"%s\" 파일을 만들 수 없음: %m"
+
+#: access/heap/rewriteheap.c:1147
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "\"%s\" 파일을 %u 크기로 정리할 수 없음: %m"
+
+#: access/heap/rewriteheap.c:1154 replication/walsender.c:481
+#: storage/smgr/md.c:1899
+#, c-format
+msgid "could not seek to end of file \"%s\": %m"
+msgstr "\"%s\" 파일의 끝을 찾을 수 없음: %m"
+
+#: access/heap/rewriteheap.c:1165 access/transam/timeline.c:367
+#: access/transam/timeline.c:401 access/transam/timeline.c:477
+#: access/transam/xlog.c:3078 access/transam/xlog.c:3242
+#: postmaster/postmaster.c:4374 postmaster/postmaster.c:4384
+#: replication/logical/origin.c:551 replication/logical/origin.c:587
+#: replication/logical/origin.c:603 replication/logical/snapbuild.c:1589
+#: replication/slot.c:1074 storage/file/copydir.c:187
+#: utils/init/miscinit.c:1228 utils/init/miscinit.c:1237
+#: utils/init/miscinit.c:1244 utils/misc/guc.c:6846 utils/misc/guc.c:6877
+#: utils/misc/guc.c:8727 utils/misc/guc.c:8741 utils/time/snapmgr.c:1280
+#: utils/time/snapmgr.c:1287
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "\"%s\" 파일 쓰기 실패: %m"
+
+#: access/heap/rewriteheap.c:1248 access/transam/xlog.c:10441
+#: access/transam/xlogarchive.c:114 access/transam/xlogarchive.c:468
+#: replication/logical/origin.c:529 replication/logical/reorderbuffer.c:2632
+#: replication/logical/reorderbuffer.c:2689
+#: replication/logical/snapbuild.c:1533 replication/logical/snapbuild.c:1908
+#: replication/slot.c:1147 storage/ipc/dsm.c:326 storage/smgr/md.c:427
+#: storage/smgr/md.c:476 storage/smgr/md.c:1394
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "\"%s\" 파일을 삭제할 수 없음: %m"
+
+#: access/heap/rewriteheap.c:1262 access/transam/timeline.c:111
+#: access/transam/timeline.c:236 access/transam/timeline.c:334
+#: access/transam/xlog.c:3019 access/transam/xlog.c:3136
+#: access/transam/xlog.c:3177 access/transam/xlog.c:3450
+#: access/transam/xlog.c:3528 access/transam/xlogutils.c:701
+#: replication/basebackup.c:403 replication/basebackup.c:1150
+#: replication/logical/origin.c:658 replication/logical/reorderbuffer.c:2156
+#: replication/logical/reorderbuffer.c:2402
+#: replication/logical/reorderbuffer.c:3081
+#: replication/logical/snapbuild.c:1582 replication/logical/snapbuild.c:1666
+#: replication/slot.c:1162 replication/walsender.c:474
+#: replication/walsender.c:2100 storage/file/copydir.c:155
+#: storage/file/fd.c:614 storage/file/fd.c:3041 storage/file/fd.c:3108
+#: storage/smgr/md.c:609 utils/error/elog.c:1879 utils/init/miscinit.c:1163
+#: utils/init/miscinit.c:1284 utils/init/miscinit.c:1362 utils/misc/guc.c:7105
+#: utils/misc/guc.c:7138
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "\"%s\" 파일을 열 수 없음: %m"
+
+#: access/index/amapi.c:82 commands/amcmds.c:164
+#, c-format
+msgid "access method \"%s\" is not of type %s"
+msgstr "\"%s\" 접근 방법은 %s 자료형에는 쓸 수 없음"
+
+#: access/index/amapi.c:98
+#, c-format
+msgid "index access method \"%s\" does not have a handler"
+msgstr "\"%s\" 인덱스 접근 방법에 대한 핸들러가 없음"
+
+#: access/index/indexam.c:155 catalog/objectaddress.c:1196
+#: commands/indexcmds.c:1800 commands/tablecmds.c:242
+#: commands/tablecmds.c:12180
+#, c-format
+msgid "\"%s\" is not an index"
+msgstr "\"%s\" 객체는 인덱스가 아닙니다"
+
+#: access/nbtree/nbtinsert.c:428
+#, c-format
+msgid "duplicate key value violates unique constraint \"%s\""
+msgstr "중복된 키 값이 \"%s\" 고유 제약 조건을 위반함"
+
+#: access/nbtree/nbtinsert.c:430
+#, c-format
+msgid "Key %s already exists."
+msgstr "%s 키가 이미 있습니다."
+
+#: access/nbtree/nbtinsert.c:497
+#, c-format
+msgid "failed to re-find tuple within index \"%s\""
+msgstr "\"%s\" 인덱스에서 튜플 재검색 실패"
+
+#: access/nbtree/nbtinsert.c:499
+#, c-format
+msgid "This may be because of a non-immutable index expression."
+msgstr "이 문제는 non-immutable 인덱스 표현식 때문인듯 합니다."
+
+#: access/nbtree/nbtinsert.c:579 access/nbtree/nbtsort.c:491
+#, c-format
+msgid ""
+"Values larger than 1/3 of a buffer page cannot be indexed.\n"
+"Consider a function index of an MD5 hash of the value, or use full text "
+"indexing."
+msgstr ""
+"버퍼 페이지의 1/3보다 큰 값은 인덱싱할 수 없습니다.\n"
+"값의 MD5 해시 함수 인덱스를 고려하거나 전체 텍스트 인덱싱을 사용하십시오."
+
+#: access/nbtree/nbtpage.c:168 access/nbtree/nbtpage.c:371
+#: access/nbtree/nbtpage.c:458 parser/parse_utilcmd.c:1702
+#, c-format
+msgid "index \"%s\" is not a btree"
+msgstr "\"%s\" 인덱스는 btree 인덱스가 아닙니다"
+
+#: access/nbtree/nbtpage.c:174 access/nbtree/nbtpage.c:377
+#: access/nbtree/nbtpage.c:464
+#, c-format
+msgid "version mismatch in index \"%s\": file version %d, code version %d"
+msgstr "\"%s\" 인덱스의 버전이 틀립니다: 파일 버전 %d, 코드 버전 %d"
+
+#: access/nbtree/nbtpage.c:1152
+#, c-format
+msgid "index \"%s\" contains a half-dead internal page"
+msgstr "\"%s\" 인덱스에 반쯤 죽은(half-dead) 내부 페이지가 있음"
+
+#: access/nbtree/nbtpage.c:1154
+#, c-format
+msgid ""
+"This can be caused by an interrupted VACUUM in version 9.3 or older, before "
+"upgrade. Please REINDEX it."
+msgstr ""
+"이 문제는 9.3 버전 이하 환경에서 VACUUM 작업이 중지되고, 그 상태로 업그레이드"
+"되었을 가능성이 큽니다. 해당 인덱스를 다시 만드십시오."
+
+#: access/nbtree/nbtvalidate.c:100
+#, c-format
+msgid ""
+"btree operator family \"%s\" contains function %s with invalid support "
+"number %d"
+msgstr ""
+"\"%s\" btree 연산자 패밀리에 포함된 %s 함수가 잘못된 지원 번호 %d 로 지정되었"
+"습니다."
+
+#: access/nbtree/nbtvalidate.c:112
+#, c-format
+msgid ""
+"btree operator family \"%s\" contains function %s with wrong signature for "
+"support number %d"
+msgstr ""
+"\"%s\" btree 연산자 패밀리에 포함된 %s 함수가 잘못된 signature 지원 번호 %d "
+"로 지정되었습니다."
+
+#: access/nbtree/nbtvalidate.c:132
+#, c-format
+msgid ""
+"btree operator family \"%s\" contains operator %s with invalid strategy "
+"number %d"
+msgstr ""
+"\"%s\" btree 연산자 패밀리에 포함된 %s 연산자의 %d 번 전략 번호가 잘못되었습"
+"니다."
+
+#: access/nbtree/nbtvalidate.c:145
+#, c-format
+msgid ""
+"btree operator family \"%s\" contains invalid ORDER BY specification for "
+"operator %s"
+msgstr ""
+"\"%s\" btree 연산자 패밀리에 %s 연산자가 잘못된 ORDER BY 명세를 사용합니다."
+
+#: access/nbtree/nbtvalidate.c:158
+#, c-format
+msgid "btree operator family \"%s\" contains operator %s with wrong signature"
+msgstr "\"%s\" btree 연산자 패밀리에 %s 연산자가 잘못된 기호를 사용합니다."
+
+#: access/nbtree/nbtvalidate.c:200
+#, c-format
+msgid "btree operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr "\"%s\" btree 연산자 패밀리에는 %s 자료형과 %s 자료형용 연산자가 빠졌음"
+
+#: access/nbtree/nbtvalidate.c:210
+#, c-format
+msgid ""
+"btree operator family \"%s\" is missing support function for types %s and %s"
+msgstr ""
+"\"%s\" btree 연산자 패밀리에는 %s 자료형과 %s 자료형용 지원 함수가 빠졌음"
+
+#: access/nbtree/nbtvalidate.c:224
+#, c-format
+msgid "btree operator class \"%s\" is missing operator(s)"
+msgstr "\"%s\" btree 연산자 클래스에는 연산자가 빠졌음"
+
+#: access/nbtree/nbtvalidate.c:241
+#, c-format
+msgid "btree operator family \"%s\" is missing cross-type operator(s)"
+msgstr "\"%s\" btree 연산자 클래스에는 cross-type 연산자가 빠졌음"
+
+#: access/spgist/spgutils.c:700
+#, c-format
+msgid "SP-GiST inner tuple size %zu exceeds maximum %zu"
+msgstr "SP-GiST 내부 튜플 크기가 초과됨: 현재값 %zu, 최대값 %zu"
+
+#: access/spgist/spgvalidate.c:92
+#, c-format
+msgid ""
+"spgist operator family \"%s\" contains support procedure %s with cross-type "
+"registration"
+msgstr ""
+"\"%s\" spgist 연산자 패밀리에 cross-type registration 으로 %s 지원 프로시져"
+"가 포함되어 있습니다."
+
+#: access/spgist/spgvalidate.c:115
+#, c-format
+msgid ""
+"spgist operator family \"%s\" contains function %s with invalid support "
+"number %d"
+msgstr ""
+"\"%s\" spgist 연산자 패밀리에 포함된 %s 함수가 잘못된 지원 번호 %d 로 지정되"
+"었습니다."
+
+#: access/spgist/spgvalidate.c:127
+#, c-format
+msgid ""
+"spgist operator family \"%s\" contains function %s with wrong signature for "
+"support number %d"
+msgstr ""
+"\"%s\" spgist 연산자 패밀리에 포함된 %s 함수가 잘못된 signature 지원 번호 %d "
+"로 지정되었습니다."
+
+#: access/spgist/spgvalidate.c:146
+#, c-format
+msgid ""
+"spgist operator family \"%s\" contains operator %s with invalid strategy "
+"number %d"
+msgstr ""
+"\"%s\" spgist 연산자 패밀리에 포함된 %s 연산자의 %d 번 전략 번호가 잘못되었습"
+"니다."
+
+#: access/spgist/spgvalidate.c:159
+#, c-format
+msgid ""
+"spgist operator family \"%s\" contains invalid ORDER BY specification for "
+"operator %s"
+msgstr ""
+"\"%s\" spgist 연산자 패밀리에 %s 연산자가 잘못된 ORDER BY 명세를 사용합니다."
+
+#: access/spgist/spgvalidate.c:172
+#, c-format
+msgid "spgist operator family \"%s\" contains operator %s with wrong signature"
+msgstr "\"%s\" spgist 연산자 패밀리에 %s 연산자가 잘못된 기호를 사용합니다."
+
+#: access/spgist/spgvalidate.c:200
+#, c-format
+msgid ""
+"spgist operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr ""
+"\"%s\" spgist 연산자 패밀리에서 %s 자료형과 %s 자료형용 연산자가 빠졌음"
+
+#: access/spgist/spgvalidate.c:220
+#, c-format
+msgid ""
+"spgist operator family \"%s\" is missing support function %d for type %s"
+msgstr "\"%s\" spgist 연산자 패밀리에 %d 지원 함수가 %s 자료형용으로 없습니다."
+
+#: access/spgist/spgvalidate.c:233
+#, c-format
+msgid "spgist operator class \"%s\" is missing operator(s)"
+msgstr "\"%s\" spgist 연산자 클래스에 연산자가 빠졌음"
+
+#: access/tablesample/bernoulli.c:152 access/tablesample/system.c:156
+#, c-format
+msgid "sample percentage must be between 0 and 100"
+msgstr "샘플 퍼센트 값은 0에서 100 사이여야 함"
+
+#: access/transam/commit_ts.c:294
+#, c-format
+msgid "cannot retrieve commit timestamp for transaction %u"
+msgstr "%u 트랜잭션의 커밋 타임스탬프를 알 수 없음"
+
+#: access/transam/commit_ts.c:392
+#, c-format
+msgid "could not get commit timestamp data"
+msgstr "커밋 타임스탬프 자료를 찾을 수 없음"
+
+#: access/transam/commit_ts.c:394
+#, c-format
+msgid ""
+"Make sure the configuration parameter \"%s\" is set on the master server."
+msgstr "운영 서버에서 \"%s\" 환경 설정 매개 변수값을 지정 하세요."
+
+#: access/transam/commit_ts.c:396 libpq/hba.c:1439
+#, c-format
+msgid "Make sure the configuration parameter \"%s\" is set."
+msgstr "\"%s\" 환경 설정 매개 변수를 지정하세요."
+
+#: access/transam/multixact.c:1000
+#, c-format
+msgid ""
+"database is not accepting commands that generate new MultiXactIds to avoid "
+"wraparound data loss in database \"%s\""
+msgstr ""
+"\"%s\" 데이터베이스 자료 손실을 막기 위해 새로운 MultiXactId 만드는 작업을 "
+"더 이상 할 수 없습니다."
+
+#: access/transam/multixact.c:1002 access/transam/multixact.c:1009
+#: access/transam/multixact.c:1033 access/transam/multixact.c:1042
+#, c-format
+msgid ""
+"Execute a database-wide VACUUM in that database.\n"
+"You might also need to commit or roll back old prepared transactions."
+msgstr ""
+"해당 데이터베이스 단위로 VACUUM 작업을 진행하십시오.\n"
+"또한 오래된 트랜잭션을 커밋하거나 롤백할 필요가 있습니다."
+
+#: access/transam/multixact.c:1007
+#, c-format
+msgid ""
+"database is not accepting commands that generate new MultiXactIds to avoid "
+"wraparound data loss in database with OID %u"
+msgstr ""
+"%u OID 데이터베이스 자료 손실을 막기 위해 새로운 MultiXactId 만드는 작업을 "
+"더 이상 할 수 없습니다."
+
+#: access/transam/multixact.c:1028 access/transam/multixact.c:2314
+#, c-format
+msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used"
+msgid_plural ""
+"database \"%s\" must be vacuumed before %u more MultiXactIds are used"
+msgstr[0] ""
+"\"%s\" 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 VACUUM 작업을 해야 합니"
+"다."
+
+#: access/transam/multixact.c:1037 access/transam/multixact.c:2323
+#, c-format
+msgid ""
+"database with OID %u must be vacuumed before %u more MultiXactId is used"
+msgid_plural ""
+"database with OID %u must be vacuumed before %u more MultiXactIds are used"
+msgstr[0] ""
+"%u OID 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 VACUUM 작업을 해야 합니"
+"다."
+
+#: access/transam/multixact.c:1098
+#, c-format
+msgid "multixact \"members\" limit exceeded"
+msgstr "multixact \"회수\" 초과"
+
+#: access/transam/multixact.c:1099
+#, c-format
+msgid ""
+"This command would create a multixact with %u members, but the remaining "
+"space is only enough for %u member."
+msgid_plural ""
+"This command would create a multixact with %u members, but the remaining "
+"space is only enough for %u members."
+msgstr[0] ""
+"이 명령은 %u 개의 multixact를 써야하는데, 쓸 수 있는 공간은 %u 개 뿐입니다."
+
+#: access/transam/multixact.c:1104
+#, c-format
+msgid ""
+"Execute a database-wide VACUUM in database with OID %u with reduced "
+"vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age "
+"settings."
+msgstr ""
+"vacuum_multixact_freeze_min_age, vacuum_multixact_freeze_table_age 값을 조정"
+"하고, %u OID 데이터베이스 대상으로 VACUUM 작업을 하십시오."
+
+#: access/transam/multixact.c:1135
+#, c-format
+msgid ""
+"database with OID %u must be vacuumed before %d more multixact member is used"
+msgid_plural ""
+"database with OID %u must be vacuumed before %d more multixact members are "
+"used"
+msgstr[0] ""
+"%u OID 데이터베이스는 %d 개의 멀티트랜잭션을 사용하기 전에 vacuum 작업을 해"
+"야 합니다."
+
+#: access/transam/multixact.c:1140
+#, c-format
+msgid ""
+"Execute a database-wide VACUUM in that database with reduced "
+"vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age "
+"settings."
+msgstr ""
+"vacuum_multixact_freeze_min_age 설정값과 vacuum_multixact_freeze_table_age 값"
+"을 줄여서 데이터베이스 단위로 VACUUM 작업을 진행하세요."
+
+#: access/transam/multixact.c:1277
+#, c-format
+msgid "MultiXactId %u does no longer exist -- apparent wraparound"
+msgstr "%u번 MultiXactId 더이상 없음 -- 번호 겹침 현상 발생"
+
+#: access/transam/multixact.c:1285
+#, c-format
+msgid "MultiXactId %u has not been created yet -- apparent wraparound"
+msgstr "%u번 MultiXactId를 만들 수 없음 -- 번호 겹침 현상 발생"
+
+#: access/transam/multixact.c:2264
+#, c-format
+msgid "MultiXactId wrap limit is %u, limited by database with OID %u"
+msgstr "MultiXactId 겹침 한계는 %u 입니다. %u OID 데이터베이스에서 제한됨"
+
+#: access/transam/multixact.c:2319 access/transam/multixact.c:2328
+#: access/transam/varsup.c:146 access/transam/varsup.c:153
+#: access/transam/varsup.c:384 access/transam/varsup.c:391
+#, c-format
+msgid ""
+"To avoid a database shutdown, execute a database-wide VACUUM in that "
+"database.\n"
+"You might also need to commit or roll back old prepared transactions."
+msgstr ""
+"데이터베이스가 종료되지 않도록 하려면 데이터베이스 수준의 VACUUM을 실행하십시"
+"오.\n"
+"또한 오래된 트랜잭션을 커밋하거나 롤백할 필요가 있습니다."
+
+#: access/transam/multixact.c:2598
+#, c-format
+msgid "oldest MultiXactId member is at offset %u"
+msgstr "제일 오래된 MultiXactId 값은 %u 위치에 있음"
+
+#: access/transam/multixact.c:2602
+#, c-format
+msgid ""
+"MultiXact member wraparound protections are disabled because oldest "
+"checkpointed MultiXact %u does not exist on disk"
+msgstr ""
+"가장 오래된 체크포인트 작업이 완료된 %u 멀티 트랜잭션 번호가 디스크에 없기 때"
+"문에, 멀티 트랜잭션 번호 겹침 방지 기능이 비활성화 되어 있습니다."
+
+#: access/transam/multixact.c:2624
+#, c-format
+msgid "MultiXact member wraparound protections are now enabled"
+msgstr "멀티 트랜잭션 번호 겹침 방지 기능이 활성화 되었음"
+
+#: access/transam/multixact.c:2626
+#, c-format
+msgid "MultiXact member stop limit is now %u based on MultiXact %u"
+msgstr "멀티 트랜잭션 중지 제한 번호는 %u 입니다. (%u 멀티트랜잭션에 기초함)"
+
+#: access/transam/multixact.c:3006
+#, c-format
+msgid ""
+"oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation"
+msgstr ""
+"가장 오래된 멀티 트랜잭션 번호는 %u, 가장 최신 것은 %u, truncate 작업 건너뜀"
+
+#: access/transam/multixact.c:3024
+#, c-format
+msgid ""
+"cannot truncate up to MultiXact %u because it does not exist on disk, "
+"skipping truncation"
+msgstr ""
+"디스크에 해당 멀티 트랜잭션 번호가 없어, %u 멀티 트랜잭션 번호로 truncate 못"
+"함, truncate 작업 건너뜀"
+
+#: access/transam/multixact.c:3350
+#, c-format
+msgid "invalid MultiXactId: %u"
+msgstr "잘못된 MultiXactId: %u"
+
+#: access/transam/parallel.c:589
+#, c-format
+msgid "postmaster exited during a parallel transaction"
+msgstr "병렬 트랜잭션 처리 중 postmaster 종료됨"
+
+#: access/transam/parallel.c:774
+#, c-format
+msgid "lost connection to parallel worker"
+msgstr "병렬 처리 작업자 프로세스 연결 끊김"
+
+#: access/transam/parallel.c:833 access/transam/parallel.c:835
+msgid "parallel worker"
+msgstr "병렬 처리 작업자"
+
+#: access/transam/parallel.c:974
+#, c-format
+msgid "could not map dynamic shared memory segment"
+msgstr "동적 공유 메모리 세그먼트를 할당할 수 없음"
+
+#: access/transam/parallel.c:979
+#, c-format
+msgid "invalid magic number in dynamic shared memory segment"
+msgstr "동적 공유 메모리 세그먼트에 잘못된 매직 번호가 있음"
+
+#: access/transam/slru.c:665
+#, c-format
+msgid "file \"%s\" doesn't exist, reading as zeroes"
+msgstr "\"%s\" 파일 없음, 0으로 읽음"
+
+#: access/transam/slru.c:895 access/transam/slru.c:901
+#: access/transam/slru.c:908 access/transam/slru.c:915
+#: access/transam/slru.c:922 access/transam/slru.c:929
+#, c-format
+msgid "could not access status of transaction %u"
+msgstr "%u 트랜잭션의 상태를 액세스할 수 없음"
+
+#: access/transam/slru.c:896
+#, c-format
+msgid "Could not open file \"%s\": %m."
+msgstr "\"%s\" 파일을 열 수 없음: %m."
+
+#: access/transam/slru.c:902
+#, c-format
+msgid "Could not seek in file \"%s\" to offset %u: %m."
+msgstr "\"%s\" 파일에서 %u 위치를 찾을 수 없음: %m."
+
+#: access/transam/slru.c:909
+#, c-format
+msgid "Could not read from file \"%s\" at offset %u: %m."
+msgstr "\"%s\" 파일에서 %u 위치를 읽을 수 없음: %m."
+
+#: access/transam/slru.c:916
+#, c-format
+msgid "Could not write to file \"%s\" at offset %u: %m."
+msgstr "\"%s\" 파일에서 %u 위치에 쓸 수 없음: %m."
+
+#: access/transam/slru.c:923
+#, c-format
+msgid "Could not fsync file \"%s\": %m."
+msgstr "\"%s\" 파일 fsync 실패: %m."
+
+#: access/transam/slru.c:930
+#, c-format
+msgid "Could not close file \"%s\": %m."
+msgstr "\"%s\" 파일을 닫을 수 없음: %m."
+
+#: access/transam/slru.c:1185
+#, c-format
+msgid "could not truncate directory \"%s\": apparent wraparound"
+msgstr "\"%s\" 디렉터리를 비울 수 없음: 랩어라운드 발생"
+
+#: access/transam/slru.c:1240 access/transam/slru.c:1296
+#, c-format
+msgid "removing file \"%s\""
+msgstr "\"%s\" 파일 삭제 중"
+
+#: access/transam/timeline.c:148 access/transam/timeline.c:153
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "히스토리 파일에서 문법오류: %s"
+
+#: access/transam/timeline.c:149
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "숫자 타임라인 ID가 필요합니다."
+
+#: access/transam/timeline.c:154
+#, c-format
+msgid "Expected a transaction log switchpoint location."
+msgstr "트랜잭션 로그 전환 위치 값이 있어야 함"
+
+#: access/transam/timeline.c:158
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "작업내역 파일에 잘못된 자료가 있음: %s"
+
+#: access/transam/timeline.c:159
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "타임라인 ID 값은 그 값이 증가하는 순번값이어야합니다."
+
+#: access/transam/timeline.c:179
+#, c-format
+msgid "invalid data in history file \"%s\""
+msgstr "작업내역 파일에 잘못된 자료가 있음: \"%s\""
+
+#: access/transam/timeline.c:180
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "타임라인 ID는 하위 타임라인 ID보다 작아야 합니다."
+
+#: access/transam/timeline.c:412 access/transam/timeline.c:488
+#: access/transam/xlog.c:3093 access/transam/xlog.c:3254
+#: access/transam/xlogfuncs.c:690 commands/copy.c:1708
+#: storage/file/copydir.c:201
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "\"%s\" 파일을 닫을 수 없음: %m"
+
+#: access/transam/timeline.c:570
+#, c-format
+msgid "requested timeline %u is not in this server's history"
+msgstr "요청한 %u 타이라인이 이 서버 내역에는 없음"
+
+#: access/transam/twophase.c:363
+#, c-format
+msgid "transaction identifier \"%s\" is too long"
+msgstr "\"%s\" 트랜잭션 식별자가 너무 깁니다"
+
+#: access/transam/twophase.c:370
+#, c-format
+msgid "prepared transactions are disabled"
+msgstr "준비된 트랜잭션이 비활성화됨"
+
+#: access/transam/twophase.c:371
+#, c-format
+msgid "Set max_prepared_transactions to a nonzero value."
+msgstr "max_prepared_transactions 설정값을 0이 아닌 값으로 설정하십시오."
+
+#: access/transam/twophase.c:390
+#, c-format
+msgid "transaction identifier \"%s\" is already in use"
+msgstr "\"%s\" 이름의 트랜잭션 식별자가 이미 사용 중입니다"
+
+#: access/transam/twophase.c:399
+#, c-format
+msgid "maximum number of prepared transactions reached"
+msgstr "준비된 트랜잭션의 최대 개수를 모두 사용했습니다"
+
+#: access/transam/twophase.c:400
+#, c-format
+msgid "Increase max_prepared_transactions (currently %d)."
+msgstr "max_prepared_transactions 값을 늘려주세요 (현재 %d)."
+
+#: access/transam/twophase.c:540
+#, c-format
+msgid "prepared transaction with identifier \"%s\" is busy"
+msgstr "\"%s\" 이름의 준비된 트랜잭션 식별자가 여러 곳에서 쓰이고 있습니다"
+
+#: access/transam/twophase.c:546
+#, c-format
+msgid "permission denied to finish prepared transaction"
+msgstr "준비된 트랜잭션 끝내기 작업 권한 없음"
+
+#: access/transam/twophase.c:547
+#, c-format
+msgid "Must be superuser or the user that prepared the transaction."
+msgstr "해당 준비된 트랜잭션의 소유주이거나 superuser여야합니다"
+
+#: access/transam/twophase.c:558
+#, c-format
+msgid "prepared transaction belongs to another database"
+msgstr "준비된 트랜잭션이 다른 데이터베이스에 속해 있음"
+
+#: access/transam/twophase.c:559
+#, c-format
+msgid ""
+"Connect to the database where the transaction was prepared to finish it."
+msgstr "작업을 마치려면 그 준비된 트랜잭션이 있는 데이터베이스에 연결하십시오."
+
+#: access/transam/twophase.c:574
+#, c-format
+msgid "prepared transaction with identifier \"%s\" does not exist"
+msgstr "\"%s\" 이름의 준비된 트랜잭션이 없습니다"
+
+#: access/transam/twophase.c:1043
+#, c-format
+msgid "two-phase state file maximum length exceeded"
+msgstr "2단계 상태 파일 최대 길이를 초과함"
+
+#: access/transam/twophase.c:1161
+#, c-format
+msgid "could not open two-phase state file \"%s\": %m"
+msgstr "\"%s\" 이름의 two-phase 상태정보 파일을 열 수 없음: %m"
+
+#: access/transam/twophase.c:1178
+#, c-format
+msgid "could not stat two-phase state file \"%s\": %m"
+msgstr "\"%s\" 이름의 two-phase 상태정보 파일의 파일정보를 알 수 없음: %m"
+
+#: access/transam/twophase.c:1210
+#, c-format
+msgid "could not read two-phase state file \"%s\": %m"
+msgstr "\"%s\" 이름의 two-phase 상태정보 파일을 읽을 수 없음: %m"
+
+#: access/transam/twophase.c:1263 access/transam/xlog.c:6109
+#, c-format
+msgid "Failed while allocating an XLog reading processor."
+msgstr "XLog 읽기 프로세서를 할당하는 중에 오류 발생"
+
+#: access/transam/twophase.c:1269
+#, c-format
+msgid "could not read two-phase state from xlog at %X/%X"
+msgstr "two-phase 상태정보을 읽을 수 없음 xlog 위치: %X/%X"
+
+#: access/transam/twophase.c:1277
+#, c-format
+msgid "expected two-phase state data is not present in xlog at %X/%X"
+msgstr "xlog %X/%X 위치에 2단계 커밋 상태 자료가 없습니다"
+
+#: access/transam/twophase.c:1512
+#, c-format
+msgid "could not remove two-phase state file \"%s\": %m"
+msgstr "\"%s\" 이름의 two-phase 상태정보 파일을 삭제할 수 없음: %m"
+
+#: access/transam/twophase.c:1542
+#, c-format
+msgid "could not recreate two-phase state file \"%s\": %m"
+msgstr "\"%s\" 이름의 two-phase 상태정보 파일을 다시 만들 수 없음: %m"
+
+#: access/transam/twophase.c:1551 access/transam/twophase.c:1558
+#, c-format
+msgid "could not write two-phase state file: %m"
+msgstr "two-phase 상태정보 파일을 쓸 수 없음: %m"
+
+#: access/transam/twophase.c:1570
+#, c-format
+msgid "could not fsync two-phase state file: %m"
+msgstr "two-phase 상태정보 파일의 fsync 작업 실패: %m"
+
+#: access/transam/twophase.c:1576
+#, c-format
+msgid "could not close two-phase state file: %m"
+msgstr "two-phase 상태정보 파일을 닫을 수 없음: %m"
+
+#: access/transam/twophase.c:1649
+#, c-format
+msgid ""
+"%u two-phase state file was written for long-running prepared transactions"
+msgid_plural ""
+"%u two-phase state files were written for long-running prepared transactions"
+msgstr[0] ""
+
+#: access/transam/twophase.c:1713
+#, c-format
+msgid "removing future two-phase state file \"%s\""
+msgstr "\"%s\" 이름의 future two-phase 상태정보 파일을 삭제함"
+
+#: access/transam/twophase.c:1729 access/transam/twophase.c:1740
+#: access/transam/twophase.c:1860 access/transam/twophase.c:1871
+#: access/transam/twophase.c:1948
+#, c-format
+msgid "removing corrupt two-phase state file \"%s\""
+msgstr "\"%s\" 이름의 잘못된 two-phase 상태정보 파일을 삭제함"
+
+#: access/transam/twophase.c:1849 access/transam/twophase.c:1937
+#, c-format
+msgid "removing stale two-phase state file \"%s\""
+msgstr "\"%s\" 이름의 오래된 two-phase 상태정보 파일을 삭제함"
+
+#: access/transam/twophase.c:1955
+#, c-format
+msgid "recovering prepared transaction %u"
+msgstr "%u 준비된 트랜잭션을 복구함"
+
+#: access/transam/varsup.c:124
+#, c-format
+msgid ""
+"database is not accepting commands to avoid wraparound data loss in database "
+"\"%s\""
+msgstr ""
+"\"%s\" 데이터베이스 트랜잭션 ID 겹침에 의한 자료 손실을 방지하기 위해 더 이"
+"상 자료 조작 작업을 허용하지 않습니다"
+
+#: access/transam/varsup.c:126 access/transam/varsup.c:133
+#, c-format
+msgid ""
+"Stop the postmaster and vacuum that database in single-user mode.\n"
+"You might also need to commit or roll back old prepared transactions."
+msgstr ""
+"postmaster를 중지하고 단일 사용자 모드로 서버를 실행한 뒤 VACUUM 작업을 하십"
+"시오.\n"
+"또한 오래된 트랜잭션을 커밋하거나 롤백할 필요가 있습니다."
+
+#: access/transam/varsup.c:131
+#, c-format
+msgid ""
+"database is not accepting commands to avoid wraparound data loss in database "
+"with OID %u"
+msgstr ""
+"%u OID 데이터베이스에서 자료 겹침으로 발생할 수 있는 자료 손실을 방지하기 위"
+"해 명령을 수락하지 않음"
+
+#: access/transam/varsup.c:143 access/transam/varsup.c:381
+#, c-format
+msgid "database \"%s\" must be vacuumed within %u transactions"
+msgstr "\"%s\" 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 청소해야 합니다"
+
+#: access/transam/varsup.c:150 access/transam/varsup.c:388
+#, c-format
+msgid "database with OID %u must be vacuumed within %u transactions"
+msgstr "%u OID 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 청소해야 합니다"
+
+#: access/transam/varsup.c:346
+#, c-format
+msgid "transaction ID wrap limit is %u, limited by database with OID %u"
+msgstr "트랜잭션 ID 겹침 제한은 %u번 입니다., %u OID 데이터베이스에서 제한됨"
+
+#: access/transam/xact.c:943
+#, c-format
+msgid "cannot have more than 2^32-2 commands in a transaction"
+msgstr "하나의 트랜잭션 안에서는 2^32-2 개의 명령을 초과할 수 없음"
+
+#: access/transam/xact.c:1467
+#, c-format
+msgid "maximum number of committed subtransactions (%d) exceeded"
+msgstr "커밋된 하위 트랜잭션 수(%d)가 최대치를 초과함"
+
+#: access/transam/xact.c:2263
+#, c-format
+msgid "cannot PREPARE a transaction that has operated on temporary tables"
+msgstr "임시 테이블에 대해 실행된 트랜잭션을 PREPARE할 수 없음"
+
+#: access/transam/xact.c:2273
+#, c-format
+msgid "cannot PREPARE a transaction that has exported snapshots"
+msgstr "스냅샷으로 내보낸 트랜잭션은 PREPARE 작업을 할 수 없음"
+
+#. translator: %s represents an SQL statement name
+#: access/transam/xact.c:3155
+#, c-format
+msgid "%s cannot run inside a transaction block"
+msgstr "%s 명령은 트랜잭션 블럭안에서 실행할 수 없음"
+
+#. translator: %s represents an SQL statement name
+#: access/transam/xact.c:3165
+#, c-format
+msgid "%s cannot run inside a subtransaction"
+msgstr "%s 명령은 서브트랜잭션 블럭안에서 실행할 수 없음"
+
+#. translator: %s represents an SQL statement name
+#: access/transam/xact.c:3175
+#, c-format
+msgid "%s cannot be executed from a function or multi-command string"
+msgstr "%s 명령은 함수나 다중명령에서 실행할 수 없음"
+
+#. translator: %s represents an SQL statement name
+#: access/transam/xact.c:3246
+#, c-format
+msgid "%s can only be used in transaction blocks"
+msgstr "%s 명령은 트랜잭션 블럭에서만 사용될 수 있음"
+
+#: access/transam/xact.c:3430
+#, c-format
+msgid "there is already a transaction in progress"
+msgstr "이미 트랜잭션 작업이 진행 중입니다"
+
+#: access/transam/xact.c:3598 access/transam/xact.c:3701
+#, c-format
+msgid "there is no transaction in progress"
+msgstr "현재 트랜잭션 작업을 하지 않고 있습니다"
+
+#: access/transam/xact.c:3609
+#, c-format
+msgid "cannot commit during a parallel operation"
+msgstr "데이터베이스 트랜잭션을 commit 할 수 없음"
+
+#: access/transam/xact.c:3712
+#, c-format
+msgid "cannot abort during a parallel operation"
+msgstr "병렬 작업 중에는 중지 할 수 없음"
+
+#: access/transam/xact.c:3754
+#, c-format
+msgid "cannot define savepoints during a parallel operation"
+msgstr "병렬 작업 중에는 savepoint 지정을 할 수 없음"
+
+#: access/transam/xact.c:3821
+#, c-format
+msgid "cannot release savepoints during a parallel operation"
+msgstr "병렬 작업 중에는 savepoint를 지울 수 없음"
+
+#: access/transam/xact.c:3832 access/transam/xact.c:3884
+#: access/transam/xact.c:3890 access/transam/xact.c:3946
+#: access/transam/xact.c:3996 access/transam/xact.c:4002
+#, c-format
+msgid "no such savepoint"
+msgstr "그런 savepoint가 없습니다"
+
+#: access/transam/xact.c:3934
+#, c-format
+msgid "cannot rollback to savepoints during a parallel operation"
+msgstr "병렬 작업 중에는 savepoint 지정 취소 작업을 할 수 없음"
+
+#: access/transam/xact.c:4062
+#, c-format
+msgid "cannot start subtransactions during a parallel operation"
+msgstr "병렬 처리 중에는 하위트랜잭션을 시작할 수 없음"
+
+#: access/transam/xact.c:4129
+#, c-format
+msgid "cannot commit subtransactions during a parallel operation"
+msgstr "병렬 처리 중에는 하위트랜잭션을 커밋할 수 없음"
+
+#: access/transam/xact.c:4737
+#, c-format
+msgid "cannot have more than 2^32-1 subtransactions in a transaction"
+msgstr "하나의 트랜잭션 안에서는 2^32-1 개의 하위트랜잭션을 초과할 수 없음"
+
+#: access/transam/xlog.c:2299
+#, c-format
+msgid "could not seek in log file %s to offset %u: %m"
+msgstr "%s 파일에서 %u 위치를 찾을 수 없음: %m"
+
+#: access/transam/xlog.c:2319
+#, c-format
+msgid "could not write to log file %s at offset %u, length %zu: %m"
+msgstr "%s 로그 파일 쓰기 실패, 위치 %u, 길이 %zu: %m"
+
+#: access/transam/xlog.c:2582
+#, c-format
+msgid "updated min recovery point to %X/%X on timeline %u"
+msgstr "최소 복구 지점: %X/%X, 타임라인: %u 변경 완료"
+
+#: access/transam/xlog.c:3224
+#, c-format
+msgid "not enough data in file \"%s\""
+msgstr "\"%s\" 파일에 자료가 불충분합니다"
+
+#: access/transam/xlog.c:3365
+#, c-format
+msgid "could not open transaction log file \"%s\": %m"
+msgstr "\"%s\" 트랜잭션 로그 파일을 열 수 없음: %m"
+
+#: access/transam/xlog.c:3554 access/transam/xlog.c:5339
+#, c-format
+msgid "could not close log file %s: %m"
+msgstr "%s 로그 파일을 닫을 수 없음: %m"
+
+#: access/transam/xlog.c:3611 access/transam/xlogutils.c:696
+#: replication/walsender.c:2095
+#, c-format
+msgid "requested WAL segment %s has already been removed"
+msgstr "요청한 %s WAL 조각 파일은 이미 지워졌음"
+
+#: access/transam/xlog.c:3671 access/transam/xlog.c:3746
+#: access/transam/xlog.c:3944
+#, c-format
+msgid "could not open transaction log directory \"%s\": %m"
+msgstr "\"%s\" 트랜잭션 로그 디렉터리 열기 실패: %m"
+
+#: access/transam/xlog.c:3827
+#, c-format
+msgid "recycled transaction log file \"%s\""
+msgstr "\"%s\" 트랜잭션 로그 파일 재활용함"
+
+#: access/transam/xlog.c:3839
+#, c-format
+msgid "removing transaction log file \"%s\""
+msgstr "\"%s\" 트랜잭션 로그 파일 삭제 중"
+
+#: access/transam/xlog.c:3859
+#, c-format
+msgid "could not rename old transaction log file \"%s\": %m"
+msgstr "이전 트랜잭션 로그 파일 \"%s\"의 이름을 바꿀 수 없음: %m"
+
+#: access/transam/xlog.c:3871
+#, c-format
+msgid "could not remove old transaction log file \"%s\": %m"
+msgstr "이전 트랜잭션 로그 파일 \"%s\"을(를) 제거할 수 없음: %m"
+
+#: access/transam/xlog.c:3904 access/transam/xlog.c:3914
+#, c-format
+msgid "required WAL directory \"%s\" does not exist"
+msgstr "필요한 WAL 디렉터리 \"%s\"이(가) 없음"
+
+#: access/transam/xlog.c:3920
+#, c-format
+msgid "creating missing WAL directory \"%s\""
+msgstr "누락된 WAL 디렉터리 \"%s\"을(를) 만드는 중"
+
+#: access/transam/xlog.c:3923
+#, c-format
+msgid "could not create missing directory \"%s\": %m"
+msgstr "누락된 \"%s\" 디렉터리를 만들 수 없음: %m"
+
+#: access/transam/xlog.c:3954
+#, c-format
+msgid "removing transaction log backup history file \"%s\""
+msgstr "\"%s\" 트랜잭션 로그 백업 히스토리 파일 삭제 중"
+
+#: access/transam/xlog.c:4035
+#, c-format
+msgid "unexpected timeline ID %u in log segment %s, offset %u"
+msgstr "예상치 못한 타임라인 ID %u, 로그 조각: %s, 위치: %u"
+
+#: access/transam/xlog.c:4157
+#, c-format
+msgid "new timeline %u is not a child of database system timeline %u"
+msgstr "요청한 %u 타임라인은 %u 데이터베이스 시스템 타임라인의 하위가 아님"
+
+#: access/transam/xlog.c:4171
+#, c-format
+msgid ""
+"new timeline %u forked off current database system timeline %u before "
+"current recovery point %X/%X"
+msgstr ""
+
+#: access/transam/xlog.c:4190
+#, c-format
+msgid "new target timeline is %u"
+msgstr "새 대상 타임라인: %u"
+
+#: access/transam/xlog.c:4270
+#, c-format
+msgid "could not create control file \"%s\": %m"
+msgstr "\"%s\" 컨트롤 파일 만들 수 없음: %m"
+
+#: access/transam/xlog.c:4281 access/transam/xlog.c:4517
+#, c-format
+msgid "could not write to control file: %m"
+msgstr "컨트롤 파일을 쓸 수 없음: %m"
+
+#: access/transam/xlog.c:4287 access/transam/xlog.c:4523
+#, c-format
+msgid "could not fsync control file: %m"
+msgstr "컨트롤 파일 fsync 실패: %m"
+
+#: access/transam/xlog.c:4292 access/transam/xlog.c:4528
+#, c-format
+msgid "could not close control file: %m"
+msgstr "컨트롤 파일 닫기 실패: %m"
+
+#: access/transam/xlog.c:4310 access/transam/xlog.c:4506
+#, c-format
+msgid "could not open control file \"%s\": %m"
+msgstr "\"%s\" 컨트롤 파일 열기 실패: %m"
+
+#: access/transam/xlog.c:4316
+#, c-format
+msgid "could not read from control file: %m"
+msgstr "컨트롤 파일 읽기 실패: %m"
+
+#: access/transam/xlog.c:4329 access/transam/xlog.c:4338
+#: access/transam/xlog.c:4362 access/transam/xlog.c:4369
+#: access/transam/xlog.c:4376 access/transam/xlog.c:4381
+#: access/transam/xlog.c:4388 access/transam/xlog.c:4395
+#: access/transam/xlog.c:4402 access/transam/xlog.c:4409
+#: access/transam/xlog.c:4416 access/transam/xlog.c:4423
+#: access/transam/xlog.c:4430 access/transam/xlog.c:4439
+#: access/transam/xlog.c:4446 access/transam/xlog.c:4455
+#: access/transam/xlog.c:4462 access/transam/xlog.c:4471
+#: access/transam/xlog.c:4478 utils/init/miscinit.c:1380
+#, c-format
+msgid "database files are incompatible with server"
+msgstr "데이터베이스 파일들이 서버와 호환성이 없습니다"
+
+#: access/transam/xlog.c:4330
+#, c-format
+msgid ""
+"The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), "
+"but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)."
+msgstr ""
+"데이터베이스 클러스터는 PG_CONTROL_VERSION %d (0x%08x)(으)로 초기화되었지만 "
+"서버는 PG_CONTROL_VERSION %d (0x%08x)(으)로 컴파일되었습니다."
+
+#: access/transam/xlog.c:4334
+#, c-format
+msgid ""
+"This could be a problem of mismatched byte ordering. It looks like you need "
+"to initdb."
+msgstr ""
+"이것은 바이트 순서 불일치 문제일 수 있습니다. initdb 작업이 필요해 보입니다."
+
+#: access/transam/xlog.c:4339
+#, c-format
+msgid ""
+"The database cluster was initialized with PG_CONTROL_VERSION %d, but the "
+"server was compiled with PG_CONTROL_VERSION %d."
+msgstr ""
+"이 데이터베이스 클러스터는 PG_CONTROL_VERSION %d 버전으로 초기화 되었지만, 서"
+"버는 PG_CONTROL_VERSION %d 버전으로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4342 access/transam/xlog.c:4366
+#: access/transam/xlog.c:4373 access/transam/xlog.c:4378
+#, c-format
+msgid "It looks like you need to initdb."
+msgstr "initdb 명령이 필요한 듯 합니다"
+
+#: access/transam/xlog.c:4353
+#, c-format
+msgid "incorrect checksum in control file"
+msgstr "컨트롤 파일에 잘못된 체크섬 값이 있습니다"
+
+#: access/transam/xlog.c:4363
+#, c-format
+msgid ""
+"The database cluster was initialized with CATALOG_VERSION_NO %d, but the "
+"server was compiled with CATALOG_VERSION_NO %d."
+msgstr ""
+"이 데이터베이스 클러스터는 CATALOG_VERSION_NO %d 버전으로 초기화 되었지만, 서"
+"버는 CATALOG_VERSION_NO %d 버전으로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4370
+#, c-format
+msgid ""
+"The database cluster was initialized with MAXALIGN %d, but the server was "
+"compiled with MAXALIGN %d."
+msgstr ""
+"이 데이터베이스 클러스터는 MAXALIGN %d (으)로 초기화 되었지만, 서버는 "
+"MAXALIGN %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4377
+#, c-format
+msgid ""
+"The database cluster appears to use a different floating-point number format "
+"than the server executable."
+msgstr ""
+"데이터베이스 클러스터와 서버 실행 파일이 서로 다른 부동 소수점 숫자 형식을 사"
+"용하고 있습니다."
+
+#: access/transam/xlog.c:4382
+#, c-format
+msgid ""
+"The database cluster was initialized with BLCKSZ %d, but the server was "
+"compiled with BLCKSZ %d."
+msgstr ""
+"이 데이터베이스 클러스터는 BLCKSZ %d (으)로 초기화 되었지만, 서버는 BLCKSZ "
+"%d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4385 access/transam/xlog.c:4392
+#: access/transam/xlog.c:4399 access/transam/xlog.c:4406
+#: access/transam/xlog.c:4413 access/transam/xlog.c:4420
+#: access/transam/xlog.c:4427 access/transam/xlog.c:4434
+#: access/transam/xlog.c:4442 access/transam/xlog.c:4449
+#: access/transam/xlog.c:4458 access/transam/xlog.c:4465
+#: access/transam/xlog.c:4474 access/transam/xlog.c:4481
+#, c-format
+msgid "It looks like you need to recompile or initdb."
+msgstr ""
+"서버를 새로 컴파일 하거나 initdb 명령을 사용해 새로 데이터베이스 클러스터를 "
+"다시 만들거나 해야할 것 같습니다."
+
+#: access/transam/xlog.c:4389
+#, c-format
+msgid ""
+"The database cluster was initialized with RELSEG_SIZE %d, but the server was "
+"compiled with RELSEG_SIZE %d."
+msgstr ""
+"이 데이터베이스 클러스터는 RELSEG_SIZE %d (으)로 초기화 되었지만, 서버는 "
+"RELSEG_SIZE %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4396
+#, c-format
+msgid ""
+"The database cluster was initialized with XLOG_BLCKSZ %d, but the server was "
+"compiled with XLOG_BLCKSZ %d."
+msgstr ""
+"이 데이터베이스 클러스터는 XLOG_BLCKSZ %d (으)로 초기화 되었지만, 서버는 "
+"XLOG_BLCKSZ %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4403
+#, c-format
+msgid ""
+"The database cluster was initialized with XLOG_SEG_SIZE %d, but the server "
+"was compiled with XLOG_SEG_SIZE %d."
+msgstr ""
+"이 데이터베이스 클러스터는 XLOG_SEG_SIZE %d (으)로 초기화 되었지만, 서버는 "
+"XLOG_SEG_SIZE %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4410
+#, c-format
+msgid ""
+"The database cluster was initialized with NAMEDATALEN %d, but the server was "
+"compiled with NAMEDATALEN %d."
+msgstr ""
+"이 데이터베이스 클러스터는 NAMEDATALEN %d (으)로 초기화 되었지만, 서버는 "
+"NAMEDATALEN %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4417
+#, c-format
+msgid ""
+"The database cluster was initialized with INDEX_MAX_KEYS %d, but the server "
+"was compiled with INDEX_MAX_KEYS %d."
+msgstr ""
+"이 데이터베이스 클러스터는 INDEX_MAX_KEYS %d (으)로 초기화 되었지만, 서버는 "
+"INDEX_MAX_KEYS %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4424
+#, c-format
+msgid ""
+"The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the "
+"server was compiled with TOAST_MAX_CHUNK_SIZE %d."
+msgstr ""
+"데이터베이스 클러스터는 TOAST_MAX_CHUNK_SIZE %d(으)로 초기화되었지만 서버는 "
+"TOAST_MAX_CHUNK_SIZE %d(으)로 컴파일 되었습니다."
+
+#: access/transam/xlog.c:4431
+#, c-format
+msgid ""
+"The database cluster was initialized with LOBLKSIZE %d, but the server was "
+"compiled with LOBLKSIZE %d."
+msgstr ""
+"이 데이터베이스 클러스터는 LOBLKSIZE %d(으)로 초기화 되었지만, 서버는 "
+"LOBLKSIZE %d (으)로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4440
+#, c-format
+msgid ""
+"The database cluster was initialized without HAVE_INT64_TIMESTAMP but the "
+"server was compiled with HAVE_INT64_TIMESTAMP."
+msgstr ""
+"이 데이터베이스 클러스터는 HAVE_INT64_TIMESTAMP 값이 false로 초기화 되었지"
+"만, 서버는 HAVE_INT64_TIMESTAMP 값이 true로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4447
+#, c-format
+msgid ""
+"The database cluster was initialized with HAVE_INT64_TIMESTAMP but the "
+"server was compiled without HAVE_INT64_TIMESTAMP."
+msgstr ""
+"이 데이터베이스 클러스터는 HAVE_INT64_TIMESTAMP 값이 true로 초기화 되었지만, "
+"서버는 HAVE_INT64_TIMESTAMP 값이 false로 컴파일 되어있습니다."
+
+#: access/transam/xlog.c:4456
+#, c-format
+msgid ""
+"The database cluster was initialized without USE_FLOAT4_BYVAL but the server "
+"was compiled with USE_FLOAT4_BYVAL."
+msgstr ""
+"데이터베이스 클러스터는 USE_FLOAT4_BYVAL 없이 초기화되었지만, 서버는 "
+"USE_FLOAT4_BYVAL을 사용하여 컴파일되었습니다."
+
+#: access/transam/xlog.c:4463
+#, c-format
+msgid ""
+"The database cluster was initialized with USE_FLOAT4_BYVAL but the server "
+"was compiled without USE_FLOAT4_BYVAL."
+msgstr ""
+"데이터베이스 클러스터는 USE_FLOAT4_BYVAL을 사용하여 초기화되었지만, 서버는 "
+"USE_FLOAT4_BYVAL 없이 컴파일되었습니다."
+
+#: access/transam/xlog.c:4472
+#, c-format
+msgid ""
+"The database cluster was initialized without USE_FLOAT8_BYVAL but the server "
+"was compiled with USE_FLOAT8_BYVAL."
+msgstr ""
+"데이터베이스 클러스터는 USE_FLOAT8_BYVAL 없이 초기화되었지만, 서버는 "
+"USE_FLOAT8_BYVAL을 사용하여 컴파일되었습니다."
+
+#: access/transam/xlog.c:4479
+#, c-format
+msgid ""
+"The database cluster was initialized with USE_FLOAT8_BYVAL but the server "
+"was compiled without USE_FLOAT8_BYVAL."
+msgstr ""
+"데이터베이스 클러스터는 USE_FLOAT8_BYVAL을 사용하여 초기화되었지만, 서버는 "
+"USE_FLOAT8_BYVAL 없이 컴파일되었습니다."
+
+#: access/transam/xlog.c:4900
+#, c-format
+msgid "could not write bootstrap transaction log file: %m"
+msgstr "bootstrap 트랜잭션 로그 파일을 쓸 수 없음: %m"
+
+#: access/transam/xlog.c:4906
+#, c-format
+msgid "could not fsync bootstrap transaction log file: %m"
+msgstr "bootstrap 트랜잭션 로그 파일을 fsync할 수 없음: %m"
+
+#: access/transam/xlog.c:4911
+#, c-format
+msgid "could not close bootstrap transaction log file: %m"
+msgstr "bootstrap 트랜잭션 로그 파일을 닫을 수 없음: %m"
+
+#: access/transam/xlog.c:4986
+#, c-format
+msgid "could not open recovery command file \"%s\": %m"
+msgstr "복구명령 파일 \"%s\"을 열 수 없습니다: %m"
+
+#: access/transam/xlog.c:5032 access/transam/xlog.c:5117
+#, c-format
+msgid "invalid value for recovery parameter \"%s\": \"%s\""
+msgstr "잘못된 \"%s\" 복구 매개 변수의 값: \"%s\""
+
+#: access/transam/xlog.c:5035
+#, c-format
+msgid "Valid values are \"pause\", \"promote\", and \"shutdown\"."
+msgstr "사용할 수 있는 값: \"pause\", \"promote\", \"shutdown\""
+
+#: access/transam/xlog.c:5055
+#, c-format
+msgid "recovery_target_timeline is not a valid number: \"%s\""
+msgstr "recovery_target_timeline 값으로 잘못된 숫자: \"%s\""
+
+#: access/transam/xlog.c:5072
+#, c-format
+msgid "recovery_target_xid is not a valid number: \"%s\""
+msgstr "recovery_target_xid 값으로 잘못된 숫자: \"%s\""
+
+#: access/transam/xlog.c:5103
+#, c-format
+msgid "recovery_target_name is too long (maximum %d characters)"
+msgstr "recovery_target_name 설정값이 너무 깁니다 (최대 %d 문자)"
+
+#: access/transam/xlog.c:5120
+#, c-format
+msgid "The only allowed value is \"immediate\"."
+msgstr "이 값으로는 \"immediate\" 만 허용합니다."
+
+#: access/transam/xlog.c:5133 access/transam/xlog.c:5144
+#: commands/extension.c:534 commands/extension.c:542 utils/misc/guc.c:5640
+#, c-format
+msgid "parameter \"%s\" requires a Boolean value"
+msgstr "\"%s\" 매개 변수의 값은 boolean 값이어야합니다."
+
+#: access/transam/xlog.c:5179
+#, c-format
+msgid "parameter \"%s\" requires a temporal value"
+msgstr "\"%s\" 매개 변수의 값은 시간값이어야 합니다."
+
+#: access/transam/xlog.c:5181 catalog/dependency.c:990
+#: catalog/dependency.c:991 catalog/dependency.c:997 catalog/dependency.c:998
+#: catalog/dependency.c:1009 catalog/dependency.c:1010
+#: catalog/objectaddress.c:1100 commands/tablecmds.c:796
+#: commands/tablecmds.c:9542 commands/user.c:1045 commands/view.c:499
+#: libpq/auth.c:307 replication/syncrep.c:919 storage/lmgr/deadlock.c:1139
+#: storage/lmgr/proc.c:1278 utils/adt/acl.c:5281 utils/misc/guc.c:5662
+#: utils/misc/guc.c:5755 utils/misc/guc.c:9708 utils/misc/guc.c:9742
+#: utils/misc/guc.c:9776 utils/misc/guc.c:9810 utils/misc/guc.c:9845
+#, c-format
+msgid "%s"
+msgstr "%s"
+
+#: access/transam/xlog.c:5188
+#, c-format
+msgid "unrecognized recovery parameter \"%s\""
+msgstr "알 수 없는 복구 매개 변수 이름: \"%s\""
+
+#: access/transam/xlog.c:5199
+#, c-format
+msgid ""
+"recovery command file \"%s\" specified neither primary_conninfo nor "
+"restore_command"
+msgstr ""
+"복구 명령 파일 \"%s\"에서 primary_conninfo 설정도, restore_command 설정도 없"
+"습니다."
+
+#: access/transam/xlog.c:5201
+#, c-format
+msgid ""
+"The database server will regularly poll the pg_xlog subdirectory to check "
+"for files placed there."
+msgstr ""
+"데이터베이스 서버는 일반적으로 주 서버에서 발생한 트랜잭션 로그를 반영하기 위"
+"해 pg_xlog 하위 디렉터리를 조사할 것입니다."
+
+#: access/transam/xlog.c:5208
+#, c-format
+msgid ""
+"recovery command file \"%s\" must specify restore_command when standby mode "
+"is not enabled"
+msgstr ""
+"대기 모드를 활성화 하지 않았다면(standby_mode = off), 복구 명령 파일 \"%s\"에"
+"서 restore_command 설정은 반드시 있어야 합니다."
+
+#: access/transam/xlog.c:5229
+#, c-format
+msgid "standby mode is not supported by single-user servers"
+msgstr "단일 사용자 서버를 대상으로 대기 모드를 사용할 수 없습니다."
+
+#: access/transam/xlog.c:5248
+#, c-format
+msgid "recovery target timeline %u does not exist"
+msgstr "%u 복구 대상 타임라인이 없음"
+
+#: access/transam/xlog.c:5369
+#, c-format
+msgid "archive recovery complete"
+msgstr "아카이브 복구 완료"
+
+#: access/transam/xlog.c:5428 access/transam/xlog.c:5656
+#, c-format
+msgid "recovery stopping after reaching consistency"
+msgstr "일관성을 다 맞추어 복구 작업을 중지합니다."
+
+#: access/transam/xlog.c:5516
+#, c-format
+msgid "recovery stopping before commit of transaction %u, time %s"
+msgstr "%u 트랜잭션 커밋 전 복구 중지함, 시간 %s"
+
+#: access/transam/xlog.c:5523
+#, c-format
+msgid "recovery stopping before abort of transaction %u, time %s"
+msgstr "%u 트랜잭션 중단 전 복구 중지함, 시간 %s"
+
+#: access/transam/xlog.c:5568
+#, c-format
+msgid "recovery stopping at restore point \"%s\", time %s"
+msgstr "복구 중지함, 복구 위치 \"%s\", 시간 %s"
+
+#: access/transam/xlog.c:5636
+#, c-format
+msgid "recovery stopping after commit of transaction %u, time %s"
+msgstr "%u 트랜잭션 커밋 후 복구 중지함, 시간 %s"
+
+#: access/transam/xlog.c:5644
+#, c-format
+msgid "recovery stopping after abort of transaction %u, time %s"
+msgstr "%u 트랜잭션 중단 후 복구 중지함, 시간 %s"
+
+#: access/transam/xlog.c:5683
+#, c-format
+msgid "recovery has paused"
+msgstr "복구 작업이 일시 중지 됨"
+
+#: access/transam/xlog.c:5684
+#, c-format
+msgid "Execute pg_xlog_replay_resume() to continue."
+msgstr "계속 진행하려면, pg_xlog_replay_resume() 함수를 호출하세요."
+
+#: access/transam/xlog.c:5891
+#, c-format
+msgid ""
+"hot standby is not possible because %s = %d is a lower setting than on the "
+"master server (its value was %d)"
+msgstr ""
+"읽기 전용 대기 서버로 운영이 불가능합니다. 현재 %s = %d 설정은 주 서버의 설정"
+"값(%d)보다 낮게 설정 되어 있기 때문입니다."
+
+#: access/transam/xlog.c:5917
+#, c-format
+msgid "WAL was generated with wal_level=minimal, data may be missing"
+msgstr ""
+"WAL 내용이 wal_level=minimal 설정으로 만들여졌습니다. 자료가 손실 될 수 있습"
+"니다."
+
+#: access/transam/xlog.c:5918
+#, c-format
+msgid ""
+"This happens if you temporarily set wal_level=minimal without taking a new "
+"base backup."
+msgstr ""
+"이 문제는 새 베이스 백업을 받지 않은 상태에서 서버가 일시적으로 "
+"wal_level=minimal 설정으로 운영된 적이 있다면 발생합니다."
+
+#: access/transam/xlog.c:5929
+#, c-format
+msgid ""
+"hot standby is not possible because wal_level was not set to \"replica\" or "
+"higher on the master server"
+msgstr ""
+"주 서버 wal_level 설정이 \"replica\" 또는 그 이상 수준으로 설정되지 않아, 읽"
+"기 전용 보조 서버로 운영될 수 없음"
+
+#: access/transam/xlog.c:5930
+#, c-format
+msgid ""
+"Either set wal_level to \"replica\" on the master, or turn off hot_standby "
+"here."
+msgstr ""
+"운영 서버의 환경 설정에서 wal_leve = \"replica\" 형태로 지정하든가 "
+"hot_standby = off 형태로 지정하십시오."
+
+#: access/transam/xlog.c:5987
+#, c-format
+msgid "control file contains invalid data"
+msgstr "컨트롤 파일에 잘못된 데이터가 있습니다"
+
+#: access/transam/xlog.c:5993
+#, c-format
+msgid "database system was shut down at %s"
+msgstr "데이터베이스 시스템 마지막 가동 중지 시각: %s"
+
+#: access/transam/xlog.c:5998
+#, c-format
+msgid "database system was shut down in recovery at %s"
+msgstr "복구 중 데이터베이스 시스템 마지막 가동 중지 시각: %s"
+
+#: access/transam/xlog.c:6002
+#, c-format
+msgid "database system shutdown was interrupted; last known up at %s"
+msgstr ""
+"데이터베이스 시스템 셧다운 작업이 비정상적으로 종료되었음; 마지막 운영시간: "
+"%s"
+
+#: access/transam/xlog.c:6006
+#, c-format
+msgid "database system was interrupted while in recovery at %s"
+msgstr "데이터베이스 시스템 복구하는 도중 비정상적으로 가동 중지된 시각: %s"
+
+#: access/transam/xlog.c:6008
+#, c-format
+msgid ""
+"This probably means that some data is corrupted and you will have to use the "
+"last backup for recovery."
+msgstr ""
+"이 사태는 몇몇 데이터가 손상되었을 의미할 수도 있습니다. 확인해 보고, 필요하"
+"다면, 마지막 백업 자료로 복구해서 사용하세요."
+
+#: access/transam/xlog.c:6012
+#, c-format
+msgid "database system was interrupted while in recovery at log time %s"
+msgstr "데이터베이스 시스템이 로그 시간 %s에 복구 도중 중지 되었음"
+
+#: access/transam/xlog.c:6014
+#, c-format
+msgid ""
+"If this has occurred more than once some data might be corrupted and you "
+"might need to choose an earlier recovery target."
+msgstr ""
+"이 사태로 몇몇 자료가 손상되었을 수도 있는데, 이런 경우라면,확인해 보고, 필요"
+"하다면, 마지막 백업 자료로 복구해서 사용하세요."
+
+#: access/transam/xlog.c:6018
+#, c-format
+msgid "database system was interrupted; last known up at %s"
+msgstr "데이터베이스 시스템이 비정상적으로 종료되었음; 마지막 운영시간: %s"
+
+#: access/transam/xlog.c:6074
+#, c-format
+msgid "entering standby mode"
+msgstr "대기 모드로 전환합니다"
+
+#: access/transam/xlog.c:6077
+#, c-format
+msgid "starting point-in-time recovery to XID %u"
+msgstr "%u XID까지 시점 기반 복구 작업을 시작합니다"
+
+#: access/transam/xlog.c:6081
+#, c-format
+msgid "starting point-in-time recovery to %s"
+msgstr "%s 까지 시점 복구 작업을 시작합니다"
+
+#: access/transam/xlog.c:6085
+#, c-format
+msgid "starting point-in-time recovery to \"%s\""
+msgstr "\"%s\" 복구 대상 이름까지 시점 복구 작업을 시작합니다"
+
+#: access/transam/xlog.c:6089
+#, c-format
+msgid "starting point-in-time recovery to earliest consistent point"
+msgstr "동기화 할 수 있는 마지막 지점까지 시점 복구 작업을 시작합니다"
+
+#: access/transam/xlog.c:6092
+#, c-format
+msgid "starting archive recovery"
+msgstr "아카이브 복구 작업을 시작합니다"
+
+#: access/transam/xlog.c:6136 access/transam/xlog.c:6264
+#, c-format
+msgid "checkpoint record is at %X/%X"
+msgstr "체크포인트 레코드 위치: %X/%X"
+
+#: access/transam/xlog.c:6150
+#, c-format
+msgid "could not find redo location referenced by checkpoint record"
+msgstr "체크포인트 기록으로 참조하는 재실행 위치를 찾을 수 없음"
+
+#: access/transam/xlog.c:6151 access/transam/xlog.c:6158
+#, c-format
+msgid ""
+"If you are not restoring from a backup, try removing the file \"%s/"
+"backup_label\"."
+msgstr ""
+"실시간 백업 자료로부터 복구 작업을 하지 않으려면, \"%s/backup_lable\" 파일을 "
+"삭제 하세요."
+
+#: access/transam/xlog.c:6157
+#, c-format
+msgid "could not locate required checkpoint record"
+msgstr "요청된 체크포인트 레코드의 위치를 바르게 잡을 수 없음"
+
+#: access/transam/xlog.c:6183 commands/tablespace.c:641
+#, c-format
+msgid "could not create symbolic link \"%s\": %m"
+msgstr "\"%s\" 심벌릭 링크를 만들 수 없음: %m"
+
+#: access/transam/xlog.c:6215 access/transam/xlog.c:6221
+#, c-format
+msgid "ignoring file \"%s\" because no file \"%s\" exists"
+msgstr "\"%s\" 파일 무시함, \"%s\" 파일 없음"
+
+#: access/transam/xlog.c:6217 access/transam/xlog.c:11032
+#, c-format
+msgid "File \"%s\" was renamed to \"%s\"."
+msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿨습니다."
+
+#: access/transam/xlog.c:6223
+#, c-format
+msgid "Could not rename file \"%s\" to \"%s\": %m."
+msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m"
+
+#: access/transam/xlog.c:6274 access/transam/xlog.c:6289
+#, c-format
+msgid "could not locate a valid checkpoint record"
+msgstr "체크포인트 레코드의 위치를 바르게 잡을 수 없음"
+
+#: access/transam/xlog.c:6283
+#, c-format
+msgid "using previous checkpoint record at %X/%X"
+msgstr "이전 체크포인트 레코드를 사용함, 위치: %X/%X"
+
+#: access/transam/xlog.c:6327
+#, c-format
+msgid "requested timeline %u is not a child of this server's history"
+msgstr "요청한 %u 타임라인은 서버 타임라인의 하위가 아님"
+
+#: access/transam/xlog.c:6329
+#, c-format
+msgid ""
+"Latest checkpoint is at %X/%X on timeline %u, but in the history of the "
+"requested timeline, the server forked off from that timeline at %X/%X."
+msgstr ""
+"마지막 체크포인트 위치는 %X/%X (%u 타임라인)입니다. 하지만, 요청받은 타임라"
+"인 내역파일에는 그 타임라인 %X/%X 위치에서 분기되었습니다."
+
+#: access/transam/xlog.c:6345
+#, c-format
+msgid ""
+"requested timeline %u does not contain minimum recovery point %X/%X on "
+"timeline %u"
+msgstr ""
+"요청한 %u 타임라인은 %X/%X 최소 복구 위치가 없습니다, 기존 타임라인: %u"
+
+#: access/transam/xlog.c:6376
+#, c-format
+msgid "invalid next transaction ID"
+msgstr "잘못된 다음 트랜잭션 ID"
+
+#: access/transam/xlog.c:6459
+#, c-format
+msgid "invalid redo in checkpoint record"
+msgstr "체크포인트 레코드 안에 잘못된 redo 정보가 있음"
+
+#: access/transam/xlog.c:6470
+#, c-format
+msgid "invalid redo record in shutdown checkpoint"
+msgstr "운영 중지 체크포인트에서 잘못된 재실행 정보 발견"
+
+#: access/transam/xlog.c:6498
+#, c-format
+msgid ""
+"database system was not properly shut down; automatic recovery in progress"
+msgstr ""
+"데이터베이스 시스템이 정상적으로 종료되지 못했습니다, 자동 복구 작업을 진행합"
+"니다"
+
+#: access/transam/xlog.c:6502
+#, c-format
+msgid "crash recovery starts in timeline %u and has target timeline %u"
+msgstr ""
+"%u 타임라인으로 비정상 중지에 대한 복구작업을 시작함, 기존 타임라인: %u"
+
+#: access/transam/xlog.c:6546
+#, c-format
+msgid "backup_label contains data inconsistent with control file"
+msgstr "backup_label 파일 안에 컨트롤 파일과 일관성이 맞지 않는 자료가 있음"
+
+#: access/transam/xlog.c:6547
+#, c-format
+msgid ""
+"This means that the backup is corrupted and you will have to use another "
+"backup for recovery."
+msgstr ""
+"이 문제는 백업 자료 자체가 손상 되었음을 말합니다. 다른 백업본으로 복구 작업"
+"을 진행해야 합니다."
+
+#: access/transam/xlog.c:6621
+#, c-format
+msgid "initializing for hot standby"
+msgstr "읽기 전용 보조 서버로 초기화 중입니다."
+
+#: access/transam/xlog.c:6753
+#, c-format
+msgid "redo starts at %X/%X"
+msgstr "%X/%X에서 redo 작업 시작됨"
+
+#: access/transam/xlog.c:6978
+#, c-format
+msgid "requested recovery stop point is before consistent recovery point"
+msgstr "요청한 복구 중지 지점이 일치하는 복구 지점 앞에 있음"
+
+#: access/transam/xlog.c:7016
+#, c-format
+msgid "redo done at %X/%X"
+msgstr "%X/%X에서 redo 작업 완료"
+
+#: access/transam/xlog.c:7021 access/transam/xlog.c:8969
+#, c-format
+msgid "last completed transaction was at log time %s"
+msgstr "마지막 완료된 트랜잭션 기록 시간: %s"
+
+#: access/transam/xlog.c:7030
+#, c-format
+msgid "redo is not required"
+msgstr "재반영해야 할 트랜잭션이 없음"
+
+#: access/transam/xlog.c:7105 access/transam/xlog.c:7109
+#, c-format
+msgid "WAL ends before end of online backup"
+msgstr "온라인 백업 작업 끝나기전에 WAL 작업 종료됨"
+
+#: access/transam/xlog.c:7106
+#, c-format
+msgid ""
+"All WAL generated while online backup was taken must be available at "
+"recovery."
+msgstr ""
+"온라인 백업 중 만들어진 WAL 조각 파일은 복구 작업에서 반드시 모두 있어야 합니"
+"다."
+
+#: access/transam/xlog.c:7110
+#, c-format
+msgid ""
+"Online backup started with pg_start_backup() must be ended with "
+"pg_stop_backup(), and all WAL up to that point must be available at recovery."
+msgstr ""
+"pg_start_backup() 함수를 호출해서 시작한 온라인 백업은 pg_stop_backup() 함수"
+"로 종료되어야 하며, 그 사이 만들어진 WAL 조각 파일은 복구 작업에서 모두 필요"
+"합니다."
+
+#: access/transam/xlog.c:7113
+#, c-format
+msgid "WAL ends before consistent recovery point"
+msgstr "WAL이 일치하는 복구 지점 앞에서 종료됨"
+
+#: access/transam/xlog.c:7140
+#, c-format
+msgid "selected new timeline ID: %u"
+msgstr "지정한 새 타임라인 ID: %u"
+
+#: access/transam/xlog.c:7551
+#, c-format
+msgid "consistent recovery state reached at %X/%X"
+msgstr "%X/%X 위치에서 복구 일관성을 맞춤"
+
+#: access/transam/xlog.c:7742
+#, c-format
+msgid "invalid primary checkpoint link in control file"
+msgstr "컨트롤 파일에서 잘못된 primary checkpoint 링크 발견"
+
+#: access/transam/xlog.c:7746
+#, c-format
+msgid "invalid secondary checkpoint link in control file"
+msgstr "컨트롤 파일에서 잘못된 secondary checkpoint 링크 발견"
+
+#: access/transam/xlog.c:7750
+#, c-format
+msgid "invalid checkpoint link in backup_label file"
+msgstr "백업 라벨 파일에서 잘못된 체크포인트 링크 발견"
+
+#: access/transam/xlog.c:7767
+#, c-format
+msgid "invalid primary checkpoint record"
+msgstr "잘못된 primary checkpoint 레코드"
+
+#: access/transam/xlog.c:7771
+#, c-format
+msgid "invalid secondary checkpoint record"
+msgstr "잘못된 secondary checkpoint 레코드"
+
+#: access/transam/xlog.c:7775
+#, c-format
+msgid "invalid checkpoint record"
+msgstr "잘못된 checkpoint 레코드"
+
+#: access/transam/xlog.c:7786
+#, c-format
+msgid "invalid resource manager ID in primary checkpoint record"
+msgstr "primary checkpoint 레코드에서 잘못된 자원 관리자 ID 발견"
+
+#: access/transam/xlog.c:7790
+#, c-format
+msgid "invalid resource manager ID in secondary checkpoint record"
+msgstr "secondary checkpoint 레코드에서 잘못된 자원 관리자 ID 발견"
+
+#: access/transam/xlog.c:7794
+#, c-format
+msgid "invalid resource manager ID in checkpoint record"
+msgstr "checkpoint 레코드에서 잘못된 자원 관리자 ID 발견"
+
+#: access/transam/xlog.c:7806
+#, c-format
+msgid "invalid xl_info in primary checkpoint record"
+msgstr "primary checkpoint 레코드에서 잘못된 xl_info 발견"
+
+#: access/transam/xlog.c:7810
+#, c-format
+msgid "invalid xl_info in secondary checkpoint record"
+msgstr "secondary checkpoint 레코드에서 잘못된 xl_info 발견"
+
+#: access/transam/xlog.c:7814
+#, c-format
+msgid "invalid xl_info in checkpoint record"
+msgstr "checkpoint 레코드에서 잘못된 xl_info 발견"
+
+#: access/transam/xlog.c:7825
+#, c-format
+msgid "invalid length of primary checkpoint record"
+msgstr "primary checkpoint 레코드 길이가 잘못되었음"
+
+#: access/transam/xlog.c:7829
+#, c-format
+msgid "invalid length of secondary checkpoint record"
+msgstr "secondary checkpoint 레코드 길이가 잘못되었음"
+
+#: access/transam/xlog.c:7833
+#, c-format
+msgid "invalid length of checkpoint record"
+msgstr "checkpoint 레코드 길이가 잘못되었음"
+
+#: access/transam/xlog.c:8001
+#, c-format
+msgid "shutting down"
+msgstr "서비스를 멈추고 있습니다"
+
+#: access/transam/xlog.c:8514
+#, c-format
+msgid ""
+"concurrent transaction log activity while database system is shutting down"
+msgstr "데이터베이스 시스템이 중지되는 동안 현재 트랜잭션 로그가 활성화 되었음"
+
+#: access/transam/xlog.c:8768
+#, c-format
+msgid "skipping restartpoint, recovery has already ended"
+msgstr "다시 시작 지점을 건너뜀, 복구가 이미 종료됨"
+
+#: access/transam/xlog.c:8791
+#, c-format
+msgid "skipping restartpoint, already performed at %X/%X"
+msgstr "다시 시작 지점을 건너뜀, %X/%X에서 이미 수행됨"
+
+#: access/transam/xlog.c:8967
+#, c-format
+msgid "recovery restart point at %X/%X"
+msgstr "%X/%X에서 복구 작업 시작함"
+
+#: access/transam/xlog.c:9100
+#, c-format
+msgid "restore point \"%s\" created at %X/%X"
+msgstr "\"%s\" 이름의 복구 위치는 %X/%X에 만들었음"
+
+#: access/transam/xlog.c:9230
+#, c-format
+msgid ""
+"unexpected previous timeline ID %u (current timeline ID %u) in checkpoint "
+"record"
+msgstr ""
+"체크포인트 레코드에 예기치 않은 이전 타임라인ID %u(현재 타임라인ID: %u)"
+
+#: access/transam/xlog.c:9239
+#, c-format
+msgid "unexpected timeline ID %u (after %u) in checkpoint record"
+msgstr "체크포인트 레코드에 예기치 않은 타임라인 ID %u이(가) 있음(%u 뒤)"
+
+#: access/transam/xlog.c:9255
+#, c-format
+msgid ""
+"unexpected timeline ID %u in checkpoint record, before reaching minimum "
+"recovery point %X/%X on timeline %u"
+msgstr ""
+"체크포인트 내역 안에 %u 타임라인 ID가 기대한 것과 다릅니다. 발생 위치: %X/%X "
+"(타임라인: %u) 최소 복구 위치 이전"
+
+#: access/transam/xlog.c:9326
+#, c-format
+msgid "online backup was canceled, recovery cannot continue"
+msgstr "온라인 백어이 취소되었음, 복구를 계속 할 수 없음"
+
+#: access/transam/xlog.c:9382 access/transam/xlog.c:9429
+#: access/transam/xlog.c:9452
+#, c-format
+msgid "unexpected timeline ID %u (should be %u) in checkpoint record"
+msgstr "체크포인트 레코드에 예기치 않은 타임라인 ID %u이(가) 있음(%u이어야 함)"
+
+#: access/transam/xlog.c:9727
+#, c-format
+msgid "could not fsync log segment %s: %m"
+msgstr "%s 로그 조각 fsync 실패: %m"
+
+#: access/transam/xlog.c:9751
+#, c-format
+msgid "could not fsync log file %s: %m"
+msgstr "\"%s\" 로그 파일 fsync 실패: %m"
+
+#: access/transam/xlog.c:9759
+#, c-format
+msgid "could not fsync write-through log file %s: %m"
+msgstr "write-through 로그 파일(%s)을 fsync할 수 없음: %m"
+
+#: access/transam/xlog.c:9768
+#, c-format
+msgid "could not fdatasync log file %s: %m"
+msgstr "%s 로그파일을 fdatasync할 수 없음: %m"
+
+#: access/transam/xlog.c:9859 access/transam/xlog.c:10363
+#: access/transam/xlogfuncs.c:294 access/transam/xlogfuncs.c:321
+#: access/transam/xlogfuncs.c:360 access/transam/xlogfuncs.c:381
+#: access/transam/xlogfuncs.c:402
+#, c-format
+msgid "WAL control functions cannot be executed during recovery."
+msgstr "WAL 제어 함수는 복구 작업 중에는 실행 될 수 없음"
+
+#: access/transam/xlog.c:9868 access/transam/xlog.c:10372
+#, c-format
+msgid "WAL level not sufficient for making an online backup"
+msgstr "온라인 백업 작업을 하기 위한 WAL 수준이 충분치 않습니다."
+
+#: access/transam/xlog.c:9869 access/transam/xlog.c:10373
+#: access/transam/xlogfuncs.c:327
+#, c-format
+msgid "wal_level must be set to \"replica\" or \"logical\" at server start."
+msgstr ""
+"wal_level 값을 \"replica\" 또는 \"logical\"로 지정하고 서버를 실행하십시오."
+
+#: access/transam/xlog.c:9874
+#, c-format
+msgid "backup label too long (max %d bytes)"
+msgstr "백업 라벨 이름이 너무 긺(최대 %d 바이트)"
+
+#: access/transam/xlog.c:9911 access/transam/xlog.c:10183
+#: access/transam/xlog.c:10221
+#, c-format
+msgid "a backup is already in progress"
+msgstr "이미 백업 작업이 진행 중입니다"
+
+#: access/transam/xlog.c:9912
+#, c-format
+msgid "Run pg_stop_backup() and try again."
+msgstr "pg_stop_backup() 함수를 실행하고 나서 다시 시도하세요."
+
+#: access/transam/xlog.c:10007
+#, c-format
+msgid ""
+"WAL generated with full_page_writes=off was replayed since last restartpoint"
+msgstr ""
+"마지막 재시작 위치부터 재반영된 WAL 내용이 full_page_writes=off 설정으로 만들"
+"어진 내용입니다."
+
+#: access/transam/xlog.c:10009 access/transam/xlog.c:10554
+#, c-format
+msgid ""
+"This means that the backup being taken on the standby is corrupt and should "
+"not be used. Enable full_page_writes and run CHECKPOINT on the master, and "
+"then try an online backup again."
+msgstr ""
+"이 경우 대기 서버의 자료가 손실되었을 가능성이 있습니다. full_page_writes 설"
+"정을 활성화 하고, 주 서버에서 CHECKPOINT 명령을 실행하고, 온라인 백업을 다시 "
+"해서 사용하세요."
+
+#: access/transam/xlog.c:10076 replication/basebackup.c:1026
+#: utils/adt/misc.c:498
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "\"%s\" 심볼릭 링크 파일을 읽을 수 없음: %m"
+
+#: access/transam/xlog.c:10083 replication/basebackup.c:1031
+#: utils/adt/misc.c:503
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "\"%s\" 심볼릭 링크의 대상이 너무 긺"
+
+#: access/transam/xlog.c:10136 commands/tablespace.c:391
+#: commands/tablespace.c:553 replication/basebackup.c:1047
+#: utils/adt/misc.c:511
+#, c-format
+msgid "tablespaces are not supported on this platform"
+msgstr "테이블스페이스 기능은 이 플랫폼에서는 지원하지 않습니다."
+
+#: access/transam/xlog.c:10177 access/transam/xlog.c:10215
+#: access/transam/xlog.c:10411 access/transam/xlogarchive.c:106
+#: access/transam/xlogarchive.c:265 commands/copy.c:1815 commands/copy.c:2839
+#: commands/extension.c:3130 commands/tablespace.c:782
+#: commands/tablespace.c:873 replication/basebackup.c:409
+#: replication/basebackup.c:477 replication/logical/snapbuild.c:1491
+#: storage/file/copydir.c:72 storage/file/copydir.c:115 storage/file/fd.c:2903
+#: storage/file/fd.c:2995 utils/adt/dbsize.c:70 utils/adt/dbsize.c:220
+#: utils/adt/dbsize.c:300 utils/adt/genfile.c:114 utils/adt/genfile.c:333
+#: guc-file.l:1002
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m"
+
+#: access/transam/xlog.c:10184 access/transam/xlog.c:10222
+#, c-format
+msgid ""
+"If you're sure there is no backup in progress, remove file \"%s\" and try "
+"again."
+msgstr ""
+"실재로는 백업 작업을 안하고 있다고 확신한다면, \"%s\" 파일을 삭제하고 다시 시"
+"도해 보십시오."
+
+#: access/transam/xlog.c:10201 access/transam/xlog.c:10239
+#: access/transam/xlog.c:10615
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "\"%s\" 파일 쓰기 실패: %m"
+
+#: access/transam/xlog.c:10388
+#, c-format
+msgid "exclusive backup not in progress"
+msgstr "exclusive 백업 작업을 하지 않고 있습니다"
+
+#: access/transam/xlog.c:10415
+#, c-format
+msgid "a backup is not in progress"
+msgstr "현재 백업 작업을 하지 않고 있습니다"
+
+#: access/transam/xlog.c:10489 access/transam/xlog.c:10502
+#: access/transam/xlog.c:10842 access/transam/xlog.c:10848
+#: access/transam/xlog.c:10932 access/transam/xlogfuncs.c:695
+#, c-format
+msgid "invalid data in file \"%s\""
+msgstr "\"%s\" 파일에 유효하지 않은 자료가 있습니다"
+
+#: access/transam/xlog.c:10506 replication/basebackup.c:938
+#, c-format
+msgid "the standby was promoted during online backup"
+msgstr "대기 서버가 온라인 백업 중 주 서버로 전환되었습니다"
+
+#: access/transam/xlog.c:10507 replication/basebackup.c:939
+#, c-format
+msgid ""
+"This means that the backup being taken is corrupt and should not be used. "
+"Try taking another online backup."
+msgstr ""
+"이런 경우, 해당 백업 자료가 손상되었을 가능성이 있습니다. 다른 백업본을 이용"
+"하세요."
+
+#: access/transam/xlog.c:10552
+#, c-format
+msgid ""
+"WAL generated with full_page_writes=off was replayed during online backup"
+msgstr ""
+"온라인 백업 도중 full_page_writes=off 설정으로 만들어진 WAL 내용이 재반영되었"
+"습니다."
+
+#: access/transam/xlog.c:10664
+#, c-format
+msgid ""
+"pg_stop_backup cleanup done, waiting for required WAL segments to be archived"
+msgstr ""
+"pg_stop_backup 작업이 끝났습니다. 필요한 WAL 조각 파일이 아카이브 되길 기다리"
+"고 있습니다."
+
+#: access/transam/xlog.c:10674
+#, c-format
+msgid ""
+"pg_stop_backup still waiting for all required WAL segments to be archived "
+"(%d seconds elapsed)"
+msgstr "pg_stop_backup에서 아카이빙이 완료되기를 기다리고 있음 (%d초 경과)"
+
+#: access/transam/xlog.c:10676
+#, c-format
+msgid ""
+"Check that your archive_command is executing properly. pg_stop_backup can "
+"be canceled safely, but the database backup will not be usable without all "
+"the WAL segments."
+msgstr ""
+"archive_command 설정을 살펴보세요. pg_stop_backup 작업은 안전하게 취소 할 "
+"수 있지만, 데이터베이스 백업은 모든 WAL 조각 없이는 사용될 수 없습니다."
+
+#: access/transam/xlog.c:10683
+#, c-format
+msgid "pg_stop_backup complete, all required WAL segments have been archived"
+msgstr ""
+"pg_stop_backup 작업이 끝났습니다. 모든 필요한 WAL 조각들이 아카이브 되었습니"
+"다."
+
+#: access/transam/xlog.c:10687
+#, c-format
+msgid ""
+"WAL archiving is not enabled; you must ensure that all required WAL segments "
+"are copied through other means to complete the backup"
+msgstr ""
+"WAL 아카이브 기능이 비활성화 되어 있습니다; 이 경우는 백업 뒤 복구에 필요한 "
+"모든 WAL 조각 파일들을 직접 찾아서 따로 보관해 두어야 바르게 복구 할 수 있습"
+"니다."
+
+#. translator: %s is an XLog record description
+#: access/transam/xlog.c:10972
+#, c-format
+msgid "xlog redo at %X/%X for %s"
+msgstr "xlog redo 위치: %X/%X, 대상: %s"
+
+#: access/transam/xlog.c:11021
+#, c-format
+msgid "online backup mode was not canceled"
+msgstr "온라인 백업 모드가 취소되지 않았음"
+
+#: access/transam/xlog.c:11022
+#, c-format
+msgid "File \"%s\" could not be renamed to \"%s\": %m."
+msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m."
+
+#: access/transam/xlog.c:11031 access/transam/xlog.c:11043
+#: access/transam/xlog.c:11053
+#, c-format
+msgid "online backup mode canceled"
+msgstr "온라인 백업 모드가 취소됨"
+
+#: access/transam/xlog.c:11044
+#, c-format
+msgid ""
+"Files \"%s\" and \"%s\" were renamed to \"%s\" and \"%s\", respectively."
+msgstr ""
+"예상한 것처럼, \"%s\", \"%s\" 파일을 \"%s\", \"%s\" 이름으로 바꿨습니다."
+
+#: access/transam/xlog.c:11054
+#, c-format
+msgid ""
+"File \"%s\" was renamed to \"%s\", but file \"%s\" could not be renamed to "
+"\"%s\": %m."
+msgstr ""
+"\"%s\" 파일은 \"%s\" 이름으로 바꿨지만, \"%s\" 파일은 \"%s\" 이름으로 바꾸지 "
+"못했습니다: %m."
+
+#: access/transam/xlog.c:11176 access/transam/xlogutils.c:718
+#: replication/walreceiver.c:994 replication/walsender.c:2112
+#, c-format
+msgid "could not seek in log segment %s to offset %u: %m"
+msgstr "%s 로그 조각에서 해당 위치를 찾을 수 없음: %u: %m"
+
+#: access/transam/xlog.c:11188
+#, c-format
+msgid "could not read from log segment %s, offset %u: %m"
+msgstr "%s 로그 조각에서 읽기 실패, 위치: %u: %m"
+
+#: access/transam/xlog.c:11662
+#, c-format
+msgid "received promote request"
+msgstr "운영 전환 신호를 받았습니다."
+
+#: access/transam/xlog.c:11675
+#, c-format
+msgid "trigger file found: %s"
+msgstr "트리거 파일이 있음: %s"
+
+#: access/transam/xlog.c:11684
+#, c-format
+msgid "could not stat trigger file \"%s\": %m"
+msgstr "\"%s\" 트리거 파일의 상태값을 알 수 없음: %m"
+
+#: access/transam/xlogarchive.c:244
+#, c-format
+msgid "archive file \"%s\" has wrong size: %lu instead of %lu"
+msgstr "\"%s\" 기록 파일의 크기가 이상합니다: 현재값 %lu, 원래값 %lu"
+
+#: access/transam/xlogarchive.c:253
+#, c-format
+msgid "restored log file \"%s\" from archive"
+msgstr "아카이브에서 \"%s\" 로그파일을 복구했음"
+
+#: access/transam/xlogarchive.c:303
+#, c-format
+msgid "could not restore file \"%s\" from archive: %s"
+msgstr "아카이브에서 \"%s\" 파일 복원 실패: %s"
+
+#. translator: First %s represents a recovery.conf parameter name like
+#. "recovery_end_command", the 2nd is the value of that parameter, the
+#. third an already translated error message.
+#: access/transam/xlogarchive.c:415
+#, c-format
+msgid "%s \"%s\": %s"
+msgstr "%s \"%s\": %s"
+
+#: access/transam/xlogarchive.c:458 replication/logical/snapbuild.c:1619
+#: replication/slot.c:480 replication/slot.c:992 replication/slot.c:1100
+#: storage/file/fd.c:642 storage/file/fd.c:700 utils/time/snapmgr.c:1298
+#, c-format
+msgid "could not rename file \"%s\" to \"%s\": %m"
+msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m"
+
+#: access/transam/xlogarchive.c:525 access/transam/xlogarchive.c:589
+#, c-format
+msgid "could not create archive status file \"%s\": %m"
+msgstr "\"%s\" archive status 파일을 만들 수 없습니다: %m"
+
+#: access/transam/xlogarchive.c:533 access/transam/xlogarchive.c:597
+#, c-format
+msgid "could not write archive status file \"%s\": %m"
+msgstr "\"%s\" archive status 파일에 쓸 수 없습니다: %m"
+
+#: access/transam/xlogfuncs.c:58
+#, c-format
+msgid "aborting backup due to backend exiting before pg_stop_backup was called"
+msgstr ""
+"pg_stop_backup 작업이 호출되기 전에 백엔드가 종료되어 백업을 중지합니다."
+
+#: access/transam/xlogfuncs.c:88
+#, c-format
+msgid "a backup is already in progress in this session"
+msgstr "이미 이 세션에서 백업 작업이 진행 중입니다"
+
+#: access/transam/xlogfuncs.c:94 commands/tablespace.c:705
+#: commands/tablespace.c:715 postmaster/postmaster.c:1406
+#: replication/basebackup.c:297 replication/basebackup.c:637
+#: storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2369
+#: storage/file/fd.c:2968 storage/ipc/dsm.c:300 utils/adt/genfile.c:439
+#: utils/adt/misc.c:411 utils/misc/tzparser.c:339
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리 열 수 없음: %m"
+
+#: access/transam/xlogfuncs.c:155 access/transam/xlogfuncs.c:229
+#, c-format
+msgid "non-exclusive backup in progress"
+msgstr "non-exclusive 백업 진행 중입니다"
+
+#: access/transam/xlogfuncs.c:156 access/transam/xlogfuncs.c:230
+#, c-format
+msgid "Did you mean to use pg_stop_backup('f')?"
+msgstr "pg_stop_backup('f') 형태로 함수를 호출했나요?"
+
+#: access/transam/xlogfuncs.c:200 commands/event_trigger.c:1445
+#: commands/event_trigger.c:1996 commands/extension.c:1729
+#: commands/extension.c:1838 commands/extension.c:2031 commands/prepare.c:702
+#: executor/execQual.c:1757 executor/execQual.c:1782 executor/execQual.c:2157
+#: executor/execQual.c:5438 executor/functions.c:1031 foreign/foreign.c:492
+#: replication/logical/logicalfuncs.c:175 replication/logical/origin.c:1391
+#: replication/slotfuncs.c:189 replication/walsender.c:2761
+#: utils/adt/jsonfuncs.c:1483 utils/adt/jsonfuncs.c:1613
+#: utils/adt/jsonfuncs.c:1801 utils/adt/jsonfuncs.c:1928
+#: utils/adt/jsonfuncs.c:2694 utils/adt/pgstatfuncs.c:554
+#: utils/adt/pgstatfuncs.c:655 utils/fmgr/funcapi.c:61 utils/misc/guc.c:8436
+#: utils/mmgr/portalmem.c:1074
+#, c-format
+msgid "set-valued function called in context that cannot accept a set"
+msgstr ""
+"set-values 함수(테이블 리턴 함수)가 set 정의 없이 사용되었습니다 (테이블과 해"
+"당 열 alias 지정하세요)"
+
+#: access/transam/xlogfuncs.c:204 commands/event_trigger.c:1449
+#: commands/event_trigger.c:2000 commands/extension.c:1733
+#: commands/extension.c:1842 commands/extension.c:2035 commands/prepare.c:706
+#: foreign/foreign.c:497 replication/logical/logicalfuncs.c:179
+#: replication/logical/origin.c:1395 replication/slotfuncs.c:193
+#: replication/walsender.c:2765 utils/adt/pgstatfuncs.c:558
+#: utils/adt/pgstatfuncs.c:659 utils/misc/guc.c:8440 utils/misc/pg_config.c:44
+#: utils/mmgr/portalmem.c:1078
+#, c-format
+msgid "materialize mode required, but it is not allowed in this context"
+msgstr "materialize 모드가 필요합니다만, 이 구문에서는 허용되지 않습니다"
+
+#: access/transam/xlogfuncs.c:247
+#, c-format
+msgid "non-exclusive backup is not in progress"
+msgstr "non-exclusive 백업 상태가 아닙니다"
+
+#: access/transam/xlogfuncs.c:248
+#, c-format
+msgid "Did you mean to use pg_stop_backup('t')?"
+msgstr "pg_stop_backup('t') 형태로 함수를 호출했나요?"
+
+#: access/transam/xlogfuncs.c:326
+#, c-format
+msgid "WAL level not sufficient for creating a restore point"
+msgstr "WAL 수준이 복원 위치를 만들 수 없는 수준입니다"
+
+#: access/transam/xlogfuncs.c:334
+#, c-format
+msgid "value too long for restore point (maximum %d characters)"
+msgstr "복원 위치 이름이 너무 깁니다. (최대값, %d 글자)"
+
+#: access/transam/xlogfuncs.c:472
+#, c-format
+msgid "pg_xlogfile_name_offset() cannot be executed during recovery."
+msgstr "복구 중에는 pg_xlogfile_name_offset() 함수를 실행할 수 없습니다."
+
+#: access/transam/xlogfuncs.c:528
+#, c-format
+msgid "pg_xlogfile_name() cannot be executed during recovery."
+msgstr "복구 중에는 pg_xlogfile_name() 함수를 실행할 수 없습니다."
+
+#: access/transam/xlogfuncs.c:548 access/transam/xlogfuncs.c:568
+#: access/transam/xlogfuncs.c:585
+#, c-format
+msgid "recovery is not in progress"
+msgstr "현재 복구 작업 상태가 아닙니다"
+
+#: access/transam/xlogfuncs.c:549 access/transam/xlogfuncs.c:569
+#: access/transam/xlogfuncs.c:586
+#, c-format
+msgid "Recovery control functions can only be executed during recovery."
+msgstr "복구 제어 함수는 복구 작업일 때만 실행할 수 있습니다."
+
+#: access/transam/xlogreader.c:276
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "잘못된 레코드 위치: %X/%X"
+
+#: access/transam/xlogreader.c:284
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "%X/%X에서 contrecord를 필요로 함"
+
+#: access/transam/xlogreader.c:325 access/transam/xlogreader.c:624
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "잘못된 레코드 길이: %X/%X, 기대값 %u, 실재값 %u"
+
+#: access/transam/xlogreader.c:340
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음"
+
+#: access/transam/xlogreader.c:381
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "%X/%X 위치에 contrecord 플래그가 없음"
+
+#: access/transam/xlogreader.c:394
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "잘못된 contrecord 길이 %u, 위치 %X/%X"
+
+#: access/transam/xlogreader.c:632
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "잘못된 자원 관리 ID %u, 위치: %X/%X"
+
+#: access/transam/xlogreader.c:646 access/transam/xlogreader.c:663
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "레코드의 잘못된 프리링크 %X/%X, 해당 레코드 %X/%X"
+
+#: access/transam/xlogreader.c:700
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "잘못된 자원관리자 데이터 체크섬, 위치: %X/%X 레코드"
+
+#: access/transam/xlogreader.c:733
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "%04X 매직 번호가 잘못됨, 로그 파일 %s, 위치 %u"
+
+#: access/transam/xlogreader.c:747 access/transam/xlogreader.c:798
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "잘못된 정보 비트 %04X, 로그 파일 %s, 위치 %u"
+
+#: access/transam/xlogreader.c:773
+#, c-format
+msgid ""
+"WAL file is from different database system: WAL file database system "
+"identifier is %s, pg_control database system identifier is %s"
+msgstr ""
+"WAL 파일이 다른 시스템의 것입니다. WAL 파일의 시스템 식별자는 %s, pg_control "
+"의 식별자는 %s"
+
+#: access/transam/xlogreader.c:780
+#, c-format
+msgid ""
+"WAL file is from different database system: incorrect XLOG_SEG_SIZE in page "
+"header"
+msgstr ""
+"WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더의 XLOG_SEG_SIZE "
+"값이 바르지 않음"
+
+#: access/transam/xlogreader.c:786
+#, c-format
+msgid ""
+"WAL file is from different database system: incorrect XLOG_BLCKSZ in page "
+"header"
+msgstr ""
+"WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더의 XLOG_BLCKSZ 값"
+"이 바르지 않음"
+
+#: access/transam/xlogreader.c:812
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "잘못된 페이지 주소 %X/%X, 로그 파일 %s, 위치 %u"
+
+#: access/transam/xlogreader.c:837
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "타임라인 범위 벗어남 %u (이전 번호 %u), 로그 파일 %s, 위치 %u"
+
+#: access/transam/xlogreader.c:1081
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "%u block_id는 범위를 벗어남, 위치 %X/%X"
+
+#: access/transam/xlogreader.c:1103
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA 지정했지만, %X/%X 에 자료가 없음"
+
+#: access/transam/xlogreader.c:1110
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA 지정 않았지만, %u 길이의 자료가 있음, 위치 %X/%X"
+
+#: access/transam/xlogreader.c:1143
+#, c-format
+msgid ""
+"BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at "
+"%X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE 설정이 되어 있지만, 옵셋: %u, 길이: %u, 블록 이미지 길이: "
+"%u, 대상: %X/%X"
+
+#: access/transam/xlogreader.c:1159
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE 설정이 안되어 있지만, 옵셋: %u, 길이: %u, 대상: %X/%X"
+
+#: access/transam/xlogreader.c:1174
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr ""
+"BKPIMAGE_IS_COMPRESSED 설정이 되어 있지만, 블록 이미지 길이: %u, 대상: %X/%X"
+
+#: access/transam/xlogreader.c:1189
+#, c-format
+msgid ""
+"neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image "
+"length is %u at %X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE, BKPIMAGE_IS_COMPRESSED 지정 안되어 있으나, 블록 이미지 길"
+"이는 %u, 대상: %X/%X"
+
+#: access/transam/xlogreader.c:1205
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL 설정이 되어 있지만, %X/%X 에 이전 릴레이션 없음"
+
+#: access/transam/xlogreader.c:1217
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "잘못된 block_id %u, 위치 %X/%X"
+
+#: access/transam/xlogreader.c:1282
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "잘못된 레코드 길이, 위치 %X/%X"
+
+#: access/transam/xlogreader.c:1371
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "잘못된 압축 이미지, 위치 %X/%X, 블록 %d"
+
+#: access/transam/xlogutils.c:739 replication/walsender.c:2129
+#, c-format
+msgid "could not read from log segment %s, offset %u, length %lu: %m"
+msgstr "%s 로그 조각 읽기 실패, 위치 %u, 길이 %lu: %m"
+
+#: bootstrap/bootstrap.c:269 postmaster/postmaster.c:793 tcop/postgres.c:3501
+#, c-format
+msgid "--%s requires a value"
+msgstr "--%s 옵션은 해당 값을 지정해야합니다"
+
+#: bootstrap/bootstrap.c:274 postmaster/postmaster.c:798 tcop/postgres.c:3506
+#, c-format
+msgid "-c %s requires a value"
+msgstr "-c %s 옵션은 해당 값을 지정해야합니다"
+
+#: bootstrap/bootstrap.c:285 postmaster/postmaster.c:810
+#: postmaster/postmaster.c:823
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "자제한 사항은 \"%s --help\" 명령으로 살펴보십시오.\n"
+
+#: bootstrap/bootstrap.c:294
+#, c-format
+msgid "%s: invalid command-line arguments\n"
+msgstr "%s: 잘못된 명령행 인자\n"
+
+#: catalog/aclchk.c:201
+#, c-format
+msgid "grant options can only be granted to roles"
+msgstr "grant 옵션들은 롤에서만 지정될 수 있습니다"
+
+#: catalog/aclchk.c:324
+#, c-format
+msgid "no privileges were granted for column \"%s\" of relation \"%s\""
+msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")에 대한 권한이 부여되지 않았음"
+
+#: catalog/aclchk.c:329
+#, c-format
+msgid "no privileges were granted for \"%s\""
+msgstr "\"%s\"에 대한 권한이 부여되지 않았음"
+
+#: catalog/aclchk.c:337
+#, c-format
+msgid "not all privileges were granted for column \"%s\" of relation \"%s\""
+msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")에 대한 일부 권한이 부여되지 않았음"
+
+#: catalog/aclchk.c:342
+#, c-format
+msgid "not all privileges were granted for \"%s\""
+msgstr "\"%s\"에 대한 일부 권한이 부여되지 않았음"
+
+#: catalog/aclchk.c:353
+#, c-format
+msgid "no privileges could be revoked for column \"%s\" of relation \"%s\""
+msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")에 대한 권한을 취소할 수 없음"
+
+#: catalog/aclchk.c:358
+#, c-format
+msgid "no privileges could be revoked for \"%s\""
+msgstr "\"%s\"에 대한 권한을 취소할 수 없음"
+
+#: catalog/aclchk.c:366
+#, c-format
+msgid ""
+"not all privileges could be revoked for column \"%s\" of relation \"%s\""
+msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")의 일부 권한을 박탈할 수 없음"
+
+#: catalog/aclchk.c:371
+#, c-format
+msgid "not all privileges could be revoked for \"%s\""
+msgstr "\"%s\"에 대한 일부 권한을 취소할 수 없음"
+
+#: catalog/aclchk.c:453 catalog/aclchk.c:943
+#, c-format
+msgid "invalid privilege type %s for relation"
+msgstr "릴레이션의 %s 권한은 잘못된 종류임"
+
+#: catalog/aclchk.c:457 catalog/aclchk.c:947
+#, c-format
+msgid "invalid privilege type %s for sequence"
+msgstr "시퀀스의 %s 권한은 잘못된 종류임"
+
+#: catalog/aclchk.c:461
+#, c-format
+msgid "invalid privilege type %s for database"
+msgstr "%s 권한은 데이터베이스에는 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:465
+#, c-format
+msgid "invalid privilege type %s for domain"
+msgstr "%s 권한은 도메인에서 유효하지 않음"
+
+#: catalog/aclchk.c:469 catalog/aclchk.c:951
+#, c-format
+msgid "invalid privilege type %s for function"
+msgstr "%s 권한은 함수에서 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:473
+#, c-format
+msgid "invalid privilege type %s for language"
+msgstr "%s 권한은 프로시주얼 언어에서 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:477
+#, c-format
+msgid "invalid privilege type %s for large object"
+msgstr "%s 권한은 대형 객체에서 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:481
+#, c-format
+msgid "invalid privilege type %s for schema"
+msgstr "%s 권한은 스키마(schema)에서 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:485
+#, c-format
+msgid "invalid privilege type %s for tablespace"
+msgstr "%s 권한은 테이블스페이스에서 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:489 catalog/aclchk.c:955
+#, c-format
+msgid "invalid privilege type %s for type"
+msgstr "%s 권한은 자료형에서 사용할 수 없은 권한 형태임"
+
+#: catalog/aclchk.c:493
+#, c-format
+msgid "invalid privilege type %s for foreign-data wrapper"
+msgstr "%s 권한 형식은 외부 데이터 래퍼에 유효하지 않음"
+
+#: catalog/aclchk.c:497
+#, c-format
+msgid "invalid privilege type %s for foreign server"
+msgstr "%s 권한 형식은 외부 서버에 유효하지 않음"
+
+#: catalog/aclchk.c:536
+#, c-format
+msgid "column privileges are only valid for relations"
+msgstr "칼럼 권한은 릴레이션에서만 유효함"
+
+#: catalog/aclchk.c:695 catalog/aclchk.c:3923 catalog/aclchk.c:4705
+#: catalog/objectaddress.c:873 catalog/pg_largeobject.c:113
+#: storage/large_object/inv_api.c:291
+#, c-format
+msgid "large object %u does not exist"
+msgstr "%u large object 없음"
+
+#: catalog/aclchk.c:882 catalog/aclchk.c:890 commands/collationcmds.c:92
+#: commands/copy.c:1047 commands/copy.c:1065 commands/copy.c:1073
+#: commands/copy.c:1081 commands/copy.c:1089 commands/copy.c:1097
+#: commands/copy.c:1105 commands/copy.c:1113 commands/copy.c:1121
+#: commands/copy.c:1137 commands/copy.c:1151 commands/copy.c:1170
+#: commands/copy.c:1185 commands/dbcommands.c:155 commands/dbcommands.c:163
+#: commands/dbcommands.c:171 commands/dbcommands.c:179
+#: commands/dbcommands.c:187 commands/dbcommands.c:195
+#: commands/dbcommands.c:203 commands/dbcommands.c:211
+#: commands/dbcommands.c:219 commands/dbcommands.c:1397
+#: commands/dbcommands.c:1405 commands/dbcommands.c:1413
+#: commands/dbcommands.c:1421 commands/extension.c:1219
+#: commands/extension.c:1227 commands/extension.c:1235
+#: commands/extension.c:1243 commands/extension.c:2761
+#: commands/foreigncmds.c:539 commands/foreigncmds.c:548
+#: commands/functioncmds.c:533 commands/functioncmds.c:649
+#: commands/functioncmds.c:657 commands/functioncmds.c:665
+#: commands/functioncmds.c:673 commands/functioncmds.c:2085
+#: commands/functioncmds.c:2093 commands/sequence.c:1189
+#: commands/sequence.c:1197 commands/sequence.c:1205 commands/sequence.c:1213
+#: commands/sequence.c:1221 commands/sequence.c:1229 commands/sequence.c:1237
+#: commands/sequence.c:1245 commands/typecmds.c:295 commands/typecmds.c:1382
+#: commands/typecmds.c:1391 commands/typecmds.c:1399 commands/typecmds.c:1407
+#: commands/typecmds.c:1415 commands/user.c:139 commands/user.c:156
+#: commands/user.c:164 commands/user.c:172 commands/user.c:180
+#: commands/user.c:188 commands/user.c:196 commands/user.c:204
+#: commands/user.c:212 commands/user.c:220 commands/user.c:228
+#: commands/user.c:236 commands/user.c:244 commands/user.c:537
+#: commands/user.c:549 commands/user.c:557 commands/user.c:565
+#: commands/user.c:573 commands/user.c:581 commands/user.c:589
+#: commands/user.c:597 commands/user.c:606 commands/user.c:614
+#: commands/user.c:622
+#, c-format
+msgid "conflicting or redundant options"
+msgstr "상충하거나 중복된 옵션들"
+
+#: catalog/aclchk.c:988
+#, c-format
+msgid "default privileges cannot be set for columns"
+msgstr "default privileges 설정은 칼럼 대상으로 할 수 없음"
+
+#: catalog/aclchk.c:1502 catalog/objectaddress.c:1390 commands/analyze.c:376
+#: commands/copy.c:4458 commands/sequence.c:1491 commands/tablecmds.c:5198
+#: commands/tablecmds.c:5304 commands/tablecmds.c:5364
+#: commands/tablecmds.c:5477 commands/tablecmds.c:5534
+#: commands/tablecmds.c:5628 commands/tablecmds.c:5724
+#: commands/tablecmds.c:7915 commands/tablecmds.c:8177
+#: commands/tablecmds.c:8597 commands/trigger.c:642 parser/analyze.c:2228
+#: parser/parse_relation.c:2628 parser/parse_relation.c:2690
+#: parser/parse_target.c:951 parser/parse_type.c:127 utils/adt/acl.c:2840
+#: utils/adt/ruleutils.c:1984
+#, c-format
+msgid "column \"%s\" of relation \"%s\" does not exist"
+msgstr "\"%s\" 열은 \"%s\" 릴레이션(relation)에 없음"
+
+#: catalog/aclchk.c:1771 catalog/objectaddress.c:1203 commands/sequence.c:1078
+#: commands/tablecmds.c:224 commands/tablecmds.c:12154 utils/adt/acl.c:2076
+#: utils/adt/acl.c:2106 utils/adt/acl.c:2138 utils/adt/acl.c:2170
+#: utils/adt/acl.c:2198 utils/adt/acl.c:2228
+#, c-format
+msgid "\"%s\" is not a sequence"
+msgstr "\"%s\" 시퀀스가 아님"
+
+#: catalog/aclchk.c:1809
+#, c-format
+msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges"
+msgstr "\"%s\" 시퀀스는 USAGE, SELECT 및 UPDATE 권한만 지원함"
+
+#: catalog/aclchk.c:1826
+#, c-format
+msgid "invalid privilege type USAGE for table"
+msgstr "테이블에서 USAGE 권한은 잘못되었음"
+
+#: catalog/aclchk.c:1994
+#, c-format
+msgid "invalid privilege type %s for column"
+msgstr "%s 권한 형식은 칼럼에서 유효하지 않음"
+
+#: catalog/aclchk.c:2007
+#, c-format
+msgid "sequence \"%s\" only supports SELECT column privileges"
+msgstr "\"%s\" 시퀀스는 SELECT 열 권한만 지원함"
+
+#: catalog/aclchk.c:2601
+#, c-format
+msgid "language \"%s\" is not trusted"
+msgstr "\"%s\" 프로시주얼 언어는 안전하지 못합니다"
+
+#: catalog/aclchk.c:2603
+#, c-format
+msgid ""
+"GRANT and REVOKE are not allowed on untrusted languages, because only "
+"superusers can use untrusted languages."
+msgstr ""
+"안전하지 않은 프로시져 언어에 대해서는 GRANT 또는 REVOKE 작업을 허용하지 않습"
+"니다, 안전하지 않은 프로시져 언어는 슈퍼유저만 사용할 수 있기 때문입니다."
+
+#: catalog/aclchk.c:3129
+#, c-format
+msgid "cannot set privileges of array types"
+msgstr "배열형 자료형에 권한 설정을 할 수 없음"
+
+#: catalog/aclchk.c:3130
+#, c-format
+msgid "Set the privileges of the element type instead."
+msgstr "그 배열 요소에 해당하는 자료형에 대해서 접근 권한 설정을 하세요."
+
+#: catalog/aclchk.c:3137 catalog/objectaddress.c:1523 commands/typecmds.c:3146
+#, c-format
+msgid "\"%s\" is not a domain"
+msgstr "\"%s\" 이름의 객체는 도메인이 아닙니다"
+
+#: catalog/aclchk.c:3260
+#, c-format
+msgid "unrecognized privilege type \"%s\""
+msgstr "알 수 없는 권한 타입 \"%s\""
+
+#: catalog/aclchk.c:3309
+#, c-format
+msgid "permission denied for column %s"
+msgstr "%s 칼럼에 대한 접근 권한 없음"
+
+#: catalog/aclchk.c:3311
+#, c-format
+msgid "permission denied for relation %s"
+msgstr "%s 릴레이션(relation) 접근 권한 없음"
+
+#: catalog/aclchk.c:3313 commands/sequence.c:561 commands/sequence.c:786
+#: commands/sequence.c:828 commands/sequence.c:865 commands/sequence.c:1543
+#, c-format
+msgid "permission denied for sequence %s"
+msgstr "%s 시퀀스 접근 권한 없음"
+
+#: catalog/aclchk.c:3315
+#, c-format
+msgid "permission denied for database %s"
+msgstr "%s 데이터베이스 접근 권한 없음"
+
+#: catalog/aclchk.c:3317
+#, c-format
+msgid "permission denied for function %s"
+msgstr "%s 함수 접근 권한 없음"
+
+#: catalog/aclchk.c:3319
+#, c-format
+msgid "permission denied for operator %s"
+msgstr "%s 연산자 접근 권한 없음"
+
+#: catalog/aclchk.c:3321
+#, c-format
+msgid "permission denied for type %s"
+msgstr "%s 자료형 접근 권한 없음"
+
+#: catalog/aclchk.c:3323
+#, c-format
+msgid "permission denied for language %s"
+msgstr "%s 프로시주얼 언어 접근 권한 없음"
+
+#: catalog/aclchk.c:3325
+#, c-format
+msgid "permission denied for large object %s"
+msgstr "%s 대형 객체 접근 권한 없음"
+
+#: catalog/aclchk.c:3327
+#, c-format
+msgid "permission denied for schema %s"
+msgstr "%s 스키마(schema) 접근 권한 없음"
+
+#: catalog/aclchk.c:3329
+#, c-format
+msgid "permission denied for operator class %s"
+msgstr "%s 연산자 클래스 접근 권한 없음"
+
+#: catalog/aclchk.c:3331
+#, c-format
+msgid "permission denied for operator family %s"
+msgstr "%s 연산자 패밀리 접근 권한 없음"
+
+#: catalog/aclchk.c:3333
+#, c-format
+msgid "permission denied for collation %s"
+msgstr "%s 정렬정의(collation) 접근 권한 없음"
+
+#: catalog/aclchk.c:3335
+#, c-format
+msgid "permission denied for conversion %s"
+msgstr "%s 문자코드변환규칙(conversion) 접근 권한 없음"
+
+#: catalog/aclchk.c:3337
+#, c-format
+msgid "permission denied for tablespace %s"
+msgstr "%s 테이블스페이스 접근 권한 없음"
+
+#: catalog/aclchk.c:3339
+#, c-format
+msgid "permission denied for text search dictionary %s"
+msgstr "%s 전문 검색 사전 접근 권한 없음"
+
+#: catalog/aclchk.c:3341
+#, c-format
+msgid "permission denied for text search configuration %s"
+msgstr "%s 전문 검색 구성 접근 권한 없음"
+
+#: catalog/aclchk.c:3343
+#, c-format
+msgid "permission denied for foreign-data wrapper %s"
+msgstr "%s 외부 데이터 래퍼 접근 권한 없음"
+
+#: catalog/aclchk.c:3345
+#, c-format
+msgid "permission denied for foreign server %s"
+msgstr "%s 외부 서버 접근 권한 없음"
+
+#: catalog/aclchk.c:3347
+#, c-format
+msgid "permission denied for event trigger %s"
+msgstr "%s 이벤트 트리거 접근 권한 없음"
+
+#: catalog/aclchk.c:3349
+#, c-format
+msgid "permission denied for extension %s"
+msgstr "%s 확장 모듈 접근 권한 없음"
+
+#: catalog/aclchk.c:3355 catalog/aclchk.c:3357
+#, c-format
+msgid "must be owner of relation %s"
+msgstr "%s 릴레이션(relation)의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3359
+#, c-format
+msgid "must be owner of sequence %s"
+msgstr "%s 시퀀스의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3361
+#, c-format
+msgid "must be owner of database %s"
+msgstr "%s 데이터베이스의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3363
+#, c-format
+msgid "must be owner of function %s"
+msgstr "%s 함수의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3365
+#, c-format
+msgid "must be owner of operator %s"
+msgstr "%s 연산자의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3367
+#, c-format
+msgid "must be owner of type %s"
+msgstr "%s 자료형의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3369
+#, c-format
+msgid "must be owner of language %s"
+msgstr "%s 프로시주얼 언어의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3371
+#, c-format
+msgid "must be owner of large object %s"
+msgstr "%s 대형 객체의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3373
+#, c-format
+msgid "must be owner of schema %s"
+msgstr "%s 스키마(schema)의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3375
+#, c-format
+msgid "must be owner of operator class %s"
+msgstr "%s 연산자 클래스의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3377
+#, c-format
+msgid "must be owner of operator family %s"
+msgstr "%s 연산자 패밀리의 소유주여야 함"
+
+#: catalog/aclchk.c:3379
+#, c-format
+msgid "must be owner of collation %s"
+msgstr "%s 정렬정의(collation)의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3381
+#, c-format
+msgid "must be owner of conversion %s"
+msgstr "%s 문자코드변환규칙(conversion)의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3383
+#, c-format
+msgid "must be owner of tablespace %s"
+msgstr "%s 테이블스페이스의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3385
+#, c-format
+msgid "must be owner of text search dictionary %s"
+msgstr "%s 전문 검색 사전의 소유주여야 함"
+
+#: catalog/aclchk.c:3387
+#, c-format
+msgid "must be owner of text search configuration %s"
+msgstr "%s 전문 검색 구성의 소유주여야 함"
+
+#: catalog/aclchk.c:3389
+#, c-format
+msgid "must be owner of foreign-data wrapper %s"
+msgstr "%s 외부 데이터 래퍼의 소유주여야 함"
+
+#: catalog/aclchk.c:3391
+#, c-format
+msgid "must be owner of foreign server %s"
+msgstr "%s 외부 서버의 소유주여야 함"
+
+#: catalog/aclchk.c:3393
+#, c-format
+msgid "must be owner of event trigger %s"
+msgstr "%s 이벤트 트리거의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3395
+#, c-format
+msgid "must be owner of extension %s"
+msgstr "%s 확장 모듈의 소유주여야만 합니다"
+
+#: catalog/aclchk.c:3437
+#, c-format
+msgid "permission denied for column \"%s\" of relation \"%s\""
+msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\") 접근 권한 없음"
+
+#: catalog/aclchk.c:3556 catalog/aclchk.c:3564
+#, c-format
+msgid "attribute %d of relation with OID %u does not exist"
+msgstr "%d번째 속성(해당 릴레이션 OID: %u)이 없음"
+
+#: catalog/aclchk.c:3637 catalog/aclchk.c:4556
+#, c-format
+msgid "relation with OID %u does not exist"
+msgstr "OID %u 릴레이션(relation) 없음"
+
+#: catalog/aclchk.c:3736 catalog/aclchk.c:4974
+#, c-format
+msgid "database with OID %u does not exist"
+msgstr "OID %u 데이터베이스 없음"
+
+#: catalog/aclchk.c:3790 catalog/aclchk.c:4634 tcop/fastpath.c:223
+#, c-format
+msgid "function with OID %u does not exist"
+msgstr "OID %u 함수 없음"
+
+#: catalog/aclchk.c:3844 catalog/aclchk.c:4660
+#, c-format
+msgid "language with OID %u does not exist"
+msgstr "OID %u 언어 없음"
+
+#: catalog/aclchk.c:4008 catalog/aclchk.c:4732
+#, c-format
+msgid "schema with OID %u does not exist"
+msgstr "OID %u 스키마 없음"
+
+#: catalog/aclchk.c:4062 catalog/aclchk.c:4759
+#, c-format
+msgid "tablespace with OID %u does not exist"
+msgstr "OID %u 테이블스페이스 없음"
+
+#: catalog/aclchk.c:4121 catalog/aclchk.c:4893 commands/foreigncmds.c:325
+#, c-format
+msgid "foreign-data wrapper with OID %u does not exist"
+msgstr "OID가 %u인 외부 데이터 래퍼가 없음"
+
+#: catalog/aclchk.c:4183 catalog/aclchk.c:4920 commands/foreigncmds.c:461
+#, c-format
+msgid "foreign server with OID %u does not exist"
+msgstr "OID가 %u인 외부 서버가 없음"
+
+#: catalog/aclchk.c:4243 catalog/aclchk.c:4582
+#, c-format
+msgid "type with OID %u does not exist"
+msgstr "OID %u 자료형 없음"
+
+#: catalog/aclchk.c:4608
+#, c-format
+msgid "operator with OID %u does not exist"
+msgstr "OID %u 연산자 없음"
+
+#: catalog/aclchk.c:4785
+#, c-format
+msgid "operator class with OID %u does not exist"
+msgstr "OID %u 연산자 클래스 없음"
+
+#: catalog/aclchk.c:4812
+#, c-format
+msgid "operator family with OID %u does not exist"
+msgstr "OID가 %u인 연산자 패밀리가 없음"
+
+#: catalog/aclchk.c:4839
+#, c-format
+msgid "text search dictionary with OID %u does not exist"
+msgstr "OID가 %u인 전문 검색 사전이 없음"
+
+#: catalog/aclchk.c:4866
+#, c-format
+msgid "text search configuration with OID %u does not exist"
+msgstr "OID가 %u인 텍스트 검색 구성이 없음"
+
+#: catalog/aclchk.c:4947 commands/event_trigger.c:587
+#, c-format
+msgid "event trigger with OID %u does not exist"
+msgstr "OID %u 이벤트 트리거가 없음"
+
+#: catalog/aclchk.c:5000
+#, c-format
+msgid "collation with OID %u does not exist"
+msgstr "OID %u 정렬정의(collation) 없음"
+
+#: catalog/aclchk.c:5026
+#, c-format
+msgid "conversion with OID %u does not exist"
+msgstr "OID %u 인코딩 변환규칙(conversion) 없음"
+
+#: catalog/aclchk.c:5067
+#, c-format
+msgid "extension with OID %u does not exist"
+msgstr "OID %u 확장 모듈이 없음"
+
+#: catalog/dependency.c:645
+#, c-format
+msgid "cannot drop %s because %s requires it"
+msgstr "%s 삭제할 수 없음, %s에서 필요로함"
+
+#: catalog/dependency.c:648
+#, c-format
+msgid "You can drop %s instead."
+msgstr "대신에, drop %s 명령을 사용할 수 있음."
+
+#: catalog/dependency.c:810 catalog/pg_shdepend.c:576
+#, c-format
+msgid "cannot drop %s because it is required by the database system"
+msgstr "%s 객체는 데이터베이스 시스템에서 필요하기 때문에 삭제 될 수 없음"
+
+#: catalog/dependency.c:926
+#, c-format
+msgid "drop auto-cascades to %s"
+msgstr "%s 객체가 자동으로 덩달아 삭제됨"
+
+#: catalog/dependency.c:938 catalog/dependency.c:947
+#, c-format
+msgid "%s depends on %s"
+msgstr "%s 의존대상: %s"
+
+#: catalog/dependency.c:959 catalog/dependency.c:968
+#, c-format
+msgid "drop cascades to %s"
+msgstr "%s 객체가 덩달아 삭제됨"
+
+#: catalog/dependency.c:976 catalog/pg_shdepend.c:687
+#, c-format
+msgid ""
+"\n"
+"and %d other object (see server log for list)"
+msgid_plural ""
+"\n"
+"and %d other objects (see server log for list)"
+msgstr[0] ""
+msgstr[1] ""
+
+#: catalog/dependency.c:988
+#, c-format
+msgid "cannot drop %s because other objects depend on it"
+msgstr "기타 다른 객체들이 이 객체에 의존하고 있어, %s 삭제할 수 없음"
+
+#: catalog/dependency.c:992 catalog/dependency.c:999
+#, c-format
+msgid "Use DROP ... CASCADE to drop the dependent objects too."
+msgstr ""
+"이 객체와 관계된 모든 객체들을 함께 삭제하려면 DROP ... CASCADE 명령을 사용하"
+"십시오"
+
+#: catalog/dependency.c:996
+#, c-format
+msgid "cannot drop desired object(s) because other objects depend on them"
+msgstr "다른 객체가 원하는 객체를 사용하고 있으므로 해당 객체를 삭제할 수 없음"
+
+#. translator: %d always has a value larger than 1
+#: catalog/dependency.c:1005
+#, c-format
+msgid "drop cascades to %d other object"
+msgid_plural "drop cascades to %d other objects"
+msgstr[0] "%d개의 다른 객체에 대한 관련 항목 삭제"
+
+#: catalog/dependency.c:1633
+#, c-format
+msgid "constant of the type \"regrole\" cannot be used here"
+msgstr "\"regrole\" 자료형 상수는 여기서 사용할 수 없음"
+
+#: catalog/heap.c:278
+#, c-format
+msgid "permission denied to create \"%s.%s\""
+msgstr "\"%s.%s\" 만들 권한이 없음"
+
+#: catalog/heap.c:280
+#, c-format
+msgid "System catalog modifications are currently disallowed."
+msgstr "시스템 카탈로그 변경은 현재 허용하지 않습니다."
+
+#: catalog/heap.c:415 commands/tablecmds.c:1439 commands/tablecmds.c:1896
+#: commands/tablecmds.c:4820
+#, c-format
+msgid "tables can have at most %d columns"
+msgstr "한 테이블에 지정할 수 있는 최대 열 수는 %d입니다"
+
+#: catalog/heap.c:432 commands/tablecmds.c:5081
+#, c-format
+msgid "column name \"%s\" conflicts with a system column name"
+msgstr "\"%s\" 열 이름은 시스템 열 이름과 충돌합니다"
+
+#: catalog/heap.c:448
+#, c-format
+msgid "column name \"%s\" specified more than once"
+msgstr "\"%s\" 칼럼 이름이 여러 번 지정됨"
+
+#: catalog/heap.c:498
+#, c-format
+msgid "column \"%s\" has type \"unknown\""
+msgstr "\"%s\" 열의 자료형이 \"unknown\" 입니다"
+
+#: catalog/heap.c:499
+#, c-format
+msgid "Proceeding with relation creation anyway."
+msgstr "관계 작성을 계속합니다."
+
+#: catalog/heap.c:512
+#, c-format
+msgid "column \"%s\" has pseudo-type %s"
+msgstr "\"%s\" 열은 %s 의사 자료형(pseudo-type)을 사용합니다"
+
+#: catalog/heap.c:542
+#, c-format
+msgid "composite type %s cannot be made a member of itself"
+msgstr "%s 복합 자료형은 자기 자신의 구성원으로 만들 수 없음"
+
+#: catalog/heap.c:584 commands/createas.c:201 commands/createas.c:498
+#, c-format
+msgid "no collation was derived for column \"%s\" with collatable type %s"
+msgstr ""
+"column \"%s\" 칼럼에 사용하는 %s 자료형에서 사용할 정렬규칙을 결정할 수 없습"
+"니다."
+
+#: catalog/heap.c:586 commands/createas.c:204 commands/createas.c:501
+#: commands/indexcmds.c:1133 commands/view.c:103 regex/regc_pg_locale.c:262
+#: utils/adt/formatting.c:1513 utils/adt/formatting.c:1565
+#: utils/adt/formatting.c:1633 utils/adt/formatting.c:1685
+#: utils/adt/formatting.c:1754 utils/adt/formatting.c:1818
+#: utils/adt/like.c:213 utils/adt/selfuncs.c:5334 utils/adt/varlena.c:1421
+#: utils/adt/varlena.c:1826
+#, c-format
+msgid "Use the COLLATE clause to set the collation explicitly."
+msgstr "명시적으로 정렬 규칙을 지정하려면 COLLATE 절을 사용하세요."
+
+#: catalog/heap.c:1067 catalog/index.c:792 commands/tablecmds.c:2623
+#, c-format
+msgid "relation \"%s\" already exists"
+msgstr "\"%s\" 이름의 릴레이션(relation)이 이미 있습니다"
+
+#: catalog/heap.c:1083 catalog/pg_type.c:412 catalog/pg_type.c:722
+#: commands/typecmds.c:237 commands/typecmds.c:784 commands/typecmds.c:1135
+#: commands/typecmds.c:1357 commands/typecmds.c:2113
+#, c-format
+msgid "type \"%s\" already exists"
+msgstr "\"%s\" 자료형이 이미 있습니다"
+
+#: catalog/heap.c:1084
+#, c-format
+msgid ""
+"A relation has an associated type of the same name, so you must use a name "
+"that doesn't conflict with any existing type."
+msgstr ""
+"하나의 릴레이션은 그 이름과 같은 자료형과 관계합니다. 그래서, 이미 같은 이름"
+"의 자료형이 있다면 해당 릴레이션을 만들 수 없습니다. 다른 이름을 사용하세요."
+
+#: catalog/heap.c:1112
+#, c-format
+msgid "pg_class heap OID value not set when in binary upgrade mode"
+msgstr "이진 업그레이드 작업 때, pg_class 자료 OID 값이 지정되지 않았습니다"
+
+#: catalog/heap.c:2291
+#, c-format
+msgid "check constraint \"%s\" already exists"
+msgstr "\"%s\" 이름의 체크 제약 조건이 이미 있습니다"
+
+#: catalog/heap.c:2456 catalog/pg_constraint.c:654 commands/tablecmds.c:6069
+#, c-format
+msgid "constraint \"%s\" for relation \"%s\" already exists"
+msgstr ""
+"\"%s\" 제약 조건이 이미 \"%s\" 릴레이션(relation)에서 사용되고 있습니다"
+
+#: catalog/heap.c:2463
+#, c-format
+msgid ""
+"constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\""
+msgstr ""
+"\"%s\" 제약 조건이 비상속 제약 조건과 충돌합니다, 해당 릴레이션: \"%s\""
+
+#: catalog/heap.c:2474
+#, c-format
+msgid ""
+"constraint \"%s\" conflicts with inherited constraint on relation \"%s\""
+msgstr "\"%s\" 제약 조건이 상속 제약 조건과 충돌합니다, 해당 릴레이션: \"%s\""
+
+#: catalog/heap.c:2484
+#, c-format
+msgid ""
+"constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\""
+msgstr ""
+"\"%s\" 제약 조건이 NOT VALID 제약 조건과 충돌합니다, 해당 릴레이션: \"%s\""
+
+#: catalog/heap.c:2489
+#, c-format
+msgid "merging constraint \"%s\" with inherited definition"
+msgstr "\"%s\" 제약 조건을 상속된 정의와 병합하는 중"
+
+#: catalog/heap.c:2595
+#, c-format
+msgid "cannot use column references in default expression"
+msgstr "default 표현식에서는 열 reference를 사용할 수 없음"
+
+#: catalog/heap.c:2606
+#, c-format
+msgid "default expression must not return a set"
+msgstr "default 표현식은 하나의 set을 반환하면 안됩니다"
+
+#: catalog/heap.c:2625 rewrite/rewriteHandler.c:1084
+#, c-format
+msgid "column \"%s\" is of type %s but default expression is of type %s"
+msgstr ""
+"\"%s\" 열의 자료형은 %s 인데, default 표현식에서는 %s 자료형을 사용했습니다"
+
+#: catalog/heap.c:2630 commands/prepare.c:374 parser/parse_node.c:428
+#: parser/parse_target.c:539 parser/parse_target.c:789
+#: parser/parse_target.c:799 rewrite/rewriteHandler.c:1089
+#, c-format
+msgid "You will need to rewrite or cast the expression."
+msgstr "다시 정의하거나 형변화자를 사용해보십시오"
+
+#: catalog/heap.c:2677
+#, c-format
+msgid "only table \"%s\" can be referenced in check constraint"
+msgstr "\"%s\" 테이블만이 체크 제약 조건에서 참조될 수 있습니다"
+
+#: catalog/heap.c:2917
+#, c-format
+msgid "unsupported ON COMMIT and foreign key combination"
+msgstr "ON COMMIT 및 외래 키 조합이 지원되지 않음"
+
+#: catalog/heap.c:2918
+#, c-format
+msgid ""
+"Table \"%s\" references \"%s\", but they do not have the same ON COMMIT "
+"setting."
+msgstr ""
+"\"%s\" 테이블에서 \"%s\" 테이블을 참조하는데 ON COMMIT 설정이 같지 않습니다."
+
+#: catalog/heap.c:2923
+#, c-format
+msgid "cannot truncate a table referenced in a foreign key constraint"
+msgstr ""
+"_^_ 테이블 내용을 모두 삭제할 수 없음, 참조키(foreign key) 제약 조건 안에서"
+
+#: catalog/heap.c:2924
+#, c-format
+msgid "Table \"%s\" references \"%s\"."
+msgstr "\"%s\" 테이블은 \"%s\" 객체를 참조합니다."
+
+#: catalog/heap.c:2926
+#, c-format
+msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE."
+msgstr ""
+"\"%s\" 테이블도 함께 자료를 지우거나, TRUNCATE ... CASCADE 구문을 사용하세요."
+
+#: catalog/index.c:210 parser/parse_utilcmd.c:1473 parser/parse_utilcmd.c:1559
+#, c-format
+msgid "multiple primary keys for table \"%s\" are not allowed"
+msgstr "\"%s\" 테이블에는 이미 기본키가 있습니다"
+
+#: catalog/index.c:228
+#, c-format
+msgid "primary keys cannot be expressions"
+msgstr "기본기(primary key)를 표현할 수 없음"
+
+#: catalog/index.c:742 catalog/index.c:1160
+#, c-format
+msgid "user-defined indexes on system catalog tables are not supported"
+msgstr "시스템 카탈로그 테이블에는 사용자 정의 인덱스를 지정할 수 없습니다"
+
+#: catalog/index.c:752
+#, c-format
+msgid "concurrent index creation on system catalog tables is not supported"
+msgstr "시스템 카탈로그 테이블에서 공존하는 인덱스 만들기는 지원하지 않습니다"
+
+#: catalog/index.c:770
+#, c-format
+msgid "shared indexes cannot be created after initdb"
+msgstr ""
+"공유되는 인덱스들은 initdb 명령으로 데이터베이스 클러스터를 만든 다음에는 만"
+"들 수 없습니다"
+
+#: catalog/index.c:784 commands/createas.c:249 commands/sequence.c:141
+#: parser/parse_utilcmd.c:191
+#, c-format
+msgid "relation \"%s\" already exists, skipping"
+msgstr "\"%s\" 이름의 릴레이션(relation)이 이미 있습니다, 건너뜀"
+
+#: catalog/index.c:820
+#, c-format
+msgid "pg_class index OID value not set when in binary upgrade mode"
+msgstr "이진 업그레이드 작업 때, pg_class 인덱스 OID 값이 지정되지 않았습니다"
+
+#: catalog/index.c:1422
+#, c-format
+msgid "DROP INDEX CONCURRENTLY must be first action in transaction"
+msgstr "DROP INDEX CONCURRENTLY 명령은 트랜잭션 내 가장 처음에 있어야 합니다"
+
+#: catalog/index.c:2004
+#, c-format
+msgid "building index \"%s\" on table \"%s\""
+msgstr "\"%s\" 인덱스를 \"%s\" 테이블에서 만드는 중"
+
+#: catalog/index.c:3322
+#, c-format
+msgid "cannot reindex temporary tables of other sessions"
+msgstr "임시 테이블의 인덱스 재생성 작업은 다른 세션에서 할 수 없음"
+
+#: catalog/index.c:3454
+#, c-format
+msgid "index \"%s\" was reindexed"
+msgstr "\"%s\" 인덱스가 다시 만들어졌음"
+
+#: catalog/index.c:3456 commands/vacuumlazy.c:1338 commands/vacuumlazy.c:1414
+#: commands/vacuumlazy.c:1603 commands/vacuumlazy.c:1813
+#, c-format
+msgid "%s."
+msgstr "%s."
+
+#: catalog/namespace.c:249 catalog/namespace.c:447 catalog/namespace.c:541
+#: commands/trigger.c:4523
+#, c-format
+msgid "cross-database references are not implemented: \"%s.%s.%s\""
+msgstr "서로 다른 데이터베이스간의 참조는 구현되어있지 않습니다: \"%s.%s.%s\""
+
+#: catalog/namespace.c:306
+#, c-format
+msgid "temporary tables cannot specify a schema name"
+msgstr "임시 테이블은 스키마 이름을 지정할 수 없음"
+
+#: catalog/namespace.c:385
+#, c-format
+msgid "could not obtain lock on relation \"%s.%s\""
+msgstr "\"%s.%s\" 릴레이션의 잠금 정보를 구할 수 없음"
+
+#: catalog/namespace.c:390 commands/lockcmds.c:146
+#, c-format
+msgid "could not obtain lock on relation \"%s\""
+msgstr "\"%s\" 릴레이션의 잠금 정보를 구할 수 없음"
+
+#: catalog/namespace.c:414 parser/parse_relation.c:1138
+#, c-format
+msgid "relation \"%s.%s\" does not exist"
+msgstr "\"%s.%s\" 이름의 릴레이션(relation)이 없습니다"
+
+#: catalog/namespace.c:419 parser/parse_relation.c:1151
+#: parser/parse_relation.c:1159 utils/adt/regproc.c:1034
+#, c-format
+msgid "relation \"%s\" does not exist"
+msgstr "\"%s\" 이름의 릴레이션(relation)이 없습니다"
+
+#: catalog/namespace.c:487 catalog/namespace.c:2841 commands/extension.c:1383
+#: commands/extension.c:1389
+#, c-format
+msgid "no schema has been selected to create in"
+msgstr "선택된 스키마 없음, 대상:"
+
+#: catalog/namespace.c:639 catalog/namespace.c:652
+#, c-format
+msgid "cannot create relations in temporary schemas of other sessions"
+msgstr "다른 세션의 임시 스키마 안에는 릴레이션을 만들 수 없음"
+
+#: catalog/namespace.c:643
+#, c-format
+msgid "cannot create temporary relation in non-temporary schema"
+msgstr "임시 스키마가 아닌 스키마에 임시 릴레이션을 만들 수 없음"
+
+#: catalog/namespace.c:658
+#, c-format
+msgid "only temporary relations may be created in temporary schemas"
+msgstr "임시 스키마 안에는 임시 릴레이션만 만들 수 있음"
+
+#: catalog/namespace.c:2154
+#, c-format
+msgid "text search parser \"%s\" does not exist"
+msgstr "\"%s\" 전문 검색 파서가 없음"
+
+#: catalog/namespace.c:2280
+#, c-format
+msgid "text search dictionary \"%s\" does not exist"
+msgstr "\"%s\" 전문 검색 사전이 없음"
+
+#: catalog/namespace.c:2407
+#, c-format
+msgid "text search template \"%s\" does not exist"
+msgstr "\"%s\" 전문 검색 템플릿이 없음"
+
+#: catalog/namespace.c:2533 commands/tsearchcmds.c:1197
+#: utils/cache/ts_cache.c:611
+#, c-format
+msgid "text search configuration \"%s\" does not exist"
+msgstr "\"%s\" 전문 검색 구성이 없음"
+
+#: catalog/namespace.c:2646 parser/parse_expr.c:792 parser/parse_target.c:1141
+#, c-format
+msgid "cross-database references are not implemented: %s"
+msgstr "서로 다른 데이터베이스간의 참조는 구현되어있지 않습니다: %s"
+
+#: catalog/namespace.c:2652 parser/parse_expr.c:799 parser/parse_target.c:1148
+#: gram.y:13454 gram.y:14823
+#, c-format
+msgid "improper qualified name (too many dotted names): %s"
+msgstr "적당하지 않은 qualified 이름 입니다 (너무 많은 점이 있네요): %s"
+
+#: catalog/namespace.c:2783
+#, c-format
+msgid "cannot move objects into or out of temporary schemas"
+msgstr "임시 스키마로(에서) 객체를 이동할 수 없습니다"
+
+#: catalog/namespace.c:2789
+#, c-format
+msgid "cannot move objects into or out of TOAST schema"
+msgstr "TOAST 스키마로(에서) 객체를 이동할 수 없습니다"
+
+#: catalog/namespace.c:2862 commands/schemacmds.c:238
+#: commands/schemacmds.c:317 commands/tablecmds.c:741
+#, c-format
+msgid "schema \"%s\" does not exist"
+msgstr "\"%s\" 스키마(schema) 없음"
+
+#: catalog/namespace.c:2893
+#, c-format
+msgid "improper relation name (too many dotted names): %s"
+msgstr ""
+"적당하지 않은 릴레이션(relation) 이름 입니다 (너무 많은 점이 있네요): %s"
+
+#: catalog/namespace.c:3403
+#, c-format
+msgid "collation \"%s\" for encoding \"%s\" does not exist"
+msgstr "\"%s\" 정렬정의(collation)가 \"%s\" 인코딩에서는 쓸 수 없음"
+
+#: catalog/namespace.c:3458
+#, c-format
+msgid "conversion \"%s\" does not exist"
+msgstr "\"%s\" 문자코드변환규칙(conversion) 없음"
+
+#: catalog/namespace.c:3666
+#, c-format
+msgid "permission denied to create temporary tables in database \"%s\""
+msgstr "\"%s\" 데이터베이스에서 임시 파일을 만들 권한이 없음"
+
+#: catalog/namespace.c:3682
+#, c-format
+msgid "cannot create temporary tables during recovery"
+msgstr "복구 작업 중에는 임시 테이블을 만들 수 없음"
+
+#: catalog/namespace.c:3688
+#, c-format
+msgid "cannot create temporary tables in parallel mode"
+msgstr "병렬 모드에서는 임시 테이블을 만들 수 없음"
+
+#: catalog/namespace.c:3932 commands/tablespace.c:1173 commands/variable.c:63
+#: utils/misc/guc.c:9875
+#, c-format
+msgid "List syntax is invalid."
+msgstr "목록 문법이 틀렸습니다."
+
+#: catalog/objectaddress.c:1065
+msgid "access method name cannot be qualified"
+msgstr "접근 방법 이름이 적당치 않습니다"
+
+#: catalog/objectaddress.c:1068
+msgid "database name cannot be qualified"
+msgstr "데이터베이스 이름이 적당치 않습니다"
+
+#: catalog/objectaddress.c:1071 commands/extension.c:2507
+#, c-format
+msgid "extension name cannot be qualified"
+msgstr "확장 모듈 이름으로 적당하지 않습니다"
+
+#: catalog/objectaddress.c:1074
+msgid "tablespace name cannot be qualified"
+msgstr "테이블스페이스 이름으로 적당하지 않습니다"
+
+#: catalog/objectaddress.c:1077
+msgid "role name cannot be qualified"
+msgstr "롤(role)이름으로 적당하지 않습니다"
+
+#: catalog/objectaddress.c:1080
+msgid "schema name cannot be qualified"
+msgstr "스키마 이름이 적당치 않습니다"
+
+#: catalog/objectaddress.c:1083
+msgid "language name cannot be qualified"
+msgstr "프로시주얼 언어 이름이 적당치 않습니다"
+
+#: catalog/objectaddress.c:1086
+msgid "foreign-data wrapper name cannot be qualified"
+msgstr "외부자료 랩퍼 이름이 적당치 않습니다"
+
+#: catalog/objectaddress.c:1089
+msgid "server name cannot be qualified"
+msgstr "서버 이름으로 적당하지 않습니다"
+
+#: catalog/objectaddress.c:1092
+msgid "event trigger name cannot be qualified"
+msgstr "이벤트 트리거 이름이 적당치 않습니다"
+
+#: catalog/objectaddress.c:1210 commands/lockcmds.c:94 commands/policy.c:94
+#: commands/policy.c:382 commands/policy.c:471 commands/tablecmds.c:218
+#: commands/tablecmds.c:1300 commands/tablecmds.c:4347
+#: commands/tablecmds.c:8017
+#, c-format
+msgid "\"%s\" is not a table"
+msgstr "\"%s\" 객체는 테이블이 아님"
+
+#: catalog/objectaddress.c:1217 commands/tablecmds.c:230
+#: commands/tablecmds.c:4377 commands/tablecmds.c:12159 commands/view.c:141
+#, c-format
+msgid "\"%s\" is not a view"
+msgstr "\"%s\" 객체는 뷰가 아님"
+
+#: catalog/objectaddress.c:1224 commands/matview.c:174
+#: commands/tablecmds.c:236 commands/tablecmds.c:12164
+#, c-format
+msgid "\"%s\" is not a materialized view"
+msgstr "\"%s\" 객체는 구체화된 뷰(materialized view)가 아닙니다"
+
+#: catalog/objectaddress.c:1231 commands/tablecmds.c:254
+#: commands/tablecmds.c:4380 commands/tablecmds.c:12169
+#, c-format
+msgid "\"%s\" is not a foreign table"
+msgstr "\"%s\" 객체는 외부 테이블이 아님"
+
+#: catalog/objectaddress.c:1376 catalog/objectaddress.c:1429
+#, c-format
+msgid "column name must be qualified"
+msgstr "칼럼 이름으로 적당하지 않습니다"
+
+#: catalog/objectaddress.c:1472
+#, c-format
+msgid "default value for column \"%s\" of relation \"%s\" does not exist"
+msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")의 기본값을 지정하지 않았음"
+
+#: catalog/objectaddress.c:1512 commands/functioncmds.c:128
+#: commands/tablecmds.c:246 commands/typecmds.c:3214 parser/parse_type.c:226
+#: parser/parse_type.c:255 parser/parse_type.c:795 utils/adt/acl.c:4374
+#: utils/adt/regproc.c:1225
+#, c-format
+msgid "type \"%s\" does not exist"
+msgstr "\"%s\" 자료형 없음"
+
+#: catalog/objectaddress.c:1629
+#, c-format
+msgid "operator %d (%s, %s) of %s does not exist"
+msgstr "%d (%s, %s) 연산자(대상 %s) 없음"
+
+#: catalog/objectaddress.c:1658
+#, c-format
+msgid "function %d (%s, %s) of %s does not exist"
+msgstr "%d (%s, %s) 함수(대상 %s) 없음"
+
+#: catalog/objectaddress.c:1707 catalog/objectaddress.c:1733
+#, c-format
+msgid "user mapping for user \"%s\" on server \"%s\" does not exist"
+msgstr "\"%s\" 사용자에 대한 사용자 맵핑 정보(대상 서버: \"%s\")가 없음"
+
+#: catalog/objectaddress.c:1722 commands/foreigncmds.c:430
+#: commands/foreigncmds.c:997 commands/foreigncmds.c:1359
+#: foreign/foreign.c:692
+#, c-format
+msgid "server \"%s\" does not exist"
+msgstr "\"%s\" 이름의 서버가 없음"
+
+#: catalog/objectaddress.c:1794
+#, c-format
+msgid "unrecognized default ACL object type %c"
+msgstr "알 수 없는 기본 ACL 객체 타입 %c"
+
+#: catalog/objectaddress.c:1795
+#, c-format
+msgid "Valid object types are \"r\", \"S\", \"f\", and \"T\"."
+msgstr "유효한 객체 형태는 \"r\", \"S\", \"f\", \"T\"."
+
+#: catalog/objectaddress.c:1841
+#, c-format
+msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist"
+msgstr "\"%s\" 사용자용 기본 ACL 없음. (해당 스키마: \"%s\", 해당 객체: %s)"
+
+#: catalog/objectaddress.c:1846
+#, c-format
+msgid "default ACL for user \"%s\" on %s does not exist"
+msgstr "\"%s\" 사용자용 기본 ACL 없음. (해당 객체: %s)"
+
+#: catalog/objectaddress.c:1873 catalog/objectaddress.c:1929
+#: catalog/objectaddress.c:1984
+#, c-format
+msgid "name or argument lists may not contain nulls"
+msgstr "이름이나 인자 목록에는 null이 포함되지 않아야 함"
+
+#: catalog/objectaddress.c:1905
+#, c-format
+msgid "unsupported object type \"%s\""
+msgstr "\"%s\" 형 지원하지 않음"
+
+#: catalog/objectaddress.c:1925 catalog/objectaddress.c:1943
+#, c-format
+msgid "name list length must be exactly %d"
+msgstr "이름 목록 길이는 %d 이어야 합니다."
+
+#: catalog/objectaddress.c:1947
+#, c-format
+msgid "large object OID may not be null"
+msgstr "대형 객체 OID는 null 값을 사용할 수 없음"
+
+#: catalog/objectaddress.c:1956 catalog/objectaddress.c:2016
+#: catalog/objectaddress.c:2023
+#, c-format
+msgid "name list length must be at least %d"
+msgstr "이름 목록 길이는 적어도 %d 개 이상이어야 함"
+
+#: catalog/objectaddress.c:2009 catalog/objectaddress.c:2029
+#, c-format
+msgid "argument list length must be exactly %d"
+msgstr "인자 목록은 %d 개여야 함"
+
+#: catalog/objectaddress.c:2165 libpq/be-fsstubs.c:350
+#, c-format
+msgid "must be owner of large object %u"
+msgstr "%u 대경 객체의 소유주여야만 합니다"
+
+#: catalog/objectaddress.c:2180 commands/functioncmds.c:1426
+#, c-format
+msgid "must be owner of type %s or type %s"
+msgstr "%s, %s 자료형의 소유주여야합니다"
+
+#: catalog/objectaddress.c:2220 catalog/objectaddress.c:2237
+#, c-format
+msgid "must be superuser"
+msgstr "슈퍼유져여야함"
+
+#: catalog/objectaddress.c:2227
+#, c-format
+msgid "must have CREATEROLE privilege"
+msgstr "CREATEROLE 권한이 있어야 함"
+
+#: catalog/objectaddress.c:2302
+#, c-format
+msgid "unrecognized object type \"%s\""
+msgstr "알 수 없는 객체 형태 \"%s\""
+
+#: catalog/objectaddress.c:2497
+#, c-format
+msgid " column %s"
+msgstr " %s 열"
+
+#: catalog/objectaddress.c:2503
+#, c-format
+msgid "function %s"
+msgstr "%s 함수"
+
+#: catalog/objectaddress.c:2508
+#, c-format
+msgid "type %s"
+msgstr "%s 자료형"
+
+#: catalog/objectaddress.c:2538
+#, c-format
+msgid "cast from %s to %s"
+msgstr "%s 자료형을 %s 자료형으로 바꾸는 작업"
+
+#: catalog/objectaddress.c:2558
+#, c-format
+msgid "collation %s"
+msgstr "collation %s"
+
+#: catalog/objectaddress.c:2582
+#, c-format
+msgid "constraint %s on %s"
+msgstr "%s 제약 조건(해당 객체: %s)"
+
+#: catalog/objectaddress.c:2588
+#, c-format
+msgid "constraint %s"
+msgstr "%s 제약 조건"
+
+#: catalog/objectaddress.c:2605
+#, c-format
+msgid "conversion %s"
+msgstr "%s 문자코드변환규칙"
+
+#: catalog/objectaddress.c:2642
+#, c-format
+msgid "default for %s"
+msgstr "default for %s"
+
+#: catalog/objectaddress.c:2651
+#, c-format
+msgid "language %s"
+msgstr "프로시주얼 언어 %s"
+
+#: catalog/objectaddress.c:2656
+#, c-format
+msgid "large object %u"
+msgstr "%u 대형 객체"
+
+#: catalog/objectaddress.c:2661
+#, c-format
+msgid "operator %s"
+msgstr "%s 연산자"
+
+#: catalog/objectaddress.c:2693
+#, c-format
+msgid "operator class %s for access method %s"
+msgstr "%s 연산자 클래스, %s 인덱스 액세스 방법"
+
+#. translator: %d is the operator strategy (a number), the
+#. first two %s's are data type names, the third %s is the
+#. description of the operator family, and the last %s is the
+#. textual form of the operator with arguments.
+#: catalog/objectaddress.c:2743
+#, c-format
+msgid "operator %d (%s, %s) of %s: %s"
+msgstr "%d (%s, %s) 연산자 (연산자 가족: %s): %s"
+
+#. translator: %d is the function number, the first two %s's
+#. are data type names, the third %s is the description of the
+#. operator family, and the last %s is the textual form of the
+#. function with arguments.
+#: catalog/objectaddress.c:2793
+#, c-format
+msgid "function %d (%s, %s) of %s: %s"
+msgstr "%d (%s, %s) 함수 (연산자 가족: %s): %s"
+
+#: catalog/objectaddress.c:2833
+#, c-format
+msgid "rule %s on "
+msgstr "%s 룰(rule), 해당 테이블: "
+
+#: catalog/objectaddress.c:2855
+#, c-format
+msgid "transform for %s language %s"
+msgstr "%s 형 변환자, 대상언어: %s"
+
+#: catalog/objectaddress.c:2889
+#, c-format
+msgid "trigger %s on "
+msgstr "%s 트리거, 해당 테이블: "
+
+#: catalog/objectaddress.c:2906
+#, c-format
+msgid "schema %s"
+msgstr "%s 스키마"
+
+#: catalog/objectaddress.c:2919
+#, c-format
+msgid "text search parser %s"
+msgstr "%s 전문 검색 파서"
+
+#: catalog/objectaddress.c:2934
+#, c-format
+msgid "text search dictionary %s"
+msgstr "%s 전문 검색 사전"
+
+#: catalog/objectaddress.c:2949
+#, c-format
+msgid "text search template %s"
+msgstr "%s 전문 검색 템플릿"
+
+#: catalog/objectaddress.c:2964
+#, c-format
+msgid "text search configuration %s"
+msgstr "%s 전문 검색 구성"
+
+#: catalog/objectaddress.c:2972
+#, c-format
+msgid "role %s"
+msgstr "%s 롤"
+
+#: catalog/objectaddress.c:2985
+#, c-format
+msgid "database %s"
+msgstr "%s 데이터베이스"
+
+#: catalog/objectaddress.c:2997
+#, c-format
+msgid "tablespace %s"
+msgstr "%s 테이블스페이스"
+
+#: catalog/objectaddress.c:3006
+#, c-format
+msgid "foreign-data wrapper %s"
+msgstr "%s 외부 데이터 래퍼"
+
+#: catalog/objectaddress.c:3015
+#, c-format
+msgid "server %s"
+msgstr "%s 서버"
+
+#: catalog/objectaddress.c:3043
+#, c-format
+msgid "user mapping for %s on server %s"
+msgstr "%s에 대한 사용자 매핑, 해당 서버: %s"
+
+#: catalog/objectaddress.c:3078
+#, c-format
+msgid "default privileges on new relations belonging to role %s"
+msgstr "%s 롤이 새 테이블을 만들 때 기본적으로 지정할 접근 권한"
+
+#: catalog/objectaddress.c:3083
+#, c-format
+msgid "default privileges on new sequences belonging to role %s"
+msgstr "%s 롤이 새 시퀀스를 만들 때 기본적으로 지정할 접근 권한"
+
+#: catalog/objectaddress.c:3088
+#, c-format
+msgid "default privileges on new functions belonging to role %s"
+msgstr "%s 롤이 새 함수를 만들 때 기본적으로 지정할 접근 권한"
+
+#: catalog/objectaddress.c:3093
+#, c-format
+msgid "default privileges on new types belonging to role %s"
+msgstr "%s 롤이 새 자료형을 만들 때 기본적으로 지정할 접근 권한"
+
+#: catalog/objectaddress.c:3099
+#, c-format
+msgid "default privileges belonging to role %s"
+msgstr "%s 롤의 기본 접근 권한"
+
+#: catalog/objectaddress.c:3107
+#, c-format
+msgid " in schema %s"
+msgstr ", 대상 스키마: %s"
+
+#: catalog/objectaddress.c:3124
+#, c-format
+msgid "extension %s"
+msgstr "%s 확장 모듈"
+
+#: catalog/objectaddress.c:3137
+#, c-format
+msgid "event trigger %s"
+msgstr "%s 이벤트 트리거"
+
+#: catalog/objectaddress.c:3169
+#, c-format
+msgid "policy %s on "
+msgstr "%s 정책 "
+
+#: catalog/objectaddress.c:3187
+#, c-format
+msgid "access method %s"
+msgstr "%s 접근 방법"
+
+#: catalog/objectaddress.c:3247
+#, c-format
+msgid "table %s"
+msgstr "%s 테이블"
+
+#: catalog/objectaddress.c:3251
+#, c-format
+msgid "index %s"
+msgstr "%s 인덱스"
+
+#: catalog/objectaddress.c:3255
+#, c-format
+msgid "sequence %s"
+msgstr "%s 시퀀스"
+
+#: catalog/objectaddress.c:3259
+#, c-format
+msgid "toast table %s"
+msgstr "%s 토스트 테이블"
+
+#: catalog/objectaddress.c:3263
+#, c-format
+msgid "view %s"
+msgstr "%s 뷰"
+
+#: catalog/objectaddress.c:3267
+#, c-format
+msgid "materialized view %s"
+msgstr "%s 구체화된 뷰"
+
+#: catalog/objectaddress.c:3271
+#, c-format
+msgid "composite type %s"
+msgstr "%s 복합 자료형"
+
+#: catalog/objectaddress.c:3275
+#, c-format
+msgid "foreign table %s"
+msgstr "%s 외부 테이블"
+
+#: catalog/objectaddress.c:3280
+#, c-format
+msgid "relation %s"
+msgstr "%s 릴레이션"
+
+#: catalog/objectaddress.c:3317
+#, c-format
+msgid "operator family %s for access method %s"
+msgstr "%s 연산자 페밀리, 접근 방법: %s"
+
+#: catalog/pg_aggregate.c:125
+#, c-format
+msgid "aggregates cannot have more than %d argument"
+msgid_plural "aggregates cannot have more than %d arguments"
+msgstr[0] "집계 함수에는 %d개 이상의 인자를 사용할 수 없음"
+
+#: catalog/pg_aggregate.c:148 catalog/pg_aggregate.c:158
+#, c-format
+msgid "cannot determine transition data type"
+msgstr "처리할(변환할) 자료형을 결정할 수 없음"
+
+#: catalog/pg_aggregate.c:149 catalog/pg_aggregate.c:159
+#, c-format
+msgid ""
+"An aggregate using a polymorphic transition type must have at least one "
+"polymorphic argument."
+msgstr ""
+"다형 변환 형식을 사용하는 집계에는 다형 인자가 하나 이상 있어야 합니다."
+
+#: catalog/pg_aggregate.c:172
+#, c-format
+msgid "a variadic ordered-set aggregate must use VARIADIC type ANY"
+msgstr "variadic 순서있는 세트 집계함수는 VARIADIC ANY 형을 사용해야 합니다"
+
+#: catalog/pg_aggregate.c:198
+#, c-format
+msgid ""
+"a hypothetical-set aggregate must have direct arguments matching its "
+"aggregated arguments"
+msgstr ""
+
+#: catalog/pg_aggregate.c:245 catalog/pg_aggregate.c:289
+#, c-format
+msgid "return type of transition function %s is not %s"
+msgstr "%s 이름의 transition 함수의 리턴 자료형이 %s 형이 아닙니다"
+
+#: catalog/pg_aggregate.c:265 catalog/pg_aggregate.c:308
+#, c-format
+msgid ""
+"must not omit initial value when transition function is strict and "
+"transition type is not compatible with input type"
+msgstr ""
+"변환 함수가 엄격하고 변환 형식이 입력 형식과 호환되지 않는 경우 초기값을 생략"
+"하면 안됨"
+
+#: catalog/pg_aggregate.c:334
+#, c-format
+msgid "return type of inverse transition function %s is not %s"
+msgstr "%s inverse transition 함수의 반환 자료형이 %s 형이 아닙니다."
+
+#: catalog/pg_aggregate.c:351 executor/nodeWindowAgg.c:2334
+#, c-format
+msgid ""
+"strictness of aggregate's forward and inverse transition functions must match"
+msgstr ""
+
+#: catalog/pg_aggregate.c:395 catalog/pg_aggregate.c:545
+#, c-format
+msgid "final function with extra arguments must not be declared STRICT"
+msgstr ""
+
+#: catalog/pg_aggregate.c:425
+#, c-format
+msgid "return type of combine function %s is not %s"
+msgstr "%s combine 함수의 반환 자료형이 %s 형이 아닙니다"
+
+#: catalog/pg_aggregate.c:436
+#, c-format
+msgid ""
+"combine function with \"%s\" transition type must not be declared STRICT"
+msgstr ""
+
+#: catalog/pg_aggregate.c:455
+#, c-format
+msgid "return type of serialization function %s is not %s"
+msgstr "%s serialization 함수의 반환 자료형이 %s 형이 아닙니다."
+
+#: catalog/pg_aggregate.c:475
+#, c-format
+msgid "return type of deserialization function %s is not %s"
+msgstr "%s deserialization 함수의 반환 자료형이 %s 형이 아닙니다"
+
+#: catalog/pg_aggregate.c:491 catalog/pg_proc.c:246 catalog/pg_proc.c:253
+#, c-format
+msgid "cannot determine result data type"
+msgstr "결과 자료형을 결정할 수 없음"
+
+#: catalog/pg_aggregate.c:492
+#, c-format
+msgid ""
+"An aggregate returning a polymorphic type must have at least one polymorphic "
+"argument."
+msgstr ""
+"다형 자료형을 반환하는 집계에는 다형 자료형 인자가 하나 이상 있어야 합니다."
+
+#: catalog/pg_aggregate.c:504 catalog/pg_proc.c:259
+#, c-format
+msgid "unsafe use of pseudo-type \"internal\""
+msgstr "\"internal\" 의사-자료형의 사용이 안전하지 않습니다"
+
+#: catalog/pg_aggregate.c:505 catalog/pg_proc.c:260
+#, c-format
+msgid ""
+"A function returning \"internal\" must have at least one \"internal\" "
+"argument."
+msgstr ""
+"\"internal\" 자료형을 리턴하는 함수는 적어도 하나 이상의 인자가 \"internal\" "
+"자료형이어야합니다."
+
+#: catalog/pg_aggregate.c:558
+#, c-format
+msgid ""
+"moving-aggregate implementation returns type %s, but plain implementation "
+"returns type %s"
+msgstr ""
+
+#: catalog/pg_aggregate.c:569
+#, c-format
+msgid "sort operator can only be specified for single-argument aggregates"
+msgstr "정렬 연산자는 단일 인자 집계에만 지정할 수 있음"
+
+#: catalog/pg_aggregate.c:812 commands/typecmds.c:1705
+#: commands/typecmds.c:1756 commands/typecmds.c:1787 commands/typecmds.c:1810
+#: commands/typecmds.c:1831 commands/typecmds.c:1858 commands/typecmds.c:1885
+#: commands/typecmds.c:1962 commands/typecmds.c:2004 parser/parse_func.c:364
+#: parser/parse_func.c:393 parser/parse_func.c:418 parser/parse_func.c:432
+#: parser/parse_func.c:507 parser/parse_func.c:518 parser/parse_func.c:1923
+#, c-format
+msgid "function %s does not exist"
+msgstr "%s 이름의 함수가 없음"
+
+#: catalog/pg_aggregate.c:818
+#, c-format
+msgid "function %s returns a set"
+msgstr "%s 함수는 한 set을 리턴함"
+
+#: catalog/pg_aggregate.c:833
+#, c-format
+msgid "function %s must accept VARIADIC ANY to be used in this aggregate"
+msgstr "%s 함수가 이 집계작업에 사용되려면 VARIADIC ANY 형을 수용해야 합니다."
+
+#: catalog/pg_aggregate.c:857
+#, c-format
+msgid "function %s requires run-time type coercion"
+msgstr "%s 함수는 run-time type coercion을 필요로 함"
+
+#: catalog/pg_collation.c:77
+#, c-format
+msgid "collation \"%s\" for encoding \"%s\" already exists"
+msgstr "\"%s\" 정렬규칙이 \"%s\" 인코딩에 이미 지정되어 있습니다"
+
+#: catalog/pg_collation.c:91
+#, c-format
+msgid "collation \"%s\" already exists"
+msgstr "\"%s\" 정렬규칙이 이미 있습니다"
+
+#: catalog/pg_constraint.c:663
+#, c-format
+msgid "constraint \"%s\" for domain %s already exists"
+msgstr "\"%s\" 제약 조건이 %s 도메인에 이미 지정되어 있습니다"
+
+#: catalog/pg_constraint.c:797
+#, c-format
+msgid "table \"%s\" has multiple constraints named \"%s\""
+msgstr "\"%s\" 테이블에는 \"%s\" 이름의 제약 조건이 여러개 있습니다"
+
+#: catalog/pg_constraint.c:809
+#, c-format
+msgid "constraint \"%s\" for table \"%s\" does not exist"
+msgstr "\"%s\" 제약 조건은 \"%s\" 테이블에 없음"
+
+#: catalog/pg_constraint.c:855
+#, c-format
+msgid "domain \"%s\" has multiple constraints named \"%s\""
+msgstr "\"%s\" 도메인에는 \"%s\" 이름의 제약 조건이 여러개 있습니다"
+
+#: catalog/pg_constraint.c:867
+#, c-format
+msgid "constraint \"%s\" for domain \"%s\" does not exist"
+msgstr "\"%s\" 제약 조건은 \"%s\" 도메인에 없음"
+
+#: catalog/pg_conversion.c:66
+#, c-format
+msgid "conversion \"%s\" already exists"
+msgstr "\"%s\" 이름의 변환규칙(conversion)이 이미 있음"
+
+#: catalog/pg_conversion.c:79
+#, c-format
+msgid "default conversion for %s to %s already exists"
+msgstr "%s 코드에서 %s 코드로 변환하는 기본 변환규칙(conversion)은 이미 있음"
+
+#: catalog/pg_depend.c:165 commands/extension.c:3029
+#, c-format
+msgid "%s is already a member of extension \"%s\""
+msgstr "%s 객체는 \"%s\" 확장모듈에 이미 구성원입니다"
+
+#: catalog/pg_depend.c:324
+#, c-format
+msgid "cannot remove dependency on %s because it is a system object"
+msgstr "%s 의존객체들은 시스템 객체이기 때문에 삭제 될 수 없습니다"
+
+#: catalog/pg_enum.c:115 catalog/pg_enum.c:202
+#, c-format
+msgid "invalid enum label \"%s\""
+msgstr "\"%s\" 열거형 라벨이 잘못됨"
+
+#: catalog/pg_enum.c:116 catalog/pg_enum.c:203
+#, c-format
+msgid "Labels must be %d characters or less."
+msgstr "라벨은 %d자 이하여야 합니다."
+
+#: catalog/pg_enum.c:231
+#, c-format
+msgid "enum label \"%s\" already exists, skipping"
+msgstr "\"%s\" 이름의 열거형 라벨이 이미 있음, 건너뜀"
+
+#: catalog/pg_enum.c:238
+#, c-format
+msgid "enum label \"%s\" already exists"
+msgstr "\"%s\" 이름의 열거형 라벨이 이미 있음"
+
+#: catalog/pg_enum.c:293
+#, c-format
+msgid "\"%s\" is not an existing enum label"
+msgstr "\"%s\" 열거형 라벨이 없음"
+
+#: catalog/pg_enum.c:349
+#, c-format
+msgid "pg_enum OID value not set when in binary upgrade mode"
+msgstr "이진 업그레이드 작업 때 pg_enum OID 값이 지정되지 않았습니다"
+
+#: catalog/pg_enum.c:359
+#, c-format
+msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade"
+msgstr ""
+"ALTER TYPE ADD BEFORE/AFTER 구문은 이진 업그레이드 작업에서 호환하지 않습니다"
+
+#: catalog/pg_namespace.c:61 commands/schemacmds.c:246
+#, c-format
+msgid "schema \"%s\" already exists"
+msgstr "\"%s\" 이름의 스키마(schema)가 이미 있음"
+
+#: catalog/pg_operator.c:219 catalog/pg_operator.c:360
+#, c-format
+msgid "\"%s\" is not a valid operator name"
+msgstr "\"%s\" 타당한 연산자 이름이 아님"
+
+#: catalog/pg_operator.c:369
+#, c-format
+msgid "only binary operators can have commutators"
+msgstr "_^_ 바이너리 연산자만이 commutator를 가질 수 있음"
+
+#: catalog/pg_operator.c:373 commands/operatorcmds.c:485
+#, c-format
+msgid "only binary operators can have join selectivity"
+msgstr "_^_ 바이너리 연산자만이 join selectivity를 가질 수 있음"
+
+#: catalog/pg_operator.c:377
+#, c-format
+msgid "only binary operators can merge join"
+msgstr "_^_ 바이너리 연산자만이 merge join할 수 있음"
+
+#: catalog/pg_operator.c:381
+#, c-format
+msgid "only binary operators can hash"
+msgstr "_^_ 바이너리 연산자만이 해시할 수 있음"
+
+#: catalog/pg_operator.c:392
+#, c-format
+msgid "only boolean operators can have negators"
+msgstr "부울 연산자만 부정어를 포함할 수 있음"
+
+#: catalog/pg_operator.c:396 commands/operatorcmds.c:493
+#, c-format
+msgid "only boolean operators can have restriction selectivity"
+msgstr "부울 연산자만 제한 선택을 포함할 수 있음"
+
+#: catalog/pg_operator.c:400 commands/operatorcmds.c:497
+#, c-format
+msgid "only boolean operators can have join selectivity"
+msgstr "부울 연산자만 조인 선택을 포함할 수 있음"
+
+#: catalog/pg_operator.c:404
+#, c-format
+msgid "only boolean operators can merge join"
+msgstr "부울 연산자만 머지 조인을 지정할 수 있음"
+
+#: catalog/pg_operator.c:408
+#, c-format
+msgid "only boolean operators can hash"
+msgstr "부울 연산자만 해시를 지정할 수 있음"
+
+#: catalog/pg_operator.c:420
+#, c-format
+msgid "operator %s already exists"
+msgstr "%s 연산자가 이미 있음"
+
+#: catalog/pg_operator.c:617
+#, c-format
+msgid "operator cannot be its own negator or sort operator"
+msgstr "연산자는 자신의 negator나 sort 연산자가 될 수 없습니다"
+
+#: catalog/pg_proc.c:134 parser/parse_func.c:1947 parser/parse_func.c:1987
+#, c-format
+msgid "functions cannot have more than %d argument"
+msgid_plural "functions cannot have more than %d arguments"
+msgstr[0] "함수는 %d개 이상의 인자를 사용할 수 없음"
+
+#: catalog/pg_proc.c:247
+#, c-format
+msgid ""
+"A function returning a polymorphic type must have at least one polymorphic "
+"argument."
+msgstr "다형 형식을 반환하는 함수에는 다형 인자가 하나 이상 있어야 합니다."
+
+#: catalog/pg_proc.c:254
+#, c-format
+msgid ""
+"A function returning \"anyrange\" must have at least one \"anyrange\" "
+"argument."
+msgstr ""
+"\"anyrange\" 자료형을 반환하는 함수는 적어도 하나 이상의 인자가 \"anyrange\" "
+"자료형이어야합니다."
+
+#: catalog/pg_proc.c:272
+#, c-format
+msgid "\"%s\" is already an attribute of type %s"
+msgstr "\"%s\"은(는) 이미 %s 형식의 속성임"
+
+#: catalog/pg_proc.c:403
+#, c-format
+msgid "function \"%s\" already exists with same argument types"
+msgstr "이미 같은 인자 자료형을 사용하는 \"%s\" 함수가 있습니다"
+
+#: catalog/pg_proc.c:417 catalog/pg_proc.c:440
+#, c-format
+msgid "cannot change return type of existing function"
+msgstr "이미 있는 함수의 리턴 자료형은 바꿀 수 없습니다"
+
+#: catalog/pg_proc.c:418 catalog/pg_proc.c:442 catalog/pg_proc.c:485
+#: catalog/pg_proc.c:509 catalog/pg_proc.c:536
+#, c-format
+msgid "Use DROP FUNCTION %s first."
+msgstr "먼저 DROP FUNCTION %s 명령으로 함수를 삭제 하세요"
+
+#: catalog/pg_proc.c:441
+#, c-format
+msgid "Row type defined by OUT parameters is different."
+msgstr "OUT 매개 변수에 정의된 행 형식이 다릅니다."
+
+#: catalog/pg_proc.c:483
+#, c-format
+msgid "cannot change name of input parameter \"%s\""
+msgstr "\"%s\" 입력 매개 변수 이름을 바꿀 수 없음"
+
+#: catalog/pg_proc.c:508
+#, c-format
+msgid "cannot remove parameter defaults from existing function"
+msgstr "기존 함수에서 매개 변수 기본 값을 제거할 수 없음"
+
+#: catalog/pg_proc.c:535
+#, c-format
+msgid "cannot change data type of existing parameter default value"
+msgstr "기존 매개 변수 기본 값의 데이터 형식을 바꿀 수 없음"
+
+#: catalog/pg_proc.c:548
+#, c-format
+msgid "function \"%s\" is an aggregate function"
+msgstr "\"%s\" 함수는 집계 함수임"
+
+#: catalog/pg_proc.c:553
+#, c-format
+msgid "function \"%s\" is not an aggregate function"
+msgstr "\"%s\" 함수는 집계 함수가 아님"
+
+#: catalog/pg_proc.c:561
+#, c-format
+msgid "function \"%s\" is a window function"
+msgstr "\"%s\" 함수는 윈도우 함수임"
+
+#: catalog/pg_proc.c:566
+#, c-format
+msgid "function \"%s\" is not a window function"
+msgstr "\"%s\" 함수는 윈도우 함수가 아님"
+
+#: catalog/pg_proc.c:774
+#, c-format
+msgid "there is no built-in function named \"%s\""
+msgstr "\"%s\" 이름의 내장 함수가 없음"
+
+#: catalog/pg_proc.c:872
+#, c-format
+msgid "SQL functions cannot return type %s"
+msgstr "SQL 함수는 %s 자료형을 리턴할 수 없음"
+
+#: catalog/pg_proc.c:887
+#, c-format
+msgid "SQL functions cannot have arguments of type %s"
+msgstr "SQL 함수의 인자로 %s 자료형은 사용될 수 없습니다"
+
+#: catalog/pg_proc.c:973 executor/functions.c:1431
+#, c-format
+msgid "SQL function \"%s\""
+msgstr "\"%s\" SQL 함수"
+
+#: catalog/pg_shdepend.c:694
+#, c-format
+msgid ""
+"\n"
+"and objects in %d other database (see server log for list)"
+msgid_plural ""
+"\n"
+"and objects in %d other databases (see server log for list)"
+msgstr[0] ""
+
+#: catalog/pg_shdepend.c:1006
+#, c-format
+msgid "role %u was concurrently dropped"
+msgstr "%u 롤이 동시에 삭제되었음"
+
+#: catalog/pg_shdepend.c:1025
+#, c-format
+msgid "tablespace %u was concurrently dropped"
+msgstr "%u 테이블스페이스는 현재 삭제되었습니다"
+
+#: catalog/pg_shdepend.c:1040
+#, c-format
+msgid "database %u was concurrently dropped"
+msgstr "%u 데이터베이스는 현재 삭제되었습니다"
+
+#: catalog/pg_shdepend.c:1085
+#, c-format
+msgid "owner of %s"
+msgstr "%s 객체의 소유주"
+
+#: catalog/pg_shdepend.c:1087
+#, c-format
+msgid "privileges for %s"
+msgstr "\"%s\"에 대한 권한"
+
+#: catalog/pg_shdepend.c:1089
+#, c-format
+msgid "target of %s"
+msgstr "%s 객체 대상"
+
+#. translator: %s will always be "database %s"
+#: catalog/pg_shdepend.c:1097
+#, c-format
+msgid "%d object in %s"
+msgid_plural "%d objects in %s"
+msgstr[0] "%d 객체(데이터베이스: %s)"
+
+#: catalog/pg_shdepend.c:1208
+#, c-format
+msgid ""
+"cannot drop objects owned by %s because they are required by the database "
+"system"
+msgstr ""
+"%s 소유주의 객체 삭제는 그 데이터베이스 시스템에서 필요하기 때문에 삭제 될 "
+"수 없음"
+
+#: catalog/pg_shdepend.c:1323
+#, c-format
+msgid ""
+"cannot reassign ownership of objects owned by %s because they are required "
+"by the database system"
+msgstr ""
+"%s 소유주의 객체 삭제는 그 데이터베이스 시스템에서 필요하기 때문에 삭제 될 "
+"수 없음"
+
+#: catalog/pg_type.c:136 catalog/pg_type.c:454
+#, c-format
+msgid "pg_type OID value not set when in binary upgrade mode"
+msgstr "이진 업그레이드 작업 때 pg_type OID 값이 지정되지 않았습니다"
+
+#: catalog/pg_type.c:253
+#, c-format
+msgid "invalid type internal size %d"
+msgstr "잘못된 자료형의 내부 크기 %d"
+
+#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285
+#: catalog/pg_type.c:294
+#, c-format
+msgid "alignment \"%c\" is invalid for passed-by-value type of size %d"
+msgstr "\"%c\" 정렬은 크기가 %d인 전달 값 형식에 유효하지 않음"
+
+#: catalog/pg_type.c:301
+#, c-format
+msgid "internal size %d is invalid for passed-by-value type"
+msgstr "내부 크기 %d은(는) 전달 값 형식에 유효하지 않음"
+
+#: catalog/pg_type.c:310 catalog/pg_type.c:316
+#, c-format
+msgid "alignment \"%c\" is invalid for variable-length type"
+msgstr "\"%c\" 정렬은 가변 길이 형식에 유효하지 않음"
+
+#: catalog/pg_type.c:324
+#, c-format
+msgid "fixed-size types must have storage PLAIN"
+msgstr "_^_ 고정크기 자료형은 PLAIN 저장방법을 가져야만 합니다"
+
+#: catalog/pg_type.c:789
+#, c-format
+msgid "could not form array type name for type \"%s\""
+msgstr "\"%s\" 형식의 배열 형식 이름을 생성할 수 없음"
+
+#: catalog/toasting.c:105 commands/indexcmds.c:389 commands/tablecmds.c:4359
+#: commands/tablecmds.c:12047
+#, c-format
+msgid "\"%s\" is not a table or materialized view"
+msgstr "\"%s\" 객체는 테이블도 구체화된 뷰도 아닙니다"
+
+#: catalog/toasting.c:158
+#, c-format
+msgid "shared tables cannot be toasted after initdb"
+msgstr "공유되는 테이블은 initdb 뒤에는 toast 될 수 없습니다"
+
+#: commands/aggregatecmds.c:159
+#, c-format
+msgid "only ordered-set aggregates can be hypothetical"
+msgstr "순서 있는 세트 집계함수만 가설적일 수 있습니다"
+
+#: commands/aggregatecmds.c:184
+#, c-format
+msgid "aggregate attribute \"%s\" not recognized"
+msgstr "\"%s\" 속성을 aggregate에서 알 수 없음"
+
+#: commands/aggregatecmds.c:194
+#, c-format
+msgid "aggregate stype must be specified"
+msgstr "aggregate stype 값을 지정하셔야합니다"
+
+#: commands/aggregatecmds.c:198
+#, c-format
+msgid "aggregate sfunc must be specified"
+msgstr "aggregate sfunc 값을 지정하셔야합니다"
+
+#: commands/aggregatecmds.c:210
+#, c-format
+msgid "aggregate msfunc must be specified when mstype is specified"
+msgstr "mstype 옵션을 사용하면 msfunc 옵션도 함께 지정 해야 함"
+
+#: commands/aggregatecmds.c:214
+#, c-format
+msgid "aggregate minvfunc must be specified when mstype is specified"
+msgstr "mstype 옵션을 사용하면 minvfunc 옵션도 함께 지정 해야 함"
+
+#: commands/aggregatecmds.c:221
+#, c-format
+msgid "aggregate msfunc must not be specified without mstype"
+msgstr "msfunc 옵션은 mstype 옵션과 함께 사용해야 함"
+
+#: commands/aggregatecmds.c:225
+#, c-format
+msgid "aggregate minvfunc must not be specified without mstype"
+msgstr "minvfunc 옵션은 mstype 옵션과 함께 사용해야 함"
+
+#: commands/aggregatecmds.c:229
+#, c-format
+msgid "aggregate mfinalfunc must not be specified without mstype"
+msgstr "mfinalfunc 옵션은 mstype 옵션과 함께 사용해야 함"
+
+#: commands/aggregatecmds.c:233
+#, c-format
+msgid "aggregate msspace must not be specified without mstype"
+msgstr "msspace 옵션은 mstype 옵션과 함께 사용해야 함"
+
+#: commands/aggregatecmds.c:237
+#, c-format
+msgid "aggregate minitcond must not be specified without mstype"
+msgstr "minitcond 옵션은 mstype 옵션과 함께 사용해야 함"
+
+#: commands/aggregatecmds.c:257
+#, c-format
+msgid "aggregate input type must be specified"
+msgstr "aggregate 입력 자료형을 지정해야 합니다"
+
+#: commands/aggregatecmds.c:287
+#, c-format
+msgid "basetype is redundant with aggregate input type specification"
+msgstr "집계 입력 형식 지정에서 basetype이 중복됨"
+
+#: commands/aggregatecmds.c:328 commands/aggregatecmds.c:369
+#, c-format
+msgid "aggregate transition data type cannot be %s"
+msgstr "%s 자료형은 aggregate transition 자료형으로 사용할 수 없습니다"
+
+#: commands/aggregatecmds.c:340
+#, c-format
+msgid ""
+"serialization functions may be specified only when the aggregate transition "
+"data type is %s"
+msgstr ""
+
+#: commands/aggregatecmds.c:350
+#, c-format
+msgid ""
+"must specify both or neither of serialization and deserialization functions"
+msgstr ""
+
+#: commands/aggregatecmds.c:415 commands/functioncmds.c:570
+#, c-format
+msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE"
+msgstr "\"parallel\" 옵션 값은 SAFE, RESTRICTED, UNSAFE 만 지정할 수 있음"
+
+#: commands/alter.c:80 commands/event_trigger.c:231
+#, c-format
+msgid "event trigger \"%s\" already exists"
+msgstr "\"%s\" 이름의 이벤트 트리거가 이미 있음"
+
+#: commands/alter.c:83 commands/foreigncmds.c:597
+#, c-format
+msgid "foreign-data wrapper \"%s\" already exists"
+msgstr "\"%s\" 이름의 외부 자료 래퍼가 이미 있음"
+
+#: commands/alter.c:86 commands/foreigncmds.c:890
+#, c-format
+msgid "server \"%s\" already exists"
+msgstr "\"%s\" 이름의 서버가 이미 있음"
+
+#: commands/alter.c:89 commands/proclang.c:366
+#, c-format
+msgid "language \"%s\" already exists"
+msgstr "\"%s\" 이름의 프로시주얼 언어가 이미 있습니다"
+
+#: commands/alter.c:112
+#, c-format
+msgid "conversion \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 이름의 변환규칙(conversin)이 \"%s\" 스키마에 이미 있습니다"
+
+#: commands/alter.c:116
+#, c-format
+msgid "text search parser \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 전문 검색 파서가 \"%s\" 스키마 안에 이미 있음"
+
+#: commands/alter.c:120
+#, c-format
+msgid "text search dictionary \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 전문 검색 사전이 \"%s\" 스키마 안에 이미 있음"
+
+#: commands/alter.c:124
+#, c-format
+msgid "text search template \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 전문 검색 템플릿이 \"%s\" 스키마 안에 이미 있음"
+
+#: commands/alter.c:128
+#, c-format
+msgid "text search configuration \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 전문 검색 구성이 \"%s\" 스키마 안에 이미 있음"
+
+#: commands/alter.c:202
+#, c-format
+msgid "must be superuser to rename %s"
+msgstr "%s 이름 변경 작업은 슈퍼유저만 할 수 있음"
+
+#: commands/alter.c:655
+#, c-format
+msgid "must be superuser to set schema of %s"
+msgstr "%s의 스키마 지정은 슈퍼유져여야합니다"
+
+#: commands/amcmds.c:58
+#, c-format
+msgid "permission denied to create access method \"%s\""
+msgstr "\"%s\" 접근 방법을 만들 권한이 없습니다."
+
+#: commands/amcmds.c:60
+#, c-format
+msgid "Must be superuser to create an access method."
+msgstr "슈퍼유저만 접근 방법을 만들 수 있습니다."
+
+#: commands/amcmds.c:68
+#, c-format
+msgid "access method \"%s\" already exists"
+msgstr "\"%s\" 이름의 인덱스 접근 방법이 이미 있습니다."
+
+#: commands/amcmds.c:124
+#, c-format
+msgid "must be superuser to drop access methods"
+msgstr "접근 방법은 슈퍼유저만 삭제할 수 있습니다."
+
+#: commands/amcmds.c:175 commands/indexcmds.c:164 commands/indexcmds.c:496
+#: commands/opclasscmds.c:365 commands/opclasscmds.c:790
+#, c-format
+msgid "access method \"%s\" does not exist"
+msgstr "\"%s\" 인덱스 접근 방법이 없습니다"
+
+#: commands/amcmds.c:251
+#, c-format
+msgid "handler function is not specified"
+msgstr "핸들러 함수 부분이 빠졌습니다"
+
+#: commands/amcmds.c:263 commands/event_trigger.c:240
+#: commands/foreigncmds.c:489 commands/proclang.c:117 commands/proclang.c:288
+#: commands/trigger.c:441 parser/parse_clause.c:761
+#, c-format
+msgid "function %s must return type %s"
+msgstr "%s 함수는 %s 자료형을 반환해야 함"
+
+#: commands/analyze.c:145
+#, c-format
+msgid "skipping analyze of \"%s\" --- lock not available"
+msgstr "\"%s\" 분석 건너뜀 --- 잠글 수 없음"
+
+#: commands/analyze.c:162
+#, c-format
+msgid "skipping \"%s\" --- only superuser can analyze it"
+msgstr "\"%s\" 분석 건너뜀 --- 슈퍼유저만 분석할 수 있음"
+
+#: commands/analyze.c:166
+#, c-format
+msgid "skipping \"%s\" --- only superuser or database owner can analyze it"
+msgstr ""
+"\"%s\" 분석 건너뜀 --- 슈퍼유저 또는 데이터베이스 소유주만 분석할 수 있음"
+
+#: commands/analyze.c:170
+#, c-format
+msgid "skipping \"%s\" --- only table or database owner can analyze it"
+msgstr "\"%s\" 건너뜀 --- 테이블이나 데이터베이스 소유주만이 분석할 수 있음"
+
+#: commands/analyze.c:230
+#, c-format
+msgid "skipping \"%s\" --- cannot analyze this foreign table"
+msgstr "\"%s\" 건너뜀 --- 외부 테이블은 분석할 수 없음"
+
+#: commands/analyze.c:241
+#, c-format
+msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables"
+msgstr ""
+"\"%s\" 건너뜀 --- 테이블이 아니거나, 특수 시스템 테이블들은 분석할 수 없음"
+
+#: commands/analyze.c:320
+#, c-format
+msgid "analyzing \"%s.%s\" inheritance tree"
+msgstr "\"%s.%s\" 상속 관계 분석중"
+
+#: commands/analyze.c:325
+#, c-format
+msgid "analyzing \"%s.%s\""
+msgstr "\"%s.%s\" 자료 통계 수집 중"
+
+#: commands/analyze.c:650
+#, c-format
+msgid "automatic analyze of table \"%s.%s.%s\" system usage: %s"
+msgstr "\"%s.%s.%s\" 테이블의 시스템 사용 자동 분석: %s"
+
+#: commands/analyze.c:1204
+#, c-format
+msgid ""
+"\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead "
+"rows; %d rows in sample, %.0f estimated total rows"
+msgstr ""
+"\"%s\": 탐색한 페이지: %d, 전체페이지: %u, 실자료: %.0f개, 쓰레기자료: %.0f"
+"개; 표본 추출 자료: %d개, 예상한 총 자료: %.0f개"
+
+#: commands/analyze.c:1283
+#, c-format
+msgid ""
+"skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree "
+"contains no child tables"
+msgstr ""
+"\"%s.%s\" 상속 나무의 통계 수집 건너뜀 --- 이 상속 나무에는 하위 테이블이 없"
+"음"
+
+#: commands/analyze.c:1372
+#, c-format
+msgid ""
+"skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree "
+"contains no analyzable child tables"
+msgstr ""
+"\"%s.%s\" 상속 나무의 통계 수집 건너뜀 --- 이 상속 나무에는 통계 수집할 하위 "
+"테이블이 없음"
+
+#: commands/analyze.c:1420 commands/tablecmds.c:8079 executor/execQual.c:2927
+msgid "could not convert row type"
+msgstr "로우 자료형을 변환 할 수 없음"
+
+#: commands/async.c:555
+#, c-format
+msgid "channel name cannot be empty"
+msgstr "채널 이름은 비워둘 수 없음"
+
+#: commands/async.c:560
+#, c-format
+msgid "channel name too long"
+msgstr "채널 이름이 너무 긺"
+
+# # nonun 부분 begin
+#: commands/async.c:567
+#, c-format
+msgid "payload string too long"
+msgstr "payload 문자열이 너무 긺"
+
+#: commands/async.c:753
+#, c-format
+msgid ""
+"cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY"
+msgstr ""
+"LISTEN, UNLISTEN 또는 NOTIFY 옵션으로 실행된 트랜잭션을 PREPARE할 수 없음"
+
+#: commands/async.c:856
+#, c-format
+msgid "too many notifications in the NOTIFY queue"
+msgstr "NOTIFY 큐에 너무 많은 알림이 있습니다"
+
+#: commands/async.c:1486
+#, c-format
+msgid "NOTIFY queue is %.0f%% full"
+msgstr "NOTIFY 큐 사용률: %.0f%%"
+
+#: commands/async.c:1488
+#, c-format
+msgid ""
+"The server process with PID %d is among those with the oldest transactions."
+msgstr "%d PID 서버 프로세스가 가장 오래된 트랜잭션을 사용하고 있습니다."
+
+#: commands/async.c:1491
+#, c-format
+msgid ""
+"The NOTIFY queue cannot be emptied until that process ends its current "
+"transaction."
+msgstr ""
+"이 프로세스의 현재 트랜잭션을 종료하지 않으면, NOTIFY 큐를 비울 수 없습니다"
+
+#: commands/cluster.c:129 commands/cluster.c:364
+#, c-format
+msgid "cannot cluster temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블은 cluster 작업을 할 수 없습니다"
+
+#: commands/cluster.c:159
+#, c-format
+msgid "there is no previously clustered index for table \"%s\""
+msgstr "\"%s\" 테이블을 위한 previously clustered 인덱스가 없음"
+
+#: commands/cluster.c:173 commands/tablecmds.c:9383 commands/tablecmds.c:11143
+#, c-format
+msgid "index \"%s\" for table \"%s\" does not exist"
+msgstr "\"%s\" 인덱스는 \"%s\" 테이블에 없음"
+
+#: commands/cluster.c:353
+#, c-format
+msgid "cannot cluster a shared catalog"
+msgstr "공유된 카탈로그는 클러스터 작업을 할 수 없음"
+
+#: commands/cluster.c:368
+#, c-format
+msgid "cannot vacuum temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블은 vacuum 작업을 할 수 없음"
+
+#: commands/cluster.c:431 commands/tablecmds.c:11153
+#, c-format
+msgid "\"%s\" is not an index for table \"%s\""
+msgstr "\"%s\" 객체는 \"%s\" 테이블을 위한 인덱스가 아님"
+
+#: commands/cluster.c:439
+#, c-format
+msgid ""
+"cannot cluster on index \"%s\" because access method does not support "
+"clustering"
+msgstr ""
+"\"%s\" 인덱스는 자료 액세스 방법이 cluster 작업을 할 수 없는 방법입니다."
+
+#: commands/cluster.c:451
+#, c-format
+msgid "cannot cluster on partial index \"%s\""
+msgstr ""
+"\"%s\" 인덱스가 부분인덱스(partial index)라서 cluster 작업을 할 수 없습니다"
+
+#: commands/cluster.c:465
+#, c-format
+msgid "cannot cluster on invalid index \"%s\""
+msgstr "잘못된 \"%s\" 인덱스에 대해 클러스터링할 수 없음"
+
+#: commands/cluster.c:918
+#, c-format
+msgid "clustering \"%s.%s\" using index scan on \"%s\""
+msgstr " \"%s.%s\" 클러스터링 중 (사용 인덱스: \"%s\")"
+
+#: commands/cluster.c:924
+#, c-format
+msgid "clustering \"%s.%s\" using sequential scan and sort"
+msgstr "순차 탐색과 정렬을 이용해서 \"%s.%s\" 객체 클러스터링 중"
+
+#: commands/cluster.c:929 commands/vacuumlazy.c:479
+#, c-format
+msgid "vacuuming \"%s.%s\""
+msgstr "\"%s.%s\" 청소 중"
+
+#: commands/cluster.c:1088
+#, c-format
+msgid ""
+"\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages"
+msgstr ""
+"\"%s\": 삭제가능한 %.0f개, 삭제불가능한 %.0f개의 행 버전을 %u 페이지에서 발견"
+"했음."
+
+#: commands/cluster.c:1092
+#, c-format
+msgid ""
+"%.0f dead row versions cannot be removed yet.\n"
+"%s."
+msgstr ""
+"%.0f 개의 사용하지 않는 로우 버전을 아직 지우지 못했음.\n"
+"%s."
+
+#: commands/collationcmds.c:80
+#, c-format
+msgid "collation attribute \"%s\" not recognized"
+msgstr "\"%s\" 연산자 속성을 처리할 수 없음"
+
+#: commands/collationcmds.c:125
+#, c-format
+msgid "parameter \"lc_collate\" must be specified"
+msgstr "\"lc_collate\" 옵션을 지정해야 함"
+
+#: commands/collationcmds.c:130
+#, c-format
+msgid "parameter \"lc_ctype\" must be specified"
+msgstr "\"lc_ctype\" 옵션을 지정해야 함"
+
+#: commands/collationcmds.c:166
+#, c-format
+msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 정렬규칙(대상 인코딩: \"%s\")이 \"%s\" 스키마 안에 이미 있음"
+
+#: commands/collationcmds.c:177
+#, c-format
+msgid "collation \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 정렬규칙이 \"%s\" 스키마에 이미 있습니다"
+
+#: commands/comment.c:62 commands/dbcommands.c:797 commands/dbcommands.c:962
+#: commands/dbcommands.c:1067 commands/dbcommands.c:1257
+#: commands/dbcommands.c:1477 commands/dbcommands.c:1594
+#: commands/dbcommands.c:2011 utils/init/postinit.c:841
+#: utils/init/postinit.c:943 utils/init/postinit.c:960
+#, c-format
+msgid "database \"%s\" does not exist"
+msgstr "\"%s\" 데이터베이스 없음"
+
+#: commands/comment.c:101 commands/seclabel.c:116 parser/parse_utilcmd.c:753
+#, c-format
+msgid ""
+"\"%s\" is not a table, view, materialized view, composite type, or foreign "
+"table"
+msgstr ""
+"\"%s\" 객체는 테이블도, 뷰도, 구체화된 뷰도, 복합 자료형도, 외부 테이블도 아"
+"닙니다."
+
+#: commands/constraint.c:60 utils/adt/ri_triggers.c:2715
+#, c-format
+msgid "function \"%s\" was not called by trigger manager"
+msgstr "\"%s\" 함수가 트리거 관리자에서 호출되지 않았음"
+
+#: commands/constraint.c:67 utils/adt/ri_triggers.c:2724
+#, c-format
+msgid "function \"%s\" must be fired AFTER ROW"
+msgstr "AFTER ROW에서 \"%s\" 함수를 실행해야 함"
+
+#: commands/constraint.c:81
+#, c-format
+msgid "function \"%s\" must be fired for INSERT or UPDATE"
+msgstr "INSERT 또는 UPDATE에 대해 \"%s\" 함수를 실행해야 함"
+
+#: commands/conversioncmds.c:67
+#, c-format
+msgid "source encoding \"%s\" does not exist"
+msgstr "\"%s\" 원본 인코딩 없음"
+
+#: commands/conversioncmds.c:74
+#, c-format
+msgid "destination encoding \"%s\" does not exist"
+msgstr "\"%s\" 대상 인코딩 없음"
+
+#: commands/conversioncmds.c:88
+#, c-format
+msgid "encoding conversion function %s must return type %s"
+msgstr "%s 인코딩 변환 함수는 %s 형을 반환해야 함"
+
+#: commands/copy.c:362 commands/copy.c:374 commands/copy.c:408
+#: commands/copy.c:420
+#, c-format
+msgid "COPY BINARY is not supported to stdout or from stdin"
+msgstr "COPY BINARY 명령은 stdout, stdin 입출력을 지원하지 않습니다"
+
+#: commands/copy.c:520
+#, c-format
+msgid "could not write to COPY program: %m"
+msgstr "COPY 프로그램으로 파일을 쓸 수 없습니다: %m"
+
+#: commands/copy.c:525
+#, c-format
+msgid "could not write to COPY file: %m"
+msgstr "COPY 파일로로 파일을 쓸 수 없습니다: %m"
+
+#: commands/copy.c:538
+#, c-format
+msgid "connection lost during COPY to stdout"
+msgstr "COPY 명령에서 stdout으로 자료를 내보내는 동안 연결이 끊겼습니다"
+
+#: commands/copy.c:579
+#, c-format
+msgid "could not read from COPY file: %m"
+msgstr "COPY 명령에 사용할 파일을 읽을 수 없습니다: %m"
+
+#: commands/copy.c:595 commands/copy.c:616 commands/copy.c:620
+#: tcop/postgres.c:341 tcop/postgres.c:377 tcop/postgres.c:404
+#, c-format
+msgid "unexpected EOF on client connection with an open transaction"
+msgstr "열린 트랜잭션과 함께 클라이언트 연결에서 예상치 않은 EOF 발견됨"
+
+#: commands/copy.c:633
+#, c-format
+msgid "COPY from stdin failed: %s"
+msgstr "COPY 명령에서 stdin으로 자료 가져오기 실패: %s"
+
+#: commands/copy.c:649
+#, c-format
+msgid "unexpected message type 0x%02X during COPY from stdin"
+msgstr ""
+"COPY 명령으로 stdin으로 자료를 가져오는 동안 예상치 않은 메시지 타입 0x%02X "
+"발견됨"
+
+#: commands/copy.c:806
+#, c-format
+msgid "must be superuser to COPY to or from an external program"
+msgstr "외부 프로그램을 이용하는 COPY 작업은 슈퍼유저만 허용합니다."
+
+#: commands/copy.c:807 commands/copy.c:813
+#, c-format
+msgid ""
+"Anyone can COPY to stdout or from stdin. psql's \\copy command also works "
+"for anyone."
+msgstr "일반 사용자인데, 이 작업이 필요하면, psql의 \\copy 명령을 이용하세요"
+
+#: commands/copy.c:812
+#, c-format
+msgid "must be superuser to COPY to or from a file"
+msgstr ""
+"COPY 명령으로 자료를 파일로 내보내거나 파일에서 가져오려면, superuser여야만 "
+"합니다"
+
+#: commands/copy.c:879
+#, c-format
+msgid "COPY FROM not supported with row-level security"
+msgstr "로우 단위 보안 기능으로 COPY FROM 명령을 사용할 수 없음"
+
+#: commands/copy.c:880
+#, c-format
+msgid "Use INSERT statements instead."
+msgstr "대신에 INSERT 구문을 사용하십시오."
+
+#: commands/copy.c:1058
+#, c-format
+msgid "COPY format \"%s\" not recognized"
+msgstr "\"%s\" COPY 양식은 지원하지 않음"
+
+#: commands/copy.c:1129 commands/copy.c:1143 commands/copy.c:1157
+#: commands/copy.c:1177
+#, c-format
+msgid "argument to option \"%s\" must be a list of column names"
+msgstr "\"%s\" 옵션에 대한 인자는 칼럼 이름 목록이어야 합니다."
+
+#: commands/copy.c:1190
+#, c-format
+msgid "argument to option \"%s\" must be a valid encoding name"
+msgstr "\"%s\" 옵션에 대한 인자는 인코딩 이름이어야 합니다."
+
+#: commands/copy.c:1196 commands/dbcommands.c:232 commands/dbcommands.c:1427
+#, c-format
+msgid "option \"%s\" not recognized"
+msgstr "\"%s\" 옵션은 타당하지 않습니다."
+
+#: commands/copy.c:1207
+#, c-format
+msgid "cannot specify DELIMITER in BINARY mode"
+msgstr "BINARY 모드에서는 DELIMITER 값을 지정할 수 없음"
+
+#: commands/copy.c:1212
+#, c-format
+msgid "cannot specify NULL in BINARY mode"
+msgstr "BINARY 모드에서는 NULL 값을 지정할 수 없음"
+
+#: commands/copy.c:1234
+#, c-format
+msgid "COPY delimiter must be a single one-byte character"
+msgstr "COPY 구분자는 1바이트의 단일 문자여야 함"
+
+#: commands/copy.c:1241
+#, c-format
+msgid "COPY delimiter cannot be newline or carriage return"
+msgstr "COPY 명령에서 사용할 칼럼 구분자로 줄바꿈 문자들을 사용할 수 없습니다"
+
+#: commands/copy.c:1247
+#, c-format
+msgid "COPY null representation cannot use newline or carriage return"
+msgstr "COPY null 표현에서 줄바꿈 또는 캐리지 리턴을 사용할 수 없음"
+
+#: commands/copy.c:1264
+#, c-format
+msgid "COPY delimiter cannot be \"%s\""
+msgstr "COPY 구분자는 \"%s\"일 수 없음"
+
+#: commands/copy.c:1270
+#, c-format
+msgid "COPY HEADER available only in CSV mode"
+msgstr "COPY HEADER는 CSV 모드에서만 사용할 수 있음"
+
+#: commands/copy.c:1276
+#, c-format
+msgid "COPY quote available only in CSV mode"
+msgstr "COPY 따옴표는 CSV 모드에서만 사용할 수 있음"
+
+#: commands/copy.c:1281
+#, c-format
+msgid "COPY quote must be a single one-byte character"
+msgstr "COPY 따옴표는 1바이트의 단일 문자여야 함"
+
+#: commands/copy.c:1286
+#, c-format
+msgid "COPY delimiter and quote must be different"
+msgstr "COPY 구분자 및 따옴표는 서로 달라야 함"
+
+#: commands/copy.c:1292
+#, c-format
+msgid "COPY escape available only in CSV mode"
+msgstr "COPY 이스케이프는 CSV 모드에서만 사용할 수 있음"
+
+#: commands/copy.c:1297
+#, c-format
+msgid "COPY escape must be a single one-byte character"
+msgstr "COPY 이스케이프는 1바이트의 단일 문자여야 함"
+
+#: commands/copy.c:1303
+#, c-format
+msgid "COPY force quote available only in CSV mode"
+msgstr "COPY force quote는 CSV 모드에서만 사용할 수 있음"
+
+#: commands/copy.c:1307
+#, c-format
+msgid "COPY force quote only available using COPY TO"
+msgstr "COPY force quote는 COPY TO에서만 사용할 수 있음"
+
+#: commands/copy.c:1313
+#, c-format
+msgid "COPY force not null available only in CSV mode"
+msgstr "COPY force not null은 CSV 모드에서만 사용할 수 있음"
+
+#: commands/copy.c:1317
+#, c-format
+msgid "COPY force not null only available using COPY FROM"
+msgstr "COPY force not null은 COPY FROM에서만 사용할 수 있음"
+
+#: commands/copy.c:1323
+#, c-format
+msgid "COPY force null available only in CSV mode"
+msgstr "COPY force null은 CSV 모드에서만 사용할 수 있음"
+
+#: commands/copy.c:1328
+#, c-format
+msgid "COPY force null only available using COPY FROM"
+msgstr "COPY force null은 COPY FROM에서만 사용할 수 있음"
+
+#: commands/copy.c:1334
+#, c-format
+msgid "COPY delimiter must not appear in the NULL specification"
+msgstr "COPY 구분자는 NULL 지정에 표시되지 않아야 함"
+
+#: commands/copy.c:1341
+#, c-format
+msgid "CSV quote character must not appear in the NULL specification"
+msgstr "CSV 따옴표는 NULL 지정에 표시되지 않아야 함"
+
+#: commands/copy.c:1402
+#, c-format
+msgid "table \"%s\" does not have OIDs"
+msgstr ""
+"\"%s\" 테이블은 without oids 속성으로 만들어졌기에 OID 값을 구할 수 없습니다"
+
+#: commands/copy.c:1419
+#, c-format
+msgid "COPY (query) WITH OIDS is not supported"
+msgstr "COPY (쿼리) WITH OIDS 지원하지 않음"
+
+#: commands/copy.c:1439
+#, c-format
+msgid "DO INSTEAD NOTHING rules are not supported for COPY"
+msgstr "DO INSTEAD NOTHING 룰(rule)은 COPY 구문에서 지원하지 않습니다."
+
+#: commands/copy.c:1453
+#, c-format
+msgid "conditional DO INSTEAD rules are not supported for COPY"
+msgstr "선택적 DO INSTEAD 룰은 COPY 구문에서 지원하지 않음"
+
+#: commands/copy.c:1457
+#, c-format
+msgid "DO ALSO rules are not supported for the COPY"
+msgstr "DO ALSO 룰(rule)은 COPY 구문에서 지원하지 않습니다."
+
+#: commands/copy.c:1462
+#, c-format
+msgid "multi-statement DO INSTEAD rules are not supported for COPY"
+msgstr "다중 구문 DO INSTEAD 룰은 COPY 구문에서 지원하지 않음"
+
+#: commands/copy.c:1472
+#, c-format
+msgid "COPY (SELECT INTO) is not supported"
+msgstr "COPY (SELECT INTO) 지원하지 않음"
+
+#: commands/copy.c:1489
+#, c-format
+msgid "COPY query must have a RETURNING clause"
+msgstr "COPY 쿼리는 RETURNING 절이 있어야 합니다"
+
+#: commands/copy.c:1517
+#, c-format
+msgid "relation referenced by COPY statement has changed"
+msgstr "COPY 문에 의해 참조된 릴레이션이 변경 되었음"
+
+#: commands/copy.c:1575
+#, c-format
+msgid "FORCE_QUOTE column \"%s\" not referenced by COPY"
+msgstr "\"%s\" FORCE_QUOTE 칼럼은 COPY에서 참조되지 않음"
+
+#: commands/copy.c:1597
+#, c-format
+msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY"
+msgstr "\"%s\" FORCE_NOT_NULL 칼럼은 COPY에서 참조되지 않음"
+
+#: commands/copy.c:1619
+#, c-format
+msgid "FORCE_NULL column \"%s\" not referenced by COPY"
+msgstr "\"%s\" FORCE_NULL 열은 COPY에서 참조되지 않음"
+
+#: commands/copy.c:1684
+#, c-format
+msgid "could not close pipe to external command: %m"
+msgstr "외부 명령으로 파이프를 닫을 수 없음: %m"
+
+#: commands/copy.c:1688
+#, c-format
+msgid "program \"%s\" failed"
+msgstr "\"%s\" 프로그램 실패"
+
+#: commands/copy.c:1738
+#, c-format
+msgid "cannot copy from view \"%s\""
+msgstr "\"%s\" 이름의 객체는 뷰(view)입니다. 자료를 내보낼 수 없습니다"
+
+#: commands/copy.c:1740 commands/copy.c:1746 commands/copy.c:1752
+#, c-format
+msgid "Try the COPY (SELECT ...) TO variant."
+msgstr "COPY (SELECT ...) TO 변형을 시도하십시오."
+
+#: commands/copy.c:1744
+#, c-format
+msgid "cannot copy from materialized view \"%s\""
+msgstr "\"%s\" 이름의 객체는 구체화된 뷰입니다. 자료를 내보낼 수 없습니다"
+
+#: commands/copy.c:1750
+#, c-format
+msgid "cannot copy from foreign table \"%s\""
+msgstr "\"%s\" 이름의 객체는 외부 테이블입니다. 자료를 내보낼 수 없습니다"
+
+#: commands/copy.c:1756
+#, c-format
+msgid "cannot copy from sequence \"%s\""
+msgstr "\"%s\" 이름의 객체는 시퀀스입니다. 자료를 내보낼 수 없습니다"
+
+#: commands/copy.c:1761
+#, c-format
+msgid "cannot copy from non-table relation \"%s\""
+msgstr ""
+"\"%s\" 객체는 테이블이 아닌 릴레이션(relation)이기에 자료를 내보낼 수 없습니"
+"다"
+
+#: commands/copy.c:1786 commands/copy.c:2822
+#, c-format
+msgid "could not execute command \"%s\": %m"
+msgstr "\"%s\" 명령을 실행할 수 없음: %m"
+
+#: commands/copy.c:1801
+#, c-format
+msgid "relative path not allowed for COPY to file"
+msgstr "COPY 명령에 사용할 파일 이름으로 상대경로는 사용할 수 없습니다"
+
+#: commands/copy.c:1809
+#, c-format
+msgid "could not open file \"%s\" for writing: %m"
+msgstr "\"%s\" 파일 열기 실패: %m"
+
+#: commands/copy.c:1821 commands/copy.c:2845
+#, c-format
+msgid "\"%s\" is a directory"
+msgstr "\"%s\" 디렉터리임"
+
+#: commands/copy.c:2144
+#, c-format
+msgid "COPY %s, line %d, column %s"
+msgstr "%s 복사, %d번째 줄, %s 열"
+
+#: commands/copy.c:2148 commands/copy.c:2195
+#, c-format
+msgid "COPY %s, line %d"
+msgstr "%s 복사, %d번째 줄"
+
+#: commands/copy.c:2159
+#, c-format
+msgid "COPY %s, line %d, column %s: \"%s\""
+msgstr "%s 복사, %d번째 줄, %s 열: \"%s\""
+
+#: commands/copy.c:2167
+#, c-format
+msgid "COPY %s, line %d, column %s: null input"
+msgstr "COPY %s, %d행, %s 열: null 입력"
+
+#: commands/copy.c:2189
+#, c-format
+msgid "COPY %s, line %d: \"%s\""
+msgstr "%s 복사, %d번째 줄: \"%s\""
+
+#: commands/copy.c:2273
+#, c-format
+msgid "cannot copy to view \"%s\""
+msgstr "\"%s\" 뷰(view)에 복사할 수 없음"
+
+#: commands/copy.c:2278
+#, c-format
+msgid "cannot copy to materialized view \"%s\""
+msgstr "\"%s\" 구체화된 뷰(view)에 복사할 수 없음"
+
+#: commands/copy.c:2283
+#, c-format
+msgid "cannot copy to foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블에 복사할 수 없음"
+
+#: commands/copy.c:2288
+#, c-format
+msgid "cannot copy to sequence \"%s\""
+msgstr "\"%s\" 시퀀스에 복사할 수 없음"
+
+#: commands/copy.c:2293
+#, c-format
+msgid "cannot copy to non-table relation \"%s\""
+msgstr "\"%s\" 객체는 테이블이 아닌 릴레이션(relation)이기에 복사할 수 없음"
+
+#: commands/copy.c:2356
+#, c-format
+msgid "cannot perform FREEZE because of prior transaction activity"
+msgstr ""
+"먼저 시작한 다른 트랜잭션이 아직 활성 상태여서 FREEZE 작업은 진행할 수 없음"
+
+#: commands/copy.c:2362
+#, c-format
+msgid ""
+"cannot perform FREEZE because the table was not created or truncated in the "
+"current subtransaction"
+msgstr ""
+"현재 하위 트랜잭션에서 만들어지거나 비워진 테이블이 아니기 때문에 FREEZE 작업"
+"을 할 수 없음"
+
+#: commands/copy.c:2865
+#, c-format
+msgid "COPY file signature not recognized"
+msgstr "file signature 복사는 인식되지 않았음"
+
+#: commands/copy.c:2870
+#, c-format
+msgid "invalid COPY file header (missing flags)"
+msgstr "COPY 명령에서 잘못된 파일 헤더를 사용함(플래그 빠졌음)"
+
+#: commands/copy.c:2876
+#, c-format
+msgid "unrecognized critical flags in COPY file header"
+msgstr "_^_ 복사 파일 헤더안에 critical flags 값들을 인식할 수 없음"
+
+#: commands/copy.c:2882
+#, c-format
+msgid "invalid COPY file header (missing length)"
+msgstr "복사 파일 헤더에 length 값이 빠졌음"
+
+#: commands/copy.c:2889
+#, c-format
+msgid "invalid COPY file header (wrong length)"
+msgstr "복사 파일 헤더에 length 값이 잘못되었음"
+
+#: commands/copy.c:3022 commands/copy.c:3729 commands/copy.c:3959
+#, c-format
+msgid "extra data after last expected column"
+msgstr "마지막 열을 초과해서 또 다른 데이터가 있음"
+
+#: commands/copy.c:3032
+#, c-format
+msgid "missing data for OID column"
+msgstr "OID 열에 자료가 없음"
+
+#: commands/copy.c:3038
+#, c-format
+msgid "null OID in COPY data"
+msgstr "복사 데이터에 null OID 값이 있음"
+
+#: commands/copy.c:3048 commands/copy.c:3171
+#, c-format
+msgid "invalid OID in COPY data"
+msgstr "복사 데이터에 잘못된 OID 값이 있음"
+
+#: commands/copy.c:3063
+#, c-format
+msgid "missing data for column \"%s\""
+msgstr "\"%s\" 열의 자료가 빠졌음"
+
+#: commands/copy.c:3146
+#, c-format
+msgid "received copy data after EOF marker"
+msgstr "EOF 표시 뒤에도 복사 데이터를 받았음"
+
+#: commands/copy.c:3153
+#, c-format
+msgid "row field count is %d, expected %d"
+msgstr "행(row) 필드 갯수가 %d 임, 예상값은 %d"
+
+#: commands/copy.c:3493 commands/copy.c:3510
+#, c-format
+msgid "literal carriage return found in data"
+msgstr "데이터에 carriage return 값이 잘못되었음"
+
+#: commands/copy.c:3494 commands/copy.c:3511
+#, c-format
+msgid "unquoted carriage return found in data"
+msgstr "데이터에 carriage return 값 표기가 잘못 되었음"
+
+#: commands/copy.c:3496 commands/copy.c:3513
+#, c-format
+msgid "Use \"\\r\" to represent carriage return."
+msgstr "carriage return값으로 \"\\r\" 문자를 사용하세요"
+
+#: commands/copy.c:3497 commands/copy.c:3514
+#, c-format
+msgid "Use quoted CSV field to represent carriage return."
+msgstr ""
+"carriage return 문자를 그대로 적용하려면, quoted CSV 필드를 사용하세요."
+
+#: commands/copy.c:3526
+#, c-format
+msgid "literal newline found in data"
+msgstr "데이터에 newline 값이 잘못되었음"
+
+#: commands/copy.c:3527
+#, c-format
+msgid "unquoted newline found in data"
+msgstr "데이터에 newline 값이 잘못 되었음"
+
+#: commands/copy.c:3529
+#, c-format
+msgid "Use \"\\n\" to represent newline."
+msgstr "newline 값으로 \"\\n\" 문자를 사용하세요"
+
+#: commands/copy.c:3530
+#, c-format
+msgid "Use quoted CSV field to represent newline."
+msgstr "newline 문자를 그대로 적용하려면, quoted CSV 필드를 사용하세요."
+
+#: commands/copy.c:3576 commands/copy.c:3612
+#, c-format
+msgid "end-of-copy marker does not match previous newline style"
+msgstr "end-of-copy 마크는 이전 newline 모양가 틀립니다"
+
+#: commands/copy.c:3585 commands/copy.c:3601
+#, c-format
+msgid "end-of-copy marker corrupt"
+msgstr "end-of-copy 마크가 잘못되었음"
+
+#: commands/copy.c:4043
+#, c-format
+msgid "unterminated CSV quoted field"
+msgstr "종료되지 않은 CSV 따옴표 필드"
+
+#: commands/copy.c:4120 commands/copy.c:4139
+#, c-format
+msgid "unexpected EOF in COPY data"
+msgstr "복사 자료 안에 예상치 않은 EOF 발견"
+
+#: commands/copy.c:4129
+#, c-format
+msgid "invalid field size"
+msgstr "잘못된 필드 크기"
+
+#: commands/copy.c:4152
+#, c-format
+msgid "incorrect binary data format"
+msgstr "잘못된 바이너리 자료 포맷"
+
+#: commands/copy.c:4463 commands/indexcmds.c:1054 commands/tablecmds.c:1464
+#: commands/tablecmds.c:2291 parser/parse_relation.c:3177
+#: parser/parse_relation.c:3197 utils/adt/tsvector_op.c:2559
+#, c-format
+msgid "column \"%s\" does not exist"
+msgstr "\"%s\" 이름의 열이 없습니다"
+
+#: commands/copy.c:4470 commands/tablecmds.c:1490 commands/trigger.c:651
+#: parser/parse_target.c:967 parser/parse_target.c:978
+#, c-format
+msgid "column \"%s\" specified more than once"
+msgstr "\"%s\" 열을 하나 이상 지정했음"
+
+#: commands/createas.c:213 commands/createas.c:509
+#, c-format
+msgid "too many column names were specified"
+msgstr "너무 많은 칼럼 이름을 지정했습니다."
+
+#: commands/createas.c:550
+#, c-format
+msgid "policies not yet implemented for this command"
+msgstr "이 명령을 위한 정책은 아직 구현되어 있지 않습니다"
+
+#: commands/dbcommands.c:226
+#, c-format
+msgid "LOCATION is not supported anymore"
+msgstr "LOCATION 예약어는 이제 더이상 지원하지 않습니다"
+
+#: commands/dbcommands.c:227
+#, c-format
+msgid "Consider using tablespaces instead."
+msgstr "대신에 테이블스페이스를 이용하세요."
+
+#: commands/dbcommands.c:251 utils/adt/ascii.c:144
+#, c-format
+msgid "%d is not a valid encoding code"
+msgstr "%d 값은 잘못된 인코딩 코드임"
+
+#: commands/dbcommands.c:261 utils/adt/ascii.c:126
+#, c-format
+msgid "%s is not a valid encoding name"
+msgstr "%s 이름은 잘못된 인코딩 이름임"
+
+#: commands/dbcommands.c:279 commands/dbcommands.c:1458 commands/user.c:272
+#: commands/user.c:650
+#, c-format
+msgid "invalid connection limit: %d"
+msgstr "잘못된 연결 제한: %d"
+
+#: commands/dbcommands.c:298
+#, c-format
+msgid "permission denied to create database"
+msgstr "데이터베이스를 만들 권한이 없음"
+
+#: commands/dbcommands.c:321
+#, c-format
+msgid "template database \"%s\" does not exist"
+msgstr "\"%s\" 템플릿 데이터베이스 없음"
+
+#: commands/dbcommands.c:333
+#, c-format
+msgid "permission denied to copy database \"%s\""
+msgstr "\"%s\" 데이터베이스를 복사할 권한이 없음"
+
+#: commands/dbcommands.c:349
+#, c-format
+msgid "invalid server encoding %d"
+msgstr "잘못된 서버 인코딩 %d"
+
+#: commands/dbcommands.c:355 commands/dbcommands.c:360
+#, c-format
+msgid "invalid locale name: \"%s\""
+msgstr "\"%s\" 로케일 이름이 잘못됨"
+
+#: commands/dbcommands.c:380
+#, c-format
+msgid ""
+"new encoding (%s) is incompatible with the encoding of the template database "
+"(%s)"
+msgstr "새 인코딩(%s)이 템플릿 데이터베이스의 인코딩(%s)과 호환되지 않음"
+
+#: commands/dbcommands.c:383
+#, c-format
+msgid ""
+"Use the same encoding as in the template database, or use template0 as "
+"template."
+msgstr ""
+"템플릿 데이터베이스와 동일한 인코딩을 사용하거나 template0을 템플릿으로 사용"
+"하십시오."
+
+#: commands/dbcommands.c:388
+#, c-format
+msgid ""
+"new collation (%s) is incompatible with the collation of the template "
+"database (%s)"
+msgstr ""
+"새 데이터 정렬 규칙 (%s)이 템플릿 데이터베이스의 데이터 정렬 규칙(%s)과 호환"
+"되지 않음"
+
+#: commands/dbcommands.c:390
+#, c-format
+msgid ""
+"Use the same collation as in the template database, or use template0 as "
+"template."
+msgstr ""
+"템플릿 데이터베이스와 동일한 데이터 정렬 규칙을 사용하거나 template0을 템플릿"
+"으로 사용하십시오."
+
+#: commands/dbcommands.c:395
+#, c-format
+msgid ""
+"new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database "
+"(%s)"
+msgstr "새 LC_CTYPE (%s)이 템플릿 데이터베이스의 LC_CTYPE (%s)과 호환되지 않음"
+
+#: commands/dbcommands.c:397
+#, c-format
+msgid ""
+"Use the same LC_CTYPE as in the template database, or use template0 as "
+"template."
+msgstr ""
+"템플릿 데이터베이스와 동일한 LC_CTYPE을 사용하거나 template0을 템플릿으로 사"
+"용하십시오."
+
+#: commands/dbcommands.c:419 commands/dbcommands.c:1113
+#, c-format
+msgid "pg_global cannot be used as default tablespace"
+msgstr "pg_global을 기본 테이블스페이스로 사용할 수 없음"
+
+#: commands/dbcommands.c:445
+#, c-format
+msgid "cannot assign new default tablespace \"%s\""
+msgstr "새 \"%s\" 테이블스페이스를 지정할 수 없습니다."
+
+#: commands/dbcommands.c:447
+#, c-format
+msgid ""
+"There is a conflict because database \"%s\" already has some tables in this "
+"tablespace."
+msgstr ""
+"\"%s\" 데이터베이스 소속 몇몇 테이블들이 이 테이블스페이스안에 있어서 충돌이 "
+"일어납니다."
+
+#: commands/dbcommands.c:467 commands/dbcommands.c:982
+#, c-format
+msgid "database \"%s\" already exists"
+msgstr "\"%s\" 이름의 데이터베이스는 이미 있음"
+
+#: commands/dbcommands.c:481
+#, c-format
+msgid "source database \"%s\" is being accessed by other users"
+msgstr "\"%s\" 원본 데이터베이스를 다른 사용자가 액세스하기 시작했습니다"
+
+#: commands/dbcommands.c:726 commands/dbcommands.c:741
+#, c-format
+msgid "encoding \"%s\" does not match locale \"%s\""
+msgstr "\"%s\" 인코딩은 \"%s\" 로케일과 일치하지 않음"
+
+#: commands/dbcommands.c:729
+#, c-format
+msgid "The chosen LC_CTYPE setting requires encoding \"%s\"."
+msgstr "선택한 LC_CTYPE 설정에는 \"%s\" 인코딩이 필요합니다."
+
+#: commands/dbcommands.c:744
+#, c-format
+msgid "The chosen LC_COLLATE setting requires encoding \"%s\"."
+msgstr "선택한 LC_COLLATE 설정에는 \"%s\" 인코딩이 필요합니다."
+
+#: commands/dbcommands.c:804
+#, c-format
+msgid "database \"%s\" does not exist, skipping"
+msgstr "\"%s\" 데이터베이스 없음, 건너 뜀"
+
+#: commands/dbcommands.c:828
+#, c-format
+msgid "cannot drop a template database"
+msgstr "템플릿 데이터베이스는 삭제할 수 없습니다"
+
+#: commands/dbcommands.c:834
+#, c-format
+msgid "cannot drop the currently open database"
+msgstr "현재 열려 있는 데이터베이스는 삭제할 수 없습니다"
+
+#: commands/dbcommands.c:844
+#, c-format
+msgid "database \"%s\" is used by a logical replication slot"
+msgstr "\"%s\" 데이터베이스가 논리 복제 슬롯에의해 사용되었음"
+
+#: commands/dbcommands.c:846
+#, c-format
+msgid "There is %d slot, %d of them active."
+msgid_plural "There are %d slots, %d of them active."
+msgstr[0] ""
+
+#: commands/dbcommands.c:860 commands/dbcommands.c:1004
+#: commands/dbcommands.c:1135
+#, c-format
+msgid "database \"%s\" is being accessed by other users"
+msgstr "\"%s\" 데이터베이스를 다른 사용자가 액세스하기 시작했습니다"
+
+#: commands/dbcommands.c:973
+#, c-format
+msgid "permission denied to rename database"
+msgstr "데이터베이스 이름을 바꿀 권한이 없습니다"
+
+#: commands/dbcommands.c:993
+#, c-format
+msgid "current database cannot be renamed"
+msgstr "현재 데이터베이스의 이름을 바꿀 수 없음"
+
+#: commands/dbcommands.c:1091
+#, c-format
+msgid "cannot change the tablespace of the currently open database"
+msgstr "현재 열려 있는 데이터베이스의 테이블스페이스를 바꿀 수 없음"
+
+#: commands/dbcommands.c:1194
+#, c-format
+msgid "some relations of database \"%s\" are already in tablespace \"%s\""
+msgstr ""
+"\"%s\" 데이터베이스의 일부 릴레이션들이 \"%s\" 테이블스페이스에 이미 있음"
+
+#: commands/dbcommands.c:1196
+#, c-format
+msgid ""
+"You must move them back to the database's default tablespace before using "
+"this command."
+msgstr ""
+"이 명령을 사용하기 전에 데이터베이스의 기본 테이블스페이스로 다시 이동해야 합"
+"니다."
+
+#: commands/dbcommands.c:1325 commands/dbcommands.c:1868
+#: commands/dbcommands.c:2072 commands/dbcommands.c:2120
+#: commands/tablespace.c:606
+#, c-format
+msgid "some useless files may be left behind in old database directory \"%s\""
+msgstr ""
+"불필요한 일부 파일이 이전 데이터베이스 디렉터리 \"%s\"에 남아 있을 수 있음"
+
+#: commands/dbcommands.c:1440
+#, c-format
+msgid "option \"%s\" cannot be specified with other options"
+msgstr "\"%s\" 옵션은 다른 옵션들과 함께 사용할 수 없습니다."
+
+#: commands/dbcommands.c:1494
+#, c-format
+msgid "cannot disallow connections for current database"
+msgstr "현재 데이터베이스 연결을 허용하지 않습니다."
+
+#: commands/dbcommands.c:1634
+#, c-format
+msgid "permission denied to change owner of database"
+msgstr "데이터베이스 소유주를 바꿀 권한이 없습니다"
+
+#: commands/dbcommands.c:1955
+#, c-format
+msgid ""
+"There are %d other session(s) and %d prepared transaction(s) using the "
+"database."
+msgstr ""
+"데이터베이스를 사용하는 %d개의 다른 세션과 %d개의 준비된 트랜잭션이 있습니다."
+
+#: commands/dbcommands.c:1958
+#, c-format
+msgid "There is %d other session using the database."
+msgid_plural "There are %d other sessions using the database."
+msgstr[0] "데이터베이스를 사용하는 %d개의 다른 세션이 있습니다."
+
+#: commands/dbcommands.c:1963
+#, c-format
+msgid "There is %d prepared transaction using the database."
+msgid_plural "There are %d prepared transactions using the database."
+msgstr[0] "데이터베이스를 사용하는 %d개의 준비된 트랜잭션이 있습니다."
+
+#: commands/define.c:54 commands/define.c:228 commands/define.c:260
+#: commands/define.c:288
+#, c-format
+msgid "%s requires a parameter"
+msgstr "%s 매개 변수를 필요로 함"
+
+#: commands/define.c:90 commands/define.c:101 commands/define.c:195
+#: commands/define.c:213
+#, c-format
+msgid "%s requires a numeric value"
+msgstr "%s 숫자값을 필요로 함"
+
+#: commands/define.c:157
+#, c-format
+msgid "%s requires a Boolean value"
+msgstr "%s 값은 boolean 값이어야합니다."
+
+#: commands/define.c:171 commands/define.c:180 commands/define.c:297
+#, c-format
+msgid "%s requires an integer value"
+msgstr "%s 하나의 정수값이 필요함"
+
+#: commands/define.c:242
+#, c-format
+msgid "argument of %s must be a name"
+msgstr "%s의 인자는 이름이어야 합니다"
+
+#: commands/define.c:272
+#, c-format
+msgid "argument of %s must be a type name"
+msgstr "%s의 인자는 자료형 이름이어야합니다"
+
+#: commands/define.c:318
+#, c-format
+msgid "invalid argument for %s: \"%s\""
+msgstr "%s의 잘못된 인자: \"%s\""
+
+#: commands/dropcmds.c:112 commands/functioncmds.c:1203
+#: utils/adt/ruleutils.c:2080
+#, c-format
+msgid "\"%s\" is an aggregate function"
+msgstr "\"%s\" 함수는 집계 함수입니다"
+
+#: commands/dropcmds.c:114
+#, c-format
+msgid "Use DROP AGGREGATE to drop aggregate functions."
+msgstr "집계 함수는 DROP AGGREGATE 명령으로 삭제할 수 있습니다"
+
+#: commands/dropcmds.c:165 commands/sequence.c:424 commands/tablecmds.c:2378
+#: commands/tablecmds.c:2529 commands/tablecmds.c:2571
+#: commands/tablecmds.c:11524 tcop/utility.c:1119
+#, c-format
+msgid "relation \"%s\" does not exist, skipping"
+msgstr "\"%s\" 릴레이션 없음, 건너뜀"
+
+#: commands/dropcmds.c:195 commands/dropcmds.c:296 commands/tablecmds.c:746
+#, c-format
+msgid "schema \"%s\" does not exist, skipping"
+msgstr "\"%s\" 스키마(schema) 없음, 건너뜀"
+
+#: commands/dropcmds.c:237 commands/dropcmds.c:276 commands/tablecmds.c:247
+#, c-format
+msgid "type \"%s\" does not exist, skipping"
+msgstr "\"%s\" 자료형 없음, 건너뜀"
+
+#: commands/dropcmds.c:266
+#, c-format
+msgid "access method \"%s\" does not exist, skipping"
+msgstr "\"%s\" 인덱스 접근 방법 없음, 건너뜀"
+
+#: commands/dropcmds.c:284
+#, c-format
+msgid "collation \"%s\" does not exist, skipping"
+msgstr "\"%s\" 정렬규칙 없음, 건너뜀"
+
+#: commands/dropcmds.c:291
+#, c-format
+msgid "conversion \"%s\" does not exist, skipping"
+msgstr "\"%s\" 문자코드변환규칙(conversion) 없음, 건너뜀"
+
+#: commands/dropcmds.c:302
+#, c-format
+msgid "text search parser \"%s\" does not exist, skipping"
+msgstr "\"%s\" 전문 검색 파서가 없음, 건너뜀"
+
+#: commands/dropcmds.c:309
+#, c-format
+msgid "text search dictionary \"%s\" does not exist, skipping"
+msgstr "\"%s\" 전문 검색 사전이 없음, 건너뜀"
+
+#: commands/dropcmds.c:316
+#, c-format
+msgid "text search template \"%s\" does not exist, skipping"
+msgstr "\"%s\" 전문 검색 템플릿이 없음, 건너뜀"
+
+#: commands/dropcmds.c:323
+#, c-format
+msgid "text search configuration \"%s\" does not exist, skipping"
+msgstr "\"%s\" 전문 검색 구성이 없음, 건너뜀"
+
+#: commands/dropcmds.c:328
+#, c-format
+msgid "extension \"%s\" does not exist, skipping"
+msgstr "\"%s\" 확장 모듈 없음, 건너 뜀"
+
+#: commands/dropcmds.c:335
+#, c-format
+msgid "function %s(%s) does not exist, skipping"
+msgstr "%s(%s) 함수가 없음, 건너뜀"
+
+#: commands/dropcmds.c:344
+#, c-format
+msgid "aggregate %s(%s) does not exist, skipping"
+msgstr "%s(%s) 집계 함수 없음, 건너뜀"
+
+#: commands/dropcmds.c:353
+#, c-format
+msgid "operator %s does not exist, skipping"
+msgstr "%s 연산자가 없음, 건너뜀"
+
+#: commands/dropcmds.c:358
+#, c-format
+msgid "language \"%s\" does not exist, skipping"
+msgstr "\"%s\" 프로시주얼 언어 없음, 건너뜀"
+
+#: commands/dropcmds.c:367
+#, c-format
+msgid "cast from type %s to type %s does not exist, skipping"
+msgstr "%s 형에서 %s 형으로 바꾸는 형변환 규칙(cast)이 없음, 건너뜀"
+
+#: commands/dropcmds.c:376
+#, c-format
+msgid "transform for type %s language \"%s\" does not exist, skipping"
+msgstr "%s 형변환자 (사용언어 \"%s\") 없음, 건너뜀"
+
+#: commands/dropcmds.c:384
+#, c-format
+msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping"
+msgstr " \"%s\" 트리거가 \"%s\" 릴레이션에 지정된 것이 없음, 건너뜀"
+
+#: commands/dropcmds.c:393
+#, c-format
+msgid "policy \"%s\" for relation \"%s\" does not exist, skipping"
+msgstr " \"%s\" 정책이 \"%s\" 릴레이션에 지정된 것이 없음, 건너뜀"
+
+#: commands/dropcmds.c:400
+#, c-format
+msgid "event trigger \"%s\" does not exist, skipping"
+msgstr "\"%s\" 이벤트 트리거 없음, 건너뜀"
+
+#: commands/dropcmds.c:406
+#, c-format
+msgid "rule \"%s\" for relation \"%s\" does not exist, skipping"
+msgstr " \"%s\" 룰(rule)이 \"%s\" 릴레이션에 지정된 것이 없음, 건너뜀"
+
+#: commands/dropcmds.c:413
+#, c-format
+msgid "foreign-data wrapper \"%s\" does not exist, skipping"
+msgstr "\"%s\" 외부 자료 래퍼가 없음, 건너뜀"
+
+#: commands/dropcmds.c:417
+#, c-format
+msgid "server \"%s\" does not exist, skipping"
+msgstr "\"%s\" 서버가 없음, 건너뜀"
+
+#: commands/dropcmds.c:426
+#, c-format
+msgid "operator class \"%s\" does not exist for access method \"%s\", skipping"
+msgstr ""
+"\"%s\" 연산자 클래스는 \"%s\" 인덱스 접근 방법에서 사용할 수 없음, 건너뜀"
+
+#: commands/dropcmds.c:438
+#, c-format
+msgid ""
+"operator family \"%s\" does not exist for access method \"%s\", skipping"
+msgstr "\"%s\" 연산자 패밀리(\"%s\" 접근 방법)가 없음, 건너뜀"
+
+#: commands/event_trigger.c:182
+#, c-format
+msgid "permission denied to create event trigger \"%s\""
+msgstr "\"%s\" 이벤트 트리거를 만들 권한이 없음"
+
+#: commands/event_trigger.c:184
+#, c-format
+msgid "Must be superuser to create an event trigger."
+msgstr "슈퍼유저만 이벤트 트리거를 만들 수 있습니다."
+
+#: commands/event_trigger.c:193
+#, c-format
+msgid "unrecognized event name \"%s\""
+msgstr "알 수 없는 이벤트 이름: \"%s\""
+
+#: commands/event_trigger.c:210
+#, c-format
+msgid "unrecognized filter variable \"%s\""
+msgstr "알 수 없는 필터 변수: \"%s\""
+
+#: commands/event_trigger.c:265
+#, c-format
+msgid "filter value \"%s\" not recognized for filter variable \"%s\""
+msgstr "\"%s\" 필터값은 \"%s\" 필터 변수으로 쓸 수 없음"
+
+#. translator: %s represents an SQL statement name
+#: commands/event_trigger.c:271 commands/event_trigger.c:341
+#, c-format
+msgid "event triggers are not supported for %s"
+msgstr "%s 용 이벤트 트리거는 지원하지 않음"
+
+#: commands/event_trigger.c:364
+#, c-format
+msgid "filter variable \"%s\" specified more than once"
+msgstr "\"%s\" 필터 변수가 한 번 이상 사용되었습니다."
+
+#: commands/event_trigger.c:512 commands/event_trigger.c:556
+#: commands/event_trigger.c:649
+#, c-format
+msgid "event trigger \"%s\" does not exist"
+msgstr "\"%s\" 이벤트 트리거 없음"
+
+#: commands/event_trigger.c:617
+#, c-format
+msgid "permission denied to change owner of event trigger \"%s\""
+msgstr "\"%s\" 이벤트 트리거 소유주를 변경할 권한이 없음"
+
+#: commands/event_trigger.c:619
+#, c-format
+msgid "The owner of an event trigger must be a superuser."
+msgstr "이벤트 트리거 소유주는 슈퍼유저여야 합니다."
+
+#: commands/event_trigger.c:1438
+#, c-format
+msgid "%s can only be called in a sql_drop event trigger function"
+msgstr "%s 객체는 sql_drop 이벤트 트리거 함수 안에서만 호출 되어야 합니다."
+
+#: commands/event_trigger.c:1558 commands/event_trigger.c:1579
+#, c-format
+msgid "%s can only be called in a table_rewrite event trigger function"
+msgstr ""
+"%s 객체는 table_rewrite 이벤트 트리거 함수 안에서만 호출 되어야 합니다."
+
+#: commands/event_trigger.c:1989
+#, c-format
+msgid "%s can only be called in an event trigger function"
+msgstr "%s 객체는 이벤트 트리거 함수 안에서만 호출 되어야 합니다."
+
+#: commands/explain.c:185
+#, c-format
+msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\""
+msgstr "\"%s\" EXPLAIN 옵션에서 쓸 수 없는 값: \"%s\""
+
+#: commands/explain.c:191
+#, c-format
+msgid "unrecognized EXPLAIN option \"%s\""
+msgstr "잘못된 EXPLAIN 옵션: \"%s\""
+
+#: commands/explain.c:198
+#, c-format
+msgid "EXPLAIN option BUFFERS requires ANALYZE"
+msgstr "BUFFERS 옵션은 EXPLAIN ANALYZE에서만 쓸 수 있습니다."
+
+#: commands/explain.c:207
+#, c-format
+msgid "EXPLAIN option TIMING requires ANALYZE"
+msgstr "TIMING 옵션은 EXPLAIN ANALYZE에서만 쓸 수 있습니다."
+
+#: commands/extension.c:155 commands/extension.c:2719
+#, c-format
+msgid "extension \"%s\" does not exist"
+msgstr "\"%s\" 이름의 확장 모듈이 없습니다"
+
+#: commands/extension.c:254 commands/extension.c:263 commands/extension.c:275
+#: commands/extension.c:285
+#, c-format
+msgid "invalid extension name: \"%s\""
+msgstr "잘못된 확장 모듈 이름: \"%s\""
+
+#: commands/extension.c:255
+#, c-format
+msgid "Extension names must not be empty."
+msgstr "확장 모듈 이름을 지정하세요."
+
+#: commands/extension.c:264
+#, c-format
+msgid "Extension names must not contain \"--\"."
+msgstr "확장 모듈 이름에 \"--\" 문자가 포함될 수 없습니다."
+
+#: commands/extension.c:276
+#, c-format
+msgid "Extension names must not begin or end with \"-\"."
+msgstr "확장 모듈 이름의 시작과 끝에는 \"-\" 문자를 사용할 수 없습니다."
+
+#: commands/extension.c:286
+#, c-format
+msgid "Extension names must not contain directory separator characters."
+msgstr "확장 모듈 이름에는 디렉터리 구분 문자를 사용할 수 없습니다."
+
+#: commands/extension.c:301 commands/extension.c:310 commands/extension.c:319
+#: commands/extension.c:329
+#, c-format
+msgid "invalid extension version name: \"%s\""
+msgstr "잘못된 확장 모듈 버전 이름: \"%s\""
+
+#: commands/extension.c:302
+#, c-format
+msgid "Version names must not be empty."
+msgstr "버전 이름은 비어있으면 안됩니다"
+
+#: commands/extension.c:311
+#, c-format
+msgid "Version names must not contain \"--\"."
+msgstr "버전 이름에 \"--\" 문자가 포함될 수 없습니다."
+
+#: commands/extension.c:320
+#, c-format
+msgid "Version names must not begin or end with \"-\"."
+msgstr "버전 이름의 앞 뒤에 \"-\" 문자를 쓸 수 없습니다."
+
+#: commands/extension.c:330
+#, c-format
+msgid "Version names must not contain directory separator characters."
+msgstr "버전 이름에는 디렉터리 분리 문자를 쓸 수 없습니다."
+
+#: commands/extension.c:480
+#, c-format
+msgid "could not open extension control file \"%s\": %m"
+msgstr "\"%s\" 확장 모듈 제어 파일 열기 실패: %m"
+
+#: commands/extension.c:502 commands/extension.c:512
+#, c-format
+msgid "parameter \"%s\" cannot be set in a secondary extension control file"
+msgstr "\"%s\" 매개 변수는 이차 확장 모듈 제어 파일에서는 사용할 수 없습니다."
+
+#: commands/extension.c:551
+#, c-format
+msgid "\"%s\" is not a valid encoding name"
+msgstr "\"%s\" 이름은 잘못된 인코딩 이름임"
+
+#: commands/extension.c:565
+#, c-format
+msgid "parameter \"%s\" must be a list of extension names"
+msgstr "\"%s\" 매개 변수는 확장 모듈 이름 목록이어야 함"
+
+#: commands/extension.c:572
+#, c-format
+msgid "unrecognized parameter \"%s\" in file \"%s\""
+msgstr "알 수 없는 \"%s\" 매개 변수가 \"%s\" 파일 안에 있습니다."
+
+#: commands/extension.c:581
+#, c-format
+msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true"
+msgstr ""
+"\"relocatable\" 값이 true 인 경우 \"schema\" 매개 변수는 사용할 수 없습니다."
+
+#: commands/extension.c:722
+#, c-format
+msgid ""
+"transaction control statements are not allowed within an extension script"
+msgstr "확장 모듈 스크립트 안에서는 트랜잭션 제어 구문은 사용할 수 없습니다."
+
+#: commands/extension.c:790
+#, c-format
+msgid "permission denied to create extension \"%s\""
+msgstr "\"%s\" 확장 모듈을 만들 권한이 없습니다"
+
+#: commands/extension.c:792
+#, c-format
+msgid "Must be superuser to create this extension."
+msgstr "확장 모듈은 슈퍼유저만 만들 수 있습니다."
+
+#: commands/extension.c:796
+#, c-format
+msgid "permission denied to update extension \"%s\""
+msgstr "\"%s\" 확장 모듈을 업데이트할 권한이 없습니다."
+
+#: commands/extension.c:798
+#, c-format
+msgid "Must be superuser to update this extension."
+msgstr "슈퍼유저만 해당 모듈을 업데이트 할 수 있습니다."
+
+#: commands/extension.c:1080
+#, c-format
+msgid ""
+"extension \"%s\" has no update path from version \"%s\" to version \"%s\""
+msgstr ""
+"\"%s\" 확장 모듈을 \"%s\" 버전에서 \"%s\" 버전으로 업데이트할 방법이 없습니"
+"다."
+
+#: commands/extension.c:1262 commands/extension.c:2779
+#, c-format
+msgid "version to install must be specified"
+msgstr "설치할 버전을 지정해야 합니다."
+
+#: commands/extension.c:1279
+#, c-format
+msgid "FROM version must be different from installation target version \"%s\""
+msgstr "FROM 절에 지정한 버전은 설치된 \"%s\" 버전과 달라야 합니다"
+
+#: commands/extension.c:1344
+#, c-format
+msgid "extension \"%s\" must be installed in schema \"%s\""
+msgstr "\"%s\" 확장 모듈은 \"%s\" 스키마 안에 설치되어야 합니다."
+
+#: commands/extension.c:1436
+#, c-format
+msgid "cyclic dependency detected between extensions \"%s\" and \"%s\""
+msgstr "\"%s\" 확장 모듈과 \"%s\" 확장 모듈이 서로 의존 관계입니다"
+
+#: commands/extension.c:1441
+#, c-format
+msgid "installing required extension \"%s\""
+msgstr "\"%s\" 확장 모듈이 필요해서 실치 하는 중"
+
+#: commands/extension.c:1469 commands/extension.c:2924
+#, c-format
+msgid "required extension \"%s\" is not installed"
+msgstr "\"%s\" 확장 모듈이 필요한데, 설치되어 있지 않습니다."
+
+#: commands/extension.c:1471
+#, c-format
+msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too."
+msgstr ""
+"필요한 모듈을 함께 설치하려면, CREATE EXTENSION ... CASCADE 구문을 사용하세"
+"요."
+
+#: commands/extension.c:1535
+#, c-format
+msgid "extension \"%s\" already exists, skipping"
+msgstr "\"%s\" 확장 모듈이 이미 있음, 건너뜀"
+
+#: commands/extension.c:1542
+#, c-format
+msgid "extension \"%s\" already exists"
+msgstr "\"%s\" 이름의 확장 모듈이 이미 있습니다"
+
+#: commands/extension.c:1553
+#, c-format
+msgid "nested CREATE EXTENSION is not supported"
+msgstr "중첩된 CREATE EXTENSION 구문은 지원하지 않습니다."
+
+#: commands/extension.c:1681
+#, c-format
+msgid "cannot drop extension \"%s\" because it is being modified"
+msgstr "%s 의존객체들은 시스템 객체이기 때문에 삭제 될 수 없습니다"
+
+#: commands/extension.c:2152
+#, c-format
+msgid ""
+"pg_extension_config_dump() can only be called from an SQL script executed by "
+"CREATE EXTENSION"
+msgstr ""
+"pg_extension_config_dump() 함수는 CREATE EXTENSION 명령에서 내부적으로 사용하"
+"는 SQL 스크립트 내에서만 사용할 수 있습니다."
+
+#: commands/extension.c:2164
+#, c-format
+msgid "OID %u does not refer to a table"
+msgstr "%u OID 자료가 테이블에 없습니다"
+
+#: commands/extension.c:2169
+#, c-format
+msgid "table \"%s\" is not a member of the extension being created"
+msgstr "\"%s\" 테이블은 만들려고 하는 확장 모듈의 구성 요소가 아닙니다."
+
+#: commands/extension.c:2534
+#, c-format
+msgid ""
+"cannot move extension \"%s\" into schema \"%s\" because the extension "
+"contains the schema"
+msgstr "\"%s\" 확장 모듈이 \"%s\" 스키마에 이미 있어 옮길 수 없습니다."
+
+#: commands/extension.c:2574 commands/extension.c:2637
+#, c-format
+msgid "extension \"%s\" does not support SET SCHEMA"
+msgstr "\"%s\" 확장 모듈은 SET SCHEMA 구문을 지원하지 않음"
+
+#: commands/extension.c:2639
+#, c-format
+msgid "%s is not in the extension's schema \"%s\""
+msgstr "%s 객체가 확장 모듈 스키마인 \"%s\" 안에 없음"
+
+#: commands/extension.c:2699
+#, c-format
+msgid "nested ALTER EXTENSION is not supported"
+msgstr "중첩된 ALTER EXTENSION 구문을 지원하지 않음"
+
+#: commands/extension.c:2790
+#, c-format
+msgid "version \"%s\" of extension \"%s\" is already installed"
+msgstr "\"%s\" 버전의 \"%s\" 확장 모듈이 이미 설치 되어 있음"
+
+#: commands/extension.c:3041
+#, c-format
+msgid ""
+"cannot add schema \"%s\" to extension \"%s\" because the schema contains the "
+"extension"
+msgstr ""
+"\"%s\" 스키마에 \"%s\" 확장 모듈을 추가할 수 없음, 이미 해당 스키마 안에 포"
+"함되어 있음"
+
+#: commands/extension.c:3069
+#, c-format
+msgid "%s is not a member of extension \"%s\""
+msgstr "\"%s\" 객체는 \"%s\" 확장 모듈의 구성 요소가 아닙니다"
+
+#: commands/extension.c:3135
+#, c-format
+msgid "file \"%s\" is too large"
+msgstr "\"%s\" 파일이 너무 큽니다."
+
+#: commands/foreigncmds.c:150 commands/foreigncmds.c:159
+#, c-format
+msgid "option \"%s\" not found"
+msgstr "\"%s\" 옵션을 찾을 수 없음"
+
+#: commands/foreigncmds.c:169
+#, c-format
+msgid "option \"%s\" provided more than once"
+msgstr "\"%s\" 옵션이 여러 번 제공되었음"
+
+#: commands/foreigncmds.c:223 commands/foreigncmds.c:231
+#, c-format
+msgid "permission denied to change owner of foreign-data wrapper \"%s\""
+msgstr "\"%s\" 외부 자료 래퍼의 소유주를 변경할 권한이 없음"
+
+#: commands/foreigncmds.c:225
+#, c-format
+msgid "Must be superuser to change owner of a foreign-data wrapper."
+msgstr "슈퍼유저만 외부 자료 래퍼의 소유주를 바꿀 수 있습니다."
+
+#: commands/foreigncmds.c:233
+#, c-format
+msgid "The owner of a foreign-data wrapper must be a superuser."
+msgstr "외부 자료 래퍼의 소유주는 슈퍼유저여야 합니다."
+
+#: commands/foreigncmds.c:292 commands/foreigncmds.c:709 foreign/foreign.c:671
+#, c-format
+msgid "foreign-data wrapper \"%s\" does not exist"
+msgstr "\"%s\" 외부 자료 래퍼가 없음"
+
+#: commands/foreigncmds.c:584
+#, c-format
+msgid "permission denied to create foreign-data wrapper \"%s\""
+msgstr "\"%s\" 외부 자료 래퍼를 만들 권한이 없음"
+
+#: commands/foreigncmds.c:586
+#, c-format
+msgid "Must be superuser to create a foreign-data wrapper."
+msgstr "슈퍼유저만 외부 자료 래퍼를 만들 수 있습니다."
+
+#: commands/foreigncmds.c:699
+#, c-format
+msgid "permission denied to alter foreign-data wrapper \"%s\""
+msgstr "\"%s\" 외부 자료 래퍼를 변경할 권한이 없음"
+
+#: commands/foreigncmds.c:701
+#, c-format
+msgid "Must be superuser to alter a foreign-data wrapper."
+msgstr "슈퍼유저만 외부 자료 래퍼를 변경할 수 있습니다."
+
+#: commands/foreigncmds.c:732
+#, c-format
+msgid ""
+"changing the foreign-data wrapper handler can change behavior of existing "
+"foreign tables"
+msgstr ""
+"외부 자료 랩퍼 핸들러를 바꾸면, 그것을 사용하는 외부 테이블의 내용이 바뀔 수 "
+"있습니다."
+
+#: commands/foreigncmds.c:747
+#, c-format
+msgid ""
+"changing the foreign-data wrapper validator can cause the options for "
+"dependent objects to become invalid"
+msgstr ""
+"외부 자료 래퍼 유효성 검사기를 바꾸면 종속 객체에 대한 옵션이 유효하지 않을 "
+"수 있음"
+
+#: commands/foreigncmds.c:1165
+#, c-format
+msgid "user mapping \"%s\" already exists for server %s"
+msgstr "\"%s\" 사용자 매핑이 %s 서버용으로 이미 있음"
+
+#: commands/foreigncmds.c:1259 commands/foreigncmds.c:1375
+#, c-format
+msgid "user mapping \"%s\" does not exist for the server"
+msgstr "해당 서버용 \"%s\" 사용자 매핑이 없음"
+
+#: commands/foreigncmds.c:1362
+#, c-format
+msgid "server does not exist, skipping"
+msgstr "서버가 없음, 건너뜀"
+
+#: commands/foreigncmds.c:1380
+#, c-format
+msgid "user mapping \"%s\" does not exist for the server, skipping"
+msgstr "\"%s\" 사용자 매핑이 해당 서버용으로 없음, 건너뜀"
+
+#: commands/foreigncmds.c:1532 foreign/foreign.c:361
+#, c-format
+msgid "foreign-data wrapper \"%s\" has no handler"
+msgstr "\"%s\" 외부 자료 래퍼용 핸들러가 없음"
+
+#: commands/foreigncmds.c:1538
+#, c-format
+msgid "foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA"
+msgstr "\"%s\" 외부 자료 래퍼는 IMPORT FOREIGN SCHEMA 구문을 지원하지 않음"
+
+#: commands/foreigncmds.c:1631
+#, c-format
+msgid "importing foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블 가져 오는 중"
+
+#: commands/functioncmds.c:99
+#, c-format
+msgid "SQL function cannot return shell type %s"
+msgstr "SQL 함수는 shell type %s 리턴할 수 없음"
+
+#: commands/functioncmds.c:104
+#, c-format
+msgid "return type %s is only a shell"
+msgstr "_^_ %s 리턴 자료형은 하나의 shell만 있습니다"
+
+#: commands/functioncmds.c:134 parser/parse_type.c:337
+#, c-format
+msgid "type modifier cannot be specified for shell type \"%s\""
+msgstr "\"%s\" 셸 형식에 대해 형식 한정자를 지정할 수 없음"
+
+#: commands/functioncmds.c:140
+#, c-format
+msgid "type \"%s\" is not yet defined"
+msgstr "\"%s\" 자료형이 아직 정의되지 않았음"
+
+#: commands/functioncmds.c:141
+#, c-format
+msgid "Creating a shell type definition."
+msgstr "셸 타입 정의를 만들고 있습니다"
+
+#: commands/functioncmds.c:239
+#, c-format
+msgid "SQL function cannot accept shell type %s"
+msgstr "SQL 함수는 셸 타입 %s 수용할 수 없음"
+
+#: commands/functioncmds.c:245
+#, c-format
+msgid "aggregate cannot accept shell type %s"
+msgstr "집계 함수는 셸 타입 %s 수용할 수 없음"
+
+#: commands/functioncmds.c:250
+#, c-format
+msgid "argument type %s is only a shell"
+msgstr "%s 인자 자료형은 단지 셸입니다"
+
+#: commands/functioncmds.c:260
+#, c-format
+msgid "type %s does not exist"
+msgstr "%s 자료형 없음"
+
+#: commands/functioncmds.c:274
+#, c-format
+msgid "aggregates cannot accept set arguments"
+msgstr "집계 함수는 세트 인자를 입력 인자로 쓸 수 없음"
+
+#: commands/functioncmds.c:278
+#, c-format
+msgid "functions cannot accept set arguments"
+msgstr "함수는 세트 인자를 입력 인자로 쓸 수 없음"
+
+#: commands/functioncmds.c:288
+#, c-format
+msgid "VARIADIC parameter must be the last input parameter"
+msgstr "VARIADIC 매개 변수는 마지막 입력 매개 변수여야 함"
+
+#: commands/functioncmds.c:316
+#, c-format
+msgid "VARIADIC parameter must be an array"
+msgstr "VARIADIC 매개 변수는 배열이어야 함"
+
+#: commands/functioncmds.c:356
+#, c-format
+msgid "parameter name \"%s\" used more than once"
+msgstr "\"%s\" 매개 변수가 여러 번 사용 됨"
+
+#: commands/functioncmds.c:371
+#, c-format
+msgid "only input parameters can have default values"
+msgstr "입력 매개 변수에서만 기본값을 사용할 수 있음"
+
+#: commands/functioncmds.c:386
+#, c-format
+msgid "cannot use table references in parameter default value"
+msgstr "입력 매개 변수 초기값으로 테이블 참조형은 사용할 수 없음"
+
+#: commands/functioncmds.c:410
+#, c-format
+msgid "input parameters after one with a default value must also have defaults"
+msgstr ""
+"기본 값이 있는 입력 매개 변수 뒤에 오는 입력 매개 변수에도 기본 값이 있어야 "
+"함"
+
+#: commands/functioncmds.c:701
+#, c-format
+msgid "no function body specified"
+msgstr "함수 본문(body) 부분이 빠졌습니다"
+
+#: commands/functioncmds.c:711
+#, c-format
+msgid "no language specified"
+msgstr "처리할 프로시주얼 언어를 지정하지 않았습니다"
+
+#: commands/functioncmds.c:736 commands/functioncmds.c:1243
+#, c-format
+msgid "COST must be positive"
+msgstr "COST는 양수여야 함"
+
+#: commands/functioncmds.c:744 commands/functioncmds.c:1251
+#, c-format
+msgid "ROWS must be positive"
+msgstr "ROWS는 양수여야 함"
+
+#: commands/functioncmds.c:785
+#, c-format
+msgid "unrecognized function attribute \"%s\" ignored"
+msgstr "알수 없는 함수 속성 \"%s\" 무시됨"
+
+#: commands/functioncmds.c:836
+#, c-format
+msgid "only one AS item needed for language \"%s\""
+msgstr "\"%s\" 언어에는 하나의 AS 항목만 필요함"
+
+#: commands/functioncmds.c:929 commands/functioncmds.c:2119
+#: commands/proclang.c:563
+#, c-format
+msgid "language \"%s\" does not exist"
+msgstr "\"%s\" 프로시주얼 언어 없음"
+
+#: commands/functioncmds.c:931 commands/functioncmds.c:2121
+#, c-format
+msgid "Use CREATE LANGUAGE to load the language into the database."
+msgstr ""
+"데이터베이스 내에서 프로시주얼 언어를 사용하려면 먼저 CREATE LANGUAGE 명령으"
+"로 사용할 언어를 등록하세요."
+
+#: commands/functioncmds.c:966 commands/functioncmds.c:1235
+#, c-format
+msgid "only superuser can define a leakproof function"
+msgstr "슈퍼유저만 leakproof 함수를 만들 수 있습니다"
+
+#: commands/functioncmds.c:1010
+#, c-format
+msgid "function result type must be %s because of OUT parameters"
+msgstr "OUT 매개 변수로 인해 함수 결과 형식은 %s이어야 함"
+
+#: commands/functioncmds.c:1023
+#, c-format
+msgid "function result type must be specified"
+msgstr "함수의 리턴 자료형을 지정해야 합니다"
+
+#: commands/functioncmds.c:1077 commands/functioncmds.c:1255
+#, c-format
+msgid "ROWS is not applicable when function does not return a set"
+msgstr "함수에서 세트를 반환하지 않는 경우 ROWS를 적용할 수 없음"
+
+#: commands/functioncmds.c:1412
+#, c-format
+msgid "source data type %s is a pseudo-type"
+msgstr "%s 원본 자료형이 의사자료형(pseudo-type) 입니다"
+
+#: commands/functioncmds.c:1418
+#, c-format
+msgid "target data type %s is a pseudo-type"
+msgstr "%s 대상 자료형이 의사자료형(pseudo-type) 입니다"
+
+#: commands/functioncmds.c:1442
+#, c-format
+msgid "cast will be ignored because the source data type is a domain"
+msgstr "원본 자료형이 도메인이어서 자료형 변환을 무시합니다."
+
+#: commands/functioncmds.c:1447
+#, c-format
+msgid "cast will be ignored because the target data type is a domain"
+msgstr "대상 자료형이 도메인이어서 자료형 변환을 무시합니다."
+
+#: commands/functioncmds.c:1474
+#, c-format
+msgid "cast function must take one to three arguments"
+msgstr "형변환 함수는 1-3개의 인자만 지정할 수 있습니다"
+
+#: commands/functioncmds.c:1478
+#, c-format
+msgid ""
+"argument of cast function must match or be binary-coercible from source data "
+"type"
+msgstr ""
+"형변환 함수의 인자로 쓸 자료형은 원본 자료형과 일치하거나 바이너리 차원으로 "
+"같은 자료형이어야 함"
+
+#: commands/functioncmds.c:1482
+#, c-format
+msgid "second argument of cast function must be type integer"
+msgstr "형변화 함수의 두번째 인자 자료형은 반드시 integer여야합니다"
+
+#: commands/functioncmds.c:1486
+#, c-format
+msgid "third argument of cast function must be type boolean"
+msgstr "형변화 함수의 세번째 인자 자료형은 반드시 boolean이여야합니다"
+
+#: commands/functioncmds.c:1490
+#, c-format
+msgid ""
+"return data type of cast function must match or be binary-coercible to "
+"target data type"
+msgstr ""
+"형변환 함수의 반환 자료형은 대상 자료형과 일치하거나 바이너리 차원으로 같은 "
+"자료형이어야 함"
+
+#: commands/functioncmds.c:1501
+#, c-format
+msgid "cast function must not be volatile"
+msgstr "형변환 함수는 volatile 특성이 없어야합니다"
+
+#: commands/functioncmds.c:1506
+#, c-format
+msgid "cast function must not be an aggregate function"
+msgstr "형변환 함수는 집계 함수가 아니여야합니다"
+
+#: commands/functioncmds.c:1510
+#, c-format
+msgid "cast function must not be a window function"
+msgstr "형변환 함수는 윈도우 함수가 아니여야 함"
+
+#: commands/functioncmds.c:1514
+#, c-format
+msgid "cast function must not return a set"
+msgstr "형변환 함수는 세트(set)를 리턴할 수 없습니다"
+
+#: commands/functioncmds.c:1540
+#, c-format
+msgid "must be superuser to create a cast WITHOUT FUNCTION"
+msgstr "CREATE CAST ... WITHOUT FUNCTION 명령은 슈퍼유저만 실행할 수 있습니다"
+
+#: commands/functioncmds.c:1555
+#, c-format
+msgid "source and target data types are not physically compatible"
+msgstr "원본 자료형과 대상 자료형이 서로 논리적인 호환성이 없습니다"
+
+#: commands/functioncmds.c:1570
+#, c-format
+msgid "composite data types are not binary-compatible"
+msgstr "복합 자료형은 바이너리와 호환되지 않음"
+
+#: commands/functioncmds.c:1576
+#, c-format
+msgid "enum data types are not binary-compatible"
+msgstr "열거 자료형은 바이너리와 호환되지 않음"
+
+#: commands/functioncmds.c:1582
+#, c-format
+msgid "array data types are not binary-compatible"
+msgstr "배열 자료형은 바이너리와 호환되지 않음"
+
+#: commands/functioncmds.c:1599
+#, c-format
+msgid "domain data types must not be marked binary-compatible"
+msgstr "도메인 자료형은 바이너리와 호환되지 않음"
+
+#: commands/functioncmds.c:1609
+#, c-format
+msgid "source data type and target data type are the same"
+msgstr "원본 자료형과 대상 자료형의 형태가 같습니다"
+
+#: commands/functioncmds.c:1642
+#, c-format
+msgid "cast from type %s to type %s already exists"
+msgstr "%s 형에서 %s 형으로 변환하는 형변환 규칙(cast)이 이미 있습니다"
+
+#: commands/functioncmds.c:1717
+#, c-format
+msgid "cast from type %s to type %s does not exist"
+msgstr "%s 형에서 %s 형으로 바꾸는 형변환 규칙(cast)가 없음"
+
+#: commands/functioncmds.c:1756
+#, c-format
+msgid "transform function must not be volatile"
+msgstr "형변환 함수는 volatile 특성이 없어야합니다"
+
+#: commands/functioncmds.c:1760
+#, c-format
+msgid "transform function must not be an aggregate function"
+msgstr "형변환 함수는 집계 함수가 아니여야합니다"
+
+#: commands/functioncmds.c:1764
+#, c-format
+msgid "transform function must not be a window function"
+msgstr "형변환 함수는 윈도우 함수가 아니여야 함"
+
+#: commands/functioncmds.c:1768
+#, c-format
+msgid "transform function must not return a set"
+msgstr "형변환 함수는 세트(set)를 리턴할 수 없습니다"
+
+#: commands/functioncmds.c:1772
+#, c-format
+msgid "transform function must take one argument"
+msgstr "형변환 함수는 1개의 인자만 지정할 수 있습니다"
+
+#: commands/functioncmds.c:1776
+#, c-format
+msgid "first argument of transform function must be type \"internal\""
+msgstr "형변화 함수의 첫번째 인자 자료형은 반드시 \"internal\"이여야합니다"
+
+#: commands/functioncmds.c:1813
+#, c-format
+msgid "data type %s is a pseudo-type"
+msgstr "%s 자료형은 의사자료형(pseudo-type) 입니다"
+
+#: commands/functioncmds.c:1819
+#, c-format
+msgid "data type %s is a domain"
+msgstr "%s 자료형은 도메인입니다"
+
+#: commands/functioncmds.c:1859
+#, c-format
+msgid "return data type of FROM SQL function must be \"internal\""
+msgstr "FROM SQL 함수의 반환 자료형은 \"internal\" 이어야 함"
+
+#: commands/functioncmds.c:1884
+#, c-format
+msgid "return data type of TO SQL function must be the transform data type"
+msgstr "TO SQL 함수의 반환 자료형은 변환 자료형이어야 함"
+
+#: commands/functioncmds.c:1911
+#, c-format
+msgid "transform for type %s language \"%s\" already exists"
+msgstr "%s 자료형(대상 언어: \"%s\")을 위한 형변환 규칙은 이미 있습니다."
+
+#: commands/functioncmds.c:2002
+#, c-format
+msgid "transform for type %s language \"%s\" does not exist"
+msgstr "%s 자료형(대상 언어: \"%s\")을 위한 형변환 규칙은 없습니다."
+
+#: commands/functioncmds.c:2053
+#, c-format
+msgid "function %s already exists in schema \"%s\""
+msgstr "%s 함수는 이미 \"%s\" 스키마안에 있습니다"
+
+#: commands/functioncmds.c:2106
+#, c-format
+msgid "no inline code specified"
+msgstr "내장 코드가 빠졌습니다"
+
+#: commands/functioncmds.c:2151
+#, c-format
+msgid "language \"%s\" does not support inline code execution"
+msgstr "\"%s\" 프로시주얼 언어는 내장 코드 실행 기능을 지원하지 않습니다"
+
+#: commands/indexcmds.c:349
+#, c-format
+msgid "must specify at least one column"
+msgstr "적어도 하나 이상의 열을 지정해 주십시오"
+
+#: commands/indexcmds.c:353
+#, c-format
+msgid "cannot use more than %d columns in an index"
+msgstr "하나의 인덱스에서는 %d개보다 많은 열을 사용할 수 없습니다"
+
+#: commands/indexcmds.c:384
+#, c-format
+msgid "cannot create index on foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블 대상으로 인덱스를 만들 수 없음"
+
+#: commands/indexcmds.c:399
+#, c-format
+msgid "cannot create indexes on temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블에 인덱스를 만들 수는 없습니다"
+
+#: commands/indexcmds.c:455 commands/tablecmds.c:546 commands/tablecmds.c:9694
+#, c-format
+msgid "only shared relations can be placed in pg_global tablespace"
+msgstr "공유 관계만 pg_global 테이블스페이스에 배치할 수 있음"
+
+#: commands/indexcmds.c:488
+#, c-format
+msgid "substituting access method \"gist\" for obsolete method \"rtree\""
+msgstr "사용하지 않는 \"rtree\" 방법을 \"gist\" 액세스 방법으로 대체하는 중"
+
+#: commands/indexcmds.c:506
+#, c-format
+msgid "hash indexes are not WAL-logged and their use is discouraged"
+msgstr "hash 인덱스는 WAL 기록을 하지 않습니다. 이 사용은 권장하지 않습니다"
+
+#: commands/indexcmds.c:511
+#, c-format
+msgid "access method \"%s\" does not support unique indexes"
+msgstr "\"%s\" 인덱스 액세스 방법은 고유 인덱스를 지원하지 않습니다"
+
+#: commands/indexcmds.c:516
+#, c-format
+msgid "access method \"%s\" does not support multicolumn indexes"
+msgstr "\"%s\" 인덱스 액세스 방법은 다중 열 인덱스를 지원하지 않습니다"
+
+#: commands/indexcmds.c:521
+#, c-format
+msgid "access method \"%s\" does not support exclusion constraints"
+msgstr "\"%s\" 인덱스 접근 방법은 exclusion 제약 조건을 지원하지 않습니다"
+
+#: commands/indexcmds.c:591 commands/indexcmds.c:611
+#, c-format
+msgid "index creation on system columns is not supported"
+msgstr "시스템 카탈로그 테이블에 대한 인덱스 만들기는 지원하지 않습니다"
+
+#: commands/indexcmds.c:636
+#, c-format
+msgid "%s %s will create implicit index \"%s\" for table \"%s\""
+msgstr "%s %s 명령으로 \"%s\" 인덱스를 \"%s\" 테이블에 자동으로 만들었음"
+
+#: commands/indexcmds.c:983
+#, c-format
+msgid "functions in index predicate must be marked IMMUTABLE"
+msgstr ""
+"인덱스 술어(predicate)에서 사용하는 함수는 IMMUTABLE 특성이 있어야합니다"
+
+#: commands/indexcmds.c:1049 parser/parse_utilcmd.c:1881
+#, c-format
+msgid "column \"%s\" named in key does not exist"
+msgstr "키에서 지정한 \"%s\" 열이 없습니다"
+
+#: commands/indexcmds.c:1109
+#, c-format
+msgid "functions in index expression must be marked IMMUTABLE"
+msgstr "인덱스 식(expression)에 사용하는 함수는 IMMUTABLE 특성이 있어야합니다"
+
+#: commands/indexcmds.c:1132
+#, c-format
+msgid "could not determine which collation to use for index expression"
+msgstr "해당 인덱스에서 사용할 정렬규칙(collation)을 결정할 수 없습니다."
+
+#: commands/indexcmds.c:1140 commands/typecmds.c:827 parser/parse_expr.c:2608
+#: parser/parse_type.c:550 parser/parse_utilcmd.c:2807 utils/adt/misc.c:666
+#, c-format
+msgid "collations are not supported by type %s"
+msgstr "%s 자료형은 collation 지원 안함"
+
+#: commands/indexcmds.c:1178
+#, c-format
+msgid "operator %s is not commutative"
+msgstr "%s 연산자는 교환법칙이 성립하지 않습니다"
+
+#: commands/indexcmds.c:1180
+#, c-format
+msgid "Only commutative operators can be used in exclusion constraints."
+msgstr ""
+"exclude 제약조건용 인덱스를 만들 때는 교환법칙이 성립하는 연산자만 사용할 수 "
+"있습니다."
+
+#: commands/indexcmds.c:1206
+#, c-format
+msgid "operator %s is not a member of operator family \"%s\""
+msgstr "%s 연산자는 \"%s\" 연산자 가족 구성원이 아닙니다."
+
+#: commands/indexcmds.c:1209
+#, c-format
+msgid ""
+"The exclusion operator must be related to the index operator class for the "
+"constraint."
+msgstr ""
+"제외 연산자는 해당 제약 조건용 인덱스 연산자 클래스의 소속이어야 합니다."
+
+#: commands/indexcmds.c:1244
+#, c-format
+msgid "access method \"%s\" does not support ASC/DESC options"
+msgstr "\"%s\" 접근 방법은 ASC/DESC 옵션을 지원하지 않음"
+
+#: commands/indexcmds.c:1249
+#, c-format
+msgid "access method \"%s\" does not support NULLS FIRST/LAST options"
+msgstr "\"%s\" 접근 방법은 NULLS FIRST/LAST 옵션을 지원하지 않음"
+
+#: commands/indexcmds.c:1305 commands/typecmds.c:1935
+#, c-format
+msgid "data type %s has no default operator class for access method \"%s\""
+msgstr ""
+"%s 자료형은 \"%s\" 인덱스 액세스 방법을 위한 기본 연산자 클래스(operator "
+"class)가 없습니다. "
+
+#: commands/indexcmds.c:1307
+#, c-format
+msgid ""
+"You must specify an operator class for the index or define a default "
+"operator class for the data type."
+msgstr ""
+"이 인덱스를 위한 연산자 클래스를 지정하거나 먼저 이 자료형을 위한 기본 연산"
+"자 클래스를 정의해 두어야합니다"
+
+#: commands/indexcmds.c:1336 commands/indexcmds.c:1344
+#: commands/opclasscmds.c:205
+#, c-format
+msgid "operator class \"%s\" does not exist for access method \"%s\""
+msgstr ""
+"\"%s\" 연산자 클래스는 \"%s\" 인덱스 액세스 방법에서 사용할 수 없습니다"
+
+#: commands/indexcmds.c:1357 commands/typecmds.c:1923
+#, c-format
+msgid "operator class \"%s\" does not accept data type %s"
+msgstr "\"%s\" 연산자 클래스는 %s 자료형을 사용할 수 없습니다"
+
+#: commands/indexcmds.c:1447
+#, c-format
+msgid "there are multiple default operator classes for data type %s"
+msgstr "%s 자료형을 위한 기본 연산자 클래스가 여러개 있습니다"
+
+#: commands/indexcmds.c:1838
+#, c-format
+msgid "table \"%s\" has no indexes"
+msgstr "\"%s\" 테이블에는 사용할 수 있는 인덱스가 없습니다"
+
+#: commands/indexcmds.c:1893
+#, c-format
+msgid "can only reindex the currently open database"
+msgstr "열려있는 현재 데이터베이스에서만 reindex 명령을 사용할 수 있습니다"
+
+#: commands/indexcmds.c:1993
+#, c-format
+msgid "table \"%s.%s\" was reindexed"
+msgstr "\"%s.%s\" 테이블의 인덱스들을 다시 만들었습니다."
+
+#: commands/matview.c:181
+#, c-format
+msgid "CONCURRENTLY cannot be used when the materialized view is not populated"
+msgstr ""
+"구체화된 뷰의 자료가 정리되고 있을 때는 CONCURRENTLY 옵션을 사용할 수 없습니"
+"다."
+
+#: commands/matview.c:187
+#, c-format
+msgid "CONCURRENTLY and WITH NO DATA options cannot be used together"
+msgstr "CONCURRENTLY 옵션과, WITH NO DATA 옵션을 함께 사용할 수 없습니다."
+
+#: commands/matview.c:257
+#, c-format
+msgid "cannot refresh materialized view \"%s\" concurrently"
+msgstr "\"%s\" 구체화된 뷰를 동시에 재갱신 할 수 없습니다."
+
+#: commands/matview.c:260
+#, c-format
+msgid ""
+"Create a unique index with no WHERE clause on one or more columns of the "
+"materialized view."
+msgstr ""
+"구체화된 뷰의 하나 또는 하나 이상의 칼럼에 대한 WHERE 절 없는 고유 인덱스를 "
+"만드세요."
+
+#: commands/matview.c:657
+#, c-format
+msgid ""
+"new data for materialized view \"%s\" contains duplicate rows without any "
+"null columns"
+msgstr ""
+"\"%s\" 구체화된 뷰의 새 자료에 아무런 null 칼럼 없이 중복된 로우를 포함하고 "
+"있습니다"
+
+#: commands/matview.c:659
+#, c-format
+msgid "Row: %s"
+msgstr "로우: %s"
+
+#: commands/opclasscmds.c:126
+#, c-format
+msgid "operator family \"%s\" does not exist for access method \"%s\""
+msgstr "\"%s\" 연산자 패밀리가 없음, 해당 접근 방법: \"%s\""
+
+#: commands/opclasscmds.c:264
+#, c-format
+msgid "operator family \"%s\" for access method \"%s\" already exists"
+msgstr "\"%s\" 연산자 패밀리가 이미 있음, 해당 접근 방법: \"%s\""
+
+#: commands/opclasscmds.c:404
+#, c-format
+msgid "must be superuser to create an operator class"
+msgstr "연산자 클래스는 슈퍼유저만 만들 수 있습니다"
+
+#: commands/opclasscmds.c:478 commands/opclasscmds.c:863
+#: commands/opclasscmds.c:996
+#, c-format
+msgid "invalid operator number %d, must be between 1 and %d"
+msgstr "잘못된 연산자 번호: %d, 타당한 번호는 1부터 %d까지 입니다"
+
+#: commands/opclasscmds.c:529 commands/opclasscmds.c:914
+#: commands/opclasscmds.c:1011
+#, c-format
+msgid "invalid procedure number %d, must be between 1 and %d"
+msgstr "잘못된 프로시저 번호 %d, 이 번호는 1부터 %d까지입니다"
+
+#: commands/opclasscmds.c:559
+#, c-format
+msgid "storage type specified more than once"
+msgstr "저장 방법이 중복되었습니다"
+
+#: commands/opclasscmds.c:586
+#, c-format
+msgid ""
+"storage type cannot be different from data type for access method \"%s\""
+msgstr "스토리지 자료형은 \"%s\" 접근 방법의 자료형과 같아야 합니다."
+
+#: commands/opclasscmds.c:602
+#, c-format
+msgid "operator class \"%s\" for access method \"%s\" already exists"
+msgstr "\"%s\" 연산자 클래스에는 이미 \"%s\" 액세스 방법이 사용되고 있습니다"
+
+#: commands/opclasscmds.c:630
+#, c-format
+msgid "could not make operator class \"%s\" be default for type %s"
+msgstr "\"%s\" 연산자 클래스를 %s 자료형의 기본값으로 지정할 수 없습니다"
+
+#: commands/opclasscmds.c:633
+#, c-format
+msgid "Operator class \"%s\" already is the default."
+msgstr "\"%s\" 연산자 클래스는 이미 기본 연산자 클래스입니다"
+
+#: commands/opclasscmds.c:760
+#, c-format
+msgid "must be superuser to create an operator family"
+msgstr "슈퍼유저만 연산자 패밀리를 만들 수 있음"
+
+#: commands/opclasscmds.c:816
+#, c-format
+msgid "must be superuser to alter an operator family"
+msgstr "슈퍼유저만 연산자 패밀리를 변경할 수 있음"
+
+#: commands/opclasscmds.c:879
+#, c-format
+msgid "operator argument types must be specified in ALTER OPERATOR FAMILY"
+msgstr "연산자 인자 형식이 ALTER OPERATOR FAMILY에 지정되어 있어야 함"
+
+#: commands/opclasscmds.c:943
+#, c-format
+msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY"
+msgstr "ALTER OPERATOR FAMILY에서 STORAGE를 지정할 수 없음"
+
+#: commands/opclasscmds.c:1066
+#, c-format
+msgid "one or two argument types must be specified"
+msgstr "한두 개의 인자 형식을 지정해야 함"
+
+#: commands/opclasscmds.c:1092
+#, c-format
+msgid "index operators must be binary"
+msgstr "인덱스 연산자는 바이너리여야 함"
+
+#: commands/opclasscmds.c:1111
+#, c-format
+msgid "access method \"%s\" does not support ordering operators"
+msgstr "\"%s\" 접근 방법은 정렬 작업을 지원하지 않음"
+
+#: commands/opclasscmds.c:1122
+#, c-format
+msgid "index search operators must return boolean"
+msgstr "인덱스 검색 연산자는 부울형을 반환해야 함"
+
+#: commands/opclasscmds.c:1164
+#, c-format
+msgid "btree comparison procedures must have two arguments"
+msgstr "btree 비교 프로시저에는 두 개의 인자가 있어야 함"
+
+#: commands/opclasscmds.c:1168
+#, c-format
+msgid "btree comparison procedures must return integer"
+msgstr "btree 비교 프로시저는 반드시 integer 자료형을 반환해야 함"
+
+#: commands/opclasscmds.c:1185
+#, c-format
+msgid "btree sort support procedures must accept type \"internal\""
+msgstr ""
+"btree 정렬 지원 프로시저는 반드시 \"internal\" 자료형 입력 인자로 사용해야함"
+
+#: commands/opclasscmds.c:1189
+#, c-format
+msgid "btree sort support procedures must return void"
+msgstr "btree 정렬 지원 프로시저는 반드시 void 값을 반환해야 함"
+
+#: commands/opclasscmds.c:1201
+#, c-format
+msgid "hash procedures must have one argument"
+msgstr "해시 프로시저에는 하나의 인자가 있어야 함"
+
+#: commands/opclasscmds.c:1205
+#, c-format
+msgid "hash procedures must return integer"
+msgstr "해시 프로시저는 정수를 반환해야 함"
+
+#: commands/opclasscmds.c:1229
+#, c-format
+msgid "associated data types must be specified for index support procedure"
+msgstr "인덱스 지원 프로시저에 대해 관련 데이터 형식을 지정해야 함"
+
+#: commands/opclasscmds.c:1254
+#, c-format
+msgid "procedure number %d for (%s,%s) appears more than once"
+msgstr "프로시저 번호 %d이(가) (%s,%s)에 대해 여러 번 표시됨"
+
+#: commands/opclasscmds.c:1261
+#, c-format
+msgid "operator number %d for (%s,%s) appears more than once"
+msgstr "연산자 번호 %d이(가) (%s,%s)에 대해 여러 번 표시됨"
+
+#: commands/opclasscmds.c:1310
+#, c-format
+msgid "operator %d(%s,%s) already exists in operator family \"%s\""
+msgstr "%d(%s,%s) 연산자가 \"%s\" 연산자 패밀리에 이미 있음"
+
+#: commands/opclasscmds.c:1426
+#, c-format
+msgid "function %d(%s,%s) already exists in operator family \"%s\""
+msgstr "%d(%s,%s) 함수가 \"%s\" 연산자 패밀리에 이미 있음"
+
+#: commands/opclasscmds.c:1516
+#, c-format
+msgid "operator %d(%s,%s) does not exist in operator family \"%s\""
+msgstr "%d(%s,%s) 연산자가 \"%s\" 연산자 패밀리에 없음"
+
+#: commands/opclasscmds.c:1556
+#, c-format
+msgid "function %d(%s,%s) does not exist in operator family \"%s\""
+msgstr "%d(%s,%s) 함수가 \"%s\" 연산자 패밀리에 없음"
+
+#: commands/opclasscmds.c:1686
+#, c-format
+msgid ""
+"operator class \"%s\" for access method \"%s\" already exists in schema \"%s"
+"\""
+msgstr ""
+"\"%s\" 연산자 클래스(\"%s\" 액세스 방법을 사용하는)는 이미 \"%s\" 스키마 안"
+"에 있습니다"
+
+#: commands/opclasscmds.c:1709
+#, c-format
+msgid ""
+"operator family \"%s\" for access method \"%s\" already exists in schema \"%s"
+"\""
+msgstr "\"%s\" 연산자 패밀리(접근 방법: \"%s\")가 \"%s\" 스키마에 이미 있음"
+
+#: commands/operatorcmds.c:114 commands/operatorcmds.c:122
+#, c-format
+msgid "SETOF type not allowed for operator argument"
+msgstr "SETOF 형식은 연산자 인자에 허용되지 않음"
+
+#: commands/operatorcmds.c:152 commands/operatorcmds.c:457
+#, c-format
+msgid "operator attribute \"%s\" not recognized"
+msgstr "\"%s\" 연산자 속성을 처리할 수 없음"
+
+#: commands/operatorcmds.c:163
+#, c-format
+msgid "operator procedure must be specified"
+msgstr "연산자 프로시저는 반드시 지정해 주어야합니다"
+
+#: commands/operatorcmds.c:174
+#, c-format
+msgid "at least one of leftarg or rightarg must be specified"
+msgstr "왼쪽 이나 오른쪽 중 적어도 하나의 인자는 지정해야 합니다"
+
+#: commands/operatorcmds.c:278
+#, c-format
+msgid "restriction estimator function %s must return type %s"
+msgstr "%s 제한 예상 함수는 %s 자료형을 반환해야 함"
+
+#: commands/operatorcmds.c:324
+#, c-format
+msgid "join estimator function %s must return type %s"
+msgstr "%s 조인 예상 함수는 %s 자료형을 반환해야 함"
+
+#: commands/operatorcmds.c:451
+#, c-format
+msgid "operator attribute \"%s\" cannot be changed"
+msgstr "\"%s\" 연산자 속성 바꿀 수 없음"
+
+#: commands/policy.c:87 commands/policy.c:388 commands/policy.c:477
+#: commands/tablecmds.c:971 commands/tablecmds.c:1313
+#: commands/tablecmds.c:2185 commands/tablecmds.c:4329
+#: commands/tablecmds.c:6280 commands/tablecmds.c:12080
+#: commands/tablecmds.c:12115 commands/trigger.c:241 commands/trigger.c:1125
+#: commands/trigger.c:1233 rewrite/rewriteDefine.c:273
+#: rewrite/rewriteDefine.c:917
+#, c-format
+msgid "permission denied: \"%s\" is a system catalog"
+msgstr "액세스 권한 없음: \"%s\" 시스템 카탈로그임"
+
+#: commands/policy.c:170
+#, c-format
+msgid "ignoring specified roles other than PUBLIC"
+msgstr "PUBLIC 아닌 지정한 모든 롤 무시함"
+
+#: commands/policy.c:171
+#, c-format
+msgid "All roles are members of the PUBLIC role."
+msgstr "모든 롤이 PUBLIC 롤의 소속입니다."
+
+#: commands/policy.c:501
+#, c-format
+msgid "role \"%s\" could not be removed from policy \"%s\" on \"%s\""
+msgstr "\"%s\" 롤을 \"%s\" 정책 (대상 릴레이션: \"%s\")에서 삭제될 수 없음"
+
+#: commands/policy.c:710
+#, c-format
+msgid "WITH CHECK cannot be applied to SELECT or DELETE"
+msgstr "WITH CHECK 옵션은 SELECT나 DELETE 작업에 적용 될 수 없음"
+
+#: commands/policy.c:719 commands/policy.c:1019
+#, c-format
+msgid "only WITH CHECK expression allowed for INSERT"
+msgstr "INSERT 구문에 대해서만 WITH CHECK 옵션을 허용합니다"
+
+#: commands/policy.c:792 commands/policy.c:1242
+#, c-format
+msgid "policy \"%s\" for table \"%s\" already exists"
+msgstr "\"%s\" 정책이 \"%s\" 테이블에 이미 지정되어있습니다"
+
+#: commands/policy.c:991 commands/policy.c:1270 commands/policy.c:1345
+#, c-format
+msgid "policy \"%s\" for table \"%s\" does not exist"
+msgstr "\"%s\" 정책이 \"%s\" 테이블에 없음"
+
+#: commands/policy.c:1009
+#, c-format
+msgid "only USING expression allowed for SELECT, DELETE"
+msgstr "USING 구문만 SELECT, DELETE 작업에 쓸 수 있음"
+
+#: commands/portalcmds.c:61 commands/portalcmds.c:160
+#: commands/portalcmds.c:212
+#, c-format
+msgid "invalid cursor name: must not be empty"
+msgstr "잘못된 커서 이름: 비어있으면 안됩니다"
+
+#: commands/portalcmds.c:168 commands/portalcmds.c:222
+#: executor/execCurrent.c:67 utils/adt/xml.c:2389 utils/adt/xml.c:2556
+#, c-format
+msgid "cursor \"%s\" does not exist"
+msgstr "\"%s\" 이름의 커서가 없음"
+
+#: commands/prepare.c:71
+#, c-format
+msgid "invalid statement name: must not be empty"
+msgstr "잘못된 명령문 이름: 비어있으면 안됩니다"
+
+#: commands/prepare.c:129 parser/parse_param.c:304 tcop/postgres.c:1343
+#, c-format
+msgid "could not determine data type of parameter $%d"
+msgstr "$%d 매개 변수의 자료형을 알수가 없습니다."
+
+#: commands/prepare.c:147
+#, c-format
+msgid "utility statements cannot be prepared"
+msgstr "utility 명령문들은 미리 준비할 수 없습니다"
+
+#: commands/prepare.c:257 commands/prepare.c:264
+#, c-format
+msgid "prepared statement is not a SELECT"
+msgstr "준비된 명령문이 SELECT 구문이 아닙니다."
+
+#: commands/prepare.c:332
+#, c-format
+msgid "wrong number of parameters for prepared statement \"%s\""
+msgstr "prepared statement \"%s\"에 매개 변수 수가 틀렸습니다"
+
+#: commands/prepare.c:334
+#, c-format
+msgid "Expected %d parameters but got %d."
+msgstr "%d 개의 매개 변수가 요구되는데 %d 개만이 존재합니다"
+
+#: commands/prepare.c:370
+#, c-format
+msgid "parameter $%d of type %s cannot be coerced to the expected type %s"
+msgstr "??? parameter $%d of type %s 는 expected type %s 로 강요할 수 없다"
+
+#: commands/prepare.c:465
+#, c-format
+msgid "prepared statement \"%s\" already exists"
+msgstr "\"%s\" 이름의 준비된 명령문(prepared statement)이 이미 있습니다"
+
+#: commands/prepare.c:504
+#, c-format
+msgid "prepared statement \"%s\" does not exist"
+msgstr "\"%s\" 이름의 준비된 명령문(prepared statement) 없음"
+
+#: commands/proclang.c:87
+#, c-format
+msgid "using pg_pltemplate information instead of CREATE LANGUAGE parameters"
+msgstr "CREATE LANGUAGE 의 매개 변수 대신에 pg_pltemplate 정보를 이용하세요"
+
+#: commands/proclang.c:97
+#, c-format
+msgid "must be superuser to create procedural language \"%s\""
+msgstr "슈퍼유저만 \"%s\" 프로시저 언어를 만들 수 있음"
+
+#: commands/proclang.c:252
+#, c-format
+msgid "unsupported language \"%s\""
+msgstr "지원하지 않는 프로시저 언어 \"%s\""
+
+#: commands/proclang.c:254
+#, c-format
+msgid "The supported languages are listed in the pg_pltemplate system catalog."
+msgstr "지원하는 언어 목록은 pg_pltemplate 시스템 카탈로그에 있습니다."
+
+#: commands/proclang.c:262
+#, c-format
+msgid "must be superuser to create custom procedural language"
+msgstr "슈퍼유저만 사용자 지정 프로시저 언어를 만들 수 있음"
+
+#: commands/proclang.c:281
+#, c-format
+msgid ""
+"changing return type of function %s from \"opaque\" to \"language_handler\""
+msgstr ""
+"%s 함수에서 \"opaque\" 자료형을 \"language_handler\" 자료형으로 리턴 자료형"
+"을 바꿉니다"
+
+#: commands/schemacmds.c:99 commands/schemacmds.c:262
+#, c-format
+msgid "unacceptable schema name \"%s\""
+msgstr "\"%s\" 스키마 이름이 적당하지 못합니다"
+
+#: commands/schemacmds.c:100 commands/schemacmds.c:263
+#, c-format
+msgid "The prefix \"pg_\" is reserved for system schemas."
+msgstr ""
+"\"pg_\" 문자로 시작하는 스키마는 시스템에서 사용하는 예약된 스키마입니다."
+
+#: commands/schemacmds.c:114
+#, c-format
+msgid "schema \"%s\" already exists, skipping"
+msgstr "\"%s\" 이름의 스키마(schema)가 이미 있음, 건너뜀"
+
+#: commands/seclabel.c:60
+#, c-format
+msgid "no security label providers have been loaded"
+msgstr "로드된 보안 라벨 제공자가 없음"
+
+#: commands/seclabel.c:64
+#, c-format
+msgid ""
+"must specify provider when multiple security label providers have been loaded"
+msgstr "다중 보안 레이블 제공자가 로드 될 때 제공자를 지정해야 합니다."
+
+#: commands/seclabel.c:82
+#, c-format
+msgid "security label provider \"%s\" is not loaded"
+msgstr "\"%s\" 이름의 보안 라벨 제공자가 로드되어 있지 않음"
+
+#: commands/sequence.c:127
+#, c-format
+msgid "unlogged sequences are not supported"
+msgstr "로그를 남기지 않는 시퀀스는 지원하지 않음"
+
+#: commands/sequence.c:651
+#, c-format
+msgid "nextval: reached maximum value of sequence \"%s\" (%s)"
+msgstr "nextval: \"%s\" 시퀀스의 최대값(%s)이 되었습니다"
+
+#: commands/sequence.c:674
+#, c-format
+msgid "nextval: reached minimum value of sequence \"%s\" (%s)"
+msgstr "nextval: \"%s\" 시퀀스의 최소값(%s)이 되었습니다"
+
+#: commands/sequence.c:792
+#, c-format
+msgid "currval of sequence \"%s\" is not yet defined in this session"
+msgstr "\"%s\" 시퀀스의 currval 값이 현재 세션에 지정되어 있지 않습니다"
+
+#: commands/sequence.c:811 commands/sequence.c:817
+#, c-format
+msgid "lastval is not yet defined in this session"
+msgstr "이 세션에는 lastval 값이 아직까지 지정되지 않았습니다"
+
+#: commands/sequence.c:893
+#, c-format
+msgid "setval: value %s is out of bounds for sequence \"%s\" (%s..%s)"
+msgstr "setval: %s 값은 \"%s\" 시퀀스의 범위(%s..%s)를 벗어났습니다"
+
+#: commands/sequence.c:1267
+#, c-format
+msgid "INCREMENT must not be zero"
+msgstr "INCREMENT 값은 0(zero)이 될 수 없습니다"
+
+#: commands/sequence.c:1323
+#, c-format
+msgid "MINVALUE (%s) must be less than MAXVALUE (%s)"
+msgstr "MINVALUE (%s) 값은 MAXVALUE (%s) 값보다 작아야합니다"
+
+#: commands/sequence.c:1348
+#, c-format
+msgid "START value (%s) cannot be less than MINVALUE (%s)"
+msgstr "START 값(%s)은 MINVALUE(%s)보다 작을 수 없음"
+
+#: commands/sequence.c:1360
+#, c-format
+msgid "START value (%s) cannot be greater than MAXVALUE (%s)"
+msgstr "START 값(%s)은 MAXVALUE(%s)보다 클 수 없음"
+
+#: commands/sequence.c:1390
+#, c-format
+msgid "RESTART value (%s) cannot be less than MINVALUE (%s)"
+msgstr "RESTART 값(%s)은 MINVALUE(%s)보다 작을 수 없음"
+
+#: commands/sequence.c:1402
+#, c-format
+msgid "RESTART value (%s) cannot be greater than MAXVALUE (%s)"
+msgstr "RESTART 값(%s)은 MAXVALUE(%s)보다 클 수 없음"
+
+#: commands/sequence.c:1417
+#, c-format
+msgid "CACHE (%s) must be greater than zero"
+msgstr "CACHE (%s) 값은 0(zero)보다 커야합니다"
+
+#: commands/sequence.c:1449
+#, c-format
+msgid "invalid OWNED BY option"
+msgstr "잘못된 OWNED BY 옵션"
+
+#: commands/sequence.c:1450
+#, c-format
+msgid "Specify OWNED BY table.column or OWNED BY NONE."
+msgstr "OWNED BY 테이블.열 또는 OWNED BY NONE을 지정하십시오."
+
+#: commands/sequence.c:1473
+#, c-format
+msgid "referenced relation \"%s\" is not a table or foreign table"
+msgstr "참조되는 \"%s\" 릴레이션은 테이블 또는 외부 테이블이 아닙니다"
+
+#: commands/sequence.c:1480
+#, c-format
+msgid "sequence must have same owner as table it is linked to"
+msgstr "시퀀스 및 이 시퀀스가 연결된 테이블의 소유주가 같아야 함"
+
+#: commands/sequence.c:1484
+#, c-format
+msgid "sequence must be in same schema as table it is linked to"
+msgstr "시퀀스 및 이 시퀀스가 연결된 테이블이 같은 스키마에 있어야 함"
+
+#: commands/tablecmds.c:216
+#, c-format
+msgid "table \"%s\" does not exist"
+msgstr "\"%s\" 테이블 없음"
+
+#: commands/tablecmds.c:217
+#, c-format
+msgid "table \"%s\" does not exist, skipping"
+msgstr "\"%s\" 테이블 없음, 무시함"
+
+#: commands/tablecmds.c:219
+msgid "Use DROP TABLE to remove a table."
+msgstr "테이블을 삭제하려면, DROP TABLE 명령을 사용하세요."
+
+#: commands/tablecmds.c:222
+#, c-format
+msgid "sequence \"%s\" does not exist"
+msgstr "\"%s\" 시퀀스 없음"
+
+#: commands/tablecmds.c:223
+#, c-format
+msgid "sequence \"%s\" does not exist, skipping"
+msgstr "\"%s\" 시퀀스 없음, 무시함"
+
+#: commands/tablecmds.c:225
+msgid "Use DROP SEQUENCE to remove a sequence."
+msgstr "시퀀스를 삭제하려면 DROP SEQUENCE 명령을 사용하세요."
+
+#: commands/tablecmds.c:228
+#, c-format
+msgid "view \"%s\" does not exist"
+msgstr "\"%s\" 뷰(view) 없음"
+
+#: commands/tablecmds.c:229
+#, c-format
+msgid "view \"%s\" does not exist, skipping"
+msgstr "\"%s\" 뷰(view) 없음, 무시함"
+
+#: commands/tablecmds.c:231
+msgid "Use DROP VIEW to remove a view."
+msgstr "뷰를 삭제하려면, DROP VIEW 명령을 사용하세요."
+
+#: commands/tablecmds.c:234
+#, c-format
+msgid "materialized view \"%s\" does not exist"
+msgstr "\"%s\" 이름의 구체화된 뷰가 없음"
+
+#: commands/tablecmds.c:235
+#, c-format
+msgid "materialized view \"%s\" does not exist, skipping"
+msgstr "\"%s\" 구체화된 뷰 없음, 건너뜀"
+
+#: commands/tablecmds.c:237
+msgid "Use DROP MATERIALIZED VIEW to remove a materialized view."
+msgstr "구체화된 뷰를 삭제하려면, DROP MATERIALIZED VIEW 명령을 사용하세요."
+
+#: commands/tablecmds.c:240 parser/parse_utilcmd.c:1630
+#, c-format
+msgid "index \"%s\" does not exist"
+msgstr "\"%s\" 인덱스 없음"
+
+#: commands/tablecmds.c:241
+#, c-format
+msgid "index \"%s\" does not exist, skipping"
+msgstr "\"%s\" 인덱스 없음, 무시함"
+
+#: commands/tablecmds.c:243
+msgid "Use DROP INDEX to remove an index."
+msgstr "인덱스를 삭제하려면, DROP INDEX 명령을 사용하세요."
+
+#: commands/tablecmds.c:248
+#, c-format
+msgid "\"%s\" is not a type"
+msgstr "\"%s\" 객체는 자료형이 아님"
+
+#: commands/tablecmds.c:249
+msgid "Use DROP TYPE to remove a type."
+msgstr "자료형을 삭제하려면 DROP TYPE 명령을 사용하세요."
+
+#: commands/tablecmds.c:252 commands/tablecmds.c:8583
+#: commands/tablecmds.c:11335
+#, c-format
+msgid "foreign table \"%s\" does not exist"
+msgstr "\"%s\" 외부 테이블 없음"
+
+#: commands/tablecmds.c:253
+#, c-format
+msgid "foreign table \"%s\" does not exist, skipping"
+msgstr "\"%s\" 외부 테이블 없음, 건너뜀"
+
+#: commands/tablecmds.c:255
+msgid "Use DROP FOREIGN TABLE to remove a foreign table."
+msgstr "외부 테이블을 삭제하려면, DROP FOREIGN TABLE 명령을 사용하세요."
+
+#: commands/tablecmds.c:494
+#, c-format
+msgid "ON COMMIT can only be used on temporary tables"
+msgstr "ON COMMIT 옵션은 임시 테이블에서만 사용될 수 있습니다"
+
+#: commands/tablecmds.c:514
+#, c-format
+msgid "cannot create temporary table within security-restricted operation"
+msgstr "보안 제한 작업 내에서 임시 테이블을 만들 수 없음"
+
+#: commands/tablecmds.c:822
+#, c-format
+msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects"
+msgstr "DROP INDEX CONCURRENTLY 명령은 하나의 인덱스만 지울 수 있습니다"
+
+#: commands/tablecmds.c:826
+#, c-format
+msgid "DROP INDEX CONCURRENTLY does not support CASCADE"
+msgstr "DROP INDEX CONCURRENTLY 명령에서는 CASCADE 옵션을 사용할 수 없음"
+
+#: commands/tablecmds.c:1085
+#, c-format
+msgid "truncate cascades to table \"%s\""
+msgstr "\"%s\" 객체의 자료도 함께 삭제됨"
+
+#: commands/tablecmds.c:1323
+#, c-format
+msgid "cannot truncate temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블 자료는 비울(truncate) 수 없습니다"
+
+#: commands/tablecmds.c:1529 parser/parse_utilcmd.c:1844
+#, c-format
+msgid "inherited relation \"%s\" is not a table or foreign table"
+msgstr "상속할 \"%s\" 릴레이션(relation)은 테이블도, 외부 테이블도 아닙니다"
+
+#: commands/tablecmds.c:1536 commands/tablecmds.c:10150
+#, c-format
+msgid "cannot inherit from temporary relation \"%s\""
+msgstr "\"%s\" 임시 테이블입니다, 그래서 상속 대상이 될 수 없습니다"
+
+#: commands/tablecmds.c:1544 commands/tablecmds.c:10158
+#, c-format
+msgid "cannot inherit from temporary relation of another session"
+msgstr "다른 세션의 임시 테이블입니다, 그래서 상속 대상이 될 수 없습니다"
+
+#: commands/tablecmds.c:1560 commands/tablecmds.c:10192
+#, c-format
+msgid "relation \"%s\" would be inherited from more than once"
+msgstr "\"%s\" 테이블이 여러 번 상속됨"
+
+#: commands/tablecmds.c:1608
+#, c-format
+msgid "merging multiple inherited definitions of column \"%s\""
+msgstr "\"%s\" 칼럼이 중복되어 상속됩니다."
+
+#: commands/tablecmds.c:1616
+#, c-format
+msgid "inherited column \"%s\" has a type conflict"
+msgstr "상위 테이블에서 지정한 \"%s\" 열의 자료형들이 일치하지 않습니다"
+
+#: commands/tablecmds.c:1618 commands/tablecmds.c:1641
+#: commands/tablecmds.c:1839 commands/tablecmds.c:1863
+#: parser/parse_coerce.c:1630 parser/parse_coerce.c:1650
+#: parser/parse_coerce.c:1670 parser/parse_coerce.c:1715
+#: parser/parse_coerce.c:1752 parser/parse_param.c:218
+#, c-format
+msgid "%s versus %s"
+msgstr "%s 형과 %s 형"
+
+#: commands/tablecmds.c:1627
+#, c-format
+msgid "inherited column \"%s\" has a collation conflict"
+msgstr "상속 받은 \"%s\" 칼럼의 정렬규칙에서 충돌합니다."
+
+#: commands/tablecmds.c:1629 commands/tablecmds.c:1851
+#: commands/tablecmds.c:4767
+#, c-format
+msgid "\"%s\" versus \"%s\""
+msgstr "\"%s\" 형과 \"%s\" 형"
+
+#: commands/tablecmds.c:1639
+#, c-format
+msgid "inherited column \"%s\" has a storage parameter conflict"
+msgstr "상속 받은 \"%s\" 칼럼의 스토리지 설정값에서 충돌합니다"
+
+#: commands/tablecmds.c:1752 commands/tablecmds.c:8088
+#: parser/parse_utilcmd.c:923 parser/parse_utilcmd.c:1274
+#: parser/parse_utilcmd.c:1350
+#, c-format
+msgid "cannot convert whole-row table reference"
+msgstr "전체 로우 테이블 참조형으로 변환할 수 없음"
+
+#: commands/tablecmds.c:1753 parser/parse_utilcmd.c:924
+#, c-format
+msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"."
+msgstr "\"%s\" 제약조건에 \"%s\" 테이블 전체 로우 참조가 있습니다"
+
+#: commands/tablecmds.c:1825
+#, c-format
+msgid "merging column \"%s\" with inherited definition"
+msgstr "\"%s\" 칼럼을 상속된 정의와 병합하는 중"
+
+#: commands/tablecmds.c:1829
+#, c-format
+msgid "moving and merging column \"%s\" with inherited definition"
+msgstr "\"%s\" 칼럼을 상속된 정의와 이동, 병합하는 중"
+
+#: commands/tablecmds.c:1830
+#, c-format
+msgid "User-specified column moved to the position of the inherited column."
+msgstr "사용자 지정 칼럼이 상속된 칼럼의 위치로 이동되었습니다"
+
+#: commands/tablecmds.c:1837
+#, c-format
+msgid "column \"%s\" has a type conflict"
+msgstr "\"%s\" 칼럼의 자료형이 충돌합니다"
+
+#: commands/tablecmds.c:1849
+#, c-format
+msgid "column \"%s\" has a collation conflict"
+msgstr "\"%s\" 칼럼의 정렬규칙이 충돌합니다"
+
+#: commands/tablecmds.c:1861
+#, c-format
+msgid "column \"%s\" has a storage parameter conflict"
+msgstr "\"%s\" 칼럼의 스토리지 설정값이 충돌합니다"
+
+#: commands/tablecmds.c:1913
+#, c-format
+msgid "column \"%s\" inherits conflicting default values"
+msgstr ""
+"상속 받는 \"%s\" 열 자료형과 이 열에 지정한 default 값의 자료형이 서로 다릅니"
+"다"
+
+#: commands/tablecmds.c:1915
+#, c-format
+msgid "To resolve the conflict, specify a default explicitly."
+msgstr "이 충돌을 피하려면, default 값을 바르게 지정하십시오."
+
+#: commands/tablecmds.c:1962
+#, c-format
+msgid ""
+"check constraint name \"%s\" appears multiple times but with different "
+"expressions"
+msgstr ""
+"\"%s\" 체크 제약 조건 이름이 여러 번 나타나지만, 각각 다른 식으로 되어있음"
+
+#: commands/tablecmds.c:2156
+#, c-format
+msgid "cannot rename column of typed table"
+msgstr "칼럼 이름을 바꿀 수 없음"
+
+#: commands/tablecmds.c:2173
+#, c-format
+msgid ""
+"\"%s\" is not a table, view, materialized view, composite type, index, or "
+"foreign table"
+msgstr ""
+"\"%s\" 객체는 테이블도, 뷰도, 구체화된 뷰도, 복합 자료형도, 인덱스도, 외부 테"
+"이블도 아닙니다."
+
+#: commands/tablecmds.c:2267
+#, c-format
+msgid "inherited column \"%s\" must be renamed in child tables too"
+msgstr "하위 테이블에서도 상속된 \"%s\" 열의 이름을 바꾸어야 함"
+
+#: commands/tablecmds.c:2299
+#, c-format
+msgid "cannot rename system column \"%s\""
+msgstr "\"%s\" 이름의 열은 시스템 열입니다, 이름을 바꿀 수 없습니다"
+
+#: commands/tablecmds.c:2314
+#, c-format
+msgid "cannot rename inherited column \"%s\""
+msgstr "\"%s\" 이름의 열은 상속 받은 열입니다, 이름을 바꿀 수 없습니다"
+
+#: commands/tablecmds.c:2469
+#, c-format
+msgid "inherited constraint \"%s\" must be renamed in child tables too"
+msgstr ""
+"하위 테이블에서도 상속된 \"%s\" 제약조건은 하위 테이블에서도 이름이 바뀌어야 "
+"함"
+
+#: commands/tablecmds.c:2476
+#, c-format
+msgid "cannot rename inherited constraint \"%s\""
+msgstr "\"%s\" 상속된 제약조건은 이름을 바꿀 수 없습니다"
+
+#. translator: first %s is a SQL command, eg ALTER TABLE
+#: commands/tablecmds.c:2702
+#, c-format
+msgid ""
+"cannot %s \"%s\" because it is being used by active queries in this session"
+msgstr "이 세션의 활성 쿼리에서 사용 중이므로 %s \"%s\" 작업을 할 수 없음"
+
+#. translator: first %s is a SQL command, eg ALTER TABLE
+#: commands/tablecmds.c:2711
+#, c-format
+msgid "cannot %s \"%s\" because it has pending trigger events"
+msgstr "보류 중인 트리거 이벤트가 있으므로 %s \"%s\" 작업을 할 수 없음"
+
+#: commands/tablecmds.c:3785
+#, c-format
+msgid "cannot rewrite system relation \"%s\""
+msgstr "\"%s\" 시스템 릴레이션을 다시 쓰기(rewrite) 할 수 없음"
+
+#: commands/tablecmds.c:3791
+#, c-format
+msgid "cannot rewrite table \"%s\" used as a catalog table"
+msgstr "카탈로그 테이블로 사용되어 \"%s\" 테이블을 rewrite 못함"
+
+#: commands/tablecmds.c:3801
+#, c-format
+msgid "cannot rewrite temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블을 다시 쓰기(rewrite) 할 수 없음"
+
+#: commands/tablecmds.c:4069
+#, c-format
+msgid "rewriting table \"%s\""
+msgstr "\"%s\" 파일 다시 쓰는 중"
+
+#: commands/tablecmds.c:4073
+#, c-format
+msgid "verifying table \"%s\""
+msgstr "\"%s\" 파일 검사 중"
+
+#: commands/tablecmds.c:4187
+#, c-format
+msgid "column \"%s\" contains null values"
+msgstr "\"%s\" 열에는 null 값 자료가 있습니다"
+
+#: commands/tablecmds.c:4202 commands/tablecmds.c:7385
+#, c-format
+msgid "check constraint \"%s\" is violated by some row"
+msgstr "\"%s\" 체크 제약 조건을 위반하는 몇몇 자료가 이미 있습니다"
+
+#: commands/tablecmds.c:4350 commands/trigger.c:235
+#: rewrite/rewriteDefine.c:267 rewrite/rewriteDefine.c:912
+#, c-format
+msgid "\"%s\" is not a table or view"
+msgstr "\"%s\" 객체는 테이블도 뷰도 아닙니다"
+
+#: commands/tablecmds.c:4353 commands/trigger.c:1119 commands/trigger.c:1224
+#, c-format
+msgid "\"%s\" is not a table, view, or foreign table"
+msgstr "\"%s\" 객체는 테이블, 뷰, 외부 테이블 그 어느 것도 아닙니다"
+
+#: commands/tablecmds.c:4356
+#, c-format
+msgid "\"%s\" is not a table, view, materialized view, or index"
+msgstr "\"%s\" 객체는 테이블, 뷰, 구체화된 뷰, 인덱스 그 어느 것도 아닙니다"
+
+#: commands/tablecmds.c:4362
+#, c-format
+msgid "\"%s\" is not a table, materialized view, or index"
+msgstr "\"%s\" 객체는 테이블, 구체화된 뷰, 인덱스 그 어느 것도 아닙니다"
+
+#: commands/tablecmds.c:4365
+#, c-format
+msgid "\"%s\" is not a table, materialized view, or foreign table"
+msgstr "\"%s\" 객체는 테이블, 구체화된 뷰, 외부 테이블 그 어느 것도 아닙니다."
+
+#: commands/tablecmds.c:4368
+#, c-format
+msgid "\"%s\" is not a table or foreign table"
+msgstr "\"%s\" 객체는 테이블도 외부 테이블도 아닙니다"
+
+#: commands/tablecmds.c:4371
+#, c-format
+msgid "\"%s\" is not a table, composite type, or foreign table"
+msgstr "\"%s\" 객체는 테이블, 복합 자료형, 외부 테이블 그 어느 것도 아닙니다."
+
+#: commands/tablecmds.c:4374 commands/tablecmds.c:5426
+#, c-format
+msgid "\"%s\" is not a table, materialized view, index, or foreign table"
+msgstr ""
+"\"%s\" 객체는 테이블, 구체화된 뷰, 인덱스, 외부 테이블 그 어느 것도 아닙니다."
+
+#: commands/tablecmds.c:4384
+#, c-format
+msgid "\"%s\" is of the wrong type"
+msgstr "\"%s\" 객체는 잘못된 객체형입니다."
+
+#: commands/tablecmds.c:4536 commands/tablecmds.c:4543
+#, c-format
+msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it"
+msgstr "\"%s\" 자료형 변경할 수 없음(\"%s.%s\" 칼럼에서 해당 형식을 사용함)"
+
+#: commands/tablecmds.c:4550
+#, c-format
+msgid ""
+"cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type"
+msgstr ""
+"\"%s\" 외부 테이블을 변경할 수 없음(\"%s.%s\" 칼럼에서 해당 로우 형을 사용함)"
+
+#: commands/tablecmds.c:4557
+#, c-format
+msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type"
+msgstr ""
+"\"%s\" 테이블을 변경할 수 없음(\"%s.%s\" 칼럼에서 해당 로우 형식을 사용함)"
+
+#: commands/tablecmds.c:4619
+#, c-format
+msgid "cannot alter type \"%s\" because it is the type of a typed table"
+msgstr ""
+"\"%s\" 자료형을 변경할 수 없음, 이 자료형은 typed 테이블의 자료형이기 때문"
+
+#: commands/tablecmds.c:4621
+#, c-format
+msgid "Use ALTER ... CASCADE to alter the typed tables too."
+msgstr ""
+"이 객체와 관계된 모든 객체들을 함께 변경하려면 ALTER ... CASCADE 명령을 사용"
+"하십시오"
+
+#: commands/tablecmds.c:4665
+#, c-format
+msgid "type %s is not a composite type"
+msgstr "%s 자료형은 복합 자료형이 아닙니다"
+
+#: commands/tablecmds.c:4691
+#, c-format
+msgid "cannot add column to typed table"
+msgstr "typed 테이블에는 칼럼을 추가 할 수 없음"
+
+#: commands/tablecmds.c:4759 commands/tablecmds.c:10351
+#, c-format
+msgid "child table \"%s\" has different type for column \"%s\""
+msgstr ""
+"\"%s\" 상속된 테이블의 \"%s\" 열 자료형이 상위 테이블의 자료형과 틀립니다"
+
+#: commands/tablecmds.c:4765 commands/tablecmds.c:10358
+#, c-format
+msgid "child table \"%s\" has different collation for column \"%s\""
+msgstr ""
+"\"%s\" 상속된 테이블의 \"%s\" 칼럼 정렬규칙이 상위 테이블의 정렬규칙과 틀립니"
+"다"
+
+#: commands/tablecmds.c:4775
+#, c-format
+msgid "child table \"%s\" has a conflicting \"%s\" column"
+msgstr "\"%s\" 하위 테이블에 충돌하는 \"%s\" 칼럼이 있음"
+
+#: commands/tablecmds.c:4787
+#, c-format
+msgid "merging definition of column \"%s\" for child \"%s\""
+msgstr "\"%s\" 열(\"%s\" 하위)의 정의를 병합하는 중"
+
+#: commands/tablecmds.c:5014
+#, c-format
+msgid "column must be added to child tables too"
+msgstr "하위 테이블에도 열을 추가해야 함"
+
+#: commands/tablecmds.c:5089
+#, c-format
+msgid "column \"%s\" of relation \"%s\" already exists, skipping"
+msgstr "\"%s\" 이름의 칼럼이 \"%s\" 릴레이션에 이미 있습니다, 건너뜀"
+
+#: commands/tablecmds.c:5096
+#, c-format
+msgid "column \"%s\" of relation \"%s\" already exists"
+msgstr "\"%s\" 이름의 열이 \"%s\" 릴레이션에 이미 있습니다"
+
+#: commands/tablecmds.c:5207 commands/tablecmds.c:5313
+#: commands/tablecmds.c:5371 commands/tablecmds.c:5485
+#: commands/tablecmds.c:5542 commands/tablecmds.c:5636
+#: commands/tablecmds.c:7924 commands/tablecmds.c:8606
+#, c-format
+msgid "cannot alter system column \"%s\""
+msgstr "\"%s\" 열은 시스템 열입니다. 그래서 변경될 수 없습니다"
+
+#: commands/tablecmds.c:5243
+#, c-format
+msgid "column \"%s\" is in a primary key"
+msgstr "\"%s\" 열은 기본키 열입니다"
+
+#: commands/tablecmds.c:5458
+#, c-format
+msgid "statistics target %d is too low"
+msgstr "대상 통계값(%d)이 너무 낮습니다"
+
+#: commands/tablecmds.c:5466
+#, c-format
+msgid "lowering statistics target to %d"
+msgstr "%d 값으로 대상 통계값을 낮춥니다"
+
+#: commands/tablecmds.c:5616
+#, c-format
+msgid "invalid storage type \"%s\""
+msgstr "잘못된 STORAGE 값: \"%s\""
+
+#: commands/tablecmds.c:5648
+#, c-format
+msgid "column data type %s can only have storage PLAIN"
+msgstr "%s 자료형의 column의 STORAGE 값은 반드시 PLAIN 이어야합니다"
+
+#: commands/tablecmds.c:5686
+#, c-format
+msgid "cannot drop column from typed table"
+msgstr "typed 테이블에서 칼럼을 삭제할 수 없음"
+
+#: commands/tablecmds.c:5730
+#, c-format
+msgid "column \"%s\" of relation \"%s\" does not exist, skipping"
+msgstr "\"%s\" 칼럼은 \"%s\" 릴레이션에 없음, 건너뜀"
+
+#: commands/tablecmds.c:5743
+#, c-format
+msgid "cannot drop system column \"%s\""
+msgstr "\"%s\" 칼럼은 시스템 칼럼입니다, 삭제될 수 없습니다"
+
+#: commands/tablecmds.c:5750
+#, c-format
+msgid "cannot drop inherited column \"%s\""
+msgstr "\"%s\" 칼럼은 상속받은 칼럼입니다, 삭제될 수 없습니다"
+
+#: commands/tablecmds.c:5990
+#, c-format
+msgid ""
+"ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\""
+msgstr ""
+"ALTER TABLE / ADD CONSTRAINT USING INDEX 작업은 \"%s\" 인덱스를 \"%s\" 이름으"
+"로 바꿀 것입니다."
+
+#: commands/tablecmds.c:6203
+#, c-format
+msgid "constraint must be added to child tables too"
+msgstr "하위 테이블에도 제약 조건을 추가해야 함"
+
+#: commands/tablecmds.c:6274
+#, c-format
+msgid "referenced relation \"%s\" is not a table"
+msgstr "참조되는 \"%s\" 릴레이션은 테이블이 아닙니다"
+
+#: commands/tablecmds.c:6297
+#, c-format
+msgid "constraints on permanent tables may reference only permanent tables"
+msgstr "영구 저장용 테이블의 제약 조건은 영구 저장용 테이블을 참조 합니다."
+
+#: commands/tablecmds.c:6304
+#, c-format
+msgid ""
+"constraints on unlogged tables may reference only permanent or unlogged "
+"tables"
+msgstr ""
+"unlogged 테이블의 제약 조건은 영구 저장용 테이블 또는 unlogged 테이블을 참조"
+"합니다."
+
+#: commands/tablecmds.c:6310
+#, c-format
+msgid "constraints on temporary tables may reference only temporary tables"
+msgstr "임시 테이블의 제약 조건은 임시 테이블에 대해서만 참조할 것입니다."
+
+#: commands/tablecmds.c:6314
+#, c-format
+msgid ""
+"constraints on temporary tables must involve temporary tables of this session"
+msgstr ""
+"임시 테이블의 제약 조건은 이 세션용 임시 테이블에 대해서만 적용 됩니다."
+
+#: commands/tablecmds.c:6375
+#, c-format
+msgid "number of referencing and referenced columns for foreign key disagree"
+msgstr "참조키(foreign key) disagree를 위한 참조하는, 또는 참조되는 열 수"
+
+#: commands/tablecmds.c:6482
+#, c-format
+msgid "foreign key constraint \"%s\" cannot be implemented"
+msgstr "\"%s\" 참조키(foreign key) 제약 조건은 구현되어질 수 없습니다"
+
+#: commands/tablecmds.c:6485
+#, c-format
+msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s."
+msgstr ""
+"\"%s\" 열과 \"%s\" 열 인덱스는 함께 사용할 수 없는 자료형입니다: %s and %s."
+
+#: commands/tablecmds.c:6692 commands/tablecmds.c:6860
+#: commands/tablecmds.c:7763 commands/tablecmds.c:7819
+#, c-format
+msgid "constraint \"%s\" of relation \"%s\" does not exist"
+msgstr "\"%s\" 제약 조건이 \"%s\" 릴레이션에 없습니다."
+
+#: commands/tablecmds.c:6698
+#, c-format
+msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint"
+msgstr "\"%s\" 제약 조건(해당 테이블: \"%s\")은 참조키 제약조건이 아닙니다."
+
+#: commands/tablecmds.c:6867
+#, c-format
+msgid ""
+"constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint"
+msgstr ""
+"\"%s\" 제약 조건(해당 테이블: \"%s\")은 참조키도 체크 제약 조건도 아닙니다."
+
+#: commands/tablecmds.c:6935
+#, c-format
+msgid "constraint must be validated on child tables too"
+msgstr "하위 테이블에도 제약 조건이 유효해야 함"
+
+#: commands/tablecmds.c:7004
+#, c-format
+msgid "column \"%s\" referenced in foreign key constraint does not exist"
+msgstr "참조키(foreign key) 제약 조건에서 참조하는 \"%s\" 열이 없음"
+
+#: commands/tablecmds.c:7009
+#, c-format
+msgid "cannot have more than %d keys in a foreign key"
+msgstr "참조키(foreign key)에서 %d 키 개수보다 많이 가질 수 없음"
+
+#: commands/tablecmds.c:7074
+#, c-format
+msgid "cannot use a deferrable primary key for referenced table \"%s\""
+msgstr "참조되는 \"%s\" 테이블의 지연 가능한 기본키를 사용할 수 없음"
+
+#: commands/tablecmds.c:7091
+#, c-format
+msgid "there is no primary key for referenced table \"%s\""
+msgstr "참조되는 \"%s\" 테이블에는 기본키(primary key)가 없습니다"
+
+#: commands/tablecmds.c:7156
+#, c-format
+msgid "foreign key referenced-columns list must not contain duplicates"
+msgstr "참조키의 참조 칼럼 목록에 칼럼이 중복되면 안됩니다"
+
+#: commands/tablecmds.c:7250
+#, c-format
+msgid "cannot use a deferrable unique constraint for referenced table \"%s\""
+msgstr "참조되는 \"%s\" 테이블의 지연 가능한 유니크 제약 조건을 사용할 수 없음"
+
+#: commands/tablecmds.c:7255
+#, c-format
+msgid ""
+"there is no unique constraint matching given keys for referenced table \"%s\""
+msgstr ""
+"참조되는 \"%s\" 테이블을 위한 주워진 키와 일치하는 고유 제약 조건이 없습니다"
+
+#: commands/tablecmds.c:7418
+#, c-format
+msgid "validating foreign key constraint \"%s\""
+msgstr "\"%s\" 참조키 제약 조건 검사 중"
+
+#: commands/tablecmds.c:7717
+#, c-format
+msgid "cannot drop inherited constraint \"%s\" of relation \"%s\""
+msgstr "상속된 \"%s\" 제약 조건(해당 테이블: \"%s\")을 삭제할 수 없음"
+
+#: commands/tablecmds.c:7769
+#, c-format
+msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping"
+msgstr "\"%s\" 제약 조건(해당 테이블: \"%s\")이 없음, 건너뜀"
+
+#: commands/tablecmds.c:7908
+#, c-format
+msgid "cannot alter column type of typed table"
+msgstr "typed 테이블의 칼럼 자료형은 변경할 수 없음"
+
+#: commands/tablecmds.c:7931
+#, c-format
+msgid "cannot alter inherited column \"%s\""
+msgstr "\"%s\" 이름의 열은 상속 받은 열입니다, 이름을 바꿀 수 없습니다"
+
+#: commands/tablecmds.c:7980
+#, c-format
+msgid ""
+"result of USING clause for column \"%s\" cannot be cast automatically to "
+"type %s"
+msgstr ""
+"\"%s\" 칼럼에서 쓰인 USING 절의 결과가 %s 자료형으로 자동 형변환을 할 수 없음"
+
+#: commands/tablecmds.c:7983
+#, c-format
+msgid "You might need to add an explicit cast."
+msgstr "명시적 형변환을 해야할 것 같습니다."
+
+#: commands/tablecmds.c:7987
+#, c-format
+msgid "column \"%s\" cannot be cast automatically to type %s"
+msgstr "\"%s\" 칼럼의 자료형을 %s 형으로 형변환할 수 없음"
+
+#. translator: USING is SQL, don't translate it
+#: commands/tablecmds.c:7990
+#, c-format
+msgid "You might need to specify \"USING %s::%s\"."
+msgstr "\"USING %s::%s\" 구문을 추가해야 할 것 같습니다."
+
+#: commands/tablecmds.c:8089
+#, c-format
+msgid "USING expression contains a whole-row table reference."
+msgstr "USING 표현식에서 전체 로우 테이블 참조를 포함하고 있습니다."
+
+#: commands/tablecmds.c:8100
+#, c-format
+msgid "type of inherited column \"%s\" must be changed in child tables too"
+msgstr "하위 테이블에서도 상속된 \"%s\" 열의 형식을 바꾸어야 함"
+
+#: commands/tablecmds.c:8187
+#, c-format
+msgid "cannot alter type of column \"%s\" twice"
+msgstr "\"%s\" 열은 시스템 열입니다. 그래서 변경될 수 없습니다"
+
+#: commands/tablecmds.c:8223
+#, c-format
+msgid "default for column \"%s\" cannot be cast automatically to type %s"
+msgstr "\"%s\" 칼럼의 기본 값을 %s 형으로 형변환할 수 없음"
+
+#: commands/tablecmds.c:8349
+#, c-format
+msgid "cannot alter type of a column used by a view or rule"
+msgstr "뷰 또는 규칙에서 사용하는 열의 형식을 변경할 수 없음"
+
+#: commands/tablecmds.c:8350 commands/tablecmds.c:8369
+#: commands/tablecmds.c:8387
+#, c-format
+msgid "%s depends on column \"%s\""
+msgstr "%s 의존대상 열: \"%s\""
+
+#: commands/tablecmds.c:8368
+#, c-format
+msgid "cannot alter type of a column used in a trigger definition"
+msgstr "트리거 정의에서 사용하는 칼럼의 자료형을 변경할 수 없음"
+
+#: commands/tablecmds.c:8386
+#, c-format
+msgid "cannot alter type of a column used in a policy definition"
+msgstr "정책 정의에서 사용하는 칼럼의 자료형을 변경할 수 없음"
+
+#: commands/tablecmds.c:9051
+#, c-format
+msgid "cannot change owner of index \"%s\""
+msgstr "\"%s\" 인덱스의 소유주를 바꿀 수 없음"
+
+#: commands/tablecmds.c:9053
+#, c-format
+msgid "Change the ownership of the index's table, instead."
+msgstr "대신에 그 인덱스의 해당 테이블 소유자을 변경하세요."
+
+#: commands/tablecmds.c:9069
+#, c-format
+msgid "cannot change owner of sequence \"%s\""
+msgstr "\"%s\" 시퀀스의 소유주를 바꿀 수 없음"
+
+#: commands/tablecmds.c:9071 commands/tablecmds.c:11543
+#, c-format
+msgid "Sequence \"%s\" is linked to table \"%s\"."
+msgstr "\"%s\" 시퀀스는 \"%s\" 테이블에 종속되어 있습니다."
+
+#: commands/tablecmds.c:9083 commands/tablecmds.c:12190
+#, c-format
+msgid "Use ALTER TYPE instead."
+msgstr "대신 ALTER TYPE을 사용하십시오."
+
+#: commands/tablecmds.c:9092
+#, c-format
+msgid "\"%s\" is not a table, view, sequence, or foreign table"
+msgstr "\"%s\" 객체는 테이블, 뷰, 시퀀스, 외부 테이블 그 어느 것도 아닙니다"
+
+#: commands/tablecmds.c:9435
+#, c-format
+msgid "cannot have multiple SET TABLESPACE subcommands"
+msgstr "SET TABLESPACE 구문이 중복 사용되었습니다"
+
+#: commands/tablecmds.c:9508
+#, c-format
+msgid "\"%s\" is not a table, view, materialized view, index, or TOAST table"
+msgstr ""
+"\"%s\" 객체는 테이블, 뷰, 구체화된 뷰, 인덱스, TOAST 테이블 그 어느 것도 아닙"
+"니다."
+
+#: commands/tablecmds.c:9541 commands/view.c:498
+#, c-format
+msgid "WITH CHECK OPTION is supported only on automatically updatable views"
+msgstr ""
+"WITH CHECK OPTION 옵션은 자동 갱신 가능한 뷰에 대해서만 사용할 수 있습니다"
+
+#: commands/tablecmds.c:9687
+#, c-format
+msgid "cannot move system relation \"%s\""
+msgstr "\"%s\" 시스템 릴레이션입니다. 이동할 수 없습니다"
+
+#: commands/tablecmds.c:9703
+#, c-format
+msgid "cannot move temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블들은 이동할 수 없습니다"
+
+#: commands/tablecmds.c:9840
+#, c-format
+msgid "only tables, indexes, and materialized views exist in tablespaces"
+msgstr "테이블스페이스에 테이블과 인덱스와 구체화된 뷰만 있습니다."
+
+#: commands/tablecmds.c:9852
+#, c-format
+msgid "cannot move relations in to or out of pg_global tablespace"
+msgstr ""
+"해당 객체를 pg_global 테이블스페이스로 옮기거나 그 반대로 작업할 수 없음"
+
+#: commands/tablecmds.c:9943
+#, c-format
+msgid "aborting because lock on relation \"%s.%s\" is not available"
+msgstr "\"%s.%s\" 릴레이션을 잠글 수 없어 중지 중입니다"
+
+#: commands/tablecmds.c:9959
+#, c-format
+msgid "no matching relations in tablespace \"%s\" found"
+msgstr "검색조건에 일치하는 릴레이션이 \"%s\" 테이블스페이스에 없음"
+
+#: commands/tablecmds.c:10033 storage/buffer/bufmgr.c:915
+#, c-format
+msgid "invalid page in block %u of relation %s"
+msgstr "%u 블록(해당 릴레이션: %s)에 잘못된 페이지가 있음"
+
+#: commands/tablecmds.c:10115
+#, c-format
+msgid "cannot change inheritance of typed table"
+msgstr "typed 테이블의 상속 정보는 변경할 수 없음"
+
+#: commands/tablecmds.c:10165
+#, c-format
+msgid "cannot inherit to temporary relation of another session"
+msgstr "다른 세션의 임시 테이블을 상속할 수 없음"
+
+#: commands/tablecmds.c:10219
+#, c-format
+msgid "circular inheritance not allowed"
+msgstr "순환 되는 상속은 허용하지 않습니다"
+
+#: commands/tablecmds.c:10220
+#, c-format
+msgid "\"%s\" is already a child of \"%s\"."
+msgstr "\"%s\" 객체는 이미 \"%s\" 객체로부터 상속받은 상태입니다."
+
+#: commands/tablecmds.c:10228
+#, c-format
+msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgstr ""
+"\"%s\" 테이블이 OID 열 없이 OID 있는 \"%s\" 테이블에서 상속 될 수 없습니다."
+
+#: commands/tablecmds.c:10369
+#, c-format
+msgid "column \"%s\" in child table must be marked NOT NULL"
+msgstr "자식 테이블의 \"%s\" 열은 NOT NULL 속성이 있어야합니다"
+
+#: commands/tablecmds.c:10385 commands/tablecmds.c:10418
+#, c-format
+msgid "child table is missing column \"%s\""
+msgstr "자식 테이블에는 \"%s\" 열이 없습니다"
+
+#: commands/tablecmds.c:10501
+#, c-format
+msgid "child table \"%s\" has different definition for check constraint \"%s\""
+msgstr "\"%s\" 하위 테이블에 \"%s\" 체크 제약 조건에 대한 다른 정의가 있음"
+
+#: commands/tablecmds.c:10509
+#, c-format
+msgid ""
+"constraint \"%s\" conflicts with non-inherited constraint on child table \"%s"
+"\""
+msgstr ""
+"\"%s\" 제약 조건이 \"%s\" 하위 테이블에 있는 비 상속 제약 조건과 충돌합니다"
+
+#: commands/tablecmds.c:10520
+#, c-format
+msgid ""
+"constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\""
+msgstr ""
+"\"%s\" 제약 조건이 \"%s\" 하위 테이블에 있는 NOT VALID 제약 조건과 충돌합니다"
+
+#: commands/tablecmds.c:10544
+#, c-format
+msgid "child table is missing constraint \"%s\""
+msgstr "자식 테이블에 \"%s\" 제약 조건이 없습니다"
+
+#: commands/tablecmds.c:10628
+#, c-format
+msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgstr "\"%s\" 릴레이션은 \"%s\" 릴레이션의 부모가 아닙니다"
+
+#: commands/tablecmds.c:10862
+#, c-format
+msgid "typed tables cannot inherit"
+msgstr "typed 테이블은 상속할 수 없음"
+
+#: commands/tablecmds.c:10893
+#, c-format
+msgid "table is missing column \"%s\""
+msgstr "테이블에는 \"%s\" 칼럼이 없습니다"
+
+#: commands/tablecmds.c:10903
+#, c-format
+msgid "table has column \"%s\" where type requires \"%s\""
+msgstr "\"%s\" 칼럼은 \"%s\" 자료형입니다."
+
+#: commands/tablecmds.c:10912
+#, c-format
+msgid "table \"%s\" has different type for column \"%s\""
+msgstr "\"%s\" 테이블의 \"%s\" 칼럼 자료형 틀립니다"
+
+#: commands/tablecmds.c:10925
+#, c-format
+msgid "table has extra column \"%s\""
+msgstr "\"%s\" 칼럼은 확장형입니다"
+
+#: commands/tablecmds.c:10977
+#, c-format
+msgid "\"%s\" is not a typed table"
+msgstr "\"%s\" 테이블은 typed 테이블이 아닙니다"
+
+#: commands/tablecmds.c:11161
+#, c-format
+msgid "cannot use non-unique index \"%s\" as replica identity"
+msgstr "\"%s\" 인덱스는 유니크 인덱스가 아니여서, 복제 식별자로 사용할 수 없음"
+
+#: commands/tablecmds.c:11167
+#, c-format
+msgid "cannot use non-immediate index \"%s\" as replica identity"
+msgstr "\"%s\" non-immediate 인덱스는 복제 식별자로 사용할 수 없음"
+
+#: commands/tablecmds.c:11173
+#, c-format
+msgid "cannot use expression index \"%s\" as replica identity"
+msgstr "\"%s\" 인덱스는 expression 인덱스여서, 복제 식별자로 사용할 수 없음"
+
+#: commands/tablecmds.c:11179
+#, c-format
+msgid "cannot use partial index \"%s\" as replica identity"
+msgstr "\"%s\" 인덱스가 부분인덱스여서, 복제 식별자로 사용할 수 없음"
+
+#: commands/tablecmds.c:11185
+#, c-format
+msgid "cannot use invalid index \"%s\" as replica identity"
+msgstr ""
+"\"%s\" 인덱스는 사용할 수 없는 인덱스여서, 복제 식별자로 사용할 수 없음"
+
+#: commands/tablecmds.c:11206
+#, c-format
+msgid ""
+"index \"%s\" cannot be used as replica identity because column %d is a "
+"system column"
+msgstr ""
+"\"%s\" 인덱스는 복제 식별자로 사용할 수 없음, %d 번째 칼럼이 시스템 칼럼임"
+
+#: commands/tablecmds.c:11213
+#, c-format
+msgid ""
+"index \"%s\" cannot be used as replica identity because column \"%s\" is "
+"nullable"
+msgstr ""
+"\"%s\" 인덱스는 복제 식별자로 사용할 수 없음, \"%s\" 칼럼이 null 값 사용가능 "
+"속성임"
+
+#: commands/tablecmds.c:11416
+#, c-format
+msgid "cannot change logged status of table \"%s\" because it is temporary"
+msgstr "\"%s\" 테이블은 임시 테이블이기에, 통계 정보를 변경 할 수 없음"
+
+#: commands/tablecmds.c:11475
+#, c-format
+msgid ""
+"could not change table \"%s\" to logged because it references unlogged table "
+"\"%s\""
+msgstr ""
+"\"%s\" 테이블이 \"%s\" unlogged 테이블을 참조하고 있어 logged 속성으로 바꿀 "
+"수 없음"
+
+#: commands/tablecmds.c:11485
+#, c-format
+msgid ""
+"could not change table \"%s\" to unlogged because it references logged table "
+"\"%s\""
+msgstr ""
+"\"%s\" 테이블이 \"%s\" logged 테이블을 참조하고 있어 unlogged 속성으로 바꿀 "
+"수 없음"
+
+#: commands/tablecmds.c:11542
+#, c-format
+msgid "cannot move an owned sequence into another schema"
+msgstr "소유된 시퀀스를 다른 스키마로 이동할 수 없음"
+
+#: commands/tablecmds.c:11647
+#, c-format
+msgid "relation \"%s\" already exists in schema \"%s\""
+msgstr "\"%s\" 릴레이션이 \"%s\" 스키마에 이미 있습니다"
+
+#: commands/tablecmds.c:12174
+#, c-format
+msgid "\"%s\" is not a composite type"
+msgstr "\"%s\" 객체는 복합 자료형입니다"
+
+#: commands/tablecmds.c:12204
+#, c-format
+msgid ""
+"\"%s\" is not a table, view, materialized view, sequence, or foreign table"
+msgstr ""
+"\"%s\" 객체는 테이블, 뷰, 구체화된 뷰, 시퀀스, 외부 테이블 그 어느 것도 아닙"
+"니다"
+
+#: commands/tablespace.c:162 commands/tablespace.c:179
+#: commands/tablespace.c:190 commands/tablespace.c:198
+#: commands/tablespace.c:625 replication/slot.c:980 storage/file/copydir.c:47
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 만들 수 없음: %m"
+
+#: commands/tablespace.c:209
+#, c-format
+msgid "could not stat directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리 상태를 파악할 수 없음: %m"
+
+#: commands/tablespace.c:218
+#, c-format
+msgid "\"%s\" exists but is not a directory"
+msgstr "\"%s\" 파일이 존재하지만 디렉터리가 아닙니다"
+
+#: commands/tablespace.c:249
+#, c-format
+msgid "permission denied to create tablespace \"%s\""
+msgstr "\"%s\" 테이블스페이스를 만들 권한이 없습니다"
+
+#: commands/tablespace.c:251
+#, c-format
+msgid "Must be superuser to create a tablespace."
+msgstr "테이블스페이스는 슈퍼유저만 만들 수 있습니다."
+
+#: commands/tablespace.c:267
+#, c-format
+msgid "tablespace location cannot contain single quotes"
+msgstr "테이블스페이스 위치에는 작은 따옴표를 사용할 수 없음"
+
+#: commands/tablespace.c:277
+#, c-format
+msgid "tablespace location must be an absolute path"
+msgstr "테이블스페이스 경로는 절대경로여야합니다"
+
+#: commands/tablespace.c:288
+#, c-format
+msgid "tablespace location \"%s\" is too long"
+msgstr "테이블스페이스 경로가 너무 깁니다: \"%s\""
+
+#: commands/tablespace.c:295
+#, c-format
+msgid "tablespace location should not be inside the data directory"
+msgstr "테이블스페이스 경로는 데이터 디렉토리 안에 있으면 안됩니다"
+
+#: commands/tablespace.c:304 commands/tablespace.c:952
+#, c-format
+msgid "unacceptable tablespace name \"%s\""
+msgstr "\"%s\" 테이블스페이스 이름은 적당치 않습니다"
+
+#: commands/tablespace.c:306 commands/tablespace.c:953
+#, c-format
+msgid "The prefix \"pg_\" is reserved for system tablespaces."
+msgstr "\"pg_\" 문자로 시작하는 테이블스페이스는 시스템 테이블스페이스입니다."
+
+#: commands/tablespace.c:316 commands/tablespace.c:965
+#, c-format
+msgid "tablespace \"%s\" already exists"
+msgstr "\"%s\" 이름의 테이블스페이스는 이미 있음"
+
+#: commands/tablespace.c:430 commands/tablespace.c:935
+#: commands/tablespace.c:1016 commands/tablespace.c:1085
+#: commands/tablespace.c:1218 commands/tablespace.c:1418
+#, c-format
+msgid "tablespace \"%s\" does not exist"
+msgstr "\"%s\" 테이블스페이스 없음"
+
+#: commands/tablespace.c:436
+#, c-format
+msgid "tablespace \"%s\" does not exist, skipping"
+msgstr "\"%s\" 테이블스페이스 없음, 건너 뜀"
+
+#: commands/tablespace.c:512
+#, c-format
+msgid "tablespace \"%s\" is not empty"
+msgstr "\"%s\" 테이블스페이스는 비어있지 않음"
+
+#: commands/tablespace.c:584
+#, c-format
+msgid "directory \"%s\" does not exist"
+msgstr "\"%s\" 디렉터리 없음"
+
+#: commands/tablespace.c:585
+#, c-format
+msgid "Create this directory for the tablespace before restarting the server."
+msgstr "이 서버를 재시작하기 전에 이 테이블스페이스 용 디렉터리를 만드세요."
+
+#: commands/tablespace.c:590
+#, c-format
+msgid "could not set permissions on directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리 액세스 권한을 지정할 수 없음: %m"
+
+#: commands/tablespace.c:620
+#, c-format
+msgid "directory \"%s\" already in use as a tablespace"
+msgstr "\"%s\" 디렉터리는 이미 테이블스페이스로 사용 중임"
+
+#: commands/tablespace.c:744 commands/tablespace.c:757
+#: commands/tablespace.c:793 commands/tablespace.c:885
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 삭제할 수 없음: %m"
+
+#: commands/tablespace.c:806 commands/tablespace.c:894
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "\"%s\" 심벌릭 링크를 삭제할 수 없음: %m"
+
+#: commands/tablespace.c:816 commands/tablespace.c:903
+#, c-format
+msgid "\"%s\" is not a directory or symbolic link"
+msgstr "\"%s\" 디렉터리도, 심볼릭 링크도 아님"
+
+#: commands/tablespace.c:1090
+#, c-format
+msgid "Tablespace \"%s\" does not exist."
+msgstr "\"%s\" 테이블스페이스 없음"
+
+#: commands/tablespace.c:1517
+#, c-format
+msgid "directories for tablespace %u could not be removed"
+msgstr "%u OID 테이블스페이스용 디렉터리는 삭제될 수 없음"
+
+#: commands/tablespace.c:1519
+#, c-format
+msgid "You can remove the directories manually if necessary."
+msgstr "필요하다면 OS 작업으로 그 디레터리를 삭제하세요"
+
+#: commands/trigger.c:184
+#, c-format
+msgid "\"%s\" is a table"
+msgstr "\"%s\" 객체는 테이블입니다."
+
+#: commands/trigger.c:186
+#, c-format
+msgid "Tables cannot have INSTEAD OF triggers."
+msgstr "테이블에 INSTEAD OF 트리거는 설정할 수 없음"
+
+#: commands/trigger.c:197 commands/trigger.c:204
+#, c-format
+msgid "\"%s\" is a view"
+msgstr "\"%s\" 객체는 뷰입니다."
+
+#: commands/trigger.c:199
+#, c-format
+msgid "Views cannot have row-level BEFORE or AFTER triggers."
+msgstr "뷰에 로우 단위 BEFORE, AFTER 트리거는 설정할 수 없음"
+
+#: commands/trigger.c:206
+#, c-format
+msgid "Views cannot have TRUNCATE triggers."
+msgstr "뷰에 TRUNCATE 트리거는 설정할 수 없음"
+
+#: commands/trigger.c:214 commands/trigger.c:221 commands/trigger.c:228
+#, c-format
+msgid "\"%s\" is a foreign table"
+msgstr "\"%s\" 객체는 외부 테이블입니다."
+
+#: commands/trigger.c:216
+#, c-format
+msgid "Foreign tables cannot have INSTEAD OF triggers."
+msgstr "외부테이블에 INSTEAD OF 트리거는 설정할 수 없음"
+
+#: commands/trigger.c:223
+#, c-format
+msgid "Foreign tables cannot have TRUNCATE triggers."
+msgstr "외부 테이블에는 TRUNCATE 트리거를 사용할 수 없음"
+
+#: commands/trigger.c:230
+#, c-format
+msgid "Foreign tables cannot have constraint triggers."
+msgstr "외부 테이블에 제약 조건 트리거는 설정할 수 없음"
+
+#: commands/trigger.c:293
+#, c-format
+msgid "TRUNCATE FOR EACH ROW triggers are not supported"
+msgstr "TRUNCATE FOR EACH ROW 트리거는 지원되지 않음"
+
+#: commands/trigger.c:301
+#, c-format
+msgid "INSTEAD OF triggers must be FOR EACH ROW"
+msgstr "INSTEAD OF 트리거는 FOR EACH ROW 옵션으로 설정해야 함"
+
+#: commands/trigger.c:305
+#, c-format
+msgid "INSTEAD OF triggers cannot have WHEN conditions"
+msgstr "INSTEAD OF 트리거는 WHEN 조건을 사용할 수 없음"
+
+#: commands/trigger.c:309
+#, c-format
+msgid "INSTEAD OF triggers cannot have column lists"
+msgstr "INSTEAD OF 트리거는 칼럼 목록을 사용할 수 없음"
+
+#: commands/trigger.c:366 commands/trigger.c:379
+#, c-format
+msgid "statement trigger's WHEN condition cannot reference column values"
+msgstr "트리거의 WHEN 조건에는 칼럼 값을 참조할 수는 없음"
+
+#: commands/trigger.c:371
+#, c-format
+msgid "INSERT trigger's WHEN condition cannot reference OLD values"
+msgstr "INSERT 트리거에서의 WHEN 조건에는 OLD 값을 참조할 수 없음"
+
+#: commands/trigger.c:384
+#, c-format
+msgid "DELETE trigger's WHEN condition cannot reference NEW values"
+msgstr "DELETE 트리거에서의 WHEN 조건에는 NEW 값을 참조할 수 없음"
+
+#: commands/trigger.c:389
+#, c-format
+msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns"
+msgstr "WHEN 조건절이 있는 BEFORE 트리거는 NEW 시스템 칼럼을 참조할 수 없음"
+
+#: commands/trigger.c:434
+#, c-format
+msgid "changing return type of function %s from \"opaque\" to \"trigger\""
+msgstr "%s 함수의 리턴 자료형을 \"opaque\"에서 \"trigger\"로 바꿉니다"
+
+#: commands/trigger.c:553 commands/trigger.c:1303
+#, c-format
+msgid "trigger \"%s\" for relation \"%s\" already exists"
+msgstr "\"%s\" 이름의 트리거가 \"%s\" 테이블에 이미 있습니다"
+
+#: commands/trigger.c:838
+msgid "Found referenced table's UPDATE trigger."
+msgstr "참조된 테이블의 UPDATE 트리거를 찾았습니다."
+
+#: commands/trigger.c:839
+msgid "Found referenced table's DELETE trigger."
+msgstr "참조된 테이블의 DELETE 트리거를 찾았습니다."
+
+#: commands/trigger.c:840
+msgid "Found referencing table's trigger."
+msgstr "참조 테이블의 트리거를 찾았습니다."
+
+#: commands/trigger.c:949 commands/trigger.c:965
+#, c-format
+msgid "ignoring incomplete trigger group for constraint \"%s\" %s"
+msgstr "\"%s\" %s 제약 조건에 대한 불완전한 트리거 그룹을 무시하는 중"
+
+#: commands/trigger.c:977
+#, c-format
+msgid "converting trigger group into constraint \"%s\" %s"
+msgstr "트리거 그룹을 \"%s\" %s 제약 조건으로 변환하는 중"
+
+#: commands/trigger.c:1190 commands/trigger.c:1351 commands/trigger.c:1469
+#, c-format
+msgid "trigger \"%s\" for table \"%s\" does not exist"
+msgstr "\"%s\" 트리거는 \"%s\" 테이블에 없음"
+
+#: commands/trigger.c:1434
+#, c-format
+msgid "permission denied: \"%s\" is a system trigger"
+msgstr "액세스 권한 없음: \"%s\" 객체는 시스템 트리거임"
+
+#: commands/trigger.c:1930
+#, c-format
+msgid "trigger function %u returned null value"
+msgstr "%u 트리거 함수가 null 값을 리턴했습니다"
+
+#: commands/trigger.c:1989 commands/trigger.c:2188 commands/trigger.c:2392
+#: commands/trigger.c:2664
+#, c-format
+msgid "BEFORE STATEMENT trigger cannot return a value"
+msgstr "BEFORE STATEMENT 트리거는 리턴값이 있으면 안됩니다"
+
+#: commands/trigger.c:2726 executor/nodeModifyTable.c:679
+#: executor/nodeModifyTable.c:972
+#, c-format
+msgid ""
+"tuple to be updated was already modified by an operation triggered by the "
+"current command"
+msgstr ""
+"현재 명령으로 실행된 트리거 작업으로 변경해야할 자료가 이미 바뀌었습니다."
+
+#: commands/trigger.c:2727 executor/nodeModifyTable.c:680
+#: executor/nodeModifyTable.c:973
+#, c-format
+msgid ""
+"Consider using an AFTER trigger instead of a BEFORE trigger to propagate "
+"changes to other rows."
+msgstr ""
+"다른 로우를 변경하는 일을 BEFORE 트리거 대신에 AFTER 트리거 사용을 고려해 보"
+"십시오"
+
+#: commands/trigger.c:2741 executor/execMain.c:2379
+#: executor/nodeLockRows.c:216 executor/nodeModifyTable.c:213
+#: executor/nodeModifyTable.c:692 executor/nodeModifyTable.c:985
+#: executor/nodeModifyTable.c:1151
+#, c-format
+msgid "could not serialize access due to concurrent update"
+msgstr "동시 업데이트 때문에 순차적 액세스가 불가능합니다"
+
+#: commands/trigger.c:4575
+#, c-format
+msgid "constraint \"%s\" is not deferrable"
+msgstr "\"%s\" 제약 조건은 DEFERRABLE 속성으로 만들어지지 않았습니다"
+
+#: commands/trigger.c:4598
+#, c-format
+msgid "constraint \"%s\" does not exist"
+msgstr "\"%s\" 이름의 제약 조건이 없음"
+
+#: commands/tsearchcmds.c:115 commands/tsearchcmds.c:685
+#, c-format
+msgid "function %s should return type %s"
+msgstr "%s 함수는 %s 자료형을 반환해야 함"
+
+#: commands/tsearchcmds.c:192
+#, c-format
+msgid "must be superuser to create text search parsers"
+msgstr "슈퍼유저만 전문 검색 파서를 만들 수 있음"
+
+#: commands/tsearchcmds.c:240
+#, c-format
+msgid "text search parser parameter \"%s\" not recognized"
+msgstr "\"%s\" 전문 검색 파서 매개 변수를 인식할 수 없음"
+
+#: commands/tsearchcmds.c:250
+#, c-format
+msgid "text search parser start method is required"
+msgstr "텍스트 검색 파서 start 메서드가 필요함"
+
+#: commands/tsearchcmds.c:255
+#, c-format
+msgid "text search parser gettoken method is required"
+msgstr "텍스트 검색 파서 gettoken 메서드가 필요함"
+
+#: commands/tsearchcmds.c:260
+#, c-format
+msgid "text search parser end method is required"
+msgstr "텍스트 검색 파서 end 메서드가 필요함"
+
+#: commands/tsearchcmds.c:265
+#, c-format
+msgid "text search parser lextypes method is required"
+msgstr "텍스트 검색 파서 lextypes 메서드가 필요함"
+
+#: commands/tsearchcmds.c:386
+#, c-format
+msgid "text search template \"%s\" does not accept options"
+msgstr "\"%s\" 전문 검색 템플릿이 옵션을 수락하지 않음"
+
+#: commands/tsearchcmds.c:460
+#, c-format
+msgid "text search template is required"
+msgstr "전문 검색 템플릿이 필요함"
+
+#: commands/tsearchcmds.c:752
+#, c-format
+msgid "must be superuser to create text search templates"
+msgstr "슈퍼유저만 전문 검색 템플릿을 만들 수 있음"
+
+#: commands/tsearchcmds.c:789
+#, c-format
+msgid "text search template parameter \"%s\" not recognized"
+msgstr "\"%s\" 전문 검색 템플릿 매개 변수를 인식할 수 없음"
+
+#: commands/tsearchcmds.c:799
+#, c-format
+msgid "text search template lexize method is required"
+msgstr "전문 검색 템플릿 lexize 메서드가 필요함"
+
+#: commands/tsearchcmds.c:1008
+#, c-format
+msgid "text search configuration parameter \"%s\" not recognized"
+msgstr "\"%s\" 전문 검색 구성 매개 변수를 인식할 수 없음"
+
+#: commands/tsearchcmds.c:1015
+#, c-format
+msgid "cannot specify both PARSER and COPY options"
+msgstr "PARSER 옵션과 COPY 옵션을 모두 지정할 수 없음"
+
+#: commands/tsearchcmds.c:1051
+#, c-format
+msgid "text search parser is required"
+msgstr "전문 검색 파서가 필요함"
+
+#: commands/tsearchcmds.c:1278
+#, c-format
+msgid "token type \"%s\" does not exist"
+msgstr "\"%s\" 토큰 형식이 없음"
+
+#: commands/tsearchcmds.c:1502
+#, c-format
+msgid "mapping for token type \"%s\" does not exist"
+msgstr "\"%s\" 토큰 형식에 대한 매핑이 없음"
+
+#: commands/tsearchcmds.c:1508
+#, c-format
+msgid "mapping for token type \"%s\" does not exist, skipping"
+msgstr "\"%s\" 토큰 형식에 대한 매핑이 없음, 건너뜀"
+
+#: commands/tsearchcmds.c:1663 commands/tsearchcmds.c:1774
+#, c-format
+msgid "invalid parameter list format: \"%s\""
+msgstr "잘못된 매개 변수 목록 형식: \"%s\""
+
+#: commands/typecmds.c:181
+#, c-format
+msgid "must be superuser to create a base type"
+msgstr "슈퍼유저만 기본 형식을 만들 수 있음"
+
+#: commands/typecmds.c:288 commands/typecmds.c:1421
+#, c-format
+msgid "type attribute \"%s\" not recognized"
+msgstr "잘못된 \"%s\" 속성의 자료형"
+
+#: commands/typecmds.c:342
+#, c-format
+msgid "invalid type category \"%s\": must be simple ASCII"
+msgstr "\"%s\" 형식 범주가 잘못됨: 단순 ASCII여야 함"
+
+#: commands/typecmds.c:361
+#, c-format
+msgid "array element type cannot be %s"
+msgstr "배열 요소의 자료형으로 %s 자료형을 사용할 수 없습니다"
+
+#: commands/typecmds.c:393
+#, c-format
+msgid "alignment \"%s\" not recognized"
+msgstr "잘못된 ALIGNMENT 값: \"%s\""
+
+#: commands/typecmds.c:410
+#, c-format
+msgid "storage \"%s\" not recognized"
+msgstr "잘못된 STORAGE 값: \"%s\""
+
+#: commands/typecmds.c:421
+#, c-format
+msgid "type input function must be specified"
+msgstr "자료형 입력 함수를 지정하십시오"
+
+#: commands/typecmds.c:425
+#, c-format
+msgid "type output function must be specified"
+msgstr "자료형 출력 함수를 지정하십시오"
+
+#: commands/typecmds.c:430
+#, c-format
+msgid ""
+"type modifier output function is useless without a type modifier input "
+"function"
+msgstr "형식 한정자 입력 함수가 없으면 형식 한정자 출력 함수는 의미가 없음"
+
+#: commands/typecmds.c:453 commands/typecmds.c:470
+#, c-format
+msgid "changing return type of function %s from %s to %s"
+msgstr "%s 함수의 반환 자료형을 %s에서 %s 자료형으로 바꿉니다"
+
+#: commands/typecmds.c:460
+#, c-format
+msgid "type input function %s must return type %s"
+msgstr "자료형 %s 입력 함수의 %s 자료형을 반환해야합니다"
+
+#: commands/typecmds.c:477
+#, c-format
+msgid "type output function %s must return type %s"
+msgstr "%s 자료형 출력 함수는 %s 자료형을 반환해야합니다"
+
+#: commands/typecmds.c:486
+#, c-format
+msgid "type receive function %s must return type %s"
+msgstr "%s 자료형 receive 함수는 %s 자료형을 반환해야합니다"
+
+#: commands/typecmds.c:495
+#, c-format
+msgid "type send function %s must return type %s"
+msgstr "%s 자료형 전송 함수는 %s 자료형을 반환해야합니다"
+
+#: commands/typecmds.c:560
+#, c-format
+msgid "type input function %s should not be volatile"
+msgstr "%s 자료형 입력 함수는 volatile 특성이 없어야합니다"
+
+#: commands/typecmds.c:565
+#, c-format
+msgid "type output function %s should not be volatile"
+msgstr "%s 자료형 출력 함수는 volatile 특성이 없어야합니다"
+
+#: commands/typecmds.c:570
+#, c-format
+msgid "type receive function %s should not be volatile"
+msgstr "%s 자료형 수신 함수는 volatile 특성이 없어야합니다"
+
+#: commands/typecmds.c:575
+#, c-format
+msgid "type send function %s should not be volatile"
+msgstr "%s 자료형 송신 함수는 volatile 특성이 없어야합니다"
+
+#: commands/typecmds.c:580
+#, c-format
+msgid "type modifier input function %s should not be volatile"
+msgstr "%s 자료형 형변환 입력 함수는 volatile 특성이 없어야합니다"
+
+#: commands/typecmds.c:585
+#, c-format
+msgid "type modifier output function %s should not be volatile"
+msgstr "%s 자료형 형변환 출력 함수는 volatile 특성이 없어야합니다"
+
+#: commands/typecmds.c:807
+#, c-format
+msgid "\"%s\" is not a valid base type for a domain"
+msgstr "\"%s\" 자료형은 도메인의 기반 자료형이 아닙니다"
+
+#: commands/typecmds.c:893
+#, c-format
+msgid "multiple default expressions"
+msgstr "default 표현식 여러개 있음"
+
+#: commands/typecmds.c:955 commands/typecmds.c:964
+#, c-format
+msgid "conflicting NULL/NOT NULL constraints"
+msgstr "NULL/NOT NULL 조건이 함께 있음"
+
+#: commands/typecmds.c:980
+#, c-format
+msgid "check constraints for domains cannot be marked NO INHERIT"
+msgstr "도메인용 체크 제약 조건에는 NO INHERIT 옵션을 사용할 수 없음"
+
+#: commands/typecmds.c:989 commands/typecmds.c:2522
+#, c-format
+msgid "unique constraints not possible for domains"
+msgstr "고유 제약 조건은 도메인 정의에 사용할 수 없음"
+
+#: commands/typecmds.c:995 commands/typecmds.c:2528
+#, c-format
+msgid "primary key constraints not possible for domains"
+msgstr "기본키 제약 조건을 도메인 정의에 사용할 수 없음"
+
+#: commands/typecmds.c:1001 commands/typecmds.c:2534
+#, c-format
+msgid "exclusion constraints not possible for domains"
+msgstr "exclusion 제약 조건은 도메인에는 사용할 수 없음"
+
+#: commands/typecmds.c:1007 commands/typecmds.c:2540
+#, c-format
+msgid "foreign key constraints not possible for domains"
+msgstr "참조키(foreign key) 제약 조건은 도메인(domain) 정의에 사용할 수 없음"
+
+#: commands/typecmds.c:1016 commands/typecmds.c:2549
+#, c-format
+msgid "specifying constraint deferrability not supported for domains"
+msgstr "도메인에 대해 제약 조건 지연을 지정할 수 없음"
+
+#: commands/typecmds.c:1291 utils/cache/typcache.c:1630
+#, c-format
+msgid "%s is not an enum"
+msgstr "%s 객체는 나열형이 아님"
+
+#: commands/typecmds.c:1429
+#, c-format
+msgid "type attribute \"subtype\" is required"
+msgstr "\"subtype\" 속성이 필요함"
+
+#: commands/typecmds.c:1434
+#, c-format
+msgid "range subtype cannot be %s"
+msgstr "range subtype은 %s 아니여야 함"
+
+#: commands/typecmds.c:1453
+#, c-format
+msgid "range collation specified but subtype does not support collation"
+msgstr ""
+"range 형에 정렬 규칙을 지정했지만, 소속 자료형이 그 정렬 규칙을 지원하지 않습"
+"니다"
+
+#: commands/typecmds.c:1687
+#, c-format
+msgid "changing argument type of function %s from \"opaque\" to \"cstring\""
+msgstr "%s 함수의 인자 자료형을 \"opaque\"에서 \"cstring\"으로 바꿉니다"
+
+#: commands/typecmds.c:1738
+#, c-format
+msgid "changing argument type of function %s from \"opaque\" to %s"
+msgstr "%s 함수의 인자 자료형을 \"opaque\"에서 %s 자료형으로 바꿉니다"
+
+#: commands/typecmds.c:1837
+#, c-format
+msgid "typmod_in function %s must return type %s"
+msgstr "%s typmod_in 함수는 %s 자료형을 반환해야 함"
+
+#: commands/typecmds.c:1864
+#, c-format
+msgid "typmod_out function %s must return type %s"
+msgstr "%s typmod_out 함수는 %s 자료형을 반환해야 함"
+
+#: commands/typecmds.c:1891
+#, c-format
+msgid "type analyze function %s must return type %s"
+msgstr "%s 자료형 분석 함수는 %s 자료형을 반환해야 함"
+
+#: commands/typecmds.c:1937
+#, c-format
+msgid ""
+"You must specify an operator class for the range type or define a default "
+"operator class for the subtype."
+msgstr ""
+"subtype을 위한 기본 연산자 클래스나 range 자료형을 위한 하나의 연산자 클래스"
+"를 지정해야 합니다"
+
+#: commands/typecmds.c:1968
+#, c-format
+msgid "range canonical function %s must return range type"
+msgstr "%s 범위 기준 함수는 range 자료형을 반환해야합니다"
+
+#: commands/typecmds.c:1974
+#, c-format
+msgid "range canonical function %s must be immutable"
+msgstr "%s 범위 기준 함수는 immutable 속성이어야 합니다"
+
+#: commands/typecmds.c:2010
+#, c-format
+msgid "range subtype diff function %s must return type %s"
+msgstr "%s 범위 하위 자료 비교 함수는 %s 자료형을 반환해야합니다"
+
+#: commands/typecmds.c:2017
+#, c-format
+msgid "range subtype diff function %s must be immutable"
+msgstr "%s 범위 하위 자료 비교 함수는 immutable 속성이어야 합니다"
+
+#: commands/typecmds.c:2044
+#, c-format
+msgid "pg_type array OID value not set when in binary upgrade mode"
+msgstr "이진 업그레이드 작업 때 pg_type 배열 OID 값이 지정되지 않았습니다"
+
+#: commands/typecmds.c:2348
+#, c-format
+msgid "column \"%s\" of table \"%s\" contains null values"
+msgstr "\"%s\" 열(해당 테이블 \"%s\")의 자료 가운데 null 값이 있습니다"
+
+#: commands/typecmds.c:2463 commands/typecmds.c:2646
+#, c-format
+msgid "constraint \"%s\" of domain \"%s\" does not exist"
+msgstr "\"%s\" 제약 조건 \"%s\" 도메인에 포함되어 있지 않습니다."
+
+#: commands/typecmds.c:2467
+#, c-format
+msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping"
+msgstr "\"%s\" 제약 조건 \"%s\" 도메인에 포함되어 있지 않음, 건너뜀"
+
+#: commands/typecmds.c:2652
+#, c-format
+msgid "constraint \"%s\" of domain \"%s\" is not a check constraint"
+msgstr "\"%s\" 제약 조건(해당 도메인: \"%s\")은 check 제약조건이 아님"
+
+#: commands/typecmds.c:2758
+#, c-format
+msgid ""
+"column \"%s\" of table \"%s\" contains values that violate the new constraint"
+msgstr ""
+"\"%s\" 열(해당 테이블 \"%s\")의 자료 중에, 새 제약 조건을 위반하는 자료가 있"
+"습니다"
+
+#: commands/typecmds.c:2971 commands/typecmds.c:3228 commands/typecmds.c:3417
+#, c-format
+msgid "%s is not a domain"
+msgstr "\"%s\" 이름의 객체는 도메인이 아닙니다"
+
+#: commands/typecmds.c:3005
+#, c-format
+msgid "constraint \"%s\" for domain \"%s\" already exists"
+msgstr "\"%s\" 제약 조건이 \"%s\" 도메인에 이미 지정되어 있습니다"
+
+#: commands/typecmds.c:3055
+#, c-format
+msgid "cannot use table references in domain check constraint"
+msgstr "도메인 용 체크 제약 조건에서는 테이블 참조를 사용할 수 없습니다"
+
+#: commands/typecmds.c:3158 commands/typecmds.c:3240 commands/typecmds.c:3534
+#, c-format
+msgid "%s is a table's row type"
+msgstr "%s 자료형은 테이블의 행 자료형(row type)입니다"
+
+#: commands/typecmds.c:3160 commands/typecmds.c:3242 commands/typecmds.c:3536
+#, c-format
+msgid "Use ALTER TABLE instead."
+msgstr "대신 ALTER TABLE을 사용하십시오."
+
+#: commands/typecmds.c:3167 commands/typecmds.c:3249 commands/typecmds.c:3449
+#, c-format
+msgid "cannot alter array type %s"
+msgstr "%s 배열 형식을 변경할 수 없음"
+
+#: commands/typecmds.c:3169 commands/typecmds.c:3251 commands/typecmds.c:3451
+#, c-format
+msgid "You can alter type %s, which will alter the array type as well."
+msgstr "%s 형식을 변경할 수 있으며, 이렇게 하면 배열 형식도 변경됩니다."
+
+#: commands/typecmds.c:3519
+#, c-format
+msgid "type \"%s\" already exists in schema \"%s\""
+msgstr "%s 자료형이 이미 \"%s\" 스키마 안에 있습니다"
+
+#: commands/user.c:149
+#, c-format
+msgid "SYSID can no longer be specified"
+msgstr "SYSID는 더 이상 지정할 수 없음"
+
+#: commands/user.c:291
+#, c-format
+msgid "must be superuser to create superusers"
+msgstr "새 슈퍼유저를 만드려면 슈퍼유져여야만 합니다"
+
+#: commands/user.c:298
+#, c-format
+msgid "must be superuser to create replication users"
+msgstr "새 복제작업용 사용자를 만드려면 슈퍼유저여야만 합니다"
+
+#: commands/user.c:305 commands/user.c:693
+#, c-format
+msgid "must be superuser to change bypassrls attribute"
+msgstr "슈퍼유저만 bypassrls 속성을 바꿀 수 있음"
+
+#: commands/user.c:312
+#, c-format
+msgid "permission denied to create role"
+msgstr "롤 만들 권한 없음"
+
+#: commands/user.c:322 commands/user.c:1176 commands/user.c:1183
+#: utils/adt/acl.c:5279 utils/adt/acl.c:5285 gram.y:13619 gram.y:13654
+#, c-format
+msgid "role name \"%s\" is reserved"
+msgstr "\"%s\" 롤 이름은 내부적으로 사용되고 있습니다"
+
+#: commands/user.c:324 commands/user.c:1178 commands/user.c:1185
+#, c-format
+msgid "Role names starting with \"pg_\" are reserved."
+msgstr "\"pg_\"로 시작하는 롤 이름은 사용할 수 없습니다."
+
+#: commands/user.c:336 commands/user.c:1191
+#, c-format
+msgid "role \"%s\" already exists"
+msgstr "\"%s\" 롤 이름이 이미 있습니다"
+
+#: commands/user.c:414
+#, c-format
+msgid "pg_authid OID value not set when in binary upgrade mode"
+msgstr "이진 업그레이드 작업 때 pg_authid OID 값이 지정되지 않았습니다"
+
+#: commands/user.c:679 commands/user.c:896 commands/user.c:1432
+#: commands/user.c:1578
+#, c-format
+msgid "must be superuser to alter superusers"
+msgstr "슈퍼유저의 속성을 변경하련 슈퍼유져여야만 합니다"
+
+#: commands/user.c:686
+#, c-format
+msgid "must be superuser to alter replication users"
+msgstr "복제작업용 사용자의 속성을 변경하련 슈퍼유져여야만 합니다"
+
+#: commands/user.c:709 commands/user.c:904
+#, c-format
+msgid "permission denied"
+msgstr "권한 없음"
+
+#: commands/user.c:934
+#, c-format
+msgid "must be superuser to alter settings globally"
+msgstr "슈퍼유저만 전역 환경 설정을 바꿀 수 있습니다."
+
+#: commands/user.c:956
+#, c-format
+msgid "permission denied to drop role"
+msgstr "롤을 삭제할 권한이 없습니다"
+
+#: commands/user.c:980
+#, c-format
+msgid "cannot use special role specifier in DROP ROLE"
+msgstr "DROP ROLE 명령으로 삭제할 수 없는 특별한 롤입니다"
+
+#: commands/user.c:990 commands/user.c:1147 commands/variable.c:825
+#: commands/variable.c:897 utils/adt/acl.c:5121 utils/adt/acl.c:5173
+#: utils/adt/acl.c:5206 utils/adt/acl.c:5224 utils/init/miscinit.c:502
+#, c-format
+msgid "role \"%s\" does not exist"
+msgstr "\"%s\" 롤(role) 없음"
+
+#: commands/user.c:995
+#, c-format
+msgid "role \"%s\" does not exist, skipping"
+msgstr "\"%s\" 룰(rule) 없음, 건너 뜀"
+
+#: commands/user.c:1007 commands/user.c:1011
+#, c-format
+msgid "current user cannot be dropped"
+msgstr "현재 사용자는 삭제 될 수 없습니다"
+
+#: commands/user.c:1015
+#, c-format
+msgid "session user cannot be dropped"
+msgstr "세션 사용자는 삭제 될 수 없습니다"
+
+#: commands/user.c:1026
+#, c-format
+msgid "must be superuser to drop superusers"
+msgstr "superuser를 사용자를 삭제하려면 superuser여야만 합니다"
+
+#: commands/user.c:1042
+#, c-format
+msgid "role \"%s\" cannot be dropped because some objects depend on it"
+msgstr "기타 다른 객체들이 이 롤에 의존하고 있어, \"%s\" 롤을 삭제할 수 없음"
+
+#: commands/user.c:1163
+#, c-format
+msgid "session user cannot be renamed"
+msgstr "세션 사용자의 이름은 바꿀 수 없습니다"
+
+#: commands/user.c:1167
+#, c-format
+msgid "current user cannot be renamed"
+msgstr "현재 사용자의 이름은 바꿀 수 없습니다"
+
+#: commands/user.c:1201
+#, c-format
+msgid "must be superuser to rename superusers"
+msgstr "superuser의 이름을 바꾸려면 superuser여야 합니다"
+
+#: commands/user.c:1208
+#, c-format
+msgid "permission denied to rename role"
+msgstr "롤 이름 바꾸기 권한 없음"
+
+#: commands/user.c:1229
+#, c-format
+msgid "MD5 password cleared because of role rename"
+msgstr "롤 이름이 변경 되어 MD5 암호를 지웠습니다"
+
+#: commands/user.c:1291
+#, c-format
+msgid "column names cannot be included in GRANT/REVOKE ROLE"
+msgstr "GRANT/REVOKE ROLE에 열 이름을 포함할 수 없음"
+
+#: commands/user.c:1329
+#, c-format
+msgid "permission denied to drop objects"
+msgstr "객체를 삭제할 권한이 없음"
+
+#: commands/user.c:1356 commands/user.c:1365
+#, c-format
+msgid "permission denied to reassign objects"
+msgstr "객체 권한을 재 지정할 권한이 없음"
+
+#: commands/user.c:1440 commands/user.c:1586
+#, c-format
+msgid "must have admin option on role \"%s\""
+msgstr "\"%s\" 역할에 admin 옵션이 있어야 함"
+
+#: commands/user.c:1457
+#, c-format
+msgid "must be superuser to set grantor"
+msgstr "grantor(?)를 지정하려면 슈퍼유져여야합니다"
+
+#: commands/user.c:1482
+#, c-format
+msgid "role \"%s\" is a member of role \"%s\""
+msgstr "\"%s\" 롤은 \"%s\" 롤의 구성원입니다"
+
+#: commands/user.c:1497
+#, c-format
+msgid "role \"%s\" is already a member of role \"%s\""
+msgstr "role \"%s\" is already a member of role \"%s\""
+
+#: commands/user.c:1608
+#, c-format
+msgid "role \"%s\" is not a member of role \"%s\""
+msgstr "\"%s\" 롤은 \"%s\"롤의 구성원이 아닙니다"
+
+#: commands/vacuum.c:185
+#, c-format
+msgid "%s cannot be executed from VACUUM or ANALYZE"
+msgstr "%s 명령은 VACUUM, ANALYZE 명령에서 실행 될 수 없음"
+
+#: commands/vacuum.c:195
+#, c-format
+msgid "VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL"
+msgstr ""
+"VACUUM 명령에서 DISABLE_PAGE_SKIPPING 옵션과 FULL 옵션을 함께 사용할 수 없습"
+"니다."
+
+# # search5 부분
+#: commands/vacuum.c:535
+#, c-format
+msgid "oldest xmin is far in the past"
+msgstr "가장 오래된 xmin이 너무 옛날 것입니다."
+
+#: commands/vacuum.c:536
+#, c-format
+msgid "Close open transactions soon to avoid wraparound problems."
+msgstr ""
+"트랜잭션ID 최대값 초과로 자료가 겹쳐지는 문제를 피하기 위해서는 지금 즉시 열"
+"려 있는 모든 트랜잭션을 닫으십시오."
+
+# # search5 부분
+#: commands/vacuum.c:575
+#, c-format
+msgid "oldest multixact is far in the past"
+msgstr "가장 오래된 multixact 값이 너무 옛날 것입니다."
+
+#: commands/vacuum.c:576
+#, c-format
+msgid ""
+"Close open transactions with multixacts soon to avoid wraparound problems."
+msgstr ""
+"멀티 트랜잭션 ID 겹침 사고를 막기 위해 빨리 열린 멀티 트랜잭션들을 닫으십시"
+"오."
+
+#: commands/vacuum.c:1146
+#, c-format
+msgid "some databases have not been vacuumed in over 2 billion transactions"
+msgstr ""
+"몇몇 데이터베이스가 20억 이상의 트랜잭션을 처리했음에도 불구하고 청소가되지 "
+"않았습니다"
+
+#: commands/vacuum.c:1147
+#, c-format
+msgid "You might have already suffered transaction-wraparound data loss."
+msgstr "이미 트래잭션 ID 겹침 현상으로 자료 손실이 발생했을 수도 있습니다."
+
+#: commands/vacuum.c:1268
+#, c-format
+msgid "skipping vacuum of \"%s\" --- lock not available"
+msgstr "\"%s\" 객체 vacuum 건너뜀 --- 사용 가능한 잠금이 없음"
+
+#: commands/vacuum.c:1294
+#, c-format
+msgid "skipping \"%s\" --- only superuser can vacuum it"
+msgstr "\"%s\" 건너뜀 --- 슈퍼유저만 청소할 수 있음"
+
+#: commands/vacuum.c:1298
+#, c-format
+msgid "skipping \"%s\" --- only superuser or database owner can vacuum it"
+msgstr "\"%s\" 건너뜀 --- 슈퍼유저 또는 데이터베이스 소유주만 청소할 수 있음"
+
+#: commands/vacuum.c:1302
+#, c-format
+msgid "skipping \"%s\" --- only table or database owner can vacuum it"
+msgstr "\"%s\" 건너뜀 --- 이 테이블이나 데이터베이스의 소유주만 청소할 수 있음"
+
+#: commands/vacuum.c:1320
+#, c-format
+msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables"
+msgstr ""
+"\"%s\" 건너뜀 --- 테이블이 아닌 것 또는 특별 시스템 테이블 등은 청소할 수 없"
+"음"
+
+#: commands/vacuumlazy.c:366
+#, c-format
+msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"
+msgstr "\"%s.%s.%s\" 테이블 자동 청소: 인덱스 탐색: %d\n"
+
+#: commands/vacuumlazy.c:371
+#, c-format
+msgid ""
+"pages: %u removed, %u remain, %u skipped due to pins, %u skipped frozen\n"
+msgstr "페이지: %u 삭제됨, %u 남음, %u 핀닝으로 건너뜀, %u 동결되어 건너뜀\n"
+
+#: commands/vacuumlazy.c:377
+#, c-format
+msgid ""
+"tuples: %.0f removed, %.0f remain, %.0f are dead but not yet removable\n"
+msgstr "튜플: %.0f 삭제됨, %.0f 남음, %.0f 삭제할 수 없는 죽은 튜플\n"
+
+#: commands/vacuumlazy.c:382
+#, c-format
+msgid "buffer usage: %d hits, %d misses, %d dirtied\n"
+msgstr "버퍼 사용량: %d 조회, %d 놓침, %d 변경됨\n"
+
+#: commands/vacuumlazy.c:386
+#, c-format
+msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"
+msgstr "평균 읽기 속도: %.3f MB/s, 평균 쓰기 속도: %.3f MB/s\n"
+
+#: commands/vacuumlazy.c:388
+#, c-format
+msgid "system usage: %s"
+msgstr "시스템 사용량: %s"
+
+#: commands/vacuumlazy.c:846
+#, c-format
+msgid "relation \"%s\" page %u is uninitialized --- fixing"
+msgstr "\"%s\" 릴레이션 %u 페이지는 초기화되지 않았음 --- 수정함"
+
+#: commands/vacuumlazy.c:1316
+#, c-format
+msgid "\"%s\": removed %.0f row versions in %u pages"
+msgstr "\"%s\": %.0f개의 행 버전을 %u개 페이지에서 삭제했습니다."
+
+#: commands/vacuumlazy.c:1326
+#, c-format
+msgid "%.0f dead row versions cannot be removed yet.\n"
+msgstr "%.0f개의 죽은 로우 버전을 아직 지울 수 없습니다.\n"
+
+#: commands/vacuumlazy.c:1328
+#, c-format
+msgid "There were %.0f unused item pointers.\n"
+msgstr "%.0f개의 사용되지 않은 아이템 포인터가 있습니다.\n"
+
+#: commands/vacuumlazy.c:1330
+#, c-format
+msgid "Skipped %u page due to buffer pins.\n"
+msgid_plural "Skipped %u pages due to buffer pins.\n"
+msgstr[0] "%u 페이지를 버퍼 핀닝으로 건너 뛰었습니다.\n"
+
+#: commands/vacuumlazy.c:1334
+#, c-format
+msgid "%u page is entirely empty.\n"
+msgid_plural "%u pages are entirely empty.\n"
+msgstr[0] ""
+
+#: commands/vacuumlazy.c:1342
+#, c-format
+msgid ""
+"\"%s\": found %.0f removable, %.0f nonremovable row versions in %u out of %u "
+"pages"
+msgstr ""
+"\"%s\": 지울 수 있는 자료 %.0f개, 지울 수 없는 자료 %.0f개를 %u/%u개 페이지에"
+"서 찾았음"
+
+#: commands/vacuumlazy.c:1411
+#, c-format
+msgid "\"%s\": removed %d row versions in %d pages"
+msgstr "\"%s\": %d 개 자료를 %d 페이지에서 삭제했음"
+
+#: commands/vacuumlazy.c:1600
+#, c-format
+msgid "scanned index \"%s\" to remove %d row versions"
+msgstr "\"%s\" 인덱스를 스캔해서 %d개의 행 버전들을 지웠습니다"
+
+#: commands/vacuumlazy.c:1646
+#, c-format
+msgid "index \"%s\" now contains %.0f row versions in %u pages"
+msgstr "\"%s\" 인덱스는 %.0f 행 버전을 %u 페이지에서 포함하고 있습니다."
+
+#: commands/vacuumlazy.c:1650
+#, c-format
+msgid ""
+"%.0f index row versions were removed.\n"
+"%u index pages have been deleted, %u are currently reusable.\n"
+"%s."
+msgstr ""
+"%.0f개의 인덱스 행 버전을 삭제했습니다.\n"
+"%u개 인덱스 페이지를 삭제해서, %u개 페이지를 다시 사용합니다.\n"
+"%s."
+
+#: commands/vacuumlazy.c:1745
+#, c-format
+msgid "\"%s\": stopping truncate due to conflicting lock request"
+msgstr "\"%s\": 잠금 요청 충돌로 자료 비우기 작업을 중지합니다"
+
+#: commands/vacuumlazy.c:1810
+#, c-format
+msgid "\"%s\": truncated %u to %u pages"
+msgstr "\"%s\": %u 에서 %u 페이지로 정지했음"
+
+#: commands/vacuumlazy.c:1866
+#, c-format
+msgid "\"%s\": suspending truncate due to conflicting lock request"
+msgstr "\"%s\": 잠금 요청 충돌로 자료 비우기 작업을 지연합니다"
+
+#: commands/variable.c:164 utils/misc/guc.c:9899
+#, c-format
+msgid "Unrecognized key word: \"%s\"."
+msgstr "알 수 없는 키워드: \"%s\""
+
+#: commands/variable.c:176
+#, c-format
+msgid "Conflicting \"datestyle\" specifications."
+msgstr "\"datestyle\" 지정이 충돌함"
+
+#: commands/variable.c:298
+#, c-format
+msgid "Cannot specify months in time zone interval."
+msgstr "타임 존 간격에 달을 지정할 수 없음"
+
+#: commands/variable.c:304
+#, c-format
+msgid "Cannot specify days in time zone interval."
+msgstr "타임 존 간격에 일을 지정할 수 없음"
+
+#: commands/variable.c:346 commands/variable.c:428
+#, c-format
+msgid "time zone \"%s\" appears to use leap seconds"
+msgstr "\"%s\" time zone 에서 leap second를 사용합니다"
+
+#: commands/variable.c:348 commands/variable.c:430
+#, c-format
+msgid "PostgreSQL does not support leap seconds."
+msgstr "PostgreSQL에서는 leap second를 지원하지 않습니다"
+
+#: commands/variable.c:357
+#, c-format
+msgid "UTC timezone offset is out of range."
+msgstr "UTC 타입존 오프세트 범위가 벗어남."
+
+#: commands/variable.c:497
+#, c-format
+msgid "cannot set transaction read-write mode inside a read-only transaction"
+msgstr "읽기 전용 트랜잭션 내에서 트랜잭션을 읽기/쓰기 모드로 설정할 수 없음"
+
+#: commands/variable.c:504
+#, c-format
+msgid "transaction read-write mode must be set before any query"
+msgstr "읽기/쓰기 모드 트랜잭션은 모든 쿼리 앞에 지정해야 합니다."
+
+#: commands/variable.c:511
+#, c-format
+msgid "cannot set transaction read-write mode during recovery"
+msgstr "복구 작업 중에는 트랜잭션을 읽기/쓰기 모드로 설정할 수 없음"
+
+#: commands/variable.c:560
+#, c-format
+msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query"
+msgstr "쿼리보다 먼저 SET TRANSACTION ISOLATION LEVEL을 호출해야 함"
+
+#: commands/variable.c:567
+#, c-format
+msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction"
+msgstr "하위 트랜잭션에서 SET TRANSACTION ISOLATION LEVEL을 호출하지 않아야 함"
+
+#: commands/variable.c:574 storage/lmgr/predicate.c:1587
+#, c-format
+msgid "cannot use serializable mode in a hot standby"
+msgstr "읽기 전용 보조 서버 상태에서는 serializable 모드를 사용할 수 없음"
+
+#: commands/variable.c:575
+#, c-format
+msgid "You can use REPEATABLE READ instead."
+msgstr "대신에, REPEATABLE READ 명령을 사용할 수 있음."
+
+#: commands/variable.c:623
+#, c-format
+msgid ""
+"SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction"
+msgstr ""
+"하위 트랜잭션에서 SET TRANSACTION [NOT] DEFERRABLE 구문은 사용할 수 없음"
+
+#: commands/variable.c:629
+#, c-format
+msgid "SET TRANSACTION [NOT] DEFERRABLE must be called before any query"
+msgstr "모든 쿼리보다 먼저 SET TRANSACTION [NOT] DEFERRABLE 구문을 사용해야 함"
+
+#: commands/variable.c:711
+#, c-format
+msgid "Conversion between %s and %s is not supported."
+msgstr "%s 인코딩과 %s 인코딩 사이의 변환은 지원하지 않습니다"
+
+#: commands/variable.c:718
+#, c-format
+msgid "Cannot change \"client_encoding\" now."
+msgstr "\"client_encoding\" 값을 바꿀 수 없음"
+
+#: commands/variable.c:779
+#, c-format
+msgid "cannot change client_encoding in a parallel worker"
+msgstr "병렬 작업자에서는 client_encoding 설정을 할 수 없음"
+
+#: commands/variable.c:915
+#, c-format
+msgid "permission denied to set role \"%s\""
+msgstr "\"%s\" 롤 권한을 지정할 수 없음"
+
+#: commands/view.c:54
+#, c-format
+msgid "invalid value for \"check_option\" option"
+msgstr "\"check_option\" 옵션값이 잘못됨"
+
+#: commands/view.c:55
+#, c-format
+msgid "Valid values are \"local\" and \"cascaded\"."
+msgstr "사용할 수 있는 값은 \"local\" 또는 \"cascaded\" 입니다"
+
+#: commands/view.c:101
+#, c-format
+msgid "could not determine which collation to use for view column \"%s\""
+msgstr "\"%s\" 칼럼 자료 처리를 위한 정렬 규칙을 결정할 수 없음"
+
+#: commands/view.c:115
+#, c-format
+msgid "view must have at least one column"
+msgstr "뷰에는 적어도 한 개 이상의 칼럼이 있어야 합니다"
+
+#: commands/view.c:280 commands/view.c:292
+#, c-format
+msgid "cannot drop columns from view"
+msgstr "뷰에서 칼럼을 삭제할 수 없음"
+
+#: commands/view.c:297
+#, c-format
+msgid "cannot change name of view column \"%s\" to \"%s\""
+msgstr "뷰에서 \"%s\" 칼럼 이름을 \"%s\"(으)로 바꿀 수 없음"
+
+#: commands/view.c:305
+#, c-format
+msgid "cannot change data type of view column \"%s\" from %s to %s"
+msgstr "뷰에서 \"%s\" 칼럼 자료형을을 %s에서 %s(으)로 바꿀 수 없음"
+
+#: commands/view.c:444
+#, c-format
+msgid "views must not contain SELECT INTO"
+msgstr "뷰에는 SELECT INTO 구문을 포함할 수 없음"
+
+#: commands/view.c:457
+#, c-format
+msgid "views must not contain data-modifying statements in WITH"
+msgstr "뷰로 사용될 쿼리의 WITH 절에는 자료 변경 구문이 있으면 안됩니다."
+
+#: commands/view.c:528
+#, c-format
+msgid "CREATE VIEW specifies more column names than columns"
+msgstr "CREATE VIEW 는 columns 보다는 좀더 많은 열 이름을 명시해야 한다"
+
+#: commands/view.c:536
+#, c-format
+msgid "views cannot be unlogged because they do not have storage"
+msgstr ""
+"뷰는 저장 공간을 사용하지 않기 때문에 unlogged 속성을 지정할 수 없습니다."
+
+#: commands/view.c:550
+#, c-format
+msgid "view \"%s\" will be a temporary view"
+msgstr "\"%s\" 뷰는 임시적인 뷰로 만들어집니다"
+
+#: executor/execCurrent.c:76
+#, c-format
+msgid "cursor \"%s\" is not a SELECT query"
+msgstr "\"%s\" 커서는 SELECT 쿼리가 아님"
+
+#: executor/execCurrent.c:82
+#, c-format
+msgid "cursor \"%s\" is held from a previous transaction"
+msgstr "\"%s\" 커서는 이전 트랜잭션에서 보류됨"
+
+#: executor/execCurrent.c:114
+#, c-format
+msgid "cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\""
+msgstr ""
+"\"%s\" 커서에는 \"%s\" 테이블에 대한 FOR UPDATE/SHARE 참조가 여러 개 있음"
+
+#: executor/execCurrent.c:123
+#, c-format
+msgid ""
+"cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\""
+msgstr "\"%s\" 커서에 \"%s\" 테이블에 대한 FOR UPDATE/SHARE 참조가 없음"
+
+#: executor/execCurrent.c:133 executor/execCurrent.c:179
+#, c-format
+msgid "cursor \"%s\" is not positioned on a row"
+msgstr "\"%s\" 커서가 로우에 놓여 있지 않음"
+
+#: executor/execCurrent.c:166
+#, c-format
+msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\""
+msgstr "\"%s\" 커서는 \"%s\" 테이블의 단순 업데이트 가능한 스캔이 아님"
+
+#: executor/execCurrent.c:231 executor/execQual.c:1178
+#, c-format
+msgid ""
+"type of parameter %d (%s) does not match that when preparing the plan (%s)"
+msgstr ""
+"%d번째 매개 변수의 자료형(%s)이 미리 준비된 실행계획의 자료형(%s)과 다릅니다"
+
+#: executor/execCurrent.c:243 executor/execQual.c:1190
+#, c-format
+msgid "no value found for parameter %d"
+msgstr "%d번째 매개 변수 값이 없습니다"
+
+#: executor/execIndexing.c:544
+#, c-format
+msgid ""
+"ON CONFLICT does not support deferrable unique constraints/exclusion "
+"constraints as arbiters"
+msgstr ""
+"지연 가능한 고유 제약조건이나 제외 제약 조건은 ON CONFLICT 판별자로 사용할 "
+"수 없습니다."
+
+#: executor/execIndexing.c:821
+#, c-format
+msgid "could not create exclusion constraint \"%s\""
+msgstr "\"%s\" exclusion 제약 조건을 만들 수 없음"
+
+#: executor/execIndexing.c:824
+#, c-format
+msgid "Key %s conflicts with key %s."
+msgstr "%s 키와 %s 가 충돌함"
+
+#: executor/execIndexing.c:826
+#, c-format
+msgid "Key conflicts exist."
+msgstr "키 충돌 발생"
+
+#: executor/execIndexing.c:832
+#, c-format
+msgid "conflicting key value violates exclusion constraint \"%s\""
+msgstr "\"%s\" exclusion 제약 조건에 따라 키 값 충돌이 발생했습니다."
+
+#: executor/execIndexing.c:835
+#, c-format
+msgid "Key %s conflicts with existing key %s."
+msgstr "%s 키가 이미 있는 %s 키와 충돌합니다."
+
+#: executor/execIndexing.c:837
+#, c-format
+msgid "Key conflicts with existing key."
+msgstr "키가 기존 키와 충돌함"
+
+#: executor/execMain.c:1027
+#, c-format
+msgid "cannot change sequence \"%s\""
+msgstr "\"%s\" 시퀀스를 바꿀 수 없음"
+
+#: executor/execMain.c:1033
+#, c-format
+msgid "cannot change TOAST relation \"%s\""
+msgstr "\"%s\" TOAST 릴레이션을 바꿀 수 없음"
+
+#: executor/execMain.c:1051 rewrite/rewriteHandler.c:2648
+#, c-format
+msgid "cannot insert into view \"%s\""
+msgstr "\"%s\" 뷰에 자료를 입력할 수 없습니다"
+
+#: executor/execMain.c:1053 rewrite/rewriteHandler.c:2651
+#, c-format
+msgid ""
+"To enable inserting into the view, provide an INSTEAD OF INSERT trigger or "
+"an unconditional ON INSERT DO INSTEAD rule."
+msgstr ""
+"뷰를 통해 자료를 입력하려면, INSTEAD OF INSERT 트리거나 ON INSERT DO INSTEAD "
+"룰을 사용하세요"
+
+#: executor/execMain.c:1059 rewrite/rewriteHandler.c:2656
+#, c-format
+msgid "cannot update view \"%s\""
+msgstr "\"%s\" 뷰로는 자료를 갱신할 수 없습니다"
+
+#: executor/execMain.c:1061 rewrite/rewriteHandler.c:2659
+#, c-format
+msgid ""
+"To enable updating the view, provide an INSTEAD OF UPDATE trigger or an "
+"unconditional ON UPDATE DO INSTEAD rule."
+msgstr ""
+"뷰 자료 갱신 기능은 INSTEAD OF UPDATE 트리거를 사용하거나, ON UPDATE DO "
+"INSTEAD 속성으로 룰을 만들어서 사용해 보세요."
+
+#: executor/execMain.c:1067 rewrite/rewriteHandler.c:2664
+#, c-format
+msgid "cannot delete from view \"%s\""
+msgstr "\"%s\" 뷰로는 자료를 삭제할 수 없습니다"
+
+#: executor/execMain.c:1069 rewrite/rewriteHandler.c:2667
+#, c-format
+msgid ""
+"To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an "
+"unconditional ON DELETE DO INSTEAD rule."
+msgstr ""
+"뷰 자료 삭제 기능은 INSTEAD OF DELETE 트리거를 사용하거나, ON DELETE DO "
+"INSTEAD 속성으로 룰을 만들어서 사용해 보세요."
+
+#: executor/execMain.c:1080
+#, c-format
+msgid "cannot change materialized view \"%s\""
+msgstr "\"%s\" 구체화된 뷰를 바꿀 수 없음"
+
+#: executor/execMain.c:1092
+#, c-format
+msgid "cannot insert into foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블에 자료를 입력할 수 없음"
+
+#: executor/execMain.c:1098
+#, c-format
+msgid "foreign table \"%s\" does not allow inserts"
+msgstr "\"%s\" 외부 테이블은 자료 입력을 허용하지 않음"
+
+#: executor/execMain.c:1105
+#, c-format
+msgid "cannot update foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블에 자료를 변경 할 수 없음"
+
+#: executor/execMain.c:1111
+#, c-format
+msgid "foreign table \"%s\" does not allow updates"
+msgstr "\"%s\" 외부 테이블은 자료 변경을 허용하지 않음"
+
+#: executor/execMain.c:1118
+#, c-format
+msgid "cannot delete from foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블에 자료를 삭제 할 수 없음"
+
+#: executor/execMain.c:1124
+#, c-format
+msgid "foreign table \"%s\" does not allow deletes"
+msgstr "\"%s\" 외부 테이블은 자료 삭제를 허용하지 않음"
+
+#: executor/execMain.c:1135
+#, c-format
+msgid "cannot change relation \"%s\""
+msgstr "\"%s\" 릴레이션을 바꿀 수 없음"
+
+#: executor/execMain.c:1161
+#, c-format
+msgid "cannot lock rows in sequence \"%s\""
+msgstr "\"%s\" 시퀀스에서 로우를 잠글 수 없음"
+
+#: executor/execMain.c:1168
+#, c-format
+msgid "cannot lock rows in TOAST relation \"%s\""
+msgstr "\"%s\" TOAST 릴레이션에서 로우를 잠글 수 없음"
+
+#: executor/execMain.c:1175
+#, c-format
+msgid "cannot lock rows in view \"%s\""
+msgstr "\"%s\" 뷰에서 로우를 잠글 수 없음"
+
+#: executor/execMain.c:1183
+#, c-format
+msgid "cannot lock rows in materialized view \"%s\""
+msgstr "\"%s\" 구체화된 뷰에서 로우를 잠글 수 없음"
+
+#: executor/execMain.c:1192 executor/execMain.c:2613
+#: executor/nodeLockRows.c:132
+#, c-format
+msgid "cannot lock rows in foreign table \"%s\""
+msgstr "\"%s\" 외부 테이블에서 로우를 잠글 수 없음"
+
+#: executor/execMain.c:1198
+#, c-format
+msgid "cannot lock rows in relation \"%s\""
+msgstr "\"%s\" 릴레이션에서 로우를 잠글 수 없음"
+
+#: executor/execMain.c:1731
+#, c-format
+msgid "null value in column \"%s\" violates not-null constraint"
+msgstr "\"%s\" 칼럼의 null 값이 not null 제약조건을 위반했습니다."
+
+#: executor/execMain.c:1733 executor/execMain.c:1759 executor/execMain.c:1848
+#, c-format
+msgid "Failing row contains %s."
+msgstr "실패한 자료: %s"
+
+#: executor/execMain.c:1757
+#, c-format
+msgid "new row for relation \"%s\" violates check constraint \"%s\""
+msgstr "새 자료가 \"%s\" 릴레이션의 \"%s\" 체크 제약 조건을 위반했습니다"
+
+#: executor/execMain.c:1846
+#, c-format
+msgid "new row violates check option for view \"%s\""
+msgstr "새 자료가 \"%s\" 뷰의 체크 제약 조건을 위반했습니다"
+
+#: executor/execMain.c:1856
+#, c-format
+msgid "new row violates row-level security policy \"%s\" for table \"%s\""
+msgstr ""
+"새 자료가 \"%s\" 로우 단위 보안 정책을 위반했습니다, 해당 테이블: \"%s\""
+
+#: executor/execMain.c:1861
+#, c-format
+msgid "new row violates row-level security policy for table \"%s\""
+msgstr "새 자료가 \"%s\" 테이블의 로우 단위 보안 정책을 위반했습니다."
+
+#: executor/execMain.c:1868
+#, c-format
+msgid ""
+"new row violates row-level security policy \"%s\" (USING expression) for "
+"table \"%s\""
+msgstr ""
+"새 자료가 \"%s\" 로우 단위 보안 정책(USING 절 사용)을 위반했습니다, 해당 테이"
+"블: \"%s\""
+
+#: executor/execMain.c:1873
+#, c-format
+msgid ""
+"new row violates row-level security policy (USING expression) for table \"%s"
+"\""
+msgstr ""
+"새 자료가 \"%s\" 테이블의 로우 단위 보안 정책(USING 절 사용)을 위반했습니다."
+
+#: executor/execQual.c:302 executor/execQual.c:339 executor/execQual.c:3236
+#: utils/adt/array_userfuncs.c:484 utils/adt/arrayfuncs.c:260
+#: utils/adt/arrayfuncs.c:558 utils/adt/arrayfuncs.c:1288
+#: utils/adt/arrayfuncs.c:3361 utils/adt/arrayfuncs.c:5241
+#: utils/adt/arrayfuncs.c:5758
+#, c-format
+msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)"
+msgstr "지정한 배열 크기(%d)가 최대치(%d)를 초과했습니다"
+
+#: executor/execQual.c:324 executor/execQual.c:360
+#, c-format
+msgid "array subscript in assignment must not be null"
+msgstr "배열 하위 스크립트로 지정하는 값으로 null 값을 사용할 수 없습니다"
+
+#: executor/execQual.c:657 executor/execQual.c:4183
+#, c-format
+msgid "attribute %d has wrong type"
+msgstr "%d 속성의 형식이 잘못됨"
+
+#: executor/execQual.c:658 executor/execQual.c:4184
+#, c-format
+msgid "Table has type %s, but query expects %s."
+msgstr "테이블에는 %s 자료형이지만, 쿼리에서는 %s 자료형입니다."
+
+#: executor/execQual.c:851 executor/execQual.c:868 executor/execQual.c:1068
+#: executor/nodeModifyTable.c:95 executor/nodeModifyTable.c:105
+#: executor/nodeModifyTable.c:122 executor/nodeModifyTable.c:130
+#, c-format
+msgid "table row type and query-specified row type do not match"
+msgstr "테이블 행 형식과 쿼리 지정 행 형식이 일치하지 않음"
+
+#: executor/execQual.c:852
+#, c-format
+msgid "Table row contains %d attribute, but query expects %d."
+msgid_plural "Table row contains %d attributes, but query expects %d."
+msgstr[0] ""
+"테이블 행에는 %d개 속성이 포함되어 있는데 쿼리에는 %d개가 필요합니다."
+
+#: executor/execQual.c:869 executor/nodeModifyTable.c:106
+#, c-format
+msgid "Table has type %s at ordinal position %d, but query expects %s."
+msgstr ""
+"테이블에는 %s 형식이 있는데(서수 위치 %d) 쿼리에는 %s이(가) 필요합니다."
+
+#: executor/execQual.c:1069 executor/execQual.c:1665
+#, c-format
+msgid "Physical storage mismatch on dropped attribute at ordinal position %d."
+msgstr "서수 위치 %d의 삭제된 속성에서 실제 스토리지 불일치가 발생합니다."
+
+#: executor/execQual.c:1344 parser/parse_func.c:115 parser/parse_func.c:542
+#: parser/parse_func.c:897
+#, c-format
+msgid "cannot pass more than %d argument to a function"
+msgid_plural "cannot pass more than %d arguments to a function"
+msgstr[0] "함수에 최대 %d개의 인자를 전달할 수 있음"
+
+#: executor/execQual.c:1533
+#, c-format
+msgid "functions and operators can take at most one set argument"
+msgstr "함수와 연산자는 set 인자로는 오직 한 개만 사용할 수 있습니다"
+
+#: executor/execQual.c:1583
+#, c-format
+msgid ""
+"function returning setof record called in context that cannot accept type "
+"record"
+msgstr ""
+"setof 레코드 반환 함수가 type 레코드를 허용하지 않는 컨텍스트에서 호출됨"
+
+#: executor/execQual.c:1638 executor/execQual.c:1654 executor/execQual.c:1664
+#, c-format
+msgid "function return row and query-specified return row do not match"
+msgstr "함수 반환 행과 쿼리 지정 반환 행이 일치하지 않음"
+
+#: executor/execQual.c:1639
+#, c-format
+msgid "Returned row contains %d attribute, but query expects %d."
+msgid_plural "Returned row contains %d attributes, but query expects %d."
+msgstr[0] ""
+"반환된 행에는 %d개 속성이 포함되어 있는데 쿼리에는 %d개가 필요합니다."
+
+#: executor/execQual.c:1655
+#, c-format
+msgid "Returned type %s at ordinal position %d, but query expects %s."
+msgstr "반환된 형식은 %s인데(서수 위치 %d) 쿼리에는 %s이(가) 필요합니다."
+
+#: executor/execQual.c:1897 executor/execQual.c:2335
+#, c-format
+msgid "table-function protocol for materialize mode was not followed"
+msgstr "materialize 모드를 위한 테이블 함수 프로토콜이 뒤이어 오지 않았습니다"
+
+#: executor/execQual.c:1917 executor/execQual.c:2342
+#, c-format
+msgid "unrecognized table-function returnMode: %d"
+msgstr "알 수 없는 테이블-함수 리턴모드: %d"
+
+#: executor/execQual.c:2287
+#, c-format
+msgid "rows returned by function are not all of the same row type"
+msgstr "함수 호출로 반환되는 로우가 같은 로우형의 전부가 아닙니다"
+
+#: executor/execQual.c:2522
+#, c-format
+msgid "IS DISTINCT FROM does not support set arguments"
+msgstr "IS DISTINCT FROM 구문에서는 set 인자들을 지원하지 않습니다"
+
+#: executor/execQual.c:2599
+#, c-format
+msgid "op ANY/ALL (array) does not support set arguments"
+msgstr "op ANY/ALL (array) 에서는 set 인자들을 지원하지 않습니다"
+
+#: executor/execQual.c:3214
+#, c-format
+msgid "cannot merge incompatible arrays"
+msgstr "배열 형태가 서로 틀려 병합할 수 없습니다"
+
+#: executor/execQual.c:3215
+#, c-format
+msgid ""
+"Array with element type %s cannot be included in ARRAY construct with "
+"element type %s."
+msgstr ""
+"%s 자료형의 요소로 구성된 배열은 %s 자료형의 요소로 구성된 ARRAY 구문에 포함"
+"될 수 없습니다."
+
+#: executor/execQual.c:3256 executor/execQual.c:3283
+#, c-format
+msgid ""
+"multidimensional arrays must have array expressions with matching dimensions"
+msgstr "다차원 배열에는 일치하는 차원이 포함된 배열 식이 있어야 함"
+
+#: executor/execQual.c:3798
+#, c-format
+msgid "NULLIF does not support set arguments"
+msgstr "NULLIF는 set 인자들을 지원하지 않습니다"
+
+#: executor/execQual.c:4046 utils/adt/domains.c:137
+#, c-format
+msgid "domain %s does not allow null values"
+msgstr "%s 도메인에서는 null 값을 허용하지 않습니다"
+
+#: executor/execQual.c:4083 utils/adt/domains.c:179
+#, c-format
+msgid "value for domain %s violates check constraint \"%s\""
+msgstr "%s 도메인용 값이 \"%s\" 체크 제약 조건을 위반했습니다"
+
+#: executor/execQual.c:4438
+#, c-format
+msgid "WHERE CURRENT OF is not supported for this table type"
+msgstr "WHERE CURRENT OF 구문은 이 테이블 형 대상으로 지원하지 않습니다."
+
+#: executor/execQual.c:4627 parser/parse_agg.c:758
+#, c-format
+msgid "window function calls cannot be nested"
+msgstr "윈도우 함수 호출을 중첩할 수 없음"
+
+#: executor/execQual.c:4839
+#, c-format
+msgid "target type is not an array"
+msgstr "대상 자료형이 배열이 아닙니다."
+
+#: executor/execQual.c:4956
+#, c-format
+msgid "ROW() column has type %s instead of type %s"
+msgstr "ROW() 열은 %s 자료형을 가집니다. %s 자료형 대신에"
+
+#: executor/execQual.c:5091 utils/adt/arrayfuncs.c:3803
+#: utils/adt/arrayfuncs.c:6325 utils/adt/rowtypes.c:927
+#, c-format
+msgid "could not identify a comparison function for type %s"
+msgstr "%s 자료형에서 사용할 비교함수를 찾을 수 없습니다."
+
+#: executor/execUtils.c:813
+#, c-format
+msgid "materialized view \"%s\" has not been populated"
+msgstr "\"%s\" 구체화된 뷰가 아직 구체화되지 못했습니다."
+
+#: executor/execUtils.c:815
+#, c-format
+msgid "Use the REFRESH MATERIALIZED VIEW command."
+msgstr "REFRESH MATERIALIZED VIEW 명령을 사용하세요."
+
+#: executor/functions.c:225
+#, c-format
+msgid "could not determine actual type of argument declared %s"
+msgstr "%s 인자의 자료형으로 지정한 자료형의 기본 자료형을 찾을 수 없습니다"
+
+#: executor/functions.c:511
+#, c-format
+msgid "cannot COPY to/from client in a SQL function"
+msgstr "SQL 함수에서 클라이언트 대상 COPY 작업을 할 수 없음"
+
+#. translator: %s is a SQL statement name
+#: executor/functions.c:517
+#, c-format
+msgid "%s is not allowed in a SQL function"
+msgstr "SQL 함수에서 %s 지원되지 않음"
+
+#. translator: %s is a SQL statement name
+#: executor/functions.c:524 executor/spi.c:1364 executor/spi.c:2154
+#, c-format
+msgid "%s is not allowed in a non-volatile function"
+msgstr "%s 구문은 비휘발성 함수(non-volatile function)에서 허용하지 않습니다"
+
+#: executor/functions.c:650
+#, c-format
+msgid ""
+"could not determine actual result type for function declared to return type "
+"%s"
+msgstr ""
+"%s 자료형을 반환한다고 정의한 함수인데, 실재 반환 자료형을 결정할 수 없습니"
+"다."
+
+#: executor/functions.c:1415
+#, c-format
+msgid "SQL function \"%s\" statement %d"
+msgstr "SQL 함수 \"%s\"의 문 %d"
+
+#: executor/functions.c:1441
+#, c-format
+msgid "SQL function \"%s\" during startup"
+msgstr "시작 중 SQL 함수 \"%s\""
+
+#: executor/functions.c:1600 executor/functions.c:1637
+#: executor/functions.c:1649 executor/functions.c:1762
+#: executor/functions.c:1795 executor/functions.c:1825
+#, c-format
+msgid "return type mismatch in function declared to return %s"
+msgstr "리턴 자료형이 함수 정의에서 지정한 %s 리턴 자료형과 틀립니다"
+
+#: executor/functions.c:1602
+#, c-format
+msgid ""
+"Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING."
+msgstr ""
+"함수 내용의 맨 마지막 구문은 SELECT 또는 INSERT/UPDATE/DELETE RETURNING이어"
+"야 합니다."
+
+#: executor/functions.c:1639
+#, c-format
+msgid "Final statement must return exactly one column."
+msgstr "맨 마지막 구문은 정확히 하나의 칼럼만 반환해야 합니다."
+
+#: executor/functions.c:1651
+#, c-format
+msgid "Actual return type is %s."
+msgstr "실재 반환 자료형은 %s"
+
+#: executor/functions.c:1764
+#, c-format
+msgid "Final statement returns too many columns."
+msgstr "맨 마지막 구문이 너무 많은 칼럼을 반환합니다."
+
+#: executor/functions.c:1797
+#, c-format
+msgid "Final statement returns %s instead of %s at column %d."
+msgstr ""
+"맨 마지막 구문이 %s(기대되는 자료형: %s) 자료형을 %d 번째 칼럼에서 반환합니"
+"다."
+
+#: executor/functions.c:1827
+#, c-format
+msgid "Final statement returns too few columns."
+msgstr "맨 마지막 구문이 너무 적은 칼럼을 반환합니다."
+
+#: executor/functions.c:1876
+#, c-format
+msgid "return type %s is not supported for SQL functions"
+msgstr "반환 자료형인 %s 자료형은 SQL 함수에서 지원되지 않음"
+
+#: executor/nodeAgg.c:3038
+#, c-format
+msgid "combine function for aggregate %u must be declared as STRICT"
+msgstr "%u OID 집계함수에서 쓸 조합 함수는 STRICT 속성을 가져야 합니다"
+
+#: executor/nodeAgg.c:3083 executor/nodeWindowAgg.c:2318
+#, c-format
+msgid "aggregate %u needs to have compatible input type and transition type"
+msgstr "%u OID 집계함수에 호환 가능한 입력 형식과 변환 형식이 있어야 함"
+
+#: executor/nodeAgg.c:3149 parser/parse_agg.c:612 parser/parse_agg.c:642
+#, c-format
+msgid "aggregate function calls cannot be nested"
+msgstr "집계 함수는 중첩되어 호출 할 수 없음"
+
+#: executor/nodeCustom.c:148 executor/nodeCustom.c:159
+#, c-format
+msgid "custom scan \"%s\" does not support MarkPos"
+msgstr "\"%s\" 이름의 칼럼 탐색은 MarkPos 기능을 지원하지 않음"
+
+#: executor/nodeHashjoin.c:823 executor/nodeHashjoin.c:853
+#, c-format
+msgid "could not rewind hash-join temporary file: %m"
+msgstr "해시-조인 임시 파일을 되감을 수 없음: %m"
+
+#: executor/nodeHashjoin.c:888 executor/nodeHashjoin.c:894
+#, c-format
+msgid "could not write to hash-join temporary file: %m"
+msgstr "hash-join 임시 파일을 쓸 수 없습니다: %m"
+
+#: executor/nodeHashjoin.c:935 executor/nodeHashjoin.c:945
+#, c-format
+msgid "could not read from hash-join temporary file: %m"
+msgstr "해시-조인 임시 파일을 읽을 수 없음: %m"
+
+#: executor/nodeIndexonlyscan.c:179
+#, c-format
+msgid "lossy distance functions are not supported in index-only scans"
+msgstr "lossy distance 함수들은 인덱스 단독 탐색을 지원하지 않음"
+
+#: executor/nodeLimit.c:253
+#, c-format
+msgid "OFFSET must not be negative"
+msgstr "OFFSET은 음수가 아니어야 함"
+
+#: executor/nodeLimit.c:280
+#, c-format
+msgid "LIMIT must not be negative"
+msgstr "LIMIT는 음수가 아니어야 함"
+
+#: executor/nodeMergejoin.c:1584
+#, c-format
+msgid "RIGHT JOIN is only supported with merge-joinable join conditions"
+msgstr "RIGHT JOIN은 병합-조인 가능 조인 조건에서만 지원됨"
+
+#: executor/nodeMergejoin.c:1604
+#, c-format
+msgid "FULL JOIN is only supported with merge-joinable join conditions"
+msgstr "FULL JOIN은 병합-조인 가능 조인 조건에서만 지원됨"
+
+#: executor/nodeModifyTable.c:96
+#, c-format
+msgid "Query has too many columns."
+msgstr "쿼리에 칼럼이 너무 많습니다."
+
+#: executor/nodeModifyTable.c:123
+#, c-format
+msgid "Query provides a value for a dropped column at ordinal position %d."
+msgstr "쿼리에서 서수 위치 %d에 있는 삭제된 열의 값을 제공합니다."
+
+#: executor/nodeModifyTable.c:131
+#, c-format
+msgid "Query has too few columns."
+msgstr "쿼리에 칼럼이 너무 적습니다."
+
+#: executor/nodeModifyTable.c:1132
+#, c-format
+msgid "ON CONFLICT DO UPDATE command cannot affect row a second time"
+msgstr ""
+
+#: executor/nodeModifyTable.c:1133
+#, c-format
+msgid ""
+"Ensure that no rows proposed for insertion within the same command have "
+"duplicate constrained values."
+msgstr ""
+
+#: executor/nodeSamplescan.c:307
+#, c-format
+msgid "TABLESAMPLE parameter cannot be null"
+msgstr "TABLESAMPLE 절에는 반드시 부가 옵션값들이 있어야 합니다"
+
+#: executor/nodeSamplescan.c:320
+#, c-format
+msgid "TABLESAMPLE REPEATABLE parameter cannot be null"
+msgstr "TABLESAMPLE REPEATABLE 절은 더 이상의 부가 옵션을 쓰면 안됩니다."
+
+#: executor/nodeSubplan.c:345 executor/nodeSubplan.c:384
+#: executor/nodeSubplan.c:1036
+#, c-format
+msgid "more than one row returned by a subquery used as an expression"
+msgstr "표현식에 사용된 서브쿼리 결과가 하나 이상의 행을 리턴했습니다"
+
+#: executor/nodeWindowAgg.c:353
+#, c-format
+msgid "moving-aggregate transition function must not return null"
+msgstr "moving-aggregate transition 함수는 null 값을 반환하면 안됩니다."
+
+#: executor/nodeWindowAgg.c:1642
+#, c-format
+msgid "frame starting offset must not be null"
+msgstr "프래임 시작 위치값으로 null 값을 사용할 수 없습니다."
+
+#: executor/nodeWindowAgg.c:1655
+#, c-format
+msgid "frame starting offset must not be negative"
+msgstr "프래임 시작 위치으로 음수 값을 사용할 수 없습니다."
+
+#: executor/nodeWindowAgg.c:1668
+#, c-format
+msgid "frame ending offset must not be null"
+msgstr "프래임 끝 위치값으로 null 값을 사용할 수 없습니다."
+
+#: executor/nodeWindowAgg.c:1681
+#, c-format
+msgid "frame ending offset must not be negative"
+msgstr "프래임 끝 위치값으로 음수 값을 사용할 수 없습니다."
+
+#: executor/spi.c:210
+#, c-format
+msgid "transaction left non-empty SPI stack"
+msgstr "트랜잭션이 비어있지 않은 SPI 스택을 남겼습니다"
+
+#: executor/spi.c:211 executor/spi.c:275
+#, c-format
+msgid "Check for missing \"SPI_finish\" calls."
+msgstr "\"SPI_finish\" 호출이 빠졌는지 확인하세요"
+
+#: executor/spi.c:274
+#, c-format
+msgid "subtransaction left non-empty SPI stack"
+msgstr "하위 트랜잭션이 비어있지 않은 SPI 스택을 남겼습니다"
+
+#: executor/spi.c:1225
+#, c-format
+msgid "cannot open multi-query plan as cursor"
+msgstr "멀티 쿼리를 커서로 열 수는 없습니다"
+
+#. translator: %s is name of a SQL command, eg INSERT
+#: executor/spi.c:1230
+#, c-format
+msgid "cannot open %s query as cursor"
+msgstr "%s 쿼리로 커서를 열 수 없음."
+
+#: executor/spi.c:1338
+#, c-format
+msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"
+msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE는 지원되지 않음"
+
+#: executor/spi.c:1339 parser/analyze.c:2360
+#, c-format
+msgid "Scrollable cursors must be READ ONLY."
+msgstr "스크롤 가능 커서는 READ ONLY여야 합니다."
+
+#: executor/spi.c:2459
+#, c-format
+msgid "SQL statement \"%s\""
+msgstr "SQL 구문: \"%s\""
+
+#: executor/tqueue.c:317
+#, c-format
+msgid "could not send tuple to shared-memory queue"
+msgstr "공유 메모리 큐로 튜플을 보낼 수 없음"
+
+#: foreign/foreign.c:192
+#, c-format
+msgid "user mapping not found for \"%s\""
+msgstr "\"%s\"에 대한 사용자 매핑을 찾을 수 없음"
+
+#: foreign/foreign.c:644
+#, c-format
+msgid "invalid option \"%s\""
+msgstr "\"%s\" 옵션이 잘못됨"
+
+#: foreign/foreign.c:645
+#, c-format
+msgid "Valid options in this context are: %s"
+msgstr "이 컨텍스트에서 유효한 옵션: %s"
+
+#: lib/stringinfo.c:259
+#, c-format
+msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes."
+msgstr "%d바이트가 포함된 문자열 버퍼를 %d바이트 더 확장할 수 없습니다."
+
+#: libpq/auth.c:254
+#, c-format
+msgid "authentication failed for user \"%s\": host rejected"
+msgstr "사용자 \"%s\"의 인증을 실패했습니다: 호스트 거부됨"
+
+#: libpq/auth.c:257
+#, c-format
+msgid "\"trust\" authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 \"trust\" 인증을 실패했습니다."
+
+#: libpq/auth.c:260
+#, c-format
+msgid "Ident authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 Ident 인증을 실패했습니다."
+
+#: libpq/auth.c:263
+#, c-format
+msgid "Peer authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 peer 인증을 실패했습니다."
+
+#: libpq/auth.c:267
+#, c-format
+msgid "password authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 password 인증을 실패했습니다"
+
+#: libpq/auth.c:272
+#, c-format
+msgid "GSSAPI authentication failed for user \"%s\""
+msgstr "\"%s\" 사용자에 대한 GSSAPI 인증을 실패했습니다."
+
+#: libpq/auth.c:275
+#, c-format
+msgid "SSPI authentication failed for user \"%s\""
+msgstr "\"%s\" 사용자에 대한 SSPI 인증을 실패했습니다."
+
+#: libpq/auth.c:278
+#, c-format
+msgid "PAM authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 PAM 인증을 실패했습니다."
+
+#: libpq/auth.c:281
+#, c-format
+msgid "BSD authentication failed for user \"%s\""
+msgstr "\"%s\" 사용자에 대한 BSD 인증을 실패했습니다."
+
+#: libpq/auth.c:284
+#, c-format
+msgid "LDAP authentication failed for user \"%s\""
+msgstr "\"%s\" 사용자의 LDAP 인증을 실패했습니다."
+
+#: libpq/auth.c:287
+#, c-format
+msgid "certificate authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 인증서 인증을 실패했습니다"
+
+#: libpq/auth.c:290
+#, c-format
+msgid "RADIUS authentication failed for user \"%s\""
+msgstr "사용자 \"%s\"의 RADIUS 인증을 실패했습니다."
+
+#: libpq/auth.c:293
+#, c-format
+msgid "authentication failed for user \"%s\": invalid authentication method"
+msgstr "사용자 \"%s\"의 인증을 실패했습니다: 잘못된 인증 방법"
+
+#: libpq/auth.c:297
+#, c-format
+msgid "Connection matched pg_hba.conf line %d: \"%s\""
+msgstr "pg_hba.conf 파일의 %d번째 줄에 지정한 인증 설정이 사용됨: \"%s\""
+
+#: libpq/auth.c:352
+#, c-format
+msgid "connection requires a valid client certificate"
+msgstr "연결에 유효한 클라이언트 인증서가 필요함"
+
+#: libpq/auth.c:394
+#, c-format
+msgid ""
+"pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s"
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\", %s 연결이 복제용 연결로는 pg_hba.conf 파일 설정"
+"에 따라 거부됩니다"
+
+#: libpq/auth.c:396 libpq/auth.c:412 libpq/auth.c:470 libpq/auth.c:488
+msgid "SSL off"
+msgstr "SSL 중지"
+
+#: libpq/auth.c:396 libpq/auth.c:412 libpq/auth.c:470 libpq/auth.c:488
+msgid "SSL on"
+msgstr "SSL 동작"
+
+#: libpq/auth.c:400
+#, c-format
+msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\""
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\" 연결이 복제용 연결로는 pg_hba.conf 파일 설정에 "
+"따라 거부됩니다"
+
+#: libpq/auth.c:409
+#, c-format
+msgid ""
+"pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s"
+"\", %s"
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\", 데이터베이스 \"%s\", %s 연결이 pg_hba.conf 파"
+"일 설정에 따라 거부됩니다"
+
+#: libpq/auth.c:416
+#, c-format
+msgid ""
+"pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\""
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\", 데이터베이스 \"%s\" 연결이 pg_hba.conf 파일 설"
+"정에 따라 거부됩니다"
+
+#: libpq/auth.c:445
+#, c-format
+msgid "Client IP address resolved to \"%s\", forward lookup matches."
+msgstr ""
+"클라이언트 IP 주소가 \"%s\" 이름으로 확인됨, 호스트 이름 확인 기능으로 맞음"
+
+#: libpq/auth.c:448
+#, c-format
+msgid "Client IP address resolved to \"%s\", forward lookup not checked."
+msgstr ""
+"클라이언트 IP 주소가 \"%s\" 이름으로 확인됨, 호스트 이름 확인 기능 사용안함"
+
+#: libpq/auth.c:451
+#, c-format
+msgid "Client IP address resolved to \"%s\", forward lookup does not match."
+msgstr ""
+"클라이언트 IP 주소가 \"%s\" 이름으로 확인됨, 호스트 이름 확인 기능으로 틀림"
+
+#: libpq/auth.c:454
+#, c-format
+msgid "Could not translate client host name \"%s\" to IP address: %s."
+msgstr "\"%s\" 클라이언트 호스트 이름을 %s IP 주소로 전환할 수 없음."
+
+#: libpq/auth.c:459
+#, c-format
+msgid "Could not resolve client IP address to a host name: %s."
+msgstr "클라이언트 IP 주소를 파악할 수 없음: 대상 호스트 이름: %s"
+
+#: libpq/auth.c:468
+#, c-format
+msgid ""
+"no pg_hba.conf entry for replication connection from host \"%s\", user \"%s"
+"\", %s"
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\", %s 연결이 복제용 연결로 pg_hba.conf 파일에 설정"
+"되어 있지 않습니다"
+
+#: libpq/auth.c:475
+#, c-format
+msgid ""
+"no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\""
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\" 연결이 복제용 연결로 pg_hba.conf 파일에 설정되"
+"어 있지 않습니다"
+
+#: libpq/auth.c:485
+#, c-format
+msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s"
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\", 데이터베이스 \"%s\", %s 연결에 대한 설정이 "
+"pg_hba.conf 파일에 없습니다."
+
+#: libpq/auth.c:493
+#, c-format
+msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\""
+msgstr ""
+"호스트 \"%s\", 사용자 \"%s\", 데이터베이스 \"%s\" 연결에 대한 설정이 pg_hba."
+"conf 파일에 없습니다."
+
+#: libpq/auth.c:536 libpq/hba.c:1178
+#, c-format
+msgid ""
+"MD5 authentication is not supported when \"db_user_namespace\" is enabled"
+msgstr "\"db_user_namespace\"가 사용 가능한 경우 MD5 인증은 지원되지 않음"
+
+#: libpq/auth.c:670
+#, c-format
+msgid "expected password response, got message type %d"
+msgstr "메시지 타입 %d를 얻는 예상된 암호 응답"
+
+#: libpq/auth.c:698
+#, c-format
+msgid "invalid password packet size"
+msgstr "유효하지 않은 암호 패킷 사이즈"
+
+#: libpq/auth.c:828
+#, c-format
+msgid "GSSAPI is not supported in protocol version 2"
+msgstr "프로토콜 버전 2에서는 GSSAPI가 지원되지 않음"
+
+#: libpq/auth.c:888
+#, c-format
+msgid "expected GSS response, got message type %d"
+msgstr "GSS 응답이 필요한데 메시지 형식 %d을(를) 받음"
+
+#: libpq/auth.c:949
+msgid "accepting GSS security context failed"
+msgstr "GSS 보안 컨텍스트를 수락하지 못함"
+
+#: libpq/auth.c:975
+msgid "retrieving GSS user name failed"
+msgstr "GSS 사용자 이름을 검색하지 못함"
+
+#: libpq/auth.c:1094
+#, c-format
+msgid "SSPI is not supported in protocol version 2"
+msgstr "프로토콜 버전 2에서는 SSPI가 지원되지 않음"
+
+#: libpq/auth.c:1109
+msgid "could not acquire SSPI credentials"
+msgstr "SSPI 자격 증명을 가져올 수 없음"
+
+#: libpq/auth.c:1127
+#, c-format
+msgid "expected SSPI response, got message type %d"
+msgstr "SSPI 응답이 필요한데 메시지 형식 %d을(를) 받음"
+
+#: libpq/auth.c:1199
+msgid "could not accept SSPI security context"
+msgstr "SSPI 보안 컨텍스트를 수락할 수 없음"
+
+#: libpq/auth.c:1261
+msgid "could not get token from SSPI security context"
+msgstr "SSPI 보안 컨텍스트에서 토큰을 가져올 수 없음"
+
+#: libpq/auth.c:1380 libpq/auth.c:1399
+#, c-format
+msgid "could not translate name"
+msgstr "이름을 변환할 수 없음"
+
+#: libpq/auth.c:1412
+#, c-format
+msgid "realm name too long"
+msgstr "realm 이름이 너무 긺"
+
+#: libpq/auth.c:1427
+#, c-format
+msgid "translated account name too long"
+msgstr "변환된 접속자 이름이 너무 깁니다"
+
+#: libpq/auth.c:1613
+#, c-format
+msgid "could not create socket for Ident connection: %m"
+msgstr "Ident 연결에 소켓을 생성할 수 없습니다: %m"
+
+#: libpq/auth.c:1628
+#, c-format
+msgid "could not bind to local address \"%s\": %m"
+msgstr "로컬 주소 \"%s\"에 바인드할 수 없습니다: %m"
+
+#: libpq/auth.c:1640
+#, c-format
+msgid "could not connect to Ident server at address \"%s\", port %s: %m"
+msgstr "주소 \"%s\", 포트 %s의 Ident 서버에게 연결할 수 없습니다: %m"
+
+#: libpq/auth.c:1662
+#, c-format
+msgid "could not send query to Ident server at address \"%s\", port %s: %m"
+msgstr "주소 \"%s\", 포트 %s의 Ident 서버에게 질의를 보낼 수 없습니다: %m"
+
+#: libpq/auth.c:1679
+#, c-format
+msgid ""
+"could not receive response from Ident server at address \"%s\", port %s: %m"
+msgstr "주소 \"%s\", 포트 %s의 Ident 서버로부터 응답을 받지 못했습니다: %m"
+
+#: libpq/auth.c:1689
+#, c-format
+msgid "invalidly formatted response from Ident server: \"%s\""
+msgstr "Ident 서버로부터 잘못된 형태의 응답를 보냈습니다: \"%s\""
+
+#: libpq/auth.c:1729
+#, c-format
+msgid "peer authentication is not supported on this platform"
+msgstr "이 플랫폼에서는 peer 인증이 지원되지 않음"
+
+#: libpq/auth.c:1733
+#, c-format
+msgid "could not get peer credentials: %m"
+msgstr "신뢰성 피어를 얻을 수 없습니다: %m"
+
+#: libpq/auth.c:1742
+#, c-format
+msgid "could not look up local user ID %ld: %s"
+msgstr "UID %ld 해당하는 사용자를 찾을 수 없음: %s"
+
+#: libpq/auth.c:1826 libpq/auth.c:2152 libpq/auth.c:2512
+#, c-format
+msgid "empty password returned by client"
+msgstr "비어있는 암호는 클라이언트에 의해 돌려보냈습니다"
+
+#: libpq/auth.c:1836
+#, c-format
+msgid "error from underlying PAM layer: %s"
+msgstr "잠재적인 PAM 레이어에서의 에러: %s"
+
+#: libpq/auth.c:1917
+#, c-format
+msgid "could not create PAM authenticator: %s"
+msgstr "PAM 인증자를 생성할 수 없습니다: %s"
+
+#: libpq/auth.c:1928
+#, c-format
+msgid "pam_set_item(PAM_USER) failed: %s"
+msgstr "pam_set_item(PAM_USER) 실패: %s"
+
+#: libpq/auth.c:1939
+#, c-format
+msgid "pam_set_item(PAM_RHOST) failed: %s"
+msgstr "pam_set_item(PAM_RHOST) 실패: %s"
+
+#: libpq/auth.c:1950
+#, c-format
+msgid "pam_set_item(PAM_CONV) failed: %s"
+msgstr "pam_set_item(PAM_CONV) 실패: %s"
+
+#: libpq/auth.c:1961
+#, c-format
+msgid "pam_authenticate failed: %s"
+msgstr "PAM 인증 실패: %s"
+
+#: libpq/auth.c:1972
+#, c-format
+msgid "pam_acct_mgmt failed: %s"
+msgstr "pam_acct_mgmt 실패: %s"
+
+#: libpq/auth.c:1983
+#, c-format
+msgid "could not release PAM authenticator: %s"
+msgstr "PAM 인증자를 릴리즈할 수 없습니다: %s"
+
+#: libpq/auth.c:2048
+#, c-format
+msgid "could not initialize LDAP: %m"
+msgstr "LDAP 초기화 실패: %m"
+
+#: libpq/auth.c:2051
+#, c-format
+msgid "could not initialize LDAP: error code %d"
+msgstr "LDAP 초기화 실패: 오류번호 %d"
+
+#: libpq/auth.c:2061
+#, c-format
+msgid "could not set LDAP protocol version: %s"
+msgstr "LDAP 프로토콜 버전을 지정할 수 없음: %s"
+
+#: libpq/auth.c:2090
+#, c-format
+msgid "could not load wldap32.dll"
+msgstr "could not load wldap32.dll"
+
+#: libpq/auth.c:2098
+#, c-format
+msgid "could not load function _ldap_start_tls_sA in wldap32.dll"
+msgstr "could not load function _ldap_start_tls_sA in wldap32.dll"
+
+#: libpq/auth.c:2099
+#, c-format
+msgid "LDAP over SSL is not supported on this platform."
+msgstr "이 플랫폼에서는 SSL을 이용한 LDAP 기능을 지원하지 않음."
+
+#: libpq/auth.c:2114
+#, c-format
+msgid "could not start LDAP TLS session: %s"
+msgstr "LDAP TLS 세션을 시작할 수 없음: %s"
+
+#: libpq/auth.c:2136
+#, c-format
+msgid "LDAP server not specified"
+msgstr "LDAP 서버가 지정되지 않음"
+
+#: libpq/auth.c:2189
+#, c-format
+msgid "invalid character in user name for LDAP authentication"
+msgstr "LDAP 인증을 위한 사용자 이름에 사용할 수 없는 문자가 있습니다"
+
+#: libpq/auth.c:2204
+#, c-format
+msgid ""
+"could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": "
+"%s"
+msgstr ""
+"\"%s\" ldapbinddn (해당 서버: \"%s\") 설정에 대한 LDAP 바인드 초기화를 할 수 "
+"없음: %s"
+
+#: libpq/auth.c:2228
+#, c-format
+msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s"
+msgstr "\"%s\" 필터로 LDAP 검색 실패함, 대상 서버: \"%s\": %s"
+
+#: libpq/auth.c:2239
+#, c-format
+msgid "LDAP user \"%s\" does not exist"
+msgstr "\"%s\" LDAP 사용자가 없음"
+
+#: libpq/auth.c:2240
+#, c-format
+msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries."
+msgstr "\"%s\" 필터로 \"%s\" 서버에서 LDAP 검색을 했으나, 해당 자료가 없음"
+
+#: libpq/auth.c:2244
+#, c-format
+msgid "LDAP user \"%s\" is not unique"
+msgstr "\"%s\" LDAP 사용자가 유일하지 않습니다"
+
+#: libpq/auth.c:2245
+#, c-format
+msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry."
+msgid_plural ""
+"LDAP search for filter \"%s\" on server \"%s\" returned %d entries."
+msgstr[0] "\"%s\" 필터로 \"%s\" 서버에서 LDAP 검색 결과 %d 항목을 반환함"
+
+#: libpq/auth.c:2263
+#, c-format
+msgid ""
+"could not get dn for the first entry matching \"%s\" on server \"%s\": %s"
+msgstr "\"%s\" 첫번째 항목 조회용 dn 값을 \"%s\" 서버에서 찾을 수 없음: %s"
+
+#: libpq/auth.c:2283
+#, c-format
+msgid "could not unbind after searching for user \"%s\" on server \"%s\": %s"
+msgstr "\"%s\" 사용자 검색 후 unbind 작업을 \"%s\" 서버에서 할 수 없음: %s"
+
+#: libpq/auth.c:2313
+#, c-format
+msgid "LDAP login failed for user \"%s\" on server \"%s\": %s"
+msgstr "\"%s\" 사용자의 \"%s\" LDAP 서버 로그인 실패: %s"
+
+#: libpq/auth.c:2341
+#, c-format
+msgid ""
+"certificate authentication failed for user \"%s\": client certificate "
+"contains no user name"
+msgstr ""
+"\"%s\" 사용자에 대한 인증서 로그인 실패: 클라이언트 인증서에 사용자 이름이 없"
+"음"
+
+#: libpq/auth.c:2468
+#, c-format
+msgid "RADIUS server not specified"
+msgstr "RADIUS 서버가 지정되지 않음"
+
+#: libpq/auth.c:2475
+#, c-format
+msgid "RADIUS secret not specified"
+msgstr "RADIUS 비밀키가 지정되지 않음"
+
+#: libpq/auth.c:2491 libpq/hba.c:1632
+#, c-format
+msgid "could not translate RADIUS server name \"%s\" to address: %s"
+msgstr "\"%s\" RADIUS 서버 이름을 주소로 바꿀 수 없음: %s"
+
+#: libpq/auth.c:2519
+#, c-format
+msgid ""
+"RADIUS authentication does not support passwords longer than %d characters"
+msgstr "RADIUS 인증은 %d 글자 보다 큰 비밀번호 인증을 지원하지 않습니다"
+
+#: libpq/auth.c:2531
+#, c-format
+msgid "could not generate random encryption vector"
+msgstr "무작위 암호화 벡터를 만들 수 없음"
+
+#: libpq/auth.c:2569
+#, c-format
+msgid "could not perform MD5 encryption of password"
+msgstr "비밀번호의 MD5 암호를 만들 수 없음"
+
+# translator: %s is IPv4, IPv6, or Unix
+#: libpq/auth.c:2594
+#, c-format
+msgid "could not create RADIUS socket: %m"
+msgstr "RADIUS 소켓을 생성할 수 없습니다: %m"
+
+# translator: %s is IPv4, IPv6, or Unix
+#: libpq/auth.c:2615
+#, c-format
+msgid "could not bind local RADIUS socket: %m"
+msgstr "RADIUS 소켓에 바인드할 수 없습니다: %m"
+
+#: libpq/auth.c:2625
+#, c-format
+msgid "could not send RADIUS packet: %m"
+msgstr "RADIUS 패킷을 보낼 수 없음: %m"
+
+#: libpq/auth.c:2658 libpq/auth.c:2683
+#, c-format
+msgid "timeout waiting for RADIUS response"
+msgstr "서버 시작을 기다리는 동안 시간 초과됨"
+
+# translator: %s is IPv4, IPv6, or Unix
+#: libpq/auth.c:2676
+#, c-format
+msgid "could not check status on RADIUS socket: %m"
+msgstr "RADIUS 소켓 상태를 확인할 수 없음: %m"
+
+#: libpq/auth.c:2705
+#, c-format
+msgid "could not read RADIUS response: %m"
+msgstr "RADIUS 응답을 읽을 수 없음: %m"
+
+#: libpq/auth.c:2717 libpq/auth.c:2721
+#, c-format
+msgid "RADIUS response was sent from incorrect port: %d"
+msgstr "RADIUS 응답이 바르지 않은 포트로부터 보내졌음: %d"
+
+#: libpq/auth.c:2730
+#, c-format
+msgid "RADIUS response too short: %d"
+msgstr "RADIUS 응답이 너무 짧음: %d"
+
+#: libpq/auth.c:2737
+#, c-format
+msgid "RADIUS response has corrupt length: %d (actual length %d)"
+msgstr "RADIUS 응답 길이가 이상함: %d (실재 길이: %d)"
+
+#: libpq/auth.c:2745
+#, c-format
+msgid "RADIUS response is to a different request: %d (should be %d)"
+msgstr "RADIUS 응답이 요청과 다름: %d (기대값: %d)"
+
+#: libpq/auth.c:2770
+#, c-format
+msgid "could not perform MD5 encryption of received packet"
+msgstr "받은 패킷을 대상으로 MD5 암호화 작업할 수 없음"
+
+#: libpq/auth.c:2779
+#, c-format
+msgid "RADIUS response has incorrect MD5 signature"
+msgstr "RADIUS 응답의 MD5 값이 이상함"
+
+#: libpq/auth.c:2796
+#, c-format
+msgid "RADIUS response has invalid code (%d) for user \"%s\""
+msgstr "RADIUS 응답이 바르지 않은 값임 (%d), 대상 사용자: \"%s\""
+
+#: libpq/be-fsstubs.c:132 libpq/be-fsstubs.c:163 libpq/be-fsstubs.c:197
+#: libpq/be-fsstubs.c:237 libpq/be-fsstubs.c:262 libpq/be-fsstubs.c:310
+#: libpq/be-fsstubs.c:333 libpq/be-fsstubs.c:581
+#, c-format
+msgid "invalid large-object descriptor: %d"
+msgstr "유효하지 않은 대형 객체 설명: %d"
+
+#: libpq/be-fsstubs.c:178 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:600
+#: libpq/be-fsstubs.c:788
+#, c-format
+msgid "permission denied for large object %u"
+msgstr "%u 대형 객체에 대한 접근 권한 없음"
+
+#: libpq/be-fsstubs.c:203 libpq/be-fsstubs.c:587
+#, c-format
+msgid "large object descriptor %d was not opened for writing"
+msgstr "%d번 대형 객체 기술자가 쓰기 모드로 열려있지 않습니다"
+
+#: libpq/be-fsstubs.c:245
+#, c-format
+msgid "lo_lseek result out of range for large-object descriptor %d"
+msgstr "%d번 대형 객체 기술자에 대한 lo_lseek 반환값이 범위를 벗어남"
+
+#: libpq/be-fsstubs.c:318
+#, c-format
+msgid "lo_tell result out of range for large-object descriptor %d"
+msgstr "%d번 대형 객체 기술자에 대한 lo_tell 반환값이 범위를 벗어남"
+
+#: libpq/be-fsstubs.c:455
+#, c-format
+msgid "must be superuser to use server-side lo_import()"
+msgstr "서버 측 lo_import() 호출을 하려면, 슈퍼유저여야 합니다"
+
+#: libpq/be-fsstubs.c:456
+#, c-format
+msgid "Anyone can use the client-side lo_import() provided by libpq."
+msgstr ""
+"libpq 라이브러리를 이용한 클라이언트 측 lo_import() 호출은 아무나 할 수 있습"
+"니다."
+
+#: libpq/be-fsstubs.c:469
+#, c-format
+msgid "could not open server file \"%s\": %m"
+msgstr "서버 파일 \"%s\"을 열 수 없습니다: %m"
+
+#: libpq/be-fsstubs.c:491
+#, c-format
+msgid "could not read server file \"%s\": %m"
+msgstr "서버 파일 \"%s\"을 읽을 수 없습니다: %m"
+
+#: libpq/be-fsstubs.c:521
+#, c-format
+msgid "must be superuser to use server-side lo_export()"
+msgstr "서버 측 lo_export()는 슈퍼유저만 가능하다"
+
+#: libpq/be-fsstubs.c:522
+#, c-format
+msgid "Anyone can use the client-side lo_export() provided by libpq."
+msgstr "아무나 libpq에 의해 제공되는 클라이언트 측 lo_export 를 사용할 수 있다"
+
+#: libpq/be-fsstubs.c:547
+#, c-format
+msgid "could not create server file \"%s\": %m"
+msgstr "서버 파일 \"%s\"의 생성을 할 수 없습니다: %m"
+
+#: libpq/be-fsstubs.c:559
+#, c-format
+msgid "could not write server file \"%s\": %m"
+msgstr "서버 파일 \"%s\"에 쓸 수 없습니다: %m"
+
+#: libpq/be-fsstubs.c:813
+#, c-format
+msgid "large object read request is too large"
+msgstr "대형 객체 읽기 요청이 너무 큽니다"
+
+#: libpq/be-fsstubs.c:855 utils/adt/genfile.c:211 utils/adt/genfile.c:252
+#, c-format
+msgid "requested length cannot be negative"
+msgstr "요청한 길이는 음수일 수 없음"
+
+#: libpq/be-secure-openssl.c:189
+#, c-format
+msgid "could not create SSL context: %s"
+msgstr "SSL 컨텍스트 정보를 생성할 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:205
+#, c-format
+msgid "could not load server certificate file \"%s\": %s"
+msgstr "서버 인증서 파일 \"%s\"을 불러들일 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:211
+#, c-format
+msgid "could not access private key file \"%s\": %m"
+msgstr "비밀키 \"%s\"에 액세스할 수 없습니다: %m"
+
+#: libpq/be-secure-openssl.c:217
+#, c-format
+msgid "private key file \"%s\" is not a regular file"
+msgstr "\"%s\" 개인 키 파일은 일반 파일이 아님"
+
+#: libpq/be-secure-openssl.c:229
+#, c-format
+msgid "private key file \"%s\" must be owned by the database user or root"
+msgstr ""
+"\"%s\" 개인 키 파일의 소유주는 데이터베이스 사용자이거나 root 여야 합니다."
+
+#: libpq/be-secure-openssl.c:249
+#, c-format
+msgid "private key file \"%s\" has group or world access"
+msgstr "\"%s\" 개인 키 파일에 그룹 또는 익명 액세스 권한이 있음"
+
+#: libpq/be-secure-openssl.c:251
+#, c-format
+msgid ""
+"File must have permissions u=rw (0600) or less if owned by the database "
+"user, or permissions u=rw,g=r (0640) or less if owned by root."
+msgstr ""
+"파일의 소유주가 데이터베이스 서버 운영 계정과 같다면, 접근 권한을 u=rw "
+"(0600) 또는 더 작게 설정하고, root가 소유주라면 u=rw,g=r (0640) 권한으로 지정"
+"하세요"
+
+#: libpq/be-secure-openssl.c:258
+#, c-format
+msgid "could not load private key file \"%s\": %s"
+msgstr "비밀키 파일 \"%s\"을 불러들일 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:263
+#, c-format
+msgid "check of private key failed: %s"
+msgstr "비밀키의 확인 실패: %s"
+
+#: libpq/be-secure-openssl.c:292
+#, c-format
+msgid "could not load root certificate file \"%s\": %s"
+msgstr "root 인증서 파일 \"%s\"을 불러들일 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:316
+#, c-format
+msgid "SSL certificate revocation list file \"%s\" ignored"
+msgstr "\"%s\" SSL 인증서 파기 목록 파일이 무시되었음"
+
+#: libpq/be-secure-openssl.c:318
+#, c-format
+msgid "SSL library does not support certificate revocation lists."
+msgstr "SSL 라이브러리가 인증서 파기 목록을 지원하지 않습니다."
+
+#: libpq/be-secure-openssl.c:323
+#, c-format
+msgid "could not load SSL certificate revocation list file \"%s\": %s"
+msgstr "\"%s\" SSL 인증서 회수 목록 파일을 불러들일 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:370
+#, c-format
+msgid "could not initialize SSL connection: %s"
+msgstr "SSL연결을 초기화할 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:378
+#, c-format
+msgid "could not set SSL socket: %s"
+msgstr "SSL 소켓을 지정할 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:432
+#, c-format
+msgid "could not accept SSL connection: %m"
+msgstr "SSL 연결을 받아드릴 수 없습니다: %m"
+
+#: libpq/be-secure-openssl.c:436 libpq/be-secure-openssl.c:447
+#, c-format
+msgid "could not accept SSL connection: EOF detected"
+msgstr "SSL 연결을 받아드릴 수 없습니다: EOF 감지됨"
+
+#: libpq/be-secure-openssl.c:441
+#, c-format
+msgid "could not accept SSL connection: %s"
+msgstr "SSL 연결을 받아드릴 수 없습니다: %s"
+
+#: libpq/be-secure-openssl.c:452 libpq/be-secure-openssl.c:593
+#: libpq/be-secure-openssl.c:653
+#, c-format
+msgid "unrecognized SSL error code: %d"
+msgstr "인식되지 않은 SSL 에러 코드 %d"
+
+#: libpq/be-secure-openssl.c:496
+#, c-format
+msgid "SSL certificate's common name contains embedded null"
+msgstr "SSL 인증서의 일반 이름에 포함된 null이 있음"
+
+#: libpq/be-secure-openssl.c:507
+#, c-format
+msgid "SSL connection from \"%s\""
+msgstr "\"%s\" 로부터의 SSL 연결"
+
+#: libpq/be-secure-openssl.c:584 libpq/be-secure-openssl.c:644
+#, c-format
+msgid "SSL error: %s"
+msgstr "SSL 에러: %s"
+
+#: libpq/be-secure-openssl.c:1055
+#, c-format
+msgid "ECDH: unrecognized curve name: %s"
+msgstr "ECDH: 알 수 없는 curve 이름: %s"
+
+#: libpq/be-secure-openssl.c:1060
+#, c-format
+msgid "ECDH: could not create key"
+msgstr "ECDH: 키 생성 실패"
+
+#: libpq/be-secure-openssl.c:1084
+msgid "no SSL error reported"
+msgstr "SSL 오류 없음"
+
+#: libpq/be-secure-openssl.c:1088
+#, c-format
+msgid "SSL error code %lu"
+msgstr "SSL 오류 번호 %lu"
+
+#: libpq/be-secure.c:171 libpq/be-secure.c:256
+#, c-format
+msgid "terminating connection due to unexpected postmaster exit"
+msgstr "postmaster의 예상치 못한 종료로 연결을 종료합니다"
+
+#: libpq/crypt.c:54
+#, c-format
+msgid "Role \"%s\" does not exist."
+msgstr "\"%s\" 롤 없음"
+
+#: libpq/crypt.c:64
+#, c-format
+msgid "User \"%s\" has no password assigned."
+msgstr "\"%s\" 사용자 비밀번호가 아직 할당되지 않음"
+
+#: libpq/crypt.c:79
+#, c-format
+msgid "User \"%s\" has an empty password."
+msgstr "\"%s\" 사용자 비밀번호가 설정되어 있지 않습니다."
+
+#: libpq/crypt.c:159
+#, c-format
+msgid "User \"%s\" has an expired password."
+msgstr "\"%s\" 사용자 비밀번호가 기한 만료되었습니다."
+
+#: libpq/crypt.c:167
+#, c-format
+msgid "Password does not match for user \"%s\"."
+msgstr "\"%s\" 사용자의 비밀번호가 틀립니다."
+
+#: libpq/hba.c:188
+#, c-format
+msgid "authentication file token too long, skipping: \"%s\""
+msgstr "인증 파일의 토큰이 너무 길어서 건너뜁니다: \"%s\""
+
+#: libpq/hba.c:332
+#, c-format
+msgid "could not open secondary authentication file \"@%s\" as \"%s\": %m"
+msgstr "2차 인증파일 \"%s\"으로 \"@%s\"를 열 수 없다: %m"
+
+#: libpq/hba.c:407
+#, c-format
+msgid "authentication file line too long"
+msgstr "인증 파일 줄이 너무 깁니다"
+
+#: libpq/hba.c:408 libpq/hba.c:755 libpq/hba.c:771 libpq/hba.c:801
+#: libpq/hba.c:847 libpq/hba.c:860 libpq/hba.c:882 libpq/hba.c:891
+#: libpq/hba.c:912 libpq/hba.c:924 libpq/hba.c:943 libpq/hba.c:964
+#: libpq/hba.c:975 libpq/hba.c:1030 libpq/hba.c:1048 libpq/hba.c:1060
+#: libpq/hba.c:1077 libpq/hba.c:1087 libpq/hba.c:1101 libpq/hba.c:1117
+#: libpq/hba.c:1132 libpq/hba.c:1143 libpq/hba.c:1179 libpq/hba.c:1217
+#: libpq/hba.c:1228 libpq/hba.c:1248 libpq/hba.c:1259 libpq/hba.c:1276
+#: libpq/hba.c:1325 libpq/hba.c:1362 libpq/hba.c:1372 libpq/hba.c:1428
+#: libpq/hba.c:1440 libpq/hba.c:1453 libpq/hba.c:1545 libpq/hba.c:1634
+#: libpq/hba.c:1652 libpq/hba.c:1673 tsearch/ts_locale.c:182
+#, c-format
+msgid "line %d of configuration file \"%s\""
+msgstr "%d번째 줄(\"%s\" 환경 설정 파일)"
+
+#. translator: the second %s is a list of auth methods
+#: libpq/hba.c:753
+#, c-format
+msgid ""
+"authentication option \"%s\" is only valid for authentication methods %s"
+msgstr "\"%s\" 인증 옵션은 %s 인증 방법에만 유효함"
+
+#: libpq/hba.c:769
+#, c-format
+msgid "authentication method \"%s\" requires argument \"%s\" to be set"
+msgstr "\"%s\" 인증 방법의 경우 \"%s\" 인자를 설정해야 함"
+
+#: libpq/hba.c:790
+#, c-format
+msgid "missing entry in file \"%s\" at end of line %d"
+msgstr "\"%s\" 파일의 %d번째 줄의 끝 라인에 빠진 엔트리가 있습니다 "
+
+#: libpq/hba.c:800
+#, c-format
+msgid "multiple values in ident field"
+msgstr "ident 자리에 여러 값이 있음"
+
+#: libpq/hba.c:845
+#, c-format
+msgid "multiple values specified for connection type"
+msgstr "연결 형식 자리에 여러 값이 있음"
+
+#: libpq/hba.c:846
+#, c-format
+msgid "Specify exactly one connection type per line."
+msgstr "한 줄에 하나의 연결 형태만 지정해야 합니다"
+
+#: libpq/hba.c:859
+#, c-format
+msgid "local connections are not supported by this build"
+msgstr "로컬 접속 기능을 뺀 채로 서버가 만들어졌습니다."
+
+#: libpq/hba.c:880
+#, c-format
+msgid "hostssl requires SSL to be turned on"
+msgstr "hostssl 접속은 SSL 기능이 활성화 되어 있어야 합니다"
+
+#: libpq/hba.c:881
+#, c-format
+msgid "Set ssl = on in postgresql.conf."
+msgstr "postgresql.conf 파일에 ssl = on 설정을 하세요."
+
+#: libpq/hba.c:889
+#, c-format
+msgid "hostssl is not supported by this build"
+msgstr "이 서버는 hostssl 접속 기능을 지원하지 않습니다."
+
+#: libpq/hba.c:890
+#, c-format
+msgid "Compile with --with-openssl to use SSL connections."
+msgstr ""
+"SSL 연결을 사용하기 위해 --enable-ssl 옵션을 사용해서 서버를 다시 컴파일 하세"
+"요"
+
+#: libpq/hba.c:910
+#, c-format
+msgid "invalid connection type \"%s\""
+msgstr "\"%s\" 값은 잘못된 연결 형식입니다"
+
+#: libpq/hba.c:923
+#, c-format
+msgid "end-of-line before database specification"
+msgstr "데이터베이스 지정 전에 줄 끝에 도달함"
+
+#: libpq/hba.c:942
+#, c-format
+msgid "end-of-line before role specification"
+msgstr "롤 지정 전에 줄 끝에 도달함"
+
+#: libpq/hba.c:963
+#, c-format
+msgid "end-of-line before IP address specification"
+msgstr "IP 주소 지정 전에 줄 끝에 도달함"
+
+#: libpq/hba.c:973
+#, c-format
+msgid "multiple values specified for host address"
+msgstr "호스트 주소 부분에 여러 값이 지정됨"
+
+#: libpq/hba.c:974
+#, c-format
+msgid "Specify one address range per line."
+msgstr "한 줄에 하나의 주소 범위가 있어야 합니다."
+
+#: libpq/hba.c:1028
+#, c-format
+msgid "invalid IP address \"%s\": %s"
+msgstr "\"%s\" 형태는 잘못된 IP 주소 형태입니다: %s"
+
+#: libpq/hba.c:1046
+#, c-format
+msgid "specifying both host name and CIDR mask is invalid: \"%s\""
+msgstr "호스트 이름과 CIDR 마스크는 함께 쓸 수 없습니다: \"%s\""
+
+#: libpq/hba.c:1058
+#, c-format
+msgid "invalid CIDR mask in address \"%s\""
+msgstr "\"%s\" 주소에 잘못된 CIDR 마스크가 있음"
+
+#: libpq/hba.c:1075
+#, c-format
+msgid "end-of-line before netmask specification"
+msgstr "넷마스크 지정 전에 줄 끝에 도달함"
+
+#: libpq/hba.c:1076
+#, c-format
+msgid ""
+"Specify an address range in CIDR notation, or provide a separate netmask."
+msgstr "주소 범위는 CIDR 표기법을 쓰거나 넷마스크 표기법을 쓰세요"
+
+#: libpq/hba.c:1086
+#, c-format
+msgid "multiple values specified for netmask"
+msgstr "넷마스크 부분에 여러 값이 지정됨"
+
+#: libpq/hba.c:1099
+#, c-format
+msgid "invalid IP mask \"%s\": %s"
+msgstr "잘못된 IP 마스크, \"%s\": %s"
+
+#: libpq/hba.c:1116
+#, c-format
+msgid "IP address and mask do not match"
+msgstr "IP 주소와 마스크가 맞지 않습니다"
+
+#: libpq/hba.c:1131
+#, c-format
+msgid "end-of-line before authentication method"
+msgstr "인증 방법 전에 줄 끝에 도달함"
+
+#: libpq/hba.c:1141
+#, c-format
+msgid "multiple values specified for authentication type"
+msgstr "인증 방법 부분에 여러 값이 지정됨"
+
+#: libpq/hba.c:1142
+#, c-format
+msgid "Specify exactly one authentication type per line."
+msgstr "하나의 인증 방법에 대해서 한 줄씩 지정해야 합니다"
+
+#: libpq/hba.c:1215
+#, c-format
+msgid "invalid authentication method \"%s\""
+msgstr "\"%s\" 인증 방법이 잘못됨"
+
+#: libpq/hba.c:1226
+#, c-format
+msgid "invalid authentication method \"%s\": not supported by this build"
+msgstr "\"%s\" 인증 방법이 잘못됨: 이 서버에서 지원되지 않음"
+
+#: libpq/hba.c:1247
+#, c-format
+msgid "gssapi authentication is not supported on local sockets"
+msgstr "gssapi 인증은 로컬 소켓에서 지원되지 않음"
+
+#: libpq/hba.c:1258
+#, c-format
+msgid "peer authentication is only supported on local sockets"
+msgstr "peer 인증은 로컬 소켓에서만 지원함"
+
+#: libpq/hba.c:1275
+#, c-format
+msgid "cert authentication is only supported on hostssl connections"
+msgstr "cert 인증은 hostssl 연결에서만 지원됨"
+
+#: libpq/hba.c:1324
+#, c-format
+msgid "authentication option not in name=value format: %s"
+msgstr "인증 옵션이 이름=값 형태가 아님: %s"
+
+#: libpq/hba.c:1361
+#, c-format
+msgid ""
+"cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or "
+"ldapurl together with ldapprefix"
+msgstr ""
+"ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapurl 옵션은 "
+"ldapprefix 옵션과 함께 사용할 수 없음"
+
+#: libpq/hba.c:1371
+#, c-format
+msgid ""
+"authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix"
+"\", or \"ldapsuffix\" to be set"
+msgstr ""
+"\"ldap\" 인증 방법의 경우 \"ldapbasedn\", \"ldapprefix\", \"ldapsuffix\"옵션"
+"이 있어야 함"
+
+#: libpq/hba.c:1414
+msgid "ident, peer, gssapi, sspi, and cert"
+msgstr "ident, peer, gssapi, sspi 및 cert"
+
+#: libpq/hba.c:1427
+#, c-format
+msgid "clientcert can only be configured for \"hostssl\" rows"
+msgstr "clientcert는 \"hostssl\" 행에 대해서만 구성할 수 있음"
+
+#: libpq/hba.c:1438
+#, c-format
+msgid ""
+"client certificates can only be checked if a root certificate store is "
+"available"
+msgstr ""
+"루트 인증서 저장소가 사용 가능한 경우에만 클라이언트 인증서를 검사할 수 있음"
+
+#: libpq/hba.c:1452
+#, c-format
+msgid "clientcert can not be set to 0 when using \"cert\" authentication"
+msgstr "\"cert\" 인증을 사용하는 경우 clientcert를 0으로 설정할 수 없음"
+
+#: libpq/hba.c:1488
+#, c-format
+msgid "could not parse LDAP URL \"%s\": %s"
+msgstr "\"%s\" LDAP URL을 분석할 수 없음: %s"
+
+#: libpq/hba.c:1496
+#, c-format
+msgid "unsupported LDAP URL scheme: %s"
+msgstr "지원하지 않는 LDAP URL 스킴: %s"
+
+#: libpq/hba.c:1512
+#, c-format
+msgid "filters not supported in LDAP URLs"
+msgstr "LDAP URL에서 필터 속성을 지원하지 않음"
+
+#: libpq/hba.c:1520
+#, c-format
+msgid "LDAP URLs not supported on this platform"
+msgstr "이 플랫폼에서는 LDAP URL 기능을 지원하지 않음."
+
+#: libpq/hba.c:1544
+#, c-format
+msgid "invalid LDAP port number: \"%s\""
+msgstr "LDAP 포트 번호가 잘못됨: \"%s\""
+
+#: libpq/hba.c:1584 libpq/hba.c:1591
+msgid "gssapi and sspi"
+msgstr "gssapi 및 sspi"
+
+#: libpq/hba.c:1600 libpq/hba.c:1609
+msgid "sspi"
+msgstr "sspi"
+
+#: libpq/hba.c:1651
+#, c-format
+msgid "invalid RADIUS port number: \"%s\""
+msgstr "RADIUS 포트 번호가 잘못됨: \"%s\""
+
+#: libpq/hba.c:1671
+#, c-format
+msgid "unrecognized authentication option name: \"%s\""
+msgstr "알 수 없는 인증 옵션 이름: \"%s\""
+
+#: libpq/hba.c:1806 guc-file.l:594
+#, c-format
+msgid "could not open configuration file \"%s\": %m"
+msgstr "\"%s\" 설정 파일 을 열수 없습니다: %m"
+
+#: libpq/hba.c:1855
+#, c-format
+msgid "configuration file \"%s\" contains no entries"
+msgstr "\"%s\" 설정 파일에 구성 항목이 없음"
+
+#: libpq/hba.c:1951
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "\"%s\" 정규식이 잘못됨: %s"
+
+#: libpq/hba.c:2011
+#, c-format
+msgid "regular expression match for \"%s\" failed: %s"
+msgstr "\"%s\"에 대한 정규식 일치 실패: %s"
+
+#: libpq/hba.c:2030
+#, c-format
+msgid ""
+"regular expression \"%s\" has no subexpressions as requested by "
+"backreference in \"%s\""
+msgstr "\"%s\" 정규식에는 \"%s\"의 backreference에서 요청된 하위 식이 없음"
+
+#: libpq/hba.c:2127
+#, c-format
+msgid "provided user name (%s) and authenticated user name (%s) do not match"
+msgstr "제공된 사용자 이름(%s) 및 인증된 사용자 이름(%s)이 일치하지 않음"
+
+#: libpq/hba.c:2147
+#, c-format
+msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\""
+msgstr ""
+"\"%s\" 사용자맵 파일에 \"%s\" 사용자를 \"%s\" 사용자로 인증할 설정이 없음"
+
+#: libpq/hba.c:2182
+#, c-format
+msgid "could not open usermap file \"%s\": %m"
+msgstr "\"%s\" 사용자맵 파일을 열 수 없습니다: %m"
+
+#: libpq/pqcomm.c:202
+#, c-format
+msgid "could not set socket to nonblocking mode: %m"
+msgstr "소켓을 nonblocking 모드로 지정할 수 없음: %m"
+
+#: libpq/pqcomm.c:354
+#, c-format
+msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)"
+msgstr "\"%s\" 유닉스 도메인 소켓 경로가 너무 깁니다 (최대 %d 바이트)"
+
+#: libpq/pqcomm.c:375
+#, c-format
+msgid "could not translate host name \"%s\", service \"%s\" to address: %s"
+msgstr "호스트 이름 \"%s\", 서비스 \"%s\"를 변환할 수 없습니다. 주소 : %s"
+
+#: libpq/pqcomm.c:379
+#, c-format
+msgid "could not translate service \"%s\" to address: %s"
+msgstr "서비스 \"%s\"를 변환할 수 없습니다. 주소 : %s"
+
+#: libpq/pqcomm.c:406
+#, c-format
+msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded"
+msgstr "최대 접속자 수 MAXLISTEN (%d) 초과로 더 이상 접속이 불가능합니다"
+
+#: libpq/pqcomm.c:415
+msgid "IPv4"
+msgstr "IPv4"
+
+#: libpq/pqcomm.c:419
+msgid "IPv6"
+msgstr "IPv6"
+
+#: libpq/pqcomm.c:424
+msgid "Unix"
+msgstr "유닉스"
+
+#: libpq/pqcomm.c:429
+#, c-format
+msgid "unrecognized address family %d"
+msgstr "%d는 인식되지 않는 가족 주소입니다"
+
+# translator: %s is IPv4, IPv6, or Unix
+#. translator: %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:440
+#, c-format
+msgid "could not create %s socket: %m"
+msgstr "%s 소켓을 생성할 수 없습니다: %m"
+
+#: libpq/pqcomm.c:465
+#, c-format
+msgid "setsockopt(SO_REUSEADDR) failed: %m"
+msgstr "setsockopt(SO_REUSEADDR) 실패: %m"
+
+#: libpq/pqcomm.c:480
+#, c-format
+msgid "setsockopt(IPV6_V6ONLY) failed: %m"
+msgstr "setsockopt(IPV6_V6ONLY) 실패: %m"
+
+# translator: %s is IPv4, IPv6, or Unix
+#. translator: %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:499
+#, c-format
+msgid "could not bind %s socket: %m"
+msgstr "%s 소켓에 바인드할 수 없습니다: %m"
+
+#: libpq/pqcomm.c:502
+#, c-format
+msgid ""
+"Is another postmaster already running on port %d? If not, remove socket file "
+"\"%s\" and retry."
+msgstr ""
+"다른 postmaster 가 포트 %d에서 이미 실행중인것 같습니다? 그렇지 않다면 소켓 "
+"파일 \"%s\"을 제거하고 다시 시도해보십시오"
+
+#: libpq/pqcomm.c:505
+#, c-format
+msgid ""
+"Is another postmaster already running on port %d? If not, wait a few seconds "
+"and retry."
+msgstr ""
+"다른 postmaster 가 포트 %d에서 이미 실행중인것 같습니다? 그렇지 않다면 몇 초"
+"를 기다렸다가 다시 시도해보십시오."
+
+# translator: %s is IPv4, IPv6, or Unix
+#. translator: %s is IPv4, IPv6, or Unix
+#: libpq/pqcomm.c:538
+#, c-format
+msgid "could not listen on %s socket: %m"
+msgstr "%s 소켓을 들을 수 없습니다: %m"
+
+#: libpq/pqcomm.c:623
+#, c-format
+msgid "group \"%s\" does not exist"
+msgstr "\"%s\" 그룹 없음"
+
+#: libpq/pqcomm.c:633
+#, c-format
+msgid "could not set group of file \"%s\": %m"
+msgstr "파일 \"%s\" 의 그룹을 세팅할 수 없습니다: %m"
+
+#: libpq/pqcomm.c:644
+#, c-format
+msgid "could not set permissions of file \"%s\": %m"
+msgstr "파일 \"%s\" 의 퍼미션을 세팅할 수 없습니다: %m"
+
+#: libpq/pqcomm.c:674
+#, c-format
+msgid "could not accept new connection: %m"
+msgstr "새로운 연결을 생성할 수 없습니다: %m"
+
+#: libpq/pqcomm.c:885
+#, c-format
+msgid "there is no client connection"
+msgstr "클라이언트 연결이 없음"
+
+#: libpq/pqcomm.c:936 libpq/pqcomm.c:1032
+#, c-format
+msgid "could not receive data from client: %m"
+msgstr "클라이언트에게 데이터를 받을 수 없습니다: %m"
+
+#: libpq/pqcomm.c:1177 tcop/postgres.c:3917
+#, c-format
+msgid "terminating connection because protocol synchronization was lost"
+msgstr "프로토콜 동기화 작업 실패로 연결을 종료합니다"
+
+#: libpq/pqcomm.c:1243
+#, c-format
+msgid "unexpected EOF within message length word"
+msgstr "예상치 못한 EOF가 메시지의 길이 워드안에서 발생했습니다."
+
+#: libpq/pqcomm.c:1254
+#, c-format
+msgid "invalid message length"
+msgstr "메시지의 길이가 유효하지 않습니다"
+
+#: libpq/pqcomm.c:1276 libpq/pqcomm.c:1289
+#, c-format
+msgid "incomplete message from client"
+msgstr "클라이언트으로부터의 완전하지 못한 메시지입니다"
+
+#: libpq/pqcomm.c:1422
+#, c-format
+msgid "could not send data to client: %m"
+msgstr "클라이언트에게 데이터를 보낼 수 없습니다: %m"
+
+#: libpq/pqformat.c:437
+#, c-format
+msgid "no data left in message"
+msgstr "메시지에 아무런 데이터가 없습니다"
+
+#: libpq/pqformat.c:557 libpq/pqformat.c:575 libpq/pqformat.c:596
+#: utils/adt/arrayfuncs.c:1457 utils/adt/rowtypes.c:563
+#, c-format
+msgid "insufficient data left in message"
+msgstr "부족한 데이터는 메시지 안에 넣어져 있습니다"
+
+#: libpq/pqformat.c:637 libpq/pqformat.c:666
+#, c-format
+msgid "invalid string in message"
+msgstr "메시지안에 유효하지 않은 문자열이 있습니다"
+
+#: libpq/pqformat.c:682
+#, c-format
+msgid "invalid message format"
+msgstr "메시지 포맷이 유효하지 않습니다."
+
+# # search5 끝
+# # advance 부분
+#: main/main.c:264
+#, c-format
+msgid "%s: WSAStartup failed: %d\n"
+msgstr "%s: WSAStartup 작업 실패: %d\n"
+
+#: main/main.c:328
+#, c-format
+msgid ""
+"%s is the PostgreSQL server.\n"
+"\n"
+msgstr ""
+"%s 프로그램은 PostgreSQL 서버입니다.\n"
+"\n"
+
+#: main/main.c:329
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"사용법:\n"
+" %s [옵션]...\n"
+"\n"
+
+#: main/main.c:330
+#, c-format
+msgid "Options:\n"
+msgstr "옵션들:\n"
+
+#: main/main.c:331
+#, c-format
+msgid " -B NBUFFERS number of shared buffers\n"
+msgstr " -B NBUFFERS 공유 버퍼 개수\n"
+
+#: main/main.c:332
+#, c-format
+msgid " -c NAME=VALUE set run-time parameter\n"
+msgstr " -c NAME=VALUE 실시간 매개 변수 지정\n"
+
+#: main/main.c:333
+#, c-format
+msgid " -C NAME print value of run-time parameter, then exit\n"
+msgstr " -C NAME 실시간 매개 변수 값을 보여주고 마침\n"
+
+#: main/main.c:334
+#, c-format
+msgid " -d 1-5 debugging level\n"
+msgstr " -d 1-5 디버깅 수준\n"
+
+#: main/main.c:335
+#, c-format
+msgid " -D DATADIR database directory\n"
+msgstr " -D DATADIR 데이터 디렉터리\n"
+
+#: main/main.c:336
+#, c-format
+msgid " -e use European date input format (DMY)\n"
+msgstr " -e 날짜 입력 양식이 유럽형(DMY)을 사용함\n"
+
+#: main/main.c:337
+#, c-format
+msgid " -F turn fsync off\n"
+msgstr " -F fsync 기능 끔\n"
+
+#: main/main.c:338
+#, c-format
+msgid " -h HOSTNAME host name or IP address to listen on\n"
+msgstr " -h HOSTNAME 서버로 사용할 호스트 이름 또는 IP\n"
+
+#: main/main.c:339
+#, c-format
+msgid " -i enable TCP/IP connections\n"
+msgstr " -i TCP/IP 연결 사용함\n"
+
+#: main/main.c:340
+#, c-format
+msgid " -k DIRECTORY Unix-domain socket location\n"
+msgstr " -k DIRECTORY 유닉스 도메인 소켓 위치\n"
+
+#: main/main.c:342
+#, c-format
+msgid " -l enable SSL connections\n"
+msgstr " -l SSL 연결 기능 사용함\n"
+
+#: main/main.c:344
+#, c-format
+msgid " -N MAX-CONNECT maximum number of allowed connections\n"
+msgstr " -N MAX-CONNECT 최대 동시 연결 개수\n"
+
+#: main/main.c:345
+#, c-format
+msgid ""
+" -o OPTIONS pass \"OPTIONS\" to each server process (obsolete)\n"
+msgstr ""
+" -o OPTIONS 개별 서버 프로세스를 \"OPTIONS\" 옵션으로 실행 (옛기"
+"능)\n"
+
+#: main/main.c:346
+#, c-format
+msgid " -p PORT port number to listen on\n"
+msgstr " -p PORT 서버 포트 번호\n"
+
+#: main/main.c:347
+#, c-format
+msgid " -s show statistics after each query\n"
+msgstr " -s 각 쿼리 뒤에 통계정보를 보여줌\n"
+
+#: main/main.c:348
+#, c-format
+msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n"
+msgstr " -S WORK-MEM 정렬작업에 사용할 메모리 크기(kb 단위)를 지정\n"
+
+#: main/main.c:349
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version 버전 정보 보여주고 마침\n"
+
+#: main/main.c:350
+#, c-format
+msgid " --NAME=VALUE set run-time parameter\n"
+msgstr " --NAME=VALUE 실시간 매개 변수 지정\n"
+
+#: main/main.c:351
+#, c-format
+msgid " --describe-config describe configuration parameters, then exit\n"
+msgstr " --describe-config 서버 환경 설정값에 대한 설명을 보여주고 마침\n"
+
+#: main/main.c:352
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help 이 도움말을 보여주고 마침\n"
+
+#: main/main.c:354
+#, c-format
+msgid ""
+"\n"
+"Developer options:\n"
+msgstr ""
+"\n"
+"개발자 옵션들:\n"
+
+#: main/main.c:355
+#, c-format
+msgid " -f s|i|n|m|h forbid use of some plan types\n"
+msgstr " -f s|i|n|m|h 쿼리최적화기의 기능을 제한 함\n"
+
+#: main/main.c:356
+#, c-format
+msgid ""
+" -n do not reinitialize shared memory after abnormal exit\n"
+msgstr ""
+" -n 비정상적 종료 뒤에 공유 메모리를 초기화 하지 않음\n"
+
+#: main/main.c:357
+#, c-format
+msgid " -O allow system table structure changes\n"
+msgstr " -O 시스템 테이블의 구조를 바꿀 수 있도록 함\n"
+
+#: main/main.c:358
+#, c-format
+msgid " -P disable system indexes\n"
+msgstr " -P 시스템 인덱스들을 사용하지 않음\n"
+
+#: main/main.c:359
+#, c-format
+msgid " -t pa|pl|ex show timings after each query\n"
+msgstr " -t pa|pl|ex 각 쿼리 다음 작업시간을 보여줌\n"
+
+#: main/main.c:360
+#, c-format
+msgid ""
+" -T send SIGSTOP to all backend processes if one dies\n"
+msgstr ""
+" -T 하나의 하위 서버 프로세스가 비정상으로 마치며 모든\n"
+" 다른 서버 프로세스에게 SIGSTOP 신호를 보냄\n"
+
+#: main/main.c:361
+#, c-format
+msgid " -W NUM wait NUM seconds to allow attach from a debugger\n"
+msgstr ""
+" -W NUM 디버그 작업을 위해 지정한 숫자의 초만큼 기다린다\n"
+
+#: main/main.c:363
+#, c-format
+msgid ""
+"\n"
+"Options for single-user mode:\n"
+msgstr ""
+"\n"
+"단일사용자 모드에서 사용할 수 있는 옵션들:\n"
+
+#: main/main.c:364
+#, c-format
+msgid ""
+" --single selects single-user mode (must be first argument)\n"
+msgstr " --single 단일 사용자 모드 선택 (인자의 첫번째로 와야함)\n"
+
+#: main/main.c:365
+#, c-format
+msgid " DBNAME database name (defaults to user name)\n"
+msgstr " DBNAME 데이터베이스 이름 (초기값: 사용자이름)\n"
+
+#: main/main.c:366
+#, c-format
+msgid " -d 0-5 override debugging level\n"
+msgstr " -d 0-5 디버깅 수준\n"
+
+#: main/main.c:367
+#, c-format
+msgid " -E echo statement before execution\n"
+msgstr " -E 실행하기 전에 작업명령을 출력함\n"
+
+#: main/main.c:368
+#, c-format
+msgid ""
+" -j do not use newline as interactive query delimiter\n"
+msgstr ""
+" -j 대화형 쿼리의 명령 실행 구분 문자로 줄바꿈문자를 쓰지 않"
+"음\n"
+
+#: main/main.c:369 main/main.c:374
+#, c-format
+msgid " -r FILENAME send stdout and stderr to given file\n"
+msgstr ""
+" -r FILENAME stdout, stderr 쪽으로 보내는 내용을 FILENAME 파일로 저장"
+"함\n"
+
+#: main/main.c:371
+#, c-format
+msgid ""
+"\n"
+"Options for bootstrapping mode:\n"
+msgstr ""
+"\n"
+"부트스트랩 모드에서 사용할 수 있는 옵션들:\n"
+
+#: main/main.c:372
+#, c-format
+msgid ""
+" --boot selects bootstrapping mode (must be first argument)\n"
+msgstr " --boot 부트스트랩 모드로 실행 (첫번째 인자로 와야함)\n"
+
+#: main/main.c:373
+#, c-format
+msgid ""
+" DBNAME database name (mandatory argument in bootstrapping "
+"mode)\n"
+msgstr " DBNAME 데이터베이스 이름 (부트스트랩 모드에서 필수)\n"
+
+#: main/main.c:375
+#, c-format
+msgid " -x NUM internal use\n"
+msgstr " -x NUM 내부적인 옵션\n"
+
+#: main/main.c:377
+#, c-format
+msgid ""
+"\n"
+"Please read the documentation for the complete list of run-time\n"
+"configuration settings and how to set them on the command line or in\n"
+"the configuration file.\n"
+"\n"
+"Report bugs to <[email protected]>.\n"
+msgstr ""
+"\n"
+"이 실시간 환경 변수용 설정값들의 자세한 사용법과\n"
+"서버 환경 설정 파일에 어떻게 지정하고 사용하는지에 대한 사항은\n"
+"PostgreSQL 문서를 참조하세요.\n"
+"\n"
+"오류 보고: <[email protected]>.\n"
+
+#: main/main.c:391
+#, c-format
+msgid ""
+"\"root\" execution of the PostgreSQL server is not permitted.\n"
+"The server must be started under an unprivileged user ID to prevent\n"
+"possible system security compromise. See the documentation for\n"
+"more information on how to properly start the server.\n"
+msgstr ""
+"시스템 보안 관련 문제로, PostgreSQL server를 \"root\" ID로 실행할 수 없습니"
+"다.\n"
+"반드시 일반 사용자 ID(시스템 관리자 권한이 없는 ID)로 서버를 실행하십시오.\n"
+"Server를 어떻게 안전하게 기동하는가 하는 것은 문서를 참조하시기 바랍니다.\n"
+
+#: main/main.c:408
+#, c-format
+msgid "%s: real and effective user IDs must match\n"
+msgstr "%s: real 또는 effective user ID 들은 반드시 일치되어야 한다.\n"
+
+#: main/main.c:415
+#, c-format
+msgid ""
+"Execution of PostgreSQL by a user with administrative permissions is not\n"
+"permitted.\n"
+"The server must be started under an unprivileged user ID to prevent\n"
+"possible system security compromises. See the documentation for\n"
+"more information on how to properly start the server.\n"
+msgstr ""
+"시스템 보안 관련 문제로, PostgreSQL server를 시스템 관리자 ID로 실행할 수 없"
+"습니다.\n"
+"반드시 일반 사용자 ID(시스템 관리자 권한이 없는 ID)로 서버를 실행하십시오.\n"
+"Server를 어떻게 안전하게 기동하는가 하는 것은 문서를 참조하시기 바랍니다.\n"
+
+#: nodes/extensible.c:66
+#, c-format
+msgid "extensible node type \"%s\" already exists"
+msgstr "\"%s\" 이름의 확장가능한 노드 형이 이미 있습니다"
+
+#: nodes/extensible.c:114
+#, c-format
+msgid "ExtensibleNodeMethods \"%s\" was not registered"
+msgstr "\"%s\" ExtensibleNodeMethods가 등록되어 있지 않음"
+
+#: nodes/nodeFuncs.c:124 nodes/nodeFuncs.c:155 parser/parse_coerce.c:1820
+#: parser/parse_coerce.c:1848 parser/parse_coerce.c:1924
+#: parser/parse_expr.c:2019 parser/parse_func.c:597 parser/parse_oper.c:952
+#, c-format
+msgid "could not find array type for data type %s"
+msgstr "자료형 %s 에 대해서는 배열 자료형을 사용할 수 없습니다"
+
+#: optimizer/path/allpaths.c:2653
+#, c-format
+msgid "WHERE CURRENT OF is not supported on a view with no underlying relation"
+msgstr ""
+"no underlying 릴레이션이 있는 뷰에서는 WHERE CURRENT OF 구문을 지원하지 않음"
+
+#: optimizer/path/allpaths.c:2658
+#, c-format
+msgid ""
+"WHERE CURRENT OF is not supported on a view with more than one underlying "
+"relation"
+msgstr ""
+"WHERE CURRENT OF 옵션은 하나 이상의 릴레이션을 사용하는 뷰에서는 사용할 수 없"
+"음"
+
+#: optimizer/path/allpaths.c:2663
+#, c-format
+msgid ""
+"WHERE CURRENT OF is not supported on a view with grouping or aggregation"
+msgstr "WHERE CURRENT OF 옵션은 그룹화나 집계 작업용 뷰에서는 사용할 수 없음"
+
+#: optimizer/path/joinrels.c:802
+#, c-format
+msgid ""
+"FULL JOIN is only supported with merge-joinable or hash-joinable join "
+"conditions"
+msgstr ""
+"FULL JOIN 구문은 머지 조인이나, 해시 조인이 가능한 상황에서만 사용할 수 있습"
+"니다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: optimizer/plan/initsplan.c:1124
+#, c-format
+msgid "%s cannot be applied to the nullable side of an outer join"
+msgstr ""
+"%s 구문은 outer 조인으로 null 값이 올 수 있는 쪽에 대해서는 적용할 수 없습니"
+"다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: optimizer/plan/planner.c:1480 parser/analyze.c:1549 parser/analyze.c:1747
+#: parser/analyze.c:2528
+#, c-format
+msgid "%s is not allowed with UNION/INTERSECT/EXCEPT"
+msgstr "%s 구문은 UNION/INTERSECT/EXCEPT 예약어들과 함께 사용할 수 없습니다."
+
+#: optimizer/plan/planner.c:3809
+#, c-format
+msgid "could not implement GROUP BY"
+msgstr "GROUP BY를 구현할 수 없음"
+
+#: optimizer/plan/planner.c:3810 optimizer/plan/planner.c:4203
+#: optimizer/prep/prepunion.c:929
+#, c-format
+msgid ""
+"Some of the datatypes only support hashing, while others only support "
+"sorting."
+msgstr "해싱만 지원하는 자료형도 있고, 정렬만 지원하는 자료형도 있습니다."
+
+#: optimizer/plan/planner.c:4202
+#, c-format
+msgid "could not implement DISTINCT"
+msgstr "DISTINCT를 구현할 수 없음"
+
+#: optimizer/plan/planner.c:4832
+#, c-format
+msgid "could not implement window PARTITION BY"
+msgstr "창 PARTITION BY를 구현할 수 없음"
+
+#: optimizer/plan/planner.c:4833
+#, c-format
+msgid "Window partitioning columns must be of sortable datatypes."
+msgstr "창 분할 열은 정렬 가능한 데이터 형식이어야 합니다."
+
+#: optimizer/plan/planner.c:4837
+#, c-format
+msgid "could not implement window ORDER BY"
+msgstr "창 ORDER BY를 구현할 수 없음"
+
+#: optimizer/plan/planner.c:4838
+#, c-format
+msgid "Window ordering columns must be of sortable datatypes."
+msgstr "창 순서 지정 열은 정렬 가능한 데이터 형식이어야 합니다."
+
+#: optimizer/plan/setrefs.c:415
+#, c-format
+msgid "too many range table entries"
+msgstr "너무 많은 테이블이 사용되었습니다"
+
+#: optimizer/prep/prepunion.c:484
+#, c-format
+msgid "could not implement recursive UNION"
+msgstr "재귀 UNION을 구현할 수 없음"
+
+#: optimizer/prep/prepunion.c:485
+#, c-format
+msgid "All column datatypes must be hashable."
+msgstr "모든 열 데이터 형식은 해시 가능해야 합니다."
+
+#. translator: %s is UNION, INTERSECT, or EXCEPT
+#: optimizer/prep/prepunion.c:928
+#, c-format
+msgid "could not implement %s"
+msgstr "%s 구문은 구현할 수 없음"
+
+#: optimizer/util/clauses.c:4634
+#, c-format
+msgid "SQL function \"%s\" during inlining"
+msgstr ""
+
+#: optimizer/util/plancat.c:114
+#, c-format
+msgid "cannot access temporary or unlogged relations during recovery"
+msgstr "복구 작업 중에는 임시 테이블이나, 언로그드 테이블을 접근할 수 없음"
+
+#: optimizer/util/plancat.c:611
+#, c-format
+msgid "whole row unique index inference specifications are not supported"
+msgstr ""
+
+#: optimizer/util/plancat.c:628
+#, c-format
+msgid "constraint in ON CONFLICT clause has no associated index"
+msgstr "ON CONFLICT 처리를 위해 관련된 인덱스가 없습니다"
+
+#: optimizer/util/plancat.c:679
+#, c-format
+msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints"
+msgstr "제외 제약 조건이 있어 ON CONFLICT DO UPDATE 작업은 할 수 없습니다"
+
+#: optimizer/util/plancat.c:784
+#, c-format
+msgid ""
+"there is no unique or exclusion constraint matching the ON CONFLICT "
+"specification"
+msgstr ""
+"ON CONFLICT 절을 사용하는 경우, unique 나 exclude 제약 조건이 있어야 함"
+
+#: parser/analyze.c:663 parser/analyze.c:1321
+#, c-format
+msgid "VALUES lists must all be the same length"
+msgstr "VALUES 목록은 모두 같은 길이여야 함"
+
+#: parser/analyze.c:859
+#, c-format
+msgid "INSERT has more expressions than target columns"
+msgstr "INSERT 구문에 target columns 보다 더 많은 표현식이 존재하고 있다"
+
+#: parser/analyze.c:877
+#, c-format
+msgid "INSERT has more target columns than expressions"
+msgstr ""
+"INSERT 구문에 target columns 보다 더 많은 표현식(expressions)이 존재하고 있다"
+
+#: parser/analyze.c:881
+#, c-format
+msgid ""
+"The insertion source is a row expression containing the same number of "
+"columns expected by the INSERT. Did you accidentally use extra parentheses?"
+msgstr ""
+
+#: parser/analyze.c:1142 parser/analyze.c:1522
+#, c-format
+msgid "SELECT ... INTO is not allowed here"
+msgstr "SELECT ... INTO 구문은 여기서는 사용할 수 없음"
+
+#: parser/analyze.c:1335
+#, c-format
+msgid "DEFAULT can only appear in a VALUES list within INSERT"
+msgstr "DEFAULT는 INSERT 내의 VALUES 목록에만 표시될 수 있음"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:1454 parser/analyze.c:2698
+#, c-format
+msgid "%s cannot be applied to VALUES"
+msgstr "%s 구문은 VALUES 에 적용할 수 없음"
+
+#: parser/analyze.c:1675
+#, c-format
+msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause"
+msgstr "UNION/INTERSECT/EXCEPT ORDER BY 절이 잘못됨"
+
+#: parser/analyze.c:1676
+#, c-format
+msgid "Only result column names can be used, not expressions or functions."
+msgstr "결과 열 이름만 사용할 수 있고 식 또는 함수는 사용할 수 없습니다."
+
+#: parser/analyze.c:1677
+#, c-format
+msgid ""
+"Add the expression/function to every SELECT, or move the UNION into a FROM "
+"clause."
+msgstr "모든 SELECT에 식/함수를 추가하거나 UNION을 FROM 절로 이동하십시오."
+
+#: parser/analyze.c:1737
+#, c-format
+msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"
+msgstr "INTO 는 UNION/INTERSECT/EXCEPT 의 첫번째 SELECT 에만 허용된다"
+
+#: parser/analyze.c:1801
+#, c-format
+msgid ""
+"UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of "
+"same query level"
+msgstr ""
+"UNION/INTERSECT/EXCEPT 멤버 문에서 같은 쿼리 수준의 다른 관계를 참조할 수 없"
+"음"
+
+#: parser/analyze.c:1890
+#, c-format
+msgid "each %s query must have the same number of columns"
+msgstr "각각의 %s query 는 같은 수의 columns 를 가져야 한다."
+
+#: parser/analyze.c:2283
+#, c-format
+msgid "RETURNING must have at least one column"
+msgstr "RETURNING 절에는 적어도 하나 이상의 칼럼이 있어야 합니다"
+
+#: parser/analyze.c:2320
+#, c-format
+msgid "cannot specify both SCROLL and NO SCROLL"
+msgstr "SCROLL 과 NO SCROLL 둘다를 명시할 수 없다"
+
+#: parser/analyze.c:2338
+#, c-format
+msgid "DECLARE CURSOR must not contain data-modifying statements in WITH"
+msgstr ""
+"DECLARE CURSOR 구문에서 사용하는 WITH 절 안에는 자료 변경 구문이 없어야 합니"
+"다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2346
+#, c-format
+msgid "DECLARE CURSOR WITH HOLD ... %s is not supported"
+msgstr "DECLARE CURSOR WITH HOLD ... %s 구문은 지원되지 않음"
+
+#: parser/analyze.c:2349
+#, c-format
+msgid "Holdable cursors must be READ ONLY."
+msgstr "보류 가능 커서는 READ ONLY여야 합니다."
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2357
+#, c-format
+msgid "DECLARE SCROLL CURSOR ... %s is not supported"
+msgstr "DECLARE SCROLL CURSOR ... %s 구문은 지원되지 않음"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2368
+#, c-format
+msgid "DECLARE INSENSITIVE CURSOR ... %s is not supported"
+msgstr "DECLARE INSENSITIVE CURSOR ... %s 구문은 지원되지 않음"
+
+#: parser/analyze.c:2371
+#, c-format
+msgid "Insensitive cursors must be READ ONLY."
+msgstr "민감하지 않은 커서는 READ ONLY여야 합니다."
+
+#: parser/analyze.c:2437
+#, c-format
+msgid "materialized views must not use data-modifying statements in WITH"
+msgstr ""
+"구체화된 뷰 정의에 사용한 WITH 절 안에는 자료 변경 구문이 없어야 합니다"
+
+#: parser/analyze.c:2447
+#, c-format
+msgid "materialized views must not use temporary tables or views"
+msgstr "구체화된 뷰는 임시 테이블이나 뷰를 사용할 수 없습니다"
+
+#: parser/analyze.c:2457
+#, c-format
+msgid "materialized views may not be defined using bound parameters"
+msgstr ""
+
+#: parser/analyze.c:2469
+#, c-format
+msgid "materialized views cannot be UNLOGGED"
+msgstr "구체화된 뷰는 UNLOGGED 옵션을 사용할 수 없습니다."
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2535
+#, c-format
+msgid "%s is not allowed with DISTINCT clause"
+msgstr "%s 절은 DISTINCT 절과 함께 사용할 수 없습니다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2542
+#, c-format
+msgid "%s is not allowed with GROUP BY clause"
+msgstr "%s 절은 GROUP BY 절과 함께 사용할 수 없습니다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2549
+#, c-format
+msgid "%s is not allowed with HAVING clause"
+msgstr "%s 절은 HAVING 절과 함께 사용할 수 없습니다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2556
+#, c-format
+msgid "%s is not allowed with aggregate functions"
+msgstr "%s 절은 집계 함수와 함께 사용할 수 없습니다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2563
+#, c-format
+msgid "%s is not allowed with window functions"
+msgstr "%s 절은 윈도우 함수와 함께 사용할 수 없습니다"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2570
+#, c-format
+msgid "%s is not allowed with set-returning functions in the target list"
+msgstr "%s 절은 대상 목록에서 세트 반환 함수와 함께 사용할 수 없습니다."
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2649
+#, c-format
+msgid "%s must specify unqualified relation names"
+msgstr "%s 절에는 unqualified 릴레이션 이름을 지정해야 합니다."
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2680
+#, c-format
+msgid "%s cannot be applied to a join"
+msgstr "%s 절은 조인을 적용할 수 없습니다."
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2689
+#, c-format
+msgid "%s cannot be applied to a function"
+msgstr "%s 절은 함수에 적용할 수 없습니다."
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2707
+#, c-format
+msgid "%s cannot be applied to a WITH query"
+msgstr "%s 절은 WITH 쿼리에 적용할 수 없음"
+
+#. translator: %s is a SQL row locking clause such as FOR UPDATE
+#: parser/analyze.c:2724
+#, c-format
+msgid "relation \"%s\" in %s clause not found in FROM clause"
+msgstr "\"%s\" 릴레이션 (대상 구문: %s) 이 FROM 절 내에 없습니다"
+
+#: parser/parse_agg.c:223 parser/parse_oper.c:220
+#, c-format
+msgid "could not identify an ordering operator for type %s"
+msgstr "%s 자료형에서 사용할 순서 정하는 연산자를 찾을 수 없습니다."
+
+#: parser/parse_agg.c:225
+#, c-format
+msgid "Aggregates with DISTINCT must be able to sort their inputs."
+msgstr ""
+"DISTINCT와 함께 작업하는 집계 작업은 그 입력 자료가 정렬될 수 있어야 합니다"
+
+#: parser/parse_agg.c:260
+#, c-format
+msgid "GROUPING must have fewer than 32 arguments"
+msgstr "GROUPING 인자로는 32개 이내로 지정해야 합니다"
+
+#: parser/parse_agg.c:363
+msgid "aggregate functions are not allowed in JOIN conditions"
+msgstr "JOIN 조건문에서는 집계 함수가 허용되지 않습니다"
+
+#: parser/parse_agg.c:365
+msgid "grouping operations are not allowed in JOIN conditions"
+msgstr "JOIN 조건문에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:377
+msgid ""
+"aggregate functions are not allowed in FROM clause of their own query level"
+msgstr "집계 함수는 자신의 쿼리 수준의 FROM 절에서는 사용할 수 없습니다."
+
+#: parser/parse_agg.c:379
+msgid ""
+"grouping operations are not allowed in FROM clause of their own query level"
+msgstr ""
+
+#: parser/parse_agg.c:384
+msgid "aggregate functions are not allowed in functions in FROM"
+msgstr "FROM 절 내의 함수 표현식 내에서는 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:386
+msgid "grouping operations are not allowed in functions in FROM"
+msgstr "FROM 절 내의 함수 표현식 내에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:394
+msgid "aggregate functions are not allowed in policy expressions"
+msgstr "정책 표현식에서는 집계 함수 사용을 허용하지 않습니다"
+
+#: parser/parse_agg.c:396
+msgid "grouping operations are not allowed in policy expressions"
+msgstr "정책 표현식에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:413
+msgid "aggregate functions are not allowed in window RANGE"
+msgstr "윈도우 RANGE 안에서는 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:415
+msgid "grouping operations are not allowed in window RANGE"
+msgstr "윈도우 RANGE 안에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:420
+msgid "aggregate functions are not allowed in window ROWS"
+msgstr "윈도우 ROWS 안에서는 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:422
+msgid "grouping operations are not allowed in window ROWS"
+msgstr "윈도우 ROWS 안에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:455
+msgid "aggregate functions are not allowed in check constraints"
+msgstr "체크 제약 조건에서는 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:457
+msgid "grouping operations are not allowed in check constraints"
+msgstr "체크 제약 조건에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:464
+msgid "aggregate functions are not allowed in DEFAULT expressions"
+msgstr "DEFAULT 표현식에서는 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:466
+msgid "grouping operations are not allowed in DEFAULT expressions"
+msgstr "DEFAULT 표현식에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:471
+msgid "aggregate functions are not allowed in index expressions"
+msgstr "인덱스 표현식에서는 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:473
+msgid "grouping operations are not allowed in index expressions"
+msgstr "인덱스 표현식에서는 그룹핑 연산이 허용되지 않습니다"
+
+#: parser/parse_agg.c:478
+msgid "aggregate functions are not allowed in index predicates"
+msgstr "집계 함수는 함수 기반 인덱스의 함수로 사용할 수 없습니다"
+
+#: parser/parse_agg.c:480
+msgid "grouping operations are not allowed in index predicates"
+msgstr "그룹핑 작업은 함수 기반 인덱스의 함수로 사용할 수 없습니다"
+
+#: parser/parse_agg.c:485
+msgid "aggregate functions are not allowed in transform expressions"
+msgstr "transform 식(expression)에 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:487
+msgid "grouping operations are not allowed in transform expressions"
+msgstr "transform 식(expression)에 그룹핑 작업를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:492
+msgid "aggregate functions are not allowed in EXECUTE parameters"
+msgstr "EXECUTE 매개 변수로 집계 함수를 사용할 수 없습니다"
+
+#: parser/parse_agg.c:494
+msgid "grouping operations are not allowed in EXECUTE parameters"
+msgstr "EXECUTE 매개 변수로 그룹핑 작업을 사용할 수 없습니다"
+
+#: parser/parse_agg.c:499
+msgid "aggregate functions are not allowed in trigger WHEN conditions"
+msgstr "트리거의 WHEN 조건절에 집계 함수가 허용되지 않습니다"
+
+#: parser/parse_agg.c:501
+msgid "grouping operations are not allowed in trigger WHEN conditions"
+msgstr "트리거의 WHEN 조건절에 그룹핑 작업이 허용되지 않습니다"
+
+#. translator: %s is name of a SQL construct, eg GROUP BY
+#: parser/parse_agg.c:524 parser/parse_clause.c:1550
+#, c-format
+msgid "aggregate functions are not allowed in %s"
+msgstr "집계 함수는 %s 절에서 사용할 수 없습니다."
+
+#. translator: %s is name of a SQL construct, eg GROUP BY
+#: parser/parse_agg.c:527
+#, c-format
+msgid "grouping operations are not allowed in %s"
+msgstr "그룹핑 작업은 %s 절에서 사용할 수 없습니다."
+
+#: parser/parse_agg.c:635
+#, c-format
+msgid ""
+"outer-level aggregate cannot contain a lower-level variable in its direct "
+"arguments"
+msgstr ""
+
+#: parser/parse_agg.c:706
+#, c-format
+msgid "aggregate function calls cannot contain window function calls"
+msgstr "집계 함수 호출은 윈도우 함수 호출을 포함할 수 없음"
+
+#: parser/parse_agg.c:784
+msgid "window functions are not allowed in JOIN conditions"
+msgstr "윈도우 함수는 JOIN 조건에 사용할 수 없음"
+
+#: parser/parse_agg.c:791
+msgid "window functions are not allowed in functions in FROM"
+msgstr "윈도우 함수는 FROM 절에 있는 함수로 사용할 수 없음"
+
+#: parser/parse_agg.c:797
+msgid "window functions are not allowed in policy expressions"
+msgstr "윈도우 함수는 정책 식에 사용할 수 없음"
+
+#: parser/parse_agg.c:809
+msgid "window functions are not allowed in window definitions"
+msgstr "윈도우 함수는 윈도우 함수 정의에 사용할 수 없음"
+
+#: parser/parse_agg.c:840
+msgid "window functions are not allowed in check constraints"
+msgstr "윈도우 함수는 check 제약조건에 사용할 수 없음"
+
+#: parser/parse_agg.c:844
+msgid "window functions are not allowed in DEFAULT expressions"
+msgstr "윈도우 함수는 DEFAULT 식에서 사용할 수 없음"
+
+#: parser/parse_agg.c:847
+msgid "window functions are not allowed in index expressions"
+msgstr "윈도우 함수는 인덱스 식에서 사용할 수 없음"
+
+#: parser/parse_agg.c:850
+msgid "window functions are not allowed in index predicates"
+msgstr "윈도우 함수는 함수 기반 인덱스에서 사용할 수 없음"
+
+#: parser/parse_agg.c:853
+msgid "window functions are not allowed in transform expressions"
+msgstr "윈도우 함수는 transform 식에서 사용할 수 없음"
+
+#: parser/parse_agg.c:856
+msgid "window functions are not allowed in EXECUTE parameters"
+msgstr "윈도우 함수는 EXECUTE 매개 변수 설정 값으로 사용할 수 없음"
+
+#: parser/parse_agg.c:859
+msgid "window functions are not allowed in trigger WHEN conditions"
+msgstr "윈도우 함수는 트리거의 WHEN 조건절에서 사용할 수 없음"
+
+#. translator: %s is name of a SQL construct, eg GROUP BY
+#: parser/parse_agg.c:879 parser/parse_clause.c:1559
+#, c-format
+msgid "window functions are not allowed in %s"
+msgstr "%s 안에서는 윈도우 함수를 사용할 수 없음"
+
+#: parser/parse_agg.c:913 parser/parse_clause.c:2396
+#, c-format
+msgid "window \"%s\" does not exist"
+msgstr "\"%s\" 윈도우 함수가 없음"
+
+#: parser/parse_agg.c:998
+#, c-format
+msgid "too many grouping sets present (maximum 4096)"
+msgstr "너무 많은 그룹핑 세트가 있습니다 (최대값 4096)"
+
+#: parser/parse_agg.c:1147
+#, c-format
+msgid ""
+"aggregate functions are not allowed in a recursive query's recursive term"
+msgstr "집계 함수는 재귀 쿼리의 재귀 조건에 사용할 수 없음"
+
+#: parser/parse_agg.c:1340
+#, c-format
+msgid ""
+"column \"%s.%s\" must appear in the GROUP BY clause or be used in an "
+"aggregate function"
+msgstr ""
+"column \"%s.%s\" 는 반드시 GROUP BY 절내에 있어야 하던지 또는 집계 함수 내에"
+"서 사용되어져야 한다"
+
+#: parser/parse_agg.c:1343
+#, c-format
+msgid ""
+"Direct arguments of an ordered-set aggregate must use only grouped columns."
+msgstr ""
+
+#: parser/parse_agg.c:1348
+#, c-format
+msgid "subquery uses ungrouped column \"%s.%s\" from outer query"
+msgstr ""
+"subquery 가 outer query 에서 그룹화 되지 않은 열인 \"%s.%s\"를 사용합니다"
+
+#: parser/parse_agg.c:1512
+#, c-format
+msgid ""
+"arguments to GROUPING must be grouping expressions of the associated query "
+"level"
+msgstr ""
+
+#: parser/parse_clause.c:649
+#, c-format
+msgid "multiple column definition lists are not allowed for the same function"
+msgstr "다중 칼럼 정의 목록은 같은 함수용으로 허용하지 않음"
+
+#: parser/parse_clause.c:682
+#, c-format
+msgid ""
+"ROWS FROM() with multiple functions cannot have a column definition list"
+msgstr ""
+
+#: parser/parse_clause.c:683
+#, c-format
+msgid ""
+"Put a separate column definition list for each function inside ROWS FROM()."
+msgstr ""
+
+#: parser/parse_clause.c:689
+#, c-format
+msgid "UNNEST() with multiple arguments cannot have a column definition list"
+msgstr ""
+
+#: parser/parse_clause.c:690
+#, c-format
+msgid ""
+"Use separate UNNEST() calls inside ROWS FROM(), and attach a column "
+"definition list to each one."
+msgstr ""
+
+#: parser/parse_clause.c:697
+#, c-format
+msgid "WITH ORDINALITY cannot be used with a column definition list"
+msgstr "WITH ORDINALITY 구문은 칼럼 정의 목록과 함께 쓸 수 없습니다."
+
+#: parser/parse_clause.c:698
+#, c-format
+msgid "Put the column definition list inside ROWS FROM()."
+msgstr "ROWS FROM() 안에 칼럼 정의 목록을 넣으세요."
+
+#: parser/parse_clause.c:753
+#, c-format
+msgid "tablesample method %s does not exist"
+msgstr "\"%s\" 테이블 샘플링 방법이 없습니다"
+
+#: parser/parse_clause.c:775
+#, c-format
+msgid "tablesample method %s requires %d argument, not %d"
+msgid_plural "tablesample method %s requires %d arguments, not %d"
+msgstr[0] "\"%s\" 테이블 샘플링 방법 %d개 인자를 지정해야함, (현재 %d개)"
+
+#: parser/parse_clause.c:809
+#, c-format
+msgid "tablesample method %s does not support REPEATABLE"
+msgstr "\"%s\" 테이블 샘플링 방법은 REPEATABLE 옵션을 지원하지 않음"
+
+#: parser/parse_clause.c:940
+#, c-format
+msgid "TABLESAMPLE clause can only be applied to tables and materialized views"
+msgstr "TABLESAMPLE 절은 테이블과 구체화된 뷰에서만 사용할 수 있습니다"
+
+#: parser/parse_clause.c:1110
+#, c-format
+msgid "column name \"%s\" appears more than once in USING clause"
+msgstr "USING 절 내에 열 이름 \"%s\" 가 한번 이상 사용되었습니다"
+
+#: parser/parse_clause.c:1125
+#, c-format
+msgid "common column name \"%s\" appears more than once in left table"
+msgstr "left table 내에 common column 이름 \"%s\" 가 한번 이상 사용되었다"
+
+#: parser/parse_clause.c:1134
+#, c-format
+msgid "column \"%s\" specified in USING clause does not exist in left table"
+msgstr "USING 조건절에서 지정한 \"%s\" 열이 왼쪽 테이블에 없음"
+
+#: parser/parse_clause.c:1148
+#, c-format
+msgid "common column name \"%s\" appears more than once in right table"
+msgstr "common column name \"%s\"가 right table 에 한번 이상 사용되었다"
+
+#: parser/parse_clause.c:1157
+#, c-format
+msgid "column \"%s\" specified in USING clause does not exist in right table"
+msgstr "USING 조건절에서 지정한 \"%s\" 열이 오른쪽 테이블에 없음"
+
+#: parser/parse_clause.c:1211
+#, c-format
+msgid "column alias list for \"%s\" has too many entries"
+msgstr " \"%s\" 를 위한 열 alias list 에 너무 많은 entry 가 포함되어 있다"
+
+#. translator: %s is name of a SQL construct, eg LIMIT
+#: parser/parse_clause.c:1520
+#, c-format
+msgid "argument of %s must not contain variables"
+msgstr "%s 의 인자로 변수를 포함할 수 없습니다."
+
+#. translator: first %s is name of a SQL construct, eg ORDER BY
+#: parser/parse_clause.c:1685
+#, c-format
+msgid "%s \"%s\" is ambiguous"
+msgstr "%s \"%s\" 가 명확하지 않은 표현입니다."
+
+#. translator: %s is name of a SQL construct, eg ORDER BY
+#: parser/parse_clause.c:1714
+#, c-format
+msgid "non-integer constant in %s"
+msgstr "정수가 아닌 상수가 %s 에 포함되어 있습니다"
+
+#. translator: %s is name of a SQL construct, eg ORDER BY
+#: parser/parse_clause.c:1736
+#, c-format
+msgid "%s position %d is not in select list"
+msgstr "%s position %d 가 select list 에 포함되어 있지 않습니다"
+
+#: parser/parse_clause.c:2178
+#, c-format
+msgid "CUBE is limited to 12 elements"
+msgstr "CUBE 인자로는 12개 이하의 인자만 허용합니다"
+
+#: parser/parse_clause.c:2384
+#, c-format
+msgid "window \"%s\" is already defined"
+msgstr "\"%s\" 이름의 윈도우 함수가 이미 정의됨"
+
+#: parser/parse_clause.c:2446
+#, c-format
+msgid "cannot override PARTITION BY clause of window \"%s\""
+msgstr "\"%s\" 창의 PARTITION BY 절을 재정의할 수 없음"
+
+#: parser/parse_clause.c:2458
+#, c-format
+msgid "cannot override ORDER BY clause of window \"%s\""
+msgstr "\"%s\" 창의 ORDER BY 절을 재정의할 수 없음"
+
+#: parser/parse_clause.c:2488 parser/parse_clause.c:2494
+#, c-format
+msgid "cannot copy window \"%s\" because it has a frame clause"
+msgstr "프래임 절이 있어, \"%s\" 윈도우를 복사할 수 없음."
+
+#: parser/parse_clause.c:2496
+#, c-format
+msgid "Omit the parentheses in this OVER clause."
+msgstr "OVER 절에 괄호가 빠졌음"
+
+#: parser/parse_clause.c:2562
+#, c-format
+msgid ""
+"in an aggregate with DISTINCT, ORDER BY expressions must appear in argument "
+"list"
+msgstr ""
+"DISTINCT, ORDER BY 표현식을 집계 함수와 쓸 때는, 반드시 select list 에 나타나"
+"야만 합니다"
+
+#: parser/parse_clause.c:2563
+#, c-format
+msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list"
+msgstr ""
+"SELECT DISTINCT, ORDER BY 표현식을 위해서 반드시 select list 에 나타나야만 합"
+"니다"
+
+#: parser/parse_clause.c:2596
+#, c-format
+msgid "an aggregate with DISTINCT must have at least one argument"
+msgstr "DISTINCT 예약어로 집계를 할 경우 적어도 하나의 인자는 있어야 함"
+
+#: parser/parse_clause.c:2597
+#, c-format
+msgid "SELECT DISTINCT must have at least one column"
+msgstr "SELECT DISTINCT 구문은 적어도 한 개 이상의 칼럼이 있어야 합니다"
+
+#: parser/parse_clause.c:2663 parser/parse_clause.c:2695
+#, c-format
+msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions"
+msgstr ""
+"SELECT DISTINCT ON 표현식은 반드시 초기 ORDER BY 표현식과 일치하여야 한다"
+
+#: parser/parse_clause.c:2774
+#, c-format
+msgid "ASC/DESC is not allowed in ON CONFLICT clause"
+msgstr "ASC/DESC 예약어는 ON CONFLICT 절과 함께 사용할 수 없습니다."
+
+#: parser/parse_clause.c:2780
+#, c-format
+msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause"
+msgstr "NULLS FIRST/LAST 절은 ON CONFLICT 절과 함께 사용할 수 없습니다."
+
+#: parser/parse_clause.c:2860
+#, c-format
+msgid ""
+"ON CONFLICT DO UPDATE requires inference specification or constraint name"
+msgstr ""
+
+#: parser/parse_clause.c:2861
+#, c-format
+msgid "For example, ON CONFLICT (column_name)."
+msgstr "사용예, ON CONFLICT (칼럼이름)."
+
+#: parser/parse_clause.c:2872
+#, c-format
+msgid "ON CONFLICT is not supported with system catalog tables"
+msgstr "ON CONFLICT 절은 시스템 카탈로그 테이블에서는 사용할 수 없습니다"
+
+#: parser/parse_clause.c:2880
+#, c-format
+msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table"
+msgstr ""
+"\"%s\" 테이블에는 ON CONFLICT 기능을 사용할 수 없습니다. 이 테이블은 카탈로"
+"그 테이블로 사용됩니다."
+
+#: parser/parse_clause.c:3012
+#, c-format
+msgid "operator %s is not a valid ordering operator"
+msgstr "%s 연산자는 유효한 순서 지정 연산자가 아님"
+
+#: parser/parse_clause.c:3014
+#, c-format
+msgid ""
+"Ordering operators must be \"<\" or \">\" members of btree operator families."
+msgstr ""
+"순서 지정 연산자는 btree 연산자 패밀리의 \"<\" or \">\" 멤버여야 합니다."
+
+#: parser/parse_coerce.c:971 parser/parse_coerce.c:1001
+#: parser/parse_coerce.c:1019 parser/parse_coerce.c:1034
+#: parser/parse_expr.c:2053 parser/parse_expr.c:2577 parser/parse_target.c:885
+#, c-format
+msgid "cannot cast type %s to %s"
+msgstr "%s 자료형을 %s 자료형으로 형변환할 수 없습니다."
+
+#: parser/parse_coerce.c:1004
+#, c-format
+msgid "Input has too few columns."
+msgstr "입력에 너무 적은 열을 지정했습니다."
+
+#: parser/parse_coerce.c:1022
+#, c-format
+msgid "Cannot cast type %s to %s in column %d."
+msgstr "%s 자료형을 %s 자료형으로 형변환할 수 없습니다 해당 열 %d."
+
+#: parser/parse_coerce.c:1037
+#, c-format
+msgid "Input has too many columns."
+msgstr "입력에 너무 많은 열을 지정했습니다."
+
+#. translator: first %s is name of a SQL construct, eg WHERE
+#: parser/parse_coerce.c:1080
+#, c-format
+msgid "argument of %s must be type boolean, not type %s"
+msgstr "%s의 인자는 %s 자료형이 아니라, boolean 자료형이어야 합니다"
+
+#. translator: %s is name of a SQL construct, eg WHERE
+#. translator: %s is name of a SQL construct, eg LIMIT
+#: parser/parse_coerce.c:1090 parser/parse_coerce.c:1139
+#, c-format
+msgid "argument of %s must not return a set"
+msgstr "%s 의 인자는 set(집합) 을 return할수 없습니다."
+
+#. translator: first %s is name of a SQL construct, eg LIMIT
+#: parser/parse_coerce.c:1127
+#, c-format
+msgid "argument of %s must be type %s, not type %s"
+msgstr "%s의 인자는 %s 자료형이어야 함(%s 자료형이 아님)"
+
+#. translator: first %s is name of a SQL construct, eg CASE
+#: parser/parse_coerce.c:1260
+#, c-format
+msgid "%s types %s and %s cannot be matched"
+msgstr "%s 자료형 %s 와 %s 는 서로 매치되지 않습니다"
+
+#. translator: first %s is name of a SQL construct, eg CASE
+#: parser/parse_coerce.c:1327
+#, c-format
+msgid "%s could not convert type %s to %s"
+msgstr "%s 는 자료형 %s 자료형에서 %s 자료형으로 변환될 수 없습니다."
+
+#: parser/parse_coerce.c:1629
+#, c-format
+msgid "arguments declared \"anyelement\" are not all alike"
+msgstr "\"anyelement\" 로 선언된 인자들이 모두 같지 않습니다"
+
+#: parser/parse_coerce.c:1649
+#, c-format
+msgid "arguments declared \"anyarray\" are not all alike"
+msgstr "\"anyarray\" 로 선언된 인자들이 모두 같지 않습니다."
+
+#: parser/parse_coerce.c:1669
+#, c-format
+msgid "arguments declared \"anyrange\" are not all alike"
+msgstr "\"anyarray\" 로 선언된 인자들이 모두 같지 않습니다."
+
+#: parser/parse_coerce.c:1698 parser/parse_coerce.c:1909
+#: parser/parse_coerce.c:1943
+#, c-format
+msgid "argument declared \"anyarray\" is not an array but type %s"
+msgstr "\"anyarray\" 로 선언된 인자들이 array 가 아니고, %s 자료형입니다"
+
+#: parser/parse_coerce.c:1714
+#, c-format
+msgid ""
+"argument declared \"anyarray\" is not consistent with argument declared "
+"\"anyelement\""
+msgstr ""
+"\"anyarray\" 로 선언된 인자들이 \"anyelement\" 로 선언된 인자들과 일관성이 있"
+"질 않습니다"
+
+#: parser/parse_coerce.c:1735 parser/parse_coerce.c:1956
+#, c-format
+msgid "argument declared \"anyrange\" is not a range type but type %s"
+msgstr "\"anyarray\" 로 선언된 인자들이 range 자료형이 아니고, %s 자료형입니다"
+
+#: parser/parse_coerce.c:1751
+#, c-format
+msgid ""
+"argument declared \"anyrange\" is not consistent with argument declared "
+"\"anyelement\""
+msgstr ""
+"\"anyrange\" 로 선언된 인자들이 \"anyelement\" 로 선언된 인자들과 일관성이 있"
+"질 않습니다"
+
+#: parser/parse_coerce.c:1771
+#, c-format
+msgid "could not determine polymorphic type because input has type \"unknown\""
+msgstr "입력에 \"unknown\" 형식이 있으므로 다변 형식을 확인할 수 없음"
+
+#: parser/parse_coerce.c:1781
+#, c-format
+msgid "type matched to anynonarray is an array type: %s"
+msgstr "anynonarray에 일치된 형식이 배열 형식임: %s"
+
+#: parser/parse_coerce.c:1791
+#, c-format
+msgid "type matched to anyenum is not an enum type: %s"
+msgstr "anyenum에 일치된 형식이 열거 형식이 아님: %s"
+
+#: parser/parse_coerce.c:1831 parser/parse_coerce.c:1861
+#, c-format
+msgid "could not find range type for data type %s"
+msgstr "자료형 %s 에 대해서는 배열 자료형을 사용할 수 없습니다"
+
+#: parser/parse_collate.c:228 parser/parse_collate.c:475
+#: parser/parse_collate.c:986
+#, c-format
+msgid "collation mismatch between implicit collations \"%s\" and \"%s\""
+msgstr ""
+"암묵적으로 선택된 \"%s\" 정렬 규칙와 \"%s\" 정렬 규칙이 매칭되지 않습니다"
+
+#: parser/parse_collate.c:231 parser/parse_collate.c:478
+#: parser/parse_collate.c:989
+#, c-format
+msgid ""
+"You can choose the collation by applying the COLLATE clause to one or both "
+"expressions."
+msgstr "한 쪽 또는 서로 COLLATE 절을 이용해 정렬 규칙을 지정하세요"
+
+#: parser/parse_collate.c:834
+#, c-format
+msgid "collation mismatch between explicit collations \"%s\" and \"%s\""
+msgstr ""
+"명시적으로 지정한 \"%s\" 정렬규칙와 \"%s\" 정렬규칙이 매칭되지 않습니다"
+
+#: parser/parse_cte.c:42
+#, c-format
+msgid ""
+"recursive reference to query \"%s\" must not appear within its non-recursive "
+"term"
+msgstr "\"%s\" 쿼리에 대한 재귀 참조가 비재귀 구문 안에는 없어야 함"
+
+#: parser/parse_cte.c:44
+#, c-format
+msgid "recursive reference to query \"%s\" must not appear within a subquery"
+msgstr "\"%s\" 쿼리에 대한 재귀 참조가 하위 쿼리 내에 표시되지 않아야 함"
+
+#: parser/parse_cte.c:46
+#, c-format
+msgid ""
+"recursive reference to query \"%s\" must not appear within an outer join"
+msgstr "\"%s\" 쿼리에 대한 재귀 참조가 outer join 구문 안에 없어야 함"
+
+#: parser/parse_cte.c:48
+#, c-format
+msgid "recursive reference to query \"%s\" must not appear within INTERSECT"
+msgstr "\"%s\" 쿼리에 대한 재귀 참조가 INTERSECT 내에 표시되지 않아야 함"
+
+#: parser/parse_cte.c:50
+#, c-format
+msgid "recursive reference to query \"%s\" must not appear within EXCEPT"
+msgstr "\"%s\" 쿼리에 대한 재귀 참조가 EXCEPT 내에 표시되지 않아야 함"
+
+#: parser/parse_cte.c:132
+#, c-format
+msgid "WITH query name \"%s\" specified more than once"
+msgstr "\"%s\" WITH 쿼리 이름이 여러 번 지정됨"
+
+#: parser/parse_cte.c:264
+#, c-format
+msgid ""
+"WITH clause containing a data-modifying statement must be at the top level"
+msgstr "자료를 변경하는 구문이 있는 WITH 절은 최상위 수준에 있어야 합니다"
+
+#: parser/parse_cte.c:313
+#, c-format
+msgid ""
+"recursive query \"%s\" column %d has type %s in non-recursive term but type "
+"%s overall"
+msgstr ""
+"\"%s\" 재귀 쿼리의 %d 번째 칼럼은 비재귀 조건에 %s 자료형을 포함하는데 전체적"
+"으로는 %s 자료형임"
+
+#: parser/parse_cte.c:319
+#, c-format
+msgid "Cast the output of the non-recursive term to the correct type."
+msgstr "비재귀 조건의 출력을 올바른 형식으로 형변환하십시오."
+
+#: parser/parse_cte.c:324
+#, c-format
+msgid ""
+"recursive query \"%s\" column %d has collation \"%s\" in non-recursive term "
+"but collation \"%s\" overall"
+msgstr ""
+"\"%s\" 재귀 쿼리의 %d 번째 칼럼은 비재귀 조건에 %s 자료형을 포함하는데 전체적"
+"으로는 %s 자료형임"
+
+#: parser/parse_cte.c:328
+#, c-format
+msgid "Use the COLLATE clause to set the collation of the non-recursive term."
+msgstr ""
+
+#: parser/parse_cte.c:419
+#, c-format
+msgid "WITH query \"%s\" has %d columns available but %d columns specified"
+msgstr ""
+"\"%s\" WITH 쿼리에는 %d개의 칼럼을 사용할 수 있는데 %d개의 칼럼이 지정됨"
+
+#: parser/parse_cte.c:599
+#, c-format
+msgid "mutual recursion between WITH items is not implemented"
+msgstr "WITH 항목 간의 상호 재귀가 구현되지 않음"
+
+#: parser/parse_cte.c:651
+#, c-format
+msgid "recursive query \"%s\" must not contain data-modifying statements"
+msgstr "\"%s\" 재귀 쿼리에 자료 변경 구문이 포함될 수 없습니다."
+
+#: parser/parse_cte.c:659
+#, c-format
+msgid ""
+"recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] "
+"recursive-term"
+msgstr "\"%s\" 재귀 쿼리에 비재귀 조건 형태의 UNION [ALL] 재귀 조건이 없음"
+
+#: parser/parse_cte.c:703
+#, c-format
+msgid "ORDER BY in a recursive query is not implemented"
+msgstr "재귀 쿼리의 ORDER BY가 구현되지 않음"
+
+#: parser/parse_cte.c:709
+#, c-format
+msgid "OFFSET in a recursive query is not implemented"
+msgstr "재귀 쿼리의 OFFSET이 구현되지 않음"
+
+#: parser/parse_cte.c:715
+#, c-format
+msgid "LIMIT in a recursive query is not implemented"
+msgstr "재귀 쿼리의 LIMIT가 구현되지 않음"
+
+#: parser/parse_cte.c:721
+#, c-format
+msgid "FOR UPDATE/SHARE in a recursive query is not implemented"
+msgstr "재귀 쿼리의 FOR UPDATE/SHARE가 구현되지 않음"
+
+#: parser/parse_cte.c:778
+#, c-format
+msgid "recursive reference to query \"%s\" must not appear more than once"
+msgstr "\"%s\" 쿼리에 대한 재귀 참조가 여러 번 표시되지 않아야 함"
+
+#: parser/parse_expr.c:390 parser/parse_relation.c:3176
+#: parser/parse_relation.c:3196
+#, c-format
+msgid "column %s.%s does not exist"
+msgstr "%s.%s 칼럼 없음"
+
+#: parser/parse_expr.c:402
+#, c-format
+msgid "column \"%s\" not found in data type %s"
+msgstr "\"%s\" 열은 %s 자료형을 찾을 수 없음"
+
+#: parser/parse_expr.c:408
+#, c-format
+msgid "could not identify column \"%s\" in record data type"
+msgstr "레코드 데이터 형식에서 \"%s\" 열을 식별할 수 없음"
+
+#: parser/parse_expr.c:414
+#, c-format
+msgid "column notation .%s applied to type %s, which is not a composite type"
+msgstr ""
+".%s 표현이 %s 자료형 사용되었는데, 이는 복소수형 (complex type)이 아닙니다"
+
+#: parser/parse_expr.c:444 parser/parse_target.c:671
+#, c-format
+msgid "row expansion via \"*\" is not supported here"
+msgstr "\"*\"를 통한 칼럼 확장은 여기서 지원되지 않음"
+
+#: parser/parse_expr.c:770 parser/parse_relation.c:668
+#: parser/parse_relation.c:768 parser/parse_target.c:1120
+#, c-format
+msgid "column reference \"%s\" is ambiguous"
+msgstr "칼럼 참조 \"%s\" 가 모호합니다."
+
+#: parser/parse_expr.c:826 parser/parse_param.c:110 parser/parse_param.c:142
+#: parser/parse_param.c:199 parser/parse_param.c:298
+#, c-format
+msgid "there is no parameter $%d"
+msgstr "$%d 매개 변수가 없습니다"
+
+#: parser/parse_expr.c:1067
+#, c-format
+msgid "NULLIF requires = operator to yield boolean"
+msgstr "NULIF 절은 boolean 값을 얻기 위해서 = 연산자를 필요로 합니다"
+
+#: parser/parse_expr.c:1501 gram.y:9887
+#, c-format
+msgid "number of columns does not match number of values"
+msgstr "열의 개수와, values의 개수가 틀립니다"
+
+#: parser/parse_expr.c:1730
+msgid "cannot use subquery in check constraint"
+msgstr "체크 제약 조건에서는 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1734
+msgid "cannot use subquery in DEFAULT expression"
+msgstr "DEFAULT 식에서는 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1737
+msgid "cannot use subquery in index expression"
+msgstr "인덱스 식(expression)에 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1740
+msgid "cannot use subquery in index predicate"
+msgstr "인덱스 술어(predicate)에 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1743
+msgid "cannot use subquery in transform expression"
+msgstr "transform 식(expression)에 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1746
+msgid "cannot use subquery in EXECUTE parameter"
+msgstr "EXECUTE 매개 변수로 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1749
+msgid "cannot use subquery in trigger WHEN condition"
+msgstr "트리거 WHEN 조건절에서는 서브쿼리를 사용할 수 없습니다"
+
+#: parser/parse_expr.c:1803
+#, c-format
+msgid "subquery must return only one column"
+msgstr "subquery는 오로지 한개의 열만을 돌려 주어야 합니다."
+
+#: parser/parse_expr.c:1887
+#, c-format
+msgid "subquery has too many columns"
+msgstr "subquery 에가 너무 많은 열을 가집니다"
+
+#: parser/parse_expr.c:1892
+#, c-format
+msgid "subquery has too few columns"
+msgstr "subquery 에 명시된 열 수가 너무 적다"
+
+#: parser/parse_expr.c:1993
+#, c-format
+msgid "cannot determine type of empty array"
+msgstr "빈 배열의 자료형을 확인할 수 없음"
+
+#: parser/parse_expr.c:1994
+#, c-format
+msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]."
+msgstr "원하는 형식으로 명시적으로 형변환하십시오(예: ARRAY[]::integer[])."
+
+#: parser/parse_expr.c:2008
+#, c-format
+msgid "could not find element type for data type %s"
+msgstr "%s 자료형의 요소 자료형을 찾을 수 없음"
+
+#: parser/parse_expr.c:2231
+#, c-format
+msgid "unnamed XML attribute value must be a column reference"
+msgstr "이름이 지정되지 않은 XML 속성 값은 열 참조여야 함"
+
+#: parser/parse_expr.c:2232
+#, c-format
+msgid "unnamed XML element value must be a column reference"
+msgstr "이름이 지정되지 않은 XML 요소 값은 열 참조여야 함"
+
+#: parser/parse_expr.c:2247
+#, c-format
+msgid "XML attribute name \"%s\" appears more than once"
+msgstr "\"%s\" XML 속성 이름이 여러 번 표시됨"
+
+#: parser/parse_expr.c:2354
+#, c-format
+msgid "cannot cast XMLSERIALIZE result to %s"
+msgstr "XMLSERIALIZE 결과를 %s 형으로 바꿀 수 없음"
+
+#: parser/parse_expr.c:2650 parser/parse_expr.c:2846
+#, c-format
+msgid "unequal number of entries in row expressions"
+msgstr "행 표현식에서 항목 수가 일치하지 않습니다"
+
+#: parser/parse_expr.c:2660
+#, c-format
+msgid "cannot compare rows of zero length"
+msgstr "길이가 영(0)인 행들은 비교할 수 없습니다"
+
+#: parser/parse_expr.c:2685
+#, c-format
+msgid "row comparison operator must yield type boolean, not type %s"
+msgstr ""
+"행 비교 연산자는 boolean형을 리턴해야합니다. %s 자료형을 사용할 수 없습니다"
+
+#: parser/parse_expr.c:2692
+#, c-format
+msgid "row comparison operator must not return a set"
+msgstr "행 비교 연산자는 set을 리턴할 수 없습니다"
+
+#: parser/parse_expr.c:2751 parser/parse_expr.c:2792
+#, c-format
+msgid "could not determine interpretation of row comparison operator %s"
+msgstr "%s 행 비교 연산자의 구문을 분석할 수 없습니다"
+
+#: parser/parse_expr.c:2753
+#, c-format
+msgid ""
+"Row comparison operators must be associated with btree operator families."
+msgstr "로우 비교 연산자를 btree 연산자 패밀리와 연결해야 함"
+
+#: parser/parse_expr.c:2794
+#, c-format
+msgid "There are multiple equally-plausible candidates."
+msgstr "여러 가지 등식들이 성립할 수 있는 가능성이 있습니다"
+
+#: parser/parse_expr.c:2886
+#, c-format
+msgid "IS DISTINCT FROM requires = operator to yield boolean"
+msgstr ""
+"IS DISTINCT FROM 절에서 boolean 값을 얻기 위해서 = 연산자를 필요로 합니다"
+
+#: parser/parse_expr.c:3199 parser/parse_expr.c:3217
+#, c-format
+msgid "operator precedence change: %s is now lower precedence than %s"
+msgstr "연산자 우선순위 변경됨: %s 연산자 우선순위가 %s 연산보다 낮습니다"
+
+#: parser/parse_func.c:174
+#, c-format
+msgid "argument name \"%s\" used more than once"
+msgstr "\"%s\" 이름의 매개 변수가 여러 번 사용 됨"
+
+#: parser/parse_func.c:185
+#, c-format
+msgid "positional argument cannot follow named argument"
+msgstr ""
+
+#: parser/parse_func.c:270
+#, c-format
+msgid "%s(*) specified, but %s is not an aggregate function"
+msgstr "%s(*) 가 명시되어 있는데, 이 %s 함수는 집계 함수가 아닙니다."
+
+#: parser/parse_func.c:277
+#, c-format
+msgid "DISTINCT specified, but %s is not an aggregate function"
+msgstr "DISTINCT 가 명시되어 있는데, 그러나 이 %s 함수는 집계 함수가 아닙니다"
+
+#: parser/parse_func.c:283
+#, c-format
+msgid "WITHIN GROUP specified, but %s is not an aggregate function"
+msgstr "WITHIN GROUP 절이 명시되어 있는데, 이 %s 함수는 집계 함수가 아닙니다"
+
+#: parser/parse_func.c:289
+#, c-format
+msgid "ORDER BY specified, but %s is not an aggregate function"
+msgstr "ORDER BY 절이 명시되어 있는데, 이 %s 함수는 집계 함수가 아닙니다."
+
+#: parser/parse_func.c:295
+#, c-format
+msgid "FILTER specified, but %s is not an aggregate function"
+msgstr "FILTER 절이 명시되어 있는데, 이 %s 함수는 집계 함수가 아닙니다"
+
+#: parser/parse_func.c:301
+#, c-format
+msgid ""
+"OVER specified, but %s is not a window function nor an aggregate function"
+msgstr "OVER 절이 지정되었는데 %s 함수는 윈도우 함수 또는 집계 함수가 아님"
+
+#: parser/parse_func.c:331
+#, c-format
+msgid "WITHIN GROUP is required for ordered-set aggregate %s"
+msgstr "순서가 있는 집계함수인 %s 때문에 WITHIN GROUP 절이 필요합니다"
+
+#: parser/parse_func.c:337
+#, c-format
+msgid "OVER is not supported for ordered-set aggregate %s"
+msgstr "OVER 절에서 정렬된 세트 집계 %s 함수를 지원하지 않음"
+
+#: parser/parse_func.c:368 parser/parse_func.c:397
+#, c-format
+msgid ""
+"There is an ordered-set aggregate %s, but it requires %d direct arguments, "
+"not %d."
+msgstr ""
+
+#: parser/parse_func.c:422
+#, c-format
+msgid ""
+"To use the hypothetical-set aggregate %s, the number of hypothetical direct "
+"arguments (here %d) must match the number of ordering columns (here %d)."
+msgstr ""
+
+#: parser/parse_func.c:436
+#, c-format
+msgid ""
+"There is an ordered-set aggregate %s, but it requires at least %d direct "
+"arguments."
+msgstr ""
+
+#: parser/parse_func.c:455
+#, c-format
+msgid "%s is not an ordered-set aggregate, so it cannot have WITHIN GROUP"
+msgstr ""
+"%s 함수는 순사가 있는 세트 집계함수가 아니여서 WITHIN GROUP 절을 사용할 수 없"
+"습니다"
+
+#: parser/parse_func.c:468
+#, c-format
+msgid "window function %s requires an OVER clause"
+msgstr "%s 윈도우 함수 호출에는 OVER 절이 필요함"
+
+#: parser/parse_func.c:475
+#, c-format
+msgid "window function %s cannot have WITHIN GROUP"
+msgstr "%s 윈도우 함수는 WITHIN GROUP 절을 사용할 수 없음"
+
+#: parser/parse_func.c:496
+#, c-format
+msgid "function %s is not unique"
+msgstr "함수 %s 는 유일성을 가지지 못합니다(not unique)"
+
+#: parser/parse_func.c:499
+#, c-format
+msgid ""
+"Could not choose a best candidate function. You might need to add explicit "
+"type casts."
+msgstr ""
+"제일 적당한 함수를 선택할 수 없습니다. 명시적 형변환자를 추가해야 할 수도 있"
+"습니다."
+
+#: parser/parse_func.c:510
+#, c-format
+msgid ""
+"No aggregate function matches the given name and argument types. Perhaps you "
+"misplaced ORDER BY; ORDER BY must appear after all regular arguments of the "
+"aggregate."
+msgstr ""
+"지정된 이름 및 인자 자료형과 일치하는 집계 함수가 없습니다. ORDER BY 절을 바"
+"른 위치에 쓰지 않은 것 같습니다. ORDER BY 절은 모든 집계용 인자들 맨 뒤에 있"
+"어야 합니다."
+
+#: parser/parse_func.c:521
+#, c-format
+msgid ""
+"No function matches the given name and argument types. You might need to add "
+"explicit type casts."
+msgstr ""
+"지정된 이름 및 인자 자료형과 일치하는 함수가 없습니다. 명시적 형변환자를 추가"
+"해야 할 수도 있습니다."
+
+#: parser/parse_func.c:623
+#, c-format
+msgid "VARIADIC argument must be an array"
+msgstr "VARIADIC 매개 변수는 배열이어야 함"
+
+#: parser/parse_func.c:671 parser/parse_func.c:735
+#, c-format
+msgid "%s(*) must be used to call a parameterless aggregate function"
+msgstr "%s(*) 사용할 때는 이 함수가 매개 변수 없는 집계 함수여야 합니다"
+
+#: parser/parse_func.c:678
+#, c-format
+msgid "aggregates cannot return sets"
+msgstr "집계 함수는 세트를 반환할 수 없음"
+
+#: parser/parse_func.c:693
+#, c-format
+msgid "aggregates cannot use named arguments"
+msgstr "집계 함수는 인자 이름을 사용할 수 없음"
+
+#: parser/parse_func.c:725
+#, c-format
+msgid "DISTINCT is not implemented for window functions"
+msgstr "윈도우 함수에 대해 DISTINCT가 구현되지 않음"
+
+#: parser/parse_func.c:745
+#, c-format
+msgid "aggregate ORDER BY is not implemented for window functions"
+msgstr "윈도우 함수에 대해 집계용 ORDER BY가 구현되지 않음"
+
+#: parser/parse_func.c:754
+#, c-format
+msgid "FILTER is not implemented for non-aggregate window functions"
+msgstr "비집계 윈도우 함수에 대해 FILTER가 구현되지 않음"
+
+#: parser/parse_func.c:760
+#, c-format
+msgid "window functions cannot return sets"
+msgstr "윈도우 함수는 세트를 반환할 수 없음"
+
+#: parser/parse_func.c:2010
+#, c-format
+msgid "aggregate %s(*) does not exist"
+msgstr "%s(*) 집계 함수 없음"
+
+#: parser/parse_func.c:2015
+#, c-format
+msgid "aggregate %s does not exist"
+msgstr "%s 집계 함수 없음"
+
+#: parser/parse_func.c:2034
+#, c-format
+msgid "function %s is not an aggregate"
+msgstr "%s 함수는 집계 함수가 아닙니다"
+
+#: parser/parse_node.c:84
+#, c-format
+msgid "target lists can have at most %d entries"
+msgstr "대상 목록은 최대 %d 개의 항목을 지정할 수 있습니다"
+
+#: parser/parse_node.c:253
+#, c-format
+msgid "cannot subscript type %s because it is not an array"
+msgstr ""
+"자료형 %s 는 배열이 아니기 때문에 배열 하위 스크립트를 기술할 수 없습니다."
+
+#: parser/parse_node.c:356 parser/parse_node.c:393
+#, c-format
+msgid "array subscript must have type integer"
+msgstr "배열 하위 스크립트는 반드시 정수형이어야 합니다."
+
+#: parser/parse_node.c:424
+#, c-format
+msgid "array assignment requires type %s but expression is of type %s"
+msgstr "배열할당은 자료형 %s 가 필요하지만, 현재 표현식이 %s 자료형입니다"
+
+#: parser/parse_oper.c:125 parser/parse_oper.c:722 utils/adt/regproc.c:583
+#: utils/adt/regproc.c:603 utils/adt/regproc.c:787
+#, c-format
+msgid "operator does not exist: %s"
+msgstr "연산자 없음: %s"
+
+#: parser/parse_oper.c:222
+#, c-format
+msgid "Use an explicit ordering operator or modify the query."
+msgstr ""
+"명시적으로 순차연산자(ordering operator) 를 사용하던지, 또는 query 를 수정하"
+"도록 하세요."
+
+#: parser/parse_oper.c:226 utils/adt/array_userfuncs.c:794
+#: utils/adt/array_userfuncs.c:933 utils/adt/arrayfuncs.c:3639
+#: utils/adt/arrayfuncs.c:4077 utils/adt/arrayfuncs.c:6039
+#: utils/adt/rowtypes.c:1167
+#, c-format
+msgid "could not identify an equality operator for type %s"
+msgstr ""
+"%s 자료형에서 사용할 동등 연산자(equality operator)를 찾을 수 없습니다."
+
+#: parser/parse_oper.c:478
+#, c-format
+msgid "operator requires run-time type coercion: %s"
+msgstr "이 연산자는 실행시에 형 강제전화이 필요합니다: %s"
+
+#: parser/parse_oper.c:714
+#, c-format
+msgid "operator is not unique: %s"
+msgstr "연산자가 고유하지 않습니다: %s"
+
+#: parser/parse_oper.c:716
+#, c-format
+msgid ""
+"Could not choose a best candidate operator. You might need to add explicit "
+"type casts."
+msgstr ""
+"가장 적당한 연산자를 선택할 수 없습니다. 명시적 형변환자를 추가해야 할 수도 "
+"있습니다."
+
+#: parser/parse_oper.c:724
+#, c-format
+msgid ""
+"No operator matches the given name and argument type(s). You might need to "
+"add explicit type casts."
+msgstr ""
+"지정된 이름 및 인자 형식과 일치하는 연산자가 없습니다. 명시적 형변환자를 추가"
+"해야 할 수도 있습니다."
+
+#: parser/parse_oper.c:783 parser/parse_oper.c:897
+#, c-format
+msgid "operator is only a shell: %s"
+msgstr "연산자는 셸일 뿐임: %s"
+
+#: parser/parse_oper.c:885
+#, c-format
+msgid "op ANY/ALL (array) requires array on right side"
+msgstr "op ANY/ALL (array) 는 우측에 배열이 있어야 합니다."
+
+#: parser/parse_oper.c:927
+#, c-format
+msgid "op ANY/ALL (array) requires operator to yield boolean"
+msgstr "op ANY/ALL (array) 는 boolean 을 얻기 위한 연산자가 필요합니다."
+
+#: parser/parse_oper.c:932
+#, c-format
+msgid "op ANY/ALL (array) requires operator not to return a set"
+msgstr "op ANY/ALL (array) 는 set 을 return 하지 않는 연산자가 요구 됩니다."
+
+#: parser/parse_param.c:216
+#, c-format
+msgid "inconsistent types deduced for parameter $%d"
+msgstr "inconsistent types deduced for parameter $%d"
+
+#: parser/parse_relation.c:175
+#, c-format
+msgid "table reference \"%s\" is ambiguous"
+msgstr "테이블 참조 \"%s\" 가 명확하지 않습니다 (ambiguous)."
+
+#: parser/parse_relation.c:219
+#, c-format
+msgid "table reference %u is ambiguous"
+msgstr "테이블 참조 %u 가 명확하지 않습니다 (ambiguous)."
+
+#: parser/parse_relation.c:398
+#, c-format
+msgid "table name \"%s\" specified more than once"
+msgstr "테이블 이름 \"%s\" 가 한번 이상 명시되어 있습니다."
+
+#: parser/parse_relation.c:425 parser/parse_relation.c:3116
+#, c-format
+msgid "invalid reference to FROM-clause entry for table \"%s\""
+msgstr "\"%s\" 테이블을 사용하는 FROM 절에 대한 참조가 잘못 되었습니다."
+
+#: parser/parse_relation.c:428 parser/parse_relation.c:3121
+#, c-format
+msgid ""
+"There is an entry for table \"%s\", but it cannot be referenced from this "
+"part of the query."
+msgstr ""
+"\"%s\" 테이블에 대한 항목이 있지만 이 쿼리 부분에서 참조할 수 없습니다."
+
+#: parser/parse_relation.c:430
+#, c-format
+msgid "The combining JOIN type must be INNER or LEFT for a LATERAL reference."
+msgstr ""
+
+#: parser/parse_relation.c:706
+#, c-format
+msgid "system column \"%s\" reference in check constraint is invalid"
+msgstr "제약 조건에서 참조하는 \"%s\" 시스템 칼럼이 없음"
+
+#: parser/parse_relation.c:1066 parser/parse_relation.c:1346
+#: parser/parse_relation.c:1848
+#, c-format
+msgid "table \"%s\" has %d columns available but %d columns specified"
+msgstr "테이블 \"%s\" 에는 %d 개의 열이 있는데, %d 개의 열만이 명시되었습니다."
+
+#: parser/parse_relation.c:1153
+#, c-format
+msgid ""
+"There is a WITH item named \"%s\", but it cannot be referenced from this "
+"part of the query."
+msgstr "\"%s\"(이)라는 WITH 항목이 있지만 이 쿼리 부분에서 참조할 수 없습니다."
+
+#: parser/parse_relation.c:1155
+#, c-format
+msgid ""
+"Use WITH RECURSIVE, or re-order the WITH items to remove forward references."
+msgstr ""
+"WITH RECURSIVE를 사용하거나 WITH 항목의 순서를 변경하여 정방향 참조를 제거하"
+"십시오."
+
+#: parser/parse_relation.c:1466
+#, c-format
+msgid ""
+"a column definition list is only allowed for functions returning \"record\""
+msgstr ""
+"열 정의 리스트 (column definition list) 는 오로지 \"record\" 를 리턴하는 함"
+"수 내에서만 허용됩니다."
+
+#: parser/parse_relation.c:1475
+#, c-format
+msgid "a column definition list is required for functions returning \"record\""
+msgstr ""
+"열 정의 리스트(column definition list)는 \"record\" 를 리턴하는 함수를 필요"
+"로 합니다"
+
+#: parser/parse_relation.c:1554
+#, c-format
+msgid "function \"%s\" in FROM has unsupported return type %s"
+msgstr ""
+"FROM 절 내의 함수 \"%s\" 에 지원되지 않는 return 자료형 %s 이 있습니다."
+
+#: parser/parse_relation.c:1676
+#, c-format
+msgid "VALUES lists \"%s\" have %d columns available but %d columns specified"
+msgstr ""
+"VALUES 뒤에 오는 \"%s\" 구문에는 %d개의 열이 있는데, 지정한 열은 %d개 입니다"
+
+#: parser/parse_relation.c:1731
+#, c-format
+msgid "joins can have at most %d columns"
+msgstr "조인에는 최대 %d개의 칼럼을 포함할 수 있음"
+
+#: parser/parse_relation.c:1821
+#, c-format
+msgid "WITH query \"%s\" does not have a RETURNING clause"
+msgstr ""
+
+#: parser/parse_relation.c:2738 parser/parse_relation.c:2900
+#, c-format
+msgid "column %d of relation \"%s\" does not exist"
+msgstr "%d번째 열이 없습니다. 해당 릴레이션: \"%s\""
+
+#: parser/parse_relation.c:3119
+#, c-format
+msgid "Perhaps you meant to reference the table alias \"%s\"."
+msgstr "아 \"%s\" alias를 참조해야 할 것 같습니다."
+
+#: parser/parse_relation.c:3127
+#, c-format
+msgid "missing FROM-clause entry for table \"%s\""
+msgstr "테이블 \"%s\"에 FROM 절이 빠져 있습니다."
+
+#: parser/parse_relation.c:3179
+#, c-format
+msgid "Perhaps you meant to reference the column \"%s.%s\"."
+msgstr "아마 \"%s.%s\" 칼럼을 참조하는 것 같습니다."
+
+#: parser/parse_relation.c:3181
+#, c-format
+msgid ""
+"There is a column named \"%s\" in table \"%s\", but it cannot be referenced "
+"from this part of the query."
+msgstr ""
+"\"%s\" 이름의 칼럼이 \"%s\" 테이블에 있지만, 이 쿼리의 이 부분에서는 참조될 "
+"수 없습니다."
+
+#: parser/parse_relation.c:3198
+#, c-format
+msgid ""
+"Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"."
+msgstr "아마 \"%s.%s\" 칼럼이나 \"%s.%s\" 칼럼을 참조하는 것 같습니다."
+
+#: parser/parse_target.c:432 parser/parse_target.c:724
+#, c-format
+msgid "cannot assign to system column \"%s\""
+msgstr "시스템 열 \"%s\"에 할당할 수 없습니다."
+
+#: parser/parse_target.c:460
+#, c-format
+msgid "cannot set an array element to DEFAULT"
+msgstr "배열 요소를 DEFAULT 로 설정할 수 없습니다."
+
+#: parser/parse_target.c:465
+#, c-format
+msgid "cannot set a subfield to DEFAULT"
+msgstr "하위필드를 DEFAULT로 설정할 수 없습니다."
+
+#: parser/parse_target.c:534
+#, c-format
+msgid "column \"%s\" is of type %s but expression is of type %s"
+msgstr "열 \"%s\"은(는) %s 자료형인데 표현식은 %s 자료형입니다."
+
+#: parser/parse_target.c:708
+#, c-format
+msgid ""
+"cannot assign to field \"%s\" of column \"%s\" because its type %s is not a "
+"composite type"
+msgstr ""
+"\"%s\" 필드 (대상 열 \"%s\")를 지정할 수 없음, %s 자료형은 복합자료형이 아니"
+"기 때문"
+
+#: parser/parse_target.c:717
+#, c-format
+msgid ""
+"cannot assign to field \"%s\" of column \"%s\" because there is no such "
+"column in data type %s"
+msgstr ""
+"\"%s\" 필드 (대상 열 \"%s\")를 지정할 수 없음, %s 자료형에서 그런 열을 찾을 "
+"수 없음"
+
+#: parser/parse_target.c:784
+#, c-format
+msgid ""
+"array assignment to \"%s\" requires type %s but expression is of type %s"
+msgstr ""
+"\"%s\" 열에 사용된 자료형은 %s 가 필요하지만, 현재 표현식이 %s 자료형입니다"
+
+#: parser/parse_target.c:794
+#, c-format
+msgid "subfield \"%s\" is of type %s but expression is of type %s"
+msgstr "하위필드 \"%s\" 는 %s 자료형인데 표현식은 %s 자료형입니다."
+
+#: parser/parse_target.c:1210
+#, c-format
+msgid "SELECT * with no tables specified is not valid"
+msgstr "테이블이 명시되지 않은 SELECT * 구문은 유효하지 않습니다."
+
+#: parser/parse_type.c:83
+#, c-format
+msgid "improper %%TYPE reference (too few dotted names): %s"
+msgstr ""
+"적절하지 않은 %%TYPE reference 입니다 (dotted name 이 너무 적습니다): %s"
+
+#: parser/parse_type.c:105
+#, c-format
+msgid "improper %%TYPE reference (too many dotted names): %s"
+msgstr ""
+"적절하지 않은 %%TYPE reference 입니다 (dotted name 이 너무 많습니다): %s"
+
+#: parser/parse_type.c:140
+#, c-format
+msgid "type reference %s converted to %s"
+msgstr "ype reference %s 가 %s 로 변환되었습니다."
+
+#: parser/parse_type.c:261 parser/parse_type.c:805 utils/cache/typcache.c:239
+#, c-format
+msgid "type \"%s\" is only a shell"
+msgstr "자료형 \"%s\" 는 오로지 shell 에만 있습니다. "
+
+#: parser/parse_type.c:346
+#, c-format
+msgid "type modifier is not allowed for type \"%s\""
+msgstr "\"%s\" 형식에는 형식 한정자를 사용할 수 없음"
+
+#: parser/parse_type.c:388
+#, c-format
+msgid "type modifiers must be simple constants or identifiers"
+msgstr "자료형 한정자는 단순 상수 또는 식별자여야 함"
+
+#: parser/parse_type.c:671 parser/parse_type.c:770
+#, c-format
+msgid "invalid type name \"%s\""
+msgstr "\"%s\" 자료형 이름은 유효하지 않은 자료형입니다."
+
+#: parser/parse_utilcmd.c:384
+#, c-format
+msgid "array of serial is not implemented"
+msgstr "serial 배열이 구현되지 않음"
+
+#: parser/parse_utilcmd.c:432
+#, c-format
+msgid "%s will create implicit sequence \"%s\" for serial column \"%s.%s\""
+msgstr ""
+"%s 명령으로 \"%s\" 시퀀스가 자동으로 만들어짐 (\"%s.%s\" serial 열 때문)"
+
+#: parser/parse_utilcmd.c:526 parser/parse_utilcmd.c:538
+#, c-format
+msgid ""
+"conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\""
+msgstr "NULL/NOT NULL 선언이 서로 충돌합니다 : column \"%s\" of table \"%s\""
+
+#: parser/parse_utilcmd.c:550
+#, c-format
+msgid "multiple default values specified for column \"%s\" of table \"%s\""
+msgstr "\"%s\" 열(\"%s\" 테이블)에 대해 여러 개의 기본 값이 지정됨"
+
+#: parser/parse_utilcmd.c:567 parser/parse_utilcmd.c:658
+#, c-format
+msgid "primary key constraints are not supported on foreign tables"
+msgstr "기본키 제약 조건을 외부 테이블에서는 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:576 parser/parse_utilcmd.c:668
+#, c-format
+msgid "unique constraints are not supported on foreign tables"
+msgstr "유니크 제약 조건은 외부 테이블에서는 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:593 parser/parse_utilcmd.c:692
+#, c-format
+msgid "foreign key constraints are not supported on foreign tables"
+msgstr "참조키 제약 조건은 외부 테이블에서는 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:678
+#, c-format
+msgid "exclusion constraints are not supported on foreign tables"
+msgstr "제외 제약 조건은 외부 테이블에서는 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:742
+#, c-format
+msgid "LIKE is not supported for creating foreign tables"
+msgstr "외부 테이블을 만들 때는 LIKE 옵션을 쓸 수 없음"
+
+#: parser/parse_utilcmd.c:1275 parser/parse_utilcmd.c:1351
+#, c-format
+msgid "Index \"%s\" contains a whole-row table reference."
+msgstr ""
+
+#: parser/parse_utilcmd.c:1621
+#, c-format
+msgid "cannot use an existing index in CREATE TABLE"
+msgstr ""
+
+#: parser/parse_utilcmd.c:1641
+#, c-format
+msgid "index \"%s\" is already associated with a constraint"
+msgstr ""
+
+#: parser/parse_utilcmd.c:1649
+#, c-format
+msgid "index \"%s\" does not belong to table \"%s\""
+msgstr "\"%s\" 인덱스가 \"%s\" 테이블용이 아님"
+
+#: parser/parse_utilcmd.c:1656
+#, c-format
+msgid "index \"%s\" is not valid"
+msgstr "\"%s\" 인덱스는 사용가능 상태가 아님"
+
+#: parser/parse_utilcmd.c:1662
+#, c-format
+msgid "\"%s\" is not a unique index"
+msgstr "\"%s\" 객체는 유니크 인덱스가 아닙니다"
+
+#: parser/parse_utilcmd.c:1663 parser/parse_utilcmd.c:1670
+#: parser/parse_utilcmd.c:1677 parser/parse_utilcmd.c:1747
+#, c-format
+msgid "Cannot create a primary key or unique constraint using such an index."
+msgstr ""
+
+#: parser/parse_utilcmd.c:1669
+#, c-format
+msgid "index \"%s\" contains expressions"
+msgstr "\"%s\" 인덱스에 표현식이 포함되어 있음"
+
+#: parser/parse_utilcmd.c:1676
+#, c-format
+msgid "\"%s\" is a partial index"
+msgstr "\"%s\" 객체는 부분 인덱스임"
+
+#: parser/parse_utilcmd.c:1688
+#, c-format
+msgid "\"%s\" is a deferrable index"
+msgstr "\"%s\" 객체는 지연가능한 인덱스임"
+
+#: parser/parse_utilcmd.c:1689
+#, c-format
+msgid "Cannot create a non-deferrable constraint using a deferrable index."
+msgstr ""
+
+#: parser/parse_utilcmd.c:1746
+#, c-format
+msgid "index \"%s\" does not have default sorting behavior"
+msgstr "\"%s\" 인덱스는 기본 정렬 방법이 없음"
+
+#: parser/parse_utilcmd.c:1893
+#, c-format
+msgid "column \"%s\" appears twice in primary key constraint"
+msgstr "기본키 제약 조건에서 \"%s\" 열이 두 번 지정되었습니다"
+
+#: parser/parse_utilcmd.c:1899
+#, c-format
+msgid "column \"%s\" appears twice in unique constraint"
+msgstr "고유 제약 조건에서 \"%s\" 열이 두 번 지정되었습니다"
+
+#: parser/parse_utilcmd.c:2103
+#, c-format
+msgid "index expression cannot return a set"
+msgstr "인덱스 식은 세트를 반환할 수 없음"
+
+#: parser/parse_utilcmd.c:2114
+#, c-format
+msgid ""
+"index expressions and predicates can refer only to the table being indexed"
+msgstr "인덱스 식 및 술어는 인덱싱되는 테이블만 참조할 수 있음"
+
+#: parser/parse_utilcmd.c:2160
+#, c-format
+msgid "rules on materialized views are not supported"
+msgstr "구체화된 뷰에서의 룰은 지원하지 않음"
+
+#: parser/parse_utilcmd.c:2221
+#, c-format
+msgid "rule WHERE condition cannot contain references to other relations"
+msgstr "룰에서 지정한 WHERE 조건에 다른 릴레이션에 대한 참조를 포함할 수 없음"
+
+#: parser/parse_utilcmd.c:2293
+#, c-format
+msgid ""
+"rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE "
+"actions"
+msgstr ""
+"룰에서 지정한 WHERE 조건이 있는 규칙에는 SELECT, INSERT, UPDATE 또는 DELETE "
+"작업만 포함할 수 있음"
+
+#: parser/parse_utilcmd.c:2311 parser/parse_utilcmd.c:2410
+#: rewrite/rewriteHandler.c:485 rewrite/rewriteManip.c:1015
+#, c-format
+msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented"
+msgstr "conditional UNION/INTERSECT/EXCEPT 구문은 구현되어 있지 않다"
+
+#: parser/parse_utilcmd.c:2329
+#, c-format
+msgid "ON SELECT rule cannot use OLD"
+msgstr "ON SELECT 룰은 OLD를 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:2333
+#, c-format
+msgid "ON SELECT rule cannot use NEW"
+msgstr "ON SELECT 룰은 NEW를 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:2342
+#, c-format
+msgid "ON INSERT rule cannot use OLD"
+msgstr "ON INSERT 룰은 OLD를 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:2348
+#, c-format
+msgid "ON DELETE rule cannot use NEW"
+msgstr "ON DELETE 룰은 NEW를 사용할 수 없음"
+
+#: parser/parse_utilcmd.c:2376
+#, c-format
+msgid "cannot refer to OLD within WITH query"
+msgstr ""
+
+#: parser/parse_utilcmd.c:2383
+#, c-format
+msgid "cannot refer to NEW within WITH query"
+msgstr ""
+
+#: parser/parse_utilcmd.c:2586
+#, c-format
+msgid "transform expression must not return a set"
+msgstr "transform 표현식은 하나의 세트를 리턴하면 안됩니다"
+
+#: parser/parse_utilcmd.c:2700
+#, c-format
+msgid "misplaced DEFERRABLE clause"
+msgstr "DEFERABLE 절이 잘못 놓여져 있습니다"
+
+#: parser/parse_utilcmd.c:2705 parser/parse_utilcmd.c:2720
+#, c-format
+msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"
+msgstr "여러 개의 DEFERRABLE/NOT DEFERRABLE절은 사용할 수 없습니다"
+
+#: parser/parse_utilcmd.c:2715
+#, c-format
+msgid "misplaced NOT DEFERRABLE clause"
+msgstr "NOT DEFERABLE 절이 잘못 놓여 있습니다"
+
+#: parser/parse_utilcmd.c:2728 parser/parse_utilcmd.c:2754 gram.y:4902
+#, c-format
+msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE"
+msgstr "INITIALLY DEFERRED 로 선언된 조건문은 반드시 DEFERABLE 여야만 한다"
+
+#: parser/parse_utilcmd.c:2736
+#, c-format
+msgid "misplaced INITIALLY DEFERRED clause"
+msgstr "INITIALLY DEFERRED 절이 잘못 놓여 있습니다"
+
+#: parser/parse_utilcmd.c:2741 parser/parse_utilcmd.c:2767
+#, c-format
+msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"
+msgstr "여러 개의 INITIALLY IMMEDIATE/DEFERRED 절은 허용되지 않습니다"
+
+#: parser/parse_utilcmd.c:2762
+#, c-format
+msgid "misplaced INITIALLY IMMEDIATE clause"
+msgstr "INITIALLY IMMEDIATE 절이 잘못 놓여 있습니다"
+
+#: parser/parse_utilcmd.c:2953
+#, c-format
+msgid ""
+"CREATE specifies a schema (%s) different from the one being created (%s)"
+msgstr "CREATE 구문에 명시된 schema (%s) 가 생성된 (%s) 의 것과 다릅니다"
+
+#: parser/scansup.c:204
+#, c-format
+msgid "identifier \"%s\" will be truncated to \"%s\""
+msgstr "\"%s\" 식별자는 \"%s\"(으)로 잘림"
+
+#: port/pg_sema.c:113 port/sysv_sema.c:113
+#, c-format
+msgid "could not create semaphores: %m"
+msgstr "세마포어를 만들 수 없음: %m"
+
+#: port/pg_sema.c:114 port/sysv_sema.c:114
+#, c-format
+msgid "Failed system call was semget(%lu, %d, 0%o)."
+msgstr "semget(%lu, %d, 0%o) 호출에 의한 시스템 콜 실패"
+
+#: port/pg_sema.c:118 port/sysv_sema.c:118
+#, c-format
+msgid ""
+"This error does *not* mean that you have run out of disk space. It occurs "
+"when either the system limit for the maximum number of semaphore sets "
+"(SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be "
+"exceeded. You need to raise the respective kernel parameter. "
+"Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its "
+"max_connections parameter.\n"
+"The PostgreSQL documentation contains more information about configuring "
+"your system for PostgreSQL."
+msgstr ""
+"이 오류는 서버를 실행하는데 필요한 디스크 공간이 부족해서 발생한 것이 아닙니"
+"다.\n"
+"이 오류는 시스템에서 지정한 최소 세마포어 수(SEMMNI)가 너무 크거나, 최대 세마"
+"포어 수(SEMMNS)가 너무 적어서 서버를 실행할 수 없을 때 발생합니다. 이에 따"
+"라, 정상적으로 서버가 실행되려면, 시스템 값들을 조정할 필요가 있습니다. 아니"
+"면, 다른 방법으로, PostgreSQL의 환경 설정에서 max_connections 값을 줄여서 세"
+"마포어 사용 수를 줄여보십시오.\n"
+"보다 자세한 내용은 PostgreSQL 관리자 메뉴얼을 참조 하십시오."
+
+#: port/pg_sema.c:148 port/sysv_sema.c:148
+#, c-format
+msgid ""
+"You possibly need to raise your kernel's SEMVMX value to be at least %d. "
+"Look into the PostgreSQL documentation for details."
+msgstr ""
+"커널의 SEMVMX 값을 적어도 %d 정도로 늘려야할 필요가 있는 것 같습니다. 자세"
+"한 것은 PostgreSQL 문서를 참조하세요."
+
+#: port/pg_shmem.c:175 port/sysv_shmem.c:175
+#, c-format
+msgid "could not create shared memory segment: %m"
+msgstr "공유 메모리 세그먼트를 만들 수 없음: %m"
+
+#: port/pg_shmem.c:176 port/sysv_shmem.c:176
+#, c-format
+msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)."
+msgstr "shmget(키=%lu, 크기=%zu, 0%o) 시스템 콜 실패"
+
+#: port/pg_shmem.c:180 port/sysv_shmem.c:180
+#, c-format
+msgid ""
+"This error usually means that PostgreSQL's request for a shared memory "
+"segment exceeded your kernel's SHMMAX parameter, or possibly that it is less "
+"than your kernel's SHMMIN parameter.\n"
+"The PostgreSQL documentation contains more information about shared memory "
+"configuration."
+msgstr ""
+"이 오류를 일반적으로 PostgreSQL에서 사용할 공유 메모리 크기가 커널의 SHMMAX "
+"값보다 크거나, SHMMIN 값보다 적은 경우 발생합니다.\n"
+"공유 메모리 설정에 대한 보다 자세한 내용은 PostgreSQL 문서를 참조하십시오."
+
+#: port/pg_shmem.c:187 port/sysv_shmem.c:187
+#, c-format
+msgid ""
+"This error usually means that PostgreSQL's request for a shared memory "
+"segment exceeded your kernel's SHMALL parameter. You might need to "
+"reconfigure the kernel with larger SHMALL.\n"
+"The PostgreSQL documentation contains more information about shared memory "
+"configuration."
+msgstr ""
+"이 오류를 일반적으로 PostgreSQL에서 사용할 공유 크기가 커널의 SHMALL 값보다 "
+"큰 경우 발생합니다. 커널 환경 변수인 SHMALL 값을 좀 더 크게 설정하세요.\n"
+"공유 메모리 설정에 대한 보다 자세한 내용은 PostgreSQL 문서를 참조하십시오."
+
+#: port/pg_shmem.c:193 port/sysv_shmem.c:193
+#, c-format
+msgid ""
+"This error does *not* mean that you have run out of disk space. It occurs "
+"either if all available shared memory IDs have been taken, in which case you "
+"need to raise the SHMMNI parameter in your kernel, or because the system's "
+"overall limit for shared memory has been reached.\n"
+"The PostgreSQL documentation contains more information about shared memory "
+"configuration."
+msgstr ""
+"이 오류는 서버를 실행하는데 필요한 디스크 공간이 부족해서 발생한 것이 아닙니"
+"다. 이 오류는 서버가 사용할 공유 메모리 ID를 선점하지 못했을 때 발생합니"
+"다. 커널 환경 설정값인 SHMMNI 값을 늘리거나, 시스템의 가용 공유 메모리량을 "
+"확보하세요.\n"
+"공유 메모리 설정에 대한 보다 자세한 내용은 PostgreSQL 문서를 참조하십시오."
+
+#: port/pg_shmem.c:483 port/sysv_shmem.c:483
+#, c-format
+msgid "could not map anonymous shared memory: %m"
+msgstr "가용 공유 메모리 확보 실패: %m"
+
+#: port/pg_shmem.c:485 port/sysv_shmem.c:485
+#, c-format
+msgid ""
+"This error usually means that PostgreSQL's request for a shared memory "
+"segment exceeded available memory, swap space, or huge pages. To reduce the "
+"request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, "
+"perhaps by reducing shared_buffers or max_connections."
+msgstr ""
+"이 오류는 일반적으로 PostgreSQL에서 사용할 공유 메모리를 확보하지 못 했을 때 "
+"발생합니다(물리 메모리, 스왑, huge page). 현재 요구 크기(%zu 바이트)를 좀 줄"
+"여 보십시오. 줄이는 방법은, shared_buffers 값을 줄이거나 max_connections 값"
+"을 줄여 보십시오."
+
+#: port/pg_shmem.c:551 port/sysv_shmem.c:551 port/win32_shmem.c:134
+#, c-format
+msgid "huge pages not supported on this platform"
+msgstr "huge page 기능은 이 플랫폼에서 지원되지 않음"
+
+#: port/pg_shmem.c:646 port/sysv_shmem.c:646
+#, c-format
+msgid "could not stat data directory \"%s\": %m"
+msgstr "\"%s\" 데이터 디렉터리 상태를 파악할 수 없음: %m"
+
+#: port/win32/crashdump.c:122
+#, c-format
+msgid "could not load dbghelp.dll, cannot write crash dump\n"
+msgstr ""
+
+#: port/win32/crashdump.c:130
+#, c-format
+msgid ""
+"could not load required functions in dbghelp.dll, cannot write crash dump\n"
+msgstr ""
+
+#: port/win32/crashdump.c:161
+#, c-format
+msgid "could not open crash dump file \"%s\" for writing: error code %lu\n"
+msgstr "\"%s\" 장애 덤프 파일을 쓰기 위해 열 수 없음: 오류 번호 %lu\n"
+
+#: port/win32/crashdump.c:168
+#, c-format
+msgid "wrote crash dump to file \"%s\"\n"
+msgstr "\"%s\" 장애 덤프 파일을 만들었습니다.\n"
+
+#: port/win32/crashdump.c:170
+#, c-format
+msgid "could not write crash dump to file \"%s\": error code %lu\n"
+msgstr "\"%s\" 장애 덤프 파일을 쓰기 실패: 오류 번호 %lu\n"
+
+#: port/win32/signal.c:194
+#, c-format
+msgid "could not create signal listener pipe for PID %d: error code %lu"
+msgstr "%d pid를 위한 시그널 리슨너 파이프를 만들 수 없음: 오류 번호 %lu"
+
+#: port/win32/signal.c:274 port/win32/signal.c:306
+#, c-format
+msgid "could not create signal listener pipe: error code %lu; retrying\n"
+msgstr "신호 수신기 파이프를 만들 수 없음: 오류 번호 %lu, 다시 시작 중\n"
+
+#: port/win32/signal.c:317
+#, c-format
+msgid "could not create signal dispatch thread: error code %lu\n"
+msgstr "시그널 디스패치 쓰레드를 만들 수 없음: 오류 번호 %lu\n"
+
+#: port/win32_sema.c:94
+#, c-format
+msgid "could not create semaphore: error code %lu"
+msgstr "세마포어를 만들 수 없음: 오류 번호 %lu"
+
+#: port/win32_sema.c:167
+#, c-format
+msgid "could not lock semaphore: error code %lu"
+msgstr "세마포어를 잠글 수 없음: 오류 번호 %lu"
+
+#: port/win32_sema.c:187
+#, c-format
+msgid "could not unlock semaphore: error code %lu"
+msgstr "세마포어 잠금을 해제할 수 없음: 오류 번호 %lu"
+
+#: port/win32_sema.c:216
+#, c-format
+msgid "could not try-lock semaphore: error code %lu"
+msgstr "세마포어 잠금 시도 실패: 오류 번호 %lu"
+
+#: port/win32_shmem.c:173 port/win32_shmem.c:208 port/win32_shmem.c:226
+#, c-format
+msgid "could not create shared memory segment: error code %lu"
+msgstr "공유 메모리 세그먼트를 만들 수 없음: 오류 번호 %lu"
+
+#: port/win32_shmem.c:174
+#, c-format
+msgid "Failed system call was CreateFileMapping(size=%zu, name=%s)."
+msgstr "실패한 시스템 호출은 CreateFileMapping(크기=%zu, 이름=%s)입니다."
+
+#: port/win32_shmem.c:198
+#, c-format
+msgid "pre-existing shared memory block is still in use"
+msgstr "기존 공유 메모리 블록이 여전히 사용되고 있음"
+
+#: port/win32_shmem.c:199
+#, c-format
+msgid ""
+"Check if there are any old server processes still running, and terminate "
+"them."
+msgstr "실행 중인 이전 서버 프로세스가 있는지 확인하고 종료하십시오."
+
+#: port/win32_shmem.c:209
+#, c-format
+msgid "Failed system call was DuplicateHandle."
+msgstr "실패한 시스템 호출은 DuplicateHandle입니다."
+
+#: port/win32_shmem.c:227
+#, c-format
+msgid "Failed system call was MapViewOfFileEx."
+msgstr "실패한 시스템 호출은 MapViewOfFileEx입니다."
+
+#: postmaster/autovacuum.c:380
+#, c-format
+msgid "could not fork autovacuum launcher process: %m"
+msgstr "autovacuum 실행기 프로세스를 실행할 수 없음: %m"
+
+#: postmaster/autovacuum.c:416
+#, c-format
+msgid "autovacuum launcher started"
+msgstr "autovacuum 실행기가 시작됨"
+
+#: postmaster/autovacuum.c:779
+#, c-format
+msgid "autovacuum launcher shutting down"
+msgstr "autovacuum 실행기를 종료하는 중"
+
+#: postmaster/autovacuum.c:1441
+#, c-format
+msgid "could not fork autovacuum worker process: %m"
+msgstr "autovacuum 작업자 프로세스를 실행할 수 없음: %m"
+
+#: postmaster/autovacuum.c:1639
+#, c-format
+msgid "autovacuum: processing database \"%s\""
+msgstr "autovacuum: \"%s\" 데이터베이스 처리 중"
+
+#: postmaster/autovacuum.c:2052
+#, c-format
+msgid "autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\""
+msgstr ""
+"autovacuum: \"%s\".\"%s\" 사용 않는 임시 테이블을 \"%s\" 데이터베이스에서 삭"
+"제하는 중"
+
+#: postmaster/autovacuum.c:2064
+#, c-format
+msgid "autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\""
+msgstr ""
+"autovacuum: \"%s\".\"%s\" 사용 않는 임시 테이블을 \"%s\" 데이터베이스에서 찾"
+"았음"
+
+#: postmaster/autovacuum.c:2347
+#, c-format
+msgid "automatic vacuum of table \"%s.%s.%s\""
+msgstr "\"%s.%s.%s\" 테이블 대상으로 자동 vacuum 작업 함"
+
+#: postmaster/autovacuum.c:2350
+#, c-format
+msgid "automatic analyze of table \"%s.%s.%s\""
+msgstr "\"%s.%s.%s\" 테이블 자동 분석"
+
+#: postmaster/autovacuum.c:2899
+#, c-format
+msgid "autovacuum not started because of misconfiguration"
+msgstr "서버 설정 정보가 잘못되어 자동 청소 작업이 실행되지 못했습니다."
+
+#: postmaster/autovacuum.c:2900
+#, c-format
+msgid "Enable the \"track_counts\" option."
+msgstr "\"track_counts\" 옵션을 사용하십시오."
+
+#: postmaster/bgworker.c:346 postmaster/bgworker.c:745
+#, c-format
+msgid "registering background worker \"%s\""
+msgstr ""
+
+#: postmaster/bgworker.c:375
+#, c-format
+msgid "unregistering background worker \"%s\""
+msgstr ""
+
+#: postmaster/bgworker.c:484
+#, c-format
+msgid ""
+"background worker \"%s\": must attach to shared memory in order to request a "
+"database connection"
+msgstr ""
+
+#: postmaster/bgworker.c:493
+#, c-format
+msgid ""
+"background worker \"%s\": cannot request database access if starting at "
+"postmaster start"
+msgstr ""
+
+#: postmaster/bgworker.c:507
+#, c-format
+msgid "background worker \"%s\": invalid restart interval"
+msgstr "\"%s\" 백그라운드 작업자: 잘못된 재실행 간격"
+
+#: postmaster/bgworker.c:552
+#, c-format
+msgid "terminating background worker \"%s\" due to administrator command"
+msgstr "관리자 명령에 의해 \"%s\" 백그라운드 작업자를 종료합니다."
+
+#: postmaster/bgworker.c:752
+#, c-format
+msgid ""
+"background worker \"%s\": must be registered in shared_preload_libraries"
+msgstr ""
+"\"%s\" 백그라운드 작업자: 먼저 shared_preload_libraries 설정값으로 등록되어"
+"야 합니다."
+
+#: postmaster/bgworker.c:764
+#, c-format
+msgid ""
+"background worker \"%s\": only dynamic background workers can request "
+"notification"
+msgstr ""
+"\"%s\" 백그라운드 작업자: 동적 백그라운드 작업자만 알림을 요청할 수 있음"
+
+#: postmaster/bgworker.c:779
+#, c-format
+msgid "too many background workers"
+msgstr "백그라운드 작업자가 너무 많음"
+
+#: postmaster/bgworker.c:780
+#, c-format
+msgid "Up to %d background worker can be registered with the current settings."
+msgid_plural ""
+"Up to %d background workers can be registered with the current settings."
+msgstr[0] "현재 설정으로는 %d개의 백그라운드 작업자를 사용할 수 있습니다."
+
+#: postmaster/bgworker.c:784
+#, c-format
+msgid ""
+"Consider increasing the configuration parameter \"max_worker_processes\"."
+msgstr "\"max_worker_processes\" 환경 매개 변수 값을 좀 느려보십시오."
+
+#: postmaster/checkpointer.c:463
+#, c-format
+msgid "checkpoints are occurring too frequently (%d second apart)"
+msgid_plural "checkpoints are occurring too frequently (%d seconds apart)"
+msgstr[0] "체크포인트가 너무 자주 발생함 (%d초 간격)"
+
+#: postmaster/checkpointer.c:467
+#, c-format
+msgid "Consider increasing the configuration parameter \"max_wal_size\"."
+msgstr "\"max_wal_size\" 환경 매개 변수 값을 좀 느려보십시오."
+
+#: postmaster/checkpointer.c:614
+#, c-format
+msgid "transaction log switch forced (archive_timeout=%d)"
+msgstr "강제로 트랜잭션 로그를 바꿨습니다 (archive_timeout=%d)"
+
+#: postmaster/checkpointer.c:1072
+#, c-format
+msgid "checkpoint request failed"
+msgstr "체크포인트 요청 실패"
+
+#: postmaster/checkpointer.c:1073
+#, c-format
+msgid "Consult recent messages in the server log for details."
+msgstr "더 자세한 것은 서버 로그 파일을 살펴보십시오."
+
+#: postmaster/checkpointer.c:1268
+#, c-format
+msgid "compacted fsync request queue from %d entries to %d entries"
+msgstr ""
+
+#: postmaster/pgarch.c:149
+#, c-format
+msgid "could not fork archiver: %m"
+msgstr "archiver 할당(fork) 실패: %m"
+
+#: postmaster/pgarch.c:456
+#, c-format
+msgid "archive_mode enabled, yet archive_command is not set"
+msgstr "archive_mode가 사용 설정되었는데 archive_command가 설정되지 않음"
+
+#: postmaster/pgarch.c:484
+#, c-format
+msgid ""
+"archiving transaction log file \"%s\" failed too many times, will try again "
+"later"
+msgstr ""
+"\"%s\" 트랜잭션 로그 파일 아카이브 작업이 계속 실패하고 있습니다. 다음에 또 "
+"시도할 것입니다."
+
+#: postmaster/pgarch.c:587
+#, c-format
+msgid "archive command failed with exit code %d"
+msgstr "아카이브 명령 실패, 종료 코드: %d"
+
+#: postmaster/pgarch.c:589 postmaster/pgarch.c:599 postmaster/pgarch.c:606
+#: postmaster/pgarch.c:612 postmaster/pgarch.c:621
+#, c-format
+msgid "The failed archive command was: %s"
+msgstr "실패한 아카이브 명령: %s"
+
+#: postmaster/pgarch.c:596
+#, c-format
+msgid "archive command was terminated by exception 0x%X"
+msgstr "0x%X 예외로 인해 아카이브 명령이 종료됨"
+
+#: postmaster/pgarch.c:598 postmaster/postmaster.c:3491
+#, c-format
+msgid ""
+"See C include file \"ntstatus.h\" for a description of the hexadecimal value."
+msgstr "16진수 값에 대한 설명은 C 포함 파일 \"ntstatus.h\"를 참조하십시오."
+
+#: postmaster/pgarch.c:603
+#, c-format
+msgid "archive command was terminated by signal %d: %s"
+msgstr "%d번 시그널로 인해 아카이브 명령이 종료됨: %s"
+
+#: postmaster/pgarch.c:610
+#, c-format
+msgid "archive command was terminated by signal %d"
+msgstr "%d번 시그널로 인해 아카이브 명령이 종료됨"
+
+#: postmaster/pgarch.c:619
+#, c-format
+msgid "archive command exited with unrecognized status %d"
+msgstr "아카이브 명령이 인식할 수 없는 %d 상태로 종료됨"
+
+#: postmaster/pgarch.c:631
+#, c-format
+msgid "archived transaction log file \"%s\""
+msgstr "\"%s\" 트랜잭션 로그파일이 아카이브 됨"
+
+#: postmaster/pgarch.c:680
+#, c-format
+msgid "could not open archive status directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 열 수 없습니다: %m"
+
+#: postmaster/pgstat.c:355
+#, c-format
+msgid "could not resolve \"localhost\": %s"
+msgstr "\"localhost\" 이름의 호스트 IP를 구할 수 없습니다: %s"
+
+#: postmaster/pgstat.c:378
+#, c-format
+msgid "trying another address for the statistics collector"
+msgstr "통계 수집기에서 사용할 다른 주소를 찾습니다"
+
+#: postmaster/pgstat.c:387
+#, c-format
+msgid "could not create socket for statistics collector: %m"
+msgstr "통계 수집기에서 사용할 소켓을 만들 수 없습니다: %m"
+
+#: postmaster/pgstat.c:399
+#, c-format
+msgid "could not bind socket for statistics collector: %m"
+msgstr "통계 수집기에서 사용할 소켓과 bind할 수 없습니다: %m"
+
+#: postmaster/pgstat.c:410
+#, c-format
+msgid "could not get address of socket for statistics collector: %m"
+msgstr "통계 수집기에서 사용할 소켓의 주소를 구할 수 없습니다: %m"
+
+#: postmaster/pgstat.c:426
+#, c-format
+msgid "could not connect socket for statistics collector: %m"
+msgstr "통계 수집기에서 사용할 소켓에 연결할 수 없습니다: %m"
+
+#: postmaster/pgstat.c:447
+#, c-format
+msgid "could not send test message on socket for statistics collector: %m"
+msgstr "통계 수집기에서 사용할 소켓으로 테스트 메시지를 보낼 수 없습니다: %m"
+
+#: postmaster/pgstat.c:473
+#, c-format
+msgid "select() failed in statistics collector: %m"
+msgstr "통계 수집기에서 select() 작업 오류: %m"
+
+#: postmaster/pgstat.c:488
+#, c-format
+msgid "test message did not get through on socket for statistics collector"
+msgstr "통계 수집기에서 사용할 소켓으로 테스트 메시지를 처리할 수 없습니다"
+
+#: postmaster/pgstat.c:503
+#, c-format
+msgid "could not receive test message on socket for statistics collector: %m"
+msgstr "통계 수집기에서 사용할 소켓으로 테스트 메시지를 받을 수 없습니다: %m"
+
+#: postmaster/pgstat.c:513
+#, c-format
+msgid "incorrect test message transmission on socket for statistics collector"
+msgstr "통계 수집기에서 사용할 소켓으로 잘못된 테스트 메시지가 전달 되었습니다"
+
+#: postmaster/pgstat.c:536
+#, c-format
+msgid "could not set statistics collector socket to nonblocking mode: %m"
+msgstr ""
+"통계 수집기에서 사용하는 소켓 모드를 nonblocking 모드로 지정할 수 없습니다: "
+"%m"
+
+#: postmaster/pgstat.c:546
+#, c-format
+msgid "disabling statistics collector for lack of working socket"
+msgstr "현재 작업 소켓의 원할한 소통을 위해 통계 수집기 기능을 중지합니다"
+
+#: postmaster/pgstat.c:693
+#, c-format
+msgid "could not fork statistics collector: %m"
+msgstr "통계 수집기를 fork할 수 없습니다: %m"
+
+#: postmaster/pgstat.c:1261
+#, c-format
+msgid "unrecognized reset target: \"%s\""
+msgstr "알 수 없는 리셋 타겟: \"%s\""
+
+#: postmaster/pgstat.c:1262
+#, c-format
+msgid "Target must be \"archiver\" or \"bgwriter\"."
+msgstr "사용 가능한 타겟은 \"archiver\" 또는 \"bgwriter\""
+
+#: postmaster/pgstat.c:3587
+#, c-format
+msgid "could not read statistics message: %m"
+msgstr "통계 메시지를 읽을 수 없음: %m"
+
+#: postmaster/pgstat.c:3918 postmaster/pgstat.c:4075
+#, c-format
+msgid "could not open temporary statistics file \"%s\": %m"
+msgstr "\"%s\" 임시 통계 파일을 열 수 없음: %m"
+
+#: postmaster/pgstat.c:3985 postmaster/pgstat.c:4120
+#, c-format
+msgid "could not write temporary statistics file \"%s\": %m"
+msgstr "\"%s\" 임시 통계 파일에 쓰기 실패: %m"
+
+#: postmaster/pgstat.c:3994 postmaster/pgstat.c:4129
+#, c-format
+msgid "could not close temporary statistics file \"%s\": %m"
+msgstr "\"%s\" 임시 통계 파일을 닫을 수 없습니다: %m"
+
+#: postmaster/pgstat.c:4002 postmaster/pgstat.c:4137
+#, c-format
+msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m"
+msgstr "\"%s\" 임시 통계 파일 이름을 \"%s\" (으)로 바꿀 수 없습니다: %m"
+
+#: postmaster/pgstat.c:4226 postmaster/pgstat.c:4411 postmaster/pgstat.c:4564
+#, c-format
+msgid "could not open statistics file \"%s\": %m"
+msgstr "\"%s\" 통계 파일을 열 수 없음: %m"
+
+#: postmaster/pgstat.c:4238 postmaster/pgstat.c:4248 postmaster/pgstat.c:4258
+#: postmaster/pgstat.c:4279 postmaster/pgstat.c:4294 postmaster/pgstat.c:4348
+#: postmaster/pgstat.c:4423 postmaster/pgstat.c:4443 postmaster/pgstat.c:4461
+#: postmaster/pgstat.c:4477 postmaster/pgstat.c:4495 postmaster/pgstat.c:4511
+#: postmaster/pgstat.c:4576 postmaster/pgstat.c:4588 postmaster/pgstat.c:4600
+#: postmaster/pgstat.c:4625 postmaster/pgstat.c:4647
+#, c-format
+msgid "corrupted statistics file \"%s\""
+msgstr "\"%s\" 통계 파일이 손상되었음"
+
+#: postmaster/pgstat.c:4776
+#, c-format
+msgid ""
+"using stale statistics instead of current ones because stats collector is "
+"not responding"
+msgstr ""
+"현재 통계 수집기가 반응하지 않아 부정확한 통계정보가 사용되고 있습니다."
+
+#: postmaster/pgstat.c:5103
+#, c-format
+msgid "database hash table corrupted during cleanup --- abort"
+msgstr "정리하는 동안 데이터베이스 해시 테이블이 손상 되었습니다 --- 중지함"
+
+#: postmaster/postmaster.c:684
+#, c-format
+msgid "%s: invalid argument for option -f: \"%s\"\n"
+msgstr "%s: -f 옵션의 잘못된 인자: \"%s\"\n"
+
+#: postmaster/postmaster.c:770
+#, c-format
+msgid "%s: invalid argument for option -t: \"%s\"\n"
+msgstr "%s: -t 옵션의 잘못된 인자: \"%s\"\n"
+
+#: postmaster/postmaster.c:821
+#, c-format
+msgid "%s: invalid argument: \"%s\"\n"
+msgstr "%s: 잘못된 인자: \"%s\"\n"
+
+#: postmaster/postmaster.c:860
+#, c-format
+msgid "%s: superuser_reserved_connections must be less than max_connections\n"
+msgstr ""
+"%s: superuser_reserved_connections 값은 max_connections 값보다 작아야합니다\n"
+
+#: postmaster/postmaster.c:865
+#, c-format
+msgid "%s: max_wal_senders must be less than max_connections\n"
+msgstr "%s: max_wal_senders 값은 max_connections 값보다 작아야합니다\n"
+
+#: postmaster/postmaster.c:870
+#, c-format
+msgid "WAL archival cannot be enabled when wal_level is \"minimal\""
+msgstr "wal_level 값이 \"minimal\"일 때는 아카이브 작업을 할 수 없습니다."
+
+#: postmaster/postmaster.c:873
+#, c-format
+msgid ""
+"WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or "
+"\"logical\""
+msgstr ""
+"WAL 스트리밍 작업(max_wal_senders > 0 인경우)은 wal_level 값이 \"replica\" 또"
+"는 \"logical\" 이어야 합니다."
+
+#: postmaster/postmaster.c:881
+#, c-format
+msgid "%s: invalid datetoken tables, please fix\n"
+msgstr "%s: 잘못된 datetoken 테이블들, 복구하십시오.\n"
+
+#: postmaster/postmaster.c:973 postmaster/postmaster.c:1071
+#: utils/init/miscinit.c:1429
+#, c-format
+msgid "invalid list syntax in parameter \"%s\""
+msgstr "\"%s\" 매개 변수 구문이 잘못 되었습니다"
+
+#: postmaster/postmaster.c:1004
+#, c-format
+msgid "could not create listen socket for \"%s\""
+msgstr "\"%s\" 응당 소켓을 만들 수 없습니다"
+
+#: postmaster/postmaster.c:1010
+#, c-format
+msgid "could not create any TCP/IP sockets"
+msgstr "TCP/IP 소켓을 만들 수 없습니다."
+
+#: postmaster/postmaster.c:1093
+#, c-format
+msgid "could not create Unix-domain socket in directory \"%s\""
+msgstr "\"%s\" 디렉터리에 유닉스 도메인 소켓을 만들 수 없습니다"
+
+#: postmaster/postmaster.c:1099
+#, c-format
+msgid "could not create any Unix-domain sockets"
+msgstr "유닉스 도메인 소켓을 만들 수 없습니다"
+
+#: postmaster/postmaster.c:1111
+#, c-format
+msgid "no socket created for listening"
+msgstr "서버 접속 대기 작업을 위한 소켓을 만들 수 없음"
+
+#: postmaster/postmaster.c:1151
+#, c-format
+msgid "could not create I/O completion port for child queue"
+msgstr "하위 대기열에 대해 I/O 완료 포트를 만들 수 없음"
+
+#: postmaster/postmaster.c:1180
+#, c-format
+msgid "%s: could not change permissions of external PID file \"%s\": %s\n"
+msgstr "%s: \"%s\" 외부 PID 파일의 접근 권한을 바꿀 수 없음: %s\n"
+
+#: postmaster/postmaster.c:1184
+#, c-format
+msgid "%s: could not write external PID file \"%s\": %s\n"
+msgstr "%s: 외부 pid 파일 \"%s\" 를 쓸 수 없음: %s\n"
+
+#: postmaster/postmaster.c:1234
+#, c-format
+msgid "ending log output to stderr"
+msgstr "stderr 쪽 로그 출력을 중지합니다."
+
+#: postmaster/postmaster.c:1235
+#, c-format
+msgid "Future log output will go to log destination \"%s\"."
+msgstr "자세한 로그는 \"%s\" 쪽으로 기록됩니다."
+
+#: postmaster/postmaster.c:1261 utils/init/postinit.c:213
+#, c-format
+msgid "could not load pg_hba.conf"
+msgstr "pg_hba.conf를 로드할 수 없음"
+
+#: postmaster/postmaster.c:1287
+#, c-format
+msgid "postmaster became multithreaded during startup"
+msgstr ""
+
+#: postmaster/postmaster.c:1288
+#, c-format
+msgid "Set the LC_ALL environment variable to a valid locale."
+msgstr "LC_ALL 환경 설정값으로 알맞은 로케일 이름을 지정하세요."
+
+#: postmaster/postmaster.c:1385
+#, c-format
+msgid "%s: could not locate matching postgres executable"
+msgstr "%s: 실행가능한 postgres 프로그램을 찾을 수 없습니다"
+
+#: postmaster/postmaster.c:1408 utils/misc/tzparser.c:341
+#, c-format
+msgid ""
+"This may indicate an incomplete PostgreSQL installation, or that the file "
+"\"%s\" has been moved away from its proper location."
+msgstr ""
+"이 문제는 PostgreSQL 설치가 불완전하게 되었거나, \"%s\" 파일이 올바른 위치에 "
+"있지 않아서 발생했습니다."
+
+#: postmaster/postmaster.c:1436
+#, c-format
+msgid "data directory \"%s\" does not exist"
+msgstr "\"%s\" 데이터 디렉터리 없음"
+
+#: postmaster/postmaster.c:1441
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리 읽기 권한 없음: %m"
+
+#: postmaster/postmaster.c:1449
+#, c-format
+msgid "specified data directory \"%s\" is not a directory"
+msgstr "지정한 \"%s\" 데이터 디렉터리는 디렉터리가 아님"
+
+#: postmaster/postmaster.c:1465
+#, c-format
+msgid "data directory \"%s\" has wrong ownership"
+msgstr "\"%s\" 데이터 디렉터리 소유주가 잘못 되었습니다."
+
+#: postmaster/postmaster.c:1467
+#, c-format
+msgid "The server must be started by the user that owns the data directory."
+msgstr "서버는 지정한 데이터 디렉터리의 소유주 권한으로 시작되어야합니다."
+
+#: postmaster/postmaster.c:1487
+#, c-format
+msgid "data directory \"%s\" has group or world access"
+msgstr "\"%s\" 데이터 디렉터리 액세스 권한이 잘못 되었습니다"
+
+#: postmaster/postmaster.c:1489
+#, c-format
+msgid "Permissions should be u=rwx (0700)."
+msgstr "액세스 권한은 u=rwx (0700) 값이어야 합니다."
+
+#: postmaster/postmaster.c:1500
+#, c-format
+msgid ""
+"%s: could not find the database system\n"
+"Expected to find it in the directory \"%s\",\n"
+"but could not open file \"%s\": %s\n"
+msgstr ""
+"%s: 데이터베이스 시스템을 찾을 수 없습니다\n"
+"\"%s\" 디렉터리 안에 해당 자료가 있기를 기대했는데,\n"
+"\"%s\" 파일을 열 수가 없었습니다: %s\n"
+
+#: postmaster/postmaster.c:1677
+#, c-format
+msgid "select() failed in postmaster: %m"
+msgstr "postmaster에서 select() 작동 실패: %m"
+
+#: postmaster/postmaster.c:1828
+#, c-format
+msgid ""
+"performing immediate shutdown because data directory lock file is invalid"
+msgstr ""
+
+#: postmaster/postmaster.c:1906 postmaster/postmaster.c:1937
+#, c-format
+msgid "incomplete startup packet"
+msgstr "아직 완료되지 않은 시작 패킷"
+
+#: postmaster/postmaster.c:1918
+#, c-format
+msgid "invalid length of startup packet"
+msgstr "시작 패킷의 길이가 잘못 되었습니다"
+
+#: postmaster/postmaster.c:1976
+#, c-format
+msgid "failed to send SSL negotiation response: %m"
+msgstr "SSL 연결 작업에 오류가 발생했습니다: %m"
+
+#: postmaster/postmaster.c:2005
+#, c-format
+msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u"
+msgstr ""
+"지원하지 않는 frontend 프로토콜 %u.%u: 서버에서 지원하는 프로토콜 %u.0 .. %u."
+"%u"
+
+#: postmaster/postmaster.c:2068 utils/misc/guc.c:5660 utils/misc/guc.c:5753
+#: utils/misc/guc.c:7051 utils/misc/guc.c:9805 utils/misc/guc.c:9839
+#, c-format
+msgid "invalid value for parameter \"%s\": \"%s\""
+msgstr "잘못된 \"%s\" 매개 변수의 값: \"%s\""
+
+#: postmaster/postmaster.c:2071
+#, c-format
+msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"."
+msgstr ""
+
+#: postmaster/postmaster.c:2091
+#, c-format
+msgid "invalid startup packet layout: expected terminator as last byte"
+msgstr "잘못된 시작 패킷 레이아웃: 마지막 바이트로 종결문자가 발견되었음"
+
+#: postmaster/postmaster.c:2119
+#, c-format
+msgid "no PostgreSQL user name specified in startup packet"
+msgstr "시작 패킷에서 지정한 사용자는 PostgreSQL 사용자 이름이 아닙니다"
+
+#: postmaster/postmaster.c:2178
+#, c-format
+msgid "the database system is starting up"
+msgstr "데이터베이스 시스템이 새로 가동 중입니다."
+
+#: postmaster/postmaster.c:2183
+#, c-format
+msgid "the database system is shutting down"
+msgstr "데이터베이스 시스템이 중지 중입니다"
+
+#: postmaster/postmaster.c:2188
+#, c-format
+msgid "the database system is in recovery mode"
+msgstr "데이터베이스 시스템이 자동 복구 작업 중입니다."
+
+#: postmaster/postmaster.c:2193 storage/ipc/procarray.c:297
+#: storage/ipc/sinvaladt.c:298 storage/lmgr/proc.c:340
+#, c-format
+msgid "sorry, too many clients already"
+msgstr "최대 동시 접속자 수를 초과했습니다."
+
+#: postmaster/postmaster.c:2255
+#, c-format
+msgid "wrong key in cancel request for process %d"
+msgstr "프로세스 %d에 대한 취소 요청에 잘못된 키가 있음"
+
+#: postmaster/postmaster.c:2263
+#, c-format
+msgid "PID %d in cancel request did not match any process"
+msgstr "취소 요청의 PID %d과(와) 일치하는 프로세스가 없음"
+
+#: postmaster/postmaster.c:2483
+#, c-format
+msgid "received SIGHUP, reloading configuration files"
+msgstr "SIGHUP 신호를 받아서, 환경설정파일을 다시 읽고 있습니다."
+
+#: postmaster/postmaster.c:2508
+#, c-format
+msgid "pg_hba.conf not reloaded"
+msgstr "pg_hba.conf가 다시 로드되지 않음"
+
+#: postmaster/postmaster.c:2512
+#, c-format
+msgid "pg_ident.conf not reloaded"
+msgstr "pg_ident.conf 파일이 다시 로드되지 않음"
+
+#: postmaster/postmaster.c:2553
+#, c-format
+msgid "received smart shutdown request"
+msgstr "smart 중지 요청을 받았습니다."
+
+#: postmaster/postmaster.c:2608
+#, c-format
+msgid "received fast shutdown request"
+msgstr "fast 중지 요청을 받았습니다."
+
+#: postmaster/postmaster.c:2638
+#, c-format
+msgid "aborting any active transactions"
+msgstr "모든 활성화 되어있는 트랜잭션을 중지하고 있습니다."
+
+#: postmaster/postmaster.c:2672
+#, c-format
+msgid "received immediate shutdown request"
+msgstr "immediate 중지 요청을 받았습니다."
+
+#: postmaster/postmaster.c:2736
+#, c-format
+msgid "shutdown at recovery target"
+msgstr "복구 타겟에서 중지함"
+
+#: postmaster/postmaster.c:2752 postmaster/postmaster.c:2775
+msgid "startup process"
+msgstr "시작 프로세스"
+
+#: postmaster/postmaster.c:2755
+#, c-format
+msgid "aborting startup due to startup process failure"
+msgstr "시작 프로세스 실패 때문에 서버 시작이 중지 되었습니다"
+
+#: postmaster/postmaster.c:2816
+#, c-format
+msgid "database system is ready to accept connections"
+msgstr "이제 데이터베이스 서버로 접속할 수 있습니다"
+
+#: postmaster/postmaster.c:2835
+msgid "background writer process"
+msgstr "백그라운드 writer 프로세스"
+
+#: postmaster/postmaster.c:2889
+msgid "checkpointer process"
+msgstr "체크포인트 프로세스"
+
+#: postmaster/postmaster.c:2905
+msgid "WAL writer process"
+msgstr "WAL 쓰기 프로세스"
+
+#: postmaster/postmaster.c:2919
+msgid "WAL receiver process"
+msgstr "WAL 수신 프로세스"
+
+#: postmaster/postmaster.c:2934
+msgid "autovacuum launcher process"
+msgstr "autovacuum 실행기 프로세스"
+
+#: postmaster/postmaster.c:2949
+msgid "archiver process"
+msgstr "archiver 프로세스"
+
+#: postmaster/postmaster.c:2965
+msgid "statistics collector process"
+msgstr "통계 수집기 프로세스"
+
+#: postmaster/postmaster.c:2979
+msgid "system logger process"
+msgstr "시스템 로그 프로세스"
+
+#: postmaster/postmaster.c:3041
+msgid "worker process"
+msgstr "작업자 프로세스"
+
+#: postmaster/postmaster.c:3124 postmaster/postmaster.c:3144
+#: postmaster/postmaster.c:3151 postmaster/postmaster.c:3169
+msgid "server process"
+msgstr "서버 프로세스"
+
+#: postmaster/postmaster.c:3223
+#, c-format
+msgid "terminating any other active server processes"
+msgstr "다른 활성화 되어있는 서버 프로세스를 마치고 있는 중입니다"
+
+#. translator: %s is a noun phrase describing a child process, such as
+#. "server process"
+#: postmaster/postmaster.c:3479
+#, c-format
+msgid "%s (PID %d) exited with exit code %d"
+msgstr "%s (PID %d) 프로그램은 %d 코드로 마쳤습니다"
+
+#: postmaster/postmaster.c:3481 postmaster/postmaster.c:3492
+#: postmaster/postmaster.c:3503 postmaster/postmaster.c:3512
+#: postmaster/postmaster.c:3522
+#, c-format
+msgid "Failed process was running: %s"
+msgstr ""
+
+#. translator: %s is a noun phrase describing a child process, such as
+#. "server process"
+#: postmaster/postmaster.c:3489
+#, c-format
+msgid "%s (PID %d) was terminated by exception 0x%X"
+msgstr "%s (PID %d) 프로세스가 0x%X 예외로 인해 종료됨"
+
+#. translator: %s is a noun phrase describing a child process, such as
+#. "server process"
+#: postmaster/postmaster.c:3499
+#, c-format
+msgid "%s (PID %d) was terminated by signal %d: %s"
+msgstr "%s (PID %d) 프로세스가 %d번 시그널을 받아 종료됨: %s"
+
+#. translator: %s is a noun phrase describing a child process, such as
+#. "server process"
+#: postmaster/postmaster.c:3510
+#, c-format
+msgid "%s (PID %d) was terminated by signal %d"
+msgstr "%s (PID %d) 프로세스가 %d번 시그널을 받아 종료됨"
+
+#. translator: %s is a noun phrase describing a child process, such as
+#. "server process"
+#: postmaster/postmaster.c:3520
+#, c-format
+msgid "%s (PID %d) exited with unrecognized status %d"
+msgstr "%s (PID %d) 프로세스가 인식할 수 없는 %d 상태로 종료됨"
+
+#: postmaster/postmaster.c:3707
+#, c-format
+msgid "abnormal database system shutdown"
+msgstr "비정상적인 데이터베이스 시스템 서비스를 중지"
+
+#: postmaster/postmaster.c:3747
+#, c-format
+msgid "all server processes terminated; reinitializing"
+msgstr "모든 서버 프로세스가 중지 되었습니다; 재 초기화 중"
+
+#: postmaster/postmaster.c:3959
+#, c-format
+msgid "could not fork new process for connection: %m"
+msgstr "연결을 위한 새 프로세스 할당(fork) 실패: %m"
+
+#: postmaster/postmaster.c:4001
+msgid "could not fork new process for connection: "
+msgstr "연결을 위한 새 프로세스 할당(fork) 실패: "
+
+#: postmaster/postmaster.c:4115
+#, c-format
+msgid "connection received: host=%s port=%s"
+msgstr "접속 수락: host=%s port=%s"
+
+#: postmaster/postmaster.c:4120
+#, c-format
+msgid "connection received: host=%s"
+msgstr "접속 수락: host=%s"
+
+#: postmaster/postmaster.c:4403
+#, c-format
+msgid "could not execute server process \"%s\": %m"
+msgstr "\"%s\" 서버 프로세스를 실행할 수 없음: %m"
+
+#: postmaster/postmaster.c:4947
+#, c-format
+msgid "database system is ready to accept read only connections"
+msgstr "데이터베이스 시스템이 읽기 전용으로 연결을 수락할 준비가 되었습니다."
+
+#: postmaster/postmaster.c:5238
+#, c-format
+msgid "could not fork startup process: %m"
+msgstr "시작 프로세스 할당(fork) 실패: %m"
+
+#: postmaster/postmaster.c:5242
+#, c-format
+msgid "could not fork background writer process: %m"
+msgstr "백그라운 writer 프로세스를 할당(fork)할 수 없습니다: %m"
+
+#: postmaster/postmaster.c:5246
+#, c-format
+msgid "could not fork checkpointer process: %m"
+msgstr "체크포인트 프로세스를 할당(fork)할 수 없습니다: %m"
+
+#: postmaster/postmaster.c:5250
+#, c-format
+msgid "could not fork WAL writer process: %m"
+msgstr "WAL 쓰기 프로세스를 할당(fork)할 수 없음: %m"
+
+#: postmaster/postmaster.c:5254
+#, c-format
+msgid "could not fork WAL receiver process: %m"
+msgstr "WAL 수신 프로세스를 할당(fork)할 수 없음: %m"
+
+#: postmaster/postmaster.c:5258
+#, c-format
+msgid "could not fork process: %m"
+msgstr "프로세스 할당(fork) 실패: %m"
+
+#: postmaster/postmaster.c:5420 postmaster/postmaster.c:5443
+#, c-format
+msgid "database connection requirement not indicated during registration"
+msgstr ""
+
+#: postmaster/postmaster.c:5427 postmaster/postmaster.c:5450
+#, c-format
+msgid "invalid processing mode in background worker"
+msgstr "백그라운드 작업자에서 잘못된 프로세싱 모드가 사용됨"
+
+#: postmaster/postmaster.c:5502
+#, c-format
+msgid "starting background worker process \"%s\""
+msgstr "\"%s\" 백그라운드 작업자 프로세스를 시작합니다."
+
+#: postmaster/postmaster.c:5513
+#, c-format
+msgid "could not fork worker process: %m"
+msgstr "작업자 프로세스를 할당(fork)할 수 없음: %m"
+
+#: postmaster/postmaster.c:5901
+#, c-format
+msgid "could not duplicate socket %d for use in backend: error code %d"
+msgstr "백엔드에서 사용하기 위해 %d 소켓을 복사할 수 없음: 오류 코드 %d"
+
+#: postmaster/postmaster.c:5933
+#, c-format
+msgid "could not create inherited socket: error code %d\n"
+msgstr "상속된 소켓을 만들 수 없음: 오류 코드 %d\n"
+
+#: postmaster/postmaster.c:5962
+#, c-format
+msgid "could not open backend variables file \"%s\": %s\n"
+msgstr "\"%s\" 백엔드 변수 파일을 열 수 없음: %s\n"
+
+#: postmaster/postmaster.c:5969
+#, c-format
+msgid "could not read from backend variables file \"%s\": %s\n"
+msgstr "\"%s\" 백엔드 변수 파일을 읽을 수 없음: %s\n"
+
+#: postmaster/postmaster.c:5978
+#, c-format
+msgid "could not remove file \"%s\": %s\n"
+msgstr "\"%s\" 파일을 삭제할 수 없음: %s\n"
+
+#: postmaster/postmaster.c:5995
+#, c-format
+msgid "could not map view of backend variables: error code %lu\n"
+msgstr "백엔드 변수 파일의 view를 map할 수 없음: 오류 코드 %lu\n"
+
+#: postmaster/postmaster.c:6004
+#, c-format
+msgid "could not unmap view of backend variables: error code %lu\n"
+msgstr "백엔드 변수 파일의 view를 unmap할 수 없음: 오류 코드 %lu\n"
+
+#: postmaster/postmaster.c:6011
+#, c-format
+msgid "could not close handle to backend parameter variables: error code %lu\n"
+msgstr "백엔드 변수 파일을 닫을 수 없음: 오류 코드 %lu\n"
+
+#: postmaster/postmaster.c:6172
+#, c-format
+msgid "could not read exit code for process\n"
+msgstr "프로세스의 종료 코드를 읽을 수 없음\n"
+
+#: postmaster/postmaster.c:6177
+#, c-format
+msgid "could not post child completion status\n"
+msgstr "하위 완료 상태를 게시할 수 없음\n"
+
+#: postmaster/syslogger.c:441 postmaster/syslogger.c:1041
+#, c-format
+msgid "could not read from logger pipe: %m"
+msgstr "로그 파이프에서 읽기 실패: %m"
+
+#: postmaster/syslogger.c:490
+#, c-format
+msgid "logger shutting down"
+msgstr "로그 작업 끝내는 중"
+
+#: postmaster/syslogger.c:534 postmaster/syslogger.c:548
+#, c-format
+msgid "could not create pipe for syslog: %m"
+msgstr "syslog에서 사용할 파이프를 만들 수 없습니다: %m"
+
+#: postmaster/syslogger.c:584
+#, c-format
+msgid "could not fork system logger: %m"
+msgstr "시스템 로거(logger)를 확보하질 못 했습니다: %m"
+
+#: postmaster/syslogger.c:620
+#, c-format
+msgid "redirecting log output to logging collector process"
+msgstr ""
+
+#: postmaster/syslogger.c:621
+#, c-format
+msgid "Future log output will appear in directory \"%s\"."
+msgstr ""
+
+#: postmaster/syslogger.c:629
+#, c-format
+msgid "could not redirect stdout: %m"
+msgstr "표준출력을 redirect 하지 못했습니다: %m"
+
+#: postmaster/syslogger.c:634 postmaster/syslogger.c:651
+#, c-format
+msgid "could not redirect stderr: %m"
+msgstr "표준오류(stderr)를 redirect 하지 못했습니다: %m"
+
+#: postmaster/syslogger.c:996
+#, c-format
+msgid "could not write to log file: %s\n"
+msgstr "로그파일 쓰기 실패: %s\n"
+
+#: postmaster/syslogger.c:1136
+#, c-format
+msgid "could not open log file \"%s\": %m"
+msgstr "\"%s\" 잠금파일을 열 수 없음: %m"
+
+#: postmaster/syslogger.c:1198 postmaster/syslogger.c:1242
+#, c-format
+msgid "disabling automatic rotation (use SIGHUP to re-enable)"
+msgstr ""
+"로그파일 자동 교체 기능을 금지합니다(교체하려면 SIGHUP 시그널을 사용함)"
+
+#: regex/regc_pg_locale.c:261
+#, c-format
+msgid "could not determine which collation to use for regular expression"
+msgstr "정규식을 사용해서 사용할 정렬규칙(collation)을 찾을 수 없음"
+
+#: replication/basebackup.c:232
+#, c-format
+msgid "could not stat control file \"%s\": %m"
+msgstr "\"%s\" 컨트롤 파일의 정보를 구할 수 없음: %m"
+
+#: replication/basebackup.c:341
+#, c-format
+msgid "could not find any WAL files"
+msgstr "어떤 WAL 파일도 찾을 수 없음"
+
+#: replication/basebackup.c:354 replication/basebackup.c:368
+#: replication/basebackup.c:377
+#, c-format
+msgid "could not find WAL file \"%s\""
+msgstr "\"%s\" WAL 파일 찾기 실패"
+
+#: replication/basebackup.c:416 replication/basebackup.c:442
+#, c-format
+msgid "unexpected WAL file size \"%s\""
+msgstr "\"%s\" WAL 파일의 크기가 알맞지 않음"
+
+#: replication/basebackup.c:428 replication/basebackup.c:1160
+#, c-format
+msgid "base backup could not send data, aborting backup"
+msgstr "베이스 백업에서 자료를 보낼 수 없음. 백업을 중지합니다."
+
+#: replication/basebackup.c:530 replication/basebackup.c:539
+#: replication/basebackup.c:548 replication/basebackup.c:557
+#: replication/basebackup.c:566 replication/basebackup.c:577
+#: replication/basebackup.c:594
+#, c-format
+msgid "duplicate option \"%s\""
+msgstr "\"%s\" 옵션을 두 번 지정했습니다"
+
+#: replication/basebackup.c:583 utils/misc/guc.c:5670
+#, c-format
+msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)"
+msgstr ""
+"%d 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%d .. %d)를 벗어났습니다."
+
+#: replication/basebackup.c:857 replication/basebackup.c:959
+#, c-format
+msgid "could not stat file or directory \"%s\": %m"
+msgstr "파일 또는 디렉터리 \"%s\"의 상태를 확인할 수 없음: %m"
+
+#: replication/basebackup.c:1112
+#, c-format
+msgid "skipping special file \"%s\""
+msgstr "\"%s\" 특수 파일을 건너뜀"
+
+#: replication/basebackup.c:1223
+#, c-format
+msgid "file name too long for tar format: \"%s\""
+msgstr "tar 파일로 묶기에는 파일 이름이 너무 긺: \"%s\""
+
+#: replication/basebackup.c:1228
+#, c-format
+msgid ""
+"symbolic link target too long for tar format: file name \"%s\", target \"%s\""
+msgstr ""
+"tar 포멧을 사용하기에는 심볼릭 링크의 대상 경로가 너무 깁니다: 파일 이름 \"%s"
+"\", 대상 \"%s\""
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:119
+#, c-format
+msgid "could not connect to the primary server: %s"
+msgstr "주 서버에 연결 할 수 없음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:142
+#, c-format
+msgid "could not parse connection string: %s"
+msgstr "접속 문자열을 분석할 수 없음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:192
+#, c-format
+msgid ""
+"could not receive database system identifier and timeline ID from the "
+"primary server: %s"
+msgstr ""
+"주 서버에서 데이터베이스 시스템 식별번호와 타임라인 번호를 받을 수 없음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:203
+#: replication/libpqwalreceiver/libpqwalreceiver.c:357
+#, c-format
+msgid "invalid response from primary server"
+msgstr "주 서버에서 잘못된 응답이 왔음"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:204
+#, c-format
+msgid ""
+"Could not identify system: got %d rows and %d fields, expected %d rows and "
+"%d or more fields."
+msgstr ""
+"시스템을 식별할 수 없음: 로우수 %d, 필드수 %d, 예상값: 로우수 %d, 필드수 %d "
+"이상"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:220
+#, c-format
+msgid "database system identifier differs between the primary and standby"
+msgstr "데이터베이스 시스템 식별번호가 주 서버와 대기 서버가 서로 다름"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:221
+#, c-format
+msgid "The primary's identifier is %s, the standby's identifier is %s."
+msgstr "주 서버: %s, 대기 서버: %s."
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:263
+#, c-format
+msgid "could not start WAL streaming: %s"
+msgstr "WAL 스트리밍 작업을 시작할 수 없음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:281
+#, c-format
+msgid "could not send end-of-streaming message to primary: %s"
+msgstr "주 서버로 스트리밍 종료 메시지를 보낼 수 없음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:303
+#, c-format
+msgid "unexpected result set after end-of-streaming"
+msgstr "스트리밍 종료 요청에 대한 잘못된 응답을 받음"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:315
+#, c-format
+msgid "error reading result of streaming command: %s"
+msgstr "스트리밍 명령에 대한 결과 처리에서 오류 발생: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:323
+#, c-format
+msgid "unexpected result after CommandComplete: %s"
+msgstr "CommandComplete 작업 후 예상치 못한 결과를 받음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:346
+#, c-format
+msgid "could not receive timeline history file from the primary server: %s"
+msgstr "주 서버에서 타임라인 내역 파일을 받을 수 없음: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:358
+#, c-format
+msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields."
+msgstr "2개의 칼럼으로 된 하나의 튜플을 예상하지만, %d 튜플 (%d 칼럼)을 수신함"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:386
+#, c-format
+msgid "invalid socket: %s"
+msgstr "잘못된 소켓: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:426
+#: storage/ipc/latch.c:1280
+#, c-format
+msgid "select() failed: %m"
+msgstr "select() 실패: %m"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:549
+#: replication/libpqwalreceiver/libpqwalreceiver.c:576
+#: replication/libpqwalreceiver/libpqwalreceiver.c:582
+#, c-format
+msgid "could not receive data from WAL stream: %s"
+msgstr "WAL 스트림에서 자료 받기 실패: %s"
+
+#: replication/libpqwalreceiver/libpqwalreceiver.c:601
+#, c-format
+msgid "could not send data to WAL stream: %s"
+msgstr "WAL 스트림에 데이터를 보낼 수 없음: %s"
+
+#: replication/logical/logical.c:83
+#, c-format
+msgid "logical decoding requires wal_level >= logical"
+msgstr "논리적 디코딩 기능은 wal_level 값이 logical 이상이어야 함"
+
+#: replication/logical/logical.c:88
+#, c-format
+msgid "logical decoding requires a database connection"
+msgstr "논리적 디코딩 기능은 데이터베이스 연결이 필요합니다"
+
+#: replication/logical/logical.c:106
+#, c-format
+msgid "logical decoding cannot be used while in recovery"
+msgstr "논리적 디코딩 기능은 복구 상태에서는 사용할 수 없음"
+
+#: replication/logical/logical.c:236 replication/logical/logical.c:348
+#, c-format
+msgid "cannot use physical replication slot for logical decoding"
+msgstr "논리적 디코딩에서는 물리적 복제 슬롯을 사용할 수 없음"
+
+#: replication/logical/logical.c:241 replication/logical/logical.c:353
+#, c-format
+msgid "replication slot \"%s\" was not created in this database"
+msgstr "\"%s\" 복제 슬롯이 이 데이터베이스 만들어져있지 않음"
+
+#: replication/logical/logical.c:248
+#, c-format
+msgid ""
+"cannot create logical replication slot in transaction that has performed "
+"writes"
+msgstr ""
+"자료 변경 작업이 있는 트랜잭션 안에서는 논리적 복제 슬롯을 만들 수 없음"
+
+#: replication/logical/logical.c:390
+#, c-format
+msgid "starting logical decoding for slot \"%s\""
+msgstr "\"%s\" 이름의 논리적 복제 슬롯을 만드는 중"
+
+#: replication/logical/logical.c:392
+#, c-format
+msgid "streaming transactions committing after %X/%X, reading WAL from %X/%X"
+msgstr ""
+
+#: replication/logical/logical.c:527
+#, c-format
+msgid ""
+"slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X"
+msgstr ""
+
+#: replication/logical/logical.c:534
+#, c-format
+msgid "slot \"%s\", output plugin \"%s\", in the %s callback"
+msgstr ""
+
+#: replication/logical/logicalfuncs.c:113 replication/slotfuncs.c:32
+#, c-format
+msgid "must be superuser or replication role to use replication slots"
+msgstr ""
+"복제 슬롯은 superuser 또는 replication 롤 옵션을 포함한 사용자만 사용할 수 있"
+"습니다."
+
+#: replication/logical/logicalfuncs.c:152
+#, c-format
+msgid "slot name must not be null"
+msgstr "슬롯 이름으로 null 값을 사용할 수 없습니다"
+
+#: replication/logical/logicalfuncs.c:168
+#, c-format
+msgid "options array must not be null"
+msgstr "옵션 배열은 null 값을 사용할 수 없습니다."
+
+#: replication/logical/logicalfuncs.c:199
+#, c-format
+msgid "array must be one-dimensional"
+msgstr "배열은 일차원 배열이어야합니다"
+
+#: replication/logical/logicalfuncs.c:205
+#, c-format
+msgid "array must not contain nulls"
+msgstr "배열에는 null 값을 포함할 수 없습니다"
+
+#: replication/logical/logicalfuncs.c:221 utils/adt/json.c:2277
+#: utils/adt/jsonb.c:1356
+#, c-format
+msgid "array must have even number of elements"
+msgstr "배열은 그 요소의 개수가 짝수여야 함"
+
+#: replication/logical/logicalfuncs.c:264
+#, c-format
+msgid ""
+"logical decoding output plugin \"%s\" produces binary output, but function "
+"\"%s\" expects textual data"
+msgstr ""
+
+#: replication/logical/origin.c:181
+#, c-format
+msgid "only superusers can query or manipulate replication origins"
+msgstr "슈퍼유저만 복제 원본에 대한 쿼리나, 관리를 할 수 있습니다."
+
+#: replication/logical/origin.c:186
+#, c-format
+msgid ""
+"cannot query or manipulate replication origin when max_replication_slots = 0"
+msgstr ""
+
+#: replication/logical/origin.c:191
+#, c-format
+msgid "cannot manipulate replication origins during recovery"
+msgstr ""
+
+#: replication/logical/origin.c:316
+#, c-format
+msgid "could not find free replication origin OID"
+msgstr "비어있는 복제 오리진 OID를 찾을 수 없음"
+
+#: replication/logical/origin.c:353
+#, c-format
+msgid "could not drop replication origin with OID %d, in use by PID %d"
+msgstr ""
+
+#: replication/logical/origin.c:671
+#, c-format
+msgid "replication checkpoint has wrong magic %u instead of %u"
+msgstr "복제 체크포인트의 잘못된 매직 번호: %u, 기대값: %u"
+
+#: replication/logical/origin.c:703
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu"
+
+#: replication/logical/origin.c:712
+#, c-format
+msgid "could not find free replication state, increase max_replication_slots"
+msgstr ""
+"사용 가능한 복제 슬롯이 부족합니다. max_replication_slots 값을 늘리세요"
+
+#: replication/logical/origin.c:730
+#, c-format
+msgid "replication slot checkpoint has wrong checksum %u, expected %u"
+msgstr "복제 슬롯 체크포인트의 체크섬 값이 잘못됨: %u, 기대값 %u"
+
+#: replication/logical/origin.c:854
+#, c-format
+msgid "replication origin with OID %d is already active for PID %d"
+msgstr ""
+
+#: replication/logical/origin.c:865 replication/logical/origin.c:1045
+#, c-format
+msgid ""
+"could not find free replication state slot for replication origin with OID %u"
+msgstr "%u OID 복제 오리진을 위한 여유 복제 슬롯을 찾을 수 없음"
+
+#: replication/logical/origin.c:867 replication/logical/origin.c:1047
+#: replication/slot.c:1299
+#, c-format
+msgid "Increase max_replication_slots and try again."
+msgstr "max_replication_slots 값을 늘린 후 다시 시도해 보세요"
+
+#: replication/logical/origin.c:1004
+#, c-format
+msgid "cannot setup replication origin when one is already setup"
+msgstr "하나가 이미 설정되어 더 이상 복제 오리진 설정을 할 수 없음"
+
+#: replication/logical/origin.c:1033
+#, c-format
+msgid "replication identifier %d is already active for PID %d"
+msgstr "%d번 복제 식별자가 %d PID에서 사용하고 있습니다."
+
+#: replication/logical/origin.c:1079 replication/logical/origin.c:1274
+#: replication/logical/origin.c:1294
+#, c-format
+msgid "no replication origin is configured"
+msgstr "복제 오리진 설정이 없습니다"
+
+#: replication/logical/reorderbuffer.c:2330
+#, c-format
+msgid "could not write to data file for XID %u: %m"
+msgstr "%u XID 내용을 데이터 파일에 쓸 수 없음: %m"
+
+#: replication/logical/reorderbuffer.c:2426
+#: replication/logical/reorderbuffer.c:2446
+#, c-format
+msgid "could not read from reorderbuffer spill file: %m"
+msgstr "reorderbuffer 처리용 파일에서 읽기 실패: %m"
+
+#: replication/logical/reorderbuffer.c:2430
+#: replication/logical/reorderbuffer.c:2450
+#, c-format
+msgid ""
+"could not read from reorderbuffer spill file: read %d instead of %u bytes"
+msgstr ""
+"reorderbuffer 처리용 파일에서 읽기 실패: %d 바이트 읽음, 기대값 %u 바이트"
+
+#: replication/logical/reorderbuffer.c:3106
+#, c-format
+msgid "could not read from file \"%s\": read %d instead of %d bytes"
+msgstr "\"%s\" 파일에서 읽기 실패: %d 바이트 읽음, 기대값 %d 바이트"
+
+#: replication/logical/snapbuild.c:598
+#, c-format
+msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID"
+msgid_plural ""
+"exported logical decoding snapshot: \"%s\" with %u transaction IDs"
+msgstr[0] ""
+
+#: replication/logical/snapbuild.c:917 replication/logical/snapbuild.c:1282
+#: replication/logical/snapbuild.c:1813
+#, c-format
+msgid "logical decoding found consistent point at %X/%X"
+msgstr "논리적 디코딩 이어서 시작할 위치: %X/%X"
+
+#: replication/logical/snapbuild.c:919
+#, c-format
+msgid "Transaction ID %u finished; no more running transactions."
+msgstr "%u 트랜잭션 ID 마침; 더 처리할 트랜잭션이 없음"
+
+#: replication/logical/snapbuild.c:1284
+#, c-format
+msgid "There are no running transactions."
+msgstr "실행할 트랜잭션이 없음"
+
+#: replication/logical/snapbuild.c:1346
+#, c-format
+msgid "logical decoding found initial starting point at %X/%X"
+msgstr "논리적 디코딩 시작 위치: %X/%X"
+
+#: replication/logical/snapbuild.c:1348
+#, c-format
+msgid "%u transaction needs to finish."
+msgid_plural "%u transactions need to finish."
+msgstr[0] "마치려면 %u개의 트랜잭션이 필요합니다."
+
+#: replication/logical/snapbuild.c:1687 replication/logical/snapbuild.c:1713
+#: replication/logical/snapbuild.c:1727 replication/logical/snapbuild.c:1741
+#, c-format
+msgid "could not read file \"%s\", read %d of %d: %m"
+msgstr "\"%s\" 파일을 읽을 수 없음, %d/%d 바이트 읽음: %m"
+
+#: replication/logical/snapbuild.c:1693
+#, c-format
+msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u"
+msgstr "\"%s\" snapbuild 상태 파일의 매직 번호가 이상함: 현재값 %u, 기대값 %u"
+
+#: replication/logical/snapbuild.c:1698
+#, c-format
+msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u"
+msgstr "\"%s\" snapbuild 상태 파일의 버전이 이상함: 현재값 %u, 기대값 %u"
+
+#: replication/logical/snapbuild.c:1754
+#, c-format
+msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u"
+msgstr ""
+
+#: replication/logical/snapbuild.c:1815
+#, c-format
+msgid "Logical decoding will begin using saved snapshot."
+msgstr ""
+
+#: replication/logical/snapbuild.c:1888
+#, c-format
+msgid "could not parse file name \"%s\""
+msgstr "\"%s\" 파일 이름을 분석할 수 없음"
+
+#: replication/slot.c:183
+#, c-format
+msgid "replication slot name \"%s\" is too short"
+msgstr "\"%s\" 복제 슬롯 이름이 너무 짧음"
+
+#: replication/slot.c:192
+#, c-format
+msgid "replication slot name \"%s\" is too long"
+msgstr "\"%s\" 복제 슬롯 이름이 너무 긺"
+
+#: replication/slot.c:205
+#, c-format
+msgid "replication slot name \"%s\" contains invalid character"
+msgstr "\"%s\" 복제 슬롯 이름에 사용할 수 없는 문자가 있음"
+
+#: replication/slot.c:207
+#, c-format
+msgid ""
+"Replication slot names may only contain lower case letters, numbers, and the "
+"underscore character."
+msgstr ""
+"복제 슬롯 이름으로 사용할 수 있는 문자는 영문 소문자, 숫자, 밑줄(_) 문자입니"
+"다."
+
+#: replication/slot.c:254
+#, c-format
+msgid "replication slot \"%s\" already exists"
+msgstr "\"%s\" 이름의 복제 슬롯이 이미 있습니다."
+
+#: replication/slot.c:264
+#, c-format
+msgid "all replication slots are in use"
+msgstr "모든 복제 슬롯이 사용 중입니다."
+
+#: replication/slot.c:265
+#, c-format
+msgid "Free one or increase max_replication_slots."
+msgstr "하나를 비우든지, max_replication_slots 설정값을 늘리세요."
+
+#: replication/slot.c:361
+#, c-format
+msgid "replication slot \"%s\" does not exist"
+msgstr "\"%s\" 이름의 복제 슬롯이 없습니다"
+
+#: replication/slot.c:365
+#, c-format
+msgid "replication slot \"%s\" is active for PID %d"
+msgstr "\"%s\" 이름의 복제 슬롯을 %d PID 프로세스가 사용중입니다."
+
+#: replication/slot.c:511 replication/slot.c:923 replication/slot.c:1260
+#, c-format
+msgid "could not remove directory \"%s\""
+msgstr "\"%s\" 디렉터리를 삭제할 수 없음"
+
+#: replication/slot.c:772
+#, c-format
+msgid "replication slots can only be used if max_replication_slots > 0"
+msgstr "복제 슬롯은 max_replication_slots > 0 상태에서 사용될 수 있습니다."
+
+#: replication/slot.c:777
+#, c-format
+msgid "replication slots can only be used if wal_level >= replica"
+msgstr "복제 슬롯은 wal_level >= replica 상태에서 사용될 수 있습니다."
+
+#: replication/slot.c:1192 replication/slot.c:1230
+#, c-format
+msgid "could not read file \"%s\", read %d of %u: %m"
+msgstr "\"%s\" 파일을 읽을 수 없음, %d/%u 바이트 읽음: %m"
+
+#: replication/slot.c:1201
+#, c-format
+msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u"
+msgstr "\"%s\" 복제 슬롯 파일의 매직 번호가 이상합니다: 현재값 %u, 기대값 %u"
+
+#: replication/slot.c:1208
+#, c-format
+msgid "replication slot file \"%s\" has unsupported version %u"
+msgstr "\"%s\" 복제 슬롯 파일은 지원하지 않는 %u 버전 파일입니다"
+
+#: replication/slot.c:1215
+#, c-format
+msgid "replication slot file \"%s\" has corrupted length %u"
+msgstr "\"%s\" 복제 슬롯 파일이 %u 길이로 손상되었습니다."
+
+#: replication/slot.c:1245
+#, c-format
+msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u"
+msgstr "\"%s\" 복제 슬롯 파일의 체크섬 값이 이상합니다: 현재값 %u, 기대값 %u"
+
+#: replication/slot.c:1298
+#, c-format
+msgid "too many replication slots active before shutdown"
+msgstr "서버 중지 전에 너무 많은 복제 슬롯이 활성화 상태입니다"
+
+#: replication/syncrep.c:221
+#, c-format
+msgid ""
+"canceling the wait for synchronous replication and terminating connection "
+"due to administrator command"
+msgstr ""
+"관리자 명령에 의해 동기식 복제의 대기 작업과 접속 끊기 작업을 취소합니다."
+
+#: replication/syncrep.c:222 replication/syncrep.c:239
+#, c-format
+msgid ""
+"The transaction has already committed locally, but might not have been "
+"replicated to the standby."
+msgstr ""
+"주 서버에서는 이 트랜잭션이 커밋되었지만, 복제용 대기 서버에서는 아직 커밋 되"
+"지 않았을 가능성이 있습니다."
+
+#: replication/syncrep.c:238
+#, c-format
+msgid "canceling wait for synchronous replication due to user request"
+msgstr "사용자 요청에 의해 동기식 복제 작업을 취소합니다."
+
+#: replication/syncrep.c:368
+#, c-format
+msgid "standby \"%s\" now has synchronous standby priority %u"
+msgstr "\"%s\" 대기 서버의 동기식 복제 우선순위가 %u 입니다"
+
+#: replication/syncrep.c:428
+#, c-format
+msgid "standby \"%s\" is now a synchronous standby with priority %u"
+msgstr "\"%s\" 대기 서버의 동기식 복제 우선순위가 %u 로 변경되었습니다."
+
+#: replication/syncrep.c:921
+#, c-format
+msgid "synchronous_standby_names parser failed"
+msgstr "synchronous_standby_names 값을 분석할 수 없음"
+
+#: replication/syncrep.c:927
+#, c-format
+msgid "number of synchronous standbys (%d) must be greater than zero"
+msgstr "동기식 대기 서버 수 (%d)는 0보다 커야 합니다."
+
+#: replication/walreceiver.c:173
+#, c-format
+msgid "terminating walreceiver process due to administrator command"
+msgstr "관리자 명령으로 인해 WAL 수신기를 종료합니다."
+
+#: replication/walreceiver.c:344
+#, c-format
+msgid "highest timeline %u of the primary is behind recovery timeline %u"
+msgstr ""
+"주 서버의 제일 최신의 타임라인은 %u 인데, 복구 타임라인 %u 보다 옛것입니다"
+
+#: replication/walreceiver.c:377
+#, c-format
+msgid "started streaming WAL from primary at %X/%X on timeline %u"
+msgstr "주 서버의 WAL 스트리밍 시작 위치: %X/%X (타임라인 %u)"
+
+#: replication/walreceiver.c:382
+#, c-format
+msgid "restarted WAL streaming at %X/%X on timeline %u"
+msgstr "WAL 스트리밍 재시작 위치: %X/%X (타임라인 %u)"
+
+#: replication/walreceiver.c:411
+#, c-format
+msgid "cannot continue WAL streaming, recovery has already ended"
+msgstr "WAL 스트리밍 계속할 수 없음, 복구가 이미 종료됨"
+
+#: replication/walreceiver.c:448
+#, c-format
+msgid "replication terminated by primary server"
+msgstr "주 서버에 의해서 복제가 끝남"
+
+#: replication/walreceiver.c:449
+#, c-format
+msgid "End of WAL reached on timeline %u at %X/%X."
+msgstr "타임라인 %u, 위치 %X/%X 에서 WAL 끝에 도달함"
+
+#: replication/walreceiver.c:543
+#, c-format
+msgid "terminating walreceiver due to timeout"
+msgstr "시간 제한으로 wal 수신기를 중지합니다."
+
+#: replication/walreceiver.c:583
+#, c-format
+msgid "primary server contains no more WAL on requested timeline %u"
+msgstr "주 서버에는 요청 받은 %u 타임라인의 WAL가 더 이상 없습니다."
+
+#: replication/walreceiver.c:598 replication/walreceiver.c:957
+#, c-format
+msgid "could not close log segment %s: %m"
+msgstr "%s 로그 조각 파일을 닫을 수 없음: %m"
+
+#: replication/walreceiver.c:722
+#, c-format
+msgid "fetching timeline history file for timeline %u from primary server"
+msgstr "주 서버에서 %u 타임라인용 타임라인 내역 파일을 가져옵니다."
+
+#: replication/walreceiver.c:1011
+#, c-format
+msgid "could not write to log segment %s at offset %u, length %lu: %m"
+msgstr "%s 로그 조각 파일 쓰기 실패: 위치 %u, 길이 %lu: %m"
+
+#: replication/walsender.c:485
+#, c-format
+msgid "could not seek to beginning of file \"%s\": %m"
+msgstr "\"%s\" 파일에서 시작 위치를 찾을 수 없음: %m"
+
+#: replication/walsender.c:536
+#, c-format
+msgid "cannot use a logical replication slot for physical replication"
+msgstr "물리적 복제에서 논리적 복제 슬롯을 사용할 수 없음"
+
+#: replication/walsender.c:599
+#, c-format
+msgid ""
+"requested starting point %X/%X on timeline %u is not in this server's history"
+msgstr "요청된 %X/%X 시작 위치(타임라인 %u)가 이 서버 내역에 없습니다."
+
+#: replication/walsender.c:603
+#, c-format
+msgid "This server's history forked from timeline %u at %X/%X."
+msgstr "이 서버의 시작 위치: 타임라인 %u, 위치 %X/%X"
+
+#: replication/walsender.c:648
+#, c-format
+msgid ""
+"requested starting point %X/%X is ahead of the WAL flush position of this "
+"server %X/%X"
+msgstr ""
+
+#: replication/walsender.c:972
+#, c-format
+msgid "terminating walsender process after promotion"
+msgstr "운영전환 뒤 wal 송신기 프로세스를 중지합니다."
+
+#: replication/walsender.c:1298
+#, c-format
+msgid "received replication command: %s"
+msgstr "수신된 복제 명령: %s"
+
+#: replication/walsender.c:1397 replication/walsender.c:1413
+#, c-format
+msgid "unexpected EOF on standby connection"
+msgstr "대기 서버 연결에서 예상치 못한 EOF 발견함"
+
+#: replication/walsender.c:1427
+#, c-format
+msgid "unexpected standby message type \"%c\", after receiving CopyDone"
+msgstr ""
+
+#: replication/walsender.c:1465
+#, c-format
+msgid "invalid standby message type \"%c\""
+msgstr "잘못된 대기 서버 메시지 형태 \"%c\""
+
+#: replication/walsender.c:1506
+#, c-format
+msgid "unexpected message type \"%c\""
+msgstr "예상치 못한 메시지 형태: \"%c\""
+
+#: replication/walsender.c:1790
+#, c-format
+msgid "terminating walsender process due to replication timeout"
+msgstr "복제 시간 제한으로 wal 송신기 프로세스를 종료합니다."
+
+#: replication/walsender.c:1875
+#, c-format
+msgid "standby \"%s\" has now caught up with primary"
+msgstr "\"%s\" 대기 서버가 운영 서버로 전환합니다"
+
+#: replication/walsender.c:1978
+#, c-format
+msgid ""
+"number of requested standby connections exceeds max_wal_senders (currently "
+"%d)"
+msgstr "대기 서버 연결 수가 max_wal_senders 설정값(현재 %d)을 초과했습니다"
+
+#: rewrite/rewriteDefine.c:112 rewrite/rewriteDefine.c:973
+#, c-format
+msgid "rule \"%s\" for relation \"%s\" already exists"
+msgstr "\"%s\" 이름의 룰(rule)이 \"%s\" 테이블에 이미 지정되어있습니다"
+
+#: rewrite/rewriteDefine.c:297
+#, c-format
+msgid "rule actions on OLD are not implemented"
+msgstr "OLD에 대한 실행 룰(rule)은 아직 구현되지 않았습니다"
+
+#: rewrite/rewriteDefine.c:298
+#, c-format
+msgid "Use views or triggers instead."
+msgstr "대신에 뷰나 트리거를 사용하십시오."
+
+#: rewrite/rewriteDefine.c:302
+#, c-format
+msgid "rule actions on NEW are not implemented"
+msgstr "NEW에 대한 실행 룰(rule)은 아직 구현되지 않았습니다"
+
+#: rewrite/rewriteDefine.c:303
+#, c-format
+msgid "Use triggers instead."
+msgstr "대신에 트리거를 사용하십시오."
+
+#: rewrite/rewriteDefine.c:316
+#, c-format
+msgid "INSTEAD NOTHING rules on SELECT are not implemented"
+msgstr "SELECT 에서 INSTEAD NOTHING 룰(rule)은 구현되지 않았습니다"
+
+#: rewrite/rewriteDefine.c:317
+#, c-format
+msgid "Use views instead."
+msgstr "대신에 뷰를 사용하십시오."
+
+#: rewrite/rewriteDefine.c:325
+#, c-format
+msgid "multiple actions for rules on SELECT are not implemented"
+msgstr "SELECT에 대한 다중 실행 룰(rule)은 구현되지 않았습니다"
+
+#: rewrite/rewriteDefine.c:336
+#, c-format
+msgid "rules on SELECT must have action INSTEAD SELECT"
+msgstr ""
+"SELECT에 대한 룰(rule)은 그 지정에 INSTEAD SELECT 실행규칙을 지정해야만합니다"
+
+#: rewrite/rewriteDefine.c:344
+#, c-format
+msgid "rules on SELECT must not contain data-modifying statements in WITH"
+msgstr ""
+
+#: rewrite/rewriteDefine.c:352
+#, c-format
+msgid "event qualifications are not implemented for rules on SELECT"
+msgstr ""
+"이벤트 자격(event qualifications)은 SELECT 룰(rule)에서 구현되지 않았습니다"
+
+#: rewrite/rewriteDefine.c:379
+#, c-format
+msgid "\"%s\" is already a view"
+msgstr "\"%s\" 이름의 뷰가 이미 있습니다"
+
+#: rewrite/rewriteDefine.c:403
+#, c-format
+msgid "view rule for \"%s\" must be named \"%s\""
+msgstr "\"%s\" 위한 뷰 룰(view rule)의 이름은 \"%s\" 여야만합니다"
+
+#: rewrite/rewriteDefine.c:432
+#, c-format
+msgid "could not convert table \"%s\" to a view because it is not empty"
+msgstr "\"%s\" 테이블에 자료가 있기 때문에, 테이블을 뷰로 변환할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:440
+#, c-format
+msgid "could not convert table \"%s\" to a view because it has triggers"
+msgstr "\"%s\" 테이블에 트리거가 포함되어 있어 뷰로 변환할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:442
+#, c-format
+msgid ""
+"In particular, the table cannot be involved in any foreign key relationships."
+msgstr "특히 테이블은 참조키 관계에 관련될 수 없습니다."
+
+#: rewrite/rewriteDefine.c:447
+#, c-format
+msgid "could not convert table \"%s\" to a view because it has indexes"
+msgstr "\"%s\" 테이블에 인덱스가 포함되어 있어 뷰로 변환할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:453
+#, c-format
+msgid "could not convert table \"%s\" to a view because it has child tables"
+msgstr "\"%s\" 테이블을 상속 받는 테이블이 있어 뷰로 변활할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:459
+#, c-format
+msgid ""
+"could not convert table \"%s\" to a view because it has row security enabled"
+msgstr ""
+"로우단위 보안 기능을 사용하고 있어 \"%s\" 테이블을 뷰로 변환할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:465
+#, c-format
+msgid ""
+"could not convert table \"%s\" to a view because it has row security policies"
+msgstr "로우단위 보안 설정이 되어 있어 \"%s\" 테이블을 뷰로 변환할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:492
+#, c-format
+msgid "cannot have multiple RETURNING lists in a rule"
+msgstr "하나의 rule에서 여러개의 RETURNING 목록을 지정할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:497
+#, c-format
+msgid "RETURNING lists are not supported in conditional rules"
+msgstr "RETURNING 목록은 conditional rule에서는 지원하지 않습니다"
+
+#: rewrite/rewriteDefine.c:501
+#, c-format
+msgid "RETURNING lists are not supported in non-INSTEAD rules"
+msgstr "RETURNING 목록은 non-INSTEAD rule에서는 지원하지 않습니다"
+
+#: rewrite/rewriteDefine.c:667
+#, c-format
+msgid "SELECT rule's target list has too many entries"
+msgstr "SELECT 룰(rule)의 대상 목록이 너무 많은 엔트리를 가지고 있습니다"
+
+#: rewrite/rewriteDefine.c:668
+#, c-format
+msgid "RETURNING list has too many entries"
+msgstr "RETURNING 목록이 너무 많은 항목를 가지고 있습니다"
+
+#: rewrite/rewriteDefine.c:695
+#, c-format
+msgid "cannot convert relation containing dropped columns to view"
+msgstr "뷰에서 삭제된 열을 포함하고 있는 릴레이션을 변환할 수 없습니다"
+
+#: rewrite/rewriteDefine.c:696
+#, c-format
+msgid ""
+"cannot create a RETURNING list for a relation containing dropped columns"
+msgstr ""
+"릴레이션에 삭제된 열을 포함하고 있는 RETURNING 목록을 만들 수 없습니다."
+
+#: rewrite/rewriteDefine.c:702
+#, c-format
+msgid ""
+"SELECT rule's target entry %d has different column name from column \"%s\""
+msgstr "SELECT 룰(rule)의 대상 엔트리 번호가(%d)가 \"%s\" 칼럼 이름과 틀립니다"
+
+#: rewrite/rewriteDefine.c:704
+#, c-format
+msgid "SELECT target entry is named \"%s\"."
+msgstr "SELECT 대상 엔트리 이름은 \"%s\" 입니다."
+
+#: rewrite/rewriteDefine.c:713
+#, c-format
+msgid "SELECT rule's target entry %d has different type from column \"%s\""
+msgstr "SELECT 룰(rule)의 대상 엔트리 번호(%d)가 \"%s\" 칼럼 자료형과 틀립니다"
+
+#: rewrite/rewriteDefine.c:715
+#, c-format
+msgid "RETURNING list's entry %d has different type from column \"%s\""
+msgstr "RETURNING 목록의 %d번째 항목의 자료형이 \"%s\" 칼럼 자료형과 틀립니다"
+
+#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:742
+#, c-format
+msgid "SELECT target entry has type %s, but column has type %s."
+msgstr "SELECT 대상 엔트리 자료형은 %s 형이지만, 칼럼 자료형은 %s 형입니다."
+
+#: rewrite/rewriteDefine.c:721 rewrite/rewriteDefine.c:746
+#, c-format
+msgid "RETURNING list entry has type %s, but column has type %s."
+msgstr "RETURNING 목록은 %s 자료형이지만, 칼럼 자료형은 %s 형입니다."
+
+#: rewrite/rewriteDefine.c:737
+#, c-format
+msgid "SELECT rule's target entry %d has different size from column \"%s\""
+msgstr "SELECT 룰(rule)의 대상 엔트리 번호(%d)가 \"%s\" 칼럼 크기와 틀립니다"
+
+#: rewrite/rewriteDefine.c:739
+#, c-format
+msgid "RETURNING list's entry %d has different size from column \"%s\""
+msgstr "RETURNING 목록의 %d번째 항목의 크기가 \"%s\" 칼럼 크기와 틀립니다"
+
+#: rewrite/rewriteDefine.c:756
+#, c-format
+msgid "SELECT rule's target list has too few entries"
+msgstr "SELECT 룰(rule)의 대상 목록이 너무 적은 엔트리를 가지고 있습니다"
+
+#: rewrite/rewriteDefine.c:757
+#, c-format
+msgid "RETURNING list has too few entries"
+msgstr "RETURNING 목록에 너무 적은 항목이 있습니다"
+
+#: rewrite/rewriteDefine.c:849 rewrite/rewriteDefine.c:964
+#: rewrite/rewriteSupport.c:112
+#, c-format
+msgid "rule \"%s\" for relation \"%s\" does not exist"
+msgstr " \"%s\" 룰(rule)이 \"%s\" 관계(relation)에 지정된 것이 없음"
+
+#: rewrite/rewriteDefine.c:983
+#, c-format
+msgid "renaming an ON SELECT rule is not allowed"
+msgstr "ON SELECT 룰의 이름 바꾸기는 허용하지 않습니다"
+
+#: rewrite/rewriteHandler.c:528
+#, c-format
+msgid ""
+"WITH query name \"%s\" appears in both a rule action and the query being "
+"rewritten"
+msgstr ""
+
+#: rewrite/rewriteHandler.c:588
+#, c-format
+msgid "cannot have RETURNING lists in multiple rules"
+msgstr "multiple rule에 RETURNING 목록을 지정할 수 없습니다"
+
+#: rewrite/rewriteHandler.c:928 rewrite/rewriteHandler.c:946
+#, c-format
+msgid "multiple assignments to same column \"%s\""
+msgstr "같은 \"%s\" 열에 지정값(assignment)이 중복되었습니다"
+
+#: rewrite/rewriteHandler.c:1721 rewrite/rewriteHandler.c:3331
+#, c-format
+msgid "infinite recursion detected in rules for relation \"%s\""
+msgstr ""
+"\"%s\" 릴레이션(relation)에서 지정된 룰에서 잘못된 재귀호출이 발견되었습니다"
+
+#: rewrite/rewriteHandler.c:1806
+#, c-format
+msgid "infinite recursion detected in policy for relation \"%s\""
+msgstr "\"%s\" 릴레이션의 정책에서 무한 재귀 호출이 발견 됨"
+
+#: rewrite/rewriteHandler.c:2123
+msgid "Junk view columns are not updatable."
+msgstr "정크 뷰 칼럼은 업데이트할 수 없습니다."
+
+#: rewrite/rewriteHandler.c:2128
+msgid ""
+"View columns that are not columns of their base relation are not updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2131
+msgid "View columns that refer to system columns are not updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2134
+msgid "View columns that return whole-row references are not updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2192
+msgid "Views containing DISTINCT are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2195
+msgid "Views containing GROUP BY are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2198
+msgid "Views containing HAVING are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2201
+msgid ""
+"Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2204
+msgid "Views containing WITH are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2207
+msgid "Views containing LIMIT or OFFSET are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2219
+msgid "Views that return aggregate functions are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2222
+msgid "Views that return window functions are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2225
+msgid ""
+"Views that return set-returning functions are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2232 rewrite/rewriteHandler.c:2236
+#: rewrite/rewriteHandler.c:2243
+msgid ""
+"Views that do not select from a single table or view are not automatically "
+"updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2246
+msgid "Views containing TABLESAMPLE are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2270
+msgid "Views that have no updatable columns are not automatically updatable."
+msgstr ""
+
+#: rewrite/rewriteHandler.c:2724
+#, c-format
+msgid "cannot insert into column \"%s\" of view \"%s\""
+msgstr "\"%s\" 칼럼 (해당 뷰: \"%s\")에 자료를 입력할 수 없습니다"
+
+#: rewrite/rewriteHandler.c:2732
+#, c-format
+msgid "cannot update column \"%s\" of view \"%s\""
+msgstr "\"%s\" 칼럼 (해당 뷰: \"%s\")에 자료를 갱신할 수 없습니다"
+
+#: rewrite/rewriteHandler.c:3130
+#, c-format
+msgid ""
+"DO INSTEAD NOTHING rules are not supported for data-modifying statements in "
+"WITH"
+msgstr ""
+
+#: rewrite/rewriteHandler.c:3144
+#, c-format
+msgid ""
+"conditional DO INSTEAD rules are not supported for data-modifying statements "
+"in WITH"
+msgstr ""
+
+#: rewrite/rewriteHandler.c:3148
+#, c-format
+msgid "DO ALSO rules are not supported for data-modifying statements in WITH"
+msgstr ""
+
+#: rewrite/rewriteHandler.c:3153
+#, c-format
+msgid ""
+"multi-statement DO INSTEAD rules are not supported for data-modifying "
+"statements in WITH"
+msgstr ""
+
+#: rewrite/rewriteHandler.c:3368
+#, c-format
+msgid "cannot perform INSERT RETURNING on relation \"%s\""
+msgstr "\"%s\" 릴레이션에서 INSERT RETURNING 관련을 구성할 수 없음"
+
+#: rewrite/rewriteHandler.c:3370
+#, c-format
+msgid ""
+"You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause."
+msgstr ""
+"RETURNING 절에서는 무조건 ON INSERT DO INSTEAD 속성으로 rule이 사용되어야합니"
+"다."
+
+#: rewrite/rewriteHandler.c:3375
+#, c-format
+msgid "cannot perform UPDATE RETURNING on relation \"%s\""
+msgstr "\"%s\" 릴레이션에서 UPDATE RETURNING 관련을 구성할 수 없습니다."
+
+#: rewrite/rewriteHandler.c:3377
+#, c-format
+msgid ""
+"You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause."
+msgstr ""
+"RETURNING 절에서는 무조건 ON UPDATE DO INSTEAD 속성으로 rule이 사용되어야합니"
+"다."
+
+#: rewrite/rewriteHandler.c:3382
+#, c-format
+msgid "cannot perform DELETE RETURNING on relation \"%s\""
+msgstr "\"%s\" 릴레이션에서 DELETE RETURNING 관련을 구성할 수 없습니다."
+
+#: rewrite/rewriteHandler.c:3384
+#, c-format
+msgid ""
+"You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause."
+msgstr ""
+"TURNING 절에서는 무조건 ON DELETE DO INSTEAD 속성으로 rule이 사용되어야합니다"
+
+#: rewrite/rewriteHandler.c:3402
+#, c-format
+msgid ""
+"INSERT with ON CONFLICT clause cannot be used with table that has INSERT or "
+"UPDATE rules"
+msgstr ""
+
+#: rewrite/rewriteHandler.c:3459
+#, c-format
+msgid ""
+"WITH cannot be used in a query that is rewritten by rules into multiple "
+"queries"
+msgstr ""
+
+#: rewrite/rewriteManip.c:1003
+#, c-format
+msgid "conditional utility statements are not implemented"
+msgstr ""
+"조건 유틸리티 명령 구문(conditional utility statement)은 구현되어있지 않습니"
+"다"
+
+#: rewrite/rewriteManip.c:1169
+#, c-format
+msgid "WHERE CURRENT OF on a view is not implemented"
+msgstr "뷰에 대한 WHERE CURRENT OF 구문이 구현되지 않음"
+
+#: rewrite/rewriteManip.c:1434
+#, c-format
+msgid ""
+"NEW variables in ON UPDATE rules cannot reference columns that are part of a "
+"multiple assignment in the subject UPDATE command"
+msgstr ""
+
+#: rewrite/rewriteSupport.c:154
+#, c-format
+msgid "rule \"%s\" does not exist"
+msgstr "\"%s\" 룰(rule) 없음"
+
+#: rewrite/rewriteSupport.c:167
+#, c-format
+msgid "there are multiple rules named \"%s\""
+msgstr "\"%s\" 이름의 룰(rule)이 여러개 있습니다"
+
+#: rewrite/rewriteSupport.c:168
+#, c-format
+msgid "Specify a relation name as well as a rule name."
+msgstr "룰(rule) 이름과 함께 릴레이션(relation) 이름도 지정하십시오"
+
+#: snowball/dict_snowball.c:177
+#, c-format
+msgid "no Snowball stemmer available for language \"%s\" and encoding \"%s\""
+msgstr "\"%s\" 언어 및 \"%s\" 인코딩에 사용 가능한 Snowball stemmer가 없음"
+
+#: snowball/dict_snowball.c:200 tsearch/dict_ispell.c:73
+#: tsearch/dict_simple.c:48
+#, c-format
+msgid "multiple StopWords parameters"
+msgstr "StopWords 매개 변수가 여러 개 있음"
+
+#: snowball/dict_snowball.c:209
+#, c-format
+msgid "multiple Language parameters"
+msgstr "여러 개의 언어 매개 변수가 있음"
+
+#: snowball/dict_snowball.c:216
+#, c-format
+msgid "unrecognized Snowball parameter: \"%s\""
+msgstr "인식할 수 없는 Snowball 매개 변수: \"%s\""
+
+#: snowball/dict_snowball.c:224
+#, c-format
+msgid "missing Language parameter"
+msgstr "Language 매개 변수가 누락됨"
+
+#: storage/buffer/bufmgr.c:544 storage/buffer/bufmgr.c:657
+#, c-format
+msgid "cannot access temporary tables of other sessions"
+msgstr "다른 세션의 임시 테이블에 액세스할 수 없음"
+
+#: storage/buffer/bufmgr.c:807
+#, c-format
+msgid "unexpected data beyond EOF in block %u of relation %s"
+msgstr "%u 블록(해당 릴레이션: %s)에 EOF 범위를 넘는 예기치 않은 데이터가 있음"
+
+#: storage/buffer/bufmgr.c:809
+#, c-format
+msgid ""
+"This has been seen to occur with buggy kernels; consider updating your "
+"system."
+msgstr "이 문제는 커널의 문제로 알려졌습니다. 시스템을 업데이트하십시오."
+
+#: storage/buffer/bufmgr.c:907
+#, c-format
+msgid "invalid page in block %u of relation %s; zeroing out page"
+msgstr ""
+"%u 블록(해당 릴레이션: %s)에 잘못된 페이지 헤더가 있음, 페이지를 삭제하는 중"
+
+#: storage/buffer/bufmgr.c:3952
+#, c-format
+msgid "could not write block %u of %s"
+msgstr "%u/%s 블록을 쓸 수 없음"
+
+#: storage/buffer/bufmgr.c:3954
+#, c-format
+msgid "Multiple failures --- write error might be permanent."
+msgstr "여러 번 실패 --- 쓰기 오류가 영구적일 수 있습니다."
+
+#: storage/buffer/bufmgr.c:3975 storage/buffer/bufmgr.c:3994
+#, c-format
+msgid "writing block %u of relation %s"
+msgstr "%u 블록(해당 릴레이션: %s)을 쓰는 중"
+
+#: storage/buffer/bufmgr.c:4295
+#, c-format
+msgid "snapshot too old"
+msgstr ""
+
+#: storage/buffer/localbuf.c:199
+#, c-format
+msgid "no empty local buffer available"
+msgstr "비어 있는 로컬 버퍼가 없습니다"
+
+#: storage/buffer/localbuf.c:427
+#, c-format
+msgid "cannot access temporary tables during a parallel operation"
+msgstr "병렬 작업 중에 임시 테이블에 액세스할 수 없음"
+
+#: storage/file/fd.c:443 storage/file/fd.c:515 storage/file/fd.c:551
+#, c-format
+msgid "could not flush dirty data: %m"
+msgstr "dirty 자료를 flush 할 수 없음: %m"
+
+#: storage/file/fd.c:473
+#, c-format
+msgid "could not determine dirty data size: %m"
+msgstr "dirty 자료 크기를 확인할 수 없음: %m"
+
+#: storage/file/fd.c:525
+#, c-format
+msgid "could not munmap() while flushing data: %m"
+msgstr "자료 flush 작업 도중 munmap() 호출 실패: %m"
+
+#: storage/file/fd.c:689
+#, c-format
+msgid "could not link file \"%s\" to \"%s\": %m"
+msgstr "\"%s\" 파일을 \"%s\" 파일로 링크할 수 없음: %m"
+
+#: storage/file/fd.c:783
+#, c-format
+msgid "getrlimit failed: %m"
+msgstr "getrlimit 실패: %m"
+
+#: storage/file/fd.c:873
+#, c-format
+msgid "insufficient file descriptors available to start server process"
+msgstr ""
+"서버 프로세스를 실행하기 위해서 열어야할 파일들을 못 열고 있습니다. 다른 프로"
+"그램에서 너무 많은 파일을 열어 두고 있습니다. 다른 프로그램들을 좀 닫고 다시 "
+"시도해 보십시오"
+
+#: storage/file/fd.c:874
+#, c-format
+msgid "System allows %d, we need at least %d."
+msgstr "시스템 허용치 %d, 서버 최소 허용치 %d."
+
+#: storage/file/fd.c:915 storage/file/fd.c:2078 storage/file/fd.c:2171
+#: storage/file/fd.c:2319
+#, c-format
+msgid "out of file descriptors: %m; release and retry"
+msgstr ""
+"열려 있는 파일이 너무 많습니다: %m; 다른 프로그램들을 좀 닫고 다시 시도해 보"
+"십시오"
+
+#: storage/file/fd.c:1520
+#, c-format
+msgid "temporary file: path \"%s\", size %lu"
+msgstr "임시 파일: 경로 \"%s\", 크기 %lu"
+
+#: storage/file/fd.c:1717
+#, c-format
+msgid "temporary file size exceeds temp_file_limit (%dkB)"
+msgstr "임시 파일 크기가 temp_file_limit (%dkB)를 초과했습니다"
+
+#: storage/file/fd.c:2054 storage/file/fd.c:2104
+#, c-format
+msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\""
+msgstr ""
+
+#: storage/file/fd.c:2144
+#, c-format
+msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\""
+msgstr ""
+
+#: storage/file/fd.c:2295
+#, c-format
+msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\""
+msgstr ""
+
+#: storage/file/fd.c:2381
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m"
+
+#: storage/ipc/dsm.c:363
+#, c-format
+msgid "dynamic shared memory control segment is corrupt"
+msgstr "동적 공유 메모리 제어 조각이 손상되었음"
+
+#: storage/ipc/dsm.c:410
+#, c-format
+msgid "dynamic shared memory is disabled"
+msgstr "동적 공유 메모리 기능이 비활성화 되어있음"
+
+#: storage/ipc/dsm.c:411
+#, c-format
+msgid "Set dynamic_shared_memory_type to a value other than \"none\"."
+msgstr "dynamic_shared_memory_type 설정값을 \"none\" 아닌 값으로 지정하세요."
+
+#: storage/ipc/dsm.c:431
+#, c-format
+msgid "dynamic shared memory control segment is not valid"
+msgstr "동적 공유 메모리 제어 조각이 타당하지 않음"
+
+#: storage/ipc/dsm.c:516
+#, c-format
+msgid "too many dynamic shared memory segments"
+msgstr "너무 많은 동적 공유 메모리 조각이 있음"
+
+#: storage/ipc/dsm_impl.c:261 storage/ipc/dsm_impl.c:361
+#: storage/ipc/dsm_impl.c:533 storage/ipc/dsm_impl.c:648
+#: storage/ipc/dsm_impl.c:819 storage/ipc/dsm_impl.c:961
+#, c-format
+msgid "could not unmap shared memory segment \"%s\": %m"
+msgstr "\"%s\" 공유 메모리 조각을 unmap 할 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:271 storage/ipc/dsm_impl.c:543
+#: storage/ipc/dsm_impl.c:658 storage/ipc/dsm_impl.c:829
+#, c-format
+msgid "could not remove shared memory segment \"%s\": %m"
+msgstr "\"%s\" 공유 메모리 조각을 삭제할 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:292 storage/ipc/dsm_impl.c:729
+#: storage/ipc/dsm_impl.c:843
+#, c-format
+msgid "could not open shared memory segment \"%s\": %m"
+msgstr "\"%s\" 공유 메모리 조각을 열 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:316 storage/ipc/dsm_impl.c:559
+#: storage/ipc/dsm_impl.c:774 storage/ipc/dsm_impl.c:867
+#, c-format
+msgid "could not stat shared memory segment \"%s\": %m"
+msgstr "\"%s\" 공유 메모리 조각 파일의 상태를 알 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:335 storage/ipc/dsm_impl.c:886
+#: storage/ipc/dsm_impl.c:934
+#, c-format
+msgid "could not resize shared memory segment \"%s\" to %zu bytes: %m"
+msgstr "\"%s\" 공유 메모리 조각 파일을 %zu 바이트로 크기 조절 할 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:385 storage/ipc/dsm_impl.c:580
+#: storage/ipc/dsm_impl.c:750 storage/ipc/dsm_impl.c:985
+#, c-format
+msgid "could not map shared memory segment \"%s\": %m"
+msgstr "\"%s\" 공유 메모리 조각을 map 할 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:515
+#, c-format
+msgid "could not get shared memory segment: %m"
+msgstr "공유 메모리 조각을 가져올 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:714
+#, c-format
+msgid "could not create shared memory segment \"%s\": %m"
+msgstr "\"%s\" 공유 메모리 조각을 만들 수 없음: %m"
+
+#: storage/ipc/dsm_impl.c:1026
+#, c-format
+msgid "could not duplicate handle for \"%s\": %m"
+msgstr "\"%s\" 용 헨들러를 이중화 할 수 없음: %m"
+
+#: storage/ipc/latch.c:778
+#, c-format
+msgid "epoll_ctl() failed: %m"
+msgstr "epoll_ctl() 실패: %m"
+
+#: storage/ipc/latch.c:1002
+#, c-format
+msgid "epoll_wait() failed: %m"
+msgstr "epoll_wait() 실패: %m"
+
+#: storage/ipc/latch.c:1122
+#, c-format
+msgid "poll() failed: %m"
+msgstr "poll() 실패: %m"
+
+#: storage/ipc/shm_toc.c:108 storage/ipc/shm_toc.c:189 storage/ipc/shmem.c:212
+#: storage/lmgr/lock.c:883 storage/lmgr/lock.c:917 storage/lmgr/lock.c:2682
+#: storage/lmgr/lock.c:4007 storage/lmgr/lock.c:4072 storage/lmgr/lock.c:4364
+#: storage/lmgr/predicate.c:2329 storage/lmgr/predicate.c:2344
+#: storage/lmgr/predicate.c:3736 storage/lmgr/predicate.c:4879
+#: storage/lmgr/proc.c:203 utils/hash/dynahash.c:1043
+#, c-format
+msgid "out of shared memory"
+msgstr "공유 메모리 부족"
+
+#: storage/ipc/shmem.c:370 storage/ipc/shmem.c:421
+#, c-format
+msgid ""
+"not enough shared memory for data structure \"%s\" (%zu bytes requested)"
+msgstr "\"%s\" 자료 구조체용 공유 메모리가 부족함 (%zu 바이트가 필요함)"
+
+#: storage/ipc/shmem.c:389
+#, c-format
+msgid "could not create ShmemIndex entry for data structure \"%s\""
+msgstr "\"%s\" 자료 구조체용 ShmemIndex 항목을 만들 수 없음"
+
+#: storage/ipc/shmem.c:404
+#, c-format
+msgid ""
+"ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, "
+"actual %zu"
+msgstr ""
+"\"%s\" 자료 구조체용 ShmemIndex 항목 크기가 잘못됨: 기대값 %zu, 현재값 %zu"
+
+#: storage/ipc/shmem.c:452 storage/ipc/shmem.c:471
+#, c-format
+msgid "requested shared memory size overflows size_t"
+msgstr "지정한 공유 메모리 사이즈가 size_t 크기를 초과했습니다"
+
+#: storage/ipc/standby.c:530 tcop/postgres.c:2976
+#, c-format
+msgid "canceling statement due to conflict with recovery"
+msgstr "복구 작업 중 충돌이 발생해 작업을 중지합니다."
+
+#: storage/ipc/standby.c:531 tcop/postgres.c:2263
+#, c-format
+msgid "User transaction caused buffer deadlock with recovery."
+msgstr "복구 작업 중 사용자 트랜잭션이 버퍼 데드락을 만들었습니다."
+
+#: storage/large_object/inv_api.c:203
+#, c-format
+msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d"
+msgstr ""
+
+#: storage/large_object/inv_api.c:284
+#, c-format
+msgid "invalid flags for opening a large object: %d"
+msgstr "대형 객체를 열기 위한 플래그가 잘못 됨: %d"
+
+#: storage/large_object/inv_api.c:436
+#, c-format
+msgid "invalid whence setting: %d"
+msgstr ""
+
+#: storage/large_object/inv_api.c:593
+#, c-format
+msgid "invalid large object write request size: %d"
+msgstr "유효하지 않은 대형 객체의 쓰기 요청된 크기: %d"
+
+#: storage/lmgr/deadlock.c:1109
+#, c-format
+msgid "Process %d waits for %s on %s; blocked by process %d."
+msgstr ""
+"%d 프로세스가 %s 상태로 지연되고 있음(해당 작업: %s); %d 프로세스에 의해 블록"
+"킹되었음"
+
+#: storage/lmgr/deadlock.c:1128
+#, c-format
+msgid "Process %d: %s"
+msgstr "프로세스 %d: %s"
+
+#: storage/lmgr/deadlock.c:1137
+#, c-format
+msgid "deadlock detected"
+msgstr "deadlock 발생했음"
+
+#: storage/lmgr/deadlock.c:1140
+#, c-format
+msgid "See server log for query details."
+msgstr "쿼리 상세 정보는 서버 로그를 참조하십시오."
+
+#: storage/lmgr/lmgr.c:719
+#, c-format
+msgid "while updating tuple (%u,%u) in relation \"%s\""
+msgstr "%u,%u 튜플(해당 릴레이션 \"%s\")을 갱신하는 중에 발생"
+
+#: storage/lmgr/lmgr.c:722
+#, c-format
+msgid "while deleting tuple (%u,%u) in relation \"%s\""
+msgstr "%u,%u 튜플(해당 릴레이션 \"%s\")을 삭제하는 중에 발생"
+
+#: storage/lmgr/lmgr.c:725
+#, c-format
+msgid "while locking tuple (%u,%u) in relation \"%s\""
+msgstr "%u,%u 튜플을 \"%s\" 릴레이션에서 잠그는 중에 발생"
+
+#: storage/lmgr/lmgr.c:728
+#, c-format
+msgid "while locking updated version (%u,%u) of tuple in relation \"%s\""
+msgstr "%u,%u 업데이트된 버전 튜플(해당 릴레이션 \"%s\")을 잠그는 중에 발생"
+
+#: storage/lmgr/lmgr.c:731
+#, c-format
+msgid "while inserting index tuple (%u,%u) in relation \"%s\""
+msgstr "%u,%u 튜플 인덱스(해당 릴레이션 \"%s\")를 삽입하는 중에 발생"
+
+#: storage/lmgr/lmgr.c:734
+#, c-format
+msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\""
+msgstr "%u,%u 튜플(해당 릴레이션: \"%s\")의 고유성을 검사하는 중에 발생"
+
+#: storage/lmgr/lmgr.c:737
+#, c-format
+msgid "while rechecking updated tuple (%u,%u) in relation \"%s\""
+msgstr "%u,%u 갱신된 튜플(해당 릴레이션: \"%s\")을 재확인하는 중에 발생"
+
+#: storage/lmgr/lmgr.c:740
+#, c-format
+msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\""
+msgstr ""
+"%u,%u 튜플(해당 릴레이션: \"%s\")의 제외 제약 조건을 검사하는 중에 발생"
+
+#: storage/lmgr/lmgr.c:960
+#, c-format
+msgid "relation %u of database %u"
+msgstr "릴레이션 %u, 데이터베이스 %u"
+
+#: storage/lmgr/lmgr.c:966
+#, c-format
+msgid "extension of relation %u of database %u"
+msgstr "%u 관계(%u 데이터베이스) 확장"
+
+#: storage/lmgr/lmgr.c:972
+#, c-format
+msgid "page %u of relation %u of database %u"
+msgstr "페이지 %u, 릴레이션 %u, 데이터베이스 %u"
+
+#: storage/lmgr/lmgr.c:979
+#, c-format
+msgid "tuple (%u,%u) of relation %u of database %u"
+msgstr "튜플 (%u,%u), 릴레이션 %u, 데이터베이스 %u"
+
+#: storage/lmgr/lmgr.c:987
+#, c-format
+msgid "transaction %u"
+msgstr "트랜잭션 %u"
+
+#: storage/lmgr/lmgr.c:992
+#, c-format
+msgid "virtual transaction %d/%u"
+msgstr "가상 트랜잭션 %d/%u"
+
+#: storage/lmgr/lmgr.c:998
+#, c-format
+msgid "speculative token %u of transaction %u"
+msgstr "%u 위험한 토큰, 대상 트랜잭션 %u"
+
+#: storage/lmgr/lmgr.c:1004
+#, c-format
+msgid "object %u of class %u of database %u"
+msgstr "객체 %u, 클래스 %u, 데이터베이스 %u"
+
+#: storage/lmgr/lmgr.c:1012
+#, c-format
+msgid "user lock [%u,%u,%u]"
+msgstr "user lock [%u,%u,%u]"
+
+#: storage/lmgr/lmgr.c:1019
+#, c-format
+msgid "advisory lock [%u,%u,%u,%u]"
+msgstr "advisory lock [%u,%u,%u,%u]"
+
+#: storage/lmgr/lmgr.c:1027
+#, c-format
+msgid "unrecognized locktag type %d"
+msgstr "알 수 없는 locktag 형태 %d"
+
+#: storage/lmgr/lock.c:732
+#, c-format
+msgid ""
+"cannot acquire lock mode %s on database objects while recovery is in progress"
+msgstr ""
+
+#: storage/lmgr/lock.c:734
+#, c-format
+msgid ""
+"Only RowExclusiveLock or less can be acquired on database objects during "
+"recovery."
+msgstr ""
+
+#: storage/lmgr/lock.c:884 storage/lmgr/lock.c:918 storage/lmgr/lock.c:2683
+#: storage/lmgr/lock.c:4008 storage/lmgr/lock.c:4073 storage/lmgr/lock.c:4365
+#, c-format
+msgid "You might need to increase max_locks_per_transaction."
+msgstr "max_locks_per_transaction을 늘려야 할 수도 있습니다."
+
+#: storage/lmgr/lock.c:3124 storage/lmgr/lock.c:3240
+#, c-format
+msgid ""
+"cannot PREPARE while holding both session-level and transaction-level locks "
+"on the same object"
+msgstr ""
+
+#: storage/lmgr/predicate.c:675
+#, c-format
+msgid "not enough elements in RWConflictPool to record a read/write conflict"
+msgstr ""
+
+#: storage/lmgr/predicate.c:676 storage/lmgr/predicate.c:704
+#, c-format
+msgid ""
+"You might need to run fewer transactions at a time or increase "
+"max_connections."
+msgstr ""
+
+#: storage/lmgr/predicate.c:703
+#, c-format
+msgid ""
+"not enough elements in RWConflictPool to record a potential read/write "
+"conflict"
+msgstr ""
+
+#: storage/lmgr/predicate.c:909
+#, c-format
+msgid "memory for serializable conflict tracking is nearly exhausted"
+msgstr ""
+
+#: storage/lmgr/predicate.c:910
+#, c-format
+msgid ""
+"There might be an idle transaction or a forgotten prepared transaction "
+"causing this."
+msgstr ""
+
+#: storage/lmgr/predicate.c:1190 storage/lmgr/predicate.c:1261
+#, c-format
+msgid ""
+"not enough shared memory for elements of data structure \"%s\" (%zu bytes "
+"requested)"
+msgstr ""
+
+#: storage/lmgr/predicate.c:1549
+#, c-format
+msgid "deferrable snapshot was unsafe; trying a new one"
+msgstr ""
+
+#: storage/lmgr/predicate.c:1588
+#, c-format
+msgid "\"default_transaction_isolation\" is set to \"serializable\"."
+msgstr ""
+
+#: storage/lmgr/predicate.c:1589
+#, c-format
+msgid ""
+"You can use \"SET default_transaction_isolation = 'repeatable read'\" to "
+"change the default."
+msgstr ""
+
+#: storage/lmgr/predicate.c:1628
+#, c-format
+msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE"
+msgstr ""
+
+#: storage/lmgr/predicate.c:1706 utils/time/snapmgr.c:617
+#: utils/time/snapmgr.c:623
+#, c-format
+msgid "could not import the requested snapshot"
+msgstr ""
+
+#: storage/lmgr/predicate.c:1707 utils/time/snapmgr.c:624
+#, c-format
+msgid "The source transaction %u is not running anymore."
+msgstr "%u 소스 트랜잭션은 더이상 실행 중이지 않습니다."
+
+#: storage/lmgr/predicate.c:2330 storage/lmgr/predicate.c:2345
+#: storage/lmgr/predicate.c:3737
+#, c-format
+msgid "You might need to increase max_pred_locks_per_transaction."
+msgstr "max_pred_locks_per_transaction 값을 늘려야 할 수도 있습니다."
+
+#: storage/lmgr/predicate.c:3891 storage/lmgr/predicate.c:3980
+#: storage/lmgr/predicate.c:3988 storage/lmgr/predicate.c:4027
+#: storage/lmgr/predicate.c:4266 storage/lmgr/predicate.c:4603
+#: storage/lmgr/predicate.c:4615 storage/lmgr/predicate.c:4657
+#: storage/lmgr/predicate.c:4695
+#, c-format
+msgid ""
+"could not serialize access due to read/write dependencies among transactions"
+msgstr "트랜잭션간 읽기/쓰기 의존성 때문에 serialize 접근을 할 수 없음"
+
+#: storage/lmgr/predicate.c:3893 storage/lmgr/predicate.c:3982
+#: storage/lmgr/predicate.c:3990 storage/lmgr/predicate.c:4029
+#: storage/lmgr/predicate.c:4268 storage/lmgr/predicate.c:4605
+#: storage/lmgr/predicate.c:4617 storage/lmgr/predicate.c:4659
+#: storage/lmgr/predicate.c:4697
+#, c-format
+msgid "The transaction might succeed if retried."
+msgstr "재시도하면 그 트랜잭션이 성공할 것입니다."
+
+#: storage/lmgr/proc.c:1265
+#, c-format
+msgid "Process %d waits for %s on %s."
+msgstr "%d 프로세스가 대기중, 잠금종류: %s, 내용: %s"
+
+#: storage/lmgr/proc.c:1276
+#, c-format
+msgid "sending cancel to blocking autovacuum PID %d"
+msgstr "%d PID autovacuum 블럭킹하기 위해 취소 신호를 보냅니다"
+
+#: storage/lmgr/proc.c:1294 utils/adt/misc.c:270
+#, c-format
+msgid "could not send signal to process %d: %m"
+msgstr "%d 프로세스로 시스템신호(signal)를 보낼 수 없습니다: %m"
+
+#: storage/lmgr/proc.c:1396
+#, c-format
+msgid ""
+"process %d avoided deadlock for %s on %s by rearranging queue order after "
+"%ld.%03d ms"
+msgstr ""
+"%d PID 프로세스는 %s(%s)에 대해 교착 상태가 발생하지 않도록 %ld.%03dms 후에 "
+"대기열 순서를 다시 조정함"
+
+#: storage/lmgr/proc.c:1411
+#, c-format
+msgid ""
+"process %d detected deadlock while waiting for %s on %s after %ld.%03d ms"
+msgstr "%d PID 프로세스에서 %s(%s) 대기중 %ld.%03dms 후에 교착 상태를 감지함"
+
+#: storage/lmgr/proc.c:1420
+#, c-format
+msgid "process %d still waiting for %s on %s after %ld.%03d ms"
+msgstr "%d PID 프로세스에서 여전히 %s(%s) 작업을 기다리고 있음(%ld.%03dms 후)"
+
+#: storage/lmgr/proc.c:1427
+#, c-format
+msgid "process %d acquired %s on %s after %ld.%03d ms"
+msgstr "%d PID 프로세스가 %s(%s) 작업을 위해 잠금 취득함(%ld.%03dms 후)"
+
+#: storage/lmgr/proc.c:1443
+#, c-format
+msgid "process %d failed to acquire %s on %s after %ld.%03d ms"
+msgstr "프로세스 %d에서 %s(%s)을(를) 취득하지 못함(%ld.%03dms 후)"
+
+#: storage/page/bufpage.c:144
+#, c-format
+msgid "page verification failed, calculated checksum %u but expected %u"
+msgstr "페이지 검사 실패, 계산된 체크섬은 %u, 기대값은 %u"
+
+#: storage/page/bufpage.c:203 storage/page/bufpage.c:522
+#: storage/page/bufpage.c:737 storage/page/bufpage.c:868
+#: storage/page/bufpage.c:968
+#, c-format
+msgid "corrupted page pointers: lower = %u, upper = %u, special = %u"
+msgstr "손상된 페이지 위치: 하위값 = %u, 상위값 = %u, 특수값 = %u"
+
+#: storage/page/bufpage.c:566
+#, c-format
+msgid "corrupted item pointer: %u"
+msgstr "손상된 아이템 위치: %u"
+
+#: storage/page/bufpage.c:577 storage/page/bufpage.c:919
+#: storage/page/bufpage.c:1074
+#, c-format
+msgid "corrupted item lengths: total %u, available space %u"
+msgstr "손상된 아이템 길이: 전체 %u, 사용가능한 공간 %u"
+
+#: storage/page/bufpage.c:756 storage/page/bufpage.c:892
+#, c-format
+msgid "corrupted item pointer: offset = %u, size = %u"
+msgstr "손상된 아이템 위치: 오프셋 = %u, 크기 = %u"
+
+#: storage/page/bufpage.c:997
+#, c-format
+msgid "corrupted item pointer: offset = %u, length = %u"
+msgstr "손상된 아이템 위치: 오프셋 = %u, 크기 = %u"
+
+#: storage/smgr/md.c:449 storage/smgr/md.c:971
+#, c-format
+msgid "could not truncate file \"%s\": %m"
+msgstr "\"%s\" 파일을 비울 수 없음: %m"
+
+#: storage/smgr/md.c:516
+#, c-format
+msgid "cannot extend file \"%s\" beyond %u blocks"
+msgstr "\"%s\" 파일을 %u개 블록을 초과하여 확장할 수 없음"
+
+#: storage/smgr/md.c:538 storage/smgr/md.c:751 storage/smgr/md.c:827
+#, c-format
+msgid "could not seek to block %u in file \"%s\": %m"
+msgstr "%u 블록을 찾을 수 없음(해당 파일: \"%s\"): %m"
+
+#: storage/smgr/md.c:546
+#, c-format
+msgid "could not extend file \"%s\": %m"
+msgstr "\"%s\" 파일을 확장할 수 없음: %m"
+
+#: storage/smgr/md.c:548 storage/smgr/md.c:555 storage/smgr/md.c:854
+#, c-format
+msgid "Check free disk space."
+msgstr "디스크 여유 공간을 확인해 주십시오."
+
+#: storage/smgr/md.c:552
+#, c-format
+msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u"
+msgstr "\"%s\" 파일을 확장할 수 없음: %d/%d바이트만 %u 블록에 썼음"
+
+#: storage/smgr/md.c:769
+#, c-format
+msgid "could not read block %u in file \"%s\": %m"
+msgstr "%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %m"
+
+#: storage/smgr/md.c:785
+#, c-format
+msgid "could not read block %u in file \"%s\": read only %d of %d bytes"
+msgstr "%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %d / %d 바이트만 읽음"
+
+#: storage/smgr/md.c:845
+#, c-format
+msgid "could not write block %u in file \"%s\": %m"
+msgstr "%u 블럭을 \"%s\" 파일에 쓸 수 없음: %m"
+
+#: storage/smgr/md.c:850
+#, c-format
+msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes"
+msgstr "%u 블럭을 \"%s\" 파일에 쓸 수 없음: %d / %d 바이트만 씀"
+
+#: storage/smgr/md.c:947
+#, c-format
+msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now"
+msgstr "\"%s\" 파일을 %u 블럭으로 비울 수 없음: 현재 %u 블럭 뿐 임"
+
+#: storage/smgr/md.c:997
+#, c-format
+msgid "could not truncate file \"%s\" to %u blocks: %m"
+msgstr "\"%s\" 파일을 %u 블럭으로 정리할 수 없음: %m"
+
+#: storage/smgr/md.c:1279
+#, c-format
+msgid "could not fsync file \"%s\" but retrying: %m"
+msgstr "\"%s\" 파일 fsync 실패, 재시도함: %m"
+
+#: storage/smgr/md.c:1442
+#, c-format
+msgid "could not forward fsync request because request queue is full"
+msgstr "요청 큐가 가득차 forward fsync 요청을 처리할 수 없음"
+
+#: storage/smgr/md.c:1863
+#, c-format
+msgid ""
+"could not open file \"%s\" (target block %u): previous segment is only %u "
+"blocks"
+msgstr "\"%s\" 파일을 열기 실패(대상 블록: %u): 이전 조각은 %u 블럭 뿐임"
+
+#: storage/smgr/md.c:1877
+#, c-format
+msgid "could not open file \"%s\" (target block %u): %m"
+msgstr "\"%s\" 파일을 열기 실패(대상 블록: %u): %m"
+
+#: tcop/fastpath.c:111 tcop/fastpath.c:475 tcop/fastpath.c:605
+#, c-format
+msgid "invalid argument size %d in function call message"
+msgstr "함수 호출 메시지 안에 있는 잘못된 %d 인자 크기"
+
+#: tcop/fastpath.c:291 tcop/postgres.c:992 tcop/postgres.c:1301
+#: tcop/postgres.c:1559 tcop/postgres.c:1964 tcop/postgres.c:2331
+#: tcop/postgres.c:2406
+#, c-format
+msgid ""
+"current transaction is aborted, commands ignored until end of transaction "
+"block"
+msgstr ""
+"현재 트랜잭션은 중지되어 있습니다. 이 트랜잭션을 종료하기 전까지는 모든 명령"
+"이 무시될 것입니다"
+
+#: tcop/fastpath.c:319
+#, c-format
+msgid "fastpath function call: \"%s\" (OID %u)"
+msgstr "fastpath 함수 호출: \"%s\" (OID %u)"
+
+#: tcop/fastpath.c:401 tcop/postgres.c:1163 tcop/postgres.c:1426
+#: tcop/postgres.c:1805 tcop/postgres.c:2022
+#, c-format
+msgid "duration: %s ms"
+msgstr "실행시간: %s ms"
+
+#: tcop/fastpath.c:405
+#, c-format
+msgid "duration: %s ms fastpath function call: \"%s\" (OID %u)"
+msgstr "작업시간: %s ms fastpath 함수 호출: \"%s\" (OID %u)"
+
+#: tcop/fastpath.c:443 tcop/fastpath.c:570
+#, c-format
+msgid "function call message contains %d arguments but function requires %d"
+msgstr "함수 호출 메시지는 %d 인자를 사용하지만, 함수는 %d 인자가 필요합니다"
+
+#: tcop/fastpath.c:451
+#, c-format
+msgid "function call message contains %d argument formats but %d arguments"
+msgstr "함수 호출 메시지는 %d 인자를 사용하지만, 함수는 %d 인자가 필요합니다"
+
+#: tcop/fastpath.c:538 tcop/fastpath.c:621
+#, c-format
+msgid "incorrect binary data format in function argument %d"
+msgstr "함수 인자 %d 안에 잘못된 바이너리 자료 형식 발견됨"
+
+#: tcop/postgres.c:352 tcop/postgres.c:388 tcop/postgres.c:415
+#, c-format
+msgid "unexpected EOF on client connection"
+msgstr "클라이언트 연결에서 예상치 않은 EOF 발견됨"
+
+#: tcop/postgres.c:438 tcop/postgres.c:450 tcop/postgres.c:461
+#: tcop/postgres.c:473 tcop/postgres.c:4314
+#, c-format
+msgid "invalid frontend message type %d"
+msgstr "잘못된 frontend 메시지 형태 %d"
+
+#: tcop/postgres.c:933
+#, c-format
+msgid "statement: %s"
+msgstr "명령 구문: %s"
+
+#: tcop/postgres.c:1168
+#, c-format
+msgid "duration: %s ms statement: %s"
+msgstr "실행시간: %s ms 명령 구문: %s"
+
+#: tcop/postgres.c:1218
+#, c-format
+msgid "parse %s: %s"
+msgstr "구문 %s: %s"
+
+#: tcop/postgres.c:1274
+#, c-format
+msgid "cannot insert multiple commands into a prepared statement"
+msgstr "준비된 명령 구문에는 다중 명령을 삽입할 수 없습니다"
+
+#: tcop/postgres.c:1431
+#, c-format
+msgid "duration: %s ms parse %s: %s"
+msgstr "실행시간: %s ms %s 구문분석: %s"
+
+#: tcop/postgres.c:1476
+#, c-format
+msgid "bind %s to %s"
+msgstr "바인드: %s -> %s"
+
+#: tcop/postgres.c:1495 tcop/postgres.c:2312
+#, c-format
+msgid "unnamed prepared statement does not exist"
+msgstr "이름없는 준비된 명령 구문(unnamed prepared statement) 없음"
+
+#: tcop/postgres.c:1537
+#, c-format
+msgid "bind message has %d parameter formats but %d parameters"
+msgstr "바인드 메시지는 %d 매개 변수 형태지만, %d 매개 변수여야함"
+
+#: tcop/postgres.c:1543
+#, c-format
+msgid ""
+"bind message supplies %d parameters, but prepared statement \"%s\" requires "
+"%d"
+msgstr ""
+"바인드 메시지는 %d개의 매개 변수를 지원하지만, \"%s\" 준비된 명령 구문"
+"(prepared statement)에서는%d 개의 매개 변수가 필요합니다"
+
+#: tcop/postgres.c:1712
+#, c-format
+msgid "incorrect binary data format in bind parameter %d"
+msgstr "바인드 매개 변수 %d 안에 잘못된 바이너리 자료 형태가 있음"
+
+#: tcop/postgres.c:1810
+#, c-format
+msgid "duration: %s ms bind %s%s%s: %s"
+msgstr "실행시간: %s ms %s%s%s 접속: %s"
+
+#: tcop/postgres.c:1858 tcop/postgres.c:2392
+#, c-format
+msgid "portal \"%s\" does not exist"
+msgstr "\"%s\" portal 없음"
+
+#: tcop/postgres.c:1943
+#, c-format
+msgid "%s %s%s%s: %s"
+msgstr "%s %s%s%s: %s"
+
+#: tcop/postgres.c:1945 tcop/postgres.c:2030
+msgid "execute fetch from"
+msgstr "자료뽑기"
+
+#: tcop/postgres.c:1946 tcop/postgres.c:2031
+msgid "execute"
+msgstr "쿼리실행"
+
+#: tcop/postgres.c:2027
+#, c-format
+msgid "duration: %s ms %s %s%s%s: %s"
+msgstr "수행시간: %s ms %s %s%s%s: %s"
+
+#: tcop/postgres.c:2153
+#, c-format
+msgid "prepare: %s"
+msgstr "prepare: %s"
+
+#: tcop/postgres.c:2216
+#, c-format
+msgid "parameters: %s"
+msgstr "매개 변수: %s"
+
+#: tcop/postgres.c:2235
+#, c-format
+msgid "abort reason: recovery conflict"
+msgstr "중지 이유: 복구 충돌"
+
+#: tcop/postgres.c:2251
+#, c-format
+msgid "User was holding shared buffer pin for too long."
+msgstr ""
+
+#: tcop/postgres.c:2254
+#, c-format
+msgid "User was holding a relation lock for too long."
+msgstr ""
+
+#: tcop/postgres.c:2257
+#, c-format
+msgid "User was or might have been using tablespace that must be dropped."
+msgstr ""
+
+#: tcop/postgres.c:2260
+#, c-format
+msgid "User query might have needed to see row versions that must be removed."
+msgstr ""
+
+#: tcop/postgres.c:2266
+#, c-format
+msgid "User was connected to a database that must be dropped."
+msgstr "삭제 되어져야할 데이터베이스 사용자 접속해 있습니다."
+
+#: tcop/postgres.c:2595
+#, c-format
+msgid "terminating connection because of crash of another server process"
+msgstr "다른 서버 프로세스가 손상을 입어 현재 연결을 중지합니다"
+
+#: tcop/postgres.c:2596
+#, c-format
+msgid ""
+"The postmaster has commanded this server process to roll back the current "
+"transaction and exit, because another server process exited abnormally and "
+"possibly corrupted shared memory."
+msgstr ""
+"postmaster 에서 현재 이서버 프로세스에게 현재 트랜잭션을 취소하고, 클라이언트"
+"와의 연결을 끊으라는 명령을 보냈습니다. 왜냐하면, 다른 서버 프로세스가 비정상"
+"적으로 중지되어 공유 메모리가 손상되었을 가능성이 있기 때문입니다"
+
+#: tcop/postgres.c:2600 tcop/postgres.c:2904
+#, c-format
+msgid ""
+"In a moment you should be able to reconnect to the database and repeat your "
+"command."
+msgstr "잠시 뒤에 다시 연결 해서 작업을 계속 하십시오"
+
+#: tcop/postgres.c:2686
+#, c-format
+msgid "floating-point exception"
+msgstr "부동소수점 예외발생"
+
+#: tcop/postgres.c:2687
+#, c-format
+msgid ""
+"An invalid floating-point operation was signaled. This probably means an out-"
+"of-range result or an invalid operation, such as division by zero."
+msgstr ""
+"잘못된 부동소수점 작업이 감지 되었습니다. 이것은 아마도 결과값 범위초과나 0으"
+"로 나누는 작업과 같은 잘못된 연산 때문에 발생한 것 같습니다"
+
+#: tcop/postgres.c:2849
+#, c-format
+msgid "canceling authentication due to timeout"
+msgstr "시간 초과로 인증 작업을 취소합니다."
+
+#: tcop/postgres.c:2853
+#, c-format
+msgid "terminating autovacuum process due to administrator command"
+msgstr "관리자 명령으로 인해 자동 청소 프로세스를 종료하는 중"
+
+#: tcop/postgres.c:2859 tcop/postgres.c:2869 tcop/postgres.c:2902
+#, c-format
+msgid "terminating connection due to conflict with recovery"
+msgstr "복구 작업 중 충돌로 연결을 종료합니다."
+
+#: tcop/postgres.c:2875
+#, c-format
+msgid "terminating connection due to administrator command"
+msgstr "관리자 요청에 의해서 연결을 끝냅니다"
+
+#: tcop/postgres.c:2885
+#, c-format
+msgid "connection to client lost"
+msgstr "서버로부터 연결이 끊어졌습니다."
+
+#: tcop/postgres.c:2953
+#, c-format
+msgid "canceling statement due to lock timeout"
+msgstr "잠금 대기 시간 초과로 작업을 취소합니다."
+
+#: tcop/postgres.c:2960
+#, c-format
+msgid "canceling statement due to statement timeout"
+msgstr "명령실행시간 초과로 작업을 취소합니다."
+
+#: tcop/postgres.c:2967
+#, c-format
+msgid "canceling autovacuum task"
+msgstr "자동 청소 작업을 취소하는 중"
+
+#: tcop/postgres.c:2990
+#, c-format
+msgid "canceling statement due to user request"
+msgstr "사용자 요청에 의해 작업을 취소합니다."
+
+#: tcop/postgres.c:3000
+#, c-format
+msgid "terminating connection due to idle-in-transaction timeout"
+msgstr "idle-in-transaction 시간 초과로 연결을 끝냅니다"
+
+#: tcop/postgres.c:3114
+#, c-format
+msgid "stack depth limit exceeded"
+msgstr "스택 깊이를 초과했습니다"
+
+#: tcop/postgres.c:3115
+#, c-format
+msgid ""
+"Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
+"after ensuring the platform's stack depth limit is adequate."
+msgstr ""
+"먼저 OS에서 지원하는 스택 depth 최대값을 확인한 뒤, 허용범위 안에서 "
+"\"max_stack_depth\" (현재값: %dkB) 매개 변수 값의 설정치를 증가시키세요."
+
+#: tcop/postgres.c:3178
+#, c-format
+msgid "\"max_stack_depth\" must not exceed %ldkB."
+msgstr "\"max_stack_depth\" 값은 %ldkB를 초과할 수 없습니다"
+
+#: tcop/postgres.c:3180
+#, c-format
+msgid ""
+"Increase the platform's stack depth limit via \"ulimit -s\" or local "
+"equivalent."
+msgstr "OS의 \"ulimit -s\" 명령과 같은 것으로 스택 깊이를 늘려주십시오."
+
+#: tcop/postgres.c:3540
+#, c-format
+msgid "invalid command-line argument for server process: %s"
+msgstr "서버 프로세스의 명령행 인자가 잘못되었습니다: %s"
+
+#: tcop/postgres.c:3541 tcop/postgres.c:3547
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요."
+
+#: tcop/postgres.c:3545
+#, c-format
+msgid "%s: invalid command-line argument: %s"
+msgstr "%s: 잘못된 명령행 인자: %s"
+
+#: tcop/postgres.c:3607
+#, c-format
+msgid "%s: no database nor user name specified"
+msgstr "%s: 데이터베이스와 사용자를 지정하지 않았습니다"
+
+#: tcop/postgres.c:4222
+#, c-format
+msgid "invalid CLOSE message subtype %d"
+msgstr "잘못된 CLOSE 메시지 서브타입 %d"
+
+#: tcop/postgres.c:4257
+#, c-format
+msgid "invalid DESCRIBE message subtype %d"
+msgstr "잘못된 DESCRIBE 메시지 서브타입 %d"
+
+#: tcop/postgres.c:4335
+#, c-format
+msgid "fastpath function calls not supported in a replication connection"
+msgstr "복제 연결에서는 fastpath 함수 호출을 지원하지 않습니다"
+
+#: tcop/postgres.c:4339
+#, c-format
+msgid "extended query protocol not supported in a replication connection"
+msgstr ""
+
+#: tcop/postgres.c:4509
+#, c-format
+msgid ""
+"disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s"
+"%s"
+msgstr ""
+"연결종료: 세션 시간: %d:%02d:%02d.%03d 사용자=%s 데이터베이스=%s 호스트=%s%s"
+"%s"
+
+#: tcop/pquery.c:665
+#, c-format
+msgid "bind message has %d result formats but query has %d columns"
+msgstr ""
+"바인드 메시지는 %d 결과 포멧을 가지고 있고, 쿼리는 %d 열을 가지고 있습니다"
+
+#: tcop/pquery.c:967
+#, c-format
+msgid "cursor can only scan forward"
+msgstr "이 커서는 앞으로 이동 전용입니다"
+
+#: tcop/pquery.c:968
+#, c-format
+msgid "Declare it with SCROLL option to enable backward scan."
+msgstr ""
+"뒤로 이동 가능한 커서를 만드려면 SCROLL 옵션을 추가해서 커서를 만드세요."
+
+#. translator: %s is name of a SQL command, eg CREATE
+#: tcop/utility.c:235
+#, c-format
+msgid "cannot execute %s in a read-only transaction"
+msgstr "읽기 전용 트랜잭션에서는 %s 명령을 실행할 수 없습니다."
+
+#. translator: %s is name of a SQL command, eg CREATE
+#: tcop/utility.c:253
+#, c-format
+msgid "cannot execute %s during a parallel operation"
+msgstr "병렬 처리 작업에서는 %s 명령을 실행할 수 없습니다."
+
+#. translator: %s is name of a SQL command, eg CREATE
+#: tcop/utility.c:272
+#, c-format
+msgid "cannot execute %s during recovery"
+msgstr "복구 작업 중에는 %s 명령을 실행할 수 없습니다."
+
+#. translator: %s is name of a SQL command, eg PREPARE
+#: tcop/utility.c:290
+#, c-format
+msgid "cannot execute %s within security-restricted operation"
+msgstr "보안 제한 작업 내에서 %s을(를) 실행할 수 없음"
+
+#: tcop/utility.c:744
+#, c-format
+msgid "must be superuser to do CHECKPOINT"
+msgstr "CHECKPOINT 명령은 슈퍼유저만 사용할 수 있습니다"
+
+#: tsearch/dict_ispell.c:51 tsearch/dict_thesaurus.c:623
+#, c-format
+msgid "multiple DictFile parameters"
+msgstr "DictFile 매개 변수가 여러 개 있음"
+
+#: tsearch/dict_ispell.c:62
+#, c-format
+msgid "multiple AffFile parameters"
+msgstr "AffFile 매개 변수가 여러 개 있음"
+
+#: tsearch/dict_ispell.c:81
+#, c-format
+msgid "unrecognized Ispell parameter: \"%s\""
+msgstr "인식할 수 없는 Ispell 매개 변수: \"%s\""
+
+#: tsearch/dict_ispell.c:95
+#, c-format
+msgid "missing AffFile parameter"
+msgstr "AffFile 매개 변수가 누락됨"
+
+#: tsearch/dict_ispell.c:101 tsearch/dict_thesaurus.c:647
+#, c-format
+msgid "missing DictFile parameter"
+msgstr "DictFile 매개 변수가 누락됨"
+
+#: tsearch/dict_simple.c:57
+#, c-format
+msgid "multiple Accept parameters"
+msgstr "Accept 매개 변수가 여러 개 있음"
+
+#: tsearch/dict_simple.c:65
+#, c-format
+msgid "unrecognized simple dictionary parameter: \"%s\""
+msgstr "인식할 수 없는 simple 사전 매개 변수: \"%s\""
+
+#: tsearch/dict_synonym.c:117
+#, c-format
+msgid "unrecognized synonym parameter: \"%s\""
+msgstr "인식할 수 없는 synonym 매개 변수: \"%s\""
+
+#: tsearch/dict_synonym.c:124
+#, c-format
+msgid "missing Synonyms parameter"
+msgstr "Synonyms 매개 변수가 누락됨"
+
+#: tsearch/dict_synonym.c:131
+#, c-format
+msgid "could not open synonym file \"%s\": %m"
+msgstr "\"%s\" 동의어 파일을 열 수 없음: %m"
+
+#: tsearch/dict_thesaurus.c:178
+#, c-format
+msgid "could not open thesaurus file \"%s\": %m"
+msgstr "\"%s\" 기준어 파일을 열 수 없음: %m"
+
+#: tsearch/dict_thesaurus.c:211
+#, c-format
+msgid "unexpected delimiter"
+msgstr "예기치 않은 구분자"
+
+#: tsearch/dict_thesaurus.c:261 tsearch/dict_thesaurus.c:277
+#, c-format
+msgid "unexpected end of line or lexeme"
+msgstr "예기치 않은 줄 끝 또는 어휘소"
+
+#: tsearch/dict_thesaurus.c:286
+#, c-format
+msgid "unexpected end of line"
+msgstr "예기치 않은 줄 끝"
+
+#: tsearch/dict_thesaurus.c:296
+#, c-format
+msgid "too many lexemes in thesaurus entry"
+msgstr "기준어 항목에 너무 많은 어휘소가 있음"
+
+#: tsearch/dict_thesaurus.c:420
+#, c-format
+msgid ""
+"thesaurus sample word \"%s\" isn't recognized by subdictionary (rule %d)"
+msgstr "\"%s\" 기준 단어는 하위 사전에서 인식할 수 없음(규칙 %d)"
+
+#: tsearch/dict_thesaurus.c:426
+#, c-format
+msgid "thesaurus sample word \"%s\" is a stop word (rule %d)"
+msgstr "\"%s\" 동의어 사전 샘플 단어는 중지 단어임(규칙 %d)"
+
+#: tsearch/dict_thesaurus.c:429
+#, c-format
+msgid "Use \"?\" to represent a stop word within a sample phrase."
+msgstr "샘플 구 내에서 중지 단어를 나타내려면 \"?\"를 사용하십시오."
+
+#: tsearch/dict_thesaurus.c:575
+#, c-format
+msgid "thesaurus substitute word \"%s\" is a stop word (rule %d)"
+msgstr "\"%s\" 동의어 사전 대체 단어는 중지 단어임(규칙 %d)"
+
+#: tsearch/dict_thesaurus.c:582
+#, c-format
+msgid ""
+"thesaurus substitute word \"%s\" isn't recognized by subdictionary (rule %d)"
+msgstr "\"%s\" 동의어 사전 대체 단어는 하위 사전에서 인식할 수 없음(규칙 %d)"
+
+#: tsearch/dict_thesaurus.c:594
+#, c-format
+msgid "thesaurus substitute phrase is empty (rule %d)"
+msgstr "동의어 사전 대체 구가 비어 있음(규칙 %d)"
+
+#: tsearch/dict_thesaurus.c:632
+#, c-format
+msgid "multiple Dictionary parameters"
+msgstr "Dictionary 매개 변수가 여러 개 있음"
+
+#: tsearch/dict_thesaurus.c:639
+#, c-format
+msgid "unrecognized Thesaurus parameter: \"%s\""
+msgstr "인식할 수 없는 Thesaurus 매개 변수: \"%s\""
+
+#: tsearch/dict_thesaurus.c:651
+#, c-format
+msgid "missing Dictionary parameter"
+msgstr "Dictionary 매개 변수가 누락됨"
+
+#: tsearch/spell.c:380 tsearch/spell.c:397 tsearch/spell.c:406
+#: tsearch/spell.c:1034
+#, c-format
+msgid "invalid affix flag \"%s\""
+msgstr "잘못된 affix 플래그: \"%s\""
+
+#: tsearch/spell.c:384 tsearch/spell.c:1038
+#, c-format
+msgid "affix flag \"%s\" is out of range"
+msgstr "affix 플래그 범위 초과: \"%s\""
+
+#: tsearch/spell.c:414
+#, c-format
+msgid "invalid character in affix flag \"%s\""
+msgstr "affix 플래그에 이상한 문자가 있음: \"%s\""
+
+#: tsearch/spell.c:434
+#, c-format
+msgid "invalid affix flag \"%s\" with \"long\" flag value"
+msgstr ""
+
+#: tsearch/spell.c:522
+#, c-format
+msgid "could not open dictionary file \"%s\": %m"
+msgstr "\"%s\" 사전 파일을 열 수 없음: %m"
+
+#: tsearch/spell.c:740 utils/adt/regexp.c:204
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "잘못된 정규식: %s"
+
+#: tsearch/spell.c:954 tsearch/spell.c:971 tsearch/spell.c:988
+#: tsearch/spell.c:1005 tsearch/spell.c:1070 gram.y:14405 gram.y:14422
+#, c-format
+msgid "syntax error"
+msgstr "구문 오류"
+
+#: tsearch/spell.c:1161 tsearch/spell.c:1721
+#, c-format
+msgid "invalid affix alias \"%s\""
+msgstr "잘못된 affix 별칭: \"%s\""
+
+#: tsearch/spell.c:1211 tsearch/spell.c:1282 tsearch/spell.c:1426
+#, c-format
+msgid "could not open affix file \"%s\": %m"
+msgstr "\"%s\" affix 파일을 열 수 없음: %m"
+
+#: tsearch/spell.c:1265
+#, c-format
+msgid ""
+"Ispell dictionary supports only \"default\", \"long\", and \"num\" flag "
+"values"
+msgstr "Ispell 사전은 \"default\", \"long\", \"num\" 플래그 값만 지원함"
+
+#: tsearch/spell.c:1309
+#, c-format
+msgid "invalid number of flag vector aliases"
+msgstr "잘못된 플래그 백터 별칭 개수"
+
+#: tsearch/spell.c:1542
+#, c-format
+msgid "affix file contains both old-style and new-style commands"
+msgstr "affix 파일에 옛방식과 새방식 명령이 함께 있습니다"
+
+#: tsearch/to_tsany.c:170 utils/adt/tsvector.c:270
+#: utils/adt/tsvector_op.c:1133
+#, c-format
+msgid "string is too long for tsvector (%d bytes, max %d bytes)"
+msgstr ""
+"문자열이 너무 길어서 tsvector에 사용할 수 없음(%d바이트, 최대 %d바이트)"
+
+#: tsearch/ts_locale.c:177
+#, c-format
+msgid "line %d of configuration file \"%s\": \"%s\""
+msgstr "%d번째 줄(해당 파일: \"%s\"): \"%s\""
+
+#: tsearch/ts_locale.c:299
+#, c-format
+msgid "conversion from wchar_t to server encoding failed: %m"
+msgstr "wchar_t에서 서버 인코딩으로 변환하지 못함: %m"
+
+#: tsearch/ts_parse.c:390 tsearch/ts_parse.c:397 tsearch/ts_parse.c:566
+#: tsearch/ts_parse.c:573
+#, c-format
+msgid "word is too long to be indexed"
+msgstr "단어가 너무 길어서 인덱싱할 수 없음"
+
+#: tsearch/ts_parse.c:391 tsearch/ts_parse.c:398 tsearch/ts_parse.c:567
+#: tsearch/ts_parse.c:574
+#, c-format
+msgid "Words longer than %d characters are ignored."
+msgstr "%d자보다 긴 단어는 무시됩니다."
+
+#: tsearch/ts_utils.c:51
+#, c-format
+msgid "invalid text search configuration file name \"%s\""
+msgstr "\"%s\" 전문 검색 구성 파일 이름이 잘못됨"
+
+#: tsearch/ts_utils.c:83
+#, c-format
+msgid "could not open stop-word file \"%s\": %m"
+msgstr "\"%s\" 중지 단어 파일을 열 수 없음: %m"
+
+#: tsearch/wparser.c:306
+#, c-format
+msgid "text search parser does not support headline creation"
+msgstr "전문 검색 분석기에서 헤드라인 작성을 지원하지 않음"
+
+#: tsearch/wparser_def.c:2583
+#, c-format
+msgid "unrecognized headline parameter: \"%s\""
+msgstr "인식할 수 없는 headline 매개 변수: \"%s\""
+
+#: tsearch/wparser_def.c:2592
+#, c-format
+msgid "MinWords should be less than MaxWords"
+msgstr "MinWords는 MaxWords보다 작아야 함"
+
+#: tsearch/wparser_def.c:2596
+#, c-format
+msgid "MinWords should be positive"
+msgstr "MinWords는 양수여야 함"
+
+#: tsearch/wparser_def.c:2600
+#, c-format
+msgid "ShortWord should be >= 0"
+msgstr "ShortWord는 0보다 크거나 같아야 함"
+
+#: tsearch/wparser_def.c:2604
+#, c-format
+msgid "MaxFragments should be >= 0"
+msgstr "MaxFragments는 0보다 크거나 같아야 함"
+
+# # nonun 부분 begin
+#: utils/adt/acl.c:170 utils/adt/name.c:91
+#, c-format
+msgid "identifier too long"
+msgstr "식별자(identifier)가 너무 깁니다."
+
+#: utils/adt/acl.c:171 utils/adt/name.c:92
+#, c-format
+msgid "Identifier must be less than %d characters."
+msgstr "식별자(Identifier)는 %d 글자 이상일 수 없습니다."
+
+#: utils/adt/acl.c:257
+#, c-format
+msgid "unrecognized key word: \"%s\""
+msgstr "알 수 없는 않은 키워드: \"%s\""
+
+#: utils/adt/acl.c:258
+#, c-format
+msgid "ACL key word must be \"group\" or \"user\"."
+msgstr "ACL 키워드는 \"group\" 또는 \"user\" 중에 하나여야 합니다."
+
+#: utils/adt/acl.c:263
+#, c-format
+msgid "missing name"
+msgstr "이름이 빠졌습니다."
+
+#: utils/adt/acl.c:264
+#, c-format
+msgid "A name must follow the \"group\" or \"user\" key word."
+msgstr "이름은 \"group\" 또는 \"user\" 키워드 뒤에 있어야 합니다."
+
+#: utils/adt/acl.c:270
+#, c-format
+msgid "missing \"=\" sign"
+msgstr "\"=\" 기호가 빠졌습니다."
+
+#: utils/adt/acl.c:323
+#, c-format
+msgid "invalid mode character: must be one of \"%s\""
+msgstr "잘못된 조건: \"%s\" 중에 한 가지여야 합니다."
+
+#: utils/adt/acl.c:345
+#, c-format
+msgid "a name must follow the \"/\" sign"
+msgstr "이름은 \"/\"기호 뒤에 있어야 합니다."
+
+#: utils/adt/acl.c:353
+#, c-format
+msgid "defaulting grantor to user ID %u"
+msgstr "%u 사용자 ID에서 기본 권한자로 할당하고 있습니다"
+
+#: utils/adt/acl.c:544
+#, c-format
+msgid "ACL array contains wrong data type"
+msgstr "ACL 배열에 잘못된 자료형을 사용하고 있습니다"
+
+#: utils/adt/acl.c:548
+#, c-format
+msgid "ACL arrays must be one-dimensional"
+msgstr "ACL 배열은 일차원 배열이어야합니다"
+
+#: utils/adt/acl.c:552
+#, c-format
+msgid "ACL arrays must not contain null values"
+msgstr "ACL 배열에는 null 값을 포함할 수 없습니다"
+
+#: utils/adt/acl.c:576
+#, c-format
+msgid "extra garbage at the end of the ACL specification"
+msgstr "ACL 설정 정보 끝에 끝에 쓸모 없는 내용들이 더 포함되어있습니다"
+
+#: utils/adt/acl.c:1196
+#, c-format
+msgid "grant options cannot be granted back to your own grantor"
+msgstr "부여 옵션을 해당 부여자에게 다시 부여할 수 없음"
+
+#: utils/adt/acl.c:1257
+#, c-format
+msgid "dependent privileges exist"
+msgstr "???의존(적인) 권한이 존재합니다"
+
+#: utils/adt/acl.c:1258
+#, c-format
+msgid "Use CASCADE to revoke them too."
+msgstr "그것들을 취소하려면 \"CASCADE\"를 사용하세요."
+
+#: utils/adt/acl.c:1537
+#, c-format
+msgid "aclinsert is no longer supported"
+msgstr "aclinsert 더이상 지원하지 않음"
+
+#: utils/adt/acl.c:1547
+#, c-format
+msgid "aclremove is no longer supported"
+msgstr "aclremovie 더이상 지원하지 않음"
+
+#: utils/adt/acl.c:1633 utils/adt/acl.c:1687
+#, c-format
+msgid "unrecognized privilege type: \"%s\""
+msgstr "알 수 없는 권한 타입: \"%s\""
+
+#: utils/adt/acl.c:3427 utils/adt/regproc.c:123 utils/adt/regproc.c:144
+#: utils/adt/regproc.c:319
+#, c-format
+msgid "function \"%s\" does not exist"
+msgstr "\"%s\" 함수가 없습니다."
+
+#: utils/adt/acl.c:4881
+#, c-format
+msgid "must be member of role \"%s\""
+msgstr "\"%s\" 롤의 구성원이어야 함"
+
+#: utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:931
+#: utils/adt/arrayfuncs.c:1519 utils/adt/arrayfuncs.c:3251
+#: utils/adt/arrayfuncs.c:3389 utils/adt/arrayfuncs.c:5848
+#: utils/adt/arrayfuncs.c:6159 utils/adt/arrayutils.c:93
+#: utils/adt/arrayutils.c:102 utils/adt/arrayutils.c:109
+#, c-format
+msgid "array size exceeds the maximum allowed (%d)"
+msgstr "배열 크기가 최대치 (%d)를 초과했습니다"
+
+#: utils/adt/array_userfuncs.c:79 utils/adt/array_userfuncs.c:541
+#: utils/adt/array_userfuncs.c:621 utils/adt/json.c:1759 utils/adt/json.c:1854
+#: utils/adt/json.c:1892 utils/adt/jsonb.c:1126 utils/adt/jsonb.c:1155
+#: utils/adt/jsonb.c:1591 utils/adt/jsonb.c:1755 utils/adt/jsonb.c:1765
+#, c-format
+msgid "could not determine input data type"
+msgstr "입력 자료형을 결정할 수 없음"
+
+#: utils/adt/array_userfuncs.c:84
+#, c-format
+msgid "input data type is not an array"
+msgstr "입력 자료형이 배열이 아닙니다."
+
+#: utils/adt/array_userfuncs.c:132 utils/adt/array_userfuncs.c:186
+#: utils/adt/arrayfuncs.c:1322 utils/adt/float.c:1228 utils/adt/float.c:1287
+#: utils/adt/float.c:3556 utils/adt/float.c:3572 utils/adt/int.c:623
+#: utils/adt/int.c:652 utils/adt/int.c:673 utils/adt/int.c:704
+#: utils/adt/int.c:737 utils/adt/int.c:759 utils/adt/int.c:907
+#: utils/adt/int.c:928 utils/adt/int.c:955 utils/adt/int.c:995
+#: utils/adt/int.c:1016 utils/adt/int.c:1043 utils/adt/int.c:1076
+#: utils/adt/int.c:1159 utils/adt/int8.c:1298 utils/adt/numeric.c:2903
+#: utils/adt/numeric.c:2912 utils/adt/varbit.c:1173 utils/adt/varbit.c:1575
+#: utils/adt/varlena.c:1055 utils/adt/varlena.c:2807
+#, c-format
+msgid "integer out of range"
+msgstr "정수 범위를 벗어남"
+
+#: utils/adt/array_userfuncs.c:139 utils/adt/array_userfuncs.c:196
+#, c-format
+msgid "argument must be empty or one-dimensional array"
+msgstr "인자는 비어있거나 1차원 배열이어야 합니다."
+
+#: utils/adt/array_userfuncs.c:278 utils/adt/array_userfuncs.c:317
+#: utils/adt/array_userfuncs.c:354 utils/adt/array_userfuncs.c:383
+#: utils/adt/array_userfuncs.c:411
+#, c-format
+msgid "cannot concatenate incompatible arrays"
+msgstr "연결할 수 없는 배열들 입니다."
+
+#: utils/adt/array_userfuncs.c:279
+#, c-format
+msgid ""
+"Arrays with element types %s and %s are not compatible for concatenation."
+msgstr "%s 자료형의 배열과 %s 자료형의 배열은 연결할 수 없습니다."
+
+#: utils/adt/array_userfuncs.c:318
+#, c-format
+msgid "Arrays of %d and %d dimensions are not compatible for concatenation."
+msgstr "%d차원(배열 깊이) 배열과 %d차원 배열은 연결할 수 없습니다."
+
+#: utils/adt/array_userfuncs.c:355
+#, c-format
+msgid ""
+"Arrays with differing element dimensions are not compatible for "
+"concatenation."
+msgstr "차원(배열 깊이)이 다른 배열들을 서로 합칠 수 없습니다"
+
+#: utils/adt/array_userfuncs.c:384 utils/adt/array_userfuncs.c:412
+#, c-format
+msgid "Arrays with differing dimensions are not compatible for concatenation."
+msgstr "차원(배열 깊이)이 다른 배열들을 서로 합칠 수 없습니다"
+
+#: utils/adt/array_userfuncs.c:480 utils/adt/arrayfuncs.c:1284
+#: utils/adt/arrayfuncs.c:3357 utils/adt/arrayfuncs.c:5754
+#, c-format
+msgid "invalid number of dimensions: %d"
+msgstr "잘못된 배열 차원(배열 깊이): %d"
+
+#: utils/adt/array_userfuncs.c:737 utils/adt/array_userfuncs.c:889
+#, c-format
+msgid "searching for elements in multidimensional arrays is not supported"
+msgstr "다차원 배열에서 요소 검색 기능은 지원하지 않음"
+
+#: utils/adt/array_userfuncs.c:761
+#, c-format
+msgid "initial position must not be null"
+msgstr "초기 위치값은 null값이 아니여야 함"
+
+#: utils/adt/arrayfuncs.c:268 utils/adt/arrayfuncs.c:282
+#: utils/adt/arrayfuncs.c:293 utils/adt/arrayfuncs.c:315
+#: utils/adt/arrayfuncs.c:330 utils/adt/arrayfuncs.c:344
+#: utils/adt/arrayfuncs.c:350 utils/adt/arrayfuncs.c:357
+#: utils/adt/arrayfuncs.c:488 utils/adt/arrayfuncs.c:504
+#: utils/adt/arrayfuncs.c:515 utils/adt/arrayfuncs.c:530
+#: utils/adt/arrayfuncs.c:551 utils/adt/arrayfuncs.c:581
+#: utils/adt/arrayfuncs.c:588 utils/adt/arrayfuncs.c:596
+#: utils/adt/arrayfuncs.c:630 utils/adt/arrayfuncs.c:653
+#: utils/adt/arrayfuncs.c:673 utils/adt/arrayfuncs.c:785
+#: utils/adt/arrayfuncs.c:794 utils/adt/arrayfuncs.c:824
+#: utils/adt/arrayfuncs.c:839 utils/adt/arrayfuncs.c:892
+#, c-format
+msgid "malformed array literal: \"%s\""
+msgstr "비정상적인 배열 문자: \"%s\""
+
+#: utils/adt/arrayfuncs.c:269
+#, c-format
+msgid "\"[\" must introduce explicitly-specified array dimensions."
+msgstr "배열 차원 정의는 \"[\" 문자로 시작해야 합니다."
+
+#: utils/adt/arrayfuncs.c:283
+#, c-format
+msgid "Missing array dimension value."
+msgstr "배열 차원(배열 깊이) 값이 빠졌습니다."
+
+#: utils/adt/arrayfuncs.c:294 utils/adt/arrayfuncs.c:331
+#, c-format
+msgid "Missing \"%s\" after array dimensions."
+msgstr "배열 차원(배열 깊이) 표현에서 \"%s\" 문자가 빠졌습니다."
+
+#: utils/adt/arrayfuncs.c:303 utils/adt/arrayfuncs.c:2870
+#: utils/adt/arrayfuncs.c:2902 utils/adt/arrayfuncs.c:2917
+#, c-format
+msgid "upper bound cannot be less than lower bound"
+msgstr "상한값은 하한값보다 작을 수 없습니다"
+
+#: utils/adt/arrayfuncs.c:316
+#, c-format
+msgid "Array value must start with \"{\" or dimension information."
+msgstr "배열값은 \"{\" 또는 배열 깊이 정보로 시작되어야 합니다"
+
+#: utils/adt/arrayfuncs.c:345
+#, c-format
+msgid "Array contents must start with \"{\"."
+msgstr "배열형은 \"{\" 문자로 시작해야 합니다."
+
+#: utils/adt/arrayfuncs.c:351 utils/adt/arrayfuncs.c:358
+#, c-format
+msgid "Specified array dimensions do not match array contents."
+msgstr "지정한 배열 차원에 해당하는 배열이 없습니다."
+
+#: utils/adt/arrayfuncs.c:489 utils/adt/arrayfuncs.c:516
+#: utils/adt/rangetypes.c:2124 utils/adt/rangetypes.c:2132
+#: utils/adt/rowtypes.c:208 utils/adt/rowtypes.c:216
+#, c-format
+msgid "Unexpected end of input."
+msgstr "입력의 예상치 못한 종료."
+
+#: utils/adt/arrayfuncs.c:505 utils/adt/arrayfuncs.c:552
+#: utils/adt/arrayfuncs.c:582 utils/adt/arrayfuncs.c:631
+#, c-format
+msgid "Unexpected \"%c\" character."
+msgstr "예기치 않은 \"%c\" 문자"
+
+#: utils/adt/arrayfuncs.c:531 utils/adt/arrayfuncs.c:654
+#, c-format
+msgid "Unexpected array element."
+msgstr "예기치 않은 배열 요소"
+
+#: utils/adt/arrayfuncs.c:589
+#, c-format
+msgid "Unmatched \"%c\" character."
+msgstr "짝이 안 맞는 \"%c\" 문자"
+
+#: utils/adt/arrayfuncs.c:597
+#, c-format
+msgid "Multidimensional arrays must have sub-arrays with matching dimensions."
+msgstr "다차원 배열에는 일치하는 차원이 포함된 배열 식이 있어야 함"
+
+#: utils/adt/arrayfuncs.c:674
+#, c-format
+msgid "Junk after closing right brace."
+msgstr "오른쪽 닫기 괄호 뒤에 정크"
+
+#: utils/adt/arrayfuncs.c:1295
+#, c-format
+msgid "invalid array flags"
+msgstr "잘못된 배열 플래그"
+
+#: utils/adt/arrayfuncs.c:1303
+#, c-format
+msgid "wrong element type"
+msgstr "잘못된 요소 타입"
+
+#: utils/adt/arrayfuncs.c:1353 utils/adt/rangetypes.c:334
+#: utils/cache/lsyscache.c:2651
+#, c-format
+msgid "no binary input function available for type %s"
+msgstr "%s 자료형에서 사용할 바이너리 입력 함수가 없습니다."
+
+#: utils/adt/arrayfuncs.c:1493
+#, c-format
+msgid "improper binary format in array element %d"
+msgstr "%d 번째 배열 요소의 포맷이 부적절합니다."
+
+#: utils/adt/arrayfuncs.c:1574 utils/adt/rangetypes.c:339
+#: utils/cache/lsyscache.c:2684
+#, c-format
+msgid "no binary output function available for type %s"
+msgstr "%s 자료형에서 사용할 바이너리 출력 함수가 없습니다."
+
+#: utils/adt/arrayfuncs.c:2052
+#, c-format
+msgid "slices of fixed-length arrays not implemented"
+msgstr "특정 크기로 배열을 절단하는 기능은 구현되지 않습니다."
+
+#: utils/adt/arrayfuncs.c:2230 utils/adt/arrayfuncs.c:2252
+#: utils/adt/arrayfuncs.c:2301 utils/adt/arrayfuncs.c:2537
+#: utils/adt/arrayfuncs.c:2848 utils/adt/arrayfuncs.c:5740
+#: utils/adt/arrayfuncs.c:5766 utils/adt/arrayfuncs.c:5777
+#: utils/adt/json.c:2290 utils/adt/json.c:2365 utils/adt/jsonb.c:1369
+#: utils/adt/jsonb.c:1455 utils/adt/jsonfuncs.c:3529
+#: utils/adt/jsonfuncs.c:3574 utils/adt/jsonfuncs.c:3621
+#, c-format
+msgid "wrong number of array subscripts"
+msgstr "잘못된 배열 하위 스크립트(1,2...차원 배열 표시 문제)"
+
+#: utils/adt/arrayfuncs.c:2235 utils/adt/arrayfuncs.c:2343
+#: utils/adt/arrayfuncs.c:2601 utils/adt/arrayfuncs.c:2907
+#, c-format
+msgid "array subscript out of range"
+msgstr "배열 하위 스크립트 범위를 초과했습니다"
+
+#: utils/adt/arrayfuncs.c:2240
+#, c-format
+msgid "cannot assign null value to an element of a fixed-length array"
+msgstr "고정 길이 배열의 요소에 null 값을 지정할 수 없음"
+
+#: utils/adt/arrayfuncs.c:2795
+#, c-format
+msgid "updates on slices of fixed-length arrays not implemented"
+msgstr "고정된 크기의 배열의 조각을 업데이트 하는 기능은 구현되지 않았습니다."
+
+#: utils/adt/arrayfuncs.c:2826
+#, c-format
+msgid "array slice subscript must provide both boundaries"
+msgstr "배열 나누기 서브스크립트는 반드시 둘다 범위안에 있어야 합니다"
+
+#: utils/adt/arrayfuncs.c:2827
+#, c-format
+msgid ""
+"When assigning to a slice of an empty array value, slice boundaries must be "
+"fully specified."
+msgstr ""
+
+#: utils/adt/arrayfuncs.c:2838 utils/adt/arrayfuncs.c:2933
+#, c-format
+msgid "source array too small"
+msgstr "원본 배열이 너무 작습니다."
+
+#: utils/adt/arrayfuncs.c:3513
+#, c-format
+msgid "null array element not allowed in this context"
+msgstr "이 구문에서는 배열의 null 요소를 허용하지 않습니다"
+
+#: utils/adt/arrayfuncs.c:3615 utils/adt/arrayfuncs.c:3786
+#: utils/adt/arrayfuncs.c:4060
+#, c-format
+msgid "cannot compare arrays of different element types"
+msgstr "배열 요소 자료형이 서로 틀린 배열은 비교할 수 없습니다."
+
+#: utils/adt/arrayfuncs.c:3962 utils/adt/rangetypes.c:1253
+#, c-format
+msgid "could not identify a hash function for type %s"
+msgstr "%s 자료형에서 사용할 해쉬함수를 찾을 수 없습니다."
+
+#: utils/adt/arrayfuncs.c:5154
+#, c-format
+msgid "data type %s is not an array type"
+msgstr "%s 자료형은 배열이 아닙니다."
+
+#: utils/adt/arrayfuncs.c:5209
+#, c-format
+msgid "cannot accumulate null arrays"
+msgstr "null 배열을 누적할 수 없음"
+
+#: utils/adt/arrayfuncs.c:5237
+#, c-format
+msgid "cannot accumulate empty arrays"
+msgstr "빈 배열을 누적할 수 없음"
+
+#: utils/adt/arrayfuncs.c:5266 utils/adt/arrayfuncs.c:5272
+#, c-format
+msgid "cannot accumulate arrays of different dimensionality"
+msgstr "배열 차수가 서로 틀린 배열은 누적할 수 없음"
+
+#: utils/adt/arrayfuncs.c:5638 utils/adt/arrayfuncs.c:5678
+#, c-format
+msgid "dimension array or low bound array cannot be null"
+msgstr "차원 배열 또는 하한 배열은 NULL일 수 없음"
+
+#: utils/adt/arrayfuncs.c:5741 utils/adt/arrayfuncs.c:5767
+#, c-format
+msgid "Dimension array must be one dimensional."
+msgstr "차원 배열은 일차원 배열이어야 합니다."
+
+#: utils/adt/arrayfuncs.c:5746 utils/adt/arrayfuncs.c:5772
+#, c-format
+msgid "dimension values cannot be null"
+msgstr "차원 값은 null일 수 없음"
+
+#: utils/adt/arrayfuncs.c:5778
+#, c-format
+msgid "Low bound array has different size than dimensions array."
+msgstr "하한 배열의 크기가 차원 배열과 다릅니다."
+
+#: utils/adt/arrayfuncs.c:6024
+#, c-format
+msgid "removing elements from multidimensional arrays is not supported"
+msgstr "다차원 배열에서 요소 삭제기능은 지원되지 않음"
+
+#: utils/adt/arrayfuncs.c:6301
+#, c-format
+msgid "thresholds must be one-dimensional array"
+msgstr "threshold 값은 1차원 배열이어야 합니다."
+
+#: utils/adt/arrayfuncs.c:6306
+#, c-format
+msgid "thresholds array must not contain NULLs"
+msgstr "threshold 배열에는 null이 포함되지 않아야 함"
+
+#: utils/adt/arrayutils.c:209
+#, c-format
+msgid "typmod array must be type cstring[]"
+msgstr "typmod 배열은 cstring[] 형식이어야 함"
+
+#: utils/adt/arrayutils.c:214
+#, c-format
+msgid "typmod array must be one-dimensional"
+msgstr "typmod 배열은 일차원 배열이어야 함"
+
+#: utils/adt/arrayutils.c:219
+#, c-format
+msgid "typmod array must not contain nulls"
+msgstr "typmod 배열에는 null이 포함되지 않아야 함"
+
+#: utils/adt/ascii.c:75
+#, c-format
+msgid "encoding conversion from %s to ASCII not supported"
+msgstr "%s 인코딩을 ASCII 인코딩으로의 변환은 지원하지 않습니다."
+
+#: utils/adt/bool.c:153
+#, c-format
+msgid "invalid input syntax for type boolean: \"%s\""
+msgstr "boolean 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/cash.c:246
+#, c-format
+msgid "invalid input syntax for type money: \"%s\""
+msgstr "money 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/cash.c:607 utils/adt/cash.c:657 utils/adt/cash.c:708
+#: utils/adt/cash.c:757 utils/adt/cash.c:809 utils/adt/cash.c:859
+#: utils/adt/float.c:855 utils/adt/float.c:919 utils/adt/float.c:3315
+#: utils/adt/float.c:3378 utils/adt/geo_ops.c:4093 utils/adt/int.c:719
+#: utils/adt/int.c:861 utils/adt/int.c:969 utils/adt/int.c:1058
+#: utils/adt/int.c:1097 utils/adt/int.c:1125 utils/adt/int8.c:597
+#: utils/adt/int8.c:657 utils/adt/int8.c:897 utils/adt/int8.c:1005
+#: utils/adt/int8.c:1094 utils/adt/int8.c:1202 utils/adt/numeric.c:6818
+#: utils/adt/numeric.c:7107 utils/adt/numeric.c:8120
+#: utils/adt/timestamp.c:3499
+#, c-format
+msgid "division by zero"
+msgstr "0으로는 나눌수 없습니다."
+
+#: utils/adt/char.c:169
+#, c-format
+msgid "\"char\" out of range"
+msgstr "\"char\" 범위를 벗어났습니다."
+
+#: utils/adt/date.c:67 utils/adt/timestamp.c:94 utils/adt/varbit.c:52
+#: utils/adt/varchar.c:45
+#, c-format
+msgid "invalid type modifier"
+msgstr "잘못된 자료형 한정자"
+
+#: utils/adt/date.c:72
+#, c-format
+msgid "TIME(%d)%s precision must not be negative"
+msgstr "TIME(%d)%s 정밀도로 음수를 사용할 수 없습니다"
+
+#: utils/adt/date.c:78
+#, c-format
+msgid "TIME(%d)%s precision reduced to maximum allowed, %d"
+msgstr "TIME(%d)%s 정밀도는 최대값(%d)으로 줄였습니다"
+
+#: utils/adt/date.c:141 utils/adt/datetime.c:1278 utils/adt/datetime.c:2191
+#, c-format
+msgid "date/time value \"current\" is no longer supported"
+msgstr "날자와 시간 입력을 위한 \"current\" 는 더이상 지원하지 않습니다."
+
+#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:3529
+#: utils/adt/formatting.c:3538
+#, c-format
+msgid "date out of range: \"%s\""
+msgstr "날짜 범위가 벗어났음: \"%s\""
+
+#: utils/adt/date.c:222 utils/adt/date.c:456 utils/adt/date.c:480
+#: utils/adt/xml.c:2027
+#, c-format
+msgid "date out of range"
+msgstr "날짜가 범위를 벗어남"
+
+#: utils/adt/date.c:264 utils/adt/timestamp.c:593
+#, c-format
+msgid "date field value out of range: %d-%02d-%02d"
+msgstr "날짜 필드의 값이 범위를 벗어남: %d-%02d-%02d"
+
+#: utils/adt/date.c:271 utils/adt/date.c:280 utils/adt/timestamp.c:599
+#, c-format
+msgid "date out of range: %d-%02d-%02d"
+msgstr "날짜 범위가 벗어났음: %d-%02d-%02d"
+
+#: utils/adt/date.c:431
+#, c-format
+msgid "cannot subtract infinite dates"
+msgstr "무한 날짜를 뺄 수 없음"
+
+#: utils/adt/date.c:509 utils/adt/date.c:544 utils/adt/date.c:566
+#: utils/adt/date.c:2629 utils/adt/date.c:2643
+#, c-format
+msgid "date out of range for timestamp"
+msgstr "날짜가 타임스탬프 범위를 벗어남"
+
+#: utils/adt/date.c:1022 utils/adt/date.c:1068 utils/adt/date.c:1678
+#: utils/adt/date.c:1714 utils/adt/date.c:1748 utils/adt/date.c:2592
+#: utils/adt/datetime.c:1759 utils/adt/formatting.c:3404
+#: utils/adt/formatting.c:3436 utils/adt/formatting.c:3504
+#: utils/adt/json.c:1534 utils/adt/json.c:1556 utils/adt/jsonb.c:823
+#: utils/adt/jsonb.c:847 utils/adt/nabstime.c:455 utils/adt/nabstime.c:498
+#: utils/adt/nabstime.c:528 utils/adt/nabstime.c:571 utils/adt/timestamp.c:224
+#: utils/adt/timestamp.c:268 utils/adt/timestamp.c:726
+#: utils/adt/timestamp.c:735 utils/adt/timestamp.c:817
+#: utils/adt/timestamp.c:857 utils/adt/timestamp.c:3074
+#: utils/adt/timestamp.c:3095 utils/adt/timestamp.c:3108
+#: utils/adt/timestamp.c:3117 utils/adt/timestamp.c:3125
+#: utils/adt/timestamp.c:3180 utils/adt/timestamp.c:3203
+#: utils/adt/timestamp.c:3216 utils/adt/timestamp.c:3227
+#: utils/adt/timestamp.c:3235 utils/adt/timestamp.c:3809
+#: utils/adt/timestamp.c:3938 utils/adt/timestamp.c:3979
+#: utils/adt/timestamp.c:4067 utils/adt/timestamp.c:4113
+#: utils/adt/timestamp.c:4224 utils/adt/timestamp.c:4631
+#: utils/adt/timestamp.c:4747 utils/adt/timestamp.c:4757
+#: utils/adt/timestamp.c:4853 utils/adt/timestamp.c:4972
+#: utils/adt/timestamp.c:4982 utils/adt/timestamp.c:5234
+#: utils/adt/timestamp.c:5248 utils/adt/timestamp.c:5253
+#: utils/adt/timestamp.c:5267 utils/adt/timestamp.c:5316
+#: utils/adt/timestamp.c:5348 utils/adt/timestamp.c:5355
+#: utils/adt/timestamp.c:5381 utils/adt/timestamp.c:5385
+#: utils/adt/timestamp.c:5454 utils/adt/timestamp.c:5458
+#: utils/adt/timestamp.c:5472 utils/adt/timestamp.c:5510 utils/adt/xml.c:2049
+#: utils/adt/xml.c:2056 utils/adt/xml.c:2076 utils/adt/xml.c:2083
+#, c-format
+msgid "timestamp out of range"
+msgstr "타임스탬프 범위를 벗어남"
+
+#: utils/adt/date.c:1094
+#, c-format
+msgid "cannot convert reserved abstime value to date"
+msgstr "예약된 abstime 값을 date로 형변환할 수 없습니다."
+
+#: utils/adt/date.c:1112 utils/adt/date.c:1118
+#, c-format
+msgid "abstime out of range for date"
+msgstr "abstime의 날짜값이 범위를 벗어남"
+
+#: utils/adt/date.c:1258 utils/adt/date.c:1265 utils/adt/date.c:2082
+#: utils/adt/date.c:2089
+#, c-format
+msgid "time out of range"
+msgstr "시간 범위를 벗어남"
+
+#: utils/adt/date.c:1326 utils/adt/timestamp.c:618
+#, c-format
+msgid "time field value out of range: %d:%02d:%02g"
+msgstr "시간 필드의 값이 범위를 벗어남: %d:%02d:%02g"
+
+#: utils/adt/date.c:1960 utils/adt/date.c:1977
+#, c-format
+msgid "\"time\" units \"%s\" not recognized"
+msgstr "\"%s\" 는 \"time\" 자료형 단위가 아닙니다."
+
+#: utils/adt/date.c:2098
+#, c-format
+msgid "time zone displacement out of range"
+msgstr "타임 존 변위가 범위를 벗어남"
+
+#: utils/adt/date.c:2740 utils/adt/date.c:2757
+#, c-format
+msgid "\"time with time zone\" units \"%s\" not recognized"
+msgstr "\"%s\" 는 \"time with time zone\" 자료형의 단위가 아닙니다."
+
+#: utils/adt/date.c:2830 utils/adt/datetime.c:995 utils/adt/datetime.c:1917
+#: utils/adt/datetime.c:4743 utils/adt/timestamp.c:532
+#: utils/adt/timestamp.c:559 utils/adt/timestamp.c:5259
+#: utils/adt/timestamp.c:5464
+#, c-format
+msgid "time zone \"%s\" not recognized"
+msgstr "\"%s\" 이름의 시간대는 없습니다."
+
+#: utils/adt/date.c:2870 utils/adt/timestamp.c:5301 utils/adt/timestamp.c:5495
+#, c-format
+msgid "interval time zone \"%s\" must not include months or days"
+msgstr ""
+"\"%s\" 시간대 간격(interval time zone) 값으로 달(month) 또는 일(day)을 포함"
+"할 수 없습니다"
+
+#: utils/adt/datetime.c:3878 utils/adt/datetime.c:3885
+#, c-format
+msgid "date/time field value out of range: \"%s\""
+msgstr "날짜/시간 필드의 값이 범위를 벗어남: \"%s\""
+
+#: utils/adt/datetime.c:3887
+#, c-format
+msgid "Perhaps you need a different \"datestyle\" setting."
+msgstr "날짜 표현 방식(\"datestyle\")을 다른 것으로 사용하고 있는 듯 합니다."
+
+#: utils/adt/datetime.c:3892
+#, c-format
+msgid "interval field value out of range: \"%s\""
+msgstr "interval 필드의 값이 범위를 벗어남: \"%s\""
+
+#: utils/adt/datetime.c:3898
+#, c-format
+msgid "time zone displacement out of range: \"%s\""
+msgstr "표준시간대 범위를 벗어남: \"%s\""
+
+#. translator: first %s is inet or cidr
+#: utils/adt/datetime.c:3905 utils/adt/float.c:461 utils/adt/float.c:544
+#: utils/adt/float.c:570 utils/adt/geo_ops.c:156 utils/adt/geo_ops.c:166
+#: utils/adt/geo_ops.c:178 utils/adt/geo_ops.c:210 utils/adt/geo_ops.c:255
+#: utils/adt/geo_ops.c:265 utils/adt/geo_ops.c:935 utils/adt/geo_ops.c:1321
+#: utils/adt/geo_ops.c:1356 utils/adt/geo_ops.c:1364 utils/adt/geo_ops.c:3430
+#: utils/adt/geo_ops.c:4563 utils/adt/geo_ops.c:4579 utils/adt/geo_ops.c:4586
+#: utils/adt/network.c:58
+#, c-format
+msgid "invalid input syntax for type %s: \"%s\""
+msgstr "%s 자료형 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/datetime.c:4745
+#, c-format
+msgid ""
+"This time zone name appears in the configuration file for time zone "
+"abbreviation \"%s\"."
+msgstr ""
+
+#: utils/adt/datum.c:86 utils/adt/datum.c:98
+#, c-format
+msgid "invalid Datum pointer"
+msgstr "잘못된 Datum 포인터"
+
+#: utils/adt/dbsize.c:110
+#, c-format
+msgid "could not open tablespace directory \"%s\": %m"
+msgstr "\"%s\" 테이블 스페이스 디렉터리 열 수 없음: %m"
+
+#: utils/adt/dbsize.c:757 utils/adt/dbsize.c:825
+#, c-format
+msgid "invalid size: \"%s\""
+msgstr "잘못된 크기: \"%s\""
+
+#: utils/adt/dbsize.c:826
+#, c-format
+msgid "Invalid size unit: \"%s\"."
+msgstr "잘못된 크기 단위: \"%s\""
+
+#: utils/adt/dbsize.c:827
+#, c-format
+msgid "Valid units are \"bytes\", \"kB\", \"MB\", \"GB\", and \"TB\"."
+msgstr ""
+"이 매개 변수에 유효한 단위는 \"bytes\",\"kB\", \"MB\", \"GB\", \"TB\"입니다."
+
+#: utils/adt/domains.c:86
+#, c-format
+msgid "type %s is not a domain"
+msgstr "%s 자료형은 도메인이 아닙니다"
+
+#: utils/adt/encode.c:55 utils/adt/encode.c:91
+#, c-format
+msgid "unrecognized encoding: \"%s\""
+msgstr "알 수 없는 인코딩: \"%s\""
+
+#: utils/adt/encode.c:150
+#, c-format
+msgid "invalid hexadecimal digit: \"%c\""
+msgstr "잘못된 16진수: \"%c\""
+
+#: utils/adt/encode.c:178
+#, c-format
+msgid "invalid hexadecimal data: odd number of digits"
+msgstr "잘못된 16진수 데이터: 데이터의 길이가 홀수 입니다."
+
+#: utils/adt/encode.c:295
+#, c-format
+msgid "unexpected \"=\" while decoding base64 sequence"
+msgstr "base64 자료를 디코딩 하는 중 예상치 못한 \"=\" 문자 발견"
+
+#: utils/adt/encode.c:307
+#, c-format
+msgid "invalid symbol \"%c\" while decoding base64 sequence"
+msgstr "base64 자료를 디코딩 하는 중 잘못된 \"%c\" 기호 발견"
+
+#: utils/adt/encode.c:327
+#, c-format
+msgid "invalid base64 end sequence"
+msgstr "base64 마침 조합이 잘못되었음"
+
+#: utils/adt/encode.c:328
+#, c-format
+msgid "Input data is missing padding, is truncated, or is otherwise corrupted."
+msgstr "입력값에 여백 처리값이 빠졌거나, 자료가 손상되었습니다."
+
+#: utils/adt/encode.c:442 utils/adt/encode.c:507 utils/adt/varlena.c:297
+#: utils/adt/varlena.c:338
+#, c-format
+msgid "invalid input syntax for type bytea"
+msgstr "bytea 자료형에 대한 잘못된 입력"
+
+#: utils/adt/enum.c:48 utils/adt/enum.c:58 utils/adt/enum.c:113
+#: utils/adt/enum.c:123
+#, c-format
+msgid "invalid input value for enum %s: \"%s\""
+msgstr "%s 열거형의 입력 값이 잘못됨: \"%s\""
+
+#: utils/adt/enum.c:85 utils/adt/enum.c:148 utils/adt/enum.c:198
+#, c-format
+msgid "invalid internal value for enum: %u"
+msgstr "열거형의 내부 값이 잘못됨: %u"
+
+#: utils/adt/enum.c:356 utils/adt/enum.c:385 utils/adt/enum.c:425
+#: utils/adt/enum.c:445
+#, c-format
+msgid "could not determine actual enum type"
+msgstr "실제 열거형의 자료형을 확인할 수 없음"
+
+#: utils/adt/enum.c:364 utils/adt/enum.c:393
+#, c-format
+msgid "enum %s contains no values"
+msgstr "\"%s\" 열거형 자료에 값이 없음"
+
+#: utils/adt/float.c:58
+#, c-format
+msgid "value out of range: overflow"
+msgstr "값이 범위를 벗어남: 오버플로"
+
+#: utils/adt/float.c:63
+#, c-format
+msgid "value out of range: underflow"
+msgstr "값이 범위를 벗어남: 언더플로"
+
+#: utils/adt/float.c:244 utils/adt/float.c:318 utils/adt/float.c:342
+#, c-format
+msgid "invalid input syntax for type real: \"%s\""
+msgstr "real 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/float.c:312
+#, c-format
+msgid "\"%s\" is out of range for type real"
+msgstr "\"%s\"는 real 자료형의 범위를 벗어납니다."
+
+#: utils/adt/float.c:537
+#, c-format
+msgid "\"%s\" is out of range for type double precision"
+msgstr "\"%s\"는 double precision 자료형의 범위를 벗어납니다."
+
+#: utils/adt/float.c:1246 utils/adt/float.c:1304 utils/adt/int.c:349
+#: utils/adt/int.c:775 utils/adt/int.c:804 utils/adt/int.c:825
+#: utils/adt/int.c:845 utils/adt/int.c:879 utils/adt/int.c:1174
+#: utils/adt/int8.c:1323 utils/adt/numeric.c:3000 utils/adt/numeric.c:3009
+#, c-format
+msgid "smallint out of range"
+msgstr "smallint의 범위를 벗어났습니다."
+
+#: utils/adt/float.c:1430 utils/adt/numeric.c:7540
+#, c-format
+msgid "cannot take square root of a negative number"
+msgstr "음수의 제곱근을 구할 수 없습니다."
+
+#: utils/adt/float.c:1472 utils/adt/numeric.c:2803
+#, c-format
+msgid "zero raised to a negative power is undefined"
+msgstr "0의 음수 거듭제곱이 정의되어 있지 않음"
+
+#: utils/adt/float.c:1476 utils/adt/numeric.c:2809
+#, c-format
+msgid "a negative number raised to a non-integer power yields a complex result"
+msgstr "음수의 비정수 거듭제곱을 계산하면 복잡한 결과가 생성됨"
+
+#: utils/adt/float.c:1542 utils/adt/float.c:1572 utils/adt/numeric.c:7806
+#, c-format
+msgid "cannot take logarithm of zero"
+msgstr "0의 대수를 구할 수 없습니다."
+
+#: utils/adt/float.c:1546 utils/adt/float.c:1576 utils/adt/numeric.c:7810
+#, c-format
+msgid "cannot take logarithm of a negative number"
+msgstr "음수의 대수를 구할 수 없습니다."
+
+#: utils/adt/float.c:1606 utils/adt/float.c:1636 utils/adt/float.c:1728
+#: utils/adt/float.c:1754 utils/adt/float.c:1781 utils/adt/float.c:1807
+#: utils/adt/float.c:1954 utils/adt/float.c:1989 utils/adt/float.c:2153
+#: utils/adt/float.c:2207 utils/adt/float.c:2271 utils/adt/float.c:2326
+#, c-format
+msgid "input is out of range"
+msgstr "입력값이 범위를 벗어났습니다."
+
+#: utils/adt/float.c:3532 utils/adt/numeric.c:1443
+#, c-format
+msgid "count must be greater than zero"
+msgstr "카운트 값은 0 보다 커야합니다"
+
+#: utils/adt/float.c:3537 utils/adt/numeric.c:1450
+#, c-format
+msgid "operand, lower bound, and upper bound cannot be NaN"
+msgstr "피연산자, 하한 및 상한은 NaN일 수 없음"
+
+#: utils/adt/float.c:3543
+#, c-format
+msgid "lower and upper bounds must be finite"
+msgstr "하한 및 상한은 유한한 값이어야 함"
+
+#: utils/adt/float.c:3581 utils/adt/numeric.c:1463
+#, c-format
+msgid "lower bound cannot equal upper bound"
+msgstr "하한값은 상한값과 같을 수 없습니다"
+
+#: utils/adt/formatting.c:485
+#, c-format
+msgid "invalid format specification for an interval value"
+msgstr "간격 값에 대한 형식 지정이 잘못됨"
+
+#: utils/adt/formatting.c:486
+#, c-format
+msgid "Intervals are not tied to specific calendar dates."
+msgstr "간격이 특정 달력 날짜에 연결되어 있지 않습니다."
+
+#: utils/adt/formatting.c:1058
+#, c-format
+msgid "\"EEEE\" must be the last pattern used"
+msgstr ""
+
+#: utils/adt/formatting.c:1066
+#, c-format
+msgid "\"9\" must be ahead of \"PR\""
+msgstr "???\"9\"는 \"PR\" 앞이어야 한다."
+
+#: utils/adt/formatting.c:1082
+#, c-format
+msgid "\"0\" must be ahead of \"PR\""
+msgstr "???\"0\"은 \"PR\" 앞이어야 한다."
+
+#: utils/adt/formatting.c:1109
+#, c-format
+msgid "multiple decimal points"
+msgstr "???여러개의 소숫점"
+
+#: utils/adt/formatting.c:1113 utils/adt/formatting.c:1196
+#, c-format
+msgid "cannot use \"V\" and decimal point together"
+msgstr "\"V\" 와 소숫점을 함께 쓸 수 없습니다."
+
+#: utils/adt/formatting.c:1125
+#, c-format
+msgid "cannot use \"S\" twice"
+msgstr "\"S\"를 두 번 사용할 수 없음"
+
+#: utils/adt/formatting.c:1129
+#, c-format
+msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together"
+msgstr "\"S\" 와 \"PL\"/\"MI\"/\"SG\"/\"PR\" 를 함께 쓸 수 없습니다."
+
+#: utils/adt/formatting.c:1149
+#, c-format
+msgid "cannot use \"S\" and \"MI\" together"
+msgstr "\"S\" 와 \"MI\" 를 함께 쓸 수 없습니다."
+
+#: utils/adt/formatting.c:1159
+#, c-format
+msgid "cannot use \"S\" and \"PL\" together"
+msgstr "\"S\" 와 \"PL\" 를 함께 쓸 수 없습니다."
+
+#: utils/adt/formatting.c:1169
+#, c-format
+msgid "cannot use \"S\" and \"SG\" together"
+msgstr "\"S\" 와 \"SG\" 를 함께 쓸 수 없습니다."
+
+#: utils/adt/formatting.c:1178
+#, c-format
+msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together"
+msgstr "\"PR\" 와 \"S\"/\"PL\"/\"MI\"/\"SG\" 를 함께 쓸 수 없습니다."
+
+#: utils/adt/formatting.c:1204
+#, c-format
+msgid "cannot use \"EEEE\" twice"
+msgstr "\"EEEE\"를 두 번 사용할 수 없음"
+
+#: utils/adt/formatting.c:1210
+#, c-format
+msgid "\"EEEE\" is incompatible with other formats"
+msgstr "\"EEEE\"는 다른 포맷과 호환하지 않습니다"
+
+#: utils/adt/formatting.c:1211
+#, c-format
+msgid ""
+"\"EEEE\" may only be used together with digit and decimal point patterns."
+msgstr ""
+
+#: utils/adt/formatting.c:1411
+#, c-format
+msgid "\"%s\" is not a number"
+msgstr "\"%s\"는 숫자가 아닙니다."
+
+#: utils/adt/formatting.c:1512 utils/adt/formatting.c:1564
+#, c-format
+msgid "could not determine which collation to use for lower() function"
+msgstr "lower() 함수에서 사용할 정렬규칙(collation)을 결정할 수 없음"
+
+#: utils/adt/formatting.c:1632 utils/adt/formatting.c:1684
+#, c-format
+msgid "could not determine which collation to use for upper() function"
+msgstr "upper() 함수에서 사용할 정렬규칙(collation)을 결정할 수 없음"
+
+#: utils/adt/formatting.c:1753 utils/adt/formatting.c:1817
+#, c-format
+msgid "could not determine which collation to use for initcap() function"
+msgstr "initcap() 함수에서 사용할 정렬규칙(collation)을 결정할 수 없음"
+
+#: utils/adt/formatting.c:2114
+#, c-format
+msgid "invalid combination of date conventions"
+msgstr "날짜 변환을 위한 잘못된 조합"
+
+#: utils/adt/formatting.c:2115
+#, c-format
+msgid ""
+"Do not mix Gregorian and ISO week date conventions in a formatting template."
+msgstr ""
+"형식 템플릿에 그레고리오력과 ISO week date 변환을 함께 사용하지 마십시오."
+
+#: utils/adt/formatting.c:2132
+#, c-format
+msgid "conflicting values for \"%s\" field in formatting string"
+msgstr "형식 문자열에서 \"%s\" 필드의 값이 충돌함"
+
+#: utils/adt/formatting.c:2134
+#, c-format
+msgid "This value contradicts a previous setting for the same field type."
+msgstr "이 값은 동일한 필드 형식의 이전 설정과 모순됩니다."
+
+#: utils/adt/formatting.c:2195
+#, c-format
+msgid "source string too short for \"%s\" formatting field"
+msgstr "소스 문자열이 너무 짧아서 \"%s\" 형식 필드에 사용할 수 없음"
+
+#: utils/adt/formatting.c:2197
+#, c-format
+msgid "Field requires %d characters, but only %d remain."
+msgstr "필드에 %d자가 필요한데 %d자만 남았습니다."
+
+#: utils/adt/formatting.c:2200 utils/adt/formatting.c:2214
+#, c-format
+msgid ""
+"If your source string is not fixed-width, try using the \"FM\" modifier."
+msgstr "소스 문자열이 고정 너비가 아닌 경우 \"FM\" 한정자를 사용해 보십시오."
+
+#: utils/adt/formatting.c:2210 utils/adt/formatting.c:2223
+#: utils/adt/formatting.c:2353
+#, c-format
+msgid "invalid value \"%s\" for \"%s\""
+msgstr "\"%s\" 값은 \"%s\"에 유효하지 않음"
+
+#: utils/adt/formatting.c:2212
+#, c-format
+msgid "Field requires %d characters, but only %d could be parsed."
+msgstr "필드에 %d자가 필요한데 %d자만 구문 분석할 수 있습니다."
+
+#: utils/adt/formatting.c:2225
+#, c-format
+msgid "Value must be an integer."
+msgstr "값은 정수여야 합니다."
+
+#: utils/adt/formatting.c:2230
+#, c-format
+msgid "value for \"%s\" in source string is out of range"
+msgstr "소스 문자열의 \"%s\" 값이 범위를 벗어남"
+
+#: utils/adt/formatting.c:2232
+#, c-format
+msgid "Value must be in the range %d to %d."
+msgstr "값은 %d에서 %d 사이의 범위에 있어야 합니다."
+
+#: utils/adt/formatting.c:2355
+#, c-format
+msgid "The given value did not match any of the allowed values for this field."
+msgstr "지정된 값이 이 필드에 허용되는 값과 일치하지 않습니다."
+
+#: utils/adt/formatting.c:2550 utils/adt/formatting.c:2570
+#: utils/adt/formatting.c:2590 utils/adt/formatting.c:2610
+#: utils/adt/formatting.c:2629 utils/adt/formatting.c:2648
+#: utils/adt/formatting.c:2672 utils/adt/formatting.c:2690
+#: utils/adt/formatting.c:2708 utils/adt/formatting.c:2726
+#: utils/adt/formatting.c:2743 utils/adt/formatting.c:2760
+#, c-format
+msgid "localized string format value too long"
+msgstr ""
+
+#: utils/adt/formatting.c:3047
+#, c-format
+msgid "\"TZ\"/\"tz\"/\"OF\" format patterns are not supported in to_date"
+msgstr "\"TZ\"/\"tz\"\"OF\" 형식 패턴은 to_date에서 지원되지 않음"
+
+#: utils/adt/formatting.c:3156
+#, c-format
+msgid "invalid input string for \"Y,YYY\""
+msgstr "\"Y,YYY\"에 대한 입력 문자열이 잘못됨"
+
+#: utils/adt/formatting.c:3668
+#, c-format
+msgid "hour \"%d\" is invalid for the 12-hour clock"
+msgstr "시간 \"%d\"은(는) 12시간제에 유효하지 않음"
+
+#: utils/adt/formatting.c:3670
+#, c-format
+msgid "Use the 24-hour clock, or give an hour between 1 and 12."
+msgstr "24시간제를 사용하거나 1에서 12 사이의 시간을 지정하십시오."
+
+#: utils/adt/formatting.c:3765
+#, c-format
+msgid "cannot calculate day of year without year information"
+msgstr "연도 정보 없이 몇번째 날(day of year) 인지 계산할 수 없습니다."
+
+#: utils/adt/formatting.c:4614
+#, c-format
+msgid "\"EEEE\" not supported for input"
+msgstr "\"EEEE\" 입력 양식은 지원되지 않습니다."
+
+#: utils/adt/formatting.c:4626
+#, c-format
+msgid "\"RN\" not supported for input"
+msgstr "\"RN\" 입력 양식은 지원되지 않습니다."
+
+#: utils/adt/genfile.c:62
+#, c-format
+msgid "reference to parent directory (\"..\") not allowed"
+msgstr "상위 디렉터리(\"..\") 참조는 허용되지 않음"
+
+#: utils/adt/genfile.c:73
+#, c-format
+msgid "absolute path not allowed"
+msgstr "절대 경로는 허용하지 않음"
+
+#: utils/adt/genfile.c:78
+#, c-format
+msgid "path must be in or below the current directory"
+msgstr "경로는 현재 디렉토리와 그 하위 디렉터리여야 합니다."
+
+#: utils/adt/genfile.c:125 utils/adt/oracle_compat.c:184
+#: utils/adt/oracle_compat.c:282 utils/adt/oracle_compat.c:758
+#: utils/adt/oracle_compat.c:1059
+#, c-format
+msgid "requested length too large"
+msgstr "요청된 길이가 너무 깁니다"
+
+#: utils/adt/genfile.c:142
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "\"%s\" 파일에서 seek 작업을 할 수 없음: %m"
+
+#: utils/adt/genfile.c:200 utils/adt/genfile.c:241
+#, c-format
+msgid "must be superuser to read files"
+msgstr "파일을 읽으려면 슈퍼유져여야함"
+
+#: utils/adt/genfile.c:318
+#, c-format
+msgid "must be superuser to get file information"
+msgstr "파일 정보를 보려면 superuser여야함"
+
+#: utils/adt/genfile.c:404
+#, c-format
+msgid "must be superuser to get directory listings"
+msgstr "디렉터리 목록을 보려면 superuser여야함"
+
+#: utils/adt/geo_ops.c:940
+#, c-format
+msgid "invalid line specification: A and B cannot both be zero"
+msgstr "선 정의가 잘못됨: A와 B 둘다 0일 수는 없음"
+
+#: utils/adt/geo_ops.c:948
+#, c-format
+msgid "invalid line specification: must be two distinct points"
+msgstr "선 정의가 잘못된: 두 점은 서로 다른 위치여야 함"
+
+#: utils/adt/geo_ops.c:1342 utils/adt/geo_ops.c:3440 utils/adt/geo_ops.c:4253
+#: utils/adt/geo_ops.c:5181
+#, c-format
+msgid "too many points requested"
+msgstr "너무 많은 점들이 요청되었습니다."
+
+#: utils/adt/geo_ops.c:1404
+#, c-format
+msgid "invalid number of points in external \"path\" value"
+msgstr "???\"path\" 의 값에 잘못된 갯수의 point들"
+
+#: utils/adt/geo_ops.c:2555
+#, c-format
+msgid "function \"dist_lb\" not implemented"
+msgstr "\"dist_lb\" 함수는 구현되지 않았습니다."
+
+#: utils/adt/geo_ops.c:3015
+#, c-format
+msgid "function \"close_sl\" not implemented"
+msgstr "\"close_sl\" 함수는 구현되지 않았습니다."
+
+#: utils/adt/geo_ops.c:3117
+#, c-format
+msgid "function \"close_lb\" not implemented"
+msgstr "\"close_lb\" 함수는 구현되지 않았습니다."
+
+#: utils/adt/geo_ops.c:3406
+#, c-format
+msgid "cannot create bounding box for empty polygon"
+msgstr "???폴리곤 없이 닫힌 상자를 생성할 수 없습니다."
+
+#: utils/adt/geo_ops.c:3487
+#, c-format
+msgid "invalid number of points in external \"polygon\" value"
+msgstr "???\"polygon\" 값에 잘못된 갯수의 point들"
+
+#: utils/adt/geo_ops.c:4012
+#, c-format
+msgid "function \"poly_distance\" not implemented"
+msgstr "\"poly_distance\" 함수는 구현되지 않았습니다."
+
+#: utils/adt/geo_ops.c:4365
+#, c-format
+msgid "function \"path_center\" not implemented"
+msgstr "\"path_center\" 함수는 구현되지 않았습니다."
+
+#: utils/adt/geo_ops.c:4382
+#, c-format
+msgid "open path cannot be converted to polygon"
+msgstr "닫히지 않은 path 는 폴리곤으로 변환할 수 없습니다."
+
+#: utils/adt/geo_ops.c:4631
+#, c-format
+msgid "invalid radius in external \"circle\" value"
+msgstr "부적절한 \"circle\" 값의 반지름"
+
+#: utils/adt/geo_ops.c:5167
+#, c-format
+msgid "cannot convert circle with radius zero to polygon"
+msgstr "반지름이 0인 원은 폴리곤으로 변환할 수 없습니다."
+
+#: utils/adt/geo_ops.c:5172
+#, c-format
+msgid "must request at least 2 points"
+msgstr "적어도 2개의 point들이 필요합니다."
+
+#: utils/adt/geo_ops.c:5216
+#, c-format
+msgid "cannot convert empty polygon to circle"
+msgstr "비어있는 폴리곤을 원으로 변환할 수 없습니다."
+
+#: utils/adt/int.c:162
+#, c-format
+msgid "int2vector has too many elements"
+msgstr "int2vector 는 너무 많은 요소를 가지고 있습니다."
+
+#: utils/adt/int.c:237
+#, c-format
+msgid "invalid int2vector data"
+msgstr "잘못된 int2vector 자료"
+
+#: utils/adt/int.c:243 utils/adt/oid.c:212 utils/adt/oid.c:293
+#, c-format
+msgid "oidvector has too many elements"
+msgstr "oidvector에 너무 많은 요소가 있습니다"
+
+#: utils/adt/int.c:1362 utils/adt/int8.c:1460 utils/adt/numeric.c:1351
+#: utils/adt/timestamp.c:5561 utils/adt/timestamp.c:5642
+#, c-format
+msgid "step size cannot equal zero"
+msgstr "단계 크기는 0일 수 없음"
+
+#: utils/adt/int8.c:98 utils/adt/int8.c:133 utils/adt/numutils.c:51
+#: utils/adt/numutils.c:61 utils/adt/numutils.c:103
+#, c-format
+msgid "invalid input syntax for integer: \"%s\""
+msgstr "잘못된 integer 자료형 입력 구문: \"%s\""
+
+#: utils/adt/int8.c:114
+#, c-format
+msgid "value \"%s\" is out of range for type bigint"
+msgstr "입력한 \"%s\" 값은 bigint 자료형 범위를 초과했습니다"
+
+#: utils/adt/int8.c:500 utils/adt/int8.c:529 utils/adt/int8.c:550
+#: utils/adt/int8.c:581 utils/adt/int8.c:615 utils/adt/int8.c:640
+#: utils/adt/int8.c:697 utils/adt/int8.c:714 utils/adt/int8.c:741
+#: utils/adt/int8.c:758 utils/adt/int8.c:834 utils/adt/int8.c:855
+#: utils/adt/int8.c:882 utils/adt/int8.c:915 utils/adt/int8.c:943
+#: utils/adt/int8.c:964 utils/adt/int8.c:991 utils/adt/int8.c:1031
+#: utils/adt/int8.c:1052 utils/adt/int8.c:1079 utils/adt/int8.c:1112
+#: utils/adt/int8.c:1140 utils/adt/int8.c:1161 utils/adt/int8.c:1188
+#: utils/adt/int8.c:1361 utils/adt/int8.c:1400 utils/adt/numeric.c:2955
+#: utils/adt/varbit.c:1655
+#, c-format
+msgid "bigint out of range"
+msgstr "bigint의 범위를 벗어났습니다."
+
+#: utils/adt/int8.c:1417
+#, c-format
+msgid "OID out of range"
+msgstr "OID의 범위를 벗어났습니다."
+
+#: utils/adt/json.c:785 utils/adt/json.c:825 utils/adt/json.c:840
+#: utils/adt/json.c:851 utils/adt/json.c:861 utils/adt/json.c:912
+#: utils/adt/json.c:943 utils/adt/json.c:961 utils/adt/json.c:973
+#: utils/adt/json.c:985 utils/adt/json.c:1130 utils/adt/json.c:1144
+#: utils/adt/json.c:1155 utils/adt/json.c:1163 utils/adt/json.c:1171
+#: utils/adt/json.c:1179 utils/adt/json.c:1187 utils/adt/json.c:1195
+#: utils/adt/json.c:1203 utils/adt/json.c:1211 utils/adt/json.c:1241
+#, c-format
+msgid "invalid input syntax for type json"
+msgstr "json 자료형에 대한 잘못된 입력"
+
+#: utils/adt/json.c:786
+#, c-format
+msgid "Character with value 0x%02x must be escaped."
+msgstr ""
+
+#: utils/adt/json.c:826
+#, c-format
+msgid "\"\\u\" must be followed by four hexadecimal digits."
+msgstr "\"\\u\" 표기법은 뒤에 4개의 16진수가 와야합니다."
+
+#: utils/adt/json.c:841
+#, c-format
+msgid "Unicode high surrogate must not follow a high surrogate."
+msgstr ""
+
+#: utils/adt/json.c:852 utils/adt/json.c:862 utils/adt/json.c:913
+#: utils/adt/json.c:974 utils/adt/json.c:986
+#, c-format
+msgid "Unicode low surrogate must follow a high surrogate."
+msgstr ""
+
+#: utils/adt/json.c:877 utils/adt/json.c:900
+#, c-format
+msgid "unsupported Unicode escape sequence"
+msgstr "지원하지 않는 유니코드 이스케이프 조합"
+
+#: utils/adt/json.c:878
+#, c-format
+msgid "\\u0000 cannot be converted to text."
+msgstr "\\u0000 값은 text 형으로 변환할 수 없음."
+
+#: utils/adt/json.c:901
+#, c-format
+msgid ""
+"Unicode escape values cannot be used for code point values above 007F when "
+"the server encoding is not UTF8."
+msgstr ""
+"서버 인코딩이 UTF8이 아닌 경우 007F보다 큰 코드 지점 값에는 유니코드 이스케이"
+"프 값을 사용할 수 없음"
+
+#: utils/adt/json.c:944 utils/adt/json.c:962
+#, c-format
+msgid "Escape sequence \"\\%s\" is invalid."
+msgstr "잘못된 이스케이프 조합: \"\\%s\""
+
+#: utils/adt/json.c:1131
+#, c-format
+msgid "The input string ended unexpectedly."
+msgstr "입력 문자열이 예상치 않게 끝났음."
+
+#: utils/adt/json.c:1145
+#, c-format
+msgid "Expected end of input, but found \"%s\"."
+msgstr "입력 자료의 끝을 기대했는데, \"%s\" 값이 더 있음."
+
+#: utils/adt/json.c:1156
+#, c-format
+msgid "Expected JSON value, but found \"%s\"."
+msgstr "JSON 값을 기대했는데, \"%s\" 값임"
+
+#: utils/adt/json.c:1164 utils/adt/json.c:1212
+#, c-format
+msgid "Expected string, but found \"%s\"."
+msgstr "문자열 값을 기대했는데, \"%s\" 값임"
+
+#: utils/adt/json.c:1172
+#, c-format
+msgid "Expected array element or \"]\", but found \"%s\"."
+msgstr "\"]\" 가 필요한데 \"%s\"이(가) 있음"
+
+#: utils/adt/json.c:1180
+#, c-format
+msgid "Expected \",\" or \"]\", but found \"%s\"."
+msgstr "\",\" 또는 \"]\"가 필요한데 \"%s\"이(가) 있음"
+
+#: utils/adt/json.c:1188
+#, c-format
+msgid "Expected string or \"}\", but found \"%s\"."
+msgstr "\"}\"가 필요한데 \"%s\"이(가) 있음"
+
+#: utils/adt/json.c:1196
+#, c-format
+msgid "Expected \":\", but found \"%s\"."
+msgstr "\":\"가 필요한데 \"%s\"이(가) 있음"
+
+#: utils/adt/json.c:1204
+#, c-format
+msgid "Expected \",\" or \"}\", but found \"%s\"."
+msgstr "\",\" 또는 \"}\"가 필요한데 \"%s\"이(가) 있음"
+
+#: utils/adt/json.c:1242
+#, c-format
+msgid "Token \"%s\" is invalid."
+msgstr "잘못된 토큰: \"%s\""
+
+#: utils/adt/json.c:1314
+#, c-format
+msgid "JSON data, line %d: %s%s%s"
+msgstr "JSON 자료, %d 번째 줄: %s%s%s"
+
+#: utils/adt/json.c:1469 utils/adt/jsonb.c:724
+#, c-format
+msgid "key value must be scalar, not array, composite, or json"
+msgstr ""
+"키 값은 스칼라 형이어야 함. 배열, 복합 자료형, json 형은 사용할 수 없음"
+
+#: utils/adt/json.c:2006
+#, c-format
+msgid "could not determine data type for argument 1"
+msgstr "첫번째 매개 변수의 자료형을 알수가 없습니다."
+
+#: utils/adt/json.c:2016
+#, c-format
+msgid "could not determine data type for argument 2"
+msgstr "두번째 매개 변수의 자료형을 알수가 없습니다."
+
+#: utils/adt/json.c:2040 utils/adt/jsonb.c:1781
+#, c-format
+msgid "field name must not be null"
+msgstr "필드 이름이 null 이면 안됩니다"
+
+#: utils/adt/json.c:2117
+#, c-format
+msgid "argument list must have even number of elements"
+msgstr "인자 목록은 요소수의 짝수개여야 합니다."
+
+#: utils/adt/json.c:2118
+#, c-format
+msgid ""
+"The arguments of json_build_object() must consist of alternating keys and "
+"values."
+msgstr ""
+"json_build_object() 함수의 인자들은 각각 key, value 쌍으로 있어야 합니다."
+
+#: utils/adt/json.c:2142 utils/adt/json.c:2163 utils/adt/json.c:2222
+#, c-format
+msgid "could not determine data type for argument %d"
+msgstr "%d번째 인자의 자료형을 알수가 없습니다."
+
+#: utils/adt/json.c:2148
+#, c-format
+msgid "argument %d cannot be null"
+msgstr "%d 번째 인자는 null 이면 안됩니다"
+
+#: utils/adt/json.c:2149
+#, c-format
+msgid "Object keys should be text."
+msgstr "객체 키는 문자열이어야 합니다."
+
+#: utils/adt/json.c:2284 utils/adt/jsonb.c:1363
+#, c-format
+msgid "array must have two columns"
+msgstr "배열은 두개의 칼럼이어야 함"
+
+#: utils/adt/json.c:2308 utils/adt/json.c:2392 utils/adt/jsonb.c:1387
+#: utils/adt/jsonb.c:1482
+#, c-format
+msgid "null value not allowed for object key"
+msgstr "객체 키 값으로 null 을 허용하지 않음"
+
+#: utils/adt/json.c:2381 utils/adt/jsonb.c:1471
+#, c-format
+msgid "mismatched array dimensions"
+msgstr "배열 차수가 안맞음"
+
+#: utils/adt/jsonb.c:257
+#, c-format
+msgid "string too long to represent as jsonb string"
+msgstr "jsonb 문자열로 길이를 초과함"
+
+#: utils/adt/jsonb.c:258
+#, c-format
+msgid ""
+"Due to an implementation restriction, jsonb strings cannot exceed %d bytes."
+msgstr "구현상 제한으로 jsonb 문자열은 %d 바이트를 넘을 수 없습니다."
+
+#: utils/adt/jsonb.c:1182
+#, c-format
+msgid "invalid number of arguments: object must be matched key value pairs"
+msgstr "잘못된 인자 번호: 객체는 key - value 쌍으로 구성되어야 합니다"
+
+#: utils/adt/jsonb.c:1195
+#, c-format
+msgid "argument %d: key must not be null"
+msgstr "%d 번째 인자: 키 값은 null이면 안됩니다."
+
+#: utils/adt/jsonb.c:1214 utils/adt/jsonb.c:1237 utils/adt/jsonb.c:1297
+#, c-format
+msgid "argument %d: could not determine data type"
+msgstr "%d 번째 인자: 자료형을 파악할 수 없음"
+
+#: utils/adt/jsonb.c:1834
+#, c-format
+msgid "object keys must be strings"
+msgstr "객체 키는 문자열이어야 합니다"
+
+#: utils/adt/jsonb_util.c:656
+#, c-format
+msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)"
+msgstr "jsonb 객체 쌍의 개수가 최대치를 초과함 (%zu)"
+
+#: utils/adt/jsonb_util.c:697
+#, c-format
+msgid "number of jsonb array elements exceeds the maximum allowed (%zu)"
+msgstr "jsonb 배열 요소 개수가 최대치를 초과함 (%zu)"
+
+#: utils/adt/jsonb_util.c:1525 utils/adt/jsonb_util.c:1545
+#, c-format
+msgid "total size of jsonb array elements exceeds the maximum of %u bytes"
+msgstr "jsonb 배열 요소 총 크기가 최대치를 초과함 (%u 바이트)"
+
+#: utils/adt/jsonb_util.c:1606 utils/adt/jsonb_util.c:1641
+#: utils/adt/jsonb_util.c:1661
+#, c-format
+msgid "total size of jsonb object elements exceeds the maximum of %u bytes"
+msgstr "jsonb 객체 요소들의 총 크기가 최대치를 초과함 (%u 바이트)"
+
+#: utils/adt/jsonfuncs.c:305 utils/adt/jsonfuncs.c:470
+#: utils/adt/jsonfuncs.c:2057 utils/adt/jsonfuncs.c:2498
+#: utils/adt/jsonfuncs.c:3004
+#, c-format
+msgid "cannot call %s on a scalar"
+msgstr "스칼라형에서는 %s 호출 할 수 없음"
+
+#: utils/adt/jsonfuncs.c:310 utils/adt/jsonfuncs.c:457
+#: utils/adt/jsonfuncs.c:2487
+#, c-format
+msgid "cannot call %s on an array"
+msgstr "배열형에서는 %s 호출 할 수 없음"
+
+#: utils/adt/jsonfuncs.c:1373 utils/adt/jsonfuncs.c:1408
+#, c-format
+msgid "cannot get array length of a scalar"
+msgstr "스칼라형의 배열 길이를 구할 수 없음"
+
+#: utils/adt/jsonfuncs.c:1377 utils/adt/jsonfuncs.c:1396
+#, c-format
+msgid "cannot get array length of a non-array"
+msgstr "비배열형 자료의 배열 길이를 구할 수 없음"
+
+#: utils/adt/jsonfuncs.c:1473
+#, c-format
+msgid "cannot call %s on a non-object"
+msgstr "비객체형에서 %s 호출 할 수 없음"
+
+#: utils/adt/jsonfuncs.c:1491 utils/adt/jsonfuncs.c:2170
+#: utils/adt/jsonfuncs.c:2707
+#, c-format
+msgid ""
+"function returning record called in context that cannot accept type record"
+msgstr "반환 자료형이 record인데 함수가 그 자료형으로 반환하지 않음"
+
+#: utils/adt/jsonfuncs.c:1730
+#, c-format
+msgid "cannot deconstruct an array as an object"
+msgstr ""
+
+#: utils/adt/jsonfuncs.c:1742
+#, c-format
+msgid "cannot deconstruct a scalar"
+msgstr "스칼라형으로 재구축할 수 없음"
+
+#: utils/adt/jsonfuncs.c:1788
+#, c-format
+msgid "cannot extract elements from a scalar"
+msgstr "스칼라형에서 요소를 추출할 수 없음"
+
+#: utils/adt/jsonfuncs.c:1792
+#, c-format
+msgid "cannot extract elements from an object"
+msgstr "객체형에서 요소를 추출할 수 없음"
+
+#: utils/adt/jsonfuncs.c:2044 utils/adt/jsonfuncs.c:2803
+#, c-format
+msgid "cannot call %s on a non-array"
+msgstr "비배열형에서 %s 호출 할 수 없음"
+
+#: utils/adt/jsonfuncs.c:2131 utils/adt/jsonfuncs.c:2683
+#, c-format
+msgid "first argument of %s must be a row type"
+msgstr "%s의 첫번째 인자는 row 형이어야 합니다"
+
+#: utils/adt/jsonfuncs.c:2172
+#, c-format
+msgid ""
+"Try calling the function in the FROM clause using a column definition list."
+msgstr "함수를 호출 할 때 FROM 절에서 칼럼 정의 목록도 함께 지정해야 합니다."
+
+#: utils/adt/jsonfuncs.c:2819 utils/adt/jsonfuncs.c:2986
+#, c-format
+msgid "argument of %s must be an array of objects"
+msgstr "%s의 인자는 객체의 배열이어야 합니다"
+
+#: utils/adt/jsonfuncs.c:2843
+#, c-format
+msgid "cannot call %s on an object"
+msgstr "객체에서 %s 호출할 수 없음"
+
+#: utils/adt/jsonfuncs.c:3410 utils/adt/jsonfuncs.c:3463
+#, c-format
+msgid "cannot delete from scalar"
+msgstr "스칼라형에서 삭제 할 수 없음"
+
+#: utils/adt/jsonfuncs.c:3468
+#, c-format
+msgid "cannot delete from object using integer index"
+msgstr "인덱스 번호를 사용해서 객체에서 삭제 할 수 없음"
+
+#: utils/adt/jsonfuncs.c:3534 utils/adt/jsonfuncs.c:3626
+#, c-format
+msgid "cannot set path in scalar"
+msgstr "스칼라형에는 path 를 지정할 수 없음"
+
+#: utils/adt/jsonfuncs.c:3579
+#, c-format
+msgid "cannot delete path in scalar"
+msgstr "스칼라형에서 path를 지울 수 없음"
+
+#: utils/adt/jsonfuncs.c:3749
+#, c-format
+msgid "invalid concatenation of jsonb objects"
+msgstr "jsonb 객체들의 잘못된 결합"
+
+#: utils/adt/jsonfuncs.c:3783
+#, c-format
+msgid "path element at position %d is null"
+msgstr "%d 위치의 path 요소는 null 입니다."
+
+#: utils/adt/jsonfuncs.c:3869
+#, c-format
+msgid "cannot replace existing key"
+msgstr "이미 있는 키로는 대체할 수 없음"
+
+#: utils/adt/jsonfuncs.c:3870
+#, c-format
+msgid "Try using the function jsonb_set to replace key value."
+msgstr "키 값을 변경하려면, jsonb_set 함수를 사용하세요."
+
+#: utils/adt/jsonfuncs.c:3952
+#, c-format
+msgid "path element at position %d is not an integer: \"%s\""
+msgstr "%d 번째 위치의 path 요소는 정수가 아님: \"%s\""
+
+#: utils/adt/levenshtein.c:133
+#, c-format
+msgid "levenshtein argument exceeds maximum length of %d characters"
+msgstr "levenshtein 인자값으로 그 길이가 %d 문자의 최대 길이를 초과했음"
+
+#: utils/adt/like.c:212 utils/adt/selfuncs.c:5333
+#, c-format
+msgid "could not determine which collation to use for ILIKE"
+msgstr "ILIKE 연산에서 사용할 정렬규칙(collation)을 결정할 수 없음"
+
+#: utils/adt/like_match.c:107 utils/adt/like_match.c:167
+#, c-format
+msgid "LIKE pattern must not end with escape character"
+msgstr "LIKE 패턴은 이스케이프 문자로 끝나지 않아야 함"
+
+#: utils/adt/like_match.c:292 utils/adt/regexp.c:698
+#, c-format
+msgid "invalid escape string"
+msgstr "잘못된 이스케이프 문자열"
+
+#: utils/adt/like_match.c:293 utils/adt/regexp.c:699
+#, c-format
+msgid "Escape string must be empty or one character."
+msgstr "이스케이프 문자열은 비어있거나 한개의 문자여야 합니다."
+
+#: utils/adt/lockfuncs.c:545
+#, c-format
+msgid "cannot use advisory locks during a parallel operation"
+msgstr "병렬 작업 중에는 자문 자금을 사용할 없습니다"
+
+#: utils/adt/mac.c:68
+#, c-format
+msgid "invalid input syntax for type macaddr: \"%s\""
+msgstr "macaddr 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/mac.c:75
+#, c-format
+msgid "invalid octet value in \"macaddr\" value: \"%s\""
+msgstr "\"macaddr\"에 대한 잘못된 옥텟(octet) 값: \"%s\""
+
+#: utils/adt/misc.c:239
+#, c-format
+msgid "PID %d is not a PostgreSQL server process"
+msgstr "PID %d 프로그램은 PostgreSQL 서버 프로세스가 아닙니다"
+
+#: utils/adt/misc.c:290
+#, c-format
+msgid "must be a superuser to cancel superuser query"
+msgstr "슈퍼유저의 쿼리를 중지하려면 슈퍼유저여야 합니다."
+
+#: utils/adt/misc.c:295
+#, c-format
+msgid ""
+"must be a member of the role whose query is being canceled or member of "
+"pg_signal_backend"
+msgstr ""
+"쿼리 작업 취소하려면 작업자의 소속 맴버이거나 pg_signal_backend 소속 맴버여"
+"야 합니다"
+
+#: utils/adt/misc.c:314
+#, c-format
+msgid "must be a superuser to terminate superuser process"
+msgstr "슈퍼유저의 세션을 정리하려면 슈퍼유저여야 합니다."
+
+#: utils/adt/misc.c:319
+#, c-format
+msgid ""
+"must be a member of the role whose process is being terminated or member of "
+"pg_signal_backend"
+msgstr ""
+"세션을 종료하려면 접속자의 소속 맴버이거나 pg_signal_backend 소속 맴버여야 합"
+"니다"
+
+#: utils/adt/misc.c:336
+#, c-format
+msgid "failed to send signal to postmaster: %m"
+msgstr "postmaster로 시그널 보내기 실패: %m"
+
+#: utils/adt/misc.c:356
+#, c-format
+msgid "rotation not possible because log collection not active"
+msgstr "로그 수집이 활성 상태가 아니므로 회전할 수 없음"
+
+#: utils/adt/misc.c:393
+#, c-format
+msgid "global tablespace never has databases"
+msgstr "전역 테이블스페이스는 데이터베이스를 결코 포함하지 않습니다."
+
+#: utils/adt/misc.c:414
+#, c-format
+msgid "%u is not a tablespace OID"
+msgstr "%u 테이블스페이스 OID가 아님"
+
+#: utils/adt/misc.c:611
+msgid "unreserved"
+msgstr "예약되지 않음"
+
+#: utils/adt/misc.c:615
+msgid "unreserved (cannot be function or type name)"
+msgstr "예약되지 않음(함수, 자료형 이름일 수 없음)"
+
+#: utils/adt/misc.c:619
+msgid "reserved (can be function or type name)"
+msgstr "예약됨(함수, 자료형 이름일 수 있음)"
+
+#: utils/adt/misc.c:623
+msgid "reserved"
+msgstr "예약됨"
+
+#: utils/adt/misc.c:797 utils/adt/misc.c:811 utils/adt/misc.c:850
+#: utils/adt/misc.c:856 utils/adt/misc.c:862 utils/adt/misc.c:885
+#, c-format
+msgid "string is not a valid identifier: \"%s\""
+msgstr "문자열이 타당한 식별자가 아님: \"%s\""
+
+#: utils/adt/misc.c:799
+#, c-format
+msgid "String has unclosed double quotes."
+msgstr "문자열 표기에서 큰따옴표 짝이 안맞습니다."
+
+#: utils/adt/misc.c:813
+#, c-format
+msgid "Quoted identifier must not be empty."
+msgstr "인용부호 있는 식별자: 비어있으면 안됩니다"
+
+#: utils/adt/misc.c:852
+#, c-format
+msgid "No valid identifier before \".\"."
+msgstr "\".\" 전에 타당한 식별자가 없음"
+
+#: utils/adt/misc.c:858
+#, c-format
+msgid "No valid identifier after \".\"."
+msgstr "\".\" 뒤에 타당한 식별자 없음"
+
+#: utils/adt/nabstime.c:136
+#, c-format
+msgid "invalid time zone name: \"%s\""
+msgstr "잘못된 타임존 이름: \"%s\""
+
+#: utils/adt/nabstime.c:481 utils/adt/nabstime.c:554
+#, c-format
+msgid "cannot convert abstime \"invalid\" to timestamp"
+msgstr "\"invalid\" abstime 자료형을 timestamp 자료형으로 변환할 수 없습니다."
+
+#: utils/adt/nabstime.c:781
+#, c-format
+msgid "invalid status in external \"tinterval\" value"
+msgstr "외부 \"tinterval\" 값에 잘못된 상태가 있음"
+
+#: utils/adt/nabstime.c:855
+#, c-format
+msgid "cannot convert reltime \"invalid\" to interval"
+msgstr "reltime \"invalid\"를 interval로 변환할 수 없음"
+
+#: utils/adt/nabstime.c:1550
+#, c-format
+msgid "invalid input syntax for type tinterval: \"%s\""
+msgstr "tinterval 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/network.c:69
+#, c-format
+msgid "invalid cidr value: \"%s\""
+msgstr "cidr 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/network.c:70 utils/adt/network.c:200
+#, c-format
+msgid "Value has bits set to right of mask."
+msgstr "마스크 오른쪽에 설정된 비트가 값에 포함되어 있습니다."
+
+#: utils/adt/network.c:111 utils/adt/network.c:607 utils/adt/network.c:632
+#: utils/adt/network.c:657
+#, c-format
+msgid "could not format inet value: %m"
+msgstr "inet 값의 형식을 지정할 수 없음: %m"
+
+#. translator: %s is inet or cidr
+#: utils/adt/network.c:168
+#, c-format
+msgid "invalid address family in external \"%s\" value"
+msgstr "잘못 된 주소군 \"%s\""
+
+#. translator: %s is inet or cidr
+#: utils/adt/network.c:175
+#, c-format
+msgid "invalid bits in external \"%s\" value"
+msgstr "\"%s\" 값에 잘못된 비트가 있음"
+
+#. translator: %s is inet or cidr
+#: utils/adt/network.c:184
+#, c-format
+msgid "invalid length in external \"%s\" value"
+msgstr "외부 \"%s\" 값의 길이가 잘못 되었음"
+
+#: utils/adt/network.c:199
+#, c-format
+msgid "invalid external \"cidr\" value"
+msgstr "외부 \"cidr\" 값이 잘못됨"
+
+#: utils/adt/network.c:321 utils/adt/network.c:348
+#, c-format
+msgid "invalid mask length: %d"
+msgstr "잘못된 마스크 길이: %d"
+
+#: utils/adt/network.c:675
+#, c-format
+msgid "could not format cidr value: %m"
+msgstr "cidr 값을 처리할 수 없음: %m"
+
+#: utils/adt/network.c:917
+#, c-format
+msgid "cannot merge addresses from different families"
+msgstr "서로 다른 페밀리에서는 주소를 병합할 수 없음"
+
+#: utils/adt/network.c:1343
+#, c-format
+msgid "cannot AND inet values of different sizes"
+msgstr "서로 크기가 틀린 inet 값들은 AND 연산을 할 수 없습니다."
+
+#: utils/adt/network.c:1375
+#, c-format
+msgid "cannot OR inet values of different sizes"
+msgstr "서로 크기가 틀린 inet 값들은 OR 연산을 할 수 없습니다."
+
+#: utils/adt/network.c:1436 utils/adt/network.c:1512
+#, c-format
+msgid "result is out of range"
+msgstr "결과가 범위를 벗어났습니다."
+
+#: utils/adt/network.c:1477
+#, c-format
+msgid "cannot subtract inet values of different sizes"
+msgstr "inet 값에서 서로 크기가 틀리게 부분 추출(subtract)할 수 없음"
+
+#: utils/adt/numeric.c:542 utils/adt/numeric.c:569 utils/adt/numeric.c:5405
+#: utils/adt/numeric.c:5428 utils/adt/numeric.c:5452
+#, c-format
+msgid "invalid input syntax for type numeric: \"%s\""
+msgstr "수치 자료형의 입력 구문에 오류가 있습니다: \"%s\""
+
+#: utils/adt/numeric.c:768
+#, c-format
+msgid "invalid sign in external \"numeric\" value"
+msgstr "외부 \"numeric\" 값의 부호가 잘못됨"
+
+#: utils/adt/numeric.c:774
+#, c-format
+msgid "invalid scale in external \"numeric\" value"
+msgstr "외부 \"numeric\" 값의 잘못된 스케일"
+
+#: utils/adt/numeric.c:783
+#, c-format
+msgid "invalid digit in external \"numeric\" value"
+msgstr "외부 \"numeric\" 값의 숫자가 잘못됨"
+
+#: utils/adt/numeric.c:974 utils/adt/numeric.c:988
+#, c-format
+msgid "NUMERIC precision %d must be between 1 and %d"
+msgstr "NUMERIC 정밀도 %d 값은 범위(1 .. %d)를 벗어났습니다."
+
+#: utils/adt/numeric.c:979
+#, c-format
+msgid "NUMERIC scale %d must be between 0 and precision %d"
+msgstr "NUMERIC 스케일 %d 값은 정밀도 범위(0 .. %d)를 벗어났습니다."
+
+#: utils/adt/numeric.c:997
+#, c-format
+msgid "invalid NUMERIC type modifier"
+msgstr "잘못된 NUMERIC 형식 한정자"
+
+#: utils/adt/numeric.c:1329
+#, c-format
+msgid "start value cannot be NaN"
+msgstr "시작값은 NaN 일 수 없음"
+
+#: utils/adt/numeric.c:1334
+#, c-format
+msgid "stop value cannot be NaN"
+msgstr "종료값은 NaN 일 수 없음"
+
+#: utils/adt/numeric.c:1344
+#, c-format
+msgid "step size cannot be NaN"
+msgstr "단계 크기는 NaN 일 수 없음"
+
+#: utils/adt/numeric.c:2539 utils/adt/numeric.c:5467 utils/adt/numeric.c:5912
+#: utils/adt/numeric.c:7616 utils/adt/numeric.c:8041 utils/adt/numeric.c:8156
+#: utils/adt/numeric.c:8229
+#, c-format
+msgid "value overflows numeric format"
+msgstr "값이 수치 형식에 넘처남"
+
+#: utils/adt/numeric.c:2881
+#, c-format
+msgid "cannot convert NaN to integer"
+msgstr "NaN 값을 정수형으로 변환할 수 없습니다"
+
+#: utils/adt/numeric.c:2947
+#, c-format
+msgid "cannot convert NaN to bigint"
+msgstr "NaN 값을 bigint형으로 변환할 수 없습니다"
+
+#: utils/adt/numeric.c:2992
+#, c-format
+msgid "cannot convert NaN to smallint"
+msgstr "NaN 값을 smallint형으로 변환할 수 없습니다"
+
+#: utils/adt/numeric.c:5982
+#, c-format
+msgid "numeric field overflow"
+msgstr "수치 필드 오버플로우"
+
+#: utils/adt/numeric.c:5983
+#, c-format
+msgid ""
+"A field with precision %d, scale %d must round to an absolute value less "
+"than %s%d."
+msgstr ""
+"전체 자릿수 %d, 소수 자릿수 %d의 필드는 %s%d보다 작은 절대 값으로 반올림해야 "
+"합니다."
+
+#: utils/adt/numeric.c:6254 utils/adt/numeric.c:6280
+#, c-format
+msgid "invalid input syntax for type double precision: \"%s\""
+msgstr "double precision 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/numutils.c:75
+#, c-format
+msgid "value \"%s\" is out of range for type integer"
+msgstr "입력한 \"%s\" 값은 integer 자료형 범위를 초과했습니다"
+
+#: utils/adt/numutils.c:81
+#, c-format
+msgid "value \"%s\" is out of range for type smallint"
+msgstr "입력한 \"%s\" 값은 smallint 자료형 범위를 초과했습니다"
+
+#: utils/adt/numutils.c:87
+#, c-format
+msgid "value \"%s\" is out of range for 8-bit integer"
+msgstr "값 \"%s\"은(는) 8비트 정수의 범위를 벗어남"
+
+#: utils/adt/oid.c:43 utils/adt/oid.c:57 utils/adt/oid.c:63 utils/adt/oid.c:84
+#, c-format
+msgid "invalid input syntax for type oid: \"%s\""
+msgstr "잘못된 oid 자료형의 입력: \"%s\""
+
+#: utils/adt/oid.c:69 utils/adt/oid.c:107
+#, c-format
+msgid "value \"%s\" is out of range for type oid"
+msgstr "입력한 \"%s\" 값은 oid 자료형 범위를 초과했습니다"
+
+#: utils/adt/oid.c:287
+#, c-format
+msgid "invalid oidvector data"
+msgstr "잘못된 oidvector 자료"
+
+#: utils/adt/oracle_compat.c:895
+#, c-format
+msgid "requested character too large"
+msgstr "요청된 문자가 너무 큼"
+
+#: utils/adt/oracle_compat.c:945 utils/adt/oracle_compat.c:1007
+#, c-format
+msgid "requested character too large for encoding: %d"
+msgstr "요청한 문자가 너무 커서 인코딩할 수 없음: %d"
+
+#: utils/adt/oracle_compat.c:986
+#, c-format
+msgid "requested character not valid for encoding: %d"
+msgstr "요청한 문자가 인코딩용으로 타당치 않음: %d"
+
+#: utils/adt/oracle_compat.c:1000
+#, c-format
+msgid "null character not permitted"
+msgstr "null 문자는 허용되지 않음"
+
+#: utils/adt/orderedsetaggs.c:425 utils/adt/orderedsetaggs.c:530
+#: utils/adt/orderedsetaggs.c:669
+#, c-format
+msgid "percentile value %g is not between 0 and 1"
+msgstr "%g 퍼센트 값이 0과 1사이가 아닙니다."
+
+#: utils/adt/pg_locale.c:1029
+#, c-format
+msgid "Apply system library package updates."
+msgstr "OS 라이브러리 패키지를 업데이트 하세요."
+
+#: utils/adt/pg_locale.c:1234
+#, c-format
+msgid "could not create locale \"%s\": %m"
+msgstr "\"%s\" 로케일을 만들 수 없음: %m"
+
+#: utils/adt/pg_locale.c:1237
+#, c-format
+msgid ""
+"The operating system could not find any locale data for the locale name \"%s"
+"\"."
+msgstr "운영체제에서 \"%s\" 로케일 이름에 대한 로케일 파일을 찾을 수 없습니다."
+
+#: utils/adt/pg_locale.c:1324
+#, c-format
+msgid ""
+"collations with different collate and ctype values are not supported on this "
+"platform"
+msgstr ""
+"이 플랫폼에서는 서로 다른 정렬규칙(collation)과 문자집합(ctype)을 함께 쓸 수 "
+"없습니다."
+
+#: utils/adt/pg_locale.c:1339
+#, c-format
+msgid "nondefault collations are not supported on this platform"
+msgstr ""
+"이 플랫폼에서는 기본값이 아닌 정렬규칙(collation)을 사용할 수 없습니다."
+
+#: utils/adt/pg_locale.c:1510
+#, c-format
+msgid "invalid multibyte character for locale"
+msgstr "로케일을 위한 잘못된 멀티바이트 문자"
+
+#: utils/adt/pg_locale.c:1511
+#, c-format
+msgid ""
+"The server's LC_CTYPE locale is probably incompatible with the database "
+"encoding."
+msgstr "서버의 LC_CTYPE 로케일은 이 데이터베이스 인코딩과 호환되지 않습니다."
+
+#: utils/adt/pg_lsn.c:44 utils/adt/pg_lsn.c:49
+#, c-format
+msgid "invalid input syntax for type pg_lsn: \"%s\""
+msgstr "pg_lsn 자료형에 대한 잘못된 입력: \"%s\""
+
+#: utils/adt/pg_upgrade_support.c:40
+#, c-format
+msgid "function can only be called when server is in binary upgrade mode"
+msgstr "함수는 서버가 이진 업그레이드 상태에서만 호출 될 수 있습니다"
+
+#: utils/adt/pgstatfuncs.c:571
+#, c-format
+msgid "invalid command name: \"%s\""
+msgstr "잘못된 명령어 이름: \"%s\""
+
+#: utils/adt/pseudotypes.c:95
+#, c-format
+msgid "cannot accept a value of type any"
+msgstr "any 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:108
+#, c-format
+msgid "cannot display a value of type any"
+msgstr "any 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:122 utils/adt/pseudotypes.c:150
+#, c-format
+msgid "cannot accept a value of type anyarray"
+msgstr "anyarray 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:175
+#, c-format
+msgid "cannot accept a value of type anyenum"
+msgstr "anyenum 자료형 값으로 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:199
+#, c-format
+msgid "cannot accept a value of type anyrange"
+msgstr "anyrange 자료형 값으로 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:276
+#, c-format
+msgid "cannot accept a value of type trigger"
+msgstr "trigger 자료형 값으로 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:289
+#, c-format
+msgid "cannot display a value of type trigger"
+msgstr "trigger 자료형 값으로 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:303
+#, c-format
+msgid "cannot accept a value of type event_trigger"
+msgstr "event_trigger 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:316
+#, c-format
+msgid "cannot display a value of type event_trigger"
+msgstr "event_trigger 자료형 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:330
+#, c-format
+msgid "cannot accept a value of type language_handler"
+msgstr "language_handler 자료형 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:343
+#, c-format
+msgid "cannot display a value of type language_handler"
+msgstr "language_handler 자료형 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:357
+#, c-format
+msgid "cannot accept a value of type fdw_handler"
+msgstr "fdw_handler 자료형 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:370
+#, c-format
+msgid "cannot display a value of type fdw_handler"
+msgstr "fdw_handler 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:384
+#, c-format
+msgid "cannot accept a value of type index_am_handler"
+msgstr "index_am_handler 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:397
+#, c-format
+msgid "cannot display a value of type index_am_handler"
+msgstr "index_am_handler 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:411
+#, c-format
+msgid "cannot accept a value of type tsm_handler"
+msgstr "tsm_handler 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:424
+#, c-format
+msgid "cannot display a value of type tsm_handler"
+msgstr "tsm_handler 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:438
+#, c-format
+msgid "cannot accept a value of type internal"
+msgstr "internal 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:451
+#, c-format
+msgid "cannot display a value of type internal"
+msgstr "internal 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:465
+#, c-format
+msgid "cannot accept a value of type opaque"
+msgstr "opaque 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:478
+#, c-format
+msgid "cannot display a value of type opaque"
+msgstr "opaque 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:492
+#, c-format
+msgid "cannot accept a value of type anyelement"
+msgstr "anyelement 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:505
+#, c-format
+msgid "cannot display a value of type anyelement"
+msgstr "anyelement 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:518
+#, c-format
+msgid "cannot accept a value of type anynonarray"
+msgstr "anynonarray 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:531
+#, c-format
+msgid "cannot display a value of type anynonarray"
+msgstr "anynonarray 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:544
+#, c-format
+msgid "cannot accept a value of a shell type"
+msgstr "셸 형태 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:557
+#, c-format
+msgid "cannot display a value of a shell type"
+msgstr "shell 형식의 값은 표시할 수 없음"
+
+#: utils/adt/pseudotypes.c:579 utils/adt/pseudotypes.c:604
+#: utils/adt/pseudotypes.c:632 utils/adt/pseudotypes.c:660
+#, c-format
+msgid "cannot accept a value of type %s"
+msgstr "%s 형식의 값은 사용할 수 없음"
+
+#: utils/adt/pseudotypes.c:647 utils/adt/pseudotypes.c:673
+#, c-format
+msgid "cannot output a value of type %s"
+msgstr "%s 형식의 값은 출력할 수 없음"
+
+#: utils/adt/rangetypes.c:405
+#, c-format
+msgid "range constructor flags argument must not be null"
+msgstr "range 자료형 구성자 플래그 인자로 null을 사용할 수 없음"
+
+#: utils/adt/rangetypes.c:992
+#, c-format
+msgid "result of range difference would not be contiguous"
+msgstr ""
+
+#: utils/adt/rangetypes.c:1053
+#, c-format
+msgid "result of range union would not be contiguous"
+msgstr ""
+
+#: utils/adt/rangetypes.c:1543
+#, c-format
+msgid "range lower bound must be less than or equal to range upper bound"
+msgstr "range 자료형의 하한값은 상한값과 같거나 작아야 합니다"
+
+#: utils/adt/rangetypes.c:1926 utils/adt/rangetypes.c:1939
+#: utils/adt/rangetypes.c:1953
+#, c-format
+msgid "invalid range bound flags"
+msgstr "잘못된 range 구성 플래그"
+
+#: utils/adt/rangetypes.c:1927 utils/adt/rangetypes.c:1940
+#: utils/adt/rangetypes.c:1954
+#, c-format
+msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"."
+msgstr "유효한 값은 \"[]\", \"[)\", \"(]\", \"()\"."
+
+#: utils/adt/rangetypes.c:2019 utils/adt/rangetypes.c:2036
+#: utils/adt/rangetypes.c:2049 utils/adt/rangetypes.c:2067
+#: utils/adt/rangetypes.c:2078 utils/adt/rangetypes.c:2122
+#: utils/adt/rangetypes.c:2130
+#, c-format
+msgid "malformed range literal: \"%s\""
+msgstr "비정상적인 range 문자: \"%s\""
+
+#: utils/adt/rangetypes.c:2021
+#, c-format
+msgid "Junk after \"empty\" key word."
+msgstr " \"empty\" 키워드 뒤에 정크가 있음"
+
+#: utils/adt/rangetypes.c:2038
+#, c-format
+msgid "Missing left parenthesis or bracket."
+msgstr "왼쪽 괄호가 빠졌음"
+
+#: utils/adt/rangetypes.c:2051
+#, c-format
+msgid "Missing comma after lower bound."
+msgstr "하한값 뒤에 쉼표가 빠졌음"
+
+#: utils/adt/rangetypes.c:2069
+#, c-format
+msgid "Too many commas."
+msgstr "칼럼이 너무 많습니다."
+
+#: utils/adt/rangetypes.c:2080
+#, c-format
+msgid "Junk after right parenthesis or bracket."
+msgstr "오른쪽 괄호 다음에 정크가 있음"
+
+#: utils/adt/regexp.c:285 utils/adt/regexp.c:1288 utils/adt/varlena.c:3829
+#, c-format
+msgid "regular expression failed: %s"
+msgstr "잘못된 정규식: %s"
+
+#: utils/adt/regexp.c:422
+#, c-format
+msgid "invalid regexp option: \"%c\""
+msgstr "잘못된 regexp 옵션: \"%c\""
+
+#: utils/adt/regexp.c:948
+#, c-format
+msgid "regexp_split does not support the global option"
+msgstr "regexp_split는 글로벌 옵션을 지원하지 않음"
+
+#: utils/adt/regproc.c:128 utils/adt/regproc.c:148
+#, c-format
+msgid "more than one function named \"%s\""
+msgstr "\"%s\"(이)라는 함수가 두 개 이상 있음"
+
+#: utils/adt/regproc.c:587 utils/adt/regproc.c:607
+#, c-format
+msgid "more than one operator named %s"
+msgstr "%s(이)라는 연산자가 두 개 이상 있음"
+
+#: utils/adt/regproc.c:774 utils/adt/regproc.c:815 gram.y:7302
+#, c-format
+msgid "missing argument"
+msgstr "인자가 빠졌음"
+
+#: utils/adt/regproc.c:775 utils/adt/regproc.c:816 gram.y:7303
+#, c-format
+msgid "Use NONE to denote the missing argument of a unary operator."
+msgstr "단항 연산자에서 인자 없음을 표시할 때는 NONE 인자를 사용하세요."
+
+#: utils/adt/regproc.c:779 utils/adt/regproc.c:820 utils/adt/regproc.c:2006
+#: utils/adt/ruleutils.c:8367 utils/adt/ruleutils.c:8536
+#, c-format
+msgid "too many arguments"
+msgstr "인자가 너무 많습니다"
+
+#: utils/adt/regproc.c:780 utils/adt/regproc.c:821
+#, c-format
+msgid "Provide two argument types for operator."
+msgstr "연산자를 위해서는 두개의 인자 자료형을 지정하십시오."
+
+#: utils/adt/regproc.c:1594 utils/adt/regproc.c:1618 utils/adt/regproc.c:1715
+#: utils/adt/regproc.c:1739 utils/adt/regproc.c:1841 utils/adt/regproc.c:1846
+#: utils/adt/varlena.c:3084 utils/adt/varlena.c:3089
+#, c-format
+msgid "invalid name syntax"
+msgstr "잘못된 이름 구문"
+
+#: utils/adt/regproc.c:1904
+#, c-format
+msgid "expected a left parenthesis"
+msgstr "왼쪽 괄호가 필요합니다."
+
+#: utils/adt/regproc.c:1920
+#, c-format
+msgid "expected a right parenthesis"
+msgstr "오른쪽 괄호가 필요합니다."
+
+#: utils/adt/regproc.c:1939
+#, c-format
+msgid "expected a type name"
+msgstr "자료형 이름을 지정하십시오"
+
+#: utils/adt/regproc.c:1971
+#, c-format
+msgid "improper type name"
+msgstr "부적절한 형식 이름"
+
+#: utils/adt/ri_triggers.c:314 utils/adt/ri_triggers.c:371
+#: utils/adt/ri_triggers.c:790 utils/adt/ri_triggers.c:1013
+#: utils/adt/ri_triggers.c:1169 utils/adt/ri_triggers.c:1350
+#: utils/adt/ri_triggers.c:1515 utils/adt/ri_triggers.c:1691
+#: utils/adt/ri_triggers.c:1871 utils/adt/ri_triggers.c:2062
+#: utils/adt/ri_triggers.c:2120 utils/adt/ri_triggers.c:2225
+#: utils/adt/ri_triggers.c:2402 gram.y:3343
+#, c-format
+msgid "MATCH PARTIAL not yet implemented"
+msgstr "MATCH PARTIAL 기능은 아직 구현 안되었습니다"
+
+#: utils/adt/ri_triggers.c:343 utils/adt/ri_triggers.c:2490
+#: utils/adt/ri_triggers.c:3315
+#, c-format
+msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\""
+msgstr ""
+"\"%s\" 테이블에서 자료 추가, 갱신 작업이 \"%s\" 참조키(foreign key) 제약 조건"
+"을 위배했습니다"
+
+#: utils/adt/ri_triggers.c:346 utils/adt/ri_triggers.c:2493
+#, c-format
+msgid "MATCH FULL does not allow mixing of null and nonnull key values."
+msgstr "MATCH FULL에 null 키 값과 nonnull 키 값을 함께 사용할 수 없습니다."
+
+#: utils/adt/ri_triggers.c:2732
+#, c-format
+msgid "function \"%s\" must be fired for INSERT"
+msgstr "INSERT에 대해 \"%s\" 함수를 실행해야 함"
+
+#: utils/adt/ri_triggers.c:2738
+#, c-format
+msgid "function \"%s\" must be fired for UPDATE"
+msgstr "UPDATE에 대해 \"%s\" 함수를 실행해야 함"
+
+#: utils/adt/ri_triggers.c:2744
+#, c-format
+msgid "function \"%s\" must be fired for DELETE"
+msgstr "DELETE에 대해 \"%s\" 함수를 실행해야 함"
+
+#: utils/adt/ri_triggers.c:2767
+#, c-format
+msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\""
+msgstr "\"%s\" 트리거(해당 테이블: \"%s\")에 대한 pg_constraint 항목이 없음"
+
+#: utils/adt/ri_triggers.c:2769
+#, c-format
+msgid ""
+"Remove this referential integrity trigger and its mates, then do ALTER TABLE "
+"ADD CONSTRAINT."
+msgstr ""
+"해당 트리거 관련 객체를 제거한 후 ALTER TABLE ADD CONSTRAINT 명령으로 추가하"
+"세요"
+
+#: utils/adt/ri_triggers.c:3225
+#, c-format
+msgid ""
+"referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave "
+"unexpected result"
+msgstr ""
+"\"%s\"에 대한 참조 무결성 쿼리(제약조건: \"%s\", 해당 릴레이션: \"%s\")를 실"
+"행하면 예기치 않은 결과가 발생함"
+
+#: utils/adt/ri_triggers.c:3229
+#, c-format
+msgid "This is most likely due to a rule having rewritten the query."
+msgstr "이 문제는 주로 룰이 재작성 되었을 때 발생합니다."
+
+#: utils/adt/ri_triggers.c:3319
+#, c-format
+msgid "Key (%s)=(%s) is not present in table \"%s\"."
+msgstr "(%s)=(%s) 키가 \"%s\" 테이블에 없습니다."
+
+#: utils/adt/ri_triggers.c:3322
+#, c-format
+msgid "Key is not present in table \"%s\"."
+msgstr "\"%s\" 테이블에 키가 없습니다."
+
+#: utils/adt/ri_triggers.c:3328
+#, c-format
+msgid ""
+"update or delete on table \"%s\" violates foreign key constraint \"%s\" on "
+"table \"%s\""
+msgstr ""
+"\"%s\" 테이블의 자료 갱신, 삭제 작업이 \"%s\" 참조키(foreign key) 제약 조건 "
+"- \"%s\" 테이블 - 을 위반했습니다"
+
+#: utils/adt/ri_triggers.c:3333
+#, c-format
+msgid "Key (%s)=(%s) is still referenced from table \"%s\"."
+msgstr "(%s)=(%s) 키가 \"%s\" 테이블에서 여전히 참조됩니다."
+
+#: utils/adt/ri_triggers.c:3336
+#, c-format
+msgid "Key is still referenced from table \"%s\"."
+msgstr "\"%s\" 테이블에서 키가 여전히 참조됩니다."
+
+#: utils/adt/rowtypes.c:103 utils/adt/rowtypes.c:479
+#, c-format
+msgid "input of anonymous composite types is not implemented"
+msgstr "익명 복합 형식의 입력이 구현되어 있지 않음"
+
+#: utils/adt/rowtypes.c:155 utils/adt/rowtypes.c:183 utils/adt/rowtypes.c:206
+#: utils/adt/rowtypes.c:214 utils/adt/rowtypes.c:266 utils/adt/rowtypes.c:274
+#, c-format
+msgid "malformed record literal: \"%s\""
+msgstr "비정상적인 레코드 문자: \"%s\""
+
+#: utils/adt/rowtypes.c:156
+#, c-format
+msgid "Missing left parenthesis."
+msgstr "왼쪽 괄호가 필요합니다."
+
+#: utils/adt/rowtypes.c:184
+#, c-format
+msgid "Too few columns."
+msgstr "열 수가 너무 적다"
+
+#: utils/adt/rowtypes.c:267
+#, c-format
+msgid "Too many columns."
+msgstr "열이 너무 많습니다."
+
+#: utils/adt/rowtypes.c:275
+#, c-format
+msgid "Junk after right parenthesis."
+msgstr "오른쪽 괄호가 필요합니다."
+
+#: utils/adt/rowtypes.c:528
+#, c-format
+msgid "wrong number of columns: %d, expected %d"
+msgstr "열 수(%d)가 최대값(%d)을 초과했습니다"
+
+#: utils/adt/rowtypes.c:555
+#, c-format
+msgid "wrong data type: %u, expected %u"
+msgstr "잘못된 자료형: %u, 예상되는 자료형 %u"
+
+#: utils/adt/rowtypes.c:616
+#, c-format
+msgid "improper binary format in record column %d"
+msgstr "%d 번째 레코드 열에서 잘못된 바이너리 포맷이 있습니다"
+
+#: utils/adt/rowtypes.c:902 utils/adt/rowtypes.c:1142
+#: utils/adt/rowtypes.c:1396 utils/adt/rowtypes.c:1673
+#, c-format
+msgid "cannot compare dissimilar column types %s and %s at record column %d"
+msgstr "서로 다른 열 형식 %s과(와) %s(레코드 열 %d)을(를) 비교할 수 없음"
+
+#: utils/adt/rowtypes.c:991 utils/adt/rowtypes.c:1213
+#: utils/adt/rowtypes.c:1529 utils/adt/rowtypes.c:1769
+#, c-format
+msgid "cannot compare record types with different numbers of columns"
+msgstr "칼럼 수가 서로 다른 레코드 자료형을 비교할 수 없음"
+
+#: utils/adt/ruleutils.c:4289
+#, c-format
+msgid "rule \"%s\" has unsupported event type %d"
+msgstr "\"%s\" 룰은 %d 이벤트 형태를 지원하지 않습니다"
+
+#: utils/adt/selfuncs.c:5318
+#, c-format
+msgid "case insensitive matching not supported on type bytea"
+msgstr "bytea 형식에서는 대/소문자를 구분하지 않는 일치가 지원되지 않음"
+
+#: utils/adt/selfuncs.c:5421
+#, c-format
+msgid "regular-expression matching not supported on type bytea"
+msgstr "bytea 형식에서는 정규식 일치가 지원되지 않음"
+
+#: utils/adt/tid.c:71 utils/adt/tid.c:79 utils/adt/tid.c:87
+#, c-format
+msgid "invalid input syntax for type tid: \"%s\""
+msgstr "tid 형식의 입력 구문이 잘못됨: \"%s\""
+
+#: utils/adt/timestamp.c:99
+#, c-format
+msgid "TIMESTAMP(%d)%s precision must not be negative"
+msgstr "TIMESTAMP(%d)%s 정밀도로 음수를 사용할 수 없습니다"
+
+#: utils/adt/timestamp.c:105
+#, c-format
+msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d"
+msgstr "TIMESTAMP(%d)%s 정밀도는 최대값(%d)으로 줄였습니다"
+
+#: utils/adt/timestamp.c:170 utils/adt/timestamp.c:445
+#, c-format
+msgid "timestamp out of range: \"%s\""
+msgstr "타임스탬프 값이 범위를 벗어났음: \"%s\""
+
+#: utils/adt/timestamp.c:188 utils/adt/timestamp.c:463
+#: utils/adt/timestamp.c:990
+#, c-format
+msgid "date/time value \"%s\" is no longer supported"
+msgstr "날짜/시간 값 \"%s\"은(는) 더 이상 지원되지 않음"
+
+#: utils/adt/timestamp.c:258 utils/adt/timestamp.c:754
+#, c-format
+msgid "timestamp cannot be NaN"
+msgstr "타임스탬프 값으로 NaN 값을 지정할 수 없음"
+
+#: utils/adt/timestamp.c:380
+#, c-format
+msgid "timestamp(%d) precision must be between %d and %d"
+msgstr "타임스탬프(%d) 정밀도는 %d에서 %d 사이여야 함"
+
+#: utils/adt/timestamp.c:513
+#, c-format
+msgid "invalid input syntax for numeric time zone: \"%s\""
+msgstr "숫자형 타임 존 입력에 문법 오류가 있음: \"%s\""
+
+#: utils/adt/timestamp.c:515
+#, c-format
+msgid "Numeric time zones must have \"-\" or \"+\" as first character."
+msgstr "숫자형 타임 존 형식은 처음에 \"-\" 또는 \"+\" 문자가 있어야 합니다."
+
+#: utils/adt/timestamp.c:528
+#, c-format
+msgid "numeric time zone \"%s\" out of range"
+msgstr "\"%s\" 숫자형 타임 존 범위 벗어남"
+
+#: utils/adt/timestamp.c:631 utils/adt/timestamp.c:641
+#: utils/adt/timestamp.c:653
+#, c-format
+msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g"
+msgstr "타임스탬프 값이 범위를 벗어났음: %d-%02d-%02d %d:%02d:%02g"
+
+#: utils/adt/timestamp.c:772 utils/adt/timestamp.c:788
+#, c-format
+msgid "timestamp out of range: \"%g\""
+msgstr "타임스탬프 값이 범위를 벗어났음: \"%g\""
+
+#: utils/adt/timestamp.c:984 utils/adt/timestamp.c:1608
+#: utils/adt/timestamp.c:2121 utils/adt/timestamp.c:3273
+#: utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3283
+#: utils/adt/timestamp.c:3333 utils/adt/timestamp.c:3340
+#: utils/adt/timestamp.c:3347 utils/adt/timestamp.c:3367
+#: utils/adt/timestamp.c:3374 utils/adt/timestamp.c:3381
+#: utils/adt/timestamp.c:3411 utils/adt/timestamp.c:3419
+#: utils/adt/timestamp.c:3464 utils/adt/timestamp.c:3804
+#: utils/adt/timestamp.c:3933 utils/adt/timestamp.c:4324
+#, c-format
+msgid "interval out of range"
+msgstr "간격이 범위를 벗어남"
+
+#: utils/adt/timestamp.c:1125 utils/adt/timestamp.c:1158
+#, c-format
+msgid "invalid INTERVAL type modifier"
+msgstr "잘못된 INTERVAL 형식 한정자"
+
+#: utils/adt/timestamp.c:1141
+#, c-format
+msgid "INTERVAL(%d) precision must not be negative"
+msgstr "INTERVAL(%d) 정밀도로 음수값이 올 수 없습니다"
+
+#: utils/adt/timestamp.c:1147
+#, c-format
+msgid "INTERVAL(%d) precision reduced to maximum allowed, %d"
+msgstr "INTERVAL(%d) 정밀도는 허용 최대치(%d)로 감소 되었습니다"
+
+#: utils/adt/timestamp.c:1552
+#, c-format
+msgid "interval(%d) precision must be between %d and %d"
+msgstr "간격(%d) 정밀도는 %d에서 %d 사이여야 함"
+
+#: utils/adt/timestamp.c:2850
+#, c-format
+msgid "cannot subtract infinite timestamps"
+msgstr "타임스탬프 무한값을 추출 할 수 없음"
+
+#: utils/adt/timestamp.c:4059 utils/adt/timestamp.c:4584
+#: utils/adt/timestamp.c:4768 utils/adt/timestamp.c:4793
+#, c-format
+msgid "timestamp units \"%s\" not supported"
+msgstr "\"%s\" timestamp 유닛은 지원하지 않습니다"
+
+#: utils/adt/timestamp.c:4073 utils/adt/timestamp.c:4538
+#: utils/adt/timestamp.c:4803
+#, c-format
+msgid "timestamp units \"%s\" not recognized"
+msgstr "\"%s\" timestamp 유닛을 처리하지 못했습니다"
+
+#: utils/adt/timestamp.c:4213 utils/adt/timestamp.c:4579
+#: utils/adt/timestamp.c:4990 utils/adt/timestamp.c:5016
+#, c-format
+msgid "timestamp with time zone units \"%s\" not supported"
+msgstr "\"%s\" 시간대 유닛이 있는 timestamp 자료형은 지원하지 않습니다"
+
+#: utils/adt/timestamp.c:4230 utils/adt/timestamp.c:4533
+#: utils/adt/timestamp.c:5025
+#, c-format
+msgid "timestamp with time zone units \"%s\" not recognized"
+msgstr "\"%s\" 시간대 유닛이 있는 timestamp 값을 처리하지 못했습니다"
+
+#: utils/adt/timestamp.c:4311
+#, c-format
+msgid ""
+"interval units \"%s\" not supported because months usually have fractional "
+"weeks"
+msgstr ""
+
+#: utils/adt/timestamp.c:4317 utils/adt/timestamp.c:5131
+#, c-format
+msgid "interval units \"%s\" not supported"
+msgstr "\"%s\" 유닛 간격(interval units)은 지원하지 않습니다"
+
+#: utils/adt/timestamp.c:4333 utils/adt/timestamp.c:5158
+#, c-format
+msgid "interval units \"%s\" not recognized"
+msgstr "\"%s\" 유닛 간격(interval units)을 처리하지 못했습니다"
+
+#: utils/adt/trigfuncs.c:42
+#, c-format
+msgid "suppress_redundant_updates_trigger: must be called as trigger"
+msgstr "suppress_redundant_updates_trigger: 트리거로 호출되어야 함"
+
+#: utils/adt/trigfuncs.c:48
+#, c-format
+msgid "suppress_redundant_updates_trigger: must be called on update"
+msgstr "suppress_redundant_updates_trigger: 업데이트 시 호출되어야 함"
+
+#: utils/adt/trigfuncs.c:54
+#, c-format
+msgid "suppress_redundant_updates_trigger: must be called before update"
+msgstr "suppress_redundant_updates_trigger: 업데이트 전에 호출되어야 함"
+
+#: utils/adt/trigfuncs.c:60
+#, c-format
+msgid "suppress_redundant_updates_trigger: must be called for each row"
+msgstr "suppress_redundant_updates_trigger: 각 행에 대해 호출되어야 함"
+
+#: utils/adt/tsgistidx.c:99
+#, c-format
+msgid "gtsvector_in not implemented"
+msgstr "gtsvector_in이 구현되어 있지 않음"
+
+#: utils/adt/tsquery.c:166
+#, c-format
+msgid "distance in phrase operator should not be greater than %d"
+msgstr "분석 작업에서 사용한 거리값은 %d 보다 클 수 없습니다"
+
+#: utils/adt/tsquery.c:254 utils/adt/tsquery.c:513
+#: utils/adt/tsvector_parser.c:141
+#, c-format
+msgid "syntax error in tsquery: \"%s\""
+msgstr "tsquery에 구문 오류가 있음: \"%s\""
+
+#: utils/adt/tsquery.c:275
+#, c-format
+msgid "no operand in tsquery: \"%s\""
+msgstr "tsquery에 피연산자가 없음: \"%s\""
+
+#: utils/adt/tsquery.c:358
+#, c-format
+msgid "value is too big in tsquery: \"%s\""
+msgstr "tsquery의 값이 너무 큼: \"%s\""
+
+#: utils/adt/tsquery.c:363
+#, c-format
+msgid "operand is too long in tsquery: \"%s\""
+msgstr "tsquery의 피연산자가 너무 긺: \"%s\""
+
+#: utils/adt/tsquery.c:391
+#, c-format
+msgid "word is too long in tsquery: \"%s\""
+msgstr "tsquery의 단어가 너무 긺: \"%s\""
+
+#: utils/adt/tsquery.c:642
+#, c-format
+msgid "text-search query doesn't contain lexemes: \"%s\""
+msgstr "텍스트 검색 쿼리에 어휘소가 포함되어 있지 않음: \"%s\""
+
+#: utils/adt/tsquery.c:653 utils/adt/tsquery_util.c:375
+#, c-format
+msgid "tsquery is too large"
+msgstr "tsquery 길이가 너무 깁니다"
+
+#: utils/adt/tsquery_cleanup.c:407
+#, c-format
+msgid ""
+"text-search query contains only stop words or doesn't contain lexemes, "
+"ignored"
+msgstr ""
+"텍스트 검색 쿼리에 중지 단어만 포함되어 있거나 어휘소가 포함되어 있지 않음, "
+"무시됨"
+
+#: utils/adt/tsquery_op.c:122
+#, c-format
+msgid "distance in phrase operator should be non-negative and less than %d"
+msgstr "분석 작업에서 사용한 거리값은 %d 보다 작고 양수값만 사용할 수 있습니다"
+
+#: utils/adt/tsquery_rewrite.c:321
+#, c-format
+msgid "ts_rewrite query must return two tsquery columns"
+msgstr "ts_rewrite 쿼리는 두 개의 tsquery 열을 반환해야 함"
+
+#: utils/adt/tsrank.c:412
+#, c-format
+msgid "array of weight must be one-dimensional"
+msgstr "가중치 배열은 일차원 배열이어야 함"
+
+#: utils/adt/tsrank.c:417
+#, c-format
+msgid "array of weight is too short"
+msgstr "가중치 배열이 너무 짧음"
+
+#: utils/adt/tsrank.c:422
+#, c-format
+msgid "array of weight must not contain nulls"
+msgstr "가중치 배열에는 null이 포함되지 않아야 함"
+
+#: utils/adt/tsrank.c:431 utils/adt/tsrank.c:868
+#, c-format
+msgid "weight out of range"
+msgstr "가중치가 범위를 벗어남"
+
+#: utils/adt/tsvector.c:213
+#, c-format
+msgid "word is too long (%ld bytes, max %ld bytes)"
+msgstr "단어가 너무 긺(%ld바이트, 최대 %ld바이트)"
+
+#: utils/adt/tsvector.c:220
+#, c-format
+msgid "string is too long for tsvector (%ld bytes, max %ld bytes)"
+msgstr ""
+"문자열이 너무 길어서 tsvector에 사용할 수 없음(%ld바이트, 최대 %ld바이트)"
+
+#: utils/adt/tsvector_op.c:322 utils/adt/tsvector_op.c:609
+#: utils/adt/tsvector_op.c:777
+#, c-format
+msgid "lexeme array may not contain nulls"
+msgstr "어휘소 배열에는 null이 포함되지 않아야 함"
+
+#: utils/adt/tsvector_op.c:852
+#, c-format
+msgid "weight array may not contain nulls"
+msgstr "가중치 배열에는 null이 포함되지 않아야 함"
+
+#: utils/adt/tsvector_op.c:876
+#, c-format
+msgid "unrecognized weight: \"%c\""
+msgstr "알 수 없는 가중치: \"%c\""
+
+#: utils/adt/tsvector_op.c:2313
+#, c-format
+msgid "ts_stat query must return one tsvector column"
+msgstr "ts_stat 쿼리는 하나의 tsvector 칼럼을 반환해야 함"
+
+#: utils/adt/tsvector_op.c:2495
+#, c-format
+msgid "tsvector column \"%s\" does not exist"
+msgstr "\"%s\" tsvector 칼럼이 없음"
+
+#: utils/adt/tsvector_op.c:2501
+#, c-format
+msgid "column \"%s\" is not of tsvector type"
+msgstr "\"%s\" 칼럼은 tsvector 형식이 아님"
+
+#: utils/adt/tsvector_op.c:2513
+#, c-format
+msgid "configuration column \"%s\" does not exist"
+msgstr "\"%s\" 구성 칼럼이 없음"
+
+#: utils/adt/tsvector_op.c:2519
+#, c-format
+msgid "column \"%s\" is not of regconfig type"
+msgstr "\"%s\" 칼럼은 regconfig 형이 아님"
+
+#: utils/adt/tsvector_op.c:2526
+#, c-format
+msgid "configuration column \"%s\" must not be null"
+msgstr "\"%s\" 구성 칼럼은 null이 아니어야 함"
+
+#: utils/adt/tsvector_op.c:2539
+#, c-format
+msgid "text search configuration name \"%s\" must be schema-qualified"
+msgstr "\"%s\" 텍스트 검색 구성 이름이 스키마로 한정되어야 함"
+
+#: utils/adt/tsvector_op.c:2564
+#, c-format
+msgid "column \"%s\" is not of a character type"
+msgstr "\"%s\" 칼럼은 문자형이 아님"
+
+#: utils/adt/tsvector_parser.c:142
+#, c-format
+msgid "syntax error in tsvector: \"%s\""
+msgstr "tsvector에 구문 오류가 있음: \"%s\""
+
+#: utils/adt/tsvector_parser.c:207
+#, c-format
+msgid "there is no escaped character: \"%s\""
+msgstr "이스케이프 문자가 없음: \"%s\""
+
+#: utils/adt/tsvector_parser.c:324
+#, c-format
+msgid "wrong position info in tsvector: \"%s\""
+msgstr "tsvector에 잘못된 위치 정보가 있음: \"%s\""
+
+#: utils/adt/txid.c:339
+#, c-format
+msgid "invalid input syntax for type txid_snapshot: \"%s\""
+msgstr "txid_snapshot 형의 입력 구문이 잘못됨: \"%s\""
+
+#: utils/adt/txid.c:534
+#, c-format
+msgid "invalid external txid_snapshot data"
+msgstr "외부 txid_snapshot 값이 잘못됨"
+
+#: utils/adt/uuid.c:145
+#, c-format
+msgid "invalid input syntax for uuid: \"%s\""
+msgstr "uuid의 입력 구문이 잘못됨: \"%s\""
+
+#: utils/adt/varbit.c:57 utils/adt/varchar.c:50
+#, c-format
+msgid "length for type %s must be at least 1"
+msgstr "%s 자료형의 길이는 최소 1 이상이어야합니다"
+
+#: utils/adt/varbit.c:62 utils/adt/varchar.c:54
+#, c-format
+msgid "length for type %s cannot exceed %d"
+msgstr "%s 자료형의 길이는 최대 %d 이하여야합니다"
+
+#: utils/adt/varbit.c:163 utils/adt/varbit.c:475 utils/adt/varbit.c:973
+#, c-format
+msgid "bit string length exceeds the maximum allowed (%d)"
+msgstr "비트 문자열 길이가 최대치 (%d)를 초과했습니다"
+
+#: utils/adt/varbit.c:177 utils/adt/varbit.c:320 utils/adt/varbit.c:377
+#, c-format
+msgid "bit string length %d does not match type bit(%d)"
+msgstr ""
+"길이가 %d인 비트 문자열 자료는 bit(%d) 자료형의 길이와 일치하지 않습니다"
+
+#: utils/adt/varbit.c:199 utils/adt/varbit.c:511
+#, c-format
+msgid "\"%c\" is not a valid binary digit"
+msgstr "\"%c\" 문자는 2진수 문자가 아닙니다"
+
+#: utils/adt/varbit.c:224 utils/adt/varbit.c:536
+#, c-format
+msgid "\"%c\" is not a valid hexadecimal digit"
+msgstr "\"%c\" 문자는 16진수 문자가 아닙니다"
+
+#: utils/adt/varbit.c:311 utils/adt/varbit.c:627
+#, c-format
+msgid "invalid length in external bit string"
+msgstr "외부 비트 문자열의 길이가 잘못되었습니다"
+
+#: utils/adt/varbit.c:489 utils/adt/varbit.c:636 utils/adt/varbit.c:731
+#, c-format
+msgid "bit string too long for type bit varying(%d)"
+msgstr "비트 문자열이 너무 깁니다(해당 자료형 bit varying(%d))"
+
+#: utils/adt/varbit.c:1066 utils/adt/varbit.c:1168 utils/adt/varlena.c:842
+#: utils/adt/varlena.c:906 utils/adt/varlena.c:1050 utils/adt/varlena.c:2735
+#: utils/adt/varlena.c:2802
+#, c-format
+msgid "negative substring length not allowed"
+msgstr "substring에서 음수 길이는 허용하지 않음"
+
+#: utils/adt/varbit.c:1226
+#, c-format
+msgid "cannot AND bit strings of different sizes"
+msgstr "서로 크기가 틀린 비트 문자열로 AND 연산을 할 수 없습니다."
+
+#: utils/adt/varbit.c:1268
+#, c-format
+msgid "cannot OR bit strings of different sizes"
+msgstr "서로 크기가 틀린 비트 문자열로 OR 연산을 할 수 없습니다."
+
+#: utils/adt/varbit.c:1315
+#, c-format
+msgid "cannot XOR bit strings of different sizes"
+msgstr "서로 크기가 틀린 비트 문자열은 XOR 연산을 할 수 없습니다."
+
+#: utils/adt/varbit.c:1803 utils/adt/varbit.c:1861
+#, c-format
+msgid "bit index %d out of valid range (0..%d)"
+msgstr "비트 %d 인덱스의 범위를 벗어남 (0..%d)"
+
+#: utils/adt/varbit.c:1812 utils/adt/varlena.c:3002
+#, c-format
+msgid "new bit must be 0 or 1"
+msgstr "새 비트값은 0 또는 1 이어야합니다"
+
+#: utils/adt/varchar.c:154 utils/adt/varchar.c:307
+#, c-format
+msgid "value too long for type character(%d)"
+msgstr "character(%d) 자료형에 너무 긴 자료를 담으려고 합니다."
+
+#: utils/adt/varchar.c:469 utils/adt/varchar.c:623
+#, c-format
+msgid "value too long for type character varying(%d)"
+msgstr "character varying(%d) 자료형에 너무 긴 자료를 담으려고 합니다."
+
+#: utils/adt/varlena.c:1420 utils/adt/varlena.c:1825
+#, c-format
+msgid "could not determine which collation to use for string comparison"
+msgstr "문자열 비교 작업에 사용할 정렬규칙(collation)을 결정할 수 없음"
+
+#: utils/adt/varlena.c:1478 utils/adt/varlena.c:1491
+#, c-format
+msgid "could not convert string to UTF-16: error code %lu"
+msgstr "UTF-16 인코딩으로 문자열을 변환할 수 없음: 오류번호 %lu"
+
+#: utils/adt/varlena.c:1506
+#, c-format
+msgid "could not compare Unicode strings: %m"
+msgstr "유니코드 문자열 비교 실패: %m"
+
+#: utils/adt/varlena.c:2880 utils/adt/varlena.c:2911 utils/adt/varlena.c:2947
+#: utils/adt/varlena.c:2990
+#, c-format
+msgid "index %d out of valid range, 0..%d"
+msgstr "%d 인덱스의 범위를 벗어남, 0..%d"
+
+#: utils/adt/varlena.c:3925
+#, c-format
+msgid "field position must be greater than zero"
+msgstr "필드 위치 값은 0 보다 커야합니다"
+
+#: utils/adt/varlena.c:4804
+#, c-format
+msgid "unterminated format() type specifier"
+msgstr "마무리 안된 format() 형 식별자"
+
+#: utils/adt/varlena.c:4805 utils/adt/varlena.c:4939 utils/adt/varlena.c:5060
+#, c-format
+msgid "For a single \"%%\" use \"%%%%\"."
+msgstr "하나의 \"%%\" 문자를 표시하려면, \"%%%%\" 형태로 사용하세요"
+
+#: utils/adt/varlena.c:4937 utils/adt/varlena.c:5058
+#, c-format
+msgid "unrecognized format() type specifier \"%c\""
+msgstr "인식할 수 없는 format() 형 식별자 \"%c\""
+
+#: utils/adt/varlena.c:4950 utils/adt/varlena.c:5007
+#, c-format
+msgid "too few arguments for format()"
+msgstr "format() 작업을 위한 인자가 너무 적음"
+
+#: utils/adt/varlena.c:5102 utils/adt/varlena.c:5285
+#, c-format
+msgid "number is out of range"
+msgstr "수치 범위를 벗어남"
+
+#: utils/adt/varlena.c:5166 utils/adt/varlena.c:5194
+#, c-format
+msgid "format specifies argument 0, but arguments are numbered from 1"
+msgstr ""
+"format 함수에서 사용할 수 있는 인자 위치 번호는 0이 아니라, 1부터 시작합니다"
+
+#: utils/adt/varlena.c:5187
+#, c-format
+msgid "width argument position must be ended by \"$\""
+msgstr "넓이 인자 위치값은 \"$\" 문자로 끝나야 합니다"
+
+#: utils/adt/varlena.c:5232
+#, c-format
+msgid "null values cannot be formatted as an SQL identifier"
+msgstr "null 값은 SQL 식별자로 포멧될 수 없음"
+
+#: utils/adt/windowfuncs.c:243
+#, c-format
+msgid "argument of ntile must be greater than zero"
+msgstr "ntile의 인자는 0보다 커야 함"
+
+#: utils/adt/windowfuncs.c:465
+#, c-format
+msgid "argument of nth_value must be greater than zero"
+msgstr "nth_value의 인자는 0보다 커야 함"
+
+#: utils/adt/xml.c:171
+#, c-format
+msgid "unsupported XML feature"
+msgstr "지원되지 않는 XML 기능"
+
+#: utils/adt/xml.c:172
+#, c-format
+msgid "This functionality requires the server to be built with libxml support."
+msgstr "이 기능을 사용하려면 libxml 지원으로 서버를 빌드해야 합니다."
+
+#: utils/adt/xml.c:173
+#, c-format
+msgid "You need to rebuild PostgreSQL using --with-libxml."
+msgstr "--with-libxml을 사용하여 PostgreSQL을 다시 빌드해야 합니다."
+
+#: utils/adt/xml.c:192 utils/mb/mbutils.c:523
+#, c-format
+msgid "invalid encoding name \"%s\""
+msgstr "\"%s\" 인코딩 이름이 잘못됨"
+
+#: utils/adt/xml.c:435 utils/adt/xml.c:440
+#, c-format
+msgid "invalid XML comment"
+msgstr "잘못된 XML 주석"
+
+#: utils/adt/xml.c:569
+#, c-format
+msgid "not an XML document"
+msgstr "XML 문서가 아님"
+
+#: utils/adt/xml.c:728 utils/adt/xml.c:751
+#, c-format
+msgid "invalid XML processing instruction"
+msgstr "잘못된 XML 처리 명령"
+
+#: utils/adt/xml.c:729
+#, c-format
+msgid "XML processing instruction target name cannot be \"%s\"."
+msgstr "XML 처리 명령 대상 이름은 \"%s\"일 수 없습니다."
+
+#: utils/adt/xml.c:752
+#, c-format
+msgid "XML processing instruction cannot contain \"?>\"."
+msgstr "XML 처리 명령에는 \"?&gt;\"를 포함할 수 없습니다."
+
+#: utils/adt/xml.c:831
+#, c-format
+msgid "xmlvalidate is not implemented"
+msgstr "xmlvalidate가 구현되어 있지 않음"
+
+#: utils/adt/xml.c:910
+#, c-format
+msgid "could not initialize XML library"
+msgstr "XML 라이브러리를 초기화할 수 없음"
+
+#: utils/adt/xml.c:911
+#, c-format
+msgid ""
+"libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u."
+msgstr ""
+"libxml2에 호환되지 않는 문자 자료형 있음: sizeof(char)=%u, sizeof(xmlChar)=%u"
+
+#: utils/adt/xml.c:997
+#, c-format
+msgid "could not set up XML error handler"
+msgstr "XML 오류 핸들러를 설정할 수 없음"
+
+#: utils/adt/xml.c:998
+#, c-format
+msgid ""
+"This probably indicates that the version of libxml2 being used is not "
+"compatible with the libxml2 header files that PostgreSQL was built with."
+msgstr ""
+"이 문제는 PostgreSQL 서버를 만들 때 사용한 libxml2 헤더 파일이 호환성이 없는 "
+"것 같습니다."
+
+#: utils/adt/xml.c:1735
+msgid "Invalid character value."
+msgstr "잘못된 문자 값입니다."
+
+#: utils/adt/xml.c:1738
+msgid "Space required."
+msgstr "공간이 필요합니다."
+
+#: utils/adt/xml.c:1741
+msgid "standalone accepts only 'yes' or 'no'."
+msgstr "독립 실행형은 &apos;yes&apos; 또는 &apos;no&apos;만 허용합니다."
+
+#: utils/adt/xml.c:1744
+msgid "Malformed declaration: missing version."
+msgstr "선언 형식이 잘못됨: 버전이 누락되었습니다."
+
+#: utils/adt/xml.c:1747
+msgid "Missing encoding in text declaration."
+msgstr "텍스트 선언에서 인코딩이 누락되었습니다."
+
+#: utils/adt/xml.c:1750
+msgid "Parsing XML declaration: '?>' expected."
+msgstr "XML 선언 구문 분석 중: &apos;?&gt;&apos;가 필요합니다."
+
+#: utils/adt/xml.c:1753
+#, c-format
+msgid "Unrecognized libxml error code: %d."
+msgstr "인식할 수 없는 libxml 오류 코드: %d."
+
+#: utils/adt/xml.c:2028
+#, c-format
+msgid "XML does not support infinite date values."
+msgstr "XML은 무한 날짜 값을 지원하지 않습니다."
+
+#: utils/adt/xml.c:2050 utils/adt/xml.c:2077
+#, c-format
+msgid "XML does not support infinite timestamp values."
+msgstr "XML은 무한 타임스탬프 값을 지원하지 않습니다."
+
+#: utils/adt/xml.c:2468
+#, c-format
+msgid "invalid query"
+msgstr "잘못된 쿼리"
+
+#: utils/adt/xml.c:3793
+#, c-format
+msgid "invalid array for XML namespace mapping"
+msgstr "XML 네임스페이스 매핑에 사용할 배열이 잘못됨"
+
+#: utils/adt/xml.c:3794
+#, c-format
+msgid ""
+"The array must be two-dimensional with length of the second axis equal to 2."
+msgstr ""
+"이 배열은 key, value로 구성된 배열을 요소로 하는 2차원 배열이어야 합니다."
+
+#: utils/adt/xml.c:3818
+#, c-format
+msgid "empty XPath expression"
+msgstr "XPath 식이 비어 있음"
+
+#: utils/adt/xml.c:3867
+#, c-format
+msgid "neither namespace name nor URI may be null"
+msgstr "네임스페이스 이름 및 URI는 null일 수 없음"
+
+#: utils/adt/xml.c:3874
+#, c-format
+msgid "could not register XML namespace with name \"%s\" and URI \"%s\""
+msgstr ""
+"이름 \"%s\" 및 URI \"%s\"을(를) 사용하여 XML 네임스페이스를 등록할 수 없음"
+
+# # nonun 부분 end
+#: utils/cache/lsyscache.c:2580 utils/cache/lsyscache.c:2613
+#: utils/cache/lsyscache.c:2646 utils/cache/lsyscache.c:2679
+#, c-format
+msgid "type %s is only a shell"
+msgstr "%s 형식은 셸일 뿐임"
+
+#: utils/cache/lsyscache.c:2585
+#, c-format
+msgid "no input function available for type %s"
+msgstr "%s 자료형을 위한 입력 함수가 없습니다"
+
+#: utils/cache/lsyscache.c:2618
+#, c-format
+msgid "no output function available for type %s"
+msgstr "%s 자료형을 위한 출력 함수가 없습니다"
+
+#: utils/cache/plancache.c:718
+#, c-format
+msgid "cached plan must not change result type"
+msgstr "캐시된 계획에서 결과 형식을 바꾸지 않아야 함"
+
+#: utils/cache/relcache.c:5226
+#, c-format
+msgid "could not create relation-cache initialization file \"%s\": %m"
+msgstr "\"%s\" 릴레이션-캐시 초기화 파일을 만들 수 없음: %m"
+
+#: utils/cache/relcache.c:5228
+#, c-format
+msgid "Continuing anyway, but there's something wrong."
+msgstr "어쨌든 계속하는데, 뭔가 잘못 된 것이 있습니다."
+
+#: utils/cache/relcache.c:5502
+#, c-format
+msgid "could not remove cache file \"%s\": %m"
+msgstr "\"%s\" 캐쉬 파일을 삭제할 수 없음: %m"
+
+#: utils/cache/relmapper.c:508
+#, c-format
+msgid "cannot PREPARE a transaction that modified relation mapping"
+msgstr "릴레이션 맵핑을 변경하는 트랜잭셜을 PREPARE할 수 없음"
+
+#: utils/cache/relmapper.c:651 utils/cache/relmapper.c:751
+#, c-format
+msgid "could not open relation mapping file \"%s\": %m"
+msgstr "\"%s\" 릴레이션 맵핑 파일을 열 수 없음: %m"
+
+#: utils/cache/relmapper.c:664
+#, c-format
+msgid "could not read relation mapping file \"%s\": %m"
+msgstr "\"%s\" 릴레이션 맵핑 파일을 읽을 수 없음: %m"
+
+#: utils/cache/relmapper.c:674
+#, c-format
+msgid "relation mapping file \"%s\" contains invalid data"
+msgstr "\"%s\" 릴레이션 맵핑 파일에 잘못된 데이터가 있습니다"
+
+#: utils/cache/relmapper.c:684
+#, c-format
+msgid "relation mapping file \"%s\" contains incorrect checksum"
+msgstr "\"%s\" 릴레이션 맵핑 파일에 잘못된 checksum 값이 있음"
+
+#: utils/cache/relmapper.c:784
+#, c-format
+msgid "could not write to relation mapping file \"%s\": %m"
+msgstr "\"%s\" 릴레이션 맵핑 파일을 쓸 수 없습니다: %m"
+
+#: utils/cache/relmapper.c:797
+#, c-format
+msgid "could not fsync relation mapping file \"%s\": %m"
+msgstr "\"%s\" 릴레이션 맵핑 파일을 fsync 할 수 없음: %m"
+
+#: utils/cache/relmapper.c:803
+#, c-format
+msgid "could not close relation mapping file \"%s\": %m"
+msgstr "\"%s\" 릴레이션 맵핑 파일을 닫을 수 없음: %m"
+
+#: utils/cache/typcache.c:1207
+#, c-format
+msgid "type %s is not composite"
+msgstr "%s 자료형은 복합 자료형이 아닙니다"
+
+#: utils/cache/typcache.c:1221
+#, c-format
+msgid "record type has not been registered"
+msgstr "레코드 형식이 등록되지 않았음"
+
+#: utils/error/assert.c:34
+#, c-format
+msgid "TRAP: ExceptionalCondition: bad arguments\n"
+msgstr "TRAP: ExceptionalCondition: 잘못된 인자\n"
+
+#: utils/error/assert.c:37
+#, c-format
+msgid "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n"
+msgstr "TRAP: %s(\"%s\", 파일: \"%s\", 줄: %d)\n"
+
+#: utils/error/elog.c:322 utils/error/elog.c:1306
+#, c-format
+msgid "error occurred at %s:%d before error message processing is available\n"
+msgstr "오류 메시지 처리가 활성화 되기 전에 %s:%d 에서 오류가 발생했습니다\n"
+
+#: utils/error/elog.c:1889
+#, c-format
+msgid "could not reopen file \"%s\" as stderr: %m"
+msgstr "stderr 로 사용하기 위해 \"%s\" 파일 다시 열기 실패: %m"
+
+#: utils/error/elog.c:1902
+#, c-format
+msgid "could not reopen file \"%s\" as stdout: %m"
+msgstr "표준출력(stdout)으로 사용하기 위해 \"%s\" 파일을 여는 도중 실패: %m"
+
+#: utils/error/elog.c:2389 utils/error/elog.c:2406 utils/error/elog.c:2422
+msgid "[unknown]"
+msgstr "[알수없음]"
+
+#: utils/error/elog.c:2882 utils/error/elog.c:3185 utils/error/elog.c:3293
+msgid "missing error text"
+msgstr "오류 내용을 뺍니다"
+
+#: utils/error/elog.c:2885 utils/error/elog.c:2888 utils/error/elog.c:3296
+#: utils/error/elog.c:3299
+#, c-format
+msgid " at character %d"
+msgstr " %d 번째 문자 부근"
+
+#: utils/error/elog.c:2898 utils/error/elog.c:2905
+msgid "DETAIL: "
+msgstr "상세정보: "
+
+#: utils/error/elog.c:2912
+msgid "HINT: "
+msgstr "힌트: "
+
+#: utils/error/elog.c:2919
+msgid "QUERY: "
+msgstr "쿼리:"
+
+#: utils/error/elog.c:2926
+msgid "CONTEXT: "
+msgstr "내용: "
+
+#: utils/error/elog.c:2936
+#, c-format
+msgid "LOCATION: %s, %s:%d\n"
+msgstr "위치: %s, %s:%d\n"
+
+#: utils/error/elog.c:2943
+#, c-format
+msgid "LOCATION: %s:%d\n"
+msgstr "위치: %s:%d\n"
+
+#: utils/error/elog.c:2957
+msgid "STATEMENT: "
+msgstr "명령 구문: "
+
+#. translator: This string will be truncated at 47
+#. characters expanded.
+#: utils/error/elog.c:3414
+#, c-format
+msgid "operating system error %d"
+msgstr "운영체제 오류 %d"
+
+#: utils/error/elog.c:3612
+msgid "DEBUG"
+msgstr "디버그"
+
+#: utils/error/elog.c:3616
+msgid "LOG"
+msgstr "로그"
+
+#: utils/error/elog.c:3619
+msgid "INFO"
+msgstr "정보"
+
+#: utils/error/elog.c:3622
+msgid "NOTICE"
+msgstr "알림"
+
+#: utils/error/elog.c:3625
+msgid "WARNING"
+msgstr "경고"
+
+#: utils/error/elog.c:3628
+msgid "ERROR"
+msgstr "오류"
+
+#: utils/error/elog.c:3631
+msgid "FATAL"
+msgstr "치명적오류"
+
+#: utils/error/elog.c:3634
+msgid "PANIC"
+msgstr "손상"
+
+#: utils/fmgr/dfmgr.c:117
+#, c-format
+msgid "could not find function \"%s\" in file \"%s\""
+msgstr "\"%s\" 함수를 \"%s\" 파일에서 찾을 수 없음"
+
+#: utils/fmgr/dfmgr.c:196 utils/fmgr/dfmgr.c:405 utils/fmgr/dfmgr.c:453
+#, c-format
+msgid "could not access file \"%s\": %m"
+msgstr "\"%s\" 파일에 액세스할 수 없음: %m"
+
+#: utils/fmgr/dfmgr.c:234
+#, c-format
+msgid "could not load library \"%s\": %s"
+msgstr "\"%s\" 라이브러리를 불러 올 수 없음: %s"
+
+#: utils/fmgr/dfmgr.c:266
+#, c-format
+msgid "incompatible library \"%s\": missing magic block"
+msgstr "\"%s\" 라이브러리는 사용할 수 없습니다: magic black 없음"
+
+#: utils/fmgr/dfmgr.c:268
+#, c-format
+msgid "Extension libraries are required to use the PG_MODULE_MAGIC macro."
+msgstr "확장 라이브러리를 만들 때, PG_MODULE_MAGIC 매크로를 사용해서 만드세요."
+
+#: utils/fmgr/dfmgr.c:304
+#, c-format
+msgid "incompatible library \"%s\": version mismatch"
+msgstr "\"%s\" 라이브러리는 사용할 수 없습니다: 버전이 틀림"
+
+#: utils/fmgr/dfmgr.c:306
+#, c-format
+msgid "Server is version %d.%d, library is version %d.%d."
+msgstr "서버 버전 = %d.%d, 라이브러리 버전 %d.%d."
+
+#: utils/fmgr/dfmgr.c:325
+#, c-format
+msgid "Server has FUNC_MAX_ARGS = %d, library has %d."
+msgstr "서버의 경우 FUNC_MAX_ARGS = %d인데 라이브러리에 %d이(가) 있습니다."
+
+#: utils/fmgr/dfmgr.c:334
+#, c-format
+msgid "Server has INDEX_MAX_KEYS = %d, library has %d."
+msgstr "서버의 경우 INDEX_MAX_KEYS = %d인데 라이브러리에 %d이(가) 있습니다."
+
+#: utils/fmgr/dfmgr.c:343
+#, c-format
+msgid "Server has NAMEDATALEN = %d, library has %d."
+msgstr "서버의 경우 NAMEDATALEN = %d인데 라이브러리에 %d이(가) 있습니다."
+
+#: utils/fmgr/dfmgr.c:352
+#, c-format
+msgid "Server has FLOAT4PASSBYVAL = %s, library has %s."
+msgstr "서버의 경우 FLOAT4PASSBYVAL = %s인데 라이브러리에 %s이(가) 있습니다."
+
+#: utils/fmgr/dfmgr.c:361
+#, c-format
+msgid "Server has FLOAT8PASSBYVAL = %s, library has %s."
+msgstr "서버의 경우 FLOAT8PASSBYVAL = %s인데 라이브러리에 %s이(가) 있습니다."
+
+#: utils/fmgr/dfmgr.c:368
+msgid "Magic block has unexpected length or padding difference."
+msgstr "매직 블록에 예기치 않은 길이 또는 여백 차이가 있습니다."
+
+#: utils/fmgr/dfmgr.c:371
+#, c-format
+msgid "incompatible library \"%s\": magic block mismatch"
+msgstr "\"%s\" 라이브러리는 사용할 수 없습니다: magic black 틀림"
+
+#: utils/fmgr/dfmgr.c:535
+#, c-format
+msgid "access to library \"%s\" is not allowed"
+msgstr "\"%s\" 라이브러리 사용이 금지되어있습니다"
+
+#: utils/fmgr/dfmgr.c:561
+#, c-format
+msgid "invalid macro name in dynamic library path: %s"
+msgstr "동적 라이브러리 경로에서 잘못된 매크로 이름: %s"
+
+#: utils/fmgr/dfmgr.c:601
+#, c-format
+msgid "zero-length component in parameter \"dynamic_library_path\""
+msgstr "\"dynamic_library_path\" 매개 변수 값으로 길이가 0인 값을 사용했음"
+
+#: utils/fmgr/dfmgr.c:620
+#, c-format
+msgid "component in parameter \"dynamic_library_path\" is not an absolute path"
+msgstr "\"dynamic_library_path\" 매개 변수 값으로 절대 경로를 사용할 수 없음"
+
+#: utils/fmgr/fmgr.c:272
+#, c-format
+msgid "internal function \"%s\" is not in internal lookup table"
+msgstr "\"%s\" 내부 함수를 내부 검색 테이블에서 찾을 수 없습니다"
+
+#: utils/fmgr/fmgr.c:479
+#, c-format
+msgid "unrecognized API version %d reported by info function \"%s\""
+msgstr "_^_ %d 알수 없는 API 버전이 \"%s\" 함수에 의해서 보고되었음"
+
+#: utils/fmgr/fmgr.c:849 utils/fmgr/fmgr.c:2106
+#, c-format
+msgid "function %u has too many arguments (%d, maximum is %d)"
+msgstr "%u 함수는 너무 많은 인자를 사용하고 있음 (%d, 최대 %d)"
+
+#: utils/fmgr/fmgr.c:2527
+#, c-format
+msgid "language validation function %u called for language %u instead of %u"
+msgstr ""
+"%u OID 언어 유효성 검사 함수가 %u OID 프로시져 언어용으로 호출되었음, 원래 언"
+"어는 %u"
+
+#: utils/fmgr/funcapi.c:353
+#, c-format
+msgid ""
+"could not determine actual result type for function \"%s\" declared to "
+"return type %s"
+msgstr "\"%s\" 함수의 실재 리턴 자료형을 알 수 없음, 정의된 리턴 자료형: %s"
+
+#: utils/fmgr/funcapi.c:1340 utils/fmgr/funcapi.c:1371
+#, c-format
+msgid "number of aliases does not match number of columns"
+msgstr "alias 수가 열 수와 틀립니다"
+
+#: utils/fmgr/funcapi.c:1365
+#, c-format
+msgid "no column alias was provided"
+msgstr "열 별칭이 제공되지 않았음"
+
+#: utils/fmgr/funcapi.c:1389
+#, c-format
+msgid "could not determine row description for function returning record"
+msgstr "레코드를 리턴하는 함수를 위한 행(row) 구성 정보를 구할 수 없음"
+
+#: utils/init/miscinit.c:121
+#, c-format
+msgid "could not change directory to \"%s\": %m"
+msgstr "\"%s\" 이름의 디렉터리로 이동할 수 없습니다: %m"
+
+#: utils/init/miscinit.c:449 utils/misc/guc.c:6016
+#, c-format
+msgid "cannot set parameter \"%s\" within security-restricted operation"
+msgstr "보안 제한 작업 내에서 \"%s\" 매개 변수를 설정할 수 없음"
+
+#: utils/init/miscinit.c:510
+#, c-format
+msgid "role with OID %u does not exist"
+msgstr "%u OID 롤이 없음"
+
+#: utils/init/miscinit.c:540
+#, c-format
+msgid "role \"%s\" is not permitted to log in"
+msgstr "\"%s\" 롤은 접속을 허용하지 않음"
+
+#: utils/init/miscinit.c:558
+#, c-format
+msgid "too many connections for role \"%s\""
+msgstr "\"%s\" 롤의 최대 동시 접속수를 초과했습니다"
+
+#: utils/init/miscinit.c:618
+#, c-format
+msgid "permission denied to set session authorization"
+msgstr "세션 인증을 지정하기 위한 권한이 없음"
+
+#: utils/init/miscinit.c:701
+#, c-format
+msgid "invalid role OID: %u"
+msgstr "잘못된 롤 OID: %u"
+
+#: utils/init/miscinit.c:755
+#, c-format
+msgid "database system is shut down"
+msgstr "데이터베이스 시스템 서비스를 중지했습니다"
+
+#: utils/init/miscinit.c:842
+#, c-format
+msgid "could not create lock file \"%s\": %m"
+msgstr "\"%s\" 잠금 파일을 만들 수 없음: %m"
+
+#: utils/init/miscinit.c:856
+#, c-format
+msgid "could not open lock file \"%s\": %m"
+msgstr "\"%s\" 잠금파일을 열 수 없음: %m"
+
+#: utils/init/miscinit.c:862
+#, c-format
+msgid "could not read lock file \"%s\": %m"
+msgstr "\"%s\" 잠금 파일을 읽을 수 없음: %m"
+
+#: utils/init/miscinit.c:870
+#, c-format
+msgid "lock file \"%s\" is empty"
+msgstr "\"%s\" 잠금 파일이 비었음"
+
+#: utils/init/miscinit.c:871
+#, c-format
+msgid ""
+"Either another server is starting, or the lock file is the remnant of a "
+"previous server startup crash."
+msgstr ""
+
+#: utils/init/miscinit.c:918
+#, c-format
+msgid "lock file \"%s\" already exists"
+msgstr "\"%s\" 잠금 파일이 이미 있음"
+
+#: utils/init/miscinit.c:922
+#, c-format
+msgid "Is another postgres (PID %d) running in data directory \"%s\"?"
+msgstr ""
+"다른 postgres 프로그램(PID %d)이 \"%s\" 데이터 디렉터리를 사용해서 실행중입니"
+"까?"
+
+#: utils/init/miscinit.c:924
+#, c-format
+msgid "Is another postmaster (PID %d) running in data directory \"%s\"?"
+msgstr ""
+"다른 postmaster 프로그램(PID %d)이 \"%s\" 데이터 디렉터리를 사용해서 실행중입"
+"니까?"
+
+#: utils/init/miscinit.c:927
+#, c-format
+msgid "Is another postgres (PID %d) using socket file \"%s\"?"
+msgstr ""
+"다른 postgres 프로그램(PID %d)이 \"%s\" 소켓 파일을 사용해서 실행중입니까?"
+
+#: utils/init/miscinit.c:929
+#, c-format
+msgid "Is another postmaster (PID %d) using socket file \"%s\"?"
+msgstr ""
+"다른 postmaster 프로그램(PID %d)이 \"%s\" 소켓 파일을 사용해서 실행중입니까?"
+
+#: utils/init/miscinit.c:965
+#, c-format
+msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use"
+msgstr "미리 확보된 공유 메모리 영역 (%lu 키, %lu ID)이 여전히 사용중입니다"
+
+#: utils/init/miscinit.c:968
+#, c-format
+msgid ""
+"If you're sure there are no old server processes still running, remove the "
+"shared memory block or just delete the file \"%s\"."
+msgstr ""
+"확실하게 공유 메모리를 사용하는 다른 프로세스가 없다고 판단되면, 공유 메모리 "
+"영역을 삭제하거나 \"%s\" 파일을 지우십시오."
+
+#: utils/init/miscinit.c:984
+#, c-format
+msgid "could not remove old lock file \"%s\": %m"
+msgstr "\"%s\" 옛 잠금 파일을 삭제할 수 없음: %m"
+
+#: utils/init/miscinit.c:986
+#, c-format
+msgid ""
+"The file seems accidentally left over, but it could not be removed. Please "
+"remove the file by hand and try again."
+msgstr ""
+"그파일은 우연찮게 왼쪽을 넘어간 것(?) 같습지만, 삭제될 수는 없습니다. 직접 "
+"셸 명령을 이용해서 파일을 삭제 하고 다시 시도해 보십시오. - 내용 참 거시기 하"
+"네"
+
+#: utils/init/miscinit.c:1022 utils/init/miscinit.c:1033
+#: utils/init/miscinit.c:1043
+#, c-format
+msgid "could not write lock file \"%s\": %m"
+msgstr "\"%s\" 잠금 파일에 쓸 수 없음: %m"
+
+#: utils/init/miscinit.c:1172 utils/init/miscinit.c:1301 utils/misc/guc.c:8818
+#, c-format
+msgid "could not read from file \"%s\": %m"
+msgstr "\"%s\" 파일을 읽을 수 없음: %m"
+
+#: utils/init/miscinit.c:1291
+#, c-format
+msgid "could not open file \"%s\": %m; continuing anyway"
+msgstr "\"%s\" 파일을 열 수 없음: %m; 어째든 계속 진행함"
+
+#: utils/init/miscinit.c:1314
+#, c-format
+msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld"
+msgstr "\"%s\" 잠금 파일에 있는 PID 값이 이상합니다: 현재값 %ld, 원래값 %ld"
+
+#: utils/init/miscinit.c:1356 utils/init/miscinit.c:1369
+#, c-format
+msgid "\"%s\" is not a valid data directory"
+msgstr "\"%s\" 값은 바른 데이터디렉터리가 아닙니다"
+
+#: utils/init/miscinit.c:1358
+#, c-format
+msgid "File \"%s\" is missing."
+msgstr "\"%s\" 파일이 없습니다."
+
+#: utils/init/miscinit.c:1371
+#, c-format
+msgid "File \"%s\" does not contain valid data."
+msgstr "\"%s\" 파일에 잘못된 자료가 기록되어 있습니다."
+
+#: utils/init/miscinit.c:1373
+#, c-format
+msgid "You might need to initdb."
+msgstr "initdb 명령을 실행해 새 클러스터를 만들어야 할 수도 있습니다."
+
+#: utils/init/miscinit.c:1381
+#, c-format
+msgid ""
+"The data directory was initialized by PostgreSQL version %ld.%ld, which is "
+"not compatible with this version %s."
+msgstr ""
+"이 데이터 디렉터리는 PostgreSQL %ld.%ld 버전으로 초기화 되어있는데, 이 서버"
+"의 %s 버전은 이 버전과 호환성이 없습니다."
+
+#: utils/init/miscinit.c:1452
+#, c-format
+msgid "loaded library \"%s\""
+msgstr "\"%s\" 라이브러리 로드 완료"
+
+#: utils/init/postinit.c:251
+#, c-format
+msgid ""
+"replication connection authorized: user=%s SSL enabled (protocol=%s, cipher="
+"%s, compression=%s)"
+msgstr ""
+"복제 연결 인증: 사용자=%s SSL 활성화 (프로토콜=%s, 알고리즘=%s, 압축=%s)"
+
+#: utils/init/postinit.c:253 utils/init/postinit.c:267
+msgid "off"
+msgstr "off"
+
+#: utils/init/postinit.c:253 utils/init/postinit.c:267
+msgid "on"
+msgstr "on"
+
+#: utils/init/postinit.c:257
+#, c-format
+msgid "replication connection authorized: user=%s"
+msgstr "복제 연결 인증: 사용자=%s"
+
+#: utils/init/postinit.c:265
+#, c-format
+msgid ""
+"connection authorized: user=%s database=%s SSL enabled (protocol=%s, cipher="
+"%s, compression=%s)"
+msgstr ""
+"연결 인증: 사용자=%s 데이터베이스=%s SSL 활성화 (프로토콜=%s, 알고리즘=%s, 압"
+"축=%s)"
+
+#: utils/init/postinit.c:271
+#, c-format
+msgid "connection authorized: user=%s database=%s"
+msgstr "연결 인증: 사용자=%s 데이터베이스=%s"
+
+#: utils/init/postinit.c:303
+#, c-format
+msgid "database \"%s\" has disappeared from pg_database"
+msgstr "\"%s\" 데이터베이스는 pg_database 항목에 없습니다"
+
+#: utils/init/postinit.c:305
+#, c-format
+msgid "Database OID %u now seems to belong to \"%s\"."
+msgstr "데이터베이스 OID %u이(가) 현재 \"%s\"에 속해 있는 것 같습니다."
+
+#: utils/init/postinit.c:325
+#, c-format
+msgid "database \"%s\" is not currently accepting connections"
+msgstr "\"%s\" 데이터베이스는 현재 접속을 허용하지 않습니다"
+
+#: utils/init/postinit.c:338
+#, c-format
+msgid "permission denied for database \"%s\""
+msgstr "\"%s\" 데이터베이스 액세스 권한 없음"
+
+#: utils/init/postinit.c:339
+#, c-format
+msgid "User does not have CONNECT privilege."
+msgstr "사용자에게 CONNECT 권한이 없습니다."
+
+#: utils/init/postinit.c:356
+#, c-format
+msgid "too many connections for database \"%s\""
+msgstr "\"%s\" 데이터베이스 최대 접속수를 초과했습니다"
+
+#: utils/init/postinit.c:378 utils/init/postinit.c:385
+#, c-format
+msgid "database locale is incompatible with operating system"
+msgstr "데이터베이스 로케일이 운영 체제와 호환되지 않음"
+
+#: utils/init/postinit.c:379
+#, c-format
+msgid ""
+"The database was initialized with LC_COLLATE \"%s\", which is not "
+"recognized by setlocale()."
+msgstr ""
+"데이터베이스가 setlocale()에서 인식할 수 없는 LC_COLLATE \"%s\"(으)로 초기화"
+"되었습니다."
+
+#: utils/init/postinit.c:381 utils/init/postinit.c:388
+#, c-format
+msgid ""
+"Recreate the database with another locale or install the missing locale."
+msgstr ""
+"다른 로케일로 데이터베이스를 다시 만들거나 누락된 로케일을 설치하십시오."
+
+#: utils/init/postinit.c:386
+#, c-format
+msgid ""
+"The database was initialized with LC_CTYPE \"%s\", which is not recognized "
+"by setlocale()."
+msgstr ""
+"setlocale()에서 인식할 수 없는 \"%s\" LC_CTYPE 값으로 데이터베이스가 초기화되"
+"었습니다."
+
+#: utils/init/postinit.c:714
+#, c-format
+msgid "no roles are defined in this database system"
+msgstr "이 데이터베이스에는 어떠한 롤 정의도 없습니다"
+
+#: utils/init/postinit.c:715
+#, c-format
+msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;."
+msgstr "다음 명령을 먼저 실행하십시오: CREATE USER \"%s\" SUPERUSER;."
+
+#: utils/init/postinit.c:751
+#, c-format
+msgid "new replication connections are not allowed during database shutdown"
+msgstr "데이터베이스 중지 중에는 새로운 복제 연결을 할 수 없습니다."
+
+#: utils/init/postinit.c:755
+#, c-format
+msgid "must be superuser to connect during database shutdown"
+msgstr "슈퍼유저만 데이터베이스 종료 중에 연결할 수 있음"
+
+#: utils/init/postinit.c:765
+#, c-format
+msgid "must be superuser to connect in binary upgrade mode"
+msgstr "슈퍼유저만 바이너리 업그레이드 모드 중에 연결 할 수 있음"
+
+#: utils/init/postinit.c:779
+#, c-format
+msgid ""
+"remaining connection slots are reserved for non-replication superuser "
+"connections"
+msgstr "남은 연결 슬롯은 non-replication 슈퍼유저 연결용으로 남겨 놓았음"
+
+#: utils/init/postinit.c:789
+#, c-format
+msgid "must be superuser or replication role to start walsender"
+msgstr ""
+"superuser 또는 replication 권한을 가진 롤만 walsender 프로세스를 시작할 수 있"
+"음"
+
+#: utils/init/postinit.c:858
+#, c-format
+msgid "database %u does not exist"
+msgstr "%u 데이터베이스가 없음"
+
+#: utils/init/postinit.c:944
+#, c-format
+msgid "It seems to have just been dropped or renamed."
+msgstr "삭제되었거나 이름이 바뀐 것 같습니다."
+
+#: utils/init/postinit.c:962
+#, c-format
+msgid "The database subdirectory \"%s\" is missing."
+msgstr "데이터베이스 디렉터리에 \"%s\" 하위 디렉터리가 없습니다"
+
+#: utils/init/postinit.c:967
+#, c-format
+msgid "could not access directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m"
+
+#: utils/mb/conv.c:405 utils/mb/conv.c:591
+#, c-format
+msgid "invalid encoding number: %d"
+msgstr "잘못된 인코딩 번호: %d"
+
+#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:137
+#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:169
+#, c-format
+msgid "unexpected encoding ID %d for ISO 8859 character sets"
+msgstr "%d은(는) ISO 8859 문자 집합에 대한 예기치 않은 인코딩 ID임"
+
+#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:127
+#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:159
+#, c-format
+msgid "unexpected encoding ID %d for WIN character sets"
+msgstr "%d은(는) WIN 문자 집합에 대한 예기치 않은 인코딩 ID임"
+
+#: utils/mb/encnames.c:496
+#, c-format
+msgid "encoding name too long"
+msgstr "인코딩 이름이 너무 깁니다"
+
+#: utils/mb/mbutils.c:307
+#, c-format
+msgid "conversion between %s and %s is not supported"
+msgstr "%s 인코딩과 %s 인코딩 사이의 변환은 지원하지 않습니다"
+
+#: utils/mb/mbutils.c:366
+#, c-format
+msgid ""
+"default conversion function for encoding \"%s\" to \"%s\" does not exist"
+msgstr ""
+"\"%s\" 인코딩을 \"%s\" 인코딩으로 변환할 기본 변환규칙(conversion)이 없음"
+
+#: utils/mb/mbutils.c:377 utils/mb/mbutils.c:710
+#, c-format
+msgid "String of %d bytes is too long for encoding conversion."
+msgstr "%d바이트의 문자열은 너무 길어서 인코딩 규칙에 맞지 않습니다."
+
+#: utils/mb/mbutils.c:464
+#, c-format
+msgid "invalid source encoding name \"%s\""
+msgstr "\"%s\" 원본 인코딩 이름이 타당치 못함"
+
+#: utils/mb/mbutils.c:469
+#, c-format
+msgid "invalid destination encoding name \"%s\""
+msgstr "\"%s\" 대상 인코딩 이름이 타당치 못함"
+
+#: utils/mb/mbutils.c:609
+#, c-format
+msgid "invalid byte value for encoding \"%s\": 0x%02x"
+msgstr "\"%s\" 인코딩에서 사용할 수 없는 바이트: 0x%02x"
+
+#: utils/mb/mbutils.c:951
+#, c-format
+msgid "bind_textdomain_codeset failed"
+msgstr "bind_textdomain_codeset 실패"
+
+#: utils/mb/wchar.c:2015
+#, c-format
+msgid "invalid byte sequence for encoding \"%s\": %s"
+msgstr "\"%s\" 인코딩에서 사용할 수 없는 문자가 있음: %s"
+
+#: utils/mb/wchar.c:2048
+#, c-format
+msgid ""
+"character with byte sequence %s in encoding \"%s\" has no equivalent in "
+"encoding \"%s\""
+msgstr ""
+"%s 바이트로 조합된 문자(인코딩: \"%s\")와 대응되는 문자 코드가 \"%s\" 인코딩"
+"에는 없습니다"
+
+#: utils/misc/guc.c:548
+msgid "Ungrouped"
+msgstr "소속그룹없음"
+
+#: utils/misc/guc.c:550
+msgid "File Locations"
+msgstr "파일 위치"
+
+#: utils/misc/guc.c:552
+msgid "Connections and Authentication"
+msgstr "연결과 인증"
+
+#: utils/misc/guc.c:554
+msgid "Connections and Authentication / Connection Settings"
+msgstr "연결과 인증 / 연결 설정값"
+
+#: utils/misc/guc.c:556
+msgid "Connections and Authentication / Security and Authentication"
+msgstr "연결과 안증 / 보안과 인증"
+
+#: utils/misc/guc.c:558
+msgid "Resource Usage"
+msgstr "자원 사용량"
+
+#: utils/misc/guc.c:560
+msgid "Resource Usage / Memory"
+msgstr "자원 사용량 / 메모리"
+
+#: utils/misc/guc.c:562
+msgid "Resource Usage / Disk"
+msgstr "자원 사용량 / 디스크"
+
+#: utils/misc/guc.c:564
+msgid "Resource Usage / Kernel Resources"
+msgstr "자원 사용량 / 커널 자원"
+
+#: utils/misc/guc.c:566
+msgid "Resource Usage / Cost-Based Vacuum Delay"
+msgstr "자원 사용량 / 비용기반 청소 지연"
+
+#: utils/misc/guc.c:568
+msgid "Resource Usage / Background Writer"
+msgstr "자원 사용량 / 백그라운드 쓰기"
+
+#: utils/misc/guc.c:570
+msgid "Resource Usage / Asynchronous Behavior"
+msgstr "자원 사용량 / 비동기 기능"
+
+#: utils/misc/guc.c:572
+msgid "Write-Ahead Log"
+msgstr "Write-Ahead 로그"
+
+#: utils/misc/guc.c:574
+msgid "Write-Ahead Log / Settings"
+msgstr "Write-Ahead 로그 / 설정값"
+
+#: utils/misc/guc.c:576
+msgid "Write-Ahead Log / Checkpoints"
+msgstr "Write-Ahead 로그 / 체크포인트"
+
+#: utils/misc/guc.c:578
+msgid "Write-Ahead Log / Archiving"
+msgstr "Write-Ahead 로그 / 아카이브"
+
+#: utils/misc/guc.c:580
+msgid "Replication"
+msgstr "복제"
+
+#: utils/misc/guc.c:582
+msgid "Replication / Sending Servers"
+msgstr "복제 / 보내기 서버"
+
+#: utils/misc/guc.c:584
+msgid "Replication / Master Server"
+msgstr "복제 / 주 서버"
+
+#: utils/misc/guc.c:586
+msgid "Replication / Standby Servers"
+msgstr "복제 / 대기 서버"
+
+#: utils/misc/guc.c:588
+msgid "Query Tuning"
+msgstr "쿼리 튜닝"
+
+#: utils/misc/guc.c:590
+msgid "Query Tuning / Planner Method Configuration"
+msgstr "쿼리 튜닝 / 실행계획기 메서드 설정"
+
+#: utils/misc/guc.c:592
+msgid "Query Tuning / Planner Cost Constants"
+msgstr "쿼리 튜닝 / 실행계획기 비용 상수"
+
+#: utils/misc/guc.c:594
+msgid "Query Tuning / Genetic Query Optimizer"
+msgstr "쿼리 튜닝 / 일반적인 쿼리 최적화기"
+
+#: utils/misc/guc.c:596
+msgid "Query Tuning / Other Planner Options"
+msgstr "쿼리 튜닝 / 기타 실행계획기 옵션들"
+
+#: utils/misc/guc.c:598
+msgid "Reporting and Logging"
+msgstr "보고와 로그"
+
+#: utils/misc/guc.c:600
+msgid "Reporting and Logging / Where to Log"
+msgstr "보고와 로그 / 로그 위치"
+
+#: utils/misc/guc.c:602
+msgid "Reporting and Logging / When to Log"
+msgstr "보고와 로그 / 로그 시점"
+
+#: utils/misc/guc.c:604
+msgid "Reporting and Logging / What to Log"
+msgstr "보고와 로그 / 로그 내용"
+
+#: utils/misc/guc.c:606
+msgid "Process Title"
+msgstr "프로세스 제목"
+
+#: utils/misc/guc.c:608
+msgid "Statistics"
+msgstr "통계"
+
+#: utils/misc/guc.c:610
+msgid "Statistics / Monitoring"
+msgstr "통계 / 모니터링"
+
+#: utils/misc/guc.c:612
+msgid "Statistics / Query and Index Statistics Collector"
+msgstr "통계 / 쿼리 및 인덱스 사용 통계 수집기"
+
+#: utils/misc/guc.c:614
+msgid "Autovacuum"
+msgstr "Autovacuum"
+
+#: utils/misc/guc.c:616
+msgid "Client Connection Defaults"
+msgstr "클라이언트 연결 초기값"
+
+#: utils/misc/guc.c:618
+msgid "Client Connection Defaults / Statement Behavior"
+msgstr "클라이언트 연결 초기값 / 구문 특성"
+
+#: utils/misc/guc.c:620
+msgid "Client Connection Defaults / Locale and Formatting"
+msgstr "클라이언트 연결 초기값 / 로케일과 출력양식"
+
+#: utils/misc/guc.c:622
+msgid "Client Connection Defaults / Shared Library Preloading"
+msgstr "클라이언트 연결 초기값 / 공유 라이브러리 미리 로딩"
+
+#: utils/misc/guc.c:624
+msgid "Client Connection Defaults / Other Defaults"
+msgstr "클라이언트 연결 초기값 / 기타 초기값"
+
+#: utils/misc/guc.c:626
+msgid "Lock Management"
+msgstr "잠금 관리"
+
+#: utils/misc/guc.c:628
+msgid "Version and Platform Compatibility"
+msgstr "버전과 플랫폼 호환성"
+
+#: utils/misc/guc.c:630
+msgid "Version and Platform Compatibility / Previous PostgreSQL Versions"
+msgstr "버전과 플랫폼 호환성 / 이전 PostgreSQL 버전"
+
+#: utils/misc/guc.c:632
+msgid "Version and Platform Compatibility / Other Platforms and Clients"
+msgstr "버전과 플랫폼 호환성 / 다른 플랫폼과 클라이언트"
+
+#: utils/misc/guc.c:634
+msgid "Error Handling"
+msgstr "오류 처리"
+
+#: utils/misc/guc.c:636
+msgid "Preset Options"
+msgstr "프리셋 옵션들"
+
+#: utils/misc/guc.c:638
+msgid "Customized Options"
+msgstr "사용자 정의 옵션들"
+
+#: utils/misc/guc.c:640
+msgid "Developer Options"
+msgstr "개발자 옵션들"
+
+#: utils/misc/guc.c:697
+msgid "Valid units for this parameter are \"kB\", \"MB\", \"GB\", and \"TB\"."
+msgstr "이 매개 변수에 유효한 단위는 \"kB\", \"MB\",\"GB\", \"TB\" 입니다."
+
+#: utils/misc/guc.c:724
+msgid ""
+"Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\"."
+msgstr ""
+"이 매개 변수에 유효한 단위는 \"ms\", \"s\", \"min\", \"h\", \"d\" 입니다."
+
+#: utils/misc/guc.c:783
+msgid "Enables the planner's use of sequential-scan plans."
+msgstr "실행계획자가 순차적-스캔(sequential-sca) 계획을 사용함"
+
+#: utils/misc/guc.c:792
+msgid "Enables the planner's use of index-scan plans."
+msgstr "실행계획자가 인덱스-스캔 계획을 사용함."
+
+#: utils/misc/guc.c:801
+msgid "Enables the planner's use of index-only-scan plans."
+msgstr "실행계획자가 인덱스-전용-탐색 계획을 사용함."
+
+#: utils/misc/guc.c:810
+msgid "Enables the planner's use of bitmap-scan plans."
+msgstr "실행계획기가 bitmap-scan 계획을 사용하도록 함"
+
+#: utils/misc/guc.c:819
+msgid "Enables the planner's use of TID scan plans."
+msgstr "실행계획자가 TID 스캔 계획을 사용함"
+
+#: utils/misc/guc.c:828
+msgid "Enables the planner's use of explicit sort steps."
+msgstr "실행계획자가 명시 정렬 단계(explicit sort step)를 사용함"
+
+#: utils/misc/guc.c:837
+msgid "Enables the planner's use of hashed aggregation plans."
+msgstr "실행계획자가 해시된 집계 계획을 사용함"
+
+#: utils/misc/guc.c:846
+msgid "Enables the planner's use of materialization."
+msgstr "실행계획자가 materialization 계획을 사용함"
+
+#: utils/misc/guc.c:855
+msgid "Enables the planner's use of nested-loop join plans."
+msgstr "실행계획자가 근접순환 조인(nested-loop join) 계획을 사용함"
+
+#: utils/misc/guc.c:864
+msgid "Enables the planner's use of merge join plans."
+msgstr "실행계획자가 병합 조인(merge join) 계획을 사용함"
+
+#: utils/misc/guc.c:873
+msgid "Enables the planner's use of hash join plans."
+msgstr "실행계획자가 해시 조인(hash join) 계획을 사용함"
+
+#: utils/misc/guc.c:883
+msgid "Enables genetic query optimization."
+msgstr "유전적 쿼리 최적화(GEQO)를 사용함"
+
+#: utils/misc/guc.c:884
+msgid "This algorithm attempts to do planning without exhaustive searching."
+msgstr "이 알고리즘은 실행계획기의 과도한 작업 비용을 낮춥니다"
+
+#: utils/misc/guc.c:894
+msgid "Shows whether the current user is a superuser."
+msgstr "현재 사용자가 슈퍼유저인지 보여줍니다."
+
+#: utils/misc/guc.c:904
+msgid "Enables advertising the server via Bonjour."
+msgstr "Bonjour 서버 사용"
+
+#: utils/misc/guc.c:913
+msgid "Collects transaction commit time."
+msgstr "트랜잭션 커밋 시간을 수집함"
+
+#: utils/misc/guc.c:922
+msgid "Enables SSL connections."
+msgstr "SSL 연결을 가능하게 함."
+
+#: utils/misc/guc.c:931
+msgid "Give priority to server ciphersuite order."
+msgstr "SSL 인증 알고리즘 우선 순위를 정함"
+
+#: utils/misc/guc.c:940
+msgid "Forces synchronization of updates to disk."
+msgstr "강제로 변경된 버퍼 자료를 디스크와 동기화 시킴."
+
+#: utils/misc/guc.c:941
+msgid ""
+"The server will use the fsync() system call in several places to make sure "
+"that updates are physically written to disk. This insures that a database "
+"cluster will recover to a consistent state after an operating system or "
+"hardware crash."
+msgstr ""
+"이 서버는 fsync() 시스템 콜 기능을 여러 곳에서 사용할 것입니다. 이 기능은 물"
+"리적으로 디스크에 변경된 자료를 즉각적으로 기록함을 의미합니다. 이 기능은 시"
+"스템의 비정상적인 동작이나, 하드웨어에서 오류가 발생되었을 경우에도 자료를 안"
+"전하게 지킬 수 있도록 도와줄 것입니다."
+
+#: utils/misc/guc.c:952
+msgid "Continues processing after a checksum failure."
+msgstr "체크섬 실패 후 처리 계속 함"
+
+#: utils/misc/guc.c:953
+msgid ""
+"Detection of a checksum failure normally causes PostgreSQL to report an "
+"error, aborting the current transaction. Setting ignore_checksum_failure to "
+"true causes the system to ignore the failure (but still report a warning), "
+"and continue processing. This behavior could cause crashes or other serious "
+"problems. Only has an effect if checksums are enabled."
+msgstr ""
+"일반적으로 손상된 페이지 헤더를 발견하게 되면, PostgreSQL에서는 오류를 발생하"
+"고, 현재 트랜잭션을 중지합니다. ignore_checksum_failure 값을 true로 지정하"
+"면, 이런 손상된 페이지를 발견하면, 경고 메시지를 보여주고, 계속 진행합니다. "
+"이 기능을 사용한다 함은 서버 비정상 종료나 기타 심각한 문제가 일어 날 수 있습"
+"니다. 이 설정은 데이터 클러스터에서 체크섬 기능이 활성화 되어 있는 경우에만 "
+"영향을 받습니다."
+
+#: utils/misc/guc.c:967
+msgid "Continues processing past damaged page headers."
+msgstr "손상된 자료 헤더 발견시 작업 진행 여부 선택"
+
+#: utils/misc/guc.c:968
+msgid ""
+"Detection of a damaged page header normally causes PostgreSQL to report an "
+"error, aborting the current transaction. Setting zero_damaged_pages to true "
+"causes the system to instead report a warning, zero out the damaged page, "
+"and continue processing. This behavior will destroy data, namely all the "
+"rows on the damaged page."
+msgstr ""
+"일반적으로 손상된 페이지 헤더를 발견하게 되면, PostgreSQL에서는 오류를 발생하"
+"고, 현재 트랜잭션을 중지합니다. 이 값을 true로 지정하면, 이런 손상된 페이지"
+"를 발견하면, 경고 메시지를 보여주고, 그 페이지의 크기를 0으로 만들고 작업을 "
+"계속 진행합니다. 이 기능을 사용한다 함은 손상된 자료를 없애겠다는 것을 의미합"
+"니다. 이것은 곧 저장되어있는 자료가 삭제 될 수도 있음을 의미하기도 합니다."
+
+#: utils/misc/guc.c:981
+msgid "Writes full pages to WAL when first modified after a checkpoint."
+msgstr "체크포인트 후 처음 수정할 때 전체 페이지를 WAL에 씁니다."
+
+#: utils/misc/guc.c:982
+msgid ""
+"A page write in process during an operating system crash might be only "
+"partially written to disk. During recovery, the row changes stored in WAL "
+"are not enough to recover. This option writes pages when first modified "
+"after a checkpoint to WAL so full recovery is possible."
+msgstr ""
+"운영 체제가 비정상 종료되는 경우 처리 중인 페이지 쓰기는 디스크에 일부만 기록"
+"될 수도 있습니다. 복구 중 WAL에 저장된 로우 변경 내용이 부족하여 복구할 수 "
+"없을 수도 있습니다. 이 옵션은 안전하게 복구가 가능하도록 체크포인트 후 처음 "
+"수정한 페이지는 그 페이지 전체를 WAL에 씁니다."
+
+#: utils/misc/guc.c:995
+msgid ""
+"Writes full pages to WAL when first modified after a checkpoint, even for a "
+"non-critical modifications."
+msgstr ""
+"체크포인트 작업 후 자료 페이지에 첫 변경이 있는 경우, WAL에 변경된 내용만 기"
+"록하는 것이 아니라, 해당 페이지 전체를 기록합니다."
+
+#: utils/misc/guc.c:1005
+msgid "Compresses full-page writes written in WAL file."
+msgstr "WAL 파일에 기록되는 전체 페이지를 압축함"
+
+#: utils/misc/guc.c:1015
+msgid "Logs each checkpoint."
+msgstr "체크포인트 관련 정보를 기록합니다."
+
+#: utils/misc/guc.c:1024
+msgid "Logs each successful connection."
+msgstr "연결 성공한 정보들 모두를 기록함"
+
+#: utils/misc/guc.c:1033
+msgid "Logs end of a session, including duration."
+msgstr "기간을 포함하여 세션의 끝을 기록합니다."
+
+#: utils/misc/guc.c:1042
+msgid "Logs each replication command."
+msgstr "복제 관련 작업 내역을 기록합니다."
+
+#: utils/misc/guc.c:1051
+msgid "Shows whether the running server has assertion checks enabled."
+msgstr "서버가 assertion 검사 기능이 활성화 되어 실행되는지 보여 줌"
+
+#: utils/misc/guc.c:1066
+msgid "Terminate session on any error."
+msgstr "어떤 오류가 생기면 세션을 종료함"
+
+#: utils/misc/guc.c:1075
+msgid "Reinitialize server after backend crash."
+msgstr "백엔드가 비정상 종료되면 서버를 재초기화함"
+
+#: utils/misc/guc.c:1085
+msgid "Logs the duration of each completed SQL statement."
+msgstr "SQL 명령 구문의 실행완료 시간을 기록함"
+
+#: utils/misc/guc.c:1094
+msgid "Logs each query's parse tree."
+msgstr "각 쿼리의 구문 분석 트리를 기록합니다."
+
+#: utils/misc/guc.c:1103
+msgid "Logs each query's rewritten parse tree."
+msgstr "각 쿼리의 재작성된 구문 분석 트리를 기록합니다."
+
+#: utils/misc/guc.c:1112
+msgid "Logs each query's execution plan."
+msgstr "각 쿼리의 실행 계획을 기록합니다."
+
+#: utils/misc/guc.c:1121
+msgid "Indents parse and plan tree displays."
+msgstr "구문과 실행계획을 보여 줄때, 들여쓰기를 함."
+
+#: utils/misc/guc.c:1130
+msgid "Writes parser performance statistics to the server log."
+msgstr "구문분석 성능 통계를 서버 로그에 기록함."
+
+#: utils/misc/guc.c:1139
+msgid "Writes planner performance statistics to the server log."
+msgstr "실행계획자 성능 통계를 서버 로그에 기록함."
+
+#: utils/misc/guc.c:1148
+msgid "Writes executor performance statistics to the server log."
+msgstr "실행자 성능 통계를 서버 로그에 기록함."
+
+#: utils/misc/guc.c:1157
+msgid "Writes cumulative performance statistics to the server log."
+msgstr "누적 성능 통계를 서버 로그에 기록함."
+
+#: utils/misc/guc.c:1167
+msgid ""
+"Logs system resource usage statistics (memory and CPU) on various B-tree "
+"operations."
+msgstr "다양한 B트리 작업에 자원(메모리, CPU) 사용 통계를 기록에 남기"
+
+#: utils/misc/guc.c:1179
+msgid "Collects information about executing commands."
+msgstr "명령 실행에 대한 정보를 수집함"
+
+#: utils/misc/guc.c:1180
+msgid ""
+"Enables the collection of information on the currently executing command of "
+"each session, along with the time at which that command began execution."
+msgstr ""
+"각 세션에서 사용하고 있는 현재 실행 중인 명령의 수행 시간, 명령 내용등에 대"
+"한 정보를 수집하도록 함"
+
+#: utils/misc/guc.c:1190
+msgid "Collects statistics on database activity."
+msgstr "데이터베이스 활동에 대한 통계를 수집합니다."
+
+#: utils/misc/guc.c:1199
+msgid "Collects timing statistics for database I/O activity."
+msgstr "데이터베이스 I/O 활동에 대한 통계를 수집합니다."
+
+#: utils/misc/guc.c:1209
+msgid "Updates the process title to show the active SQL command."
+msgstr "활성 SQL 명령을 표시하도록 프로세스 제목을 업데이트합니다."
+
+#: utils/misc/guc.c:1210
+msgid ""
+"Enables updating of the process title every time a new SQL command is "
+"received by the server."
+msgstr ""
+"서버가 새 SQL 명령을 받을 때마다 프로세스 제목이 업데이트될 수 있도록 합니다."
+
+#: utils/misc/guc.c:1223
+msgid "Starts the autovacuum subprocess."
+msgstr "자동 청소 하위 프로세스를 실행함"
+
+#: utils/misc/guc.c:1233
+msgid "Generates debugging output for LISTEN and NOTIFY."
+msgstr "LISTEN, NOTIFY 명령 사용을 위한 디버깅 출력을 만듦."
+
+#: utils/misc/guc.c:1245
+msgid "Emits information about lock usage."
+msgstr "잠금 사용 정보를 로그로 남김"
+
+#: utils/misc/guc.c:1255
+msgid "Emits information about user lock usage."
+msgstr "사용자 잠금 사용 정보를 로그로 남김"
+
+#: utils/misc/guc.c:1265
+msgid "Emits information about lightweight lock usage."
+msgstr "가벼운 잠금 사용 정보를 로그로 남김"
+
+#: utils/misc/guc.c:1275
+msgid ""
+"Dumps information about all current locks when a deadlock timeout occurs."
+msgstr "교착 잠금 시간 제한 상황이 발생하면 그 때의 모든 잠금 정보를 보여줌"
+
+#: utils/misc/guc.c:1287
+msgid "Logs long lock waits."
+msgstr "긴 잠금 대기를 기록합니다."
+
+#: utils/misc/guc.c:1297
+msgid "Logs the host name in the connection logs."
+msgstr "연결 기록에서 호스트 이름을 기록함."
+
+#: utils/misc/guc.c:1298
+msgid ""
+"By default, connection logs only show the IP address of the connecting host. "
+"If you want them to show the host name you can turn this on, but depending "
+"on your host name resolution setup it might impose a non-negligible "
+"performance penalty."
+msgstr ""
+"이 기능은 기본적으로 연결기록에서 기본적으로 IP 주소만 기록합니다. 이 값을 "
+"true로 바꾼다면, 이 IP의 호스트 이름을 구해서 이 이름을 사용합니다 이것의 성"
+"능은 OS의 IP에서 이름구하기 성능과 관계됩니다."
+
+#: utils/misc/guc.c:1309
+msgid "Causes subtables to be included by default in various commands."
+msgstr ""
+"다양한 명령들에서 기본적으로 상속되는 테이블들 함께 사용할 것인지 정함."
+
+#: utils/misc/guc.c:1318
+msgid "Encrypt passwords."
+msgstr "암호를 암호화 해서 기록함"
+
+#: utils/misc/guc.c:1319
+msgid ""
+"When a password is specified in CREATE USER or ALTER USER without writing "
+"either ENCRYPTED or UNENCRYPTED, this parameter determines whether the "
+"password is to be encrypted."
+msgstr ""
+"CREATE USER 또는 ALTER USER 명령에서 ENCRYPTED 또는 UNENCRYPTED 속성을 특별"
+"히 지정하지 않았고 사용자 암호를 지정했을 때, 그 암호를 암호화 해서 저장할 것"
+"인지 아닌지를 지정함"
+
+#: utils/misc/guc.c:1329
+msgid "Treats \"expr=NULL\" as \"expr IS NULL\"."
+msgstr "\"표현=NULL\" 식을 \"표현 IS NULL\"로 취급함."
+
+#: utils/misc/guc.c:1330
+msgid ""
+"When turned on, expressions of the form expr = NULL (or NULL = expr) are "
+"treated as expr IS NULL, that is, they return true if expr evaluates to the "
+"null value, and false otherwise. The correct behavior of expr = NULL is to "
+"always return null (unknown)."
+msgstr ""
+"표현 = NULL 의 바른 처리는 항상 null 값을 리턴해야하지만, 편의성을 위해서 "
+"expr = NULL 구문을 expr IS NULL 구문으로 바꾸어서 처리하도록 함이렇게하면, "
+"윗 구문은 true 를 리턴함"
+
+#: utils/misc/guc.c:1342
+msgid "Enables per-database user names."
+msgstr "per-database 사용자 이름 활성화."
+
+#: utils/misc/guc.c:1351
+msgid "Sets the default read-only status of new transactions."
+msgstr "새로운 트랜잭션의 상태를 초기값으로 읽기전용으로 설정합니다."
+
+#: utils/misc/guc.c:1360
+msgid "Sets the current transaction's read-only status."
+msgstr "현재 트랜잭셕의 읽기 전용 상태를 지정합니다."
+
+#: utils/misc/guc.c:1370
+msgid "Sets the default deferrable status of new transactions."
+msgstr "새 트랜잭션의 기본 지연 가능한 상태를 지정"
+
+#: utils/misc/guc.c:1379
+msgid ""
+"Whether to defer a read-only serializable transaction until it can be "
+"executed with no possible serialization failures."
+msgstr ""
+"읽기 전용 직렬화 가능한 트랜잭션이 직렬 처리에서 오류가 없을 때까지 그 트랜잭"
+"션을 지연할 것이지 결정함"
+
+#: utils/misc/guc.c:1389
+msgid "Enable row security."
+msgstr "로우 단위 보안 기능을 활성화"
+
+#: utils/misc/guc.c:1390
+msgid "When enabled, row security will be applied to all users."
+msgstr "이 값이 활성화 되면 로우 단위 보안 기능이 모든 사용자 대상으로 적용됨"
+
+#: utils/misc/guc.c:1398
+msgid "Check function bodies during CREATE FUNCTION."
+msgstr ""
+"CREATE FUNCTION 명령으로 함수를 만들 때, 함수 본문 부분의 구문을 검사합니다."
+
+#: utils/misc/guc.c:1407
+msgid "Enable input of NULL elements in arrays."
+msgstr "배열에 NULL 요소가 입력될 수 있도록 합니다."
+
+#: utils/misc/guc.c:1408
+msgid ""
+"When turned on, unquoted NULL in an array input value means a null value; "
+"otherwise it is taken literally."
+msgstr ""
+"이 값이 on이면 배열 입력 값에 따옴표 없이 입력된 NULL이 null 값을 의미하고, "
+"그렇지 않으면 문자 그대로 처리됩니다."
+
+#: utils/misc/guc.c:1418
+msgid "Create new tables with OIDs by default."
+msgstr "기본적으로 OID를 사용하여 새 테이블을 만듭니다."
+
+#: utils/misc/guc.c:1427
+msgid ""
+"Start a subprocess to capture stderr output and/or csvlogs into log files."
+msgstr ""
+"로그 기록 하위 프로세스를 시작하여 stderr 출력 및/또는 csvlog를 로그 파일에 "
+"씁니다."
+
+#: utils/misc/guc.c:1436
+msgid "Truncate existing log files of same name during log rotation."
+msgstr "로그 회전 중 동일한 이름의 기존 로그 파일을 자릅니다."
+
+#: utils/misc/guc.c:1447
+msgid "Emit information about resource usage in sorting."
+msgstr "정렬 시 리소스 사용 정보를 내보냅니다."
+
+#: utils/misc/guc.c:1461
+msgid "Generate debugging output for synchronized scanning."
+msgstr "동기화된 스캔을 위해 디버깅 출력을 생성합니다."
+
+#: utils/misc/guc.c:1476
+msgid "Enable bounded sorting using heap sort."
+msgstr "힙 정렬을 통해 제한적 정렬을 사용합니다."
+
+#: utils/misc/guc.c:1489
+msgid "Emit WAL-related debugging output."
+msgstr "WAL 관련 디버깅 출력을 내보냅니다."
+
+#: utils/misc/guc.c:1501
+msgid "Datetimes are integer based."
+msgstr "datetime 형을 정수형으로 사용함"
+
+#: utils/misc/guc.c:1516
+msgid ""
+"Sets whether Kerberos and GSSAPI user names should be treated as case-"
+"insensitive."
+msgstr ""
+"Kerberos 및 GSSAPI 사용자 이름에서 대/소문자를 구분하지 않을지 여부를 설정합"
+"니다."
+
+#: utils/misc/guc.c:1526
+msgid "Warn about backslash escapes in ordinary string literals."
+msgstr "일반 문자열 리터럴의 백슬래시 이스케이프에 대해 경고합니다."
+
+#: utils/misc/guc.c:1536
+msgid "Causes '...' strings to treat backslashes literally."
+msgstr "&apos;...&apos; 문자열에서 백슬래시가 리터럴로 처리되도록 합니다."
+
+#: utils/misc/guc.c:1547
+msgid "Enable synchronized sequential scans."
+msgstr "동기화된 순차적 스캔을 사용합니다."
+
+#: utils/misc/guc.c:1557
+msgid "Allows connections and queries during recovery."
+msgstr "복구 중에서도 접속과 쿼리 사용을 허용함"
+
+#: utils/misc/guc.c:1567
+msgid ""
+"Allows feedback from a hot standby to the primary that will avoid query "
+"conflicts."
+msgstr ""
+"읽기 전용 보조 서버가 보내는 쿼리 충돌을 피하기 위한 피드백을 주 서버가 받음"
+
+#: utils/misc/guc.c:1577
+msgid "Allows modifications of the structure of system tables."
+msgstr "시스템 테이블의 구조를 수정할 수 있도록 합니다."
+
+#: utils/misc/guc.c:1588
+msgid "Disables reading from system indexes."
+msgstr "시스템 인덱스 읽기를 금지함"
+
+#: utils/misc/guc.c:1589
+msgid ""
+"It does not prevent updating the indexes, so it is safe to use. The worst "
+"consequence is slowness."
+msgstr ""
+"이 설정이 활성화 되어도 그 인덱스는 갱신되어 사용하는데는 안전합니다. 하지"
+"만 서버가 전체적으로 늦어질 수 있습니다."
+
+#: utils/misc/guc.c:1600
+msgid ""
+"Enables backward compatibility mode for privilege checks on large objects."
+msgstr "대형 객체에 대한 접근 권한 검사를 위한 하위 호환성이 있게 함"
+
+#: utils/misc/guc.c:1601
+msgid ""
+"Skips privilege checks when reading or modifying large objects, for "
+"compatibility with PostgreSQL releases prior to 9.0."
+msgstr ""
+"PostgreSQL 9.0 이전 버전의 호환성을 위해 대형 객체에 대한 읽기, 변경 시 접근 "
+"권한 검사를 안 하도록 설정함"
+
+#: utils/misc/guc.c:1611
+msgid ""
+"Emit a warning for constructs that changed meaning since PostgreSQL 9.4."
+msgstr "PostgreSQL 9.4 버전까지 사용되었던 우선 순위가 적용되면 경고를 보여줌"
+
+#: utils/misc/guc.c:1621
+msgid "When generating SQL fragments, quote all identifiers."
+msgstr "SQL 구문을 만들 때, 모든 식별자는 따옴표를 사용함"
+
+#: utils/misc/guc.c:1631
+msgid "Shows whether data checksums are turned on for this cluster."
+msgstr ""
+
+#: utils/misc/guc.c:1642
+msgid "Add sequence number to syslog messages to avoid duplicate suppression."
+msgstr "syslog 사용시 메시지 중복을 방지하기 위해 일련 번호를 매깁니다."
+
+#: utils/misc/guc.c:1652
+msgid "Split messages sent to syslog by lines and to fit into 1024 bytes."
+msgstr "syslog 사용시 메시지를 한 줄에 1024 바이트만 쓰도록 나눕니다"
+
+#: utils/misc/guc.c:1671
+msgid ""
+"Forces a switch to the next xlog file if a new file has not been started "
+"within N seconds."
+msgstr ""
+"새 파일이 N초 내에 시작되지 않은 경우 강제로 다음 xlog 파일로 전환합니다."
+
+#: utils/misc/guc.c:1682
+msgid "Waits N seconds on connection startup after authentication."
+msgstr "연결 작업에서 인증이 끝난 뒤 N초 기다림"
+
+#: utils/misc/guc.c:1683 utils/misc/guc.c:2206
+msgid "This allows attaching a debugger to the process."
+msgstr "이렇게 하면 디버거를 프로세스에 연결할 수 있습니다."
+
+#: utils/misc/guc.c:1692
+msgid "Sets the default statistics target."
+msgstr "기본 통계 대상을 지정합니다."
+
+#: utils/misc/guc.c:1693
+msgid ""
+"This applies to table columns that have not had a column-specific target set "
+"via ALTER TABLE SET STATISTICS."
+msgstr ""
+"특정 열을 지정하지 않고 ALTER TABLE SET STATISTICS 명령을 사용했을 때, 통계 "
+"대상이 될 열을 지정합니다."
+
+#: utils/misc/guc.c:1702
+msgid "Sets the FROM-list size beyond which subqueries are not collapsed."
+msgstr ""
+"이 크기를 초과할 경우 하위 쿼리가 축소되지 않는 FROM 목록 크기를 설정합니다."
+
+#: utils/misc/guc.c:1704
+msgid ""
+"The planner will merge subqueries into upper queries if the resulting FROM "
+"list would have no more than this many items."
+msgstr ""
+"<qbq>결과 FROM 목록에 포함된 항목이 이 개수를 넘지 않는 경우 계획 관리자가 하"
+"위 쿼리를 상위 쿼리에 병합합니다."
+
+#: utils/misc/guc.c:1714
+msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened."
+msgstr ""
+"이 크기를 초과할 경우 JOIN 구문이 결합되지 않는 FROM 목록 크기를 설정합니다."
+
+#: utils/misc/guc.c:1716
+msgid ""
+"The planner will flatten explicit JOIN constructs into lists of FROM items "
+"whenever a list of no more than this many items would result."
+msgstr ""
+"<qbq>결과 목록에 포함된 항목이 이 개수를 넘지 않을 때마다 계획 관리자가 명시"
+"적 JOIN 구문을 FROM 항목 목록에 결합합니다."
+
+#: utils/misc/guc.c:1726
+msgid "Sets the threshold of FROM items beyond which GEQO is used."
+msgstr ""
+"이 임계값을 초과할 경우 GEQO가 사용되는 FROM 항목의 임계값을 설정합니다."
+
+#: utils/misc/guc.c:1735
+msgid "GEQO: effort is used to set the default for other GEQO parameters."
+msgstr "GEQO: 다른 GEQO 매개 변수의 기본 값을 설정하는 데 사용됩니다."
+
+#: utils/misc/guc.c:1744
+msgid "GEQO: number of individuals in the population."
+msgstr "GEQO: 모집단의 개인 수입니다."
+
+#: utils/misc/guc.c:1745 utils/misc/guc.c:1754
+msgid "Zero selects a suitable default value."
+msgstr "0을 지정하면 적절한 기본 값이 선택됩니다."
+
+#: utils/misc/guc.c:1753
+msgid "GEQO: number of iterations of the algorithm."
+msgstr "GEQO: 알고리즘의 반복 수입니다."
+
+#: utils/misc/guc.c:1764
+msgid "Sets the time to wait on a lock before checking for deadlock."
+msgstr "교착 상태를 확인하기 전에 잠금을 기다릴 시간을 설정합니다."
+
+#: utils/misc/guc.c:1775
+msgid ""
+"Sets the maximum delay before canceling queries when a hot standby server is "
+"processing archived WAL data."
+msgstr ""
+"읽기 전용 보조 서버가 아카이브된 WAL 자료를 처리할 때, 지연될 수 있는 최대 시"
+"간"
+
+#: utils/misc/guc.c:1786
+msgid ""
+"Sets the maximum delay before canceling queries when a hot standby server is "
+"processing streamed WAL data."
+msgstr ""
+"읽기 전용 보조 서버가 스트림 WAL 자료를 처리할 때, 지연될 수 있는 최대 시간"
+
+#: utils/misc/guc.c:1797
+msgid ""
+"Sets the maximum interval between WAL receiver status reports to the primary."
+msgstr "주 서버로 WAL 수신기 상태를 보고하는 최대 간격"
+
+#: utils/misc/guc.c:1808
+msgid "Sets the maximum wait time to receive data from the primary."
+msgstr ""
+"주 서버에서 보낸 자료를 받기위해 기다릴 수 있는 최대 허용 시간을 설정합니다."
+
+#: utils/misc/guc.c:1819
+msgid "Sets the maximum number of concurrent connections."
+msgstr "최대 동시 접속수를 지정합니다."
+
+#: utils/misc/guc.c:1829
+msgid "Sets the number of connection slots reserved for superusers."
+msgstr "superuser 동시 접속수를 지정합니다."
+
+#: utils/misc/guc.c:1843
+msgid "Sets the number of shared memory buffers used by the server."
+msgstr "서버에서 사용할 공유 메모리의 개수를 지정함"
+
+#: utils/misc/guc.c:1854
+msgid "Sets the maximum number of temporary buffers used by each session."
+msgstr "각 세션에서 사용하는 임시 버퍼의 최대 개수를 지정"
+
+#: utils/misc/guc.c:1865
+msgid "Sets the TCP port the server listens on."
+msgstr "TCP 포트 번호를 지정함."
+
+#: utils/misc/guc.c:1875
+msgid "Sets the access permissions of the Unix-domain socket."
+msgstr "유닉스 도메인 소켓 파일의 액세스 권한을 지정함"
+
+#: utils/misc/guc.c:1876
+msgid ""
+"Unix-domain sockets use the usual Unix file system permission set. The "
+"parameter value is expected to be a numeric mode specification in the form "
+"accepted by the chmod and umask system calls. (To use the customary octal "
+"format the number must start with a 0 (zero).)"
+msgstr ""
+"Unix 도메인 소켓은 일반적인 Unix 파일 시스템 권한 집합을 사용합니다. 매개 변"
+"수 값은 chmod 및 umask 시스템 호출에서 수락되는 형태의 숫자 모드 지정이어야 "
+"합니다. (일반적인 8진수 형식을 사용하려면 숫자가 0으로 시작해야 합니다.)"
+
+#: utils/misc/guc.c:1890
+msgid "Sets the file permissions for log files."
+msgstr "로그 파일의 파일 접근 권한을 지정합니다."
+
+#: utils/misc/guc.c:1891
+msgid ""
+"The parameter value is expected to be a numeric mode specification in the "
+"form accepted by the chmod and umask system calls. (To use the customary "
+"octal format the number must start with a 0 (zero).)"
+msgstr ""
+"매개 변수 값은 chmod 및 umask 시스템 호출에서 수락되는 형태의 숫자 모드 지정"
+"이어야 합니다. (일반적인 8진수 형식을 사용하려면 숫자가 0으로 시작해야 합니"
+"다.)"
+
+#: utils/misc/guc.c:1904
+msgid "Sets the maximum memory to be used for query workspaces."
+msgstr "쿼리 작업공간을 위해 사용될 메모리의 최대값을 지정함."
+
+#: utils/misc/guc.c:1905
+msgid ""
+"This much memory can be used by each internal sort operation and hash table "
+"before switching to temporary disk files."
+msgstr ""
+"임시 디스크 파일로 전환하기 전에 각 내부 정렬 작업과 해시 테이블에서 이 크기"
+"의 메모리를 사용할 수 있습니다."
+
+#: utils/misc/guc.c:1917
+msgid "Sets the maximum memory to be used for maintenance operations."
+msgstr "관리 작업을 위해 사용될 메모리의 최대값을 지정함."
+
+#: utils/misc/guc.c:1918
+msgid "This includes operations such as VACUUM and CREATE INDEX."
+msgstr "관리작업은 VACUUM, CREATE INDEX 같은 작업을 뜻합니다."
+
+#: utils/misc/guc.c:1928
+msgid ""
+"Sets the maximum number of tuples to be sorted using replacement selection."
+msgstr "replacement selection 기능을 이용할 최대 튜플 수"
+
+#: utils/misc/guc.c:1929
+msgid "When more tuples than this are present, quicksort will be used."
+msgstr "이 튜플 수 보다 많으면, quicksort 를 사용함"
+
+#: utils/misc/guc.c:1943
+msgid "Sets the maximum stack depth, in kilobytes."
+msgstr "스택깊이(KB 단위) 최대값을 지정합니다."
+
+#: utils/misc/guc.c:1954
+msgid "Limits the total size of all temporary files used by each process."
+msgstr "각 프로세스에서 사용하는 모든 임시 파일의 총 크기 제한"
+
+#: utils/misc/guc.c:1955
+msgid "-1 means no limit."
+msgstr "-1은 제한 없음"
+
+#: utils/misc/guc.c:1965
+msgid "Vacuum cost for a page found in the buffer cache."
+msgstr "버퍼 캐시에 있는 페이지의 청소 비용입니다."
+
+#: utils/misc/guc.c:1975
+msgid "Vacuum cost for a page not found in the buffer cache."
+msgstr "버퍼 캐시에 없는 페이지의 청소 비용입니다."
+
+#: utils/misc/guc.c:1985
+msgid "Vacuum cost for a page dirtied by vacuum."
+msgstr "청소로 페이지 변경 시 부과되는 비용입니다."
+
+#: utils/misc/guc.c:1995
+msgid "Vacuum cost amount available before napping."
+msgstr "청소가 중지되는 청소 비용 합계입니다."
+
+#: utils/misc/guc.c:2005
+msgid "Vacuum cost delay in milliseconds."
+msgstr "청소 비용 지연(밀리초)입니다."
+
+#: utils/misc/guc.c:2016
+msgid "Vacuum cost delay in milliseconds, for autovacuum."
+msgstr "자동 청소에 대한 청소 비용 지연(밀리초)입니다."
+
+#: utils/misc/guc.c:2027
+msgid "Vacuum cost amount available before napping, for autovacuum."
+msgstr "자동 청소에 대한 청소가 중지되는 청소 비용 합계입니다."
+
+#: utils/misc/guc.c:2037
+msgid ""
+"Sets the maximum number of simultaneously open files for each server process."
+msgstr "각각의 서버 프로세스에서 동시에 열릴 수 있는 최대 파일 갯수를 지정함."
+
+#: utils/misc/guc.c:2050
+msgid "Sets the maximum number of simultaneously prepared transactions."
+msgstr "동시에 준비된 트랜잭션 최대 개수 지정"
+
+#: utils/misc/guc.c:2061
+msgid "Sets the minimum OID of tables for tracking locks."
+msgstr "잠금 추적을 위한 테이블의 최소 OID 지정"
+
+#: utils/misc/guc.c:2062
+msgid "Is used to avoid output on system tables."
+msgstr ""
+
+#: utils/misc/guc.c:2071
+msgid "Sets the OID of the table with unconditionally lock tracing."
+msgstr ""
+
+#: utils/misc/guc.c:2083
+msgid "Sets the maximum allowed duration of any statement."
+msgstr "모든 쿼리문에 적용되는 허용되는 최대 수행시간"
+
+#: utils/misc/guc.c:2084 utils/misc/guc.c:2095 utils/misc/guc.c:2106
+msgid "A value of 0 turns off the timeout."
+msgstr "이 값이 0이면 이런 제한이 없음."
+
+#: utils/misc/guc.c:2094
+msgid "Sets the maximum allowed duration of any wait for a lock."
+msgstr "모든 잠금에 적용되는 기다리는 최대 대기 시간"
+
+#: utils/misc/guc.c:2105
+msgid "Sets the maximum allowed duration of any idling transaction."
+msgstr "idle-in-transaction 상태로 있을 수 있는 최대 시간"
+
+#: utils/misc/guc.c:2116
+msgid "Minimum age at which VACUUM should freeze a table row."
+msgstr "VACUUM에서 테이블 행을 동결할 때까지의 최소 기간입니다."
+
+#: utils/misc/guc.c:2126
+msgid "Age at which VACUUM should scan whole table to freeze tuples."
+msgstr ""
+"VACUUM에서 튜플을 동결하기 위해 전체 테이블을 스캔할 때까지의 기간입니다."
+
+#: utils/misc/guc.c:2136
+msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row."
+msgstr "VACUUM에서 테이블 MultiXactId 동결할 때까지의 최소 기간입니다."
+
+#: utils/misc/guc.c:2146
+msgid "Multixact age at which VACUUM should scan whole table to freeze tuples."
+msgstr ""
+"VACUUM에서 튜플을 동결하기 위해 전체 테이블을 스캔할 때까지의 멀티트랜잭션 기"
+"간입니다."
+
+#: utils/misc/guc.c:2156
+msgid ""
+"Number of transactions by which VACUUM and HOT cleanup should be deferred, "
+"if any."
+msgstr ""
+
+#: utils/misc/guc.c:2169
+msgid "Sets the maximum number of locks per transaction."
+msgstr "하나의 트랜잭션에서 사용할 수 있는 최대 잠금 횟수를 지정함."
+
+#: utils/misc/guc.c:2170
+msgid ""
+"The shared lock table is sized on the assumption that at most "
+"max_locks_per_transaction * max_connections distinct objects will need to be "
+"locked at any one time."
+msgstr ""
+"공유 잠금 테이블은 한 번에 잠궈야 할 고유 객체 수가 "
+"max_locks_per_transaction * max_connections를 넘지 않는다는 가정 하에 크기가 "
+"지정됩니다."
+
+#: utils/misc/guc.c:2181
+msgid "Sets the maximum number of predicate locks per transaction."
+msgstr "하나의 트랜잭션에서 사용할 수 있는 최대 잠금 횟수를 지정함."
+
+#: utils/misc/guc.c:2182
+msgid ""
+"The shared predicate lock table is sized on the assumption that at most "
+"max_pred_locks_per_transaction * max_connections distinct objects will need "
+"to be locked at any one time."
+msgstr ""
+"공유 predicate 잠금 테이블은 한 번에 잠궈야 할 고유 객체 수가 "
+"max_pred_locks_per_transaction * max_connections를 넘지 않는다는 가정 하에 크"
+"기가 지정됩니다."
+
+#: utils/misc/guc.c:2193
+msgid "Sets the maximum allowed time to complete client authentication."
+msgstr "클라이언트 인증을 완료할 수 있는 최대 허용 시간을 설정합니다."
+
+#: utils/misc/guc.c:2205
+msgid "Waits N seconds on connection startup before authentication."
+msgstr "인증 전에 연결이 시작되도록 N초 동안 기다립니다."
+
+#: utils/misc/guc.c:2216
+msgid "Sets the number of WAL files held for standby servers."
+msgstr "대기 서버를 위해 보관하고 있을 WAL 파일 개수 지정"
+
+#: utils/misc/guc.c:2226
+msgid "Sets the minimum size to shrink the WAL to."
+msgstr "WAL 최소 크기"
+
+#: utils/misc/guc.c:2237
+msgid "Sets the WAL size that triggers a checkpoint."
+msgstr "체크포인트 작업을 할 WAL 크기 지정"
+
+#: utils/misc/guc.c:2248
+msgid "Sets the maximum time between automatic WAL checkpoints."
+msgstr "자동 WAL 체크포인트 사이의 최대 간격을 설정합니다."
+
+#: utils/misc/guc.c:2259
+msgid ""
+"Enables warnings if checkpoint segments are filled more frequently than this."
+msgstr "지정 시간 안에 체크포인트 조각이 모두 채워지면 경고를 냄"
+
+#: utils/misc/guc.c:2261
+msgid ""
+"Write a message to the server log if checkpoints caused by the filling of "
+"checkpoint segment files happens more frequently than this number of "
+"seconds. Zero turns off the warning."
+msgstr ""
+"체크포인트 작업이 지금 지정한 시간(초)보다 자주 체크포인트 세그먼트 파일에 내"
+"용이 꽉 차는 사태가 발생하면 경고 메시지를 서버 로그에 남깁니다. 이 값을 0으"
+"로 지정하면 이 기능 없음"
+
+#: utils/misc/guc.c:2273 utils/misc/guc.c:2430 utils/misc/guc.c:2457
+msgid ""
+"Number of pages after which previously performed writes are flushed to disk."
+msgstr ""
+
+#: utils/misc/guc.c:2284
+msgid "Sets the number of disk-page buffers in shared memory for WAL."
+msgstr ""
+"WAL 기능을 위해 공유 메모리에서 사용할 디스크 페이지 버퍼 개수를 지정함."
+
+#: utils/misc/guc.c:2295
+msgid "Time between WAL flushes performed in the WAL writer."
+msgstr "WAL 기록자가 지정 시간 만큼 쉬고 쓰기 작업을 반복함"
+
+#: utils/misc/guc.c:2306
+msgid "Amount of WAL written out by WAL writer that triggers a flush."
+msgstr ""
+
+#: utils/misc/guc.c:2318
+msgid "Sets the maximum number of simultaneously running WAL sender processes."
+msgstr "동시에 작동할 WAL 송신 프로세스 최대 수 지정"
+
+#: utils/misc/guc.c:2329
+msgid "Sets the maximum number of simultaneously defined replication slots."
+msgstr "동시에 사용할 수 있는 복제 슬롯 최대 수 지정"
+
+#: utils/misc/guc.c:2339
+msgid "Sets the maximum time to wait for WAL replication."
+msgstr "WAL 복제를 위해 기다릴 최대 시간 설정"
+
+#: utils/misc/guc.c:2350
+msgid ""
+"Sets the delay in microseconds between transaction commit and flushing WAL "
+"to disk."
+msgstr ""
+"트랜잭션과 트랜잭션 로그의 적용 사이의 간격을 microsecond 단위로 지정함"
+
+#: utils/misc/guc.c:2362
+msgid ""
+"Sets the minimum concurrent open transactions before performing commit_delay."
+msgstr "commit_delay 처리하기 전에 있는 최소 동시 열려 있는 트랜잭션 개수."
+
+#: utils/misc/guc.c:2373
+msgid "Sets the number of digits displayed for floating-point values."
+msgstr "부동소수형 값을 표기할 때 "
+
+#: utils/misc/guc.c:2374
+msgid ""
+"This affects real, double precision, and geometric data types. The parameter "
+"value is added to the standard number of digits (FLT_DIG or DBL_DIG as "
+"appropriate)."
+msgstr ""
+"이 값은 real, duoble 부동 소숫점과 지리정보 자료형에 영향을 끼칩니다. 이 값"
+"은 정수여야합니다(FLT_DIG or DBL_DIG as appropriate - 무슨 말인지)."
+
+#: utils/misc/guc.c:2385
+msgid "Sets the minimum execution time above which statements will be logged."
+msgstr ""
+"이 시간을 초과할 경우 쿼리문을 로그로 남길 최소 실행 시간을 설정합니다."
+
+#: utils/misc/guc.c:2387
+msgid "Zero prints all queries. -1 turns this feature off."
+msgstr ""
+"0을 지정하면 모든 쿼리가 인쇄됩니다. -1을 지정하면 이 기능이 해제됩니다."
+
+#: utils/misc/guc.c:2397
+msgid ""
+"Sets the minimum execution time above which autovacuum actions will be "
+"logged."
+msgstr ""
+"이 시간을 초과할 경우 자동 청소 작업 로그를 남길 최소 실행 시간을 설정합니"
+"다."
+
+#: utils/misc/guc.c:2399
+msgid "Zero prints all actions. -1 turns autovacuum logging off."
+msgstr ""
+"0을 지정하면 모든 작업이 인쇄됩니다. -1을 지정하면 자동 청소 기록이 해제됩니"
+"다."
+
+#: utils/misc/guc.c:2409
+msgid "Background writer sleep time between rounds."
+msgstr "백그라운드 기록자의 잠자는 시간"
+
+#: utils/misc/guc.c:2420
+msgid "Background writer maximum number of LRU pages to flush per round."
+msgstr "라운드당 플러시할 백그라운드 작성기 최대 LRU 페이지 수입니다."
+
+#: utils/misc/guc.c:2443
+msgid ""
+"Number of simultaneous requests that can be handled efficiently by the disk "
+"subsystem."
+msgstr ""
+"<qbq>디스크 하위 시스템에서 효율적으로 처리할 수 있는 동시 요청 수입니다."
+
+#: utils/misc/guc.c:2444
+msgid ""
+"For RAID arrays, this should be approximately the number of drive spindles "
+"in the array."
+msgstr "<qbq>RAID 배열의 경우 이 값은 대략 배열의 드라이브 스핀들 수입니다."
+
+#: utils/misc/guc.c:2470
+msgid "Maximum number of concurrent worker processes."
+msgstr "동시 작업자 프로세스의 최대 수"
+
+#: utils/misc/guc.c:2480
+msgid "Automatic log file rotation will occur after N minutes."
+msgstr "N분 후에 자동 로그 파일 회전이 발생합니다."
+
+#: utils/misc/guc.c:2491
+msgid "Automatic log file rotation will occur after N kilobytes."
+msgstr "N킬로바이트 후에 자동 로그 파일 회전이 발생합니다."
+
+#: utils/misc/guc.c:2502
+msgid "Shows the maximum number of function arguments."
+msgstr "함수 인자의 최대 갯수를 보여줍니다"
+
+#: utils/misc/guc.c:2513
+msgid "Shows the maximum number of index keys."
+msgstr "인덱스 키의 최대개수를 보여줍니다."
+
+#: utils/misc/guc.c:2524
+msgid "Shows the maximum identifier length."
+msgstr "최대 식별자 길이를 표시합니다."
+
+#: utils/misc/guc.c:2535
+msgid "Shows the size of a disk block."
+msgstr "디스크 블록의 크기를 표시합니다."
+
+#: utils/misc/guc.c:2546
+msgid "Shows the number of pages per disk file."
+msgstr "디스크 파일당 페이지 수를 표시합니다."
+
+#: utils/misc/guc.c:2557
+msgid "Shows the block size in the write ahead log."
+msgstr "미리 쓰기 로그의 블록 크기를 표시합니다."
+
+#: utils/misc/guc.c:2568
+msgid ""
+"Sets the time to wait before retrying to retrieve WAL after a failed attempt."
+msgstr ""
+
+#: utils/misc/guc.c:2580
+msgid "Shows the number of pages per write ahead log segment."
+msgstr "미리 쓰기 로그 세그먼트당 페이지 수를 표시합니다."
+
+#: utils/misc/guc.c:2593
+msgid "Time to sleep between autovacuum runs."
+msgstr "자동 청소 실행 사이의 절전 모드 시간입니다."
+
+#: utils/misc/guc.c:2603
+msgid "Minimum number of tuple updates or deletes prior to vacuum."
+msgstr "청소 전의 최소 튜플 업데이트 또는 삭제 수입니다."
+
+#: utils/misc/guc.c:2612
+msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze."
+msgstr "통계 정보 수집을 위한 최소 튜플 삽입, 업데이트 또는 삭제 수입니다."
+
+#: utils/misc/guc.c:2622
+msgid ""
+"Age at which to autovacuum a table to prevent transaction ID wraparound."
+msgstr ""
+"트랜잭션 ID 겹침 방지를 위해 테이블에 대해 autovacuum 작업을 수행할 테이블 나"
+"이를 지정합니다."
+
+#: utils/misc/guc.c:2633
+msgid ""
+"Multixact age at which to autovacuum a table to prevent multixact wraparound."
+msgstr ""
+"멀티 트랜잭션 ID 겹침 방지를 위해 테이블에 대해 autovacuum 작업을 수행할 트랜"
+"잭션 나이를 지정합니다."
+
+#: utils/misc/guc.c:2643
+msgid ""
+"Sets the maximum number of simultaneously running autovacuum worker "
+"processes."
+msgstr "동시에 작업할 수 있는 autovacuum 작업자 최대 수 지정"
+
+#: utils/misc/guc.c:2653
+msgid "Sets the maximum number of parallel processes per executor node."
+msgstr "실행 노드당 최대 병렬 처리 수 지정"
+
+#: utils/misc/guc.c:2663
+msgid "Sets the maximum memory to be used by each autovacuum worker process."
+msgstr "각 autovacuum 작업자 프로세스가 사용할 메모리 최대치"
+
+#: utils/misc/guc.c:2674
+msgid ""
+"Time before a snapshot is too old to read pages changed after the snapshot "
+"was taken."
+msgstr ""
+
+#: utils/misc/guc.c:2675
+msgid "A value of -1 disables this feature."
+msgstr "이 값이 -1 이면 이 기능 사용 안함"
+
+#: utils/misc/guc.c:2685
+msgid "Time between issuing TCP keepalives."
+msgstr "TCP 연결 유지 실행 간격입니다."
+
+#: utils/misc/guc.c:2686 utils/misc/guc.c:2697
+msgid "A value of 0 uses the system default."
+msgstr "이 값이 0이면 시스템 기본 값"
+
+#: utils/misc/guc.c:2696
+msgid "Time between TCP keepalive retransmits."
+msgstr "TCP keepalive 시간 설정"
+
+#: utils/misc/guc.c:2707
+msgid "SSL renegotiation is no longer supported; this can only be 0."
+msgstr ""
+
+#: utils/misc/guc.c:2718
+msgid "Maximum number of TCP keepalive retransmits."
+msgstr "TCP keepalive 확인 최대 횟수"
+
+#: utils/misc/guc.c:2719
+msgid ""
+"This controls the number of consecutive keepalive retransmits that can be "
+"lost before a connection is considered dead. A value of 0 uses the system "
+"default."
+msgstr ""
+"<qbq>이 값은 연결이 중단된 것으로 간주되기 전에 손실될 수 있는 연속 연결 유"
+"지 재전송 수를 제어합니다. 값 0을 지정하면 시스템 기본 값이 사용됩니다."
+
+#: utils/misc/guc.c:2730
+msgid "Sets the maximum allowed result for exact search by GIN."
+msgstr "정확한 GIN 기준 검색에 허용되는 최대 결과 수를 설정합니다."
+
+#: utils/misc/guc.c:2741
+msgid "Sets the planner's assumption about the size of the disk cache."
+msgstr "디스크 캐시 크기에 대한 계획 관리자의 가정을 설정합니다."
+
+#: utils/misc/guc.c:2742
+msgid ""
+"That is, the portion of the kernel's disk cache that will be used for "
+"PostgreSQL data files. This is measured in disk pages, which are normally 8 "
+"kB each."
+msgstr ""
+"<qbq>즉, PostgreSQL 데이터 파일에 사용될 커널의 디스크 캐시 부분입니다. 이 값"
+"은 디스크 페이지 단위로 측정되며, 일반적으로 각각 8KB입니다."
+
+#: utils/misc/guc.c:2754
+msgid "Sets the minimum size of relations to be considered for parallel scan."
+msgstr ""
+
+#: utils/misc/guc.c:2766
+msgid "Shows the server version as an integer."
+msgstr "서버 버전을 정수형으로 보여줍니다"
+
+#: utils/misc/guc.c:2777
+msgid "Log the use of temporary files larger than this number of kilobytes."
+msgstr "이 킬로바이트 수보다 큰 임시 파일의 사용을 기록합니다."
+
+#: utils/misc/guc.c:2778
+msgid "Zero logs all files. The default is -1 (turning this feature off)."
+msgstr ""
+"0을 지정하면 모든 파일이 기록됩니다. 기본 값은 -1로, 이 기능이 해제됩니다."
+
+#: utils/misc/guc.c:2788
+msgid "Sets the size reserved for pg_stat_activity.query, in bytes."
+msgstr "pg_stat_activity.query에 예약되는 크기(바이트)를 설정합니다."
+
+#: utils/misc/guc.c:2803
+msgid "Sets the maximum size of the pending list for GIN index."
+msgstr "GIN 인덱스를 위한 팬딩(pending) 목록의 최대 크기 지정"
+
+#: utils/misc/guc.c:2823
+msgid ""
+"Sets the planner's estimate of the cost of a sequentially fetched disk page."
+msgstr ""
+"순차적으로 접근하는 디스크 페이지에 대한 계획 관리자의 예상 비용을 설정합니"
+"다."
+
+#: utils/misc/guc.c:2833
+msgid ""
+"Sets the planner's estimate of the cost of a nonsequentially fetched disk "
+"page."
+msgstr ""
+"비순차적으로 접근하는 디스크 페이지에 대한 계획 관리자의 예상 비용을 설정합니"
+"다."
+
+#: utils/misc/guc.c:2843
+msgid "Sets the planner's estimate of the cost of processing each tuple (row)."
+msgstr "각 튜플(행)에 대한 계획 관리자의 예상 처리 비용을 설정합니다."
+
+#: utils/misc/guc.c:2853
+msgid ""
+"Sets the planner's estimate of the cost of processing each index entry "
+"during an index scan."
+msgstr ""
+"실행 계획기의 비용 계산에 사용될 인덱스 스캔으로 각 인덱스 항목을 처리하는 예"
+"상 처리 비용을 설정합니다."
+
+#: utils/misc/guc.c:2863
+msgid ""
+"Sets the planner's estimate of the cost of processing each operator or "
+"function call."
+msgstr ""
+"실행 계획기의 비용 계산에 사용될 함수 호출이나 연산자 연산 처리하는 예상 처"
+"리 비용을 설정합니다."
+
+#: utils/misc/guc.c:2873
+msgid ""
+"Sets the planner's estimate of the cost of passing each tuple (row) from "
+"worker to master backend."
+msgstr "각 튜플(행)에 대한 계획 관리자의 예상 처리 비용을 설정합니다."
+
+#: utils/misc/guc.c:2883
+msgid ""
+"Sets the planner's estimate of the cost of starting up worker processes for "
+"parallel query."
+msgstr ""
+
+#: utils/misc/guc.c:2894
+msgid ""
+"Sets the planner's estimate of the fraction of a cursor's rows that will be "
+"retrieved."
+msgstr "<qbq>검색될 커서 행에 대한 계획 관리자의 예상 분수 값을 설정합니다."
+
+#: utils/misc/guc.c:2905
+msgid "GEQO: selective pressure within the population."
+msgstr "GEQO: 모집단 내의 선택 압력입니다."
+
+#: utils/misc/guc.c:2915
+msgid "GEQO: seed for random path selection."
+msgstr "GEQO: 무작위 경로 선택을 위한 씨드"
+
+#: utils/misc/guc.c:2925
+msgid "Multiple of the average buffer usage to free per round."
+msgstr "라운드당 해제할 평균 버퍼 사용의 배수입니다."
+
+#: utils/misc/guc.c:2935
+msgid "Sets the seed for random-number generation."
+msgstr "난수 생성 속도를 설정합니다."
+
+#: utils/misc/guc.c:2946
+msgid ""
+"Number of tuple updates or deletes prior to vacuum as a fraction of "
+"reltuples."
+msgstr ""
+"vacuum 작업을 진행할 update, delete 작업량을 전체 자료에 대한 분수값으로 지정"
+"합니다."
+
+#: utils/misc/guc.c:2955
+msgid ""
+"Number of tuple inserts, updates, or deletes prior to analyze as a fraction "
+"of reltuples."
+msgstr ""
+"통계 수집 작업을 진행할 insert, update, delete 작업량을 전체 자료에 대한 분수"
+"값으로 지정합니다."
+
+#: utils/misc/guc.c:2965
+msgid ""
+"Time spent flushing dirty buffers during checkpoint, as fraction of "
+"checkpoint interval."
+msgstr ""
+"<qbq>체크포인트 도중 변경된 버퍼 플러시에 사용된 시간으로, 체크포인트 간격의 "
+"분수 값입니다."
+
+#: utils/misc/guc.c:2984
+msgid "Sets the shell command that will be called to archive a WAL file."
+msgstr "WAL 파일을 아카이빙하기 위해 호출될 셸 명령을 설정합니다."
+
+#: utils/misc/guc.c:2994
+msgid "Sets the client's character set encoding."
+msgstr "클라이언트 문자 세트 인코딩을 지정함"
+
+#: utils/misc/guc.c:3005
+msgid "Controls information prefixed to each log line."
+msgstr "각 로그 줄 앞에 추가할 정보를 제어합니다."
+
+#: utils/misc/guc.c:3006
+msgid "If blank, no prefix is used."
+msgstr "비워 두면 접두사가 사용되지 않습니다."
+
+#: utils/misc/guc.c:3015
+msgid "Sets the time zone to use in log messages."
+msgstr "로그 메시지에 사용할 표준 시간대를 설정합니다."
+
+#: utils/misc/guc.c:3025
+msgid "Sets the display format for date and time values."
+msgstr "날짜와 시간 값을 나타내는 모양을 지정합니다."
+
+#: utils/misc/guc.c:3026
+msgid "Also controls interpretation of ambiguous date inputs."
+msgstr "또한 모호한 날짜 입력의 해석을 제어합니다."
+
+#: utils/misc/guc.c:3037
+msgid "Sets the default tablespace to create tables and indexes in."
+msgstr "테이블 및 인덱스를 만들 기본 테이블스페이스를 설정합니다."
+
+#: utils/misc/guc.c:3038
+msgid "An empty string selects the database's default tablespace."
+msgstr "빈 문자열을 지정하면 데이터베이스의 기본 테이블스페이스가 선택됩니다."
+
+#: utils/misc/guc.c:3048
+msgid "Sets the tablespace(s) to use for temporary tables and sort files."
+msgstr "임시 테이블 및 정렬 파일에 사용할 테이블스페이스를 설정합니다."
+
+#: utils/misc/guc.c:3059
+msgid "Sets the path for dynamically loadable modules."
+msgstr "동적으로 불러올 수 있는 모듈들이 있는 경로를 지정함."
+
+#: utils/misc/guc.c:3060
+msgid ""
+"If a dynamically loadable module needs to be opened and the specified name "
+"does not have a directory component (i.e., the name does not contain a "
+"slash), the system will search this path for the specified file."
+msgstr ""
+"<qbq>동적으로 로드 가능한 모듈을 열어야 하는데 지정한 이름에 디렉터리 구성 요"
+"소가 없는 경우(즉, 이름에 슬래시가 없음) 시스템은 이 경로에서 지정한 파일을 "
+"검색합니다."
+
+#: utils/misc/guc.c:3073
+msgid "Sets the location of the Kerberos server key file."
+msgstr "Kerberos 서버 키 파일의 위치를 지정함."
+
+#: utils/misc/guc.c:3084
+msgid "Sets the Bonjour service name."
+msgstr "Bonjour 서비스 이름을 지정"
+
+#: utils/misc/guc.c:3096
+msgid "Shows the collation order locale."
+msgstr "데이터 정렬 순서 로케일을 표시합니다."
+
+#: utils/misc/guc.c:3107
+msgid "Shows the character classification and case conversion locale."
+msgstr "문자 분류 및 대/소문자 변환 로케일을 표시합니다."
+
+#: utils/misc/guc.c:3118
+msgid "Sets the language in which messages are displayed."
+msgstr "보여질 메시지로 사용할 언어 지정."
+
+#: utils/misc/guc.c:3128
+msgid "Sets the locale for formatting monetary amounts."
+msgstr "통화금액 표현 양식으로 사용할 로케일 지정."
+
+#: utils/misc/guc.c:3138
+msgid "Sets the locale for formatting numbers."
+msgstr "숫자 표현 양식으로 사용할 로케일 지정."
+
+#: utils/misc/guc.c:3148
+msgid "Sets the locale for formatting date and time values."
+msgstr "날짜와 시간 값을 표현할 양식으로 사용할 로케일 지정."
+
+#: utils/misc/guc.c:3158
+msgid "Lists shared libraries to preload into each backend."
+msgstr "각각의 백엔드에 미리 불러올 공유 라이브러리들을 지정합니다"
+
+#: utils/misc/guc.c:3169
+msgid "Lists shared libraries to preload into server."
+msgstr "서버에 미리 불러올 공유 라이브러리들을 지정합니다"
+
+#: utils/misc/guc.c:3180
+msgid "Lists unprivileged shared libraries to preload into each backend."
+msgstr ""
+"각각의 백엔드에 미리 불러올 접근제한 없는 공유 라이브러리들을 지정합니다"
+
+#: utils/misc/guc.c:3191
+msgid "Sets the schema search order for names that are not schema-qualified."
+msgstr "스키마로 한정되지 않은 이름의 스키마 검색 순서를 설정합니다."
+
+#: utils/misc/guc.c:3203
+msgid "Sets the server (database) character set encoding."
+msgstr "서버 문자 코드 세트 인코딩 지정."
+
+#: utils/misc/guc.c:3215
+msgid "Shows the server version."
+msgstr "서버 버전 보임."
+
+#: utils/misc/guc.c:3227
+msgid "Sets the current role."
+msgstr "현재 롤을 지정"
+
+#: utils/misc/guc.c:3239
+msgid "Sets the session user name."
+msgstr "세션 사용자 이름 지정."
+
+#: utils/misc/guc.c:3250
+msgid "Sets the destination for server log output."
+msgstr "서버 로그 출력을 위한 대상을 지정합니다."
+
+#: utils/misc/guc.c:3251
+msgid ""
+"Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", and "
+"\"eventlog\", depending on the platform."
+msgstr ""
+"유효한 값은 플랫폼에 따라 \"stderr\", \"syslog\", \"csvlog\" 및 \"eventlog"
+"\"의 조합입니다."
+
+#: utils/misc/guc.c:3262
+msgid "Sets the destination directory for log files."
+msgstr "로그 파일의 대상 디렉터리를 설정합니다."
+
+#: utils/misc/guc.c:3263
+msgid "Can be specified as relative to the data directory or as absolute path."
+msgstr "데이터 디렉터리의 상대 경로 또는 절대 경로로 지정할 수 있습니다."
+
+#: utils/misc/guc.c:3273
+msgid "Sets the file name pattern for log files."
+msgstr "로그 파일의 파일 이름 패턴을 설정합니다."
+
+#: utils/misc/guc.c:3284
+msgid "Sets the program name used to identify PostgreSQL messages in syslog."
+msgstr "syslog에서 구분할 PostgreSQL 메시지에 사용될 프로그램 이름을 지정."
+
+#: utils/misc/guc.c:3295
+msgid ""
+"Sets the application name used to identify PostgreSQL messages in the event "
+"log."
+msgstr ""
+"이벤트 로그에서 PostgreSQL 메시지 식별자로 사용할 응용프로그램 이름 지정"
+
+#: utils/misc/guc.c:3306
+msgid "Sets the time zone for displaying and interpreting time stamps."
+msgstr "시간대(time zone)를 지정함."
+
+#: utils/misc/guc.c:3316
+msgid "Selects a file of time zone abbreviations."
+msgstr "표준 시간대 약어 파일을 선택합니다."
+
+#: utils/misc/guc.c:3326
+msgid "Sets the current transaction's isolation level."
+msgstr "현재 트랜잭션 독립성 수준(isolation level)을 지정함."
+
+#: utils/misc/guc.c:3337
+msgid "Sets the owning group of the Unix-domain socket."
+msgstr "유닉스 도메인 소켓의 소유주를 지정"
+
+#: utils/misc/guc.c:3338
+msgid ""
+"The owning user of the socket is always the user that starts the server."
+msgstr "소켓 소유자는 항상 서버를 시작하는 사용자입니다."
+
+#: utils/misc/guc.c:3348
+msgid "Sets the directories where Unix-domain sockets will be created."
+msgstr "유닉스 도메인 소켓을 만들 디렉터리를 지정합니다."
+
+#: utils/misc/guc.c:3363
+msgid "Sets the host name or IP address(es) to listen to."
+msgstr "서비스할 호스트이름이나, IP를 지정함."
+
+#: utils/misc/guc.c:3378
+msgid "Sets the server's data directory."
+msgstr "서버의 데이터 디렉터리 위치를 지정합니다."
+
+#: utils/misc/guc.c:3389
+msgid "Sets the server's main configuration file."
+msgstr "서버의 기본 환경설정 파일 경로를 지정합니다."
+
+#: utils/misc/guc.c:3400
+msgid "Sets the server's \"hba\" configuration file."
+msgstr "서버의 \"hba\" 구성 파일을 설정합니다."
+
+#: utils/misc/guc.c:3411
+msgid "Sets the server's \"ident\" configuration file."
+msgstr "서버의 \"ident\" 구성 파일을 설정합니다."
+
+#: utils/misc/guc.c:3422
+msgid "Writes the postmaster PID to the specified file."
+msgstr "postmaster PID가 기록된 파일의 경로를 지정합니다."
+
+#: utils/misc/guc.c:3433
+msgid "Location of the SSL server certificate file."
+msgstr "서버 인증서 파일 위치를 지정함"
+
+#: utils/misc/guc.c:3443
+msgid "Location of the SSL server private key file."
+msgstr "SSL 서버 개인 키 파일의 위치를 지정함."
+
+#: utils/misc/guc.c:3453
+msgid "Location of the SSL certificate authority file."
+msgstr ""
+
+#: utils/misc/guc.c:3463
+msgid "Location of the SSL certificate revocation list file."
+msgstr "SSL 인증서 파기 목록 파일의 위치"
+
+#: utils/misc/guc.c:3473
+msgid "Writes temporary statistics files to the specified directory."
+msgstr "지정한 디렉터리에 임시 통계 파일을 씁니다."
+
+#: utils/misc/guc.c:3484
+msgid ""
+"Number of synchronous standbys and list of names of potential synchronous "
+"ones."
+msgstr ""
+
+#: utils/misc/guc.c:3495
+msgid "Sets default text search configuration."
+msgstr "기본 텍스트 검색 구성을 설정합니다."
+
+#: utils/misc/guc.c:3505
+msgid "Sets the list of allowed SSL ciphers."
+msgstr "허용되는 SSL 암호 목록을 설정합니다."
+
+#: utils/misc/guc.c:3520
+msgid "Sets the curve to use for ECDH."
+msgstr "ECDH에 사용할 curve 설정"
+
+#: utils/misc/guc.c:3535
+msgid "Sets the application name to be reported in statistics and logs."
+msgstr ""
+
+#: utils/misc/guc.c:3546
+msgid "Sets the name of the cluster, which is included in the process title."
+msgstr ""
+
+#: utils/misc/guc.c:3566
+msgid "Sets whether \"\\'\" is allowed in string literals."
+msgstr "문자열에서 \"\\'\" 문자 사용을 허용할 것인지를 정하세요"
+
+#: utils/misc/guc.c:3576
+msgid "Sets the output format for bytea."
+msgstr "bytea 값의 표시 형식을 설정합니다."
+
+#: utils/misc/guc.c:3586
+msgid "Sets the message levels that are sent to the client."
+msgstr "클라이언트 측에 보여질 메시지 수준을 지정함."
+
+#: utils/misc/guc.c:3587 utils/misc/guc.c:3640 utils/misc/guc.c:3651
+#: utils/misc/guc.c:3717
+msgid ""
+"Each level includes all the levels that follow it. The later the level, the "
+"fewer messages are sent."
+msgstr ""
+"<qbq>각 수준에는 이 수준 뒤에 있는 모든 수준이 포함됩니다. 수준이 뒤에 있을수"
+"록 전송되는 메시지 수가 적습니다."
+
+#: utils/misc/guc.c:3597
+msgid "Enables the planner to use constraints to optimize queries."
+msgstr "실행계획기가 쿼리 최적화 작업에서 제약 조건을 사용하도록 함"
+
+#: utils/misc/guc.c:3598
+msgid ""
+"Table scans will be skipped if their constraints guarantee that no rows "
+"match the query."
+msgstr ""
+"<qbq>제약 조건에 의해 쿼리와 일치하는 행이 없는 경우 테이블 스캔을 건너뜁니"
+"다."
+
+#: utils/misc/guc.c:3608
+msgid "Sets the transaction isolation level of each new transaction."
+msgstr "각 새 트랜잭션의 트랜잭션 격리 수준을 설정합니다."
+
+#: utils/misc/guc.c:3618
+msgid "Sets the display format for interval values."
+msgstr "간격 값의 표시 형식을 설정합니다."
+
+#: utils/misc/guc.c:3629
+msgid "Sets the verbosity of logged messages."
+msgstr "기록되는 메시지의 상세 정도를 지정합니다."
+
+#: utils/misc/guc.c:3639
+msgid "Sets the message levels that are logged."
+msgstr "서버 로그에 기록될 메시지 수준을 지정함."
+
+#: utils/misc/guc.c:3650
+msgid ""
+"Causes all statements generating error at or above this level to be logged."
+msgstr ""
+"오류가 있는 모든 쿼리문이나 지정한 로그 레벨 이상의 쿼리문을 로그로 남김"
+
+#: utils/misc/guc.c:3661
+msgid "Sets the type of statements logged."
+msgstr "서버로그에 기록될 구문 종류를 지정합니다."
+
+#: utils/misc/guc.c:3671
+msgid "Sets the syslog \"facility\" to be used when syslog enabled."
+msgstr "syslog 기능을 사용할 때, 사용할 syslog \"facility\" 값을 지정."
+
+#: utils/misc/guc.c:3686
+msgid "Sets the session's behavior for triggers and rewrite rules."
+msgstr "트리거 및 다시 쓰기 규칙에 대한 세션의 동작을 설정합니다."
+
+#: utils/misc/guc.c:3696
+msgid "Sets the current transaction's synchronization level."
+msgstr "현재 트랜잭션 격리 수준(isolation level)을 지정함."
+
+#: utils/misc/guc.c:3706
+msgid "Allows archiving of WAL files using archive_command."
+msgstr "archive_command를 사용하여 WAL 파일을 따로 보관하도록 설정합니다."
+
+#: utils/misc/guc.c:3716
+msgid "Enables logging of recovery-related debugging information."
+msgstr "복구 작업과 관련된 디버깅 정보를 기록하도록 합니다."
+
+#: utils/misc/guc.c:3732
+msgid "Collects function-level statistics on database activity."
+msgstr "데이터베이스 활동에 대한 함수 수준 통계를 수집합니다."
+
+#: utils/misc/guc.c:3742
+msgid "Set the level of information written to the WAL."
+msgstr "WAL에 저장할 내용 수준을 지정합니다."
+
+#: utils/misc/guc.c:3752
+msgid "Selects the dynamic shared memory implementation used."
+msgstr "사용할 동적 공유 메모리 관리방식을 선택합니다."
+
+#: utils/misc/guc.c:3762
+msgid "Selects the method used for forcing WAL updates to disk."
+msgstr "디스크에 대한 강제 WAL 업데이트에 사용되는 방법을 선택합니다."
+
+#: utils/misc/guc.c:3772
+msgid "Sets how binary values are to be encoded in XML."
+msgstr "XML에서 바이너리 값이 인코딩되는 방식을 설정합니다."
+
+#: utils/misc/guc.c:3782
+msgid ""
+"Sets whether XML data in implicit parsing and serialization operations is to "
+"be considered as documents or content fragments."
+msgstr ""
+"암시적 구문 분석 및 직렬화 작업의 XML 데이터를 문서 또는 내용 조각으로 간주할"
+"지 여부를 설정합니다."
+
+#: utils/misc/guc.c:3793
+msgid "Use of huge pages on Linux."
+msgstr "리눅스 huge 페이지 사용 여부"
+
+#: utils/misc/guc.c:3803
+msgid "Forces use of parallel query facilities."
+msgstr "병렬 쿼리 기능을 활성화"
+
+#: utils/misc/guc.c:3804
+msgid ""
+"If possible, run query using a parallel worker and with parallel "
+"restrictions."
+msgstr ""
+
+#: utils/misc/guc.c:4604
+#, c-format
+msgid "%s: could not access directory \"%s\": %s\n"
+msgstr "%s: \"%s\" 디렉터리에 액세스할 수 없음: %s\n"
+
+#: utils/misc/guc.c:4609
+#, c-format
+msgid ""
+"Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n"
+msgstr ""
+"initdb 명령이나, pg_basebackup 명령으로 PostgreSQL 데이터 디렉토리를 초기화 "
+"하세요.\n"
+
+#: utils/misc/guc.c:4629
+#, c-format
+msgid ""
+"%s does not know where to find the server configuration file.\n"
+"You must specify the --config-file or -D invocation option or set the PGDATA "
+"environment variable.\n"
+msgstr ""
+"%s 프로그램은 데이터베이스 시스템 환경 설정 파일을 찾지 못했습니다.\n"
+"직접 --config-file 또는 -D 옵션을 이용해서 데이터 디렉터리를 지정하든지,\n"
+"PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n"
+"이 프로그램을 다시 실행해 보십시오.\n"
+
+#: utils/misc/guc.c:4648
+#, c-format
+msgid "%s: could not access the server configuration file \"%s\": %s\n"
+msgstr "%s: \"%s\" 환경 설정 파일을 접근할 수 없습니다: %s\n"
+
+#: utils/misc/guc.c:4674
+#, c-format
+msgid ""
+"%s does not know where to find the database system data.\n"
+"This can be specified as \"data_directory\" in \"%s\", or by the -D "
+"invocation option, or by the PGDATA environment variable.\n"
+msgstr ""
+"%s 프로그램은 데이터베이스 시스템 데이터 디렉터리를 찾지 못했습니다.\n"
+"\"%s\" 파일에서 \"data_directory\" 값을 지정하든지,\n"
+"직접 -D 옵션을 이용해서 데이터 디렉터리를 지정하든지,\n"
+"PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n"
+"이 프로그램을 다시 실행해 보십시오.\n"
+
+#: utils/misc/guc.c:4722
+#, c-format
+msgid ""
+"%s does not know where to find the \"hba\" configuration file.\n"
+"This can be specified as \"hba_file\" in \"%s\", or by the -D invocation "
+"option, or by the PGDATA environment variable.\n"
+msgstr ""
+"%s 프로그램은 \"hba\" 환경설정파일을 찾지 못했습니다.\n"
+"\"%s\" 파일에서 \"hba_file\" 값을 지정하든지,\n"
+"직접 -D 옵션을 이용해서 데이터 디렉터리를 지정하든지,\n"
+"PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n"
+"이 프로그램을 다시 실행해 보십시오.\n"
+
+#: utils/misc/guc.c:4745
+#, c-format
+msgid ""
+"%s does not know where to find the \"ident\" configuration file.\n"
+"This can be specified as \"ident_file\" in \"%s\", or by the -D invocation "
+"option, or by the PGDATA environment variable.\n"
+msgstr ""
+"%s 프로그램은 \"ident\" 환경설정파일을 찾지 못했습니다.\n"
+"\"%s\" 파일에서 \"ident_file\" 값을 지정하든지,\n"
+"직접 -D 옵션을 이용해서 데이터 디렉터리를 지정하든지,\n"
+"PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n"
+"이 프로그램을 다시 실행해 보십시오.\n"
+
+#: utils/misc/guc.c:5419 utils/misc/guc.c:5466
+msgid "Value exceeds integer range."
+msgstr "값이 정수 범위를 초과합니다."
+
+#: utils/misc/guc.c:5689
+#, c-format
+msgid "parameter \"%s\" requires a numeric value"
+msgstr "\"%s\" 매개 변수의 값은 숫자형이어야합니다."
+
+#: utils/misc/guc.c:5698
+#, c-format
+msgid "%g is outside the valid range for parameter \"%s\" (%g .. %g)"
+msgstr ""
+"%g 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%g .. %g)를 벗어났습니다."
+
+#: utils/misc/guc.c:5851 utils/misc/guc.c:7194
+#, c-format
+msgid "cannot set parameters during a parallel operation"
+msgstr "병렬 작업 중에는 매개 변수를 설정할 수 없음"
+
+#: utils/misc/guc.c:5858 utils/misc/guc.c:6609 utils/misc/guc.c:6661
+#: utils/misc/guc.c:7022 utils/misc/guc.c:7782 utils/misc/guc.c:7950
+#: utils/misc/guc.c:9625
+#, c-format
+msgid "unrecognized configuration parameter \"%s\""
+msgstr "알 수 없는 환경 매개 변수 이름: \"%s\""
+
+#: utils/misc/guc.c:5873 utils/misc/guc.c:7034
+#, c-format
+msgid "parameter \"%s\" cannot be changed"
+msgstr "\"%s\" 매개 변수는 변경될 수 없음"
+
+#: utils/misc/guc.c:5896 utils/misc/guc.c:6089 utils/misc/guc.c:6179
+#: utils/misc/guc.c:6269 utils/misc/guc.c:6377 utils/misc/guc.c:6472
+#: guc-file.l:351
+#, c-format
+msgid "parameter \"%s\" cannot be changed without restarting the server"
+msgstr "\"%s\" 매개 변수는 서버 재실행 없이 지금 변경 될 수 없음"
+
+#: utils/misc/guc.c:5906
+#, c-format
+msgid "parameter \"%s\" cannot be changed now"
+msgstr "\"%s\" 매개 변수는 지금 변경 될 수 없음"
+
+#: utils/misc/guc.c:5924 utils/misc/guc.c:5970 utils/misc/guc.c:9641
+#, c-format
+msgid "permission denied to set parameter \"%s\""
+msgstr "\"%s\" 매개 변수를 지정할 권한이 없습니다."
+
+#: utils/misc/guc.c:5960
+#, c-format
+msgid "parameter \"%s\" cannot be set after connection start"
+msgstr "\"%s\" 매개 변수값은 연결 시작한 뒤에는 변경할 수 없습니다"
+
+#: utils/misc/guc.c:6008
+#, c-format
+msgid "cannot set parameter \"%s\" within security-definer function"
+msgstr "보안 정의자 함수 내에서 \"%s\" 매개 변수를 설정할 수 없음"
+
+#: utils/misc/guc.c:6617 utils/misc/guc.c:6665 utils/misc/guc.c:7956
+#, c-format
+msgid "must be superuser to examine \"%s\""
+msgstr "\"%s\" 검사를 위해서는 superuser여야합니다"
+
+#: utils/misc/guc.c:6731
+#, c-format
+msgid "SET %s takes only one argument"
+msgstr "SET %s 명령은 하나의 값만 지정해야합니다"
+
+#: utils/misc/guc.c:6982
+#, c-format
+msgid "must be superuser to execute ALTER SYSTEM command"
+msgstr "슈퍼유저만 ALTER SYSTEM 명령을 실행할 수 있음"
+
+#: utils/misc/guc.c:7067
+#, c-format
+msgid "parameter value for ALTER SYSTEM must not contain a newline"
+msgstr ""
+"ALTER SYSTEM 명령으로 지정하는 매개 변수 값에는 줄바꿈 문자가 없어야 합니다"
+
+#: utils/misc/guc.c:7112
+#, c-format
+msgid "could not parse contents of file \"%s\""
+msgstr "\"%s\" 파일의 내용을 분석할 수 없음"
+
+#: utils/misc/guc.c:7270
+#, c-format
+msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented"
+msgstr "SET LOCAL TRANSACTION SNAPSHOT 명령은 아직 구현 되지 않았습니다"
+
+#: utils/misc/guc.c:7355
+#, c-format
+msgid "SET requires parameter name"
+msgstr "SET 명령은 매개 변수 이름이 필요합니다"
+
+#: utils/misc/guc.c:7479
+#, c-format
+msgid "attempt to redefine parameter \"%s\""
+msgstr "\"%s\" 매개 변수를 다시 정의하려고 함"
+
+#: utils/misc/guc.c:9258
+#, c-format
+msgid "parameter \"%s\" could not be set"
+msgstr "\"%s\" 매개 변수는 설정할 수 없음"
+
+#: utils/misc/guc.c:9345
+#, c-format
+msgid "could not parse setting for parameter \"%s\""
+msgstr "지정한 \"%s\" 매개 변수값의 구문분석을 실패했습니다."
+
+#: utils/misc/guc.c:9703 utils/misc/guc.c:9737
+#, c-format
+msgid "invalid value for parameter \"%s\": %d"
+msgstr "잘못된 \"%s\" 매개 변수의 값: %d"
+
+#: utils/misc/guc.c:9771
+#, c-format
+msgid "invalid value for parameter \"%s\": %g"
+msgstr "잘못된 \"%s\" 매개 변수의 값: %g"
+
+#: utils/misc/guc.c:9961
+#, c-format
+msgid ""
+"\"temp_buffers\" cannot be changed after any temporary tables have been "
+"accessed in the session."
+msgstr ""
+"해당 세션에서 어떤 임시 테이블도 사용하고 있지 않아야 \"temp_buffers\" 설정"
+"을 변경할 수 있습니다."
+
+#: utils/misc/guc.c:9973
+#, c-format
+msgid "Bonjour is not supported by this build"
+msgstr "Bonjour 기능을 뺀 채로 서버가 만들어졌습니다."
+
+#: utils/misc/guc.c:9986
+#, c-format
+msgid "SSL is not supported by this build"
+msgstr "SSL 접속 기능을 뺀 채로 서버가 만들어졌습니다."
+
+#: utils/misc/guc.c:9998
+#, c-format
+msgid "Cannot enable parameter when \"log_statement_stats\" is true."
+msgstr "\"log_statement_stats\" 값이 true 일 때는 이 값을 활성화할 수 없습니다"
+
+#: utils/misc/guc.c:10010
+#, c-format
+msgid ""
+"Cannot enable \"log_statement_stats\" when \"log_parser_stats\", "
+"\"log_planner_stats\", or \"log_executor_stats\" is true."
+msgstr ""
+"\"log_parser_stats\", \"log_planner_stats\", \"log_executor_stats\" 설정값들 "
+"중 하나가 true 일 때는 \"log_statement_stats\" 설정을 활성화할 수 없습니다"
+
+#: utils/misc/help_config.c:131
+#, c-format
+msgid "internal error: unrecognized run-time parameter type\n"
+msgstr "내부 오류: 알 수 없는 실시간 서버 설정 변수\n"
+
+#: utils/misc/pg_config.c:61
+#, c-format
+msgid ""
+"query-specified return tuple and function return type are not compatible"
+msgstr ""
+
+#: utils/misc/rls.c:127
+#, c-format
+msgid "query would be affected by row-level security policy for table \"%s\""
+msgstr "\"%s\" 테이블의 로우 단위 보안 정책에 의해 쿼리가 영향을 받음"
+
+#: utils/misc/rls.c:129
+#, c-format
+msgid ""
+"To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW "
+"LEVEL SECURITY."
+msgstr ""
+"테이블 소유주를 위해 정책을 비활성하려면, ALTER TABLE NO FORCE ROW LEVEL "
+"SECURITY 명령을 사용하세요"
+
+#: utils/misc/timeout.c:388
+#, c-format
+msgid "cannot add more timeout reasons"
+msgstr "시간 초과로 더이상 추가할 수 없음"
+
+#: utils/misc/tzparser.c:61
+#, c-format
+msgid ""
+"time zone abbreviation \"%s\" is too long (maximum %d characters) in time "
+"zone file \"%s\", line %d"
+msgstr ""
+"\"%s\" 타임 존 이름이 너무 깁니다(최대 %d자) (\"%s\" 타임 존 파일의 %d번째 줄"
+"에 있음)."
+
+#: utils/misc/tzparser.c:73
+#, c-format
+msgid "time zone offset %d is out of range in time zone file \"%s\", line %d"
+msgstr ""
+"%d 타임 존 오프셋 값이 범위를 벗어났습니다(\"%s\" 타임 존 파일의 %d번째 줄에 "
+"있음)."
+
+#: utils/misc/tzparser.c:112
+#, c-format
+msgid "missing time zone abbreviation in time zone file \"%s\", line %d"
+msgstr "\"%s\" time zone 파일의 %d번째 줄에 time zone 생략형이 빠졌음"
+
+#: utils/misc/tzparser.c:121
+#, c-format
+msgid "missing time zone offset in time zone file \"%s\", line %d"
+msgstr "\"%s\" time zone 파일의 %d번째 줄에 time zone 옵셋이 빠졌음"
+
+#: utils/misc/tzparser.c:133
+#, c-format
+msgid "invalid number for time zone offset in time zone file \"%s\", line %d"
+msgstr ""
+"\"%s\" 표준 시간대 파일의 %d번째 줄에서 표준 시간대 오프셋 숫자가 잘못됨"
+
+#: utils/misc/tzparser.c:169
+#, c-format
+msgid "invalid syntax in time zone file \"%s\", line %d"
+msgstr "\"%s\" time zone 파일의 %d번째 줄에 구문 오류"
+
+#: utils/misc/tzparser.c:237
+#, c-format
+msgid "time zone abbreviation \"%s\" is multiply defined"
+msgstr "표준 시간대 약어 \"%s\"은(는) 배수로 정의됨"
+
+#: utils/misc/tzparser.c:239
+#, c-format
+msgid ""
+"Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s"
+"\", line %d."
+msgstr ""
+"\"%s\" 타임 존 파일의 %d번째 줄에 있는 항목이 \"%s\" 파일의 %d번째 줄에 있는 "
+"항목과 충돌합니다."
+
+#: utils/misc/tzparser.c:301
+#, c-format
+msgid "invalid time zone file name \"%s\""
+msgstr "잘못된 time zone 파일 이름: \"%s\""
+
+#: utils/misc/tzparser.c:314
+#, c-format
+msgid "time zone file recursion limit exceeded in file \"%s\""
+msgstr "\"%s\" 파일에서 time zone 파일 재귀호출 최대치를 초과했음"
+
+#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366
+#, c-format
+msgid "could not read time zone file \"%s\": %m"
+msgstr "\"%s\" time zone 파일을 읽을 수 없음: %m"
+
+#: utils/misc/tzparser.c:376
+#, c-format
+msgid "line is too long in time zone file \"%s\", line %d"
+msgstr "\"%s\" 표준 시간대 파일의 %d번째 줄이 너무 깁니다."
+
+#: utils/misc/tzparser.c:399
+#, c-format
+msgid "@INCLUDE without file name in time zone file \"%s\", line %d"
+msgstr "\"%s\" 표준 시간대 파일의 %d번째 줄에 파일 이름이 없는 @INCLUDE가 있음"
+
+#: utils/mmgr/aset.c:510
+#, c-format
+msgid "Failed while creating memory context \"%s\"."
+msgstr "\"%s\" 메모리 컨텍스트를 만드는 동안 오류가 발생했습니다."
+
+#: utils/mmgr/mcxt.c:768 utils/mmgr/mcxt.c:803 utils/mmgr/mcxt.c:840
+#: utils/mmgr/mcxt.c:877 utils/mmgr/mcxt.c:911 utils/mmgr/mcxt.c:940
+#: utils/mmgr/mcxt.c:974 utils/mmgr/mcxt.c:1056 utils/mmgr/mcxt.c:1090
+#: utils/mmgr/mcxt.c:1139
+#, c-format
+msgid "Failed on request of size %zu."
+msgstr "크기가 %zu인 요청에서 오류가 발생했습니다."
+
+#: utils/mmgr/portalmem.c:207
+#, c-format
+msgid "cursor \"%s\" already exists"
+msgstr "\"%s\" 이름의 커서가 이미 있음"
+
+#: utils/mmgr/portalmem.c:211
+#, c-format
+msgid "closing existing cursor \"%s\""
+msgstr "이미 있는 \"%s\" 커서를 닫습니다"
+
+#: utils/mmgr/portalmem.c:415
+#, c-format
+msgid "portal \"%s\" cannot be run"
+msgstr "\"%s\" portal 실행할 수 없음"
+
+#: utils/mmgr/portalmem.c:495
+#, c-format
+msgid "cannot drop active portal \"%s\""
+msgstr "\"%s\" 활성 포털을 삭제할 수 없음"
+
+#: utils/mmgr/portalmem.c:699
+#, c-format
+msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD"
+msgstr "WITH HOLD 옵션으로 커서를 만든 트랜잭션을 PREPARE할 수 없음"
+
+#: utils/sort/logtape.c:226
+#, c-format
+msgid "could not read block %ld of temporary file: %m"
+msgstr "임시 파일의 %ld 블럭을 읽을 수 없음: %m"
+
+#: utils/sort/tuplesort.c:3402
+#, c-format
+msgid "cannot have more than %d runs for an external sort"
+msgstr "외부 정렬을 위해 %d 개 이상의 런을 만들 수 없음"
+
+#: utils/sort/tuplesort.c:4474
+#, c-format
+msgid "could not create unique index \"%s\""
+msgstr "\"%s\" 고유 인덱스를 만들 수 없음"
+
+#: utils/sort/tuplesort.c:4476
+#, c-format
+msgid "Key %s is duplicated."
+msgstr "%s 키가 중복됨"
+
+#: utils/sort/tuplesort.c:4477
+#, c-format
+msgid "Duplicate keys exist."
+msgstr "중복된 키가 있음"
+
+#: utils/sort/tuplestore.c:515 utils/sort/tuplestore.c:525
+#: utils/sort/tuplestore.c:852 utils/sort/tuplestore.c:956
+#: utils/sort/tuplestore.c:1020 utils/sort/tuplestore.c:1037
+#: utils/sort/tuplestore.c:1239 utils/sort/tuplestore.c:1304
+#: utils/sort/tuplestore.c:1313
+#, c-format
+msgid "could not seek in tuplestore temporary file: %m"
+msgstr "tuplestore 파일에서 seek 작업을 할 수 없음: %m"
+
+#: utils/sort/tuplestore.c:1460 utils/sort/tuplestore.c:1533
+#: utils/sort/tuplestore.c:1539
+#, c-format
+msgid "could not read from tuplestore temporary file: %m"
+msgstr "tuplestore 임시 파일을 읽을 수 없음: %m"
+
+#: utils/sort/tuplestore.c:1501 utils/sort/tuplestore.c:1506
+#: utils/sort/tuplestore.c:1512
+#, c-format
+msgid "could not write to tuplestore temporary file: %m"
+msgstr "tuplestore 임시 파일을 쓸 수 없습니다: %m"
+
+#: utils/time/snapmgr.c:618
+#, c-format
+msgid "The source transaction is not running anymore."
+msgstr "소스 트랜잭션이 더 이상 실행중이지 않음"
+
+#: utils/time/snapmgr.c:1190
+#, c-format
+msgid "cannot export a snapshot from a subtransaction"
+msgstr "서브트랜잭션에서 스냅샷을 내보낼 수 없음"
+
+#: utils/time/snapmgr.c:1339 utils/time/snapmgr.c:1344
+#: utils/time/snapmgr.c:1349 utils/time/snapmgr.c:1364
+#: utils/time/snapmgr.c:1369 utils/time/snapmgr.c:1374
+#: utils/time/snapmgr.c:1473 utils/time/snapmgr.c:1489
+#: utils/time/snapmgr.c:1514
+#, c-format
+msgid "invalid snapshot data in file \"%s\""
+msgstr "\"%s\" 파일에 유효하지 않은 스냅샷 자료가 있습니다"
+
+#: utils/time/snapmgr.c:1411
+#, c-format
+msgid "SET TRANSACTION SNAPSHOT must be called before any query"
+msgstr "쿼리보다 먼저 SET TRANSACTION SNAPSHOP 명령을 호출해야 함"
+
+#: utils/time/snapmgr.c:1420
+#, c-format
+msgid ""
+"a snapshot-importing transaction must have isolation level SERIALIZABLE or "
+"REPEATABLE READ"
+msgstr ""
+"스냅샷 가져오기 트랜잭션은 그 격리 수준이 SERIALIZABLE 또는 REPEATABLE READ "
+"여야 함"
+
+#: utils/time/snapmgr.c:1429 utils/time/snapmgr.c:1438
+#, c-format
+msgid "invalid snapshot identifier: \"%s\""
+msgstr "잘못된 스냅샷 식별자: \"%s\""
+
+#: utils/time/snapmgr.c:1527
+#, c-format
+msgid ""
+"a serializable transaction cannot import a snapshot from a non-serializable "
+"transaction"
+msgstr ""
+"직렬화 가능한 트랜잭션은 직렬화 가능하지 않은 트랜잭션에서 스냅샷을 가져올 "
+"수 없음"
+
+#: utils/time/snapmgr.c:1531
+#, c-format
+msgid ""
+"a non-read-only serializable transaction cannot import a snapshot from a "
+"read-only transaction"
+msgstr ""
+"읽기-쓰기 직렬화된 트랜잭션이 읽기 전용 트랜잭션의 스냅샷을 가져올 수 없음"
+
+#: utils/time/snapmgr.c:1546
+#, c-format
+msgid "cannot import a snapshot from a different database"
+msgstr "서로 다른 데이터베이스를 대상으로는 스냅샷을 가져올 수 없음"
+
+#: gram.y:1004
+#, c-format
+msgid "unrecognized role option \"%s\""
+msgstr "인식할 수 없는 롤 옵션 \"%s\""
+
+#: gram.y:1278 gram.y:1293
+#, c-format
+msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements"
+msgstr ""
+"CREATE SCHEMA IF NOT EXISTS 구문에서는 스키마 요소들을 포함할 수 없습니다."
+
+#: gram.y:1438
+#, c-format
+msgid "current database cannot be changed"
+msgstr "현재 데이터베이스를 바꿀 수 없음"
+
+#: gram.y:1562
+#, c-format
+msgid "time zone interval must be HOUR or HOUR TO MINUTE"
+msgstr ""
+"지역시간대 간격(time zone interval) 값은 시(HOUR) 또는 시분(HOUR TO MINUTE) "
+"값이어야합니다"
+
+#: gram.y:2600 gram.y:2629
+#, c-format
+msgid "STDIN/STDOUT not allowed with PROGRAM"
+msgstr "PROGRAM 옵션과 STDIN/STDOUT 옵션은 함께 쓸 수 없습니다"
+
+#: gram.y:2895 gram.y:2902 gram.y:10295 gram.y:10303
+#, c-format
+msgid "GLOBAL is deprecated in temporary table creation"
+msgstr "GLOBAL 예약어는 임시 테이블 만들기에서 더 이상 사용하지 않습니다"
+
+#: gram.y:4809
+msgid "duplicate trigger events specified"
+msgstr "중복 트리거 이벤트가 지정됨"
+
+#: gram.y:4909
+#, c-format
+msgid "conflicting constraint properties"
+msgstr "제약조건 속성이 충돌함"
+
+#: gram.y:5041
+#, c-format
+msgid "CREATE ASSERTION is not yet implemented"
+msgstr "CREATE ASSERTION 명령은 아직 구현 되지 않았습니다"
+
+#: gram.y:5057
+#, c-format
+msgid "DROP ASSERTION is not yet implemented"
+msgstr "CREATE ASSERTION 명령은 아직 구현 되지 않았습니다"
+
+#: gram.y:5403
+#, c-format
+msgid "RECHECK is no longer required"
+msgstr "RECHECK는 더 이상 필요하지 않음"
+
+#: gram.y:5404
+#, c-format
+msgid "Update your data type."
+msgstr "자료형을 업데이트하십시오."
+
+#: gram.y:6983
+#, c-format
+msgid "aggregates cannot have output arguments"
+msgstr "집계 함수는 output 인자를 지정할 수 없음"
+
+#: gram.y:8853 gram.y:8871
+#, c-format
+msgid "WITH CHECK OPTION not supported on recursive views"
+msgstr "WITH CHECK OPTION 구문은 재귀적인 뷰에서 지원하지 않습니다"
+
+#: gram.y:9389
+#, c-format
+msgid "unrecognized VACUUM option \"%s\""
+msgstr "인식할 수 없는 VACUUM 옵션 \"%s\""
+
+#: gram.y:10403
+#, c-format
+msgid "LIMIT #,# syntax is not supported"
+msgstr "LIMIT #,# 구문은 지원하지 않습니다."
+
+#: gram.y:10404
+#, c-format
+msgid "Use separate LIMIT and OFFSET clauses."
+msgstr "LIMIT # OFFSET # 구문을 사용하세요."
+
+#: gram.y:10667 gram.y:10692
+#, c-format
+msgid "VALUES in FROM must have an alias"
+msgstr "FROM 안의 VALUES는 반드시 alias가 있어야합니다"
+
+#: gram.y:10668 gram.y:10693
+#, c-format
+msgid "For example, FROM (VALUES ...) [AS] foo."
+msgstr "예, FROM (VALUES ...) [AS] foo."
+
+#: gram.y:10673 gram.y:10698
+#, c-format
+msgid "subquery in FROM must have an alias"
+msgstr "FROM 절 내의 subquery 에는 반드시 alias 를 가져야만 합니다"
+
+#: gram.y:10674 gram.y:10699
+#, c-format
+msgid "For example, FROM (SELECT ...) [AS] foo."
+msgstr "예, FROM (SELECT ...) [AS] foo."
+
+#: gram.y:11273
+#, c-format
+msgid "precision for type float must be at least 1 bit"
+msgstr "실수형 자료의 정밀도 값으로는 적어도 1 bit 이상을 지정해야합니다."
+
+#: gram.y:11282
+#, c-format
+msgid "precision for type float must be less than 54 bits"
+msgstr "실수형 자료의 정밀도 값으로 최대 54 bit 까지입니다."
+
+#: gram.y:11786
+#, c-format
+msgid "wrong number of parameters on left side of OVERLAPS expression"
+msgstr "OVERLAPS 식의 왼쪽에 있는 매개 변수 수가 잘못됨"
+
+#: gram.y:11791
+#, c-format
+msgid "wrong number of parameters on right side of OVERLAPS expression"
+msgstr "OVERLAPS 식의 오른쪽에 있는 매개 변수 수가 잘못됨"
+
+#: gram.y:11966
+#, c-format
+msgid "UNIQUE predicate is not yet implemented"
+msgstr "UNIQUE 술어는 아직 구현되지 못했습니다"
+
+#: gram.y:12300
+#, c-format
+msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP"
+msgstr "WITHIN GROUP 구문 안에서 중복된 ORDER BY 구문은 허용하지 않습니다"
+
+#: gram.y:12305
+#, c-format
+msgid "cannot use DISTINCT with WITHIN GROUP"
+msgstr "DISTINCT과 WITHIN GROUP을 함께 쓸 수 없습니다"
+
+#: gram.y:12310
+#, c-format
+msgid "cannot use VARIADIC with WITHIN GROUP"
+msgstr "VARIADIC과 WITHIN GROUP을 함께 쓸 수 없습니다"
+
+#: gram.y:12816
+#, c-format
+msgid "RANGE PRECEDING is only supported with UNBOUNDED"
+msgstr "RANGE PRECEDING은 UNBOUNDED와 함께 사용해야 합니다"
+
+#: gram.y:12822
+#, c-format
+msgid "RANGE FOLLOWING is only supported with UNBOUNDED"
+msgstr "RANGE FOLLOWING은 UNBOUNDED와 함께 사용해야 합니다"
+
+#: gram.y:12849 gram.y:12872
+#, c-format
+msgid "frame start cannot be UNBOUNDED FOLLOWING"
+msgstr "프레임 시작은 UNBOUNDED FOLLOWING일 수 없음"
+
+#: gram.y:12854
+#, c-format
+msgid "frame starting from following row cannot end with current row"
+msgstr "따라오는 로우의 프레임 시작은 현재 로우의 끝일 수 없습니다"
+
+#: gram.y:12877
+#, c-format
+msgid "frame end cannot be UNBOUNDED PRECEDING"
+msgstr "프레임 끝은 UNBOUNDED PRECEDING일 수 없음"
+
+#: gram.y:12883
+#, c-format
+msgid "frame starting from current row cannot have preceding rows"
+msgstr "현재 로우의 프레임 시작은 선행하는 로우를 가질 수 없습니다"
+
+#: gram.y:12890
+#, c-format
+msgid "frame starting from following row cannot have preceding rows"
+msgstr "따라오는 로우의 프레임 시작은 선행하는 로우를 가질 수 없습니다"
+
+#: gram.y:13555
+#, c-format
+msgid "type modifier cannot have parameter name"
+msgstr "자료형 한정자는 매개 변수 이름을 사용할 수 없음"
+
+#: gram.y:13561
+#, c-format
+msgid "type modifier cannot have ORDER BY"
+msgstr "자료형 한정자는 ORDER BY 구문을 사용할 수 없음"
+
+#: gram.y:13625 gram.y:13631
+#, c-format
+msgid "%s cannot be used as a role name here"
+msgstr "%s 이름은 여기서 롤 이름으로 사용할 수 없음"
+
+#: gram.y:14253 gram.y:14442
+msgid "improper use of \"*\""
+msgstr "\"*\" 사용이 잘못됨"
+
+#: gram.y:14506
+#, c-format
+msgid ""
+"an ordered-set aggregate with a VARIADIC direct argument must have one "
+"VARIADIC aggregated argument of the same data type"
+msgstr ""
+
+#: gram.y:14543
+#, c-format
+msgid "multiple ORDER BY clauses not allowed"
+msgstr "중복된 ORDER BY 구문은 허용하지 않습니다"
+
+#: gram.y:14554
+#, c-format
+msgid "multiple OFFSET clauses not allowed"
+msgstr "중복된 OFFSET 구문은 허용하지 않습니다"
+
+#: gram.y:14563
+#, c-format
+msgid "multiple LIMIT clauses not allowed"
+msgstr "중복된 LIMIT 구문은 허용하지 않습니다"
+
+#: gram.y:14572
+#, c-format
+msgid "multiple WITH clauses not allowed"
+msgstr "중복된 WITH 절은 허용하지 않음"
+
+#: gram.y:14764
+#, c-format
+msgid "OUT and INOUT arguments aren't allowed in TABLE functions"
+msgstr "OUT 및 INOUT 인자는 TABLE 함수에 사용할 수 없음"
+
+#: gram.y:14865
+#, c-format
+msgid "multiple COLLATE clauses not allowed"
+msgstr "중복된 COLLATE 구문은 허용하지 않습니다"
+
+#. translator: %s is CHECK, UNIQUE, or similar
+#: gram.y:14903 gram.y:14916
+#, c-format
+msgid "%s constraints cannot be marked DEFERRABLE"
+msgstr "%s 제약조건에는 DEFERRABLE 옵션을 쓸 수 없음"
+
+#. translator: %s is CHECK, UNIQUE, or similar
+#: gram.y:14929
+#, c-format
+msgid "%s constraints cannot be marked NOT VALID"
+msgstr "%s 제약조건에는 NOT VALID 옵션을 쓸 수 없음"
+
+#. translator: %s is CHECK, UNIQUE, or similar
+#: gram.y:14942
+#, c-format
+msgid "%s constraints cannot be marked NO INHERIT"
+msgstr "%s 제약조건에는 NO INHERIT 옵션을 쓸 수 없음"
+
+#: guc-file.l:314
+#, c-format
+msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %u"
+msgstr "알 수 없는 환경 매개 변수 이름: \"%s\", 해당 파일: \"%s\", 줄번호: %u"
+
+#: guc-file.l:387
+#, c-format
+msgid "parameter \"%s\" removed from configuration file, reset to default"
+msgstr "환경설정 파일에 \"%s\" 매개 변수가 빠졌음, 초기값을 사용함"
+
+#: guc-file.l:453
+#, c-format
+msgid "parameter \"%s\" changed to \"%s\""
+msgstr "\"%s\" 매개 변수 값을 \"%s\"(으)로 바꿨음"
+
+#: guc-file.l:495
+#, c-format
+msgid "configuration file \"%s\" contains errors"
+msgstr "\"%s\" 환경 설정파일에 오류가 있음"
+
+#: guc-file.l:500
+#, c-format
+msgid ""
+"configuration file \"%s\" contains errors; unaffected changes were applied"
+msgstr "\"%s\" 환경 설정 파일에 오류가 있어 새로 변경될 설정이 없습니다"
+
+#: guc-file.l:505
+#, c-format
+msgid "configuration file \"%s\" contains errors; no changes were applied"
+msgstr "\"%s\" 환경 설정 파일에 오류가 있어 아무 설정도 반영되지 않았습니다."
+
+#: guc-file.l:578
+#, c-format
+msgid ""
+"could not open configuration file \"%s\": maximum nesting depth exceeded"
+msgstr "설정 파일 \"%s\"을 열 수 없습니다: 최대 디렉터리 깊이를 초과했음"
+
+#: guc-file.l:605
+#, c-format
+msgid "skipping missing configuration file \"%s\""
+msgstr "\"%s\" 환경 설정파일이 없으나 건너뜀"
+
+#: guc-file.l:859
+#, c-format
+msgid "syntax error in file \"%s\" line %u, near end of line"
+msgstr "\"%s\" 파일 %u 줄 끝부분에서 구문 오류 있음"
+
+#: guc-file.l:869
+#, c-format
+msgid "syntax error in file \"%s\" line %u, near token \"%s\""
+msgstr "\"%s\" 파일 %u 줄에서 구문 오류 있음, \"%s\" 토큰 부근"
+
+#: guc-file.l:889
+#, c-format
+msgid "too many syntax errors found, abandoning file \"%s\""
+msgstr "구문 오류가 너무 많습니다. \"%s\" 파일을 무시합니다"
+
+#: guc-file.l:941
+#, c-format
+msgid "could not open configuration directory \"%s\": %m"
+msgstr "\"%s\" 환경 설정 디렉터리를 열 수 없습니다: %m"
+
+#: repl_gram.y:260 repl_gram.y:292
+#, c-format
+msgid "invalid timeline %u"
+msgstr "잘못된 타임라인: %u"
+
+#: repl_scanner.l:120
+msgid "invalid streaming start location"
+msgstr "잘못된 스트리밍 시작 위치"
+
+#: repl_scanner.l:171 scan.l:670
+msgid "unterminated quoted string"
+msgstr "마무리 안된 따옴표 안의 문자열"
+
+#: repl_scanner.l:181
+#, c-format
+msgid "syntax error: unexpected character \"%s\""
+msgstr "구문 오류: \"%s\" 부근"
+
+# # advance 끝
+#: scan.l:432
+msgid "unterminated /* comment"
+msgstr "마무리 안된 /* 주석"
+
+#: scan.l:461
+msgid "unterminated bit string literal"
+msgstr "마무리 안된 비트 문자열 문자"
+
+#: scan.l:482
+msgid "unterminated hexadecimal string literal"
+msgstr "마무리 안된 16진수 문자열 문자"
+
+#: scan.l:532
+#, c-format
+msgid "unsafe use of string constant with Unicode escapes"
+msgstr "유니코드 이스케이프와 함께 문자열 상수를 사용하는 것은 안전하지 않음"
+
+#: scan.l:533
+#, c-format
+msgid ""
+"String constants with Unicode escapes cannot be used when "
+"standard_conforming_strings is off."
+msgstr ""
+"standard_conforming_strings = off 인 경우 문자열 상수 표기에서 유니코드 이스"
+"케이프를 사용할 수 없습니다."
+
+#: scan.l:579 scan.l:778
+msgid "invalid Unicode escape character"
+msgstr "잘못된 유니코드 이스케이프 문자"
+
+#: scan.l:605 scan.l:613 scan.l:621 scan.l:622 scan.l:623 scan.l:1338
+#: scan.l:1365 scan.l:1369 scan.l:1407 scan.l:1411 scan.l:1433 scan.l:1443
+msgid "invalid Unicode surrogate pair"
+msgstr "잘못된 유니코드 대리 쌍"
+
+#: scan.l:627
+#, c-format
+msgid "invalid Unicode escape"
+msgstr "잘못된 유니코드 이스케이프 값"
+
+#: scan.l:628
+#, c-format
+msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX."
+msgstr "유니코드 이스케이프는 \\uXXXX 또는 \\UXXXXXXXX 형태여야 합니다."
+
+#: scan.l:639
+#, c-format
+msgid "unsafe use of \\' in a string literal"
+msgstr "문자열 안에 \\' 사용이 안전하지 않습니다"
+
+#: scan.l:640
+#, c-format
+msgid ""
+"Use '' to write quotes in strings. \\' is insecure in client-only encodings."
+msgstr ""
+"작은 따옴표는 '' 형태로 사용하십시오. \\' 표기법은 클라이언트 전용 인코딩에"
+"서 안전하지 않습니다."
+
+#: scan.l:715
+msgid "unterminated dollar-quoted string"
+msgstr "마무리 안된 달러-따옴표 안의 문자열"
+
+#: scan.l:732 scan.l:758 scan.l:773
+msgid "zero-length delimited identifier"
+msgstr "길이가 0인 구분 식별자"
+
+#: scan.l:793 syncrep_scanner.l:84
+msgid "unterminated quoted identifier"
+msgstr "마무리 안된 따옴표 안의 식별자"
+
+# # nonun 부분 begin
+#: scan.l:924
+msgid "operator too long"
+msgstr "연산자가 너무 깁니다."
+
+#. translator: %s is typically the translation of "syntax error"
+#: scan.l:1078
+#, c-format
+msgid "%s at end of input"
+msgstr "%s, 입력 끝부분"
+
+#. translator: first %s is typically the translation of "syntax error"
+#: scan.l:1086
+#, c-format
+msgid "%s at or near \"%s\""
+msgstr "%s, \"%s\" 부근"
+
+#: scan.l:1252 scan.l:1284
+msgid ""
+"Unicode escape values cannot be used for code point values above 007F when "
+"the server encoding is not UTF8"
+msgstr ""
+"서버 인코딩이 UTF8이 아닌 경우 007F보다 큰 코드 지점 값에는 유니코드 이스케이"
+"프 값을 사용할 수 없음"
+
+#: scan.l:1280 scan.l:1425
+msgid "invalid Unicode escape value"
+msgstr "잘못된 유니코드 이스케이프 값"
+
+#: scan.l:1489
+#, c-format
+msgid "nonstandard use of \\' in a string literal"
+msgstr "문자열 안에 있는 \\' 문자는 표준이 아닙니다"
+
+#: scan.l:1490
+#, c-format
+msgid ""
+"Use '' to write quotes in strings, or use the escape string syntax (E'...')."
+msgstr "작은 따옴표는 '' 형태니, 인용부호 표기법(E'...') 형태로 사용하십시오."
+
+#: scan.l:1499
+#, c-format
+msgid "nonstandard use of \\\\ in a string literal"
+msgstr "문자열 안에 있는 \\\\ 문자는 표준이 아닙니다"
+
+#: scan.l:1500
+#, c-format
+msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'."
+msgstr "백슬래시 표기는 인용부호 표기법으로 사용하세요, 예, E'\\\\'."
+
+#: scan.l:1514
+#, c-format
+msgid "nonstandard use of escape in a string literal"
+msgstr "문자열 안에 비표준 escape 문자를 사용하고 있습니다"
+
+#: scan.l:1515
+#, c-format
+msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'."
+msgstr "인용부호 표기법을 사용하세요, 예, E'\\r\\n'."
diff --git a/src/backend/po/pl.po b/src/backend/po/pl.po
index 677badf5be..3ac9d0451c 100644
--- a/src/backend/po/pl.po
+++ b/src/backend/po/pl.po
@@ -1,11 +1,11 @@
# Begina Felicysym <[email protected]>, 2011, 2012, 2013.
-# grzegorz <[email protected]>, 2014, 2015, 2016.
+# grzegorz <[email protected]>, 2014, 2015, 2016, 2017.
msgid ""
msgstr ""
"Project-Id-Version: PostgreSQL 9.5\n"
"Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2016-07-18 17:41+0000\n"
-"PO-Revision-Date: 2016-07-18 23:17+0200\n"
+"POT-Creation-Date: 2017-04-09 21:11+0000\n"
+"PO-Revision-Date: 2017-04-11 23:38+0200\n"
"Last-Translator: grzegorz <[email protected]>\n"
"Language-Team: [email protected]\n"
"Language: pl\n"
@@ -26,57 +26,40 @@ msgstr ""
msgid "not recorded"
msgstr "niezarejestrowane"
-#: ../common/controldata_utils.c:52 commands/copy.c:2798
-#: commands/extension.c:3120 utils/adt/genfile.c:134
+#: ../common/controldata_utils.c:57 commands/copy.c:3042
+#: commands/extension.c:3325 utils/adt/genfile.c:135
#, c-format
msgid "could not open file \"%s\" for reading: %m"
msgstr "nie można otworzyć pliku \"%s\" do odczytu: %m"
-#: ../common/controldata_utils.c:56
+#: ../common/controldata_utils.c:61
#, c-format
msgid "%s: could not open file \"%s\" for reading: %s\n"
msgstr "%s: nie można otworzyć pliku \"%s\" do odczytu: %s\n"
-#: ../common/controldata_utils.c:66 access/transam/timeline.c:346
-#: access/transam/xlog.c:3193 access/transam/xlog.c:10338
-#: access/transam/xlog.c:10351 access/transam/xlog.c:10714
-#: access/transam/xlog.c:10757 access/transam/xlog.c:10796
-#: access/transam/xlog.c:10839 access/transam/xlogfuncs.c:665
-#: access/transam/xlogfuncs.c:684 commands/extension.c:3130
-#: replication/logical/origin.c:665 replication/logical/origin.c:695
-#: replication/logical/reorderbuffer.c:3090 replication/walsender.c:499
-#: storage/file/copydir.c:176 utils/adt/genfile.c:151
+#: ../common/controldata_utils.c:71 access/transam/timeline.c:348
+#: access/transam/xlog.c:3385 access/transam/xlog.c:10770
+#: access/transam/xlog.c:10783 access/transam/xlog.c:11175
+#: access/transam/xlog.c:11218 access/transam/xlog.c:11257
+#: access/transam/xlog.c:11300 access/transam/xlogfuncs.c:667
+#: access/transam/xlogfuncs.c:686 commands/extension.c:3335 libpq/hba.c:499
+#: replication/logical/origin.c:658 replication/logical/origin.c:688
+#: replication/logical/reorderbuffer.c:3064 replication/walsender.c:498
+#: storage/file/copydir.c:178 utils/adt/genfile.c:152 utils/adt/misc.c:924
#, c-format
msgid "could not read file \"%s\": %m"
msgstr "nie można czytać z pliku \"%s\": %m"
-#: ../common/controldata_utils.c:69
+#: ../common/controldata_utils.c:74
#, c-format
msgid "%s: could not read file \"%s\": %s\n"
msgstr "%s: nie można czytać z pliku \"%s\": %s\n"
-#: ../common/controldata_utils.c:86
-msgid "calculated CRC checksum does not match value stored in file"
-msgstr "wyliczona suma kontrolna CRC nie pasuje do wartości przechowywanej w pliku"
-
-#: ../common/controldata_utils.c:88
-#, c-format
-msgid ""
-"WARNING: Calculated CRC checksum does not match value stored in file.\n"
-"Either the file is corrupt, or it has a different layout than this program\n"
-"is expecting. The results below are untrustworthy.\n"
-"\n"
-msgstr ""
-"UWAGA: obliczona suma kontrolna CRC pliku nie zgadza się.\n"
-"Albo plik jest uszkodzony albo posiada inny układ niż program się spodziewał.\n"
-"Rezultaty mogą być niepewne.\n"
-"\n"
-
-#: ../common/controldata_utils.c:97
+#: ../common/controldata_utils.c:95
msgid "byte ordering mismatch"
msgstr "niepoprawna kolejność bajtów"
-#: ../common/controldata_utils.c:99
+#: ../common/controldata_utils.c:97
#, c-format
msgid ""
"WARNING: possible byte ordering mismatch\n"
@@ -126,7 +109,9 @@ msgstr "pclose nie powiodło się: %s"
#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75
#: ../common/fe_memutils.c:98 ../common/psprintf.c:181 ../port/path.c:632
-#: ../port/path.c:670 ../port/path.c:687
+#: ../port/path.c:670 ../port/path.c:687 utils/misc/ps_status.c:171
+#: utils/misc/ps_status.c:179 utils/misc/ps_status.c:209
+#: utils/misc/ps_status.c:217
#, c-format
msgid "out of memory\n"
msgstr "brak pamięci\n"
@@ -136,6 +121,37 @@ msgstr "brak pamięci\n"
msgid "cannot duplicate null pointer (internal error)\n"
msgstr "nie można powielić pustego wskazania (błąd wewnętrzny)\n"
+#: ../common/file_utils.c:82 ../common/file_utils.c:186
+#, c-format
+msgid "%s: could not stat file \"%s\": %s\n"
+msgstr "%s: nie można wykonać stat na pliku \"%s\": %s\n"
+
+#: ../common/file_utils.c:162
+#, c-format
+msgid "%s: could not open directory \"%s\": %s\n"
+msgstr "%s: nie można otworzyć katalogu \"%s\": %s\n"
+
+#: ../common/file_utils.c:198
+#, c-format
+msgid "%s: could not read directory \"%s\": %s\n"
+msgstr "%s: nie można odczytać katalogu \"%s\": %s\n"
+
+#: ../common/file_utils.c:231 ../common/file_utils.c:291
+#: ../common/file_utils.c:367
+#, c-format
+msgid "%s: could not open file \"%s\": %s\n"
+msgstr "%s: nie można otworzyć pliku \"%s\": %s\n"
+
+#: ../common/file_utils.c:304 ../common/file_utils.c:376
+#, c-format
+msgid "%s: could not fsync file \"%s\": %s\n"
+msgstr "%s: nie można wykonać fsync na pliku \"%s\": %s\n"
+
+#: ../common/file_utils.c:387
+#, c-format
+msgid "%s: could not rename file \"%s\" to \"%s\": %s\n"
+msgstr "%s: nie można zmienić nazwy pliku \"%s\" na \"%s\": %s\n"
+
#: ../common/pgfnames.c:45
#, c-format
msgid "could not open directory \"%s\": %s\n"
@@ -152,30 +168,32 @@ msgid "could not close directory \"%s\": %s\n"
msgstr "nie można zamknąć katalogu \"%s\": %s\n"
#: ../common/psprintf.c:179 ../port/path.c:630 ../port/path.c:668
-#: ../port/path.c:685 access/transam/twophase.c:1261
-#: access/transam/xlog.c:6069 lib/stringinfo.c:258 libpq/auth.c:847
-#: libpq/auth.c:1210 libpq/auth.c:1278 libpq/auth.c:1794
-#: postmaster/bgworker.c:289 postmaster/bgworker.c:797
-#: postmaster/postmaster.c:2326 postmaster/postmaster.c:2357
-#: postmaster/postmaster.c:3890 postmaster/postmaster.c:4580
-#: postmaster/postmaster.c:4648 postmaster/postmaster.c:5347
-#: postmaster/postmaster.c:5600
-#: replication/libpqwalreceiver/libpqwalreceiver.c:143
-#: replication/logical/logical.c:170 storage/buffer/localbuf.c:436
-#: storage/file/fd.c:729 storage/file/fd.c:1126 storage/file/fd.c:1244
-#: storage/file/fd.c:1916 storage/ipc/procarray.c:1060
-#: storage/ipc/procarray.c:1546 storage/ipc/procarray.c:1553
-#: storage/ipc/procarray.c:1967 storage/ipc/procarray.c:2570
-#: utils/adt/formatting.c:1522 utils/adt/formatting.c:1642
-#: utils/adt/formatting.c:1763 utils/adt/regexp.c:219 utils/adt/varlena.c:4440
-#: utils/adt/varlena.c:4461 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:431
-#: utils/hash/dynahash.c:537 utils/hash/dynahash.c:1049 utils/mb/mbutils.c:376
-#: utils/mb/mbutils.c:709 utils/misc/guc.c:3886 utils/misc/guc.c:3902
-#: utils/misc/guc.c:3915 utils/misc/guc.c:6861 utils/misc/tzparser.c:470
-#: utils/mmgr/aset.c:505 utils/mmgr/mcxt.c:770 utils/mmgr/mcxt.c:805
-#: utils/mmgr/mcxt.c:842 utils/mmgr/mcxt.c:879 utils/mmgr/mcxt.c:913
-#: utils/mmgr/mcxt.c:942 utils/mmgr/mcxt.c:976 utils/mmgr/mcxt.c:1058
-#: utils/mmgr/mcxt.c:1092 utils/mmgr/mcxt.c:1141
+#: ../port/path.c:685 access/transam/twophase.c:1307
+#: access/transam/xlog.c:6351 lib/stringinfo.c:300 libpq/auth.c:1063
+#: libpq/auth.c:1428 libpq/auth.c:1496 libpq/auth.c:2012
+#: postmaster/bgworker.c:332 postmaster/bgworker.c:874
+#: postmaster/postmaster.c:2363 postmaster/postmaster.c:2385
+#: postmaster/postmaster.c:3935 postmaster/postmaster.c:4635
+#: postmaster/postmaster.c:4710 postmaster/postmaster.c:5379
+#: postmaster/postmaster.c:5660
+#: replication/libpqwalreceiver/libpqwalreceiver.c:251
+#: replication/logical/logical.c:168 storage/buffer/localbuf.c:436
+#: storage/file/fd.c:773 storage/file/fd.c:1201 storage/file/fd.c:1319
+#: storage/file/fd.c:2044 storage/ipc/procarray.c:1057
+#: storage/ipc/procarray.c:1545 storage/ipc/procarray.c:1552
+#: storage/ipc/procarray.c:1966 storage/ipc/procarray.c:2569
+#: utils/adt/formatting.c:1567 utils/adt/formatting.c:1685
+#: utils/adt/formatting.c:1804 utils/adt/pg_locale.c:468
+#: utils/adt/pg_locale.c:652 utils/adt/regexp.c:219 utils/adt/varlena.c:4552
+#: utils/adt/varlena.c:4573 utils/fmgr/dfmgr.c:216 utils/hash/dynahash.c:429
+#: utils/hash/dynahash.c:535 utils/hash/dynahash.c:1047 utils/mb/mbutils.c:376
+#: utils/mb/mbutils.c:709 utils/misc/guc.c:3989 utils/misc/guc.c:4005
+#: utils/misc/guc.c:4018 utils/misc/guc.c:6967 utils/misc/tzparser.c:468
+#: utils/mmgr/aset.c:404 utils/mmgr/dsa.c:713 utils/mmgr/dsa.c:795
+#: utils/mmgr/mcxt.c:725 utils/mmgr/mcxt.c:760 utils/mmgr/mcxt.c:797
+#: utils/mmgr/mcxt.c:834 utils/mmgr/mcxt.c:868 utils/mmgr/mcxt.c:897
+#: utils/mmgr/mcxt.c:931 utils/mmgr/mcxt.c:982 utils/mmgr/mcxt.c:1016
+#: utils/mmgr/mcxt.c:1050
#, c-format
msgid "out of memory"
msgstr "brak pamięci"
@@ -235,67 +253,67 @@ msgstr "nie można wykonać polecenia stat na pliku lub katalogu \"%s\": %s\n"
msgid "could not remove file or directory \"%s\": %s\n"
msgstr "nie można usunąć pliku lub katalogu \"%s\": %s\n"
-#: ../common/username.c:45
+#: ../common/saslprep.c:1090
+#, c-format
+#| msgid "operator too long"
+msgid "password too long"
+msgstr "hasło zbyt długie"
+
+#: ../common/username.c:43
#, c-format
msgid "could not look up effective user ID %ld: %s"
msgstr "nie udało się odnaleźć efektywnego ID użytkownika %ld: %s"
-#: ../common/username.c:47 libpq/auth.c:1741
+#: ../common/username.c:45 libpq/auth.c:1959
msgid "user does not exist"
msgstr "użytkownik nie istnieje"
-#: ../common/username.c:62
+#: ../common/username.c:60
#, c-format
msgid "user name lookup failure: error code %lu"
msgstr "niepowodzenie wyszukiwania nazwy użytkownika: kod błędu %lu"
-#: ../common/wait_error.c:47
+#: ../common/wait_error.c:45
#, c-format
msgid "command not executable"
msgstr "polecenie nie wykonywalne"
-#: ../common/wait_error.c:51
+#: ../common/wait_error.c:49
#, c-format
msgid "command not found"
msgstr "polecenie nie znalezione"
-#: ../common/wait_error.c:56
+#: ../common/wait_error.c:54
#, c-format
msgid "child process exited with exit code %d"
msgstr "proces potomny zakończył działanie z kodem %d"
-#: ../common/wait_error.c:63
+#: ../common/wait_error.c:61
#, c-format
msgid "child process was terminated by exception 0x%X"
msgstr "proces potomny został zatrzymany przez wyjątek 0x%X"
-#: ../common/wait_error.c:73
+#: ../common/wait_error.c:71
#, c-format
msgid "child process was terminated by signal %s"
msgstr "proces potomny został zatrzymany przez sygnał %s"
-#: ../common/wait_error.c:77
+#: ../common/wait_error.c:75
#, c-format
msgid "child process was terminated by signal %d"
msgstr "proces potomny został zakończony przez sygnał %d"
-#: ../common/wait_error.c:82
+#: ../common/wait_error.c:80
#, c-format
msgid "child process exited with unrecognized status %d"
msgstr "proces potomny zakończył działanie z nieznanym stanem %d"
-#: ../port/chklocale.c:293
+#: ../port/chklocale.c:288
#, c-format
msgid "could not determine encoding for codeset \"%s\""
msgstr "nie udało się określić kodowania dla zestawu znaków \"%s\""
-#: ../port/chklocale.c:294 ../port/chklocale.c:423
-#: postmaster/postmaster.c:4880
-#, c-format
-msgid "Please report this to <[email protected]>."
-msgstr "Proszę zgłosić to na adres <[email protected]>."
-
-#: ../port/chklocale.c:415 ../port/chklocale.c:421
+#: ../port/chklocale.c:409 ../port/chklocale.c:415
#, c-format
msgid "could not determine encoding for locale \"%s\": codeset is \"%s\""
msgstr "nie udało się określić kodowania dla lokalizacji \"%s\": zestaw znaków to \"%s\""
@@ -320,25 +338,25 @@ msgstr "nie można ustanowić złączenia dla \"%s\": %s"
msgid "could not get junction for \"%s\": %s\n"
msgstr "nie można pobrać złączenia dla \"%s\": %s\n"
-#: ../port/open.c:112
+#: ../port/open.c:111
#, c-format
msgid "could not open file \"%s\": %s"
msgstr "nie można otworzyć pliku \"%s\": %s"
-#: ../port/open.c:113
+#: ../port/open.c:112
msgid "lock violation"
msgstr "naruszenie blokady"
-#: ../port/open.c:113
+#: ../port/open.c:112
msgid "sharing violation"
msgstr "naruszenie współdzielenia"
-#: ../port/open.c:114
+#: ../port/open.c:113
#, c-format
msgid "Continuing to retry for 30 seconds."
msgstr "Kontynuacja ponownej próby za 30 sekund."
-#: ../port/open.c:115
+#: ../port/open.c:114
#, c-format
msgid "You might have antivirus, backup, or similar software interfering with the database system."
msgstr "Prawdopodobnie twój program antywirusowy, kopii zapasowej lub podobny ingeruje w system bazy danych."
@@ -353,75 +371,105 @@ msgstr "nie można zidentyfikować aktualnego folderu roboczego: %s\n"
msgid "unrecognized error %d"
msgstr "nierozpoznany błąd %d"
-#: access/brin/brin.c:813
+#: ../port/win32security.c:62
+#, c-format
+msgid "could not get SID for Administrators group: error code %lu\n"
+msgstr "nie można pobrać SID dla grupy Administratorów: kod błędu %lu\n"
+
+#: ../port/win32security.c:72
+#, c-format
+msgid "could not get SID for PowerUsers group: error code %lu\n"
+msgstr "nie można pobrać SID dla grupy Użytkowników zaawansowanych: kod błędu %lu\n"
+
+#: ../port/win32security.c:80
+#, fuzzy, c-format
+#| msgid "could not open process token: error code %lu\n"
+msgid "could not check access token membership: error code %lu\n"
+msgstr "nie można sprawdzić członkostwa tokenu dostępu: kod błędu %lu\n"
+
+#: access/brin/brin.c:866 access/brin/brin.c:937
+#, c-format
+#| msgid "number is out of range"
+msgid "block number out of range: %s"
+msgstr "numer bloku jest poza zakresem: %s"
+
+#: access/brin/brin.c:889 access/brin/brin.c:960
#, c-format
msgid "\"%s\" is not a BRIN index"
msgstr "\"%s\" nie jest indeksem BRIN"
-#: access/brin/brin.c:829
+#: access/brin/brin.c:905 access/brin/brin.c:976
#, c-format
msgid "could not open parent table of index %s"
msgstr "nie można otworzyć tabeli nadrzędnej indeksu %s"
-#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362
+#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:360
#: access/brin/brin_pageops.c:828
#, c-format
msgid "index row size %lu exceeds maximum %lu for index \"%s\""
msgstr "rozmiar indeksu wiersza %lu przekracza maksimum %lu dla indeksu \"%s\""
-#: access/brin/brin_revmap.c:459
+#: access/brin/brin_revmap.c:379 access/brin/brin_revmap.c:385
+#, c-format
+msgid "corrupted BRIN index: inconsistent range map"
+msgstr "uszkodzony indeks BRIN: niespójna mapa przedziału"
+
+#: access/brin/brin_revmap.c:401
+#, c-format
+msgid "leftover placeholder tuple detected in BRIN index \"%s\", deleting"
+msgstr "pozostała krotka zastępcza wykryta w indeksie BRIN \"%s\", usunięcie"
+
+#: access/brin/brin_revmap.c:598
#, c-format
msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u"
msgstr "nieoczekiwany typ strony 0x%04X w indeksie BRIN \"%s\" blok %u"
-#: access/brin/brin_validate.c:115
+#: access/brin/brin_validate.c:116
#, c-format
-msgid "brin opfamily %s contains function %s with invalid support number %d"
-msgstr "brin opfamily %s zawiera funkcję %s z niepoprawnym numerem obsługi %d"
+msgid "brin operator family \"%s\" contains function %s with invalid support number %d"
+msgstr "rodzina operatorów brin \"%s\" zawiera funkcję %s z niepoprawnym numerem obsługi %d"
-#: access/brin/brin_validate.c:131
+#: access/brin/brin_validate.c:132
#, c-format
-msgid "brin opfamily %s contains function %s with wrong signature for support number %d"
-msgstr ""
-"brin opfamily %s zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
+msgid "brin operator family \"%s\" contains function %s with wrong signature for support number %d"
+msgstr "rodzina operatorów brin \"%s\" zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
-#: access/brin/brin_validate.c:153
+#: access/brin/brin_validate.c:154
#, c-format
-msgid "brin opfamily %s contains operator %s with invalid strategy number %d"
-msgstr "brin opfamily %s zawiera funkcję %s z niepoprawnym numerem strategii %d"
+msgid "brin operator family \"%s\" contains operator %s with invalid strategy number %d"
+msgstr "rodzina operatorów brin \"%s\" zawiera funkcję %s z niepoprawnym numerem strategii %d"
-#: access/brin/brin_validate.c:182
+#: access/brin/brin_validate.c:183
#, c-format
-msgid "brin opfamily %s contains invalid ORDER BY specification for operator %s"
-msgstr "brin opfamily %s zawiera niepoprawną specyfikację ORDER BY operatora %s"
+msgid "brin operator family \"%s\" contains invalid ORDER BY specification for operator %s"
+msgstr "rodzina operatorów brin \"%s\" zawiera niepoprawną specyfikację ORDER BY operatora %s"
-#: access/brin/brin_validate.c:195
+#: access/brin/brin_validate.c:196
#, c-format
-msgid "brin opfamily %s contains operator %s with wrong signature"
-msgstr "brin opfamily %s zawiera operator %s z błędnym podpisem"
+msgid "brin operator family \"%s\" contains operator %s with wrong signature"
+msgstr "rodzina operatorów brin \"%s\" zawiera operator %s z błędnym podpisem"
-#: access/brin/brin_validate.c:233
+#: access/brin/brin_validate.c:234
#, c-format
-msgid "brin opfamily %s is missing operator(s) for types %s and %s"
-msgstr "brin opfamily %s brakuje operator(ów) dla typów %s i %s"
+msgid "brin operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr "rodzinie operatorów brin \"%s\" brakuje operator(ów) dla typów %s i %s"
-#: access/brin/brin_validate.c:243
+#: access/brin/brin_validate.c:244
#, c-format
-msgid "brin opfamily %s is missing support function(s) for types %s and %s"
-msgstr "brin opfamily %s brakuje funkcji dla typów %s i %s"
+msgid "brin operator family \"%s\" is missing support function(s) for types %s and %s"
+msgstr "rodzinie operatorów brin \"%s\" brakuje funkcji obsługi dla typów %s i %s"
-#: access/brin/brin_validate.c:256
+#: access/brin/brin_validate.c:257
#, c-format
-msgid "brin opclass %s is missing operator(s)"
-msgstr "brin opclass %s brakuje operator(ów)"
+msgid "brin operator class \"%s\" is missing operator(s)"
+msgstr "klasie operatorów brin \"%s\" brakuje operator(ów)"
-#: access/brin/brin_validate.c:267
+#: access/brin/brin_validate.c:268
#, c-format
-#| msgid "return type %s is not supported for SQL functions"
-msgid "brin opclass %s is missing support function %d"
-msgstr "brin opclass %s brakuje funkcji obsługi %d"
+msgid "brin operator class \"%s\" is missing support function %d"
+msgstr "klasie operatorów brin \"%s\" brakuje funkcji obsługi %d"
-#: access/common/heaptuple.c:708 access/common/heaptuple.c:1339
+#: access/common/heaptuple.c:708 access/common/heaptuple.c:1407
#, c-format
msgid "number of columns (%d) exceeds limit (%d)"
msgstr "liczba kolumn (%d) osiągnęła limit (%d)"
@@ -431,68 +479,68 @@ msgstr "liczba kolumn (%d) osiągnęła limit (%d)"
msgid "number of index columns (%d) exceeds limit (%d)"
msgstr "liczba kolumn indeksu (%d) osiągnęła limit (%d)"
-#: access/common/indextuple.c:176 access/spgist/spgutils.c:641
+#: access/common/indextuple.c:176 access/spgist/spgutils.c:647
#, c-format
msgid "index row requires %zu bytes, maximum size is %zu"
msgstr "wiersz indeksu wymaga %zu bajtów, największy rozmiar to %zu"
-#: access/common/printtup.c:294 tcop/fastpath.c:182 tcop/fastpath.c:544
-#: tcop/postgres.c:1721
+#: access/common/printtup.c:290 tcop/fastpath.c:182 tcop/fastpath.c:532
+#: tcop/postgres.c:1732
#, c-format
msgid "unsupported format code: %d"
msgstr "nieobsługiwany kod formatu: %d"
-#: access/common/reloptions.c:493
+#: access/common/reloptions.c:540
#, c-format
msgid "user-defined relation parameter types limit exceeded"
msgstr "przekroczony limit typów parametrów relacji zdefiniowanej przez użytkownika"
-#: access/common/reloptions.c:775
+#: access/common/reloptions.c:821
#, c-format
msgid "RESET must not include values for parameters"
msgstr "RESET nie może zawierać wartości parametrów"
-#: access/common/reloptions.c:808
+#: access/common/reloptions.c:854
#, c-format
msgid "unrecognized parameter namespace \"%s\""
msgstr "nierozpoznana przestrzeń nazw parametru \"%s\""
-#: access/common/reloptions.c:1050 parser/parse_clause.c:281
+#: access/common/reloptions.c:1094 parser/parse_clause.c:270
#, c-format
msgid "unrecognized parameter \"%s\""
msgstr "nierozpoznany parametr \"%s\""
-#: access/common/reloptions.c:1080
+#: access/common/reloptions.c:1124
#, c-format
msgid "parameter \"%s\" specified more than once"
msgstr "parametr \"%s\" użyty więcej niż raz"
-#: access/common/reloptions.c:1096
+#: access/common/reloptions.c:1140
#, c-format
msgid "invalid value for boolean option \"%s\": %s"
msgstr "niepoprawna wartość dla opcji logicznej \"%s\": %s"
-#: access/common/reloptions.c:1108
+#: access/common/reloptions.c:1152
#, c-format
msgid "invalid value for integer option \"%s\": %s"
msgstr "niepoprawna wartość dla opcji całkowitej \"%s\": %s"
-#: access/common/reloptions.c:1114 access/common/reloptions.c:1134
+#: access/common/reloptions.c:1158 access/common/reloptions.c:1178
#, c-format
msgid "value %s out of bounds for option \"%s\""
msgstr "wartość %s spoza zakresu dla opcji \"%s\""
-#: access/common/reloptions.c:1116
+#: access/common/reloptions.c:1160
#, c-format
msgid "Valid values are between \"%d\" and \"%d\"."
msgstr "Prawidłowe wartości są pomiędzy \"%d\" a \"%d\"."
-#: access/common/reloptions.c:1128
+#: access/common/reloptions.c:1172
#, c-format
msgid "invalid value for floating point option \"%s\": %s"
msgstr "niepoprawna wartość dla opcji liczby zmiennopozycyjnej \"%s\": %s"
-#: access/common/reloptions.c:1136
+#: access/common/reloptions.c:1180
#, c-format
msgid "Valid values are between \"%f\" and \"%f\"."
msgstr "Prawidłowe wartości są pomiędzy \"%f\" a \"%f\"."
@@ -507,24 +555,24 @@ msgstr "Zwrócony typ %s nie pasuje do oczekiwanego typu %s dla kolumny %d."
msgid "Number of returned columns (%d) does not match expected column count (%d)."
msgstr "Liczba zwróconych kolumn (%d) nie jest równa oczekiwanej liczby kolumn (%d)."
-#: access/common/tupconvert.c:241
+#: access/common/tupconvert.c:318
#, c-format
msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s."
msgstr "Atrybut \"%s\" typu %s nie pasuje do odpowiedniego atrybutu typu %s."
-#: access/common/tupconvert.c:253
+#: access/common/tupconvert.c:330
#, c-format
msgid "Attribute \"%s\" of type %s does not exist in type %s."
msgstr "Atrybut \"%s\" typu %s nie istnieje w typie %s."
-#: access/common/tupdesc.c:635 parser/parse_relation.c:1517
+#: access/common/tupdesc.c:728 parser/parse_clause.c:816
+#: parser/parse_relation.c:1543
#, c-format
msgid "column \"%s\" cannot be declared SETOF"
msgstr "kolumna \"%s\" nie może być zadeklarowana jako SETOF"
#: access/gin/ginbulk.c:44
#, c-format
-#| msgid "payload string too long"
msgid "posting list is too long"
msgstr "lista nadawana jest za długa"
@@ -533,121 +581,124 @@ msgstr "lista nadawana jest za długa"
msgid "Reduce maintenance_work_mem."
msgstr "Ogranicz maintenance_work_mem."
-#: access/gin/ginentrypage.c:109 access/gist/gist.c:1338
-#: access/nbtree/nbtinsert.c:576 access/nbtree/nbtsort.c:488
-#: access/spgist/spgdoinsert.c:1907
+#: access/gin/ginentrypage.c:110 access/gist/gist.c:1363
+#: access/nbtree/nbtinsert.c:577 access/nbtree/nbtsort.c:488
+#: access/spgist/spgdoinsert.c:1933
#, c-format
msgid "index row size %zu exceeds maximum %zu for index \"%s\""
msgstr "rozmiar indeksu wiersza %zu przekracza maksimum %zu dla indeksu \"%s\""
-#: access/gin/ginfast.c:991 access/transam/xlog.c:9795
-#: access/transam/xlog.c:10266 access/transam/xlogfuncs.c:293
-#: access/transam/xlogfuncs.c:320 access/transam/xlogfuncs.c:359
-#: access/transam/xlogfuncs.c:380 access/transam/xlogfuncs.c:401
-#: access/transam/xlogfuncs.c:471 access/transam/xlogfuncs.c:527
+#: access/gin/ginfast.c:991 access/transam/xlog.c:10192
+#: access/transam/xlog.c:10709 access/transam/xlogfuncs.c:295
+#: access/transam/xlogfuncs.c:322 access/transam/xlogfuncs.c:361
+#: access/transam/xlogfuncs.c:382 access/transam/xlogfuncs.c:403
+#: access/transam/xlogfuncs.c:473 access/transam/xlogfuncs.c:529
#, c-format
msgid "recovery is in progress"
msgstr "trwa odzyskiwanie"
#: access/gin/ginfast.c:992
#, c-format
-#| msgid "WAL control functions cannot be executed during recovery."
msgid "GIN pending list cannot be cleaned up during recovery."
msgstr "Lista oczekujących GIN nie może być czyszczona w trakcie odzyskiwania."
#: access/gin/ginfast.c:999
#, c-format
-#| msgid "\"%s\" is not a BRIN index"
msgid "\"%s\" is not a GIN index"
msgstr "\"%s\" nie jest indeksem GIN"
#: access/gin/ginfast.c:1010
#, c-format
-#| msgid "cannot access temporary tables of other sessions"
msgid "cannot access temporary indexes of other sessions"
msgstr "nie można uzyskać dostępu do indeksów tymczasowych innych sesji"
-#: access/gin/ginscan.c:409
+#: access/gin/ginscan.c:405
#, c-format
msgid "old GIN indexes do not support whole-index scans nor searches for nulls"
msgstr "stare indeksy GIN nie wspierają pełnego skanowania indeksu ani wyszukiwania wartości pustych"
-#: access/gin/ginscan.c:410
+#: access/gin/ginscan.c:406
#, c-format
msgid "To fix this, do REINDEX INDEX \"%s\"."
msgstr "By to naprawić, wykonaj REINDEX INDEX \"%s\"."
-#: access/gin/ginvalidate.c:92
+#: access/gin/ginutil.c:134 executor/execExpr.c:1765
+#: utils/adt/arrayfuncs.c:3803 utils/adt/arrayfuncs.c:6325
+#: utils/adt/rowtypes.c:927
#, c-format
-msgid "gin opfamily %s contains support procedure %s with cross-type registration"
-msgstr ""
-"gin opfamily %s zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
+msgid "could not identify a comparison function for type %s"
+msgstr "nie można określić funkcji porównującej dla typu %s"
+
+#: access/gin/ginvalidate.c:93
+#, c-format
+msgid "gin operator family \"%s\" contains support procedure %s with cross-type registration"
+msgstr "rodzina operatorów gin \"%s\" zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
-#: access/gin/ginvalidate.c:148
+#: access/gin/ginvalidate.c:149
#, c-format
-msgid "gin opfamily %s contains function %s with invalid support number %d"
-msgstr "gin opfamily %s zawiera funkcję %s z niepoprawnym numerem obsługi %d"
+msgid "gin operator family \"%s\" contains function %s with invalid support number %d"
+msgstr "rodzina operatorów gin \"%s\" zawiera funkcję %s z niepoprawnym numerem obsługi %d"
-#: access/gin/ginvalidate.c:160
+#: access/gin/ginvalidate.c:161
#, c-format
-msgid "gin opfamily %s contains function %s with wrong signature for support number %d"
-msgstr "gin opfamily %s zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
+msgid "gin operator family \"%s\" contains function %s with wrong signature for support number %d"
+msgstr "rodzina operatorów gin \"%s\" zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
-#: access/gin/ginvalidate.c:179
+#: access/gin/ginvalidate.c:180
#, c-format
-msgid "gin opfamily %s contains operator %s with invalid strategy number %d"
-msgstr "gin opfamily %s zawiera funkcję %s z niepoprawnym numerem strategii %d"
+msgid "gin operator family \"%s\" contains operator %s with invalid strategy number %d"
+msgstr "rodzina operatorów gin \"%s\" zawiera funkcję %s z niepoprawnym numerem strategii %d"
-#: access/gin/ginvalidate.c:192
+#: access/gin/ginvalidate.c:193
#, c-format
-msgid "gin opfamily %s contains invalid ORDER BY specification for operator %s"
-msgstr "gin opfamily %s zawiera niepoprawną specyfikację ORDER BY operatora %s"
+msgid "gin operator family \"%s\" contains invalid ORDER BY specification for operator %s"
+msgstr "rodzina operatorów gin \"%s\" zawiera niepoprawną specyfikację ORDER BY operatora %s"
-#: access/gin/ginvalidate.c:205
+#: access/gin/ginvalidate.c:206
#, c-format
-msgid "gin opfamily %s contains operator %s with wrong signature"
-msgstr "gin opfamily %s zawiera operator %s z błędnym podpisem"
+msgid "gin operator family \"%s\" contains operator %s with wrong signature"
+msgstr "rodzina operatorów gin \"%s\" zawiera operator %s z błędnym podpisem"
-#: access/gin/ginvalidate.c:246
+#: access/gin/ginvalidate.c:247
#, c-format
-msgid "gin opclass %s is missing support function %d"
-msgstr "gin opclass %s brakuje funkcji obsługi %d"
+msgid "gin operator class \"%s\" is missing support function %d"
+msgstr "klasie operatorów gin \"%s\" brakuje funkcji obsługi %d"
-#: access/gin/ginvalidate.c:256
+#: access/gin/ginvalidate.c:257
#, c-format
-msgid "gin opclass %s is missing support function %d or %d"
-msgstr "gin opclass %s brakuje funkcji obsługi %d lub %d"
+msgid "gin operator class \"%s\" is missing support function %d or %d"
+msgstr "klasie operatorów gin \"%s\" brakuje funkcji obsługi %d lub %d"
-#: access/gist/gist.c:681 access/gist/gistvacuum.c:258
+#: access/gist/gist.c:706 access/gist/gistvacuum.c:258
#, c-format
msgid "index \"%s\" contains an inner tuple marked as invalid"
msgstr "indeks \"%s\" zawiera wewnętrzną krotkę oznaczoną jako niepoprawna"
-#: access/gist/gist.c:683 access/gist/gistvacuum.c:260
+#: access/gist/gist.c:708 access/gist/gistvacuum.c:260
#, c-format
msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1."
msgstr "Jest to spowodowane przez niekompletny podział strony podczas odtwarzania po awarii, przed uaktualnieniem do PostgreSQL 9.1."
-#: access/gist/gist.c:684 access/gist/gistutil.c:735
-#: access/gist/gistutil.c:746 access/gist/gistvacuum.c:261
-#: access/hash/hashutil.c:172 access/hash/hashutil.c:183
-#: access/hash/hashutil.c:195 access/hash/hashutil.c:216
-#: access/nbtree/nbtpage.c:518 access/nbtree/nbtpage.c:529
+#: access/gist/gist.c:709 access/gist/gistutil.c:739
+#: access/gist/gistutil.c:750 access/gist/gistvacuum.c:261
+#: access/hash/hashutil.c:241 access/hash/hashutil.c:252
+#: access/hash/hashutil.c:264 access/hash/hashutil.c:285
+#: access/nbtree/nbtpage.c:519 access/nbtree/nbtpage.c:530
#, c-format
msgid "Please REINDEX it."
msgstr "Proszę wykonać REINDEX."
-#: access/gist/gistbuild.c:249
+#: access/gist/gistbuild.c:250
#, c-format
msgid "invalid value for \"buffering\" option"
msgstr "niepoprawna wartość dla opcji \"buffering\""
-#: access/gist/gistbuild.c:250
+#: access/gist/gistbuild.c:251
#, c-format
msgid "Valid values are \"on\", \"off\", and \"auto\"."
msgstr "Prawidłowe wartości to \"on\", \"off\" i \"auto\"."
-#: access/gist/gistbuildbuffers.c:778 utils/sort/logtape.c:209
+#: access/gist/gistbuildbuffers.c:778 utils/sort/logtape.c:231
#, c-format
msgid "could not write block %ld of temporary file: %m"
msgstr "nie można zapisać bloku %ld pliku tymczasowego: %m"
@@ -662,186 +713,185 @@ msgstr "metoda picksplit dla kolumny %d indeksu \"%s\" nie powiodła się"
msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command."
msgstr "Indeks nie jest optymalny. Aby go zoptymalizować, skontaktuj się z programistą lub spróbuj użyć tej kolumny jako drugiej w poleceniu CREATE INDEX."
-#: access/gist/gistutil.c:732 access/hash/hashutil.c:169
-#: access/nbtree/nbtpage.c:515
+#: access/gist/gistutil.c:736 access/hash/hashutil.c:238
+#: access/nbtree/nbtpage.c:516
#, c-format
msgid "index \"%s\" contains unexpected zero page at block %u"
msgstr "indeks \"%s\" zawiera nieoczekiwaną stronę zerową w bloku %u"
-#: access/gist/gistutil.c:743 access/hash/hashutil.c:180
-#: access/hash/hashutil.c:192 access/nbtree/nbtpage.c:526
+#: access/gist/gistutil.c:747 access/hash/hashutil.c:249
+#: access/hash/hashutil.c:261 access/nbtree/nbtpage.c:527
#, c-format
msgid "index \"%s\" contains corrupted page at block %u"
msgstr "indeks \"%s\" zawiera uszkodzoną stronę w bloku %u"
-#: access/gist/gistvalidate.c:92
+#: access/gist/gistvalidate.c:93
#, c-format
-msgid "gist opfamily %s contains support procedure %s with cross-type registration"
-msgstr ""
-"gist opfamily %s zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
+msgid "gist operator family \"%s\" contains support procedure %s with cross-type registration"
+msgstr "rodzina operatorów gist \"%s\" zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
-#: access/gist/gistvalidate.c:145
+#: access/gist/gistvalidate.c:146
#, c-format
-msgid "gist opfamily %s contains function %s with invalid support number %d"
-msgstr "gist opfamily %s zawiera funkcję %s z niepoprawnym numerem obsługi %d"
+msgid "gist operator family \"%s\" contains function %s with invalid support number %d"
+msgstr "rodzina operatorów gist \"%s\" zawiera funkcję %s z niepoprawnym numerem obsługi %d"
-#: access/gist/gistvalidate.c:157
+#: access/gist/gistvalidate.c:158
#, c-format
-msgid "gist opfamily %s contains function %s with wrong signature for support number %d"
-msgstr ""
-"gist opfamily %s zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
+msgid "gist operator family \"%s\" contains function %s with wrong signature for support number %d"
+msgstr "rodzina operatorów gist \"%s\" zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
-#: access/gist/gistvalidate.c:177
+#: access/gist/gistvalidate.c:178
#, c-format
-msgid "gist opfamily %s contains operator %s with invalid strategy number %d"
-msgstr "gist opfamily %s zawiera funkcję %s z niepoprawnym numerem strategii %d"
+msgid "gist operator family \"%s\" contains operator %s with invalid strategy number %d"
+msgstr "rodzina operatorów gist \"%s\" zawiera funkcję %s z niepoprawnym numerem strategii %d"
-#: access/gist/gistvalidate.c:195
+#: access/gist/gistvalidate.c:196
#, c-format
-msgid "gist opfamily %s contains unsupported ORDER BY specification for operator %s"
-msgstr ""
-"gist opfamily %s zawiera nieobsługiwaną specyfikację ORDER BY operatora %s"
+msgid "gist operator family \"%s\" contains unsupported ORDER BY specification for operator %s"
+msgstr "rodzina operatorów gist \"%s\" zawiera nieobsługiwaną specyfikację ORDER BY operatora %s"
-#: access/gist/gistvalidate.c:206
+#: access/gist/gistvalidate.c:207
#, c-format
-msgid "gist opfamily %s contains incorrect ORDER BY opfamily specification for operator %s"
-msgstr ""
-"gist opfamily %s zawiera niepoprawną specyfikację opfamily ORDER BY "
-"operatora %s"
+msgid "gist operator family \"%s\" contains incorrect ORDER BY opfamily specification for operator %s"
+msgstr "rodzina operatorów gist \"%s\" zawiera niepoprawną specyfikację opfamily ORDER BY operatora %s"
-#: access/gist/gistvalidate.c:225
+#: access/gist/gistvalidate.c:226
#, c-format
-msgid "gist opfamily %s contains operator %s with wrong signature"
-msgstr "gist opfamily %s zawiera operator %s z błędnym podpisem"
+msgid "gist operator family \"%s\" contains operator %s with wrong signature"
+msgstr "rodzina operatorów gist \"%s\" zawiera operator %s z błędnym podpisem"
-#: access/gist/gistvalidate.c:264
+#: access/gist/gistvalidate.c:265
#, c-format
-msgid "gist opclass %s is missing support function %d"
-msgstr "gist opclass %s brakuje funkcji obsługi %d"
+msgid "gist operator class \"%s\" is missing support function %d"
+msgstr "klasie operatorów gist \"%s\" brakuje funkcji obsługi %d"
-#: access/hash/hashinsert.c:68
+#: access/hash/hashinsert.c:82
#, c-format
msgid "index row size %zu exceeds hash maximum %zu"
msgstr "rozmiar wiersza indeksu %zu przekracza maksymalny hasz %zu"
-#: access/hash/hashinsert.c:70 access/spgist/spgdoinsert.c:1911
-#: access/spgist/spgutils.c:702
+#: access/hash/hashinsert.c:84 access/spgist/spgdoinsert.c:1937
+#: access/spgist/spgutils.c:708
#, c-format
msgid "Values larger than a buffer page cannot be indexed."
msgstr "Wartości dłuższe niż strona bufora nie mogą być zindeksowane."
-#: access/hash/hashovfl.c:546
+#: access/hash/hashovfl.c:87
+#, c-format
+#| msgid "invalid port number: \"%s\"\n"
+msgid "invalid overflow block number %u"
+msgstr "nieprawidłowy nadmiarowy numer bloku: %u"
+
+#: access/hash/hashovfl.c:283 access/hash/hashpage.c:453
#, c-format
msgid "out of overflow pages in hash index \"%s\""
msgstr "brak stron przepełnienia w indeksie haszującym \"%s\""
-#: access/hash/hashsearch.c:153
+#: access/hash/hashsearch.c:250
#, c-format
msgid "hash indexes do not support whole-index scans"
msgstr "indeksy haszujące nie obsługują pełnych skanów indeksu"
-#: access/hash/hashutil.c:208
+#: access/hash/hashutil.c:277
#, c-format
msgid "index \"%s\" is not a hash index"
msgstr "indeks \"%s\" nie jest indeksem haszującym"
-#: access/hash/hashutil.c:214
+#: access/hash/hashutil.c:283
#, c-format
msgid "index \"%s\" has wrong hash version"
msgstr "indeks \"%s\" ma niepoprawną wersję haszu"
-#: access/hash/hashvalidate.c:98
+#: access/hash/hashvalidate.c:99
#, c-format
-msgid "hash opfamily %s contains support procedure %s with cross-type registration"
-msgstr ""
-"hash opfamily %s zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
+msgid "hash operator family \"%s\" contains support procedure %s with cross-type registration"
+msgstr "rodzina operatorów hash \"%s\" zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
-#: access/hash/hashvalidate.c:113
+#: access/hash/hashvalidate.c:114
#, c-format
-msgid "hash opfamily %s contains function %s with wrong signature for support number %d"
-msgstr ""
-"hash opfamily %s zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
+msgid "hash operator family \"%s\" contains function %s with wrong signature for support number %d"
+msgstr "rodzina operatorów hash \"%s\" zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
-#: access/hash/hashvalidate.c:130
+#: access/hash/hashvalidate.c:131
#, c-format
-msgid "hash opfamily %s contains function %s with invalid support number %d"
-msgstr "hash opfamily %s zawiera funkcję %s z niepoprawnym numerem obsługi %d"
+msgid "hash operator family \"%s\" contains function %s with invalid support number %d"
+msgstr "rodzina operatorów hash \"%s\" zawiera funkcję %s z niepoprawnym numerem obsługi %d"
-#: access/hash/hashvalidate.c:151
+#: access/hash/hashvalidate.c:152
#, c-format
-msgid "hash opfamily %s contains operator %s with invalid strategy number %d"
-msgstr "hash opfamily %s zawiera funkcję %s z niepoprawnym numerem strategii %d"
+msgid "hash operator family \"%s\" contains operator %s with invalid strategy number %d"
+msgstr "rodzina operatorów hash \"%s\" zawiera funkcję %s z niepoprawnym numerem strategii %d"
-#: access/hash/hashvalidate.c:164
+#: access/hash/hashvalidate.c:165
#, c-format
-msgid "hash opfamily %s contains invalid ORDER BY specification for operator %s"
-msgstr "hash opfamily %s zawiera niepoprawną specyfikację ORDER BY operatora %s"
+msgid "hash operator family \"%s\" contains invalid ORDER BY specification for operator %s"
+msgstr "rodzina operatorów hash \"%s\" zawiera niepoprawną specyfikację ORDER BY operatora %s"
-#: access/hash/hashvalidate.c:177
+#: access/hash/hashvalidate.c:178
#, c-format
-msgid "hash opfamily %s contains operator %s with wrong signature"
-msgstr "hash opfamily %s zawiera operator %s z błędnym podpisem"
+msgid "hash operator family \"%s\" contains operator %s with wrong signature"
+msgstr "rodzina operatorów hash \"%s\" zawiera operator %s z błędnym podpisem"
-#: access/hash/hashvalidate.c:189
+#: access/hash/hashvalidate.c:190
#, c-format
-msgid "hash opfamily %s lacks support function for operator %s"
-msgstr "hash opfamily %s brakuje funkcji obsługującej operator %s"
+msgid "hash operator family \"%s\" lacks support function for operator %s"
+msgstr "rodzinie operatorów hash \"%s\" brakuje funkcji obsługującej operator %s"
-#: access/hash/hashvalidate.c:217
+#: access/hash/hashvalidate.c:218
#, c-format
-msgid "hash opfamily %s is missing operator(s) for types %s and %s"
-msgstr "hash opfamily %s brakuje operator(ów) dla typów %s i %s"
+msgid "hash operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr "rodzinie operatorów hash \"%s\" brakuje operator(ów) dla typów %s i %s"
-#: access/hash/hashvalidate.c:231
+#: access/hash/hashvalidate.c:232
#, c-format
-msgid "hash opclass %s is missing operator(s)"
-msgstr "hash opclass %s brakuje operator(ów)"
+msgid "hash operator class \"%s\" is missing operator(s)"
+msgstr "klasie operatorów hash \"%s\" brakuje operator(ów)"
-#: access/hash/hashvalidate.c:247
+#: access/hash/hashvalidate.c:248
#, c-format
-msgid "hash opfamily %s is missing cross-type operator(s)"
-msgstr "hash opfamily %s brakuje operatora(ów) międzytypowych"
+msgid "hash operator family \"%s\" is missing cross-type operator(s)"
+msgstr "rodzinie operatorów hash \"%s\" brakuje operatora(ów) międzytypowych"
-#: access/heap/heapam.c:1295 access/heap/heapam.c:1323
-#: access/heap/heapam.c:1355 catalog/aclchk.c:1748
+#: access/heap/heapam.c:1293 access/heap/heapam.c:1321
+#: access/heap/heapam.c:1353 catalog/aclchk.c:1772
#, c-format
msgid "\"%s\" is an index"
msgstr "\"%s\" jest indeksem"
-#: access/heap/heapam.c:1300 access/heap/heapam.c:1328
-#: access/heap/heapam.c:1360 catalog/aclchk.c:1755 commands/tablecmds.c:8984
-#: commands/tablecmds.c:12042
+#: access/heap/heapam.c:1298 access/heap/heapam.c:1326
+#: access/heap/heapam.c:1358 catalog/aclchk.c:1779 commands/tablecmds.c:9851
+#: commands/tablecmds.c:13063
#, c-format
msgid "\"%s\" is a composite type"
msgstr "\"%s\" jest typem złożonym"
-#: access/heap/heapam.c:2567
+#: access/heap/heapam.c:2592
#, c-format
msgid "cannot insert tuples during a parallel operation"
msgstr "nie można wstawiać krotek w czasie trwania operacji równoległej"
-#: access/heap/heapam.c:3017
+#: access/heap/heapam.c:3042
#, c-format
msgid "cannot delete tuples during a parallel operation"
msgstr "nie można usuwać krotek w czasie trwania operacji równoległej"
-#: access/heap/heapam.c:3063
+#: access/heap/heapam.c:3088
#, c-format
msgid "attempted to delete invisible tuple"
msgstr "próbowano usunąć niewidoczną krotkę"
-#: access/heap/heapam.c:3489 access/heap/heapam.c:6191
+#: access/heap/heapam.c:3514 access/heap/heapam.c:6213
#, c-format
msgid "cannot update tuples during a parallel operation"
msgstr "nie można zmieniać krotek w czasie trwania operacji równoległej"
-#: access/heap/heapam.c:3611
+#: access/heap/heapam.c:3661
#, c-format
msgid "attempted to update invisible tuple"
msgstr "próbowano zmienić niewidoczną krotkę"
-#: access/heap/heapam.c:4960 access/heap/heapam.c:4998
-#: access/heap/heapam.c:5233 executor/execMain.c:2312
+#: access/heap/heapam.c:4936 access/heap/heapam.c:4974
+#: access/heap/heapam.c:5226 executor/execMain.c:2497
#, c-format
msgid "could not obtain lock on row in relation \"%s\""
msgstr "nie można nałożyć blokady na rekord w relacji \"%s\""
@@ -851,130 +901,130 @@ msgstr "nie można nałożyć blokady na rekord w relacji \"%s\""
msgid "row is too big: size %zu, maximum size %zu"
msgstr "rekord jest zbyt duży: rozmiar %zu, maksymalny rozmiar %zu"
-#: access/heap/rewriteheap.c:925
+#: access/heap/rewriteheap.c:926
#, c-format
msgid "could not write to file \"%s\", wrote %d of %d: %m"
msgstr "nie można pisać do pliku \"%s\", zapisano %d z %d: %m"
-#: access/heap/rewriteheap.c:965 access/heap/rewriteheap.c:1177
-#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:407
-#: access/transam/timeline.c:483 access/transam/xlog.c:3060
-#: access/transam/xlog.c:3222 replication/logical/snapbuild.c:1607
-#: replication/slot.c:1078 replication/slot.c:1163 storage/file/fd.c:624
-#: storage/file/fd.c:3052 storage/smgr/md.c:1044 storage/smgr/md.c:1277
-#: storage/smgr/md.c:1450 utils/misc/guc.c:6883
+#: access/heap/rewriteheap.c:966 access/heap/rewriteheap.c:1183
+#: access/heap/rewriteheap.c:1282 access/transam/timeline.c:412
+#: access/transam/timeline.c:492 access/transam/xlog.c:3250
+#: access/transam/xlog.c:3418 replication/logical/snapbuild.c:1626
+#: replication/slot.c:1215 replication/slot.c:1302 storage/file/fd.c:631
+#: storage/file/fd.c:3180 storage/smgr/md.c:1044 storage/smgr/md.c:1277
+#: storage/smgr/md.c:1450 utils/misc/guc.c:6989
#, c-format
msgid "could not fsync file \"%s\": %m"
msgstr "nie udało się fsync na pliku \"%s\": %m"
-#: access/heap/rewriteheap.c:1020 access/heap/rewriteheap.c:1140
-#: access/transam/timeline.c:315 access/transam/timeline.c:461
-#: access/transam/xlog.c:3016 access/transam/xlog.c:3165
-#: access/transam/xlog.c:10124 access/transam/xlog.c:10162
-#: access/transam/xlog.c:10489 postmaster/postmaster.c:4355
-#: replication/logical/origin.c:542 replication/slot.c:1035
-#: storage/file/copydir.c:162 storage/smgr/md.c:331 utils/time/snapmgr.c:1183
+#: access/heap/rewriteheap.c:1021 access/heap/rewriteheap.c:1141
+#: access/transam/timeline.c:315 access/transam/timeline.c:467
+#: access/transam/xlog.c:3203 access/transam/xlog.c:3356
+#: access/transam/xlog.c:10526 access/transam/xlog.c:10564
+#: access/transam/xlog.c:10949 postmaster/postmaster.c:4410
+#: replication/logical/origin.c:535 replication/slot.c:1167
+#: storage/file/copydir.c:162 storage/smgr/md.c:327 utils/time/snapmgr.c:1284
#, c-format
msgid "could not create file \"%s\": %m"
msgstr "nie można utworzyć pliku \"%s\": %m"
-#: access/heap/rewriteheap.c:1149
+#: access/heap/rewriteheap.c:1151
#, c-format
msgid "could not truncate file \"%s\" to %u: %m"
msgstr "nie można obciąć pliku \"%s\" do %u: %m"
-#: access/heap/rewriteheap.c:1156 replication/walsender.c:481
-#: storage/smgr/md.c:1902
+#: access/heap/rewriteheap.c:1159 replication/walsender.c:478
+#: storage/smgr/md.c:1949
#, c-format
msgid "could not seek to end of file \"%s\": %m"
msgstr "nie można pozycjonować do końca w pliku \"%s\": %m"
-#: access/heap/rewriteheap.c:1167 access/transam/timeline.c:367
-#: access/transam/timeline.c:401 access/transam/timeline.c:477
-#: access/transam/xlog.c:3051 access/transam/xlog.c:3215
-#: postmaster/postmaster.c:4365 postmaster/postmaster.c:4375
-#: replication/logical/origin.c:551 replication/logical/origin.c:587
-#: replication/logical/origin.c:603 replication/logical/snapbuild.c:1591
-#: replication/slot.c:1064 storage/file/copydir.c:187
-#: utils/init/miscinit.c:1228 utils/init/miscinit.c:1237
-#: utils/init/miscinit.c:1244 utils/misc/guc.c:6844 utils/misc/guc.c:6875
-#: utils/misc/guc.c:8717 utils/misc/guc.c:8731 utils/time/snapmgr.c:1188
-#: utils/time/snapmgr.c:1195
+#: access/heap/rewriteheap.c:1171 access/transam/timeline.c:370
+#: access/transam/timeline.c:405 access/transam/timeline.c:484
+#: access/transam/xlog.c:3239 access/transam/xlog.c:3409
+#: postmaster/postmaster.c:4420 postmaster/postmaster.c:4430
+#: replication/logical/origin.c:544 replication/logical/origin.c:580
+#: replication/logical/origin.c:596 replication/logical/snapbuild.c:1608
+#: replication/slot.c:1198 storage/file/copydir.c:191
+#: utils/init/miscinit.c:1240 utils/init/miscinit.c:1251
+#: utils/init/miscinit.c:1259 utils/misc/guc.c:6950 utils/misc/guc.c:6981
+#: utils/misc/guc.c:8831 utils/misc/guc.c:8845 utils/time/snapmgr.c:1289
+#: utils/time/snapmgr.c:1296
#, c-format
msgid "could not write to file \"%s\": %m"
msgstr "nie można pisać do pliku \"%s\": %m"
-#: access/heap/rewriteheap.c:1250 access/transam/xlog.c:10356
-#: access/transam/xlogarchive.c:114 access/transam/xlogarchive.c:468
-#: replication/logical/origin.c:529 replication/logical/reorderbuffer.c:2624
-#: replication/logical/reorderbuffer.c:2681
-#: replication/logical/snapbuild.c:1535 replication/logical/snapbuild.c:1910
-#: replication/slot.c:1137 storage/ipc/dsm.c:326 storage/smgr/md.c:431
-#: storage/smgr/md.c:480 storage/smgr/md.c:1397
+#: access/heap/rewriteheap.c:1257 access/transam/xlogarchive.c:113
+#: access/transam/xlogarchive.c:467 postmaster/postmaster.c:1239
+#: postmaster/syslogger.c:1371 replication/logical/origin.c:522
+#: replication/logical/reorderbuffer.c:2595
+#: replication/logical/reorderbuffer.c:2652
+#: replication/logical/snapbuild.c:1551 replication/logical/snapbuild.c:1938
+#: replication/slot.c:1275 storage/file/fd.c:682 storage/ipc/dsm.c:327
+#: storage/smgr/md.c:426 storage/smgr/md.c:475 storage/smgr/md.c:1397
#, c-format
msgid "could not remove file \"%s\": %m"
msgstr "nie można usunąć pliku \"%s\": %m"
-#: access/heap/rewriteheap.c:1264 access/transam/timeline.c:111
+#: access/heap/rewriteheap.c:1271 access/transam/timeline.c:111
#: access/transam/timeline.c:236 access/transam/timeline.c:334
-#: access/transam/xlog.c:2992 access/transam/xlog.c:3109
-#: access/transam/xlog.c:3150 access/transam/xlog.c:3423
-#: access/transam/xlog.c:3501 access/transam/xlogutils.c:701
-#: replication/basebackup.c:401 replication/basebackup.c:1162
-#: replication/logical/origin.c:658 replication/logical/reorderbuffer.c:2154
-#: replication/logical/reorderbuffer.c:2394
-#: replication/logical/reorderbuffer.c:3072
-#: replication/logical/snapbuild.c:1584 replication/logical/snapbuild.c:1668
-#: replication/slot.c:1152 replication/walsender.c:474
-#: replication/walsender.c:2104 storage/file/copydir.c:155
-#: storage/file/fd.c:607 storage/file/fd.c:2964 storage/file/fd.c:3031
-#: storage/smgr/md.c:613 utils/error/elog.c:1870 utils/init/miscinit.c:1163
-#: utils/init/miscinit.c:1284 utils/init/miscinit.c:1362 utils/misc/guc.c:7103
-#: utils/misc/guc.c:7136
+#: access/transam/xlog.c:3179 access/transam/xlog.c:3300
+#: access/transam/xlog.c:3341 access/transam/xlog.c:3620
+#: access/transam/xlog.c:3698 access/transam/xlogutils.c:706
+#: postmaster/syslogger.c:1380 replication/basebackup.c:474
+#: replication/basebackup.c:1218 replication/logical/origin.c:651
+#: replication/logical/reorderbuffer.c:2113
+#: replication/logical/reorderbuffer.c:2361
+#: replication/logical/reorderbuffer.c:3044
+#: replication/logical/snapbuild.c:1600 replication/logical/snapbuild.c:1688
+#: replication/slot.c:1290 replication/walsender.c:471
+#: replication/walsender.c:2314 storage/file/copydir.c:155
+#: storage/file/fd.c:614 storage/file/fd.c:3092 storage/file/fd.c:3159
+#: storage/smgr/md.c:608 utils/error/elog.c:1879 utils/init/miscinit.c:1171
+#: utils/init/miscinit.c:1299 utils/init/miscinit.c:1376 utils/misc/guc.c:7209
+#: utils/misc/guc.c:7242
#, c-format
msgid "could not open file \"%s\": %m"
msgstr "nie można otworzyć pliku \"%s\": %m"
-#: access/index/amapi.c:69 commands/amcmds.c:164
+#: access/index/amapi.c:83 commands/amcmds.c:163
#, c-format
-#| msgid "access method \"%s\" does not exist"
msgid "access method \"%s\" is not of type %s"
msgstr "metoda dostępu \"%s\" nie jest typu %s"
-#: access/index/amapi.c:78
+#: access/index/amapi.c:99
#, c-format
-#| msgid "access method \"%s\" does not exist"
msgid "index access method \"%s\" does not have a handler"
msgstr "metoda dostępu \"%s\" do indeksu nie ma procesu obsługi"
-#: access/index/indexam.c:155 catalog/objectaddress.c:1196
-#: commands/indexcmds.c:1799 commands/tablecmds.c:241
-#: commands/tablecmds.c:12033
+#: access/index/indexam.c:160 catalog/objectaddress.c:1223
+#: commands/indexcmds.c:1806 commands/tablecmds.c:247
+#: commands/tablecmds.c:13054
#, c-format
msgid "\"%s\" is not an index"
msgstr "\"%s\" nie jest indeksem"
-#: access/nbtree/nbtinsert.c:428
+#: access/nbtree/nbtinsert.c:429
#, c-format
msgid "duplicate key value violates unique constraint \"%s\""
msgstr "podwójna wartość klucza narusza ograniczenie unikalności \"%s\""
-#: access/nbtree/nbtinsert.c:430
+#: access/nbtree/nbtinsert.c:431
#, c-format
msgid "Key %s already exists."
msgstr "Klucz %s już istnieje."
-#: access/nbtree/nbtinsert.c:497
+#: access/nbtree/nbtinsert.c:498
#, c-format
msgid "failed to re-find tuple within index \"%s\""
msgstr "nie udało się odnaleźć ponownie krotki w ramach indeksu \"%s\""
-#: access/nbtree/nbtinsert.c:499
+#: access/nbtree/nbtinsert.c:500
#, c-format
msgid "This may be because of a non-immutable index expression."
msgstr "Może to być spowodowane nie niezmienny wyrażeniem indeksu."
-#: access/nbtree/nbtinsert.c:579 access/nbtree/nbtsort.c:491
+#: access/nbtree/nbtinsert.c:580 access/nbtree/nbtsort.c:491
#, c-format
msgid ""
"Values larger than 1/3 of a buffer page cannot be indexed.\n"
@@ -983,130 +1033,122 @@ msgstr ""
"Wartości większe niż 1/3 strony bufora nie może być zindeksowane.\n"
"Rozważ indeks funkcji z haszem MD5 z wartości, lub użyj indeksowania pełnego indeksowania tekstowego."
-#: access/nbtree/nbtpage.c:168 access/nbtree/nbtpage.c:371
-#: access/nbtree/nbtpage.c:458 parser/parse_utilcmd.c:1715
+#: access/nbtree/nbtpage.c:169 access/nbtree/nbtpage.c:372
+#: access/nbtree/nbtpage.c:459 parser/parse_utilcmd.c:1888
#, c-format
msgid "index \"%s\" is not a btree"
msgstr "indeks \"%s\" nie jest indeksem btree"
-#: access/nbtree/nbtpage.c:174 access/nbtree/nbtpage.c:377
-#: access/nbtree/nbtpage.c:464
+#: access/nbtree/nbtpage.c:175 access/nbtree/nbtpage.c:378
+#: access/nbtree/nbtpage.c:465
#, c-format
msgid "version mismatch in index \"%s\": file version %d, code version %d"
msgstr "niezgodność wersji w indeksie \"%s\": wersja pliku %d, wersja kodu %d"
-#: access/nbtree/nbtpage.c:1152
+#: access/nbtree/nbtpage.c:1153
#, c-format
msgid "index \"%s\" contains a half-dead internal page"
msgstr "indeks \"%s\" zawiera pół-martwą stronę wewnętrzną"
-#: access/nbtree/nbtpage.c:1154
+#: access/nbtree/nbtpage.c:1155
#, c-format
msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it."
msgstr "Może to być spowodowane przerwanym VACUUM w wersji 9.3 lub starszej, przed uaktualnieniem. Należy wykonać REINDEX."
-#: access/nbtree/nbtvalidate.c:100
+#: access/nbtree/nbtvalidate.c:101
#, c-format
-msgid "btree opfamily %s contains function %s with invalid support number %d"
-msgstr "btree opfamily %s zawiera funkcję %s z niepoprawnym numerem obsługi %d"
+msgid "btree operator family \"%s\" contains function %s with invalid support number %d"
+msgstr "rodzina operatorów btree \"%s\" zawiera funkcję %s z niepoprawnym numerem obsługi %d"
-#: access/nbtree/nbtvalidate.c:112
+#: access/nbtree/nbtvalidate.c:113
#, c-format
-msgid "btree opfamily %s contains function %s with wrong signature for support number %d"
-msgstr ""
-"btree opfamily %s zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
+msgid "btree operator family \"%s\" contains function %s with wrong signature for support number %d"
+msgstr "rodzina operatorów btree \"%s\" zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
-#: access/nbtree/nbtvalidate.c:132
+#: access/nbtree/nbtvalidate.c:133
#, c-format
-msgid "btree opfamily %s contains operator %s with invalid strategy number %d"
-msgstr ""
-"btree opfamily %s zawiera funkcję %s z niepoprawnym numerem strategii %d"
+msgid "btree operator family \"%s\" contains operator %s with invalid strategy number %d"
+msgstr "rodzina operatorów btree \"%s\" zawiera funkcję %s z niepoprawnym numerem strategii %d"
-#: access/nbtree/nbtvalidate.c:145
+#: access/nbtree/nbtvalidate.c:146
#, c-format
-msgid "btree opfamily %s contains invalid ORDER BY specification for operator %s"
-msgstr ""
-"btree opfamily %s zawiera niepoprawną specyfikację ORDER BY operatora %s"
+msgid "btree operator family \"%s\" contains invalid ORDER BY specification for operator %s"
+msgstr "rodzina operatorów btree \"%s\" zawiera niepoprawną specyfikację ORDER BY operatora %s"
-#: access/nbtree/nbtvalidate.c:158
+#: access/nbtree/nbtvalidate.c:159
#, c-format
-msgid "btree opfamily %s contains operator %s with wrong signature"
-msgstr "btree opfamily %s zawiera operator %s z błędnym podpisem"
+msgid "btree operator family \"%s\" contains operator %s with wrong signature"
+msgstr "rodzina operatorów btree \"%s\" zawiera operator %s z błędnym podpisem"
-#: access/nbtree/nbtvalidate.c:200
+#: access/nbtree/nbtvalidate.c:201
#, c-format
-msgid "btree opfamily %s is missing operator(s) for types %s and %s"
-msgstr "btree opfamily %s brakuje operator(ów) dla typów %s i %s"
+msgid "btree operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr "rodzinie operatorów btree \"%s\" brakuje operator(ów) dla typów %s i %s"
-#: access/nbtree/nbtvalidate.c:210
+#: access/nbtree/nbtvalidate.c:211
#, c-format
-msgid "btree opfamily %s is missing support function for types %s and %s"
-msgstr "btree opfamily %s brakuje funkcji dla typów %s i %s"
+msgid "btree operator family \"%s\" is missing support function for types %s and %s"
+msgstr "rodzinie operatorów btree \"%s\" brakuje funkcji obsługi dla typów %s i %s"
-#: access/nbtree/nbtvalidate.c:224
+#: access/nbtree/nbtvalidate.c:225
#, c-format
-msgid "btree opclass %s is missing operator(s)"
-msgstr "btree opclass %s brakuje operator(ów)"
+msgid "btree operator class \"%s\" is missing operator(s)"
+msgstr "klasie operatorów btree \"%s\" brakuje operator(ów)"
-#: access/nbtree/nbtvalidate.c:241
+#: access/nbtree/nbtvalidate.c:242
#, c-format
-msgid "btree opfamily %s is missing cross-type operator(s)"
-msgstr "btree opfamily %s brakuje operatora(ów) międzytypowych"
+msgid "btree operator family \"%s\" is missing cross-type operator(s)"
+msgstr "rodzinie operatorów btree \"%s\" brakuje operatora(ów) międzytypowych"
-#: access/spgist/spgutils.c:699
+#: access/spgist/spgutils.c:705
#, c-format
msgid "SP-GiST inner tuple size %zu exceeds maximum %zu"
msgstr "rozmiar wewnętrznej krotki SP-GiST %zu przekracza maksimum %zu"
-#: access/spgist/spgvalidate.c:92
+#: access/spgist/spgvalidate.c:93
#, c-format
-msgid "spgist opfamily %s contains support procedure %s with cross-type registration"
-msgstr ""
-"spgist opfamily %s zawiera procedurę obsługi %s z rejestracją typu "
-"krzyżowego"
+msgid "spgist operator family \"%s\" contains support procedure %s with cross-type registration"
+msgstr "rodzina operatorów spgist \"%s\" zawiera procedurę obsługi %s z rejestracją typu krzyżowego"
-#: access/spgist/spgvalidate.c:115
+#: access/spgist/spgvalidate.c:116
#, c-format
-msgid "spgist opfamily %s contains function %s with invalid support number %d"
-msgstr "spgist opfamily %s zawiera funkcję %s z niepoprawnym numerem obsługi %d"
+msgid "spgist operator family \"%s\" contains function %s with invalid support number %d"
+msgstr "rodzina operatorów spgist \"%s\" zawiera funkcję %s z niepoprawnym numerem obsługi %d"
-#: access/spgist/spgvalidate.c:127
+#: access/spgist/spgvalidate.c:128
#, c-format
-msgid "spgist opfamily %s contains function %s with wrong signature for support number %d"
-msgstr ""
-"spgist opfamily %s zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
+msgid "spgist operator family \"%s\" contains function %s with wrong signature for support number %d"
+msgstr "rodzina operatorów spgist \"%s\" zawiera funkcję %s z błędnym podpisem numeru obsługi %d"
-#: access/spgist/spgvalidate.c:146
+#: access/spgist/spgvalidate.c:147
#, c-format
-msgid "spgist opfamily %s contains operator %s with invalid strategy number %d"
-msgstr ""
-"spgist opfamily %s zawiera funkcję %s z niepoprawnym numerem strategii %d"
+msgid "spgist operator family \"%s\" contains operator %s with invalid strategy number %d"
+msgstr "rodzina operatorów spgist \"%s\" zawiera funkcję %s z niepoprawnym numerem strategii %d"
-#: access/spgist/spgvalidate.c:159
+#: access/spgist/spgvalidate.c:160
#, c-format
-msgid "spgist opfamily %s contains invalid ORDER BY specification for operator %s"
-msgstr ""
-"spgist opfamily %s zawiera niepoprawną specyfikację ORDER BY operatora %s"
+msgid "spgist operator family \"%s\" contains invalid ORDER BY specification for operator %s"
+msgstr "rodzina operatorów spgist \"%s\" zawiera niepoprawną specyfikację ORDER BY operatora %s"
-#: access/spgist/spgvalidate.c:172
+#: access/spgist/spgvalidate.c:173
#, c-format
-msgid "spgist opfamily %s contains operator %s with wrong signature"
-msgstr "spgist opfamily %s zawiera operator %s z błędnym podpisem"
+msgid "spgist operator family \"%s\" contains operator %s with wrong signature"
+msgstr "rodzina operatorów spgist \"%s\" zawiera operator %s z błędnym podpisem"
-#: access/spgist/spgvalidate.c:200
+#: access/spgist/spgvalidate.c:201
#, c-format
-msgid "spgist opfamily %s is missing operator(s) for types %s and %s"
-msgstr "spgist opfamily %s brakuje operator(ów) dla typów %s i %s"
+msgid "spgist operator family \"%s\" is missing operator(s) for types %s and %s"
+msgstr "rodzinie operatorów spgist \"%s\" brakuje operator(ów) dla typów %s i %s"
-#: access/spgist/spgvalidate.c:220
+#: access/spgist/spgvalidate.c:221
#, c-format
-msgid "spgist opfamily %s is missing support function %d for type %s"
-msgstr "spgist opfamily %s brakuje funkcji obsługi dla typów %d i %s"
+msgid "spgist operator family \"%s\" is missing support function %d for type %s"
+msgstr "rodzinie operatorów spgist \"%s\" brakuje funkcji obsługi %d dla typu %s"
-#: access/spgist/spgvalidate.c:233
+#: access/spgist/spgvalidate.c:234
#, c-format
-msgid "spgist opclass %s is missing operator(s)"
-msgstr "spgist opclass %s brakuje operator(ów)"
+msgid "spgist operator class \"%s\" is missing operator(s)"
+msgstr "klasie operatorów spgist \"%s\" brakuje operator(ów)"
#: access/tablesample/bernoulli.c:152 access/tablesample/system.c:156
#, c-format
@@ -1118,17 +1160,17 @@ msgstr "procent próbki musi być spomiędzy 0 a 100"
msgid "cannot retrieve commit timestamp for transaction %u"
msgstr "nie można uzyskać znacznika czasu zatwierdzenia transakcji %u"
-#: access/transam/commit_ts.c:385
+#: access/transam/commit_ts.c:393
#, c-format
msgid "could not get commit timestamp data"
msgstr "nie można uzyskać znacznika czasowego zatwierdzenia"
-#: access/transam/commit_ts.c:387
+#: access/transam/commit_ts.c:395
#, c-format
msgid "Make sure the configuration parameter \"%s\" is set on the master server."
msgstr "Należy sprawdzić, czy ustawiono parametr konfiguracyjny \"%s\" na serwerze głównym."
-#: access/transam/commit_ts.c:389 libpq/hba.c:1441
+#: access/transam/commit_ts.c:397
#, c-format
msgid "Make sure the configuration parameter \"%s\" is set."
msgstr "Należy sprawdzić, czy ustawiono parametr konfiguracyjny \"%s\"."
@@ -1153,7 +1195,7 @@ msgstr ""
msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u"
msgstr "baza danych nie przyjmuje poleceń generujących nowe MultiXactIds by uniknąć utraty nakładających się danych w bazie danych o OID %u"
-#: access/transam/multixact.c:1028 access/transam/multixact.c:2316
+#: access/transam/multixact.c:1028 access/transam/multixact.c:2318
#, c-format
msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used"
msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used"
@@ -1161,7 +1203,7 @@ msgstr[0] "baza danych \"%s\" musi być odkurzona zanim %u więcej MultiXactId b
msgstr[1] "baza danych \"%s\" musi być odkurzona zanim %u więcej MultiXactIdów będzie użyte"
msgstr[2] "baza danych \"%s\" musi być odkurzona zanim %u więcej MultiXactIdów będzie użytych"
-#: access/transam/multixact.c:1037 access/transam/multixact.c:2325
+#: access/transam/multixact.c:1037 access/transam/multixact.c:2327
#, c-format
msgid "database with OID %u must be vacuumed before %u more MultiXactId is used"
msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used"
@@ -1210,14 +1252,14 @@ msgstr "MultiXactId %u już nie istnieje -- pozorne zachodzenie na siebie"
msgid "MultiXactId %u has not been created yet -- apparent wraparound"
msgstr "MultiXactId %u nie został jeszcze utworzony -- pozorne zachodzenie na siebie"
-#: access/transam/multixact.c:2266
+#: access/transam/multixact.c:2268
#, c-format
msgid "MultiXactId wrap limit is %u, limited by database with OID %u"
msgstr "limit zawijania MultiXactId to %u, ograniczone przez bazę danych o OID %u"
-#: access/transam/multixact.c:2321 access/transam/multixact.c:2330
+#: access/transam/multixact.c:2323 access/transam/multixact.c:2332
#: access/transam/varsup.c:146 access/transam/varsup.c:153
-#: access/transam/varsup.c:384 access/transam/varsup.c:391
+#: access/transam/varsup.c:405 access/transam/varsup.c:412
#, c-format
msgid ""
"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
@@ -1226,115 +1268,113 @@ msgstr ""
"Aby uniknąć zamknięcia bazy danych, wykonaj VACUUM dla całej bazy danych w tej bazie.\n"
"Może być także konieczne zatwierdzenie lub wycofanie starych przygotowanych transakcji."
-#: access/transam/multixact.c:2600
+#: access/transam/multixact.c:2602
#, c-format
msgid "oldest MultiXactId member is at offset %u"
msgstr "najstarszy członek MultiXactId ma przesunięcie %u"
-#: access/transam/multixact.c:2604
+#: access/transam/multixact.c:2606
#, c-format
msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk"
msgstr "zabezpieczenia zawijania członków MultiXact są wyłączone ponieważ najstarszy MultiXact %u z punktem kontrolnym nie istnieje na dysku"
-#: access/transam/multixact.c:2626
+#: access/transam/multixact.c:2628
#, c-format
msgid "MultiXact member wraparound protections are now enabled"
msgstr "abezpieczenia zawijania członków MultiXact są teraz włączone"
-#: access/transam/multixact.c:2628
+#: access/transam/multixact.c:2631
#, c-format
msgid "MultiXact member stop limit is now %u based on MultiXact %u"
msgstr "ograniczenie zatrzymania członków MultiXact oparty na %u w MultiXact %u"
-#: access/transam/multixact.c:3008
+#: access/transam/multixact.c:3011
#, c-format
msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation"
msgstr "najstarszy MultiXact %u nie odnaleziony, najnowszy MultiXact %u, pominięcie obcięcia"
-#: access/transam/multixact.c:3026
+#: access/transam/multixact.c:3029
#, c-format
msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation"
msgstr "nie można obciąć do MultiXact %u ponieważ nie istnieje na dysku, pominięto obcięcie"
-#: access/transam/multixact.c:3352
+#: access/transam/multixact.c:3355
#, c-format
msgid "invalid MultiXactId: %u"
msgstr "nieprawidłowy MultiXactId: %u"
-#: access/transam/parallel.c:588
+#: access/transam/parallel.c:592
#, c-format
msgid "postmaster exited during a parallel transaction"
msgstr "postmaster zakończył działanie podczas równoległej operacji"
-#: access/transam/parallel.c:746
+#: access/transam/parallel.c:777
#, c-format
msgid "lost connection to parallel worker"
msgstr "brak połączenia z równoległym procesem roboczym"
-#: access/transam/parallel.c:931
+#: access/transam/parallel.c:836 access/transam/parallel.c:838
+msgid "parallel worker"
+msgstr "równoległy proces roboczy"
+
+#: access/transam/parallel.c:977
#, c-format
msgid "could not map dynamic shared memory segment"
msgstr "nie można zmapować dynamicznego segmentu pamięci współdzielonej"
-#: access/transam/parallel.c:936
+#: access/transam/parallel.c:982
#, c-format
msgid "invalid magic number in dynamic shared memory segment"
msgstr "niepoprawna magiczna liczba w dynamicznym segmencie pamięci współdzielonej"
-#: access/transam/parallel.c:1114
-#, c-format
-#| msgid "parallel worker, PID %d"
-msgid "parallel worker"
-msgstr "równoległy proces roboczy"
-
-#: access/transam/slru.c:665
+#: access/transam/slru.c:664
#, c-format
msgid "file \"%s\" doesn't exist, reading as zeroes"
msgstr "plik \"%s\" nie istnieje, odczyt jako zera"
-#: access/transam/slru.c:895 access/transam/slru.c:901
-#: access/transam/slru.c:908 access/transam/slru.c:915
-#: access/transam/slru.c:922 access/transam/slru.c:929
+#: access/transam/slru.c:903 access/transam/slru.c:909
+#: access/transam/slru.c:916 access/transam/slru.c:923
+#: access/transam/slru.c:930 access/transam/slru.c:937
#, c-format
msgid "could not access status of transaction %u"
msgstr "brak dostępu do statusu transakcji %u"
-#: access/transam/slru.c:896
+#: access/transam/slru.c:904
#, c-format
msgid "Could not open file \"%s\": %m."
msgstr "Nie można otworzyć pliku \"%s\": %m."
-#: access/transam/slru.c:902
+#: access/transam/slru.c:910
#, c-format
msgid "Could not seek in file \"%s\" to offset %u: %m."
msgstr "Nie można pozycjonować pliku \"%s\" od pozycji %u: %m."
-#: access/transam/slru.c:909
+#: access/transam/slru.c:917
#, c-format
msgid "Could not read from file \"%s\" at offset %u: %m."
msgstr "Nie można czytać z pliku \"%s\" od pozycji %u: %m."
-#: access/transam/slru.c:916
+#: access/transam/slru.c:924
#, c-format
msgid "Could not write to file \"%s\" at offset %u: %m."
msgstr "Nie można pisać do pliku \"%s\" od pozycji %u: %m."
-#: access/transam/slru.c:923
+#: access/transam/slru.c:931
#, c-format
msgid "Could not fsync file \"%s\": %m."
msgstr "Nie udało się fsync na pliku \"%s\": %m."
-#: access/transam/slru.c:930
+#: access/transam/slru.c:938
#, c-format
msgid "Could not close file \"%s\": %m."
msgstr "Nie można zamknąć pliku \"%s\": %m."
-#: access/transam/slru.c:1185
+#: access/transam/slru.c:1195
#, c-format
msgid "could not truncate directory \"%s\": apparent wraparound"
msgstr "nie można obciąć folderu \"%s\": pozorne zachodzenie na siebie"
-#: access/transam/slru.c:1240 access/transam/slru.c:1296
+#: access/transam/slru.c:1250 access/transam/slru.c:1306
#, c-format
msgid "removing file \"%s\""
msgstr "usuwanie pliku \"%s\""
@@ -1374,168 +1414,200 @@ msgstr "niepoprawne dane w pliku historii \"%s\""
msgid "Timeline IDs must be less than child timeline's ID."
msgstr "IDy linii czasu muszą być mniejsze niż ID potomnej linii czasu."
-#: access/transam/timeline.c:412 access/transam/timeline.c:488
-#: access/transam/xlog.c:3066 access/transam/xlog.c:3227
-#: access/transam/xlogfuncs.c:690 commands/copy.c:1671
-#: storage/file/copydir.c:201
+#: access/transam/timeline.c:418 access/transam/timeline.c:498
+#: access/transam/xlog.c:3257 access/transam/xlog.c:3424
+#: access/transam/xlogfuncs.c:692 commands/copy.c:1751
+#: storage/file/copydir.c:206
#, c-format
msgid "could not close file \"%s\": %m"
msgstr "nie można zamknąć pliku \"%s\": %m"
-#: access/transam/timeline.c:570
+#: access/transam/timeline.c:580
#, c-format
msgid "requested timeline %u is not in this server's history"
msgstr "żądanej linii czasu %u nie ma w historii tego serwera"
-#: access/transam/twophase.c:363
+#: access/transam/twophase.c:386
#, c-format
msgid "transaction identifier \"%s\" is too long"
msgstr "identyfikator transakcji \"%s\" jest zbyt długi"
-#: access/transam/twophase.c:370
+#: access/transam/twophase.c:393
#, c-format
msgid "prepared transactions are disabled"
msgstr "przygotowane transakcje są wyłączone"
-#: access/transam/twophase.c:371
+#: access/transam/twophase.c:394
#, c-format
msgid "Set max_prepared_transactions to a nonzero value."
msgstr "Ustawienie wartości niezerowej max_prepared_transactions."
-#: access/transam/twophase.c:390
+#: access/transam/twophase.c:413
#, c-format
msgid "transaction identifier \"%s\" is already in use"
msgstr "identyfikator transakcji \"%s\" jest już używany"
-#: access/transam/twophase.c:399
+#: access/transam/twophase.c:422 access/transam/twophase.c:2345
#, c-format
msgid "maximum number of prepared transactions reached"
msgstr "osiągnięto maksymalną liczbę przygotowanych transakcji"
-#: access/transam/twophase.c:400
+#: access/transam/twophase.c:423 access/transam/twophase.c:2346
#, c-format
msgid "Increase max_prepared_transactions (currently %d)."
msgstr "Zwiększenie max_prepared_transactions (obecnie %d)."
-#: access/transam/twophase.c:539
+#: access/transam/twophase.c:584
#, c-format
msgid "prepared transaction with identifier \"%s\" is busy"
msgstr "przygotowana transakcja o identyfikatorze \"%s\" jest zajęta"
-#: access/transam/twophase.c:545
+#: access/transam/twophase.c:590
#, c-format
msgid "permission denied to finish prepared transaction"
msgstr "brak dostępu do zakończenia przygotowanej transakcji"
-#: access/transam/twophase.c:546
+#: access/transam/twophase.c:591
#, c-format
msgid "Must be superuser or the user that prepared the transaction."
msgstr "Trzeba być superużytkownikiem lub użytkownikiem, który przygotował transakcję."
-#: access/transam/twophase.c:557
+#: access/transam/twophase.c:602
#, c-format
msgid "prepared transaction belongs to another database"
msgstr "przygotowana transakcja należy do innej bazy danych"
-#: access/transam/twophase.c:558
+#: access/transam/twophase.c:603
#, c-format
msgid "Connect to the database where the transaction was prepared to finish it."
msgstr "Połączenie do bazy danych gdzie była przygotowana transakcja by ją zakończyć."
-#: access/transam/twophase.c:573
+#: access/transam/twophase.c:618
#, c-format
msgid "prepared transaction with identifier \"%s\" does not exist"
msgstr "przygotowana transakcja z identyfikatorem \"%s\" nie istnieje"
-#: access/transam/twophase.c:1042
+#: access/transam/twophase.c:1087
#, c-format
msgid "two-phase state file maximum length exceeded"
msgstr "przekroczona maksymalna długość pliku stanu dwufazowego"
-#: access/transam/twophase.c:1160
+#: access/transam/twophase.c:1205
#, c-format
msgid "could not open two-phase state file \"%s\": %m"
msgstr "nie można otworzyć pliku stanu dwufazowego \"%s\": %m"
-#: access/transam/twophase.c:1177
+#: access/transam/twophase.c:1222
#, c-format
msgid "could not stat two-phase state file \"%s\": %m"
msgstr "nie można czytać pliku stanu dwufazowego \"%s\": %m"
-#: access/transam/twophase.c:1209
+#: access/transam/twophase.c:1256
#, c-format
msgid "could not read two-phase state file \"%s\": %m"
msgstr "nie można czytać pliku stanu dwufazowego \"%s\": %m"
-#: access/transam/twophase.c:1262 access/transam/xlog.c:6070
+#: access/transam/twophase.c:1308 access/transam/xlog.c:6352
#, c-format
-msgid "Failed while allocating an XLog reading processor."
-msgstr "Niepowodzenie podczas rezerwowania pamięci na procesor czytania XLog."
+#| msgid "Failed while allocating an XLog reading processor."
+msgid "Failed while allocating a WAL reading processor."
+msgstr "Niepowodzenie podczas rezerwowania procesora odczytu WAL."
-#: access/transam/twophase.c:1268
+#: access/transam/twophase.c:1314
#, c-format
-#| msgid "could not read two-phase state file \"%s\": %m"
-msgid "could not read two-phase state from xlog at %X/%X"
-msgstr "nie można czytać stanu dwufazowego z xlogu na %X/%X"
+#| msgid "could not read two-phase state from xlog at %X/%X"
+msgid "could not read two-phase state from WAL at %X/%X"
+msgstr "nie można czytać stanu dwufazowego z WAL na %X/%X"
-#: access/transam/twophase.c:1276
+#: access/transam/twophase.c:1322
#, c-format
-msgid "expected two-phase state data is not present in xlog at %X/%X"
-msgstr "oczekiwanych danych stanu dwufazowego nie ma w xlog na %X/%X"
+#| msgid "expected two-phase state data is not present in xlog at %X/%X"
+msgid "expected two-phase state data is not present in WAL at %X/%X"
+msgstr "oczekiwanych danych stanu dwufazowego nie ma w WAL na %X/%X"
-#: access/transam/twophase.c:1511
+#: access/transam/twophase.c:1557
#, c-format
msgid "could not remove two-phase state file \"%s\": %m"
msgstr "nie można usunąć pliku stanu dwufazowego \"%s\": %m"
-#: access/transam/twophase.c:1541
+#: access/transam/twophase.c:1587
#, c-format
msgid "could not recreate two-phase state file \"%s\": %m"
msgstr "nie można utworzyć ponownie pliku stanu dwufazowego \"%s\": %m"
-#: access/transam/twophase.c:1550 access/transam/twophase.c:1557
+#: access/transam/twophase.c:1598 access/transam/twophase.c:1606
#, c-format
msgid "could not write two-phase state file: %m"
msgstr "nie można pisać do pliku stanu dwufazowego: %m"
-#: access/transam/twophase.c:1569
+#: access/transam/twophase.c:1620
#, c-format
msgid "could not fsync two-phase state file: %m"
msgstr "nie można wykonać fsync na pliku stanu dwufazowego: %m"
-#: access/transam/twophase.c:1575
+#: access/transam/twophase.c:1627
#, c-format
msgid "could not close two-phase state file: %m"
msgstr "nie można zamknąć pliku stanu dwufazowego: %m"
-#: access/transam/twophase.c:1648
+#: access/transam/twophase.c:1712
#, c-format
-msgid "%u two-phase state files were written for long-running prepared transactions"
-msgstr ""
-"%u plików stanu dwufazowego zostały zapisane dla długo działających "
+#| msgid "%u two-phase state file was written for long-running prepared transactions"
+#| msgid_plural "%u two-phase state files were written for long-running prepared transactions"
+msgid "%u two-phase state file was written for a long-running prepared transaction"
+msgid_plural "%u two-phase state files were written for long-running prepared transactions"
+msgstr[0] ""
+"%u plik stanu dwufazowego został zapisany dla długo działającej "
+"przygotowanej transakcji"
+msgstr[1] ""
+"%u pliki stanu dwufazowego zostały zapisane dla długo działających "
+"przygotowanych transakcji"
+msgstr[2] ""
+"%u plików stanu dwufazowego zostało zapisanych dla długo działających "
"przygotowanych transakcji"
-#: access/transam/twophase.c:1709
+#: access/transam/twophase.c:1932
#, c-format
-msgid "removing future two-phase state file \"%s\""
-msgstr "usunięcie przyszłego pliku stanu dwufazowego \"%s\""
+#| msgid "recovering prepared transaction %u"
+msgid "recovering prepared transaction %u from shared memory"
+msgstr "odzyskiwanie przygotowanej transakcji %u z pamięci współdzielonej"
-#: access/transam/twophase.c:1725 access/transam/twophase.c:1736
-#: access/transam/twophase.c:1855 access/transam/twophase.c:1866
-#: access/transam/twophase.c:1940
+#: access/transam/twophase.c:2048
#, c-format
-msgid "removing corrupt two-phase state file \"%s\""
-msgstr "usunięcie uszkodzonego pliku stanu dwufazowego \"%s\""
+#| msgid "removing stale two-phase state file \"%s\""
+msgid "removing stale two-phase state file for \"%u\""
+msgstr "usunięcie nieaktualnego pliku stanu dwufazowego \"%u\""
-#: access/transam/twophase.c:1844 access/transam/twophase.c:1929
+#: access/transam/twophase.c:2055
#, c-format
-msgid "removing stale two-phase state file \"%s\""
-msgstr "usunięcie nieaktualnego pliku stanu dwufazowego \"%s\""
+#| msgid "removing stale two-phase state file \"%s\""
+msgid "removing stale two-phase state from shared memory for \"%u\""
+msgstr ""
+"usunięcie nieaktualnego stanu dwufazowego z pamięci współdzielonej dla \"%u\""
-#: access/transam/twophase.c:1947
+#: access/transam/twophase.c:2068
#, c-format
-msgid "recovering prepared transaction %u"
-msgstr "odzyskiwanie przygotowanej transakcji %u"
+#| msgid "removing future two-phase state file \"%s\""
+msgid "removing future two-phase state file for \"%u\""
+msgstr "usunięcie przyszłego pliku stanu dwufazowego \"%u\""
+
+#: access/transam/twophase.c:2075
+#, c-format
+#| msgid "removing future two-phase state file \"%s\""
+msgid "removing future two-phase state from memory for \"%u\""
+msgstr "usunięcie przyszłego stanu dwufazowego z pamięci dla \"%u\""
+
+#: access/transam/twophase.c:2089 access/transam/twophase.c:2108
+#, c-format
+#| msgid "removing corrupt two-phase state file \"%s\""
+msgid "removing corrupt two-phase state file for \"%u\""
+msgstr "usunięcie uszkodzonego pliku stanu dwufazowego dla \"%u\""
+
+#: access/transam/twophase.c:2115
+#, c-format
+#| msgid "removing corrupt two-phase state file \"%s\""
+msgid "removing corrupt two-phase state from memory for \"%u\""
+msgstr "usunięcie uszkodzonego stanu dwufazowego z pamięci dla \"%u\""
#: access/transam/varsup.c:124
#, c-format
@@ -1556,22 +1628,22 @@ msgstr ""
msgid "database is not accepting commands to avoid wraparound data loss in database with OID %u"
msgstr "baza danych nie przyjmuje poleceń by uniknąć utraty nakładających się danych w bazie danych o OID %u"
-#: access/transam/varsup.c:143 access/transam/varsup.c:381
+#: access/transam/varsup.c:143 access/transam/varsup.c:402
#, c-format
msgid "database \"%s\" must be vacuumed within %u transactions"
msgstr "baza danych \"%s\" musi być odkurzona w %u transakcjach"
-#: access/transam/varsup.c:150 access/transam/varsup.c:388
+#: access/transam/varsup.c:150 access/transam/varsup.c:409
#, c-format
msgid "database with OID %u must be vacuumed within %u transactions"
msgstr "baza danych o OID %u musi być odkurzona w %u transakcjach"
-#: access/transam/varsup.c:346
+#: access/transam/varsup.c:367
#, c-format
msgid "transaction ID wrap limit is %u, limited by database with OID %u"
msgstr "limit zawijania transakcji ID to %u, ograniczone przez bazę danych o OID %u"
-#: access/transam/xact.c:943
+#: access/transam/xact.c:946
#, c-format
msgid "cannot have more than 2^32-2 commands in a transaction"
msgstr "nie można zawrzeć więcej niż 2^32-2 poleceń w transakcji"
@@ -1581,1145 +1653,1157 @@ msgstr "nie można zawrzeć więcej niż 2^32-2 poleceń w transakcji"
msgid "maximum number of committed subtransactions (%d) exceeded"
msgstr "przekroczona maksymalna liczba zatwierdzonych podtransakcji (%d)"
-#: access/transam/xact.c:2267
+#: access/transam/xact.c:2268
#, c-format
msgid "cannot PREPARE a transaction that has operated on temporary tables"
msgstr "nie można wykonać PREPARE transakcji która przeprowadziła działania na tabelach tymczasowych"
-#: access/transam/xact.c:2277
+#: access/transam/xact.c:2278
#, c-format
msgid "cannot PREPARE a transaction that has exported snapshots"
msgstr "nie można wykonać PREPARE transakcji która wykonała eksport migawek"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3159
+#: access/transam/xact.c:3163
#, c-format
msgid "%s cannot run inside a transaction block"
msgstr "%s nie można wykonać wewnątrz bloku transakcji"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3169
+#: access/transam/xact.c:3173
#, c-format
msgid "%s cannot run inside a subtransaction"
msgstr "%s nie można wykonać wewnątrz podtransakcji"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3179
+#: access/transam/xact.c:3183
#, c-format
msgid "%s cannot be executed from a function or multi-command string"
msgstr "%s nie może być wykonane z funkcji ani ciągu wielopoleceniowego"
#. translator: %s represents an SQL statement name
-#: access/transam/xact.c:3250
+#: access/transam/xact.c:3254
#, c-format
msgid "%s can only be used in transaction blocks"
msgstr "%s może być użyty tylko w blokach transakcji"
-#: access/transam/xact.c:3434
+#: access/transam/xact.c:3438
#, c-format
msgid "there is already a transaction in progress"
msgstr "istnieje już aktywna transakcja"
-#: access/transam/xact.c:3602 access/transam/xact.c:3705
+#: access/transam/xact.c:3606 access/transam/xact.c:3709
#, c-format
msgid "there is no transaction in progress"
msgstr "brak aktywnej transakcji"
-#: access/transam/xact.c:3613
+#: access/transam/xact.c:3617
#, c-format
msgid "cannot commit during a parallel operation"
msgstr "nie można zatwierdzić transakcji podczas trwania operacji tównoległej"
-#: access/transam/xact.c:3716
+#: access/transam/xact.c:3720
#, c-format
msgid "cannot abort during a parallel operation"
msgstr "nie można przerwać podczas trwania operacji równoległej"
-#: access/transam/xact.c:3758
+#: access/transam/xact.c:3762
#, c-format
msgid "cannot define savepoints during a parallel operation"
msgstr "nie można definiować punktów zapisu w czasie trwania operacji równoległej"
-#: access/transam/xact.c:3825
+#: access/transam/xact.c:3829
#, c-format
msgid "cannot release savepoints during a parallel operation"
msgstr "nie można uwalniać punktów zapisu w czasie trwania operacji równoległej"
-#: access/transam/xact.c:3836 access/transam/xact.c:3888
-#: access/transam/xact.c:3894 access/transam/xact.c:3950
-#: access/transam/xact.c:4000 access/transam/xact.c:4006
+#: access/transam/xact.c:3840 access/transam/xact.c:3892
+#: access/transam/xact.c:3898 access/transam/xact.c:3954
+#: access/transam/xact.c:4004 access/transam/xact.c:4010
#, c-format
msgid "no such savepoint"
msgstr "nie ma takiego punktu zapisu"
-#: access/transam/xact.c:3938
+#: access/transam/xact.c:3942
#, c-format
msgid "cannot rollback to savepoints during a parallel operation"
msgstr "nie można wycofywać do punktu zapisu w czasie trwania operacji równoległej"
-#: access/transam/xact.c:4066
+#: access/transam/xact.c:4070
#, c-format
msgid "cannot start subtransactions during a parallel operation"
msgstr "nie można uruchomić podtransakcji w czasie wykonywania operacji równoległej"
-#: access/transam/xact.c:4133
+#: access/transam/xact.c:4137
#, c-format
msgid "cannot commit subtransactions during a parallel operation"
msgstr "nie można zatwierdzać podtransakcji w czasie wykonywania operacji równoległej"
-#: access/transam/xact.c:4741
+#: access/transam/xact.c:4745
#, c-format
msgid "cannot have more than 2^32-1 subtransactions in a transaction"
msgstr "nie można zawrzeć więcej niż 2^32-1 podtransakcji w transakcji"
-#: access/transam/xlog.c:2272
+#: access/transam/xlog.c:2456
#, c-format
msgid "could not seek in log file %s to offset %u: %m"
msgstr "nie można pozycjonować pliku dziennika %s od pozycji %u: %m"
-#: access/transam/xlog.c:2292
+#: access/transam/xlog.c:2478
#, c-format
msgid "could not write to log file %s at offset %u, length %zu: %m"
msgstr "nie można pisać do pliku dziennika %s do offsetu %u, długość %zu: %m"
-#: access/transam/xlog.c:2555
+#: access/transam/xlog.c:2742
#, c-format
msgid "updated min recovery point to %X/%X on timeline %u"
msgstr "zaktualizowano min punkt przywracania do %X/%X na osi czasu %u"
-#: access/transam/xlog.c:3197
+#: access/transam/xlog.c:3389
#, c-format
msgid "not enough data in file \"%s\""
msgstr "niewystarczająca ilość danych w pliku \"%s\""
-#: access/transam/xlog.c:3338
+#: access/transam/xlog.c:3535
#, c-format
msgid "could not open transaction log file \"%s\": %m"
msgstr "nie można otworzyć pliku dziennika transakcji \"%s\": %m"
-#: access/transam/xlog.c:3527 access/transam/xlog.c:5300
+#: access/transam/xlog.c:3724 access/transam/xlog.c:5537
#, c-format
msgid "could not close log file %s: %m"
msgstr "nie można zamknąć pliku dziennika %s: %m"
-#: access/transam/xlog.c:3584 access/transam/xlogutils.c:696
-#: replication/walsender.c:2099
+#: access/transam/xlog.c:3781 access/transam/xlogutils.c:701
+#: replication/walsender.c:2309
#, c-format
msgid "requested WAL segment %s has already been removed"
msgstr "żądany segment WAL %s został już usunięty"
-#: access/transam/xlog.c:3644 access/transam/xlog.c:3719
-#: access/transam/xlog.c:3917
+#: access/transam/xlog.c:3841 access/transam/xlog.c:3916
+#: access/transam/xlog.c:4111
#, c-format
msgid "could not open transaction log directory \"%s\": %m"
msgstr "nie można otworzyć katalogu dziennika transakcji \"%s\": %m"
-#: access/transam/xlog.c:3800
+#: access/transam/xlog.c:3997
#, c-format
msgid "recycled transaction log file \"%s\""
msgstr "odzyskano plik dziennika transakcji \"%s\""
-#: access/transam/xlog.c:3812
+#: access/transam/xlog.c:4009
#, c-format
msgid "removing transaction log file \"%s\""
msgstr "usuwanie pliku dziennika transakcji \"%s\""
-#: access/transam/xlog.c:3832
+#: access/transam/xlog.c:4029
#, c-format
msgid "could not rename old transaction log file \"%s\": %m"
msgstr "nie można zmienić nazwy starego pliku dziennika transakcji \"%s\": %m"
-#: access/transam/xlog.c:3844
-#, c-format
-msgid "could not remove old transaction log file \"%s\": %m"
-msgstr "nie można usunąć starego pliku dziennika transakcji \"%s\": %m"
-
-#: access/transam/xlog.c:3877 access/transam/xlog.c:3887
+#: access/transam/xlog.c:4071 access/transam/xlog.c:4081
#, c-format
msgid "required WAL directory \"%s\" does not exist"
msgstr "wymagany folder WAL \"%s\" nie istnieje"
-#: access/transam/xlog.c:3893
+#: access/transam/xlog.c:4087
#, c-format
msgid "creating missing WAL directory \"%s\""
msgstr "tworzenie brakującego folderu WAL \"%s\""
-#: access/transam/xlog.c:3896
+#: access/transam/xlog.c:4090
#, c-format
msgid "could not create missing directory \"%s\": %m"
msgstr "nie można utworzyć brakującego katalogu \"%s\": %m"
-#: access/transam/xlog.c:3927
+#: access/transam/xlog.c:4121
#, c-format
msgid "removing transaction log backup history file \"%s\""
msgstr "usunięcie pliku kopii zapasowej historii dziennika transakcji \"%s\""
-#: access/transam/xlog.c:4008
+#: access/transam/xlog.c:4202
#, c-format
msgid "unexpected timeline ID %u in log segment %s, offset %u"
msgstr "nieoczekiwany ID linii czasu %u w segmencie dziennika %s, offset %u"
-#: access/transam/xlog.c:4130
+#: access/transam/xlog.c:4324
#, c-format
msgid "new timeline %u is not a child of database system timeline %u"
msgstr "nowa linia czasu %u nie jest potomna dla linii czasu systemu bazy danych %u"
-#: access/transam/xlog.c:4144
+#: access/transam/xlog.c:4338
#, c-format
msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X"
msgstr "nowa linia czasu %u nie jest potomna dla linii czasu systemu bazy danych %u przed bieżącym punktem przywracania %X/%X"
-#: access/transam/xlog.c:4163
+#: access/transam/xlog.c:4357
#, c-format
msgid "new target timeline is %u"
msgstr "nowa docelowa linia czasu to %u"
-#: access/transam/xlog.c:4243
+#: access/transam/xlog.c:4432
#, c-format
msgid "could not create control file \"%s\": %m"
msgstr "nie można utworzyć pliku kontrolnego \"%s\": %m"
-#: access/transam/xlog.c:4254 access/transam/xlog.c:4490
+#: access/transam/xlog.c:4444 access/transam/xlog.c:4670
#, c-format
msgid "could not write to control file: %m"
msgstr "nie można pisać do pliku kontrolnego: %m"
-#: access/transam/xlog.c:4260 access/transam/xlog.c:4496
+#: access/transam/xlog.c:4452 access/transam/xlog.c:4678
#, c-format
msgid "could not fsync control file: %m"
msgstr "nie można wykonać fsync na pliku kontrolnym: %m"
-#: access/transam/xlog.c:4265 access/transam/xlog.c:4501
+#: access/transam/xlog.c:4458 access/transam/xlog.c:4684
#, c-format
msgid "could not close control file: %m"
msgstr "nie można zamknąć pliku kontrolnego: %m"
-#: access/transam/xlog.c:4283 access/transam/xlog.c:4479
+#: access/transam/xlog.c:4476 access/transam/xlog.c:4658
#, c-format
msgid "could not open control file \"%s\": %m"
msgstr "nie można otworzyć pliku kontrolnego \"%s\": %m"
-#: access/transam/xlog.c:4289
+#: access/transam/xlog.c:4483
#, c-format
msgid "could not read from control file: %m"
msgstr "nie można czytać z pliku kontrolnego: %m"
-#: access/transam/xlog.c:4302 access/transam/xlog.c:4311
-#: access/transam/xlog.c:4335 access/transam/xlog.c:4342
-#: access/transam/xlog.c:4349 access/transam/xlog.c:4354
-#: access/transam/xlog.c:4361 access/transam/xlog.c:4368
-#: access/transam/xlog.c:4375 access/transam/xlog.c:4382
-#: access/transam/xlog.c:4389 access/transam/xlog.c:4396
-#: access/transam/xlog.c:4403 access/transam/xlog.c:4412
-#: access/transam/xlog.c:4419 access/transam/xlog.c:4428
-#: access/transam/xlog.c:4435 access/transam/xlog.c:4444
-#: access/transam/xlog.c:4451 utils/init/miscinit.c:1380
+#: access/transam/xlog.c:4497 access/transam/xlog.c:4506
+#: access/transam/xlog.c:4530 access/transam/xlog.c:4537
+#: access/transam/xlog.c:4544 access/transam/xlog.c:4549
+#: access/transam/xlog.c:4556 access/transam/xlog.c:4563
+#: access/transam/xlog.c:4570 access/transam/xlog.c:4577
+#: access/transam/xlog.c:4584 access/transam/xlog.c:4591
+#: access/transam/xlog.c:4598 access/transam/xlog.c:4607
+#: access/transam/xlog.c:4614 access/transam/xlog.c:4623
+#: access/transam/xlog.c:4630 utils/init/miscinit.c:1397
#, c-format
msgid "database files are incompatible with server"
msgstr "pliki bazy danych są niezgodne z serwerem"
-#: access/transam/xlog.c:4303
+#: access/transam/xlog.c:4498
#, c-format
msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)."
msgstr "Klaster bazy danych został zainicjowany z PG_CONTROL_VERSION %d (0x%08x), ale serwer był skompilowany z PG_CONTROL_VERSION %d (0x%08x)."
-#: access/transam/xlog.c:4307
+#: access/transam/xlog.c:4502
#, c-format
msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb."
msgstr "Może to być problem niepoprawnego uporządkowania bajtów. Wydaje się jakby konieczne było initdb."
-#: access/transam/xlog.c:4312
+#: access/transam/xlog.c:4507
#, c-format
msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d."
msgstr "Klaster bazy danych został zainicjowany z PG_CONTROL_VERSION %d, ale serwer był skompilowany z PG_CONTROL_VERSION %d."
-#: access/transam/xlog.c:4315 access/transam/xlog.c:4339
-#: access/transam/xlog.c:4346 access/transam/xlog.c:4351
+#: access/transam/xlog.c:4510 access/transam/xlog.c:4534
+#: access/transam/xlog.c:4541 access/transam/xlog.c:4546
#, c-format
msgid "It looks like you need to initdb."
msgstr "Wydaje się jakby konieczne było initdb."
-#: access/transam/xlog.c:4326
+#: access/transam/xlog.c:4521
#, c-format
msgid "incorrect checksum in control file"
msgstr "niepoprawna suma kontrolna pliku kontrolnego"
-#: access/transam/xlog.c:4336
+#: access/transam/xlog.c:4531
#, c-format
msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d."
msgstr "Klaster bazy danych został zainicjowany z CATALOG_VERSION_NO %d, ale serwer był skompilowany z CATALOG_VERSION_NO %d."
-#: access/transam/xlog.c:4343
+#: access/transam/xlog.c:4538
#, c-format
msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d."
msgstr "Klaster bazy danych został zainicjowany z MAXALIGN %d, ale serwer był skompilowany z MAXALIGN %d."
-#: access/transam/xlog.c:4350
+#: access/transam/xlog.c:4545
#, c-format
msgid "The database cluster appears to use a different floating-point number format than the server executable."
msgstr "Klaster bazy danych wydaje się używać innego formatu liczb zmiennoprzecinkowych niż plik wykonywalny serwera."
-#: access/transam/xlog.c:4355
+#: access/transam/xlog.c:4550
#, c-format
msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d."
msgstr "Klaster bazy danych został zainicjowany z BLCKSZ %d, ale serwer był skompilowany z BLCKSZ %d."
-#: access/transam/xlog.c:4358 access/transam/xlog.c:4365
-#: access/transam/xlog.c:4372 access/transam/xlog.c:4379
-#: access/transam/xlog.c:4386 access/transam/xlog.c:4393
-#: access/transam/xlog.c:4400 access/transam/xlog.c:4407
-#: access/transam/xlog.c:4415 access/transam/xlog.c:4422
-#: access/transam/xlog.c:4431 access/transam/xlog.c:4438
-#: access/transam/xlog.c:4447 access/transam/xlog.c:4454
+#: access/transam/xlog.c:4553 access/transam/xlog.c:4560
+#: access/transam/xlog.c:4567 access/transam/xlog.c:4574
+#: access/transam/xlog.c:4581 access/transam/xlog.c:4588
+#: access/transam/xlog.c:4595 access/transam/xlog.c:4602
+#: access/transam/xlog.c:4610 access/transam/xlog.c:4617
+#: access/transam/xlog.c:4626 access/transam/xlog.c:4633
#, c-format
msgid "It looks like you need to recompile or initdb."
msgstr "Wydaje się jakby konieczna była rekompilacja lub initdb."
-#: access/transam/xlog.c:4362
+#: access/transam/xlog.c:4557
#, c-format
msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d."
msgstr "Klaster bazy danych został zainicjowany z RELSEG_SIZE %d, ale serwer był skompilowany z RELSEG_SIZE %d."
-#: access/transam/xlog.c:4369
+#: access/transam/xlog.c:4564
#, c-format
msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d."
msgstr "Klaster bazy danych został zainicjowany z XLOG_BLCKSZ %d, ale serwer był skompilowany z XLOG_BLCKSZ %d."
-#: access/transam/xlog.c:4376
+#: access/transam/xlog.c:4571
#, c-format
msgid "The database cluster was initialized with XLOG_SEG_SIZE %d, but the server was compiled with XLOG_SEG_SIZE %d."
msgstr "Klaster bazy danych został zainicjowany z XLOG_SEG_SIZE %d, ale serwer był skompilowany z XLOG_SEG_SIZE %d."
-#: access/transam/xlog.c:4383
+#: access/transam/xlog.c:4578
#, c-format
msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d."
msgstr "Klaster bazy danych został zainicjowany z NAMEDATALEN %d, ale serwer był skompilowany z NAMEDATALEN %d."
-#: access/transam/xlog.c:4390
+#: access/transam/xlog.c:4585
#, c-format
msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d."
msgstr "Klaster bazy danych został zainicjowany z INDEX_MAX_KEYS %d, ale serwer był skompilowany z INDEX_MAX_KEYS %d."
-#: access/transam/xlog.c:4397
+#: access/transam/xlog.c:4592
#, c-format
msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d."
msgstr "Klaster bazy danych został zainicjowany z TOAST_MAX_CHUNK_SIZE %d, ale serwer był skompilowany z TOAST_MAX_CHUNK_SIZE %d."
-#: access/transam/xlog.c:4404
+#: access/transam/xlog.c:4599
#, c-format
msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d."
msgstr "Klaster bazy danych został zainicjowany z LOBLKSIZE %d, ale serwer był skompilowany z LOBLKSIZE %d."
-#: access/transam/xlog.c:4413
-#, c-format
-msgid "The database cluster was initialized without HAVE_INT64_TIMESTAMP but the server was compiled with HAVE_INT64_TIMESTAMP."
-msgstr "Klaster bazy danych został zainicjowany bez HAVE_INT64_TIMESTAMP, ale serwer był skompilowany z HAVE_INT64_TIMESTAMP."
-
-#: access/transam/xlog.c:4420
-#, c-format
-msgid "The database cluster was initialized with HAVE_INT64_TIMESTAMP but the server was compiled without HAVE_INT64_TIMESTAMP."
-msgstr "Klaster bazy danych został zainicjowany z HAVE_INT64_TIMESTAMP, ale serwer był skompilowany bez HAVE_INT64_TIMESTAMP."
-
-#: access/transam/xlog.c:4429
+#: access/transam/xlog.c:4608
#, c-format
msgid "The database cluster was initialized without USE_FLOAT4_BYVAL but the server was compiled with USE_FLOAT4_BYVAL."
msgstr "Klaster bazy danych został zainicjowany bez USE_FLOAT4_BYVAL, ale serwer był skompilowany z USE_FLOAT4_BYVAL."
-#: access/transam/xlog.c:4436
+#: access/transam/xlog.c:4615
#, c-format
msgid "The database cluster was initialized with USE_FLOAT4_BYVAL but the server was compiled without USE_FLOAT4_BYVAL."
msgstr "Klaster bazy danych został zainicjowany z USE_FLOAT4_BYVAL, ale serwer był skompilowany bez USE_FLOAT4_BYVAL."
-#: access/transam/xlog.c:4445
+#: access/transam/xlog.c:4624
#, c-format
msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL."
msgstr "Klaster bazy danych został zainicjowany bez USE_FLOAT8_BYVAL, ale serwer był skompilowany z USE_FLOAT8_BYVAL."
-#: access/transam/xlog.c:4452
+#: access/transam/xlog.c:4631
#, c-format
msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL."
msgstr "Klaster bazy danych został zainicjowany z USE_FLOAT8_BYVAL, ale serwer był skompilowany bez USE_FLOAT8_BYVAL."
-#: access/transam/xlog.c:4875
+#: access/transam/xlog.c:4987
+#, c-format
+#| msgid "could not generate random encryption vector"
+msgid "could not generate secret authorization token"
+msgstr "nie można wygenerować tajemniczego tokenu autentykacji"
+
+#: access/transam/xlog.c:5077
#, c-format
msgid "could not write bootstrap transaction log file: %m"
msgstr "nie można pisać do pliku dziennika transakcji ładującej: %m"
-#: access/transam/xlog.c:4881
+#: access/transam/xlog.c:5085
#, c-format
msgid "could not fsync bootstrap transaction log file: %m"
msgstr "nie można wykonać fsync na pliku dziennika transakcji ładującej: %m"
-#: access/transam/xlog.c:4886
+#: access/transam/xlog.c:5091
#, c-format
msgid "could not close bootstrap transaction log file: %m"
msgstr "nie można zamknąć pliku dziennika transakcji ładującej: %m"
-#: access/transam/xlog.c:4961
+#: access/transam/xlog.c:5167
#, c-format
msgid "could not open recovery command file \"%s\": %m"
msgstr "nie można otworzyć pliku polecenia odtworzenia \"%s\": %m"
-#: access/transam/xlog.c:5007 access/transam/xlog.c:5090
+#: access/transam/xlog.c:5213 access/transam/xlog.c:5315
#, c-format
msgid "invalid value for recovery parameter \"%s\": \"%s\""
msgstr "nieprawidłowa wartość dla parametru odzyskiwania \"%s\": \"%s\""
-#: access/transam/xlog.c:5010
+#: access/transam/xlog.c:5216
#, c-format
msgid "Valid values are \"pause\", \"promote\", and \"shutdown\"."
msgstr "Poprawne wartości to \"pause\", \"promote\" i \"shutdown\"."
-#: access/transam/xlog.c:5029
+#: access/transam/xlog.c:5236
#, c-format
msgid "recovery_target_timeline is not a valid number: \"%s\""
msgstr "linia_czasu_celu_odzyskiwania nie jest poprawną liczbą: \"%s\""
-#: access/transam/xlog.c:5045
+#: access/transam/xlog.c:5253
#, c-format
msgid "recovery_target_xid is not a valid number: \"%s\""
msgstr "xid_celu_odzyskiwania nie jest poprawną liczbą: \"%s\""
-#: access/transam/xlog.c:5076
+#: access/transam/xlog.c:5284
#, c-format
msgid "recovery_target_name is too long (maximum %d characters)"
msgstr "nazwa_celu_odzyskiwania jest zbyt długa (maksymalnie %d znaki)"
-#: access/transam/xlog.c:5093
+#: access/transam/xlog.c:5318
#, c-format
msgid "The only allowed value is \"immediate\"."
msgstr "Jedyną dozwoloną wartością jest \"immediate\"."
-#: access/transam/xlog.c:5106 access/transam/xlog.c:5117
-#: commands/extension.c:533 commands/extension.c:541 utils/misc/guc.c:5638
+#: access/transam/xlog.c:5331 access/transam/xlog.c:5342
+#: commands/extension.c:546 commands/extension.c:554 utils/misc/guc.c:5741
#, c-format
msgid "parameter \"%s\" requires a Boolean value"
msgstr "parametr \"%s\" wymaga wartości Boolean"
-#: access/transam/xlog.c:5152
+#: access/transam/xlog.c:5377
#, c-format
msgid "parameter \"%s\" requires a temporal value"
msgstr "parametr \"%s\" wymaga wartości czasowej"
-#: access/transam/xlog.c:5154 catalog/dependency.c:991
-#: catalog/dependency.c:992 catalog/dependency.c:998 catalog/dependency.c:999
-#: catalog/dependency.c:1010 catalog/dependency.c:1011
-#: catalog/objectaddress.c:1100 commands/tablecmds.c:795
-#: commands/tablecmds.c:9445 commands/user.c:1045 commands/view.c:470
-#: libpq/auth.c:304 replication/syncrep.c:926 storage/lmgr/deadlock.c:1139
-#: storage/lmgr/proc.c:1276 utils/adt/acl.c:5281 utils/misc/guc.c:5660
-#: utils/misc/guc.c:5753 utils/misc/guc.c:9688 utils/misc/guc.c:9722
-#: utils/misc/guc.c:9756 utils/misc/guc.c:9790 utils/misc/guc.c:9825
+#: access/transam/xlog.c:5379 catalog/dependency.c:961
+#: catalog/dependency.c:962 catalog/dependency.c:968 catalog/dependency.c:969
+#: catalog/dependency.c:980 catalog/dependency.c:981 commands/tablecmds.c:954
+#: commands/tablecmds.c:10311 commands/user.c:1052 commands/view.c:505
+#: libpq/auth.c:328 replication/syncrep.c:1118 storage/lmgr/deadlock.c:1139
+#: storage/lmgr/proc.c:1313 utils/adt/acl.c:5248 utils/misc/guc.c:5763
+#: utils/misc/guc.c:5856 utils/misc/guc.c:9812 utils/misc/guc.c:9846
+#: utils/misc/guc.c:9880 utils/misc/guc.c:9914 utils/misc/guc.c:9949
#, c-format
msgid "%s"
msgstr "%s"
-#: access/transam/xlog.c:5160
+#: access/transam/xlog.c:5386
#, c-format
msgid "unrecognized recovery parameter \"%s\""
msgstr "nierozpoznany parametr odzyskiwania: \"%s\""
-#: access/transam/xlog.c:5171
+#: access/transam/xlog.c:5397
#, c-format
msgid "recovery command file \"%s\" specified neither primary_conninfo nor restore_command"
msgstr "plik poleceń odzyskiwania \"%s\" nie wskazuje ani na infopołącz_pierwotnego ani polecenie_odtworzenia"
-#: access/transam/xlog.c:5173
+#: access/transam/xlog.c:5399
#, c-format
-msgid "The database server will regularly poll the pg_xlog subdirectory to check for files placed there."
-msgstr "Serwer bazy danych będzie regularnie odpytywać podfolder pg_xlog by sprawdzić położone tu pliki."
+#| msgid "The database server will regularly poll the pg_xlog subdirectory to check for files placed there."
+msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there."
+msgstr ""
+"Serwer bazy danych będzie regularnie odpytywać podfolder pg_wal by sprawdzić "
+"położone tu pliki."
-#: access/transam/xlog.c:5179
+#: access/transam/xlog.c:5406
#, c-format
msgid "recovery command file \"%s\" must specify restore_command when standby mode is not enabled"
msgstr "plik polecenia odzyskiwania \"%s\" musi wskazywać polecenie_odtworzenia gdy nie jest włączony tryb gotowości"
-#: access/transam/xlog.c:5209
+#: access/transam/xlog.c:5427
+#, c-format
+msgid "standby mode is not supported by single-user servers"
+msgstr "tryb gotowości nie jest obsługiwany przez serwery pojedynczego użytkownika"
+
+#: access/transam/xlog.c:5446
#, c-format
msgid "recovery target timeline %u does not exist"
msgstr "linia czasowa celu odtworzenia %u nie istnieje"
-#: access/transam/xlog.c:5330
+#: access/transam/xlog.c:5567
#, c-format
msgid "archive recovery complete"
msgstr "wykonane odtworzenie archiwum"
-#: access/transam/xlog.c:5389 access/transam/xlog.c:5617
+#: access/transam/xlog.c:5626 access/transam/xlog.c:5892
#, c-format
msgid "recovery stopping after reaching consistency"
msgstr "zatrzymanie odzyskiwania po osiągnięciu spójności"
-#: access/transam/xlog.c:5477
+#: access/transam/xlog.c:5647
+#, c-format
+#| msgid "recovery stopping before abort of transaction %u, time %s"
+msgid "recovery stopping before WAL position (LSN) \"%X/%X\""
+msgstr "zatrzymanie odzyskiwania przed pozycją WAL (LSN) \"%X/%X\""
+
+#: access/transam/xlog.c:5733
#, c-format
msgid "recovery stopping before commit of transaction %u, time %s"
msgstr "zatrzymanie odzyskiwania przed zatwierdzeniem transakcji %u, czas %s"
-#: access/transam/xlog.c:5484
+#: access/transam/xlog.c:5740
#, c-format
msgid "recovery stopping before abort of transaction %u, time %s"
msgstr "zatrzymanie odzyskiwania przed przerwaniem transakcji %u, czas %s"
-#: access/transam/xlog.c:5529
+#: access/transam/xlog.c:5786
#, c-format
msgid "recovery stopping at restore point \"%s\", time %s"
msgstr "zatrzymanie odzyskiwania w punkcie przywrócenia \"%s\", czas %s"
-#: access/transam/xlog.c:5597
+#: access/transam/xlog.c:5804
+#, c-format
+#| msgid "recovery stopping after abort of transaction %u, time %s"
+msgid "recovery stopping after WAL position (LSN) \"%X/%X\""
+msgstr "zatrzymanie odzyskiwania po pozycji WAL (LSN) \"%X/%X\""
+
+#: access/transam/xlog.c:5872
#, c-format
msgid "recovery stopping after commit of transaction %u, time %s"
msgstr "zatrzymanie odzyskiwania po zatwierdzeniu transakcji %u, czas %s"
-#: access/transam/xlog.c:5605
+#: access/transam/xlog.c:5880
#, c-format
msgid "recovery stopping after abort of transaction %u, time %s"
msgstr "zatrzymanie odzyskiwania po przerwaniu transakcji %u, czas %s"
-#: access/transam/xlog.c:5644
+#: access/transam/xlog.c:5920
#, c-format
msgid "recovery has paused"
msgstr "odzyskiwanie zostało wstrzymane"
-#: access/transam/xlog.c:5645
+#: access/transam/xlog.c:5921
#, c-format
-msgid "Execute pg_xlog_replay_resume() to continue."
-msgstr "Wykonaj pg_xlog_replay_resume() by kontynuować."
+#| msgid "Execute pg_xlog_replay_resume() to continue."
+msgid "Execute pg_wal_replay_resume() to continue."
+msgstr "Wykonaj pg_wal_replay_resume() by kontynuować."
-#: access/transam/xlog.c:5852
+#: access/transam/xlog.c:6129
#, c-format
msgid "hot standby is not possible because %s = %d is a lower setting than on the master server (its value was %d)"
msgstr "rezerwa dynamiczna nie jest możliwa ponieważ %s = %d jest niższym ustawieniem niż na serwerze podstawowym (jego wartość była %d)"
-#: access/transam/xlog.c:5878
+#: access/transam/xlog.c:6155
#, c-format
msgid "WAL was generated with wal_level=minimal, data may be missing"
msgstr "WAL został utworzony z wal_level=minimal, może brakować danych"
-#: access/transam/xlog.c:5879
+#: access/transam/xlog.c:6156
#, c-format
msgid "This happens if you temporarily set wal_level=minimal without taking a new base backup."
msgstr "To zdarza się, jeśli ustawi się tymczasowo wal_level=minimal bez wykonania nowej kopii zapasowej bazy."
-#: access/transam/xlog.c:5890
+#: access/transam/xlog.c:6167
#, c-format
-#| msgid "hot standby is not possible because wal_level was not set to \"hot_standby\" or higher on the master server"
msgid "hot standby is not possible because wal_level was not set to \"replica\" or higher on the master server"
-msgstr ""
-"rezerwa dynamiczna nie jest możliwa ponieważ wal_level nie był ustawiony na "
-"\"replica\" lub wyżej na serwerze podstawowym"
+msgstr "rezerwa dynamiczna nie jest możliwa ponieważ wal_level nie był ustawiony na \"replica\" lub wyżej na serwerze podstawowym"
-#: access/transam/xlog.c:5891
+#: access/transam/xlog.c:6168
#, c-format
-#| msgid "Either set wal_level to \"hot_standby\" on the master, or turn off hot_standby here."
msgid "Either set wal_level to \"replica\" on the master, or turn off hot_standby here."
-msgstr ""
-"Albo ustaw wal_level na \"replica\" na podstawowym, albo wyłącz hot_standby "
-"tutaj."
+msgstr "Albo ustaw wal_level na \"replica\" na podstawowym, albo wyłącz hot_standby tutaj."
-#: access/transam/xlog.c:5948
+#: access/transam/xlog.c:6225
#, c-format
msgid "control file contains invalid data"
msgstr "plik kontrolny zawiera niepoprawne dane"
-#: access/transam/xlog.c:5954
+#: access/transam/xlog.c:6231
#, c-format
msgid "database system was shut down at %s"
msgstr "system bazy danych został zamknięty %s"
-#: access/transam/xlog.c:5959
+#: access/transam/xlog.c:6236
#, c-format
msgid "database system was shut down in recovery at %s"
msgstr "system bazy danych został zamknięty w odzysku %s"
-#: access/transam/xlog.c:5963
+#: access/transam/xlog.c:6240
#, c-format
msgid "database system shutdown was interrupted; last known up at %s"
msgstr "zamknięcie systemu bazy danych zostało przerwane; ostatnie znane podniesienie %s"
-#: access/transam/xlog.c:5967
+#: access/transam/xlog.c:6244
#, c-format
msgid "database system was interrupted while in recovery at %s"
msgstr "system bazy danych został przerwany podczas odzysku %s"
-#: access/transam/xlog.c:5969
+#: access/transam/xlog.c:6246
#, c-format
msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery."
msgstr "Oznacza to prawdopodobnie, że pewne dane zostały uszkodzone będzie konieczne użycie ostatniej kopii zapasowej do odzyskania."
-#: access/transam/xlog.c:5973
+#: access/transam/xlog.c:6250
#, c-format
msgid "database system was interrupted while in recovery at log time %s"
msgstr "system bazy danych został przerwany podczas odzysku - czas dziennika %s"
-#: access/transam/xlog.c:5975
+#: access/transam/xlog.c:6252
#, c-format
msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target."
msgstr "Jeśli zdarzyło się to więcej niż raz, pewne dane mogły zostać uszkodzone i należy wybrać wcześniejszy cel odzyskiwania."
-#: access/transam/xlog.c:5979
+#: access/transam/xlog.c:6256
#, c-format
msgid "database system was interrupted; last known up at %s"
msgstr "działanie systemu bazy danych zostało przerwane; ostatnie znane podniesienie %s"
-#: access/transam/xlog.c:6035
+#: access/transam/xlog.c:6312
#, c-format
msgid "entering standby mode"
msgstr "wejście w tryb gotowości"
-#: access/transam/xlog.c:6038
+#: access/transam/xlog.c:6315
#, c-format
msgid "starting point-in-time recovery to XID %u"
msgstr "chwila początkowa odzyskiwania do XID %u"
-#: access/transam/xlog.c:6042
+#: access/transam/xlog.c:6319
#, c-format
msgid "starting point-in-time recovery to %s"
msgstr "chwila początkowa odzyskiwania do %s"
-#: access/transam/xlog.c:6046
+#: access/transam/xlog.c:6323
#, c-format
msgid "starting point-in-time recovery to \"%s\""
msgstr "chwila początkowa odzyskiwania do \"%s\""
-#: access/transam/xlog.c:6050
+#: access/transam/xlog.c:6327
+#, c-format
+#| msgid "starting point-in-time recovery to \"%s\""
+msgid "starting point-in-time recovery to WAL position (LSN) \"%X/%X\""
+msgstr "chwila początkowa odzyskiwania do pozycji WAL (LSN) \"%X/%X\""
+
+#: access/transam/xlog.c:6332
#, c-format
msgid "starting point-in-time recovery to earliest consistent point"
msgstr "chwila początkowa odzyskiwania do najwcześniejszego punktu spójności"
-#: access/transam/xlog.c:6053
+#: access/transam/xlog.c:6335
#, c-format
msgid "starting archive recovery"
msgstr "rozpoczęto odzyskiwanie archiwum"
-#: access/transam/xlog.c:6097 access/transam/xlog.c:6225
+#: access/transam/xlog.c:6386 access/transam/xlog.c:6514
#, c-format
msgid "checkpoint record is at %X/%X"
msgstr "rekord punktu kontrolnego jest w %X/%X"
-#: access/transam/xlog.c:6111
+#: access/transam/xlog.c:6400
#, c-format
msgid "could not find redo location referenced by checkpoint record"
msgstr "nie można odnaleźć położenia ponowienia wskazywanego przez rekord punktu kontrolnego"
-#: access/transam/xlog.c:6112 access/transam/xlog.c:6119
+#: access/transam/xlog.c:6401 access/transam/xlog.c:6408
#, c-format
msgid "If you are not restoring from a backup, try removing the file \"%s/backup_label\"."
msgstr "Jeśli nie odtwarzasz z kopii zapasowej, spróbuj usunąć plik \"%s/backup_label\"."
-#: access/transam/xlog.c:6118
+#: access/transam/xlog.c:6407
#, c-format
msgid "could not locate required checkpoint record"
msgstr "nie można odnaleźć wymaganego rekordu punktu kontrolnego"
-#: access/transam/xlog.c:6144 commands/tablespace.c:641
+#: access/transam/xlog.c:6433 commands/tablespace.c:639
#, c-format
msgid "could not create symbolic link \"%s\": %m"
msgstr "nie można utworzyć linku symbolicznego \"%s\": %m"
-#: access/transam/xlog.c:6176 access/transam/xlog.c:6182
+#: access/transam/xlog.c:6465 access/transam/xlog.c:6471
#, c-format
msgid "ignoring file \"%s\" because no file \"%s\" exists"
msgstr "pominięcie piku \"%s\" ponieważ plik \"%s\" nie istnieje"
-#: access/transam/xlog.c:6178 access/transam/xlog.c:10918
+#: access/transam/xlog.c:6467 access/transam/xlog.c:11379
#, c-format
msgid "File \"%s\" was renamed to \"%s\"."
msgstr "Plik \"%s\" został przemianowany na \"%s\"."
-#: access/transam/xlog.c:6184
+#: access/transam/xlog.c:6473
#, c-format
msgid "Could not rename file \"%s\" to \"%s\": %m."
msgstr "Nie można zmienić nazwy pliku \"%s\" na \"%s\": %m."
-#: access/transam/xlog.c:6235 access/transam/xlog.c:6250
+#: access/transam/xlog.c:6524 access/transam/xlog.c:6539
#, c-format
msgid "could not locate a valid checkpoint record"
msgstr "nie można odnaleźć poprawnego rekordu punktu kontrolnego"
-#: access/transam/xlog.c:6244
+#: access/transam/xlog.c:6533
#, c-format
msgid "using previous checkpoint record at %X/%X"
msgstr "użycie poprzedniego rekordu punktu kontrolnego w %X/%X"
-#: access/transam/xlog.c:6288
+#: access/transam/xlog.c:6577
#, c-format
msgid "requested timeline %u is not a child of this server's history"
msgstr "żądana linia czasu %u nie jest potomna dla historii tego procesu"
-#: access/transam/xlog.c:6290
+#: access/transam/xlog.c:6579
#, c-format
msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X."
msgstr "Ostatni punkt kontrolny znajduje się na %X/%X osi czasu %u, ale w historii żądanej osi czasu serwer rozłączył się z tą osią na %X/%X."
-#: access/transam/xlog.c:6306
+#: access/transam/xlog.c:6595
#, c-format
msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u"
msgstr "żądana linia czasu %u nie zawiera minimalnego punktu przywrócenia %X/%X na osi czasu %u"
-#: access/transam/xlog.c:6337
+#: access/transam/xlog.c:6626
#, c-format
msgid "invalid next transaction ID"
msgstr "nieprawidłowy ID następnej transakcji"
-#: access/transam/xlog.c:6420
+#: access/transam/xlog.c:6720
#, c-format
msgid "invalid redo in checkpoint record"
msgstr "niepoprawne ponowienie w rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:6431
+#: access/transam/xlog.c:6731
#, c-format
msgid "invalid redo record in shutdown checkpoint"
msgstr "niepoprawny rekord ponowienia w punkcie kontrolnym zamknięcia"
-#: access/transam/xlog.c:6459
+#: access/transam/xlog.c:6759
#, c-format
msgid "database system was not properly shut down; automatic recovery in progress"
msgstr "system bazy danych nie został poprawnie zamknięty; trwa automatyczne odzyskiwanie"
-#: access/transam/xlog.c:6463
+#: access/transam/xlog.c:6763
#, c-format
msgid "crash recovery starts in timeline %u and has target timeline %u"
msgstr "odtwarzanie po awarii rozpoczęto na linii czasu %u i ma docelową linię czasu %u"
-#: access/transam/xlog.c:6507
+#: access/transam/xlog.c:6807
#, c-format
msgid "backup_label contains data inconsistent with control file"
msgstr "backup_label zawiera dane niespójne z plikiem sterującym"
-#: access/transam/xlog.c:6508
+#: access/transam/xlog.c:6808
#, c-format
msgid "This means that the backup is corrupted and you will have to use another backup for recovery."
msgstr "Oznacza to, że kopia zapasowa została uszkodzona i będzie konieczne użycie innej kopii zapasowej do odzyskania."
-#: access/transam/xlog.c:6582
+#: access/transam/xlog.c:6882
#, c-format
msgid "initializing for hot standby"
msgstr "inicjacja dla rezerwy dynamicznej"
-#: access/transam/xlog.c:6714
+#: access/transam/xlog.c:7014
#, c-format
msgid "redo starts at %X/%X"
msgstr "ponowienie uruchamia się w %X/%X"
-#: access/transam/xlog.c:6939
+#: access/transam/xlog.c:7248
#, c-format
msgid "requested recovery stop point is before consistent recovery point"
msgstr "żądany punkt zatrzymania odtworzenia znajduje się przed punktem spójnego odzyskania"
-#: access/transam/xlog.c:6977
+#: access/transam/xlog.c:7286
#, c-format
msgid "redo done at %X/%X"
msgstr "ponowienie wykonane w %X/%X"
-#: access/transam/xlog.c:6982 access/transam/xlog.c:8906
+#: access/transam/xlog.c:7291 access/transam/xlog.c:9294
#, c-format
msgid "last completed transaction was at log time %s"
msgstr "czas ostatniej zakończonej transakcji według dziennika %s"
-#: access/transam/xlog.c:6991
+#: access/transam/xlog.c:7300
#, c-format
msgid "redo is not required"
msgstr "ponowienie nie jest wymagane"
-#: access/transam/xlog.c:7066 access/transam/xlog.c:7070
+#: access/transam/xlog.c:7375 access/transam/xlog.c:7379
#, c-format
msgid "WAL ends before end of online backup"
msgstr "WAL kończy się prze końcem backupu online"
-#: access/transam/xlog.c:7067
+#: access/transam/xlog.c:7376
#, c-format
msgid "All WAL generated while online backup was taken must be available at recovery."
msgstr "Wszystkie WAL utworzone podczas wykonywania ostatniego backupu online muszą być dostępne w czasie odtworzenia."
-#: access/transam/xlog.c:7071
+#: access/transam/xlog.c:7380
#, c-format
msgid "Online backup started with pg_start_backup() must be ended with pg_stop_backup(), and all WAL up to that point must be available at recovery."
msgstr "Backup online uruchomiony z pg_start_backup() musi być zakończony pg_stop_backup(), a wszystkie WALL do tego miejsca muszą być dostępne podczas odzyskiwania."
-#: access/transam/xlog.c:7074
+#: access/transam/xlog.c:7383
#, c-format
msgid "WAL ends before consistent recovery point"
msgstr "WAL kończy się przed punktem spójnego odzyskiwania"
-#: access/transam/xlog.c:7101
+#: access/transam/xlog.c:7410
#, c-format
msgid "selected new timeline ID: %u"
msgstr "wybrany nowy ID linii czasowej: %u"
-#: access/transam/xlog.c:7512
+#: access/transam/xlog.c:7839
#, c-format
msgid "consistent recovery state reached at %X/%X"
msgstr "stan spójnego odzyskania osiągnięty w %X/%X"
-#: access/transam/xlog.c:7703
+#: access/transam/xlog.c:8031
#, c-format
msgid "invalid primary checkpoint link in control file"
msgstr "niepoprawny link podstawowego punktu kontrolnego w pliku kontrolnym"
-#: access/transam/xlog.c:7707
+#: access/transam/xlog.c:8035
#, c-format
msgid "invalid secondary checkpoint link in control file"
msgstr "niepoprawny link wtórnego punktu kontrolnego w pliku kontrolnym"
-#: access/transam/xlog.c:7711
+#: access/transam/xlog.c:8039
#, c-format
msgid "invalid checkpoint link in backup_label file"
msgstr "niepoprawny link punktu kontrolnego w pliku etykiety_backupu"
-#: access/transam/xlog.c:7728
+#: access/transam/xlog.c:8056
#, c-format
msgid "invalid primary checkpoint record"
msgstr "niepoprawny podstawowy rekord punktu kontrolnego"
-#: access/transam/xlog.c:7732
+#: access/transam/xlog.c:8060
#, c-format
msgid "invalid secondary checkpoint record"
msgstr "niepoprawny wtórny rekord punktu kontrolnego"
-#: access/transam/xlog.c:7736
+#: access/transam/xlog.c:8064
#, c-format
msgid "invalid checkpoint record"
msgstr "niepoprawny rekord punktu kontrolnego"
-#: access/transam/xlog.c:7747
+#: access/transam/xlog.c:8075
#, c-format
msgid "invalid resource manager ID in primary checkpoint record"
msgstr "niepoprawny ID menadżera zasobów w podstawowym rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:7751
+#: access/transam/xlog.c:8079
#, c-format
msgid "invalid resource manager ID in secondary checkpoint record"
msgstr "niepoprawny ID menadżera zasobów we wtórnym rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:7755
+#: access/transam/xlog.c:8083
#, c-format
msgid "invalid resource manager ID in checkpoint record"
msgstr "niepoprawny ID menadżera zasobów w rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:7767
+#: access/transam/xlog.c:8096
#, c-format
msgid "invalid xl_info in primary checkpoint record"
msgstr "niepoprawny xl_info w podstawowym rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:7771
+#: access/transam/xlog.c:8100
#, c-format
msgid "invalid xl_info in secondary checkpoint record"
msgstr "niepoprawny xl_info we wtórnym rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:7775
+#: access/transam/xlog.c:8104
#, c-format
msgid "invalid xl_info in checkpoint record"
msgstr "niepoprawny xl_info w rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:7786
+#: access/transam/xlog.c:8115
#, c-format
msgid "invalid length of primary checkpoint record"
msgstr "niepoprawna długość podstawowego rekordu punktu kontrolnego"
-#: access/transam/xlog.c:7790
+#: access/transam/xlog.c:8119
#, c-format
msgid "invalid length of secondary checkpoint record"
msgstr "niepoprawna długość wtórnego rekordu punktu kontrolnego"
-#: access/transam/xlog.c:7794
+#: access/transam/xlog.c:8123
#, c-format
msgid "invalid length of checkpoint record"
msgstr "niepoprawna długość rekordu punktu kontrolnego"
-#: access/transam/xlog.c:7962
+#: access/transam/xlog.c:8326
#, c-format
msgid "shutting down"
msgstr "zamykanie"
-#: access/transam/xlog.c:8475
+#: access/transam/xlog.c:8634
+#, c-format
+#| msgid "checkpoint request failed"
+msgid "checkpoint skipped due to an idle system"
+msgstr "punkt kontrolny pominięty ze względu na bezczynność systemu"
+
+#: access/transam/xlog.c:8839
#, c-format
msgid "concurrent transaction log activity while database system is shutting down"
msgstr "równoczesna aktywność dziennika transakcji podczas gdy system bazy danych jest zamykany"
-#: access/transam/xlog.c:8726
+#: access/transam/xlog.c:9093
#, c-format
msgid "skipping restartpoint, recovery has already ended"
msgstr "pominięcie punktu restartu, odzyskiwanie już się zakończyło"
-#: access/transam/xlog.c:8749
+#: access/transam/xlog.c:9116
#, c-format
msgid "skipping restartpoint, already performed at %X/%X"
msgstr "pominięcie punktu restartu, wykonano już w %X/%X"
-#: access/transam/xlog.c:8904
+#: access/transam/xlog.c:9292
#, c-format
msgid "recovery restart point at %X/%X"
msgstr "punkt restartu odzyskiwania w %X/%X"
-#: access/transam/xlog.c:9037
+#: access/transam/xlog.c:9428
#, c-format
msgid "restore point \"%s\" created at %X/%X"
msgstr "punkt przywrócenia \"%s\" utworzony w %X/%X"
-#: access/transam/xlog.c:9167
+#: access/transam/xlog.c:9558
#, c-format
msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record"
msgstr "nieoczekiwany ID poprzedniej linii czasu %u (obecny ID linii %u) w rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:9176
+#: access/transam/xlog.c:9567
#, c-format
msgid "unexpected timeline ID %u (after %u) in checkpoint record"
msgstr "nieoczekiwany ID linii czasu %u (po %u) w rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:9192
+#: access/transam/xlog.c:9583
#, c-format
msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u"
msgstr "nieoczekiwany ID linii czasu %u w rekordzie punktu kontrolnego, przed osiągnięciem minimalnego punktu przywrócenia %X/%X na linii czasu %u"
-#: access/transam/xlog.c:9263
+#: access/transam/xlog.c:9658
#, c-format
msgid "online backup was canceled, recovery cannot continue"
msgstr "zapis kopii roboczej online został anulowany, odzyskiwanie nie może być kontynuowane"
-#: access/transam/xlog.c:9319 access/transam/xlog.c:9366
-#: access/transam/xlog.c:9389
+#: access/transam/xlog.c:9714 access/transam/xlog.c:9761
+#: access/transam/xlog.c:9784
#, c-format
msgid "unexpected timeline ID %u (should be %u) in checkpoint record"
msgstr "nieoczekiwany ID linii czasu %u (powinien być %u) w rekordzie punktu kontrolnego"
-#: access/transam/xlog.c:9664
+#: access/transam/xlog.c:10060
#, c-format
msgid "could not fsync log segment %s: %m"
msgstr "nie można wykonać fsync na segmencie dziennika %s: %m"
-#: access/transam/xlog.c:9688
+#: access/transam/xlog.c:10085
#, c-format
msgid "could not fsync log file %s: %m"
msgstr "nie udało się fsync na pliku dziennika %s: %m"
-#: access/transam/xlog.c:9696
+#: access/transam/xlog.c:10093
#, c-format
msgid "could not fsync write-through log file %s: %m"
msgstr "nie można wykonać fsync write-through na pliku dziennika %s: %m"
-#: access/transam/xlog.c:9705
+#: access/transam/xlog.c:10102
#, c-format
msgid "could not fdatasync log file %s: %m"
msgstr "nie można wykonać fdatasync na pliku dziennika %s: %m"
-#: access/transam/xlog.c:9796 access/transam/xlog.c:10267
-#: access/transam/xlogfuncs.c:294 access/transam/xlogfuncs.c:321
-#: access/transam/xlogfuncs.c:360 access/transam/xlogfuncs.c:381
-#: access/transam/xlogfuncs.c:402
+#: access/transam/xlog.c:10193 access/transam/xlog.c:10710
+#: access/transam/xlogfuncs.c:296 access/transam/xlogfuncs.c:323
+#: access/transam/xlogfuncs.c:362 access/transam/xlogfuncs.c:383
+#: access/transam/xlogfuncs.c:404
#, c-format
msgid "WAL control functions cannot be executed during recovery."
msgstr "Funkcje kontroli WAL nie mogą być wykonywane w trakcie odzyskiwania."
-#: access/transam/xlog.c:9805 access/transam/xlog.c:10276
+#: access/transam/xlog.c:10202 access/transam/xlog.c:10719
#, c-format
msgid "WAL level not sufficient for making an online backup"
msgstr "poziom WAL niewystarczający do wykonania kopii zapasowej online"
-#: access/transam/xlog.c:9806 access/transam/xlog.c:10277
-#: access/transam/xlogfuncs.c:327
+#: access/transam/xlog.c:10203 access/transam/xlog.c:10720
+#: access/transam/xlogfuncs.c:329
#, c-format
-#| msgid "wal_level must be set to \"archive\", \"hot_standby\", or \"logical\" at server start."
msgid "wal_level must be set to \"replica\" or \"logical\" at server start."
-msgstr ""
-"wal_level musi być ustawiony na \"replica\" lub \"logical\" w czasie "
-"uruchomienia serwera."
+msgstr "wal_level musi być ustawiony na \"replica\" lub \"logical\" w czasie uruchomienia serwera."
-#: access/transam/xlog.c:9811
+#: access/transam/xlog.c:10208
#, c-format
msgid "backup label too long (max %d bytes)"
msgstr "za długa etykieta backupu (maks %d bajtów)"
-#: access/transam/xlog.c:9843 access/transam/xlog.c:10115
-#: access/transam/xlog.c:10153
+#: access/transam/xlog.c:10245 access/transam/xlog.c:10517
+#: access/transam/xlog.c:10555
#, c-format
msgid "a backup is already in progress"
msgstr "tworzenie kopii zapasowej jest już w toku"
-#: access/transam/xlog.c:9844
+#: access/transam/xlog.c:10246
#, c-format
msgid "Run pg_stop_backup() and try again."
msgstr "Uruchom pg_stop_backup() i spróbuj ponownie."
-#: access/transam/xlog.c:9939
+#: access/transam/xlog.c:10341
#, c-format
msgid "WAL generated with full_page_writes=off was replayed since last restartpoint"
msgstr "WAL wygenerowane z full_page_writes=off zostały ponownie odtworzone od ostatniego punktu restartu"
-#: access/transam/xlog.c:9941 access/transam/xlog.c:10440
+#: access/transam/xlog.c:10343 access/transam/xlog.c:10900
#, c-format
msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable full_page_writes and run CHECKPOINT on the master, and then try an online backup again."
msgstr "Oznacza to, że kopia zapasowa wykonana w czasie gotowości jest uszkodzony i nie powinna być używana. Włącz full_page_writes i uruchom CHECKPOINT na podstawowym, a następnie spróbuj wykonać ponownie backup online."
-#: access/transam/xlog.c:10008 replication/basebackup.c:1038
-#: utils/adt/misc.c:498
+#: access/transam/xlog.c:10410 replication/basebackup.c:1096
+#: utils/adt/misc.c:497
#, c-format
msgid "could not read symbolic link \"%s\": %m"
msgstr "nie można odczytać linku symbolicznego \"%s\": %m"
-#: access/transam/xlog.c:10015 replication/basebackup.c:1043
-#: utils/adt/misc.c:503
+#: access/transam/xlog.c:10417 replication/basebackup.c:1101
+#: utils/adt/misc.c:502
#, c-format
msgid "symbolic link \"%s\" target is too long"
msgstr "cel linku symbolicznego \"%s\" jest za długi"
-#: access/transam/xlog.c:10068 commands/tablespace.c:391
-#: commands/tablespace.c:553 replication/basebackup.c:1059
-#: utils/adt/misc.c:511
+#: access/transam/xlog.c:10470 commands/tablespace.c:389
+#: commands/tablespace.c:551 replication/basebackup.c:1116
+#: utils/adt/misc.c:510
#, c-format
msgid "tablespaces are not supported on this platform"
msgstr "przestrzenie tabel nie są obsługiwane na tej platformie"
-#: access/transam/xlog.c:10109 access/transam/xlog.c:10147
-#: access/transam/xlog.c:10326 access/transam/xlogarchive.c:106
-#: access/transam/xlogarchive.c:265 commands/copy.c:1778 commands/copy.c:2804
-#: commands/extension.c:3109 commands/tablespace.c:782
-#: commands/tablespace.c:873 guc-file.l:1003 replication/basebackup.c:407
-#: replication/basebackup.c:475 replication/logical/snapbuild.c:1493
-#: storage/file/copydir.c:72 storage/file/copydir.c:115 storage/file/fd.c:2826
-#: storage/file/fd.c:2918 utils/adt/dbsize.c:70 utils/adt/dbsize.c:220
-#: utils/adt/dbsize.c:300 utils/adt/genfile.c:114 utils/adt/genfile.c:333
+#: access/transam/xlog.c:10511 access/transam/xlog.c:10549
+#: access/transam/xlog.c:10758 access/transam/xlogarchive.c:105
+#: access/transam/xlogarchive.c:264 commands/copy.c:1872 commands/copy.c:3052
+#: commands/extension.c:3314 commands/tablespace.c:780
+#: commands/tablespace.c:871 guc-file.l:1001 replication/basebackup.c:480
+#: replication/basebackup.c:548 replication/logical/snapbuild.c:1509
+#: storage/file/copydir.c:72 storage/file/copydir.c:115 storage/file/fd.c:2954
+#: storage/file/fd.c:3046 utils/adt/dbsize.c:70 utils/adt/dbsize.c:227
+#: utils/adt/dbsize.c:307 utils/adt/genfile.c:115 utils/adt/genfile.c:334
#, c-format
msgid "could not stat file \"%s\": %m"
msgstr "nie można wykonać stat na pliku \"%s\": %m"
-#: access/transam/xlog.c:10116 access/transam/xlog.c:10154
+#: access/transam/xlog.c:10518 access/transam/xlog.c:10556
#, c-format
msgid "If you're sure there is no backup in progress, remove file \"%s\" and try again."
msgstr "Jeśli masz pewność, że nie jest wykonywany żaden backup, usuń plik \"%s\" i spróbuj raz jeszcze."
-#: access/transam/xlog.c:10133 access/transam/xlog.c:10171
-#: access/transam/xlog.c:10501
+#: access/transam/xlog.c:10535 access/transam/xlog.c:10573
+#: access/transam/xlog.c:10961 postmaster/syslogger.c:1391
+#: postmaster/syslogger.c:1404
#, c-format
msgid "could not write file \"%s\": %m"
msgstr "nie można pisać do pliku \"%s\": %m"
-#: access/transam/xlog.c:10290
+#: access/transam/xlog.c:10735
#, c-format
-#| msgid "a backup is not in progress"
msgid "exclusive backup not in progress"
msgstr "tworzenie wyłącznej kopii zapasowej nie jest w toku"
-#: access/transam/xlog.c:10330
+#: access/transam/xlog.c:10762
#, c-format
msgid "a backup is not in progress"
msgstr "tworzenie kopii zapasowej nie jest w toku"
-#: access/transam/xlog.c:10375 access/transam/xlog.c:10388
-#: access/transam/xlog.c:10728 access/transam/xlog.c:10734
-#: access/transam/xlog.c:10818 access/transam/xlogfuncs.c:695
+#: access/transam/xlog.c:10835 access/transam/xlog.c:10848
+#: access/transam/xlog.c:11189 access/transam/xlog.c:11195
+#: access/transam/xlog.c:11279 access/transam/xlogfuncs.c:697
#, c-format
msgid "invalid data in file \"%s\""
msgstr "nieprawidłowe dane w pliku \"%s\""
-#: access/transam/xlog.c:10392 replication/basebackup.c:936
+#: access/transam/xlog.c:10852 replication/basebackup.c:994
#, c-format
msgid "the standby was promoted during online backup"
msgstr "tryb gotowości został rozgłoszony podczas backupu online"
-#: access/transam/xlog.c:10393 replication/basebackup.c:937
+#: access/transam/xlog.c:10853 replication/basebackup.c:995
#, c-format
msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup."
msgstr "Oznacza to, że wykonywana właśnie kopia zapasowa jest uszkodzona i nie powinna być wykorzystana. Spróbuj wykonać kolejny backup online."
-#: access/transam/xlog.c:10438
+#: access/transam/xlog.c:10898
#, c-format
msgid "WAL generated with full_page_writes=off was replayed during online backup"
msgstr "WAL wygenerowane z full_page_writes=off zostały ponownie odtworzone podczas ostatniego punktu restartu"
-#: access/transam/xlog.c:10550
+#: access/transam/xlog.c:11011
#, c-format
msgid "pg_stop_backup cleanup done, waiting for required WAL segments to be archived"
msgstr "wykonano czyszczenie pg_stop_backup, oczekiwanie na wymagane segmenty WAL do zarchiwizowania"
-#: access/transam/xlog.c:10560
+#: access/transam/xlog.c:11021
#, c-format
msgid "pg_stop_backup still waiting for all required WAL segments to be archived (%d seconds elapsed)"
msgstr "pg_stop_backup, wciąż trwa oczekiwanie na wszystkie wymagane segmenty WAL do zarchiwizowania (upłynęło %d sekund)"
-#: access/transam/xlog.c:10562
+#: access/transam/xlog.c:11023
#, c-format
msgid "Check that your archive_command is executing properly. pg_stop_backup can be canceled safely, but the database backup will not be usable without all the WAL segments."
msgstr "Sprawdź, że archive_command jest poprawnie wykonywane. pg_stop_backup może być bezpiecznie anulowane, ale backup bazy danych nie będzie zdatny do użytku bez wszystkich segmentów WAL."
-#: access/transam/xlog.c:10569
+#: access/transam/xlog.c:11030
#, c-format
msgid "pg_stop_backup complete, all required WAL segments have been archived"
msgstr "pg_stop_backup kompletny, zarchiwizowano wszystkie wymagane segmenty WAL"
-#: access/transam/xlog.c:10573
+#: access/transam/xlog.c:11034
#, c-format
msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup"
msgstr "archiwizacja WAL nie jest włączona; musisz upewnić się, że wszystkie segmenty WAL zostały skopiowane innymi środkami by w całości zakończyć backup"
-#. translator: %s is an XLog record description
-#: access/transam/xlog.c:10858
+#. translator: %s is a WAL record description
+#: access/transam/xlog.c:11319
#, c-format
-#| msgid "xlog redo %s"
-msgid "xlog redo at %X/%X for %s"
-msgstr "ponowienie xlog na %X/%X dla %s"
+#| msgid "xlog redo at %X/%X for %s"
+msgid "WAL redo at %X/%X for %s"
+msgstr "ponowienie WAL na %X/%X dla %s"
-#: access/transam/xlog.c:10907
+#: access/transam/xlog.c:11368
#, c-format
msgid "online backup mode was not canceled"
msgstr "tryb wykonania kopii zapasowej online nie został anulowany"
-#: access/transam/xlog.c:10908
+#: access/transam/xlog.c:11369
#, c-format
msgid "File \"%s\" could not be renamed to \"%s\": %m."
msgstr "Nie można zmienić nazwy pliku \"%s\" na \"%s\": %m."
-#: access/transam/xlog.c:10917 access/transam/xlog.c:10929
-#: access/transam/xlog.c:10939
+#: access/transam/xlog.c:11378 access/transam/xlog.c:11390
+#: access/transam/xlog.c:11400
#, c-format
msgid "online backup mode canceled"
msgstr "tryb wykonania kopii zapasowej online anulowany"
-#: access/transam/xlog.c:10930
+#: access/transam/xlog.c:11391
#, c-format
msgid "Files \"%s\" and \"%s\" were renamed to \"%s\" and \"%s\", respectively."
msgstr "Pliki \"%s\" i \"%s\" zostały przemianowane odpowiednio na \"%s\" and \"%s\"."
-#: access/transam/xlog.c:10940
+#: access/transam/xlog.c:11401
#, c-format
msgid "File \"%s\" was renamed to \"%s\", but file \"%s\" could not be renamed to \"%s\": %m."
msgstr "Plik \"%s\" zmienił nazwę na \"%s\", jednak plik \"%s\" nie mógł zostać przemianowany na \"%s\": %m."
-#: access/transam/xlog.c:11062 access/transam/xlogutils.c:718
-#: replication/walreceiver.c:994 replication/walsender.c:2116
+#: access/transam/xlog.c:11523 access/transam/xlogutils.c:724
+#: replication/walreceiver.c:1006 replication/walsender.c:2326
#, c-format
msgid "could not seek in log segment %s to offset %u: %m"
msgstr "nie można pozycjonować w segmentu dziennika %s do offsetu %u: %m"
-#: access/transam/xlog.c:11074
+#: access/transam/xlog.c:11537
#, c-format
msgid "could not read from log segment %s, offset %u: %m"
msgstr "nie można czytać z segmentu logów %s, offset %u: %m"
-#: access/transam/xlog.c:11548
+#: access/transam/xlog.c:12026
#, c-format
msgid "received promote request"
msgstr "otrzymano żądanie rozgłoszenia"
-#: access/transam/xlog.c:11561
+#: access/transam/xlog.c:12039
#, c-format
msgid "trigger file found: %s"
msgstr "odnaleziono plik wyzwalacza: %s"
-#: access/transam/xlog.c:11570
+#: access/transam/xlog.c:12048
#, c-format
msgid "could not stat trigger file \"%s\": %m"
msgstr "nie można wykonać stat na pliku wyzwalacza \"%s\": %m"
-#: access/transam/xlogarchive.c:244
+#: access/transam/xlogarchive.c:243
#, c-format
msgid "archive file \"%s\" has wrong size: %lu instead of %lu"
msgstr "plik archiwum \"%s\" ma niepoprawny rozmiar: %lu zamiast %lu"
-#: access/transam/xlogarchive.c:253
+#: access/transam/xlogarchive.c:252
#, c-format
msgid "restored log file \"%s\" from archive"
msgstr "odtworzono plik dziennika \"%s\" z archiwum"
-#: access/transam/xlogarchive.c:303
+#: access/transam/xlogarchive.c:302
#, c-format
msgid "could not restore file \"%s\" from archive: %s"
msgstr "nie można przywrócić pliku \"%s\" z archiwum: %s"
@@ -2727,129 +2811,129 @@ msgstr "nie można przywrócić pliku \"%s\" z archiwum: %s"
#. translator: First %s represents a recovery.conf parameter name like
#. "recovery_end_command", the 2nd is the value of that parameter, the
#. third an already translated error message.
-#: access/transam/xlogarchive.c:415
+#: access/transam/xlogarchive.c:414
#, c-format
msgid "%s \"%s\": %s"
msgstr "%s \"%s\": %s"
-#: access/transam/xlogarchive.c:458 replication/logical/snapbuild.c:1621
-#: replication/slot.c:470 replication/slot.c:982 replication/slot.c:1090
-#: storage/file/fd.c:635 storage/file/fd.c:693 utils/time/snapmgr.c:1206
+#: access/transam/xlogarchive.c:457 postmaster/syslogger.c:1415
+#: replication/logical/snapbuild.c:1641 replication/slot.c:518
+#: replication/slot.c:1114 replication/slot.c:1228 storage/file/fd.c:642
+#: storage/file/fd.c:737 utils/time/snapmgr.c:1307
#, c-format
msgid "could not rename file \"%s\" to \"%s\": %m"
msgstr "nie można zmienić nazwy pliku \"%s\" na \"%s\": %m"
-#: access/transam/xlogarchive.c:525 access/transam/xlogarchive.c:589
+#: access/transam/xlogarchive.c:524 access/transam/xlogarchive.c:588
#, c-format
msgid "could not create archive status file \"%s\": %m"
msgstr "nie można utworzyć pliku stanu archiwum \"%s\": %m"
-#: access/transam/xlogarchive.c:533 access/transam/xlogarchive.c:597
+#: access/transam/xlogarchive.c:532 access/transam/xlogarchive.c:596
#, c-format
msgid "could not write archive status file \"%s\": %m"
msgstr "nie można zapisać pliku stanu archiwum \"%s\": %m"
-#: access/transam/xlogfuncs.c:58
+#: access/transam/xlogfuncs.c:55
#, c-format
msgid "aborting backup due to backend exiting before pg_stop_backup was called"
-msgstr ""
-"przerwanie tworzenia kopii zapasowej ze względu na wyjście backendu przed "
-"wywołaniem pg_stop_backu"
+msgstr "przerwanie tworzenia kopii zapasowej ze względu na wyjście backendu przed wywołaniem pg_stop_backu"
-#: access/transam/xlogfuncs.c:88
+#: access/transam/xlogfuncs.c:86
#, c-format
-#| msgid "a backup is already in progress"
msgid "a backup is already in progress in this session"
msgstr "tworzenie kopii zapasowej jest już w toku w tej sesji"
-#: access/transam/xlogfuncs.c:94 commands/tablespace.c:705
-#: commands/tablespace.c:715 postmaster/postmaster.c:1398
-#: replication/basebackup.c:295 replication/basebackup.c:635
-#: storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2292
-#: storage/file/fd.c:2891 storage/ipc/dsm.c:300 utils/adt/genfile.c:439
-#: utils/adt/misc.c:411 utils/misc/tzparser.c:339
+#: access/transam/xlogfuncs.c:92 commands/tablespace.c:703
+#: commands/tablespace.c:713 postmaster/postmaster.c:1434
+#: replication/basebackup.c:368 replication/basebackup.c:708
+#: storage/file/copydir.c:53 storage/file/copydir.c:96 storage/file/fd.c:2420
+#: storage/file/fd.c:3019 storage/ipc/dsm.c:301 utils/adt/genfile.c:440
+#: utils/adt/misc.c:410 utils/misc/tzparser.c:339
#, c-format
msgid "could not open directory \"%s\": %m"
msgstr "nie można otworzyć folderu \"%s\": %m"
-#: access/transam/xlogfuncs.c:155 access/transam/xlogfuncs.c:229
+#: access/transam/xlogfuncs.c:152 access/transam/xlogfuncs.c:233
#, c-format
-#| msgid "a backup is not in progress"
msgid "non-exclusive backup in progress"
msgstr "tworzenie niewyłącznej kopii zapasowej jest w toku"
-#: access/transam/xlogfuncs.c:156 access/transam/xlogfuncs.c:230
+#: access/transam/xlogfuncs.c:153 access/transam/xlogfuncs.c:234
#, c-format
msgid "Did you mean to use pg_stop_backup('f')?"
msgstr "Czy chodziło o wykonanie pg_stop_backup('f')?"
-#: access/transam/xlogfuncs.c:200 commands/event_trigger.c:1449
-#: commands/event_trigger.c:2000 commands/extension.c:1728
-#: commands/extension.c:1837 commands/extension.c:2030 commands/prepare.c:702
-#: executor/execQual.c:1757 executor/execQual.c:1782 executor/execQual.c:2157
-#: executor/execQual.c:5391 executor/functions.c:1024 foreign/foreign.c:580
-#: replication/logical/logicalfuncs.c:175 replication/logical/origin.c:1391
-#: replication/slotfuncs.c:189 replication/walsender.c:2765
-#: utils/adt/jsonfuncs.c:1483 utils/adt/jsonfuncs.c:1615
-#: utils/adt/jsonfuncs.c:1805 utils/adt/jsonfuncs.c:1934
-#: utils/adt/jsonfuncs.c:2702 utils/adt/pgstatfuncs.c:554
-#: utils/adt/pgstatfuncs.c:655 utils/fmgr/funcapi.c:61 utils/misc/guc.c:8426
-#: utils/mmgr/portalmem.c:1064
+#: access/transam/xlogfuncs.c:204 commands/event_trigger.c:1453
+#: commands/event_trigger.c:2004 commands/extension.c:1891
+#: commands/extension.c:2000 commands/extension.c:2224 commands/prepare.c:721
+#: executor/execExpr.c:2106 executor/execSRF.c:686 executor/functions.c:1028
+#: foreign/foreign.c:488 libpq/hba.c:2560 replication/logical/launcher.c:762
+#: replication/logical/logicalfuncs.c:176 replication/logical/origin.c:1384
+#: replication/slotfuncs.c:196 replication/walsender.c:3019
+#: utils/adt/jsonfuncs.c:1686 utils/adt/jsonfuncs.c:1816
+#: utils/adt/jsonfuncs.c:2004 utils/adt/jsonfuncs.c:2131
+#: utils/adt/jsonfuncs.c:3468 utils/adt/pgstatfuncs.c:456
+#: utils/adt/pgstatfuncs.c:557 utils/fmgr/funcapi.c:62 utils/misc/guc.c:8540
+#: utils/mmgr/portalmem.c:1053
#, c-format
msgid "set-valued function called in context that cannot accept a set"
msgstr "funkcja zwracająca zbiór rekordów wywołana w kontekście, w którym nie jest to dopuszczalne"
-#: access/transam/xlogfuncs.c:204 commands/event_trigger.c:1453
-#: commands/event_trigger.c:2004 commands/extension.c:1732
-#: commands/extension.c:1841 commands/extension.c:2034 commands/prepare.c:706
-#: foreign/foreign.c:585 replication/logical/logicalfuncs.c:179
-#: replication/logical/origin.c:1395 replication/slotfuncs.c:193
-#: replication/walsender.c:2769 utils/adt/pgstatfuncs.c:558
-#: utils/adt/pgstatfuncs.c:659 utils/misc/guc.c:8430 utils/misc/pg_config.c:44
-#: utils/mmgr/portalmem.c:1068
+#: access/transam/xlogfuncs.c:208 commands/event_trigger.c:1457
+#: commands/event_trigger.c:2008 commands/extension.c:1895
+#: commands/extension.c:2004 commands/extension.c:2228 commands/prepare.c:725
+#: foreign/foreign.c:493 libpq/hba.c:2564 replication/logical/launcher.c:766
+#: replication/logical/logicalfuncs.c:180 replication/logical/origin.c:1388
+#: replication/slotfuncs.c:200 replication/walsender.c:3023
+#: utils/adt/pgstatfuncs.c:460 utils/adt/pgstatfuncs.c:561
+#: utils/misc/guc.c:8544 utils/misc/pg_config.c:44 utils/mmgr/portalmem.c:1057
#, c-format
msgid "materialize mode required, but it is not allowed in this context"
msgstr "wymagany jest tryb materializacji, jednak nie jest on dopuszczalny w tym kontekście"
-#: access/transam/xlogfuncs.c:247
+#: access/transam/xlogfuncs.c:250
#, c-format
-#| msgid "a backup is not in progress"
msgid "non-exclusive backup is not in progress"
msgstr "tworzenie niewyłącznej kopii zapasowej nie jest w toku"
-#: access/transam/xlogfuncs.c:248
+#: access/transam/xlogfuncs.c:251
#, c-format
msgid "Did you mean to use pg_stop_backup('t')?"
msgstr "Czy chodziło o wykonanie pg_stop_backup('t')?"
-#: access/transam/xlogfuncs.c:326
+#: access/transam/xlogfuncs.c:328
#, c-format
msgid "WAL level not sufficient for creating a restore point"
msgstr "poziom WAL niewystarczający do utworzenia punktu przywrócenia"
-#: access/transam/xlogfuncs.c:334
+#: access/transam/xlogfuncs.c:336
#, c-format
msgid "value too long for restore point (maximum %d characters)"
msgstr "wartość zbyt długa punktu przywrócenia (maksimum %d znaków)"
-#: access/transam/xlogfuncs.c:472
+#: access/transam/xlogfuncs.c:474
#, c-format
-msgid "pg_xlogfile_name_offset() cannot be executed during recovery."
-msgstr "pg_xlogfile_name_offset() nie może być uruchomiony podczas trwania odzyskiwania."
+#| msgid "pg_xlogfile_name_offset() cannot be executed during recovery."
+msgid "pg_walfile_name_offset() cannot be executed during recovery."
+msgstr ""
+"pg_walfile_name_offset() nie może być uruchomiony podczas trwania "
+"odzyskiwania."
-#: access/transam/xlogfuncs.c:528
+#: access/transam/xlogfuncs.c:530
#, c-format
-msgid "pg_xlogfile_name() cannot be executed during recovery."
-msgstr "pg_xlogfile_name() nie może być uruchomiony podczas trwania."
+#| msgid "pg_xlogfile_name() cannot be executed during recovery."
+msgid "pg_walfile_name() cannot be executed during recovery."
+msgstr "pg_walfile_name() nie może być uruchomiony podczas trwania."
-#: access/transam/xlogfuncs.c:548 access/transam/xlogfuncs.c:568
-#: access/transam/xlogfuncs.c:585
+#: access/transam/xlogfuncs.c:550 access/transam/xlogfuncs.c:570
+#: access/transam/xlogfuncs.c:587
#, c-format
msgid "recovery is not in progress"
msgstr "odzyskiwanie nie jest w toku"
-#: access/transam/xlogfuncs.c:549 access/transam/xlogfuncs.c:569
-#: access/transam/xlogfuncs.c:586
+#: access/transam/xlogfuncs.c:551 access/transam/xlogfuncs.c:571
+#: access/transam/xlogfuncs.c:588
#, c-format
msgid "Recovery control functions can only be executed during recovery."
msgstr "Funkcje kontroli odzyskiwania mogą być wykonywane tylko w trakcie odzyskiwania."
@@ -2864,7 +2948,7 @@ msgstr "niepoprawne przesunięcie rekordu w %X/%X"
msgid "contrecord is requested by %X/%X"
msgstr "wymagany kontrekord w %X/%X"
-#: access/transam/xlogreader.c:325 access/transam/xlogreader.c:624
+#: access/transam/xlogreader.c:325 access/transam/xlogreader.c:625
#, c-format
msgid "invalid record length at %X/%X: wanted %u, got %u"
msgstr "niepoprawna długość rekordu w %X/%X: oczekiwana %u, jest %u"
@@ -2884,706 +2968,778 @@ msgstr "brak flagi kontrekordu na %X/%X"
msgid "invalid contrecord length %u at %X/%X"
msgstr "niepoprawna długość kontrekordu %u na %X/%X"
-#: access/transam/xlogreader.c:632
+#: access/transam/xlogreader.c:633
#, c-format
msgid "invalid resource manager ID %u at %X/%X"
msgstr "niepoprawny ID menażera zasobów %u w %X/%X"
-#: access/transam/xlogreader.c:646 access/transam/xlogreader.c:663
+#: access/transam/xlogreader.c:647 access/transam/xlogreader.c:664
#, c-format
msgid "record with incorrect prev-link %X/%X at %X/%X"
msgstr "rekord z niepoprawnym poprz-linkiem %X/%X w %X/%X"
-#: access/transam/xlogreader.c:700
+#: access/transam/xlogreader.c:701
#, c-format
msgid "incorrect resource manager data checksum in record at %X/%X"
msgstr "niepoprawna suma kontrolna danych menadżera zasobów w rekordzie w %X/%X"
-#: access/transam/xlogreader.c:733
+#: access/transam/xlogreader.c:734
#, c-format
msgid "invalid magic number %04X in log segment %s, offset %u"
msgstr "niepoprawny magiczny numer %04X w segmencie dziennika %s, przesunięcie %u"
-#: access/transam/xlogreader.c:747 access/transam/xlogreader.c:798
+#: access/transam/xlogreader.c:748 access/transam/xlogreader.c:799
#, c-format
msgid "invalid info bits %04X in log segment %s, offset %u"
msgstr "niepoprawny bity informacji %04X w segmencie dziennika %s, przesunięcie %u"
-#: access/transam/xlogreader.c:773
+#: access/transam/xlogreader.c:774
#, c-format
msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s"
msgstr "plik WAL pochodzi z innego systemu bazy danych: identyfikator systemu bazy danych z pliku WAL to %s, a identyfikator systemu bazy danych z pg_control to %s"
-#: access/transam/xlogreader.c:780
+#: access/transam/xlogreader.c:781
#, c-format
msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header"
msgstr "plik WAL pochodzi z innego systemu bazy danych: niepoprawny XLOG_SEG_SIZE w nagłówku strony"
-#: access/transam/xlogreader.c:786
+#: access/transam/xlogreader.c:787
#, c-format
msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
msgstr "plik WAL pochodzi z innego systemu bazy danych: niepoprawny XLOG_BLCKSZ w nagłówku strony"
-#: access/transam/xlogreader.c:812
+#: access/transam/xlogreader.c:813
#, c-format
msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
msgstr "nieoczekiwany adrstrony %X/%X w segmencie dziennika %s, przesunięcie %u"
-#: access/transam/xlogreader.c:837
+#: access/transam/xlogreader.c:838
#, c-format
msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
msgstr "nieoczekiwany ID linii czasu %u (po %u) w segmencie dziennika %s, przesunięcie %u"
-#: access/transam/xlogreader.c:1044
+#: access/transam/xlogreader.c:1083
#, c-format
msgid "out-of-order block_id %u at %X/%X"
msgstr "poza porządkiem block_id %u na %X/%X"
-#: access/transam/xlogreader.c:1066
+#: access/transam/xlogreader.c:1106
#, c-format
msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
msgstr "BKPBLOCK_HAS_DATA jest ustawione, ale nie załączono danych na %X/%X"
-#: access/transam/xlogreader.c:1073
+#: access/transam/xlogreader.c:1113
#, c-format
msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
msgstr "BKPBLOCK_HAS_DATA nie jest ustawione, długość danych to %u na %X/%X"
-#: access/transam/xlogreader.c:1106
+#: access/transam/xlogreader.c:1149
#, c-format
msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
msgstr "BKPIMAGE_HAS_HOLE jest ustawione, ale przesunięcie dziury %u długości %u blok obrazu o długości %u na %X/%X"
-#: access/transam/xlogreader.c:1122
+#: access/transam/xlogreader.c:1165
#, c-format
msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
msgstr "BKPIMAGE_HAS_HOLE nie jest ustawione, ale przesunięcie dziury %u o długości %u na %X/%X"
-#: access/transam/xlogreader.c:1137
+#: access/transam/xlogreader.c:1180
#, c-format
msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
msgstr "BKPIMAGE_IS_COMPRESSED jest ustawione, ale blok obrazu o długości %u na %X/%X"
-#: access/transam/xlogreader.c:1152
+#: access/transam/xlogreader.c:1195
#, c-format
msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
msgstr "ani BKPIMAGE_HAS_HOLE ani BKPIMAGE_IS_COMPRESSED nie jest ustawione, ale długość bloku obrazu to %u na %X/%X"
-#: access/transam/xlogreader.c:1168
+#: access/transam/xlogreader.c:1211
#, c-format
msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
msgstr "BKPBLOCK_SAME_REL jest ustawione ale brak poprzedniej rel na %X/%X"
-#: access/transam/xlogreader.c:1180
+#: access/transam/xlogreader.c:1223
#, c-format
msgid "invalid block_id %u at %X/%X"
msgstr "niepoprawny block_id %u na %X/%X"
-#: access/transam/xlogreader.c:1245
+#: access/transam/xlogreader.c:1291
#, c-format
msgid "record with invalid length at %X/%X"
msgstr "rekord o niepoprawnej długości w %X/%X"
-#: access/transam/xlogreader.c:1334
+#: access/transam/xlogreader.c:1380
#, c-format
msgid "invalid compressed image at %X/%X, block %d"
msgstr "niepoprawny skompresowany obraz na %X/%X, blok %d"
-#: access/transam/xlogutils.c:739 replication/walsender.c:2133
+#: access/transam/xlogutils.c:747 replication/walsender.c:2345
#, c-format
msgid "could not read from log segment %s, offset %u, length %lu: %m"
msgstr "nie można czytać z segmentu dziennika %s, przesunięcie %u, długość %lu: %m"
-#: bootstrap/bootstrap.c:269 postmaster/postmaster.c:785 tcop/postgres.c:3503
+#: bootstrap/bootstrap.c:271 postmaster/postmaster.c:801 tcop/postgres.c:3495
#, c-format
msgid "--%s requires a value"
msgstr "--%s wymaga wartości"
-#: bootstrap/bootstrap.c:274 postmaster/postmaster.c:790 tcop/postgres.c:3508
+#: bootstrap/bootstrap.c:276 postmaster/postmaster.c:806 tcop/postgres.c:3500
#, c-format
msgid "-c %s requires a value"
msgstr "-c %s wymaga wartości"
-#: bootstrap/bootstrap.c:285 postmaster/postmaster.c:802
-#: postmaster/postmaster.c:815
+#: bootstrap/bootstrap.c:287 postmaster/postmaster.c:818
+#: postmaster/postmaster.c:831
#, c-format
msgid "Try \"%s --help\" for more information.\n"
msgstr "Użyj \"%s --help\" aby uzyskać więcej informacji.\n"
-#: bootstrap/bootstrap.c:294
+#: bootstrap/bootstrap.c:296
#, c-format
msgid "%s: invalid command-line arguments\n"
msgstr "%s: nieprawidłowe argumenty wiersza poleceń\n"
-#: catalog/aclchk.c:193
+#: catalog/aclchk.c:203
#, c-format
msgid "grant options can only be granted to roles"
msgstr "opcja przyznawania uprawnień może być przyznana tylko roli"
-#: catalog/aclchk.c:316
+#: catalog/aclchk.c:326
#, c-format
msgid "no privileges were granted for column \"%s\" of relation \"%s\""
msgstr "nie przyznano żadnych uprawnień do kolumny \"%s\" relacji \"%s\""
-#: catalog/aclchk.c:321
+#: catalog/aclchk.c:331
#, c-format
msgid "no privileges were granted for \"%s\""
msgstr "nie przyznano żadnych uprawnień do \"%s\""
-#: catalog/aclchk.c:329
+#: catalog/aclchk.c:339
#, c-format
msgid "not all privileges were granted for column \"%s\" of relation \"%s\""
msgstr "nie przyznano wszystkich uprawnień do kolumny \"%s\" relacji \"%s\""
-#: catalog/aclchk.c:334
+#: catalog/aclchk.c:344
#, c-format
msgid "not all privileges were granted for \"%s\""
msgstr "nie przyznano wszystkich uprawnień do \"%s\""
-#: catalog/aclchk.c:345
+#: catalog/aclchk.c:355
#, c-format
msgid "no privileges could be revoked for column \"%s\" of relation \"%s\""
msgstr "nie można odwołać żadnych uprawnień do kolumny \"%s\" relacji \"%s\""
-#: catalog/aclchk.c:350
+#: catalog/aclchk.c:360
#, c-format
msgid "no privileges could be revoked for \"%s\""
msgstr "nie można odwołać żadnych uprawnień do \"%s\""
-#: catalog/aclchk.c:358
+#: catalog/aclchk.c:368
#, c-format
msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\""
msgstr "nie udało się odwołać wszystkich uprawnień do kolumny \"%s\" relacji \"%s\""
-#: catalog/aclchk.c:363
+#: catalog/aclchk.c:373
#, c-format
msgid "not all privileges could be revoked for \"%s\""
msgstr "nie udało się odwołać wszystkich uprawnień do \"%s\""
-#: catalog/aclchk.c:445 catalog/aclchk.c:935
+#: catalog/aclchk.c:455 catalog/aclchk.c:948
#, c-format
msgid "invalid privilege type %s for relation"
msgstr "nieprawidłowy typ uprawnienia %s dla relacji"
-#: catalog/aclchk.c:449 catalog/aclchk.c:939
+#: catalog/aclchk.c:459 catalog/aclchk.c:952
#, c-format
msgid "invalid privilege type %s for sequence"
msgstr "nieprawidłowy typ uprawnienia %s dla sekwencji"
-#: catalog/aclchk.c:453
+#: catalog/aclchk.c:463
#, c-format
msgid "invalid privilege type %s for database"
msgstr "nieprawidłowy typ uprawnienia %s dla bazy danych"
-#: catalog/aclchk.c:457
+#: catalog/aclchk.c:467
#, c-format
msgid "invalid privilege type %s for domain"
msgstr "nieprawidłowy typ uprawnienia %s dla domeny"
-#: catalog/aclchk.c:461 catalog/aclchk.c:943
+#: catalog/aclchk.c:471 catalog/aclchk.c:956
#, c-format
msgid "invalid privilege type %s for function"
msgstr "nieprawidłowy typ uprawnienia %s dla funkcji"
-#: catalog/aclchk.c:465
+#: catalog/aclchk.c:475
#, c-format
msgid "invalid privilege type %s for language"
msgstr "nieprawidłowy typ uprawnienia %s dla języka"
-#: catalog/aclchk.c:469
+#: catalog/aclchk.c:479
#, c-format
msgid "invalid privilege type %s for large object"
msgstr "nieprawidłowy typ uprawnienia %s dla dużego obiektu"
-#: catalog/aclchk.c:473
+#: catalog/aclchk.c:483 catalog/aclchk.c:964
#, c-format
msgid "invalid privilege type %s for schema"
msgstr "nieprawidłowy typ uprawnienia %s dla schematu"
-#: catalog/aclchk.c:477
+#: catalog/aclchk.c:487
#, c-format
msgid "invalid privilege type %s for tablespace"
msgstr "nieprawidłowy typ uprawnienia %s dla przestrzeni tabel"
-#: catalog/aclchk.c:481 catalog/aclchk.c:947
+#: catalog/aclchk.c:491 catalog/aclchk.c:960
#, c-format
msgid "invalid privilege type %s for type"
msgstr "nieprawidłowy typ uprawnienia %s dla typu"
-#: catalog/aclchk.c:485
+#: catalog/aclchk.c:495
#, c-format
msgid "invalid privilege type %s for foreign-data wrapper"
msgstr "nieprawidłowy typ uprawnienia %s dla opakowania obcych danych"
-#: catalog/aclchk.c:489
+#: catalog/aclchk.c:499
#, c-format
msgid "invalid privilege type %s for foreign server"
msgstr "nieprawidłowy typ uprawnienia %s dla serwera obcego"
-#: catalog/aclchk.c:528
+#: catalog/aclchk.c:538
#, c-format
msgid "column privileges are only valid for relations"
msgstr "uprawnienia do kolumn są poprawne tylko dla relacji"
-#: catalog/aclchk.c:687 catalog/aclchk.c:3915 catalog/aclchk.c:4697
-#: catalog/objectaddress.c:873 catalog/pg_largeobject.c:113
+#: catalog/aclchk.c:696 catalog/aclchk.c:3926 catalog/aclchk.c:4708
+#: catalog/objectaddress.c:929 catalog/pg_largeobject.c:111
#: storage/large_object/inv_api.c:291
#, c-format
msgid "large object %u does not exist"
msgstr "duży obiekt %u nie istnieje"
-#: catalog/aclchk.c:874 catalog/aclchk.c:882 commands/collationcmds.c:92
-#: commands/copy.c:1008 commands/copy.c:1026 commands/copy.c:1034
-#: commands/copy.c:1042 commands/copy.c:1050 commands/copy.c:1058
-#: commands/copy.c:1066 commands/copy.c:1074 commands/copy.c:1082
-#: commands/copy.c:1098 commands/copy.c:1112 commands/copy.c:1131
-#: commands/copy.c:1146 commands/dbcommands.c:155 commands/dbcommands.c:163
-#: commands/dbcommands.c:171 commands/dbcommands.c:179
-#: commands/dbcommands.c:187 commands/dbcommands.c:195
-#: commands/dbcommands.c:203 commands/dbcommands.c:211
-#: commands/dbcommands.c:219 commands/dbcommands.c:1397
-#: commands/dbcommands.c:1405 commands/dbcommands.c:1413
-#: commands/dbcommands.c:1421 commands/extension.c:1218
-#: commands/extension.c:1226 commands/extension.c:1234
-#: commands/extension.c:1242 commands/extension.c:2760
-#: commands/foreigncmds.c:539 commands/foreigncmds.c:548
-#: commands/functioncmds.c:533 commands/functioncmds.c:649
-#: commands/functioncmds.c:657 commands/functioncmds.c:665
-#: commands/functioncmds.c:673 commands/functioncmds.c:2085
-#: commands/functioncmds.c:2093 commands/sequence.c:1189
-#: commands/sequence.c:1197 commands/sequence.c:1205 commands/sequence.c:1213
-#: commands/sequence.c:1221 commands/sequence.c:1229 commands/sequence.c:1237
-#: commands/sequence.c:1245 commands/typecmds.c:295 commands/typecmds.c:1382
-#: commands/typecmds.c:1391 commands/typecmds.c:1399 commands/typecmds.c:1407
-#: commands/typecmds.c:1415 commands/user.c:139 commands/user.c:156
-#: commands/user.c:164 commands/user.c:172 commands/user.c:180
-#: commands/user.c:188 commands/user.c:196 commands/user.c:204
-#: commands/user.c:212 commands/user.c:220 commands/user.c:228
-#: commands/user.c:236 commands/user.c:244 commands/user.c:537
-#: commands/user.c:549 commands/user.c:557 commands/user.c:565
-#: commands/user.c:573 commands/user.c:581 commands/user.c:589
-#: commands/user.c:597 commands/user.c:606 commands/user.c:614
-#: commands/user.c:622
+#: catalog/aclchk.c:885 catalog/aclchk.c:894 commands/collationcmds.c:106
+#: commands/copy.c:1046 commands/copy.c:1066 commands/copy.c:1075
+#: commands/copy.c:1084 commands/copy.c:1093 commands/copy.c:1102
+#: commands/copy.c:1111 commands/copy.c:1120 commands/copy.c:1129
+#: commands/copy.c:1147 commands/copy.c:1163 commands/copy.c:1183
+#: commands/copy.c:1200 commands/dbcommands.c:155 commands/dbcommands.c:164
+#: commands/dbcommands.c:173 commands/dbcommands.c:182
+#: commands/dbcommands.c:191 commands/dbcommands.c:200
+#: commands/dbcommands.c:209 commands/dbcommands.c:218
+#: commands/dbcommands.c:227 commands/dbcommands.c:1427
+#: commands/dbcommands.c:1436 commands/dbcommands.c:1445
+#: commands/dbcommands.c:1454 commands/extension.c:1674
+#: commands/extension.c:1684 commands/extension.c:1694
+#: commands/extension.c:1704 commands/extension.c:2944
+#: commands/foreigncmds.c:537 commands/foreigncmds.c:546
+#: commands/functioncmds.c:526 commands/functioncmds.c:643
+#: commands/functioncmds.c:652 commands/functioncmds.c:661
+#: commands/functioncmds.c:670 commands/functioncmds.c:2076
+#: commands/functioncmds.c:2084 commands/publicationcmds.c:89
+#: commands/publicationcmds.c:99 commands/publicationcmds.c:109
+#: commands/publicationcmds.c:119 commands/publicationcmds.c:129
+#: commands/publicationcmds.c:139 commands/sequence.c:1251
+#: commands/sequence.c:1260 commands/sequence.c:1269 commands/sequence.c:1278
+#: commands/sequence.c:1287 commands/sequence.c:1296 commands/sequence.c:1305
+#: commands/sequence.c:1314 commands/sequence.c:1323
+#: commands/subscriptioncmds.c:94 commands/subscriptioncmds.c:104
+#: commands/subscriptioncmds.c:114 commands/subscriptioncmds.c:124
+#: commands/subscriptioncmds.c:134 commands/subscriptioncmds.c:144
+#: commands/subscriptioncmds.c:153 commands/subscriptioncmds.c:163
+#: commands/tablecmds.c:5952 commands/typecmds.c:298 commands/typecmds.c:1375
+#: commands/typecmds.c:1384 commands/typecmds.c:1392 commands/typecmds.c:1400
+#: commands/typecmds.c:1408 commands/user.c:138 commands/user.c:161
+#: commands/user.c:170 commands/user.c:179 commands/user.c:188
+#: commands/user.c:197 commands/user.c:206 commands/user.c:215
+#: commands/user.c:224 commands/user.c:233 commands/user.c:242
+#: commands/user.c:251 commands/user.c:260 commands/user.c:547
+#: commands/user.c:564 commands/user.c:572 commands/user.c:580
+#: commands/user.c:588 commands/user.c:596 commands/user.c:604
+#: commands/user.c:612 commands/user.c:621 commands/user.c:629
+#: commands/user.c:637 parser/parse_utilcmd.c:398
+#: replication/pgoutput/pgoutput.c:107 replication/pgoutput/pgoutput.c:128
+#: replication/walsender.c:797 replication/walsender.c:808
+#: replication/walsender.c:818
#, c-format
msgid "conflicting or redundant options"
msgstr "sprzeczne lub zbędne opcje"
-#: catalog/aclchk.c:980
+#: catalog/aclchk.c:997
#, c-format
msgid "default privileges cannot be set for columns"
msgstr "uprawnienia domyślne nie mogą być ustawione dla kolumn"
-#: catalog/aclchk.c:1494 catalog/objectaddress.c:1390 commands/analyze.c:378
-#: commands/copy.c:4423 commands/sequence.c:1491 commands/tablecmds.c:5197
-#: commands/tablecmds.c:5303 commands/tablecmds.c:5363
-#: commands/tablecmds.c:5476 commands/tablecmds.c:5533
-#: commands/tablecmds.c:5627 commands/tablecmds.c:5723
-#: commands/tablecmds.c:7875 commands/tablecmds.c:8080
-#: commands/tablecmds.c:8500 commands/trigger.c:642 parser/analyze.c:2182
-#: parser/parse_relation.c:2542 parser/parse_relation.c:2604
-#: parser/parse_target.c:940 parser/parse_type.c:127 utils/adt/acl.c:2840
-#: utils/adt/ruleutils.c:1870
+#: catalog/aclchk.c:1157
+#, c-format
+msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS"
+msgstr "nie można używać klauzuli IN SCHEMA razem z GRANT/REVOKE ON SCHEMAS"
+
+#: catalog/aclchk.c:1521 catalog/objectaddress.c:1390 commands/analyze.c:390
+#: commands/copy.c:4671 commands/sequence.c:1668 commands/tablecmds.c:5580
+#: commands/tablecmds.c:5747 commands/tablecmds.c:5804
+#: commands/tablecmds.c:5877 commands/tablecmds.c:5971
+#: commands/tablecmds.c:6030 commands/tablecmds.c:6155
+#: commands/tablecmds.c:6209 commands/tablecmds.c:6301
+#: commands/tablecmds.c:6457 commands/tablecmds.c:8678
+#: commands/tablecmds.c:8954 commands/tablecmds.c:9371 commands/trigger.c:739
+#: parser/analyze.c:2310 parser/parse_relation.c:2698
+#: parser/parse_relation.c:2760 parser/parse_target.c:1002
+#: parser/parse_type.c:127 utils/adt/acl.c:2823 utils/adt/ruleutils.c:2311
#, c-format
msgid "column \"%s\" of relation \"%s\" does not exist"
msgstr "kolumna \"%s\" relacji \"%s\" nie istnieje"
-#: catalog/aclchk.c:1763 catalog/objectaddress.c:1203 commands/sequence.c:1078
-#: commands/tablecmds.c:223 commands/tablecmds.c:12007 utils/adt/acl.c:2076
-#: utils/adt/acl.c:2106 utils/adt/acl.c:2138 utils/adt/acl.c:2170
-#: utils/adt/acl.c:2198 utils/adt/acl.c:2228
+#: catalog/aclchk.c:1787 catalog/objectaddress.c:1230 commands/sequence.c:1138
+#: commands/tablecmds.c:229 commands/tablecmds.c:13028 utils/adt/acl.c:2059
+#: utils/adt/acl.c:2089 utils/adt/acl.c:2121 utils/adt/acl.c:2153
+#: utils/adt/acl.c:2181 utils/adt/acl.c:2211
#, c-format
msgid "\"%s\" is not a sequence"
msgstr "\"%s\" nie jest sekwencją"
-#: catalog/aclchk.c:1801
+#: catalog/aclchk.c:1825
#, c-format
msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges"
msgstr "sekwencja \"%s\" pozwala jedynie na uprawnienia USAGE, SELECT i UPDATE"
-#: catalog/aclchk.c:1818
+#: catalog/aclchk.c:1842
#, c-format
-msgid "invalid privilege type USAGE for table"
-msgstr "niepoprawny typ uprawnienia USAGE dla tabeli"
+#| msgid "invalid privilege type %s for tablespace"
+msgid "invalid privilege type %s for table"
+msgstr "nieprawidłowy typ uprawnienia %s dla tabeli"
-#: catalog/aclchk.c:1986
+#: catalog/aclchk.c:2008
#, c-format
msgid "invalid privilege type %s for column"
msgstr "nieprawidłowy typ uprawnienia %s dla kolumny"
-#: catalog/aclchk.c:1999
+#: catalog/aclchk.c:2021
#, c-format
msgid "sequence \"%s\" only supports SELECT column privileges"
msgstr "sekwencja \"%s\" pozwala jedynie na uprawnienia kolumnowe SELECT"
-#: catalog/aclchk.c:2593
+#: catalog/aclchk.c:2603
#, c-format
msgid "language \"%s\" is not trusted"
msgstr "język \"%s\" nie jest zaufany"
-#: catalog/aclchk.c:2595
+#: catalog/aclchk.c:2605
#, c-format
msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages."
-msgstr ""
-"GRANT i REVOKE są niedozwolone w niezaufanych językach, ponieważ tylko "
-"superużytkownicy mogą używać niezaufanych języków."
+msgstr "GRANT i REVOKE są niedozwolone w niezaufanych językach, ponieważ tylko superużytkownicy mogą używać niezaufanych języków."
-#: catalog/aclchk.c:3121
+#: catalog/aclchk.c:3119
#, c-format
msgid "cannot set privileges of array types"
msgstr "nie można ustalić uprawnień dla typów tablicowych"
-#: catalog/aclchk.c:3122
+#: catalog/aclchk.c:3120
#, c-format
msgid "Set the privileges of the element type instead."
msgstr "Ustaw zamiast tego uprawnienia dla typu elementu."
-#: catalog/aclchk.c:3129 catalog/objectaddress.c:1523 commands/typecmds.c:3146
+#: catalog/aclchk.c:3127 catalog/objectaddress.c:1520 commands/typecmds.c:3165
#, c-format
msgid "\"%s\" is not a domain"
msgstr "\"%s\" nie jest domeną"
-#: catalog/aclchk.c:3252
+#: catalog/aclchk.c:3247
#, c-format
msgid "unrecognized privilege type \"%s\""
msgstr "nierozpoznany typ uprawnienia \"%s\""
-#: catalog/aclchk.c:3301
+#: catalog/aclchk.c:3296
#, c-format
msgid "permission denied for column %s"
msgstr "odmowa dostępu do kolumny %s"
-#: catalog/aclchk.c:3303
+#: catalog/aclchk.c:3298
#, c-format
msgid "permission denied for relation %s"
msgstr "odmowa dostępu do relacji %s"
-#: catalog/aclchk.c:3305 commands/sequence.c:561 commands/sequence.c:786
-#: commands/sequence.c:828 commands/sequence.c:865 commands/sequence.c:1543
+#: catalog/aclchk.c:3300 commands/sequence.c:600 commands/sequence.c:834
+#: commands/sequence.c:876 commands/sequence.c:917 commands/sequence.c:1759
+#: commands/sequence.c:1823
#, c-format
msgid "permission denied for sequence %s"
msgstr "odmowa dostępu do sekwencji %s"
-#: catalog/aclchk.c:3307
+#: catalog/aclchk.c:3302
#, c-format
msgid "permission denied for database %s"
msgstr "odmowa dostępu do bazy danych %s"
-#: catalog/aclchk.c:3309
+#: catalog/aclchk.c:3304
#, c-format
msgid "permission denied for function %s"
msgstr "odmowa dostępu do funkcji %s"
-#: catalog/aclchk.c:3311
+#: catalog/aclchk.c:3306
#, c-format
msgid "permission denied for operator %s"
msgstr "odmowa dostępu do operatora %s"
-#: catalog/aclchk.c:3313
+#: catalog/aclchk.c:3308
#, c-format
msgid "permission denied for type %s"
msgstr "odmowa dostępu do typu %s"
-#: catalog/aclchk.c:3315
+#: catalog/aclchk.c:3310
#, c-format
msgid "permission denied for language %s"
msgstr "odmowa dostępu do języka %s"
-#: catalog/aclchk.c:3317
+#: catalog/aclchk.c:3312
#, c-format
msgid "permission denied for large object %s"
msgstr "odmowa dostępu do dużego obiektu %s"
-#: catalog/aclchk.c:3319
+#: catalog/aclchk.c:3314
#, c-format
msgid "permission denied for schema %s"
msgstr "odmowa dostępu do schematu %s"
-#: catalog/aclchk.c:3321
+#: catalog/aclchk.c:3316
#, c-format
msgid "permission denied for operator class %s"
msgstr "odmowa dostępu do klasy operatora %s"
-#: catalog/aclchk.c:3323
+#: catalog/aclchk.c:3318
#, c-format
msgid "permission denied for operator family %s"
msgstr "odmowa dostępu do rodziny operatora %s"
-#: catalog/aclchk.c:3325
+#: catalog/aclchk.c:3320
#, c-format
msgid "permission denied for collation %s"
msgstr "odmowa dostępu do porównania %s"
-#: catalog/aclchk.c:3327
+#: catalog/aclchk.c:3322
#, c-format
msgid "permission denied for conversion %s"
msgstr "odmowa dostępu do konwersji %s"
-#: catalog/aclchk.c:3329
+#: catalog/aclchk.c:3324
+#, c-format
+#| msgid "permission denied for tablespace %s"
+msgid "permission denied for statistics %s"
+msgstr "odmowa dostępu do statystyki %s"
+
+#: catalog/aclchk.c:3326
#, c-format
msgid "permission denied for tablespace %s"
msgstr "odmowa dostępu do przestrzeni tabel %s"
-#: catalog/aclchk.c:3331
+#: catalog/aclchk.c:3328
#, c-format
msgid "permission denied for text search dictionary %s"
msgstr "odmowa dostępu do słownika wyszukiwania tekstowego %s"
-#: catalog/aclchk.c:3333
+#: catalog/aclchk.c:3330
#, c-format
msgid "permission denied for text search configuration %s"
msgstr "odmowa dostępu do konfiguracji wyszukiwania tekstowego %s"
-#: catalog/aclchk.c:3335
+#: catalog/aclchk.c:3332
#, c-format
msgid "permission denied for foreign-data wrapper %s"
msgstr "odmowa dostępu do opakowania obcych danych %s"
-#: catalog/aclchk.c:3337
+#: catalog/aclchk.c:3334
#, c-format
msgid "permission denied for foreign server %s"
msgstr "odmowa dostępu do serwera obcego %s"
-#: catalog/aclchk.c:3339
+#: catalog/aclchk.c:3336
#, c-format
msgid "permission denied for event trigger %s"
msgstr "odmowa dostępu do wyzwalacza zdarzeniowego %s"
-#: catalog/aclchk.c:3341
+#: catalog/aclchk.c:3338
#, c-format
msgid "permission denied for extension %s"
msgstr "odmowa dostępu do rozszerzenia %s"
-#: catalog/aclchk.c:3347 catalog/aclchk.c:3349
+#: catalog/aclchk.c:3340
+#, c-format
+#| msgid "permission denied for relation %s"
+msgid "permission denied for publication %s"
+msgstr "odmowa dostępu do publikacji %s"
+
+#: catalog/aclchk.c:3342
+#, c-format
+#| msgid "permission denied for function %s"
+msgid "permission denied for subscription %s"
+msgstr "odmowa dostępu do subskrypcji %s"
+
+#: catalog/aclchk.c:3348 catalog/aclchk.c:3350
#, c-format
msgid "must be owner of relation %s"
msgstr "musi być właścicielem relacji %s"
-#: catalog/aclchk.c:3351
+#: catalog/aclchk.c:3352
#, c-format
msgid "must be owner of sequence %s"
msgstr "musi być właścicielem sekwencji %s"
-#: catalog/aclchk.c:3353
+#: catalog/aclchk.c:3354
#, c-format
msgid "must be owner of database %s"
msgstr "musi być właścicielem bazy %s"
-#: catalog/aclchk.c:3355
+#: catalog/aclchk.c:3356
#, c-format
msgid "must be owner of function %s"
msgstr "musi być właścicielem funkcji %s"
-#: catalog/aclchk.c:3357
+#: catalog/aclchk.c:3358
#, c-format
msgid "must be owner of operator %s"
msgstr "musi być właścicielem operatora %s"
-#: catalog/aclchk.c:3359
+#: catalog/aclchk.c:3360
#, c-format
msgid "must be owner of type %s"
msgstr "musi być właścicielem typu %s"
-#: catalog/aclchk.c:3361
+#: catalog/aclchk.c:3362
#, c-format
msgid "must be owner of language %s"
msgstr "musi być właścicielem języka %s"
-#: catalog/aclchk.c:3363
+#: catalog/aclchk.c:3364
#, c-format
msgid "must be owner of large object %s"
msgstr "musi być właścicielem dużego obiektu %s"
-#: catalog/aclchk.c:3365
+#: catalog/aclchk.c:3366
#, c-format
msgid "must be owner of schema %s"
msgstr "musi być właścicielem schematu %s"
-#: catalog/aclchk.c:3367
+#: catalog/aclchk.c:3368
#, c-format
msgid "must be owner of operator class %s"
msgstr "musi być właścicielem klasy operatora %s"
-#: catalog/aclchk.c:3369
+#: catalog/aclchk.c:3370
#, c-format
msgid "must be owner of operator family %s"
msgstr "musi być właścicielem rodziny operatora %s"
-#: catalog/aclchk.c:3371
+#: catalog/aclchk.c:3372
#, c-format
msgid "must be owner of collation %s"
msgstr "musi być właścicielem porównania %s"
-#: catalog/aclchk.c:3373
+#: catalog/aclchk.c:3374
#, c-format
msgid "must be owner of conversion %s"
msgstr "musi być właścicielem konwersji %s"
-#: catalog/aclchk.c:3375
+#: catalog/aclchk.c:3376
+#, c-format
+#| msgid "must be owner of tablespace %s"
+msgid "must be owner of statistics %s"
+msgstr "musi być właścicielem statystyki %s"
+
+#: catalog/aclchk.c:3378
#, c-format
msgid "must be owner of tablespace %s"
msgstr "musi być właścicielem przestrzeni tabel %s"
-#: catalog/aclchk.c:3377
+#: catalog/aclchk.c:3380
#, c-format
msgid "must be owner of text search dictionary %s"
msgstr "musi być właścicielem słownika wyszukiwania tekstowego %s"
-#: catalog/aclchk.c:3379
+#: catalog/aclchk.c:3382
#, c-format
msgid "must be owner of text search configuration %s"
msgstr "musi być właścicielem konfiguracji wyszukiwania tekstowego %s"
-#: catalog/aclchk.c:3381
+#: catalog/aclchk.c:3384
#, c-format
msgid "must be owner of foreign-data wrapper %s"
msgstr "musi być właścicielem opakowania obcych danych %s"
-#: catalog/aclchk.c:3383
+#: catalog/aclchk.c:3386
#, c-format
msgid "must be owner of foreign server %s"
msgstr "musi być właścicielem serwera obcego %s"
-#: catalog/aclchk.c:3385
+#: catalog/aclchk.c:3388
#, c-format
msgid "must be owner of event trigger %s"
msgstr "musi być właścicielem wyzwalacza zdarzeniowego %s"
-#: catalog/aclchk.c:3387
+#: catalog/aclchk.c:3390
#, c-format
msgid "must be owner of extension %s"
msgstr "musi być właścicielem rozszerzenia %s"
-#: catalog/aclchk.c:3429
+#: catalog/aclchk.c:3392
+#, c-format
+#| msgid "must be owner of relation %s"
+msgid "must be owner of publication %s"
+msgstr "musi być właścicielem publikacji %s"
+
+#: catalog/aclchk.c:3394
+#, c-format
+#| msgid "must be owner of function %s"
+msgid "must be owner of subscription %s"
+msgstr "musi być właścicielem subskrypcji %s"
+
+#: catalog/aclchk.c:3436
#, c-format
msgid "permission denied for column \"%s\" of relation \"%s\""
msgstr "odmowa dostępu do kolumny \"%s\" relacji \"%s\""
-#: catalog/aclchk.c:3548 catalog/aclchk.c:3556
+#: catalog/aclchk.c:3559 catalog/aclchk.c:3567
#, c-format
msgid "attribute %d of relation with OID %u does not exist"
msgstr "atrybut %d relacji o OID %u nie istnieje"
-#: catalog/aclchk.c:3629 catalog/aclchk.c:4548
+#: catalog/aclchk.c:3640 catalog/aclchk.c:4559
#, c-format
msgid "relation with OID %u does not exist"
msgstr "relacja z OID %u nie istnieje"
-#: catalog/aclchk.c:3728 catalog/aclchk.c:4966
+#: catalog/aclchk.c:3739 catalog/aclchk.c:4977
#, c-format
msgid "database with OID %u does not exist"
msgstr "baza z OID %u nie istnieje"
-#: catalog/aclchk.c:3782 catalog/aclchk.c:4626 tcop/fastpath.c:223
+#: catalog/aclchk.c:3793 catalog/aclchk.c:4637 tcop/fastpath.c:223
+#: utils/fmgr/fmgr.c:2117
#, c-format
msgid "function with OID %u does not exist"
msgstr "funkcja z OID %u nie istnieje"
-#: catalog/aclchk.c:3836 catalog/aclchk.c:4652
+#: catalog/aclchk.c:3847 catalog/aclchk.c:4663
#, c-format
msgid "language with OID %u does not exist"
msgstr "język z OID %u nie istnieje"
-#: catalog/aclchk.c:4000 catalog/aclchk.c:4724
+#: catalog/aclchk.c:4011 catalog/aclchk.c:4735
#, c-format
msgid "schema with OID %u does not exist"
msgstr "schemat z OID %u nie istnieje"
-#: catalog/aclchk.c:4054 catalog/aclchk.c:4751
+#: catalog/aclchk.c:4065 catalog/aclchk.c:4762
#, c-format
msgid "tablespace with OID %u does not exist"
msgstr "przestrzeń tabel z OID %u nie istnieje"
-#: catalog/aclchk.c:4113 catalog/aclchk.c:4885 commands/foreigncmds.c:325
+#: catalog/aclchk.c:4124 catalog/aclchk.c:4896 commands/foreigncmds.c:324
#, c-format
msgid "foreign-data wrapper with OID %u does not exist"
msgstr "opakowanie obcych danych z OID %u nie istnieje"
-#: catalog/aclchk.c:4175 catalog/aclchk.c:4912 commands/foreigncmds.c:461
+#: catalog/aclchk.c:4186 catalog/aclchk.c:4923 commands/foreigncmds.c:459
#, c-format
msgid "foreign server with OID %u does not exist"
msgstr "serwer obcy z OID %u nie istnieje"
-#: catalog/aclchk.c:4235 catalog/aclchk.c:4574
+#: catalog/aclchk.c:4246 catalog/aclchk.c:4585 utils/cache/typcache.c:238
#, c-format
msgid "type with OID %u does not exist"
msgstr "typ z OID %u nie istnieje"
-#: catalog/aclchk.c:4600
+#: catalog/aclchk.c:4611
#, c-format
msgid "operator with OID %u does not exist"
msgstr "operator z OID %u nie istnieje"
-#: catalog/aclchk.c:4777
+#: catalog/aclchk.c:4788
#, c-format
msgid "operator class with OID %u does not exist"
msgstr "klasa operatora z OID %u nie istnieje"
-#: catalog/aclchk.c:4804
+#: catalog/aclchk.c:4815
#, c-format
msgid "operator family with OID %u does not exist"
msgstr "rodzina operatora z OID %u nie istnieje"
-#: catalog/aclchk.c:4831
+#: catalog/aclchk.c:4842
#, c-format
msgid "text search dictionary with OID %u does not exist"
msgstr "słownik wyszukiwania tekstowego z OID %u nie istnieje"
-#: catalog/aclchk.c:4858
+#: catalog/aclchk.c:4869
#, c-format
msgid "text search configuration with OID %u does not exist"
msgstr "konfiguracja wyszukiwania tekstowego z OID %u nie istnieje"
-#: catalog/aclchk.c:4939 commands/event_trigger.c:587
+#: catalog/aclchk.c:4950 commands/event_trigger.c:588
#, c-format
msgid "event trigger with OID %u does not exist"
msgstr "wyzwalacz zdarzeniowy z OID %u nie istnieje"
-#: catalog/aclchk.c:4992
+#: catalog/aclchk.c:5003 commands/collationcmds.c:319
#, c-format
msgid "collation with OID %u does not exist"
msgstr "porównanie z OID %u nie istnieje"
-#: catalog/aclchk.c:5018
+#: catalog/aclchk.c:5029
#, c-format
msgid "conversion with OID %u does not exist"
msgstr "konwersja z OID %u nie istnieje"
-#: catalog/aclchk.c:5059
+#: catalog/aclchk.c:5070
#, c-format
msgid "extension with OID %u does not exist"
msgstr "rozszerzenie z OID %u nie istnieje"
-#: catalog/dependency.c:646
+#: catalog/aclchk.c:5097 commands/publicationcmds.c:760
+#, c-format
+#| msgid "relation with OID %u does not exist"
+msgid "publication with OID %u does not exist"
+msgstr "publikacja z OID %u nie istnieje"
+
+#: catalog/aclchk.c:5123 commands/subscriptioncmds.c:943
+#, c-format
+#| msgid "function with OID %u does not exist"
+msgid "subscription with OID %u does not exist"
+msgstr "subskrypcja z OID %u nie istnieje"
+
+#: catalog/aclchk.c:5149
+#, c-format
+#| msgid "tablespace with OID %u does not exist"
+msgid "statistics with OID %u do not exist"
+msgstr "statystyka z OID %u nie istnieje"
+
+#: catalog/dependency.c:613
#, c-format
msgid "cannot drop %s because %s requires it"
msgstr "nie można skasować %s ponieważ jest wymagany przez %s"
-#: catalog/dependency.c:649
+#: catalog/dependency.c:616
#, c-format
msgid "You can drop %s instead."
msgstr "W zamian możesz usunąć %s."
-#: catalog/dependency.c:811 catalog/pg_shdepend.c:576
+#: catalog/dependency.c:779 catalog/pg_shdepend.c:574
#, c-format
msgid "cannot drop %s because it is required by the database system"
msgstr "nie można skasować %s ponieważ jest wymagany przez system bazy danych"
-#: catalog/dependency.c:927
+#: catalog/dependency.c:897
#, c-format
msgid "drop auto-cascades to %s"
msgstr "kasowanie z automatycznym kaskadowaniem do %s"
-#: catalog/dependency.c:939 catalog/dependency.c:948
+#: catalog/dependency.c:909 catalog/dependency.c:918
#, c-format
msgid "%s depends on %s"
msgstr "%s zależy od %s"
-#: catalog/dependency.c:960 catalog/dependency.c:969
+#: catalog/dependency.c:930 catalog/dependency.c:939
#, c-format
msgid "drop cascades to %s"
msgstr "kasowanie kaskadowe do %s"
-#: catalog/dependency.c:977 catalog/pg_shdepend.c:687
+#: catalog/dependency.c:947 catalog/pg_shdepend.c:685
#, c-format
msgid ""
"\n"
@@ -3601,23 +3757,23 @@ msgstr[2] ""
"\n"
"oraz %d innych obiektów (by obejrzeć listę sprawdź dziennik serwera)"
-#: catalog/dependency.c:989
+#: catalog/dependency.c:959
#, c-format
msgid "cannot drop %s because other objects depend on it"
msgstr "nie można usunąć %s ponieważ inne obiekty zależą od niego"
-#: catalog/dependency.c:993 catalog/dependency.c:1000
+#: catalog/dependency.c:963 catalog/dependency.c:970
#, c-format
msgid "Use DROP ... CASCADE to drop the dependent objects too."
msgstr "Użyj DROP ... CASCADE aby usunąć wraz z obiektami zależnymi."
-#: catalog/dependency.c:997
+#: catalog/dependency.c:967
#, c-format
msgid "cannot drop desired object(s) because other objects depend on them"
msgstr "nie można skasować żądanych obiektów ponieważ inne obiekty zależą od nich"
#. translator: %d always has a value larger than 1
-#: catalog/dependency.c:1006
+#: catalog/dependency.c:976
#, c-format
msgid "drop cascades to %d other object"
msgid_plural "drop cascades to %d other objects"
@@ -3625,168 +3781,174 @@ msgstr[0] "kasuje kaskadowo %d inny obiekt"
msgstr[1] "kasuje kaskadowo %d inne obiekty"
msgstr[2] "kasuje kaskadowo %d innych obiektów"
-#: catalog/dependency.c:1634
+#: catalog/dependency.c:1622
#, c-format
-msgid "constant of the type \"regrole\" cannot be used here"
-msgstr "stała typu \"regrole\" nie może być tu użyta"
+#| msgid "constant of the type \"regrole\" cannot be used here"
+msgid "constant of the type %s cannot be used here"
+msgstr "stała typu %s nie może być tu użyta"
-#: catalog/heap.c:277
+#: catalog/heap.c:283
#, c-format
msgid "permission denied to create \"%s.%s\""
msgstr "odmowa dostępu do tworzenia \"%s.%s\""
-#: catalog/heap.c:279
+#: catalog/heap.c:285
#, c-format
msgid "System catalog modifications are currently disallowed."
msgstr "Modyfikacje katalogu systemowego są aktualnie zabronione."
-#: catalog/heap.c:414 commands/tablecmds.c:1438 commands/tablecmds.c:1895
-#: commands/tablecmds.c:4819
+#: catalog/heap.c:421 commands/tablecmds.c:1627 commands/tablecmds.c:2136
+#: commands/tablecmds.c:5190
#, c-format
msgid "tables can have at most %d columns"
msgstr "tabele mogą posiadać maksymalnie do %d kolumn"
-#: catalog/heap.c:431 commands/tablecmds.c:5080
+#: catalog/heap.c:438 commands/tablecmds.c:5449
#, c-format
msgid "column name \"%s\" conflicts with a system column name"
msgstr "nazwa kolumny \"%s\" powoduje konflikt z nazwą kolumny systemowej"
-#: catalog/heap.c:447
+#: catalog/heap.c:454
#, c-format
msgid "column name \"%s\" specified more than once"
msgstr "nazwa kolumny \"%s\" określona więcej niż raz"
-#: catalog/heap.c:497
-#, c-format
-msgid "column \"%s\" has type \"unknown\""
-msgstr "kolumna \"%s\" jest typu \"unknown\""
-
-#: catalog/heap.c:498
-#, c-format
-msgid "Proceeding with relation creation anyway."
-msgstr "Kontynuacja utworzenia relacji mimo wszystko."
-
-#: catalog/heap.c:511
+#: catalog/heap.c:507
#, c-format
msgid "column \"%s\" has pseudo-type %s"
msgstr "kolumna \"%s\" jest pseudotypu %s"
-#: catalog/heap.c:541
+#: catalog/heap.c:537
#, c-format
msgid "composite type %s cannot be made a member of itself"
msgstr "złożony typ %s nie może być składnikiem samego siebie"
-#: catalog/heap.c:583 commands/createas.c:201 commands/createas.c:498
+#: catalog/heap.c:579 commands/createas.c:201 commands/createas.c:498
#, c-format
msgid "no collation was derived for column \"%s\" with collatable type %s"
msgstr "nie określono porównania dla kolumny \"%s\" o typie porównywalnym %s"
-#: catalog/heap.c:585 commands/createas.c:204 commands/createas.c:501
-#: commands/indexcmds.c:1132 commands/view.c:105 regex/regc_pg_locale.c:262
-#: utils/adt/formatting.c:1513 utils/adt/formatting.c:1565
-#: utils/adt/formatting.c:1633 utils/adt/formatting.c:1685
-#: utils/adt/formatting.c:1754 utils/adt/formatting.c:1818
-#: utils/adt/like.c:213 utils/adt/selfuncs.c:5330 utils/adt/varlena.c:1421
-#: utils/adt/varlena.c:1826
+#: catalog/heap.c:581 commands/createas.c:204 commands/createas.c:501
+#: commands/indexcmds.c:1136 commands/tablecmds.c:13294 commands/view.c:103
+#: regex/regc_pg_locale.c:263 utils/adt/formatting.c:1537
+#: utils/adt/formatting.c:1656 utils/adt/formatting.c:1775
+#: utils/adt/like.c:184 utils/adt/selfuncs.c:5507 utils/adt/varlena.c:1417
+#: utils/adt/varlena.c:1860
#, c-format
msgid "Use the COLLATE clause to set the collation explicitly."
msgstr "Użyj klauzuli COLLATE by ustawić jawnie porównanie."
-#: catalog/heap.c:1066 catalog/index.c:792 commands/tablecmds.c:2622
+#: catalog/heap.c:1067 catalog/index.c:807 commands/tablecmds.c:2917
#, c-format
msgid "relation \"%s\" already exists"
msgstr "relacja \"%s\" już istnieje"
-#: catalog/heap.c:1082 catalog/pg_type.c:412 catalog/pg_type.c:722
-#: commands/typecmds.c:237 commands/typecmds.c:784 commands/typecmds.c:1135
-#: commands/typecmds.c:1357 commands/typecmds.c:2113
+#: catalog/heap.c:1083 catalog/pg_type.c:410 catalog/pg_type.c:717
+#: commands/typecmds.c:239 commands/typecmds.c:788 commands/typecmds.c:1139
+#: commands/typecmds.c:1350 commands/typecmds.c:2106
#, c-format
msgid "type \"%s\" already exists"
msgstr "typ \"%s\" już istnieje"
-#: catalog/heap.c:1083
+#: catalog/heap.c:1084
#, c-format
msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type."
msgstr "Relacja posiada powiązany typ o tej samej nazwie, musisz zatem użyć nazwy, która nie rodzi konfliktów z istniejącym typem."
-#: catalog/heap.c:1111
+#: catalog/heap.c:1113
#, c-format
msgid "pg_class heap OID value not set when in binary upgrade mode"
msgstr "nie ustawiona wartość OID sterty pg_class w binarnym trybie aktualizacji"
-#: catalog/heap.c:2289
+#: catalog/heap.c:2079
+#, c-format
+#| msgid "cannot use a deferrable unique constraint for referenced table \"%s\""
+msgid "cannot add NO INHERIT constraint to partitioned table \"%s\""
+msgstr "nie można dodać ograniczenia NO INHERIT do podzielonej tabeli \"%s\""
+
+#: catalog/heap.c:2337
#, c-format
msgid "check constraint \"%s\" already exists"
msgstr "ograniczenie kontrolne \"%s\" już istnieje"
-#: catalog/heap.c:2442 catalog/pg_constraint.c:654 commands/tablecmds.c:6068
+#: catalog/heap.c:2505 catalog/pg_constraint.c:649 commands/tablecmds.c:6815
#, c-format
msgid "constraint \"%s\" for relation \"%s\" already exists"
msgstr "ograniczenie \"%s\" dla relacji \"%s\" już istnieje"
-#: catalog/heap.c:2452
+#: catalog/heap.c:2512
#, c-format
msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\""
msgstr "ograniczenie \"%s\" jest niezgodne z niedziedziczonym ograniczeniem na relacji \"%s\""
-#: catalog/heap.c:2466
+#: catalog/heap.c:2523
+#, c-format
+#| msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\""
+msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\""
+msgstr ""
+"ograniczenie \"%s\" jest niezgodne z dziedziczonym ograniczeniem na relacji \"%"
+"s\""
+
+#: catalog/heap.c:2533
+#, c-format
+#| msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\""
+msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\""
+msgstr ""
+"ograniczenie \"%s\" jest niezgodne z ograniczeniem NOT VALID na relacji \"%s\""
+
+#: catalog/heap.c:2538
#, c-format
msgid "merging constraint \"%s\" with inherited definition"
msgstr "połączenie ograniczenia \"%s\" z dziedziczoną definicją"
-#: catalog/heap.c:2559
+#: catalog/heap.c:2654
#, c-format
msgid "cannot use column references in default expression"
msgstr "nie można użyć referencji kolumn w domyślnym wyrażeniu"
-#: catalog/heap.c:2570
-#, c-format
-msgid "default expression must not return a set"
-msgstr "domyślne wyrażenie nie może zwracać zbioru"
-
-#: catalog/heap.c:2589 rewrite/rewriteHandler.c:1084
+#: catalog/heap.c:2679 rewrite/rewriteHandler.c:1140
#, c-format
msgid "column \"%s\" is of type %s but default expression is of type %s"
msgstr "kolumna \"%s\" jest typu %s ale domyślne wyrażenie jest typu %s"
-#: catalog/heap.c:2594 commands/prepare.c:374 parser/parse_node.c:428
-#: parser/parse_target.c:528 parser/parse_target.c:778
-#: parser/parse_target.c:788 rewrite/rewriteHandler.c:1089
+#: catalog/heap.c:2684 commands/prepare.c:384 parser/parse_node.c:430
+#: parser/parse_target.c:590 parser/parse_target.c:840
+#: parser/parse_target.c:850 rewrite/rewriteHandler.c:1145
#, c-format
msgid "You will need to rewrite or cast the expression."
msgstr "Będziesz musiał przepisać lub rzutować wyrażenie."
-#: catalog/heap.c:2641
+#: catalog/heap.c:2731
#, c-format
msgid "only table \"%s\" can be referenced in check constraint"
msgstr "tylko tabela \"%s\" może być wskazana w ograniczeniu kontrolnym"
-#: catalog/heap.c:2881
+#: catalog/heap.c:3040
#, c-format
msgid "unsupported ON COMMIT and foreign key combination"
msgstr "nieobsługiwana kombinacja ON COMMIT i klucza obcego"
-#: catalog/heap.c:2882
+#: catalog/heap.c:3041
#, c-format
msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting."
msgstr "Tabela \"%s\" wskazuje na \"%s\", ale nie mają tego samego ustawienia ON COMMIT."
-#: catalog/heap.c:2887
+#: catalog/heap.c:3046
#, c-format
msgid "cannot truncate a table referenced in a foreign key constraint"
msgstr "nie można obciąć tabeli wskazywanej w ograniczeniu klucza obcego"
-#: catalog/heap.c:2888
+#: catalog/heap.c:3047
#, c-format
msgid "Table \"%s\" references \"%s\"."
msgstr "Tabela \"%s\" wskazuje na \"%s\"."
-#: catalog/heap.c:2890
+#: catalog/heap.c:3049
#, c-format
msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE."
msgstr "Obetnij jednocześnie tabelę \"%s\", albo użyj TRUNCATE ... CASCADE."
-#: catalog/index.c:210 parser/parse_utilcmd.c:1486 parser/parse_utilcmd.c:1572
+#: catalog/index.c:210 parser/parse_utilcmd.c:1659 parser/parse_utilcmd.c:1745
#, c-format
msgid "multiple primary keys for table \"%s\" are not allowed"
msgstr "wielokrotne klucze główne dla tabeli \"%s\" nie są dopuszczalne"
@@ -3796,263 +3958,234 @@ msgstr "wielokrotne klucze główne dla tabeli \"%s\" nie są dopuszczalne"
msgid "primary keys cannot be expressions"
msgstr "klucze główne nie mogą być wyrażeniami"
-#: catalog/index.c:742 catalog/index.c:1160
+#: catalog/index.c:757 catalog/index.c:1175
#, c-format
msgid "user-defined indexes on system catalog tables are not supported"
msgstr "indeksy utworzone przez użytkownika na tabelach katalogu systemowego nie są obsługiwane"
-#: catalog/index.c:752
+#: catalog/index.c:767
#, c-format
msgid "concurrent index creation on system catalog tables is not supported"
msgstr "równoczesne tworzenie indeksów na tabelach katalogu systemowego nie jest obsługiwane"
-#: catalog/index.c:770
+#: catalog/index.c:785
#, c-format
msgid "shared indexes cannot be created after initdb"
msgstr "indeksy współdzielone nie mogą być tworzone po initdb"
-#: catalog/index.c:784 commands/createas.c:249 commands/sequence.c:141
-#: parser/parse_utilcmd.c:192
+#: catalog/index.c:799 commands/createas.c:250 commands/sequence.c:149
+#: parser/parse_utilcmd.c:198
#, c-format
msgid "relation \"%s\" already exists, skipping"
msgstr "relacja \"%s\" już istnieje, pominięto"
-#: catalog/index.c:820
+#: catalog/index.c:835
#, c-format
msgid "pg_class index OID value not set when in binary upgrade mode"
msgstr "nie ustawiona wartość OID indeksu pg_class w binarnym trybie aktualizacji"
-#: catalog/index.c:1422
+#: catalog/index.c:1436
#, c-format
msgid "DROP INDEX CONCURRENTLY must be first action in transaction"
msgstr "DROP INDEX CONCURRENTLY musi być pierwszą akcją transakcji"
-#: catalog/index.c:2004
+#: catalog/index.c:2020
#, c-format
msgid "building index \"%s\" on table \"%s\""
msgstr "tworzenie indeksu \"%s\" na tabeli \"%s\""
-#: catalog/index.c:3322
+#: catalog/index.c:3332
#, c-format
msgid "cannot reindex temporary tables of other sessions"
msgstr "nie można przeindeksować tabel tymczasowych z innych sesji"
-#: catalog/index.c:3454
+#: catalog/index.c:3463
#, c-format
msgid "index \"%s\" was reindexed"
msgstr "indeks \"%s\" został przeindeksowany"
-#: catalog/index.c:3456 commands/vacuumlazy.c:1338 commands/vacuumlazy.c:1414
-#: commands/vacuumlazy.c:1603 commands/vacuumlazy.c:1804
+#: catalog/index.c:3465 commands/vacuumlazy.c:1356 commands/vacuumlazy.c:1432
+#: commands/vacuumlazy.c:1621 commands/vacuumlazy.c:1831
#, c-format
msgid "%s."
msgstr "%s."
-#: catalog/namespace.c:249 catalog/namespace.c:447 catalog/namespace.c:541
-#: commands/trigger.c:4527
+#: catalog/namespace.c:234 catalog/namespace.c:432 catalog/namespace.c:526
+#: commands/trigger.c:4789
#, c-format
msgid "cross-database references are not implemented: \"%s.%s.%s\""
msgstr "międzybazodanowe referencje nie są zaimplementowane: \"%s.%s.%s\""
-#: catalog/namespace.c:306
+#: catalog/namespace.c:291
#, c-format
msgid "temporary tables cannot specify a schema name"
msgstr "tymczasowe tabele nie mogą wskazywać nazwy schematu"
-#: catalog/namespace.c:385
+#: catalog/namespace.c:370
#, c-format
msgid "could not obtain lock on relation \"%s.%s\""
msgstr "nie można nałożyć blokady na relację \"%s.%s\""
-#: catalog/namespace.c:390 commands/lockcmds.c:146
+#: catalog/namespace.c:375 commands/lockcmds.c:145
#, c-format
msgid "could not obtain lock on relation \"%s\""
msgstr "nie można nałożyć blokady na relację \"%s\""
-#: catalog/namespace.c:414 parser/parse_relation.c:1137
+#: catalog/namespace.c:399 parser/parse_relation.c:1158
#, c-format
msgid "relation \"%s.%s\" does not exist"
msgstr "relacja \"%s.%s\" nie istnieje"
-#: catalog/namespace.c:419 parser/parse_relation.c:1150
-#: parser/parse_relation.c:1158 utils/adt/regproc.c:1034
+#: catalog/namespace.c:404 parser/parse_relation.c:1176
+#: parser/parse_relation.c:1184 utils/adt/regproc.c:1036
#, c-format
msgid "relation \"%s\" does not exist"
msgstr "relacja \"%s\" nie istnieje"
-#: catalog/namespace.c:487 catalog/namespace.c:2841 commands/extension.c:1382
-#: commands/extension.c:1388
+#: catalog/namespace.c:472 catalog/namespace.c:2882 commands/extension.c:1462
+#: commands/extension.c:1468
#, c-format
msgid "no schema has been selected to create in"
msgstr "nie wskazano schematu utworzenia obiektu"
-#: catalog/namespace.c:639 catalog/namespace.c:652
+#: catalog/namespace.c:624 catalog/namespace.c:637
#, c-format
msgid "cannot create relations in temporary schemas of other sessions"
msgstr "nie można utworzyć relacji w schematach tymczasowych z innych sesji"
-#: catalog/namespace.c:643
+#: catalog/namespace.c:628
#, c-format
msgid "cannot create temporary relation in non-temporary schema"
msgstr "nie można tworzyć obiektów tymczasowych w schematach nietymczasowych"
-#: catalog/namespace.c:658
+#: catalog/namespace.c:643
#, c-format
msgid "only temporary relations may be created in temporary schemas"
msgstr "tylko relacje tymczasowe mogą być utworzone w schematach tymczasowych"
-#: catalog/namespace.c:2154
+#: catalog/namespace.c:2138
+#, c-format
+#| msgid "constraint \"%s\" does not exist"
+msgid "statistics \"%s\" do not exist"
+msgstr "statystyka \"%s\" nie istnieje"
+
+#: catalog/namespace.c:2195
#, c-format
msgid "text search parser \"%s\" does not exist"
msgstr "parser wyszukiwania tekstowego \"%s\" nie istnieje"
-#: catalog/namespace.c:2280
+#: catalog/namespace.c:2321
#, c-format
msgid "text search dictionary \"%s\" does not exist"
msgstr "słownik wyszukiwania tekstowego \"%s\" nie istnieje"
-#: catalog/namespace.c:2407
+#: catalog/namespace.c:2448
#, c-format
msgid "text search template \"%s\" does not exist"
msgstr "szablon wyszukiwania tekstowego \"%s\" nie istnieje"
-#: catalog/namespace.c:2533 commands/tsearchcmds.c:1197
-#: utils/cache/ts_cache.c:613
+#: catalog/namespace.c:2574 commands/tsearchcmds.c:1185
+#: utils/cache/ts_cache.c:612
#, c-format
msgid "text search configuration \"%s\" does not exist"
msgstr "konfiguracja wyszukiwania tekstowego \"%s\" nie istnieje"
-#: catalog/namespace.c:2646 parser/parse_expr.c:789 parser/parse_target.c:1130
+#: catalog/namespace.c:2687 parser/parse_expr.c:791 parser/parse_target.c:1192
#, c-format
msgid "cross-database references are not implemented: %s"
msgstr "międzybazodanowe referencje nie są zaimplementowane: %s"
-#: catalog/namespace.c:2652 gram.y:13445 gram.y:14814 parser/parse_expr.c:796
-#: parser/parse_target.c:1137
+#: catalog/namespace.c:2693 gram.y:14345 gram.y:15768 parser/parse_expr.c:798
+#: parser/parse_target.c:1199
#, c-format
msgid "improper qualified name (too many dotted names): %s"
msgstr "niewłaściwa nazwa kwalifikowana (zbyt dużo nazw kropkowanych): %s"
-#: catalog/namespace.c:2783
+#: catalog/namespace.c:2824
#, c-format
msgid "cannot move objects into or out of temporary schemas"
msgstr "nie można przenosić obiektów do lub poza schematy tymczasowe"
-#: catalog/namespace.c:2789
+#: catalog/namespace.c:2830
#, c-format
msgid "cannot move objects into or out of TOAST schema"
msgstr "nie można przenosić obiektów do lub poza schemat TOAST"
-#: catalog/namespace.c:2862 commands/schemacmds.c:238
-#: commands/schemacmds.c:317 commands/tablecmds.c:740
+#: catalog/namespace.c:2903 commands/schemacmds.c:256
+#: commands/schemacmds.c:334 commands/tablecmds.c:899
#, c-format
msgid "schema \"%s\" does not exist"
msgstr "schemat \"%s\" nie istnieje"
-#: catalog/namespace.c:2893
+#: catalog/namespace.c:2934
#, c-format
msgid "improper relation name (too many dotted names): %s"
msgstr "niewłaściwa nazwa relacji (zbyt dużo nazw kropkowanych): %s"
-#: catalog/namespace.c:3403
+#: catalog/namespace.c:3444
#, c-format
msgid "collation \"%s\" for encoding \"%s\" does not exist"
msgstr "porównanie \"%s\" dla kodowania \"%s\" nie istnieje"
-#: catalog/namespace.c:3458
+#: catalog/namespace.c:3499
#, c-format
msgid "conversion \"%s\" does not exist"
msgstr "konwersja \"%s\" nie istnieje"
-#: catalog/namespace.c:3666
+#: catalog/namespace.c:3707
#, c-format
msgid "permission denied to create temporary tables in database \"%s\""
msgstr "zabronione tworzenie tabel tymczasowych w bazie danych \"%s\""
-#: catalog/namespace.c:3682
+#: catalog/namespace.c:3723
#, c-format
msgid "cannot create temporary tables during recovery"
msgstr "nie można utworzyć tabel tymczasowych w czasie trwania odzyskiwania"
-#: catalog/namespace.c:3688
+#: catalog/namespace.c:3729
#, c-format
msgid "cannot create temporary tables in parallel mode"
msgstr "nie można utworzyć tabel tymczasowych w czasie trwania równoległym"
-#: catalog/namespace.c:3932 commands/tablespace.c:1173 commands/variable.c:63
-#: utils/misc/guc.c:9855
+#: catalog/namespace.c:3978 commands/tablespace.c:1169 commands/variable.c:64
+#: utils/misc/guc.c:9981 utils/misc/guc.c:10059
#, c-format
msgid "List syntax is invalid."
msgstr "Składnia listy jest niepoprawna."
-#: catalog/objectaddress.c:1065
-#| msgid "schema name cannot be qualified"
-msgid "access method name cannot be qualified"
-msgstr "metoda dostępu nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1068
-msgid "database name cannot be qualified"
-msgstr "nazwa bazy danych nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1071 commands/extension.c:2506
-#, c-format
-msgid "extension name cannot be qualified"
-msgstr "nazwa rozszerzenia nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1074
-msgid "tablespace name cannot be qualified"
-msgstr "nazwa przestrzeni tabel nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1077
-msgid "role name cannot be qualified"
-msgstr "nazwa roli nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1080
-msgid "schema name cannot be qualified"
-msgstr "nazwa schematu nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1083
-msgid "language name cannot be qualified"
-msgstr "nazwa języka nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1086
-msgid "foreign-data wrapper name cannot be qualified"
-msgstr "opakowanie obcych danych nie może być kwalifikowane"
-
-#: catalog/objectaddress.c:1089
-msgid "server name cannot be qualified"
-msgstr "nazwa serwera nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1092
-msgid "event trigger name cannot be qualified"
-msgstr "nazwa wyzwalacza zdarzeniowego nie może być kwalifikowana"
-
-#: catalog/objectaddress.c:1210 commands/lockcmds.c:94 commands/policy.c:94
-#: commands/policy.c:384 commands/policy.c:473 commands/tablecmds.c:217
-#: commands/tablecmds.c:1299 commands/tablecmds.c:4346
-#: commands/tablecmds.c:7977
+#: catalog/objectaddress.c:1238 catalog/pg_publication.c:57
+#: commands/lockcmds.c:93 commands/policy.c:94 commands/policy.c:391
+#: commands/policy.c:480 commands/tablecmds.c:223 commands/tablecmds.c:265
+#: commands/tablecmds.c:1485 commands/tablecmds.c:4700
+#: commands/tablecmds.c:8794
#, c-format
msgid "\"%s\" is not a table"
msgstr "\"%s\" nie jest tabelą"
-#: catalog/objectaddress.c:1217 commands/tablecmds.c:229
-#: commands/tablecmds.c:4376 commands/tablecmds.c:12012 commands/view.c:143
+#: catalog/objectaddress.c:1245 commands/tablecmds.c:235
+#: commands/tablecmds.c:4730 commands/tablecmds.c:13033 commands/view.c:141
#, c-format
msgid "\"%s\" is not a view"
msgstr "\"%s\" nie jest widokiem"
-#: catalog/objectaddress.c:1224 commands/matview.c:174
-#: commands/tablecmds.c:235 commands/tablecmds.c:12017
+#: catalog/objectaddress.c:1252 commands/matview.c:174
+#: commands/tablecmds.c:241 commands/tablecmds.c:13038
#, c-format
msgid "\"%s\" is not a materialized view"
msgstr "\"%s\" nie jest widokiem materializowanym"
-#: catalog/objectaddress.c:1231 commands/tablecmds.c:253
-#: commands/tablecmds.c:4379 commands/tablecmds.c:12022
+#: catalog/objectaddress.c:1259 commands/tablecmds.c:259
+#: commands/tablecmds.c:4733 commands/tablecmds.c:13043
#, c-format
msgid "\"%s\" is not a foreign table"
msgstr "\"%s\" nie jest tabelą obcą"
+#: catalog/objectaddress.c:1300
+#, c-format
+#| msgid "%s must specify unqualified relation names"
+msgid "must specify relation and object name"
+msgstr "musi wskazywać nazwę relacji i obiektu"
+
#: catalog/objectaddress.c:1376 catalog/objectaddress.c:1429
#, c-format
msgid "column name must be qualified"
@@ -4063,174 +4196,182 @@ msgstr "nazwa kolumny nie może być kwalifikowana"
msgid "default value for column \"%s\" of relation \"%s\" does not exist"
msgstr "wartość domyślna kolumny \"%s\" relacji \"%s\" nie istnieje"
-#: catalog/objectaddress.c:1512 commands/functioncmds.c:128
-#: commands/tablecmds.c:245 commands/typecmds.c:3214 parser/parse_type.c:226
-#: parser/parse_type.c:255 parser/parse_type.c:795 utils/adt/acl.c:4374
-#: utils/adt/regproc.c:1225
+#: catalog/objectaddress.c:1509 commands/functioncmds.c:128
+#: commands/tablecmds.c:251 commands/typecmds.c:3233 parser/parse_type.c:226
+#: parser/parse_type.c:255 parser/parse_type.c:794 utils/adt/acl.c:4357
+#: utils/adt/regproc.c:1227
#, c-format
msgid "type \"%s\" does not exist"
msgstr "typ \"%s\" nie istnieje"
-#: catalog/objectaddress.c:1629
+#: catalog/objectaddress.c:1626
#, c-format
msgid "operator %d (%s, %s) of %s does not exist"
msgstr "operator %d (%s, %s) dla %s nie istnieje"
-#: catalog/objectaddress.c:1658
+#: catalog/objectaddress.c:1657
#, c-format
msgid "function %d (%s, %s) of %s does not exist"
msgstr "funkcja %d (%s, %s) dla %s nie istnieje"
-#: catalog/objectaddress.c:1707 catalog/objectaddress.c:1733
+#: catalog/objectaddress.c:1708 catalog/objectaddress.c:1734
#, c-format
msgid "user mapping for user \"%s\" on server \"%s\" does not exist"
msgstr "mapowanie użytkownika dla użytkownika \"%s\" na serwerze \"%s\" nie istnieje"
-#: catalog/objectaddress.c:1722 commands/foreigncmds.c:430
-#: commands/foreigncmds.c:997 commands/foreigncmds.c:1359
-#: foreign/foreign.c:780
+#: catalog/objectaddress.c:1723 commands/foreigncmds.c:428
+#: commands/foreigncmds.c:1004 commands/foreigncmds.c:1377
+#: foreign/foreign.c:688
#, c-format
msgid "server \"%s\" does not exist"
msgstr "serwer \"%s\" nie istnieje"
-#: catalog/objectaddress.c:1794
+#: catalog/objectaddress.c:1790
+#, c-format
+#| msgid "constraint \"%s\" of relation \"%s\" does not exist"
+msgid "publication relation \"%s\" in publication \"%s\" does not exist"
+msgstr "relacja publikacji \"%s\" w publikacji \"%s\" nie istnieje"
+
+#: catalog/objectaddress.c:1852
#, c-format
msgid "unrecognized default ACL object type %c"
msgstr "nierozpoznany domyślny typ obiektu ACL %c"
-#: catalog/objectaddress.c:1795
+#: catalog/objectaddress.c:1853
#, c-format
-msgid "Valid object types are \"r\", \"S\", \"f\", and \"T\"."
-msgstr "Poprawne typy obiektów to \"r\", \"S\", \"f\" i \"T\"."
+#| msgid "Valid object types are \"r\", \"S\", \"f\", and \"T\"."
+msgid "Valid object types are \"r\", \"S\", \"f\", \"T\" and \"s\"."
+msgstr "Poprawne typy obiektów to \"r\", \"S\", \"f\", \"T\" i \"s\"."
-#: catalog/objectaddress.c:1841
+#: catalog/objectaddress.c:1899
#, c-format
msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist"
msgstr "domyślny ACL dla użytkownika \"%s\" w schemacie \"%s\" na %s nie istnieje"
-#: catalog/objectaddress.c:1846
+#: catalog/objectaddress.c:1904
#, c-format
msgid "default ACL for user \"%s\" on %s does not exist"
msgstr "domyślny ACL dla użytkownika \"%s\" na %s nie istnieje"
-#: catalog/objectaddress.c:1873 catalog/objectaddress.c:1929
-#: catalog/objectaddress.c:1984
+#: catalog/objectaddress.c:1931 catalog/objectaddress.c:1989
+#: catalog/objectaddress.c:2044
#, c-format
msgid "name or argument lists may not contain nulls"
msgstr "listy nazw i argumentów nie mogą zawierać wartości pustych"
-#: catalog/objectaddress.c:1905
+#: catalog/objectaddress.c:1965
#, c-format
msgid "unsupported object type \"%s\""
msgstr "nieobsługiwany typ obiektowy \"%s\""
-#: catalog/objectaddress.c:1925 catalog/objectaddress.c:1943
+#: catalog/objectaddress.c:1985 catalog/objectaddress.c:2003
+#: catalog/objectaddress.c:2141
#, c-format
msgid "name list length must be exactly %d"
msgstr "długość listy nazw musi być równa %d"
-#: catalog/objectaddress.c:1947
+#: catalog/objectaddress.c:2007
#, c-format
msgid "large object OID may not be null"
msgstr "OID dużego obiektu nie może być pusty"
-#: catalog/objectaddress.c:1956 catalog/objectaddress.c:2016
-#: catalog/objectaddress.c:2023
+#: catalog/objectaddress.c:2016 catalog/objectaddress.c:2077
+#: catalog/objectaddress.c:2084
#, c-format
msgid "name list length must be at least %d"
msgstr "długość listy nazw musi być nie mniejsza niż %d"
-#: catalog/objectaddress.c:2009 catalog/objectaddress.c:2029
+#: catalog/objectaddress.c:2070 catalog/objectaddress.c:2090
#, c-format
msgid "argument list length must be exactly %d"
msgstr "długość listy argumentów musi być równa %d"
-#: catalog/objectaddress.c:2165 libpq/be-fsstubs.c:352
+#: catalog/objectaddress.c:2316 libpq/be-fsstubs.c:350
#, c-format
msgid "must be owner of large object %u"
msgstr "musi być właścicielem dużego obiektu %u"
-#: catalog/objectaddress.c:2180 commands/functioncmds.c:1426
+#: catalog/objectaddress.c:2331 commands/functioncmds.c:1419
#, c-format
msgid "must be owner of type %s or type %s"
msgstr "musi być właścicielem typu %s lub typu %s"
-#: catalog/objectaddress.c:2220 catalog/objectaddress.c:2237
+#: catalog/objectaddress.c:2381 catalog/objectaddress.c:2398
#, c-format
msgid "must be superuser"
msgstr "musi być superużytkownikiem"
-#: catalog/objectaddress.c:2227
+#: catalog/objectaddress.c:2388
#, c-format
msgid "must have CREATEROLE privilege"
msgstr "musi mieć uprawnienie CREATEROLE"
-#: catalog/objectaddress.c:2307
+#: catalog/objectaddress.c:2467
#, c-format
msgid "unrecognized object type \"%s\""
msgstr "nierozpoznany typ obiektowy \"%s\""
-#: catalog/objectaddress.c:2502
+#: catalog/objectaddress.c:2662
#, c-format
msgid " column %s"
msgstr " kolumna %s"
-#: catalog/objectaddress.c:2508
+#: catalog/objectaddress.c:2668
#, c-format
msgid "function %s"
msgstr "funkcja %s"
-#: catalog/objectaddress.c:2513
+#: catalog/objectaddress.c:2673
#, c-format
msgid "type %s"
msgstr "typ %s"
-#: catalog/objectaddress.c:2543
+#: catalog/objectaddress.c:2703
#, c-format
msgid "cast from %s to %s"
msgstr "rzutowanie z %s na %s"
-#: catalog/objectaddress.c:2563
+#: catalog/objectaddress.c:2723
#, c-format
msgid "collation %s"
msgstr "porównanie %s"
-#: catalog/objectaddress.c:2587
+#: catalog/objectaddress.c:2747
#, c-format
msgid "constraint %s on %s"
msgstr "ograniczenie %s na %s"
-#: catalog/objectaddress.c:2593
+#: catalog/objectaddress.c:2753
#, c-format
msgid "constraint %s"
msgstr "ograniczenie %s"
-#: catalog/objectaddress.c:2610
+#: catalog/objectaddress.c:2770
#, c-format
msgid "conversion %s"
msgstr "konwersja %s"
-#: catalog/objectaddress.c:2647
+#: catalog/objectaddress.c:2807
#, c-format
msgid "default for %s"
msgstr "domyślne dla %s"
-#: catalog/objectaddress.c:2656
+#: catalog/objectaddress.c:2816
#, c-format
msgid "language %s"
msgstr "język %s"
-#: catalog/objectaddress.c:2661
+#: catalog/objectaddress.c:2821
#, c-format
msgid "large object %u"
msgstr "duży obiekt %u nie istnieje"
-#: catalog/objectaddress.c:2666
+#: catalog/objectaddress.c:2826
#, c-format
msgid "operator %s"
msgstr "operator %s"
-#: catalog/objectaddress.c:2698
+#: catalog/objectaddress.c:2858
#, c-format
msgid "operator class %s for access method %s"
msgstr "klasa operatora %s dla metody dostępu %s"
@@ -4239,7 +4380,7 @@ msgstr "klasa operatora %s dla metody dostępu %s"
#. first two %s's are data type names, the third %s is the
#. description of the operator family, and the last %s is the
#. textual form of the operator with arguments.
-#: catalog/objectaddress.c:2748
+#: catalog/objectaddress.c:2908
#, c-format
msgid "operator %d (%s, %s) of %s: %s"
msgstr "operator %d (%s, %s) dla %s: %s"
@@ -4248,182 +4389,234 @@ msgstr "operator %d (%s, %s) dla %s: %s"
#. are data type names, the third %s is the description of the
#. operator family, and the last %s is the textual form of the
#. function with arguments.
-#: catalog/objectaddress.c:2798
+#: catalog/objectaddress.c:2958
#, c-format
msgid "function %d (%s, %s) of %s: %s"
msgstr "funkcja %d (%s, %s) dla %s: %s"
-#: catalog/objectaddress.c:2838
+#: catalog/objectaddress.c:2998
#, c-format
msgid "rule %s on "
msgstr "reguła %s na "
-#: catalog/objectaddress.c:2860
+#: catalog/objectaddress.c:3020
#, c-format
msgid "transform for %s language %s"
msgstr "transformacja dla %s języka %s"
-#: catalog/objectaddress.c:2894
+#: catalog/objectaddress.c:3054
#, c-format
msgid "trigger %s on "
msgstr "wyzwalacz %s na "
-#: catalog/objectaddress.c:2911
+#: catalog/objectaddress.c:3071
#, c-format
msgid "schema %s"
msgstr "schemat %s"
-#: catalog/objectaddress.c:2924
+#: catalog/objectaddress.c:3084
#, c-format
msgid "text search parser %s"
msgstr "parser wyszukiwania tekstowego %s"
-#: catalog/objectaddress.c:2939
+#: catalog/objectaddress.c:3099
#, c-format
msgid "text search dictionary %s"
msgstr "słownik wyszukiwania tekstowego %s"
-#: catalog/objectaddress.c:2954
+#: catalog/objectaddress.c:3114
#, c-format
msgid "text search template %s"
msgstr "szablon wyszukiwania tekstowego %s"
-#: catalog/objectaddress.c:2969
+#: catalog/objectaddress.c:3129
#, c-format
msgid "text search configuration %s"
msgstr "konfiguracja wyszukiwania tekstowego %s"
-#: catalog/objectaddress.c:2977
+#: catalog/objectaddress.c:3137
#, c-format
msgid "role %s"
msgstr "rola %s"
-#: catalog/objectaddress.c:2990
+#: catalog/objectaddress.c:3150
#, c-format
msgid "database %s"
msgstr "baza danych %s"
-#: catalog/objectaddress.c:3002
+#: catalog/objectaddress.c:3162
#, c-format
msgid "tablespace %s"
msgstr "przestrzeń tabel %s"
-#: catalog/objectaddress.c:3011
+#: catalog/objectaddress.c:3171
#, c-format
msgid "foreign-data wrapper %s"
msgstr "opakowanie obcych danych %s"
-#: catalog/objectaddress.c:3020
+#: catalog/objectaddress.c:3180
#, c-format
msgid "server %s"
msgstr "serwer %s"
-#: catalog/objectaddress.c:3048
+#: catalog/objectaddress.c:3208
#, c-format
msgid "user mapping for %s on server %s"
msgstr "mapowanie użytkownika dla %s na serwer %s"
-#: catalog/objectaddress.c:3083
+#: catalog/objectaddress.c:3243
#, c-format
msgid "default privileges on new relations belonging to role %s"
msgstr "uprawnienia domyślne do nowych relacji należących do roli %s"
-#: catalog/objectaddress.c:3088
+#: catalog/objectaddress.c:3248
#, c-format
msgid "default privileges on new sequences belonging to role %s"
msgstr "uprawnienia domyślne do nowych sekwencji należących do roli %s"
-#: catalog/objectaddress.c:3093
+#: catalog/objectaddress.c:3253
#, c-format
msgid "default privileges on new functions belonging to role %s"
msgstr "uprawnienia domyślne do nowych funkcji należących do roli %s"
-#: catalog/objectaddress.c:3098
+#: catalog/objectaddress.c:3258
#, c-format
msgid "default privileges on new types belonging to role %s"
msgstr "uprawnienia domyślne do nowych typów należących do roli %s"
-#: catalog/objectaddress.c:3104
+#: catalog/objectaddress.c:3263
+#, c-format
+#| msgid "default privileges on new sequences belonging to role %s"
+msgid "default privileges on new schemas belonging to role %s"
+msgstr "uprawnienia domyślne do nowych schematów należących do roli %s"
+
+#: catalog/objectaddress.c:3269
#, c-format
msgid "default privileges belonging to role %s"
msgstr "uprawnienia domyślne należące do roli %s"
-#: catalog/objectaddress.c:3112
+#: catalog/objectaddress.c:3277
#, c-format
msgid " in schema %s"
msgstr " w schemacie %s"
-#: catalog/objectaddress.c:3129
+#: catalog/objectaddress.c:3294
#, c-format
msgid "extension %s"
msgstr "rozszerzenie %s"
-#: catalog/objectaddress.c:3142
+#: catalog/objectaddress.c:3307
#, c-format
msgid "event trigger %s"
msgstr "wyzwalacz zdarzeniowy %s"
-#: catalog/objectaddress.c:3174
+#: catalog/objectaddress.c:3339
#, c-format
msgid "policy %s on "
msgstr "polityka %s na "
-#: catalog/objectaddress.c:3192
+#: catalog/objectaddress.c:3357
#, c-format
-#| msgid "access method \"%s\" does not exist"
msgid "access method %s"
msgstr "metoda dostępu %s"
-#: catalog/objectaddress.c:3252
+#: catalog/objectaddress.c:3365
+#, c-format
+#| msgid "relation %s"
+msgid "publication %s"
+msgstr "publikacja %s"
+
+#: catalog/objectaddress.c:3385
+#, c-format
+msgid "publication table %s in publication %s"
+msgstr "tabela publikacji %s w publikacji %s"
+
+#: catalog/objectaddress.c:3393
+#, c-format
+#| msgid "reading subscriptions\n"
+msgid "subscription %s"
+msgstr "subskrypcja %s"
+
+#: catalog/objectaddress.c:3453
#, c-format
msgid "table %s"
msgstr "tabela %s"
-#: catalog/objectaddress.c:3256
+#: catalog/objectaddress.c:3457
#, c-format
msgid "index %s"
msgstr "indeks %s"
-#: catalog/objectaddress.c:3260
+#: catalog/objectaddress.c:3461
#, c-format
msgid "sequence %s"
msgstr "sekwencja %s"
-#: catalog/objectaddress.c:3264
+#: catalog/objectaddress.c:3465
#, c-format
msgid "toast table %s"
msgstr "tabela toast %s"
-#: catalog/objectaddress.c:3268
+#: catalog/objectaddress.c:3469
#, c-format
msgid "view %s"
msgstr "widok %s"
-#: catalog/objectaddress.c:3272
+#: catalog/objectaddress.c:3473
#, c-format
msgid "materialized view %s"
msgstr "widok zmaterializowany %s"
-#: catalog/objectaddress.c:3276
+#: catalog/objectaddress.c:3477
#, c-format
msgid "composite type %s"
msgstr "typ złożony %s"
-#: catalog/objectaddress.c:3280
+#: catalog/objectaddress.c:3481
#, c-format
msgid "foreign table %s"
msgstr "tabela obca %s"
-#: catalog/objectaddress.c:3285
+#: catalog/objectaddress.c:3486
#, c-format
msgid "relation %s"
msgstr "relacja %s"
-#: catalog/objectaddress.c:3322
+#: catalog/objectaddress.c:3523
#, c-format
msgid "operator family %s for access method %s"
msgstr "rodzina operatorów %s dla metody dostępu %s"
+#: catalog/objectaddress.c:4902
+#, c-format
+#| msgid "reading publications\n"
+msgid "%s in publication %s"
+msgstr "%s w publikacji %s"
+
+#: catalog/partition.c:741
+#, c-format
+#| msgid "cannot determine transition data type"
+msgid "cannot create range partition with empty range"
+msgstr "nie można utworzyć partycji na przedziały z pustym przedziałem"
+
+#: catalog/partition.c:835
+#, c-format
+#| msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgid "partition \"%s\" would overlap partition \"%s\""
+msgstr "partycja \"%s\" pokrywałaby się z partycją \"%s\""
+
+#: catalog/partition.c:943 catalog/partition.c:1092 commands/analyze.c:1446
+#: commands/tablecmds.c:8856 executor/execExprInterp.c:2837
+#: executor/execMain.c:3195
+msgid "could not convert row type"
+msgstr "nie można przekształcić typu wierszowego"
+
+#: catalog/partition.c:1729
+#, c-format
+#| msgid "reading partition key information for interesting tables\n"
+msgid "range partition key of row contains null"
+msgstr "klucz przedziału partycji wiersza zawiera null"
+
#: catalog/pg_aggregate.c:125
#, c-format
msgid "aggregates cannot have more than %d argument"
@@ -4467,7 +4660,7 @@ msgstr "nie wolno pominąć wartości początkowej, gdy funkcja przejścia jest
msgid "return type of inverse transition function %s is not %s"
msgstr "zwracany typ funkcji przejściowej inwersji %s nie jest %s"
-#: catalog/pg_aggregate.c:351 executor/nodeWindowAgg.c:2305
+#: catalog/pg_aggregate.c:351 executor/nodeWindowAgg.c:2294
#, c-format
msgid "strictness of aggregate's forward and inverse transition functions must match"
msgstr "ścisłość funkcji przejścia do przodu i wycofania agregatu musi się zgadzać"
@@ -4479,31 +4672,25 @@ msgstr "funkcja final z dodatkowymi argumentami nie może być zadeklarowana ze
#: catalog/pg_aggregate.c:425
#, c-format
-#| msgid "return type of transition function %s is not %s"
msgid "return type of combine function %s is not %s"
msgstr "zwracany typ funkcji łączącej %s nie jest %s"
#: catalog/pg_aggregate.c:436
#, c-format
-#| msgid "final function with extra arguments must not be declared STRICT"
msgid "combine function with \"%s\" transition type must not be declared STRICT"
-msgstr ""
-"funkcja łącząca typem przejściowym \"%s\" nie może być zadeklarowana jako "
-"STRICT"
+msgstr "funkcja łącząca typem przejściowym \"%s\" nie może być zadeklarowana jako STRICT"
#: catalog/pg_aggregate.c:455
#, c-format
-#| msgid "return type of transition function %s is not %s"
msgid "return type of serialization function %s is not %s"
msgstr "zwracany typ funkcji serializującej %s nie jest %s"
#: catalog/pg_aggregate.c:475
#, c-format
-#| msgid "return type of transition function %s is not %s"
msgid "return type of deserialization function %s is not %s"
msgstr "zwracany typ funkcji deserializującej %s nie jest %s"
-#: catalog/pg_aggregate.c:491 catalog/pg_proc.c:246 catalog/pg_proc.c:253
+#: catalog/pg_aggregate.c:491 catalog/pg_proc.c:243 catalog/pg_proc.c:250
#, c-format
msgid "cannot determine result data type"
msgstr "nie można określić typu wyniku"
@@ -4513,12 +4700,12 @@ msgstr "nie można określić typu wyniku"
msgid "An aggregate returning a polymorphic type must have at least one polymorphic argument."
msgstr "Agregat zwracający typ polimorficzny musi mieć co najmniej jeden argument polimorficzny."
-#: catalog/pg_aggregate.c:504 catalog/pg_proc.c:259
+#: catalog/pg_aggregate.c:504 catalog/pg_proc.c:256
#, c-format
msgid "unsafe use of pseudo-type \"internal\""
msgstr "niebezpieczne użycie pseudo-typu \"internal\""
-#: catalog/pg_aggregate.c:505 catalog/pg_proc.c:260
+#: catalog/pg_aggregate.c:505 catalog/pg_proc.c:257
#, c-format
msgid "A function returning \"internal\" must have at least one \"internal\" argument."
msgstr "Funkcja zwracająca \"internal\" musi mieć co najmniej jeden argument \"internal\"."
@@ -4533,62 +4720,74 @@ msgstr "implementacja przenoszącego agregatu zwraca typ %s, zaś pełna impleme
msgid "sort operator can only be specified for single-argument aggregates"
msgstr "operator sortowania może być określony tylko dla agregatów jednoargumentowych agregatów"
-#: catalog/pg_aggregate.c:812 commands/typecmds.c:1705
-#: commands/typecmds.c:1756 commands/typecmds.c:1787 commands/typecmds.c:1810
-#: commands/typecmds.c:1831 commands/typecmds.c:1858 commands/typecmds.c:1885
-#: commands/typecmds.c:1962 commands/typecmds.c:2004 parser/parse_func.c:364
-#: parser/parse_func.c:393 parser/parse_func.c:418 parser/parse_func.c:432
-#: parser/parse_func.c:507 parser/parse_func.c:518 parser/parse_func.c:1923
+#: catalog/pg_aggregate.c:810 commands/typecmds.c:1698
+#: commands/typecmds.c:1749 commands/typecmds.c:1780 commands/typecmds.c:1803
+#: commands/typecmds.c:1824 commands/typecmds.c:1851 commands/typecmds.c:1878
+#: commands/typecmds.c:1955 commands/typecmds.c:1997 parser/parse_func.c:365
+#: parser/parse_func.c:394 parser/parse_func.c:419 parser/parse_func.c:433
+#: parser/parse_func.c:508 parser/parse_func.c:519 parser/parse_func.c:1958
#, c-format
msgid "function %s does not exist"
msgstr "funkcja %s nie istnieje"
-#: catalog/pg_aggregate.c:818
+#: catalog/pg_aggregate.c:816
#, c-format
msgid "function %s returns a set"
msgstr "funkcja %s zwraca zbiór"
-#: catalog/pg_aggregate.c:833
+#: catalog/pg_aggregate.c:831
#, c-format
msgid "function %s must accept VARIADIC ANY to be used in this aggregate"
msgstr "funkcja %s musi przyjmować VARIADIC ANY aby ją wykorzystać w tym agregacie"
-#: catalog/pg_aggregate.c:857
+#: catalog/pg_aggregate.c:855
#, c-format
msgid "function %s requires run-time type coercion"
msgstr "funkcja %s wymaga zgodności typu czasu wykonania"
-#: catalog/pg_collation.c:77
+#: catalog/pg_collation.c:85 catalog/pg_collation.c:127
#, c-format
-msgid "collation \"%s\" for encoding \"%s\" already exists"
-msgstr "ograniczenie \"%s\" dla kodowania \"%s\" już istnieje"
+#| msgid "relation \"%s\" already exists, skipping"
+msgid "collation \"%s\" already exists, skipping"
+msgstr "porównanie \"%s\" już istnieje, pominięto"
-#: catalog/pg_collation.c:91
+#: catalog/pg_collation.c:87
+#, c-format
+#| msgid "collation \"%s\" for encoding \"%s\" already exists"
+msgid "collation \"%s\" for encoding \"%s\" already exists, skipping"
+msgstr "porównanie \"%s\" dla kodowania \"%s\" już istnieje, pominięto"
+
+#: catalog/pg_collation.c:95 catalog/pg_collation.c:134
#, c-format
msgid "collation \"%s\" already exists"
msgstr "porównanie \"%s\" już istnieje"
-#: catalog/pg_constraint.c:663
+#: catalog/pg_collation.c:97
+#, c-format
+msgid "collation \"%s\" for encoding \"%s\" already exists"
+msgstr "ograniczenie \"%s\" dla kodowania \"%s\" już istnieje"
+
+#: catalog/pg_constraint.c:658
#, c-format
msgid "constraint \"%s\" for domain %s already exists"
msgstr "ograniczenie \"%s\" dla domeny %s już istnieje"
-#: catalog/pg_constraint.c:797
+#: catalog/pg_constraint.c:788
#, c-format
msgid "table \"%s\" has multiple constraints named \"%s\""
msgstr "tabela \"%s\" ma wiele ograniczeń o nazwie \"%s\""
-#: catalog/pg_constraint.c:809
+#: catalog/pg_constraint.c:800
#, c-format
msgid "constraint \"%s\" for table \"%s\" does not exist"
msgstr "ograniczenie \"%s\" dla tabeli \"%s\" nie istnieje"
-#: catalog/pg_constraint.c:855
+#: catalog/pg_constraint.c:846
#, c-format
msgid "domain \"%s\" has multiple constraints named \"%s\""
msgstr "domena \"%s\" ma wiele ograniczeń o nazwie \"%s\""
-#: catalog/pg_constraint.c:867
+#: catalog/pg_constraint.c:858
#, c-format
msgid "constraint \"%s\" for domain \"%s\" does not exist"
msgstr "ograniczenie \"%s\" dla domeny \"%s\" nie istnieje"
@@ -4603,117 +4802,117 @@ msgstr "konwersja \"%s\" już istnieje"
msgid "default conversion for %s to %s already exists"
msgstr "domyślna konwersja z %s na %s już istnieje"
-#: catalog/pg_depend.c:165 commands/extension.c:3028
+#: catalog/pg_depend.c:163 commands/extension.c:3213
#, c-format
msgid "%s is already a member of extension \"%s\""
msgstr "%s jest już składnikiem rozszerzenia \"%s\""
-#: catalog/pg_depend.c:324
+#: catalog/pg_depend.c:322
#, c-format
msgid "cannot remove dependency on %s because it is a system object"
msgstr "nie można usunąć zależności od %s ponieważ jest ona obiektem systemowym"
-#: catalog/pg_enum.c:115 catalog/pg_enum.c:202
+#: catalog/pg_enum.c:115 catalog/pg_enum.c:201 catalog/pg_enum.c:488
#, c-format
msgid "invalid enum label \"%s\""
msgstr "nieprawidłowa etykieta enumeracji \"%s\""
-#: catalog/pg_enum.c:116 catalog/pg_enum.c:203
+#: catalog/pg_enum.c:116 catalog/pg_enum.c:202 catalog/pg_enum.c:489
#, c-format
msgid "Labels must be %d characters or less."
msgstr "Etykieta musi posiadać %d znaków lub mniej."
-#: catalog/pg_enum.c:231
+#: catalog/pg_enum.c:230
#, c-format
msgid "enum label \"%s\" already exists, skipping"
msgstr "etykieta wyliczenia \"%s\" już istnieje, pominięto"
-#: catalog/pg_enum.c:238
+#: catalog/pg_enum.c:237 catalog/pg_enum.c:532
#, c-format
msgid "enum label \"%s\" already exists"
msgstr "etykieta wyliczenia \"%s\" już istnieje"
-#: catalog/pg_enum.c:293
+#: catalog/pg_enum.c:292 catalog/pg_enum.c:527
#, c-format
msgid "\"%s\" is not an existing enum label"
msgstr "\"%s\" nie jest istniejącą wartością enumeracji"
-#: catalog/pg_enum.c:349
+#: catalog/pg_enum.c:350
#, c-format
msgid "pg_enum OID value not set when in binary upgrade mode"
msgstr "wartość OID pg_enum nieustawiona w binarnym trybie aktualizacji"
-#: catalog/pg_enum.c:359
+#: catalog/pg_enum.c:360
#, c-format
msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade"
msgstr "ALTER TYPE ADD BEFORE/AFTER nie jest zgodna z aktualizacją binarną"
-#: catalog/pg_namespace.c:61 commands/schemacmds.c:246
+#: catalog/pg_namespace.c:63 commands/schemacmds.c:264
#, c-format
msgid "schema \"%s\" already exists"
msgstr "schemat \"%s\" już istnieje"
-#: catalog/pg_operator.c:219 catalog/pg_operator.c:360
+#: catalog/pg_operator.c:219 catalog/pg_operator.c:358
#, c-format
msgid "\"%s\" is not a valid operator name"
msgstr "\"%s\" nie jest prawidłową nazwą operatora"
-#: catalog/pg_operator.c:369
+#: catalog/pg_operator.c:367
#, c-format
msgid "only binary operators can have commutators"
msgstr "tylko operatory binarne mogą mieć komutatory"
-#: catalog/pg_operator.c:373 commands/operatorcmds.c:485
+#: catalog/pg_operator.c:371 commands/operatorcmds.c:482
#, c-format
msgid "only binary operators can have join selectivity"
msgstr "tylko operatory binarne mogą mieć selektywność ograniczenia"
-#: catalog/pg_operator.c:377
+#: catalog/pg_operator.c:375
#, c-format
msgid "only binary operators can merge join"
msgstr "tylko operatory binarne mogą łączyć przez scalenie"
-#: catalog/pg_operator.c:381
+#: catalog/pg_operator.c:379
#, c-format
msgid "only binary operators can hash"
msgstr "tylko operatory binarne mogą haszować"
-#: catalog/pg_operator.c:392
+#: catalog/pg_operator.c:390
#, c-format
msgid "only boolean operators can have negators"
msgstr "tylko operatory logiczne mogą mieć negatory"
-#: catalog/pg_operator.c:396 commands/operatorcmds.c:493
+#: catalog/pg_operator.c:394 commands/operatorcmds.c:490
#, c-format
msgid "only boolean operators can have restriction selectivity"
msgstr "tylko operatory logiczne mogą mieć selektywność ograniczenia"
-#: catalog/pg_operator.c:400 commands/operatorcmds.c:497
+#: catalog/pg_operator.c:398 commands/operatorcmds.c:494
#, c-format
msgid "only boolean operators can have join selectivity"
msgstr "tylko operatory logiczne mogą mieć selektywność przyłączania"
-#: catalog/pg_operator.c:404
+#: catalog/pg_operator.c:402
#, c-format
msgid "only boolean operators can merge join"
msgstr "tylko operatory logiczne mogą łączyć przez scalenie"
-#: catalog/pg_operator.c:408
+#: catalog/pg_operator.c:406
#, c-format
msgid "only boolean operators can hash"
msgstr "tylko operatory logiczne mogą haszować"
-#: catalog/pg_operator.c:420
+#: catalog/pg_operator.c:418
#, c-format
msgid "operator %s already exists"
msgstr "operator %s już istnieje"
-#: catalog/pg_operator.c:617
+#: catalog/pg_operator.c:612
#, c-format
msgid "operator cannot be its own negator or sort operator"
msgstr "operator nie może być własnym negatorem ani operatorem sortowania"
-#: catalog/pg_proc.c:134 parser/parse_func.c:1947 parser/parse_func.c:1987
+#: catalog/pg_proc.c:131 parser/parse_func.c:1982 parser/parse_func.c:2022
#, c-format
msgid "functions cannot have more than %d argument"
msgid_plural "functions cannot have more than %d arguments"
@@ -4721,98 +4920,140 @@ msgstr[0] "funkcje nie mogą mieć więcej niż %d argument"
msgstr[1] "funkcje nie mogą mieć więcej niż %d argumenty"
msgstr[2] "funkcje nie mogą mieć więcej niż %d argumentów"
-#: catalog/pg_proc.c:247
+#: catalog/pg_proc.c:244
#, c-format
msgid "A function returning a polymorphic type must have at least one polymorphic argument."
msgstr "Funkcja zwracająca typ polimorficzny musi mieć co najmniej jeden argument polimorficzny."
-#: catalog/pg_proc.c:254
+#: catalog/pg_proc.c:251
#, c-format
msgid "A function returning \"anyrange\" must have at least one \"anyrange\" argument."
msgstr "Funkcja zwracająca \"anyrange\" musi mieć co najmniej jeden argument \"anyrange\"."
-#: catalog/pg_proc.c:272
+#: catalog/pg_proc.c:269
#, c-format
msgid "\"%s\" is already an attribute of type %s"
msgstr "\"%s\" jest już atrybutem typu %s"
-#: catalog/pg_proc.c:403
+#: catalog/pg_proc.c:400
#, c-format
msgid "function \"%s\" already exists with same argument types"
msgstr "funkcja \"%s\" z argumentami identycznego typu już istnieje"
-#: catalog/pg_proc.c:417 catalog/pg_proc.c:440
+#: catalog/pg_proc.c:414 catalog/pg_proc.c:437
#, c-format
msgid "cannot change return type of existing function"
msgstr "nie można zmieniać zwracanego typu istniejącej funkcji"
-#: catalog/pg_proc.c:418 catalog/pg_proc.c:442 catalog/pg_proc.c:485
-#: catalog/pg_proc.c:509 catalog/pg_proc.c:536
+#: catalog/pg_proc.c:415 catalog/pg_proc.c:439 catalog/pg_proc.c:482
+#: catalog/pg_proc.c:506 catalog/pg_proc.c:532
#, c-format
msgid "Use DROP FUNCTION %s first."
msgstr "Użyj najpierw DROP FUNCTION %s."
-#: catalog/pg_proc.c:441
+#: catalog/pg_proc.c:438
#, c-format
msgid "Row type defined by OUT parameters is different."
msgstr "Typ rekordu zdefiniowany przez parametr OUT jest inny."
-#: catalog/pg_proc.c:483
+#: catalog/pg_proc.c:480
#, c-format
msgid "cannot change name of input parameter \"%s\""
msgstr "nie można zmienić nazwy parametru wejściowego \"%s\""
-#: catalog/pg_proc.c:508
+#: catalog/pg_proc.c:505
#, c-format
msgid "cannot remove parameter defaults from existing function"
msgstr "nie można zmieniać domyślnych wartości parametru z istniejącej funkcji"
-#: catalog/pg_proc.c:535
+#: catalog/pg_proc.c:531
#, c-format
msgid "cannot change data type of existing parameter default value"
msgstr "nie można zmieniać typu danych wartości domyślnej istniejącego parametru"
-#: catalog/pg_proc.c:548
+#: catalog/pg_proc.c:544
#, c-format
msgid "function \"%s\" is an aggregate function"
msgstr "funkcja \"%s\" jest funkcją agregującą"
-#: catalog/pg_proc.c:553
+#: catalog/pg_proc.c:549
#, c-format
msgid "function \"%s\" is not an aggregate function"
msgstr "funkcja \"%s\" nie jest funkcją agregującą"
-#: catalog/pg_proc.c:561
+#: catalog/pg_proc.c:557
#, c-format
msgid "function \"%s\" is a window function"
msgstr "funkcja \"%s\" jest funkcją okna"
-#: catalog/pg_proc.c:566
+#: catalog/pg_proc.c:562
#, c-format
msgid "function \"%s\" is not a window function"
msgstr "funkcja \"%s\" nie jest funkcją okna"
-#: catalog/pg_proc.c:774
+#: catalog/pg_proc.c:768
#, c-format
msgid "there is no built-in function named \"%s\""
msgstr "brak wbudowanej funkcji o nazwie \"%s\""
-#: catalog/pg_proc.c:872
+#: catalog/pg_proc.c:866
#, c-format
msgid "SQL functions cannot return type %s"
msgstr "funkcja SQL nie może zwracać typu %s"
-#: catalog/pg_proc.c:887
+#: catalog/pg_proc.c:881
#, c-format
msgid "SQL functions cannot have arguments of type %s"
msgstr "funkcja SQL nie może posiadać argumentów typu %s"
-#: catalog/pg_proc.c:973 executor/functions.c:1424
+#: catalog/pg_proc.c:968 executor/functions.c:1428
#, c-format
msgid "SQL function \"%s\""
msgstr "funkcja SQL \"%s\""
-#: catalog/pg_shdepend.c:694
+#: catalog/pg_publication.c:59
+#, c-format
+msgid "Only tables can be added to publications."
+msgstr "Tylko tabele mogą być dodane do publikacji."
+
+#: catalog/pg_publication.c:65
+#, c-format
+#| msgid "\"%s\" is a table"
+msgid "\"%s\" is a system table"
+msgstr "\"%s\" jest tabelą systemową"
+
+#: catalog/pg_publication.c:67
+#, c-format
+#| msgid "%s cannot be applied to a function"
+msgid "System tables cannot be added to publications."
+msgstr "Tabele systemowe nie mogą być dodawane do publikacji."
+
+#: catalog/pg_publication.c:73
+#, c-format
+#| msgid "portal \"%s\" cannot be run"
+msgid "table \"%s\" cannot be replicated"
+msgstr "tabela \"%s\" nie może być replikowana"
+
+#: catalog/pg_publication.c:75
+#, c-format
+#| msgid "cannot access temporary or unlogged relations during recovery"
+msgid "Temporary and unlogged relations cannot be replicated."
+msgstr "Tymczasowe lub nielogowane relacje nie mogą być replikowane."
+
+#: catalog/pg_publication.c:134
+#, c-format
+#| msgid "role \"%s\" is already a member of role \"%s\""
+msgid "relation \"%s\" is already member of publication \"%s\""
+msgstr "relacja \"%s\" jest już członkiem publikacji \"%s\""
+
+#: catalog/pg_publication.c:361 catalog/pg_publication.c:382
+#: commands/publicationcmds.c:430 commands/publicationcmds.c:729
+#, c-format
+#| msgid "relation \"%s\" does not exist"
+msgid "publication \"%s\" does not exist"
+msgstr "publikacja \"%s\" nie istnieje"
+
+#: catalog/pg_shdepend.c:692
#, c-format
msgid ""
"\n"
@@ -4830,38 +5071,38 @@ msgstr[2] ""
"\n"
"i obiekty z %d innych baz danych (lista w dzienniku serwera)"
-#: catalog/pg_shdepend.c:1006
+#: catalog/pg_shdepend.c:998
#, c-format
msgid "role %u was concurrently dropped"
msgstr "rola %u została równocześnie usunięta"
-#: catalog/pg_shdepend.c:1025
+#: catalog/pg_shdepend.c:1017
#, c-format
msgid "tablespace %u was concurrently dropped"
msgstr "przestrzeń tabel %u została równocześnie usunięta"
-#: catalog/pg_shdepend.c:1040
+#: catalog/pg_shdepend.c:1032
#, c-format
msgid "database %u was concurrently dropped"
msgstr "baza danych %u została równocześnie usunięta"
-#: catalog/pg_shdepend.c:1085
+#: catalog/pg_shdepend.c:1077
#, c-format
msgid "owner of %s"
msgstr "właściciel %s"
-#: catalog/pg_shdepend.c:1087
+#: catalog/pg_shdepend.c:1079
#, c-format
msgid "privileges for %s"
msgstr "uprawnienia dla %s"
-#: catalog/pg_shdepend.c:1089
+#: catalog/pg_shdepend.c:1081
#, c-format
msgid "target of %s"
msgstr "cel %s"
#. translator: %s will always be "database %s"
-#: catalog/pg_shdepend.c:1097
+#: catalog/pg_shdepend.c:1089
#, c-format
msgid "%d object in %s"
msgid_plural "%d objects in %s"
@@ -4869,54 +5110,61 @@ msgstr[0] "%d obiekt w %s"
msgstr[1] "%d obiekty w %s"
msgstr[2] "%d obiektów w %s"
-#: catalog/pg_shdepend.c:1208
+#: catalog/pg_shdepend.c:1200
#, c-format
msgid "cannot drop objects owned by %s because they are required by the database system"
msgstr "nie można skasować obiektów posiadanych przez %s ponieważ są one wymagane przez system bazy danych"
-#: catalog/pg_shdepend.c:1323
+#: catalog/pg_shdepend.c:1315
#, c-format
msgid "cannot reassign ownership of objects owned by %s because they are required by the database system"
msgstr "nie można przydzielić ponownie obiektów posiadanych przez %s ponieważ są one wymagane przez system bazy danych"
-#: catalog/pg_type.c:136 catalog/pg_type.c:454
+#: catalog/pg_subscription.c:163 commands/subscriptioncmds.c:565
+#: commands/subscriptioncmds.c:734 commands/subscriptioncmds.c:912
+#, c-format
+#| msgid "descriptor \"%s\" does not exist"
+msgid "subscription \"%s\" does not exist"
+msgstr "subskrypcja \"%s\" nie istnieje"
+
+#: catalog/pg_type.c:136 catalog/pg_type.c:452
#, c-format
msgid "pg_type OID value not set when in binary upgrade mode"
msgstr "wartość OID typu nieustawiona w binarnym trybie aktualizacji"
-#: catalog/pg_type.c:253
+#: catalog/pg_type.c:251
#, c-format
msgid "invalid type internal size %d"
msgstr "niepoprawny rozmiar wewnętrzny typu %d"
-#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285
-#: catalog/pg_type.c:294
+#: catalog/pg_type.c:267 catalog/pg_type.c:275 catalog/pg_type.c:283
+#: catalog/pg_type.c:292
#, c-format
msgid "alignment \"%c\" is invalid for passed-by-value type of size %d"
msgstr "wyrównanie \"%c\" jest niepoprawne dla przekazywanego przez wartość typu o rozmiarze %d"
-#: catalog/pg_type.c:301
+#: catalog/pg_type.c:299
#, c-format
msgid "internal size %d is invalid for passed-by-value type"
msgstr "wewnętrzny rozmiar %d jest niepoprawny dla typu przekazywanego przez wartość"
-#: catalog/pg_type.c:310 catalog/pg_type.c:316
+#: catalog/pg_type.c:308 catalog/pg_type.c:314
#, c-format
msgid "alignment \"%c\" is invalid for variable-length type"
msgstr "wyrównanie \"%c\" jest niepoprawne dla typu o zmiennej długości"
-#: catalog/pg_type.c:324
+#: catalog/pg_type.c:322
#, c-format
msgid "fixed-size types must have storage PLAIN"
msgstr "typy o stałej długości muszą mieć przechowywanie PLAIN"
-#: catalog/pg_type.c:789
+#: catalog/pg_type.c:781
#, c-format
msgid "could not form array type name for type \"%s\""
msgstr "nie udało się utworzyć nazwy typu tablicowego dla typu \"%s\""
-#: catalog/toasting.c:105 commands/indexcmds.c:389 commands/tablecmds.c:4358
-#: commands/tablecmds.c:11900
+#: catalog/toasting.c:105 commands/indexcmds.c:395 commands/tablecmds.c:4712
+#: commands/tablecmds.c:12921
#, c-format
msgid "\"%s\" is not a table or materialized view"
msgstr "\"%s\" nie jest widokiem zmaterializowanym"
@@ -4926,258 +5174,262 @@ msgstr "\"%s\" nie jest widokiem zmaterializowanym"
msgid "shared tables cannot be toasted after initdb"
msgstr "tabele współdzielone nie mogą być prażone po initdb"
-#: commands/aggregatecmds.c:159
+#: commands/aggregatecmds.c:157
#, c-format
msgid "only ordered-set aggregates can be hypothetical"
msgstr "tylko agregaty uporządkowanego zbioru mogą być hipotetyczne"
-#: commands/aggregatecmds.c:184
+#: commands/aggregatecmds.c:182
#, c-format
msgid "aggregate attribute \"%s\" not recognized"
msgstr "atrybut agregatu \"%s\" nie rozpoznany"
-#: commands/aggregatecmds.c:194
+#: commands/aggregatecmds.c:192
#, c-format
msgid "aggregate stype must be specified"
msgstr "konieczne wskazanie stype agregatu"
-#: commands/aggregatecmds.c:198
+#: commands/aggregatecmds.c:196
#, c-format
msgid "aggregate sfunc must be specified"
msgstr "konieczne wskazanie sfunc agregatu"
-#: commands/aggregatecmds.c:210
+#: commands/aggregatecmds.c:208
#, c-format
msgid "aggregate msfunc must be specified when mstype is specified"
msgstr "msfunc agregatu musi być określona gdy określony jest mstype"
-#: commands/aggregatecmds.c:214
+#: commands/aggregatecmds.c:212
#, c-format
msgid "aggregate minvfunc must be specified when mstype is specified"
msgstr "agregat minvfunc musi być określony gdy określona jest mstype"
-#: commands/aggregatecmds.c:221
+#: commands/aggregatecmds.c:219
#, c-format
msgid "aggregate msfunc must not be specified without mstype"
msgstr "agregat msfunc nie może być określony bez mstype"
-#: commands/aggregatecmds.c:225
+#: commands/aggregatecmds.c:223
#, c-format
msgid "aggregate minvfunc must not be specified without mstype"
msgstr "agregat minvfunc nie może być określony bez mstype"
-#: commands/aggregatecmds.c:229
+#: commands/aggregatecmds.c:227
#, c-format
msgid "aggregate mfinalfunc must not be specified without mstype"
msgstr "agregat mfinalfunc nie może być określony bez mstype"
-#: commands/aggregatecmds.c:233
+#: commands/aggregatecmds.c:231
#, c-format
msgid "aggregate msspace must not be specified without mstype"
msgstr "agregat msspace nie może być określony bez mstype"
-#: commands/aggregatecmds.c:237
+#: commands/aggregatecmds.c:235
#, c-format
msgid "aggregate minitcond must not be specified without mstype"
msgstr "agregat minitcond nie może być określony bez mstype"
-#: commands/aggregatecmds.c:257
+#: commands/aggregatecmds.c:255
#, c-format
msgid "aggregate input type must be specified"
msgstr "konieczne wskazanie typu wejścia agregatu"
-#: commands/aggregatecmds.c:287
+#: commands/aggregatecmds.c:285
#, c-format
msgid "basetype is redundant with aggregate input type specification"
msgstr "typ bazowy jest nadmierny z jednoczesnym wskazaniem typu wejścia"
-#: commands/aggregatecmds.c:328 commands/aggregatecmds.c:369
+#: commands/aggregatecmds.c:326 commands/aggregatecmds.c:367
#, c-format
msgid "aggregate transition data type cannot be %s"
msgstr "typ danych transformacji agregatu nie może być %s"
-#: commands/aggregatecmds.c:340
+#: commands/aggregatecmds.c:338
#, c-format
msgid "serialization functions may be specified only when the aggregate transition data type is %s"
-msgstr ""
-"funkcje deserializacyjne mogą być określone tylko gdy typ danych przejścia "
-"agregującego to %s"
+msgstr "funkcje deserializacyjne mogą być określone tylko gdy typ danych przejścia agregującego to %s"
-#: commands/aggregatecmds.c:350
+#: commands/aggregatecmds.c:348
#, c-format
msgid "must specify both or neither of serialization and deserialization functions"
-msgstr ""
-"trzeba wskazać obie lub żadnej z funkcji serializującej i deserializującej"
+msgstr "trzeba wskazać obie lub żadnej z funkcji serializującej i deserializującej"
-#: commands/aggregatecmds.c:415 commands/functioncmds.c:570
+#: commands/aggregatecmds.c:413 commands/functioncmds.c:564
#, c-format
msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE"
-msgstr ""
-"parametr \"parallel\" musi przyjmować wartość SAFE, RESTRICTED, albo UNSAFE"
+msgstr "parametr \"parallel\" musi przyjmować wartość SAFE, RESTRICTED, albo UNSAFE"
-#: commands/alter.c:80 commands/event_trigger.c:231
+#: commands/alter.c:84 commands/event_trigger.c:234
#, c-format
msgid "event trigger \"%s\" already exists"
msgstr "wyzwalacz zdarzeniowy \"%s\" już istnieje"
-#: commands/alter.c:83 commands/foreigncmds.c:597
+#: commands/alter.c:87 commands/foreigncmds.c:595
#, c-format
msgid "foreign-data wrapper \"%s\" already exists"
msgstr "opakowanie danych obcych \"%s\" już istnieje"
-#: commands/alter.c:86 commands/foreigncmds.c:890
+#: commands/alter.c:90 commands/foreigncmds.c:898
#, c-format
msgid "server \"%s\" already exists"
msgstr "serwer \"%s\" już istnieje"
-#: commands/alter.c:89 commands/proclang.c:366
+#: commands/alter.c:93 commands/proclang.c:367
#, c-format
msgid "language \"%s\" already exists"
msgstr "język \"%s\" już istnieje"
-#: commands/alter.c:112
+#: commands/alter.c:96 commands/publicationcmds.c:189
+#, c-format
+#| msgid "relation \"%s\" already exists"
+msgid "publication \"%s\" already exists"
+msgstr "publikacja \"%s\" już istnieje"
+
+#: commands/alter.c:99 commands/subscriptioncmds.c:308
+#, c-format
+#| msgid "relation \"%s\" already exists"
+msgid "subscription \"%s\" already exists"
+msgstr "subskrypcja \"%s\" już istnieje"
+
+#: commands/alter.c:122
#, c-format
msgid "conversion \"%s\" already exists in schema \"%s\""
msgstr "konwersja \"%s\" istnieje już w schemacie \"%s\""
-#: commands/alter.c:116
+#: commands/alter.c:126
+#, c-format
+#| msgid "relation \"%s\" already exists in schema \"%s\""
+msgid "statistics \"%s\" already exists in schema \"%s\""
+msgstr "statystyka \"%s\" istnieje już w schemacie \"%s\""
+
+#: commands/alter.c:130
#, c-format
msgid "text search parser \"%s\" already exists in schema \"%s\""
msgstr "parser wyszukiwania tekstowego \"%s\" już istnieje w schemacie \"%s\""
-#: commands/alter.c:120
+#: commands/alter.c:134
#, c-format
msgid "text search dictionary \"%s\" already exists in schema \"%s\""
msgstr "słownik wyszukiwania tekstowego \"%s\" już istnieje w schemacie \"%s\""
-#: commands/alter.c:124
+#: commands/alter.c:138
#, c-format
msgid "text search template \"%s\" already exists in schema \"%s\""
msgstr "szablon wyszukiwania tekstowego \"%s\" już istnieje w schemacie \"%s\""
-#: commands/alter.c:128
+#: commands/alter.c:142
#, c-format
msgid "text search configuration \"%s\" already exists in schema \"%s\""
msgstr "konfiguracja wyszukiwania tekstowego \"%s\" już istnieje w schemacie \"%s\""
-#: commands/alter.c:202
+#: commands/alter.c:216
#, c-format
msgid "must be superuser to rename %s"
msgstr "musisz być superużytkownikiem by zmienić nazwę %s"
-#: commands/alter.c:655
+#: commands/alter.c:677
#, c-format
msgid "must be superuser to set schema of %s"
msgstr "musisz być superużytkownikiem aby ustawić schemat dla %s"
#: commands/amcmds.c:58
#, c-format
-#| msgid "permission denied to create tablespace \"%s\""
msgid "permission denied to create access method \"%s\""
msgstr "odmowa dostępu do tworzenia metody dostępu \"%s\""
#: commands/amcmds.c:60
#, c-format
-#| msgid "Must be superuser to create a tablespace."
msgid "Must be superuser to create an access method."
msgstr "Musisz być superużytkownikiem aby utworzyć metodę dostępu."
#: commands/amcmds.c:68
#, c-format
-#| msgid "access method \"%s\" does not exist"
msgid "access method \"%s\" already exists"
msgstr "metoda dostępu \"%s\" już istnieje"
-#: commands/amcmds.c:124
+#: commands/amcmds.c:123
#, c-format
-#| msgid "must be superuser to drop superusers"
msgid "must be superuser to drop access methods"
msgstr "musisz być superużytkownikiem aby usuwać metody dostępu"
-#: commands/amcmds.c:175 commands/indexcmds.c:164 commands/indexcmds.c:495
-#: commands/opclasscmds.c:365 commands/opclasscmds.c:790
+#: commands/amcmds.c:174 commands/indexcmds.c:163 commands/indexcmds.c:502
+#: commands/opclasscmds.c:363 commands/opclasscmds.c:777
#, c-format
msgid "access method \"%s\" does not exist"
msgstr "metoda dostępu \"%s\" nie istnieje"
-#: commands/amcmds.c:251
+#: commands/amcmds.c:250
#, c-format
-#| msgid "no function body specified"
msgid "handler function is not specified"
msgstr "nie określono funkcji obsługi"
-#: commands/amcmds.c:263 commands/event_trigger.c:240
-#: commands/foreigncmds.c:489 commands/proclang.c:117 commands/proclang.c:288
-#: commands/trigger.c:441 parser/parse_clause.c:761
+#: commands/amcmds.c:262 commands/event_trigger.c:243
+#: commands/foreigncmds.c:487 commands/proclang.c:117 commands/proclang.c:289
+#: commands/trigger.c:538 parser/parse_clause.c:986
#, c-format
-#| msgid "function %s should return type %s"
msgid "function %s must return type %s"
msgstr "funkcja %s musi zwracać typ %s"
-#: commands/analyze.c:145
+#: commands/analyze.c:151
#, c-format
msgid "skipping analyze of \"%s\" --- lock not available"
msgstr "pominięto analizę \"%s\" --- blokada niedostępna"
-#: commands/analyze.c:162
+#: commands/analyze.c:168
#, c-format
msgid "skipping \"%s\" --- only superuser can analyze it"
msgstr "pominięto \"%s\" --- tylko superużytkownik może to analizować"
-#: commands/analyze.c:166
+#: commands/analyze.c:172
#, c-format
msgid "skipping \"%s\" --- only superuser or database owner can analyze it"
msgstr "pominięto \"%s\" --- tylko właściciel bazy danych może to analizować"
-#: commands/analyze.c:170
+#: commands/analyze.c:176
#, c-format
msgid "skipping \"%s\" --- only table or database owner can analyze it"
msgstr "pominięto \"%s\" --- tylko właściciel tabeli lub bazy danych może to analizować"
-#: commands/analyze.c:230
+#: commands/analyze.c:236
#, c-format
msgid "skipping \"%s\" --- cannot analyze this foreign table"
msgstr "pominięto \"%s\" --- nie można analizować tej tabeli obcej"
-#: commands/analyze.c:241
+#: commands/analyze.c:253
#, c-format
msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables"
msgstr "pominięto \"%s\" --- nie można analizować nie tabel ani specjalnych tabel systemowych"
-#: commands/analyze.c:320
+#: commands/analyze.c:334
#, c-format
msgid "analyzing \"%s.%s\" inheritance tree"
msgstr "analiza drzewa dziedziczenia \"%s.%s\""
-#: commands/analyze.c:325
+#: commands/analyze.c:339
#, c-format
msgid "analyzing \"%s.%s\""
msgstr "analiza \"%s.%s\""
-#: commands/analyze.c:654
+#: commands/analyze.c:668
#, c-format
msgid "automatic analyze of table \"%s.%s.%s\" system usage: %s"
msgstr "automatyczna analiza użycia tabeli \"%s.%s.%s\" przez system: %s"
-#: commands/analyze.c:1210
+#: commands/analyze.c:1220
#, c-format
msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows"
msgstr "\"%s\": przeskanowano %d z %u stron, zawierających %.0f żywych wierszy i %.0f martwych wierszy; %d wierszy w przykładzie, %.0f szacowanych wszystkich wierszy"
-#: commands/analyze.c:1289
+#: commands/analyze.c:1300
#, c-format
msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables"
msgstr "pominięcie analizy drzewa dziedziczenia \"%s.%s\" --- to drzewo dziedziczenia nie ma tabel potomnych"
-#: commands/analyze.c:1378
+#: commands/analyze.c:1398
#, c-format
msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables"
msgstr "pominięcie analizy drzewa dziedziczenia \"%s.%s\" --- to drzewo dziedziczenia nie ma tabel potomnych dostępnych do analizowania"
-#: commands/analyze.c:1426 executor/execQual.c:2922
-msgid "could not convert row type"
-msgstr "nie można przekształcić typu wierszowego"
-
#: commands/async.c:555
#, c-format
msgid "channel name cannot be empty"
@@ -5218,7 +5470,7 @@ msgstr "Proces serwera o PID %d jest pośród tych z najstarszymi transakcjami."
msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction."
msgstr "Kolejka NOTIFY nie może być opróżniona dopóki procesy z niej nie zakończą swoich bieżące transakcji."
-#: commands/cluster.c:129 commands/cluster.c:366
+#: commands/cluster.c:129 commands/cluster.c:364
#, c-format
msgid "cannot cluster temporary tables of other sessions"
msgstr "nie można sklastrować tabel tymczasowych z innych sesji"
@@ -5228,62 +5480,63 @@ msgstr "nie można sklastrować tabel tymczasowych z innych sesji"
msgid "there is no previously clustered index for table \"%s\""
msgstr "nie ma uprzednio sklastrowanego indeksu dla tabeli \"%s\""
-#: commands/cluster.c:173 commands/tablecmds.c:9286 commands/tablecmds.c:11002
+#: commands/cluster.c:173 commands/tablecmds.c:10151
+#: commands/tablecmds.c:12014
#, c-format
msgid "index \"%s\" for table \"%s\" does not exist"
msgstr "indeks \"%s\" dla tabeli \"%s\" nie istnieje"
-#: commands/cluster.c:355
+#: commands/cluster.c:353
#, c-format
msgid "cannot cluster a shared catalog"
msgstr "nie można sklastrować współdzielonego katalogu"
-#: commands/cluster.c:370
+#: commands/cluster.c:368
#, c-format
msgid "cannot vacuum temporary tables of other sessions"
msgstr "nie można odkurzyć tabel tymczasowych z innych sesji"
-#: commands/cluster.c:433 commands/tablecmds.c:11012
+#: commands/cluster.c:431 commands/tablecmds.c:12024
#, c-format
msgid "\"%s\" is not an index for table \"%s\""
msgstr "\"%s\" nie jest indeksem dla tabeli \"%s\""
-#: commands/cluster.c:441
+#: commands/cluster.c:439
#, c-format
msgid "cannot cluster on index \"%s\" because access method does not support clustering"
msgstr "nie można klastrować na indeksie \"%s\" ponieważ metoda dostępu nie obsługuje klastrowania"
-#: commands/cluster.c:453
+#: commands/cluster.c:451
#, c-format
msgid "cannot cluster on partial index \"%s\""
msgstr "nie można sklastrować indeksu częściowego \"%s\""
-#: commands/cluster.c:467
+#: commands/cluster.c:465
#, c-format
msgid "cannot cluster on invalid index \"%s\""
msgstr "nie można sklastrować niepoprawnego indeksu \"%s\""
-#: commands/cluster.c:920
+#: commands/cluster.c:918
#, c-format
msgid "clustering \"%s.%s\" using index scan on \"%s\""
msgstr "klastrowanie \"%s.%s\" przy użyciu skanowania indeksu na \"%s\""
-#: commands/cluster.c:926
+#: commands/cluster.c:924
#, c-format
msgid "clustering \"%s.%s\" using sequential scan and sort"
msgstr "klastrowanie \"%s.%s\" przy użyciu skanu sekwencyjnego i sortowania"
-#: commands/cluster.c:931 commands/vacuumlazy.c:479
+#: commands/cluster.c:929 commands/vacuumlazy.c:491
#, c-format
msgid "vacuuming \"%s.%s\""
msgstr "odkurzanie \"%s.%s\""
-#: commands/cluster.c:1090
+#: commands/cluster.c:1084
#, c-format
msgid "\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages"
msgstr "\"%s\": znaleziono %.0f usuwalnych, %.0f nieusuwalnych wersji wierszy na %u stronach"
-#: commands/cluster.c:1094
+#: commands/cluster.c:1088
#, c-format
msgid ""
"%.0f dead row versions cannot be removed yet.\n"
@@ -5292,51 +5545,109 @@ msgstr ""
"%.0f martwych wersji wierszy nie może być jeszcze usuniętych.\n"
"%s."
-#: commands/collationcmds.c:80
+#: commands/collationcmds.c:93
#, c-format
msgid "collation attribute \"%s\" not recognized"
msgstr "atrybut porównania \"%s\" nie rozpoznany"
-#: commands/collationcmds.c:125
+#: commands/collationcmds.c:152
+#, c-format
+#| msgid "unrecognized configuration parameter \"%s\""
+msgid "unrecognized collation provider: %s"
+msgstr "nierozpoznany dostawca porównania: %s"
+
+#: commands/collationcmds.c:161
#, c-format
msgid "parameter \"lc_collate\" must be specified"
msgstr "parametr \"lc_collate\" musi być określony"
-#: commands/collationcmds.c:130
+#: commands/collationcmds.c:166
#, c-format
msgid "parameter \"lc_ctype\" must be specified"
msgstr "parametr \"lc_ctype\" musi być określony"
-#: commands/collationcmds.c:166
+#: commands/collationcmds.c:217
#, c-format
msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\""
msgstr "porównanie \"%s\" kodowania \"%s\" istnieje już w schemacie \"%s\""
-#: commands/collationcmds.c:177
+#: commands/collationcmds.c:228
#, c-format
msgid "collation \"%s\" already exists in schema \"%s\""
msgstr "porównanie \"%s\" istnieje już w schemacie \"%s\""
-#: commands/comment.c:62 commands/dbcommands.c:797 commands/dbcommands.c:962
-#: commands/dbcommands.c:1067 commands/dbcommands.c:1257
-#: commands/dbcommands.c:1477 commands/dbcommands.c:1594
-#: commands/dbcommands.c:2011 utils/init/postinit.c:843
-#: utils/init/postinit.c:945 utils/init/postinit.c:962
+#: commands/collationcmds.c:276
+#, c-format
+#| msgid "changing return type of function %s from %s to %s"
+msgid "changing version from %s to %s"
+msgstr "zmiana wersji z %s na %s"
+
+#: commands/collationcmds.c:291
+#, c-format
+msgid "version has not changed"
+msgstr "nie zmieniono wersji"
+
+#: commands/collationcmds.c:382
+#, c-format
+#| msgid "could not connect to database \"%s\" on line %d"
+msgid "could not convert locale name \"%s\" to language tag: %s"
+msgstr "nie można zmienić nazwy lokalizacji \"%s\" na znacznik języka: %s"
+
+#: commands/collationcmds.c:401
+#, c-format
+#| msgid "could not create locale \"%s\": %m"
+msgid "could get display name for locale \"%s\": %s"
+msgstr "nie można wyświetlić nazwy dla lokalizacji \"%s\": %s"
+
+#: commands/collationcmds.c:432
+#, c-format
+#| msgid "must be superuser to get file information"
+msgid "must be superuser to import system collations"
+msgstr "musisz być superużytkownikiem by importować porównania systemowe"
+
+#: commands/collationcmds.c:439 commands/copy.c:1835 commands/copy.c:3027
+#, c-format
+msgid "could not execute command \"%s\": %m"
+msgstr "nie udało się wykonać polecenia \"%s\": %m"
+
+#: commands/collationcmds.c:536
+#, c-format
+#| msgid "No usable system locales were found.\n"
+msgid "no usable system locales were found"
+msgstr "nie znaleziono żadnych używalnych lokalizacji systemowych"
+
+#: commands/collationcmds.c:544 utils/mb/encnames.c:473
+#, c-format
+#| msgid "interval units \"%s\" not supported"
+msgid "encoding \"%s\" not supported by ICU"
+msgstr "kodowanie \"%s\" nieobsługiwane przez ICU"
+
+#: commands/collationcmds.c:588 commands/collationcmds.c:609
+#, c-format
+#| msgid "could not open backend variables file \"%s\": %s\n"
+msgid "could not get keyword values for locale \"%s\": %s"
+msgstr "nie można pobrać wartości słów kluczowych dla lokalizacji \"%s\": %s"
+
+#: commands/comment.c:61 commands/dbcommands.c:808 commands/dbcommands.c:996
+#: commands/dbcommands.c:1100 commands/dbcommands.c:1290
+#: commands/dbcommands.c:1513 commands/dbcommands.c:1627
+#: commands/dbcommands.c:2043 utils/init/postinit.c:846
+#: utils/init/postinit.c:951 utils/init/postinit.c:968
#, c-format
msgid "database \"%s\" does not exist"
msgstr "baza danych \"%s\" nie istnieje"
-#: commands/comment.c:101 commands/seclabel.c:116 parser/parse_utilcmd.c:768
+#: commands/comment.c:100 commands/seclabel.c:117 parser/parse_utilcmd.c:921
#, c-format
msgid "\"%s\" is not a table, view, materialized view, composite type, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem, widokiem materializowanym, typem złożonym ani tabelą zewnętrzną"
-#: commands/constraint.c:60 utils/adt/ri_triggers.c:2717
+#: commands/constraint.c:60 utils/adt/ri_triggers.c:2715
#, c-format
msgid "function \"%s\" was not called by trigger manager"
msgstr "funkcja \"%s\" nie była wywołana przez menadżera wyzwalaczy"
-#: commands/constraint.c:67 utils/adt/ri_triggers.c:2726
+#: commands/constraint.c:67 utils/adt/ri_triggers.c:2724
#, c-format
msgid "function \"%s\" must be fired AFTER ROW"
msgstr "funkcja \"%s\" musi być odpalana AFTER ROW"
@@ -5346,538 +5657,556 @@ msgstr "funkcja \"%s\" musi być odpalana AFTER ROW"
msgid "function \"%s\" must be fired for INSERT or UPDATE"
msgstr "funkcja \"%s\" musi być odpalona dla INSERT lub UPDATE"
-#: commands/conversioncmds.c:67
+#: commands/conversioncmds.c:66
#, c-format
msgid "source encoding \"%s\" does not exist"
msgstr "kodowanie źródłowe \"%s\" nie istnieje"
-#: commands/conversioncmds.c:74
+#: commands/conversioncmds.c:73
#, c-format
msgid "destination encoding \"%s\" does not exist"
msgstr "kodowanie docelowe \"%s\" nie istnieje"
-#: commands/conversioncmds.c:88
+#: commands/conversioncmds.c:87
#, c-format
-#| msgid "encoding conversion function %s must return type \"void\""
msgid "encoding conversion function %s must return type %s"
msgstr "funkcja konwersji kodowania %s musi zwracać typ %s"
-#: commands/copy.c:362 commands/copy.c:374 commands/copy.c:408
-#: commands/copy.c:420
+#: commands/copy.c:370 commands/copy.c:404
#, c-format
msgid "COPY BINARY is not supported to stdout or from stdin"
msgstr "COPY BINARY nie jest obsługiwane do stdout ani ze stdin"
-#: commands/copy.c:520
+#: commands/copy.c:504
#, c-format
msgid "could not write to COPY program: %m"
msgstr "nie można pisać do programu COPY: %m"
-#: commands/copy.c:525
+#: commands/copy.c:509
#, c-format
msgid "could not write to COPY file: %m"
msgstr "nie można pisać do pliku COPY: %m"
-#: commands/copy.c:538
+#: commands/copy.c:522
#, c-format
msgid "connection lost during COPY to stdout"
msgstr "utracono połączenie podczas DOPY do stdout"
-#: commands/copy.c:579
+#: commands/copy.c:566
#, c-format
msgid "could not read from COPY file: %m"
msgstr "nie można czytać z pliku COPY: %m"
-#: commands/copy.c:595 commands/copy.c:616 commands/copy.c:620
+#: commands/copy.c:582 commands/copy.c:603 commands/copy.c:607
#: tcop/postgres.c:341 tcop/postgres.c:377 tcop/postgres.c:404
#, c-format
msgid "unexpected EOF on client connection with an open transaction"
msgstr "nieoczekiwany EOF w połączeniu klienta przy otwartej transakcji"
-#: commands/copy.c:633
+#: commands/copy.c:620
#, c-format
msgid "COPY from stdin failed: %s"
msgstr "nie powiodło się COPY ze stdin: %s"
-#: commands/copy.c:649
+#: commands/copy.c:636
#, c-format
msgid "unexpected message type 0x%02X during COPY from stdin"
msgstr "nieoczekiwany typ komunikatu 0x%02X podczas COPY ze stdin"
-#: commands/copy.c:806
+#: commands/copy.c:798
#, c-format
msgid "must be superuser to COPY to or from an external program"
msgstr "musisz być superużytkownikiem by wykonywać COPY do lub z programu zewnętrznego"
-#: commands/copy.c:807 commands/copy.c:813
+#: commands/copy.c:799 commands/copy.c:805
#, c-format
msgid "Anyone can COPY to stdout or from stdin. psql's \\copy command also works for anyone."
msgstr "Każdy może wykonać COPY do stdout lub ze stdin. Polecenie psql \\copy również może każdy uruchomić."
-#: commands/copy.c:812
+#: commands/copy.c:804
#, c-format
msgid "must be superuser to COPY to or from a file"
msgstr "musisz być superużytkownikiem by wykonywać COPY z pliku"
-#: commands/copy.c:878
+#: commands/copy.c:871
#, c-format
msgid "COPY FROM not supported with row-level security"
msgstr "COPY FROM nie jest obsługiwane przy bezpieczeństwie na poziomie wierszy"
-#: commands/copy.c:879
+#: commands/copy.c:872
#, c-format
msgid "Use INSERT statements instead."
msgstr "Zamiast tego używaj poleceń INSERT."
-#: commands/copy.c:1019
+#: commands/copy.c:1058
#, c-format
msgid "COPY format \"%s\" not recognized"
msgstr "format COPY \"%s\" nie rozpoznany"
-#: commands/copy.c:1090 commands/copy.c:1104 commands/copy.c:1118
-#: commands/copy.c:1138
+#: commands/copy.c:1138 commands/copy.c:1154 commands/copy.c:1169
+#: commands/copy.c:1191
#, c-format
msgid "argument to option \"%s\" must be a list of column names"
msgstr "argument dla opcji \"%s\" musi być listą nazw kolumn"
-#: commands/copy.c:1151
+#: commands/copy.c:1206
#, c-format
msgid "argument to option \"%s\" must be a valid encoding name"
msgstr "argument dla opcji \"%s\" musi być poprawną nazwą kodowania"
-#: commands/copy.c:1157 commands/dbcommands.c:232 commands/dbcommands.c:1427
+#: commands/copy.c:1213 commands/dbcommands.c:242 commands/dbcommands.c:1461
#, c-format
msgid "option \"%s\" not recognized"
msgstr "opcja \"%s\" nie rozpoznana"
-#: commands/copy.c:1168
+#: commands/copy.c:1225
#, c-format
msgid "cannot specify DELIMITER in BINARY mode"
msgstr "nie można wskazać DELIMITER w trybie BINARY"
-#: commands/copy.c:1173
+#: commands/copy.c:1230
#, c-format
msgid "cannot specify NULL in BINARY mode"
msgstr "nie można wskazać NULL w trybie BINARY"
-#: commands/copy.c:1195
+#: commands/copy.c:1252
#, c-format
msgid "COPY delimiter must be a single one-byte character"
msgstr "ogranicznik COPY musi być pojedynczym jednobajtowym znakiem"
-#: commands/copy.c:1202
+#: commands/copy.c:1259
#, c-format
msgid "COPY delimiter cannot be newline or carriage return"
msgstr "ogranicznik COPY nie może być znakiem nowej linii ani powrotu karetki"
-#: commands/copy.c:1208
+#: commands/copy.c:1265
#, c-format
msgid "COPY null representation cannot use newline or carriage return"
msgstr "reprezentacja null w COPY nie może używać znaku nowej linii ani powrotu karetki"
-#: commands/copy.c:1225
+#: commands/copy.c:1282
#, c-format
msgid "COPY delimiter cannot be \"%s\""
msgstr "ogranicznik COPY nie może być \"%s\""
-#: commands/copy.c:1231
+#: commands/copy.c:1288
#, c-format
msgid "COPY HEADER available only in CSV mode"
msgstr "COPY HEADER dostępny tylko w trybie CSV"
-#: commands/copy.c:1237
+#: commands/copy.c:1294
#, c-format
msgid "COPY quote available only in CSV mode"
msgstr "cytowanie COPY dostępny tylko w trybie CSV"
-#: commands/copy.c:1242
+#: commands/copy.c:1299
#, c-format
msgid "COPY quote must be a single one-byte character"
msgstr "cytowanie COPY musi być pojedynczym jednobajtowym znakiem"
-#: commands/copy.c:1247
+#: commands/copy.c:1304
#, c-format
msgid "COPY delimiter and quote must be different"
msgstr "ogranicznik i cytowanie COPY muszą być różne"
-#: commands/copy.c:1253
+#: commands/copy.c:1310
#, c-format
msgid "COPY escape available only in CSV mode"
msgstr "znak ucieczki COPY dostępny tylko w trybie CSV"
-#: commands/copy.c:1258
+#: commands/copy.c:1315
#, c-format
msgid "COPY escape must be a single one-byte character"
msgstr "znak ucieczki COPY musi być pojedynczym jednobajtowym znakiem"
-#: commands/copy.c:1264
+#: commands/copy.c:1321
#, c-format
msgid "COPY force quote available only in CSV mode"
msgstr "znak wymuszenia cytowania COPY dostępny tylko w trybie CSV"
-#: commands/copy.c:1268
+#: commands/copy.c:1325
#, c-format
msgid "COPY force quote only available using COPY TO"
msgstr "znak wymuszenia cytowania COPY dostępny tylko podczas użycia COPY TO"
-#: commands/copy.c:1274
+#: commands/copy.c:1331
#, c-format
msgid "COPY force not null available only in CSV mode"
msgstr "znak wymuszenia niepustych COPY dostępny tylko w trybie CSV"
-#: commands/copy.c:1278
+#: commands/copy.c:1335
#, c-format
msgid "COPY force not null only available using COPY FROM"
msgstr "znak wymuszenia niepustych COPY dostępny tylko podczas użycia COPY TO"
-#: commands/copy.c:1284
+#: commands/copy.c:1341
#, c-format
msgid "COPY force null available only in CSV mode"
msgstr "znak wymuszenia wartości pustych COPY dostępny tylko w trybie CSV"
-#: commands/copy.c:1289
+#: commands/copy.c:1346
#, c-format
msgid "COPY force null only available using COPY FROM"
msgstr "znak wymuszenia pustych COPY dostępny tylko podczas użycia COPY TO"
-#: commands/copy.c:1295
+#: commands/copy.c:1352
#, c-format
msgid "COPY delimiter must not appear in the NULL specification"
msgstr "ogranicznik COPY nie może pojawić się w specyfikacji NULL"
-#: commands/copy.c:1302
+#: commands/copy.c:1359
#, c-format
msgid "CSV quote character must not appear in the NULL specification"
msgstr "znak ogranicznika CSV nie może pojawić się w specyfikacji NULL"
-#: commands/copy.c:1365
+#: commands/copy.c:1420
#, c-format
msgid "table \"%s\" does not have OIDs"
msgstr "tabela \"%s\" nie ma OIDów"
-#: commands/copy.c:1382
+#: commands/copy.c:1461
#, c-format
-#| msgid "COPY (SELECT) WITH OIDS is not supported"
msgid "COPY (query) WITH OIDS is not supported"
msgstr "COPY (zapytanie) WITH OIDS nie jest obsługiwane"
-#: commands/copy.c:1402
+#: commands/copy.c:1482
#, c-format
-#| msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH"
msgid "DO INSTEAD NOTHING rules are not supported for COPY"
msgstr "reguły DO INSTEAD NOTHING nie są obsługiwane dla COPY"
-#: commands/copy.c:1416
+#: commands/copy.c:1496
#, c-format
-#| msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH"
msgid "conditional DO INSTEAD rules are not supported for COPY"
msgstr "reguły warunkowe DO INSTEAD nie są obsługiwane dla COPY"
-#: commands/copy.c:1420
+#: commands/copy.c:1500
#, c-format
-#| msgid "DO ALSO rules are not supported for data-modifying statements in WITH"
msgid "DO ALSO rules are not supported for the COPY"
msgstr "reguły DO ALSO nie są obsługiwane dla COPY"
-#: commands/copy.c:1425
+#: commands/copy.c:1505
#, c-format
-#| msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH"
msgid "multi-statement DO INSTEAD rules are not supported for COPY"
msgstr "reguły wielowyrażeniowe DO INSTEAD nie są obsługiwane dla COPY"
-#: commands/copy.c:1435
+#: commands/copy.c:1515
#, c-format
msgid "COPY (SELECT INTO) is not supported"
msgstr "COPY (SELECT INTO) nie jest obsługiwane"
-#: commands/copy.c:1452
+#: commands/copy.c:1532
#, c-format
-#| msgid "WITH query \"%s\" does not have a RETURNING clause"
msgid "COPY query must have a RETURNING clause"
msgstr "kwerenda COPY musi posiadać klauzulę RETURNING"
-#: commands/copy.c:1480
+#: commands/copy.c:1560
#, c-format
msgid "relation referenced by COPY statement has changed"
msgstr "relacja wskazywana przez COPY zmieniła się"
-#: commands/copy.c:1538
+#: commands/copy.c:1618
#, c-format
-#| msgid "FORCE QUOTE column \"%s\" not referenced by COPY"
msgid "FORCE_QUOTE column \"%s\" not referenced by COPY"
msgstr "kolumna FORCE_QUOTE \"%s\" nie jest wskazana w COPY"
-#: commands/copy.c:1560
+#: commands/copy.c:1640
#, c-format
-#| msgid "FORCE NOT NULL column \"%s\" not referenced by COPY"
msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY"
msgstr "kolumna FORCE_NOT_NULL \"%s\" nie jest wskazana w COPY"
-#: commands/copy.c:1582
+#: commands/copy.c:1662
#, c-format
-#| msgid "FORCE NULL column \"%s\" not referenced by COPY"
msgid "FORCE_NULL column \"%s\" not referenced by COPY"
msgstr "kolumna FORCE_NULL \"%s\" nie jest wskazana w COPY"
-#: commands/copy.c:1647
+#: commands/copy.c:1727
#, c-format
msgid "could not close pipe to external command: %m"
msgstr "nie można zamknąć potoku do polecenia zewnętrznego: %m"
-#: commands/copy.c:1651
+#: commands/copy.c:1731
#, c-format
msgid "program \"%s\" failed"
msgstr "program \"%s\" nie wykonał się"
-#: commands/copy.c:1701
+#: commands/copy.c:1781
#, c-format
msgid "cannot copy from view \"%s\""
msgstr "nie można kopiować z widoku \"%s\""
-#: commands/copy.c:1703 commands/copy.c:1709 commands/copy.c:1715
+#: commands/copy.c:1783 commands/copy.c:1789 commands/copy.c:1795
+#: commands/copy.c:1806
#, c-format
msgid "Try the COPY (SELECT ...) TO variant."
msgstr "Spróbuj z alternatywnym COPY (SELECT ...) TO."
-#: commands/copy.c:1707
+#: commands/copy.c:1787
#, c-format
msgid "cannot copy from materialized view \"%s\""
msgstr "nie można kopiować z widoku materializowanego \"%s\""
-#: commands/copy.c:1713
+#: commands/copy.c:1793
#, c-format
msgid "cannot copy from foreign table \"%s\""
msgstr "nie można kopiować z tabeli obcej \"%s\""
-#: commands/copy.c:1719
+#: commands/copy.c:1799
#, c-format
msgid "cannot copy from sequence \"%s\""
msgstr "nie można kopiować z sekwencji \"%s\""
-#: commands/copy.c:1724
+#: commands/copy.c:1804
#, c-format
-msgid "cannot copy from non-table relation \"%s\""
-msgstr "nie można kopiować z relacji \"%s\" nie będącej tabelą"
+#| msgid "cannot copy from foreign table \"%s\""
+msgid "cannot copy from partitioned table \"%s\""
+msgstr "nie można kopiować z partycjonowanej tabeli \"%s\""
-#: commands/copy.c:1749 commands/copy.c:2787
+#: commands/copy.c:1810
#, c-format
-msgid "could not execute command \"%s\": %m"
-msgstr "nie udało się wykonać polecenia \"%s\": %m"
+msgid "cannot copy from non-table relation \"%s\""
+msgstr "nie można kopiować z relacji \"%s\" nie będącej tabelą"
-#: commands/copy.c:1764
+#: commands/copy.c:1850
#, c-format
msgid "relative path not allowed for COPY to file"
msgstr "ścieżka względna niedozwolona dla COPY do pliku"
-#: commands/copy.c:1772
+#: commands/copy.c:1862
#, c-format
msgid "could not open file \"%s\" for writing: %m"
msgstr "nie można otworzyć pliku \"%s\" do zapisu: %m"
-#: commands/copy.c:1784 commands/copy.c:2810
+#: commands/copy.c:1865
+#, c-format
+msgid "COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \\copy."
+msgstr ""
+"COPY TO informuje proces serwera PostgreSQL by zapisać plik. Może jednak "
+"należy użyć narzędzia po stronie klienta jak \\copy w psql."
+
+#: commands/copy.c:1878 commands/copy.c:3058
#, c-format
msgid "\"%s\" is a directory"
msgstr "\"%s\" jest katalogiem"
-#: commands/copy.c:2109
+#: commands/copy.c:2201
#, c-format
msgid "COPY %s, line %d, column %s"
msgstr "COPY %s, linia %d, kolumna %s"
-#: commands/copy.c:2113 commands/copy.c:2160
+#: commands/copy.c:2205 commands/copy.c:2252
#, c-format
msgid "COPY %s, line %d"
msgstr "COPY %s, linia %d"
-#: commands/copy.c:2124
+#: commands/copy.c:2216
#, c-format
msgid "COPY %s, line %d, column %s: \"%s\""
msgstr "COPY %s, linia %d, kolumna %s: \"%s\""
-#: commands/copy.c:2132
+#: commands/copy.c:2224
#, c-format
msgid "COPY %s, line %d, column %s: null input"
msgstr "COPY %s, linia %d, kolumna %s: puste wejście"
-#: commands/copy.c:2154
+#: commands/copy.c:2246
#, c-format
msgid "COPY %s, line %d: \"%s\""
msgstr "COPY %s, linia %d: \"%s\""
-#: commands/copy.c:2238
+#: commands/copy.c:2340
#, c-format
msgid "cannot copy to view \"%s\""
msgstr "nie można kopiować do widoku \"%s\""
-#: commands/copy.c:2243
+#: commands/copy.c:2342
+#, c-format
+#| msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."
+msgid "To enable copying to a view, provide an INSTEAD OF INSERT trigger."
+msgstr "By włączyć kopiowanie do widoku, wskaż wyzwalacz INSTEAD OF INSERT."
+
+#: commands/copy.c:2346
#, c-format
msgid "cannot copy to materialized view \"%s\""
msgstr "nie można kopiować do widoku materializowanego \"%s\""
-#: commands/copy.c:2248
+#: commands/copy.c:2351
#, c-format
msgid "cannot copy to foreign table \"%s\""
msgstr "nie można kopiować do tabeli obcej \"%s\""
-#: commands/copy.c:2253
+#: commands/copy.c:2356
#, c-format
msgid "cannot copy to sequence \"%s\""
msgstr "nie można kopiować do sekwencji \"%s\""
-#: commands/copy.c:2258
+#: commands/copy.c:2361
#, c-format
msgid "cannot copy to non-table relation \"%s\""
msgstr "nie można kopiować do relacji \"%s\" nie będącej tabelą"
-#: commands/copy.c:2321
+#: commands/copy.c:2424
#, c-format
msgid "cannot perform FREEZE because of prior transaction activity"
msgstr "nie można wykonać FREEZE ze względu na wcześniejsze działania transakcji"
-#: commands/copy.c:2327
+#: commands/copy.c:2430
#, c-format
msgid "cannot perform FREEZE because the table was not created or truncated in the current subtransaction"
msgstr "nie można wykonać FREEZE ponieważ tabela nie została utworzona ani obcięta w bieżącej podtransakcji"
-#: commands/copy.c:2830
+#: commands/copy.c:2595 executor/nodeModifyTable.c:312
+#, c-format
+#| msgid "cannot insert into foreign table \"%s\""
+msgid "cannot route inserted tuples to a foreign table"
+msgstr "nie można przekierować wstawianych krotek do tabeli zewnętrznej"
+
+#: commands/copy.c:3045
+#, c-format
+msgid "COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \\copy."
+msgstr ""
+"COPY FROM informuje proces serwera PostgreSQL by czytać z pliku. Może jednak "
+"należy użyć narzędzia po stronie klienta jak \\copy w psql."
+
+#: commands/copy.c:3078
#, c-format
msgid "COPY file signature not recognized"
msgstr "nierozpoznana sygnatura pliku COPY"
-#: commands/copy.c:2835
+#: commands/copy.c:3083
#, c-format
msgid "invalid COPY file header (missing flags)"
msgstr "niepoprawny nagłówek pliku COPY (brakuje flag)"
-#: commands/copy.c:2841
+#: commands/copy.c:3089
#, c-format
msgid "unrecognized critical flags in COPY file header"
msgstr "nierozpoznane istotne flagi w nagłówku pliku COPY"
-#: commands/copy.c:2847
+#: commands/copy.c:3095
#, c-format
msgid "invalid COPY file header (missing length)"
msgstr "niepoprawny nagłówek pliku COPY (brakuje długości)"
-#: commands/copy.c:2854
+#: commands/copy.c:3102
#, c-format
msgid "invalid COPY file header (wrong length)"
msgstr "niepoprawny nagłówek pliku COPY (niepoprawna długość)"
-#: commands/copy.c:2987 commands/copy.c:3694 commands/copy.c:3924
+#: commands/copy.c:3235 commands/copy.c:3942 commands/copy.c:4172
#, c-format
msgid "extra data after last expected column"
msgstr "nieoczekiwane dane po ostatniej oczekiwanej kolumnie"
-#: commands/copy.c:2997
+#: commands/copy.c:3245
#, c-format
msgid "missing data for OID column"
msgstr "brak danych dla kolumny OID"
-#: commands/copy.c:3003
+#: commands/copy.c:3251
#, c-format
msgid "null OID in COPY data"
msgstr "pusty OID w danych COPY"
-#: commands/copy.c:3013 commands/copy.c:3136
+#: commands/copy.c:3261 commands/copy.c:3384
#, c-format
msgid "invalid OID in COPY data"
msgstr "niepoprawny OID w danych COPY"
-#: commands/copy.c:3028
+#: commands/copy.c:3276
#, c-format
msgid "missing data for column \"%s\""
msgstr "brak danych dla kolumny \"%s\""
-#: commands/copy.c:3111
+#: commands/copy.c:3359
#, c-format
msgid "received copy data after EOF marker"
msgstr "odebrano kopiowane dane po znaczniku EOF"
-#: commands/copy.c:3118
+#: commands/copy.c:3366
#, c-format
msgid "row field count is %d, expected %d"
msgstr "liczba pól wiersza wynosi %d, oczekiwano %d"
-#: commands/copy.c:3458 commands/copy.c:3475
+#: commands/copy.c:3706 commands/copy.c:3723
#, c-format
msgid "literal carriage return found in data"
msgstr "znaleziono literał powrotu karetki w danych"
-#: commands/copy.c:3459 commands/copy.c:3476
+#: commands/copy.c:3707 commands/copy.c:3724
#, c-format
msgid "unquoted carriage return found in data"
msgstr "znaleziono niecytowany powrót karetki w danych"
-#: commands/copy.c:3461 commands/copy.c:3478
+#: commands/copy.c:3709 commands/copy.c:3726
#, c-format
msgid "Use \"\\r\" to represent carriage return."
msgstr "Użyj \"\\r\" jako reprezentacji powrotu karetki."
-#: commands/copy.c:3462 commands/copy.c:3479
+#: commands/copy.c:3710 commands/copy.c:3727
#, c-format
msgid "Use quoted CSV field to represent carriage return."
msgstr "Użyj cytowanego pola CSV jako reprezentacji powrotu karetki."
-#: commands/copy.c:3491
+#: commands/copy.c:3739
#, c-format
msgid "literal newline found in data"
msgstr "znaleziono literał nowej linii w danych"
-#: commands/copy.c:3492
+#: commands/copy.c:3740
#, c-format
msgid "unquoted newline found in data"
msgstr "znaleziono niecytowany znak nowej linii w danych"
-#: commands/copy.c:3494
+#: commands/copy.c:3742
#, c-format
msgid "Use \"\\n\" to represent newline."
msgstr "Użyj \"\\n\" jako reprezentacji znaku nowej linii."
-#: commands/copy.c:3495
+#: commands/copy.c:3743
#, c-format
msgid "Use quoted CSV field to represent newline."
msgstr "Użyj cytowanego pola CSV jako reprezentacji nowej linii."
-#: commands/copy.c:3541 commands/copy.c:3577
+#: commands/copy.c:3789 commands/copy.c:3825
#, c-format
msgid "end-of-copy marker does not match previous newline style"
msgstr "znacznik końcowy kopii nie pasuje do poprzedniego stylu nowej linii"
-#: commands/copy.c:3550 commands/copy.c:3566
+#: commands/copy.c:3798 commands/copy.c:3814
#, c-format
msgid "end-of-copy marker corrupt"
msgstr "uszkodzony znak końcowy kopii"
-#: commands/copy.c:4008
+#: commands/copy.c:4256
#, c-format
msgid "unterminated CSV quoted field"
msgstr "niezakończone cytowane pole CSV"
-#: commands/copy.c:4085 commands/copy.c:4104
+#: commands/copy.c:4333 commands/copy.c:4352
#, c-format
msgid "unexpected EOF in COPY data"
msgstr "nieoczekiwany EOF w danych COPY"
-#: commands/copy.c:4094
+#: commands/copy.c:4342
#, c-format
msgid "invalid field size"
msgstr "nieprawidłowy rozmiar pola"
-#: commands/copy.c:4117
+#: commands/copy.c:4365
#, c-format
msgid "incorrect binary data format"
msgstr "nieprawidłowy binarny format danych"
-#: commands/copy.c:4428 commands/indexcmds.c:1053 commands/tablecmds.c:1463
-#: commands/tablecmds.c:2290 parser/parse_relation.c:3084
-#: parser/parse_relation.c:3104 utils/adt/tsvector_op.c:2256
+#: commands/copy.c:4676 commands/indexcmds.c:1057 commands/tablecmds.c:1663
+#: commands/tablecmds.c:2164 commands/tablecmds.c:2587
+#: parser/parse_relation.c:3248 parser/parse_relation.c:3268
+#: utils/adt/tsvector_op.c:2561
#, c-format
msgid "column \"%s\" does not exist"
msgstr "kolumna \"%s\" nie istnieje"
-#: commands/copy.c:4435 commands/tablecmds.c:1489 commands/trigger.c:651
-#: parser/parse_target.c:956 parser/parse_target.c:967
+#: commands/copy.c:4683 commands/tablecmds.c:1689 commands/trigger.c:748
+#: parser/parse_target.c:1018 parser/parse_target.c:1029
#, c-format
msgid "column \"%s\" specified more than once"
msgstr "kolumna \"%s\" określona więcej niż raz"
@@ -5892,214 +6221,234 @@ msgstr "określono zbyt wiele nazw kolumn"
msgid "policies not yet implemented for this command"
msgstr "polityki nie zostały jeszcze zaimplementowane dla tego polecenia"
-#: commands/dbcommands.c:226
+#: commands/dbcommands.c:235
#, c-format
msgid "LOCATION is not supported anymore"
msgstr "LOCATION nie jest już obsługiwane"
-#: commands/dbcommands.c:227
+#: commands/dbcommands.c:236
#, c-format
msgid "Consider using tablespaces instead."
msgstr "Rozważ w zamian użycie przestrzeni tabel."
-#: commands/dbcommands.c:251 utils/adt/ascii.c:144
+#: commands/dbcommands.c:262 utils/adt/ascii.c:145
#, c-format
msgid "%d is not a valid encoding code"
msgstr "%d nie jest poprawną kodem kodowania"
-#: commands/dbcommands.c:261 utils/adt/ascii.c:126
+#: commands/dbcommands.c:273 utils/adt/ascii.c:127
#, c-format
msgid "%s is not a valid encoding name"
msgstr "%s nie jest poprawną nazwą kodowania"
-#: commands/dbcommands.c:279 commands/dbcommands.c:1458 commands/user.c:272
-#: commands/user.c:650
+#: commands/dbcommands.c:292 commands/dbcommands.c:1494 commands/user.c:289
+#: commands/user.c:665
#, c-format
msgid "invalid connection limit: %d"
msgstr "błędne ograniczenie liczby połączeń: %d"
-#: commands/dbcommands.c:298
+#: commands/dbcommands.c:311
#, c-format
msgid "permission denied to create database"
msgstr "odmowa dostępu do tworzenia bazy"
-#: commands/dbcommands.c:321
+#: commands/dbcommands.c:334
#, c-format
msgid "template database \"%s\" does not exist"
msgstr "tymczasowa baza \"%s\" nie istnieje"
-#: commands/dbcommands.c:333
+#: commands/dbcommands.c:346
#, c-format
msgid "permission denied to copy database \"%s\""
msgstr "odmowa dostępu do kopiowania bazy danych \"%s\""
-#: commands/dbcommands.c:349
+#: commands/dbcommands.c:362
#, c-format
msgid "invalid server encoding %d"
msgstr "nieprawidłowe kodowanie serwera %d"
-#: commands/dbcommands.c:355 commands/dbcommands.c:360
+#: commands/dbcommands.c:368 commands/dbcommands.c:373
#, c-format
msgid "invalid locale name: \"%s\""
msgstr "nieprawidłowa nazwa lokalizacji: \"%s\""
-#: commands/dbcommands.c:380
+#: commands/dbcommands.c:393
#, c-format
msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)"
msgstr "nowe kodowanie (%s) jest niedopasowana do kodowania szablonu bazy danych (%s)"
-#: commands/dbcommands.c:383
+#: commands/dbcommands.c:396
#, c-format
msgid "Use the same encoding as in the template database, or use template0 as template."
msgstr "Użyj tego samego kodowania jak w szablonie bazy danych, lub użyj template0 jako szablonu."
-#: commands/dbcommands.c:388
+#: commands/dbcommands.c:401
#, c-format
msgid "new collation (%s) is incompatible with the collation of the template database (%s)"
msgstr "nowe porównanie (%s) jest niedopasowana do porównania szablonu bazy danych (%s)"
-#: commands/dbcommands.c:390
+#: commands/dbcommands.c:403
#, c-format
msgid "Use the same collation as in the template database, or use template0 as template."
msgstr "Użyj tego samego porównania jak w szablonie bazy danych, lub użyj template0 jako szablonu."
-#: commands/dbcommands.c:395
+#: commands/dbcommands.c:408
#, c-format
msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)"
msgstr "nowe LC_CTYPE (%s) jest niedopasowana do LC_CTYPE szablonu bazy danych (%s)"
-#: commands/dbcommands.c:397
+#: commands/dbcommands.c:410
#, c-format
msgid "Use the same LC_CTYPE as in the template database, or use template0 as template."
msgstr "Użyj tego samego LC_CTYPE jak w szablonie bazy danych, lub użyj template0 jako szablonu."
-#: commands/dbcommands.c:419 commands/dbcommands.c:1113
+#: commands/dbcommands.c:432 commands/dbcommands.c:1146
#, c-format
msgid "pg_global cannot be used as default tablespace"
msgstr "pg_global nie może być użyty jako domyślna przestrzeń tabel"
-#: commands/dbcommands.c:445
+#: commands/dbcommands.c:458
#, c-format
msgid "cannot assign new default tablespace \"%s\""
msgstr "nie można przydzielić domyślnej przestrzeni tabel \"%s\""
-#: commands/dbcommands.c:447
+#: commands/dbcommands.c:460
#, c-format
msgid "There is a conflict because database \"%s\" already has some tables in this tablespace."
msgstr "Wystąpił konflikt, ponieważ baza danych \"%s\" posiada już kilka tabel w tej przestrzeni tabel."
-#: commands/dbcommands.c:467 commands/dbcommands.c:982
+#: commands/dbcommands.c:480 commands/dbcommands.c:1016
#, c-format
msgid "database \"%s\" already exists"
msgstr "baza danych \"%s\" już istnieje"
-#: commands/dbcommands.c:481
+#: commands/dbcommands.c:494
#, c-format
msgid "source database \"%s\" is being accessed by other users"
msgstr "źródłowa baza danych \"%s\" jest używana przez innych użytkowników"
-#: commands/dbcommands.c:726 commands/dbcommands.c:741
+#: commands/dbcommands.c:736 commands/dbcommands.c:751
#, c-format
msgid "encoding \"%s\" does not match locale \"%s\""
msgstr "kodowanie \"%s\" nie pasuje do ustawień lokalnych \"%s\""
-#: commands/dbcommands.c:729
+#: commands/dbcommands.c:739
#, c-format
msgid "The chosen LC_CTYPE setting requires encoding \"%s\"."
msgstr "Wybrane ustawienie LC_TYPE wymaga kodowania \"%s\"."
-#: commands/dbcommands.c:744
+#: commands/dbcommands.c:754
#, c-format
msgid "The chosen LC_COLLATE setting requires encoding \"%s\"."
msgstr "Wybrane ustawienie LC_COLLATE wymaga kodowania \"%s\"."
-#: commands/dbcommands.c:804
+#: commands/dbcommands.c:815
#, c-format
msgid "database \"%s\" does not exist, skipping"
msgstr "baza danych \"%s\" nie istnieje, pominięto"
-#: commands/dbcommands.c:828
+#: commands/dbcommands.c:839
#, c-format
msgid "cannot drop a template database"
msgstr "nie można usunąć tymczasowej bazy danych"
-#: commands/dbcommands.c:834
+#: commands/dbcommands.c:845
#, c-format
msgid "cannot drop the currently open database"
msgstr "nie można usunąć aktualnie otwartej bazy danych"
-#: commands/dbcommands.c:844
+#: commands/dbcommands.c:858
#, c-format
-msgid "database \"%s\" is used by a logical replication slot"
-msgstr "baza danych \"%s\" jest używana przez logiczne gniazdo replikacji"
+#| msgid "database \"%s\" is used by a logical replication slot"
+msgid "database \"%s\" is used by an active logical replication slot"
+msgstr "baza danych \"%s\" jest używana przez aktywne logiczne gniazdo replikacji"
-#: commands/dbcommands.c:846
+#: commands/dbcommands.c:860
#, c-format
-msgid "There is %d slot, %d of them active."
-msgid_plural "There are %d slots, %d of them active."
-msgstr[0] "Jest %d slot, %d z nich aktywny."
-msgstr[1] "Są %d sloty, %d z nich aktywne."
-msgstr[2] "Jest %d slotów, %d z nich aktywnych."
+#| msgid "There is %d slot, %d of them active."
+#| msgid_plural "There are %d slots, %d of them active."
+msgid "There is %d active slot"
+msgid_plural "There are %d active slots"
+msgstr[0] "Jest %d aktywne gniazdo"
+msgstr[1] "Są %d aktywne gniazda"
+msgstr[2] "Jest %d aktywnych gniazd"
-#: commands/dbcommands.c:860 commands/dbcommands.c:1004
-#: commands/dbcommands.c:1135
+#: commands/dbcommands.c:874 commands/dbcommands.c:1038
+#: commands/dbcommands.c:1168
#, c-format
msgid "database \"%s\" is being accessed by other users"
msgstr "baza danych \"%s\" jest używana przez innych użytkowników"
-#: commands/dbcommands.c:973
+#: commands/dbcommands.c:887
+#, c-format
+#| msgid "database \"%s\" is used by a logical replication slot"
+msgid "database \"%s\" is being used by logical replication subscription"
+msgstr ""
+"baza danych \"%s\" jest w trakcie użytkowania przez logiczną subskrypcję "
+"replikacji"
+
+#: commands/dbcommands.c:889
+#, c-format
+#| msgid "reading subscriptions\n"
+msgid "There is %d subscription."
+msgid_plural "There are %d subscriptions."
+msgstr[0] "Jest %d subskrypcja."
+msgstr[1] "Są %d subskrypcje."
+msgstr[2] "Jest %d subskrypcji."
+
+#: commands/dbcommands.c:1007
#, c-format
msgid "permission denied to rename database"
msgstr "odmowa dostępu do zmiany nazwy bazy"
-#: commands/dbcommands.c:993
+#: commands/dbcommands.c:1027
#, c-format
msgid "current database cannot be renamed"
msgstr "nie można zmieniać nazwy aktualnie otwartej bazy"
-#: commands/dbcommands.c:1091
+#: commands/dbcommands.c:1124
#, c-format
msgid "cannot change the tablespace of the currently open database"
msgstr "nie można usunąć aktualnie otwartej bazy danych"
-#: commands/dbcommands.c:1194
+#: commands/dbcommands.c:1227
#, c-format
msgid "some relations of database \"%s\" are already in tablespace \"%s\""
msgstr "pewne relacje bazy danych \"%s\" są już w przestrzeni tabel \"%s\""
-#: commands/dbcommands.c:1196
+#: commands/dbcommands.c:1229
#, c-format
msgid "You must move them back to the database's default tablespace before using this command."
msgstr "Musisz przesunąć je z powrotem do domyślnej przestrzeni tabel bazy danych zanim użyjesz tego polecenia."
-#: commands/dbcommands.c:1325 commands/dbcommands.c:1868
-#: commands/dbcommands.c:2072 commands/dbcommands.c:2120
-#: commands/tablespace.c:606
+#: commands/dbcommands.c:1355 commands/dbcommands.c:1900
+#: commands/dbcommands.c:2104 commands/dbcommands.c:2158
+#: commands/tablespace.c:604
#, c-format
msgid "some useless files may be left behind in old database directory \"%s\""
msgstr "pewne niepotrzebne pliki mogą pozostać w starym folderze bazy danych \"%s\""
-#: commands/dbcommands.c:1440
+#: commands/dbcommands.c:1475
#, c-format
msgid "option \"%s\" cannot be specified with other options"
msgstr "opcja \"%s\" nie może być użyta razem z innymi opcjami"
-#: commands/dbcommands.c:1494
+#: commands/dbcommands.c:1530
#, c-format
msgid "cannot disallow connections for current database"
msgstr "nie można zabronić połączeń do bieżącej bazy danych"
-#: commands/dbcommands.c:1634
+#: commands/dbcommands.c:1667
#, c-format
msgid "permission denied to change owner of database"
msgstr "odmowa dostępu do zmiany właściciela bazy danych"
-#: commands/dbcommands.c:1955
+#: commands/dbcommands.c:1987
#, c-format
msgid "There are %d other session(s) and %d prepared transaction(s) using the database."
msgstr "Inne sesje (%d) i przygotowane transakcje (%d) używają bazy danych."
-#: commands/dbcommands.c:1958
+#: commands/dbcommands.c:1990
#, c-format
msgid "There is %d other session using the database."
msgid_plural "There are %d other sessions using the database."
@@ -6107,7 +6456,7 @@ msgstr[0] "%d inna sesja używa bazy danych."
msgstr[1] "%d inne sesje używają bazy danych."
msgstr[2] "%d innych sesji używa bazy danych."
-#: commands/dbcommands.c:1963
+#: commands/dbcommands.c:1995
#, c-format
msgid "There is %d prepared transaction using the database."
msgid_plural "There are %d prepared transactions using the database."
@@ -6116,7 +6465,7 @@ msgstr[1] "%d przygotowane transakcje używają bazy danych."
msgstr[2] "%d przygotowanych transakcji używa bazy danych."
#: commands/define.c:54 commands/define.c:228 commands/define.c:260
-#: commands/define.c:288
+#: commands/define.c:288 commands/define.c:334
#, c-format
msgid "%s requires a parameter"
msgstr "%s wymaga parametru"
@@ -6152,460 +6501,473 @@ msgstr "argument %s musi być nazwą typu"
msgid "invalid argument for %s: \"%s\""
msgstr "nieprawidłowy argument dla %s: \"%s\""
-#: commands/dropcmds.c:112 commands/functioncmds.c:1203
-#: utils/adt/ruleutils.c:1965
+#: commands/dropcmds.c:104 commands/functioncmds.c:1200
+#: utils/adt/ruleutils.c:2407
#, c-format
msgid "\"%s\" is an aggregate function"
msgstr "\"%s\" jest funkcją agregującą"
-#: commands/dropcmds.c:114
+#: commands/dropcmds.c:106
#, c-format
msgid "Use DROP AGGREGATE to drop aggregate functions."
msgstr "Użyj DROP AGGREGATE aby usunąć funkcje agregujące."
-#: commands/dropcmds.c:165 commands/sequence.c:424 commands/tablecmds.c:2377
-#: commands/tablecmds.c:2528 commands/tablecmds.c:2570
-#: commands/tablecmds.c:11377 tcop/utility.c:1119
+#: commands/dropcmds.c:157 commands/sequence.c:430 commands/tablecmds.c:2671
+#: commands/tablecmds.c:2822 commands/tablecmds.c:2865
+#: commands/tablecmds.c:12397 tcop/utility.c:1168
#, c-format
msgid "relation \"%s\" does not exist, skipping"
msgstr "relacja \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:195 commands/dropcmds.c:296 commands/tablecmds.c:745
+#: commands/dropcmds.c:187 commands/dropcmds.c:286 commands/tablecmds.c:904
#, c-format
msgid "schema \"%s\" does not exist, skipping"
msgstr "schemat \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:237 commands/dropcmds.c:276 commands/tablecmds.c:246
+#: commands/dropcmds.c:227 commands/dropcmds.c:266 commands/tablecmds.c:252
#, c-format
msgid "type \"%s\" does not exist, skipping"
msgstr "typ \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:266
+#: commands/dropcmds.c:256
#, c-format
-#| msgid "access method \"%s\" does not exist"
msgid "access method \"%s\" does not exist, skipping"
msgstr "metoda dostępu \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:284
+#: commands/dropcmds.c:274
#, c-format
msgid "collation \"%s\" does not exist, skipping"
msgstr "porównanie \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:291
+#: commands/dropcmds.c:281
#, c-format
msgid "conversion \"%s\" does not exist, skipping"
msgstr "konwersja \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:302
+#: commands/dropcmds.c:292
+#, c-format
+#| msgid "extension \"%s\" does not exist, skipping"
+msgid "extended statistics \"%s\" do not exist, skipping"
+msgstr "rozszerzona statystyka \"%s\" nie istnieje, pominięto"
+
+#: commands/dropcmds.c:299
#, c-format
msgid "text search parser \"%s\" does not exist, skipping"
msgstr "parser wyszukiwania tekstowego \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:309
+#: commands/dropcmds.c:306
#, c-format
msgid "text search dictionary \"%s\" does not exist, skipping"
msgstr "słownik wyszukiwania tekstowego \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:316
+#: commands/dropcmds.c:313
#, c-format
msgid "text search template \"%s\" does not exist, skipping"
msgstr "szablon wyszukiwania tekstowego \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:323
+#: commands/dropcmds.c:320
#, c-format
msgid "text search configuration \"%s\" does not exist, skipping"
msgstr "konfiguracja wyszukiwania tekstowego \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:328
+#: commands/dropcmds.c:325
#, c-format
msgid "extension \"%s\" does not exist, skipping"
msgstr "rozszerzenie \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:335
+#: commands/dropcmds.c:334
#, c-format
msgid "function %s(%s) does not exist, skipping"
msgstr "funkcja %s(%s) nie istnieje, pominięto"
-#: commands/dropcmds.c:344
+#: commands/dropcmds.c:346
#, c-format
msgid "aggregate %s(%s) does not exist, skipping"
msgstr "agregat %s(%s) nie istnieje, pominięto"
-#: commands/dropcmds.c:353
+#: commands/dropcmds.c:358
#, c-format
msgid "operator %s does not exist, skipping"
msgstr "operator %s nie istnieje, pominięto"
-#: commands/dropcmds.c:358
+#: commands/dropcmds.c:364
#, c-format
msgid "language \"%s\" does not exist, skipping"
msgstr "język \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:367
+#: commands/dropcmds.c:373
#, c-format
msgid "cast from type %s to type %s does not exist, skipping"
msgstr "rzutowanie z typu %s na typ %s nie istnieje, pominięto"
-#: commands/dropcmds.c:376
+#: commands/dropcmds.c:382
#, c-format
msgid "transform for type %s language \"%s\" does not exist, skipping"
msgstr "transformacja dla typu %s język \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:384
+#: commands/dropcmds.c:390
#, c-format
msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping"
msgstr "wyzwalacz \"%s\" relacji \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:393
+#: commands/dropcmds.c:399
#, c-format
msgid "policy \"%s\" for relation \"%s\" does not exist, skipping"
msgstr "polityka \"%s\" relacji \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:400
+#: commands/dropcmds.c:406
#, c-format
msgid "event trigger \"%s\" does not exist, skipping"
msgstr "wyzwalacz zdarzeniowy \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:406
+#: commands/dropcmds.c:412
#, c-format
msgid "rule \"%s\" for relation \"%s\" does not exist, skipping"
msgstr "reguła \"%s\" relacji \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:413
+#: commands/dropcmds.c:419
#, c-format
msgid "foreign-data wrapper \"%s\" does not exist, skipping"
msgstr "opakowanie danych obcych \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:417
+#: commands/dropcmds.c:423
#, c-format
msgid "server \"%s\" does not exist, skipping"
msgstr "serwer \"%s\" nie istnieje, pominięto"
-#: commands/dropcmds.c:426
+#: commands/dropcmds.c:432
#, c-format
msgid "operator class \"%s\" does not exist for access method \"%s\", skipping"
msgstr "klasa operatora \"%s\" nie istnieje dla metody dostępu \"%s\", pominięto"
-#: commands/dropcmds.c:438
+#: commands/dropcmds.c:444
#, c-format
msgid "operator family \"%s\" does not exist for access method \"%s\", skipping"
msgstr "rodzina operatora \"%s\" nie istnieje dla metody dostępu \"%s\", pominięto"
-#: commands/event_trigger.c:182
+#: commands/dropcmds.c:451
+#, c-format
+#| msgid "relation \"%s\" does not exist, skipping"
+msgid "publication \"%s\" does not exist, skipping"
+msgstr "publikacja \"%s\" nie istnieje, pominięto"
+
+#: commands/event_trigger.c:185
#, c-format
msgid "permission denied to create event trigger \"%s\""
msgstr "odmowa dostępu do tworzenia wyzwalacza zdarzeniowego \"%s\""
-#: commands/event_trigger.c:184
+#: commands/event_trigger.c:187
#, c-format
msgid "Must be superuser to create an event trigger."
msgstr "Musisz być superużytkownikiem aby tworzyć wyzwalacz zdarzeniowy."
-#: commands/event_trigger.c:193
+#: commands/event_trigger.c:196
#, c-format
msgid "unrecognized event name \"%s\""
msgstr "nierozpoznana nazwa zdarzenia \"%s\""
-#: commands/event_trigger.c:210
+#: commands/event_trigger.c:213
#, c-format
msgid "unrecognized filter variable \"%s\""
msgstr "nierozpoznana zmienna filtru \"%s\""
-#: commands/event_trigger.c:265
+#: commands/event_trigger.c:268
#, c-format
msgid "filter value \"%s\" not recognized for filter variable \"%s\""
msgstr "nierozpoznana wartość filtru \"%s\" w zmiennej filtru \"%s\""
#. translator: %s represents an SQL statement name
-#: commands/event_trigger.c:271 commands/event_trigger.c:341
+#: commands/event_trigger.c:274 commands/event_trigger.c:344
#, c-format
msgid "event triggers are not supported for %s"
msgstr "wyzwalacze zdarzeniowe nie są obsługiwane dla %s"
-#: commands/event_trigger.c:364
+#: commands/event_trigger.c:367
#, c-format
msgid "filter variable \"%s\" specified more than once"
msgstr "zmienna filtru \"%s\" określona więcej niż raz"
-#: commands/event_trigger.c:512 commands/event_trigger.c:556
+#: commands/event_trigger.c:514 commands/event_trigger.c:557
#: commands/event_trigger.c:649
#, c-format
msgid "event trigger \"%s\" does not exist"
msgstr "wyzwalacz zdarzeniowy \"%s\" nie istnieje"
-#: commands/event_trigger.c:617
+#: commands/event_trigger.c:618
#, c-format
msgid "permission denied to change owner of event trigger \"%s\""
-msgstr "odmowa dostępu do zmiany właściciela wyzwalacza zdarzeniowy \"%s\""
+msgstr "odmowa dostępu do zmiany właściciela wyzwalacza zdarzeniowego \"%s\""
-#: commands/event_trigger.c:619
+#: commands/event_trigger.c:620
#, c-format
msgid "The owner of an event trigger must be a superuser."
msgstr "Właściciel wyzwalacza zdarzeniowego musi być superużytkownikiem."
-#: commands/event_trigger.c:1442
+#: commands/event_trigger.c:1446
#, c-format
msgid "%s can only be called in a sql_drop event trigger function"
msgstr "%s może być wywołane tylko w funkcji wyzwalacza zdarzeniowego sql_drop"
-#: commands/event_trigger.c:1562 commands/event_trigger.c:1583
+#: commands/event_trigger.c:1566 commands/event_trigger.c:1587
#, c-format
msgid "%s can only be called in a table_rewrite event trigger function"
msgstr "%s może być wywołane tylko w funkcji wyzwalacza zdarzeniowego table_rewrite"
-#: commands/event_trigger.c:1993
+#: commands/event_trigger.c:1997
#, c-format
msgid "%s can only be called in an event trigger function"
msgstr "%s może być wywołane tylko w funkcji wyzwalacza zdarzeniowego"
-#: commands/explain.c:184
+#: commands/explain.c:194
#, c-format
msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\""
msgstr "nieprawidłowa wartość dla opcji EXPLAIN \"%s\": \"%s\""
-#: commands/explain.c:190
+#: commands/explain.c:201
#, c-format
msgid "unrecognized EXPLAIN option \"%s\""
msgstr "nieznana opcja EXPLAIN \"%s\""
-#: commands/explain.c:197
+#: commands/explain.c:209
#, c-format
msgid "EXPLAIN option BUFFERS requires ANALYZE"
msgstr "opcja EXPLAIN BUFFERS wymaga ANALYZE"
-#: commands/explain.c:206
+#: commands/explain.c:218
#, c-format
msgid "EXPLAIN option TIMING requires ANALYZE"
msgstr "opcja TIMING polecenia EXPLAIN wymaga ANALYZE"
-#: commands/extension.c:154 commands/extension.c:2718
+#: commands/extension.c:167 commands/extension.c:2902
#, c-format
msgid "extension \"%s\" does not exist"
msgstr "rozszerzenie \"%s\" nie istnieje"
-#: commands/extension.c:253 commands/extension.c:262 commands/extension.c:274
-#: commands/extension.c:284
+#: commands/extension.c:266 commands/extension.c:275 commands/extension.c:287
+#: commands/extension.c:297
#, c-format
msgid "invalid extension name: \"%s\""
msgstr "nieprawidłowa nazwa rozszerzenia: \"%s\""
-#: commands/extension.c:254
+#: commands/extension.c:267
#, c-format
msgid "Extension names must not be empty."
msgstr "Nazwy rozszerzeń nie mogą być puste."
-#: commands/extension.c:263
+#: commands/extension.c:276
#, c-format
msgid "Extension names must not contain \"--\"."
msgstr "Nazwy rozszerzeń nie mogą zawierać \"--\"."
-#: commands/extension.c:275
+#: commands/extension.c:288
#, c-format
msgid "Extension names must not begin or end with \"-\"."
msgstr "Nazwy rozszerzeń nie mogą zaczynać się ani kończyć znakiem \"-\"."
-#: commands/extension.c:285
+#: commands/extension.c:298
#, c-format
msgid "Extension names must not contain directory separator characters."
msgstr "Nazwy rozszerzeń nie mogą zawierać znaków rozdzielających słownika."
-#: commands/extension.c:300 commands/extension.c:309 commands/extension.c:318
-#: commands/extension.c:328
+#: commands/extension.c:313 commands/extension.c:322 commands/extension.c:331
+#: commands/extension.c:341
#, c-format
msgid "invalid extension version name: \"%s\""
msgstr "nieprawidłowa nazwa wersji rozszerzenia: \"%s\""
-#: commands/extension.c:301
+#: commands/extension.c:314
#, c-format
msgid "Version names must not be empty."
msgstr "Nazwy wersji nie mogą być puste."
-#: commands/extension.c:310
+#: commands/extension.c:323
#, c-format
msgid "Version names must not contain \"--\"."
msgstr "Nazwy wersji nie mogą zawierać \"--\"."
-#: commands/extension.c:319
+#: commands/extension.c:332
#, c-format
msgid "Version names must not begin or end with \"-\"."
msgstr "Nazwy wersji nie mogą zaczynać się ani kończyć znakiem \"-\"."
-#: commands/extension.c:329
+#: commands/extension.c:342
#, c-format
msgid "Version names must not contain directory separator characters."
msgstr "Nazwy wersji nie mogą zawierać znaków rozdzielających słownika."
-#: commands/extension.c:479
+#: commands/extension.c:492
#, c-format
msgid "could not open extension control file \"%s\": %m"
msgstr "nie można otworzyć pliku kontrolnego rozszerzenia \"%s\": %m"
-#: commands/extension.c:501 commands/extension.c:511
+#: commands/extension.c:514 commands/extension.c:524
#, c-format
msgid "parameter \"%s\" cannot be set in a secondary extension control file"
msgstr "parametr \"%s\" nie może być ustawiony we wtórnym pliku kontrolnym rozszerzenia"
-#: commands/extension.c:550
+#: commands/extension.c:563
#, c-format
msgid "\"%s\" is not a valid encoding name"
msgstr "\"%s\" nie jest poprawną nazwą kodowania"
-#: commands/extension.c:564
+#: commands/extension.c:577
#, c-format
msgid "parameter \"%s\" must be a list of extension names"
msgstr "parametr \"%s\" nie może być listą nazw rozszerzeń"
-#: commands/extension.c:571
+#: commands/extension.c:584
#, c-format
msgid "unrecognized parameter \"%s\" in file \"%s\""
msgstr "nierozpoznany parametr \"%s\" w pliku \"%s\""
-#: commands/extension.c:580
+#: commands/extension.c:593
#, c-format
msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true"
msgstr "parametr \"schema\" nie może być wskazany gdy \"relocatable\" jest prawdą"
-#: commands/extension.c:721
+#: commands/extension.c:757
#, c-format
msgid "transaction control statements are not allowed within an extension script"
msgstr "wyrażenia kontrolne transakcji nie są dopuszczalne w skryptach rozszerzeń"
-#: commands/extension.c:789
+#: commands/extension.c:803
#, c-format
msgid "permission denied to create extension \"%s\""
msgstr "odmowa dostępu do tworzenia rozszerzenia \"%s\""
-#: commands/extension.c:791
+#: commands/extension.c:805
#, c-format
msgid "Must be superuser to create this extension."
msgstr "musisz być superużytkownikiem aby utworzyć to rozszerzenie."
-#: commands/extension.c:795
+#: commands/extension.c:809
#, c-format
msgid "permission denied to update extension \"%s\""
msgstr "odmowa dostępu do modyfikacji rozszerzenia \"%s\""
-#: commands/extension.c:797
+#: commands/extension.c:811
#, c-format
msgid "Must be superuser to update this extension."
msgstr "Musisz być superużytkownikiem aby zmodyfikować to rozszerzenie."
-#: commands/extension.c:1079
+#: commands/extension.c:1093
#, c-format
msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\""
msgstr "rozszerzenie \"%s\" nie ma ścieżki modyfikacji z wersji \"%s\" do wersji \"%s\""
-#: commands/extension.c:1261 commands/extension.c:2778
+#: commands/extension.c:1300 commands/extension.c:2963
#, c-format
msgid "version to install must be specified"
msgstr "wersja do zainstalowanie musi być określona"
-#: commands/extension.c:1278
+#: commands/extension.c:1322
#, c-format
msgid "FROM version must be different from installation target version \"%s\""
msgstr "wersja FROM musi być inna niż wersja docelowa instalacji \"%s\""
-#: commands/extension.c:1343
+#: commands/extension.c:1387
+#, c-format
+#| msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\""
+msgid "extension \"%s\" has no installation script nor update path for version \"%s\""
+msgstr ""
+"rozszerzenie \"%s\" nie ma skryptu ani ścieżki aktualizacji dla wersji \"%s\""
+
+#: commands/extension.c:1422
#, c-format
msgid "extension \"%s\" must be installed in schema \"%s\""
msgstr "rozszerzenie \"%s\" musi być zainstalowane w schemacie \"%s\""
-#: commands/extension.c:1435
+#: commands/extension.c:1575
#, c-format
-#| msgid "collation mismatch between explicit collations \"%s\" and \"%s\""
msgid "cyclic dependency detected between extensions \"%s\" and \"%s\""
msgstr "wykryto zależność cykliczną między rozszerzeniami \"%s\" i \"%s\""
-#: commands/extension.c:1440
+#: commands/extension.c:1580
#, c-format
-#| msgid "invalid extension name: \"%s\""
msgid "installing required extension \"%s\""
msgstr "instalacja wymaganego rozszerzenia \"%s\""
-#: commands/extension.c:1468 commands/extension.c:2923
+#: commands/extension.c:1604
#, c-format
msgid "required extension \"%s\" is not installed"
msgstr "wymagane rozszerzenie \"%s\" nie jest zainstalowane"
-#: commands/extension.c:1470
+#: commands/extension.c:1607
#, c-format
-#| msgid "Use ALTER ... CASCADE to alter the typed tables too."
-msgid "Use CREATE EXTENSION CASCADE to install required extensions too."
-msgstr ""
-"Użyj CREATE EXTENSION CASCADE aby zainstalować również wymagane "
-"rozszerzenia."
+msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too."
+msgstr "Użyj CREATE EXTENSION ... CASCADE aby zainstalować również wymagane rozszerzenia."
-#: commands/extension.c:1534
+#: commands/extension.c:1644
#, c-format
msgid "extension \"%s\" already exists, skipping"
msgstr "rozszerzenie \"%s\" już istnieje, pominięto"
-#: commands/extension.c:1541
+#: commands/extension.c:1651
#, c-format
msgid "extension \"%s\" already exists"
msgstr "rozszerzenie \"%s\" już istnieje"
-#: commands/extension.c:1552
+#: commands/extension.c:1662
#, c-format
msgid "nested CREATE EXTENSION is not supported"
msgstr "zagnieżdżone CREATE EXTENSION nie jest obsługiwane"
-#: commands/extension.c:1680
+#: commands/extension.c:1843
#, c-format
msgid "cannot drop extension \"%s\" because it is being modified"
msgstr "nie można usunąć rozszerzenia \"%s\" ponieważ jest właśnie modyfikowane"
-#: commands/extension.c:2151
+#: commands/extension.c:2345
#, c-format
msgid "pg_extension_config_dump() can only be called from an SQL script executed by CREATE EXTENSION"
msgstr "pg_extension_config_dump() może być wywołane tylko ze skryptu SQL wykonywanego przez CREATE EXTENSION"
-#: commands/extension.c:2163
+#: commands/extension.c:2357
#, c-format
msgid "OID %u does not refer to a table"
msgstr "OID %u nie wskazuje na tabelę"
-#: commands/extension.c:2168
+#: commands/extension.c:2362
#, c-format
msgid "table \"%s\" is not a member of the extension being created"
msgstr "tabela \"%s\" nie jest składnikiem tworzonego właśnie rozszerzenia"
-#: commands/extension.c:2533
+#: commands/extension.c:2718
#, c-format
msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema"
msgstr "nie można przenieść rozszerzenia \"%s\" do schematu \"%s\" ponieważ rozszerzenie zawiera ten schemat"
-#: commands/extension.c:2573 commands/extension.c:2636
+#: commands/extension.c:2758 commands/extension.c:2821
#, c-format
msgid "extension \"%s\" does not support SET SCHEMA"
msgstr "rozszerzenie \"%s\" nie obsługuje SET SCHEMA"
-#: commands/extension.c:2638
+#: commands/extension.c:2823
#, c-format
msgid "%s is not in the extension's schema \"%s\""
msgstr "%s nie znajduje się w schemacie \"%s\" rozszerzenia"
-#: commands/extension.c:2698
+#: commands/extension.c:2882
#, c-format
msgid "nested ALTER EXTENSION is not supported"
msgstr "zagnieżdżone ALTER EXTENSION nie jest obsługiwane"
-#: commands/extension.c:2789
+#: commands/extension.c:2974
#, c-format
msgid "version \"%s\" of extension \"%s\" is already installed"
msgstr "wersja \"%s\" rozszerzenia \"%s\" jest już zainstalowana"
-#: commands/extension.c:3040
+#: commands/extension.c:3225
#, c-format
msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension"
msgstr "nie można dodać schematu \"%s\" do rozszerzenia \"%s\" ponieważ schemat zawiera to rozszerzenie"
-#: commands/extension.c:3058
+#: commands/extension.c:3253
#, c-format
msgid "%s is not a member of extension \"%s\""
msgstr "%s nie jest składnikiem rozszerzenia \"%s\""
-#: commands/extension.c:3114
+#: commands/extension.c:3319
#, c-format
msgid "file \"%s\" is too large"
msgstr "plik \"%s\" jest za duży"
@@ -6635,72 +6997,87 @@ msgstr "Musisz być superużytkownikiem by zmienić właściciela opakowania obc
msgid "The owner of a foreign-data wrapper must be a superuser."
msgstr "Właściciel opakowania obcych danych musi być superużytkownikiem."
-#: commands/foreigncmds.c:292 commands/foreigncmds.c:709 foreign/foreign.c:759
+#: commands/foreigncmds.c:291 commands/foreigncmds.c:706 foreign/foreign.c:667
#, c-format
msgid "foreign-data wrapper \"%s\" does not exist"
msgstr "opakowanie obcych danych \"%s\" nie istnieje"
-#: commands/foreigncmds.c:584
+#: commands/foreigncmds.c:582
#, c-format
msgid "permission denied to create foreign-data wrapper \"%s\""
msgstr "odmowa dostępu do tworzenia opakowania obcych danych \"%s\""
-#: commands/foreigncmds.c:586
+#: commands/foreigncmds.c:584
#, c-format
msgid "Must be superuser to create a foreign-data wrapper."
msgstr "Musisz być superużytkownikiem aby tworzyć opakowanie danych obcych."
-#: commands/foreigncmds.c:699
+#: commands/foreigncmds.c:696
#, c-format
msgid "permission denied to alter foreign-data wrapper \"%s\""
msgstr "odmowa dostępu do zmiany opakowania danych zewnętrznych \"%s\""
-#: commands/foreigncmds.c:701
+#: commands/foreigncmds.c:698
#, c-format
msgid "Must be superuser to alter a foreign-data wrapper."
msgstr "Musisz być superużytkownikiem aby zmienić opakowanie danych obcych."
-#: commands/foreigncmds.c:732
+#: commands/foreigncmds.c:729
#, c-format
msgid "changing the foreign-data wrapper handler can change behavior of existing foreign tables"
msgstr "zmiana programu obsługi opakowania danych obcych może zmienić zachowanie istniejących tabel obcych"
-#: commands/foreigncmds.c:747
+#: commands/foreigncmds.c:744
#, c-format
msgid "changing the foreign-data wrapper validator can cause the options for dependent objects to become invalid"
msgstr "zmiana walidatora opakowania danych obcych może sprawić, że opcje zależnych obiektów staną się niepoprawne"
-#: commands/foreigncmds.c:1165
+#: commands/foreigncmds.c:890
#, c-format
-msgid "user mapping \"%s\" already exists for server %s"
-msgstr "mapowanie użytkownika \"%s\" istnieje już w dla serwera %s"
+#| msgid "schema \"%s\" already exists, skipping"
+msgid "server \"%s\" already exists, skipping"
+msgstr "serwer \"%s\" już istnieje, pominięto"
-#: commands/foreigncmds.c:1259 commands/foreigncmds.c:1375
+#: commands/foreigncmds.c:1175
#, c-format
-msgid "user mapping \"%s\" does not exist for the server"
-msgstr "mapowanie użytkownika \"%s\" nie istnieje dla tego serwera"
+#| msgid "user mapping \"%s\" already exists for server %s"
+msgid "user mapping for \"%s\" already exists for server %s, skipping"
+msgstr "mapowanie użytkownika \"%s\" istnieje już w dla serwera %s, pominięto"
-#: commands/foreigncmds.c:1362
+#: commands/foreigncmds.c:1185
+#, c-format
+#| msgid "user mapping \"%s\" already exists for server %s"
+msgid "user mapping for \"%s\" already exists for server %s"
+msgstr "mapowanie użytkownika \"%s\" już istnieje dla serwera %s"
+
+#: commands/foreigncmds.c:1278 commands/foreigncmds.c:1393
+#, c-format
+#| msgid "user mapping \"%s\" does not exist for the server"
+msgid "user mapping for \"%s\" does not exist for the server"
+msgstr "mapowanie użytkownika dla \"%s\" nie istnieje dla tego serwera"
+
+#: commands/foreigncmds.c:1380
#, c-format
msgid "server does not exist, skipping"
msgstr "serwer nie istnieje, pominięto"
-#: commands/foreigncmds.c:1380
+#: commands/foreigncmds.c:1398
#, c-format
-msgid "user mapping \"%s\" does not exist for the server, skipping"
-msgstr "mapowanie użytkownika \"%s\" nie istnieje dla tego serwera, pominięto"
+#| msgid "user mapping \"%s\" does not exist for the server, skipping"
+msgid "user mapping for \"%s\" does not exist for the server, skipping"
+msgstr "mapowanie użytkownika dla \"%s\" nie istnieje dla tego serwera, pominięto"
-#: commands/foreigncmds.c:1532 foreign/foreign.c:449
+#: commands/foreigncmds.c:1549 foreign/foreign.c:357
#, c-format
msgid "foreign-data wrapper \"%s\" has no handler"
msgstr "opakowanie obcych danych \"%s\" nie ma uchwytu"
-#: commands/foreigncmds.c:1538
+#: commands/foreigncmds.c:1555
#, c-format
msgid "foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA"
msgstr "opakowanie obcych danych \"%s\" nie obsługuje IMPORT FOREIGN SCHEMA"
-#: commands/foreigncmds.c:1631
+#: commands/foreigncmds.c:1658
#, c-format
msgid "importing foreign table \"%s\""
msgstr "importowanie tabeli zewnętrznej \"%s\""
@@ -6730,87 +7107,87 @@ msgstr "typ \"%s\" nie jest jeszcze zdefiniowany"
msgid "Creating a shell type definition."
msgstr "Tworzenie definicji typu powłoki."
-#: commands/functioncmds.c:239
+#: commands/functioncmds.c:233
#, c-format
msgid "SQL function cannot accept shell type %s"
msgstr "funkcja SQL nie może przyjmować typu powłoki %s"
-#: commands/functioncmds.c:245
+#: commands/functioncmds.c:239
#, c-format
msgid "aggregate cannot accept shell type %s"
msgstr "agregat nie może przyjmować typu powłoki %s"
-#: commands/functioncmds.c:250
+#: commands/functioncmds.c:244
#, c-format
msgid "argument type %s is only a shell"
msgstr "typ argumentu %s jest jedynie powłoką"
-#: commands/functioncmds.c:260
+#: commands/functioncmds.c:254
#, c-format
msgid "type %s does not exist"
msgstr "typ %s nie istnieje"
-#: commands/functioncmds.c:274
+#: commands/functioncmds.c:268
#, c-format
msgid "aggregates cannot accept set arguments"
msgstr "agregaty nie mogą używać zbiorów argumentów"
-#: commands/functioncmds.c:278
+#: commands/functioncmds.c:272
#, c-format
msgid "functions cannot accept set arguments"
msgstr "funkcje nie mogą przyjmować grupy argumentów"
-#: commands/functioncmds.c:288
+#: commands/functioncmds.c:282
#, c-format
msgid "VARIADIC parameter must be the last input parameter"
msgstr "parametr VARIADIC musi być ostatnim parametrem wejścia"
-#: commands/functioncmds.c:316
+#: commands/functioncmds.c:310
#, c-format
msgid "VARIADIC parameter must be an array"
msgstr "parametr VARIADIC nie może być typu tablicowego"
-#: commands/functioncmds.c:356
+#: commands/functioncmds.c:350
#, c-format
msgid "parameter name \"%s\" used more than once"
msgstr "nazwa parametru \"%s\" użyta więcej niż raz"
-#: commands/functioncmds.c:371
+#: commands/functioncmds.c:365
#, c-format
msgid "only input parameters can have default values"
msgstr "tylko parametry wejścia mogą posiadać wartości domyślne"
-#: commands/functioncmds.c:386
+#: commands/functioncmds.c:380
#, c-format
msgid "cannot use table references in parameter default value"
msgstr "nie można użyć odwołania do tabeli w domyślnej wartości parametru"
-#: commands/functioncmds.c:410
+#: commands/functioncmds.c:404
#, c-format
msgid "input parameters after one with a default value must also have defaults"
msgstr "parametry wejścia po posiadającym wartość domyślną muszą również posiadać wartości domyślne"
-#: commands/functioncmds.c:701
+#: commands/functioncmds.c:700
#, c-format
msgid "no function body specified"
msgstr "nie określono ciała funkcji"
-#: commands/functioncmds.c:711
+#: commands/functioncmds.c:710
#, c-format
msgid "no language specified"
msgstr "nie określono języka"
-#: commands/functioncmds.c:736 commands/functioncmds.c:1243
+#: commands/functioncmds.c:735 commands/functioncmds.c:1241
#, c-format
msgid "COST must be positive"
msgstr "COST musi być dodatni"
-#: commands/functioncmds.c:744 commands/functioncmds.c:1251
+#: commands/functioncmds.c:743 commands/functioncmds.c:1249
#, c-format
msgid "ROWS must be positive"
msgstr "ROWS musi być dodatni"
-#: commands/functioncmds.c:785
+#: commands/functioncmds.c:784
#, c-format
msgid "unrecognized function attribute \"%s\" ignored"
msgstr "pominięto nierozpoznany atrybut \"%s\" funkcji"
@@ -6820,376 +7197,382 @@ msgstr "pominięto nierozpoznany atrybut \"%s\" funkcji"
msgid "only one AS item needed for language \"%s\""
msgstr "wyłącznie jeden element AS jest wymagany dla języka \"%s\""
-#: commands/functioncmds.c:929 commands/functioncmds.c:2119
-#: commands/proclang.c:563
+#: commands/functioncmds.c:930 commands/functioncmds.c:2110
+#: commands/proclang.c:561
#, c-format
msgid "language \"%s\" does not exist"
msgstr "język \"%s\" nie istnieje"
-#: commands/functioncmds.c:931 commands/functioncmds.c:2121
+#: commands/functioncmds.c:932 commands/functioncmds.c:2112
#, c-format
msgid "Use CREATE LANGUAGE to load the language into the database."
msgstr "Użyj CREATE LANGUAGE aby załadować język do bazy danych."
-#: commands/functioncmds.c:966 commands/functioncmds.c:1235
+#: commands/functioncmds.c:967 commands/functioncmds.c:1233
#, c-format
msgid "only superuser can define a leakproof function"
msgstr "tylko superużytkownik może zdefiniować szczelną funkcję"
-#: commands/functioncmds.c:1010
+#: commands/functioncmds.c:1009
#, c-format
msgid "function result type must be %s because of OUT parameters"
msgstr "wynik funkcji musi być typu %s ze względu na parametry OUT"
-#: commands/functioncmds.c:1023
+#: commands/functioncmds.c:1022
#, c-format
msgid "function result type must be specified"
msgstr "wynik funkcji musi być określony"
-#: commands/functioncmds.c:1077 commands/functioncmds.c:1255
+#: commands/functioncmds.c:1076 commands/functioncmds.c:1253
#, c-format
msgid "ROWS is not applicable when function does not return a set"
msgstr "ROWS nie jest odpowiedni gdy funkcja nie zwraca zbioru"
-#: commands/functioncmds.c:1412
+#: commands/functioncmds.c:1405
#, c-format
msgid "source data type %s is a pseudo-type"
msgstr "źródłowy typ danych %s jest pseudo-typem"
-#: commands/functioncmds.c:1418
+#: commands/functioncmds.c:1411
#, c-format
msgid "target data type %s is a pseudo-type"
msgstr "docelowy typ danych %s jest pseudo-typem"
-#: commands/functioncmds.c:1442
+#: commands/functioncmds.c:1435
#, c-format
msgid "cast will be ignored because the source data type is a domain"
msgstr "funkcja rzutująca zostanie zignorowana ponieważ źródłowy typ danych jest domeną"
-#: commands/functioncmds.c:1447
+#: commands/functioncmds.c:1440
#, c-format
msgid "cast will be ignored because the target data type is a domain"
msgstr "funkcja rzutująca zostanie zignorowana ponieważ docelowy typ danych jest domeną"
-#: commands/functioncmds.c:1474
+#: commands/functioncmds.c:1465
#, c-format
msgid "cast function must take one to three arguments"
msgstr "funkcja rzutująca musi przyjmować od jednego do trzech argumentów"
-#: commands/functioncmds.c:1478
+#: commands/functioncmds.c:1469
#, c-format
msgid "argument of cast function must match or be binary-coercible from source data type"
msgstr "argumenty funkcji rzutującej muszą pasować lub być binarnie zgodne ze źródłowym typem danych"
-#: commands/functioncmds.c:1482
+#: commands/functioncmds.c:1473
#, c-format
-msgid "second argument of cast function must be type integer"
-msgstr "drugi argument funkcji rzutującej musi być typu całkowitego"
+#| msgid "second argument of cast function must be type integer"
+msgid "second argument of cast function must be type %s"
+msgstr "drugi argument funkcji rzutującej musi być typu %s"
-#: commands/functioncmds.c:1486
+#: commands/functioncmds.c:1478
#, c-format
-msgid "third argument of cast function must be type boolean"
-msgstr "trzeci argument funkcji rzutującej musi być typu logicznego"
+#| msgid "third argument of cast function must be type boolean"
+msgid "third argument of cast function must be type %s"
+msgstr "trzeci argument funkcji rzutującej musi być typu %s"
-#: commands/functioncmds.c:1490
+#: commands/functioncmds.c:1483
#, c-format
msgid "return data type of cast function must match or be binary-coercible to target data type"
msgstr "zwracany typ danych funkcji rzutującej musi pasować lub być binarnie zgodny z docelowym typem danych"
-#: commands/functioncmds.c:1501
+#: commands/functioncmds.c:1494
#, c-format
msgid "cast function must not be volatile"
msgstr "funkcja rzutująca nie może być zmienna"
-#: commands/functioncmds.c:1506
+#: commands/functioncmds.c:1499
#, c-format
msgid "cast function must not be an aggregate function"
msgstr "funkcja rzutująca nie może być funkcją agregującą"
-#: commands/functioncmds.c:1510
+#: commands/functioncmds.c:1503
#, c-format
msgid "cast function must not be a window function"
msgstr "funkcja rzutująca nie może być funkcją okna"
-#: commands/functioncmds.c:1514
+#: commands/functioncmds.c:1507
#, c-format
msgid "cast function must not return a set"
msgstr "funkcja rzutująca nie może zwracać grupy"
-#: commands/functioncmds.c:1540
+#: commands/functioncmds.c:1533
#, c-format
msgid "must be superuser to create a cast WITHOUT FUNCTION"
msgstr "musisz być superużytkownikiem aby utworzyć rzutowanie WITHOUT FUNCTION"
-#: commands/functioncmds.c:1555
+#: commands/functioncmds.c:1548
#, c-format
msgid "source and target data types are not physically compatible"
msgstr "źródłowy i docelowy typ danych nie są fizycznie kompatybilne"
-#: commands/functioncmds.c:1570
+#: commands/functioncmds.c:1563
#, c-format
msgid "composite data types are not binary-compatible"
msgstr "złożone typy danych nie są binarnie kompatybilne"
-#: commands/functioncmds.c:1576
+#: commands/functioncmds.c:1569
#, c-format
msgid "enum data types are not binary-compatible"
msgstr "enumeracyjne typy danych nie są binarnie kompatybilne"
-#: commands/functioncmds.c:1582
+#: commands/functioncmds.c:1575
#, c-format
msgid "array data types are not binary-compatible"
msgstr "tablicowe typy danych nie są binarnie kompatybilne"
-#: commands/functioncmds.c:1599
+#: commands/functioncmds.c:1592
#, c-format
msgid "domain data types must not be marked binary-compatible"
msgstr "domenowe typy danych nie mogą być zaznaczone jako binarnie kompatybilne"
-#: commands/functioncmds.c:1609
+#: commands/functioncmds.c:1602
#, c-format
msgid "source data type and target data type are the same"
msgstr "źródłowy typ danych i docelowy typ danych są takie same"
-#: commands/functioncmds.c:1642
+#: commands/functioncmds.c:1635
#, c-format
msgid "cast from type %s to type %s already exists"
msgstr "rzutowanie z typu %s na typ %s już istnieje"
-#: commands/functioncmds.c:1717
+#: commands/functioncmds.c:1708
#, c-format
msgid "cast from type %s to type %s does not exist"
msgstr "rzutowanie z typu %s do typu %s nie istnieje"
-#: commands/functioncmds.c:1756
+#: commands/functioncmds.c:1747
#, c-format
msgid "transform function must not be volatile"
msgstr "funkcja transformacji nie może być zmienna"
-#: commands/functioncmds.c:1760
+#: commands/functioncmds.c:1751
#, c-format
msgid "transform function must not be an aggregate function"
msgstr "funkcja transformacji nie może być funkcją agregującą"
-#: commands/functioncmds.c:1764
+#: commands/functioncmds.c:1755
#, c-format
msgid "transform function must not be a window function"
msgstr "funkcja transformacji nie może być funkcją okna"
-#: commands/functioncmds.c:1768
+#: commands/functioncmds.c:1759
#, c-format
msgid "transform function must not return a set"
msgstr "funkcja transformacji nie może zwracać grupy"
-#: commands/functioncmds.c:1772
+#: commands/functioncmds.c:1763
#, c-format
msgid "transform function must take one argument"
msgstr "funkcja transformacji musi przyjmować jeden argument"
-#: commands/functioncmds.c:1776
+#: commands/functioncmds.c:1767
#, c-format
-msgid "first argument of transform function must be type \"internal\""
-msgstr "pierwszy argument funkcji transformacji musi być typu \"internal\""
+#| msgid "first argument of transform function must be type \"internal\""
+msgid "first argument of transform function must be type %s"
+msgstr "pierwszy argument funkcji transformacji musi być typu %s"
-#: commands/functioncmds.c:1813
+#: commands/functioncmds.c:1805
#, c-format
msgid "data type %s is a pseudo-type"
msgstr "typ danych %s jest pseudo-typem"
-#: commands/functioncmds.c:1819
+#: commands/functioncmds.c:1811
#, c-format
msgid "data type %s is a domain"
msgstr "typ danych %s jest domeną"
-#: commands/functioncmds.c:1859
+#: commands/functioncmds.c:1851
#, c-format
-msgid "return data type of FROM SQL function must be \"internal\""
-msgstr "zwracany typ danych funkcji FROM SQL musi być \"internal\""
+#| msgid "return data type of FROM SQL function must be \"internal\""
+msgid "return data type of FROM SQL function must be %s"
+msgstr "zwracany typ danych funkcji FROM SQL musi być %s"
-#: commands/functioncmds.c:1884
+#: commands/functioncmds.c:1877
#, c-format
msgid "return data type of TO SQL function must be the transform data type"
msgstr "zwracany typ danych funkcji TO SQL musi pasować lub być typem danych transformacji"
-#: commands/functioncmds.c:1911
+#: commands/functioncmds.c:1904
#, c-format
msgid "transform for type %s language \"%s\" already exists"
msgstr "transformacja dla typu %s język \"%s\" już istnieje"
-#: commands/functioncmds.c:2002
+#: commands/functioncmds.c:1993
#, c-format
msgid "transform for type %s language \"%s\" does not exist"
msgstr "transformacja dla typu %s język \"%s\" nie istnieje"
-#: commands/functioncmds.c:2053
+#: commands/functioncmds.c:2044
#, c-format
msgid "function %s already exists in schema \"%s\""
msgstr "funkcja %s istnieje już w schemacie \"%s\""
-#: commands/functioncmds.c:2106
+#: commands/functioncmds.c:2097
#, c-format
msgid "no inline code specified"
msgstr "nie określono kodu wbudowanego"
-#: commands/functioncmds.c:2151
+#: commands/functioncmds.c:2142
#, c-format
msgid "language \"%s\" does not support inline code execution"
msgstr "język \"%s\" nie obsługuje wykonywania kodu wbudowanego"
-#: commands/indexcmds.c:349
+#: commands/indexcmds.c:350
#, c-format
msgid "must specify at least one column"
msgstr "musi określać przynajmniej jedną kolumnę"
-#: commands/indexcmds.c:353
+#: commands/indexcmds.c:354
#, c-format
msgid "cannot use more than %d columns in an index"
msgstr "nie można użyć więcej niż %d kolumn w indeksie"
-#: commands/indexcmds.c:384
+#: commands/indexcmds.c:385
#, c-format
msgid "cannot create index on foreign table \"%s\""
msgstr "nie można utworzyć indeksu na tabeli obcej \"%s\""
-#: commands/indexcmds.c:399
+#: commands/indexcmds.c:390
+#, c-format
+#| msgid "cannot create index on foreign table \"%s\""
+msgid "cannot create index on partitioned table \"%s\""
+msgstr "nie można utworzyć indeksu na tabeli partycjonowanej \"%s\""
+
+#: commands/indexcmds.c:405
#, c-format
msgid "cannot create indexes on temporary tables of other sessions"
msgstr "nie można tworzyć indeksów na tabelach tymczasowych z innych sesji"
-#: commands/indexcmds.c:454 commands/tablecmds.c:545 commands/tablecmds.c:9597
+#: commands/indexcmds.c:461 commands/tablecmds.c:584
+#: commands/tablecmds.c:10459
#, c-format
msgid "only shared relations can be placed in pg_global tablespace"
msgstr "tylko relacje współdzielone mogą być umieszczone w przestrzeni tabel pg_global"
-#: commands/indexcmds.c:487
+#: commands/indexcmds.c:494
#, c-format
msgid "substituting access method \"gist\" for obsolete method \"rtree\""
msgstr "zastąpienie metodą dostępu \"gist\" przestarzałej metody \"rtree\""
-#: commands/indexcmds.c:505
-#, c-format
-msgid "hash indexes are not WAL-logged and their use is discouraged"
-msgstr "indeksy haszowane nie są logowane WAL i ich użycie jest odradzane"
-
-#: commands/indexcmds.c:510
+#: commands/indexcmds.c:512
#, c-format
msgid "access method \"%s\" does not support unique indexes"
msgstr "metoda dostępu \"%s\" nie obsługuje indeksów unikalnych"
-#: commands/indexcmds.c:515
+#: commands/indexcmds.c:517
#, c-format
msgid "access method \"%s\" does not support multicolumn indexes"
msgstr "metoda dostępu \"%s\" nie obsługuje indeksów wielokolumnowych"
-#: commands/indexcmds.c:520
+#: commands/indexcmds.c:522
#, c-format
msgid "access method \"%s\" does not support exclusion constraints"
msgstr "metoda dostępu \"%s\" nie obsługuje ograniczeń wykluczających"
-#: commands/indexcmds.c:590 commands/indexcmds.c:610
+#: commands/indexcmds.c:594 commands/indexcmds.c:614
#, c-format
-#| msgid "concurrent index creation on system catalog tables is not supported"
msgid "index creation on system columns is not supported"
msgstr "tworzenie indeksów kolumnach systemowych nie jest obsługiwane"
-#: commands/indexcmds.c:635
+#: commands/indexcmds.c:639
#, c-format
msgid "%s %s will create implicit index \"%s\" for table \"%s\""
msgstr "%s %s utworzy niejawny indeks \"%s\" na tabeli \"%s\""
-#: commands/indexcmds.c:982
+#: commands/indexcmds.c:986
#, c-format
msgid "functions in index predicate must be marked IMMUTABLE"
msgstr "funkcje w predykacie indeksu muszą być oznaczone jako IMMUTABLE"
-#: commands/indexcmds.c:1048 parser/parse_utilcmd.c:1894
+#: commands/indexcmds.c:1052 parser/parse_utilcmd.c:2064
#, c-format
msgid "column \"%s\" named in key does not exist"
msgstr "kolumna \"%s\" nazwana w kluczu nie istnieje"
-#: commands/indexcmds.c:1108
+#: commands/indexcmds.c:1112
#, c-format
msgid "functions in index expression must be marked IMMUTABLE"
msgstr "funkcje w wyrażeniu indeksu muszą być oznaczone jako IMMUTABLE"
-#: commands/indexcmds.c:1131
+#: commands/indexcmds.c:1135
#, c-format
msgid "could not determine which collation to use for index expression"
msgstr "nie można określić, jakiego porównania użyć dla wyrażenia indeksu"
-#: commands/indexcmds.c:1139 commands/typecmds.c:827 parser/parse_expr.c:2583
-#: parser/parse_type.c:550 parser/parse_utilcmd.c:2820 utils/adt/misc.c:666
+#: commands/indexcmds.c:1143 commands/tablecmds.c:13301
+#: commands/typecmds.c:831 parser/parse_expr.c:2730 parser/parse_type.c:549
+#: parser/parse_utilcmd.c:3089 utils/adt/misc.c:661
#, c-format
msgid "collations are not supported by type %s"
msgstr "rzutowania nie są obsługiwane przez typ %s"
-#: commands/indexcmds.c:1177
+#: commands/indexcmds.c:1181
#, c-format
msgid "operator %s is not commutative"
msgstr "operator %s nie jest przemienny"
-#: commands/indexcmds.c:1179
+#: commands/indexcmds.c:1183
#, c-format
msgid "Only commutative operators can be used in exclusion constraints."
msgstr "Tylko operatory przemienne mogą być używane w ograniczeniach wykluczających."
-#: commands/indexcmds.c:1205
+#: commands/indexcmds.c:1209
#, c-format
msgid "operator %s is not a member of operator family \"%s\""
msgstr "operator %s nie jest członkiem rodziny operatorów \"%s\""
-#: commands/indexcmds.c:1208
+#: commands/indexcmds.c:1212
#, c-format
msgid "The exclusion operator must be related to the index operator class for the constraint."
msgstr "Operator wykluczający musi być powiązany z klasą operatora indeksu do ograniczenia."
-#: commands/indexcmds.c:1243
+#: commands/indexcmds.c:1247
#, c-format
msgid "access method \"%s\" does not support ASC/DESC options"
msgstr "metoda dostępu \"%s\" nie obsługuje opcji ASC/DESC"
-#: commands/indexcmds.c:1248
+#: commands/indexcmds.c:1252
#, c-format
msgid "access method \"%s\" does not support NULLS FIRST/LAST options"
msgstr "metoda dostępu \"%s\" nie obsługuje opcji NULLS FIRST/LAST"
-#: commands/indexcmds.c:1304 commands/typecmds.c:1935
+#: commands/indexcmds.c:1311 commands/typecmds.c:1928
#, c-format
msgid "data type %s has no default operator class for access method \"%s\""
msgstr "typ danych %s nie ma domyślnej klasy operatora dla metody dostępu \"%s\""
-#: commands/indexcmds.c:1306
+#: commands/indexcmds.c:1313
#, c-format
msgid "You must specify an operator class for the index or define a default operator class for the data type."
msgstr "Musisz wskazać klasę operatora dla indeksu lub zdefiniować domyślną klasę operatora dla typu danych."
-#: commands/indexcmds.c:1335 commands/indexcmds.c:1343
+#: commands/indexcmds.c:1342 commands/indexcmds.c:1350
#: commands/opclasscmds.c:205
#, c-format
msgid "operator class \"%s\" does not exist for access method \"%s\""
msgstr "klasa operatora \"%s\" nie istnieje dla metody dostępu \"%s\""
-#: commands/indexcmds.c:1356 commands/typecmds.c:1923
+#: commands/indexcmds.c:1363 commands/typecmds.c:1916
#, c-format
msgid "operator class \"%s\" does not accept data type %s"
msgstr "klasa operatora \"%s\" nie akceptuje typu danych %s"
-#: commands/indexcmds.c:1446
+#: commands/indexcmds.c:1453
#, c-format
msgid "there are multiple default operator classes for data type %s"
msgstr "jest wiele domyślnych klas operatorów dla typu danych %s"
-#: commands/indexcmds.c:1837
+#: commands/indexcmds.c:1844
#, c-format
msgid "table \"%s\" has no indexes"
msgstr "tabela \"%s\" nie posiada indeksów"
-#: commands/indexcmds.c:1892
+#: commands/indexcmds.c:1899
#, c-format
msgid "can only reindex the currently open database"
msgstr "nie można przeindeksować aktualnie otwartej bazy danych"
-#: commands/indexcmds.c:1994
+#: commands/indexcmds.c:1999
#, c-format
msgid "table \"%s.%s\" was reindexed"
msgstr "tabela \"%s.%s\" została przeindeksowana"
@@ -7214,12 +7597,12 @@ msgstr "nie można odświeżyć widoku materializowanego \"%s\" równolegle"
msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view."
msgstr "Utwórz indeks UNIQUE bez klauzuli WHERE na jednej lub więcej kolumn widoku zmaterializowanego."
-#: commands/matview.c:657
+#: commands/matview.c:678
#, c-format
msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns"
msgstr "nowe dane dla widoku zmaterializowanego \"%s\" zawierają wielokrotne wiersze bez żadnej pustej kolumny"
-#: commands/matview.c:659
+#: commands/matview.c:680
#, c-format
msgid "Row: %s"
msgstr "Wiersz: %s"
@@ -7234,159 +7617,159 @@ msgstr "rodzina operatora \"%s\" nie istnieje dla metody dostępu \"%s\""
msgid "operator family \"%s\" for access method \"%s\" already exists"
msgstr "rodzina operatora \"%s\" dla metody dostępu \"%s\" już istnieje"
-#: commands/opclasscmds.c:404
+#: commands/opclasscmds.c:402
#, c-format
msgid "must be superuser to create an operator class"
msgstr "musisz być superużytkownikiem aby utworzyć klasę operatora"
-#: commands/opclasscmds.c:478 commands/opclasscmds.c:863
-#: commands/opclasscmds.c:996
+#: commands/opclasscmds.c:475 commands/opclasscmds.c:849
+#: commands/opclasscmds.c:973
#, c-format
msgid "invalid operator number %d, must be between 1 and %d"
msgstr "niepoprawny numer operatora %d, musi być pomiędzy 1 a %d"
-#: commands/opclasscmds.c:529 commands/opclasscmds.c:914
-#: commands/opclasscmds.c:1011
+#: commands/opclasscmds.c:519 commands/opclasscmds.c:893
+#: commands/opclasscmds.c:988
#, c-format
msgid "invalid procedure number %d, must be between 1 and %d"
msgstr "niepoprawny numer procedury %d, musi być pomiędzy 1 a %d"
-#: commands/opclasscmds.c:559
+#: commands/opclasscmds.c:548
#, c-format
msgid "storage type specified more than once"
msgstr "typ składowania określony więcej niż raz"
-#: commands/opclasscmds.c:586
+#: commands/opclasscmds.c:575
#, c-format
msgid "storage type cannot be different from data type for access method \"%s\""
msgstr "typ składowania nie może być inny niż ten z typu danych dla metody dostępu \"%s\""
-#: commands/opclasscmds.c:602
+#: commands/opclasscmds.c:591
#, c-format
msgid "operator class \"%s\" for access method \"%s\" already exists"
msgstr "klasa operatora \"%s\" dla metody dostępu \"%s\" już istnieje"
-#: commands/opclasscmds.c:630
+#: commands/opclasscmds.c:619
#, c-format
msgid "could not make operator class \"%s\" be default for type %s"
msgstr "nie można uczynić klasy operatora \"%s\" domyślną dla typu %s"
-#: commands/opclasscmds.c:633
+#: commands/opclasscmds.c:622
#, c-format
msgid "Operator class \"%s\" already is the default."
msgstr "Klasa operatora \"%s\" jest już domyślna."
-#: commands/opclasscmds.c:760
+#: commands/opclasscmds.c:747
#, c-format
msgid "must be superuser to create an operator family"
msgstr "musisz być superużytkownikiem aby utworzyć rodzinę operatora"
-#: commands/opclasscmds.c:816
+#: commands/opclasscmds.c:803
#, c-format
msgid "must be superuser to alter an operator family"
msgstr "musisz być superużytkownikiem aby zmienić rodzinę operatora"
-#: commands/opclasscmds.c:879
+#: commands/opclasscmds.c:858
#, c-format
msgid "operator argument types must be specified in ALTER OPERATOR FAMILY"
msgstr "typy argumentów operatora muszą być wskazane w ALTER OPERATOR FAMILY"
-#: commands/opclasscmds.c:943
+#: commands/opclasscmds.c:921
#, c-format
msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY"
msgstr "STORAGE nie może być wskazana w ALTER OPERATOR FAMILY"
-#: commands/opclasscmds.c:1066
+#: commands/opclasscmds.c:1043
#, c-format
msgid "one or two argument types must be specified"
msgstr "jeden lub wiele typów argumentów musi być wskazane"
-#: commands/opclasscmds.c:1092
+#: commands/opclasscmds.c:1069
#, c-format
msgid "index operators must be binary"
msgstr "operatory indeksowe muszą być binarne"
-#: commands/opclasscmds.c:1111
+#: commands/opclasscmds.c:1088
#, c-format
msgid "access method \"%s\" does not support ordering operators"
msgstr "metoda dostępu \"%s\" nie obsługuje operatorów porządkujących"
-#: commands/opclasscmds.c:1122
+#: commands/opclasscmds.c:1099
#, c-format
msgid "index search operators must return boolean"
msgstr "operatory przeszukiwania indeksu muszą zwracać wartości logiczne"
-#: commands/opclasscmds.c:1164
+#: commands/opclasscmds.c:1141
#, c-format
msgid "btree comparison procedures must have two arguments"
msgstr "procedury porównania btree muszą być dwuargumentowe"
-#: commands/opclasscmds.c:1168
+#: commands/opclasscmds.c:1145
#, c-format
msgid "btree comparison procedures must return integer"
msgstr "procedury porównania btree muszą zwracać wartości całkowite"
-#: commands/opclasscmds.c:1185
+#: commands/opclasscmds.c:1162
#, c-format
msgid "btree sort support procedures must accept type \"internal\""
msgstr "procedury obsługi sortowania btree muszą przyjmować typ \"internal\""
-#: commands/opclasscmds.c:1189
+#: commands/opclasscmds.c:1166
#, c-format
msgid "btree sort support procedures must return void"
msgstr "procedury obsługi sortowania btree nie może nic zwracać"
-#: commands/opclasscmds.c:1201
+#: commands/opclasscmds.c:1178
#, c-format
msgid "hash procedures must have one argument"
msgstr "procedury haszujące muszą być jednoargumentowe"
-#: commands/opclasscmds.c:1205
+#: commands/opclasscmds.c:1182
#, c-format
msgid "hash procedures must return integer"
msgstr "procedury haszujące muszą zwracać wartości całkowite"
-#: commands/opclasscmds.c:1229
+#: commands/opclasscmds.c:1206
#, c-format
msgid "associated data types must be specified for index support procedure"
msgstr "powiązane typy danych muszą być określone dla procedury wsparcia indeksu"
-#: commands/opclasscmds.c:1254
+#: commands/opclasscmds.c:1231
#, c-format
msgid "procedure number %d for (%s,%s) appears more than once"
msgstr "numer procedury %d dla (%s,%s) pojawia się więcej niż raz"
-#: commands/opclasscmds.c:1261
+#: commands/opclasscmds.c:1238
#, c-format
msgid "operator number %d for (%s,%s) appears more than once"
msgstr "numer operatora %d dla (%s,%s) pojawia się więcej niż raz"
-#: commands/opclasscmds.c:1310
+#: commands/opclasscmds.c:1287
#, c-format
msgid "operator %d(%s,%s) already exists in operator family \"%s\""
msgstr "operator %d(%s,%s) już istnieje w rodzinie operatorów \"%s\""
-#: commands/opclasscmds.c:1426
+#: commands/opclasscmds.c:1401
#, c-format
msgid "function %d(%s,%s) already exists in operator family \"%s\""
msgstr "funkcja %d(%s,%s) już istnieje w rodzinie operatorów \"%s\""
-#: commands/opclasscmds.c:1516
+#: commands/opclasscmds.c:1489
#, c-format
msgid "operator %d(%s,%s) does not exist in operator family \"%s\""
msgstr "operator %d(%s,%s) nie istnieje w rodzinie operatorów \"%s\""
-#: commands/opclasscmds.c:1556
+#: commands/opclasscmds.c:1529
#, c-format
msgid "function %d(%s,%s) does not exist in operator family \"%s\""
msgstr "funkcja %d(%s,%s) nie istnieje w rodzinie operatorów \"%s\""
-#: commands/opclasscmds.c:1686
+#: commands/opclasscmds.c:1659
#, c-format
msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\""
msgstr "klasa operatora \"%s\" dla metody dostępu \"%s\" już istnieje w schemacie \"%s\""
-#: commands/opclasscmds.c:1709
+#: commands/opclasscmds.c:1682
#, c-format
msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\""
msgstr "rodzina operatora \"%s\" dla metody dostępu \"%s\" już istnieje w schemacie \"%s\""
@@ -7396,7 +7779,7 @@ msgstr "rodzina operatora \"%s\" dla metody dostępu \"%s\" już istnieje w sche
msgid "SETOF type not allowed for operator argument"
msgstr "typ SETOF niedozwolony jako argument operatora"
-#: commands/operatorcmds.c:152 commands/operatorcmds.c:457
+#: commands/operatorcmds.c:152 commands/operatorcmds.c:454
#, c-format
msgid "operator attribute \"%s\" not recognized"
msgstr "atrybut operatora \"%s\" nie rozpoznany"
@@ -7413,29 +7796,26 @@ msgstr "musi być wskazany co najmniej jeden lewyarg lub prawyarg"
#: commands/operatorcmds.c:278
#, c-format
-#| msgid "restriction estimator function %s must return type \"float8\""
msgid "restriction estimator function %s must return type %s"
msgstr "funkcja estymatora ograniczenia %s musi zwracać typ %s"
#: commands/operatorcmds.c:324
#, c-format
-#| msgid "join estimator function %s must return type \"float8\""
msgid "join estimator function %s must return type %s"
msgstr "funkcja estymatora złączenia %s musi zwracać typ %s"
-#: commands/operatorcmds.c:451
+#: commands/operatorcmds.c:448
#, c-format
-#| msgid "operator attribute \"%s\" not recognized"
msgid "operator attribute \"%s\" cannot be changed"
msgstr "atrybut operatora \"%s\" nie może być zmieniony"
-#: commands/policy.c:87 commands/policy.c:390 commands/policy.c:479
-#: commands/tablecmds.c:970 commands/tablecmds.c:1312
-#: commands/tablecmds.c:2184 commands/tablecmds.c:4328
-#: commands/tablecmds.c:6279 commands/tablecmds.c:11933
-#: commands/tablecmds.c:11968 commands/trigger.c:241 commands/trigger.c:1125
-#: commands/trigger.c:1233 rewrite/rewriteDefine.c:273
-#: rewrite/rewriteDefine.c:917
+#: commands/policy.c:87 commands/policy.c:397 commands/policy.c:486
+#: commands/tablecmds.c:1142 commands/tablecmds.c:1498
+#: commands/tablecmds.c:2481 commands/tablecmds.c:4682
+#: commands/tablecmds.c:7031 commands/tablecmds.c:12954
+#: commands/tablecmds.c:12989 commands/trigger.c:251 commands/trigger.c:1242
+#: commands/trigger.c:1351 rewrite/rewriteDefine.c:272
+#: rewrite/rewriteDefine.c:911
#, c-format
msgid "permission denied: \"%s\" is a system catalog"
msgstr "odmowa dostępu: \"%s\" jest katalogiem systemowym"
@@ -7450,89 +7830,89 @@ msgstr "ignorowanie ról określonych inaczej niż PUBLIC"
msgid "All roles are members of the PUBLIC role."
msgstr "Wszystkie role są członkami roli PUBLIC."
-#: commands/policy.c:503
+#: commands/policy.c:510
#, c-format
msgid "role \"%s\" could not be removed from policy \"%s\" on \"%s\""
msgstr "rola \"%s\" nie mogła zostać usunięta z polityki \"%s\" na \"%s\""
-#: commands/policy.c:712
+#: commands/policy.c:716
#, c-format
msgid "WITH CHECK cannot be applied to SELECT or DELETE"
msgstr "WITH CHECK nie może być stosowane do SELECT ani DELETE"
-#: commands/policy.c:721 commands/policy.c:1021
+#: commands/policy.c:725 commands/policy.c:1023
#, c-format
msgid "only WITH CHECK expression allowed for INSERT"
msgstr "wyrażenie WITH CHECK dostępne tylko w INSERT"
-#: commands/policy.c:794 commands/policy.c:1244
+#: commands/policy.c:798 commands/policy.c:1243
#, c-format
msgid "policy \"%s\" for table \"%s\" already exists"
msgstr "polityka \"%s\" dla tabeli \"%s\" już istnieje"
-#: commands/policy.c:993 commands/policy.c:1272 commands/policy.c:1347
+#: commands/policy.c:995 commands/policy.c:1271 commands/policy.c:1343
#, c-format
msgid "policy \"%s\" for table \"%s\" does not exist"
msgstr "polityka \"%s\" dla tabeli \"%s\" nie istnieje"
-#: commands/policy.c:1011
+#: commands/policy.c:1013
#, c-format
msgid "only USING expression allowed for SELECT, DELETE"
msgstr "tylko wyrażenie USING dozwolone w SELECT, DELETE"
-#: commands/portalcmds.c:61 commands/portalcmds.c:160
-#: commands/portalcmds.c:212
+#: commands/portalcmds.c:58 commands/portalcmds.c:182
+#: commands/portalcmds.c:234
#, c-format
msgid "invalid cursor name: must not be empty"
msgstr "niepoprawna nazwa kursora: nie może być pusta"
-#: commands/portalcmds.c:168 commands/portalcmds.c:222
-#: executor/execCurrent.c:67 utils/adt/xml.c:2391 utils/adt/xml.c:2558
+#: commands/portalcmds.c:190 commands/portalcmds.c:244
+#: executor/execCurrent.c:67 utils/adt/xml.c:2459 utils/adt/xml.c:2626
#, c-format
msgid "cursor \"%s\" does not exist"
msgstr "kursor \"%s\" nie istnieje"
-#: commands/prepare.c:71
+#: commands/prepare.c:75
#, c-format
msgid "invalid statement name: must not be empty"
msgstr "niepoprawna nazwa wyrażenia: nie może być pusta"
-#: commands/prepare.c:129 parser/parse_param.c:304 tcop/postgres.c:1345
+#: commands/prepare.c:141 parser/parse_param.c:304 tcop/postgres.c:1355
#, c-format
msgid "could not determine data type of parameter $%d"
msgstr "nie można określić typu danych parametru $%d"
-#: commands/prepare.c:147
+#: commands/prepare.c:159
#, c-format
msgid "utility statements cannot be prepared"
msgstr "nie można przygotować wyrażeń narzędzia"
-#: commands/prepare.c:257 commands/prepare.c:264
+#: commands/prepare.c:269 commands/prepare.c:274
#, c-format
msgid "prepared statement is not a SELECT"
msgstr "przygotowane wyrażenie to nie SELECT"
-#: commands/prepare.c:332
+#: commands/prepare.c:342
#, c-format
msgid "wrong number of parameters for prepared statement \"%s\""
msgstr "niepoprawna liczba parametrów dla przygotowanego wyrażenia \"%s\""
-#: commands/prepare.c:334
+#: commands/prepare.c:344
#, c-format
msgid "Expected %d parameters but got %d."
msgstr "Oczekiwano %d parametrów ale otrzymano %d."
-#: commands/prepare.c:370
+#: commands/prepare.c:380
#, c-format
msgid "parameter $%d of type %s cannot be coerced to the expected type %s"
msgstr "parametr $%d typu %s nie może być nagięty do oczekiwanego typu %s"
-#: commands/prepare.c:465
+#: commands/prepare.c:474
#, c-format
msgid "prepared statement \"%s\" already exists"
msgstr "przygotowane wyrażenie \"%s\" już istnieje"
-#: commands/prepare.c:504
+#: commands/prepare.c:513
#, c-format
msgid "prepared statement \"%s\" does not exist"
msgstr "przygotowane wyrażenie \"%s\" nie istnieje"
@@ -7562,22 +7942,57 @@ msgstr "Obsługiwane języki są wymienione w katalogu systemowym pg_pltemplate.
msgid "must be superuser to create custom procedural language"
msgstr "musisz być superużytkownikiem aby stworzyć własny język proceduralny"
-#: commands/proclang.c:281
+#: commands/proclang.c:281 commands/trigger.c:530 commands/typecmds.c:457
+#: commands/typecmds.c:474
#, c-format
-msgid "changing return type of function %s from \"opaque\" to \"language_handler\""
-msgstr "zmiana typu zwracanego przez funkcję %s z \"opaque\" na \"language_handler\""
+msgid "changing return type of function %s from %s to %s"
+msgstr "zmiana zwracanego typu funkcji %s z %s na %s"
-#: commands/schemacmds.c:99 commands/schemacmds.c:262
+#: commands/publicationcmds.c:179
+#, c-format
+#| msgid "must be superuser to create replication users"
+msgid "must be superuser to create FOR ALL TABLES publication"
+msgstr "musisz być superużytkownikiem aby utworzyć publikację FOR ALL TABLES"
+
+#: commands/publicationcmds.c:351
+#, c-format
+msgid "publication \"%s\" is defined as FOR ALL TABLES"
+msgstr "publikacja\"%s\" jest zdefiniowana jako FOR ALL TABLES"
+
+#: commands/publicationcmds.c:353
+#, c-format
+msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications."
+msgstr "Tabele nie mogą być dodawane ani usuwane z publikacji FOR ALL TABLES."
+
+#: commands/publicationcmds.c:651
+#, c-format
+#| msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgid "relation \"%s\" is not part of the publication"
+msgstr "relacja \"%s\" nie jest częścią tej publikacji"
+
+#: commands/publicationcmds.c:694
+#, c-format
+#| msgid "permission denied to change owner of database"
+msgid "permission denied to change owner of publication \"%s\""
+msgstr "odmowa dostępu do zmiany właściciela publikacji \"%s\""
+
+#: commands/publicationcmds.c:696
+#, c-format
+#| msgid "The owner of an event trigger must be a superuser."
+msgid "The owner of a FOR ALL TABLES publication must be a superuser."
+msgstr "Właściciel publikacji FOR ALL TABLES musi być superużytkownikiem."
+
+#: commands/schemacmds.c:106 commands/schemacmds.c:280
#, c-format
msgid "unacceptable schema name \"%s\""
msgstr "nieprawidłowa nazwa schematu \"%s\""
-#: commands/schemacmds.c:100 commands/schemacmds.c:263
+#: commands/schemacmds.c:107 commands/schemacmds.c:281
#, c-format
msgid "The prefix \"pg_\" is reserved for system schemas."
msgstr "Prefiks \"pg_\" jest zarezerwowany dla schematów systemowych."
-#: commands/schemacmds.c:114
+#: commands/schemacmds.c:121
#, c-format
msgid "schema \"%s\" already exists, skipping"
msgstr "schemat \"%s\" już istnieje, pominięto"
@@ -7597,1017 +8012,1555 @@ msgstr "wymagane wskazanie dostawcy gdy wczytano wielu dostawców etykiet bezpie
msgid "security label provider \"%s\" is not loaded"
msgstr "dostawca etykiety bezpieczeństwa \"%s\" nie jest wczytany"
-#: commands/sequence.c:127
+#: commands/sequence.c:135
#, c-format
msgid "unlogged sequences are not supported"
msgstr "nielogowane sekwencje nie są obsługiwane"
-#: commands/sequence.c:651
+#: commands/sequence.c:699
#, c-format
msgid "nextval: reached maximum value of sequence \"%s\" (%s)"
msgstr "nextval: osiągnięto maksymalną wartość sekwencji \"%s\" (%s)"
-#: commands/sequence.c:674
+#: commands/sequence.c:722
#, c-format
msgid "nextval: reached minimum value of sequence \"%s\" (%s)"
msgstr "nextval: osiągnięto minimalną wartość sekwencji \"%s\" (%s)"
-#: commands/sequence.c:792
+#: commands/sequence.c:840
#, c-format
msgid "currval of sequence \"%s\" is not yet defined in this session"
msgstr "currval sekwencji \"%s\" nie jest jeszcze zdefiniowana w tej sesji"
-#: commands/sequence.c:811 commands/sequence.c:817
+#: commands/sequence.c:859 commands/sequence.c:865
#, c-format
msgid "lastval is not yet defined in this session"
msgstr "lastval nie jest jeszcze zdefiniowana w tej sesji"
-#: commands/sequence.c:893
+#: commands/sequence.c:953
#, c-format
msgid "setval: value %s is out of bounds for sequence \"%s\" (%s..%s)"
msgstr "setval: wartość %s jest poza zakresem sekwencji \"%s\" (%s..%s)"
-#: commands/sequence.c:1267
+#: commands/sequence.c:1336
+#, c-format
+msgid "invalid sequence option SEQUENCE NAME"
+msgstr "niepoprawna opcja sekwencji SEQUENCE NAME"
+
+#: commands/sequence.c:1362
+#, c-format
+msgid "identity column type must be smallint, integer, or bigint"
+msgstr "typ kolumn identyfikatora to musi być smallint, integer, lub bigint"
+
+#: commands/sequence.c:1363
+#, c-format
+msgid "sequence type must be smallint, integer, or bigint"
+msgstr "typ sekwencji to musi być smallint, integer, lub bigint"
+
+#: commands/sequence.c:1395
#, c-format
msgid "INCREMENT must not be zero"
msgstr "INCREMENT nie może być zerowy"
-#: commands/sequence.c:1323
+#: commands/sequence.c:1444
+#, c-format
+#| msgid "\"%s\" is out of range for type real"
+msgid "MAXVALUE (%s) is out of range for sequence data type %s"
+msgstr "MAXVALUE (%s) jest poza zakresem dla danych sekwencji %s"
+
+#: commands/sequence.c:1481
+#, c-format
+#| msgid "\"%s\" is out of range for type real"
+msgid "MINVALUE (%s) is out of range for sequence data type %s"
+msgstr "MINVALUE (%s) jest poza zakresem dla danych sekwencji %s"
+
+#: commands/sequence.c:1495
#, c-format
msgid "MINVALUE (%s) must be less than MAXVALUE (%s)"
msgstr "MINVALUE (%s) musi być mniejsza niż MAXVALUE (%s)"
-#: commands/sequence.c:1348
+#: commands/sequence.c:1520
#, c-format
msgid "START value (%s) cannot be less than MINVALUE (%s)"
msgstr "wartość START (%s) nie może być mniejsza niż MINVALUE (%s)"
-#: commands/sequence.c:1360
+#: commands/sequence.c:1532
#, c-format
msgid "START value (%s) cannot be greater than MAXVALUE (%s)"
msgstr "wartość START (%s) nie może być większa niż MAXVALUE (%s)"
-#: commands/sequence.c:1390
+#: commands/sequence.c:1562
#, c-format
msgid "RESTART value (%s) cannot be less than MINVALUE (%s)"
msgstr "wartość RESTART (%s) nie może być mniejsza niż MINVALUE (%s)"
-#: commands/sequence.c:1402
+#: commands/sequence.c:1574
#, c-format
msgid "RESTART value (%s) cannot be greater than MAXVALUE (%s)"
msgstr "wartość RESTART (%s) nie może być większa niż MAXVALUE (%s)"
-#: commands/sequence.c:1417
+#: commands/sequence.c:1589
#, c-format
msgid "CACHE (%s) must be greater than zero"
msgstr "CACHE (%s) musi być większa niż zero"
-#: commands/sequence.c:1449
+#: commands/sequence.c:1624
#, c-format
msgid "invalid OWNED BY option"
msgstr "nieprawidłowa opcja OWNED BY"
-#: commands/sequence.c:1450
+#: commands/sequence.c:1625
#, c-format
msgid "Specify OWNED BY table.column or OWNED BY NONE."
msgstr "Wskaż OWNED BY tabela.kolumna lub OWNED BY NONE."
-#: commands/sequence.c:1473
+#: commands/sequence.c:1650
#, c-format
msgid "referenced relation \"%s\" is not a table or foreign table"
msgstr "wskazywana relacja \"%s\" nie jest tabelą ani tabelą zewnętrzną"
-#: commands/sequence.c:1480
+#: commands/sequence.c:1657
#, c-format
msgid "sequence must have same owner as table it is linked to"
msgstr "sekwencja musi mieć tego samego właściciela co powiązana z nią tabela"
-#: commands/sequence.c:1484
+#: commands/sequence.c:1661
#, c-format
msgid "sequence must be in same schema as table it is linked to"
msgstr "sekwencja musi być w tym samym schemacie co powiązana z nią tabela"
-#: commands/tablecmds.c:215
+#: commands/sequence.c:1683
+#, c-format
+#| msgid "cannot change owner of sequence \"%s\""
+msgid "cannot change ownership of identity sequence"
+msgstr "nie można zmienić właściciela sekwencji identyfikatora"
+
+#: commands/sequence.c:1684 commands/tablecmds.c:9841
+#: commands/tablecmds.c:12417
+#, c-format
+msgid "Sequence \"%s\" is linked to table \"%s\"."
+msgstr "Sekwencja \"%s\" jest połączona z tabelą \"%s\"."
+
+#: commands/statscmds.c:89
+#, c-format
+#| msgid "relation \"%s\" already exists, skipping"
+msgid "statistics \"%s\" already exist, skipping"
+msgstr "statystyka \"%s\" już istnieje, pominięto"
+
+#: commands/statscmds.c:96
+#, c-format
+#| msgid "tablespace \"%s\" already exists"
+msgid "statistics \"%s\" already exist"
+msgstr "statystyka \"%s\" już istnieje"
+
+#: commands/statscmds.c:112
+#, c-format
+#| msgid "\"%s\" is not a table or materialized view"
+msgid "relation \"%s\" is not a table or materialized view"
+msgstr "relacja \"%s\" nie jest tabelą ani widokiem zmaterializowanym"
+
+#: commands/statscmds.c:130
+#, c-format
+#| msgid "column \"%s\" referenced in foreign key constraint does not exist"
+msgid "column \"%s\" referenced in statistics does not exist"
+msgstr "kolumna \"%s\" wskazywana w statystyce nie istnieje"
+
+#: commands/statscmds.c:138
+#, c-format
+#| msgid "index creation on system columns is not supported"
+msgid "statistic creation on system columns is not supported"
+msgstr "tworzenie statystyk na kolumnach systemowych nie jest obsługiwane"
+
+#: commands/statscmds.c:145
+#, c-format
+#| msgid "Only commutative operators can be used in exclusion constraints."
+msgid "only scalar types can be used in extended statistics"
+msgstr "tylko typy skalarne mogą być używane w statystykach rozszerzonych"
+
+#: commands/statscmds.c:151
+#, c-format
+#| msgid "cannot have more than %d keys in a foreign key"
+msgid "cannot have more than %d keys in statistics"
+msgstr "nie można mieć więcej niż %d kluczy w statystyce"
+
+#: commands/statscmds.c:166
+#, c-format
+#| msgid "must request at least 2 points"
+msgid "statistics require at least 2 columns"
+msgstr "statystyka wymaga co najmniej 2 kolumn"
+
+#: commands/statscmds.c:183
+#, c-format
+#| msgid "cannot alter type of a column used in a policy definition"
+msgid "duplicate column name in statistics definition"
+msgstr "powielona nazwa kolumny w definicji statystyki"
+
+#: commands/statscmds.c:210
+#, c-format
+#| msgid "unrecognized VACUUM option \"%s\""
+msgid "unrecognized STATISTICS option \"%s\""
+msgstr "nieznana opcja STATISTICS \"%s\""
+
+#: commands/subscriptioncmds.c:182
+#, c-format
+msgid "noconnect and enabled are mutually exclusive options"
+msgstr "noconnect i enabled to wzajemnie wykluczające się opcje"
+
+#: commands/subscriptioncmds.c:187
+#, c-format
+msgid "noconnect and create slot are mutually exclusive options"
+msgstr "noconnect i create slot to wzajemnie wykluczające się opcje"
+
+#: commands/subscriptioncmds.c:192
+#, c-format
+msgid "noconnect and copy data are mutually exclusive options"
+msgstr "noconnect i copy data to wzajemnie wykluczające się opcje"
+
+#: commands/subscriptioncmds.c:239
+#, c-format
+#| msgid "parameter name \"%s\" used more than once"
+msgid "publication name \"%s\" used more than once"
+msgstr "nazwa publikacji \"%s\" użyta więcej niż raz"
+
+#: commands/subscriptioncmds.c:297
+#, c-format
+#| msgid "must be superuser to create superusers"
+msgid "must be superuser to create subscriptions"
+msgstr "musisz być superużytkownikiem aby tworzyć subskrypcje"
+
+#: commands/subscriptioncmds.c:368 commands/subscriptioncmds.c:457
+#: replication/logical/tablesync.c:726 replication/logical/worker.c:1548
+#, c-format
+#| msgid "could not connect to the primary server: %s"
+msgid "could not connect to the publisher: %s"
+msgstr "nie można połączyć się do publikatora: %s"
+
+#: commands/subscriptioncmds.c:382
+#, c-format
+#| msgid "%s: creating replication slot \"%s\"\n"
+msgid "created replication slot \"%s\" on publisher"
+msgstr "utworzono gniazda replikacji \"%s\" na publikatorze"
+
+#: commands/subscriptioncmds.c:409
+#, c-format
+#| msgid "Enable synchronized sequential scans."
+msgid "synchronized table states"
+msgstr "stany tabel zsynchronizowanych"
+
+#: commands/subscriptioncmds.c:424
+#, c-format
+msgid "tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables"
+msgstr ""
+"tabele nie są subskrybowane, aby je subskrybować należy uruchomić ALTER "
+"SUBSCRIPTION ... REFRESH PUBLICATION"
+
+#: commands/subscriptioncmds.c:508
+#, c-format
+#| msgid "reading publication membership for table \"%s.%s\"\n"
+msgid "added subscription for table %s.%s"
+msgstr "dodano subskrypcję do tabeli %s.%s"
+
+#: commands/subscriptioncmds.c:534
+#, c-format
+#| msgid "processing data for table \"%s.%s\"\n"
+msgid "removed subscription for table %s.%s"
+msgstr "usunięto subskrypcję z tabeli %s.%s"
+
+#: commands/subscriptioncmds.c:738
+#, c-format
+#| msgid "relation \"%s\" does not exist, skipping"
+msgid "subscription \"%s\" does not exist, skipping"
+msgstr "subskrypcja \"%s\" nie istnieje, pominięto"
+
+#: commands/subscriptioncmds.c:820
+#, c-format
+#| msgid "%s: could not create temporary replication slot \"%s\": %s"
+msgid "could not connect to publisher when attempting to drop the replication slot \"%s\""
+msgstr ""
+"nie można połączyć do publikatora podczas próby skasowania gniazda "
+"replikacji \"%s\""
+
+#: commands/subscriptioncmds.c:822 commands/subscriptioncmds.c:833
+#: replication/logical/tablesync.c:775 replication/logical/tablesync.c:795
+#, c-format
+#| msgid "The command was: %s\n"
+msgid "The error was: %s"
+msgstr "Wystąpił błąd: %s"
+
+#: commands/subscriptioncmds.c:831
+#, c-format
+#| msgid "%s: could not create temporary replication slot \"%s\": %s"
+msgid "could not drop the replication slot \"%s\" on publisher"
+msgstr "nie można skasować gniazda replikacji \"%s\" na publikatorze"
+
+#: commands/subscriptioncmds.c:836
+#, c-format
+#| msgid "%s: dropping replication slot \"%s\"\n"
+msgid "dropped replication slot \"%s\" on publisher"
+msgstr "skasowano gniazdo replikacji \"%s\" na publikatorze"
+
+#: commands/subscriptioncmds.c:877
+#, c-format
+#| msgid "permission denied to change owner of event trigger \"%s\""
+msgid "permission denied to change owner of subscription \"%s\""
+msgstr "odmowa dostępu do zmiany właściciela subskrypcji \"%s\""
+
+#: commands/subscriptioncmds.c:879
+#, c-format
+#| msgid "The owner of an event trigger must be a superuser."
+msgid "The owner of an subscription must be a superuser."
+msgstr "Właściciel subskrypcji musi być superużytkownikiem."
+
+#: commands/subscriptioncmds.c:992
+#, c-format
+#| msgid "could not receive timeline history file from the primary server: %s"
+msgid "could not receive list of replicated tables from the publisher: %s"
+msgstr "nie udało się odebrać listy replikowanych tabel z publikatora: %s"
+
+#: commands/tablecmds.c:221 commands/tablecmds.c:263
#, c-format
msgid "table \"%s\" does not exist"
msgstr "tabela \"%s\" nie istnieje"
-#: commands/tablecmds.c:216
+#: commands/tablecmds.c:222 commands/tablecmds.c:264
#, c-format
msgid "table \"%s\" does not exist, skipping"
msgstr "tabela \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:218
+#: commands/tablecmds.c:224 commands/tablecmds.c:266
msgid "Use DROP TABLE to remove a table."
msgstr "Użyj DROP TABLE aby skasować tabelę."
-#: commands/tablecmds.c:221
+#: commands/tablecmds.c:227
#, c-format
msgid "sequence \"%s\" does not exist"
msgstr "sekwencja \"%s\" nie istnieje"
-#: commands/tablecmds.c:222
+#: commands/tablecmds.c:228
#, c-format
msgid "sequence \"%s\" does not exist, skipping"
msgstr "sekwencja \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:224
+#: commands/tablecmds.c:230
msgid "Use DROP SEQUENCE to remove a sequence."
msgstr "Użyj DROP SEQUENCE aby usunąć sekwencję."
-#: commands/tablecmds.c:227
+#: commands/tablecmds.c:233
#, c-format
msgid "view \"%s\" does not exist"
msgstr "widok \"%s\" nie istnieje"
-#: commands/tablecmds.c:228
+#: commands/tablecmds.c:234
#, c-format
msgid "view \"%s\" does not exist, skipping"
msgstr "widok \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:230
+#: commands/tablecmds.c:236
msgid "Use DROP VIEW to remove a view."
msgstr "Użyj DROP VIEW aby usunąć widok."
-#: commands/tablecmds.c:233
+#: commands/tablecmds.c:239
#, c-format
msgid "materialized view \"%s\" does not exist"
msgstr "zmaterializowany widok \"%s\" nie istnieje"
-#: commands/tablecmds.c:234
+#: commands/tablecmds.c:240
#, c-format
msgid "materialized view \"%s\" does not exist, skipping"
msgstr "zmaterializowany widok \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:236
+#: commands/tablecmds.c:242
msgid "Use DROP MATERIALIZED VIEW to remove a materialized view."
msgstr "Użyj DROP MATERIALIZED VIEW aby usunąć widok zmaterializowany."
-#: commands/tablecmds.c:239 parser/parse_utilcmd.c:1643
+#: commands/tablecmds.c:245 parser/parse_utilcmd.c:1816
#, c-format
msgid "index \"%s\" does not exist"
msgstr "indeks \"%s\" nie istnieje"
-#: commands/tablecmds.c:240
+#: commands/tablecmds.c:246
#, c-format
msgid "index \"%s\" does not exist, skipping"
msgstr "indeks \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:242
+#: commands/tablecmds.c:248
msgid "Use DROP INDEX to remove an index."
msgstr "Użyj DROP INDEX aby usunąć indeks."
-#: commands/tablecmds.c:247
+#: commands/tablecmds.c:253
#, c-format
msgid "\"%s\" is not a type"
msgstr "\"%s\" nie jest typem"
-#: commands/tablecmds.c:248
+#: commands/tablecmds.c:254
msgid "Use DROP TYPE to remove a type."
msgstr "Użyj DROP TYPE aby usunąć typ."
-#: commands/tablecmds.c:251 commands/tablecmds.c:8486
-#: commands/tablecmds.c:11194
+#: commands/tablecmds.c:257 commands/tablecmds.c:9357
+#: commands/tablecmds.c:12197
#, c-format
msgid "foreign table \"%s\" does not exist"
msgstr "tabela obca \"%s\" nie istnieje"
-#: commands/tablecmds.c:252
+#: commands/tablecmds.c:258
#, c-format
msgid "foreign table \"%s\" does not exist, skipping"
msgstr "tabela obca \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:254
+#: commands/tablecmds.c:260
msgid "Use DROP FOREIGN TABLE to remove a foreign table."
msgstr "Użyj DROP FOREIGN TABLE aby usunąć tabelę obcą."
-#: commands/tablecmds.c:493
+#: commands/tablecmds.c:524
#, c-format
msgid "ON COMMIT can only be used on temporary tables"
msgstr "ON COMMIT może być używane jedynie na tabelach tymczasowych"
-#: commands/tablecmds.c:513
+#: commands/tablecmds.c:552
#, c-format
msgid "cannot create temporary table within security-restricted operation"
msgstr "nie można utworzyć tabeli tymczasowej operacją o ograniczonym bezpieczeństwie"
-#: commands/tablecmds.c:821
+#: commands/tablecmds.c:651
+#, c-format
+#| msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgid "cannot create table with OIDs as partition of table without OIDs"
+msgstr "nie można tworzyć tabeli z OIDami jako partycji tabeli bez OIDów"
+
+#: commands/tablecmds.c:772 parser/parse_utilcmd.c:3256
+#, c-format
+#| msgid "\"%s\" is not an index"
+msgid "\"%s\" is not partitioned"
+msgstr "\"%s\" nie jest partycjonowana"
+
+#: commands/tablecmds.c:980
#, c-format
msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects"
msgstr "DROP INDEX CONCURRENTLY nie obsługuje usuwania wielu obiektów"
-#: commands/tablecmds.c:825
+#: commands/tablecmds.c:984
#, c-format
msgid "DROP INDEX CONCURRENTLY does not support CASCADE"
msgstr "DROP INDEX CONCURRENTLY nie obsługuje CASCADE"
-#: commands/tablecmds.c:1084
+#: commands/tablecmds.c:1232
+#, c-format
+#| msgid "column must be added to child tables too"
+msgid "must truncate child tables too"
+msgstr "wymagane jest również obcięcie tabel podrzędnych"
+
+#: commands/tablecmds.c:1260
#, c-format
msgid "truncate cascades to table \"%s\""
msgstr "obcięcie kaskadowe do tabeli \"%s\""
-#: commands/tablecmds.c:1322
+#: commands/tablecmds.c:1508
#, c-format
msgid "cannot truncate temporary tables of other sessions"
msgstr "nie można obcinać tabel tymczasowych z innych sesji"
-#: commands/tablecmds.c:1528 parser/parse_utilcmd.c:1857
+#: commands/tablecmds.c:1739 commands/tablecmds.c:10941
+#, c-format
+#| msgid "cannot insert into foreign table \"%s\""
+msgid "cannot inherit from partitioned table \"%s\""
+msgstr "nie można dziedziczyć z partycjonowanej tabeli \"%s\""
+
+#: commands/tablecmds.c:1744
+#, c-format
+#| msgid "cannot inherit from temporary relation \"%s\""
+msgid "cannot inherit from partition \"%s\""
+msgstr "nie można dziedziczyć z partycji \"%s\""
+
+#: commands/tablecmds.c:1752 parser/parse_utilcmd.c:2027
#, c-format
msgid "inherited relation \"%s\" is not a table or foreign table"
msgstr "dziedziczona relacja \"%s\" nie jest tabelą ani tabelą zewnętrzną"
-#: commands/tablecmds.c:1535 commands/tablecmds.c:10053
+#: commands/tablecmds.c:1760 commands/tablecmds.c:10920
#, c-format
msgid "cannot inherit from temporary relation \"%s\""
msgstr "nie można dziedziczyć z tymczasowej relacji \"%s\""
-#: commands/tablecmds.c:1543 commands/tablecmds.c:10061
+#: commands/tablecmds.c:1770 commands/tablecmds.c:10928
#, c-format
msgid "cannot inherit from temporary relation of another session"
msgstr "nie można dziedziczyć z tymczasowej relacji z innej sesji"
-#: commands/tablecmds.c:1559 commands/tablecmds.c:10095
+#: commands/tablecmds.c:1787 commands/tablecmds.c:11039
#, c-format
msgid "relation \"%s\" would be inherited from more than once"
msgstr "relacja \"%s\" byłaby dziedziczona więcej niż raz"
-#: commands/tablecmds.c:1607
+#: commands/tablecmds.c:1835
#, c-format
msgid "merging multiple inherited definitions of column \"%s\""
msgstr "łączenie wielu dziedziczonych definicji kolumny \"%s\""
-#: commands/tablecmds.c:1615
+#: commands/tablecmds.c:1843
#, c-format
msgid "inherited column \"%s\" has a type conflict"
msgstr "kolumna dziedziczona \"%s\" jest w konflikcie typów"
-#: commands/tablecmds.c:1617 commands/tablecmds.c:1640
-#: commands/tablecmds.c:1838 commands/tablecmds.c:1862
-#: parser/parse_coerce.c:1630 parser/parse_coerce.c:1650
-#: parser/parse_coerce.c:1670 parser/parse_coerce.c:1715
-#: parser/parse_coerce.c:1752 parser/parse_param.c:218
+#: commands/tablecmds.c:1845 commands/tablecmds.c:1868
+#: commands/tablecmds.c:2073 commands/tablecmds.c:2103
+#: parser/parse_coerce.c:1650 parser/parse_coerce.c:1670
+#: parser/parse_coerce.c:1690 parser/parse_coerce.c:1736
+#: parser/parse_coerce.c:1775 parser/parse_param.c:218
#, c-format
msgid "%s versus %s"
msgstr "%s kontra %s"
-#: commands/tablecmds.c:1626
+#: commands/tablecmds.c:1854
#, c-format
msgid "inherited column \"%s\" has a collation conflict"
msgstr "kolumna dziedziczona \"%s\" jest konflikcie porównań"
-#: commands/tablecmds.c:1628 commands/tablecmds.c:1850
-#: commands/tablecmds.c:4766
+#: commands/tablecmds.c:1856 commands/tablecmds.c:2085
+#: commands/tablecmds.c:5127
#, c-format
msgid "\"%s\" versus \"%s\""
msgstr "\"%s\" kontra \"%s\""
-#: commands/tablecmds.c:1638
+#: commands/tablecmds.c:1866
#, c-format
msgid "inherited column \"%s\" has a storage parameter conflict"
msgstr "kolumna dziedziczona \"%s\" jest konflikcie parametrów składowania"
-#: commands/tablecmds.c:1751 parser/parse_utilcmd.c:938
-#: parser/parse_utilcmd.c:1287 parser/parse_utilcmd.c:1363
+#: commands/tablecmds.c:1979 commands/tablecmds.c:8865
+#: parser/parse_utilcmd.c:1111 parser/parse_utilcmd.c:1461
+#: parser/parse_utilcmd.c:1537
#, c-format
msgid "cannot convert whole-row table reference"
msgstr "nie można zmienić wskazania na tabelę całowierszową"
-#: commands/tablecmds.c:1752 parser/parse_utilcmd.c:939
+#: commands/tablecmds.c:1980 parser/parse_utilcmd.c:1112
#, c-format
msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"."
msgstr "Ograniczenie \"%s\" zawiera całowierszowe wskazanie na tabelę \"%s\"."
-#: commands/tablecmds.c:1824
+#: commands/tablecmds.c:2059
#, c-format
msgid "merging column \"%s\" with inherited definition"
msgstr "połączenie kolumny \"%s\" z dziedziczoną definicją"
-#: commands/tablecmds.c:1828
+#: commands/tablecmds.c:2063
#, c-format
msgid "moving and merging column \"%s\" with inherited definition"
msgstr "przenoszenie i połączenie kolumny \"%s\" z dziedziczoną definicją"
-#: commands/tablecmds.c:1829
+#: commands/tablecmds.c:2064
#, c-format
msgid "User-specified column moved to the position of the inherited column."
msgstr "Kolumna zdefiniowana przez użytkownika przeniesiona na pozycję dziedziczonej kolumny."
-#: commands/tablecmds.c:1836
+#: commands/tablecmds.c:2071
#, c-format
msgid "column \"%s\" has a type conflict"
msgstr "kolumna \"%s\" jest w konflikcie typów"
-#: commands/tablecmds.c:1848
+#: commands/tablecmds.c:2083
#, c-format
msgid "column \"%s\" has a collation conflict"
msgstr "kolumna \"%s\" jest w konflikcie porównań"
-#: commands/tablecmds.c:1860
+#: commands/tablecmds.c:2101
#, c-format
msgid "column \"%s\" has a storage parameter conflict"
msgstr "kolumna \"%s\" jest w konflikcie parametrów składowania"
-#: commands/tablecmds.c:1912
+#: commands/tablecmds.c:2203
#, c-format
msgid "column \"%s\" inherits conflicting default values"
msgstr "kolumna \"%s\" dziedziczy sprzeczne wartości domyślne"
-#: commands/tablecmds.c:1914
+#: commands/tablecmds.c:2205
#, c-format
msgid "To resolve the conflict, specify a default explicitly."
msgstr "Aby rozwiązać konflikt, wskaż wyraźnie ustawienie domyślne."
-#: commands/tablecmds.c:1961
+#: commands/tablecmds.c:2252
#, c-format
msgid "check constraint name \"%s\" appears multiple times but with different expressions"
msgstr "nazwa ograniczenia kontrolnego \"%s\" pojawia się wielokrotnie w różnych wyrażeniach"
-#: commands/tablecmds.c:2155
+#: commands/tablecmds.c:2451
#, c-format
msgid "cannot rename column of typed table"
msgstr "nie można zmienić nazwy kolumny tabeli typizowanej"
-#: commands/tablecmds.c:2172
+#: commands/tablecmds.c:2469
#, c-format
msgid "\"%s\" is not a table, view, materialized view, composite type, index, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem, widokiem materializowanym, indeksem, typem złożonym ani tabelą zewnętrzną"
-#: commands/tablecmds.c:2266
+#: commands/tablecmds.c:2563
#, c-format
msgid "inherited column \"%s\" must be renamed in child tables too"
msgstr "kolumna dziedziczona \"%s\" musi być przemianowana również w tabelach potomnych"
-#: commands/tablecmds.c:2298
+#: commands/tablecmds.c:2595
#, c-format
msgid "cannot rename system column \"%s\""
msgstr "nie można zmienić nazwy kolumny systemowej \"%s\""
-#: commands/tablecmds.c:2313
+#: commands/tablecmds.c:2610
#, c-format
msgid "cannot rename inherited column \"%s\""
msgstr "nie można zmienić nazwy kolumny dziedziczonej \"%s\""
-#: commands/tablecmds.c:2468
+#: commands/tablecmds.c:2762
#, c-format
msgid "inherited constraint \"%s\" must be renamed in child tables too"
msgstr "ograniczenie dziedziczona \"%s\" musi być przemianowane również w tabelach potomnych"
-#: commands/tablecmds.c:2475
+#: commands/tablecmds.c:2769
#, c-format
msgid "cannot rename inherited constraint \"%s\""
msgstr "nie można zmienić nazwy ograniczenia dziedziczonego \"%s\""
#. translator: first %s is a SQL command, eg ALTER TABLE
-#: commands/tablecmds.c:2701
+#: commands/tablecmds.c:2993
#, c-format
msgid "cannot %s \"%s\" because it is being used by active queries in this session"
msgstr "nie można %s \"%s\" ponieważ jest używane przez aktywne zapytania w tej sesji"
#. translator: first %s is a SQL command, eg ALTER TABLE
-#: commands/tablecmds.c:2710
+#: commands/tablecmds.c:3002
#, c-format
msgid "cannot %s \"%s\" because it has pending trigger events"
msgstr "nie można %s \"%s\" ponieważ posiada oczekujące zdarzenia wyzwalaczy"
-#: commands/tablecmds.c:3784
+#: commands/tablecmds.c:4125
#, c-format
msgid "cannot rewrite system relation \"%s\""
msgstr "nie można nadpisać relacji systemowej \"%s\""
-#: commands/tablecmds.c:3790
+#: commands/tablecmds.c:4131
#, c-format
msgid "cannot rewrite table \"%s\" used as a catalog table"
msgstr "nie udało się przekształcić tabeli \"%s\" używanej jako tabela katalogu"
-#: commands/tablecmds.c:3800
+#: commands/tablecmds.c:4141
#, c-format
msgid "cannot rewrite temporary tables of other sessions"
msgstr "nie można nadpisać tabel tymczasowych z innych sesji"
-#: commands/tablecmds.c:4068
+#: commands/tablecmds.c:4417
#, c-format
msgid "rewriting table \"%s\""
msgstr "nadpisanie tabeli \"%s\""
-#: commands/tablecmds.c:4072
+#: commands/tablecmds.c:4421
#, c-format
msgid "verifying table \"%s\""
msgstr "sprawdzanie tabeli \"%s\""
-#: commands/tablecmds.c:4186
+#: commands/tablecmds.c:4534
#, c-format
msgid "column \"%s\" contains null values"
msgstr "kolumna \"%s\" zawiera puste wartości"
-#: commands/tablecmds.c:4201 commands/tablecmds.c:7366
+#: commands/tablecmds.c:4549 commands/tablecmds.c:8136
#, c-format
msgid "check constraint \"%s\" is violated by some row"
msgstr "ograniczenie sprawdzające \"%s\" jest naruszone przez kilka rekordów"
-#: commands/tablecmds.c:4349 commands/trigger.c:235
-#: rewrite/rewriteDefine.c:267 rewrite/rewriteDefine.c:912
+#: commands/tablecmds.c:4565
+#, c-format
+#| msgid "check constraint \"%s\" is violated by some row"
+msgid "partition constraint is violated by some row"
+msgstr "ograniczenie partycji jest naruszone przez jakieś rekordy"
+
+#: commands/tablecmds.c:4703 commands/trigger.c:245
+#: rewrite/rewriteDefine.c:266 rewrite/rewriteDefine.c:906
#, c-format
msgid "\"%s\" is not a table or view"
msgstr "\"%s\" nie jest tabelą ani widokiem"
-#: commands/tablecmds.c:4352 commands/trigger.c:1119 commands/trigger.c:1224
+#: commands/tablecmds.c:4706 commands/trigger.c:1236 commands/trigger.c:1342
#, c-format
msgid "\"%s\" is not a table, view, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem ani tabelą obcą"
-#: commands/tablecmds.c:4355
+#: commands/tablecmds.c:4709
#, c-format
msgid "\"%s\" is not a table, view, materialized view, or index"
msgstr "\"%s\" nie jest tabelą, widokiem, widokiem zmaterializowanym ani tabelą obcą"
-#: commands/tablecmds.c:4361
+#: commands/tablecmds.c:4715
#, c-format
msgid "\"%s\" is not a table, materialized view, or index"
msgstr "\"%s\" nie jest tabelą, widokiem zmaterializowanym ani indeksem"
-#: commands/tablecmds.c:4364
+#: commands/tablecmds.c:4718
#, c-format
msgid "\"%s\" is not a table, materialized view, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem zmaterializowanym ani tabelą zewnętrzną"
-#: commands/tablecmds.c:4367
+#: commands/tablecmds.c:4721
#, c-format
msgid "\"%s\" is not a table or foreign table"
msgstr "\"%s\" nie jest tabelą ani tabelą obcą"
-#: commands/tablecmds.c:4370
+#: commands/tablecmds.c:4724
#, c-format
msgid "\"%s\" is not a table, composite type, or foreign table"
msgstr "\"%s\" nie jest tabelą, typem złożonym ani tabelą obcą"
-#: commands/tablecmds.c:4373 commands/tablecmds.c:5425
+#: commands/tablecmds.c:4727 commands/tablecmds.c:6104
#, c-format
msgid "\"%s\" is not a table, materialized view, index, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem zmaterializowanym, indeksem ani tabelą zewnętrzną"
-#: commands/tablecmds.c:4383
+#: commands/tablecmds.c:4737
#, c-format
msgid "\"%s\" is of the wrong type"
msgstr "\"%s\" jest niepoprawnego typu"
-#: commands/tablecmds.c:4535 commands/tablecmds.c:4542
+#: commands/tablecmds.c:4891 commands/tablecmds.c:4898
#, c-format
msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it"
msgstr "nie można zmieniać typu \"%s\" ponieważ używa go kolumna \"%s.%s\""
-#: commands/tablecmds.c:4549
+#: commands/tablecmds.c:4905
#, c-format
msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type"
msgstr "nie można zmieniać tabeli obcej \"%s\" ponieważ kolumna \"%s.%s\" używa jej typu wiersza"
-#: commands/tablecmds.c:4556
+#: commands/tablecmds.c:4912
#, c-format
msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type"
msgstr "nie można zmieniać tabeli \"%s\" ponieważ kolumna \"%s.%s\" używa jej typu wiersza"
-#: commands/tablecmds.c:4618
+#: commands/tablecmds.c:4974
#, c-format
msgid "cannot alter type \"%s\" because it is the type of a typed table"
msgstr "nie można zmienić typu \"%s\" ponieważ definiuje on typ tabeli typizowanej"
-#: commands/tablecmds.c:4620
+#: commands/tablecmds.c:4976
#, c-format
msgid "Use ALTER ... CASCADE to alter the typed tables too."
msgstr "Użyj ALTER ... CASCADE aby zmienić również tabele typizowane."
-#: commands/tablecmds.c:4664
+#: commands/tablecmds.c:5020
#, c-format
msgid "type %s is not a composite type"
msgstr "typ %s nie jest typem złożonym"
-#: commands/tablecmds.c:4690
+#: commands/tablecmds.c:5046
#, c-format
msgid "cannot add column to typed table"
-msgstr "nie dodać kolumny tabeli typizowanej"
+msgstr "nie można dodać kolumny tabeli typizowanej"
+
+#: commands/tablecmds.c:5090
+#, c-format
+#| msgid "cannot add column to typed table"
+msgid "cannot add column to a partition"
+msgstr "nie można dodać kolumny do partycji"
-#: commands/tablecmds.c:4758 commands/tablecmds.c:10254
+#: commands/tablecmds.c:5119 commands/tablecmds.c:11165
#, c-format
msgid "child table \"%s\" has different type for column \"%s\""
msgstr "tabela potomna \"%s\" posiada inny typ kolumny \"%s\""
-#: commands/tablecmds.c:4764 commands/tablecmds.c:10261
+#: commands/tablecmds.c:5125 commands/tablecmds.c:11172
#, c-format
msgid "child table \"%s\" has different collation for column \"%s\""
msgstr "tabela potomna \"%s\" posiada inne porównanie dla kolumny \"%s\""
-#: commands/tablecmds.c:4774
+#: commands/tablecmds.c:5135
#, c-format
msgid "child table \"%s\" has a conflicting \"%s\" column"
msgstr "tabela potomna \"%s\" posiada sprzeczną kolumnę \"%s\""
-#: commands/tablecmds.c:4786
+#: commands/tablecmds.c:5146
#, c-format
msgid "merging definition of column \"%s\" for child \"%s\""
msgstr "łączenie definicji kolumny \"%s\" dla podrzędnej \"%s\""
-#: commands/tablecmds.c:5013
+#: commands/tablecmds.c:5170
+#, c-format
+msgid "cannot recursively add identity column to table that has child tables"
+msgstr ""
+"nie można rekursywnie dodać kolumny identyfikatora do tabeli z tabelami "
+"podrzędnymi"
+
+#: commands/tablecmds.c:5382
#, c-format
msgid "column must be added to child tables too"
msgstr "kolumna musi być dodana również do tabel podrzędnych"
-#: commands/tablecmds.c:5088
+#: commands/tablecmds.c:5457
#, c-format
-#| msgid "column \"%s\" of relation \"%s\" already exists"
msgid "column \"%s\" of relation \"%s\" already exists, skipping"
msgstr "kolumna \"%s\" relacji \"%s\" już istnieje, pominięto"
-#: commands/tablecmds.c:5095
+#: commands/tablecmds.c:5464
#, c-format
msgid "column \"%s\" of relation \"%s\" already exists"
msgstr "kolumna \"%s\" relacji \"%s\" już istnieje"
-#: commands/tablecmds.c:5206 commands/tablecmds.c:5312
-#: commands/tablecmds.c:5370 commands/tablecmds.c:5484
-#: commands/tablecmds.c:5541 commands/tablecmds.c:5635
-#: commands/tablecmds.c:7884 commands/tablecmds.c:8509
+#: commands/tablecmds.c:5558 commands/tablecmds.c:8538
+#, c-format
+#| msgid "constraint must be added to child tables too"
+msgid "constraint must be dropped from child tables too"
+msgstr "ograniczenie musi być skasowane również na tabelach podrzędnych"
+
+#: commands/tablecmds.c:5589 commands/tablecmds.c:5756
+#: commands/tablecmds.c:5811 commands/tablecmds.c:5886
+#: commands/tablecmds.c:5980 commands/tablecmds.c:6039
+#: commands/tablecmds.c:6163 commands/tablecmds.c:6217
+#: commands/tablecmds.c:6309 commands/tablecmds.c:8687
+#: commands/tablecmds.c:9380
#, c-format
msgid "cannot alter system column \"%s\""
msgstr "nie można zmieniać kolumny systemowej \"%s\""
-#: commands/tablecmds.c:5242
+#: commands/tablecmds.c:5595 commands/tablecmds.c:5817
+#, c-format
+#| msgid "column \"%s\" of relation \"%s\" does not exist"
+msgid "column \"%s\" of relation \"%s\" is an identity column"
+msgstr "kolumna \"%s\" relacji \"%s\" jest kolumną identyfikującą"
+
+#: commands/tablecmds.c:5631
#, c-format
msgid "column \"%s\" is in a primary key"
msgstr "kolumna \"%s\" jest w kluczu głównym"
-#: commands/tablecmds.c:5457
+#: commands/tablecmds.c:5653
+#, c-format
+#| msgid "column \"%s\" in child table must be marked NOT NULL"
+msgid "column \"%s\" is marked NOT NULL in parent table"
+msgstr "kolumna \"%s\" jest oznaczona NOT NULL w tabeli nadrzędnej"
+
+#: commands/tablecmds.c:5678
+#, fuzzy, c-format
+#| msgid "column \"%s\" is in a primary key"
+msgid "column \"%s\" is in range partition key"
+msgstr "kolumna \"%s\" jest w przedziale klucza partycji"
+
+#: commands/tablecmds.c:5725 commands/tablecmds.c:6948
+#, c-format
+msgid "constraint must be added to child tables too"
+msgstr "ograniczenie musi być dodane również do tabel potomnych"
+
+#: commands/tablecmds.c:5819
+#, c-format
+msgid "Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY instead."
+msgstr "Użyj w zamian ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY."
+
+#: commands/tablecmds.c:5897
+#, c-format
+msgid "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added"
+msgstr ""
+"kolumna \"%s\" relacji \"%s\" musi być zadeklarowana jako NOT NULL zanim będzie "
+"można dodać identyfikację"
+
+#: commands/tablecmds.c:5903
+#, c-format
+#| msgid "column \"%s\" of relation \"%s\" already exists"
+msgid "column \"%s\" of relation \"%s\" is already an identity column"
+msgstr "kolumna \"%s\" relacji \"%s\" jest już kolumną identyfikującą"
+
+#: commands/tablecmds.c:5909
+#, c-format
+#| msgid "column \"%s\" of relation \"%s\" already exists"
+msgid "column \"%s\" of relation \"%s\" already has a default value"
+msgstr "kolumna \"%s\" relacji \"%s\" już ma wartość domyślną"
+
+#: commands/tablecmds.c:5986 commands/tablecmds.c:6047
+#, c-format
+#| msgid "column \"%s\" of relation \"%s\" does not exist"
+msgid "column \"%s\" of relation \"%s\" is not an identity column"
+msgstr "kolumna \"%s\" relacji \"%s\" nie jest kolumną identyfikującą"
+
+#: commands/tablecmds.c:6052
+#, c-format
+#| msgid "column \"%s\" of relation \"%s\" does not exist, skipping"
+msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping"
+msgstr "kolumna \"%s\" relacji \"%s\" nie jest kolumną identyfikującą, pominięto"
+
+#: commands/tablecmds.c:6136
#, c-format
msgid "statistics target %d is too low"
msgstr "Próbka statystyczna %d jest zbyt mała"
-#: commands/tablecmds.c:5465
+#: commands/tablecmds.c:6144
#, c-format
msgid "lowering statistics target to %d"
msgstr "obniżanie próbki statystycznej do %d"
-#: commands/tablecmds.c:5615
+#: commands/tablecmds.c:6289
#, c-format
msgid "invalid storage type \"%s\""
msgstr "niepoprawny typ przechowywania \"%s\""
-#: commands/tablecmds.c:5647
+#: commands/tablecmds.c:6321
#, c-format
msgid "column data type %s can only have storage PLAIN"
msgstr "typ danych kolumny %s może mieć przechowywanie tylko PLAIN"
-#: commands/tablecmds.c:5685
+#: commands/tablecmds.c:6356
#, c-format
msgid "cannot drop column from typed table"
msgstr "nie można skasować kolumn tabeli typizowanej"
-#: commands/tablecmds.c:5729
+#: commands/tablecmds.c:6463
#, c-format
msgid "column \"%s\" of relation \"%s\" does not exist, skipping"
msgstr "kolumna \"%s\" relacji \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:5742
+#: commands/tablecmds.c:6476
#, c-format
msgid "cannot drop system column \"%s\""
msgstr "nie można usunąć kolumny systemowej \"%s\""
-#: commands/tablecmds.c:5749
+#: commands/tablecmds.c:6483
#, c-format
msgid "cannot drop inherited column \"%s\""
msgstr "nie można usunąć kolumny dziedziczonej \"%s\""
-#: commands/tablecmds.c:5989
+#: commands/tablecmds.c:6492
+#, fuzzy, c-format
+#| msgid "cannot drop column from typed table"
+msgid "cannot drop column named in partition key"
+msgstr "nie można skasować kolumn tabeli typizowanej"
+
+#: commands/tablecmds.c:6496
+#, fuzzy, c-format
+#| msgid "cannot use column references in default expression"
+msgid "cannot drop column referenced in partition key expression"
+msgstr "nie można użyć referencji kolumn w domyślnym wyrażeniu"
+
+#: commands/tablecmds.c:6520
+#, fuzzy, c-format
+#| msgid "column must be added to child tables too"
+msgid "column must be dropped from child tables too"
+msgstr "kolumna musi być dodana również do tabel podrzędnych"
+
+#: commands/tablecmds.c:6736
#, c-format
msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\""
msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX przemianuje indeks \"%s\" na \"%s\""
-#: commands/tablecmds.c:6202
-#, c-format
-msgid "constraint must be added to child tables too"
-msgstr "ograniczenie musi być dodane również do tabel potomnych"
+#: commands/tablecmds.c:7019
+#, fuzzy, c-format
+#| msgid "cannot insert into foreign table \"%s\""
+msgid "cannot reference partitioned table \"%s\""
+msgstr "nie można wstawiać do tabeli zewnętrznej \"%s\""
-#: commands/tablecmds.c:6273
+#: commands/tablecmds.c:7025
#, c-format
msgid "referenced relation \"%s\" is not a table"
msgstr "wskazywana relacja \"%s\" nie jest tabelą"
-#: commands/tablecmds.c:6296
+#: commands/tablecmds.c:7048
#, c-format
msgid "constraints on permanent tables may reference only permanent tables"
msgstr "ograniczenia na tabelach trwałych mogą wskazywać tylko tabele trwałe"
-#: commands/tablecmds.c:6303
+#: commands/tablecmds.c:7055
#, c-format
msgid "constraints on unlogged tables may reference only permanent or unlogged tables"
msgstr "ograniczenia na nielogowanych mogą wskazywać tylko tabele nielogowane"
-#: commands/tablecmds.c:6309
+#: commands/tablecmds.c:7061
#, c-format
msgid "constraints on temporary tables may reference only temporary tables"
msgstr "ograniczenia na tabelach tymczasowych mogą wskazywać tylko tabele tymczasowe"
-#: commands/tablecmds.c:6313
+#: commands/tablecmds.c:7065
#, c-format
msgid "constraints on temporary tables must involve temporary tables of this session"
msgstr "ograniczenia na tabelach tymczasowych muszą dotyczyć tylko tabel tymczasowych tej sesji"
-#: commands/tablecmds.c:6374
+#: commands/tablecmds.c:7125
#, c-format
msgid "number of referencing and referenced columns for foreign key disagree"
msgstr "nie zgadza się liczba kolumn wskazujących i wskazywanych w kluczu obcym"
-#: commands/tablecmds.c:6481
+#: commands/tablecmds.c:7232
#, c-format
msgid "foreign key constraint \"%s\" cannot be implemented"
msgstr "klucz obcy \"%s\" nie może być zaimplementowany"
-#: commands/tablecmds.c:6484
+#: commands/tablecmds.c:7235
#, c-format
msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s."
msgstr "Kolumny klucza \"%s\" i \"%s\" są różnych typów: %s i %s."
-#: commands/tablecmds.c:6691 commands/tablecmds.c:6841
-#: commands/tablecmds.c:7723 commands/tablecmds.c:7779
+#: commands/tablecmds.c:7441 commands/tablecmds.c:7607
+#: commands/tablecmds.c:8517 commands/tablecmds.c:8583
#, c-format
msgid "constraint \"%s\" of relation \"%s\" does not exist"
msgstr "ograniczenie \"%s\" relacji \"%s\" nie istnieje"
-#: commands/tablecmds.c:6697
+#: commands/tablecmds.c:7447
#, c-format
msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint"
msgstr "ograniczenie \"%s\" relacji \"%s\" nie jest kluczem obcym"
-#: commands/tablecmds.c:6848
+#: commands/tablecmds.c:7614
#, c-format
msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint"
msgstr "ograniczenie \"%s\" relacji \"%s\" nie jest kluczem obcym ani ograniczeniem sprawdzającym"
-#: commands/tablecmds.c:6916
+#: commands/tablecmds.c:7683
#, c-format
msgid "constraint must be validated on child tables too"
msgstr "ograniczenie musi być sprawdzane również na tabelach potomnych"
-#: commands/tablecmds.c:6985
+#: commands/tablecmds.c:7751
#, c-format
msgid "column \"%s\" referenced in foreign key constraint does not exist"
msgstr "kolumna \"%s\" wskazywana w ograniczeniu klucza obcego nie istnieje"
-#: commands/tablecmds.c:6990
+#: commands/tablecmds.c:7756
#, c-format
msgid "cannot have more than %d keys in a foreign key"
msgstr "nie można użyć więcej niż %d kluczy w kluczu obcym"
-#: commands/tablecmds.c:7055
+#: commands/tablecmds.c:7821
#, c-format
msgid "cannot use a deferrable primary key for referenced table \"%s\""
msgstr "nie można użyć odraczalnego klucza głównego dla tabeli referencyjnej \"%s\""
-#: commands/tablecmds.c:7072
+#: commands/tablecmds.c:7838
#, c-format
msgid "there is no primary key for referenced table \"%s\""
msgstr "brak klucza głównego dla tabeli referencyjnej \"%s\""
-#: commands/tablecmds.c:7137
+#: commands/tablecmds.c:7903
#, c-format
msgid "foreign key referenced-columns list must not contain duplicates"
msgstr "lista kolumn wskazanych przez klucz obcy nie może zawierać duplikatów"
-#: commands/tablecmds.c:7231
+#: commands/tablecmds.c:7997
#, c-format
msgid "cannot use a deferrable unique constraint for referenced table \"%s\""
msgstr "brak klucza odraczalnego ograniczenia unikalnego dla tabeli referencyjnej \"%s\""
-#: commands/tablecmds.c:7236
+#: commands/tablecmds.c:8002
#, c-format
msgid "there is no unique constraint matching given keys for referenced table \"%s\""
msgstr "brak ograniczenia unikalnego pasującego do danych kluczy dla tabeli referencyjnej \"%s\""
-#: commands/tablecmds.c:7399
+#: commands/tablecmds.c:8169
#, c-format
msgid "validating foreign key constraint \"%s\""
msgstr "sprawdzenie ograniczenia klucza obcego \"%s\""
-#: commands/tablecmds.c:7695
+#: commands/tablecmds.c:8471
#, c-format
msgid "cannot drop inherited constraint \"%s\" of relation \"%s\""
msgstr "nie można skasować dziedziczonego ograniczenia \"%s\" relacji \"%s\""
-#: commands/tablecmds.c:7729
+#: commands/tablecmds.c:8523
#, c-format
msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping"
msgstr "ograniczenie \"%s\" relacji \"%s\" nie istnieje, pominięto"
-#: commands/tablecmds.c:7868
+#: commands/tablecmds.c:8671
#, c-format
msgid "cannot alter column type of typed table"
msgstr "nie można zmienić typu kolumny tabeli typizowanej"
-#: commands/tablecmds.c:7891
+#: commands/tablecmds.c:8694
#, c-format
msgid "cannot alter inherited column \"%s\""
msgstr "nie można zmieniać kolumny dziedziczonej \"%s\""
-#: commands/tablecmds.c:7940
+#: commands/tablecmds.c:8703
+#, fuzzy, c-format
+#| msgid "cannot alter type of a column used in a trigger definition"
+msgid "cannot alter type of column named in partition key"
+msgstr "nie można zmieniać typu kolumny używanej przez definicję wyzwalacza"
+
+#: commands/tablecmds.c:8707
+#, fuzzy, c-format
+#| msgid "cannot use column references in default expression"
+msgid "cannot alter type of column referenced in partition key expression"
+msgstr "nie można użyć referencji kolumn w domyślnym wyrażeniu"
+
+#: commands/tablecmds.c:8757
#, c-format
msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s"
msgstr "wynik klauzuli USING kolumny \"%s\" nie może być automatycznie rzutowana na typ %s"
-#: commands/tablecmds.c:7943
+#: commands/tablecmds.c:8760
#, c-format
msgid "You might need to add an explicit cast."
msgstr "Możesz potrzebować dodać jawne rzutowanie."
-#: commands/tablecmds.c:7947
+#: commands/tablecmds.c:8764
#, c-format
msgid "column \"%s\" cannot be cast automatically to type %s"
msgstr "kolumna \"%s\" nie może być rzutowana automatycznie na typ %s"
#. translator: USING is SQL, don't translate it
-#: commands/tablecmds.c:7950
+#: commands/tablecmds.c:8767
#, c-format
msgid "You might need to specify \"USING %s::%s\"."
msgstr "Być może trzeba wskazać \"USING %s::%s\"."
-#: commands/tablecmds.c:8003
+#: commands/tablecmds.c:8866
+#, fuzzy, c-format
+#| msgid "Index \"%s\" contains a whole-row table reference."
+msgid "USING expression contains a whole-row table reference."
+msgstr "indeks \"%s\" zawiera wskazanie na tabelę całowierszową"
+
+#: commands/tablecmds.c:8877
#, c-format
msgid "type of inherited column \"%s\" must be changed in child tables too"
msgstr "typ kolumny dziedziczonej \"%s\" musi być zmieniony również w tabelach potomnych"
-#: commands/tablecmds.c:8090
+#: commands/tablecmds.c:8964
#, c-format
msgid "cannot alter type of column \"%s\" twice"
msgstr "nie można zmieniać typu kolumny \"%s\" dwukrotnie"
-#: commands/tablecmds.c:8126
+#: commands/tablecmds.c:9000
#, c-format
msgid "default for column \"%s\" cannot be cast automatically to type %s"
msgstr "wartość domyślna kolumny \"%s\" nie może być automatycznie rzutowana na typ %s"
-#: commands/tablecmds.c:8252
+#: commands/tablecmds.c:9126
#, c-format
msgid "cannot alter type of a column used by a view or rule"
msgstr "nie można zmieniać typu kolumny używanej przez widok lub regułę"
-#: commands/tablecmds.c:8253 commands/tablecmds.c:8272
-#: commands/tablecmds.c:8290
+#: commands/tablecmds.c:9127 commands/tablecmds.c:9146
+#: commands/tablecmds.c:9164
#, c-format
msgid "%s depends on column \"%s\""
msgstr "%s zależy od kolumny \"%s\""
-#: commands/tablecmds.c:8271
+#: commands/tablecmds.c:9145
#, c-format
msgid "cannot alter type of a column used in a trigger definition"
msgstr "nie można zmieniać typu kolumny używanej przez definicję wyzwalacza"
-#: commands/tablecmds.c:8289
+#: commands/tablecmds.c:9163
#, c-format
msgid "cannot alter type of a column used in a policy definition"
msgstr "nie można zmieniać typu kolumny używanej przez definicję polityki"
-#: commands/tablecmds.c:8954
+#: commands/tablecmds.c:9820
#, c-format
msgid "cannot change owner of index \"%s\""
msgstr "nie można zmienić właściciela indeksu \"%s\""
-#: commands/tablecmds.c:8956
+#: commands/tablecmds.c:9822
#, c-format
msgid "Change the ownership of the index's table, instead."
msgstr "W zamian zmień właściciela tabeli indeksu."
-#: commands/tablecmds.c:8972
+#: commands/tablecmds.c:9839
#, c-format
msgid "cannot change owner of sequence \"%s\""
msgstr "nie można zmienić właściciela sekwencji \"%s\""
-#: commands/tablecmds.c:8974 commands/tablecmds.c:11396
-#, c-format
-msgid "Sequence \"%s\" is linked to table \"%s\"."
-msgstr "Sekwencja \"%s\" jest połączona z tabelą \"%s\"."
-
-#: commands/tablecmds.c:8986 commands/tablecmds.c:12043
+#: commands/tablecmds.c:9853 commands/tablecmds.c:13064
#, c-format
msgid "Use ALTER TYPE instead."
msgstr "W zamian użyj ALTER TYPE."
-#: commands/tablecmds.c:8995
+#: commands/tablecmds.c:9862
#, c-format
msgid "\"%s\" is not a table, view, sequence, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem, sekwencją ani tabelą obcą"
-#: commands/tablecmds.c:9338
+#: commands/tablecmds.c:10203
#, c-format
msgid "cannot have multiple SET TABLESPACE subcommands"
msgstr "nie można użyć wielu poleceń podrzędnych SET TABLESPACE"
-#: commands/tablecmds.c:9411
+#: commands/tablecmds.c:10277
#, c-format
msgid "\"%s\" is not a table, view, materialized view, index, or TOAST table"
msgstr "\"%s\" nie jest tabelą, widokiem, zmaterializowanym widokiem, indeksem ani tabelą TOAST"
-#: commands/tablecmds.c:9444 commands/view.c:469
+#: commands/tablecmds.c:10310 commands/view.c:504
#, c-format
msgid "WITH CHECK OPTION is supported only on automatically updatable views"
msgstr "WITH CHECK OPTION jest obsługiwane tylko w automatycznie aktualizujących się widokach"
-#: commands/tablecmds.c:9590
+#: commands/tablecmds.c:10452
#, c-format
msgid "cannot move system relation \"%s\""
msgstr "nie można przenieść relacji systemowej \"%s\""
-#: commands/tablecmds.c:9606
+#: commands/tablecmds.c:10468
#, c-format
msgid "cannot move temporary tables of other sessions"
msgstr "nie można przenieść tabel tymczasowych innych sesji"
-#: commands/tablecmds.c:9743
+#: commands/tablecmds.c:10604
#, c-format
msgid "only tables, indexes, and materialized views exist in tablespaces"
msgstr "tylko tabele, indeksy i zmaterializowane widoki istnieją w przestrzeni tabel"
-#: commands/tablecmds.c:9755
+#: commands/tablecmds.c:10616
#, c-format
msgid "cannot move relations in to or out of pg_global tablespace"
msgstr "nie można przenosić relacji do lub poza przestrzeń tabel pg_global"
-#: commands/tablecmds.c:9846
+#: commands/tablecmds.c:10708
#, c-format
msgid "aborting because lock on relation \"%s.%s\" is not available"
msgstr "przerwano ponieważ blokada na relacji \"%s.%s\" nie jest dostępna"
-#: commands/tablecmds.c:9862
+#: commands/tablecmds.c:10724
#, c-format
msgid "no matching relations in tablespace \"%s\" found"
msgstr "nie znaleziono pasujących relacji w przestrzeni tabel \"%s\""
-#: commands/tablecmds.c:9936 storage/buffer/bufmgr.c:915
+#: commands/tablecmds.c:10798 storage/buffer/bufmgr.c:915
#, c-format
msgid "invalid page in block %u of relation %s"
msgstr "nieprawidłowa strona w bloku %u relacji %s"
-#: commands/tablecmds.c:10018
+#: commands/tablecmds.c:10880
#, c-format
msgid "cannot change inheritance of typed table"
msgstr "nie można zmienić dziedziczenia tabeli typizowanej"
-#: commands/tablecmds.c:10068
+#: commands/tablecmds.c:10885 commands/tablecmds.c:11413
+#, fuzzy, c-format
+#| msgid "cannot change inheritance of typed table"
+msgid "cannot change inheritance of a partition"
+msgstr "nie można zmienić dziedziczenia tabeli typizowanej"
+
+#: commands/tablecmds.c:10890
+#, fuzzy, c-format
+#| msgid "cannot change inheritance of typed table"
+msgid "cannot change inheritance of partitioned table"
+msgstr "nie można zmienić dziedziczenia tabeli typizowanej"
+
+#: commands/tablecmds.c:10935
#, c-format
msgid "cannot inherit to temporary relation of another session"
msgstr "nie można dziedziczyć do tymczasowej relacji z innej sesji"
-#: commands/tablecmds.c:10122
+#: commands/tablecmds.c:10948
+#, fuzzy, c-format
+#| msgid "cannot inherit from temporary relation \"%s\""
+msgid "cannot inherit from a partition"
+msgstr "nie można dziedziczyć z tymczasowej relacji \"%s\""
+
+#: commands/tablecmds.c:10970 commands/tablecmds.c:13416
#, c-format
msgid "circular inheritance not allowed"
msgstr "dziedziczenie cykliczne nie jest dozwolone"
-#: commands/tablecmds.c:10123
+#: commands/tablecmds.c:10971 commands/tablecmds.c:13417
#, c-format
msgid "\"%s\" is already a child of \"%s\"."
msgstr "\"%s\" jest już potomkiem \"%s\"."
-#: commands/tablecmds.c:10131
+#: commands/tablecmds.c:10979
#, c-format
msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
msgstr "tabela \"%s\" bez OIDu nie może dziedziczyć z tabeli \"%s\" z OIDem"
-#: commands/tablecmds.c:10272
+#: commands/tablecmds.c:11183
#, c-format
msgid "column \"%s\" in child table must be marked NOT NULL"
msgstr "kolumna \"%s\" w tabeli potomnej musi być oznaczona jako NOT NULL"
-#: commands/tablecmds.c:10288
+#: commands/tablecmds.c:11210 commands/tablecmds.c:11249
#, c-format
msgid "child table is missing column \"%s\""
msgstr "w tabeli potomnej brak kolumny \"%s\""
-#: commands/tablecmds.c:10371
+#: commands/tablecmds.c:11337
#, c-format
msgid "child table \"%s\" has different definition for check constraint \"%s\""
msgstr "tabela potomna \"%s\" posiada inną definicję ograniczenia sprawdzającego \"%s\""
-#: commands/tablecmds.c:10379
+#: commands/tablecmds.c:11345
#, c-format
msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\""
msgstr "ograniczenie \"%s\" jest niezgodne z niedziedziczonym ograniczeniem na tabeli potomnej \"%s\""
-#: commands/tablecmds.c:10403
+#: commands/tablecmds.c:11356
+#, c-format
+#| msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\""
+msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\""
+msgstr ""
+"ograniczenie \"%s\" jest niezgodne z ograniczeniem NOT VALID na tabeli "
+"potomnej \"%s\""
+
+#: commands/tablecmds.c:11391
#, c-format
msgid "child table is missing constraint \"%s\""
msgstr "w tabeli potomnej brak ograniczenia \"%s\""
-#: commands/tablecmds.c:10487
+#: commands/tablecmds.c:11507
+#, fuzzy, c-format
+#| msgid "relation \"%s\" is not a parent of relation \"%s\""
+msgid "relation \"%s\" is not a partition of relation \"%s\""
+msgstr "relacja \"%s\" nie jest rodzicem relacji \"%s\""
+
+#: commands/tablecmds.c:11513
#, c-format
msgid "relation \"%s\" is not a parent of relation \"%s\""
msgstr "relacja \"%s\" nie jest rodzicem relacji \"%s\""
-#: commands/tablecmds.c:10721
+#: commands/tablecmds.c:11737
#, c-format
msgid "typed tables cannot inherit"
msgstr "tabela typizowana nie może dziedziczyć"
-#: commands/tablecmds.c:10752
+#: commands/tablecmds.c:11768
#, c-format
msgid "table is missing column \"%s\""
msgstr "w tabeli brak kolumny \"%s\""
-#: commands/tablecmds.c:10762
+#: commands/tablecmds.c:11778
#, c-format
msgid "table has column \"%s\" where type requires \"%s\""
msgstr "tabela posiada kolumnę \"%s\", której typ wymaga \"%s\""
-#: commands/tablecmds.c:10771
+#: commands/tablecmds.c:11787
#, c-format
msgid "table \"%s\" has different type for column \"%s\""
msgstr "tabela \"%s\" posiada inny typ dla kolumny \"%s\""
-#: commands/tablecmds.c:10784
+#: commands/tablecmds.c:11800
#, c-format
msgid "table has extra column \"%s\""
msgstr "tabela posiada nadmiarową kolumnę \"%s\""
-#: commands/tablecmds.c:10836
+#: commands/tablecmds.c:11851
#, c-format
msgid "\"%s\" is not a typed table"
msgstr "\"%s\" nie jest tabelą typizowaną"
-#: commands/tablecmds.c:11020
+#: commands/tablecmds.c:12032
#, c-format
msgid "cannot use non-unique index \"%s\" as replica identity"
msgstr "nie można użyć nieunikalnego indeksu \"%s\" jako identyczności repliki"
-#: commands/tablecmds.c:11026
+#: commands/tablecmds.c:12038
#, c-format
msgid "cannot use non-immediate index \"%s\" as replica identity"
msgstr "nie można użyć niebezopśredniego indeksu \"%s\" jako identyczności repliki"
-#: commands/tablecmds.c:11032
+#: commands/tablecmds.c:12044
#, c-format
msgid "cannot use expression index \"%s\" as replica identity"
msgstr "nie można użyć indeksu opartego na wyrażeniu \"%s\" jako identyczności repliki"
-#: commands/tablecmds.c:11038
+#: commands/tablecmds.c:12050
#, c-format
msgid "cannot use partial index \"%s\" as replica identity"
msgstr "nie można użyć indeksu częściowego \"%s\" jako identyczności repliki"
-#: commands/tablecmds.c:11044
+#: commands/tablecmds.c:12056
#, c-format
msgid "cannot use invalid index \"%s\" as replica identity"
msgstr "nie można użyć niepoprawnego indeksu \"%s\" jako identyczności repliki"
-#: commands/tablecmds.c:11065
+#: commands/tablecmds.c:12077
#, c-format
-#| msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable"
msgid "index \"%s\" cannot be used as replica identity because column %d is a system column"
-msgstr ""
-"indeks \"%s\" nie może być użyty jako identyczność repliki ponieważ kolumna %d "
-"jest systemowa"
+msgstr "indeks \"%s\" nie może być użyty jako identyczność repliki ponieważ kolumna %d jest systemowa"
-#: commands/tablecmds.c:11072
+#: commands/tablecmds.c:12084
#, c-format
msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable"
msgstr "indeks \"%s\" nie może być użyty jako identyczność repliki ponieważ kolumna \"%s\" dopuszcza wartości puste"
-#: commands/tablecmds.c:11269
+#: commands/tablecmds.c:12277
#, c-format
msgid "cannot change logged status of table \"%s\" because it is temporary"
msgstr "nie można zmienić stanu logowania tabeli \"%s\" ponieważ jest ona tymczasowa"
-#: commands/tablecmds.c:11328
+#: commands/tablecmds.c:12301
+#, fuzzy, c-format
+#| msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\""
+msgid "cannot change table \"%s\" to unlogged because it is part of a publication"
+msgstr ""
+"nie udało się zmienić tabeli \"%s\" na nielogowaną ponieważ wskazuje na "
+"logowaną tabelę \"%s\""
+
+#: commands/tablecmds.c:12303
+#, fuzzy, c-format
+#| msgid "aggregate function calls cannot be nested"
+msgid "Unlogged relations cannot be replicated."
+msgstr "wywołania funkcji agregującej nie mogą być zagnieżdżone"
+
+#: commands/tablecmds.c:12348
#, c-format
msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\""
msgstr "nie udało zmienić tabeli \"%s\" na logowaną ponieważ wskazuje na nielogowaną tabelę \"%s\""
-#: commands/tablecmds.c:11338
+#: commands/tablecmds.c:12358
#, c-format
msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\""
msgstr "nie udało się zmienić tabeli \"%s\" na nielogowaną ponieważ wskazuje na logowaną tabelę \"%s\""
-#: commands/tablecmds.c:11395
+#: commands/tablecmds.c:12416
#, c-format
msgid "cannot move an owned sequence into another schema"
msgstr "nie można przenieść sekwencji mającej właściciela do innego schematu"
-#: commands/tablecmds.c:11500
+#: commands/tablecmds.c:12522
#, c-format
msgid "relation \"%s\" already exists in schema \"%s\""
msgstr "relacja \"%s\" istnieje już w schemacie \"%s\""
-#: commands/tablecmds.c:12027
+#: commands/tablecmds.c:13048
#, c-format
msgid "\"%s\" is not a composite type"
msgstr "\"%s\" nie jest typem złożonym"
-#: commands/tablecmds.c:12057
+#: commands/tablecmds.c:13079
#, c-format
msgid "\"%s\" is not a table, view, materialized view, sequence, or foreign table"
msgstr "\"%s\" nie jest tabelą, widokiem, widokiem zmaterializowanym, sekwencją ani tabelą zewnętrzną"
+#: commands/tablecmds.c:13110
+#, fuzzy, c-format
+#| msgid "unrecognized privilege type \"%s\""
+msgid "unrecognized partitioning strategy \"%s\""
+msgstr "nierozpoznany typ uprawnienia \"%s\""
+
+#: commands/tablecmds.c:13136
+#, fuzzy, c-format
+#| msgid "common column name \"%s\" appears more than once in right table"
+msgid "column \"%s\" appears more than once in partition key"
+msgstr "wspólna nazwa kolumny \"%s\" występuje więcej niż raz w prawej tabeli"
+
+#: commands/tablecmds.c:13184
+#, fuzzy, c-format
+#| msgid "column \"%s\" named in key does not exist"
+msgid "column \"%s\" named in partition key does not exist"
+msgstr "kolumna \"%s\" nazwana w kluczu nie istnieje"
+
+#: commands/tablecmds.c:13191
+#, fuzzy, c-format
+#| msgid "cannot alter system column \"%s\""
+msgid "cannot use system column \"%s\" in partition key"
+msgstr "nie można zmieniać kolumny systemowej \"%s\""
+
+#: commands/tablecmds.c:13249
+#, fuzzy, c-format
+#| msgid "functions in index expression must be marked IMMUTABLE"
+msgid "functions in partition key expression must be marked IMMUTABLE"
+msgstr "funkcje w wyrażeniu indeksu muszą być oznaczone jako IMMUTABLE"
+
+#: commands/tablecmds.c:13258
+#, fuzzy, c-format
+#| msgid "cannot use expression index \"%s\" as replica identity"
+msgid "cannot use constant expression as partition key"
+msgstr ""
+"nie można użyć indeksu opartego na wyrażeniu \"%s\" jako identyczności repliki"
+
+#: commands/tablecmds.c:13272
+#, fuzzy, c-format
+#| msgid "cannot convert whole-row table reference"
+msgid "partition key expressions cannot contain whole-row references"
+msgstr "nie można zmienić wskazania na tabelę całowierszową"
+
+#: commands/tablecmds.c:13293
+#, fuzzy, c-format
+#| msgid "could not determine which collation to use for index expression"
+msgid "could not determine which collation to use for partition expression"
+msgstr "nie można określić, jakiego porównania użyć dla wyrażenia indeksu"
+
+#: commands/tablecmds.c:13318
+#, fuzzy, c-format
+#| msgid "data type %s has no default operator class for access method \"%s\""
+msgid "data type %s has no default btree operator class"
+msgstr "typ danych %s nie ma domyślnej klasy operatora dla metody dostępu \"%s\""
+
+#: commands/tablecmds.c:13320
+#, fuzzy, c-format
+#| msgid "You must specify an operator class for the index or define a default operator class for the data type."
+msgid "You must specify a btree operator class or define a default btree operator class for the data type."
+msgstr ""
+"Musisz wskazać klasę operatora dla indeksu lub zdefiniować domyślną klasę "
+"operatora dla typu danych."
+
+#: commands/tablecmds.c:13367
+#, c-format
+#| msgid "\"%s\" is already a view"
+msgid "\"%s\" is already a partition"
+msgstr "\"%s\" jest już partycją"
+
+#: commands/tablecmds.c:13373
+#, fuzzy, c-format
+#| msgid "cannot add column to typed table"
+msgid "cannot attach a typed table as partition"
+msgstr "nie dodać kolumny tabeli typizowanej"
+
+#: commands/tablecmds.c:13389
+#, c-format
+msgid "cannot attach inheritance child as partition"
+msgstr ""
+
+#: commands/tablecmds.c:13403
+#, fuzzy, c-format
+#| msgid "cannot change inheritance of typed table"
+msgid "cannot attach inheritance parent as partition"
+msgstr "nie można zmienić dziedziczenia tabeli typizowanej"
+
+#: commands/tablecmds.c:13426
+#, fuzzy, c-format
+#| msgid "cannot inherit from temporary relation \"%s\""
+msgid "cannot attach a permanent relation as partition of temporary relation \"%s\""
+msgstr "nie można dziedziczyć z tymczasowej relacji \"%s\""
+
+#: commands/tablecmds.c:13434
+#, fuzzy, c-format
+#| msgid "cannot inherit to temporary relation of another session"
+msgid "cannot attach as partition of temporary relation of another session"
+msgstr "nie można dziedziczyć do tymczasowej relacji z innej sesji"
+
+#: commands/tablecmds.c:13441
+#, fuzzy, c-format
+#| msgid "cannot inherit to temporary relation of another session"
+msgid "cannot attach temporary relation of another session as partition"
+msgstr "nie można dziedziczyć do tymczasowej relacji z innej sesji"
+
+#: commands/tablecmds.c:13447
+#, fuzzy, c-format
+#| msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgid "cannot attach table \"%s\" without OIDs as partition of table \"%s\" with OIDs"
+msgstr "tabela \"%s\" bez OIDu nie może dziedziczyć z tabeli \"%s\" z OIDem"
+
+#: commands/tablecmds.c:13455
+#, fuzzy, c-format
+#| msgid "table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs"
+msgid "cannot attach table \"%s\" with OIDs as partition of table \"%s\" without OIDs"
+msgstr "tabela \"%s\" bez OIDu nie może dziedziczyć z tabeli \"%s\" z OIDem"
+
+#: commands/tablecmds.c:13477
+#, fuzzy, c-format
+#| msgid "column \"%s\" not found in data type %s"
+msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\""
+msgstr "nie odnaleziono kolumny \"%s\" w typie danych %s"