bmg 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bmg/algebra.rb +2 -26
  3. data/lib/bmg/algebra/shortcuts.rb +14 -0
  4. data/lib/bmg/operator/autowrap.rb +32 -2
  5. data/lib/bmg/operator/constants.rb +12 -0
  6. data/lib/bmg/operator/image.rb +10 -0
  7. data/lib/bmg/operator/rename.rb +8 -0
  8. data/lib/bmg/relation/spied.rb +4 -9
  9. data/lib/bmg/sequel.rb +53 -2
  10. data/lib/bmg/sequel/relation.rb +24 -19
  11. data/lib/bmg/sequel/translator.rb +153 -0
  12. data/lib/bmg/sequel/type_inference.rb +42 -0
  13. data/lib/bmg/sql.rb +20 -0
  14. data/lib/bmg/sql/builder.rb +177 -0
  15. data/lib/bmg/sql/dialect.rb +15 -0
  16. data/lib/bmg/sql/ext/predicate.rb +23 -0
  17. data/lib/bmg/sql/ext/predicate/and.rb +9 -0
  18. data/lib/bmg/sql/ext/predicate/contradiction.rb +10 -0
  19. data/lib/bmg/sql/ext/predicate/dyadic_comp.rb +12 -0
  20. data/lib/bmg/sql/ext/predicate/eq.rb +9 -0
  21. data/lib/bmg/sql/ext/predicate/exists.rb +12 -0
  22. data/lib/bmg/sql/ext/predicate/expr.rb +18 -0
  23. data/lib/bmg/sql/ext/predicate/gt.rb +9 -0
  24. data/lib/bmg/sql/ext/predicate/gte.rb +9 -0
  25. data/lib/bmg/sql/ext/predicate/identifier.rb +10 -0
  26. data/lib/bmg/sql/ext/predicate/in.rb +29 -0
  27. data/lib/bmg/sql/ext/predicate/literal.rb +10 -0
  28. data/lib/bmg/sql/ext/predicate/lt.rb +9 -0
  29. data/lib/bmg/sql/ext/predicate/lte.rb +9 -0
  30. data/lib/bmg/sql/ext/predicate/nadic_bool.rb +16 -0
  31. data/lib/bmg/sql/ext/predicate/native.rb +9 -0
  32. data/lib/bmg/sql/ext/predicate/neq.rb +9 -0
  33. data/lib/bmg/sql/ext/predicate/not.rb +12 -0
  34. data/lib/bmg/sql/ext/predicate/or.rb +9 -0
  35. data/lib/bmg/sql/ext/predicate/qualified_identifier.rb +12 -0
  36. data/lib/bmg/sql/ext/predicate/tautology.rb +10 -0
  37. data/lib/bmg/sql/grammar.rb +45 -0
  38. data/lib/bmg/sql/grammar.sexp.yml +96 -0
  39. data/lib/bmg/sql/nodes/column_name.rb +25 -0
  40. data/lib/bmg/sql/nodes/cross_join.rb +28 -0
  41. data/lib/bmg/sql/nodes/except.rb +14 -0
  42. data/lib/bmg/sql/nodes/expr.rb +94 -0
  43. data/lib/bmg/sql/nodes/from_clause.rb +24 -0
  44. data/lib/bmg/sql/nodes/inner_join.rb +37 -0
  45. data/lib/bmg/sql/nodes/intersect.rb +14 -0
  46. data/lib/bmg/sql/nodes/limit_clause.rb +19 -0
  47. data/lib/bmg/sql/nodes/literal.rb +18 -0
  48. data/lib/bmg/sql/nodes/name_intro.rb +23 -0
  49. data/lib/bmg/sql/nodes/native_table_as.rb +31 -0
  50. data/lib/bmg/sql/nodes/offset_clause.rb +19 -0
  51. data/lib/bmg/sql/nodes/order_by_clause.rb +25 -0
  52. data/lib/bmg/sql/nodes/order_by_term.rb +30 -0
  53. data/lib/bmg/sql/nodes/qualified_name.rb +32 -0
  54. data/lib/bmg/sql/nodes/range_var_name.rb +17 -0
  55. data/lib/bmg/sql/nodes/select_exp.rb +109 -0
  56. data/lib/bmg/sql/nodes/select_item.rb +37 -0
  57. data/lib/bmg/sql/nodes/select_list.rb +35 -0
  58. data/lib/bmg/sql/nodes/select_star.rb +22 -0
  59. data/lib/bmg/sql/nodes/set_operator.rb +68 -0
  60. data/lib/bmg/sql/nodes/set_quantifier.rb +20 -0
  61. data/lib/bmg/sql/nodes/subquery_as.rb +28 -0
  62. data/lib/bmg/sql/nodes/table_as.rb +31 -0
  63. data/lib/bmg/sql/nodes/table_name.rb +17 -0
  64. data/lib/bmg/sql/nodes/union.rb +14 -0
  65. data/lib/bmg/sql/nodes/where_clause.rb +20 -0
  66. data/lib/bmg/sql/nodes/with_exp.rb +51 -0
  67. data/lib/bmg/sql/nodes/with_spec.rb +24 -0
  68. data/lib/bmg/sql/processor.rb +85 -0
  69. data/lib/bmg/sql/processor/all.rb +17 -0
  70. data/lib/bmg/sql/processor/clip.rb +57 -0
  71. data/lib/bmg/sql/processor/distinct.rb +17 -0
  72. data/lib/bmg/sql/processor/flatten.rb +24 -0
  73. data/lib/bmg/sql/processor/from_self.rb +29 -0
  74. data/lib/bmg/sql/processor/join.rb +80 -0
  75. data/lib/bmg/sql/processor/join_support.rb +28 -0
  76. data/lib/bmg/sql/processor/limit_offset.rb +30 -0
  77. data/lib/bmg/sql/processor/merge.rb +49 -0
  78. data/lib/bmg/sql/processor/order_by.rb +32 -0
  79. data/lib/bmg/sql/processor/rename.rb +25 -0
  80. data/lib/bmg/sql/processor/reorder.rb +21 -0
  81. data/lib/bmg/sql/processor/requalify.rb +24 -0
  82. data/lib/bmg/sql/processor/semi_join.rb +68 -0
  83. data/lib/bmg/sql/processor/star.rb +17 -0
  84. data/lib/bmg/sql/processor/where.rb +25 -0
  85. data/lib/bmg/sql/relation.rb +141 -0
  86. data/lib/bmg/sql/version.rb +16 -0
  87. data/lib/bmg/support.rb +1 -0
  88. data/lib/bmg/support/keys.rb +59 -0
  89. data/lib/bmg/type.rb +95 -14
  90. data/lib/bmg/version.rb +2 -2
  91. data/tasks/test.rake +9 -2
  92. metadata +97 -5
