pg_query 2.1.0 → 2.1.4
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 +55 -0
 - data/Rakefile +2 -2
 - data/ext/pg_query/extconf.rb +8 -2
 - data/ext/pg_query/include/pg_config.h +3 -0
 - data/ext/pg_query/pg_query_fingerprint.c +15 -0
 - data/ext/pg_query/pg_query_fingerprint.h +3 -1
 - data/ext/pg_query/pg_query_normalize.c +119 -12
 - data/ext/pg_query/pg_query_parse_plpgsql.c +21 -1
 - data/ext/pg_query/pg_query_ruby.c +1 -1
 - data/ext/pg_query/pg_query_ruby_freebsd.sym +2 -0
 - data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1 -1
 - data/lib/pg_query/filter_columns.rb +5 -3
 - data/lib/pg_query/parse.rb +69 -45
 - data/lib/pg_query/truncate.rb +53 -7
 - data/lib/pg_query/version.rb +1 -1
 - metadata +6 -5
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: fe9be3677078ec8a4990a53c9e0aa74c21f2a66672fe3a0990b23c00a6da34af
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 31e3bbcdfac0cd27a1553ac0f0d33f7cbd7e36ce8c5080f29a314da67adcc76a
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 7a8e0ef4b389446f952988903aa6b5772c6caabaea80d97e4f40affdf0830227285e60af0848a2786fcdab98232e96a5a75d3b5f73b24378b9ef67e9d24d9bf8
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: ffd90f7bdf9a155cb7a014eaf9c8bfbf06d0905e70bc5dadc739015c4d11695ead10ae1960e1bcee44e3d81d3c8a5b7d47b6705a32ef93daa8d909b328ee9602
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -4,6 +4,61 @@ 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            * ...
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
            ## 2.1.4     2022-09-19
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            * Truncate: Simplify VALUES(...) lists
         
     | 
| 
      
 10 
     | 
    
         
            +
            * Truncate: Correctly handle UPDATE and ON CONFLICT target lists
         
     | 
| 
      
 11 
     | 
    
         
            +
            * Support complex queries with deeply nested ASTs ([#238](https://github.com/pganalyze/pg_query/pull/238))
         
     | 
| 
      
 12 
     | 
    
         
            +
            * Find table references inside type casts
         
     | 
| 
      
 13 
     | 
    
         
            +
            * Find function calls referenced in expression indexes ([#249](https://github.com/pganalyze/pg_query/pull/249))
         
     | 
| 
      
 14 
     | 
    
         
            +
            * Drop `Init_pg_query` from exported symbol map ([#256](https://github.com/pganalyze/pg_query/pull/256))
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ## 2.1.3     2022-01-28
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            * Track tables in EXCEPT and INTERSECT queries ([#239](https://github.com/pganalyze/pg_query/pull/239))
         
     | 
| 
      
 19 
     | 
    
         
            +
            * Get filter_columns working with UNION/EXCEPT/INTERSECT ([#240](https://github.com/pganalyze/pg_query/pull/240))
         
     | 
| 
      
 20 
     | 
    
         
            +
            * Update google-protobuf to address CVE scanner complaints
         
     | 
| 
      
 21 
     | 
    
         
            +
              - Note that none of the CVEs apply to pg_query, but this avoids unnecessary errors when
         
     | 
| 
      
 22 
     | 
    
         
            +
                the google-protobuf dependency is pulled in
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ## 2.1.2     2021-11-12
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            * Find tables in using clause of delete statement ([#234](https://github.com/pganalyze/pg_query/pull/234))
         
     | 
| 
      
 28 
     | 
    
         
            +
            * Find tables in case statements ([#235](https://github.com/pganalyze/pg_query/pull/235))
         
     | 
| 
      
 29 
     | 
    
         
            +
            * Correctly find nested tables in a subselect in a join condition ([#233](https://github.com/pganalyze/pg_query/pull/233))
         
     | 
| 
      
 30 
     | 
    
         
            +
            * Mark Postgres methods as visibility hidden, to avoid bloating dynamic symbol table ([#232](https://github.com/pganalyze/pg_query/pull/232))
         
     | 
| 
      
 31 
     | 
    
         
            +
              - This is required on ELF platforms (i.e. Linux, etc) to avoid including all global
         
     | 
| 
      
 32 
     | 
    
         
            +
                symbols in the shared library's symbol table, bloating the size, and causing
         
     | 
| 
      
 33 
     | 
    
         
            +
                potential conflicts with other C libraries using the same symbol names.
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            ## 2.1.1     2021-10-13
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            * Update to libpg_query 13-2.1.0 ([#230](https://github.com/pganalyze/pg_query/pull/230))
         
     | 
| 
      
 39 
     | 
    
         
            +
              - Normalize: add funcname error object
         
     | 
| 
      
 40 
     | 
    
         
            +
              - Normalize: Match GROUP BY against target list and re-use param refs
         
     | 
| 
      
 41 
     | 
    
         
            +
              - PL/pgSQL: Setup namespace items for parameters, support RECORD types
         
     | 
| 
      
 42 
     | 
    
         
            +
                - This significantly improves parsing for PL/pgSQL functions, to the extent
         
     | 
| 
      
 43 
     | 
    
         
            +
                  that most functions should now parse successfully
         
     | 
| 
      
 44 
     | 
    
         
            +
              - Normalize: Don't modify constants in TypeName typmods/arrayBounds fields
         
     | 
| 
      
 45 
     | 
    
         
            +
                - This matches how pg_stat_statement behaves, and avoids causing parsing
         
     | 
| 
      
 46 
     | 
    
         
            +
                  errors on the normalized statement
         
     | 
| 
      
 47 
     | 
    
         
            +
              - Don't fail builds on systems that have strchrnul support (FreeBSD)
         
     | 
| 
      
 48 
     | 
    
         
            +
            * Fix build on FreeBSD ([#222](https://github.com/pganalyze/pg_query/pull/222))
         
     | 
| 
      
 49 
     | 
    
         
            +
            * Add workaround for Ruby garbage collection bug ([#227](https://github.com/pganalyze/pg_query/pull/227))
         
     | 
| 
      
 50 
     | 
    
         
            +
              - The Ruby interpreter has a bug in `String#concat` where the appended
         
     | 
| 
      
 51 
     | 
    
         
            +
                array may be garbage collected prematurely because the compiler
         
     | 
| 
      
 52 
     | 
    
         
            +
                optimized out a Ruby stack variable. We now call `to_ary` on the
         
     | 
| 
      
 53 
     | 
    
         
            +
                Protobuf object to ensure the array lands on the Ruby stack so the
         
     | 
| 
      
 54 
     | 
    
         
            +
                garbage collector sees it.
         
     | 
| 
      
 55 
     | 
    
         
            +
              - The real fix in the interpreter is described in
         
     | 
| 
      
 56 
     | 
    
         
            +
                https://bugs.ruby-lang.org/issues/18140#note-2, but most current Ruby
         
     | 
| 
      
 57 
     | 
    
         
            +
                interpreters won't have this fix for some time.
         
     | 
| 
      
 58 
     | 
    
         
            +
            * Table/function extraction: Support subselects and LATERAL better ([#229](https://github.com/pganalyze/pg_query/pull/229))
         
     | 
| 
      
 59 
     | 
    
         
            +
              - This reworks the parsing logic so we don't ignore certain kinds of
         
     | 
| 
      
 60 
     | 
    
         
            +
                subselects.
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
       7 
62 
     | 
    
         | 
| 
       8 
63 
     | 
    
         
             
            ## 2.1.0     2021-07-04
         
     | 
| 
       9 
64 
     | 
    
         | 
    
        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.0 
     | 
| 
       9 
     | 
    
         
            -
            LIB_PG_QUERY_SHA256SUM = ' 
     | 
| 
      
 8 
     | 
    
         
            +
            LIB_PG_QUERY_TAG = '13-2.1.0'.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
            LIB_PG_QUERY_SHA256SUM = 'a01329ae5bac19b10b8ddf8012bd663a20f85f180d6d7b900c1a1ca8444d19a5'.freeze
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            Rake::ExtensionTask.new 'pg_query' do |ext|
         
     | 
| 
       12 
12 
     | 
    
         
             
              ext.lib_dir = 'lib/pg_query'
         
     | 
    
        data/ext/pg_query/extconf.rb
    CHANGED
    
    | 
         @@ -7,11 +7,17 @@ require 'pathname' 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            $objs = Dir.glob(File.join(__dir__, '*.c')).map { |f| Pathname.new(f).sub_ext('.o').to_s }
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
            $CFLAGS << " -O3 -Wall -fno-strict-aliasing -fwrapv -fstack-protector -Wno-unused-function -Wno-unused-variable -g"
         
     | 
| 
      
 10 
     | 
    
         
            +
            $CFLAGS << " -fvisibility=hidden -O3 -Wall -fno-strict-aliasing -fwrapv -fstack-protector -Wno-unused-function -Wno-unused-variable -Wno-clobbered -Wno-sign-compare -Wno-discarded-qualifiers -g"
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
            $INCFLAGS = "-I#{File.join(__dir__, 'include')} " + $INCFLAGS
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
            SYMFILE = 
     | 
| 
      
 14 
     | 
    
         
            +
            SYMFILE =
         
     | 
| 
      
 15 
     | 
    
         
            +
              if RUBY_PLATFORM =~ /freebsd/
         
     | 
| 
      
 16 
     | 
    
         
            +
                File.join(__dir__, 'pg_query_ruby_freebsd.sym')
         
     | 
| 
      
 17 
     | 
    
         
            +
              else
         
     | 
| 
      
 18 
     | 
    
         
            +
                File.join(__dir__, 'pg_query_ruby.sym')
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       15 
21 
     | 
    
         
             
            if RUBY_PLATFORM =~ /darwin/
         
     | 
| 
       16 
22 
     | 
    
         
             
              $DLDFLAGS << " -Wl,-exported_symbols_list #{SYMFILE}" unless defined?(::Rubinius)
         
     | 
| 
       17 
23 
     | 
    
         
             
            else
         
     | 
| 
         @@ -291,6 +291,21 @@ _fingerprintNode(FingerprintContext *ctx, const void *obj, const void *parent, c 
     | 
|
| 
       291 
291 
     | 
    
         
             
            	}
         
     | 
| 
       292 
292 
     | 
    
         
             
            }
         
     | 
| 
       293 
293 
     | 
    
         | 
| 
      
 294 
     | 
    
         
            +
            uint64_t pg_query_fingerprint_node(const void *node)
         
     | 
| 
      
 295 
     | 
    
         
            +
            {
         
     | 
| 
      
 296 
     | 
    
         
            +
            	FingerprintContext ctx;
         
     | 
| 
      
 297 
     | 
    
         
            +
            	uint64 result;
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
            	_fingerprintInitContext(&ctx, NULL, false);
         
     | 
| 
      
 300 
     | 
    
         
            +
            	_fingerprintNode(&ctx, node, NULL, NULL, 0);
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
            	result = XXH3_64bits_digest(ctx.xxh_state);
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
            	_fingerprintFreeContext(&ctx);
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
            	return result;
         
     | 
| 
      
 307 
     | 
    
         
            +
            }
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
       294 
309 
     | 
    
         
             
            PgQueryFingerprintResult pg_query_fingerprint_with_opts(const char* input, bool printTokens)
         
     | 
| 
       295 
310 
     | 
    
         
             
            {
         
     | 
| 
       296 
311 
     | 
    
         
             
            	MemoryContext ctx = NULL;
         
     | 
| 
         @@ -3,6 +3,8 @@ 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            #include <stdbool.h>
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
            PgQueryFingerprintResult pg_query_fingerprint_with_opts(const char* input, bool printTokens);
         
     | 
| 
      
 6 
     | 
    
         
            +
            extern PgQueryFingerprintResult pg_query_fingerprint_with_opts(const char* input, bool printTokens);
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            extern uint64_t pg_query_fingerprint_node(const void * node);
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
            #endif
         
     | 
| 
         @@ -1,5 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include "pg_query.h"
         
     | 
| 
       2 
2 
     | 
    
         
             
            #include "pg_query_internal.h"
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include "pg_query_fingerprint.h"
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            #include "parser/parser.h"
         
     | 
| 
       5 
6 
     | 
    
         
             
            #include "parser/scanner.h"
         
     | 
| 
         @@ -14,6 +15,7 @@ typedef struct pgssLocationLen 
     | 
|
| 
       14 
15 
     | 
    
         
             
            {
         
     | 
| 
       15 
16 
     | 
    
         
             
            	int			location;		/* start offset in query text */
         
     | 
| 
       16 
17 
     | 
    
         
             
            	int			length;			/* length in bytes, or -1 to ignore */
         
     | 
| 
      
 18 
     | 
    
         
            +
            	int			param_id;		/* Param id to use - if negative prefix, need to abs(..) and add highest_extern_param_id */
         
     | 
| 
       17 
19 
     | 
    
         
             
            } pgssLocationLen;
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
       19 
21 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -30,14 +32,32 @@ typedef struct pgssConstLocations 
     | 
|
| 
       30 
32 
     | 
    
         
             
            	/* Current number of valid entries in clocations array */
         
     | 
| 
       31 
33 
     | 
    
         
             
            	int			clocations_count;
         
     | 
| 
       32 
34 
     | 
    
         | 
| 
      
 35 
     | 
    
         
            +
            	/* highest Param id we have assigned, not yet taking into account external param refs */
         
     | 
| 
      
 36 
     | 
    
         
            +
            	int			highest_normalize_param_id;
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       33 
38 
     | 
    
         
             
            	/* highest Param id we've seen, in order to start normalization correctly */
         
     | 
| 
       34 
39 
     | 
    
         
             
            	int			highest_extern_param_id;
         
     | 
| 
       35 
40 
     | 
    
         | 
| 
       36 
41 
     | 
    
         
             
            	/* query text */
         
     | 
| 
       37 
42 
     | 
    
         
             
            	const char * query;
         
     | 
| 
       38 
43 
     | 
    
         
             
            	int			query_len;
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            	/* optional recording of assigned or discovered param refs, only active if param_refs is not NULL */
         
     | 
| 
      
 46 
     | 
    
         
            +
            	int *param_refs;
         
     | 
| 
      
 47 
     | 
    
         
            +
            	int param_refs_buf_size;
         
     | 
| 
      
 48 
     | 
    
         
            +
            	int param_refs_count;
         
     | 
| 
       39 
49 
     | 
    
         
             
            } pgssConstLocations;
         
     | 
| 
       40 
50 
     | 
    
         | 
| 
      
 51 
     | 
    
         
            +
            /*
         
     | 
| 
      
 52 
     | 
    
         
            +
             * Intermediate working state struct to remember param refs for individual target list elements
         
     | 
| 
      
 53 
     | 
    
         
            +
             */
         
     | 
| 
      
 54 
     | 
    
         
            +
            typedef struct FpAndParamRefs
         
     | 
| 
      
 55 
     | 
    
         
            +
            {
         
     | 
| 
      
 56 
     | 
    
         
            +
            	uint64_t fp;
         
     | 
| 
      
 57 
     | 
    
         
            +
            	int* param_refs;
         
     | 
| 
      
 58 
     | 
    
         
            +
            	int param_refs_count;
         
     | 
| 
      
 59 
     | 
    
         
            +
            } FpAndParamRefs;
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
       41 
61 
     | 
    
         
             
            /*
         
     | 
| 
       42 
62 
     | 
    
         
             
             * comp_location: comparator for qsorting pgssLocationLen structs by location
         
     | 
| 
       43 
63 
     | 
    
         
             
             */
         
     | 
| 
         @@ -230,7 +250,8 @@ generate_normalized_query(pgssConstLocations *jstate, int query_loc, int* query_ 
     | 
|
| 
       230 
250 
     | 
    
         
             
            	for (i = 0; i < jstate->clocations_count; i++)
         
     | 
| 
       231 
251 
     | 
    
         
             
            	{
         
     | 
| 
       232 
252 
     | 
    
         
             
            		int			off,		/* Offset from start for cur tok */
         
     | 
| 
       233 
     | 
    
         
            -
            					tok_len 
     | 
| 
      
 253 
     | 
    
         
            +
            					tok_len,	/* Length (in bytes) of that tok */
         
     | 
| 
      
 254 
     | 
    
         
            +
            					param_id;	/* Param ID to be assigned */
         
     | 
| 
       234 
255 
     | 
    
         | 
| 
       235 
256 
     | 
    
         
             
            		off = jstate->clocations[i].location;
         
     | 
| 
       236 
257 
     | 
    
         
             
            		/* Adjust recorded location if we're dealing with partial string */
         
     | 
| 
         @@ -250,8 +271,10 @@ generate_normalized_query(pgssConstLocations *jstate, int query_loc, int* query_ 
     | 
|
| 
       250 
271 
     | 
    
         
             
            		n_quer_loc += len_to_wrt;
         
     | 
| 
       251 
272 
     | 
    
         | 
| 
       252 
273 
     | 
    
         
             
            		/* And insert a param symbol in place of the constant token */
         
     | 
| 
       253 
     | 
    
         
            -
            		 
     | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
      
 274 
     | 
    
         
            +
            		param_id = (jstate->clocations[i].param_id < 0) ?
         
     | 
| 
      
 275 
     | 
    
         
            +
            					jstate->highest_extern_param_id + abs(jstate->clocations[i].param_id) :
         
     | 
| 
      
 276 
     | 
    
         
            +
            					jstate->clocations[i].param_id;
         
     | 
| 
      
 277 
     | 
    
         
            +
            		n_quer_loc += sprintf(norm_query + n_quer_loc, "$%d", param_id);
         
     | 
| 
       255 
278 
     | 
    
         | 
| 
       256 
279 
     | 
    
         
             
            		quer_loc = off + tok_len;
         
     | 
| 
       257 
280 
     | 
    
         
             
            		last_off = off;
         
     | 
| 
         @@ -292,6 +315,18 @@ static void RecordConstLocation(pgssConstLocations *jstate, int location) 
     | 
|
| 
       292 
315 
     | 
    
         
             
            		jstate->clocations[jstate->clocations_count].location = location;
         
     | 
| 
       293 
316 
     | 
    
         
             
            		/* initialize lengths to -1 to simplify fill_in_constant_lengths */
         
     | 
| 
       294 
317 
     | 
    
         
             
            		jstate->clocations[jstate->clocations_count].length = -1;
         
     | 
| 
      
 318 
     | 
    
         
            +
            		/* by default we assume that we need a new param ref */
         
     | 
| 
      
 319 
     | 
    
         
            +
            		jstate->clocations[jstate->clocations_count].param_id = - jstate->highest_normalize_param_id;
         
     | 
| 
      
 320 
     | 
    
         
            +
            		jstate->highest_normalize_param_id++;
         
     | 
| 
      
 321 
     | 
    
         
            +
            		/* record param ref number if requested */
         
     | 
| 
      
 322 
     | 
    
         
            +
            		if (jstate->param_refs != NULL) {
         
     | 
| 
      
 323 
     | 
    
         
            +
            			jstate->param_refs[jstate->param_refs_count] = jstate->clocations[jstate->clocations_count].param_id;
         
     | 
| 
      
 324 
     | 
    
         
            +
            			jstate->param_refs_count++;
         
     | 
| 
      
 325 
     | 
    
         
            +
            			if (jstate->param_refs_count >= jstate->param_refs_buf_size) {
         
     | 
| 
      
 326 
     | 
    
         
            +
            				jstate->param_refs_buf_size *= 2;
         
     | 
| 
      
 327 
     | 
    
         
            +
            				jstate->param_refs = (int *) repalloc(jstate->param_refs, jstate->param_refs_buf_size * sizeof(int));
         
     | 
| 
      
 328 
     | 
    
         
            +
            			}
         
     | 
| 
      
 329 
     | 
    
         
            +
            		}
         
     | 
| 
       295 
330 
     | 
    
         
             
            		jstate->clocations_count++;
         
     | 
| 
       296 
331 
     | 
    
         
             
            	}
         
     | 
| 
       297 
332 
     | 
    
         
             
            }
         
     | 
| 
         @@ -313,6 +348,15 @@ static bool const_record_walker(Node *node, pgssConstLocations *jstate) 
     | 
|
| 
       313 
348 
     | 
    
         
             
            				/* Track the highest ParamRef number */
         
     | 
| 
       314 
349 
     | 
    
         
             
            				if (((ParamRef *) node)->number > jstate->highest_extern_param_id)
         
     | 
| 
       315 
350 
     | 
    
         
             
            					jstate->highest_extern_param_id = castNode(ParamRef, node)->number;
         
     | 
| 
      
 351 
     | 
    
         
            +
             
     | 
| 
      
 352 
     | 
    
         
            +
            				if (jstate->param_refs != NULL) {
         
     | 
| 
      
 353 
     | 
    
         
            +
            					jstate->param_refs[jstate->param_refs_count] = ((ParamRef *) node)->number;
         
     | 
| 
      
 354 
     | 
    
         
            +
            					jstate->param_refs_count++;
         
     | 
| 
      
 355 
     | 
    
         
            +
            					if (jstate->param_refs_count >= jstate->param_refs_buf_size) {
         
     | 
| 
      
 356 
     | 
    
         
            +
            						jstate->param_refs_buf_size *= 2;
         
     | 
| 
      
 357 
     | 
    
         
            +
            						jstate->param_refs = (int *) repalloc(jstate->param_refs, jstate->param_refs_buf_size * sizeof(int));
         
     | 
| 
      
 358 
     | 
    
         
            +
            					}
         
     | 
| 
      
 359 
     | 
    
         
            +
            				}
         
     | 
| 
       316 
360 
     | 
    
         
             
            			}
         
     | 
| 
       317 
361 
     | 
    
         
             
            			break;
         
     | 
| 
       318 
362 
     | 
    
         
             
            		case T_DefElem:
         
     | 
| 
         @@ -343,39 +387,95 @@ static bool const_record_walker(Node *node, pgssConstLocations *jstate) 
     | 
|
| 
       343 
387 
     | 
    
         
             
            			return const_record_walker((Node *) ((AlterRoleStmt *) node)->options, jstate);
         
     | 
| 
       344 
388 
     | 
    
         
             
            		case T_DeclareCursorStmt:
         
     | 
| 
       345 
389 
     | 
    
         
             
            			return const_record_walker((Node *) ((DeclareCursorStmt *) node)->query, jstate);
         
     | 
| 
      
 390 
     | 
    
         
            +
            		case T_TypeName:
         
     | 
| 
      
 391 
     | 
    
         
            +
            			/* Don't normalize constants in typmods or arrayBounds */
         
     | 
| 
      
 392 
     | 
    
         
            +
            			return false;
         
     | 
| 
       346 
393 
     | 
    
         
             
            		case T_SelectStmt:
         
     | 
| 
       347 
394 
     | 
    
         
             
            			{
         
     | 
| 
       348 
395 
     | 
    
         
             
            				SelectStmt *stmt = (SelectStmt *) node;
         
     | 
| 
       349 
396 
     | 
    
         
             
            				ListCell *lc;
         
     | 
| 
      
 397 
     | 
    
         
            +
            				List *fp_and_param_refs_list = NIL;
         
     | 
| 
       350 
398 
     | 
    
         | 
| 
       351 
399 
     | 
    
         
             
            				if (const_record_walker((Node *) stmt->distinctClause, jstate))
         
     | 
| 
       352 
400 
     | 
    
         
             
            					return true;
         
     | 
| 
       353 
401 
     | 
    
         
             
            				if (const_record_walker((Node *) stmt->intoClause, jstate))
         
     | 
| 
       354 
402 
     | 
    
         
             
            					return true;
         
     | 
| 
       355 
     | 
    
         
            -
            				 
     | 
| 
       356 
     | 
    
         
            -
             
     | 
| 
      
 403 
     | 
    
         
            +
            				foreach(lc, stmt->targetList)
         
     | 
| 
      
 404 
     | 
    
         
            +
            				{
         
     | 
| 
      
 405 
     | 
    
         
            +
            					ResTarget *res_target = lfirst_node(ResTarget, lc);
         
     | 
| 
      
 406 
     | 
    
         
            +
            					FpAndParamRefs *fp_and_param_refs = palloc0(sizeof(FpAndParamRefs));
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
            					/* Save all param refs we encounter or assign */
         
     | 
| 
      
 409 
     | 
    
         
            +
            					jstate->param_refs = palloc0(1 * sizeof(int));
         
     | 
| 
      
 410 
     | 
    
         
            +
            					jstate->param_refs_buf_size = 1;
         
     | 
| 
      
 411 
     | 
    
         
            +
            					jstate->param_refs_count = 0;
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
            					/* Walk the element */
         
     | 
| 
      
 414 
     | 
    
         
            +
            					if (const_record_walker((Node *) res_target, jstate))
         
     | 
| 
      
 415 
     | 
    
         
            +
            						return true;
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
            					/* Remember fingerprint and param refs for later */
         
     | 
| 
      
 418 
     | 
    
         
            +
            					fp_and_param_refs->fp = pg_query_fingerprint_node(res_target->val);
         
     | 
| 
      
 419 
     | 
    
         
            +
            					fp_and_param_refs->param_refs = jstate->param_refs;
         
     | 
| 
      
 420 
     | 
    
         
            +
            					fp_and_param_refs->param_refs_count = jstate->param_refs_count;
         
     | 
| 
      
 421 
     | 
    
         
            +
            					fp_and_param_refs_list = lappend(fp_and_param_refs_list, fp_and_param_refs);
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
            					/* Reset for next element, or stop recording if this is the last element */
         
     | 
| 
      
 424 
     | 
    
         
            +
            					jstate->param_refs = NULL;
         
     | 
| 
      
 425 
     | 
    
         
            +
            					jstate->param_refs_buf_size = 0;
         
     | 
| 
      
 426 
     | 
    
         
            +
            					jstate->param_refs_count = 0;
         
     | 
| 
      
 427 
     | 
    
         
            +
            				}
         
     | 
| 
       357 
428 
     | 
    
         
             
            				if (const_record_walker((Node *) stmt->fromClause, jstate))
         
     | 
| 
       358 
429 
     | 
    
         
             
            					return true;
         
     | 
| 
       359 
430 
     | 
    
         
             
            				if (const_record_walker((Node *) stmt->whereClause, jstate))
         
     | 
| 
       360 
431 
     | 
    
         
             
            					return true;
         
     | 
| 
       361 
432 
     | 
    
         | 
| 
       362 
     | 
    
         
            -
            				 
     | 
| 
       363 
     | 
    
         
            -
             
     | 
| 
      
 433 
     | 
    
         
            +
            				/*
         
     | 
| 
      
 434 
     | 
    
         
            +
            				 * Instead of walking all of groupClause (like raw_expression_tree_walker does),
         
     | 
| 
      
 435 
     | 
    
         
            +
            				 * only walk certain items.
         
     | 
| 
      
 436 
     | 
    
         
            +
            				 */
         
     | 
| 
       364 
437 
     | 
    
         
             
            				foreach(lc, stmt->groupClause)
         
     | 
| 
       365 
438 
     | 
    
         
             
            				{
         
     | 
| 
       366 
     | 
    
         
            -
            					 
     | 
| 
       367 
     | 
    
         
            -
             
     | 
| 
       368 
     | 
    
         
            -
             
     | 
| 
       369 
     | 
    
         
            -
             
     | 
| 
      
 439 
     | 
    
         
            +
            					/*
         
     | 
| 
      
 440 
     | 
    
         
            +
            					 * Do not walk A_Const values that are simple integers, this avoids
         
     | 
| 
      
 441 
     | 
    
         
            +
            					 * turning "GROUP BY 1" into "GROUP BY $n", which obscures an important
         
     | 
| 
      
 442 
     | 
    
         
            +
            					 * semantic meaning. This matches how pg_stat_statements handles the
         
     | 
| 
      
 443 
     | 
    
         
            +
            					 * GROUP BY clause (i.e. it doesn't touch these constants)
         
     | 
| 
      
 444 
     | 
    
         
            +
            					 */
         
     | 
| 
       370 
445 
     | 
    
         
             
            					if (IsA(lfirst(lc), A_Const) && IsA(&castNode(A_Const, lfirst(lc))->val, Integer))
         
     | 
| 
       371 
446 
     | 
    
         
             
            						continue;
         
     | 
| 
       372 
447 
     | 
    
         | 
| 
      
 448 
     | 
    
         
            +
            					/*
         
     | 
| 
      
 449 
     | 
    
         
            +
            					 * Match up GROUP BY clauses against the target list, to assign the same
         
     | 
| 
      
 450 
     | 
    
         
            +
            					 * param refs as used in the target list - this ensures the query is valid,
         
     | 
| 
      
 451 
     | 
    
         
            +
            					 * instead of throwing a bogus "columns ... must appear in the GROUP BY
         
     | 
| 
      
 452 
     | 
    
         
            +
            					 * clause or be used in an aggregate function" error
         
     | 
| 
      
 453 
     | 
    
         
            +
            					 */
         
     | 
| 
      
 454 
     | 
    
         
            +
            					uint64_t fp = pg_query_fingerprint_node(lfirst(lc));
         
     | 
| 
      
 455 
     | 
    
         
            +
            					FpAndParamRefs *fppr = NULL;
         
     | 
| 
      
 456 
     | 
    
         
            +
            					ListCell *lc2;
         
     | 
| 
      
 457 
     | 
    
         
            +
            					foreach(lc2, fp_and_param_refs_list) {
         
     | 
| 
      
 458 
     | 
    
         
            +
            						if (fp == ((FpAndParamRefs *) lfirst(lc2))->fp) {
         
     | 
| 
      
 459 
     | 
    
         
            +
            							fppr = (FpAndParamRefs *) lfirst(lc2);
         
     | 
| 
      
 460 
     | 
    
         
            +
            							foreach_delete_current(fp_and_param_refs_list, lc2);
         
     | 
| 
      
 461 
     | 
    
         
            +
            							break;
         
     | 
| 
      
 462 
     | 
    
         
            +
            						}
         
     | 
| 
      
 463 
     | 
    
         
            +
            					}
         
     | 
| 
      
 464 
     | 
    
         
            +
             
     | 
| 
      
 465 
     | 
    
         
            +
            					int prev_cloc_count = jstate->clocations_count;
         
     | 
| 
       373 
466 
     | 
    
         
             
            					if (const_record_walker((Node *) lfirst(lc), jstate))
         
     | 
| 
       374 
467 
     | 
    
         
             
            						return true;
         
     | 
| 
      
 468 
     | 
    
         
            +
             
     | 
| 
      
 469 
     | 
    
         
            +
            					if (fppr != NULL && fppr->param_refs_count == jstate->clocations_count - prev_cloc_count) {
         
     | 
| 
      
 470 
     | 
    
         
            +
            						for (int i = prev_cloc_count; i < jstate->clocations_count; i++) {
         
     | 
| 
      
 471 
     | 
    
         
            +
            							jstate->clocations[i].param_id = fppr->param_refs[i - prev_cloc_count];
         
     | 
| 
      
 472 
     | 
    
         
            +
            						}
         
     | 
| 
      
 473 
     | 
    
         
            +
            						jstate->highest_normalize_param_id -= fppr->param_refs_count;
         
     | 
| 
      
 474 
     | 
    
         
            +
            					}
         
     | 
| 
       375 
475 
     | 
    
         
             
            				}
         
     | 
| 
       376 
476 
     | 
    
         
             
            				foreach(lc, stmt->sortClause)
         
     | 
| 
       377 
477 
     | 
    
         
             
            				{
         
     | 
| 
       378 
     | 
    
         
            -
            					 
     | 
| 
      
 478 
     | 
    
         
            +
            					/* Similarly, don't turn "ORDER BY 1" into "ORDER BY $n" */
         
     | 
| 
       379 
479 
     | 
    
         
             
            					if (IsA(lfirst(lc), SortBy) && IsA(castNode(SortBy, lfirst(lc))->node, A_Const) &&
         
     | 
| 
       380 
480 
     | 
    
         
             
            					    IsA(&castNode(A_Const, castNode(SortBy, lfirst(lc))->node)->val, Integer))
         
     | 
| 
       381 
481 
     | 
    
         
             
            						continue;
         
     | 
| 
         @@ -445,9 +545,13 @@ PgQueryNormalizeResult pg_query_normalize(const char* input) 
     | 
|
| 
       445 
545 
     | 
    
         
             
            		jstate.clocations = (pgssLocationLen *)
         
     | 
| 
       446 
546 
     | 
    
         
             
            			palloc(jstate.clocations_buf_size * sizeof(pgssLocationLen));
         
     | 
| 
       447 
547 
     | 
    
         
             
            		jstate.clocations_count = 0;
         
     | 
| 
      
 548 
     | 
    
         
            +
            		jstate.highest_normalize_param_id = 1;
         
     | 
| 
       448 
549 
     | 
    
         
             
            		jstate.highest_extern_param_id = 0;
         
     | 
| 
       449 
550 
     | 
    
         
             
            		jstate.query = input;
         
     | 
| 
       450 
551 
     | 
    
         
             
            		jstate.query_len = query_len;
         
     | 
| 
      
 552 
     | 
    
         
            +
            		jstate.param_refs = NULL;
         
     | 
| 
      
 553 
     | 
    
         
            +
            		jstate.param_refs_buf_size = 0;
         
     | 
| 
      
 554 
     | 
    
         
            +
            		jstate.param_refs_count = 0;
         
     | 
| 
       451 
555 
     | 
    
         | 
| 
       452 
556 
     | 
    
         
             
            		/* Walk tree and record const locations */
         
     | 
| 
       453 
557 
     | 
    
         
             
            		const_record_walker((Node *) tree, &jstate);
         
     | 
| 
         @@ -466,6 +570,8 @@ PgQueryNormalizeResult pg_query_normalize(const char* input) 
     | 
|
| 
       466 
570 
     | 
    
         
             
            		error = malloc(sizeof(PgQueryError));
         
     | 
| 
       467 
571 
     | 
    
         
             
            		error->message   = strdup(error_data->message);
         
     | 
| 
       468 
572 
     | 
    
         
             
            		error->filename  = strdup(error_data->filename);
         
     | 
| 
      
 573 
     | 
    
         
            +
            		error->funcname  = strdup(error_data->funcname);
         
     | 
| 
      
 574 
     | 
    
         
            +
            		error->context   = NULL;
         
     | 
| 
       469 
575 
     | 
    
         
             
            		error->lineno    = error_data->lineno;
         
     | 
| 
       470 
576 
     | 
    
         
             
            		error->cursorpos = error_data->cursorpos;
         
     | 
| 
       471 
577 
     | 
    
         | 
| 
         @@ -484,6 +590,7 @@ void pg_query_free_normalize_result(PgQueryNormalizeResult result) 
     | 
|
| 
       484 
590 
     | 
    
         
             
              if (result.error) {
         
     | 
| 
       485 
591 
     | 
    
         
             
                free(result.error->message);
         
     | 
| 
       486 
592 
     | 
    
         
             
                free(result.error->filename);
         
     | 
| 
      
 593 
     | 
    
         
            +
                free(result.error->funcname);
         
     | 
| 
       487 
594 
     | 
    
         
             
                free(result.error);
         
     | 
| 
       488 
595 
     | 
    
         
             
              }
         
     | 
| 
       489 
596 
     | 
    
         | 
| 
         @@ -108,7 +108,7 @@ static PLpgSQL_function *compile_create_function_stmt(CreateFunctionStmt* stmt) 
     | 
|
| 
       108 
108 
     | 
    
         
             
            		}
         
     | 
| 
       109 
109 
     | 
    
         
             
            	}
         
     | 
| 
       110 
110 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
            	assert(proc_source);
         
     | 
| 
      
 111 
     | 
    
         
            +
            	assert(proc_source != NULL);
         
     | 
| 
       112 
112 
     | 
    
         | 
| 
       113 
113 
     | 
    
         
             
            	if (stmt->returnType != NULL) {
         
     | 
| 
       114 
114 
     | 
    
         
             
            		foreach(lc3, stmt->returnType->names)
         
     | 
| 
         @@ -179,6 +179,26 @@ static PLpgSQL_function *compile_create_function_stmt(CreateFunctionStmt* stmt) 
     | 
|
| 
       179 
179 
     | 
    
         
             
            	plpgsql_DumpExecTree = false;
         
     | 
| 
       180 
180 
     | 
    
         
             
            	plpgsql_start_datums();
         
     | 
| 
       181 
181 
     | 
    
         | 
| 
      
 182 
     | 
    
         
            +
            	/* Setup parameter names */
         
     | 
| 
      
 183 
     | 
    
         
            +
            	foreach(lc, stmt->parameters)
         
     | 
| 
      
 184 
     | 
    
         
            +
            	{
         
     | 
| 
      
 185 
     | 
    
         
            +
            		FunctionParameter *param = lfirst_node(FunctionParameter, lc);
         
     | 
| 
      
 186 
     | 
    
         
            +
            		if (param->name != NULL)
         
     | 
| 
      
 187 
     | 
    
         
            +
            		{
         
     | 
| 
      
 188 
     | 
    
         
            +
            			char buf[32];
         
     | 
| 
      
 189 
     | 
    
         
            +
            			PLpgSQL_type *argdtype;
         
     | 
| 
      
 190 
     | 
    
         
            +
            			PLpgSQL_variable *argvariable;
         
     | 
| 
      
 191 
     | 
    
         
            +
            			PLpgSQL_nsitem_type argitemtype;
         
     | 
| 
      
 192 
     | 
    
         
            +
            			snprintf(buf, sizeof(buf), "$%d", foreach_current_index(lc) + 1);
         
     | 
| 
      
 193 
     | 
    
         
            +
            			argdtype = plpgsql_build_datatype(UNKNOWNOID, -1, InvalidOid, NULL);
         
     | 
| 
      
 194 
     | 
    
         
            +
            			argvariable = plpgsql_build_variable(param->name ? param->name : buf, 0, argdtype, false);
         
     | 
| 
      
 195 
     | 
    
         
            +
            			argitemtype = argvariable->dtype == PLPGSQL_DTYPE_VAR ? PLPGSQL_NSTYPE_VAR : PLPGSQL_NSTYPE_REC;
         
     | 
| 
      
 196 
     | 
    
         
            +
            			plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
         
     | 
| 
      
 197 
     | 
    
         
            +
            			if (param->name != NULL)
         
     | 
| 
      
 198 
     | 
    
         
            +
            				plpgsql_ns_additem(argitemtype, argvariable->dno, param->name);
         
     | 
| 
      
 199 
     | 
    
         
            +
            		}
         
     | 
| 
      
 200 
     | 
    
         
            +
            	}
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
       182 
202 
     | 
    
         
             
            	/* Set up as though in a function returning VOID */
         
     | 
| 
       183 
203 
     | 
    
         
             
            	function->fn_rettype = VOIDOID;
         
     | 
| 
       184 
204 
     | 
    
         
             
            	function->fn_retset = is_setof;
         
     | 
| 
         @@ -14,7 +14,7 @@ VALUE pg_query_ruby_fingerprint(VALUE self, VALUE input); 
     | 
|
| 
       14 
14 
     | 
    
         
             
            VALUE pg_query_ruby_scan(VALUE self, VALUE input);
         
     | 
| 
       15 
15 
     | 
    
         
             
            VALUE pg_query_ruby_hash_xxh3_64(VALUE self, VALUE input, VALUE seed);
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
            void Init_pg_query(void)
         
     | 
| 
      
 17 
     | 
    
         
            +
            __attribute__((visibility ("default"))) void Init_pg_query(void)
         
     | 
| 
       18 
18 
     | 
    
         
             
            {
         
     | 
| 
       19 
19 
     | 
    
         
             
            	VALUE cPgQuery;
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
         @@ -6147,7 +6147,7 @@ plpgsql_sql_error_callback(void *arg) 
     | 
|
| 
       6147 
6147 
     | 
    
         
             
             * This is handled the same as in check_sql_expr(), and we likewise
         
     | 
| 
       6148 
6148 
     | 
    
         
             
             * expect that the given string is a copy from the source text.
         
     | 
| 
       6149 
6149 
     | 
    
         
             
             */
         
     | 
| 
       6150 
     | 
    
         
            -
            static PLpgSQL_type * parse_datatype(const char *string, int location) { PLpgSQL_type *typ; typ = (PLpgSQL_type *) palloc0(sizeof(PLpgSQL_type)); typ->typname = pstrdup(string); typ->ttype = PLPGSQL_TTYPE_SCALAR; return typ; }
         
     | 
| 
      
 6150 
     | 
    
         
            +
            static PLpgSQL_type * parse_datatype(const char *string, int location) { PLpgSQL_type *typ; typ = (PLpgSQL_type *) palloc0(sizeof(PLpgSQL_type)); typ->typname = pstrdup(string); typ->ttype = strcmp(string, "RECORD") == 0 ? PLPGSQL_TTYPE_REC : PLPGSQL_TTYPE_SCALAR; return typ; }
         
     | 
| 
       6151 
6151 
     | 
    
         | 
| 
       6152 
6152 
     | 
    
         | 
| 
       6153 
6153 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -42,14 +42,16 @@ module PgQuery 
     | 
|
| 
       42 
42 
     | 
    
         
             
                              statements << item.common_table_expr.ctequery if item.node == :common_table_expr
         
     | 
| 
       43 
43 
     | 
    
         
             
                            end
         
     | 
| 
       44 
44 
     | 
    
         
             
                          end
         
     | 
| 
       45 
     | 
    
         
            -
                        when :SETOP_UNION
         
     | 
| 
       46 
     | 
    
         
            -
                          statements << statement.select_stmt.larg if statement.select_stmt.larg
         
     | 
| 
       47 
     | 
    
         
            -
                          statements << statement.select_stmt.rarg if statement.select_stmt.rarg
         
     | 
| 
      
 45 
     | 
    
         
            +
                        when :SETOP_UNION, :SETOP_EXCEPT, :SETOP_INTERSECT
         
     | 
| 
      
 46 
     | 
    
         
            +
                          statements << PgQuery::Node.new(select_stmt: statement.select_stmt.larg) if statement.select_stmt.larg
         
     | 
| 
      
 47 
     | 
    
         
            +
                          statements << PgQuery::Node.new(select_stmt: statement.select_stmt.rarg) if statement.select_stmt.rarg
         
     | 
| 
       48 
48 
     | 
    
         
             
                        end
         
     | 
| 
       49 
49 
     | 
    
         
             
                      when :update_stmt
         
     | 
| 
       50 
50 
     | 
    
         
             
                        condition_items << statement.update_stmt.where_clause if statement.update_stmt.where_clause
         
     | 
| 
       51 
51 
     | 
    
         
             
                      when :delete_stmt
         
     | 
| 
       52 
52 
     | 
    
         
             
                        condition_items << statement.delete_stmt.where_clause if statement.delete_stmt.where_clause
         
     | 
| 
      
 53 
     | 
    
         
            +
                      when :index_stmt
         
     | 
| 
      
 54 
     | 
    
         
            +
                        condition_items << statement.index_stmt.where_clause if statement.index_stmt.where_clause
         
     | 
| 
       53 
55 
     | 
    
         
             
                      end
         
     | 
| 
       54 
56 
     | 
    
         
             
                    end
         
     | 
| 
       55 
57 
     | 
    
         | 
    
        data/lib/pg_query/parse.rb
    CHANGED
    
    | 
         @@ -3,7 +3,13 @@ module PgQuery 
     | 
|
| 
       3 
3 
     | 
    
         
             
                result, stderr = parse_protobuf(query)
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                begin
         
     | 
| 
       6 
     | 
    
         
            -
                  result = PgQuery::ParseResult.decode 
     | 
| 
      
 6 
     | 
    
         
            +
                  result = if PgQuery::ParseResult.method(:decode).arity == 1
         
     | 
| 
      
 7 
     | 
    
         
            +
                             PgQuery::ParseResult.decode(result)
         
     | 
| 
      
 8 
     | 
    
         
            +
                           elsif PgQuery::ParseResult.method(:decode).arity == -1
         
     | 
| 
      
 9 
     | 
    
         
            +
                             PgQuery::ParseResult.decode(result, recursion_limit: 1_000)
         
     | 
| 
      
 10 
     | 
    
         
            +
                           else
         
     | 
| 
      
 11 
     | 
    
         
            +
                             raise ArgumentError, 'Unsupported protobuf Ruby API'
         
     | 
| 
      
 12 
     | 
    
         
            +
                           end
         
     | 
| 
       7 
13 
     | 
    
         
             
                rescue Google::Protobuf::ParseError => e
         
     | 
| 
       8 
14 
     | 
    
         
             
                  raise PgQuery::ParseError.new(format('Failed to parse tree: %s', e.message), __FILE__, __LINE__, -1)
         
     | 
| 
       9 
15 
     | 
    
         
             
                end
         
     | 
| 
         @@ -89,6 +95,10 @@ module PgQuery 
     | 
|
| 
       89 
95 
     | 
    
         | 
| 
       90 
96 
     | 
    
         
             
                protected
         
     | 
| 
       91 
97 
     | 
    
         | 
| 
      
 98 
     | 
    
         
            +
                # Parses the query and finds table and function references
         
     | 
| 
      
 99 
     | 
    
         
            +
                #
         
     | 
| 
      
 100 
     | 
    
         
            +
                # Note we use ".to_ary" on arrays from the Protobuf library before
         
     | 
| 
      
 101 
     | 
    
         
            +
                # passing them to concat, because of https://bugs.ruby-lang.org/issues/18140
         
     | 
| 
       92 
102 
     | 
    
         
             
                def load_objects! # rubocop:disable Metrics/CyclomaticComplexity
         
     | 
| 
       93 
103 
     | 
    
         
             
                  @tables = [] # types: select, dml, ddl
         
     | 
| 
       94 
104 
     | 
    
         
             
                  @cte_names = []
         
     | 
| 
         @@ -108,22 +118,18 @@ module PgQuery 
     | 
|
| 
       108 
118 
     | 
    
         
             
                      # The following statement types do not modify tables and are added to from_clause_items
         
     | 
| 
       109 
119 
     | 
    
         
             
                      # (and subsequently @tables)
         
     | 
| 
       110 
120 
     | 
    
         
             
                      when :select_stmt
         
     | 
| 
       111 
     | 
    
         
            -
                        subselect_items.concat(statement.select_stmt.target_list)
         
     | 
| 
      
 121 
     | 
    
         
            +
                        subselect_items.concat(statement.select_stmt.target_list.to_ary)
         
     | 
| 
       112 
122 
     | 
    
         
             
                        subselect_items << statement.select_stmt.where_clause if statement.select_stmt.where_clause
         
     | 
| 
       113 
123 
     | 
    
         
             
                        subselect_items.concat(statement.select_stmt.sort_clause.collect { |h| h.sort_by.node })
         
     | 
| 
       114 
     | 
    
         
            -
                        subselect_items.concat(statement.select_stmt.group_clause)
         
     | 
| 
      
 124 
     | 
    
         
            +
                        subselect_items.concat(statement.select_stmt.group_clause.to_ary)
         
     | 
| 
       115 
125 
     | 
    
         
             
                        subselect_items << statement.select_stmt.having_clause if statement.select_stmt.having_clause
         
     | 
| 
       116 
126 
     | 
    
         | 
| 
       117 
127 
     | 
    
         
             
                        case statement.select_stmt.op
         
     | 
| 
       118 
128 
     | 
    
         
             
                        when :SETOP_NONE
         
     | 
| 
       119 
129 
     | 
    
         
             
                          (statement.select_stmt.from_clause || []).each do |item|
         
     | 
| 
       120 
     | 
    
         
            -
                             
     | 
| 
       121 
     | 
    
         
            -
                              statements << item.range_subselect.subquery
         
     | 
| 
       122 
     | 
    
         
            -
                            else
         
     | 
| 
       123 
     | 
    
         
            -
                              from_clause_items << { item: item, type: :select }
         
     | 
| 
       124 
     | 
    
         
            -
                            end
         
     | 
| 
      
 130 
     | 
    
         
            +
                            from_clause_items << { item: item, type: :select }
         
     | 
| 
       125 
131 
     | 
    
         
             
                          end
         
     | 
| 
       126 
     | 
    
         
            -
                        when :SETOP_UNION
         
     | 
| 
      
 132 
     | 
    
         
            +
                        when :SETOP_UNION, :SETOP_EXCEPT, :SETOP_INTERSECT
         
     | 
| 
       127 
133 
     | 
    
         
             
                          statements << PgQuery::Node.new(select_stmt: statement.select_stmt.larg) if statement.select_stmt.larg
         
     | 
| 
       128 
134 
     | 
    
         
             
                          statements << PgQuery::Node.new(select_stmt: statement.select_stmt.rarg) if statement.select_stmt.rarg
         
     | 
| 
       129 
135 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -143,12 +149,18 @@ module PgQuery 
     | 
|
| 
       143 
149 
     | 
    
         
             
                          value.from_clause.each do |item|
         
     | 
| 
       144 
150 
     | 
    
         
             
                            from_clause_items << { item: item, type: :select }
         
     | 
| 
       145 
151 
     | 
    
         
             
                          end
         
     | 
| 
       146 
     | 
    
         
            -
                          subselect_items.concat(statement.update_stmt.target_list)
         
     | 
| 
      
 152 
     | 
    
         
            +
                          subselect_items.concat(statement.update_stmt.target_list.to_ary)
         
     | 
| 
       147 
153 
     | 
    
         
             
                        end
         
     | 
| 
       148 
154 
     | 
    
         | 
| 
       149 
155 
     | 
    
         
             
                        subselect_items << statement.update_stmt.where_clause if statement.node == :update_stmt && statement.update_stmt.where_clause
         
     | 
| 
       150 
156 
     | 
    
         
             
                        subselect_items << statement.delete_stmt.where_clause if statement.node == :delete_stmt && statement.delete_stmt.where_clause
         
     | 
| 
       151 
157 
     | 
    
         | 
| 
      
 158 
     | 
    
         
            +
                        if statement.node == :delete_stmt
         
     | 
| 
      
 159 
     | 
    
         
            +
                          statement.delete_stmt.using_clause.each do |using_clause|
         
     | 
| 
      
 160 
     | 
    
         
            +
                            from_clause_items << { item: using_clause, type: :select }
         
     | 
| 
      
 161 
     | 
    
         
            +
                          end
         
     | 
| 
      
 162 
     | 
    
         
            +
                        end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
       152 
164 
     | 
    
         
             
                        if value.with_clause
         
     | 
| 
       153 
165 
     | 
    
         
             
                          cte_statements, cte_names = statements_and_cte_names_for_with_clause(value.with_clause)
         
     | 
| 
       154 
166 
     | 
    
         
             
                          @cte_names.concat(cte_names)
         
     | 
| 
         @@ -174,6 +186,11 @@ module PgQuery 
     | 
|
| 
       174 
186 
     | 
    
         
             
                        statements << statement.view_stmt.query
         
     | 
| 
       175 
187 
     | 
    
         
             
                      when :index_stmt
         
     | 
| 
       176 
188 
     | 
    
         
             
                        from_clause_items << { item: PgQuery::Node.new(range_var: statement.index_stmt.relation), type: :ddl }
         
     | 
| 
      
 189 
     | 
    
         
            +
                        statement.index_stmt.index_params.each do |p|
         
     | 
| 
      
 190 
     | 
    
         
            +
                          next if p.index_elem.expr.nil?
         
     | 
| 
      
 191 
     | 
    
         
            +
                          subselect_items << p.index_elem.expr
         
     | 
| 
      
 192 
     | 
    
         
            +
                        end
         
     | 
| 
      
 193 
     | 
    
         
            +
                        subselect_items << statement.index_stmt.where_clause if statement.index_stmt.where_clause
         
     | 
| 
       177 
194 
     | 
    
         
             
                      when :create_trig_stmt
         
     | 
| 
       178 
195 
     | 
    
         
             
                        from_clause_items << { item: PgQuery::Node.new(range_var: statement.create_trig_stmt.relation), type: :ddl }
         
     | 
| 
       179 
196 
     | 
    
         
             
                      when :rule_stmt
         
     | 
| 
         @@ -236,6 +253,8 @@ module PgQuery 
     | 
|
| 
       236 
253 
     | 
    
         
             
                    next_item = subselect_items.shift
         
     | 
| 
       237 
254 
     | 
    
         
             
                    if next_item
         
     | 
| 
       238 
255 
     | 
    
         
             
                      case next_item.node
         
     | 
| 
      
 256 
     | 
    
         
            +
                      when :list
         
     | 
| 
      
 257 
     | 
    
         
            +
                        subselect_items += next_item.list.items.to_ary
         
     | 
| 
       239 
258 
     | 
    
         
             
                      when :a_expr
         
     | 
| 
       240 
259 
     | 
    
         
             
                        %w[lexpr rexpr].each do |side|
         
     | 
| 
       241 
260 
     | 
    
         
             
                          elem = next_item.a_expr.public_send(side)
         
     | 
| 
         @@ -247,56 +266,61 @@ module PgQuery 
     | 
|
| 
       247 
266 
     | 
    
         
             
                          end
         
     | 
| 
       248 
267 
     | 
    
         
             
                        end
         
     | 
| 
       249 
268 
     | 
    
         
             
                      when :bool_expr
         
     | 
| 
       250 
     | 
    
         
            -
                        subselect_items.concat(next_item.bool_expr.args)
         
     | 
| 
      
 269 
     | 
    
         
            +
                        subselect_items.concat(next_item.bool_expr.args.to_ary)
         
     | 
| 
       251 
270 
     | 
    
         
             
                      when :coalesce_expr
         
     | 
| 
       252 
     | 
    
         
            -
                        subselect_items.concat(next_item.coalesce_expr.args)
         
     | 
| 
      
 271 
     | 
    
         
            +
                        subselect_items.concat(next_item.coalesce_expr.args.to_ary)
         
     | 
| 
       253 
272 
     | 
    
         
             
                      when :min_max_expr
         
     | 
| 
       254 
     | 
    
         
            -
                        subselect_items.concat(next_item.min_max_expr.args)
         
     | 
| 
      
 273 
     | 
    
         
            +
                        subselect_items.concat(next_item.min_max_expr.args.to_ary)
         
     | 
| 
       255 
274 
     | 
    
         
             
                      when :res_target
         
     | 
| 
       256 
275 
     | 
    
         
             
                        subselect_items << next_item.res_target.val
         
     | 
| 
       257 
276 
     | 
    
         
             
                      when :sub_link
         
     | 
| 
       258 
277 
     | 
    
         
             
                        statements << next_item.sub_link.subselect
         
     | 
| 
       259 
278 
     | 
    
         
             
                      when :func_call
         
     | 
| 
      
 279 
     | 
    
         
            +
                        subselect_items.concat(next_item.func_call.args.to_ary)
         
     | 
| 
       260 
280 
     | 
    
         
             
                        @functions << {
         
     | 
| 
       261 
     | 
    
         
            -
                          function: next_item.func_call.funcname 
     | 
| 
      
 281 
     | 
    
         
            +
                          function: next_item.func_call.funcname.map { |f| f.string.str }.join('.'),
         
     | 
| 
       262 
282 
     | 
    
         
             
                          type: :call
         
     | 
| 
       263 
283 
     | 
    
         
             
                        }
         
     | 
| 
      
 284 
     | 
    
         
            +
                      when :case_expr
         
     | 
| 
      
 285 
     | 
    
         
            +
                        subselect_items.concat(next_item.case_expr.args.map { |arg| arg.case_when.expr })
         
     | 
| 
      
 286 
     | 
    
         
            +
                        subselect_items.concat(next_item.case_expr.args.map { |arg| arg.case_when.result })
         
     | 
| 
      
 287 
     | 
    
         
            +
                        subselect_items << next_item.case_expr.defresult
         
     | 
| 
      
 288 
     | 
    
         
            +
                      when :type_cast
         
     | 
| 
      
 289 
     | 
    
         
            +
                        subselect_items << next_item.type_cast.arg
         
     | 
| 
       264 
290 
     | 
    
         
             
                      end
         
     | 
| 
       265 
291 
     | 
    
         
             
                    end
         
     | 
| 
       266 
292 
     | 
    
         | 
| 
       267 
     | 
    
         
            -
                    break if subselect_items.empty? && statements.empty?
         
     | 
| 
       268 
     | 
    
         
            -
                  end
         
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
                  loop do
         
     | 
| 
       271 
293 
     | 
    
         
             
                    next_item = from_clause_items.shift
         
     | 
| 
       272 
     | 
    
         
            -
                     
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
       274 
     | 
    
         
            -
             
     | 
| 
       275 
     | 
    
         
            -
             
     | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
       277 
     | 
    
         
            -
             
     | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
       279 
     | 
    
         
            -
             
     | 
| 
       280 
     | 
    
         
            -
             
     | 
| 
       281 
     | 
    
         
            -
             
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
             
     | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
       288 
     | 
    
         
            -
             
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
       293 
     | 
    
         
            -
             
     | 
| 
       294 
     | 
    
         
            -
             
     | 
| 
       295 
     | 
    
         
            -
             
     | 
| 
       296 
     | 
    
         
            -
             
     | 
| 
       297 
     | 
    
         
            -
             
     | 
| 
       298 
     | 
    
         
            -
                       
     | 
| 
      
 294 
     | 
    
         
            +
                    if next_item && next_item[:item]
         
     | 
| 
      
 295 
     | 
    
         
            +
                      case next_item[:item].node
         
     | 
| 
      
 296 
     | 
    
         
            +
                      when :join_expr
         
     | 
| 
      
 297 
     | 
    
         
            +
                        from_clause_items << { item: next_item[:item].join_expr.larg, type: next_item[:type] }
         
     | 
| 
      
 298 
     | 
    
         
            +
                        from_clause_items << { item: next_item[:item].join_expr.rarg, type: next_item[:type] }
         
     | 
| 
      
 299 
     | 
    
         
            +
                        subselect_items << next_item[:item].join_expr.quals
         
     | 
| 
      
 300 
     | 
    
         
            +
                      when :row_expr
         
     | 
| 
      
 301 
     | 
    
         
            +
                        from_clause_items += next_item[:item].row_expr.args.map { |a| { item: a, type: next_item[:type] } }
         
     | 
| 
      
 302 
     | 
    
         
            +
                      when :range_var
         
     | 
| 
      
 303 
     | 
    
         
            +
                        rangevar = next_item[:item].range_var
         
     | 
| 
      
 304 
     | 
    
         
            +
                        next if rangevar.schemaname.empty? && @cte_names.include?(rangevar.relname)
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                        table = [rangevar.schemaname, rangevar.relname].reject { |s| s.nil? || s.empty? }.join('.')
         
     | 
| 
      
 307 
     | 
    
         
            +
                        @tables << {
         
     | 
| 
      
 308 
     | 
    
         
            +
                          name: table,
         
     | 
| 
      
 309 
     | 
    
         
            +
                          type: next_item[:type],
         
     | 
| 
      
 310 
     | 
    
         
            +
                          location: rangevar.location,
         
     | 
| 
      
 311 
     | 
    
         
            +
                          schemaname: (rangevar.schemaname unless rangevar.schemaname.empty?),
         
     | 
| 
      
 312 
     | 
    
         
            +
                          relname: rangevar.relname,
         
     | 
| 
      
 313 
     | 
    
         
            +
                          inh: rangevar.inh
         
     | 
| 
      
 314 
     | 
    
         
            +
                        }
         
     | 
| 
      
 315 
     | 
    
         
            +
                        @aliases[rangevar.alias.aliasname] = table if rangevar.alias
         
     | 
| 
      
 316 
     | 
    
         
            +
                      when :range_subselect
         
     | 
| 
      
 317 
     | 
    
         
            +
                        statements << next_item[:item].range_subselect.subquery
         
     | 
| 
      
 318 
     | 
    
         
            +
                      when :range_function
         
     | 
| 
      
 319 
     | 
    
         
            +
                        subselect_items += next_item[:item].range_function.functions
         
     | 
| 
      
 320 
     | 
    
         
            +
                      end
         
     | 
| 
       299 
321 
     | 
    
         
             
                    end
         
     | 
| 
      
 322 
     | 
    
         
            +
             
     | 
| 
      
 323 
     | 
    
         
            +
                    break if subselect_items.empty? && statements.empty? && from_clause_items.empty?
         
     | 
| 
       300 
324 
     | 
    
         
             
                  end
         
     | 
| 
       301 
325 
     | 
    
         | 
| 
       302 
326 
     | 
    
         
             
                  @tables.uniq!
         
     | 
    
        data/lib/pg_query/truncate.rb
    CHANGED
    
    | 
         @@ -32,6 +32,12 @@ module PgQuery 
     | 
|
| 
       32 
32 
     | 
    
         
             
                        )
         
     | 
| 
       33 
33 
     | 
    
         
             
                      when :where_clause
         
     | 
| 
       34 
34 
     | 
    
         
             
                        node.where_clause = dummy_column_ref
         
     | 
| 
      
 35 
     | 
    
         
            +
                      when :values_lists
         
     | 
| 
      
 36 
     | 
    
         
            +
                        node.values_lists.replace(
         
     | 
| 
      
 37 
     | 
    
         
            +
                          [
         
     | 
| 
      
 38 
     | 
    
         
            +
                            PgQuery::Node.new(list: PgQuery::List.new(items: [dummy_column_ref]))
         
     | 
| 
      
 39 
     | 
    
         
            +
                          ]
         
     | 
| 
      
 40 
     | 
    
         
            +
                        )
         
     | 
| 
       35 
41 
     | 
    
         
             
                      when :ctequery
         
     | 
| 
       36 
42 
     | 
    
         
             
                        node.ctequery = PgQuery::Node.new(select_stmt: PgQuery::SelectStmt.new(where_clause: dummy_column_ref, op: :SETOP_NONE))
         
     | 
| 
       37 
43 
     | 
    
         
             
                      when :cols
         
     | 
| 
         @@ -58,7 +64,11 @@ module PgQuery 
     | 
|
| 
       58 
64 
     | 
    
         
             
                    case k
         
     | 
| 
       59 
65 
     | 
    
         
             
                    when :target_list
         
     | 
| 
       60 
66 
     | 
    
         
             
                      next unless node.is_a?(PgQuery::SelectStmt) || node.is_a?(PgQuery::UpdateStmt) || node.is_a?(PgQuery::OnConflictClause)
         
     | 
| 
       61 
     | 
    
         
            -
                      length =  
     | 
| 
      
 67 
     | 
    
         
            +
                      length = if node.is_a?(PgQuery::SelectStmt)
         
     | 
| 
      
 68 
     | 
    
         
            +
                                 select_target_list_len(v)
         
     | 
| 
      
 69 
     | 
    
         
            +
                               else # UpdateStmt / OnConflictClause
         
     | 
| 
      
 70 
     | 
    
         
            +
                                 update_target_list_len(v)
         
     | 
| 
      
 71 
     | 
    
         
            +
                               end
         
     | 
| 
       62 
72 
     | 
    
         
             
                      truncations << PossibleTruncation.new(location, :target_list, length, true)
         
     | 
| 
       63 
73 
     | 
    
         
             
                    when :where_clause
         
     | 
| 
       64 
74 
     | 
    
         
             
                      next unless node.is_a?(PgQuery::SelectStmt) || node.is_a?(PgQuery::UpdateStmt) || node.is_a?(PgQuery::DeleteStmt) ||
         
     | 
| 
         @@ -67,23 +77,59 @@ module PgQuery 
     | 
|
| 
       67 
77 
     | 
    
         | 
| 
       68 
78 
     | 
    
         
             
                      length = PgQuery.deparse_expr(v).size
         
     | 
| 
       69 
79 
     | 
    
         
             
                      truncations << PossibleTruncation.new(location, :where_clause, length, false)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    when :values_lists
         
     | 
| 
      
 81 
     | 
    
         
            +
                      length = select_values_lists_len(v)
         
     | 
| 
      
 82 
     | 
    
         
            +
                      truncations << PossibleTruncation.new(location, :values_lists, length, false)
         
     | 
| 
       70 
83 
     | 
    
         
             
                    when :ctequery
         
     | 
| 
       71 
84 
     | 
    
         
             
                      next unless node.is_a?(PgQuery::CommonTableExpr)
         
     | 
| 
       72 
85 
     | 
    
         
             
                      length = PgQuery.deparse_stmt(v[v.node.to_s]).size
         
     | 
| 
       73 
86 
     | 
    
         
             
                      truncations << PossibleTruncation.new(location, :ctequery, length, false)
         
     | 
| 
       74 
87 
     | 
    
         
             
                    when :cols
         
     | 
| 
       75 
88 
     | 
    
         
             
                      next unless node.is_a?(PgQuery::InsertStmt)
         
     | 
| 
       76 
     | 
    
         
            -
                      length =  
     | 
| 
       77 
     | 
    
         
            -
                        PgQuery::InsertStmt.new(
         
     | 
| 
       78 
     | 
    
         
            -
                          relation: PgQuery::RangeVar.new(relname: 'x', inh: true),
         
     | 
| 
       79 
     | 
    
         
            -
                          cols: v.to_a
         
     | 
| 
       80 
     | 
    
         
            -
                        )
         
     | 
| 
       81 
     | 
    
         
            -
                      ).size - 31 # "INSERT INTO x () DEFAULT VALUES".size
         
     | 
| 
      
 89 
     | 
    
         
            +
                      length = cols_len(v)
         
     | 
| 
       82 
90 
     | 
    
         
             
                      truncations << PossibleTruncation.new(location, :cols, length, true)
         
     | 
| 
       83 
91 
     | 
    
         
             
                    end
         
     | 
| 
       84 
92 
     | 
    
         
             
                  end
         
     | 
| 
       85 
93 
     | 
    
         | 
| 
       86 
94 
     | 
    
         
             
                  truncations
         
     | 
| 
       87 
95 
     | 
    
         
             
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                def select_target_list_len(target_list)
         
     | 
| 
      
 98 
     | 
    
         
            +
                  deparsed_len = PgQuery.deparse_stmt(
         
     | 
| 
      
 99 
     | 
    
         
            +
                    PgQuery::SelectStmt.new(
         
     | 
| 
      
 100 
     | 
    
         
            +
                      target_list: target_list.to_a, op: :SETOP_NONE
         
     | 
| 
      
 101 
     | 
    
         
            +
                    )
         
     | 
| 
      
 102 
     | 
    
         
            +
                  ).size
         
     | 
| 
      
 103 
     | 
    
         
            +
                  deparsed_len - 7 # 'SELECT '.size
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                def select_values_lists_len(values_lists)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  deparsed_len = PgQuery.deparse_stmt(
         
     | 
| 
      
 108 
     | 
    
         
            +
                    PgQuery::SelectStmt.new(
         
     | 
| 
      
 109 
     | 
    
         
            +
                      values_lists: values_lists.to_a, op: :SETOP_NONE
         
     | 
| 
      
 110 
     | 
    
         
            +
                    )
         
     | 
| 
      
 111 
     | 
    
         
            +
                  ).size
         
     | 
| 
      
 112 
     | 
    
         
            +
                  deparsed_len - 7 # 'SELECT '.size
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                def update_target_list_len(target_list)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  deparsed_len = PgQuery.deparse_stmt(
         
     | 
| 
      
 117 
     | 
    
         
            +
                    PgQuery::UpdateStmt.new(
         
     | 
| 
      
 118 
     | 
    
         
            +
                      target_list: target_list.to_a,
         
     | 
| 
      
 119 
     | 
    
         
            +
                      relation: PgQuery::RangeVar.new(relname: 'x', inh: true)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    )
         
     | 
| 
      
 121 
     | 
    
         
            +
                  ).size
         
     | 
| 
      
 122 
     | 
    
         
            +
                  deparsed_len - 13 # 'UPDATE x SET '.size
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                def cols_len(cols)
         
     | 
| 
      
 126 
     | 
    
         
            +
                  deparsed_len = PgQuery.deparse_stmt(
         
     | 
| 
      
 127 
     | 
    
         
            +
                    PgQuery::InsertStmt.new(
         
     | 
| 
      
 128 
     | 
    
         
            +
                      relation: PgQuery::RangeVar.new(relname: 'x', inh: true),
         
     | 
| 
      
 129 
     | 
    
         
            +
                      cols: cols.to_a
         
     | 
| 
      
 130 
     | 
    
         
            +
                    )
         
     | 
| 
      
 131 
     | 
    
         
            +
                  ).size
         
     | 
| 
      
 132 
     | 
    
         
            +
                  deparsed_len - 31 # "INSERT INTO x () DEFAULT VALUES".size
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
       88 
134 
     | 
    
         
             
              end
         
     | 
| 
       89 
135 
     | 
    
         
             
            end
         
     | 
    
        data/lib/pg_query/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: pg_query
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.1.4
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Lukas Fittl
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2022-09-17 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake-compiler
         
     | 
| 
         @@ -72,14 +72,14 @@ dependencies: 
     | 
|
| 
       72 
72 
     | 
    
         
             
                requirements:
         
     | 
| 
       73 
73 
     | 
    
         
             
                - - ">="
         
     | 
| 
       74 
74 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       75 
     | 
    
         
            -
                    version: 3. 
     | 
| 
      
 75 
     | 
    
         
            +
                    version: 3.19.2
         
     | 
| 
       76 
76 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       77 
77 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       78 
78 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       79 
79 
     | 
    
         
             
                requirements:
         
     | 
| 
       80 
80 
     | 
    
         
             
                - - ">="
         
     | 
| 
       81 
81 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       82 
     | 
    
         
            -
                    version: 3. 
     | 
| 
      
 82 
     | 
    
         
            +
                    version: 3.19.2
         
     | 
| 
       83 
83 
     | 
    
         
             
            description: Parses SQL queries using a copy of the PostgreSQL server query parser
         
     | 
| 
       84 
84 
     | 
    
         
             
            email: lukas@fittl.com
         
     | 
| 
       85 
85 
     | 
    
         
             
            executables: []
         
     | 
| 
         @@ -484,6 +484,7 @@ files: 
     | 
|
| 
       484 
484 
     | 
    
         
             
            - ext/pg_query/pg_query_readfuncs_protobuf.c
         
     | 
| 
       485 
485 
     | 
    
         
             
            - ext/pg_query/pg_query_ruby.c
         
     | 
| 
       486 
486 
     | 
    
         
             
            - ext/pg_query/pg_query_ruby.sym
         
     | 
| 
      
 487 
     | 
    
         
            +
            - ext/pg_query/pg_query_ruby_freebsd.sym
         
     | 
| 
       487 
488 
     | 
    
         
             
            - ext/pg_query/pg_query_scan.c
         
     | 
| 
       488 
489 
     | 
    
         
             
            - ext/pg_query/pg_query_split.c
         
     | 
| 
       489 
490 
     | 
    
         
             
            - ext/pg_query/protobuf-c.c
         
     | 
| 
         @@ -561,7 +562,7 @@ files: 
     | 
|
| 
       561 
562 
     | 
    
         
             
            - lib/pg_query/treewalker.rb
         
     | 
| 
       562 
563 
     | 
    
         
             
            - lib/pg_query/truncate.rb
         
     | 
| 
       563 
564 
     | 
    
         
             
            - lib/pg_query/version.rb
         
     | 
| 
       564 
     | 
    
         
            -
            homepage:  
     | 
| 
      
 565 
     | 
    
         
            +
            homepage: https://github.com/pganalyze/pg_query
         
     | 
| 
       565 
566 
     | 
    
         
             
            licenses:
         
     | 
| 
       566 
567 
     | 
    
         
             
            - BSD-3-Clause
         
     | 
| 
       567 
568 
     | 
    
         
             
            metadata: {}
         
     |