bmg 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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