pg_query 1.0.2 → 1.1.0
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 +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
|