pg_query 6.0.0 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -1
  3. data/README.md +1 -1
  4. data/Rakefile +5 -4
  5. data/ext/pg_query/ext_symbols_freebsd_with_ruby_abi_version.sym +2 -0
  6. data/ext/pg_query/ext_symbols_openbsd.sym +1 -0
  7. data/ext/pg_query/ext_symbols_openbsd_with_ruby_abi_version.sym +2 -0
  8. data/ext/pg_query/ext_symbols_with_ruby_abi_version.sym +2 -0
  9. data/ext/pg_query/extconf.rb +21 -7
  10. data/ext/pg_query/include/pg_query.h +32 -2
  11. data/ext/pg_query/include/postgres/access/amapi.h +5 -1
  12. data/ext/pg_query/include/postgres/access/genam.h +9 -0
  13. data/ext/pg_query/include/postgres/access/slru.h +4 -7
  14. data/ext/pg_query/include/postgres/access/tableam.h +13 -5
  15. data/ext/pg_query/include/postgres/access/transam.h +43 -0
  16. data/ext/pg_query/include/postgres/access/xlog.h +1 -0
  17. data/ext/pg_query/include/postgres/access/xlogdefs.h +2 -1
  18. data/ext/pg_query/include/postgres/c.h +1 -1
  19. data/ext/pg_query/include/postgres/catalog/objectaddress.h +4 -0
  20. data/ext/pg_query/include/postgres/commands/defrem.h +1 -1
  21. data/ext/pg_query/include/postgres/commands/event_trigger.h +6 -0
  22. data/ext/pg_query/include/postgres/commands/trigger.h +18 -0
  23. data/ext/pg_query/include/postgres/common/hashfn_unstable.h +6 -52
  24. data/ext/pg_query/include/postgres/datatype/timestamp.h +1 -1
  25. data/ext/pg_query/include/postgres/executor/execdesc.h +1 -1
  26. data/ext/pg_query/include/postgres/executor/executor.h +4 -0
  27. data/ext/pg_query/include/postgres/libpq/libpq-be.h +6 -3
  28. data/ext/pg_query/include/postgres/mb/pg_wchar.h +3 -0
  29. data/ext/pg_query/include/postgres/miscadmin.h +12 -3
  30. data/ext/pg_query/include/postgres/nodes/execnodes.h +9 -8
  31. data/ext/pg_query/include/postgres/nodes/pathnodes.h +3 -1
  32. data/ext/pg_query/include/postgres/nodes/pg_list.h +1 -1
  33. data/ext/pg_query/include/postgres/nodes/primnodes.h +9 -5
  34. data/ext/pg_query/include/postgres/parser/parse_coerce.h +3 -0
  35. data/ext/pg_query/include/postgres/pg_config.h +32 -23
  36. data/ext/pg_query/include/postgres/pg_config_manual.h +2 -0
  37. data/ext/pg_query/include/postgres/port/atomics/generic-gcc.h +10 -2
  38. data/ext/pg_query/include/postgres/port/pg_iovec.h +11 -5
  39. data/ext/pg_query/include/postgres/port/win32_port.h +0 -2
  40. data/ext/pg_query/include/postgres/port.h +32 -1
  41. data/ext/pg_query/include/postgres/replication/reorderbuffer.h +38 -27
  42. data/ext/pg_query/include/postgres/replication/slot.h +7 -1
  43. data/ext/pg_query/include/postgres/storage/lockdefs.h +2 -0
  44. data/ext/pg_query/include/postgres/storage/proc.h +13 -16
  45. data/ext/pg_query/include/postgres/storage/smgr.h +5 -2
  46. data/ext/pg_query/include/postgres/utils/catcache.h +1 -0
  47. data/ext/pg_query/include/postgres/utils/elog.h +1 -0
  48. data/ext/pg_query/include/postgres/utils/guc.h +1 -1
  49. data/ext/pg_query/include/postgres/utils/guc_hooks.h +0 -2
  50. data/ext/pg_query/include/postgres/utils/pg_locale.h +5 -0
  51. data/ext/pg_query/include/postgres/utils/pgstat_internal.h +19 -0
  52. data/ext/pg_query/include/postgres/utils/portal.h +1 -1
  53. data/ext/pg_query/include/postgres/utils/syscache.h +5 -0
  54. data/ext/pg_query/include/postgres_deparse.h +34 -0
  55. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +673 -516
  56. data/ext/pg_query/pg_query.pb-c.c +488 -0
  57. data/ext/pg_query/pg_query_deparse.c +148 -15
  58. data/ext/pg_query/pg_query_internal.h +9 -8
  59. data/ext/pg_query/pg_query_is_utility_stmt.c +70 -0
  60. data/ext/pg_query/pg_query_normalize.c +3 -0
  61. data/ext/pg_query/pg_query_raw_tree_walker_supports.c +117 -0
  62. data/ext/pg_query/pg_query_ruby.c +150 -0
  63. data/ext/pg_query/pg_query_summary.c +941 -0
  64. data/ext/pg_query/pg_query_summary.h +109 -0
  65. data/ext/pg_query/pg_query_summary_statement_type.c +797 -0
  66. data/ext/pg_query/pg_query_summary_truncate.c +530 -0
  67. data/ext/pg_query/postgres_deparse.c +4531 -3879
  68. data/ext/pg_query/src_backend_catalog_namespace.c +29 -0
  69. data/ext/pg_query/src_backend_nodes_bitmapset.c +84 -1
  70. data/ext/pg_query/src_backend_nodes_list.c +60 -1
  71. data/ext/pg_query/src_backend_parser_gram.c +740 -733
  72. data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +2 -2
  73. data/ext/pg_query/src_backend_utils_error_elog.c +11 -0
  74. data/ext/pg_query/src_backend_utils_mb_mbutils.c +43 -4
  75. data/ext/pg_query/src_backend_utils_mmgr_alignedalloc.c +22 -7
  76. data/ext/pg_query/src_backend_utils_mmgr_aset.c +3 -3
  77. data/ext/pg_query/src_backend_utils_mmgr_bump.c +1 -1
  78. data/ext/pg_query/src_common_stringinfo.c +20 -0
  79. data/ext/pg_query/src_common_wchar.c +93 -7
  80. data/ext/pg_query/src_port_snprintf.c +14 -17
  81. data/lib/pg_query/deparse.rb +29 -8
  82. data/lib/pg_query/fingerprint.rb +3 -5
  83. data/lib/pg_query/param_refs.rb +1 -1
  84. data/lib/pg_query/parse.rb +24 -7
  85. data/lib/pg_query/parse_error.rb +1 -0
  86. data/lib/pg_query/pg_query_pb.rb +8 -24
  87. data/lib/pg_query/scan.rb +1 -0
  88. data/lib/pg_query/split.rb +20 -0
  89. data/lib/pg_query/treewalker.rb +11 -13
  90. data/lib/pg_query/truncate.rb +17 -19
  91. data/lib/pg_query/version.rb +1 -1
  92. data/lib/pg_query.rb +1 -0
  93. metadata +23 -81
  94. data/ext/pg_query/postgres_deparse.h +0 -9
  95. /data/ext/pg_query/{pg_query_ruby.sym → ext_symbols.sym} +0 -0
  96. /data/ext/pg_query/{pg_query_ruby_freebsd.sym → ext_symbols_freebsd.sym} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85e421b39bee624275e2ff1d69ffe925cdcf0f288c63e8adbcadf2d5ca41454d