@@ -0,0 +1,9 @@
1
+ class Predicate
2
+ module Lte
3
+
4
+ def to_sql_operator
5
+ Sql::Expr::LESS_OR_EQUAL
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ class Predicate
2
+ module NadicBool
3
+
4
+ def to_sql(buffer, dialect)
5
+ each_with_index do |child, index|
6
+ next if index == 0
7
+ unless index == 1
8
+ buffer << Sql::Expr::SPACE << to_sql_operator << Sql::Expr::SPACE
9
+ end
10
+ child.to_sql(buffer, dialect)
11
+ end
12
+ buffer
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ class Predicate
2
+ module Native
3
+
4
+ def to_sql(buffer, dialect)
5
+ raise NotSupportedError, "Unable to compile native predicates to SQL"
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Predicate
2
+ module Neq
3
+
4
+ def to_sql_operator
5
+ Sql::Expr::NOT_EQUAL
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ class Predicate
2
+ module Not
3
+
4
+ def to_sql(buffer, dialect)
5
+ buffer << Sql::Expr::NOT << Sql::Expr::LEFT_PARENTHESE
6
+ last.to_sql(buffer, dialect)
7
+ buffer << Sql::Expr::RIGHT_PARENTHESE
8
+ buffer
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class Predicate
2
+ module Or
3
+
4
+ def to_sql_operator
5
+ Sql::Expr::OR
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ class Predicate
2
+ module QualifiedIdentifier
3
+
4
+ def to_sql(buffer, dialect)
5
+ buffer << dialect.quote_identifier(qualifier)
6
+ buffer << Sql::Expr::DOT
7
+ buffer << dialect.quote_identifier(name)
8
+ buffer
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class Predicate
2
+ module Tautology
3
+
4
+ def to_sql(buffer, dialect)
5
+ buffer << Sql::Expr::TRUE
6
+ buffer
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,45 @@
1
+ module Bmg
2
+ module Sql
3
+ Grammar = Sexpr.load(Path.dir/'grammar.sexp.yml')
4
+ module Grammar
5
+
6
+ def tagging_reference
7
+ Sql
8
+ end
9
+
10
+ def default_tagging_module
11
+ Expr
12
+ end
13
+
14
+ end # module Grammar
15
+ end # module Sql
16
+ end # module Bmg
17
+ require_relative "nodes/expr"
18
+ require_relative "nodes/set_operator"
19
+ require_relative "nodes/literal"
20
+ require_relative "nodes/column_name"
21
+ require_relative "nodes/qualified_name"
22
+ require_relative "nodes/range_var_name"
23
+ require_relative "nodes/select_exp"
24
+ require_relative "nodes/set_quantifier"
25
+ require_relative "nodes/select_list"
26
+ require_relative "nodes/select_star"
27
+ require_relative "nodes/select_item"
28
+ require_relative "nodes/from_clause"
29
+ require_relative "nodes/table_as"
30
+ require_relative "nodes/native_table_as"
31
+ require_relative "nodes/subquery_as"
32
+ require_relative "nodes/table_name"
33
+ require_relative "nodes/order_by_clause"
34
+ require_relative "nodes/order_by_term"
35
+ require_relative "nodes/limit_clause"
36
+ require_relative "nodes/offset_clause"
37
+ require_relative "nodes/union"
38
+ require_relative "nodes/intersect"
39
+ require_relative "nodes/except"
40
+ require_relative "nodes/with_exp"
41
+ require_relative "nodes/with_spec"
42
+ require_relative "nodes/name_intro"
43
+ require_relative "nodes/where_clause"
44
+ require_relative "nodes/cross_join"
45
+ require_relative "nodes/inner_join"
@@ -0,0 +1,96 @@
1
+ rules:
2
+ query:
3
+ - with_exp
4
+ - nonjoin_exp
5
+ with_exp:
6
+ - [ with_spec, nonjoin_exp ]
7
+ with_spec:
8
+ - [ name_intro+ ]
9
+ name_intro:
10
+ - [ table_name, nonjoin_exp ]
11
+ nonjoin_exp:
12
+ - union
13
+ - except
14
+ - intersect
15
+ - select_exp
16
+ union:
17
+ - [ all, nonjoin_exp, nonjoin_exp ]
18
+ all:
19
+ - truth_value
20
+ except:
21
+ - [ set_quantifier, nonjoin_exp, nonjoin_exp ]
22
+ intersect:
23
+ - [ set_quantifier, nonjoin_exp, nonjoin_exp ]
24
+ join_exp:
25
+ - cross_join
26
+ - inner_join
27
+ cross_join:
28
+ - [ table_spec, table_spec ]
29
+ inner_join:
30
+ - [ table_spec, table_spec, predicate ]
31
+ using:
32
+ - [ column_name+ ]
33
+ select_exp:
34
+ - [ set_quantifier,
35
+ [ select_list, select_star ],
36
+ from_clause,
37
+ where_clause,
38
+ order_by_clause,
39
+ limit_clause,
40
+ offset_clause ]
41
+ set_quantifier:
42
+ - [ set_quantifier_name ]
43
+ select_star:
44
+ - []
45
+ set_quantifier_name:
46
+ !ruby/regexp /^all|distinct$/
47
+ select_list:
48
+ - [ select_item+ ]
49
+ from_clause:
50
+ - [ table_spec ]
51
+ where_clause:
52
+ - [ predicate ]
53
+ order_by_clause:
54
+ - [ order_by_term+ ]
55
+ order_by_term:
56
+ - [ qualified_name, direction ]
57
+ direction:
58
+ !ruby/regexp /^asc|desc$/
59
+ select_item:
60
+ - [ scalar_exp, column_name ]
61
+ table_spec:
62
+ - native_table_as
63
+ - table_as
64
+ - subquery_as
65
+ - join_exp
66
+ table_as:
67
+ - [ table_name, range_var_name ]
68
+ native_table_as:
69
+ - "::Object"
70
+ subquery_as:
71
+ - [ nonjoin_exp, range_var_name ]
72
+ scalar_exp:
73
+ - qualified_name
74
+ - column_name
75
+ - literal
76
+ qualified_name:
77
+ - [ range_var_name, column_name ]
78
+ column_name:
79
+ - [ name_rgx ]
80
+ table_name:
81
+ - [ name_rgx ]
82
+ range_var_name:
83
+ - [ name_rgx ]
84
+ limit_clause:
85
+ - [ integer ]
86
+ offset_clause:
87
+ - [ integer ]
88
+ integer:
89
+ - "::Integer"
90
+ literal:
91
+ - "::Object"
92
+ name_rgx:
93
+ !ruby/regexp /^[a-zA-Z0-9_]+$/
94
+ truth_value:
95
+ - "::TrueClass"
96
+ - "::FalseClass"
@@ -0,0 +1,25 @@
1
+ module Bmg
2
+ module Sql
3
+ module ColumnName
4
+ include Expr
5
+
6
+ def qualifier
7
+ nil
8
+ end
9
+
10
+ def as_name
11
+ last
12
+ end
13
+
14
+ def would_be_name
15
+ last
16
+ end
17
+
18
+ def to_sql(buffer, dialect)
19
+ buffer << dialect.quote_identifier(last)
20
+ buffer
21
+ end
22
+
23
+ end # module ColumnName
24
+ end # module Sql
25
+ end # module Bmg
@@ -0,0 +1,28 @@
1
+ module Bmg
2
+ module Sql
3
+ module CrossJoin
4
+ include Expr
5
+
6
+ def join?
7
+ true
8
+ end
9
+
10
+ def left
11
+ self[1]
12
+ end
13
+
14
+ def right
15
+ self[2]
16
+ end
17
+
18
+ def to_sql(buffer, dialect)
19
+ each_child do |child, index|
20
+ buffer << COMMA << SPACE unless index == 0
21
+ child.to_sql(buffer, dialect)
22
+ end
23
+ buffer
24
+ end
25
+
26
+ end # module CrossJoin
27
+ end # module Sql
28
+ end # module Bmg
@@ -0,0 +1,14 @@
1
+ module Bmg
2
+ module Sql
3
+ module Except
4
+ include SetOperator
5
+
6
+ EXCEPT = "EXCEPT".freeze
7
+
8
+ def keyword
9
+ EXCEPT
10
+ end
11
+
12
+ end # module Except
13
+ end # module Sql
14
+ end # module Bmg
@@ -0,0 +1,94 @@
1
+ module Bmg
2
+ module Sql
3
+ module Expr
4
+
5
+ LEFT_PARENTHESE = "(".freeze
6
+ RIGHT_PARENTHESE = ")".freeze
7
+ SPACE = " ".freeze
8
+ COMMA = ",".freeze
9
+ DOT = ".".freeze
10
+ QUOTE = "'".freeze
11
+ AS = "AS".freeze
12
+ AND = "AND".freeze
13
+ OR = "OR".freeze
14
+ NOT = "NOT".freeze
15
+ TRUE = "TRUE".freeze
16
+ FALSE = "FALSE".freeze
17
+ EQUAL = "=".freeze
18
+ NOT_EQUAL = "<>".freeze
19
+ GREATER = ">".freeze
20
+ LESS = "<".freeze
21
+ GREATER_OR_EQUAL = ">=".freeze
22
+ LESS_OR_EQUAL = "<=".freeze
23
+ IN = "IN".freeze
24
+ EXISTS = "EXISTS".freeze
25
+
26
+ def set_operator?
27
+ false
28
+ end
29
+
30
+ def limit_or_offset?
31
+ not(limit_clause.nil? and offset_clause.nil?)
32
+ end
33
+
34
+ def join?
35
+ false
36
+ end
37
+
38
+ def ordering
39
+ obc = order_by_clause
40
+ obc && order_by_clause.to_ordering
41
+ end
42
+
43
+ def with_update(index, what)
44
+ index = find_child_index(index) if index.is_a?(Symbol)
45
+ dup.tap{|x| x[index] = Grammar.sexpr(what) }
46
+ end
47
+
48
+ def with_insert(index, what)
49
+ dup.tap{|x| x.insert(index, Grammar.sexpr(what)) }
50
+ end
51
+
52
+ def with_push(*sexprs)
53
+ dup.push(*sexprs)
54
+ end
55
+
56
+ def each_child(skip = 0)
57
+ each_with_index do |c,i|
58
+ next if i <= skip
59
+ yield(c, i - 1)
60
+ end
61
+ end
62
+
63
+ def flatten
64
+ Processor::Flatten.new(nil).call(self)
65
+ end
66
+
67
+ private
68
+
69
+ def find_child(kind = nil, &search)
70
+ if search.nil? and kind
71
+ search = ->(x){ x.is_a?(Array) && x.first == kind }
72
+ end
73
+ each_child do |child|
74
+ return child if search.call(child)
75
+ end
76
+ nil
77
+ end
78
+
79
+ def find_child_index(kind)
80
+ each_with_index do |child,index|
81
+ return index if child.is_a?(Array) && child.first == kind
82
+ end
83
+ nil
84
+ end
85
+
86
+ def sql_parenthesized(buffer)
87
+ buffer << LEFT_PARENTHESE
88
+ yield(buffer)
89
+ buffer << RIGHT_PARENTHESE
90
+ end
91
+
92
+ end # module Expr
93
+ end # module Sql
94
+ end # module Bmg
@@ -0,0 +1,24 @@
1
+ module Bmg
2
+ module Sql
3
+ module FromClause
4
+ include Expr
5
+
6
+ FROM = "FROM".freeze
7
+
8
+ def table_spec
9
+ last
10
+ end
11
+
12
+ def join?
13
+ table_spec.join?
14
+ end
15
+
16
+ def to_sql(buffer, dialect)
17
+ buffer << FROM << SPACE
18
+ last.to_sql(buffer, dialect)
19
+ buffer
20
+ end
21
+
22
+ end # module FromClause
23
+ end # module Sql
24
+ end # module Bmg
@@ -0,0 +1,37 @@
1
+ module Bmg
2
+ module Sql
3
+ module InnerJoin
4
+ include Expr
5
+
6
+ INNER = "INNER".freeze
7
+ JOIN = "JOIN".freeze
8
+ ON = "ON".freeze
9
+
10
+ def join?
11
+ true
12
+ end
13
+
14
+ def left
15
+ self[1]
16
+ end
17
+
18
+ def right
19
+ self[2]
20
+ end
21
+
22
+ def predicate
23
+ last
24
+ end
25
+
26
+ def to_sql(buffer, dialect)
27
+ left.to_sql(buffer, dialect)
28
+ buffer << SPACE << JOIN << SPACE
29
+ right.to_sql(buffer, dialect)
30
+ buffer << SPACE << ON << SPACE
31
+ predicate.to_sql(buffer, dialect)
32
+ buffer
33
+ end
34
+
35
+ end # module InnerJoin
36
+ end # module Sql
37
+ end # module Bmg