pg_query 6.1.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 +38 -1
- data/README.md +1 -1
- data/Rakefile +3 -2
- data/ext/pg_query/extconf.rb +2 -2
- data/ext/pg_query/include/pg_query.h +32 -2
- data/ext/pg_query/include/postgres/access/amapi.h +1 -1
- data/ext/pg_query/include/postgres/access/slru.h +1 -1
- data/ext/pg_query/include/postgres/access/tableam.h +11 -4
- 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/commands/defrem.h +1 -1
- data/ext/pg_query/include/postgres/commands/trigger.h +18 -0
- data/ext/pg_query/include/postgres/executor/executor.h +4 -0
- data/ext/pg_query/include/postgres/mb/pg_wchar.h +2 -0
- data/ext/pg_query/include/postgres/miscadmin.h +2 -1
- data/ext/pg_query/include/postgres/nodes/execnodes.h +6 -8
- data/ext/pg_query/include/postgres/nodes/pathnodes.h +1 -2
- data/ext/pg_query/include/postgres/pg_config.h +10 -9
- 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 +9 -3
- data/ext/pg_query/include/postgres/replication/reorderbuffer.h +29 -9
- data/ext/pg_query/include/postgres/replication/slot.h +2 -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_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 +4481 -3870
- 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 +739 -732
- 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 +46 -6
- data/lib/pg_query/deparse.rb +29 -8
- data/lib/pg_query/parse.rb +19 -0
- data/lib/pg_query/pg_query_pb.rb +7 -2
- data/lib/pg_query/split.rb +20 -0
- data/lib/pg_query/treewalker.rb +9 -7
- data/lib/pg_query/version.rb +1 -1
- data/lib/pg_query.rb +1 -0
- metadata +10 -3
- data/ext/pg_query/postgres_deparse.h +0 -9
|
@@ -130,8 +130,8 @@ __thread SessionEndType pgStatSessionEndCause = DISCONNECT_NORMAL;
|
|
|
130
130
|
/*
|
|
131
131
|
* Flush out pending stats for the entry
|
|
132
132
|
*
|
|
133
|
-
* If nowait is true
|
|
134
|
-
*
|
|
133
|
+
* If nowait is true and the lock could not be immediately acquired, returns
|
|
134
|
+
* false without flushing the entry. Otherwise returns true.
|
|
135
135
|
*/
|
|
136
136
|
#define PGSTAT_ACCUM_DBCOUNT(item) \
|
|
137
137
|
(sharedent)->stats.item += (pendingent)->item
|
|
@@ -1939,6 +1939,17 @@ write_stderr(const char *fmt,...)
|
|
|
1939
1939
|
}
|
|
1940
1940
|
|
|
1941
1941
|
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
/*
|
|
1945
|
+
* Write errors to stderr (or by equal means when stderr is
|
|
1946
|
+
* not available) - va_list version
|
|
1947
|
+
*/
|
|
1948
|
+
#ifdef WIN32
|
|
1949
|
+
#endif
|
|
1950
|
+
#ifndef WIN32
|
|
1951
|
+
#else
|
|
1952
|
+
#endif
|
|
1942
1953
|
#ifdef WIN32
|
|
1943
1954
|
__thread volatile int pg_signal_queue;
|
|
1944
1955
|
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* - pg_mbstrlen_with_len
|
|
18
18
|
* - pg_mblen
|
|
19
19
|
* - SetDatabaseEncoding
|
|
20
|
+
* - pg_mbcharcliplen
|
|
21
|
+
* - pg_mbstrlen
|
|
20
22
|
* - GetMessageEncoding
|
|
21
23
|
* - MessageEncoding
|
|
22
24
|
*--------------------------------------------------------------------
|
|
@@ -386,7 +388,22 @@ pg_mblen(const char *mbstr)
|
|
|
386
388
|
|
|
387
389
|
|
|
388
390
|
/* returns the length (counted in wchars) of a multibyte string */
|
|
391
|
+
int
|
|
392
|
+
pg_mbstrlen(const char *mbstr)
|
|
393
|
+
{
|
|
394
|
+
int len = 0;
|
|
389
395
|
|
|
396
|
+
/* optimization for single byte encoding */
|
|
397
|
+
if (pg_database_encoding_max_length() == 1)
|
|
398
|
+
return strlen(mbstr);
|
|
399
|
+
|
|
400
|
+
while (*mbstr)
|
|
401
|
+
{
|
|
402
|
+
mbstr += pg_mblen(mbstr);
|
|
403
|
+
len++;
|
|
404
|
+
}
|
|
405
|
+
return len;
|
|
406
|
+
}
|
|
390
407
|
|
|
391
408
|
/* returns the length (counted in wchars) of a multibyte string
|
|
392
409
|
* (not necessarily NULL terminated)
|
|
@@ -425,7 +442,7 @@ pg_mbcliplen(const char *mbstr, int len, int limit)
|
|
|
425
442
|
}
|
|
426
443
|
|
|
427
444
|
/*
|
|
428
|
-
* pg_mbcliplen with specified encoding
|
|
445
|
+
* pg_mbcliplen with specified encoding; string must be valid in encoding
|
|
429
446
|
*/
|
|
430
447
|
int
|
|
431
448
|
pg_encoding_mbcliplen(int encoding, const char *mbstr,
|
|
@@ -459,7 +476,29 @@ pg_encoding_mbcliplen(int encoding, const char *mbstr,
|
|
|
459
476
|
* Similar to pg_mbcliplen except the limit parameter specifies the
|
|
460
477
|
* character length, not the byte length.
|
|
461
478
|
*/
|
|
479
|
+
int
|
|
480
|
+
pg_mbcharcliplen(const char *mbstr, int len, int limit)
|
|
481
|
+
{
|
|
482
|
+
int clen = 0;
|
|
483
|
+
int nch = 0;
|
|
484
|
+
int l;
|
|
462
485
|
|
|
486
|
+
/* optimization for single byte encoding */
|
|
487
|
+
if (pg_database_encoding_max_length() == 1)
|
|
488
|
+
return cliplen(mbstr, len, limit);
|
|
489
|
+
|
|
490
|
+
while (len > 0 && *mbstr)
|
|
491
|
+
{
|
|
492
|
+
l = pg_mblen(mbstr);
|
|
493
|
+
nch++;
|
|
494
|
+
if (nch > limit)
|
|
495
|
+
break;
|
|
496
|
+
clen += l;
|
|
497
|
+
len -= l;
|
|
498
|
+
mbstr += l;
|
|
499
|
+
}
|
|
500
|
+
return clen;
|
|
501
|
+
}
|
|
463
502
|
|
|
464
503
|
/* mbcliplen for any single-byte encoding */
|
|
465
504
|
static int
|
|
@@ -726,12 +765,12 @@ pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
|
|
|
726
765
|
* report_invalid_encoding: complain about invalid multibyte character
|
|
727
766
|
*
|
|
728
767
|
* note: len is remaining length of string, not length of character;
|
|
729
|
-
* len must be greater than zero
|
|
768
|
+
* len must be greater than zero (or we'd neglect initializing "buf").
|
|
730
769
|
*/
|
|
731
770
|
void
|
|
732
771
|
report_invalid_encoding(int encoding, const char *mbstr, int len)
|
|
733
772
|
{
|
|
734
|
-
int l =
|
|
773
|
+
int l = pg_encoding_mblen_or_incomplete(encoding, mbstr, len);
|
|
735
774
|
char buf[8 * 5 + 1];
|
|
736
775
|
char *p = buf;
|
|
737
776
|
int j,
|
|
@@ -758,7 +797,7 @@ report_invalid_encoding(int encoding, const char *mbstr, int len)
|
|
|
758
797
|
* report_untranslatable_char: complain about untranslatable character
|
|
759
798
|
*
|
|
760
799
|
* note: len is remaining length of string, not length of character;
|
|
761
|
-
* len must be greater than zero
|
|
800
|
+
* len must be greater than zero (or we'd neglect initializing "buf").
|
|
762
801
|
*/
|
|
763
802
|
|
|
764
803
|
|
|
@@ -54,6 +54,7 @@ AlignedAllocFree(void *pointer)
|
|
|
54
54
|
GetMemoryChunkContext(unaligned)->name, chunk);
|
|
55
55
|
#endif
|
|
56
56
|
|
|
57
|
+
/* Recursively pfree the unaligned chunk */
|
|
57
58
|
pfree(unaligned);
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -105,18 +106,32 @@ AlignedAllocRealloc(void *pointer, Size size, int flags)
|
|
|
105
106
|
Assert(old_size >= redirchunk->requested_size);
|
|
106
107
|
#endif
|
|
107
108
|
|
|
109
|
+
/*
|
|
110
|
+
* To keep things simple, we always allocate a new aligned chunk and copy
|
|
111
|
+
* data into it. Because of the above inaccuracy, this may end in copying
|
|
112
|
+
* more data than was in the original allocation request size, but that
|
|
113
|
+
* should be OK.
|
|
114
|
+
*/
|
|
108
115
|
ctx = GetMemoryChunkContext(unaligned);
|
|
109
116
|
newptr = MemoryContextAllocAligned(ctx, size, alignto, flags);
|
|
110
117
|
|
|
111
|
-
/*
|
|
112
|
-
|
|
113
|
-
* so we must mark the entire allocation as defined.
|
|
114
|
-
*/
|
|
115
|
-
if (likely(newptr != NULL))
|
|
118
|
+
/* Cope cleanly with OOM */
|
|
119
|
+
if (unlikely(newptr == NULL))
|
|
116
120
|
{
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
VALGRIND_MAKE_MEM_NOACCESS(redirchunk, sizeof(MemoryChunk));
|
|
122
|
+
return MemoryContextAllocationFailure(ctx, size, flags);
|
|
119
123
|
}
|
|
124
|
+
|
|
125
|
+
/*
|
|
126
|
+
* We may memcpy more than the original allocation request size, which
|
|
127
|
+
* would result in trying to copy trailing bytes that the original
|
|
128
|
+
* MemoryContextAllocAligned call marked NOACCESS. So we must mark the
|
|
129
|
+
* entire old_size as defined. That's slightly annoying, but probably not
|
|
130
|
+
* worth improving.
|
|
131
|
+
*/
|
|
132
|
+
VALGRIND_MAKE_MEM_DEFINED(pointer, old_size);
|
|
133
|
+
memcpy(newptr, pointer, Min(size, old_size));
|
|
134
|
+
|
|
120
135
|
pfree(unaligned);
|
|
121
136
|
|
|
122
137
|
return newptr;
|
|
@@ -1632,9 +1632,9 @@ AllocSetCheck(MemoryContext context)
|
|
|
1632
1632
|
prevblock = block, block = block->next)
|
|
1633
1633
|
{
|
|
1634
1634
|
char *bpoz = ((char *) block) + ALLOC_BLOCKHDRSZ;
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1635
|
+
Size blk_used = block->freeptr - bpoz;
|
|
1636
|
+
Size blk_data = 0;
|
|
1637
|
+
Size nchunks = 0;
|
|
1638
1638
|
bool has_external_chunk = false;
|
|
1639
1639
|
|
|
1640
1640
|
if (IsKeeperBlock(set, block))
|
|
@@ -236,7 +236,7 @@ BumpAllocLarge(MemoryContext context, Size size, int flags)
|
|
|
236
236
|
|
|
237
237
|
block = (BumpBlock *) malloc(blksize);
|
|
238
238
|
if (block == NULL)
|
|
239
|
-
return
|
|
239
|
+
return MemoryContextAllocationFailure(context, size, flags);
|
|
240
240
|
|
|
241
241
|
context->mem_allocated += blksize;
|
|
242
242
|
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* - enlargeStringInfo
|
|
10
10
|
* - appendStringInfo
|
|
11
11
|
* - appendStringInfoSpaces
|
|
12
|
+
* - makeStringInfo
|
|
13
|
+
* - destroyStringInfo
|
|
12
14
|
*--------------------------------------------------------------------
|
|
13
15
|
*/
|
|
14
16
|
|
|
@@ -51,7 +53,17 @@
|
|
|
51
53
|
*
|
|
52
54
|
* Create an empty 'StringInfoData' & return a pointer to it.
|
|
53
55
|
*/
|
|
56
|
+
StringInfo
|
|
57
|
+
makeStringInfo(void)
|
|
58
|
+
{
|
|
59
|
+
StringInfo res;
|
|
60
|
+
|
|
61
|
+
res = (StringInfo) palloc(sizeof(StringInfoData));
|
|
54
62
|
|
|
63
|
+
initStringInfo(res);
|
|
64
|
+
|
|
65
|
+
return res;
|
|
66
|
+
}
|
|
55
67
|
|
|
56
68
|
/*
|
|
57
69
|
* initStringInfo
|
|
@@ -350,4 +362,12 @@ enlargeStringInfo(StringInfo str, int needed)
|
|
|
350
362
|
* Frees a StringInfo and its buffer (opposite of makeStringInfo()).
|
|
351
363
|
* This must only be called on palloc'd StringInfos.
|
|
352
364
|
*/
|
|
365
|
+
void
|
|
366
|
+
destroyStringInfo(StringInfo str)
|
|
367
|
+
{
|
|
368
|
+
/* don't allow destroys of read-only StringInfos */
|
|
369
|
+
Assert(str->maxlen != 0);
|
|
353
370
|
|
|
371
|
+
pfree(str->data);
|
|
372
|
+
pfree(str);
|
|
373
|
+
}
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
* - pg_johab_dsplen
|
|
77
77
|
* - pg_johab_verifychar
|
|
78
78
|
* - pg_johab_verifystr
|
|
79
|
+
* - pg_encoding_mblen_or_incomplete
|
|
79
80
|
* - pg_encoding_mblen
|
|
80
81
|
*--------------------------------------------------------------------
|
|
81
82
|
*/
|
|
@@ -94,6 +95,8 @@
|
|
|
94
95
|
*/
|
|
95
96
|
#include "c.h"
|
|
96
97
|
|
|
98
|
+
#include <limits.h>
|
|
99
|
+
|
|
97
100
|
#include "mb/pg_wchar.h"
|
|
98
101
|
#include "utils/ascii.h"
|
|
99
102
|
|
|
@@ -2182,10 +2185,27 @@ const pg_wchar_tbl pg_wchar_table[] = {
|
|
|
2182
2185
|
/*
|
|
2183
2186
|
* Returns the byte length of a multibyte character.
|
|
2184
2187
|
*
|
|
2185
|
-
*
|
|
2186
|
-
*
|
|
2187
|
-
*
|
|
2188
|
-
*
|
|
2188
|
+
* Choose "mblen" functions based on the input string characteristics.
|
|
2189
|
+
* pg_encoding_mblen() can be used when ANY of these conditions are met:
|
|
2190
|
+
*
|
|
2191
|
+
* - The input string is zero-terminated
|
|
2192
|
+
*
|
|
2193
|
+
* - The input string is known to be valid in the encoding (e.g., string
|
|
2194
|
+
* converted from database encoding)
|
|
2195
|
+
*
|
|
2196
|
+
* - The encoding is not GB18030 (e.g., when only database encodings are
|
|
2197
|
+
* passed to 'encoding' parameter)
|
|
2198
|
+
*
|
|
2199
|
+
* encoding==GB18030 requires examining up to two bytes to determine character
|
|
2200
|
+
* length. Therefore, callers satisfying none of those conditions must use
|
|
2201
|
+
* pg_encoding_mblen_or_incomplete() instead, as access to mbstr[1] cannot be
|
|
2202
|
+
* guaranteed to be within allocation bounds.
|
|
2203
|
+
*
|
|
2204
|
+
* When dealing with text that is not certainly valid in the specified
|
|
2205
|
+
* encoding, the result may exceed the actual remaining string length.
|
|
2206
|
+
* Callers that are not prepared to deal with that should use Min(remaining,
|
|
2207
|
+
* pg_encoding_mblen_or_incomplete()). For zero-terminated strings, that and
|
|
2208
|
+
* pg_encoding_mblen_bounded() are interchangeable.
|
|
2189
2209
|
*/
|
|
2190
2210
|
int
|
|
2191
2211
|
pg_encoding_mblen(int encoding, const char *mbstr)
|
|
@@ -2196,8 +2216,28 @@ pg_encoding_mblen(int encoding, const char *mbstr)
|
|
|
2196
2216
|
}
|
|
2197
2217
|
|
|
2198
2218
|
/*
|
|
2199
|
-
* Returns the byte length of a multibyte character
|
|
2200
|
-
*
|
|
2219
|
+
* Returns the byte length of a multibyte character (possibly not
|
|
2220
|
+
* zero-terminated), or INT_MAX if too few bytes remain to determine a length.
|
|
2221
|
+
*/
|
|
2222
|
+
int
|
|
2223
|
+
pg_encoding_mblen_or_incomplete(int encoding, const char *mbstr,
|
|
2224
|
+
size_t remaining)
|
|
2225
|
+
{
|
|
2226
|
+
/*
|
|
2227
|
+
* Define zero remaining as too few, even for single-byte encodings.
|
|
2228
|
+
* pg_gb18030_mblen() reads one or two bytes; single-byte encodings read
|
|
2229
|
+
* zero; others read one.
|
|
2230
|
+
*/
|
|
2231
|
+
if (remaining < 1 ||
|
|
2232
|
+
(encoding == PG_GB18030 && IS_HIGHBIT_SET(*mbstr) && remaining < 2))
|
|
2233
|
+
return INT_MAX;
|
|
2234
|
+
return pg_encoding_mblen(encoding, mbstr);
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
/*
|
|
2238
|
+
* Returns the byte length of a multibyte character; but not more than the
|
|
2239
|
+
* distance to the terminating zero byte. For input that might lack a
|
|
2240
|
+
* terminating zero, use Min(remaining, pg_encoding_mblen_or_incomplete()).
|
|
2201
2241
|
*/
|
|
2202
2242
|
|
|
2203
2243
|
|
data/lib/pg_query/deparse.rb
CHANGED
|
@@ -1,18 +1,39 @@
|
|
|
1
1
|
module PgQuery
|
|
2
2
|
class ParserResult
|
|
3
|
-
def deparse
|
|
4
|
-
PgQuery.deparse(@tree)
|
|
3
|
+
def deparse(opts: nil)
|
|
4
|
+
PgQuery.deparse(@tree, opts: opts)
|
|
5
5
|
end
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
class DeparseComment
|
|
9
|
+
attr_accessor :match_location, :newlines_before_comment, :newlines_after_comment, :str
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
DeparseOpts = Struct.new(:pretty_print, :comments, :indent_size, :max_line_length,
|
|
13
|
+
:trailing_newline, :commas_start_of_line, keyword_init: true)
|
|
14
|
+
|
|
8
15
|
# Reconstruct all of the parsed queries into their original form
|
|
9
|
-
def self.deparse(tree)
|
|
10
|
-
if PgQuery::ParseResult.method(:encode).arity == 1
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
def self.deparse(tree, opts: nil)
|
|
17
|
+
protobuf_encoded = if PgQuery::ParseResult.method(:encode).arity == 1
|
|
18
|
+
PgQuery::ParseResult.encode(tree)
|
|
19
|
+
elsif PgQuery::ParseResult.method(:encode).arity == -1
|
|
20
|
+
PgQuery::ParseResult.encode(tree, recursion_limit: 1_000)
|
|
21
|
+
else
|
|
22
|
+
raise ArgumentError, 'Unsupported protobuf Ruby API'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if opts
|
|
26
|
+
PgQuery.deparse_protobuf_opts(
|
|
27
|
+
protobuf_encoded,
|
|
28
|
+
opts.pretty_print,
|
|
29
|
+
opts.comments || [],
|
|
30
|
+
opts.indent_size || 0,
|
|
31
|
+
opts.max_line_length || 0,
|
|
32
|
+
opts.trailing_newline,
|
|
33
|
+
opts.commas_start_of_line
|
|
34
|
+
).force_encoding('UTF-8')
|
|
14
35
|
else
|
|
15
|
-
|
|
36
|
+
PgQuery.deparse_protobuf(protobuf_encoded).force_encoding('UTF-8')
|
|
16
37
|
end
|
|
17
38
|
end
|
|
18
39
|
|
data/lib/pg_query/parse.rb
CHANGED
|
@@ -106,6 +106,7 @@ module PgQuery
|
|
|
106
106
|
statements = @tree.stmts.dup.to_a.map(&:stmt)
|
|
107
107
|
from_clause_items = [] # types: select, dml, ddl
|
|
108
108
|
subselect_items = []
|
|
109
|
+
call_items = [] # CALL fn()
|
|
109
110
|
|
|
110
111
|
loop do
|
|
111
112
|
statement = statements.shift
|
|
@@ -171,6 +172,8 @@ module PgQuery
|
|
|
171
172
|
when :copy_stmt
|
|
172
173
|
from_clause_items << { item: PgQuery::Node.new(range_var: statement.copy_stmt.relation), type: :dml } if statement.copy_stmt.relation
|
|
173
174
|
statements << statement.copy_stmt.query
|
|
175
|
+
when :call_stmt
|
|
176
|
+
call_items << statement.call_stmt
|
|
174
177
|
# The following statement types are DDL (changing table structure)
|
|
175
178
|
when :alter_table_stmt
|
|
176
179
|
case statement.alter_table_stmt.objtype
|
|
@@ -276,15 +279,20 @@ module PgQuery
|
|
|
276
279
|
end
|
|
277
280
|
when :bool_expr
|
|
278
281
|
subselect_items.concat(next_item.bool_expr.args.to_ary)
|
|
282
|
+
when :boolean_test
|
|
283
|
+
subselect_items << next_item.boolean_test.arg
|
|
279
284
|
when :coalesce_expr
|
|
280
285
|
subselect_items.concat(next_item.coalesce_expr.args.to_ary)
|
|
281
286
|
when :min_max_expr
|
|
282
287
|
subselect_items.concat(next_item.min_max_expr.args.to_ary)
|
|
288
|
+
when :null_test
|
|
289
|
+
subselect_items << next_item.null_test.arg
|
|
283
290
|
when :res_target
|
|
284
291
|
subselect_items << next_item.res_target.val
|
|
285
292
|
when :sub_link
|
|
286
293
|
statements << next_item.sub_link.subselect
|
|
287
294
|
when :func_call
|
|
295
|
+
# See also CALL below
|
|
288
296
|
subselect_items.concat(next_item.func_call.args.to_ary)
|
|
289
297
|
@functions << {
|
|
290
298
|
function: next_item.func_call.funcname.map { |f| f.string.sval }.join('.'),
|
|
@@ -299,6 +307,17 @@ module PgQuery
|
|
|
299
307
|
end
|
|
300
308
|
end
|
|
301
309
|
|
|
310
|
+
# CALL fn()
|
|
311
|
+
next_item = call_items.shift
|
|
312
|
+
if next_item
|
|
313
|
+
# Treat as a sub-select. Note the difference in underscore in func_call versus the above.
|
|
314
|
+
subselect_items.concat(next_item.funccall.args.to_ary)
|
|
315
|
+
@functions << {
|
|
316
|
+
function: next_item.funccall.funcname.map { |f| f.string.sval }.join('.'),
|
|
317
|
+
type: :call
|
|
318
|
+
}
|
|
319
|
+
end
|
|
320
|
+
|
|
302
321
|
next_item = from_clause_items.shift
|
|
303
322
|
if next_item && next_item[:item]
|
|
304
323
|
case next_item[:item].node
|