4
- data.tar.gz: 2feb313edc5c8497e26c79ea4f082d2a24556b89d2f276d20f174b532046d1b8
3
+ metadata.gz: 6368eb8723a3304d1a1d3c60cd51e91903b6d755cd6b7a6a74a1c7b0ddee0d1f
4
+ data.tar.gz: a5bc85ef1993dc502d600043c91901767facfafcaa0c0d811f4df6f401fac9d9
5
5
  SHA512:
6
- metadata.gz: ba036a7d58cd45c6f99b60c471f9cdbcf95db06f7f9b1512fac92044a030ac3c817871010b1d9fcd97d62465170432af1a8c83a931e1cdf7d9cb3cd6342d1701
7
- data.tar.gz: ce73c516573fdae71d8441eb4fc012c408467b53303b3f2a921aef5508660da5a5ab1f3debf6ffca9da8498943397b14dbd8f48b182fb7c35ec9bd7f84a518e0
6
+ metadata.gz: b5a7a69cd2224bed11134276a5f76d4e5cd2d3876e8b1613493e4e1ee67f9ec6409d5f2962f354a25352b678beaf98332b594067e8c80eeb16fb8fad25cf907a
7
+ data.tar.gz: 9db3709022d52488e135f4092dbf3c35c33ec88f01573780eb407587749369fb201e25f55e6a9ac9c236a2c2cde0c8af57f30824eaf5a93cdcc784c4c874f646
data/CHANGELOG.md CHANGED
@@ -4,6 +4,55 @@
4
4
 
5
5
  * ...
6
6
 
