bmg 0.13.0 → 0.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7cf04c07c2f88598d086c9eb174c857995a3646
4
- data.tar.gz: 368fdda422f043d57c7da57f5019b4682e9d37eb
3
+ metadata.gz: e9b2b82ef90b6ca136323d9ef107a1e94733c1b6
4
+ data.tar.gz: 4fdf4e423a73779e03a4870da5d647c6d2c6f403
5
5
  SHA512:
6
- metadata.gz: 9ef7574e4dfe6e30619310daf922e16ca20f5721f2d4f339a13fd8077520316215d8306f6b7150a3df5648944163fc5bb9329d40663b6ccf4be1eeba7d26af4c
7
- data.tar.gz: a5c71d8cfb1b9e52ab360b3deaffc6c9986b7388154b78141256a83b949300b329c433f7a265cf97d6ab1ba7433ebd08f15e0a549fb39f2b02f19cb2d5cd5a7b
6
+ metadata.gz: 6c692d1ae8b5146b96e117621721a69880a82fa6f58292fd4d8b3fe709e0189b194701acefb17244201af3a15dcfc284d746e009a4b11a16207ba64195aee68c
7
+ data.tar.gz: 45cdc9e8479d8e1c30cf733339cbc60a08bf36c64fd388002fcd96c3aa52b2b5e7810869c3587246a25d8f620d6a381cfaec33e6735317e6a99244f6b45214c0
@@ -57,7 +57,7 @@ module Bmg
57
57
  protected :_group
58
58
 
59
59
  def image(right, as = :image, on = [], options = {})
60
- _image self.type.image(right, as, on, options), right, as, on, options
60
+ _image self.type.image(right.type, as, on, options), right, as, on, options
61
61
  end
62
62
 
63
63
  def _image(type, right, as, on, options)
@@ -75,7 +75,7 @@ module Bmg
75
75
  protected :_join
76
76
 
77
77
  def matching(right, on = [])
78
- _matching self.type.matching(right, on), right, on
78
+ _matching self.type.matching(right.type, on), right, on
79
79
  end
80
80
 
81
81
  def _matching(type, right, on)
@@ -84,7 +84,7 @@ module Bmg
84
84
  protected :_matching
85
85
 
86
86
  def not_matching(right, on = [])
87
- _not_matching self.type.not_matching(right, on), right, on
87
+ _not_matching self.type.not_matching(right.type, on), right, on
88
88
  end
89
89
 
90
90
  def _not_matching(type, right, on)
@@ -9,4 +9,7 @@ module Bmg
9
9
  # Raised when an update is invalid for some reason
10
10
  class InvalidUpdateError < Error; end
11
11
 
12
+ # Raised when violating types
13
+ class TypeError < Error; end
14
+
12
15
  end
@@ -2,6 +2,10 @@ module Bmg
2
2
  module Operator
3
3
  include Relation
4
4
 
5
+ attr_reader :type
6
+ attr_writer :type
7
+ protected :type=
8
+
5
9
  def to_s
6
10
  str = "(#{self.class.name.split('::').last.downcase}\n"
7
11
  str << operands.map{|op| op.to_s.gsub(/^/m, " ") }.join("\n")
@@ -23,7 +27,7 @@ module Bmg
23
27
  module Unary
24
28
  include Operator
25
29
 
26
- attr_reader :type, :operand
30
+ attr_reader :operand
27
31
 
28
32
  def _visit(parent, visitor)
29
33
  visitor.call(self, parent)
@@ -39,7 +43,7 @@ module Bmg
39
43
  module Binary
40
44
  include Operator
41
45
 
42
- attr_reader :type, :left, :right
46
+ attr_reader :left, :right
43
47
 
44
48
  def _visit(parent, visitor)
45
49
  visitor.call(self, parent)
@@ -55,7 +59,7 @@ module Bmg
55
59
  module Nary
56
60
  include Operator
57
61
 
58
- attr_reader :type, :operands
62
+ attr_reader :operands
59
63
 
60
64
  def _visit(parent, visitor)
61
65
  visitor.call(self, parent)
@@ -80,7 +80,7 @@ module Bmg
80
80
  end
81
81
 
82
82
  def group_type
83
- type.project(attrs)
83
+ operand.type.project(attrs)
84
84
  end
85
85
 
86
86
  end # class Extend
@@ -2,7 +2,8 @@ module Bmg
2
2
  module Reader
3
3
  include Relation
4
4
 
5
- attr_reader :type
5
+ attr_accessor :type
6
+ protected :type=
6
7
 
7
8
  end
8
9
  end
@@ -13,6 +13,18 @@ module Bmg
13
13
  Relation::Empty.new(type)
14
14
  end
15
15
 
16
+ def with_typecheck
17
+ dup.tap{|r|
18
+ r.type = r.type.with_typecheck
19
+ }
20
+ end
21
+
22
+ def without_typecheck
23
+ dup.tap{|r|
24
+ r.type = r.type.with_typecheck
25
+ }
26
+ end
27
+
16
28
  def empty?
