sqlpp 1.1.1 → 1.2.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 +22 -0
- data/lib/sqlpp/parser.rb +34 -3
- data/lib/sqlpp/tokenizer.rb +3 -0
- data/lib/sqlpp/version.rb +2 -2
- data/test/formatter_test.rb +43 -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: e96af138b105ce5c23190556cfe34c20e7d275da
|
4
|
+
data.tar.gz: 33dc95f6c3d0222cd82b3c2c373c5462c698506f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ead60811f2f761ae6da39c124a50dcc3d2cef1eeca80c38a3213fc5d44537ee97276d538996c609b703dd954ceb1bff366bf060e51159505341d51dcbfac707
|
7
|
+
data.tar.gz: c1eb147f0e416a3f04911f208c23e825cf83530b3d83f392a5dac9382e7cba3d2a868c42c77021a2908ff57f04327152f97861c3de72b482842a6ba507dff3c5
|
data/lib/sqlpp/ast.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module SQLPP
|
2
2
|
module AST
|
3
|
-
class Select < Struct.new(:projections, :froms, :wheres, :groups, :orders)
|
3
|
+
class Select < Struct.new(:projections, :froms, :wheres, :groups, :orders, :distinct, :limit, :offset)
|
4
4
|
end
|
5
5
|
|
6
6
|
class Expr < Struct.new(:left, :op, :right)
|
@@ -26,5 +26,11 @@ module SQLPP
|
|
26
26
|
|
27
27
|
class SortKey < Struct.new(:key, :options)
|
28
28
|
end
|
29
|
+
|
30
|
+
class Limit < Struct.new(:expr)
|
31
|
+
end
|
32
|
+
|
33
|
+
class Offset < Struct.new(:expr)
|
34
|
+
end
|
29
35
|
end
|
30
36
|
end
|
data/lib/sqlpp/formatter.rb
CHANGED
@@ -23,6 +23,7 @@ module SQLPP
|
|
23
23
|
end
|
24
24
|
|
25
25
|
output << (select = "#{_indent}SELECT ")
|
26
|
+
output << "DISTINCT " if node.distinct
|
26
27
|
link = ","
|
27
28
|
link << ((@projections == :wrap) ? "\n#{" " * select.length}" : " ")
|
28
29
|
output << node.projections.map { |c| format(c) }.join(link)
|
@@ -54,6 +55,19 @@ module SQLPP
|
|
54
55
|
output << "\n"
|
55
56
|
end
|
56
57
|
|
58
|
+
if node.limit || node.offset
|
59
|
+
output << _indent
|
60
|
+
|
61
|
+
if node.limit
|
62
|
+
output << format(node.limit)
|
63
|
+
output << " " if node.offset
|
64
|
+
end
|
65
|
+
|
66
|
+
output << format(node.offset) if node.offset
|
67
|
+
|
68
|
+
output << "\n"
|
69
|
+
end
|
70
|
+
|
57
71
|
@indent -= 2
|
58
72
|
@indent = nil if @indent < 0
|
59
73
|
|
@@ -156,6 +170,14 @@ module SQLPP
|
|
156
170
|
output
|
157
171
|
end
|
158
172
|
|
173
|
+
def _format_Limit(node)
|
174
|
+
"LIMIT #{format(node.expr)}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def _format_Offset(node)
|
178
|
+
"OFFSET #{format(node.expr)}"
|
179
|
+
end
|
180
|
+
|
159
181
|
def _format_String(string)
|
160
182
|
string
|
161
183
|
end
|
data/lib/sqlpp/parser.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
require 'sqlpp/ast'
|
2
2
|
|
3
|
-
# select := 'SELECT'
|
3
|
+
# select := 'SELECT' optional_distinct
|
4
4
|
# optional_projections
|
5
5
|
# optional_froms
|
6
6
|
# optional_wheres
|
7
7
|
# optional_groups
|
8
8
|
# optional_orders
|
9
|
+
# optional_limit
|
10
|
+
# optional_offset
|
11
|
+
#
|
12
|
+
# optional_distinct := ''
|
13
|
+
# | 'DISTINCT'
|
9
14
|
#
|
10
15
|
# optional_projections := ''
|
11
16
|
# | list
|
@@ -22,6 +27,12 @@ require 'sqlpp/ast'
|
|
22
27
|
# optional_orders := ''
|
23
28
|
# | 'ORDER' 'BY' sort_keys
|
24
29
|
#
|
30
|
+
# optional_limit := ''
|
31
|
+
# | 'LIMIT' expr4
|
32
|
+
#
|
33
|
+
# optional_offset := ''
|
34
|
+
# | 'OFFSET' expr4
|
35
|
+
#
|
25
36
|
# sort_keys := sort_key
|
26
37
|
# | sort_key ',' sort_keys
|
27
38
|
#
|
@@ -67,7 +78,7 @@ require 'sqlpp/ast'
|
|
67
78
|
#
|
68
79
|
# op2 := '+' | '-' | '*' | '/'
|
69
80
|
#
|
70
|
-
# unary := '+' | '-' | 'NOT'
|
81
|
+
# unary := '+' | '-' | 'NOT' | 'DISTINCT'
|
71
82
|
#
|
72
83
|
# expr4 := lit
|
73
84
|
# | id
|
@@ -133,6 +144,10 @@ module SQLPP
|
|
133
144
|
select = AST::Select.new
|
134
145
|
|
135
146
|
_eat :space
|
147
|
+
if _eat(:key, :distinct)
|
148
|
+
select.distinct = true
|
149
|
+
_eat :space
|
150
|
+
end
|
136
151
|
|
137
152
|
if !_peek(:key, /^(from|where)$/) && !_peek(:eof)
|
138
153
|
list = []
|
@@ -212,6 +227,22 @@ module SQLPP
|
|
212
227
|
select.orders = list
|
213
228
|
end
|
214
229
|
|
230
|
+
if _eat(:key, :limit)
|
231
|
+
_eat :space
|
232
|
+
atom = _parse_atom
|
233
|
+
_eat :space
|
234
|
+
|
235
|
+
select.limit = AST::Limit.new(atom)
|
236
|
+
end
|
237
|
+
|
238
|
+
if _eat(:key, :offset)
|
239
|
+
_eat :space
|
240
|
+
atom = _parse_atom
|
241
|
+
_eat :space
|
242
|
+
|
243
|
+
select.offset = AST::Offset.new(atom)
|
244
|
+
end
|
245
|
+
|
215
246
|
select
|
216
247
|
end
|
217
248
|
|
@@ -346,7 +377,7 @@ module SQLPP
|
|
346
377
|
def _parse_expr3
|
347
378
|
_eat :space
|
348
379
|
|
349
|
-
if (op = (_eat(:punct, /[-+]/) || _eat(:key,
|
380
|
+
if (op = (_eat(:punct, /[-+]/) || _eat(:key, /^(not|distinct)$/)))
|
350
381
|
_eat :space
|
351
382
|
AST::Unary.new(op.text, _parse_expr3)
|
352
383
|
|
data/lib/sqlpp/tokenizer.rb
CHANGED
data/lib/sqlpp/version.rb
CHANGED
data/test/formatter_test.rb
CHANGED
@@ -42,6 +42,49 @@ FROM foo
|
|
42
42
|
SQL
|
43
43
|
end
|
44
44
|
|
45
|
+
def test_format_select_distinct
|
46
|
+
ast = _parser("select distinct a, b, c, d from foo").parse
|
47
|
+
assert_equal <<-SQL, _format(ast)
|
48
|
+
SELECT DISTINCT a, b, c, d
|
49
|
+
FROM foo
|
50
|
+
SQL
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_format_count_distinct
|
54
|
+
ast = _parser("select count(distinct id) from foo").parse
|
55
|
+
assert_equal <<-SQL, _format(ast)
|
56
|
+
SELECT count(DISTINCT id)
|
57
|
+
FROM foo
|
58
|
+
SQL
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_format_limit
|
62
|
+
ast = _parser("select * from foo limit 5").parse
|
63
|
+
assert_equal <<-SQL, _format(ast)
|
64
|
+
SELECT *
|
65
|
+
FROM foo
|
66
|
+
LIMIT 5
|
67
|
+
SQL
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_format_offset
|
71
|
+
ast = _parser("select * from foo offset 5").parse
|
72
|
+
assert_equal <<-SQL, _format(ast)
|
73
|
+
SELECT *
|
74
|
+
FROM foo
|
75
|
+
OFFSET 5
|
76
|
+
SQL
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_format_limit_and_offset
|
80
|
+
ast = _parser("select * from foo limit 10 offset 5").parse
|
81
|
+
assert_equal <<-SQL, _format(ast)
|
82
|
+
SELECT *
|
83
|
+
FROM foo
|
84
|
+
LIMIT 10 OFFSET 5
|
85
|
+
SQL
|
86
|
+
end
|
87
|
+
|
45
88
|
def _parser(string)
|
46
89
|
SQLPP::Parser.new(string)
|
47
90
|
end
|
data/test/parser_test.rb
CHANGED
@@ -179,6 +179,19 @@ class ParserTest < Minitest::Test
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
+
def test_it_should_parse_distinct_expression
|
183
|
+
expr = _parser("count(distinct id)").parse_expression
|
184
|
+
assert_instance_of SQLPP::AST::Atom, expr
|
185
|
+
assert_equal :func, expr.type
|
186
|
+
assert_equal 1, expr.right.count
|
187
|
+
|
188
|
+
assert_instance_of SQLPP::AST::Unary, expr.right[0]
|
189
|
+
assert_equal :distinct, expr.right[0].op
|
190
|
+
assert_instance_of SQLPP::AST::Atom, expr.right[0].expr
|
191
|
+
assert_equal :attr, expr.right[0].expr.type
|
192
|
+
assert_equal "id", expr.right[0].expr.left
|
193
|
+
end
|
194
|
+
|
182
195
|
def test_from_should_recognize_single_attr
|
183
196
|
from = _parser("x").parse_from
|
184
197
|
assert_instance_of SQLPP::AST::Atom, from
|
@@ -269,11 +282,33 @@ class ParserTest < Minitest::Test
|
|
269
282
|
assert_equal [:desc, "nulls last"], s.orders[1].options
|
270
283
|
end
|
271
284
|
|
285
|
+
def test_accepts_select_distinct
|
286
|
+
s = _parser("select distinct * from x").parse_select
|
287
|
+
assert_instance_of SQLPP::AST::Select, s
|
288
|
+
assert_equal s.distinct, true
|
289
|
+
end
|
290
|
+
|
272
291
|
def test_parse_should_recognize_select
|
273
292
|
s = _parser("select * from x").parse
|
274
293
|
assert_instance_of SQLPP::AST::Select, s
|
275
294
|
end
|
276
295
|
|
296
|
+
def test_accepts_select_with_limit
|
297
|
+
s = _parser("select * from x limit 5").parse_select
|
298
|
+
assert_instance_of SQLPP::AST::Limit, s.limit
|
299
|
+
assert_instance_of SQLPP::AST::Atom, s.limit.expr
|
300
|
+
assert_equal :lit, s.limit.expr.type
|
301
|
+
assert_equal "5", s.limit.expr.left
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_accepts_select_with_offset
|
305
|
+
s = _parser("select * from x offset 5").parse_select
|
306
|
+
assert_instance_of SQLPP::AST::Offset, s.offset
|
307
|
+
assert_instance_of SQLPP::AST::Atom, s.offset.expr
|
308
|
+
assert_equal :lit, s.offset.expr.type
|
309
|
+
assert_equal "5", s.offset.expr.left
|
310
|
+
end
|
311
|
+
|
277
312
|
def _parser(string)
|
278
313
|
SQLPP::Parser.new(string)
|
279
314
|
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.2.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-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|