pg_query 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +17 -0
- data/Rakefile +3 -3
- data/ext/pg_query/extconf.rb +2 -2
- data/lib/pg_query/deparse.rb +129 -3
- data/lib/pg_query/node_types.rb +2 -0
- data/lib/pg_query/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0db8e898d08ff3642a800ab296d7ac10dd9556e3c5a626f005bae86d35273372
|
4
|
+
data.tar.gz: a869a1faeb3ae0bed9d5031f2a4d26263843fde368bfeb096c1c9f48ea30c9f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0f51970e5f268d9d9d32d791288db0d7a048c4880f706ff7d483b0efacd1a355600f5b8ca8a0b57b75a05cda8c7b207402bb6680fad0fdaeaf7809fab06c441
|
7
|
+
data.tar.gz: 6281530a32add88cd8a474a8e224e817723e288e850f9d9232aba69208b1178d89b7135d613d15800176bd611b3d6fcd0600fb48c3e8c880f6aa47f5296bae45
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.1.0 2018-10-04
|
4
|
+
|
5
|
+
* Deparsing improvements by [@herwinw](https://github.com/herwinw)
|
6
|
+
* Add NULLS FIRST/LAST to ORDER BY [#95](https://github.com/lfittl/pg_query/pull/95)
|
7
|
+
* VACUUM [#97](https://github.com/lfittl/pg_query/pull/97)
|
8
|
+
* UPDATE with multiple columns [#99](https://github.com/lfittl/pg_query/pull/99)
|
9
|
+
* DISTINCT ON [#101](https://github.com/lfittl/pg_query/pull/101)
|
10
|
+
* CREATE TABLE AS [#102](https://github.com/lfittl/pg_query/pull/102)
|
11
|
+
* SQL value functions [#103](https://github.com/lfittl/pg_query/pull/103)
|
12
|
+
* LOCK [#105](https://github.com/lfittl/pg_query/pull/105)
|
13
|
+
* EXPLAIN [#107](https://github.com/lfittl/pg_query/pull/107)
|
14
|
+
* COPY [#108](https://github.com/lfittl/pg_query/pull/108)
|
15
|
+
* DO [#109](https://github.com/lfittl/pg_query/pull/109)
|
16
|
+
* Ignore pg_query.so in git checkout [#110](https://github.com/lfittl/pg_query/pull/110) [@herwinw](https://github.com/herwinw)
|
17
|
+
* Prefer __dir__ over File.dirname(__FILE__) [#110](https://github.com/lfittl/pg_query/pull/104) [@herwinw](https://github.com/herwinw)
|
18
|
+
|
19
|
+
|
3
20
|
## 1.0.2 2018-04-11
|
4
21
|
|
5
22
|
* Deparsing improvements
|
data/Rakefile
CHANGED
@@ -17,7 +17,7 @@ task test: :spec
|
|
17
17
|
task lint: :rubocop
|
18
18
|
|
19
19
|
task :clean do
|
20
|
-
FileUtils.rm_rf File.join(
|
21
|
-
FileUtils.rm_f Dir.glob(File.join(
|
22
|
-
FileUtils.rm_f File.join(
|
20
|
+
FileUtils.rm_rf File.join(__dir__, 'tmp/')
|
21
|
+
FileUtils.rm_f Dir.glob(File.join(__dir__, 'ext/pg_query/*.o'))
|
22
|
+
FileUtils.rm_f File.join(__dir__, 'lib/pg_query/pg_query.bundle')
|
23
23
|
end
|
data/ext/pg_query/extconf.rb
CHANGED
@@ -7,7 +7,7 @@ LIB_PG_QUERY_TAG = '10-1.0.1'.freeze
|
|
7
7
|
|
8
8
|
workdir = Dir.pwd
|
9
9
|
libdir = File.join(workdir, 'libpg_query-' + LIB_PG_QUERY_TAG)
|
10
|
-
gemdir = File.join(
|
10
|
+
gemdir = File.join(__dir__, '../..')
|
11
11
|
libfile = libdir + '/libpg_query.a'
|
12
12
|
|
13
13
|
unless File.exist?("#{workdir}/libpg_query.tar.gz")
|
@@ -36,7 +36,7 @@ $LOCAL_LIBS << '-lpg_query'
|
|
36
36
|
$LIBPATH << libdir
|
37
37
|
$CFLAGS << " -I #{libdir} -O3 -Wall -fno-strict-aliasing -fwrapv -g"
|
38
38
|
|
39
|
-
SYMFILE = File.join(
|
39
|
+
SYMFILE = File.join(__dir__, 'pg_query_ruby.sym')
|
40
40
|
if RUBY_PLATFORM =~ /darwin/
|
41
41
|
$DLDFLAGS << " -Wl,-exported_symbols_list #{SYMFILE}" unless defined?(::Rubinius)
|
42
42
|
else
|
data/lib/pg_query/deparse.rb
CHANGED
@@ -86,16 +86,24 @@ class PgQuery
|
|
86
86
|
deparse_cte(node)
|
87
87
|
when CONSTRAINT
|
88
88
|
deparse_constraint(node)
|
89
|
+
when COPY_STMT
|
90
|
+
deparse_copy(node)
|
89
91
|
when CREATE_FUNCTION_STMT
|
90
92
|
deparse_create_function(node)
|
91
93
|
when CREATE_STMT
|
92
94
|
deparse_create_table(node)
|
95
|
+
when CREATE_TABLE_AS_STMT
|
96
|
+
deparse_create_table_as(node)
|
97
|
+
when INTO_CLAUSE
|
98
|
+
deparse_into_clause(node)
|
93
99
|
when DEF_ELEM
|
94
100
|
deparse_defelem(node)
|
95
101
|
when DELETE_STMT
|
96
102
|
deparse_delete_from(node)
|
97
103
|
when DROP_STMT
|
98
104
|
deparse_drop(node)
|
105
|
+
when EXPLAIN_STMT
|
106
|
+
deparse_explain(node)
|
99
107
|
when FUNC_CALL
|
100
108
|
deparse_funccall(node)
|
101
109
|
when FUNCTION_PARAMETER
|
@@ -104,6 +112,8 @@ class PgQuery
|
|
104
112
|
deparse_insert_into(node)
|
105
113
|
when JOIN_EXPR
|
106
114
|
deparse_joinexpr(node)
|
115
|
+
when LOCK_STMT
|
116
|
+
deparse_lock(node)
|
107
117
|
when LOCKING_CLAUSE
|
108
118
|
deparse_lockingclause(node)
|
109
119
|
when NULL_TEST
|
@@ -126,6 +136,8 @@ class PgQuery
|
|
126
136
|
deparse_row(node)
|
127
137
|
when SELECT_STMT
|
128
138
|
deparse_select(node)
|
139
|
+
when SQL_VALUE_FUNCTION
|
140
|
+
deparse_sql_value_function(node)
|
129
141
|
when SORT_BY
|
130
142
|
deparse_sortby(node)
|
131
143
|
when SUB_LINK
|
@@ -148,6 +160,10 @@ class PgQuery
|
|
148
160
|
deparse_viewstmt(node)
|
149
161
|
when VARIABLE_SET_STMT
|
150
162
|
deparse_variable_set_stmt(node)
|
163
|
+
when VACUUM_STMT
|
164
|
+
deparse_vacuum_stmt(node)
|
165
|
+
when DO_STMT
|
166
|
+
deparse_do_stmt(node)
|
151
167
|
when STRING
|
152
168
|
if context == A_CONST
|
153
169
|
format("'%s'", node['str'].gsub("'", "''"))
|
@@ -458,6 +474,14 @@ class PgQuery
|
|
458
474
|
output.join(' ')
|
459
475
|
end
|
460
476
|
|
477
|
+
def deparse_lock(node)
|
478
|
+
output = []
|
479
|
+
output << 'LOCK TABLE'
|
480
|
+
tables = node['relations'].map { |table| deparse_item(table) }
|
481
|
+
output << tables.join(', ')
|
482
|
+
output.join(' ')
|
483
|
+
end
|
484
|
+
|
461
485
|
LOCK_CLAUSE_STRENGTH = {
|
462
486
|
LCS_FORKEYSHARE => 'FOR KEY SHARE',
|
463
487
|
LCS_FORSHARE => 'FOR SHARE',
|
@@ -481,6 +505,8 @@ class PgQuery
|
|
481
505
|
output << deparse_item(node['node'])
|
482
506
|
output << 'ASC' if node['sortby_dir'] == 1
|
483
507
|
output << 'DESC' if node['sortby_dir'] == 2
|
508
|
+
output << 'NULLS FIRST' if node['sortby_nulls'] == 1
|
509
|
+
output << 'NULLS LAST' if node['sortby_nulls'] == 2
|
484
510
|
output.join(' ')
|
485
511
|
end
|
486
512
|
|
@@ -527,6 +553,35 @@ class PgQuery
|
|
527
553
|
output.join(' ')
|
528
554
|
end
|
529
555
|
|
556
|
+
def deparse_vacuum_stmt(node)
|
557
|
+
output = []
|
558
|
+
output << 'VACUUM'
|
559
|
+
output.concat(deparse_vacuum_options(node))
|
560
|
+
output << deparse_item(node['relation']) if node.key?('relation')
|
561
|
+
if node.key?('va_cols')
|
562
|
+
output << "(#{node['va_cols'].map(&method(:deparse_item)).join(', ')})"
|
563
|
+
end
|
564
|
+
output.join(' ')
|
565
|
+
end
|
566
|
+
|
567
|
+
def deparse_vacuum_options(node)
|
568
|
+
output = []
|
569
|
+
output << 'FULL' if node['options'][4] == 1
|
570
|
+
output << 'FREEZE' if node['options'][3] == 1
|
571
|
+
output << 'VERBOSE' if node['options'][2] == 1
|
572
|
+
output << 'ANALYZE' if node['options'][1] == 1
|
573
|
+
output
|
574
|
+
end
|
575
|
+
|
576
|
+
def deparse_do_stmt(node)
|
577
|
+
output = []
|
578
|
+
output << 'DO'
|
579
|
+
statement, *rest = node['args']
|
580
|
+
output << "$$#{statement['DefElem']['arg']['String']['str']}$$"
|
581
|
+
output += rest.map { |item| deparse_item(item) }
|
582
|
+
output.join(' ')
|
583
|
+
end
|
584
|
+
|
530
585
|
def deparse_cte(node)
|
531
586
|
output = []
|
532
587
|
output << node['ctename']
|
@@ -601,6 +656,21 @@ class PgQuery
|
|
601
656
|
output.join(' ')
|
602
657
|
end
|
603
658
|
|
659
|
+
def deparse_copy(node)
|
660
|
+
output = ['COPY']
|
661
|
+
output << deparse_item(node['relation'])
|
662
|
+
columns = node.fetch('attlist', []).map { |column| deparse_item(column) }
|
663
|
+
output << "(#{columns.join(', ')})" unless columns.empty?
|
664
|
+
output << (node['is_from'] ? 'FROM' : 'TO')
|
665
|
+
output << 'PROGRAM' if node['is_program']
|
666
|
+
output << if node.key?('filename')
|
667
|
+
"'#{node['filename']}'"
|
668
|
+
else
|
669
|
+
node['is_from'] ? 'STDIN' : 'STDOUT'
|
670
|
+
end
|
671
|
+
output.join(' ')
|
672
|
+
end
|
673
|
+
|
604
674
|
def deparse_create_function(node)
|
605
675
|
output = []
|
606
676
|
output << 'CREATE'
|
@@ -645,6 +715,19 @@ class PgQuery
|
|
645
715
|
output.join(' ')
|
646
716
|
end
|
647
717
|
|
718
|
+
def deparse_create_table_as(node)
|
719
|
+
output = []
|
720
|
+
output << 'CREATE TEMPORARY TABLE'
|
721
|
+
output << deparse_item(node['into'])
|
722
|
+
output << 'AS'
|
723
|
+
output << deparse_item(node['query'])
|
724
|
+
output.join(' ')
|
725
|
+
end
|
726
|
+
|
727
|
+
def deparse_into_clause(node)
|
728
|
+
deparse_item(node['rel'])
|
729
|
+
end
|
730
|
+
|
648
731
|
def deparse_when(node)
|
649
732
|
output = ['WHEN']
|
650
733
|
output << deparse_item(node['expr'])
|
@@ -691,7 +774,13 @@ class PgQuery
|
|
691
774
|
|
692
775
|
if node[TARGET_LIST_FIELD]
|
693
776
|
output << 'SELECT'
|
694
|
-
|
777
|
+
if node['distinctClause']
|
778
|
+
output << 'DISTINCT'
|
779
|
+
unless node['distinctClause'].compact.empty?
|
780
|
+
columns = node['distinctClause'].map { |item| deparse_item(item, :select) }
|
781
|
+
output << "ON (#{columns.join(', ')})"
|
782
|
+
end
|
783
|
+
end
|
695
784
|
output << node[TARGET_LIST_FIELD].map do |item|
|
696
785
|
deparse_item(item, :select)
|
697
786
|
end.join(', ')
|
@@ -754,6 +843,30 @@ class PgQuery
|
|
754
843
|
output.join(' ')
|
755
844
|
end
|
756
845
|
|
846
|
+
def deparse_sql_value_function(node)
|
847
|
+
output = []
|
848
|
+
lookup = [
|
849
|
+
'current_date',
|
850
|
+
'current_time',
|
851
|
+
'current_time', # with precision
|
852
|
+
'current_timestamp',
|
853
|
+
'current_timestamp', # with precision
|
854
|
+
'localtime',
|
855
|
+
'localtime', # with precision
|
856
|
+
'localtimestamp',
|
857
|
+
'localtimestamp', # with precision
|
858
|
+
'current_role',
|
859
|
+
'current_user',
|
860
|
+
'session_user',
|
861
|
+
'user',
|
862
|
+
'current_catalog',
|
863
|
+
'current_schema'
|
864
|
+
]
|
865
|
+
output << lookup[node['op']]
|
866
|
+
output << "(#{node['typmod']})" unless node.fetch('typmod', -1) == -1
|
867
|
+
output.join('')
|
868
|
+
end
|
869
|
+
|
757
870
|
def deparse_insert_into(node)
|
758
871
|
output = []
|
759
872
|
output << deparse_item(node['withClause']) if node['withClause']
|
@@ -781,9 +894,10 @@ class PgQuery
|
|
781
894
|
|
782
895
|
if node[TARGET_LIST_FIELD]
|
783
896
|
output << 'SET'
|
784
|
-
node[TARGET_LIST_FIELD].
|
785
|
-
|
897
|
+
columns = node[TARGET_LIST_FIELD].map do |item|
|
898
|
+
deparse_item(item, :update)
|
786
899
|
end
|
900
|
+
output << columns.join(', ')
|
787
901
|
end
|
788
902
|
|
789
903
|
if node['whereClause']
|
@@ -984,6 +1098,18 @@ class PgQuery
|
|
984
1098
|
output.join(' ')
|
985
1099
|
end
|
986
1100
|
|
1101
|
+
def deparse_explain(node)
|
1102
|
+
output = ['EXPLAIN']
|
1103
|
+
options = node.fetch('options', []).map { |option| option['DefElem']['defname'].upcase }
|
1104
|
+
if options.size == 1
|
1105
|
+
output.concat(options)
|
1106
|
+
elsif options.size > 1
|
1107
|
+
output << "(#{options.join(', ')})"
|
1108
|
+
end
|
1109
|
+
output << deparse_item(node['query'])
|
1110
|
+
output.join(' ')
|
1111
|
+
end
|
1112
|
+
|
987
1113
|
# The PG parser adds several pieces of view data onto the RANGEVAR
|
988
1114
|
# that need to be printed before deparse_rangevar is called.
|
989
1115
|
def relpersistence(rangevar)
|
data/lib/pg_query/node_types.rb
CHANGED
@@ -34,6 +34,7 @@ class PgQuery
|
|
34
34
|
DECLARE_CURSOR_STMT = 'DeclareCursorStmt'.freeze
|
35
35
|
DEF_ELEM = 'DefElem'.freeze
|
36
36
|
DELETE_STMT = 'DeleteStmt'.freeze
|
37
|
+
DO_STMT = 'DoStmt'.freeze
|
37
38
|
DROP_STMT = 'DropStmt'.freeze
|
38
39
|
EXECUTE_STMT = 'ExecuteStmt'.freeze
|
39
40
|
EXPLAIN_STMT = 'ExplainStmt'.freeze
|
@@ -70,6 +71,7 @@ class PgQuery
|
|
70
71
|
SELECT_STMT = 'SelectStmt'.freeze
|
71
72
|
SET_TO_DEFAULT = 'SetToDefault'.freeze
|
72
73
|
SORT_BY = 'SortBy'.freeze
|
74
|
+
SQL_VALUE_FUNCTION = 'SQLValueFunction'.freeze
|
73
75
|
STRING = 'String'.freeze
|
74
76
|
SUB_LINK = 'SubLink'.freeze
|
75
77
|
TRANSACTION_STMT = 'TransactionStmt'.freeze
|
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: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lukas Fittl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04
|
11
|
+
date: 2018-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
version: '0'
|
123
123
|
requirements: []
|
124
124
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.6
|
125
|
+
rubygems_version: 2.7.6
|
126
126
|
signing_key:
|
127
127
|
specification_version: 4
|
128
128
|
summary: PostgreSQL query parsing and normalization library
|