17
29
  each{|t| return false }
18
30
  true
@@ -13,7 +13,8 @@ module Bmg
13
13
  def initialize(type)
14
14
  @type = type
15
15
  end
16
- attr_reader :type
16
+ attr_accessor :type
17
+ protected :type=
17
18
 
18
19
  def each(&bl)
19
20
  end
@@ -7,7 +7,9 @@ module Bmg
7
7
  @operand = operand
8
8
  @type = type
9
9
  end
10
- attr_reader :type, :operand
10
+ attr_accessor :type
11
+ protected :type=
12
+ attr_reader :operand
11
13
 
12
14
  public
13
15
 
@@ -18,6 +18,11 @@ module Bmg
18
18
  operand.type
19
19
  end
20
20
 
21
+ def type=(type)
22
+ operand.type = type
23
+ end
24
+ protected :type=
25
+
21
26
  def each(&bl)
22
27
  spy.call(self)
23
28
  operand.each(&bl)
@@ -134,10 +134,8 @@ module Bmg
134
134
 
135
135
  public ### Predicate hack
136
136
 
137
- def on_in(sexpr)
138
- left, right = apply(sexpr.identifier), sexpr.last
139
- right = apply(right) if sexpr.subquery?
140
- ::Sequel.expr(left => right)
137
+ def on_opaque(sexpr)
138
+ apply(sexpr.last)
141
139
  end
142
140
 
143
141
  def on_exists(sexpr)
@@ -41,7 +41,7 @@ module Bmg
41
41
  builder.exists(subquery)
42
42
  elsif commons.size == 1
43
43
  identifier = left.desaliaser(true)[commons.to_a.first]
44
- Predicate::Factory.in(identifier, subquery)
44
+ Predicate::Factory.in(identifier, Predicate::Factory.opaque(subquery))
45
45
  else
46
46
  join_pre = join_predicate(left, subquery, commons)
47
47
  subquery = expand_where_clause(subquery, join_pre)
@@ -8,7 +8,9 @@ module Bmg
8
8
  @builder = builder
9
9
  @expr = expr
10
10
  end
11
- attr_reader :type
11
+
12
+ attr_accessor :type
13
+ protected :type=
12
14
 
13
15
  protected
14
16
 
@@ -3,11 +3,33 @@ module Bmg
3
3
 
4
4
  def initialize(predicate = Predicate.tautology)
5
5
  @predicate = predicate
6
+ @typechecked = false
6
7
  raise ArgumentError if @predicate.nil?
7
8
  end
8
9
 
9
10
  ANY = Type.new
10
11
 
12
+ public ## type checking
13
+
14
+ attr_writer :typechecked
15
+ protected :typechecked=
16
+
17
+ def typechecked?
18
+ @typechecked
19
+ end
20
+
21
+ def with_typecheck
22
+ dup.tap{|x|
23
+ x.typechecked = true
24
+ }
25
+ end
26
+
27
+ def without_typecheck
28
+ dup.tap{|x|
29
+ x.typechecked = false
30
+ }
31
+ end
32
+
11
33
  public ## predicate
12
34
 
13
35
  attr_accessor :predicate
@@ -69,6 +91,7 @@ module Bmg
69
91
  public ### algebra
70
92
 
71
93
  def allbut(butlist)
