bmg 0.9.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bmg/algebra.rb +2 -26
- data/lib/bmg/algebra/shortcuts.rb +14 -0
- data/lib/bmg/operator/autowrap.rb +32 -2
- data/lib/bmg/operator/constants.rb +12 -0
- data/lib/bmg/operator/image.rb +10 -0
- data/lib/bmg/operator/rename.rb +8 -0
- data/lib/bmg/relation/spied.rb +4 -9
- data/lib/bmg/sequel.rb +53 -2
- data/lib/bmg/sequel/relation.rb +24 -19
- data/lib/bmg/sequel/translator.rb +153 -0
- data/lib/bmg/sequel/type_inference.rb +42 -0
- data/lib/bmg/sql.rb +20 -0
- data/lib/bmg/sql/builder.rb +177 -0
- data/lib/bmg/sql/dialect.rb +15 -0
- data/lib/bmg/sql/ext/predicate.rb +23 -0
- data/lib/bmg/sql/ext/predicate/and.rb +9 -0
- data/lib/bmg/sql/ext/predicate/contradiction.rb +10 -0
- data/lib/bmg/sql/ext/predicate/dyadic_comp.rb +12 -0
- data/lib/bmg/sql/ext/predicate/eq.rb +9 -0
- data/lib/bmg/sql/ext/predicate/exists.rb +12 -0
- data/lib/bmg/sql/ext/predicate/expr.rb +18 -0
- data/lib/bmg/sql/ext/predicate/gt.rb +9 -0
- data/lib/bmg/sql/ext/predicate/gte.rb +9 -0
- data/lib/bmg/sql/ext/predicate/identifier.rb +10 -0
- data/lib/bmg/sql/ext/predicate/in.rb +29 -0
- data/lib/bmg/sql/ext/predicate/literal.rb +10 -0
- data/lib/bmg/sql/ext/predicate/lt.rb +9 -0
- data/lib/bmg/sql/ext/predicate/lte.rb +9 -0
- data/lib/bmg/sql/ext/predicate/nadic_bool.rb +16 -0
- data/lib/bmg/sql/ext/predicate/native.rb +9 -0
- data/lib/bmg/sql/ext/predicate/neq.rb +9 -0
- data/lib/bmg/sql/ext/predicate/not.rb +12 -0
- data/lib/bmg/sql/ext/predicate/or.rb +9 -0
- data/lib/bmg/sql/ext/predicate/qualified_identifier.rb +12 -0
- data/lib/bmg/sql/ext/predicate/tautology.rb +10 -0
- data/lib/bmg/sql/grammar.rb +45 -0
- data/lib/bmg/sql/grammar.sexp.yml +96 -0
- data/lib/bmg/sql/nodes/column_name.rb +25 -0
- data/lib/bmg/sql/nodes/cross_join.rb +28 -0
- data/lib/bmg/sql/nodes/except.rb +14 -0
- data/lib/bmg/sql/nodes/expr.rb +94 -0
- data/lib/bmg/sql/nodes/from_clause.rb +24 -0
- data/lib/bmg/sql/nodes/inner_join.rb +37 -0
- data/lib/bmg/sql/nodes/intersect.rb +14 -0
- data/lib/bmg/sql/nodes/limit_clause.rb +19 -0
- data/lib/bmg/sql/nodes/literal.rb +18 -0
- data/lib/bmg/sql/nodes/name_intro.rb +23 -0
- data/lib/bmg/sql/nodes/native_table_as.rb +31 -0
- data/lib/bmg/sql/nodes/offset_clause.rb +19 -0
- data/lib/bmg/sql/nodes/order_by_clause.rb +25 -0
- data/lib/bmg/sql/nodes/order_by_term.rb +30 -0
- data/lib/bmg/sql/nodes/qualified_name.rb +32 -0
- data/lib/bmg/sql/nodes/range_var_name.rb +17 -0
- data/lib/bmg/sql/nodes/select_exp.rb +109 -0
- data/lib/bmg/sql/nodes/select_item.rb +37 -0
- data/lib/bmg/sql/nodes/select_list.rb +35 -0
- data/lib/bmg/sql/nodes/select_star.rb +22 -0
- data/lib/bmg/sql/nodes/set_operator.rb +68 -0
- data/lib/bmg/sql/nodes/set_quantifier.rb +20 -0
- data/lib/bmg/sql/nodes/subquery_as.rb +28 -0
- data/lib/bmg/sql/nodes/table_as.rb +31 -0
- data/lib/bmg/sql/nodes/table_name.rb +17 -0
- data/lib/bmg/sql/nodes/union.rb +14 -0
- data/lib/bmg/sql/nodes/where_clause.rb +20 -0
- data/lib/bmg/sql/nodes/with_exp.rb +51 -0
- data/lib/bmg/sql/nodes/with_spec.rb +24 -0
- data/lib/bmg/sql/processor.rb +85 -0
- data/lib/bmg/sql/processor/all.rb +17 -0
- data/lib/bmg/sql/processor/clip.rb +57 -0
- data/lib/bmg/sql/processor/distinct.rb +17 -0
- data/lib/bmg/sql/processor/flatten.rb +24 -0
- data/lib/bmg/sql/processor/from_self.rb +29 -0
- data/lib/bmg/sql/processor/join.rb +80 -0
- data/lib/bmg/sql/processor/join_support.rb +28 -0
- data/lib/bmg/sql/processor/limit_offset.rb +30 -0
- data/lib/bmg/sql/processor/merge.rb +49 -0
- data/lib/bmg/sql/processor/order_by.rb +32 -0
- data/lib/bmg/sql/processor/rename.rb +25 -0
- data/lib/bmg/sql/processor/reorder.rb +21 -0
- data/lib/bmg/sql/processor/requalify.rb +24 -0
- data/lib/bmg/sql/processor/semi_join.rb +68 -0
- data/lib/bmg/sql/processor/star.rb +17 -0
- data/lib/bmg/sql/processor/where.rb +25 -0
- data/lib/bmg/sql/relation.rb +141 -0
- data/lib/bmg/sql/version.rb +16 -0
- data/lib/bmg/support.rb +1 -0
- data/lib/bmg/support/keys.rb +59 -0
- data/lib/bmg/type.rb +95 -14
- data/lib/bmg/version.rb +2 -2
- data/tasks/test.rake +9 -2
- metadata +97 -5
@@ -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,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,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
|