7
+ ## 6.2.1 2026-01-20
8
+
9
+ * Upgrade to libpg_query 17-6.2.1
10
+ - Add pg_query_is_utility_stmt function to determine if query text contains utility statements [#313](https://github.com/pganalyze/libpg_query/pull/313)
11
+ - This is a fast check for callers that don't actually need the parse tree itself
12
+ - Add fast summary information function (pg_query_summary)
13
+ - This allows gathering certain information, for example which tables are referenced in a
14
+ statement, without requiring a Protobuf serialization step in a higher level library
15
+ - Additionally this can also be used to perform "smart truncation" of a query by
16
+ omitting deeply nested information (e.g. a CTE definition, or a target list) whilst
17
+ preserving more essential parts like the FROM clause
18
+ - Deparser:
19
+ - Introduce pretty printing / formatting
20
+ - Introduces a new optional pretty print mode that emits a human readable
21
+ output. A detailed explanation of the mechanism can be found at the start
22
+ of the deparser file.
23
+ - Rework handling of expressions inside typecasts
24
+ - Prefer (..)::type syntax, unless we are already in a function call.
25
+ - Use lowercase keywords in xmlroot functions
26
+ - This matches other XML functions as well as the Postgres documentation,
27
+ since these are closer to function argument names than regular keywords.
28
+ - Fix deparse of ALTER TABLE a ALTER b SET STATISTICS DEFAULT
29
+ - Fix the null pointer dereference when handling identity columns
30
+ - Allow alternate definitions of NAMEDATALEN identifier limit
31
+ - This allows building libpg_query with an override of the built-time limit of
32
+ Postgres identifiers (typically 63 characters)
33
+ - Normalization: Add support for CALL statements
34
+ - Bump Postgres to 17.7 and switch back to release tarballs
35
+ * Deparser: Support pretty-printing and other deparser options
36
+ - `PgQuery::ParserResult#deparse` now takes options like `pretty_print`
37
+ * Add `PgQuery.split_with_parser` method to allow splitting statements
38
+ * Support Ruby 4.0+ development versions for extension building
39
+ * Fix ABI version error with TruffleRuby on Mac
40
+ * Support finding functions invoked with CALL
41
+ * Support null_test and boolean_test node type with parsing
42
+ * Expose `PgQuery::ParserResult#find_tree_location` method
43
+
44
+ ## 6.1.0 2025-04-02
45
+
46
+ * Upgrade to libpg_query 17-6.1.0
47
+ - Update to Postgres 17.4, and add recent patches scheduled for Postgres 17.5 (not yet released)
48
+ - Notably, this pulls in support for macOS 15.4 which defines strchrnul
49
+ in its standard library, fixing builds on up-to-date macOS versions.
50
+ - Deparser improvements
51
+ - Add parenthesis around AT LOCAL / AT TIMEZONE if needed
52
+ - Correctness improvements related to expressions and function calls
53
+ - Fixes to support newer Rubocop version linting of the codebase
54
+ - Add support for OpenBSD
55
+
7
56
  ## 6.0.0 2024-11-26
8
57
 
9
58
  * Upgrade to libpg_query 17-6.0.0
@@ -162,7 +211,7 @@
162
211
 
163
212
  * Update to libpg_query 13-2.0.6
164
213
  - Update to Postgres 13.3 patch release
165
- - Normalize: Don't touch "GROUP BY 1" and "ORDER BY 1" expressions, keep original text
214
+ - Normalize: Don't touch "GROUP BY 1" and "ORDER BY 1" expressions, keep original text
166
215
  - Fingerprint: Cache list item hashes to fingerprint complex queries faster
167
216
  - Deparser: Emit the RangeVar catalogname if present
168
217
  - Fix crash in pg_scan function when encountering backslash escapes
data/README.md CHANGED
@@ -178,11 +178,11 @@ not correctly handle all CTEs, or rewrite columns with explicit table names.
178
178
 
179
179
  Currently tested and officially supported Ruby versions:
180
180
 
181
- * CRuby 2.7
182
181
  * CRuby 3.0
183
182
  * CRuby 3.1
184
183
  * CRuby 3.2
185
184
  * CRuby 3.3
185
+ * CRuby 3.4
186
186
 
187
187
  Not supported:
188
188
 
data/Rakefile CHANGED
@@ -5,8 +5,8 @@ require 'rspec/core/rake_task'
5
5
  require 'rubocop/rake_task'
6
6
  require 'open-uri'
7
7
 
8
- LIB_PG_QUERY_TAG = '17-6.0.0'.freeze
9
- LIB_PG_QUERY_SHA256SUM = '98cf618ec94595d530c5fdff21c77cb2403187fd660993aeab4ad73ca06bbabd'.freeze
8
+ LIB_PG_QUERY_TAG = '17-6.2.1'.freeze
9
+ LIB_PG_QUERY_SHA256SUM = '678434d59511c8892c37ba5b9816ab641bd007cef2eda215b2297c39b79c861d'.freeze
10
10
 
11
11
  Rake::ExtensionTask.new 'pg_query' do |ext|
12
12
  ext.lib_dir = 'lib/pg_query'
@@ -55,7 +55,7 @@ task :update_source do
55
55
  # Backup important files from ext dir
56
56
  system("rm -fr #{extbakdir}")
57
57
  system("mkdir -p #{extbakdir}")
58
- system("cp -a #{extdir}/pg_query_ruby{.c,.sym,_freebsd.sym} #{extdir}/extconf.rb #{extbakdir}")
58
+ system("cp -a #{extdir}/pg_query_ruby.c #{extdir}/ext_symbols*.sym #{extdir}/extconf.rb #{extbakdir}")
59
59
 
60
60
  FileUtils.rm_rf extdir
61
61
 
@@ -66,6 +66,7 @@ task :update_source do
66
66
  system("mv #{extdir}/postgres/* #{extdir}/")
67
67
  system("rmdir #{extdir}/postgres")
68
68
  system("cp -a #{libdir}/pg_query.h #{extdir}/include")
69
+ system("cp -a #{libdir}/postgres_deparse.h #{extdir}/include")
69
70
  # Protobuf definitions
70
71
  system("protoc --proto_path=#{libdir}/protobuf --ruby_out=#{File.join(__dir__, 'lib/pg_query')} #{libdir}/protobuf/pg_query.proto")
71
72
  system("mkdir -p #{extdir}/include/protobuf")
@@ -84,5 +85,5 @@ task :update_source do
84
85
  # Other support files
85
86
  system("cp -a #{libdir}/testdata/* #{testfilesdir}")
86
87
  # Copy back the custom ext files
87
- system("cp -a #{extbakdir}/pg_query_ruby{.c,.sym,_freebsd.sym} #{extbakdir}/extconf.rb #{extdir}")
88
+ system("cp -a #{extbakdir}/pg_query_ruby.c #{extbakdir}/ext_symbols*.sym #{extbakdir}/extconf.rb #{extdir}")
88
89
  end
@@ -0,0 +1,2 @@
1
+ Init_pg_query
2
+ ruby_abi_version
@@ -0,0 +1 @@
1
+ Init_pg_query
@@ -0,0 +1,2 @@
1
+ Init_pg_query
2
+ ruby_abi_version
@@ -0,0 +1,2 @@
1
+ _Init_pg_query
2
+ _ruby_abi_version
@@ -21,15 +21,29 @@ if RUBY_PLATFORM =~ /mswin/
21
21
  $INCFLAGS = "-I#{File.join(__dir__, 'include', 'postgres', 'port', 'win32_msvc')} " + $INCFLAGS
22
22
  end
23
23
 
24
- SYMFILE =
25
- if RUBY_PLATFORM =~ /freebsd/
26
- File.join(__dir__, 'pg_query_ruby_freebsd.sym')
27
- elsif RUBY_PLATFORM !~ /cygwin|mswin|mingw|bccwin|wince|emx/
28
- File.join(__dir__, 'pg_query_ruby.sym')
29
- end
24
+ # "ruby_abi_version" is a required symbol to be exported on Ruby 3.2+ development releases
25
+ # See https://github.com/ruby/ruby/pull/5474 and https://github.com/ruby/ruby/pull/6231
26
+ def export_ruby_abi_version
27
+ return false if RUBY_PATCHLEVEL >= 0 # Not a development release
28
+ m = /(\d+)\.(\d+)/.match(RUBY_VERSION)
29
+ return false if m.nil?
30
+ major = m[1].to_i
31
+ minor = m[2].to_i
32
+ ((major >= 3 && minor >= 2) || major >= 4)
33
+ end
34
+
35
+ def ext_symbols_filename
36
+ name = 'ext_symbols'
37
+ name += '_freebsd' if RUBY_PLATFORM =~ /freebsd/
38
+ name += '_openbsd' if RUBY_PLATFORM =~ /openbsd/
39
+ name += '_with_ruby_abi_version' if export_ruby_abi_version
40
+ "#{name}.sym"
41
+ end
42
+
43
+ SYMFILE = File.join(__dir__, ext_symbols_filename)
30
44
 
31
45
  if RUBY_PLATFORM =~ /darwin/
32
- $DLDFLAGS << " -Wl,-exported_symbols_list #{SYMFILE}" unless defined?(::Rubinius)
46
+ $DLDFLAGS << " -Wl,-exported_symbols_list #{SYMFILE}" unless %w(rbx truffleruby).include?(RUBY_ENGINE)
33
47
  elsif RUBY_PLATFORM !~ /cygwin|mswin|mingw|bccwin|wince|emx/
34
48
  $DLDFLAGS << " -Wl,--retain-symbols-file=#{SYMFILE}"
35
49
  end
@@ -1,9 +1,12 @@
1
1
  #ifndef PG_QUERY_H
2
2
  #define PG_QUERY_H
3
3
 
4
+ #include <stdbool.h>
4
5
  #include <stdint.h>
5
6
  #include <sys/types.h>
6
7
 
8
+ #include "postgres_deparse.h"
9
+
7
10
  typedef struct {
8
11
  char* message; // exception message
9
12
  char* funcname; // source function of exception (e.g. SearchSysCache)
@@ -13,6 +16,12 @@ typedef struct {
13
16
  char* context; // additional context (optional, can be NULL)
14
17
  } PgQueryError;
15
18
 
19
+ typedef struct {
20
+ int length;
21
+ bool *items;
22
+ PgQueryError* error;
23
+ } PgQueryIsUtilityResult;
24
+
16
25
  typedef struct {
17
26
  size_t len;
18
27
  char* data;
@@ -53,6 +62,12 @@ typedef struct {
53
62
  PgQueryError* error;
54
63
  } PgQueryDeparseResult;
55
64
 
65
+ typedef struct {
66
+ PostgresDeparseComment **comments;
67
+ size_t comment_count;
68
+ PgQueryError* error;
69
+ } PgQueryDeparseCommentsResult;
70
+
56
71
  typedef struct {
57
72
  char* plpgsql_funcs;
58
73
  PgQueryError* error;
@@ -70,6 +85,12 @@ typedef struct {
70
85
  PgQueryError* error;
71
86
  } PgQueryNormalizeResult;
72
87
 
88
+ typedef struct {
89
+ PgQueryProtobuf summary;
90
+ char* stderr_buffer;
91
+ PgQueryError* error;
92
+ } PgQuerySummaryParseResult;
93
+
73
94
  // Postgres parser options (parse mode and GUCs that affect parsing)
74
95
 
75
96
  typedef enum
@@ -118,23 +139,32 @@ PgQuerySplitResult pg_query_split_with_scanner(const char *input);
118
139
  PgQuerySplitResult pg_query_split_with_parser(const char *input);
119
140
 
120
141
  PgQueryDeparseResult pg_query_deparse_protobuf(PgQueryProtobuf parse_tree);
142
+ PgQueryDeparseResult pg_query_deparse_protobuf_opts(PgQueryProtobuf parse_tree, struct PostgresDeparseOpts opts);
143
+ PgQueryDeparseCommentsResult pg_query_deparse_comments_for_query(const char *query);
144
+
145
+ PgQueryIsUtilityResult pg_query_is_utility_stmt(const char *query);
146
+
147
+ PgQuerySummaryParseResult pg_query_summary(const char* input, int parser_options, int truncate_limit);
121
148
 
122
149
  void pg_query_free_normalize_result(PgQueryNormalizeResult result);
123
150
  void pg_query_free_scan_result(PgQueryScanResult result);
124
151
  void pg_query_free_parse_result(PgQueryParseResult result);
125
152
  void pg_query_free_split_result(PgQuerySplitResult result);
126
153
  void pg_query_free_deparse_result(PgQueryDeparseResult result);
154
+ void pg_query_free_deparse_comments_result(PgQueryDeparseCommentsResult result);
127
155
  void pg_query_free_protobuf_parse_result(PgQueryProtobufParseResult result);
128
156
  void pg_query_free_plpgsql_parse_result(PgQueryPlpgsqlParseResult result);
129
157
  void pg_query_free_fingerprint_result(PgQueryFingerprintResult result);
158
+ void pg_query_free_is_utility_result(PgQueryIsUtilityResult result);
159
+ void pg_query_free_summary_parse_result(PgQuerySummaryParseResult result);
130
160
 
131
161
  // Optional, cleans up the top-level memory context (automatically done for threads that exit)
132
162
  void pg_query_exit(void);
133
163
 
134
164
  // Postgres version information
135
165
  #define PG_MAJORVERSION "17"
136
- #define PG_VERSION "17.0"
137
- #define PG_VERSION_NUM 170000
166
+ #define PG_VERSION "17.7"
167
+ #define PG_VERSION_NUM 170007
138
168
 
139
169
  // Deprecated APIs below
140
170
 
@@ -76,6 +76,10 @@ typedef enum IndexAMProperty
76
76
  * opfamily. This allows ALTER OPERATOR FAMILY DROP, and causes that to
77
77
  * happen automatically if the operator or support func is dropped. This
78
78
  * is the right behavior for inessential ("loose") objects.
79
+ *
80
+ * We also make dependencies on lefttype/righttype, of the same strength as
81
+ * the dependency on the operator or support func, unless these dependencies
82
+ * are redundant with the dependency on the operator or support func.
79
83
  */
80
84
  typedef struct OpFamilyMember
81
85
  {
@@ -267,7 +271,7 @@ typedef struct IndexAmRoutine
267
271
  ambuild_function ambuild;
268
272
  ambuildempty_function ambuildempty;
269
273
  aminsert_function aminsert;
270
- aminsertcleanup_function aminsertcleanup;
274
+ aminsertcleanup_function aminsertcleanup; /* can be NULL */
271
275
  ambulkdelete_function ambulkdelete;
272
276
  amvacuumcleanup_function amvacuumcleanup;
273
277
  amcanreturn_function amcanreturn; /* can be NULL */
@@ -233,5 +233,14 @@ extern SysScanDesc systable_beginscan_ordered(Relation heapRelation,
233
233
  extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan,
234
234
  ScanDirection direction);
235
235
  extern void systable_endscan_ordered(SysScanDesc sysscan);
236
+ extern void systable_inplace_update_begin(Relation relation,
237
+ Oid indexId,
238
+ bool indexOK,
239
+ Snapshot snapshot,
240
+ int nkeys, const ScanKeyData *key,
241
+ HeapTuple *oldtupcopy,
242
+ void **state);
243
+ extern void systable_inplace_update_finish(void *state, HeapTuple tuple);
244
+ extern void systable_inplace_update_cancel(void *state);
236
245
 
237
246
  #endif /* GENAM_H */
@@ -55,7 +55,7 @@ typedef enum
55
55
  /*
56
56
  * Shared-memory state
57
57
  *
58
- * ControlLock is used to protect access to the other fields, except
58
+ * SLRU bank locks are used to protect access to the other fields, except
59
59
  * latest_page_number, which uses atomics; see comment in slru.c.
60
60
  */
61
61
  typedef struct SlruSharedData
@@ -128,10 +128,8 @@ typedef struct SlruCtlData
128
128
  {
129
129
  SlruShared shared;
130
130
 
131
- /*
132
- * Bitmask to determine bank number from page number.
133
- */
134
- bits16 bank_mask;
131
+ /* Number of banks in this SLRU. */
132
+ uint16 nbanks;
135
133
 
136
134
  /*
137
135
  * If true, use long segment file names. Otherwise, use short file names.
@@ -163,7 +161,6 @@ typedef struct SlruCtlData
163
161
  * it's always the same, it doesn't need to be in shared memory.
164
162
  */
165
163
  char Dir[64];
166
-
167
164
  } SlruCtlData;
168
165
 
169
166
  typedef SlruCtlData *SlruCtl;
@@ -179,7 +176,7 @@ SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
179
176
  {
180
177
  int bankno;
181
178
 
182
- bankno = pageno & ctl->bank_mask;
179
+ bankno = pageno % ctl->nbanks;
183
180
  return &(ctl->shared->bank_locks[bankno].lock);
184
181
  }
185
182
 
@@ -129,7 +129,9 @@ typedef enum TU_UpdateIndexes
129
129
  /*
130
130
  * When table_tuple_update, table_tuple_delete, or table_tuple_lock fail
131
131
  * because the target tuple is already outdated, they fill in this struct to
132
- * provide information to the caller about what happened.
132
+ * provide information to the caller about what happened. When those functions
133
+ * succeed, the contents of this struct should not be relied upon, except for
134
+ * `traversed`, which may be set in both success and failure cases.
133
135
  *
134
136
  * ctid is the target's ctid link: it is the same as the target's TID if the
135
137
  * target was deleted, or the location of the replacement tuple if the target
@@ -137,13 +139,17 @@ typedef enum TU_UpdateIndexes
137
139
  *
138
140
  * xmax is the outdating transaction's XID. If the caller wants to visit the
139
141
  * replacement tuple, it must check that this matches before believing the
140
- * replacement is really a match.
142
+ * replacement is really a match. This is InvalidTransactionId if the target
143
+ * was !LP_NORMAL (expected only for a TID retrieved from syscache).
141
144
  *
142
145
  * cmax is the outdating command's CID, but only when the failure code is
143
146
  * TM_SelfModified (i.e., something in the current transaction outdated the
144
147
  * tuple); otherwise cmax is zero. (We make this restriction because
145
148
  * HeapTupleHeaderGetCmax doesn't work for tuples outdated in other
146
149
  * transactions.)
150
+ *
151
+ * traversed indicates if an update chain was followed in order to try to lock
152
+ * the target tuple. (This may be set in both success and failure cases.)
147
153
  */
148
154
  typedef struct TM_FailureData
149
155
  {
@@ -1548,7 +1554,7 @@ table_tuple_update(Relation rel, ItemPointer otid, TupleTableSlot *slot,
1548
1554
  *
1549
1555
  * Input parameters:
1550
1556
  * relation: relation containing tuple (caller must hold suitable lock)
1551
- * tid: TID of tuple to lock
1557
+ * tid: TID of tuple to lock (updated if an update chain was followed)
1552
1558
  * snapshot: snapshot to use for visibility determinations
1553
1559
  * cid: current command ID (used for visibility test, and stored into
1554
1560
  * tuple's cmax if lock is successful)
@@ -1573,8 +1579,10 @@ table_tuple_update(Relation rel, ItemPointer otid, TupleTableSlot *slot,
1573
1579
  * TM_WouldBlock: lock couldn't be acquired and wait_policy is skip
1574
1580
  *
1575
1581
  * In the failure cases other than TM_Invisible and TM_Deleted, the routine
1576
- * fills *tmfd with the tuple's t_ctid, t_xmax, and, if possible, t_cmax. See
1577
- * comments for struct TM_FailureData for additional info.
1582
+ * fills *tmfd with the tuple's t_ctid, t_xmax, and, if possible, t_cmax.
1583
+ * Additionally, in both success and failure cases, tmfd->traversed is set if
1584
+ * an update chain was followed. See comments for struct TM_FailureData for
1585
+ * additional info.
1578
1586
  */
1579
1587
  static inline TM_Result
1580
1588
  table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot,
@@ -370,6 +370,49 @@ FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
370
370
  return b;
371
371
  }
372
372
 
373
+ /*
374
+ * Compute FullTransactionId for the given TransactionId, assuming xid was
375
+ * between [oldestXid, nextXid] at the time when TransamVariables->nextXid was
376
+ * nextFullXid. When adding calls, evaluate what prevents xid from preceding
377
+ * oldestXid if SetTransactionIdLimit() runs between the collection of xid and
378
+ * the collection of nextFullXid.
379
+ */
380
+ static inline FullTransactionId
381
+ FullTransactionIdFromAllowableAt(FullTransactionId nextFullXid,
382
+ TransactionId xid)
383
+ {
384
+ uint32 epoch;
385
+
386
+ /* Special transaction ID. */
387
+ if (!TransactionIdIsNormal(xid))
388
+ return FullTransactionIdFromEpochAndXid(0, xid);
389
+
390
+ Assert(TransactionIdPrecedesOrEquals(xid,
391
+ XidFromFullTransactionId(nextFullXid)));
392
+
393
+ /*
394
+ * The 64 bit result must be <= nextFullXid, since nextFullXid hadn't been
395
+ * issued yet when xid was in the past. The xid must therefore be from
396
+ * the epoch of nextFullXid or the epoch before. We know this because we
397
+ * must remove (by freezing) an XID before assigning the XID half an epoch
398
+ * ahead of it.
399
+ *
400
+ * The unlikely() branch hint is dubious. It's perfect for the first 2^32
401
+ * XIDs of a cluster's life. Right at 2^32 XIDs, misprediction shoots to
402
+ * 100%, then improves until perfection returns 2^31 XIDs later. Since
403
+ * current callers pass relatively-recent XIDs, expect >90% prediction
404
+ * accuracy overall. This favors average latency over tail latency.
405
+ */
406
+ epoch = EpochFromFullTransactionId(nextFullXid);
407
+ if (unlikely(xid > XidFromFullTransactionId(nextFullXid)))
408
+ {
409
+ Assert(epoch != 0);
410
+ epoch--;
411
+ }
412
+
413
+ return FullTransactionIdFromEpochAndXid(epoch, xid);
414
+ }
415
+
373
416
  #endif /* FRONTEND */
374
417
 
375
418
  #endif /* TRANSAM_H */
@@ -265,6 +265,7 @@ extern void SwitchIntoArchiveRecovery(XLogRecPtr EndRecPtr, TimeLineID replayTLI
265
265
  extern void ReachedEndOfBackup(XLogRecPtr EndRecPtr, TimeLineID tli);
266
266
  extern void SetInstallXLogFileSegmentActive(void);
267
267
  extern bool IsInstallXLogFileSegmentActive(void);
268
+ extern void ResetInstallXLogFileSegmentActive(void);
268
269
  extern void XLogShutdownWalRcv(void);
269
270
 
270
271
  /*
@@ -25,7 +25,8 @@ typedef uint64 XLogRecPtr;
25
25
  * WAL segment, initializing the first WAL page at WAL segment size, so no XLOG
26
26
  * record can begin at zero.
27
27
  */
28
- #define InvalidXLogRecPtr 0
28
+ #define InvalidXLogRecPtr 0
29
+ #define XLogRecPtrIsValid(r) ((r) != InvalidXLogRecPtr)
29
30
  #define XLogRecPtrIsInvalid(r) ((r) == InvalidXLogRecPtr)
30
31
 
31
32
  /*
@@ -435,7 +435,7 @@ typedef void (*pg_funcptr_t) (void);
435
435
  * bool
436
436
  * Boolean value, either true or false.
437
437
  *
438
- * We use stdbool.h if available and its bool has size 1. That's useful for
438
+ * We use stdbool.h if bool has size 1 after including it. That's useful for
439
439
  * better compiler and debugger output and for compatibility with third-party
440
440
  * libraries. But PostgreSQL currently cannot deal with bool of other sizes;
441
441
  * there are static assertions around the code to prevent that.
@@ -69,6 +69,10 @@ extern bool get_object_namensp_unique(Oid class_id);
69
69
 
70
70
  extern HeapTuple get_catalog_object_by_oid(Relation catalog,
71
71
  AttrNumber oidcol, Oid objectId);
72
+ extern HeapTuple get_catalog_object_by_oid_extended(Relation catalog,
73
+ AttrNumber oidcol,
74
+ Oid objectId,
75
+ bool locktup);
72
76
 
73
77
  extern char *getObjectDescription(const ObjectAddress *object,
74
78
  bool missing_ok);
@@ -81,7 +81,7 @@ extern void RemoveOperatorById(Oid operOid);
81
81
  extern ObjectAddress AlterOperator(AlterOperatorStmt *stmt);
82
82
 
83
83
  /* commands/statscmds.c */
84
- extern ObjectAddress CreateStatistics(CreateStatsStmt *stmt);
84
+ extern ObjectAddress CreateStatistics(CreateStatsStmt *stmt, bool check_rights);
85
85
  extern ObjectAddress AlterStatistics(AlterStatsStmt *stmt);
86
86
  extern void RemoveStatisticsById(Oid statsOid);
87
87
  extern void RemoveStatisticsDataById(Oid statsOid, bool inh);
@@ -31,6 +31,12 @@ typedef struct EventTriggerData
31
31
 
32
32
  extern PGDLLIMPORT bool event_triggers;
33
33
 
34
+ /*
35
+ * Reasons for relation rewrites.
36
+ *
37
+ * pg_event_trigger_table_rewrite_reason() uses these values, so make sure to
38
+ * update the documentation when changing this list.
39
+ */
34
40
  #define AT_REWRITE_ALTER_PERSISTENCE 0x01
35
41
  #define AT_REWRITE_DEFAULT_VAL 0x02
36
42
  #define AT_REWRITE_COLUMN_REWRITE 0x04
@@ -206,6 +206,15 @@ extern void ExecBSDeleteTriggers(EState *estate,
206
206
  extern void ExecASDeleteTriggers(EState *estate,
207
207
  ResultRelInfo *relinfo,
208
208
  TransitionCaptureState *transition_capture);
209
+ extern bool ExecBRDeleteTriggersNew(EState *estate,
210
+ EPQState *epqstate,
211
+ ResultRelInfo *relinfo,
212
+ ItemPointer tupleid,
213
+ HeapTuple fdw_trigtuple,
214
+ TupleTableSlot **epqslot,
215
+ TM_Result *tmresult,
216
+ TM_FailureData *tmfd,
217
+ bool is_merge_delete);
209
218
  extern bool ExecBRDeleteTriggers(EState *estate,
210
219
  EPQState *epqstate,
211
220
  ResultRelInfo *relinfo,
@@ -228,6 +237,15 @@ extern void ExecBSUpdateTriggers(EState *estate,
228
237
  extern void ExecASUpdateTriggers(EState *estate,
229
238
  ResultRelInfo *relinfo,
230
239
  TransitionCaptureState *transition_capture);
240
+ extern bool ExecBRUpdateTriggersNew(EState *estate,
241
+ EPQState *epqstate,
242
+ ResultRelInfo *relinfo,
243
+ ItemPointer tupleid,
244
+ HeapTuple fdw_trigtuple,
245
+ TupleTableSlot *newslot,
246
+ TM_Result *tmresult,
247
+ TM_FailureData *tmfd,
248
+ bool is_merge_update);
231
249
  extern bool ExecBRUpdateTriggers(EState *estate,
232
250
  EPQState *epqstate,
233
251
  ResultRelInfo *relinfo,
@@ -14,8 +14,6 @@
14
14
  #ifndef HASHFN_UNSTABLE_H
15
15
  #define HASHFN_UNSTABLE_H
16
16
 
17
- #include "port/pg_bitutils.h"
18
- #include "port/pg_bswap.h"
19
17
 
20
18
  /*
21
19
  * fasthash is a modification of code taken from
@@ -219,13 +217,6 @@ fasthash_accum(fasthash_state *hs, const char *k, size_t len)
219
217
  #define haszero64(v) \
220
218
  (((v) - 0x0101010101010101) & ~(v) & 0x8080808080808080)
221
219
 
222
- /* get first byte in memory order */
223
- #ifdef WORDS_BIGENDIAN
224
- #define firstbyte64(v) ((v) >> 56)
225
- #else
226
- #define firstbyte64(v) ((v) & 0xFF)
227
- #endif
228
-
229
220
  /*
230
221
  * all-purpose workhorse for fasthash_accum_cstring
231
222
  */
@@ -262,33 +253,20 @@ static inline size_t
262
253
  fasthash_accum_cstring_aligned(fasthash_state *hs, const char *str)
263
254
  {
264
255
  const char *const start = str;
265
- uint64 chunk;
256
+ size_t remainder;
266
257
  uint64 zero_byte_low;
267
258
 
268
259
  Assert(PointerIsAligned(start, uint64));
269
260
 
270
261
  /*
271
262
  * For every chunk of input, check for zero bytes before mixing into the
272
- * hash. The chunk with zeros must contain the NUL terminator. We arrange
273
- * so that zero_byte_low tells us not only that a zero exists, but also
274
- * where it is, so we can hash the remainder of the string.
275
- *
276
- * The haszero64 calculation will set bits corresponding to the lowest
277
- * byte where a zero exists, so that suffices for little-endian machines.
278
- * For big-endian machines, we would need bits set for the highest zero
279
- * byte in the chunk, since the trailing junk past the terminator could
280
- * contain additional zeros. haszero64 does not give us that, so we
281
- * byteswap the chunk first.
263
+ * hash. The chunk with zeros must contain the NUL terminator.
282
264
  */
283
265
  for (;;)
284
266
  {
285
- chunk = *(uint64 *) str;
267
+ uint64 chunk = *(uint64 *) str;
286
268
 
287
- #ifdef WORDS_BIGENDIAN
288
- zero_byte_low = haszero64(pg_bswap64(chunk));
289
- #else
290
269
  zero_byte_low = haszero64(chunk);
291
- #endif
292
270
  if (zero_byte_low)
293
271
  break;
294
272
 
@@ -297,33 +275,9 @@ fasthash_accum_cstring_aligned(fasthash_state *hs, const char *str)
297
275
  str += FH_SIZEOF_ACCUM;
298
276
  }
299
277
 
300
- if (firstbyte64(chunk) != 0)
301
- {
302
- size_t remainder;
303
- uint64 mask;
304
-
305
- /*
306
- * The byte corresponding to the NUL will be 0x80, so the rightmost
307
- * bit position will be in the range 15, 23, ..., 63. Turn this into
308
- * byte position by dividing by 8.
309
- */
310
- remainder = pg_rightmost_one_pos64(zero_byte_low) / BITS_PER_BYTE;
311
-
312
- /*
313
- * Create a mask for the remaining bytes so we can combine them into
314
- * the hash. This must have the same result as mixing the remaining
315
- * bytes with fasthash_accum().
316
- */
317
- #ifdef WORDS_BIGENDIAN
318
- mask = ~UINT64CONST(0) << BITS_PER_BYTE * (FH_SIZEOF_ACCUM - remainder);
319
- #else
320
- mask = ~UINT64CONST(0) >> BITS_PER_BYTE * (FH_SIZEOF_ACCUM - remainder);
321
- #endif
322
- hs->accum = chunk & mask;
323
- fasthash_combine(hs);
324
-
325
- str += remainder;
326
- }
278
+ /* mix in remaining bytes */
279
+ remainder = fasthash_accum_cstring_unaligned(hs, str);
280
+ str += remainder;
327
281
 
328
282
  return str - start;
329
283
  }
@@ -136,7 +136,7 @@ struct pg_itm_in
136
136
  /*
137
137
  * We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
138
138
  * Currently, the record holders for wackiest offsets in actual use are zones
139
- * Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42
139
+ * Asia/Manila, at -15:56:08 until 1844, and America/Metlakatla, at +15:13:42
140
140
  * until 1867. If we were to reject such values we would fail to dump and
141
141
  * restore old timestamptz values with these zone settings.
142
142
  */
@@ -48,7 +48,7 @@ typedef struct QueryDesc
48
48
  EState *estate; /* executor's query-wide state */
49
49
  PlanState *planstate; /* tree of per-plan-node state */
50
50
 
51
- /* This field is set by ExecutorRun */
51
+ /* This field is set by ExecutePlan */
52
52
  bool already_executed; /* true if previously executed */
53
53
 
54
54
  /* This is always set NULL by the core system, but plugins can change it */