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.
-
#keys ⇒ Object
readonly
Returns the value of attribute keys.
-
#predicate ⇒ Object
readonly
Returns the value of attribute predicate.
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
- #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
- #ungroup(attrlist) ⇒ Object
- #union(other) ⇒ Object
- #union_compatible!(other, opname) ⇒ Object
- #unknown_attributes!(attrs) ⇒ Object
- #unwrap(attrlist) ⇒ Object
- #with_attrlist(attrlist) ⇒ 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.
46 47 48 |
# File 'lib/bmg/type.rb', line 46 def attrlist @attrlist end |
#keys ⇒ Object
Returns the value of attribute keys.
74 75 76 |
# File 'lib/bmg/type.rb', line 74 def keys @keys end |
#predicate ⇒ Object
Returns the value of attribute predicate.
35 36 37 |
# File 'lib/bmg/type.rb', line 35 def predicate @predicate end |
Instance Method Details
#[](attribute) ⇒ Object
96 97 98 |
# File 'lib/bmg/type.rb', line 96 def [](attribute) ANY end |
#allbut(butlist) ⇒ Object
102 103 104 105 106 107 108 109 |
# File 'lib/bmg/type.rb', line 102 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
49 50 51 52 |
# File 'lib/bmg/type.rb', line 49 def attrlist! knows_attrlist! attrlist end |
#autosummarize(by, summarization, options) ⇒ Object
130 131 132 133 134 135 136 137 |
# File 'lib/bmg/type.rb', line 130 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
118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/bmg/type.rb', line 118 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
139 140 141 142 143 144 145 146 |
# File 'lib/bmg/type.rb', line 139 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
340 341 342 343 344 345 |
# File 'lib/bmg/type.rb', line 340 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
148 149 150 151 152 153 154 155 |
# File 'lib/bmg/type.rb', line 148 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
157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/bmg/type.rb', line 157 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
111 112 113 114 115 116 |
# File 'lib/bmg/type.rb', line 111 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
169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/bmg/type.rb', line 169 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
181 182 183 184 185 186 187 188 |
# File 'lib/bmg/type.rb', line 181 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
331 332 333 334 335 336 337 338 |
# File 'lib/bmg/type.rb', line 331 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
321 322 323 324 |
# File 'lib/bmg/type.rb', line 321 def known_attributes!(attrs) extra = attrs - self.attrlist raise TypeError, "Unknown attributes #{extra.join(', ')}" unless extra.empty? end |
#knows_attrlist! ⇒ Object
64 65 66 |
# File 'lib/bmg/type.rb', line 64 def knows_attrlist! raise UnknownAttributesError unless knows_attrlist? end |
#knows_attrlist? ⇒ Boolean
60 61 62 |
# File 'lib/bmg/type.rb', line 60 def knows_attrlist? !self.attrlist.nil? end |
#knows_keys? ⇒ Boolean
78 79 80 |
# File 'lib/bmg/type.rb', line 78 def knows_keys? !!@keys end |
#left_join(right, on, default_right_tuple) ⇒ Object
190 191 192 193 194 195 196 197 |
# File 'lib/bmg/type.rb', line 190 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
199 200 201 202 |
# File 'lib/bmg/type.rb', line 199 def matching(right, on) join_compatible!(right, on) if typechecked? && knows_attrlist? self end |
#minus(other) ⇒ Object
299 300 301 302 303 304 305 306 307 308 |
# File 'lib/bmg/type.rb', line 299 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
204 205 206 207 |
# File 'lib/bmg/type.rb', line 204 def not_matching(right, on) join_compatible!(right, on) if typechecked? && knows_attrlist? self end |
#page(ordering, page_size, options) ⇒ Object
209 210 211 212 |
# File 'lib/bmg/type.rb', line 209 def page(ordering, page_size, ) known_attributes!(ordering.map{|(k,v)| k}) if typechecked? && knows_attrlist? self end |
#project(attrlist) ⇒ Object
214 215 216 217 218 219 220 221 |
# File 'lib/bmg/type.rb', line 214 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
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/bmg/type.rb', line 223 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
240 241 242 243 244 245 246 247 |
# File 'lib/bmg/type.rb', line 240 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
249 250 251 252 253 254 |
# File 'lib/bmg/type.rb', line 249 def summarize(by, summarization) dup.tap{|x| x.attrlist = by + summarization.keys x.keys = Keys.new([by]) } end |
#to_attrlist ⇒ Object
68 69 70 |
# File 'lib/bmg/type.rb', line 68 def to_attrlist self.attrlist end |
#transform(transformation, options = {}) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/bmg/type.rb', line 256 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
17 18 19 |
# File 'lib/bmg/type.rb', line 17 def typechecked? @typechecked end |
#ungroup(attrlist) ⇒ Object
281 282 283 284 285 286 287 288 |
# File 'lib/bmg/type.rb', line 281 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
290 291 292 293 294 295 296 297 |
# File 'lib/bmg/type.rb', line 290 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
347 348 349 350 351 352 353 354 |
# File 'lib/bmg/type.rb', line 347 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
326 327 328 329 |
# File 'lib/bmg/type.rb', line 326 def unknown_attributes!(attrs) clash = self.attrlist & attrs raise TypeError, "Existing attributes #{clash.join(', ')}" unless clash.empty? end |
#unwrap(attrlist) ⇒ Object
310 311 312 313 314 315 316 317 |
# File 'lib/bmg/type.rb', line 310 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
54 55 56 57 58 |
# File 'lib/bmg/type.rb', line 54 def with_attrlist(attrlist) dup.tap{|x| x.attrlist = attrlist } end |
#with_keys(keys) ⇒ Object
88 89 90 91 92 |
# File 'lib/bmg/type.rb', line 88 def with_keys(keys) dup.tap{|x| x.keys = keys ? Keys.new(keys) : nil } end |
#with_predicate(predicate) ⇒ Object
38 39 40 41 42 |
# File 'lib/bmg/type.rb', line 38 def with_predicate(predicate) dup.tap{|x| x.predicate = predicate } end |
#with_typecheck ⇒ Object
21 22 23 24 25 |
# File 'lib/bmg/type.rb', line 21 def with_typecheck dup.tap{|x| x.typechecked = true } end |
#without_typecheck ⇒ Object
27 28 29 30 31 |
# File 'lib/bmg/type.rb', line 27 def without_typecheck dup.tap{|x| x.typechecked = false } end |