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.
- 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
|