bmg 0.10.1 → 0.11.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 +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
|