sqlpp 1.1.1 → 1.2.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 +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
|