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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -1
- data/README.md +1 -1
- data/Rakefile +5 -4
- data/ext/pg_query/ext_symbols_freebsd_with_ruby_abi_version.sym +2 -0
- data/ext/pg_query/ext_symbols_openbsd.sym +1 -0
- data/ext/pg_query/ext_symbols_openbsd_with_ruby_abi_version.sym +2 -0
- data/ext/pg_query/ext_symbols_with_ruby_abi_version.sym +2 -0
- data/ext/pg_query/extconf.rb +21 -7
- data/ext/pg_query/include/pg_query.h +32 -2
- data/ext/pg_query/include/postgres/access/amapi.h +5 -1
- data/ext/pg_query/include/postgres/access/genam.h +9 -0
- data/ext/pg_query/include/postgres/access/slru.h +4 -7
- data/ext/pg_query/include/postgres/access/tableam.h +13 -5
- data/ext/pg_query/include/postgres/access/transam.h +43 -0
- data/ext/pg_query/include/postgres/access/xlog.h +1 -0
- data/ext/pg_query/include/postgres/access/xlogdefs.h +2 -1
- data/ext/pg_query/include/postgres/c.h +1 -1
- data/ext/pg_query/include/postgres/catalog/objectaddress.h +4 -0
- data/ext/pg_query/include/postgres/commands/defrem.h +1 -1
- data/ext/pg_query/include/postgres/commands/event_trigger.h +6 -0
- data/ext/pg_query/include/postgres/commands/trigger.h +18 -0
- data/ext/pg_query/include/postgres/common/hashfn_unstable.h +6 -52
- data/ext/pg_query/include/postgres/datatype/timestamp.h +1 -1
- data/ext/pg_query/include/postgres/executor/execdesc.h +1 -1
- data/ext/pg_query/include/postgres/executor/executor.h +4 -0
- data/ext/pg_query/include/postgres/libpq/libpq-be.h +6 -3
- data/ext/pg_query/include/postgres/mb/pg_wchar.h +3 -0
- data/ext/pg_query/include/postgres/miscadmin.h +12 -3
- data/ext/pg_query/include/postgres/nodes/execnodes.h +9 -8
- data/ext/pg_query/include/postgres/nodes/pathnodes.h +3 -1
- data/ext/pg_query/include/postgres/nodes/pg_list.h +1 -1
- data/ext/pg_query/include/postgres/nodes/primnodes.h +9 -5
- data/ext/pg_query/include/postgres/parser/parse_coerce.h +3 -0
- data/ext/pg_query/include/postgres/pg_config.h +32 -23
- data/ext/pg_query/include/postgres/pg_config_manual.h +2 -0
- data/ext/pg_query/include/postgres/port/atomics/generic-gcc.h +10 -2
- data/ext/pg_query/include/postgres/port/pg_iovec.h +11 -5
- data/ext/pg_query/include/postgres/port/win32_port.h +0 -2
- data/ext/pg_query/include/postgres/port.h +32 -1
- data/ext/pg_query/include/postgres/replication/reorderbuffer.h +38 -27
- data/ext/pg_query/include/postgres/replication/slot.h +7 -1
- data/ext/pg_query/include/postgres/storage/lockdefs.h +2 -0
- data/ext/pg_query/include/postgres/storage/proc.h +13 -16
- data/ext/pg_query/include/postgres/storage/smgr.h +5 -2
- data/ext/pg_query/include/postgres/utils/catcache.h +1 -0
- data/ext/pg_query/include/postgres/utils/elog.h +1 -0
- data/ext/pg_query/include/postgres/utils/guc.h +1 -1
- data/ext/pg_query/include/postgres/utils/guc_hooks.h +0 -2
- data/ext/pg_query/include/postgres/utils/pg_locale.h +5 -0
- data/ext/pg_query/include/postgres/utils/pgstat_internal.h +19 -0
- data/ext/pg_query/include/postgres/utils/portal.h +1 -1
- data/ext/pg_query/include/postgres/utils/syscache.h +5 -0
- data/ext/pg_query/include/postgres_deparse.h +34 -0
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +673 -516
- data/ext/pg_query/pg_query.pb-c.c +488 -0
- data/ext/pg_query/pg_query_deparse.c +148 -15
- data/ext/pg_query/pg_query_internal.h +9 -8
- data/ext/pg_query/pg_query_is_utility_stmt.c +70 -0
- data/ext/pg_query/pg_query_normalize.c +3 -0
- data/ext/pg_query/pg_query_raw_tree_walker_supports.c +117 -0
- data/ext/pg_query/pg_query_ruby.c +150 -0
- data/ext/pg_query/pg_query_summary.c +941 -0
- data/ext/pg_query/pg_query_summary.h +109 -0
- data/ext/pg_query/pg_query_summary_statement_type.c +797 -0
- data/ext/pg_query/pg_query_summary_truncate.c +530 -0
- data/ext/pg_query/postgres_deparse.c +4531 -3879
- data/ext/pg_query/src_backend_catalog_namespace.c +29 -0
- data/ext/pg_query/src_backend_nodes_bitmapset.c +84 -1
- data/ext/pg_query/src_backend_nodes_list.c +60 -1
- data/ext/pg_query/src_backend_parser_gram.c +740 -733
- data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +2 -2
- data/ext/pg_query/src_backend_utils_error_elog.c +11 -0
- data/ext/pg_query/src_backend_utils_mb_mbutils.c +43 -4
- data/ext/pg_query/src_backend_utils_mmgr_alignedalloc.c +22 -7
- data/ext/pg_query/src_backend_utils_mmgr_aset.c +3 -3
- data/ext/pg_query/src_backend_utils_mmgr_bump.c +1 -1
- data/ext/pg_query/src_common_stringinfo.c +20 -0
- data/ext/pg_query/src_common_wchar.c +93 -7
- data/ext/pg_query/src_port_snprintf.c +14 -17
- data/lib/pg_query/deparse.rb +29 -8
- data/lib/pg_query/fingerprint.rb +3 -5
- data/lib/pg_query/param_refs.rb +1 -1
- data/lib/pg_query/parse.rb +24 -7
- data/lib/pg_query/parse_error.rb +1 -0
- data/lib/pg_query/pg_query_pb.rb +8 -24
- data/lib/pg_query/scan.rb +1 -0
- data/lib/pg_query/split.rb +20 -0
- data/lib/pg_query/treewalker.rb +11 -13
- data/lib/pg_query/truncate.rb +17 -19
- data/lib/pg_query/version.rb +1 -1
- data/lib/pg_query.rb +1 -0
- metadata +23 -81
- data/ext/pg_query/postgres_deparse.h +0 -9
- /data/ext/pg_query/{pg_query_ruby.sym → ext_symbols.sym} +0 -0
- /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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6368eb8723a3304d1a1d3c60cd51e91903b6d755cd6b7a6a74a1c7b0ddee0d1f
|
|
4
|
+
data.tar.gz: a5bc85ef1993dc502d600043c91901767facfafcaa0c0d811f4df6f401fac9d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
9
|
-
LIB_PG_QUERY_SHA256SUM = '
|
|
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
|
|
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
|
|
88
|
+
system("cp -a #{extbakdir}/pg_query_ruby.c #{extbakdir}/ext_symbols*.sym #{extbakdir}/extconf.rb #{extdir}")
|
|
88
89
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Init_pg_query
|
data/ext/pg_query/extconf.rb
CHANGED
|
@@ -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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
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.
|
|
137
|
-
#define PG_VERSION_NUM
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
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.
|
|
1577
|
-
*
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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:
|
|
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
|
|
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 */
|