pg_query_pg_ddm 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -4
- data/ext/pg_query/extconf.rb +15 -5
- data/lib/pg_query/deparse.rb +31 -9
- data/lib/pg_query/node_types.rb +1 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b5b6ecf3017b7a20ab2e560e092ac24860d3be847df753556c784fdb63106a4
|
4
|
+
data.tar.gz: 488e1d7c21031689b9db0b266ba24395d91fbddb0c65783728243d0231bbd82b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 900b3da4a2ce5066f4f851c7e6f0bb4f317f7d90ae44aeb2d4a16440c6afd5741c5e1e98ecaf6e6d389088533ccdb0be09045299905a4e3ee1d2bbc894c6b09a
|
7
|
+
data.tar.gz: 951806619168d1f76b3b3d8d0dc65e4c90a4e86f2f979b4a9657de185ea351abe8b81c3bf1eb7f7eab31744f8843a536589ab2076eae331961503449c68a58a5
|
data/README.md
CHANGED
@@ -151,11 +151,15 @@ to support parsing normalized queries containing `?` replacement characters.
|
|
151
151
|
|
152
152
|
Currently tested and officially supported Ruby versions:
|
153
153
|
|
154
|
-
*
|
155
|
-
*
|
156
|
-
*
|
157
|
-
*
|
154
|
+
* CRuby 2.5
|
155
|
+
* CRuby 2.6
|
156
|
+
* CRuby 2.7
|
157
|
+
* CRuby 3.0
|
158
158
|
|
159
|
+
Not supported:
|
160
|
+
|
161
|
+
* JRuby: `pg_query` relies on a C extension, which is discouraged / not properly supported for JRuby
|
162
|
+
* TruffleRuby: GraalVM [does not support sigjmp](https://www.graalvm.org/reference-manual/llvm/NativeExecution/), which is used by the Postgres error handling code (`pg_query` uses a copy of the Postgres parser & error handling code)
|
159
163
|
|
160
164
|
## Resources
|
161
165
|
|
data/ext/pg_query/extconf.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# rubocop:disable Style/GlobalVars
|
2
2
|
|
3
|
+
require 'digest'
|
3
4
|
require 'mkmf'
|
4
5
|
require 'open-uri'
|
5
6
|
|
@@ -10,21 +11,30 @@ libdir = File.join(workdir, 'libpg_query-' + LIB_PG_QUERY_TAG)
|
|
10
11
|
gemdir = File.join(__dir__, '../..')
|
11
12
|
libfile = libdir + '/libpg_query.a'
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
expected_sha256 = '1332761f31c198cb9825e6ccccda0b6a0e57daeb824870e8524df77f1592d149'
|
15
|
+
filename = "#{workdir}/libpg_query.tar.gz"
|
16
|
+
|
17
|
+
unless File.exist?(filename)
|
18
|
+
File.open(filename, 'wb') do |target_file|
|
19
|
+
URI.open('https://codeload.github.com/lfittl/libpg_query/tar.gz/' + LIB_PG_QUERY_TAG, 'rb') do |read_file|
|
16
20
|
target_file.write(read_file.read)
|
17
21
|
end
|
18
22
|
end
|
23
|
+
|
24
|
+
checksum = Digest::SHA256.hexdigest(File.read(filename))
|
25
|
+
|
26
|
+
if checksum != expected_sha256
|
27
|
+
raise "SHA256 of #{filename} does not match: got #{checksum}, expected #{expected_sha256}"
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
31
|
unless Dir.exist?(libdir)
|
22
|
-
system("tar -xzf #{
|
32
|
+
system("tar -xzf #{filename}") || raise('ERROR')
|
23
33
|
end
|
24
34
|
|
25
35
|
unless Dir.exist?(libfile)
|
26
36
|
# Build libpg_query (and parts of PostgreSQL)
|
27
|
-
system("cd
|
37
|
+
system(format("cd %s; %s build", libdir, ENV['MAKE'] || (RUBY_PLATFORM =~ /bsd/ ? 'gmake' : 'make')))
|
28
38
|
end
|
29
39
|
|
30
40
|
# Copy test files (this intentionally overwrites existing files!)
|
data/lib/pg_query/deparse.rb
CHANGED
@@ -314,7 +314,7 @@ class PgQuery
|
|
314
314
|
if node['indirection']
|
315
315
|
array_indirection = node['indirection'].select { |a| a.key?(A_INDICES) }
|
316
316
|
end
|
317
|
-
output << if node['arg'].key?(FUNC_CALL) || node['arg'].key?(A_EXPR) || (node['arg'].key?(SUB_LINK) && array_indirection.count.zero?)
|
317
|
+
output << if node['arg'].key?(FUNC_CALL) || node['arg'].key?(COLUMN_REF) || node['arg'].key?(A_EXPR) || (node['arg'].key?(SUB_LINK) && array_indirection.count.zero?)
|
318
318
|
"(#{arg})."
|
319
319
|
else
|
320
320
|
arg
|
@@ -417,9 +417,11 @@ class PgQuery
|
|
417
417
|
# COUNT(*)
|
418
418
|
args << '*' if node['agg_star']
|
419
419
|
|
420
|
-
name = (node['funcname'].map { |n| deparse_item(n, FUNC_CALL) }
|
421
|
-
if name == 'overlay'
|
422
|
-
|
420
|
+
name = (node['funcname'].map { |n| deparse_item(n, FUNC_CALL) }).join('.')
|
421
|
+
if name == 'pg_catalog.overlay'
|
422
|
+
# Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
|
423
|
+
# keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
|
424
|
+
output << format('OVERLAY(%s PLACING %s FROM %s FOR %s)', args[0], args[1], args[2], args[3])
|
423
425
|
else
|
424
426
|
distinct = node['agg_distinct'] ? 'DISTINCT ' : ''
|
425
427
|
output << format('%s(%s%s)', name, distinct, args.join(', '))
|
@@ -1223,7 +1225,7 @@ class PgQuery
|
|
1223
1225
|
output << deparse_item(node['selectStmt'])
|
1224
1226
|
|
1225
1227
|
if node['onConflictClause']
|
1226
|
-
output << deparse_insert_onconflict(node['onConflictClause'][
|
1228
|
+
output << deparse_insert_onconflict(node['onConflictClause'][ON_CONFLICT_CLAUSE])
|
1227
1229
|
end
|
1228
1230
|
|
1229
1231
|
if node['returningList']
|
@@ -1308,10 +1310,30 @@ class PgQuery
|
|
1308
1310
|
output.join(' ')
|
1309
1311
|
end
|
1310
1312
|
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1313
|
+
# Builds a properly-qualified reference to a built-in Postgres type.
|
1314
|
+
#
|
1315
|
+
# Inspired by SystemTypeName in Postgres' gram.y, but without node name
|
1316
|
+
# and locations, to simplify comparison.
|
1317
|
+
def make_system_type_name(name)
|
1318
|
+
{
|
1319
|
+
'names' => [
|
1320
|
+
{ 'String' => { 'str' => 'pg_catalog' } },
|
1321
|
+
{ 'String' => { 'str' => name } }
|
1322
|
+
],
|
1323
|
+
'typemod' => -1
|
1324
|
+
}
|
1325
|
+
end
|
1326
|
+
|
1327
|
+
def make_string(str)
|
1328
|
+
{ 'String' => { 'str' => str } }
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
def deparse_typecast(node)
|
1332
|
+
# Handle "bool" or "false" in the statement, which is represented as a typecast
|
1333
|
+
# (other boolean casts should be represented as a cast, i.e. don't need special handling)
|
1334
|
+
if node['arg'][A_CONST] && node['typeName'][TYPE_NAME].slice('names', 'typemod') == make_system_type_name('bool')
|
1335
|
+
return 'true' if node['arg'][A_CONST]['val'] == make_string('t')
|
1336
|
+
return 'false' if node['arg'][A_CONST]['val'] == make_string('f')
|
1315
1337
|
end
|
1316
1338
|
|
1317
1339
|
context = true if node['arg']['A_Expr']
|
data/lib/pg_query/node_types.rb
CHANGED
@@ -68,6 +68,7 @@ class PgQuery
|
|
68
68
|
NULL_TEST = 'NullTest'.freeze
|
69
69
|
OBJECT_WITH_ARGS = 'ObjectWithArgs'.freeze
|
70
70
|
OID_LIST = 'OidList'.freeze
|
71
|
+
ON_CONFLICT_CLAUSE = 'OnConflictClause'.freeze
|
71
72
|
PARAM_REF = 'ParamRef'.freeze
|
72
73
|
PREPARE_STMT = 'PrepareStmt'.freeze
|
73
74
|
RANGE_FUNCTION = 'RangeFunction'.freeze
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_query_pg_ddm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mehmet Emin KARAKAŞ
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -126,8 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: '0'
|
128
128
|
requirements: []
|
129
|
-
|
130
|
-
rubygems_version: 2.7.6
|
129
|
+
rubygems_version: 3.1.2
|
131
130
|
signing_key:
|
132
131
|
specification_version: 4
|
133
132
|
summary: PostgreSQL query parsing and normalization library
|