pg_query 2.1.4 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +32 -0
- data/Rakefile +2 -2
- data/ext/pg_query/include/access/twophase.h +2 -0
- data/ext/pg_query/include/access/xact.h +6 -0
- data/ext/pg_query/include/access/xlog_internal.h +10 -1
- data/ext/pg_query/include/access/xlogreader.h +10 -0
- data/ext/pg_query/include/catalog/dependency.h +2 -0
- data/ext/pg_query/include/catalog/pg_class.h +1 -1
- data/ext/pg_query/include/catalog/pg_class_d.h +1 -1
- data/ext/pg_query/include/catalog/pg_control.h +2 -0
- data/ext/pg_query/include/catalog/pg_operator.h +3 -1
- data/ext/pg_query/include/catalog/pg_publication.h +3 -0
- data/ext/pg_query/include/catalog/pg_type.h +1 -0
- data/ext/pg_query/include/commands/async.h +1 -1
- data/ext/pg_query/include/commands/tablespace.h +2 -0
- data/ext/pg_query/include/commands/trigger.h +8 -0
- data/ext/pg_query/include/lib/simplehash.h +13 -13
- data/ext/pg_query/include/libpq/libpq.h +1 -0
- data/ext/pg_query/include/mb/pg_wchar.h +1 -0
- data/ext/pg_query/include/miscadmin.h +24 -11
- data/ext/pg_query/include/nodes/execnodes.h +2 -2
- data/ext/pg_query/include/nodes/parsenodes.h +5 -4
- data/ext/pg_query/include/nodes/pathnodes.h +2 -1
- data/ext/pg_query/include/nodes/pg_list.h +1 -0
- data/ext/pg_query/include/nodes/plannodes.h +18 -3
- data/ext/pg_query/include/optimizer/optimizer.h +0 -5
- data/ext/pg_query/include/parser/gram.h +2 -2
- data/ext/pg_query/include/parser/kwlist.h +1 -1
- data/ext/pg_query/include/parser/parse_coerce.h +1 -0
- data/ext/pg_query/include/pg_config.h +16 -13
- data/ext/pg_query/include/pg_query.h +2 -2
- data/ext/pg_query/include/pg_query_fingerprint_defs.c +286 -314
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +1 -0
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +1 -0
- data/ext/pg_query/include/pgstat.h +2 -1
- data/ext/pg_query/include/plpgsql.h +2 -2
- data/ext/pg_query/include/port/pg_bitutils.h +48 -2
- data/ext/pg_query/include/port.h +4 -0
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +4 -3
- data/ext/pg_query/include/replication/reorderbuffer.h +6 -5
- data/ext/pg_query/include/replication/slot.h +1 -1
- data/ext/pg_query/include/storage/block.h +1 -1
- data/ext/pg_query/include/storage/lock.h +6 -5
- data/ext/pg_query/include/storage/lwlock.h +1 -0
- data/ext/pg_query/include/storage/proc.h +14 -0
- data/ext/pg_query/include/storage/s_lock.h +24 -0
- data/ext/pg_query/include/tcop/pquery.h +6 -0
- data/ext/pg_query/include/utils/builtins.h +1 -0
- data/ext/pg_query/include/utils/inval.h +1 -0
- data/ext/pg_query/include/utils/portal.h +13 -0
- data/ext/pg_query/include/utils/rel.h +0 -1
- data/ext/pg_query/include/utils/relcache.h +1 -2
- data/ext/pg_query/include/utils/snapmgr.h +1 -0
- data/ext/pg_query/pg_query.pb-c.c +18 -5
- data/ext/pg_query/pg_query_deparse.c +8 -8
- data/ext/pg_query/pg_query_fingerprint.c +1 -0
- data/ext/pg_query/pg_query_json_plpgsql.c +68 -0
- data/ext/pg_query/pg_query_normalize.c +43 -7
- data/ext/pg_query/pg_query_outfuncs.h +1 -0
- data/ext/pg_query/pg_query_outfuncs_json.c +11 -0
- data/ext/pg_query/pg_query_parse_plpgsql.c +58 -15
- data/ext/pg_query/src_backend_catalog_namespace.c +1 -0
- data/ext/pg_query/src_backend_libpq_pqcomm.c +8 -0
- data/ext/pg_query/src_backend_nodes_copyfuncs.c +23 -33
- data/ext/pg_query/src_backend_nodes_equalfuncs.c +1 -0
- data/ext/pg_query/src_backend_nodes_list.c +12 -0
- data/ext/pg_query/src_backend_parser_gram.c +18 -3
- data/ext/pg_query/src_backend_parser_scan.c +493 -253
- data/ext/pg_query/src_backend_tcop_postgres.c +11 -1
- data/ext/pg_query/src_backend_utils_adt_ruleutils.c +38 -10
- data/ext/pg_query/src_backend_utils_misc_guc.c +1 -0
- data/ext/pg_query/src_common_wchar.c +11 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +4 -2
- data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1 -1
- data/ext/pg_query/src_port_pg_bitutils.c +1 -22
- data/ext/pg_query/src_port_snprintf.c +9 -7
- data/lib/pg_query/deparse.rb +7 -1
- data/lib/pg_query/fingerprint.rb +13 -2
- data/lib/pg_query/parse.rb +5 -3
- data/lib/pg_query/pg_query_pb.rb +2 -1
- data/lib/pg_query/treewalker.rb +6 -0
- data/lib/pg_query/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9625ed6fd4d8f67673ee922f191996d2c157addf6d97aa092af682a21bf96ce7
|
4
|
+
data.tar.gz: 9a20dedc0420e5a7f2162c642c2ddee60cd98fd6bbfeff1b1affc181f6dcbc27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f4633dd45e1530cebc92731315a238f22e4111ba23e10ea6991b6466f444ce2b974ffd858aaf5c93c5b6597e004e0b2334ac1832c24851956e34dd629fe58ff
|
7
|
+
data.tar.gz: 36d225dc15a58db4336cdbdd571a385308403b93d5507ec25b0deb5179be87b8a00fb029b1e5b77bdf62f79861fedd39ba350a50897bcfec4d61e266b2cdf639
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,34 @@
|
|
4
4
|
|
5
5
|
* ...
|
6
6
|
|
7
|
+
## 2.2.1 2022-01-20
|
8
|
+
|
9
|
+
* Detect tables used in the query of a PREPARE statement ([#273](https://github.com/pganalyze/pg_query/pull/273))
|
10
|
+
* Expose recursive walk functionality via walk! ([#268](https://github.com/pganalyze/pg_query/pull/268))
|
11
|
+
* Retain schema in name when parsing out functions ([#272](https://github.com/pganalyze/pg_query/pull/272))
|
12
|
+
|
13
|
+
## 2.2.0 2022-11-02
|
14
|
+
|
15
|
+
* Update to libpg_query 13-2.2.0 ([#264](https://github.com/pganalyze/pg_query/pull/264))
|
16
|
+
- Fingerprinting version 3.1
|
17
|
+
- Fixes issue with "SELECT DISTINCT" having the same fingerprint as "SELECT"
|
18
|
+
(fingerprints for "SELECT DISTINCT" will change with this revision)
|
19
|
+
- Group additional DDL statements together that otherwise generate a lot of
|
20
|
+
unique fingerprints (ListenStmt, UnlistenStmt, NotifyStmt, CreateFunctionStmt,
|
21
|
+
FunctionParameter and DoStmt)
|
22
|
+
- Deparser improvements
|
23
|
+
- Prefix errors with "deparse", and remove some asserts
|
24
|
+
- Fix potential segfault when passing invalid protobuf (RawStmt without Stmt)
|
25
|
+
- Update to Postgres 13.8 patch release
|
26
|
+
- Backport Xcode 14.1 build fix from upcoming 13.9 release
|
27
|
+
- Normalize additional DDL statements
|
28
|
+
- Add support for analyzing PL/pgSQL code inside DO blocks
|
29
|
+
- Fix memory leak in pg_query_fingerprint error handling
|
30
|
+
- PL/pgSQL parser: Add support for Assert, SET, COMMIT, ROLLBACK and CALL
|
31
|
+
- Add support for parsing more operators that include a `?` character
|
32
|
+
* Support deparsing deeply nested queries ([#259](https://github.com/pganalyze/pg_query/pull/259))
|
33
|
+
|
34
|
+
|
7
35
|
## 2.1.4 2022-09-19
|
8
36
|
|
9
37
|
* Truncate: Simplify VALUES(...) lists
|
@@ -13,6 +41,7 @@
|
|
13
41
|
* Find function calls referenced in expression indexes ([#249](https://github.com/pganalyze/pg_query/pull/249))
|
14
42
|
* Drop `Init_pg_query` from exported symbol map ([#256](https://github.com/pganalyze/pg_query/pull/256))
|
15
43
|
|
44
|
+
|
16
45
|
## 2.1.3 2022-01-28
|
17
46
|
|
18
47
|
* Track tables in EXCEPT and INTERSECT queries ([#239](https://github.com/pganalyze/pg_query/pull/239))
|
data/README.md
CHANGED
@@ -72,6 +72,8 @@ PgQuery.parse("SELECT 1")
|
|
72
72
|
|
73
73
|
### Modifying a parsed query and turning it into SQL again
|
74
74
|
|
75
|
+
This is a simple example for `deparse`, for more complex modification, use `walk!`.
|
76
|
+
|
75
77
|
```ruby
|
76
78
|
parsed_query = PgQuery.parse("SELECT * FROM users")
|
77
79
|
|
@@ -145,6 +147,36 @@ PgQuery.scan('SELECT 1 --comment')
|
|
145
147
|
[]]
|
146
148
|
```
|
147
149
|
|
150
|
+
### Walking the parse tree
|
151
|
+
|
152
|
+
For generalized use, PgQuery provides `walk!` as a means to recursively work with the parsed query.
|
153
|
+
|
154
|
+
This can be used to create a bespoke pretty printer:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
parsed_query = PgQuery.parse "SELECT * FROM tbl"
|
158
|
+
parsed_query.walk! { |node, k, v, location| puts k }
|
159
|
+
```
|
160
|
+
|
161
|
+
More usefully, this can be used to rewrite a query. For example:
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
parsed_query.walk! do |node, k, v, location| puts k
|
165
|
+
next unless k.eql?(:range_var) || k.eql?(:relation)
|
166
|
+
next if v.relname.nil?
|
167
|
+
v.relname = "X_" + v.relname
|
168
|
+
end
|
169
|
+
|
170
|
+
parsed_query.deparse
|
171
|
+
```
|
172
|
+
|
173
|
+
There are some caveats, and limitations, in this example.
|
174
|
+
|
175
|
+
First, some of the tree nodes are frozen. You can replace them, but you cannot modify in place.
|
176
|
+
|
177
|
+
Second, table rewriting is a bit more nuanced than this example. While this will rewrite the table names, it will
|
178
|
+
not correctly handle all CTEs, or rewrite columns with explicit table names.
|
179
|
+
|
148
180
|
## Differences from Upstream PostgreSQL
|
149
181
|
|
150
182
|
This gem is based on [libpg_query](https://github.com/pganalyze/libpg_query),
|
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 = '13-2.
|
9
|
-
LIB_PG_QUERY_SHA256SUM = '
|
8
|
+
LIB_PG_QUERY_TAG = '13-2.2.0'.freeze
|
9
|
+
LIB_PG_QUERY_SHA256SUM = '07916be1a2b780dee6feed936aaa04ccee2a3afde8570a6920c3a839c87539c6'.freeze
|
10
10
|
|
11
11
|
Rake::ExtensionTask.new 'pg_query' do |ext|
|
12
12
|
ext.lib_dir = 'lib/pg_query'
|
@@ -34,6 +34,8 @@ extern void TwoPhaseShmemInit(void);
|
|
34
34
|
extern void AtAbort_Twophase(void);
|
35
35
|
extern void PostPrepare_Twophase(void);
|
36
36
|
|
37
|
+
extern TransactionId TwoPhaseGetXidByVirtualXID(VirtualTransactionId vxid,
|
38
|
+
bool *have_more);
|
37
39
|
extern PGPROC *TwoPhaseGetDummyProc(TransactionId xid, bool lock_held);
|
38
40
|
extern BackendId TwoPhaseGetDummyBackendId(TransactionId xid, bool lock_held);
|
39
41
|
|
@@ -103,6 +103,12 @@ extern int MyXactFlags;
|
|
103
103
|
*/
|
104
104
|
#define XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK (1U << 1)
|
105
105
|
|
106
|
+
/*
|
107
|
+
* XACT_FLAGS_NEEDIMMEDIATECOMMIT - records whether the top level statement
|
108
|
+
* is one that requires immediate commit, such as CREATE DATABASE.
|
109
|
+
*/
|
110
|
+
#define XACT_FLAGS_NEEDIMMEDIATECOMMIT (1U << 2)
|
111
|
+
|
106
112
|
/*
|
107
113
|
* start- and end-of-transaction callbacks for dynamically loaded modules
|
108
114
|
*/
|
@@ -79,8 +79,10 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
|
|
79
79
|
#define XLP_LONG_HEADER 0x0002
|
80
80
|
/* This flag indicates backup blocks starting in this page are optional */
|
81
81
|
#define XLP_BKP_REMOVABLE 0x0004
|
82
|
+
/* Replaces a missing contrecord; see CreateOverwriteContrecordRecord */
|
83
|
+
#define XLP_FIRST_IS_OVERWRITE_CONTRECORD 0x0008
|
82
84
|
/* All defined flag bits in xlp_info (used for validity checking of header) */
|
83
|
-
#define XLP_ALL_FLAGS
|
85
|
+
#define XLP_ALL_FLAGS 0x000F
|
84
86
|
|
85
87
|
#define XLogPageHeaderSize(hdr) \
|
86
88
|
(((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
|
@@ -252,6 +254,13 @@ typedef struct xl_restore_point
|
|
252
254
|
char rp_name[MAXFNAMELEN];
|
253
255
|
} xl_restore_point;
|
254
256
|
|
257
|
+
/* Overwrite of prior contrecord */
|
258
|
+
typedef struct xl_overwrite_contrecord
|
259
|
+
{
|
260
|
+
XLogRecPtr overwritten_lsn;
|
261
|
+
TimestampTz overwrite_time;
|
262
|
+
} xl_overwrite_contrecord;
|
263
|
+
|
255
264
|
/* End of recovery mark, when we don't do an END_OF_RECOVERY checkpoint */
|
256
265
|
typedef struct xl_end_of_recovery
|
257
266
|
{
|
@@ -250,6 +250,16 @@ struct XLogReaderState
|
|
250
250
|
|
251
251
|
/* Buffer to hold error message */
|
252
252
|
char *errormsg_buf;
|
253
|
+
|
254
|
+
/*
|
255
|
+
* Set at the end of recovery: the start point of a partial record at the
|
256
|
+
* end of WAL (InvalidXLogRecPtr if there wasn't one), and the start
|
257
|
+
* location of its first contrecord that went missing.
|
258
|
+
*/
|
259
|
+
XLogRecPtr abortedRecPtr;
|
260
|
+
XLogRecPtr missingContrecPtr;
|
261
|
+
/* Set when XLP_FIRST_IS_OVERWRITE_CONTRECORD is found */
|
262
|
+
XLogRecPtr overwrittenRecPtr;
|
253
263
|
};
|
254
264
|
|
255
265
|
/* Get a new XLogReader */
|
@@ -201,6 +201,8 @@ extern void recordMultipleDependencies(const ObjectAddress *depender,
|
|
201
201
|
extern void recordDependencyOnCurrentExtension(const ObjectAddress *object,
|
202
202
|
bool isReplace);
|
203
203
|
|
204
|
+
extern void checkMembershipInCurrentExtension(const ObjectAddress *object);
|
205
|
+
|
204
206
|
extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
|
205
207
|
bool skipExtensionDeps);
|
206
208
|
|
@@ -178,7 +178,7 @@ typedef FormData_pg_class *Form_pg_class;
|
|
178
178
|
/*
|
179
179
|
* an explicitly chosen candidate key's columns are used as replica identity.
|
180
180
|
* Note this will still be set if the index has been dropped; in that case it
|
181
|
-
* has the same meaning as '
|
181
|
+
* has the same meaning as 'n'.
|
182
182
|
*/
|
183
183
|
#define REPLICA_IDENTITY_INDEX 'i'
|
184
184
|
|
@@ -82,7 +82,7 @@
|
|
82
82
|
/*
|
83
83
|
* an explicitly chosen candidate key's columns are used as replica identity.
|
84
84
|
* Note this will still be set if the index has been dropped; in that case it
|
85
|
-
* has the same meaning as '
|
85
|
+
* has the same meaning as 'n'.
|
86
86
|
*/
|
87
87
|
#define REPLICA_IDENTITY_INDEX 'i'
|
88
88
|
|
@@ -95,7 +95,9 @@ extern ObjectAddress OperatorCreate(const char *operatorName,
|
|
95
95
|
bool canMerge,
|
96
96
|
bool canHash);
|
97
97
|
|
98
|
-
extern ObjectAddress makeOperatorDependencies(HeapTuple tuple,
|
98
|
+
extern ObjectAddress makeOperatorDependencies(HeapTuple tuple,
|
99
|
+
bool makeExtensionDep,
|
100
|
+
bool isUpdate);
|
99
101
|
|
100
102
|
extern void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete);
|
101
103
|
|
@@ -107,6 +107,9 @@ extern List *GetAllTablesPublicationRelations(bool pubviaroot);
|
|
107
107
|
extern bool is_publishable_relation(Relation rel);
|
108
108
|
extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel,
|
109
109
|
bool if_not_exists);
|
110
|
+
extern List *GetPubPartitionOptionRelations(List *result,
|
111
|
+
PublicationPartOpt pub_partopt,
|
112
|
+
Oid relid);
|
110
113
|
|
111
114
|
extern Oid get_publication_oid(const char *pubname, bool missing_ok);
|
112
115
|
extern char *get_publication_name(Oid pubid, bool missing_ok);
|
@@ -162,12 +162,20 @@ extern ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString
|
|
162
162
|
Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
|
163
163
|
Oid funcoid, Oid parentTriggerOid, Node *whenClause,
|
164
164
|
bool isInternal, bool in_partition);
|
165
|
+
extern ObjectAddress CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
|
166
|
+
Oid relOid, Oid refRelOid, Oid constraintOid,
|
167
|
+
Oid indexOid, Oid funcoid, Oid parentTriggerOid,
|
168
|
+
Node *whenClause, bool isInternal, bool in_partition,
|
169
|
+
char trigger_fires_when);
|
165
170
|
|
166
171
|
extern void RemoveTriggerById(Oid trigOid);
|
167
172
|
extern Oid get_trigger_oid(Oid relid, const char *name, bool missing_ok);
|
168
173
|
|
169
174
|
extern ObjectAddress renametrig(RenameStmt *stmt);
|
170
175
|
|
176
|
+
extern void EnableDisableTriggerNew(Relation rel, const char *tgname,
|
177
|
+
char fires_when, bool skip_system, bool recurse,
|
178
|
+
LOCKMODE lockmode);
|
171
179
|
extern void EnableDisableTrigger(Relation rel, const char *tgname,
|
172
180
|
char fires_when, bool skip_system, LOCKMODE lockmode);
|
173
181
|
|
@@ -55,6 +55,11 @@
|
|
55
55
|
* presence is relevant to determine whether a lookup needs to continue
|
56
56
|
* looking or is done - buckets following a deleted element are shifted
|
57
57
|
* backwards, unless they're empty or already at their optimal position.
|
58
|
+
*
|
59
|
+
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
|
60
|
+
* Portions Copyright (c) 1994, Regents of the University of California
|
61
|
+
*
|
62
|
+
* src/include/lib/simplehash.h
|
58
63
|
*/
|
59
64
|
|
60
65
|
#include "port/pg_bitutils.h"
|
@@ -156,7 +161,7 @@ SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements,
|
|
156
161
|
#endif
|
157
162
|
SH_SCOPE void SH_DESTROY(SH_TYPE * tb);
|
158
163
|
SH_SCOPE void SH_RESET(SH_TYPE * tb);
|
159
|
-
SH_SCOPE void SH_GROW(SH_TYPE * tb,
|
164
|
+
SH_SCOPE void SH_GROW(SH_TYPE * tb, uint64 newsize);
|
160
165
|
SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found);
|
161
166
|
SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
|
162
167
|
uint32 hash, bool *found);
|
@@ -218,7 +223,8 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
|
|
218
223
|
#define SIMPLEHASH_H
|
219
224
|
|
220
225
|
#ifdef FRONTEND
|
221
|
-
#define sh_error(...)
|
226
|
+
#define sh_error(...) \
|
227
|
+
do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0)
|
222
228
|
#define sh_log(...) pg_log_info(__VA_ARGS__)
|
223
229
|
#else
|
224
230
|
#define sh_error(...) elog(ERROR, __VA_ARGS__)
|
@@ -232,7 +238,7 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
|
|
232
238
|
* the hashtable.
|
233
239
|
*/
|
234
240
|
static inline void
|
235
|
-
SH_COMPUTE_PARAMETERS(SH_TYPE * tb,
|
241
|
+
SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint64 newsize)
|
236
242
|
{
|
237
243
|
uint64 size;
|
238
244
|
|
@@ -247,16 +253,12 @@ SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint32 newsize)
|
|
247
253
|
* Verify that allocation of ->data is possible on this platform, without
|
248
254
|
* overflowing Size.
|
249
255
|
*/
|
250
|
-
if ((((uint64) sizeof(SH_ELEMENT_TYPE)) * size) >= SIZE_MAX / 2)
|
256
|
+
if (unlikely((((uint64) sizeof(SH_ELEMENT_TYPE)) * size) >= SIZE_MAX / 2))
|
251
257
|
sh_error("hash table too large");
|
252
258
|
|
253
259
|
/* now set size */
|
254
260
|
tb->size = size;
|
255
|
-
|
256
|
-
if (tb->size == SH_MAX_SIZE)
|
257
|
-
tb->sizemask = 0;
|
258
|
-
else
|
259
|
-
tb->sizemask = tb->size - 1;
|
261
|
+
tb->sizemask = (uint32) (size - 1);
|
260
262
|
|
261
263
|
/*
|
262
264
|
* Compute the next threshold at which we need to grow the hash table
|
@@ -406,7 +408,7 @@ SH_RESET(SH_TYPE * tb)
|
|
406
408
|
* performance-wise, when known at some point.
|
407
409
|
*/
|
408
410
|
SH_SCOPE void
|
409
|
-
SH_GROW(SH_TYPE * tb,
|
411
|
+
SH_GROW(SH_TYPE * tb, uint64 newsize)
|
410
412
|
{
|
411
413
|
uint64 oldsize = tb->size;
|
412
414
|
SH_ELEMENT_TYPE *olddata = tb->data;
|
@@ -536,10 +538,8 @@ restart:
|
|
536
538
|
*/
|
537
539
|
if (unlikely(tb->members >= tb->grow_threshold))
|
538
540
|
{
|
539
|
-
if (tb->size == SH_MAX_SIZE)
|
540
|
-
{
|
541
|
+
if (unlikely(tb->size == SH_MAX_SIZE))
|
541
542
|
sh_error("hash table size exceeded");
|
542
|
-
}
|
543
543
|
|
544
544
|
/*
|
545
545
|
* When optimizing, it can be very useful to print these out.
|
@@ -72,6 +72,7 @@ extern int pq_getmessage(StringInfo s, int maxlen);
|
|
72
72
|
extern int pq_getbyte(void);
|
73
73
|
extern int pq_peekbyte(void);
|
74
74
|
extern int pq_getbyte_if_available(unsigned char *c);
|
75
|
+
extern bool pq_buffer_has_data(void);
|
75
76
|
extern int pq_putbytes(const char *s, size_t len);
|
76
77
|
|
77
78
|
/*
|
@@ -553,6 +553,7 @@ extern int pg_valid_server_encoding_id(int encoding);
|
|
553
553
|
* earlier in this file are also available from libpgcommon.
|
554
554
|
*/
|
555
555
|
extern int pg_encoding_mblen(int encoding, const char *mbstr);
|
556
|
+
extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr);
|
556
557
|
extern int pg_encoding_dsplen(int encoding, const char *mbstr);
|
557
558
|
extern int pg_encoding_verifymb(int encoding, const char *mbstr, int len);
|
558
559
|
extern int pg_encoding_max_length(int encoding);
|
@@ -57,6 +57,15 @@
|
|
57
57
|
* allowing die interrupts: HOLD_CANCEL_INTERRUPTS() and
|
58
58
|
* RESUME_CANCEL_INTERRUPTS().
|
59
59
|
*
|
60
|
+
* Note that ProcessInterrupts() has also acquired a number of tasks that
|
61
|
+
* do not necessarily cause a query-cancel-or-die response. Hence, it's
|
62
|
+
* possible that it will just clear InterruptPending and return.
|
63
|
+
*
|
64
|
+
* INTERRUPTS_PENDING_CONDITION() can be checked to see whether an
|
65
|
+
* interrupt needs to be serviced, without trying to do so immediately.
|
66
|
+
* Some callers are also interested in INTERRUPTS_CAN_BE_PROCESSED(),
|
67
|
+
* which tells whether ProcessInterrupts is sure to clear the interrupt.
|
68
|
+
*
|
60
69
|
* Special mechanisms are used to let an interrupt be accepted when we are
|
61
70
|
* waiting for a lock or when we are waiting for command input (but, of
|
62
71
|
* course, only if the interrupt holdoff counter is zero). See the
|
@@ -94,24 +103,27 @@ extern PGDLLIMPORT __thread volatile uint32 CritSectionCount;
|
|
94
103
|
/* in tcop/postgres.c */
|
95
104
|
extern void ProcessInterrupts(void);
|
96
105
|
|
106
|
+
/* Test whether an interrupt is pending */
|
97
107
|
#ifndef WIN32
|
108
|
+
#define INTERRUPTS_PENDING_CONDITION() \
|
109
|
+
(unlikely(InterruptPending))
|
110
|
+
#else
|
111
|
+
#define INTERRUPTS_PENDING_CONDITION() \
|
112
|
+
(unlikely(UNBLOCKED_SIGNAL_QUEUE()) ? pgwin32_dispatch_queued_signals() : 0, \
|
113
|
+
unlikely(InterruptPending))
|
114
|
+
#endif
|
98
115
|
|
116
|
+
/* Service interrupt, if one is pending and it's safe to service it now */
|
99
117
|
#define CHECK_FOR_INTERRUPTS() \
|
100
118
|
do { \
|
101
|
-
if (
|
102
|
-
ProcessInterrupts(); \
|
103
|
-
} while(0)
|
104
|
-
#else /* WIN32 */
|
105
|
-
|
106
|
-
#define CHECK_FOR_INTERRUPTS() \
|
107
|
-
do { \
|
108
|
-
if (unlikely(UNBLOCKED_SIGNAL_QUEUE())) \
|
109
|
-
pgwin32_dispatch_queued_signals(); \
|
110
|
-
if (unlikely(InterruptPending)) \
|
119
|
+
if (INTERRUPTS_PENDING_CONDITION()) \
|
111
120
|
ProcessInterrupts(); \
|
112
121
|
} while(0)
|
113
|
-
#endif /* WIN32 */
|
114
122
|
|
123
|
+
/* Is ProcessInterrupts() guaranteed to clear InterruptPending? */
|
124
|
+
#define INTERRUPTS_CAN_BE_PROCESSED() \
|
125
|
+
(InterruptHoldoffCount == 0 && CritSectionCount == 0 && \
|
126
|
+
QueryCancelHoldoffCount == 0)
|
115
127
|
|
116
128
|
#define HOLD_INTERRUPTS() (InterruptHoldoffCount++)
|
117
129
|
|
@@ -471,6 +483,7 @@ extern bool BackupInProgress(void);
|
|
471
483
|
extern void CancelBackup(void);
|
472
484
|
|
473
485
|
/* in executor/nodeHash.c */
|
486
|
+
extern size_t get_hash_memory_limit(void);
|
474
487
|
extern int get_hash_mem(void);
|
475
488
|
|
476
489
|
#endif /* MISCADMIN_H */
|
@@ -1454,7 +1454,7 @@ typedef struct IndexScanState
|
|
1454
1454
|
/* ----------------
|
1455
1455
|
* IndexOnlyScanState information
|
1456
1456
|
*
|
1457
|
-
*
|
1457
|
+
* recheckqual execution state for recheckqual expressions
|
1458
1458
|
* ScanKeys Skey structures for index quals
|
1459
1459
|
* NumScanKeys number of ScanKeys
|
1460
1460
|
* OrderByKeys Skey structures for index ordering operators
|
@@ -1473,7 +1473,7 @@ typedef struct IndexScanState
|
|
1473
1473
|
typedef struct IndexOnlyScanState
|
1474
1474
|
{
|
1475
1475
|
ScanState ss; /* its first field is NodeTag */
|
1476
|
-
ExprState *
|
1476
|
+
ExprState *recheckqual;
|
1477
1477
|
struct ScanKeyData *ioss_ScanKeys;
|
1478
1478
|
int ioss_NumScanKeys;
|
1479
1479
|
struct ScanKeyData *ioss_OrderByKeys;
|
@@ -915,10 +915,10 @@ typedef struct PartitionCmd
|
|
915
915
|
* inFromCl marks those range variables that are listed in the FROM clause.
|
916
916
|
* It's false for RTEs that are added to a query behind the scenes, such
|
917
917
|
* as the NEW and OLD variables for a rule, or the subqueries of a UNION.
|
918
|
-
* This flag is not used
|
919
|
-
* a separate "namespace" data structure to
|
920
|
-
* needed by ruleutils.c to determine
|
921
|
-
* decompiled queries.
|
918
|
+
* This flag is not used during parsing (except in transformLockingClause,
|
919
|
+
* q.v.); the parser now uses a separate "namespace" data structure to
|
920
|
+
* control visibility. But it is needed by ruleutils.c to determine
|
921
|
+
* whether RTEs should be shown in decompiled queries.
|
922
922
|
*
|
923
923
|
* requiredPerms and checkAsUser specify run-time access permissions
|
924
924
|
* checks to be performed at query startup. The user must have *all*
|
@@ -1876,6 +1876,7 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
|
|
1876
1876
|
* constraint, or parent table */
|
1877
1877
|
DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
|
1878
1878
|
bool missing_ok; /* skip error if missing? */
|
1879
|
+
bool recurse; /* exec-time recursion */
|
1879
1880
|
} AlterTableCmd;
|
1880
1881
|
|
1881
1882
|
|
@@ -258,7 +258,8 @@ struct PlannerInfo
|
|
258
258
|
|
259
259
|
List *init_plans; /* init SubPlans for query */
|
260
260
|
|
261
|
-
List *cte_plan_ids; /* per-CTE-item list of subplan IDs
|
261
|
+
List *cte_plan_ids; /* per-CTE-item list of subplan IDs (or -1 if
|
262
|
+
* no subplan was made for that CTE) */
|
262
263
|
|
263
264
|
List *multiexpr_params; /* List of Lists of Params for MULTIEXPR
|
264
265
|
* subquery outputs */
|
@@ -560,6 +560,7 @@ extern List *list_delete_int(List *list, int datum);
|
|
560
560
|
extern List *list_delete_oid(List *list, Oid datum);
|
561
561
|
extern List *list_delete_first(List *list);
|
562
562
|
extern List *list_delete_last(List *list);
|
563
|
+
extern List *list_delete_first_n(List *list, int n);
|
563
564
|
extern List *list_delete_nth_cell(List *list, int n);
|
564
565
|
extern List *list_delete_cell(List *list, ListCell *cell);
|
565
566
|
|
@@ -418,14 +418,28 @@ typedef struct IndexScan
|
|
418
418
|
* index-only scan, in which the data comes from the index not the heap.
|
419
419
|
* Because of this, *all* Vars in the plan node's targetlist, qual, and
|
420
420
|
* index expressions reference index columns and have varno = INDEX_VAR.
|
421
|
-
*
|
422
|
-
*
|
421
|
+
*
|
422
|
+
* We could almost use indexqual directly against the index's output tuple
|
423
|
+
* when rechecking lossy index operators, but that won't work for quals on
|
424
|
+
* index columns that are not retrievable. Hence, recheckqual is needed
|
425
|
+
* for rechecks: it expresses the same condition as indexqual, but using
|
426
|
+
* only index columns that are retrievable. (We will not generate an
|
427
|
+
* index-only scan if this is not possible. An example is that if an
|
428
|
+
* index has table column "x" in a retrievable index column "ind1", plus
|
429
|
+
* an expression f(x) in a non-retrievable column "ind2", an indexable
|
430
|
+
* query on f(x) will use "ind2" in indexqual and f(ind1) in recheckqual.
|
431
|
+
* Without the "ind1" column, an index-only scan would be disallowed.)
|
432
|
+
*
|
433
|
+
* We don't currently need a recheckable equivalent of indexorderby,
|
434
|
+
* because we don't support lossy operators in index ORDER BY.
|
423
435
|
*
|
424
436
|
* To help EXPLAIN interpret the index Vars for display, we provide
|
425
437
|
* indextlist, which represents the contents of the index as a targetlist
|
426
438
|
* with one TLE per index column. Vars appearing in this list reference
|
427
439
|
* the base table, and this is the only field in the plan node that may
|
428
|
-
* contain such Vars.
|
440
|
+
* contain such Vars. Also, for the convenience of setrefs.c, TLEs in
|
441
|
+
* indextlist are marked as resjunk if they correspond to columns that
|
442
|
+
* the index AM cannot reconstruct.
|
429
443
|
* ----------------
|
430
444
|
*/
|
431
445
|
typedef struct IndexOnlyScan
|
@@ -436,6 +450,7 @@ typedef struct IndexOnlyScan
|
|
436
450
|
List *indexorderby; /* list of index ORDER BY exprs */
|
437
451
|
List *indextlist; /* TargetEntry list describing index's cols */
|
438
452
|
ScanDirection indexorderdir; /* forward or backward or don't care */
|
453
|
+
List *recheckqual; /* index quals in recheckable form */
|
439
454
|
} IndexOnlyScan;
|
440
455
|
|
441
456
|
/* ----------------
|
@@ -24,11 +24,6 @@
|
|
24
24
|
|
25
25
|
#include "nodes/parsenodes.h"
|
26
26
|
|
27
|
-
/* Test if an expression node represents a SRF call. Beware multiple eval! */
|
28
|
-
#define IS_SRF_CALL(node) \
|
29
|
-
((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
|
30
|
-
(IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
|
31
|
-
|
32
27
|
/*
|
33
28
|
* We don't want to include nodes/pathnodes.h here, because non-planner
|
34
29
|
* code should generally treat PlannerInfo as an opaque typedef.
|
@@ -363,7 +363,7 @@
|
|
363
363
|
REASSIGN = 579,
|
364
364
|
RECHECK = 580,
|
365
365
|
RECURSIVE = 581,
|
366
|
-
|
366
|
+
REF_P = 582,
|
367
367
|
REFERENCES = 583,
|
368
368
|
REFERENCING = 584,
|
369
369
|
REFRESH = 585,
|
@@ -840,7 +840,7 @@
|
|
840
840
|
#define REASSIGN 579
|
841
841
|
#define RECHECK 580
|
842
842
|
#define RECURSIVE 581
|
843
|
-
#define
|
843
|
+
#define REF_P 582
|
844
844
|
#define REFERENCES 583
|
845
845
|
#define REFERENCING 584
|
846
846
|
#define REFRESH 585
|
@@ -330,7 +330,7 @@ PG_KEYWORD("real", REAL, COL_NAME_KEYWORD)
|
|
330
330
|
PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD)
|
331
331
|
PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD)
|
332
332
|
PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD)
|
333
|
-
PG_KEYWORD("ref",
|
333
|
+
PG_KEYWORD("ref", REF_P, UNRESERVED_KEYWORD)
|
334
334
|
PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD)
|
335
335
|
PG_KEYWORD("referencing", REFERENCING, UNRESERVED_KEYWORD)
|
336
336
|
PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD)
|
@@ -70,6 +70,7 @@ extern Oid select_common_type(ParseState *pstate, List *exprs,
|
|
70
70
|
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
|
71
71
|
Oid targetTypeId,
|
72
72
|
const char *context);
|
73
|
+
extern bool verify_common_type(Oid common_type, List *exprs);
|
73
74
|
|
74
75
|
extern bool check_generic_type_consistency(const Oid *actual_arg_types,
|
75
76
|
const Oid *declared_arg_types,
|