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,17 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Distinct < Processor
|
5
|
+
|
6
|
+
def on_set_quantified(sexpr)
|
7
|
+
sexpr.with_update(1, builder.distinct)
|
8
|
+
end
|
9
|
+
alias :on_union :on_set_quantified
|
10
|
+
alias :on_except :on_set_quantified
|
11
|
+
alias :on_intersect :on_set_quantified
|
12
|
+
alias :on_select_exp :on_set_quantified
|
13
|
+
|
14
|
+
end # class Distinct
|
15
|
+
end # class Processor
|
16
|
+
end # module Sql
|
17
|
+
end # module Bmg
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Flatten < Processor
|
5
|
+
|
6
|
+
def on_with_exp(sexpr)
|
7
|
+
@subqueries = sexpr.with_spec.to_hash
|
8
|
+
apply(sexpr.select_exp)
|
9
|
+
end
|
10
|
+
attr_reader :subqueries
|
11
|
+
|
12
|
+
alias :on_select_exp :copy_and_apply
|
13
|
+
alias :on_missing :copy_and_apply
|
14
|
+
|
15
|
+
def on_table_as(sexpr)
|
16
|
+
return sexpr unless subqueries
|
17
|
+
return sexpr unless subquery = subqueries[sexpr.table_name]
|
18
|
+
[ :subquery_as, apply(subquery), sexpr.right ]
|
19
|
+
end
|
20
|
+
|
21
|
+
end # class Flatten
|
22
|
+
end # class Processor
|
23
|
+
end # module Sql
|
24
|
+
end # module Bmg
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class FromSelf < Processor
|
5
|
+
|
6
|
+
def on_with_exp(sexpr)
|
7
|
+
q = builder.next_qualifier!
|
8
|
+
name_intro = builder.name_intro(q, sexpr.select_exp)
|
9
|
+
[ :with_exp,
|
10
|
+
sexpr.with_spec.dup.push(name_intro),
|
11
|
+
builder.select_all(sexpr.select_exp, q, q) ]
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_nonjoin_exp(sexpr)
|
15
|
+
q = builder.next_qualifier!
|
16
|
+
[ :with_exp,
|
17
|
+
[:with_spec,
|
18
|
+
builder.name_intro(q, sexpr)],
|
19
|
+
builder.select_all(sexpr, q, q) ]
|
20
|
+
end
|
21
|
+
alias :on_union :on_nonjoin_exp
|
22
|
+
alias :on_except :on_nonjoin_exp
|
23
|
+
alias :on_intersect :on_nonjoin_exp
|
24
|
+
alias :on_select_exp :on_nonjoin_exp
|
25
|
+
|
26
|
+
end # class FromSelf
|
27
|
+
end # class Processor
|
28
|
+
end # module Sql
|
29
|
+
end # module Bmg
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Join < Processor
|
5
|
+
include JoinSupport
|
6
|
+
|
7
|
+
def initialize(right, builder)
|
8
|
+
super(builder)
|
9
|
+
@right = right
|
10
|
+
end
|
11
|
+
attr_reader :right
|
12
|
+
|
13
|
+
def call(sexpr)
|
14
|
+
if unjoinable?(sexpr)
|
15
|
+
call(builder.from_self(sexpr))
|
16
|
+
elsif unjoinable?(right)
|
17
|
+
Join.new(builder.from_self(right), builder).call(sexpr)
|
18
|
+
else
|
19
|
+
super(sexpr)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def apply_join_strategy(left, right)
|
26
|
+
[ :select_exp,
|
27
|
+
join_set_quantifiers(left, right),
|
28
|
+
join_select_lists(left, right),
|
29
|
+
join_from_clauses(left, right),
|
30
|
+
join_where_clauses(left, right),
|
31
|
+
join_order_by_clauses(left, right) ].compact
|
32
|
+
end
|
33
|
+
|
34
|
+
def unjoinable?(sexpr)
|
35
|
+
sexpr.set_operator? or sexpr.limit_or_offset? or sexpr.join?
|
36
|
+
end
|
37
|
+
|
38
|
+
def join_set_quantifiers(left, right)
|
39
|
+
left_q, right_q = left.set_quantifier, right.set_quantifier
|
40
|
+
left_q == right_q ? left_q : builder.distinct
|
41
|
+
end
|
42
|
+
|
43
|
+
def join_select_lists(left, right)
|
44
|
+
left_list, right_list = left.select_list, right.select_list
|
45
|
+
list = left_list.dup
|
46
|
+
right_list.each_child do |child, index|
|
47
|
+
list << child unless left_list.knows?(child.as_name)
|
48
|
+
end
|
49
|
+
list
|
50
|
+
end
|
51
|
+
|
52
|
+
def join_from_clauses(left, right)
|
53
|
+
joincon = join_predicate(left, right)
|
54
|
+
join = if joincon.tautology?
|
55
|
+
[:cross_join, left.table_spec, right.table_spec]
|
56
|
+
else
|
57
|
+
[:inner_join, left.table_spec, right.table_spec, joincon]
|
58
|
+
end
|
59
|
+
left.from_clause.with_update(-1, join)
|
60
|
+
end
|
61
|
+
|
62
|
+
def join_where_clauses(left, right)
|
63
|
+
predicate = [ tautology, left.predicate, right.predicate ].compact
|
64
|
+
case predicate.size
|
65
|
+
when 1 then nil
|
66
|
+
when 2 then [ :where_clause, predicate.last ]
|
67
|
+
else [ :where_clause, predicate.reduce(:&) ]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def join_order_by_clauses(left, right)
|
72
|
+
order_by = [ left.order_by_clause, right.order_by_clause ].compact
|
73
|
+
return order_by.first if order_by.size <= 1
|
74
|
+
order_by.first + order_by.last.sexpr_body
|
75
|
+
end
|
76
|
+
|
77
|
+
end # class Join
|
78
|
+
end # class Processor
|
79
|
+
end # module Sql
|
80
|
+
end # module Bmg
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
module JoinSupport
|
5
|
+
|
6
|
+
def on_main_exp(sexpr)
|
7
|
+
joined = apply_join_strategy(sexpr.select_exp, right.select_exp)
|
8
|
+
merge_with_exps(sexpr, right, joined)
|
9
|
+
end
|
10
|
+
alias :on_with_exp :on_main_exp
|
11
|
+
alias :on_select_exp :on_main_exp
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def join_predicate(left, right, commons)
|
16
|
+
left_d, right_d = left.desaliaser, right.desaliaser
|
17
|
+
commons.to_a.inject(tautology){|cond, attr|
|
18
|
+
left_attr, right_attr = left_d[attr], right_d[attr]
|
19
|
+
left_p = Predicate::Factory.qualified_identifier(left_attr.qualifier, left_attr.as_name)
|
20
|
+
right_p = Predicate::Factory.qualified_identifier(right_attr.qualifier, right_attr.as_name)
|
21
|
+
cond &= Predicate::Factory.eq(left_p, right_p)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
end # class JoinSupport
|
26
|
+
end # class Processor
|
27
|
+
end # module Sql
|
28
|
+
end # module Bmg
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class LimitOffset < Processor
|
5
|
+
|
6
|
+
def initialize(limit, offset, builder)
|
7
|
+
super(builder)
|
8
|
+
@limit = limit
|
9
|
+
@offset = offset
|
10
|
+
end
|
11
|
+
attr_reader :limit, :offset
|
12
|
+
|
13
|
+
def on_set_operator(sexpr)
|
14
|
+
apply(builder.from_self(sexpr))
|
15
|
+
end
|
16
|
+
alias :on_union :on_set_operator
|
17
|
+
alias :on_except :on_set_operator
|
18
|
+
alias :on_intersect :on_set_operator
|
19
|
+
|
20
|
+
def on_select_exp(sexpr)
|
21
|
+
sexpr = builder.from_self(sexpr) if obc = sexpr.limit_or_offset?
|
22
|
+
limit_clause = builder.limit_clause(limit)
|
23
|
+
offset_clause = builder.offset_clause(offset)
|
24
|
+
sexpr.with_push(limit_clause, offset_clause)
|
25
|
+
end
|
26
|
+
|
27
|
+
end # class LimitOffset
|
28
|
+
end # class Processor
|
29
|
+
end # module Sql
|
30
|
+
end # module Bmg
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Merge < Processor
|
5
|
+
|
6
|
+
def initialize(kind, all, right, builder)
|
7
|
+
super(builder)
|
8
|
+
@kind = kind
|
9
|
+
@all = all
|
10
|
+
@right = right
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_with_exp(sexpr)
|
14
|
+
if @right.with_exp?
|
15
|
+
reordered = Reorder.new(sexpr.to_attr_list, builder).call(@right)
|
16
|
+
main = [ @kind, modifier, sexpr.select_exp, reordered.select_exp ]
|
17
|
+
merge_with_exps(sexpr, reordered, main)
|
18
|
+
else
|
19
|
+
[ :with_exp,
|
20
|
+
sexpr.with_spec,
|
21
|
+
apply(sexpr.last) ]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_nonjoin_exp(sexpr)
|
26
|
+
reordered = Reorder.new(sexpr.to_attr_list, builder).call(@right)
|
27
|
+
if @right.with_exp?
|
28
|
+
[ :with_exp,
|
29
|
+
reordered.with_spec,
|
30
|
+
[ @kind, modifier, sexpr, reordered.select_exp ] ]
|
31
|
+
else
|
32
|
+
[ @kind, modifier, sexpr, reordered ]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
alias :on_union :on_nonjoin_exp
|
36
|
+
alias :on_except :on_nonjoin_exp
|
37
|
+
alias :on_intersect :on_nonjoin_exp
|
38
|
+
alias :on_select_exp :on_nonjoin_exp
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def modifier
|
43
|
+
@all ? builder.all : builder.distinct
|
44
|
+
end
|
45
|
+
|
46
|
+
end # class Merge
|
47
|
+
end # class Processor
|
48
|
+
end # module Sql
|
49
|
+
end # module Bmg
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class OrderBy < Processor
|
5
|
+
|
6
|
+
def initialize(ordering, builder)
|
7
|
+
super(builder)
|
8
|
+
@ordering = ordering
|
9
|
+
end
|
10
|
+
attr_reader :ordering
|
11
|
+
|
12
|
+
def on_set_operator(sexpr)
|
13
|
+
call(builder.from_self(sexpr))
|
14
|
+
end
|
15
|
+
alias :on_union :on_set_operator
|
16
|
+
alias :on_except :on_set_operator
|
17
|
+
alias :on_intersect :on_set_operator
|
18
|
+
|
19
|
+
def on_select_exp(sexpr)
|
20
|
+
if obc = sexpr.order_by_clause
|
21
|
+
sexpr = builder.from_self(sexpr)
|
22
|
+
call(sexpr)
|
23
|
+
else
|
24
|
+
needed = builder.order_by_clause(ordering, &sexpr.desaliaser)
|
25
|
+
sexpr.dup.push(needed)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class OrderBy
|
30
|
+
end # class Processor
|
31
|
+
end # module Sql
|
32
|
+
end # module Bmg
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Rename < Processor
|
5
|
+
|
6
|
+
def initialize(renaming, builder)
|
7
|
+
super(builder)
|
8
|
+
@renaming = renaming
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_select_list(sexpr)
|
12
|
+
sexpr.each_with_index.map{|child,index|
|
13
|
+
index == 0 ? child : apply(child)
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_select_item(sexpr)
|
18
|
+
return sexpr unless newname = @renaming[sexpr.as_name.to_sym]
|
19
|
+
builder.select_item(sexpr.qualifier, sexpr.would_be_name, newname.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
end # class Rename
|
23
|
+
end # class Processor
|
24
|
+
end # module Sql
|
25
|
+
end # module Bmg
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Reorder < Processor
|
5
|
+
|
6
|
+
def initialize(attr_list, builder)
|
7
|
+
super(builder)
|
8
|
+
@indexes = Hash[attr_list.to_a.map(&:to_s).each_with_index.to_a]
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_select_list(sexpr)
|
12
|
+
reordered = sexpr.sexpr_body.sort{|i1,i2|
|
13
|
+
@indexes[i1.as_name] <=> @indexes[i2.as_name]
|
14
|
+
}
|
15
|
+
reordered.unshift(:select_list)
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class Reorder
|
19
|
+
end # class Processor
|
20
|
+
end # module Sql
|
21
|
+
end # module Bmg
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Requalify < Processor
|
5
|
+
|
6
|
+
def initialize(builder)
|
7
|
+
super
|
8
|
+
@requalify = Hash.new{|h,k|
|
9
|
+
h[k] = Grammar.sexpr [:range_var_name, builder.next_qualifier!]
|
10
|
+
}
|
11
|
+
end
|
12
|
+
attr_reader :requalify
|
13
|
+
|
14
|
+
alias :on_select_exp :copy_and_apply
|
15
|
+
alias :on_missing :copy_and_apply
|
16
|
+
|
17
|
+
def on_range_var_name(sexpr)
|
18
|
+
requalify[sexpr]
|
19
|
+
end
|
20
|
+
|
21
|
+
end # class Requalify
|
22
|
+
end # class Processor
|
23
|
+
end # module Sql
|
24
|
+
end # module Bmg
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class SemiJoin < Processor
|
5
|
+
include JoinSupport
|
6
|
+
|
7
|
+
def initialize(right, on, negate = false, builder)
|
8
|
+
super(builder)
|
9
|
+
@right = right
|
10
|
+
@on = on
|
11
|
+
@negate = negate
|
12
|
+
end
|
13
|
+
attr_reader :right, :on, :negate
|
14
|
+
|
15
|
+
def call(sexpr)
|
16
|
+
if sexpr.set_operator?
|
17
|
+
call(builder.from_self(sexpr))
|
18
|
+
elsif right.set_operator?
|
19
|
+
SemiJoin.new(builder.from_self(right), negate, builder).call(sexpr)
|
20
|
+
else
|
21
|
+
super(sexpr)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def apply_join_strategy(left, right)
|
28
|
+
predicate = build_semijoin_predicate(left, right)
|
29
|
+
expand_where_clause(left, negate ? !predicate : predicate)
|
30
|
+
end
|
31
|
+
|
32
|
+
def build_semijoin_predicate(left, right)
|
33
|
+
if right.is_table_dee?
|
34
|
+
right.where_clause.predicate
|
35
|
+
else
|
36
|
+
commons = self.on
|
37
|
+
subquery = Clip.new(commons, false, :star, builder).call(right)
|
38
|
+
subquery = Requalify.new(builder).call(subquery)
|
39
|
+
if commons.size == 0
|
40
|
+
builder.exists(subquery)
|
41
|
+
elsif commons.size == 1
|
42
|
+
identifier = left.desaliaser[commons.to_a.first]
|
43
|
+
Predicate::Factory.in(identifier, subquery)
|
44
|
+
else
|
45
|
+
join_pre = join_predicate(left, subquery, commons)
|
46
|
+
subquery = expand_where_clause(subquery, join_pre)
|
47
|
+
subquery = Star.new(builder).call(subquery)
|
48
|
+
builder.exists(subquery)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def expand_where_clause(sexpr, predicate)
|
54
|
+
Grammar.sexpr \
|
55
|
+
[ :select_exp,
|
56
|
+
sexpr.set_quantifier,
|
57
|
+
sexpr.select_list,
|
58
|
+
sexpr.from_clause,
|
59
|
+
[ :where_clause, (sexpr.predicate || tautology) & predicate ],
|
60
|
+
sexpr.order_by_clause,
|
61
|
+
sexpr.limit_clause,
|
62
|
+
sexpr.offset_clause ].compact
|
63
|
+
end
|
64
|
+
|
65
|
+
end # class SemiJoin
|
66
|
+
end # class Processor
|
67
|
+
end # module Sql
|
68
|
+
end # module Bmg
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Star < Processor
|
5
|
+
|
6
|
+
def on_select_exp(sexpr)
|
7
|
+
if sexpr.from_clause
|
8
|
+
sexpr.with_update(:select_list, builder.select_star)
|
9
|
+
else
|
10
|
+
sexpr
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end # class Star
|
15
|
+
end # class Processor
|
16
|
+
end # module Sql
|
17
|
+
end # module Bmg
|