bmg 0.16.7 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/lib/bmg/operator/image.rb +120 -9
- data/lib/bmg/operator/restrict.rb +4 -0
- data/lib/bmg/operator/shared/binary.rb +12 -1
- data/lib/bmg/operator/shared/nary.rb +9 -1
- data/lib/bmg/operator/shared/unary.rb +9 -1
- data/lib/bmg/relation.rb +4 -0
- data/lib/bmg/sequel/translator.rb +1 -1
- data/lib/bmg/sql/processor.rb +1 -0
- data/lib/bmg/sql/processor/bind.rb +23 -0
- data/lib/bmg/sql/processor/requalify.rb +1 -1
- data/lib/bmg/sql/relation.rb +6 -0
- data/lib/bmg/version.rb +2 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d94c440e4e3c70b16735c6d31e3ba50a4be12430d347d9ac8cff6622bc64fb3
|
4
|
+
data.tar.gz: 1443c66b0c1c621f97b2f2f8bea2c522c07151ec4bbef71b45585078635c5b7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7eba5332a684097f8cd95a1c28463bbb1e5b004788bf3b3133a55a0c1cf1b5b5335a41924b9ba98cae10fe81f2c4b0ad70bb27d4f97618a8d18a7dbc0f48265f
|
7
|
+
data.tar.gz: 0241a9d8b895ca70df1a7f705ceecce062369810a8b4f60e1f314db0ab2888dc0060ad2f37697b7c83ab11cd2eaefd13e8445d1486d9827f294766bd9f3471aa
|
data/Gemfile
CHANGED
data/lib/bmg/operator/image.rb
CHANGED
@@ -12,7 +12,21 @@ module Bmg
|
|
12
12
|
|
13
13
|
# Whether we need to convert each image as an Array,
|
14
14
|
# instead of keeping a Relation instance
|
15
|
-
array: false
|
15
|
+
array: false,
|
16
|
+
|
17
|
+
# The strategy to use for actual image algorithm. Default is
|
18
|
+
# :refilter_right. Possible values are:
|
19
|
+
#
|
20
|
+
# - :index_right : builds a memory index with tuples from right, then
|
21
|
+
# passes left tuples and joins them with the index values.
|
22
|
+
#
|
23
|
+
# - :refilter_right : the left operand is materialized and all
|
24
|
+
# distinct values collected. The right operand is lately restricted
|
25
|
+
# to only those matching values. :index_right is then applied on
|
26
|
+
# resulting operabds. This option only applies when (optimized) `on`
|
27
|
+
# contains one attribute only. ; it fallbacks on :index_right
|
28
|
+
# otherwise.
|
29
|
+
strategy: :refilter_right
|
16
30
|
|
17
31
|
}
|
18
32
|
|
@@ -31,7 +45,55 @@ module Bmg
|
|
31
45
|
|
32
46
|
public
|
33
47
|
|
34
|
-
def each
|
48
|
+
def each(*args, &bl)
|
49
|
+
(options[:jit_optimized] ? self : jit_optimize)._each(*args, &bl)
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_ast
|
53
|
+
[ :image, left.to_ast, right.to_ast, as, on, options.dup ]
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def _each(*args, &bl)
|
59
|
+
case s = options[:strategy]
|
60
|
+
when :index_right then _each_index_right(*args, &bl)
|
61
|
+
when :refilter_right then _each_refilter_right(*args, &bl)
|
62
|
+
else
|
63
|
+
raise ArgumentError, "Unknown strategy `#{s}`"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def _each_index_right(*args, &bl)
|
68
|
+
left_rel, right_rel = self.left, self.right
|
69
|
+
_each_implem(left_rel, right_rel, *args, &bl)
|
70
|
+
end
|
71
|
+
|
72
|
+
def _each_refilter_right(*args, &bl)
|
73
|
+
left_rel, right_rel = self.left, self.right
|
74
|
+
|
75
|
+
# find matching keys on left and rebind the right
|
76
|
+
# placeholder to them
|
77
|
+
values = left_rel.map{|t| t[on.first] }
|
78
|
+
placeholder = options[:refilter_right][:placeholder]
|
79
|
+
right_rel = right_rel.bind(placeholder => values)
|
80
|
+
|
81
|
+
_each_implem(left_rel, right_rel, *args, &bl)
|
82
|
+
end
|
83
|
+
|
84
|
+
def _each_implem(left_rel, right_rel, *args)
|
85
|
+
# build right index
|
86
|
+
index = build_right_index(right_rel)
|
87
|
+
|
88
|
+
# each left with image from right index
|
89
|
+
left_rel.each do |tuple|
|
90
|
+
key = tuple_project(tuple, on)
|
91
|
+
image = index[key] || (options[:array] ? [] : empty_image)
|
92
|
+
yield tuple.merge(as => image)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_right_index(right)
|
35
97
|
index = Hash.new{|h,k| h[k] = empty_image }
|
36
98
|
right.each_with_object(index) do |t, index|
|
37
99
|
key = tuple_project(t, on)
|
@@ -42,15 +104,54 @@ module Bmg
|
|
42
104
|
ix[k] = v.to_a
|
43
105
|
end
|
44
106
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
107
|
+
index
|
108
|
+
end
|
109
|
+
|
110
|
+
protected ### jit_optimization
|
111
|
+
|
112
|
+
def jit_optimize
|
113
|
+
case s = options[:strategy]
|
114
|
+
when :index_right then jit_index_right
|
115
|
+
when :refilter_right then jit_refilter_right
|
116
|
+
else
|
117
|
+
raise ArgumentError, "Unknown strategy `#{s}`"
|
49
118
|
end
|
50
119
|
end
|
51
120
|
|
52
|
-
def
|
53
|
-
|
121
|
+
def jit_index_right
|
122
|
+
Image.new(
|
123
|
+
type,
|
124
|
+
left,
|
125
|
+
right,
|
126
|
+
as,
|
127
|
+
on,
|
128
|
+
options.merge(jit_optimized: true))
|
129
|
+
end
|
130
|
+
|
131
|
+
def jit_refilter_right
|
132
|
+
ltc = left.type.predicate.constants
|
133
|
+
rtc = right.type.predicate.constants
|
134
|
+
jit_allbut, jit_on = on.partition{|attr|
|
135
|
+
ltc.has_key?(attr) && rtc.has_key?(attr) && ltc[attr] == rtc[attr]
|
136
|
+
}
|
137
|
+
if jit_on.size == 1
|
138
|
+
p = Predicate.placeholder
|
139
|
+
Image.new(
|
140
|
+
type,
|
141
|
+
left.materialize,
|
142
|
+
right.restrict(Predicate.in(jit_on.first, p)).allbut(jit_allbut),
|
143
|
+
as,
|
144
|
+
jit_on,
|
145
|
+
options.merge(jit_optimized: true, refilter_right: { placeholder: p }))
|
146
|
+
else
|
147
|
+
Image.new(
|
148
|
+
type,
|
149
|
+
left,
|
150
|
+
right.allbut(jit_allbut),
|
151
|
+
as,
|
152
|
+
jit_on,
|
153
|
+
options.merge(jit_optimized: true, strategy: :index_right))
|
154
|
+
end
|
54
155
|
end
|
55
156
|
|
56
157
|
protected ### optimization
|
@@ -68,7 +169,7 @@ module Bmg
|
|
68
169
|
def _restrict(type, predicate)
|
69
170
|
on_as, rest = predicate.and_split([as])
|
70
171
|
if rest.tautology?
|
71
|
-
# push
|
172
|
+
# push index_right situation: on_as is still the full predicate
|
72
173
|
super
|
73
174
|
else
|
74
175
|
# rest makes no reference to `as` and can be pushed
|
@@ -126,6 +227,16 @@ module Bmg
|
|
126
227
|
Relation::InMemory.new(image_type, Set.new)
|
127
228
|
end
|
128
229
|
|
230
|
+
public
|
231
|
+
|
232
|
+
def to_s
|
233
|
+
options[:jit_optimized] ? super : jit_optimize.to_s
|
234
|
+
end
|
235
|
+
|
236
|
+
def inspect
|
237
|
+
options[:jit_optimized] ? super : jit_optimize.inspect
|
238
|
+
end
|
239
|
+
|
129
240
|
end # class Project
|
130
241
|
end # module Operator
|
131
242
|
end # module Bmg
|
@@ -3,9 +3,13 @@ module Bmg
|
|
3
3
|
module Binary
|
4
4
|
include Operator
|
5
5
|
|
6
|
+
def bind(binding)
|
7
|
+
_with_operands(left.bind(binding), right.bind(binding))
|
8
|
+
end
|
9
|
+
|
6
10
|
protected
|
7
11
|
|
8
|
-
|
12
|
+
attr_accessor :left, :right
|
9
13
|
|
10
14
|
def _visit(parent, visitor)
|
11
15
|
visitor.call(self, parent)
|
@@ -13,6 +17,13 @@ module Bmg
|
|
13
17
|
right.send(:_visit, self, visitor)
|
14
18
|
end
|
15
19
|
|
20
|
+
def _with_operands(left, right)
|
21
|
+
dup.tap{|d|
|
22
|
+
d.left = left
|
23
|
+
d.right = right
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
16
27
|
def operands
|
17
28
|
[left, right]
|
18
29
|
end
|
@@ -3,9 +3,17 @@ module Bmg
|
|
3
3
|
module Nary
|
4
4
|
include Operator
|
5
5
|
|
6
|
+
def bind(binding)
|
7
|
+
_with_operands(operands.map{|op| op.bind(binding) })
|
8
|
+
end
|
9
|
+
|
6
10
|
protected
|
7
11
|
|
8
|
-
|
12
|
+
attr_accessor :operands
|
13
|
+
|
14
|
+
def _with_operands(operands)
|
15
|
+
dup.tap{|d| d.operands = operands }
|
16
|
+
end
|
9
17
|
|
10
18
|
def _visit(parent, visitor)
|
11
19
|
visitor.call(self, parent)
|
@@ -3,15 +3,23 @@ module Bmg
|
|
3
3
|
module Unary
|
4
4
|
include Operator
|
5
5
|
|
6
|
+
def bind(binding)
|
7
|
+
_with_operand(operand.bind(binding))
|
8
|
+
end
|
9
|
+
|
6
10
|
protected
|
7
11
|
|
8
|
-
|
12
|
+
attr_accessor :operand
|
9
13
|
|
10
14
|
def _visit(parent, visitor)
|
11
15
|
visitor.call(self, parent)
|
12
16
|
operand._visit(self, visitor)
|
13
17
|
end
|
14
18
|
|
19
|
+
def _with_operand(operand)
|
20
|
+
dup.tap{|d| d.operand = operand }
|
21
|
+
end
|
22
|
+
|
15
23
|
def operands
|
16
24
|
[operand]
|
17
25
|
end
|
data/lib/bmg/relation.rb
CHANGED
@@ -50,7 +50,7 @@ module Bmg
|
|
50
50
|
dataset = dataset.select(*selection)
|
51
51
|
dataset = dataset.distinct if sexpr.distinct?
|
52
52
|
dataset = dataset.where(predicate) if predicate
|
53
|
-
dataset = dataset.group(
|
53
|
+
dataset = dataset.group(grouping) if grouping
|
54
54
|
dataset = dataset.order_by(*order) if order
|
55
55
|
dataset = dataset.limit(limit, offset == 0 ? nil : offset) if limit or offset
|
56
56
|
dataset
|
data/lib/bmg/sql/processor.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Bmg
|
2
|
+
module Sql
|
3
|
+
class Processor
|
4
|
+
class Bind < Processor
|
5
|
+
|
6
|
+
def initialize(binding, builder)
|
7
|
+
super(builder)
|
8
|
+
@binding = binding
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_select_exp(sexpr)
|
12
|
+
if w = sexpr.where_clause
|
13
|
+
pred = Predicate::Grammar.sexpr(w.predicate.bind(@binding))
|
14
|
+
sexpr.with_update(:where_clause, [ :where_clause, pred ])
|
15
|
+
else
|
16
|
+
sexpr
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end # class Bind
|
21
|
+
end # class Processor
|
22
|
+
end # module Sql
|
23
|
+
end # module Bmg
|
data/lib/bmg/sql/relation.rb
CHANGED
data/lib/bmg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: predicate
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '2.
|
19
|
+
version: '2.3'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 2.
|
22
|
+
version: 2.3.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '2.
|
29
|
+
version: '2.3'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 2.
|
32
|
+
version: 2.3.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: rake
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -222,6 +222,7 @@ files:
|
|
222
222
|
- lib/bmg/sql/nodes/with_spec.rb
|
223
223
|
- lib/bmg/sql/processor.rb
|
224
224
|
- lib/bmg/sql/processor/all.rb
|
225
|
+
- lib/bmg/sql/processor/bind.rb
|
225
226
|
- lib/bmg/sql/processor/clip.rb
|
226
227
|
- lib/bmg/sql/processor/constants.rb
|
227
228
|
- lib/bmg/sql/processor/distinct.rb
|