bmg 0.9.1 → 0.10.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.
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