sqlpp 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sqlpp/ast.rb +7 -1
- data/lib/sqlpp/formatter.rb +13 -1
- data/lib/sqlpp/parser.rb +35 -6
- data/lib/sqlpp/tokenizer.rb +2 -2
- data/lib/sqlpp/version.rb +1 -1
- data/test/formatter_test.rb +25 -0
- data/test/parser_test.rb +35 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5571413a37bafba8fb43af7c8ecbf43f5e0638e
|
4
|
+
data.tar.gz: d33d23f80b2ad5652c59eb6d12eb6b4cabfda9f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73f76ef17b727d6632a3ab893fad0c222b938e2bee87b92d47bfbdbbfd6e362fe2dfdfcd074ef3112aaf4edf5a9e8e055bdf1f3be05bced91e84c6e46a01de26
|
7
|
+
data.tar.gz: eb2275e0b716d9acb7338ed8f6728161f6a32933bf058b6795c2b31c70c28bf6be4f861d7171f0bb459b36c2f4feabffc67a04e10e7f29c3115dcda74d308c4f
|
data/lib/sqlpp/ast.rb
CHANGED
@@ -3,7 +3,7 @@ module SQLPP
|
|
3
3
|
class Select < Struct.new(:projections, :froms, :wheres, :groups, :orders, :distinct, :limit, :offset)
|
4
4
|
end
|
5
5
|
|
6
|
-
class Expr < Struct.new(:left, :op, :right)
|
6
|
+
class Expr < Struct.new(:left, :op, :right, :not)
|
7
7
|
end
|
8
8
|
|
9
9
|
class Unary < Struct.new(:op, :expr)
|
@@ -32,5 +32,11 @@ module SQLPP
|
|
32
32
|
|
33
33
|
class Offset < Struct.new(:expr)
|
34
34
|
end
|
35
|
+
|
36
|
+
class Subscript < Struct.new(:left, :right)
|
37
|
+
end
|
38
|
+
|
39
|
+
class TypeCast < Struct.new(:value, :type)
|
40
|
+
end
|
35
41
|
end
|
36
42
|
end
|
data/lib/sqlpp/formatter.rb
CHANGED
@@ -85,6 +85,7 @@ module SQLPP
|
|
85
85
|
output << " "
|
86
86
|
end
|
87
87
|
|
88
|
+
output << "NOT " if node.not
|
88
89
|
output << op << " "
|
89
90
|
output << format(node.right)
|
90
91
|
end
|
@@ -164,7 +165,7 @@ module SQLPP
|
|
164
165
|
|
165
166
|
if node.options.any?
|
166
167
|
output << " "
|
167
|
-
output << node.options.map { |opt| opt.upcase }.join("
|
168
|
+
output << node.options.map { |opt| opt.upcase }.join(" ")
|
168
169
|
end
|
169
170
|
|
170
171
|
output
|
@@ -182,6 +183,17 @@ module SQLPP
|
|
182
183
|
string
|
183
184
|
end
|
184
185
|
|
186
|
+
def _format_Subscript(node)
|
187
|
+
output = ""
|
188
|
+
output << format(node.left)
|
189
|
+
output << "[" << format(node.right) << "]"
|
190
|
+
output
|
191
|
+
end
|
192
|
+
|
193
|
+
def _format_TypeCast(node)
|
194
|
+
format(node.value) << '::' << format(node.type)
|
195
|
+
end
|
196
|
+
|
185
197
|
def _indent
|
186
198
|
" " * (@indent || 0)
|
187
199
|
end
|
data/lib/sqlpp/parser.rb
CHANGED
@@ -65,10 +65,14 @@ require 'sqlpp/ast'
|
|
65
65
|
#
|
66
66
|
# op := 'AND' | 'OR' | 'IS' | 'IS NOT'
|
67
67
|
#
|
68
|
-
# expr2 := expr3
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
68
|
+
# expr2 := expr3 optional_op
|
69
|
+
#
|
70
|
+
# optional_op := ''
|
71
|
+
# | 'NOT' optional_op
|
72
|
+
# | 'BETWEEN' expr3 AND expr3
|
73
|
+
# | 'NOT IN' '(' list ')'
|
74
|
+
# | 'IN' '(' list ')'
|
75
|
+
# | bop expr3
|
72
76
|
#
|
73
77
|
# bop := '<' | '<=' | '<>' | '=' | '>=' | '>'
|
74
78
|
#
|
@@ -86,6 +90,8 @@ require 'sqlpp/ast'
|
|
86
90
|
# | id '(' args ')'
|
87
91
|
# | 'CASE' case_stmt 'END'
|
88
92
|
# | '(' expr1 ')'
|
93
|
+
# | expr4 '[' expr1 ']'
|
94
|
+
# | expr4 '::' expr4
|
89
95
|
#
|
90
96
|
# list := expr1
|
91
97
|
# | expr1 ',' list
|
@@ -338,6 +344,9 @@ module SQLPP
|
|
338
344
|
left = _parse_expr3
|
339
345
|
_eat :space
|
340
346
|
|
347
|
+
not_kw = _eat(:key, :not)
|
348
|
+
_eat :space if not_kw
|
349
|
+
|
341
350
|
if (op = _eat(:key, :between))
|
342
351
|
op = op.text
|
343
352
|
|
@@ -368,7 +377,9 @@ module SQLPP
|
|
368
377
|
end
|
369
378
|
|
370
379
|
if right
|
371
|
-
AST::Expr.new(left, op, right)
|
380
|
+
AST::Expr.new(left, op, right, not_kw != nil)
|
381
|
+
elsif not_kw
|
382
|
+
raise UnexpectedToken, "got #{not_kw.inspect}"
|
372
383
|
else
|
373
384
|
left
|
374
385
|
end
|
@@ -385,6 +396,23 @@ module SQLPP
|
|
385
396
|
atom = _parse_atom
|
386
397
|
_eat :space
|
387
398
|
|
399
|
+
if _eat(:punct, "[")
|
400
|
+
subscript = _parse_expr1
|
401
|
+
_eat :space
|
402
|
+
_expect(:punct, "]")
|
403
|
+
_eat :space
|
404
|
+
|
405
|
+
atom = AST::Subscript.new(atom, subscript)
|
406
|
+
end
|
407
|
+
|
408
|
+
if _eat(:punct, "::")
|
409
|
+
_eat :space
|
410
|
+
type = _parse_atom
|
411
|
+
_eat :space
|
412
|
+
|
413
|
+
atom = AST::TypeCast.new(atom, type)
|
414
|
+
end
|
415
|
+
|
388
416
|
if (op = _eat(:punct, /[-+*\/]/))
|
389
417
|
_eat :space
|
390
418
|
AST::Expr.new(atom, op.text, _parse_expr3)
|
@@ -398,7 +426,7 @@ module SQLPP
|
|
398
426
|
if (lit = _eat(:lit))
|
399
427
|
AST::Atom.new(:lit, lit.text)
|
400
428
|
|
401
|
-
elsif
|
429
|
+
elsif _eat(:key, :case)
|
402
430
|
_parse_case
|
403
431
|
|
404
432
|
elsif _eat(:punct, "(")
|
@@ -470,6 +498,7 @@ module SQLPP
|
|
470
498
|
def _parse_list
|
471
499
|
_eat :space
|
472
500
|
args = []
|
501
|
+
return args if _peek(:punct, ')')
|
473
502
|
|
474
503
|
loop do
|
475
504
|
args << _parse_expr1
|
data/lib/sqlpp/tokenizer.rb
CHANGED
@@ -85,9 +85,9 @@ module SQLPP
|
|
85
85
|
Token.new(:lit, num, pos)
|
86
86
|
elsif (id = @scanner.scan(/\w+/))
|
87
87
|
Token.new(:id, id, pos)
|
88
|
-
elsif (punct = @scanner.scan(
|
88
|
+
elsif (punct = @scanner.scan(/<=|<>|!=|>=|::/))
|
89
89
|
Token.new(:punct, punct, pos)
|
90
|
-
elsif (punct = @scanner.scan(/[<>=\(\)
|
90
|
+
elsif (punct = @scanner.scan(/[<>=\(\).*,\/+\-\[\]]/))
|
91
91
|
Token.new(:punct, punct, pos)
|
92
92
|
elsif (delim = @scanner.scan(/["`]/))
|
93
93
|
contents = _scan_to_delim(delim, pos)
|
data/lib/sqlpp/version.rb
CHANGED
data/test/formatter_test.rb
CHANGED
@@ -85,6 +85,31 @@ LIMIT 10 OFFSET 5
|
|
85
85
|
SQL
|
86
86
|
end
|
87
87
|
|
88
|
+
def test_format_NOT_expr
|
89
|
+
ast = _parser("select * from foo where x not in (5, 6)").parse
|
90
|
+
assert_equal <<-SQL, _format(ast)
|
91
|
+
SELECT *
|
92
|
+
FROM foo
|
93
|
+
WHERE x NOT IN (5, 6)
|
94
|
+
SQL
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_format_subscript_in_expr
|
98
|
+
ast = _parser("select (array_agg(x))[0] from foo").parse
|
99
|
+
assert_equal <<-SQL, _format(ast)
|
100
|
+
SELECT (array_agg(x))[0]
|
101
|
+
FROM foo
|
102
|
+
SQL
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_format_double_colon_typecast
|
106
|
+
ast = _parser("select 'month'::interval from foo").parse
|
107
|
+
assert_equal <<-SQL, _format(ast)
|
108
|
+
SELECT 'month'::interval
|
109
|
+
FROM foo
|
110
|
+
SQL
|
111
|
+
end
|
112
|
+
|
88
113
|
def _parser(string)
|
89
114
|
SQLPP::Parser.new(string)
|
90
115
|
end
|
data/test/parser_test.rb
CHANGED
@@ -309,6 +309,41 @@ class ParserTest < Minitest::Test
|
|
309
309
|
assert_equal "5", s.offset.expr.left
|
310
310
|
end
|
311
311
|
|
312
|
+
def test_accepts_not_in_syntax
|
313
|
+
s = _parser("select * from x where x.id not in (5)").parse_select
|
314
|
+
assert s.wheres.not
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_accepts_array_subscript_in_expression
|
318
|
+
expr = _parser("a[5]").parse_expression
|
319
|
+
assert_instance_of SQLPP::AST::Subscript, expr
|
320
|
+
assert_instance_of SQLPP::AST::Atom, expr.left
|
321
|
+
assert_instance_of SQLPP::AST::Atom, expr.right
|
322
|
+
assert_equal :attr, expr.left.type
|
323
|
+
assert_equal "a", expr.left.left
|
324
|
+
assert_equal :lit, expr.right.type
|
325
|
+
assert_equal "5", expr.right.left
|
326
|
+
end
|
327
|
+
|
328
|
+
def test_accepts_double_colon_as_typecast
|
329
|
+
expr = _parser("'month'::INTERVAL").parse_expression
|
330
|
+
assert_instance_of SQLPP::AST::TypeCast, expr
|
331
|
+
assert_instance_of SQLPP::AST::Atom, expr.value
|
332
|
+
assert_instance_of SQLPP::AST::Atom, expr.type
|
333
|
+
assert_equal :lit, expr.value.type
|
334
|
+
assert_equal "'month'", expr.value.left
|
335
|
+
assert_equal :attr, expr.type.type
|
336
|
+
assert_equal "INTERVAL", expr.type.left
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_accept_empty_parameter_list
|
340
|
+
expr = _parser("NOW()").parse_expression
|
341
|
+
assert_instance_of SQLPP::AST::Atom, expr
|
342
|
+
assert_equal :func, expr.type
|
343
|
+
assert_equal "NOW", expr.left
|
344
|
+
assert_equal 0, expr.right.count
|
345
|
+
end
|
346
|
+
|
312
347
|
def _parser(string)
|
313
348
|
SQLPP::Parser.new(string)
|
314
349
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqlpp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamis Buck
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|