gitlab-pg_query 1.3.1 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +217 -99
- data/README.md +92 -69
- data/Rakefile +85 -5
- data/ext/pg_query/extconf.rb +3 -40
- data/ext/pg_query/guc-file.c +0 -0
- data/ext/pg_query/include/access/amapi.h +246 -0
- data/ext/pg_query/include/access/attmap.h +52 -0
- data/ext/pg_query/include/access/attnum.h +64 -0
- data/ext/pg_query/include/access/clog.h +61 -0
- data/ext/pg_query/include/access/commit_ts.h +77 -0
- data/ext/pg_query/include/access/detoast.h +92 -0
- data/ext/pg_query/include/access/genam.h +228 -0
- data/ext/pg_query/include/access/gin.h +78 -0
- data/ext/pg_query/include/access/htup.h +89 -0
- data/ext/pg_query/include/access/htup_details.h +819 -0
- data/ext/pg_query/include/access/itup.h +161 -0
- data/ext/pg_query/include/access/parallel.h +82 -0
- data/ext/pg_query/include/access/printtup.h +35 -0
- data/ext/pg_query/include/access/relation.h +28 -0
- data/ext/pg_query/include/access/relscan.h +176 -0
- data/ext/pg_query/include/access/rmgr.h +35 -0
- data/ext/pg_query/include/access/rmgrlist.h +49 -0
- data/ext/pg_query/include/access/sdir.h +58 -0
- data/ext/pg_query/include/access/skey.h +151 -0
- data/ext/pg_query/include/access/stratnum.h +83 -0
- data/ext/pg_query/include/access/sysattr.h +29 -0
- data/ext/pg_query/include/access/table.h +27 -0
- data/ext/pg_query/include/access/tableam.h +1825 -0
- data/ext/pg_query/include/access/transam.h +265 -0
- data/ext/pg_query/include/access/tupconvert.h +51 -0
- data/ext/pg_query/include/access/tupdesc.h +154 -0
- data/ext/pg_query/include/access/tupmacs.h +247 -0
- data/ext/pg_query/include/access/twophase.h +61 -0
- data/ext/pg_query/include/access/xact.h +463 -0
- data/ext/pg_query/include/access/xlog.h +398 -0
- data/ext/pg_query/include/access/xlog_internal.h +330 -0
- data/ext/pg_query/include/access/xlogdefs.h +109 -0
- data/ext/pg_query/include/access/xloginsert.h +64 -0
- data/ext/pg_query/include/access/xlogreader.h +327 -0
- data/ext/pg_query/include/access/xlogrecord.h +227 -0
- data/ext/pg_query/include/bootstrap/bootstrap.h +62 -0
- data/ext/pg_query/include/c.h +1322 -0
- data/ext/pg_query/include/catalog/catalog.h +42 -0
- data/ext/pg_query/include/catalog/catversion.h +58 -0
- data/ext/pg_query/include/catalog/dependency.h +275 -0
- data/ext/pg_query/include/catalog/genbki.h +64 -0
- data/ext/pg_query/include/catalog/index.h +199 -0
- data/ext/pg_query/include/catalog/indexing.h +366 -0
- data/ext/pg_query/include/catalog/namespace.h +188 -0
- data/ext/pg_query/include/catalog/objectaccess.h +197 -0
- data/ext/pg_query/include/catalog/objectaddress.h +84 -0
- data/ext/pg_query/include/catalog/pg_aggregate.h +176 -0
- data/ext/pg_query/include/catalog/pg_aggregate_d.h +77 -0
- data/ext/pg_query/include/catalog/pg_am.h +60 -0
- data/ext/pg_query/include/catalog/pg_am_d.h +45 -0
- data/ext/pg_query/include/catalog/pg_attribute.h +204 -0
- data/ext/pg_query/include/catalog/pg_attribute_d.h +59 -0
- data/ext/pg_query/include/catalog/pg_authid.h +58 -0
- data/ext/pg_query/include/catalog/pg_authid_d.h +49 -0
- data/ext/pg_query/include/catalog/pg_class.h +200 -0
- data/ext/pg_query/include/catalog/pg_class_d.h +103 -0
- data/ext/pg_query/include/catalog/pg_collation.h +73 -0
- data/ext/pg_query/include/catalog/pg_collation_d.h +45 -0
- data/ext/pg_query/include/catalog/pg_constraint.h +247 -0
- data/ext/pg_query/include/catalog/pg_constraint_d.h +67 -0
- data/ext/pg_query/include/catalog/pg_control.h +250 -0
- data/ext/pg_query/include/catalog/pg_conversion.h +72 -0
- data/ext/pg_query/include/catalog/pg_conversion_d.h +35 -0
- data/ext/pg_query/include/catalog/pg_depend.h +73 -0
- data/ext/pg_query/include/catalog/pg_depend_d.h +34 -0
- data/ext/pg_query/include/catalog/pg_event_trigger.h +51 -0
- data/ext/pg_query/include/catalog/pg_event_trigger_d.h +34 -0
- data/ext/pg_query/include/catalog/pg_index.h +80 -0
- data/ext/pg_query/include/catalog/pg_index_d.h +56 -0
- data/ext/pg_query/include/catalog/pg_language.h +67 -0
- data/ext/pg_query/include/catalog/pg_language_d.h +39 -0
- data/ext/pg_query/include/catalog/pg_namespace.h +59 -0
- data/ext/pg_query/include/catalog/pg_namespace_d.h +34 -0
- data/ext/pg_query/include/catalog/pg_opclass.h +85 -0
- data/ext/pg_query/include/catalog/pg_opclass_d.h +49 -0
- data/ext/pg_query/include/catalog/pg_operator.h +102 -0
- data/ext/pg_query/include/catalog/pg_operator_d.h +106 -0
- data/ext/pg_query/include/catalog/pg_opfamily.h +60 -0
- data/ext/pg_query/include/catalog/pg_opfamily_d.h +47 -0
- data/ext/pg_query/include/catalog/pg_partitioned_table.h +63 -0
- data/ext/pg_query/include/catalog/pg_partitioned_table_d.h +35 -0
- data/ext/pg_query/include/catalog/pg_proc.h +211 -0
- data/ext/pg_query/include/catalog/pg_proc_d.h +99 -0
- data/ext/pg_query/include/catalog/pg_publication.h +115 -0
- data/ext/pg_query/include/catalog/pg_publication_d.h +36 -0
- data/ext/pg_query/include/catalog/pg_replication_origin.h +57 -0
- data/ext/pg_query/include/catalog/pg_replication_origin_d.h +29 -0
- data/ext/pg_query/include/catalog/pg_statistic.h +275 -0
- data/ext/pg_query/include/catalog/pg_statistic_d.h +194 -0
- data/ext/pg_query/include/catalog/pg_statistic_ext.h +74 -0
- data/ext/pg_query/include/catalog/pg_statistic_ext_d.h +40 -0
- data/ext/pg_query/include/catalog/pg_transform.h +45 -0
- data/ext/pg_query/include/catalog/pg_transform_d.h +32 -0
- data/ext/pg_query/include/catalog/pg_trigger.h +137 -0
- data/ext/pg_query/include/catalog/pg_trigger_d.h +106 -0
- data/ext/pg_query/include/catalog/pg_ts_config.h +50 -0
- data/ext/pg_query/include/catalog/pg_ts_config_d.h +32 -0
- data/ext/pg_query/include/catalog/pg_ts_dict.h +54 -0
- data/ext/pg_query/include/catalog/pg_ts_dict_d.h +33 -0
- data/ext/pg_query/include/catalog/pg_ts_parser.h +57 -0
- data/ext/pg_query/include/catalog/pg_ts_parser_d.h +35 -0
- data/ext/pg_query/include/catalog/pg_ts_template.h +48 -0
- data/ext/pg_query/include/catalog/pg_ts_template_d.h +32 -0
- data/ext/pg_query/include/catalog/pg_type.h +372 -0
- data/ext/pg_query/include/catalog/pg_type_d.h +285 -0
- data/ext/pg_query/include/catalog/storage.h +48 -0
- data/ext/pg_query/include/commands/async.h +54 -0
- data/ext/pg_query/include/commands/dbcommands.h +35 -0
- data/ext/pg_query/include/commands/defrem.h +173 -0
- data/ext/pg_query/include/commands/event_trigger.h +88 -0
- data/ext/pg_query/include/commands/explain.h +127 -0
- data/ext/pg_query/include/commands/prepare.h +61 -0
- data/ext/pg_query/include/commands/tablespace.h +67 -0
- data/ext/pg_query/include/commands/trigger.h +277 -0
- data/ext/pg_query/include/commands/user.h +37 -0
- data/ext/pg_query/include/commands/vacuum.h +293 -0
- data/ext/pg_query/include/commands/variable.h +38 -0
- data/ext/pg_query/include/common/file_perm.h +56 -0
- data/ext/pg_query/include/common/hashfn.h +104 -0
- data/ext/pg_query/include/common/ip.h +37 -0
- data/ext/pg_query/include/common/keywords.h +33 -0
- data/ext/pg_query/include/common/kwlookup.h +44 -0
- data/ext/pg_query/include/common/relpath.h +90 -0
- data/ext/pg_query/include/common/string.h +19 -0
- data/ext/pg_query/include/common/unicode_combining_table.h +196 -0
- data/ext/pg_query/include/datatype/timestamp.h +197 -0
- data/ext/pg_query/include/executor/execdesc.h +70 -0
- data/ext/pg_query/include/executor/executor.h +614 -0
- data/ext/pg_query/include/executor/functions.h +41 -0
- data/ext/pg_query/include/executor/instrument.h +101 -0
- data/ext/pg_query/include/executor/spi.h +175 -0
- data/ext/pg_query/include/executor/tablefunc.h +67 -0
- data/ext/pg_query/include/executor/tuptable.h +487 -0
- data/ext/pg_query/include/fmgr.h +775 -0
- data/ext/pg_query/include/funcapi.h +348 -0
- data/ext/pg_query/include/getaddrinfo.h +162 -0
- data/ext/pg_query/include/jit/jit.h +105 -0
- data/ext/pg_query/include/kwlist_d.h +1072 -0
- data/ext/pg_query/include/lib/ilist.h +727 -0
- data/ext/pg_query/include/lib/pairingheap.h +102 -0
- data/ext/pg_query/include/lib/simplehash.h +1059 -0
- data/ext/pg_query/include/lib/stringinfo.h +161 -0
- data/ext/pg_query/include/libpq/auth.h +29 -0
- data/ext/pg_query/include/libpq/crypt.h +46 -0
- data/ext/pg_query/include/libpq/hba.h +140 -0
- data/ext/pg_query/include/libpq/libpq-be.h +326 -0
- data/ext/pg_query/include/libpq/libpq.h +133 -0
- data/ext/pg_query/include/libpq/pqcomm.h +208 -0
- data/ext/pg_query/include/libpq/pqformat.h +210 -0
- data/ext/pg_query/include/libpq/pqsignal.h +42 -0
- data/ext/pg_query/include/mb/pg_wchar.h +672 -0
- data/ext/pg_query/include/mb/stringinfo_mb.h +24 -0
- data/ext/pg_query/include/miscadmin.h +476 -0
- data/ext/pg_query/include/nodes/bitmapset.h +122 -0
- data/ext/pg_query/include/nodes/execnodes.h +2520 -0
- data/ext/pg_query/include/nodes/extensible.h +160 -0
- data/ext/pg_query/include/nodes/lockoptions.h +61 -0
- data/ext/pg_query/include/nodes/makefuncs.h +108 -0
- data/ext/pg_query/include/nodes/memnodes.h +108 -0
- data/ext/pg_query/include/nodes/nodeFuncs.h +162 -0
- data/ext/pg_query/include/nodes/nodes.h +842 -0
- data/ext/pg_query/include/nodes/params.h +170 -0
- data/ext/pg_query/include/nodes/parsenodes.h +3579 -0
- data/ext/pg_query/include/nodes/pathnodes.h +2556 -0
- data/ext/pg_query/include/nodes/pg_list.h +605 -0
- data/ext/pg_query/include/nodes/plannodes.h +1251 -0
- data/ext/pg_query/include/nodes/primnodes.h +1541 -0
- data/ext/pg_query/include/nodes/print.h +34 -0
- data/ext/pg_query/include/nodes/tidbitmap.h +75 -0
- data/ext/pg_query/include/nodes/value.h +61 -0
- data/ext/pg_query/include/optimizer/cost.h +206 -0
- data/ext/pg_query/include/optimizer/geqo.h +88 -0
- data/ext/pg_query/include/optimizer/geqo_gene.h +45 -0
- data/ext/pg_query/include/optimizer/optimizer.h +199 -0
- data/ext/pg_query/include/optimizer/paths.h +249 -0
- data/ext/pg_query/include/optimizer/planmain.h +119 -0
- data/ext/pg_query/include/parser/analyze.h +49 -0
- data/ext/pg_query/include/parser/gram.h +1067 -0
- data/ext/pg_query/include/parser/gramparse.h +75 -0
- data/ext/pg_query/include/parser/kwlist.h +477 -0
- data/ext/pg_query/include/parser/parse_agg.h +68 -0
- data/ext/pg_query/include/parser/parse_clause.h +54 -0
- data/ext/pg_query/include/parser/parse_coerce.h +97 -0
- data/ext/pg_query/include/parser/parse_collate.h +27 -0
- data/ext/pg_query/include/parser/parse_expr.h +26 -0
- data/ext/pg_query/include/parser/parse_func.h +73 -0
- data/ext/pg_query/include/parser/parse_node.h +327 -0
- data/ext/pg_query/include/parser/parse_oper.h +67 -0
- data/ext/pg_query/include/parser/parse_relation.h +123 -0
- data/ext/pg_query/include/parser/parse_target.h +46 -0
- data/ext/pg_query/include/parser/parse_type.h +60 -0
- data/ext/pg_query/include/parser/parser.h +41 -0
- data/ext/pg_query/include/parser/parsetree.h +61 -0
- data/ext/pg_query/include/parser/scanner.h +152 -0
- data/ext/pg_query/include/parser/scansup.h +30 -0
- data/ext/pg_query/include/partitioning/partdefs.h +26 -0
- data/ext/pg_query/include/pg_config.h +989 -0
- data/ext/pg_query/include/pg_config_ext.h +8 -0
- data/ext/pg_query/include/pg_config_manual.h +350 -0
- data/ext/pg_query/include/pg_config_os.h +8 -0
- data/ext/pg_query/include/pg_getopt.h +56 -0
- data/ext/pg_query/include/pg_query.h +121 -0
- data/ext/pg_query/include/pg_query_enum_defs.c +2454 -0
- data/ext/pg_query/include/pg_query_fingerprint_conds.c +875 -0
- data/ext/pg_query/include/pg_query_fingerprint_defs.c +12413 -0
- data/ext/pg_query/include/pg_query_json_helper.c +61 -0
- data/ext/pg_query/include/pg_query_outfuncs_conds.c +686 -0
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +2437 -0
- data/ext/pg_query/include/pg_query_readfuncs_conds.c +222 -0
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +2878 -0
- data/ext/pg_query/include/pg_trace.h +17 -0
- data/ext/pg_query/include/pgstat.h +1487 -0
- data/ext/pg_query/include/pgtime.h +84 -0
- data/ext/pg_query/include/pl_gram.h +385 -0
- data/ext/pg_query/include/pl_reserved_kwlist.h +52 -0
- data/ext/pg_query/include/pl_reserved_kwlist_d.h +114 -0
- data/ext/pg_query/include/pl_unreserved_kwlist.h +112 -0
- data/ext/pg_query/include/pl_unreserved_kwlist_d.h +246 -0
- data/ext/pg_query/include/plerrcodes.h +990 -0
- data/ext/pg_query/include/plpgsql.h +1347 -0
- data/ext/pg_query/include/port.h +524 -0
- data/ext/pg_query/include/port/atomics.h +524 -0
- data/ext/pg_query/include/port/atomics/arch-arm.h +26 -0
- data/ext/pg_query/include/port/atomics/arch-ppc.h +254 -0
- data/ext/pg_query/include/port/atomics/arch-x86.h +252 -0
- data/ext/pg_query/include/port/atomics/fallback.h +170 -0
- data/ext/pg_query/include/port/atomics/generic-gcc.h +286 -0
- data/ext/pg_query/include/port/atomics/generic.h +401 -0
- data/ext/pg_query/include/port/pg_bitutils.h +226 -0
- data/ext/pg_query/include/port/pg_bswap.h +161 -0
- data/ext/pg_query/include/port/pg_crc32c.h +101 -0
- data/ext/pg_query/include/portability/instr_time.h +256 -0
- data/ext/pg_query/include/postgres.h +764 -0
- data/ext/pg_query/include/postgres_ext.h +74 -0
- data/ext/pg_query/include/postmaster/autovacuum.h +83 -0
- data/ext/pg_query/include/postmaster/bgworker.h +161 -0
- data/ext/pg_query/include/postmaster/bgworker_internals.h +64 -0
- data/ext/pg_query/include/postmaster/bgwriter.h +45 -0
- data/ext/pg_query/include/postmaster/fork_process.h +17 -0
- data/ext/pg_query/include/postmaster/interrupt.h +32 -0
- data/ext/pg_query/include/postmaster/pgarch.h +39 -0
- data/ext/pg_query/include/postmaster/postmaster.h +77 -0
- data/ext/pg_query/include/postmaster/syslogger.h +98 -0
- data/ext/pg_query/include/postmaster/walwriter.h +21 -0
- data/ext/pg_query/include/protobuf-c.h +1106 -0
- data/ext/pg_query/include/protobuf-c/protobuf-c.h +1106 -0
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +10846 -0
- data/ext/pg_query/include/protobuf/pg_query.pb.h +124718 -0
- data/ext/pg_query/include/regex/regex.h +184 -0
- data/ext/pg_query/include/replication/logicallauncher.h +31 -0
- data/ext/pg_query/include/replication/logicalproto.h +110 -0
- data/ext/pg_query/include/replication/logicalworker.h +19 -0
- data/ext/pg_query/include/replication/origin.h +73 -0
- data/ext/pg_query/include/replication/reorderbuffer.h +467 -0
- data/ext/pg_query/include/replication/slot.h +219 -0
- data/ext/pg_query/include/replication/syncrep.h +115 -0
- data/ext/pg_query/include/replication/walreceiver.h +340 -0
- data/ext/pg_query/include/replication/walsender.h +74 -0
- data/ext/pg_query/include/rewrite/prs2lock.h +46 -0
- data/ext/pg_query/include/rewrite/rewriteHandler.h +40 -0
- data/ext/pg_query/include/rewrite/rewriteManip.h +87 -0
- data/ext/pg_query/include/rewrite/rewriteSupport.h +26 -0
- data/ext/pg_query/include/storage/backendid.h +37 -0
- data/ext/pg_query/include/storage/block.h +121 -0
- data/ext/pg_query/include/storage/buf.h +46 -0
- data/ext/pg_query/include/storage/bufmgr.h +292 -0
- data/ext/pg_query/include/storage/bufpage.h +459 -0
- data/ext/pg_query/include/storage/condition_variable.h +62 -0
- data/ext/pg_query/include/storage/dsm.h +61 -0
- data/ext/pg_query/include/storage/dsm_impl.h +75 -0
- data/ext/pg_query/include/storage/fd.h +168 -0
- data/ext/pg_query/include/storage/ipc.h +81 -0
- data/ext/pg_query/include/storage/item.h +19 -0
- data/ext/pg_query/include/storage/itemid.h +184 -0
- data/ext/pg_query/include/storage/itemptr.h +206 -0
- data/ext/pg_query/include/storage/large_object.h +100 -0
- data/ext/pg_query/include/storage/latch.h +190 -0
- data/ext/pg_query/include/storage/lmgr.h +114 -0
- data/ext/pg_query/include/storage/lock.h +612 -0
- data/ext/pg_query/include/storage/lockdefs.h +59 -0
- data/ext/pg_query/include/storage/lwlock.h +232 -0
- data/ext/pg_query/include/storage/lwlocknames.h +51 -0
- data/ext/pg_query/include/storage/off.h +57 -0
- data/ext/pg_query/include/storage/pg_sema.h +61 -0
- data/ext/pg_query/include/storage/pg_shmem.h +90 -0
- data/ext/pg_query/include/storage/pmsignal.h +94 -0
- data/ext/pg_query/include/storage/predicate.h +87 -0
- data/ext/pg_query/include/storage/proc.h +333 -0
- data/ext/pg_query/include/storage/proclist_types.h +51 -0
- data/ext/pg_query/include/storage/procsignal.h +75 -0
- data/ext/pg_query/include/storage/relfilenode.h +99 -0
- data/ext/pg_query/include/storage/s_lock.h +1047 -0
- data/ext/pg_query/include/storage/sharedfileset.h +45 -0
- data/ext/pg_query/include/storage/shm_mq.h +85 -0
- data/ext/pg_query/include/storage/shm_toc.h +58 -0
- data/ext/pg_query/include/storage/shmem.h +81 -0
- data/ext/pg_query/include/storage/sinval.h +153 -0
- data/ext/pg_query/include/storage/sinvaladt.h +43 -0
- data/ext/pg_query/include/storage/smgr.h +109 -0
- data/ext/pg_query/include/storage/spin.h +77 -0
- data/ext/pg_query/include/storage/standby.h +91 -0
- data/ext/pg_query/include/storage/standbydefs.h +74 -0
- data/ext/pg_query/include/storage/sync.h +62 -0
- data/ext/pg_query/include/tcop/cmdtag.h +58 -0
- data/ext/pg_query/include/tcop/cmdtaglist.h +217 -0
- data/ext/pg_query/include/tcop/deparse_utility.h +108 -0
- data/ext/pg_query/include/tcop/dest.h +149 -0
- data/ext/pg_query/include/tcop/fastpath.h +21 -0
- data/ext/pg_query/include/tcop/pquery.h +45 -0
- data/ext/pg_query/include/tcop/tcopprot.h +89 -0
- data/ext/pg_query/include/tcop/utility.h +108 -0
- data/ext/pg_query/include/tsearch/ts_cache.h +98 -0
- data/ext/pg_query/include/utils/acl.h +312 -0
- data/ext/pg_query/include/utils/aclchk_internal.h +45 -0
- data/ext/pg_query/include/utils/array.h +458 -0
- data/ext/pg_query/include/utils/builtins.h +127 -0
- data/ext/pg_query/include/utils/bytea.h +27 -0
- data/ext/pg_query/include/utils/catcache.h +231 -0
- data/ext/pg_query/include/utils/date.h +90 -0
- data/ext/pg_query/include/utils/datetime.h +343 -0
- data/ext/pg_query/include/utils/datum.h +68 -0
- data/ext/pg_query/include/utils/dsa.h +123 -0
- data/ext/pg_query/include/utils/dynahash.h +19 -0
- data/ext/pg_query/include/utils/elog.h +439 -0
- data/ext/pg_query/include/utils/errcodes.h +352 -0
- data/ext/pg_query/include/utils/expandeddatum.h +159 -0
- data/ext/pg_query/include/utils/expandedrecord.h +231 -0
- data/ext/pg_query/include/utils/float.h +356 -0
- data/ext/pg_query/include/utils/fmgroids.h +2657 -0
- data/ext/pg_query/include/utils/fmgrprotos.h +2646 -0
- data/ext/pg_query/include/utils/fmgrtab.h +48 -0
- data/ext/pg_query/include/utils/guc.h +443 -0
- data/ext/pg_query/include/utils/guc_tables.h +272 -0
- data/ext/pg_query/include/utils/hsearch.h +149 -0
- data/ext/pg_query/include/utils/inval.h +64 -0
- data/ext/pg_query/include/utils/lsyscache.h +197 -0
- data/ext/pg_query/include/utils/memdebug.h +82 -0
- data/ext/pg_query/include/utils/memutils.h +225 -0
- data/ext/pg_query/include/utils/numeric.h +76 -0
- data/ext/pg_query/include/utils/palloc.h +136 -0
- data/ext/pg_query/include/utils/partcache.h +102 -0
- data/ext/pg_query/include/utils/pg_locale.h +119 -0
- data/ext/pg_query/include/utils/pg_lsn.h +29 -0
- data/ext/pg_query/include/utils/pidfile.h +56 -0
- data/ext/pg_query/include/utils/plancache.h +235 -0
- data/ext/pg_query/include/utils/portal.h +241 -0
- data/ext/pg_query/include/utils/probes.h +114 -0
- data/ext/pg_query/include/utils/ps_status.h +25 -0
- data/ext/pg_query/include/utils/queryenvironment.h +74 -0
- data/ext/pg_query/include/utils/regproc.h +28 -0
- data/ext/pg_query/include/utils/rel.h +644 -0
- data/ext/pg_query/include/utils/relcache.h +151 -0
- data/ext/pg_query/include/utils/reltrigger.h +81 -0
- data/ext/pg_query/include/utils/resowner.h +86 -0
- data/ext/pg_query/include/utils/rls.h +50 -0
- data/ext/pg_query/include/utils/ruleutils.h +44 -0
- data/ext/pg_query/include/utils/sharedtuplestore.h +61 -0
- data/ext/pg_query/include/utils/snapmgr.h +158 -0
- data/ext/pg_query/include/utils/snapshot.h +206 -0
- data/ext/pg_query/include/utils/sortsupport.h +276 -0
- data/ext/pg_query/include/utils/syscache.h +219 -0
- data/ext/pg_query/include/utils/timeout.h +88 -0
- data/ext/pg_query/include/utils/timestamp.h +116 -0
- data/ext/pg_query/include/utils/tuplesort.h +277 -0
- data/ext/pg_query/include/utils/tuplestore.h +91 -0
- data/ext/pg_query/include/utils/typcache.h +202 -0
- data/ext/pg_query/include/utils/tzparser.h +39 -0
- data/ext/pg_query/include/utils/varlena.h +39 -0
- data/ext/pg_query/include/utils/xml.h +84 -0
- data/ext/pg_query/include/xxhash.h +5445 -0
- data/ext/pg_query/include/xxhash/xxhash.h +5445 -0
- data/ext/pg_query/pg_query.c +104 -0
- data/ext/pg_query/pg_query.pb-c.c +37628 -0
- data/ext/pg_query/pg_query_deparse.c +9959 -0
- data/ext/pg_query/pg_query_fingerprint.c +295 -0
- data/ext/pg_query/pg_query_fingerprint.h +8 -0
- data/ext/pg_query/pg_query_internal.h +24 -0
- data/ext/pg_query/pg_query_json_plpgsql.c +738 -0
- data/ext/pg_query/pg_query_json_plpgsql.h +9 -0
- data/ext/pg_query/pg_query_normalize.c +439 -0
- data/ext/pg_query/pg_query_outfuncs.h +10 -0
- data/ext/pg_query/pg_query_outfuncs_json.c +297 -0
- data/ext/pg_query/pg_query_outfuncs_protobuf.c +237 -0
- data/ext/pg_query/pg_query_parse.c +148 -0
- data/ext/pg_query/pg_query_parse_plpgsql.c +460 -0
- data/ext/pg_query/pg_query_readfuncs.h +11 -0
- data/ext/pg_query/pg_query_readfuncs_protobuf.c +142 -0
- data/ext/pg_query/pg_query_ruby.c +108 -12
- data/ext/pg_query/pg_query_scan.c +173 -0
- data/ext/pg_query/pg_query_split.c +221 -0
- data/ext/pg_query/protobuf-c.c +3660 -0
- data/ext/pg_query/src_backend_catalog_namespace.c +1051 -0
- data/ext/pg_query/src_backend_catalog_pg_proc.c +142 -0
- data/ext/pg_query/src_backend_commands_define.c +117 -0
- data/ext/pg_query/src_backend_libpq_pqcomm.c +651 -0
- data/ext/pg_query/src_backend_nodes_bitmapset.c +513 -0
- data/ext/pg_query/src_backend_nodes_copyfuncs.c +6013 -0
- data/ext/pg_query/src_backend_nodes_equalfuncs.c +4003 -0
- data/ext/pg_query/src_backend_nodes_extensible.c +99 -0
- data/ext/pg_query/src_backend_nodes_list.c +922 -0
- data/ext/pg_query/src_backend_nodes_makefuncs.c +417 -0
- data/ext/pg_query/src_backend_nodes_nodeFuncs.c +1363 -0
- data/ext/pg_query/src_backend_nodes_value.c +84 -0
- data/ext/pg_query/src_backend_parser_gram.c +47456 -0
- data/ext/pg_query/src_backend_parser_parse_expr.c +313 -0
- data/ext/pg_query/src_backend_parser_parser.c +497 -0
- data/ext/pg_query/src_backend_parser_scan.c +7091 -0
- data/ext/pg_query/src_backend_parser_scansup.c +160 -0
- data/ext/pg_query/src_backend_postmaster_postmaster.c +2230 -0
- data/ext/pg_query/src_backend_storage_ipc_ipc.c +192 -0
- data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +370 -0
- data/ext/pg_query/src_backend_tcop_postgres.c +776 -0
- data/ext/pg_query/src_backend_utils_adt_datum.c +326 -0
- data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +98 -0
- data/ext/pg_query/src_backend_utils_adt_format_type.c +136 -0
- data/ext/pg_query/src_backend_utils_adt_ruleutils.c +1683 -0
- data/ext/pg_query/src_backend_utils_error_assert.c +74 -0
- data/ext/pg_query/src_backend_utils_error_elog.c +1748 -0
- data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +570 -0
- data/ext/pg_query/src_backend_utils_hash_dynahash.c +1086 -0
- data/ext/pg_query/src_backend_utils_init_globals.c +168 -0
- data/ext/pg_query/src_backend_utils_mb_mbutils.c +839 -0
- data/ext/pg_query/src_backend_utils_misc_guc.c +1831 -0
- data/ext/pg_query/src_backend_utils_mmgr_aset.c +1560 -0
- data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +1006 -0
- data/ext/pg_query/src_common_encnames.c +158 -0
- data/ext/pg_query/src_common_keywords.c +39 -0
- data/ext/pg_query/src_common_kwlist_d.h +1081 -0
- data/ext/pg_query/src_common_kwlookup.c +91 -0
- data/ext/pg_query/src_common_psprintf.c +158 -0
- data/ext/pg_query/src_common_string.c +86 -0
- data/ext/pg_query/src_common_stringinfo.c +336 -0
- data/ext/pg_query/src_common_wchar.c +1651 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +1133 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +877 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +6533 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +107 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +123 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +671 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +255 -0
- data/ext/pg_query/src_port_erand48.c +127 -0
- data/ext/pg_query/src_port_pg_bitutils.c +246 -0
- data/ext/pg_query/src_port_pgsleep.c +69 -0
- data/ext/pg_query/src_port_pgstrcasecmp.c +83 -0
- data/ext/pg_query/src_port_qsort.c +240 -0
- data/ext/pg_query/src_port_random.c +31 -0
- data/ext/pg_query/src_port_snprintf.c +1449 -0
- data/ext/pg_query/src_port_strerror.c +324 -0
- data/ext/pg_query/src_port_strnlen.c +39 -0
- data/ext/pg_query/xxhash.c +43 -0
- data/lib/pg_query.rb +7 -4
- data/lib/pg_query/constants.rb +21 -0
- data/lib/pg_query/deparse.rb +15 -1581
- data/lib/pg_query/filter_columns.rb +88 -85
- data/lib/pg_query/fingerprint.rb +122 -87
- data/lib/pg_query/json_field_names.rb +1402 -0
- data/lib/pg_query/node.rb +31 -0
- data/lib/pg_query/param_refs.rb +42 -37
- data/lib/pg_query/parse.rb +220 -203
- data/lib/pg_query/parse_error.rb +1 -1
- data/lib/pg_query/pg_query_pb.rb +3211 -0
- data/lib/pg_query/scan.rb +23 -0
- data/lib/pg_query/treewalker.rb +24 -40
- data/lib/pg_query/truncate.rb +71 -42
- data/lib/pg_query/version.rb +2 -2
- metadata +472 -11
- data/ext/pg_query/pg_query_ruby.h +0 -10
- data/lib/pg_query/deep_dup.rb +0 -16
- data/lib/pg_query/deparse/alter_table.rb +0 -42
- data/lib/pg_query/deparse/interval.rb +0 -105
- data/lib/pg_query/deparse/keywords.rb +0 -159
- data/lib/pg_query/deparse/rename.rb +0 -41
- data/lib/pg_query/legacy_parsetree.rb +0 -109
- data/lib/pg_query/node_types.rb +0 -296
@@ -0,0 +1,74 @@
|
|
1
|
+
/*--------------------------------------------------------------------
|
2
|
+
* Symbols referenced in this file:
|
3
|
+
* - ExceptionalCondition
|
4
|
+
*--------------------------------------------------------------------
|
5
|
+
*/
|
6
|
+
|
7
|
+
/*-------------------------------------------------------------------------
|
8
|
+
*
|
9
|
+
* assert.c
|
10
|
+
* Assert code.
|
11
|
+
*
|
12
|
+
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
13
|
+
* Portions Copyright (c) 1994, Regents of the University of California
|
14
|
+
*
|
15
|
+
*
|
16
|
+
* IDENTIFICATION
|
17
|
+
* src/backend/utils/error/assert.c
|
18
|
+
*
|
19
|
+
* NOTE
|
20
|
+
* This should eventually work with elog()
|
21
|
+
*
|
22
|
+
*-------------------------------------------------------------------------
|
23
|
+
*/
|
24
|
+
#include "postgres.h"
|
25
|
+
|
26
|
+
#include <unistd.h>
|
27
|
+
#ifdef HAVE_EXECINFO_H
|
28
|
+
#include <execinfo.h>
|
29
|
+
#endif
|
30
|
+
|
31
|
+
/*
|
32
|
+
* ExceptionalCondition - Handles the failure of an Assert()
|
33
|
+
*/
|
34
|
+
void
|
35
|
+
ExceptionalCondition(const char *conditionName,
|
36
|
+
const char *errorType,
|
37
|
+
const char *fileName,
|
38
|
+
int lineNumber)
|
39
|
+
{
|
40
|
+
if (!PointerIsValid(conditionName)
|
41
|
+
|| !PointerIsValid(fileName)
|
42
|
+
|| !PointerIsValid(errorType))
|
43
|
+
write_stderr("TRAP: ExceptionalCondition: bad arguments\n");
|
44
|
+
else
|
45
|
+
{
|
46
|
+
write_stderr("TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
|
47
|
+
errorType, conditionName,
|
48
|
+
fileName, lineNumber);
|
49
|
+
}
|
50
|
+
|
51
|
+
/* Usually this shouldn't be needed, but make sure the msg went out */
|
52
|
+
fflush(stderr);
|
53
|
+
|
54
|
+
#ifdef HAVE_BACKTRACE_SYMBOLS
|
55
|
+
{
|
56
|
+
void *buf[100];
|
57
|
+
int nframes;
|
58
|
+
|
59
|
+
nframes = backtrace(buf, lengthof(buf));
|
60
|
+
backtrace_symbols_fd(buf, nframes, fileno(stderr));
|
61
|
+
}
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#ifdef SLEEP_ON_ASSERT
|
65
|
+
|
66
|
+
/*
|
67
|
+
* It would be nice to use pg_usleep() here, but only does 2000 sec or 33
|
68
|
+
* minutes, which seems too short.
|
69
|
+
*/
|
70
|
+
sleep(1000000);
|
71
|
+
#endif
|
72
|
+
|
73
|
+
abort();
|
74
|
+
}
|
@@ -0,0 +1,1748 @@
|
|
1
|
+
/*--------------------------------------------------------------------
|
2
|
+
* Symbols referenced in this file:
|
3
|
+
* - errstart
|
4
|
+
* - PG_exception_stack
|
5
|
+
* - write_stderr
|
6
|
+
* - err_gettext
|
7
|
+
* - in_error_recursion_trouble
|
8
|
+
* - error_context_stack
|
9
|
+
* - errordata_stack_depth
|
10
|
+
* - errordata
|
11
|
+
* - is_log_level_output
|
12
|
+
* - recursion_depth
|
13
|
+
* - errmsg_internal
|
14
|
+
* - errcode
|
15
|
+
* - errmsg
|
16
|
+
* - errdetail
|
17
|
+
* - errfinish
|
18
|
+
* - pg_re_throw
|
19
|
+
* - EmitErrorReport
|
20
|
+
* - emit_log_hook
|
21
|
+
* - send_message_to_server_log
|
22
|
+
* - send_message_to_frontend
|
23
|
+
* - matches_backtrace_functions
|
24
|
+
* - set_backtrace
|
25
|
+
* - geterrcode
|
26
|
+
* - errhint
|
27
|
+
* - errposition
|
28
|
+
* - internalerrposition
|
29
|
+
* - internalerrquery
|
30
|
+
* - geterrposition
|
31
|
+
* - getinternalerrposition
|
32
|
+
* - set_errcontext_domain
|
33
|
+
* - errcontext_msg
|
34
|
+
* - CopyErrorData
|
35
|
+
* - FlushErrorState
|
36
|
+
*--------------------------------------------------------------------
|
37
|
+
*/
|
38
|
+
|
39
|
+
/*-------------------------------------------------------------------------
|
40
|
+
*
|
41
|
+
* elog.c
|
42
|
+
* error logging and reporting
|
43
|
+
*
|
44
|
+
* Because of the extremely high rate at which log messages can be generated,
|
45
|
+
* we need to be mindful of the performance cost of obtaining any information
|
46
|
+
* that may be logged. Also, it's important to keep in mind that this code may
|
47
|
+
* get called from within an aborted transaction, in which case operations
|
48
|
+
* such as syscache lookups are unsafe.
|
49
|
+
*
|
50
|
+
* Some notes about recursion and errors during error processing:
|
51
|
+
*
|
52
|
+
* We need to be robust about recursive-error scenarios --- for example,
|
53
|
+
* if we run out of memory, it's important to be able to report that fact.
|
54
|
+
* There are a number of considerations that go into this.
|
55
|
+
*
|
56
|
+
* First, distinguish between re-entrant use and actual recursion. It
|
57
|
+
* is possible for an error or warning message to be emitted while the
|
58
|
+
* parameters for an error message are being computed. In this case
|
59
|
+
* errstart has been called for the outer message, and some field values
|
60
|
+
* may have already been saved, but we are not actually recursing. We handle
|
61
|
+
* this by providing a (small) stack of ErrorData records. The inner message
|
62
|
+
* can be computed and sent without disturbing the state of the outer message.
|
63
|
+
* (If the inner message is actually an error, this isn't very interesting
|
64
|
+
* because control won't come back to the outer message generator ... but
|
65
|
+
* if the inner message is only debug or log data, this is critical.)
|
66
|
+
*
|
67
|
+
* Second, actual recursion will occur if an error is reported by one of
|
68
|
+
* the elog.c routines or something they call. By far the most probable
|
69
|
+
* scenario of this sort is "out of memory"; and it's also the nastiest
|
70
|
+
* to handle because we'd likely also run out of memory while trying to
|
71
|
+
* report this error! Our escape hatch for this case is to reset the
|
72
|
+
* ErrorContext to empty before trying to process the inner error. Since
|
73
|
+
* ErrorContext is guaranteed to have at least 8K of space in it (see mcxt.c),
|
74
|
+
* we should be able to process an "out of memory" message successfully.
|
75
|
+
* Since we lose the prior error state due to the reset, we won't be able
|
76
|
+
* to return to processing the original error, but we wouldn't have anyway.
|
77
|
+
* (NOTE: the escape hatch is not used for recursive situations where the
|
78
|
+
* inner message is of less than ERROR severity; in that case we just
|
79
|
+
* try to process it and return normally. Usually this will work, but if
|
80
|
+
* it ends up in infinite recursion, we will PANIC due to error stack
|
81
|
+
* overflow.)
|
82
|
+
*
|
83
|
+
*
|
84
|
+
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
85
|
+
* Portions Copyright (c) 1994, Regents of the University of California
|
86
|
+
*
|
87
|
+
*
|
88
|
+
* IDENTIFICATION
|
89
|
+
* src/backend/utils/error/elog.c
|
90
|
+
*
|
91
|
+
*-------------------------------------------------------------------------
|
92
|
+
*/
|
93
|
+
#include "postgres.h"
|
94
|
+
|
95
|
+
#include <fcntl.h>
|
96
|
+
#include <time.h>
|
97
|
+
#include <unistd.h>
|
98
|
+
#include <signal.h>
|
99
|
+
#include <ctype.h>
|
100
|
+
#ifdef HAVE_SYSLOG
|
101
|
+
#include <syslog.h>
|
102
|
+
#endif
|
103
|
+
#ifdef HAVE_EXECINFO_H
|
104
|
+
#include <execinfo.h>
|
105
|
+
#endif
|
106
|
+
|
107
|
+
#include "access/transam.h"
|
108
|
+
#include "access/xact.h"
|
109
|
+
#include "libpq/libpq.h"
|
110
|
+
#include "libpq/pqformat.h"
|
111
|
+
#include "mb/pg_wchar.h"
|
112
|
+
#include "miscadmin.h"
|
113
|
+
#include "postmaster/bgworker.h"
|
114
|
+
#include "postmaster/postmaster.h"
|
115
|
+
#include "postmaster/syslogger.h"
|
116
|
+
#include "storage/ipc.h"
|
117
|
+
#include "storage/proc.h"
|
118
|
+
#include "tcop/tcopprot.h"
|
119
|
+
#include "utils/guc.h"
|
120
|
+
#include "utils/memutils.h"
|
121
|
+
#include "utils/ps_status.h"
|
122
|
+
|
123
|
+
|
124
|
+
/* In this module, access gettext() via err_gettext() */
|
125
|
+
#undef _
|
126
|
+
#define _(x) err_gettext(x)
|
127
|
+
|
128
|
+
|
129
|
+
/* Global variables */
|
130
|
+
__thread ErrorContextCallback *error_context_stack = NULL;
|
131
|
+
|
132
|
+
|
133
|
+
__thread sigjmp_buf *PG_exception_stack = NULL;
|
134
|
+
|
135
|
+
|
136
|
+
extern bool redirection_done;
|
137
|
+
|
138
|
+
/*
|
139
|
+
* Hook for intercepting messages before they are sent to the server log.
|
140
|
+
* Note that the hook will not get called for messages that are suppressed
|
141
|
+
* by log_min_messages. Also note that logging hooks implemented in preload
|
142
|
+
* libraries will miss any log messages that are generated before the
|
143
|
+
* library is loaded.
|
144
|
+
*/
|
145
|
+
__thread emit_log_hook_type emit_log_hook = NULL;
|
146
|
+
|
147
|
+
|
148
|
+
/* GUC parameters */
|
149
|
+
|
150
|
+
/* format for extra log line info */
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
#ifdef HAVE_SYSLOG
|
157
|
+
|
158
|
+
/*
|
159
|
+
* Max string length to send to syslog(). Note that this doesn't count the
|
160
|
+
* sequence-number prefix we add, and of course it doesn't count the prefix
|
161
|
+
* added by syslog itself. Solaris and sysklogd truncate the final message
|
162
|
+
* at 1024 bytes, so this value leaves 124 bytes for those prefixes. (Most
|
163
|
+
* other syslog implementations seem to have limits of 2KB or so.)
|
164
|
+
*/
|
165
|
+
#ifndef PG_SYSLOG_LIMIT
|
166
|
+
#define PG_SYSLOG_LIMIT 900
|
167
|
+
#endif
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
|
172
|
+
|
173
|
+
static void write_syslog(int level, const char *line);
|
174
|
+
#endif
|
175
|
+
|
176
|
+
#ifdef WIN32
|
177
|
+
extern char *event_source;
|
178
|
+
|
179
|
+
static void write_eventlog(int level, const char *line, int len);
|
180
|
+
#endif
|
181
|
+
|
182
|
+
/* We provide a small stack of ErrorData records for re-entrant cases */
|
183
|
+
#define ERRORDATA_STACK_SIZE 5
|
184
|
+
|
185
|
+
static __thread ErrorData errordata[ERRORDATA_STACK_SIZE];
|
186
|
+
|
187
|
+
|
188
|
+
static __thread int errordata_stack_depth = -1;
|
189
|
+
/* index of topmost active frame */
|
190
|
+
|
191
|
+
static __thread int recursion_depth = 0;
|
192
|
+
/* to detect actual recursion */
|
193
|
+
|
194
|
+
/*
|
195
|
+
* Saved timeval and buffers for formatted timestamps that might be used by
|
196
|
+
* both log_line_prefix and csv logs.
|
197
|
+
*/
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
#define FORMATTED_TS_LEN 128
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
/* Macro for checking errordata_stack_depth is reasonable */
|
207
|
+
#define CHECK_STACK_DEPTH() \
|
208
|
+
do { \
|
209
|
+
if (errordata_stack_depth < 0) \
|
210
|
+
{ \
|
211
|
+
errordata_stack_depth = -1; \
|
212
|
+
ereport(ERROR, (errmsg_internal("errstart was not called"))); \
|
213
|
+
} \
|
214
|
+
} while (0)
|
215
|
+
|
216
|
+
|
217
|
+
static const char *err_gettext(const char *str) pg_attribute_format_arg(1);
|
218
|
+
static pg_noinline void set_backtrace(ErrorData *edata, int num_skip);
|
219
|
+
static void set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str);
|
220
|
+
static void write_console(const char *line, int len);
|
221
|
+
static void setup_formatted_log_time(void);
|
222
|
+
static void setup_formatted_start_time(void);
|
223
|
+
static const char *process_log_prefix_padding(const char *p, int *padding);
|
224
|
+
static void log_line_prefix(StringInfo buf, ErrorData *edata);
|
225
|
+
static void write_csvlog(ErrorData *edata);
|
226
|
+
static void send_message_to_server_log(ErrorData *edata);
|
227
|
+
static void write_pipe_chunks(char *data, int len, int dest);
|
228
|
+
static void send_message_to_frontend(ErrorData *edata);
|
229
|
+
static const char *error_severity(int elevel);
|
230
|
+
static void append_with_tabs(StringInfo buf, const char *str);
|
231
|
+
static bool is_log_level_output(int elevel, int log_min_level);
|
232
|
+
|
233
|
+
|
234
|
+
/*
|
235
|
+
* in_error_recursion_trouble --- are we at risk of infinite error recursion?
|
236
|
+
*
|
237
|
+
* This function exists to provide common control of various fallback steps
|
238
|
+
* that we take if we think we are facing infinite error recursion. See the
|
239
|
+
* callers for details.
|
240
|
+
*/
|
241
|
+
bool
|
242
|
+
in_error_recursion_trouble(void)
|
243
|
+
{
|
244
|
+
/* Pull the plug if recurse more than once */
|
245
|
+
return (recursion_depth > 2);
|
246
|
+
}
|
247
|
+
|
248
|
+
/*
|
249
|
+
* One of those fallback steps is to stop trying to localize the error
|
250
|
+
* message, since there's a significant probability that that's exactly
|
251
|
+
* what's causing the recursion.
|
252
|
+
*/
|
253
|
+
static inline const char *
|
254
|
+
err_gettext(const char *str)
|
255
|
+
{
|
256
|
+
#ifdef ENABLE_NLS
|
257
|
+
if (in_error_recursion_trouble())
|
258
|
+
return str;
|
259
|
+
else
|
260
|
+
return gettext(str);
|
261
|
+
#else
|
262
|
+
return str;
|
263
|
+
#endif
|
264
|
+
}
|
265
|
+
|
266
|
+
|
267
|
+
/*
|
268
|
+
* errstart --- begin an error-reporting cycle
|
269
|
+
*
|
270
|
+
* Create and initialize error stack entry. Subsequently, errmsg() and
|
271
|
+
* perhaps other routines will be called to further populate the stack entry.
|
272
|
+
* Finally, errfinish() will be called to actually process the error report.
|
273
|
+
*
|
274
|
+
* Returns true in normal case. Returns false to short-circuit the error
|
275
|
+
* report (if it's a warning or lower and not to be reported anywhere).
|
276
|
+
*/
|
277
|
+
bool
|
278
|
+
errstart(int elevel, const char *domain)
|
279
|
+
{
|
280
|
+
ErrorData *edata;
|
281
|
+
bool output_to_server;
|
282
|
+
bool output_to_client = false;
|
283
|
+
int i;
|
284
|
+
|
285
|
+
/*
|
286
|
+
* Check some cases in which we want to promote an error into a more
|
287
|
+
* severe error. None of this logic applies for non-error messages.
|
288
|
+
*/
|
289
|
+
if (elevel >= ERROR)
|
290
|
+
{
|
291
|
+
/*
|
292
|
+
* If we are inside a critical section, all errors become PANIC
|
293
|
+
* errors. See miscadmin.h.
|
294
|
+
*/
|
295
|
+
if (CritSectionCount > 0)
|
296
|
+
elevel = PANIC;
|
297
|
+
|
298
|
+
/*
|
299
|
+
* Check reasons for treating ERROR as FATAL:
|
300
|
+
*
|
301
|
+
* 1. we have no handler to pass the error to (implies we are in the
|
302
|
+
* postmaster or in backend startup).
|
303
|
+
*
|
304
|
+
* 2. ExitOnAnyError mode switch is set (initdb uses this).
|
305
|
+
*
|
306
|
+
* 3. the error occurred after proc_exit has begun to run. (It's
|
307
|
+
* proc_exit's responsibility to see that this doesn't turn into
|
308
|
+
* infinite recursion!)
|
309
|
+
*/
|
310
|
+
if (elevel == ERROR)
|
311
|
+
{
|
312
|
+
if (PG_exception_stack == NULL ||
|
313
|
+
ExitOnAnyError ||
|
314
|
+
proc_exit_inprogress)
|
315
|
+
elevel = FATAL;
|
316
|
+
}
|
317
|
+
|
318
|
+
/*
|
319
|
+
* If the error level is ERROR or more, errfinish is not going to
|
320
|
+
* return to caller; therefore, if there is any stacked error already
|
321
|
+
* in progress it will be lost. This is more or less okay, except we
|
322
|
+
* do not want to have a FATAL or PANIC error downgraded because the
|
323
|
+
* reporting process was interrupted by a lower-grade error. So check
|
324
|
+
* the stack and make sure we panic if panic is warranted.
|
325
|
+
*/
|
326
|
+
for (i = 0; i <= errordata_stack_depth; i++)
|
327
|
+
elevel = Max(elevel, errordata[i].elevel);
|
328
|
+
}
|
329
|
+
|
330
|
+
/*
|
331
|
+
* Now decide whether we need to process this report at all; if it's
|
332
|
+
* warning or less and not enabled for logging, just return false without
|
333
|
+
* starting up any error logging machinery.
|
334
|
+
*/
|
335
|
+
|
336
|
+
/* Determine whether message is enabled for server log output */
|
337
|
+
output_to_server = is_log_level_output(elevel, log_min_messages);
|
338
|
+
|
339
|
+
/* Determine whether message is enabled for client output */
|
340
|
+
if (whereToSendOutput == DestRemote && elevel != LOG_SERVER_ONLY)
|
341
|
+
{
|
342
|
+
/*
|
343
|
+
* client_min_messages is honored only after we complete the
|
344
|
+
* authentication handshake. This is required both for security
|
345
|
+
* reasons and because many clients can't handle NOTICE messages
|
346
|
+
* during authentication.
|
347
|
+
*/
|
348
|
+
if (ClientAuthInProgress)
|
349
|
+
output_to_client = (elevel >= ERROR);
|
350
|
+
else
|
351
|
+
output_to_client = (elevel >= client_min_messages ||
|
352
|
+
elevel == INFO);
|
353
|
+
}
|
354
|
+
|
355
|
+
/* Skip processing effort if non-error message will not be output */
|
356
|
+
if (elevel < ERROR && !output_to_server && !output_to_client)
|
357
|
+
return false;
|
358
|
+
|
359
|
+
/*
|
360
|
+
* We need to do some actual work. Make sure that memory context
|
361
|
+
* initialization has finished, else we can't do anything useful.
|
362
|
+
*/
|
363
|
+
if (ErrorContext == NULL)
|
364
|
+
{
|
365
|
+
/* Oops, hard crash time; very little we can do safely here */
|
366
|
+
write_stderr("error occurred before error message processing is available\n");
|
367
|
+
exit(2);
|
368
|
+
}
|
369
|
+
|
370
|
+
/*
|
371
|
+
* Okay, crank up a stack entry to store the info in.
|
372
|
+
*/
|
373
|
+
|
374
|
+
if (recursion_depth++ > 0 && elevel >= ERROR)
|
375
|
+
{
|
376
|
+
/*
|
377
|
+
* Oops, error during error processing. Clear ErrorContext as
|
378
|
+
* discussed at top of file. We will not return to the original
|
379
|
+
* error's reporter or handler, so we don't need it.
|
380
|
+
*/
|
381
|
+
MemoryContextReset(ErrorContext);
|
382
|
+
|
383
|
+
/*
|
384
|
+
* Infinite error recursion might be due to something broken in a
|
385
|
+
* context traceback routine. Abandon them too. We also abandon
|
386
|
+
* attempting to print the error statement (which, if long, could
|
387
|
+
* itself be the source of the recursive failure).
|
388
|
+
*/
|
389
|
+
if (in_error_recursion_trouble())
|
390
|
+
{
|
391
|
+
error_context_stack = NULL;
|
392
|
+
debug_query_string = NULL;
|
393
|
+
}
|
394
|
+
}
|
395
|
+
if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)
|
396
|
+
{
|
397
|
+
/*
|
398
|
+
* Wups, stack not big enough. We treat this as a PANIC condition
|
399
|
+
* because it suggests an infinite loop of errors during error
|
400
|
+
* recovery.
|
401
|
+
*/
|
402
|
+
errordata_stack_depth = -1; /* make room on stack */
|
403
|
+
ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
|
404
|
+
}
|
405
|
+
|
406
|
+
/* Initialize data for this error frame */
|
407
|
+
edata = &errordata[errordata_stack_depth];
|
408
|
+
MemSet(edata, 0, sizeof(ErrorData));
|
409
|
+
edata->elevel = elevel;
|
410
|
+
edata->output_to_server = output_to_server;
|
411
|
+
edata->output_to_client = output_to_client;
|
412
|
+
/* the default text domain is the backend's */
|
413
|
+
edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres");
|
414
|
+
/* initialize context_domain the same way (see set_errcontext_domain()) */
|
415
|
+
edata->context_domain = edata->domain;
|
416
|
+
/* Select default errcode based on elevel */
|
417
|
+
if (elevel >= ERROR)
|
418
|
+
edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
|
419
|
+
else if (elevel == WARNING)
|
420
|
+
edata->sqlerrcode = ERRCODE_WARNING;
|
421
|
+
else
|
422
|
+
edata->sqlerrcode = ERRCODE_SUCCESSFUL_COMPLETION;
|
423
|
+
/* errno is saved here so that error parameter eval can't change it */
|
424
|
+
edata->saved_errno = errno;
|
425
|
+
|
426
|
+
/*
|
427
|
+
* Any allocations for this error state level should go into ErrorContext
|
428
|
+
*/
|
429
|
+
edata->assoc_context = ErrorContext;
|
430
|
+
|
431
|
+
recursion_depth--;
|
432
|
+
return true;
|
433
|
+
}
|
434
|
+
|
435
|
+
/*
|
436
|
+
* Checks whether the given funcname matches backtrace_functions; see
|
437
|
+
* check_backtrace_functions.
|
438
|
+
*/
|
439
|
+
static bool
|
440
|
+
matches_backtrace_functions(const char *funcname)
|
441
|
+
{
|
442
|
+
char *p;
|
443
|
+
|
444
|
+
if (!backtrace_symbol_list || funcname == NULL || funcname[0] == '\0')
|
445
|
+
return false;
|
446
|
+
|
447
|
+
p = backtrace_symbol_list;
|
448
|
+
for (;;)
|
449
|
+
{
|
450
|
+
if (*p == '\0') /* end of backtrace_symbol_list */
|
451
|
+
break;
|
452
|
+
|
453
|
+
if (strcmp(funcname, p) == 0)
|
454
|
+
return true;
|
455
|
+
p += strlen(p) + 1;
|
456
|
+
}
|
457
|
+
|
458
|
+
return false;
|
459
|
+
}
|
460
|
+
|
461
|
+
/*
|
462
|
+
* errfinish --- end an error-reporting cycle
|
463
|
+
*
|
464
|
+
* Produce the appropriate error report(s) and pop the error stack.
|
465
|
+
*
|
466
|
+
* If elevel, as passed to errstart(), is ERROR or worse, control does not
|
467
|
+
* return to the caller. See elog.h for the error level definitions.
|
468
|
+
*/
|
469
|
+
void
|
470
|
+
errfinish(const char *filename, int lineno, const char *funcname)
|
471
|
+
{
|
472
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
473
|
+
int elevel;
|
474
|
+
MemoryContext oldcontext;
|
475
|
+
ErrorContextCallback *econtext;
|
476
|
+
|
477
|
+
recursion_depth++;
|
478
|
+
CHECK_STACK_DEPTH();
|
479
|
+
|
480
|
+
/* Save the last few bits of error state into the stack entry */
|
481
|
+
if (filename)
|
482
|
+
{
|
483
|
+
const char *slash;
|
484
|
+
|
485
|
+
/* keep only base name, useful especially for vpath builds */
|
486
|
+
slash = strrchr(filename, '/');
|
487
|
+
if (slash)
|
488
|
+
filename = slash + 1;
|
489
|
+
}
|
490
|
+
|
491
|
+
edata->filename = filename;
|
492
|
+
edata->lineno = lineno;
|
493
|
+
edata->funcname = funcname;
|
494
|
+
|
495
|
+
elevel = edata->elevel;
|
496
|
+
|
497
|
+
/*
|
498
|
+
* Do processing in ErrorContext, which we hope has enough reserved space
|
499
|
+
* to report an error.
|
500
|
+
*/
|
501
|
+
oldcontext = MemoryContextSwitchTo(ErrorContext);
|
502
|
+
|
503
|
+
if (!edata->backtrace &&
|
504
|
+
edata->funcname &&
|
505
|
+
backtrace_functions &&
|
506
|
+
matches_backtrace_functions(edata->funcname))
|
507
|
+
set_backtrace(edata, 2);
|
508
|
+
|
509
|
+
/*
|
510
|
+
* Call any context callback functions. Errors occurring in callback
|
511
|
+
* functions will be treated as recursive errors --- this ensures we will
|
512
|
+
* avoid infinite recursion (see errstart).
|
513
|
+
*/
|
514
|
+
for (econtext = error_context_stack;
|
515
|
+
econtext != NULL;
|
516
|
+
econtext = econtext->previous)
|
517
|
+
econtext->callback(econtext->arg);
|
518
|
+
|
519
|
+
/*
|
520
|
+
* If ERROR (not more nor less) we pass it off to the current handler.
|
521
|
+
* Printing it and popping the stack is the responsibility of the handler.
|
522
|
+
*/
|
523
|
+
if (elevel == ERROR)
|
524
|
+
{
|
525
|
+
/*
|
526
|
+
* We do some minimal cleanup before longjmp'ing so that handlers can
|
527
|
+
* execute in a reasonably sane state.
|
528
|
+
*
|
529
|
+
* Reset InterruptHoldoffCount in case we ereport'd from inside an
|
530
|
+
* interrupt holdoff section. (We assume here that no handler will
|
531
|
+
* itself be inside a holdoff section. If necessary, such a handler
|
532
|
+
* could save and restore InterruptHoldoffCount for itself, but this
|
533
|
+
* should make life easier for most.)
|
534
|
+
*/
|
535
|
+
InterruptHoldoffCount = 0;
|
536
|
+
QueryCancelHoldoffCount = 0;
|
537
|
+
|
538
|
+
CritSectionCount = 0; /* should be unnecessary, but... */
|
539
|
+
|
540
|
+
/*
|
541
|
+
* Note that we leave CurrentMemoryContext set to ErrorContext. The
|
542
|
+
* handler should reset it to something else soon.
|
543
|
+
*/
|
544
|
+
|
545
|
+
recursion_depth--;
|
546
|
+
PG_RE_THROW();
|
547
|
+
}
|
548
|
+
|
549
|
+
/*
|
550
|
+
* If we are doing FATAL or PANIC, abort any old-style COPY OUT in
|
551
|
+
* progress, so that we can report the message before dying. (Without
|
552
|
+
* this, pq_putmessage will refuse to send the message at all, which is
|
553
|
+
* what we want for NOTICE messages, but not for fatal exits.) This hack
|
554
|
+
* is necessary because of poor design of old-style copy protocol.
|
555
|
+
*/
|
556
|
+
if (elevel >= FATAL && whereToSendOutput == DestRemote)
|
557
|
+
pq_endcopyout(true);
|
558
|
+
|
559
|
+
/* Emit the message to the right places */
|
560
|
+
EmitErrorReport();
|
561
|
+
|
562
|
+
/* Now free up subsidiary data attached to stack entry, and release it */
|
563
|
+
if (edata->message)
|
564
|
+
pfree(edata->message);
|
565
|
+
if (edata->detail)
|
566
|
+
pfree(edata->detail);
|
567
|
+
if (edata->detail_log)
|
568
|
+
pfree(edata->detail_log);
|
569
|
+
if (edata->hint)
|
570
|
+
pfree(edata->hint);
|
571
|
+
if (edata->context)
|
572
|
+
pfree(edata->context);
|
573
|
+
if (edata->backtrace)
|
574
|
+
pfree(edata->backtrace);
|
575
|
+
if (edata->schema_name)
|
576
|
+
pfree(edata->schema_name);
|
577
|
+
if (edata->table_name)
|
578
|
+
pfree(edata->table_name);
|
579
|
+
if (edata->column_name)
|
580
|
+
pfree(edata->column_name);
|
581
|
+
if (edata->datatype_name)
|
582
|
+
pfree(edata->datatype_name);
|
583
|
+
if (edata->constraint_name)
|
584
|
+
pfree(edata->constraint_name);
|
585
|
+
if (edata->internalquery)
|
586
|
+
pfree(edata->internalquery);
|
587
|
+
|
588
|
+
errordata_stack_depth--;
|
589
|
+
|
590
|
+
/* Exit error-handling context */
|
591
|
+
MemoryContextSwitchTo(oldcontext);
|
592
|
+
recursion_depth--;
|
593
|
+
|
594
|
+
/*
|
595
|
+
* Perform error recovery action as specified by elevel.
|
596
|
+
*/
|
597
|
+
if (elevel == FATAL)
|
598
|
+
{
|
599
|
+
/*
|
600
|
+
* For a FATAL error, we let proc_exit clean up and exit.
|
601
|
+
*
|
602
|
+
* If we just reported a startup failure, the client will disconnect
|
603
|
+
* on receiving it, so don't send any more to the client.
|
604
|
+
*/
|
605
|
+
if (PG_exception_stack == NULL && whereToSendOutput == DestRemote)
|
606
|
+
whereToSendOutput = DestNone;
|
607
|
+
|
608
|
+
/*
|
609
|
+
* fflush here is just to improve the odds that we get to see the
|
610
|
+
* error message, in case things are so hosed that proc_exit crashes.
|
611
|
+
* Any other code you might be tempted to add here should probably be
|
612
|
+
* in an on_proc_exit or on_shmem_exit callback instead.
|
613
|
+
*/
|
614
|
+
fflush(stdout);
|
615
|
+
fflush(stderr);
|
616
|
+
|
617
|
+
/*
|
618
|
+
* Do normal process-exit cleanup, then return exit code 1 to indicate
|
619
|
+
* FATAL termination. The postmaster may or may not consider this
|
620
|
+
* worthy of panic, depending on which subprocess returns it.
|
621
|
+
*/
|
622
|
+
proc_exit(1);
|
623
|
+
}
|
624
|
+
|
625
|
+
if (elevel >= PANIC)
|
626
|
+
{
|
627
|
+
/*
|
628
|
+
* Serious crash time. Postmaster will observe SIGABRT process exit
|
629
|
+
* status and kill the other backends too.
|
630
|
+
*
|
631
|
+
* XXX: what if we are *in* the postmaster? abort() won't kill our
|
632
|
+
* children...
|
633
|
+
*/
|
634
|
+
fflush(stdout);
|
635
|
+
fflush(stderr);
|
636
|
+
abort();
|
637
|
+
}
|
638
|
+
|
639
|
+
/*
|
640
|
+
* Check for cancel/die interrupt first --- this is so that the user can
|
641
|
+
* stop a query emitting tons of notice or warning messages, even if it's
|
642
|
+
* in a loop that otherwise fails to check for interrupts.
|
643
|
+
*/
|
644
|
+
CHECK_FOR_INTERRUPTS();
|
645
|
+
}
|
646
|
+
|
647
|
+
|
648
|
+
/*
|
649
|
+
* errcode --- add SQLSTATE error code to the current error
|
650
|
+
*
|
651
|
+
* The code is expected to be represented as per MAKE_SQLSTATE().
|
652
|
+
*/
|
653
|
+
int
|
654
|
+
errcode(int sqlerrcode)
|
655
|
+
{
|
656
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
657
|
+
|
658
|
+
/* we don't bother incrementing recursion_depth */
|
659
|
+
CHECK_STACK_DEPTH();
|
660
|
+
|
661
|
+
edata->sqlerrcode = sqlerrcode;
|
662
|
+
|
663
|
+
return 0; /* return value does not matter */
|
664
|
+
}
|
665
|
+
|
666
|
+
|
667
|
+
/*
|
668
|
+
* errcode_for_file_access --- add SQLSTATE error code to the current error
|
669
|
+
*
|
670
|
+
* The SQLSTATE code is chosen based on the saved errno value. We assume
|
671
|
+
* that the failing operation was some type of disk file access.
|
672
|
+
*
|
673
|
+
* NOTE: the primary error message string should generally include %m
|
674
|
+
* when this is used.
|
675
|
+
*/
|
676
|
+
#ifdef EROFS
|
677
|
+
#endif
|
678
|
+
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
|
679
|
+
#endif
|
680
|
+
|
681
|
+
/*
|
682
|
+
* errcode_for_socket_access --- add SQLSTATE error code to the current error
|
683
|
+
*
|
684
|
+
* The SQLSTATE code is chosen based on the saved errno value. We assume
|
685
|
+
* that the failing operation was some type of socket access.
|
686
|
+
*
|
687
|
+
* NOTE: the primary error message string should generally include %m
|
688
|
+
* when this is used.
|
689
|
+
*/
|
690
|
+
#ifdef ECONNRESET
|
691
|
+
#endif
|
692
|
+
|
693
|
+
|
694
|
+
/*
|
695
|
+
* This macro handles expansion of a format string and associated parameters;
|
696
|
+
* it's common code for errmsg(), errdetail(), etc. Must be called inside
|
697
|
+
* a routine that is declared like "const char *fmt, ..." and has an edata
|
698
|
+
* pointer set up. The message is assigned to edata->targetfield, or
|
699
|
+
* appended to it if appendval is true. The message is subject to translation
|
700
|
+
* if translateit is true.
|
701
|
+
*
|
702
|
+
* Note: we pstrdup the buffer rather than just transferring its storage
|
703
|
+
* to the edata field because the buffer might be considerably larger than
|
704
|
+
* really necessary.
|
705
|
+
*/
|
706
|
+
#define EVALUATE_MESSAGE(domain, targetfield, appendval, translateit) \
|
707
|
+
{ \
|
708
|
+
StringInfoData buf; \
|
709
|
+
/* Internationalize the error format string */ \
|
710
|
+
if ((translateit) && !in_error_recursion_trouble()) \
|
711
|
+
fmt = dgettext((domain), fmt); \
|
712
|
+
initStringInfo(&buf); \
|
713
|
+
if ((appendval) && edata->targetfield) { \
|
714
|
+
appendStringInfoString(&buf, edata->targetfield); \
|
715
|
+
appendStringInfoChar(&buf, '\n'); \
|
716
|
+
} \
|
717
|
+
/* Generate actual output --- have to use appendStringInfoVA */ \
|
718
|
+
for (;;) \
|
719
|
+
{ \
|
720
|
+
va_list args; \
|
721
|
+
int needed; \
|
722
|
+
errno = edata->saved_errno; \
|
723
|
+
va_start(args, fmt); \
|
724
|
+
needed = appendStringInfoVA(&buf, fmt, args); \
|
725
|
+
va_end(args); \
|
726
|
+
if (needed == 0) \
|
727
|
+
break; \
|
728
|
+
enlargeStringInfo(&buf, needed); \
|
729
|
+
} \
|
730
|
+
/* Save the completed message into the stack item */ \
|
731
|
+
if (edata->targetfield) \
|
732
|
+
pfree(edata->targetfield); \
|
733
|
+
edata->targetfield = pstrdup(buf.data); \
|
734
|
+
pfree(buf.data); \
|
735
|
+
}
|
736
|
+
|
737
|
+
/*
|
738
|
+
* Same as above, except for pluralized error messages. The calling routine
|
739
|
+
* must be declared like "const char *fmt_singular, const char *fmt_plural,
|
740
|
+
* unsigned long n, ...". Translation is assumed always wanted.
|
741
|
+
*/
|
742
|
+
#define EVALUATE_MESSAGE_PLURAL(domain, targetfield, appendval) \
|
743
|
+
{ \
|
744
|
+
const char *fmt; \
|
745
|
+
StringInfoData buf; \
|
746
|
+
/* Internationalize the error format string */ \
|
747
|
+
if (!in_error_recursion_trouble()) \
|
748
|
+
fmt = dngettext((domain), fmt_singular, fmt_plural, n); \
|
749
|
+
else \
|
750
|
+
fmt = (n == 1 ? fmt_singular : fmt_plural); \
|
751
|
+
initStringInfo(&buf); \
|
752
|
+
if ((appendval) && edata->targetfield) { \
|
753
|
+
appendStringInfoString(&buf, edata->targetfield); \
|
754
|
+
appendStringInfoChar(&buf, '\n'); \
|
755
|
+
} \
|
756
|
+
/* Generate actual output --- have to use appendStringInfoVA */ \
|
757
|
+
for (;;) \
|
758
|
+
{ \
|
759
|
+
va_list args; \
|
760
|
+
int needed; \
|
761
|
+
errno = edata->saved_errno; \
|
762
|
+
va_start(args, n); \
|
763
|
+
needed = appendStringInfoVA(&buf, fmt, args); \
|
764
|
+
va_end(args); \
|
765
|
+
if (needed == 0) \
|
766
|
+
break; \
|
767
|
+
enlargeStringInfo(&buf, needed); \
|
768
|
+
} \
|
769
|
+
/* Save the completed message into the stack item */ \
|
770
|
+
if (edata->targetfield) \
|
771
|
+
pfree(edata->targetfield); \
|
772
|
+
edata->targetfield = pstrdup(buf.data); \
|
773
|
+
pfree(buf.data); \
|
774
|
+
}
|
775
|
+
|
776
|
+
|
777
|
+
/*
|
778
|
+
* errmsg --- add a primary error message text to the current error
|
779
|
+
*
|
780
|
+
* In addition to the usual %-escapes recognized by printf, "%m" in
|
781
|
+
* fmt is replaced by the error message for the caller's value of errno.
|
782
|
+
*
|
783
|
+
* Note: no newline is needed at the end of the fmt string, since
|
784
|
+
* ereport will provide one for the output methods that need it.
|
785
|
+
*/
|
786
|
+
int
|
787
|
+
errmsg(const char *fmt,...)
|
788
|
+
{
|
789
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
790
|
+
MemoryContext oldcontext;
|
791
|
+
|
792
|
+
recursion_depth++;
|
793
|
+
CHECK_STACK_DEPTH();
|
794
|
+
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
|
795
|
+
|
796
|
+
edata->message_id = fmt;
|
797
|
+
EVALUATE_MESSAGE(edata->domain, message, false, true);
|
798
|
+
|
799
|
+
MemoryContextSwitchTo(oldcontext);
|
800
|
+
recursion_depth--;
|
801
|
+
return 0; /* return value does not matter */
|
802
|
+
}
|
803
|
+
|
804
|
+
/*
|
805
|
+
* Add a backtrace to the containing ereport() call. This is intended to be
|
806
|
+
* added temporarily during debugging.
|
807
|
+
*/
|
808
|
+
|
809
|
+
|
810
|
+
/*
|
811
|
+
* Compute backtrace data and add it to the supplied ErrorData. num_skip
|
812
|
+
* specifies how many inner frames to skip. Use this to avoid showing the
|
813
|
+
* internal backtrace support functions in the backtrace. This requires that
|
814
|
+
* this and related functions are not inlined.
|
815
|
+
*/
|
816
|
+
static void
|
817
|
+
set_backtrace(ErrorData *edata, int num_skip)
|
818
|
+
{
|
819
|
+
StringInfoData errtrace;
|
820
|
+
|
821
|
+
initStringInfo(&errtrace);
|
822
|
+
|
823
|
+
#ifdef HAVE_BACKTRACE_SYMBOLS
|
824
|
+
{
|
825
|
+
void *buf[100];
|
826
|
+
int nframes;
|
827
|
+
char **strfrms;
|
828
|
+
|
829
|
+
nframes = backtrace(buf, lengthof(buf));
|
830
|
+
strfrms = backtrace_symbols(buf, nframes);
|
831
|
+
if (strfrms == NULL)
|
832
|
+
return;
|
833
|
+
|
834
|
+
for (int i = num_skip; i < nframes; i++)
|
835
|
+
appendStringInfo(&errtrace, "\n%s", strfrms[i]);
|
836
|
+
free(strfrms);
|
837
|
+
}
|
838
|
+
#else
|
839
|
+
appendStringInfoString(&errtrace,
|
840
|
+
"backtrace generation is not supported by this installation");
|
841
|
+
#endif
|
842
|
+
|
843
|
+
edata->backtrace = errtrace.data;
|
844
|
+
}
|
845
|
+
|
846
|
+
/*
|
847
|
+
* errmsg_internal --- add a primary error message text to the current error
|
848
|
+
*
|
849
|
+
* This is exactly like errmsg() except that strings passed to errmsg_internal
|
850
|
+
* are not translated, and are customarily left out of the
|
851
|
+
* internationalization message dictionary. This should be used for "can't
|
852
|
+
* happen" cases that are probably not worth spending translation effort on.
|
853
|
+
* We also use this for certain cases where we *must* not try to translate
|
854
|
+
* the message because the translation would fail and result in infinite
|
855
|
+
* error recursion.
|
856
|
+
*/
|
857
|
+
int
|
858
|
+
errmsg_internal(const char *fmt,...)
|
859
|
+
{
|
860
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
861
|
+
MemoryContext oldcontext;
|
862
|
+
|
863
|
+
recursion_depth++;
|
864
|
+
CHECK_STACK_DEPTH();
|
865
|
+
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
|
866
|
+
|
867
|
+
edata->message_id = fmt;
|
868
|
+
EVALUATE_MESSAGE(edata->domain, message, false, false);
|
869
|
+
|
870
|
+
MemoryContextSwitchTo(oldcontext);
|
871
|
+
recursion_depth--;
|
872
|
+
return 0; /* return value does not matter */
|
873
|
+
}
|
874
|
+
|
875
|
+
|
876
|
+
/*
|
877
|
+
* errmsg_plural --- add a primary error message text to the current error,
|
878
|
+
* with support for pluralization of the message text
|
879
|
+
*/
|
880
|
+
|
881
|
+
|
882
|
+
|
883
|
+
/*
|
884
|
+
* errdetail --- add a detail error message text to the current error
|
885
|
+
*/
|
886
|
+
int
|
887
|
+
errdetail(const char *fmt,...)
|
888
|
+
{
|
889
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
890
|
+
MemoryContext oldcontext;
|
891
|
+
|
892
|
+
recursion_depth++;
|
893
|
+
CHECK_STACK_DEPTH();
|
894
|
+
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
|
895
|
+
|
896
|
+
EVALUATE_MESSAGE(edata->domain, detail, false, true);
|
897
|
+
|
898
|
+
MemoryContextSwitchTo(oldcontext);
|
899
|
+
recursion_depth--;
|
900
|
+
return 0; /* return value does not matter */
|
901
|
+
}
|
902
|
+
|
903
|
+
|
904
|
+
/*
|
905
|
+
* errdetail_internal --- add a detail error message text to the current error
|
906
|
+
*
|
907
|
+
* This is exactly like errdetail() except that strings passed to
|
908
|
+
* errdetail_internal are not translated, and are customarily left out of the
|
909
|
+
* internationalization message dictionary. This should be used for detail
|
910
|
+
* messages that seem not worth translating for one reason or another
|
911
|
+
* (typically, that they don't seem to be useful to average users).
|
912
|
+
*/
|
913
|
+
|
914
|
+
|
915
|
+
|
916
|
+
/*
|
917
|
+
* errdetail_log --- add a detail_log error message text to the current error
|
918
|
+
*/
|
919
|
+
|
920
|
+
|
921
|
+
/*
|
922
|
+
* errdetail_log_plural --- add a detail_log error message text to the current error
|
923
|
+
* with support for pluralization of the message text
|
924
|
+
*/
|
925
|
+
|
926
|
+
|
927
|
+
|
928
|
+
/*
|
929
|
+
* errdetail_plural --- add a detail error message text to the current error,
|
930
|
+
* with support for pluralization of the message text
|
931
|
+
*/
|
932
|
+
|
933
|
+
|
934
|
+
|
935
|
+
/*
|
936
|
+
* errhint --- add a hint error message text to the current error
|
937
|
+
*/
|
938
|
+
int
|
939
|
+
errhint(const char *fmt,...)
|
940
|
+
{
|
941
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
942
|
+
MemoryContext oldcontext;
|
943
|
+
|
944
|
+
recursion_depth++;
|
945
|
+
CHECK_STACK_DEPTH();
|
946
|
+
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
|
947
|
+
|
948
|
+
EVALUATE_MESSAGE(edata->domain, hint, false, true);
|
949
|
+
|
950
|
+
MemoryContextSwitchTo(oldcontext);
|
951
|
+
recursion_depth--;
|
952
|
+
return 0; /* return value does not matter */
|
953
|
+
}
|
954
|
+
|
955
|
+
|
956
|
+
/*
|
957
|
+
* errcontext_msg --- add a context error message text to the current error
|
958
|
+
*
|
959
|
+
* Unlike other cases, multiple calls are allowed to build up a stack of
|
960
|
+
* context information. We assume earlier calls represent more-closely-nested
|
961
|
+
* states.
|
962
|
+
*/
|
963
|
+
int
|
964
|
+
errcontext_msg(const char *fmt,...)
|
965
|
+
{
|
966
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
967
|
+
MemoryContext oldcontext;
|
968
|
+
|
969
|
+
recursion_depth++;
|
970
|
+
CHECK_STACK_DEPTH();
|
971
|
+
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
|
972
|
+
|
973
|
+
EVALUATE_MESSAGE(edata->context_domain, context, true, true);
|
974
|
+
|
975
|
+
MemoryContextSwitchTo(oldcontext);
|
976
|
+
recursion_depth--;
|
977
|
+
return 0; /* return value does not matter */
|
978
|
+
}
|
979
|
+
|
980
|
+
/*
|
981
|
+
* set_errcontext_domain --- set message domain to be used by errcontext()
|
982
|
+
*
|
983
|
+
* errcontext_msg() can be called from a different module than the original
|
984
|
+
* ereport(), so we cannot use the message domain passed in errstart() to
|
985
|
+
* translate it. Instead, each errcontext_msg() call should be preceded by
|
986
|
+
* a set_errcontext_domain() call to specify the domain. This is usually
|
987
|
+
* done transparently by the errcontext() macro.
|
988
|
+
*/
|
989
|
+
int
|
990
|
+
set_errcontext_domain(const char *domain)
|
991
|
+
{
|
992
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
993
|
+
|
994
|
+
/* we don't bother incrementing recursion_depth */
|
995
|
+
CHECK_STACK_DEPTH();
|
996
|
+
|
997
|
+
/* the default text domain is the backend's */
|
998
|
+
edata->context_domain = domain ? domain : PG_TEXTDOMAIN("postgres");
|
999
|
+
|
1000
|
+
return 0; /* return value does not matter */
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
|
1004
|
+
/*
|
1005
|
+
* errhidestmt --- optionally suppress STATEMENT: field of log entry
|
1006
|
+
*
|
1007
|
+
* This should be called if the message text already includes the statement.
|
1008
|
+
*/
|
1009
|
+
|
1010
|
+
|
1011
|
+
/*
|
1012
|
+
* errhidecontext --- optionally suppress CONTEXT: field of log entry
|
1013
|
+
*
|
1014
|
+
* This should only be used for verbose debugging messages where the repeated
|
1015
|
+
* inclusion of context would bloat the log volume too much.
|
1016
|
+
*/
|
1017
|
+
|
1018
|
+
|
1019
|
+
|
1020
|
+
/*
|
1021
|
+
* errfunction --- add reporting function name to the current error
|
1022
|
+
*
|
1023
|
+
* This is used when backwards compatibility demands that the function
|
1024
|
+
* name appear in messages sent to old-protocol clients. Note that the
|
1025
|
+
* passed string is expected to be a non-freeable constant string.
|
1026
|
+
*/
|
1027
|
+
|
1028
|
+
|
1029
|
+
/*
|
1030
|
+
* errposition --- add cursor position to the current error
|
1031
|
+
*/
|
1032
|
+
int
|
1033
|
+
errposition(int cursorpos)
|
1034
|
+
{
|
1035
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1036
|
+
|
1037
|
+
/* we don't bother incrementing recursion_depth */
|
1038
|
+
CHECK_STACK_DEPTH();
|
1039
|
+
|
1040
|
+
edata->cursorpos = cursorpos;
|
1041
|
+
|
1042
|
+
return 0; /* return value does not matter */
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
/*
|
1046
|
+
* internalerrposition --- add internal cursor position to the current error
|
1047
|
+
*/
|
1048
|
+
int
|
1049
|
+
internalerrposition(int cursorpos)
|
1050
|
+
{
|
1051
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1052
|
+
|
1053
|
+
/* we don't bother incrementing recursion_depth */
|
1054
|
+
CHECK_STACK_DEPTH();
|
1055
|
+
|
1056
|
+
edata->internalpos = cursorpos;
|
1057
|
+
|
1058
|
+
return 0; /* return value does not matter */
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
/*
|
1062
|
+
* internalerrquery --- add internal query text to the current error
|
1063
|
+
*
|
1064
|
+
* Can also pass NULL to drop the internal query text entry. This case
|
1065
|
+
* is intended for use in error callback subroutines that are editorializing
|
1066
|
+
* on the layout of the error report.
|
1067
|
+
*/
|
1068
|
+
int
|
1069
|
+
internalerrquery(const char *query)
|
1070
|
+
{
|
1071
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1072
|
+
|
1073
|
+
/* we don't bother incrementing recursion_depth */
|
1074
|
+
CHECK_STACK_DEPTH();
|
1075
|
+
|
1076
|
+
if (edata->internalquery)
|
1077
|
+
{
|
1078
|
+
pfree(edata->internalquery);
|
1079
|
+
edata->internalquery = NULL;
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
if (query)
|
1083
|
+
edata->internalquery = MemoryContextStrdup(edata->assoc_context, query);
|
1084
|
+
|
1085
|
+
return 0; /* return value does not matter */
|
1086
|
+
}
|
1087
|
+
|
1088
|
+
/*
|
1089
|
+
* err_generic_string -- used to set individual ErrorData string fields
|
1090
|
+
* identified by PG_DIAG_xxx codes.
|
1091
|
+
*
|
1092
|
+
* This intentionally only supports fields that don't use localized strings,
|
1093
|
+
* so that there are no translation considerations.
|
1094
|
+
*
|
1095
|
+
* Most potential callers should not use this directly, but instead prefer
|
1096
|
+
* higher-level abstractions, such as errtablecol() (see relcache.c).
|
1097
|
+
*/
|
1098
|
+
|
1099
|
+
|
1100
|
+
/*
|
1101
|
+
* set_errdata_field --- set an ErrorData string field
|
1102
|
+
*/
|
1103
|
+
|
1104
|
+
|
1105
|
+
/*
|
1106
|
+
* geterrcode --- return the currently set SQLSTATE error code
|
1107
|
+
*
|
1108
|
+
* This is only intended for use in error callback subroutines, since there
|
1109
|
+
* is no other place outside elog.c where the concept is meaningful.
|
1110
|
+
*/
|
1111
|
+
int
|
1112
|
+
geterrcode(void)
|
1113
|
+
{
|
1114
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1115
|
+
|
1116
|
+
/* we don't bother incrementing recursion_depth */
|
1117
|
+
CHECK_STACK_DEPTH();
|
1118
|
+
|
1119
|
+
return edata->sqlerrcode;
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
/*
|
1123
|
+
* geterrposition --- return the currently set error position (0 if none)
|
1124
|
+
*
|
1125
|
+
* This is only intended for use in error callback subroutines, since there
|
1126
|
+
* is no other place outside elog.c where the concept is meaningful.
|
1127
|
+
*/
|
1128
|
+
int
|
1129
|
+
geterrposition(void)
|
1130
|
+
{
|
1131
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1132
|
+
|
1133
|
+
/* we don't bother incrementing recursion_depth */
|
1134
|
+
CHECK_STACK_DEPTH();
|
1135
|
+
|
1136
|
+
return edata->cursorpos;
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
/*
|
1140
|
+
* getinternalerrposition --- same for internal error position
|
1141
|
+
*
|
1142
|
+
* This is only intended for use in error callback subroutines, since there
|
1143
|
+
* is no other place outside elog.c where the concept is meaningful.
|
1144
|
+
*/
|
1145
|
+
int
|
1146
|
+
getinternalerrposition(void)
|
1147
|
+
{
|
1148
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1149
|
+
|
1150
|
+
/* we don't bother incrementing recursion_depth */
|
1151
|
+
CHECK_STACK_DEPTH();
|
1152
|
+
|
1153
|
+
return edata->internalpos;
|
1154
|
+
}
|
1155
|
+
|
1156
|
+
|
1157
|
+
/*
|
1158
|
+
* Functions to allow construction of error message strings separately from
|
1159
|
+
* the ereport() call itself.
|
1160
|
+
*
|
1161
|
+
* The expected calling convention is
|
1162
|
+
*
|
1163
|
+
* pre_format_elog_string(errno, domain), var = format_elog_string(format,...)
|
1164
|
+
*
|
1165
|
+
* which can be hidden behind a macro such as GUC_check_errdetail(). We
|
1166
|
+
* assume that any functions called in the arguments of format_elog_string()
|
1167
|
+
* cannot result in re-entrant use of these functions --- otherwise the wrong
|
1168
|
+
* text domain might be used, or the wrong errno substituted for %m. This is
|
1169
|
+
* okay for the current usage with GUC check hooks, but might need further
|
1170
|
+
* effort someday.
|
1171
|
+
*
|
1172
|
+
* The result of format_elog_string() is stored in ErrorContext, and will
|
1173
|
+
* therefore survive until FlushErrorState() is called.
|
1174
|
+
*/
|
1175
|
+
|
1176
|
+
|
1177
|
+
|
1178
|
+
|
1179
|
+
|
1180
|
+
|
1181
|
+
|
1182
|
+
|
1183
|
+
/*
|
1184
|
+
* Actual output of the top-of-stack error message
|
1185
|
+
*
|
1186
|
+
* In the ereport(ERROR) case this is called from PostgresMain (or not at all,
|
1187
|
+
* if the error is caught by somebody). For all other severity levels this
|
1188
|
+
* is called by errfinish.
|
1189
|
+
*/
|
1190
|
+
void
|
1191
|
+
EmitErrorReport(void)
|
1192
|
+
{
|
1193
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1194
|
+
MemoryContext oldcontext;
|
1195
|
+
|
1196
|
+
recursion_depth++;
|
1197
|
+
CHECK_STACK_DEPTH();
|
1198
|
+
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
|
1199
|
+
|
1200
|
+
/*
|
1201
|
+
* Call hook before sending message to log. The hook function is allowed
|
1202
|
+
* to turn off edata->output_to_server, so we must recheck that afterward.
|
1203
|
+
* Making any other change in the content of edata is not considered
|
1204
|
+
* supported.
|
1205
|
+
*
|
1206
|
+
* Note: the reason why the hook can only turn off output_to_server, and
|
1207
|
+
* not turn it on, is that it'd be unreliable: we will never get here at
|
1208
|
+
* all if errstart() deems the message uninteresting. A hook that could
|
1209
|
+
* make decisions in that direction would have to hook into errstart(),
|
1210
|
+
* where it would have much less information available. emit_log_hook is
|
1211
|
+
* intended for custom log filtering and custom log message transmission
|
1212
|
+
* mechanisms.
|
1213
|
+
*
|
1214
|
+
* The log hook has access to both the translated and original English
|
1215
|
+
* error message text, which is passed through to allow it to be used as a
|
1216
|
+
* message identifier. Note that the original text is not available for
|
1217
|
+
* detail, detail_log, hint and context text elements.
|
1218
|
+
*/
|
1219
|
+
if (edata->output_to_server && emit_log_hook)
|
1220
|
+
(*emit_log_hook) (edata);
|
1221
|
+
|
1222
|
+
/* Send to server log, if enabled */
|
1223
|
+
if (edata->output_to_server)
|
1224
|
+
send_message_to_server_log(edata);
|
1225
|
+
|
1226
|
+
/* Send to client, if enabled */
|
1227
|
+
if (edata->output_to_client)
|
1228
|
+
send_message_to_frontend(edata);
|
1229
|
+
|
1230
|
+
MemoryContextSwitchTo(oldcontext);
|
1231
|
+
recursion_depth--;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
/*
|
1235
|
+
* CopyErrorData --- obtain a copy of the topmost error stack entry
|
1236
|
+
*
|
1237
|
+
* This is only for use in error handler code. The data is copied into the
|
1238
|
+
* current memory context, so callers should always switch away from
|
1239
|
+
* ErrorContext first; otherwise it will be lost when FlushErrorState is done.
|
1240
|
+
*/
|
1241
|
+
ErrorData *
|
1242
|
+
CopyErrorData(void)
|
1243
|
+
{
|
1244
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1245
|
+
ErrorData *newedata;
|
1246
|
+
|
1247
|
+
/*
|
1248
|
+
* we don't increment recursion_depth because out-of-memory here does not
|
1249
|
+
* indicate a problem within the error subsystem.
|
1250
|
+
*/
|
1251
|
+
CHECK_STACK_DEPTH();
|
1252
|
+
|
1253
|
+
Assert(CurrentMemoryContext != ErrorContext);
|
1254
|
+
|
1255
|
+
/* Copy the struct itself */
|
1256
|
+
newedata = (ErrorData *) palloc(sizeof(ErrorData));
|
1257
|
+
memcpy(newedata, edata, sizeof(ErrorData));
|
1258
|
+
|
1259
|
+
/* Make copies of separately-allocated fields */
|
1260
|
+
if (newedata->message)
|
1261
|
+
newedata->message = pstrdup(newedata->message);
|
1262
|
+
if (newedata->detail)
|
1263
|
+
newedata->detail = pstrdup(newedata->detail);
|
1264
|
+
if (newedata->detail_log)
|
1265
|
+
newedata->detail_log = pstrdup(newedata->detail_log);
|
1266
|
+
if (newedata->hint)
|
1267
|
+
newedata->hint = pstrdup(newedata->hint);
|
1268
|
+
if (newedata->context)
|
1269
|
+
newedata->context = pstrdup(newedata->context);
|
1270
|
+
if (newedata->backtrace)
|
1271
|
+
newedata->backtrace = pstrdup(newedata->backtrace);
|
1272
|
+
if (newedata->schema_name)
|
1273
|
+
newedata->schema_name = pstrdup(newedata->schema_name);
|
1274
|
+
if (newedata->table_name)
|
1275
|
+
newedata->table_name = pstrdup(newedata->table_name);
|
1276
|
+
if (newedata->column_name)
|
1277
|
+
newedata->column_name = pstrdup(newedata->column_name);
|
1278
|
+
if (newedata->datatype_name)
|
1279
|
+
newedata->datatype_name = pstrdup(newedata->datatype_name);
|
1280
|
+
if (newedata->constraint_name)
|
1281
|
+
newedata->constraint_name = pstrdup(newedata->constraint_name);
|
1282
|
+
if (newedata->internalquery)
|
1283
|
+
newedata->internalquery = pstrdup(newedata->internalquery);
|
1284
|
+
|
1285
|
+
/* Use the calling context for string allocation */
|
1286
|
+
newedata->assoc_context = CurrentMemoryContext;
|
1287
|
+
|
1288
|
+
return newedata;
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
/*
|
1292
|
+
* FreeErrorData --- free the structure returned by CopyErrorData.
|
1293
|
+
*
|
1294
|
+
* Error handlers should use this in preference to assuming they know all
|
1295
|
+
* the separately-allocated fields.
|
1296
|
+
*/
|
1297
|
+
|
1298
|
+
|
1299
|
+
/*
|
1300
|
+
* FlushErrorState --- flush the error state after error recovery
|
1301
|
+
*
|
1302
|
+
* This should be called by an error handler after it's done processing
|
1303
|
+
* the error; or as soon as it's done CopyErrorData, if it intends to
|
1304
|
+
* do stuff that is likely to provoke another error. You are not "out" of
|
1305
|
+
* the error subsystem until you have done this.
|
1306
|
+
*/
|
1307
|
+
void
|
1308
|
+
FlushErrorState(void)
|
1309
|
+
{
|
1310
|
+
/*
|
1311
|
+
* Reset stack to empty. The only case where it would be more than one
|
1312
|
+
* deep is if we serviced an error that interrupted construction of
|
1313
|
+
* another message. We assume control escaped out of that message
|
1314
|
+
* construction and won't ever go back.
|
1315
|
+
*/
|
1316
|
+
errordata_stack_depth = -1;
|
1317
|
+
recursion_depth = 0;
|
1318
|
+
/* Delete all data in ErrorContext */
|
1319
|
+
MemoryContextResetAndDeleteChildren(ErrorContext);
|
1320
|
+
}
|
1321
|
+
|
1322
|
+
/*
|
1323
|
+
* ThrowErrorData --- report an error described by an ErrorData structure
|
1324
|
+
*
|
1325
|
+
* This is somewhat like ReThrowError, but it allows elevels besides ERROR,
|
1326
|
+
* and the boolean flags such as output_to_server are computed via the
|
1327
|
+
* default rules rather than being copied from the given ErrorData.
|
1328
|
+
* This is primarily used to re-report errors originally reported by
|
1329
|
+
* background worker processes and then propagated (with or without
|
1330
|
+
* modification) to the backend responsible for them.
|
1331
|
+
*/
|
1332
|
+
|
1333
|
+
|
1334
|
+
/*
|
1335
|
+
* ReThrowError --- re-throw a previously copied error
|
1336
|
+
*
|
1337
|
+
* A handler can do CopyErrorData/FlushErrorState to get out of the error
|
1338
|
+
* subsystem, then do some processing, and finally ReThrowError to re-throw
|
1339
|
+
* the original error. This is slower than just PG_RE_THROW() but should
|
1340
|
+
* be used if the "some processing" is likely to incur another error.
|
1341
|
+
*/
|
1342
|
+
|
1343
|
+
|
1344
|
+
/*
|
1345
|
+
* pg_re_throw --- out-of-line implementation of PG_RE_THROW() macro
|
1346
|
+
*/
|
1347
|
+
void
|
1348
|
+
pg_re_throw(void)
|
1349
|
+
{
|
1350
|
+
/* If possible, throw the error to the next outer setjmp handler */
|
1351
|
+
if (PG_exception_stack != NULL)
|
1352
|
+
siglongjmp(*PG_exception_stack, 1);
|
1353
|
+
else
|
1354
|
+
{
|
1355
|
+
/*
|
1356
|
+
* If we get here, elog(ERROR) was thrown inside a PG_TRY block, which
|
1357
|
+
* we have now exited only to discover that there is no outer setjmp
|
1358
|
+
* handler to pass the error to. Had the error been thrown outside
|
1359
|
+
* the block to begin with, we'd have promoted the error to FATAL, so
|
1360
|
+
* the correct behavior is to make it FATAL now; that is, emit it and
|
1361
|
+
* then call proc_exit.
|
1362
|
+
*/
|
1363
|
+
ErrorData *edata = &errordata[errordata_stack_depth];
|
1364
|
+
|
1365
|
+
Assert(errordata_stack_depth >= 0);
|
1366
|
+
Assert(edata->elevel == ERROR);
|
1367
|
+
edata->elevel = FATAL;
|
1368
|
+
|
1369
|
+
/*
|
1370
|
+
* At least in principle, the increase in severity could have changed
|
1371
|
+
* where-to-output decisions, so recalculate. This should stay in
|
1372
|
+
* sync with errstart(), which see for comments.
|
1373
|
+
*/
|
1374
|
+
if (IsPostmasterEnvironment)
|
1375
|
+
edata->output_to_server = is_log_level_output(FATAL,
|
1376
|
+
log_min_messages);
|
1377
|
+
else
|
1378
|
+
edata->output_to_server = (FATAL >= log_min_messages);
|
1379
|
+
if (whereToSendOutput == DestRemote)
|
1380
|
+
edata->output_to_client = true;
|
1381
|
+
|
1382
|
+
/*
|
1383
|
+
* We can use errfinish() for the rest, but we don't want it to call
|
1384
|
+
* any error context routines a second time. Since we know we are
|
1385
|
+
* about to exit, it should be OK to just clear the context stack.
|
1386
|
+
*/
|
1387
|
+
error_context_stack = NULL;
|
1388
|
+
|
1389
|
+
errfinish(edata->filename, edata->lineno, edata->funcname);
|
1390
|
+
}
|
1391
|
+
|
1392
|
+
/* Doesn't return ... */
|
1393
|
+
ExceptionalCondition("pg_re_throw tried to return", "FailedAssertion",
|
1394
|
+
__FILE__, __LINE__);
|
1395
|
+
}
|
1396
|
+
|
1397
|
+
|
1398
|
+
/*
|
1399
|
+
* GetErrorContextStack - Return the context stack, for display/diags
|
1400
|
+
*
|
1401
|
+
* Returns a pstrdup'd string in the caller's context which includes the PG
|
1402
|
+
* error call stack. It is the caller's responsibility to ensure this string
|
1403
|
+
* is pfree'd (or its context cleaned up) when done.
|
1404
|
+
*
|
1405
|
+
* This information is collected by traversing the error contexts and calling
|
1406
|
+
* each context's callback function, each of which is expected to call
|
1407
|
+
* errcontext() to return a string which can be presented to the user.
|
1408
|
+
*/
|
1409
|
+
|
1410
|
+
|
1411
|
+
|
1412
|
+
/*
|
1413
|
+
* Initialization of error output file
|
1414
|
+
*/
|
1415
|
+
|
1416
|
+
|
1417
|
+
|
1418
|
+
#ifdef HAVE_SYSLOG
|
1419
|
+
|
1420
|
+
/*
|
1421
|
+
* Set or update the parameters for syslog logging
|
1422
|
+
*/
|
1423
|
+
|
1424
|
+
|
1425
|
+
|
1426
|
+
/*
|
1427
|
+
* Write a message line to syslog
|
1428
|
+
*/
|
1429
|
+
|
1430
|
+
#endif /* HAVE_SYSLOG */
|
1431
|
+
|
1432
|
+
#ifdef WIN32
|
1433
|
+
/*
|
1434
|
+
* Get the PostgreSQL equivalent of the Windows ANSI code page. "ANSI" system
|
1435
|
+
* interfaces (e.g. CreateFileA()) expect string arguments in this encoding.
|
1436
|
+
* Every process in a given system will find the same value at all times.
|
1437
|
+
*/
|
1438
|
+
static int
|
1439
|
+
GetACPEncoding(void)
|
1440
|
+
{
|
1441
|
+
static int encoding = -2;
|
1442
|
+
|
1443
|
+
if (encoding == -2)
|
1444
|
+
encoding = pg_codepage_to_encoding(GetACP());
|
1445
|
+
|
1446
|
+
return encoding;
|
1447
|
+
}
|
1448
|
+
|
1449
|
+
/*
|
1450
|
+
* Write a message line to the windows event log
|
1451
|
+
*/
|
1452
|
+
static void
|
1453
|
+
write_eventlog(int level, const char *line, int len)
|
1454
|
+
{
|
1455
|
+
WCHAR *utf16;
|
1456
|
+
int eventlevel = EVENTLOG_ERROR_TYPE;
|
1457
|
+
static HANDLE evtHandle = INVALID_HANDLE_VALUE;
|
1458
|
+
|
1459
|
+
if (evtHandle == INVALID_HANDLE_VALUE)
|
1460
|
+
{
|
1461
|
+
evtHandle = RegisterEventSource(NULL,
|
1462
|
+
event_source ? event_source : DEFAULT_EVENT_SOURCE);
|
1463
|
+
if (evtHandle == NULL)
|
1464
|
+
{
|
1465
|
+
evtHandle = INVALID_HANDLE_VALUE;
|
1466
|
+
return;
|
1467
|
+
}
|
1468
|
+
}
|
1469
|
+
|
1470
|
+
switch (level)
|
1471
|
+
{
|
1472
|
+
case DEBUG5:
|
1473
|
+
case DEBUG4:
|
1474
|
+
case DEBUG3:
|
1475
|
+
case DEBUG2:
|
1476
|
+
case DEBUG1:
|
1477
|
+
case LOG:
|
1478
|
+
case LOG_SERVER_ONLY:
|
1479
|
+
case INFO:
|
1480
|
+
case NOTICE:
|
1481
|
+
eventlevel = EVENTLOG_INFORMATION_TYPE;
|
1482
|
+
break;
|
1483
|
+
case WARNING:
|
1484
|
+
eventlevel = EVENTLOG_WARNING_TYPE;
|
1485
|
+
break;
|
1486
|
+
case ERROR:
|
1487
|
+
case FATAL:
|
1488
|
+
case PANIC:
|
1489
|
+
default:
|
1490
|
+
eventlevel = EVENTLOG_ERROR_TYPE;
|
1491
|
+
break;
|
1492
|
+
}
|
1493
|
+
|
1494
|
+
/*
|
1495
|
+
* If message character encoding matches the encoding expected by
|
1496
|
+
* ReportEventA(), call it to avoid the hazards of conversion. Otherwise,
|
1497
|
+
* try to convert the message to UTF16 and write it with ReportEventW().
|
1498
|
+
* Fall back on ReportEventA() if conversion failed.
|
1499
|
+
*
|
1500
|
+
* Since we palloc the structure required for conversion, also fall
|
1501
|
+
* through to writing unconverted if we have not yet set up
|
1502
|
+
* CurrentMemoryContext.
|
1503
|
+
*
|
1504
|
+
* Also verify that we are not on our way into error recursion trouble due
|
1505
|
+
* to error messages thrown deep inside pgwin32_message_to_UTF16().
|
1506
|
+
*/
|
1507
|
+
if (!in_error_recursion_trouble() &&
|
1508
|
+
CurrentMemoryContext != NULL &&
|
1509
|
+
GetMessageEncoding() != GetACPEncoding())
|
1510
|
+
{
|
1511
|
+
utf16 = pgwin32_message_to_UTF16(line, len, NULL);
|
1512
|
+
if (utf16)
|
1513
|
+
{
|
1514
|
+
ReportEventW(evtHandle,
|
1515
|
+
eventlevel,
|
1516
|
+
0,
|
1517
|
+
0, /* All events are Id 0 */
|
1518
|
+
NULL,
|
1519
|
+
1,
|
1520
|
+
0,
|
1521
|
+
(LPCWSTR *) &utf16,
|
1522
|
+
NULL);
|
1523
|
+
/* XXX Try ReportEventA() when ReportEventW() fails? */
|
1524
|
+
|
1525
|
+
pfree(utf16);
|
1526
|
+
return;
|
1527
|
+
}
|
1528
|
+
}
|
1529
|
+
ReportEventA(evtHandle,
|
1530
|
+
eventlevel,
|
1531
|
+
0,
|
1532
|
+
0, /* All events are Id 0 */
|
1533
|
+
NULL,
|
1534
|
+
1,
|
1535
|
+
0,
|
1536
|
+
&line,
|
1537
|
+
NULL);
|
1538
|
+
}
|
1539
|
+
#endif /* WIN32 */
|
1540
|
+
|
1541
|
+
#ifdef WIN32
|
1542
|
+
#else
|
1543
|
+
#endif
|
1544
|
+
|
1545
|
+
/*
|
1546
|
+
* setup formatted_log_time, for consistent times between CSV and regular logs
|
1547
|
+
*/
|
1548
|
+
|
1549
|
+
|
1550
|
+
/*
|
1551
|
+
* setup formatted_start_time
|
1552
|
+
*/
|
1553
|
+
|
1554
|
+
|
1555
|
+
/*
|
1556
|
+
* process_log_prefix_padding --- helper function for processing the format
|
1557
|
+
* string in log_line_prefix
|
1558
|
+
*
|
1559
|
+
* Note: This function returns NULL if it finds something which
|
1560
|
+
* it deems invalid in the format string.
|
1561
|
+
*/
|
1562
|
+
|
1563
|
+
|
1564
|
+
/*
|
1565
|
+
* Format tag info for log lines; append to the provided buffer.
|
1566
|
+
*/
|
1567
|
+
|
1568
|
+
|
1569
|
+
/*
|
1570
|
+
* append a CSV'd version of a string to a StringInfo
|
1571
|
+
* We use the PostgreSQL defaults for CSV, i.e. quote = escape = '"'
|
1572
|
+
* If it's NULL, append nothing.
|
1573
|
+
*/
|
1574
|
+
|
1575
|
+
|
1576
|
+
/*
|
1577
|
+
* Constructs the error message, depending on the Errordata it gets, in a CSV
|
1578
|
+
* format which is described in doc/src/sgml/config.sgml.
|
1579
|
+
*/
|
1580
|
+
|
1581
|
+
|
1582
|
+
/*
|
1583
|
+
* Unpack MAKE_SQLSTATE code. Note that this returns a pointer to a
|
1584
|
+
* static buffer.
|
1585
|
+
*/
|
1586
|
+
|
1587
|
+
|
1588
|
+
|
1589
|
+
/*
|
1590
|
+
* Write error report to server's log
|
1591
|
+
*/
|
1592
|
+
static void send_message_to_server_log(ErrorData *edata) {}
|
1593
|
+
|
1594
|
+
|
1595
|
+
/*
|
1596
|
+
* Send data to the syslogger using the chunked protocol
|
1597
|
+
*
|
1598
|
+
* Note: when there are multiple backends writing into the syslogger pipe,
|
1599
|
+
* it's critical that each write go into the pipe indivisibly, and not
|
1600
|
+
* get interleaved with data from other processes. Fortunately, the POSIX
|
1601
|
+
* spec requires that writes to pipes be atomic so long as they are not
|
1602
|
+
* more than PIPE_BUF bytes long. So we divide long messages into chunks
|
1603
|
+
* that are no more than that length, and send one chunk per write() call.
|
1604
|
+
* The collector process knows how to reassemble the chunks.
|
1605
|
+
*
|
1606
|
+
* Because of the atomic write requirement, there are only two possible
|
1607
|
+
* results from write() here: -1 for failure, or the requested number of
|
1608
|
+
* bytes. There is not really anything we can do about a failure; retry would
|
1609
|
+
* probably be an infinite loop, and we can't even report the error usefully.
|
1610
|
+
* (There is noplace else we could send it!) So we might as well just ignore
|
1611
|
+
* the result from write(). However, on some platforms you get a compiler
|
1612
|
+
* warning from ignoring write()'s result, so do a little dance with casting
|
1613
|
+
* rc to void to shut up the compiler.
|
1614
|
+
*/
|
1615
|
+
|
1616
|
+
|
1617
|
+
|
1618
|
+
/*
|
1619
|
+
* Append a text string to the error report being built for the client.
|
1620
|
+
*
|
1621
|
+
* This is ordinarily identical to pq_sendstring(), but if we are in
|
1622
|
+
* error recursion trouble we skip encoding conversion, because of the
|
1623
|
+
* possibility that the problem is a failure in the encoding conversion
|
1624
|
+
* subsystem itself. Code elsewhere should ensure that the passed-in
|
1625
|
+
* strings will be plain 7-bit ASCII, and thus not in need of conversion,
|
1626
|
+
* in such cases. (In particular, we disable localization of error messages
|
1627
|
+
* to help ensure that's true.)
|
1628
|
+
*/
|
1629
|
+
|
1630
|
+
|
1631
|
+
/*
|
1632
|
+
* Write error report to client
|
1633
|
+
*/
|
1634
|
+
static void send_message_to_frontend(ErrorData *edata) {}
|
1635
|
+
|
1636
|
+
|
1637
|
+
|
1638
|
+
/*
|
1639
|
+
* Support routines for formatting error messages.
|
1640
|
+
*/
|
1641
|
+
|
1642
|
+
|
1643
|
+
/*
|
1644
|
+
* error_severity --- get string representing elevel
|
1645
|
+
*
|
1646
|
+
* The string is not localized here, but we mark the strings for translation
|
1647
|
+
* so that callers can invoke _() on the result.
|
1648
|
+
*/
|
1649
|
+
|
1650
|
+
|
1651
|
+
|
1652
|
+
/*
|
1653
|
+
* append_with_tabs
|
1654
|
+
*
|
1655
|
+
* Append the string to the StringInfo buffer, inserting a tab after any
|
1656
|
+
* newline.
|
1657
|
+
*/
|
1658
|
+
|
1659
|
+
|
1660
|
+
|
1661
|
+
/*
|
1662
|
+
* Write errors to stderr (or by equal means when stderr is
|
1663
|
+
* not available). Used before ereport/elog can be used
|
1664
|
+
* safely (memory context, GUC load etc)
|
1665
|
+
*/
|
1666
|
+
void
|
1667
|
+
write_stderr(const char *fmt,...)
|
1668
|
+
{
|
1669
|
+
va_list ap;
|
1670
|
+
|
1671
|
+
#ifdef WIN32
|
1672
|
+
char errbuf[2048]; /* Arbitrary size? */
|
1673
|
+
#endif
|
1674
|
+
|
1675
|
+
fmt = _(fmt);
|
1676
|
+
|
1677
|
+
va_start(ap, fmt);
|
1678
|
+
#ifndef WIN32
|
1679
|
+
/* On Unix, we just fprintf to stderr */
|
1680
|
+
vfprintf(stderr, fmt, ap);
|
1681
|
+
fflush(stderr);
|
1682
|
+
#else
|
1683
|
+
vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
|
1684
|
+
|
1685
|
+
/*
|
1686
|
+
* On Win32, we print to stderr if running on a console, or write to
|
1687
|
+
* eventlog if running as a service
|
1688
|
+
*/
|
1689
|
+
if (pgwin32_is_service()) /* Running as a service */
|
1690
|
+
{
|
1691
|
+
write_eventlog(ERROR, errbuf, strlen(errbuf));
|
1692
|
+
}
|
1693
|
+
else
|
1694
|
+
{
|
1695
|
+
/* Not running as service, write to stderr */
|
1696
|
+
write_console(errbuf, strlen(errbuf));
|
1697
|
+
fflush(stderr);
|
1698
|
+
}
|
1699
|
+
#endif
|
1700
|
+
va_end(ap);
|
1701
|
+
}
|
1702
|
+
|
1703
|
+
|
1704
|
+
/*
|
1705
|
+
* is_log_level_output -- is elevel logically >= log_min_level?
|
1706
|
+
*
|
1707
|
+
* We use this for tests that should consider LOG to sort out-of-order,
|
1708
|
+
* between ERROR and FATAL. Generally this is the right thing for testing
|
1709
|
+
* whether a message should go to the postmaster log, whereas a simple >=
|
1710
|
+
* test is correct for testing whether the message should go to the client.
|
1711
|
+
*/
|
1712
|
+
static bool
|
1713
|
+
is_log_level_output(int elevel, int log_min_level)
|
1714
|
+
{
|
1715
|
+
if (elevel == LOG || elevel == LOG_SERVER_ONLY)
|
1716
|
+
{
|
1717
|
+
if (log_min_level == LOG || log_min_level <= ERROR)
|
1718
|
+
return true;
|
1719
|
+
}
|
1720
|
+
else if (log_min_level == LOG)
|
1721
|
+
{
|
1722
|
+
/* elevel != LOG */
|
1723
|
+
if (elevel >= FATAL)
|
1724
|
+
return true;
|
1725
|
+
}
|
1726
|
+
/* Neither is LOG */
|
1727
|
+
else if (elevel >= log_min_level)
|
1728
|
+
return true;
|
1729
|
+
|
1730
|
+
return false;
|
1731
|
+
}
|
1732
|
+
|
1733
|
+
/*
|
1734
|
+
* Adjust the level of a recovery-related message per trace_recovery_messages.
|
1735
|
+
*
|
1736
|
+
* The argument is the default log level of the message, eg, DEBUG2. (This
|
1737
|
+
* should only be applied to DEBUGn log messages, otherwise it's a no-op.)
|
1738
|
+
* If the level is >= trace_recovery_messages, we return LOG, causing the
|
1739
|
+
* message to be logged unconditionally (for most settings of
|
1740
|
+
* log_min_messages). Otherwise, we return the argument unchanged.
|
1741
|
+
* The message will then be shown based on the setting of log_min_messages.
|
1742
|
+
*
|
1743
|
+
* Intention is to keep this for at least the whole of the 9.0 production
|
1744
|
+
* release, so we can more easily diagnose production problems in the field.
|
1745
|
+
* It should go away eventually, though, because it's an ugly and
|
1746
|
+
* hard-to-explain kluge.
|
1747
|
+
*/
|
1748
|
+
|