94
+ known_attributes!(butlist) if typechecked? && knows_attrlist?
72
95
  dup.tap{|x|
73
96
  x.attrlist = self.attrlist - butlist if knows_attrlist?
74
97
  x.predicate = Predicate.tautology
@@ -89,10 +112,16 @@ module Bmg
89
112
  end
90
113
 
91
114
  def autosummarize(by, summarization)
92
- ANY
115
+ known_attributes!(by + summarization.keys) if typechecked? && knows_attrlist?
116
+ dup.tap{|x|
117
+ x.attrlist = nil
118
+ x.predicate = Predicate.tautology
119
+ x.keys = nil
120
+ }
93
121
  end
94
122
 
95
123
  def constants(cs)
124
+ unknown_attributes!(cs.keys) if typechecked? && knows_attrlist?
96
125
  dup.tap{|x|
97
126
  x.attrlist = self.attrlist + cs.keys if knows_attrlist?
98
127
  x.predicate = self.predicate & Predicate.eq(cs)
@@ -101,6 +130,7 @@ module Bmg
101
130
  end
102
131
 
103
132
  def extend(extension)
133
+ unknown_attributes!(extension.keys) if typechecked? && knows_attrlist?
104
134
  dup.tap{|x|
105
135
  x.attrlist = self.attrlist + extension.keys if knows_attrlist?
106
136
  x.predicate = Predicate.tautology
@@ -109,6 +139,10 @@ module Bmg
109
139
  end
110
140
 
111
141
  def group(attrs, as)
142
+ if typechecked? && knows_attrlist?
143
+ known_attributes!(attrs)
144
+ unknown_attributes!([as])
145
+ end
112
146
  dup.tap{|x|
113
147
  x.attrlist = self.attrlist - attrs + [as] if knows_attrlist?
114
148
  x.predicate = Predicate.tautology
@@ -117,6 +151,10 @@ module Bmg
117
151
  end
118
152
 
119
153
  def image(right, as, on, options)
154
+ if typechecked? && knows_attrlist?
155
+ join_compatible!(right, on)
156
+ unknown_attributes!([as])
157
+ end
120
158
  dup.tap{|x|
121
159
  x.attrlist = self.attrlist + [as] if knows_attrlist?
122
160
  x.predicate = Predicate.tautology
@@ -125,6 +163,7 @@ module Bmg
125
163
  end
126
164
 
127
165
  def join(right, on)
166
+ join_compatible!(right, on) if typechecked? && knows_attrlist?
128
167
  dup.tap{|x|
129
168
  x.attrlist = (knows_attrlist? and right.knows_attrlist?) ? (self.attrlist + right.attrlist).uniq : nil
130
169
  x.predicate = self.predicate & right.predicate
@@ -133,18 +172,22 @@ module Bmg
133
172
  end
134
173
 
135
174
  def matching(right, on)
175
+ join_compatible!(right, on) if typechecked? && knows_attrlist?
136
176
  self
137
177
  end
138
178
 
139
179
  def not_matching(right, on)
180
+ join_compatible!(right, on) if typechecked? && knows_attrlist?
140
181
  self
141
182
  end
142
183
 
143
184
  def page(ordering, page_size, options)
185
+ known_attributes!(ordering.map{|(k,v)| k}) if typechecked? && knows_attrlist?
144
186
  self
145
187
  end
146
188
 
147
189
  def project(attrlist)
190
+ known_attributes!(attrlist) if typechecked? && knows_attrlist?
148
191
  dup.tap{|x|
149
192
  x.attrlist = attrlist
150
193
  x.predicate = Predicate.tautology
@@ -153,6 +196,10 @@ module Bmg
153
196
  end
154
197
 
155
198
  def rename(renaming)
199
+ if typechecked? && knows_attrlist?
200
+ known_attributes!(renaming.keys)
201
+ unknown_attributes!(renaming.values)
202
+ end
156
203
  dup.tap{|x|
157
204
  x.attrlist = self.attrlist.map{|a| renaming[a] || a } if knows_attrlist?
158
205
  x.predicate = self.predicate.rename(renaming)
@@ -161,6 +208,7 @@ module Bmg
161
208
  end
162
209
 
163
210
  def restrict(predicate)
211
+ known_attributes!(predicate.free_variables) if typechecked? && knows_attrlist?
164
212
  dup.tap{|x|
165
213
  ### attrlist stays the same
166
214
  x.predicate = self.predicate & predicate
@@ -169,6 +217,12 @@ module Bmg
169
217
  end
170
218
 
171
219
  def union(other)
220
+ if typechecked? && knows_attrlist? && other.knows_attrlist?
221
+ missing = self.attrlist - other.attrlist
222
+ raise TypeError, "Union incompatible: missing right attributes #{missing.join(', ')}" unless missing.empty?
223
+ extra = other.attrlist - self.attrlist
224
+ raise TypeError, "Union incompatible: missing left attributes #{extra.join(', ')}" unless extra.empty?
225
+ end
172
226
  dup.tap{|x|
173
227
  ### attrlist stays the same
174
228
  x.predicate = self.predicate | predicate
@@ -176,5 +230,26 @@ module Bmg
176
230
  }
177
231
  end
178
232
 
233
+ private
234
+
235
+ def known_attributes!(attrs)
236
+ extra = attrs - self.attrlist
237
+ raise TypeError, "Unknown attributes #{extra.join(', ')}" unless extra.empty?
238
+ end
239
+
240
+ def unknown_attributes!(attrs)
241
+ clash = self.attrlist & attrs
242
+ raise TypeError, "Existing attributes #{clash.join(', ')}" unless clash.empty?
243
+ end
244
+
245
+ def join_compatible!(right, on)
246
+ extra = on - self.attrlist
247
+ raise TypeError, "Unknow attributes #{extra.join(', ')}" unless extra.empty?
248
+ if right.knows_attrlist?
249
+ extra = on - right.attrlist
250
+ raise TypeError, "Unknow attributes #{extra.join(', ')}" unless extra.empty?
251
+ end
252
+ end
253
+
179
254
  end # class Type
180
255
  end # module Bmg
@@ -1,7 +1,7 @@
1
1
  module Bmg
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 13
4
+ MINOR = 14
5
5
  TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
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.13.0
4
+ version: 0.14.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: 2018-05-31 00:00:00.000000000 Z
11
+ date: 2018-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: predicate
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '2.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement