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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e96af138b105ce5c23190556cfe34c20e7d275da
4
- data.tar.gz: 33dc95f6c3d0222cd82b3c2c373c5462c698506f
3
+ metadata.gz: d5571413a37bafba8fb43af7c8ecbf43f5e0638e
4
+ data.tar.gz: d33d23f80b2ad5652c59eb6d12eb6b4cabfda9f0
5
5
  SHA512:
6
- metadata.gz: 8ead60811f2f761ae6da39c124a50dcc3d2cef1eeca80c38a3213fc5d44537ee97276d538996c609b703dd954ceb1bff366bf060e51159505341d51dcbfac707
7
- data.tar.gz: c1eb147f0e416a3f04911f208c23e825cf83530b3d83f392a5dac9382e7cba3d2a868c42c77021a2908ff57f04327152f97861c3de72b482842a6ba507dff3c5
6
+ metadata.gz: 73f76ef17b727d6632a3ab893fad0c222b938e2bee87b92d47bfbdbbfd6e362fe2dfdfcd074ef3112aaf4edf5a9e8e055bdf1f3be05bced91e84c6e46a01de26
7
+ data.tar.gz: eb2275e0b716d9acb7338ed8f6728161f6a32933bf058b6795c2b31c70c28bf6be4f861d7171f0bb459b36c2f4feabffc67a04e10e7f29c3115dcda74d308c4f
@@ -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
@@ -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
@@ -65,10 +65,14 @@ require 'sqlpp/ast'
65
65
  #
66
66
  # op := 'AND' | 'OR' | 'IS' | 'IS NOT'
67
67
  #
68
- # expr2 := expr3
69
- # | expr3 'BETWEEN' expr3 AND expr3
70
- # | expr3 'IN' '(' list ')'
71
- # | expr3 bop expr3
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 (key = _eat(:key, :case))
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
@@ -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)
@@ -1,7 +1,7 @@
1
1
  module SQLPP
2
2
  module Version
3
3
  MAJOR = 1
4
- MINOR = 2
4
+ MINOR = 3
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join(".")
@@ -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
@@ -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.2.0
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-03-15 00:00:00.000000000 Z
11
+ date: 2016-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake