bmg 0.10.1 → 0.11.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 +9 -0
- data/lib/bmg/algebra/shortcuts.rb +16 -0
- data/lib/bmg/operator.rb +1 -0
- data/lib/bmg/operator/join.rb +59 -0
- data/lib/bmg/operator/matching.rb +1 -1
- data/lib/bmg/sql/processor/join.rb +4 -3
- data/lib/bmg/sql/relation.rb +11 -0
- data/lib/bmg/support/keys.rb +19 -0
- data/lib/bmg/type.rb +23 -1
- data/lib/bmg/version.rb +2 -2
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31a0ebe96dae3801143c423e0b014bc9dee902b9
|
4
|
+
data.tar.gz: 6c4c003b7af5154301bf64f68f12e2bd7ab880f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acaf31901fc7b3da45dfce9d7e1e23f1fe4ca86437db8c954538e3817fb4f4297825177ceb77d2fba60afabbb57e199fd0e932b1e944c5a750882c568fe0ea48
|
7
|
+
data.tar.gz: b27cd4e4d9132ac73a5fa27b0e03fa6badd197283b369aab9a463519df3b3f5092e3a669c856528063baa7f2a7eadc98c72aadd2a2a11b40f0a9614f0793c9cf
|
data/lib/bmg/algebra.rb
CHANGED
@@ -64,6 +64,15 @@ module Bmg
|
|
64
64
|
end
|
65
65
|
protected :_image
|
66
66
|
|
67
|
+
def join(right, on = [])
|
68
|
+
_join self.type.join(right.type, on), right, on
|
69
|
+
end
|
70
|
+
|
71
|
+
def _join(type, right, on)
|
72
|
+
Operator::Join.new(type, self, right, on)
|
73
|
+
end
|
74
|
+
protected :_join
|
75
|
+
|
67
76
|
def matching(right, on = [])
|
68
77
|
_matching self.type.matching(right, on), right, on
|
69
78
|
end
|
@@ -9,6 +9,22 @@ module Bmg
|
|
9
9
|
self.restrict(predicate)
|
10
10
|
end
|
11
11
|
|
12
|
+
def prefix(prefix)
|
13
|
+
raise "Attrlist must be known to use `prefix`" unless self.type.knows_attrlist?
|
14
|
+
renaming = self.type.to_attrlist.each_with_object({}){|a,r|
|
15
|
+
r[a] = :"#{prefix}#{a}"
|
16
|
+
}
|
17
|
+
self.rename(renaming)
|
18
|
+
end
|
19
|
+
|
20
|
+
def suffix(suffix)
|
21
|
+
raise "Attrlist must be known to use `suffix`" unless self.type.knows_attrlist?
|
22
|
+
renaming = self.type.to_attrlist.each_with_object({}){|a,r|
|
23
|
+
r[a] = :"#{a}#{suffix}"
|
24
|
+
}
|
25
|
+
self.rename(renaming)
|
26
|
+
end
|
27
|
+
|
12
28
|
end # module Shortcuts
|
13
29
|
end # module Algebra
|
14
30
|
end # module Bmg
|
data/lib/bmg/operator.rb
CHANGED
@@ -72,6 +72,7 @@ require_relative 'operator/constants'
|
|
72
72
|
require_relative 'operator/extend'
|
73
73
|
require_relative 'operator/group'
|
74
74
|
require_relative 'operator/image'
|
75
|
+
require_relative 'operator/join'
|
75
76
|
require_relative 'operator/matching'
|
76
77
|
require_relative 'operator/page'
|
77
78
|
require_relative 'operator/project'
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Operator
|
3
|
+
#
|
4
|
+
# Join operator.
|
5
|
+
#
|
6
|
+
# Natural join, following relational algebra
|
7
|
+
#
|
8
|
+
class Join
|
9
|
+
include Operator::Binary
|
10
|
+
|
11
|
+
def initialize(type, left, right, on)
|
12
|
+
@type = type
|
13
|
+
@left = left
|
14
|
+
@right = right
|
15
|
+
@on = on
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :on
|
21
|
+
|
22
|
+
public
|
23
|
+
|
24
|
+
def each
|
25
|
+
index = Hash.new
|
26
|
+
right.each_with_object(index) do |t, index|
|
27
|
+
key = tuple_project(t, on)
|
28
|
+
index[key] ||= []
|
29
|
+
index[key] << t
|
30
|
+
end
|
31
|
+
left.each do |tuple|
|
32
|
+
key = tuple_project(tuple, on)
|
33
|
+
if to_join = index[key]
|
34
|
+
to_join.each do |right|
|
35
|
+
yield right.merge(tuple)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_ast
|
42
|
+
[ :join, left.to_ast, right.to_ast, on ]
|
43
|
+
end
|
44
|
+
|
45
|
+
protected ### inspect
|
46
|
+
|
47
|
+
def args
|
48
|
+
[ on ]
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def tuple_project(tuple, on)
|
54
|
+
TupleAlgebra.project(tuple, on)
|
55
|
+
end
|
56
|
+
|
57
|
+
end # class Join
|
58
|
+
end # module Operator
|
59
|
+
end # module Bmg
|
@@ -4,11 +4,12 @@ module Bmg
|
|
4
4
|
class Join < Processor
|
5
5
|
include JoinSupport
|
6
6
|
|
7
|
-
def initialize(right, builder)
|
7
|
+
def initialize(right, on, builder)
|
8
8
|
super(builder)
|
9
9
|
@right = right
|
10
|
+
@on = on
|
10
11
|
end
|
11
|
-
attr_reader :right
|
12
|
+
attr_reader :right, :on
|
12
13
|
|
13
14
|
def call(sexpr)
|
14
15
|
if unjoinable?(sexpr)
|
@@ -50,7 +51,7 @@ module Bmg
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def join_from_clauses(left, right)
|
53
|
-
joincon = join_predicate(left, right)
|
54
|
+
joincon = join_predicate(left, right, on)
|
54
55
|
join = if joincon.tautology?
|
55
56
|
[:cross_join, left.table_spec, right.table_spec]
|
56
57
|
else
|
data/lib/bmg/sql/relation.rb
CHANGED
@@ -44,6 +44,17 @@ module Bmg
|
|
44
44
|
_instance(type, builder, expr)
|
45
45
|
end
|
46
46
|
|
47
|
+
def _join(type, right, on)
|
48
|
+
if right_expr = extract_compatible_sexpr(right)
|
49
|
+
right_expr = Processor::Requalify.new(builder).call(right_expr)
|
50
|
+
expr = before_use(self.expr)
|
51
|
+
expr = Processor::Join.new(right_expr, on, builder).call(expr)
|
52
|
+
_instance(type, builder, expr)
|
53
|
+
else
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
47
58
|
def _matching(type, right, on)
|
48
59
|
if right_expr = extract_compatible_sexpr(right)
|
49
60
|
expr = before_use(self.expr)
|
data/lib/bmg/support/keys.rb
CHANGED
@@ -15,12 +15,31 @@ module Bmg
|
|
15
15
|
Keys.new(keys, false)
|
16
16
|
end
|
17
17
|
|
18
|
+
def autowrap(oldtype, newtype, options)
|
19
|
+
sep = options[:split] || Operator::Autowrap::DEFAULT_OPTIONS[:split]
|
20
|
+
keys = @keys.map{|k|
|
21
|
+
k.map{|a| a.to_s.split(sep).first }.uniq.map(&:to_sym)
|
22
|
+
}
|
23
|
+
Keys.new(keys, false)
|
24
|
+
end
|
25
|
+
|
18
26
|
def group(oldtype, newtype, attrs, as)
|
19
27
|
keys = [ oldtype.attrlist - attrs ]
|
20
28
|
keys += @keys.map{|k| (k & attrs).empty? ? k : (k - attrs) + [as] }
|
21
29
|
Keys.new(keys, true)
|
22
30
|
end
|
23
31
|
|
32
|
+
def join(oldtype, newtype, right_type, on)
|
33
|
+
return nil unless rkeys = right_type.keys
|
34
|
+
keys = []
|
35
|
+
@keys.each do |k1|
|
36
|
+
right_type.keys.each do |k2|
|
37
|
+
keys << (k1 + k2).uniq
|
38
|
+
end
|
39
|
+
end
|
40
|
+
Keys.new(keys, true)
|
41
|
+
end
|
42
|
+
|
24
43
|
def project(oldtype, newtype, attrlist)
|
25
44
|
keys = @keys.select{|k| k.all?{|a| attrlist.include?(a) } }
|
26
45
|
keys = [newtype.attrlist] if keys.empty?
|
data/lib/bmg/type.rb
CHANGED
@@ -13,6 +13,12 @@ module Bmg
|
|
13
13
|
attr_accessor :predicate
|
14
14
|
protected :predicate=
|
15
15
|
|
16
|
+
def with_predicate(predicate)
|
17
|
+
dup.tap{|x|
|
18
|
+
x.predicate = predicate
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
16
22
|
public ## attrlist
|
17
23
|
|
18
24
|
attr_accessor :attrlist
|
@@ -71,7 +77,15 @@ module Bmg
|
|
71
77
|
end
|
72
78
|
|
73
79
|
def autowrap(options)
|
74
|
-
|
80
|
+
sep = options[:split] || Operator::Autowrap::DEFAULT_OPTIONS[:split]
|
81
|
+
splitter = ->(a){ a.to_s.split(sep).first }
|
82
|
+
is_split = ->(a){ a.to_s.split(sep).size > 1 }
|
83
|
+
dup.tap{|x|
|
84
|
+
x.attrlist = self.attrlist.map(&splitter).uniq.map(&:to_sym) if knows_attrlist?
|
85
|
+
x.keys = self._keys.autowrap(self, x, options) if knows_keys?
|
86
|
+
autowrapped = self.predicate.free_variables.select(&is_split)
|
87
|
+
x.predicate = autowrapped.empty? ? self.predicate : self.predicate.and_split(autowrapped).last
|
88
|
+
}
|
75
89
|
end
|
76
90
|
|
77
91
|
def autosummarize(by, summarization)
|
@@ -110,6 +124,14 @@ module Bmg
|
|
110
124
|
}
|
111
125
|
end
|
112
126
|
|
127
|
+
def join(right, on)
|
128
|
+
dup.tap{|x|
|
129
|
+
x.attrlist = (knows_attrlist? and right.knows_attrlist?) ? (self.attrlist + right.attrlist).uniq : nil
|
130
|
+
x.predicate = self.predicate & right.predicate
|
131
|
+
x.keys = (knows_keys? and right.knows_keys?) ? self._keys.join(self, x, right, on) : nil
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
113
135
|
def matching(right, on)
|
114
136
|
self
|
115
137
|
end
|
data/lib/bmg/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/bmg/operator/extend.rb
|
132
132
|
- lib/bmg/operator/group.rb
|
133
133
|
- lib/bmg/operator/image.rb
|
134
|
+
- lib/bmg/operator/join.rb
|
134
135
|
- lib/bmg/operator/matching.rb
|
135
136
|
- lib/bmg/operator/page.rb
|
136
137
|
- lib/bmg/operator/project.rb
|