pg_query 0.11.5 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Rakefile +1 -1
- data/ext/pg_query/extconf.rb +2 -2
- data/lib/pg_query/deparse.rb +27 -18
- data/lib/pg_query/deparse/alter_table.rb +1 -1
- data/lib/pg_query/deparse/interval.rb +15 -15
- data/lib/pg_query/filter_columns.rb +5 -4
- data/lib/pg_query/param_refs.rb +1 -1
- data/lib/pg_query/parse.rb +7 -6
- data/lib/pg_query/treewalker.rb +6 -6
- data/lib/pg_query/truncate.rb +1 -1
- data/lib/pg_query/version.rb +1 -1
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61359adbe400bc68cb1dc1d922483daf361eb143
|
4
|
+
data.tar.gz: b9af1134fffbcb19935c16ee0ce9c3571a27d6ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe42b2f8e3ccf33bbebca91340f9f1cc22439064a7ada8b8d3fac2ad8ea7e22f3d4ced2afd27c35b730a835b2b18b798c0e12e66a0a246edcd4fe04e661690cf
|
7
|
+
data.tar.gz: 12b4a53a3496c59ff0f275fc6a6e6829035593d360f098ecebf5d276aeb9324360d0f11dd3a836fa80eaa38b8822fa37ea54462b1df54d48204481305dea0b22
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.12.0 2017-07-29
|
4
|
+
|
5
|
+
* Update libpg_query to 9.5-1.6.0
|
6
|
+
* BREAKING CHANGE in PgQuery.normalize(..) output
|
7
|
+
* This matches the change in the upcoming Postgres 10, and makes it easier to
|
8
|
+
migrate applications to the new normalization format using $1..$N instead of ?
|
9
|
+
|
10
|
+
|
3
11
|
## 0.11.5 2017-07-09
|
4
12
|
|
5
13
|
* Deparse coldeflist [#64](https://github.com/lfittl/pg_query/pull/64) [@jcsjcs](https://github.com/jcsjcs)
|
data/Rakefile
CHANGED
data/ext/pg_query/extconf.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'mkmf'
|
4
4
|
require 'open-uri'
|
5
5
|
|
6
|
-
LIB_PG_QUERY_TAG = '9.5-1.
|
6
|
+
LIB_PG_QUERY_TAG = '9.5-1.6.0'.freeze
|
7
7
|
|
8
8
|
workdir = Dir.pwd
|
9
9
|
libdir = File.join(workdir, 'libpg_query-' + LIB_PG_QUERY_TAG)
|
@@ -19,7 +19,7 @@ unless File.exist?("#{workdir}/libpg_query.tar.gz")
|
|
19
19
|
end
|
20
20
|
|
21
21
|
unless Dir.exist?(libdir)
|
22
|
-
system("tar -xf #{workdir}/libpg_query.tar.gz") ||
|
22
|
+
system("tar -xf #{workdir}/libpg_query.tar.gz") || raise('ERROR')
|
23
23
|
end
|
24
24
|
|
25
25
|
unless Dir.exist?(libfile)
|
data/lib/pg_query/deparse.rb
CHANGED
@@ -43,7 +43,7 @@ class PgQuery
|
|
43
43
|
when AEXPR_NULLIF
|
44
44
|
deparse_aexpr_nullif(node)
|
45
45
|
else
|
46
|
-
|
46
|
+
raise format("Can't deparse: %s: %s", type, node.inspect)
|
47
47
|
end
|
48
48
|
when ALIAS
|
49
49
|
deparse_alias(node)
|
@@ -161,7 +161,7 @@ class PgQuery
|
|
161
161
|
when NULL
|
162
162
|
'NULL'
|
163
163
|
else
|
164
|
-
|
164
|
+
raise format("Can't deparse: %s: %s", type, node.inspect)
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
@@ -171,7 +171,10 @@ class PgQuery
|
|
171
171
|
|
172
172
|
def deparse_rangevar(node)
|
173
173
|
output = []
|
174
|
-
|
174
|
+
case node['inhOpt']
|
175
|
+
when 0
|
176
|
+
output << 'ONLY'
|
177
|
+
end
|
175
178
|
output << '"' + node['relname'] + '"'
|
176
179
|
output << deparse_item(node['alias']) if node['alias']
|
177
180
|
output.join(' ')
|
@@ -180,13 +183,14 @@ class PgQuery
|
|
180
183
|
def deparse_renamestmt(node)
|
181
184
|
output = []
|
182
185
|
|
183
|
-
|
186
|
+
case node['renameType']
|
187
|
+
when OBJECT_TYPE_TABLE
|
184
188
|
output << 'ALTER TABLE'
|
185
189
|
output << deparse_item(node['relation'])
|
186
190
|
output << 'RENAME TO'
|
187
191
|
output << node['newname']
|
188
192
|
else
|
189
|
-
|
193
|
+
raise format("Can't deparse: %s", node.inspect)
|
190
194
|
end
|
191
195
|
|
192
196
|
output.join(' ')
|
@@ -276,7 +280,7 @@ class PgQuery
|
|
276
280
|
elsif node['val'].nil?
|
277
281
|
node['name']
|
278
282
|
else
|
279
|
-
|
283
|
+
raise format("Can't deparse %s in context %s", node.inspect, context)
|
280
284
|
end
|
281
285
|
end
|
282
286
|
|
@@ -423,8 +427,12 @@ class PgQuery
|
|
423
427
|
def deparse_joinexpr(node)
|
424
428
|
output = []
|
425
429
|
output << deparse_item(node['larg'])
|
426
|
-
|
427
|
-
|
430
|
+
case node['jointype']
|
431
|
+
when 0
|
432
|
+
output << 'CROSS' if node['quals'].nil?
|
433
|
+
when 1
|
434
|
+
output << 'LEFT'
|
435
|
+
end
|
428
436
|
output << 'JOIN'
|
429
437
|
output << deparse_item(node['rarg'])
|
430
438
|
|
@@ -441,7 +449,7 @@ class PgQuery
|
|
441
449
|
LCS_FORSHARE => 'FOR SHARE',
|
442
450
|
LCS_FORNOKEYUPDATE => 'FOR NO KEY UPDATE',
|
443
451
|
LCS_FORUPDATE => 'FOR UPDATE'
|
444
|
-
}
|
452
|
+
}.freeze
|
445
453
|
def deparse_lockingclause(node)
|
446
454
|
output = []
|
447
455
|
output << LOCK_CLAUSE_STRENGTH[node['strength']]
|
@@ -632,11 +640,11 @@ class PgQuery
|
|
632
640
|
|
633
641
|
def deparse_sublink(node)
|
634
642
|
if node['subLinkType'] == SUBLINK_TYPE_ANY
|
635
|
-
|
643
|
+
format('%s IN (%s)', deparse_item(node['testexpr']), deparse_item(node['subselect']))
|
636
644
|
elsif node['subLinkType'] == SUBLINK_TYPE_EXISTS
|
637
|
-
|
645
|
+
format('EXISTS(%s)', deparse_item(node['subselect']))
|
638
646
|
else
|
639
|
-
|
647
|
+
format('(%s)', deparse_item(node['subselect']))
|
640
648
|
end
|
641
649
|
end
|
642
650
|
|
@@ -791,7 +799,7 @@ class PgQuery
|
|
791
799
|
|
792
800
|
# Intervals are tricky and should be handled in a separate method because
|
793
801
|
# they require performing some bitmask operations.
|
794
|
-
return deparse_interval_type(node) if names == %w
|
802
|
+
return deparse_interval_type(node) if names == %w[pg_catalog interval]
|
795
803
|
|
796
804
|
output = []
|
797
805
|
output << 'SETOF' if node['setof']
|
@@ -844,7 +852,7 @@ class PgQuery
|
|
844
852
|
when 'timestamptz'
|
845
853
|
'timestamp with time zone'
|
846
854
|
else
|
847
|
-
|
855
|
+
raise format("Can't deparse type: %s", type)
|
848
856
|
end
|
849
857
|
end
|
850
858
|
|
@@ -870,9 +878,10 @@ class PgQuery
|
|
870
878
|
|
871
879
|
def deparse_nulltest(node)
|
872
880
|
output = [deparse_item(node['arg'])]
|
873
|
-
|
881
|
+
case node['nulltesttype']
|
882
|
+
when 0
|
874
883
|
output << 'IS NULL'
|
875
|
-
|
884
|
+
when 1
|
876
885
|
output << 'IS NOT NULL'
|
877
886
|
end
|
878
887
|
output.join(' ')
|
@@ -885,10 +894,10 @@ class PgQuery
|
|
885
894
|
TRANS_STMT_SAVEPOINT => 'SAVEPOINT',
|
886
895
|
TRANS_STMT_RELEASE => 'RELEASE',
|
887
896
|
TRANS_STMT_ROLLBACK_TO => 'ROLLBACK TO SAVEPOINT'
|
888
|
-
}
|
897
|
+
}.freeze
|
889
898
|
def deparse_transaction(node)
|
890
899
|
output = []
|
891
|
-
output << TRANSACTION_CMDS[node['kind']] ||
|
900
|
+
output << TRANSACTION_CMDS[node['kind']] || raise(format("Can't deparse TRANSACTION %s", node.inspect))
|
892
901
|
|
893
902
|
if node['options']
|
894
903
|
output += node['options'].map { |item| deparse_item(item) }
|
@@ -15,7 +15,7 @@ class PgQuery
|
|
15
15
|
# ALTER COLUMN {column_name} DROP NOT NULL
|
16
16
|
#
|
17
17
|
def self.commands(node)
|
18
|
-
action = ALTER_TABLE_TYPES_MAPPING[node['subtype']] ||
|
18
|
+
action = ALTER_TABLE_TYPES_MAPPING[node['subtype']] || raise(format("Can't deparse: %s", node.inspect))
|
19
19
|
PgQuery::Deparse.instance_exec(node, &action)
|
20
20
|
end
|
21
21
|
|
@@ -57,7 +57,7 @@ class PgQuery
|
|
57
57
|
26 => 'CENTURY',
|
58
58
|
27 => 'MILLENNIUM',
|
59
59
|
28 => 'DTZMOD'
|
60
|
-
}
|
60
|
+
}.freeze
|
61
61
|
KEYS = MASKS.invert
|
62
62
|
|
63
63
|
# Postgres stores the interval 'day second' as 'day hour minute second' so
|
@@ -75,31 +75,31 @@ class PgQuery
|
|
75
75
|
# { 6 => 'year to month' }
|
76
76
|
#
|
77
77
|
SQL_BY_MASK = {
|
78
|
-
(1 << KEYS['YEAR']) => %w
|
79
|
-
(1 << KEYS['MONTH']) => %w
|
80
|
-
(1 << KEYS['DAY']) => %w
|
81
|
-
(1 << KEYS['HOUR']) => %w
|
82
|
-
(1 << KEYS['MINUTE']) => %w
|
83
|
-
(1 << KEYS['SECOND']) => %w
|
78
|
+
(1 << KEYS['YEAR']) => %w[year],
|
79
|
+
(1 << KEYS['MONTH']) => %w[month],
|
80
|
+
(1 << KEYS['DAY']) => %w[day],
|
81
|
+
(1 << KEYS['HOUR']) => %w[hour],
|
82
|
+
(1 << KEYS['MINUTE']) => %w[minute],
|
83
|
+
(1 << KEYS['SECOND']) => %w[second],
|
84
84
|
(1 << KEYS['YEAR'] |
|
85
|
-
1 << KEYS['MONTH']) => %w
|
85
|
+
1 << KEYS['MONTH']) => %w[year month],
|
86
86
|
(1 << KEYS['DAY'] |
|
87
|
-
1 << KEYS['HOUR']) => %w
|
87
|
+
1 << KEYS['HOUR']) => %w[day hour],
|
88
88
|
(1 << KEYS['DAY'] |
|
89
89
|
1 << KEYS['HOUR'] |
|
90
|
-
1 << KEYS['MINUTE']) => %w
|
90
|
+
1 << KEYS['MINUTE']) => %w[day minute],
|
91
91
|
(1 << KEYS['DAY'] |
|
92
92
|
1 << KEYS['HOUR'] |
|
93
93
|
1 << KEYS['MINUTE'] |
|
94
|
-
1 << KEYS['SECOND']) => %w
|
94
|
+
1 << KEYS['SECOND']) => %w[day second],
|
95
95
|
(1 << KEYS['HOUR'] |
|
96
|
-
1 << KEYS['MINUTE']) => %w
|
96
|
+
1 << KEYS['MINUTE']) => %w[hour minute],
|
97
97
|
(1 << KEYS['HOUR'] |
|
98
98
|
1 << KEYS['MINUTE'] |
|
99
|
-
1 << KEYS['SECOND']) => %w
|
99
|
+
1 << KEYS['SECOND']) => %w[hour second],
|
100
100
|
(1 << KEYS['MINUTE'] |
|
101
|
-
1 << KEYS['SECOND']) => %w
|
102
|
-
}
|
101
|
+
1 << KEYS['SECOND']) => %w[minute second]
|
102
|
+
}.freeze
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -14,7 +14,8 @@ class PgQuery
|
|
14
14
|
statement = statements.shift
|
15
15
|
if statement
|
16
16
|
if statement[SELECT_STMT]
|
17
|
-
|
17
|
+
case statement[SELECT_STMT]['op']
|
18
|
+
when 0
|
18
19
|
if statement[SELECT_STMT][FROM_CLAUSE_FIELD]
|
19
20
|
# FROM subselects
|
20
21
|
statement[SELECT_STMT][FROM_CLAUSE_FIELD].each do |item|
|
@@ -35,7 +36,7 @@ class PgQuery
|
|
35
36
|
statements << item['CommonTableExpr']['ctequery'] if item['CommonTableExpr']
|
36
37
|
end
|
37
38
|
end
|
38
|
-
|
39
|
+
when 1
|
39
40
|
statements << statement[SELECT_STMT]['larg'] if statement[SELECT_STMT]['larg']
|
40
41
|
statements << statement[SELECT_STMT]['rarg'] if statement[SELECT_STMT]['rarg']
|
41
42
|
end
|
@@ -50,7 +51,7 @@ class PgQuery
|
|
50
51
|
next_item = condition_items.shift
|
51
52
|
if next_item
|
52
53
|
if next_item[A_EXPR]
|
53
|
-
%w
|
54
|
+
%w[lexpr rexpr].each do |side|
|
54
55
|
expr = next_item.values[0][side]
|
55
56
|
next unless expr && expr.is_a?(Hash)
|
56
57
|
condition_items << expr
|
@@ -93,7 +94,7 @@ class PgQuery
|
|
93
94
|
next_item = joinexpr_items.shift
|
94
95
|
break unless next_item
|
95
96
|
condition_items << next_item['quals'] if next_item['quals']
|
96
|
-
%w
|
97
|
+
%w[larg rarg].each do |side|
|
97
98
|
next unless next_item[side][JOIN_EXPR]
|
98
99
|
joinexpr_items << next_item[side][JOIN_EXPR]
|
99
100
|
end
|
data/lib/pg_query/param_refs.rb
CHANGED
@@ -36,7 +36,7 @@ class PgQuery
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def param_ref_length(paramref_node)
|
39
|
-
if paramref_node['number'] == 0
|
39
|
+
if paramref_node['number'] == 0 # rubocop:disable Style/NumericPredicate
|
40
40
|
1 # Actually a ? replacement character
|
41
41
|
else
|
42
42
|
('$' + paramref_node['number'].to_s).size
|
data/lib/pg_query/parse.rb
CHANGED
@@ -60,7 +60,8 @@ class PgQuery
|
|
60
60
|
if statement
|
61
61
|
case statement.keys[0]
|
62
62
|
when SELECT_STMT
|
63
|
-
|
63
|
+
case statement[SELECT_STMT]['op']
|
64
|
+
when 0
|
64
65
|
(statement[SELECT_STMT][FROM_CLAUSE_FIELD] || []).each do |item|
|
65
66
|
if item[RANGE_SUBSELECT]
|
66
67
|
statements << item[RANGE_SUBSELECT]['subquery']
|
@@ -78,7 +79,7 @@ class PgQuery
|
|
78
79
|
statements << item[COMMON_TABLE_EXPR]['ctequery']
|
79
80
|
end
|
80
81
|
end
|
81
|
-
|
82
|
+
when 1
|
82
83
|
statements << statement[SELECT_STMT]['larg'] if statement[SELECT_STMT]['larg']
|
83
84
|
statements << statement[SELECT_STMT]['rarg'] if statement[SELECT_STMT]['rarg']
|
84
85
|
end
|
@@ -100,11 +101,11 @@ class PgQuery
|
|
100
101
|
when GRANT_STMT
|
101
102
|
objects = statement[GRANT_STMT]['objects']
|
102
103
|
case statement[GRANT_STMT]['objtype']
|
103
|
-
when 0 # Column
|
104
|
+
when 0 # Column # rubocop:disable Lint/EmptyWhen
|
104
105
|
# FIXME
|
105
106
|
when 1 # Table
|
106
107
|
from_clause_items += objects
|
107
|
-
when 2 # Sequence
|
108
|
+
when 2 # Sequence # rubocop:disable Lint/EmptyWhen
|
108
109
|
# FIXME
|
109
110
|
end
|
110
111
|
when DROP_STMT
|
@@ -131,7 +132,7 @@ class PgQuery
|
|
131
132
|
if next_item
|
132
133
|
case next_item.keys[0]
|
133
134
|
when A_EXPR
|
134
|
-
%w
|
135
|
+
%w[lexpr rexpr].each do |side|
|
135
136
|
elem = next_item.values[0][side]
|
136
137
|
next unless elem
|
137
138
|
if elem.is_a?(Array)
|
@@ -158,7 +159,7 @@ class PgQuery
|
|
158
159
|
|
159
160
|
case next_item.keys[0]
|
160
161
|
when JOIN_EXPR
|
161
|
-
%w
|
162
|
+
%w[larg rarg].each do |side|
|
162
163
|
from_clause_items << next_item[JOIN_EXPR][side]
|
163
164
|
end
|
164
165
|
when ROW_EXPR
|
data/lib/pg_query/treewalker.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class PgQuery
|
2
2
|
private
|
3
3
|
|
4
|
-
def treewalker!(normalized_parsetree
|
4
|
+
def treewalker!(normalized_parsetree)
|
5
5
|
exprs = normalized_parsetree.dup.map { |e| [e, []] }
|
6
6
|
|
7
7
|
loop do
|
@@ -11,7 +11,7 @@ class PgQuery
|
|
11
11
|
expr.each do |k, v|
|
12
12
|
location = parent_location + [k]
|
13
13
|
|
14
|
-
|
14
|
+
yield(expr, k, v, location)
|
15
15
|
|
16
16
|
exprs << [v, location] unless v.nil?
|
17
17
|
end
|
@@ -23,14 +23,14 @@ class PgQuery
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def find_tree_location(normalized_parsetree, searched_location
|
26
|
+
def find_tree_location(normalized_parsetree, searched_location)
|
27
27
|
treewalker! normalized_parsetree do |expr, k, v, location|
|
28
28
|
next unless location == searched_location
|
29
|
-
|
29
|
+
yield(expr, k, v)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def transform_nodes!(parsetree
|
33
|
+
def transform_nodes!(parsetree)
|
34
34
|
result = deep_dup(parsetree)
|
35
35
|
exprs = result.dup
|
36
36
|
|
@@ -38,7 +38,7 @@ class PgQuery
|
|
38
38
|
expr = exprs.shift
|
39
39
|
|
40
40
|
if expr.is_a?(Hash)
|
41
|
-
|
41
|
+
yield(expr) if expr.size == 1 && expr.keys[0][/^[A-Z]+/]
|
42
42
|
|
43
43
|
exprs += expr.values.compact
|
44
44
|
elsif expr.is_a?(Array)
|
data/lib/pg_query/truncate.rb
CHANGED
@@ -41,7 +41,7 @@ class PgQuery
|
|
41
41
|
treewalker! @tree do |_expr, k, v, location|
|
42
42
|
case k
|
43
43
|
when TARGET_LIST_FIELD
|
44
|
-
length = deparse([{ SELECT_STMT => { k => v } }]).size - 'SELECT '.size
|
44
|
+
length = deparse([{ SELECT_STMT => { k => v } }]).size - 7 # 'SELECT '.size
|
45
45
|
|
46
46
|
truncations << PossibleTruncation.new(location, TARGET_LIST_FIELD, length, true)
|
47
47
|
when 'whereClause'
|
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: 0.
|
4
|
+
version: 0.12.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: 2017-07-
|
11
|
+
date: 2017-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -42,30 +42,30 @@ dependencies:
|
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.49.1
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.49.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rubocop-rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.15.1
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 1.15.1
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: json
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
142
|
version: '0'
|
143
143
|
requirements: []
|
144
144
|
rubyforge_project:
|
145
|
-
rubygems_version: 2.
|
145
|
+
rubygems_version: 2.6.11
|
146
146
|
signing_key:
|
147
147
|
specification_version: 4
|
148
148
|
summary: PostgreSQL query parsing and normalization library
|