Class: Bmg::Type
- Inherits:
-
Object
- Object
- Bmg::Type
- Defined in:
- lib/bmg/type.rb
Constant Summary collapse
- ANY =
Type.new
Instance Attribute Summary collapse
-
#attrlist ⇒ Object
readonly
Returns the value of attribute attrlist.
-
#heading ⇒ Object
readonly
Returns the value of attribute heading.
-
#keys ⇒ Object
readonly
Returns the value of attribute keys.
-
#predicate ⇒ Object
readonly
Returns the value of attribute predicate.
Class Method Summary collapse
Instance Method Summary collapse
- #[](attribute) ⇒ Object
- #allbut(butlist) ⇒ Object
- #attrlist! ⇒ Object
- #autosummarize(by, summarization, options) ⇒ Object
- #autowrap(options) ⇒ Object
- #constants(cs) ⇒ Object
- #cross_join_compatible!(right) ⇒ Object
- #extend(extension) ⇒ Object
- #group(attrs, as) ⇒ Object
- #identity_autowrap?(options) ⇒ Boolean
- #image(right, as, on, options) ⇒ Object
-
#initialize(predicate = Predicate.tautology) ⇒ Type
constructor
A new instance of Type.
- #join(right, on) ⇒ Object
- #join_compatible!(right, on) ⇒ Object
- #known_attributes!(attrs) ⇒ Object
- #knows_attrlist! ⇒ Object
- #knows_attrlist? ⇒ Boolean
- #knows_keys? ⇒ Boolean
- #knows_types? ⇒ Boolean
- #left_join(right, on, default_right_tuple) ⇒ Object
- #matching(right, on) ⇒ Object
- #minus(other) ⇒ Object
- #not_matching(right, on) ⇒ Object
- #page(ordering, page_size, options) ⇒ Object
- #project(attrlist) ⇒ Object
- #rename(renaming) ⇒ Object
- #restrict(predicate) ⇒ Object
- #summarize(by, summarization) ⇒ Object
- #to_attrlist ⇒ Object
- #transform(transformation, options = {}) ⇒ Object
- #typechecked? ⇒ Boolean
- #undress(options) ⇒ Object
- #ungroup(attrlist) ⇒ Object
- #union(other) ⇒ Object
- #union_compatible!(other, opname) ⇒ Object
- #unknown_attributes!(attrs) ⇒ Object
- #unwrap(attrlist) ⇒ Object
- #with_attrlist(attrlist) ⇒ Object
- #with_heading(heading) ⇒ Object
- #with_keys(keys) ⇒ Object
- #with_predicate(predicate) ⇒ Object
- #with_typecheck ⇒ Object
- #without_typecheck ⇒ Object
Constructor Details
Instance Attribute Details
#attrlist ⇒ Object
Returns the value of attribute attrlist.
66 67 68 |
# File 'lib/bmg/type.rb', line 66 def attrlist @attrlist end |
#heading ⇒ Object
Returns the value of attribute heading.
50 51 52 |
# File 'lib/bmg/type.rb', line 50 def heading @heading end |
#keys ⇒ Object
Returns the value of attribute keys.
94 95 96 |
# File 'lib/bmg/type.rb', line 94 def keys @keys end |
#predicate ⇒ Object
Returns the value of attribute predicate.
39 40 41 |
# File 'lib/bmg/type.rb', line 39 def predicate @predicate end |
Class Method Details
.for_heading(heading) ⇒ Object
12 13 14 |
# File 'lib/bmg/type.rb', line 12 def self.for_heading(heading) Type.new.with_heading(heading) end |
Instance Method Details
#[](attribute) ⇒ Object
116 117 118 |
# File 'lib/bmg/type.rb', line 116 def [](attribute) ANY end |
#allbut(butlist) ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/bmg/type.rb', line 122 def allbut(butlist) known_attributes!(butlist) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = self.attrlist - butlist if knows_attrlist? x.predicate = Predicate.tautology x.keys = self._keys.allbut(self, x, butlist) if knows_keys? } end |
#attrlist! ⇒ Object
69 70 71 72 |
# File 'lib/bmg/type.rb', line 69 def attrlist! knows_attrlist! attrlist end |
#autosummarize(by, summarization, options) ⇒ Object
150 151 152 153 154 155 156 157 |
# File 'lib/bmg/type.rb', line 150 def autosummarize(by, summarization, ) known_attributes!(by + summarization.keys) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = nil x.predicate = Predicate.tautology x.keys = nil } end |
#autowrap(options) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/bmg/type.rb', line 138 def autowrap() sep = Operator::Autowrap.separator() splitter = ->(a){ a.to_s.split(sep).first } is_split = ->(a){ a.to_s.split(sep).size > 1 } dup.tap{|x| x.attrlist = self.attrlist.map(&splitter).uniq.map(&:to_sym) if knows_attrlist? x.keys = self._keys.autowrap(self, x, ) if knows_keys? autowrapped = self.predicate.free_variables.select(&is_split) x.predicate = autowrapped.empty? ? self.predicate : self.predicate.and_split(autowrapped).last } end |
#constants(cs) ⇒ Object
159 160 161 162 163 164 165 166 |
# File 'lib/bmg/type.rb', line 159 def constants(cs) unknown_attributes!(cs.keys) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = self.attrlist + cs.keys if knows_attrlist? x.predicate = self.predicate & Predicate.eq(cs) ### keys stay the same } end |
#cross_join_compatible!(right) ⇒ Object
366 367 368 369 370 371 |
# File 'lib/bmg/type.rb', line 366 def cross_join_compatible!(right) shared = self.attrlist & right.type.attrlist unless shared.empty? raise TypeError, "Cross product incompatible — duplicate attribute(s): #{shared.join(', ')}" end end |
#extend(extension) ⇒ Object
168 169 170 171 172 173 174 175 |
# File 'lib/bmg/type.rb', line 168 def extend(extension) unknown_attributes!(extension.keys) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = self.attrlist + extension.keys if knows_attrlist? x.predicate = Predicate.tautology ### keys stay the same (?) } end |
#group(attrs, as) ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/bmg/type.rb', line 177 def group(attrs, as) if typechecked? && knows_attrlist? known_attributes!(attrs) unknown_attributes!([as]) end dup.tap{|x| x.attrlist = self.attrlist - attrs + [as] if knows_attrlist? x.predicate = Predicate.tautology x.keys = self._keys.group(self, x, attrs, as) if knows_keys? } end |
#identity_autowrap?(options) ⇒ Boolean
131 132 133 134 135 136 |
# File 'lib/bmg/type.rb', line 131 def identity_autowrap?() return false unless knows_attrlist? sep = Operator::Autowrap.separator() self.attrlist.all?{|a| a.to_s.index(sep).nil? } end |
#image(right, as, on, options) ⇒ Object
189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/bmg/type.rb', line 189 def image(right, as, on, ) if typechecked? && knows_attrlist? join_compatible!(right, on) unknown_attributes!([as]) end dup.tap{|x| x.attrlist = self.attrlist + [as] if knows_attrlist? x.predicate = Predicate.tautology x.keys = self._keys } end |
#join(right, on) ⇒ Object
201 202 203 204 205 206 207 208 |
# File 'lib/bmg/type.rb', line 201 def join(right, on) join_compatible!(right, on) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = (knows_attrlist? and right.knows_attrlist?) ? (self.attrlist + right.attrlist).uniq : nil x.predicate = self.predicate & right.predicate x.keys = (knows_keys? and right.knows_keys?) ? self._keys.join(self, x, right, on) : nil } end |
#join_compatible!(right, on) ⇒ Object
357 358 359 360 361 362 363 364 |
# File 'lib/bmg/type.rb', line 357 def join_compatible!(right, on) extra = on - self.attrlist raise TypeError, "Unknow attributes #{extra.join(', ')}" unless extra.empty? if right.knows_attrlist? extra = on - right.attrlist raise TypeError, "Unknow attributes #{extra.join(', ')}" unless extra.empty? end end |
#known_attributes!(attrs) ⇒ Object
347 348 349 350 |
# File 'lib/bmg/type.rb', line 347 def known_attributes!(attrs) extra = attrs - self.attrlist raise TypeError, "Unknown attributes #{extra.join(', ')}" unless extra.empty? end |
#knows_attrlist! ⇒ Object
84 85 86 |
# File 'lib/bmg/type.rb', line 84 def knows_attrlist! raise UnknownAttributesError unless knows_attrlist? end |
#knows_attrlist? ⇒ Boolean
80 81 82 |
# File 'lib/bmg/type.rb', line 80 def knows_attrlist? !self.attrlist.nil? end |
#knows_keys? ⇒ Boolean
98 99 100 |
# File 'lib/bmg/type.rb', line 98 def knows_keys? !!@keys end |
#knows_types? ⇒ Boolean
60 61 62 |
# File 'lib/bmg/type.rb', line 60 def knows_types? !@heading.nil? end |
#left_join(right, on, default_right_tuple) ⇒ Object
210 211 212 213 214 215 216 217 |
# File 'lib/bmg/type.rb', line 210 def left_join(right, on, default_right_tuple) join_compatible!(right, on) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = (knows_attrlist? and right.knows_attrlist?) ? (self.attrlist + right.attrlist).uniq : nil x.predicate = Predicate.tautology x.keys = nil } end |
#matching(right, on) ⇒ Object
219 220 221 222 |
# File 'lib/bmg/type.rb', line 219 def matching(right, on) join_compatible!(right, on) if typechecked? && knows_attrlist? self end |
#minus(other) ⇒ Object
224 225 226 227 228 229 230 231 232 233 |
# File 'lib/bmg/type.rb', line 224 def minus(other) union_compatible!(other, "Minus") dup.tap{|x| # 1. attributes do not change # 2. predicate does not change, we can't strengthen it in any way but it # does not become weaker either # 3. we can safely keep all existing keys, but it's not obvious we can # gain some new ones } end |
#not_matching(right, on) ⇒ Object
235 236 237 238 |
# File 'lib/bmg/type.rb', line 235 def not_matching(right, on) join_compatible!(right, on) if typechecked? && knows_attrlist? self end |
#page(ordering, page_size, options) ⇒ Object
240 241 242 243 |
# File 'lib/bmg/type.rb', line 240 def page(ordering, page_size, ) known_attributes!(ordering.map{|(k,v)| k}) if typechecked? && knows_attrlist? self end |
#project(attrlist) ⇒ Object
245 246 247 248 249 250 251 252 |
# File 'lib/bmg/type.rb', line 245 def project(attrlist) known_attributes!(attrlist) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = attrlist x.predicate = Predicate.tautology x.keys = self._keys.project(self, x, attrlist) if knows_keys? } end |
#rename(renaming) ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/bmg/type.rb', line 254 def rename(renaming) if typechecked? && knows_attrlist? known_attributes!(renaming.keys) unknown_attributes!(renaming.values) end new_pred = begin self.predicate.rename(renaming) rescue Predicate::NotSupportedError => e Predicate.tautology end dup.tap{|x| x.attrlist = self.attrlist.map{|a| renaming[a] || a } if knows_attrlist? x.predicate = new_pred x.keys = self._keys.rename(self, x, renaming) if knows_keys? } end |
#restrict(predicate) ⇒ Object
271 272 273 274 275 276 277 278 |
# File 'lib/bmg/type.rb', line 271 def restrict(predicate) known_attributes!(predicate.free_variables) if typechecked? && knows_attrlist? dup.tap{|x| ### attrlist stays the same x.predicate = self.predicate & predicate x.keys = self._keys.restrict(self, x, predicate) if knows_keys? } end |
#summarize(by, summarization) ⇒ Object
280 281 282 283 284 285 |
# File 'lib/bmg/type.rb', line 280 def summarize(by, summarization) dup.tap{|x| x.attrlist = by + summarization.keys x.keys = Keys.new([by]) } end |
#to_attrlist ⇒ Object
88 89 90 |
# File 'lib/bmg/type.rb', line 88 def to_attrlist self.attrlist end |
#transform(transformation, options = {}) ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/bmg/type.rb', line 287 def transform(transformation, = {}) transformer = TupleTransformer.new(transformation) if typechecked? && knows_attrlist? && transformer.knows_attrlist? known_attributes!(transformer.to_attrlist) end keys = if [:key_preserving] self._keys elsif transformer.knows_attrlist? && knows_keys? touched_attrs = transformer.to_attrlist keys = self._keys.select{|k| (k & touched_attrs).empty? } else nil end pred = if transformer.knows_attrlist? attr_list = transformer.to_attrlist predicate.and_split(attr_list).last else Predicate.tautology end dup.tap{|x| x.keys = keys x.predicate = pred } end |
#typechecked? ⇒ Boolean
21 22 23 |
# File 'lib/bmg/type.rb', line 21 def typechecked? @typechecked end |
#undress(options) ⇒ Object
312 313 314 315 316 |
# File 'lib/bmg/type.rb', line 312 def undress() dup.tap{|x| x.predicate = Predicate.tautology } end |
#ungroup(attrlist) ⇒ Object
318 319 320 321 322 323 324 325 |
# File 'lib/bmg/type.rb', line 318 def ungroup(attrlist) known_attributes!(attrlist) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = nil x.predicate = Predicate.tautology x.keys = nil } end |
#union(other) ⇒ Object
327 328 329 330 331 332 333 334 |
# File 'lib/bmg/type.rb', line 327 def union(other) union_compatible!(other, "Union") dup.tap{|x| ### attrlist stays the same x.predicate = self.predicate | predicate x.keys = self._keys.union(self, x, other) if knows_keys? } end |
#union_compatible!(other, opname) ⇒ Object
373 374 375 376 377 378 379 380 |
# File 'lib/bmg/type.rb', line 373 def union_compatible!(other, opname) if typechecked? && knows_attrlist? && other.knows_attrlist? missing = self.attrlist - other.attrlist raise TypeError, "#{opname} requires compatible attribute lists, but the right operand is missing the following attributes: #{missing.join(', ')}" unless missing.empty? extra = other.attrlist - self.attrlist raise TypeError, "#{opname} requires compatible attribute lists, but the left operand is missing the following attributes: #{extra.join(', ')}" unless extra.empty? end end |
#unknown_attributes!(attrs) ⇒ Object
352 353 354 355 |
# File 'lib/bmg/type.rb', line 352 def unknown_attributes!(attrs) clash = self.attrlist & attrs raise TypeError, "Existing attributes #{clash.join(', ')}" unless clash.empty? end |
#unwrap(attrlist) ⇒ Object
336 337 338 339 340 341 342 343 |
# File 'lib/bmg/type.rb', line 336 def unwrap(attrlist) known_attributes!(attrlist) if typechecked? && knows_attrlist? dup.tap{|x| x.attrlist = nil x.predicate = predicate.and_split(attrlist).last x.keys = self._keys.unwrap(self, x, attrlist) if knows_keys? } end |
#with_attrlist(attrlist) ⇒ Object
74 75 76 77 78 |
# File 'lib/bmg/type.rb', line 74 def with_attrlist(attrlist) dup.tap{|x| x.attrlist = attrlist } end |
#with_heading(heading) ⇒ Object
53 54 55 56 57 58 |
# File 'lib/bmg/type.rb', line 53 def with_heading(heading) dup.tap{|x| x.heading = heading x.attrlist = heading.keys } end |
#with_keys(keys) ⇒ Object
108 109 110 111 112 |
# File 'lib/bmg/type.rb', line 108 def with_keys(keys) dup.tap{|x| x.keys = keys ? Keys.new(keys) : nil } end |
#with_predicate(predicate) ⇒ Object
42 43 44 45 46 |
# File 'lib/bmg/type.rb', line 42 def with_predicate(predicate) dup.tap{|x| x.predicate = predicate } end |
#with_typecheck ⇒ Object
25 26 27 28 29 |
# File 'lib/bmg/type.rb', line 25 def with_typecheck dup.tap{|x| x.typechecked = true } end |
#without_typecheck ⇒ Object
31 32 33 34 35 |
# File 'lib/bmg/type.rb', line 31 def without_typecheck dup.tap{|x| x.typechecked = false } end |