Class: Relation
- Inherits:
-
Object
- Object
- Relation
- Defined in:
- lib/values/relation.rb
Overview
A relation is a set of tupels constrainted to what can be described as a relational type by a heading, this means that the relation only takes tuples with the same heading as the relation.
It has a body
It has a heading
All parts of the body must of the heading
Instance Attribute Summary collapse
-
#body ⇒ Object
readonly
Returns the value of attribute body.
-
#heading ⇒ Object
readonly
Returns the value of attribute heading.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #add(tuple) ⇒ Object
- #cartesian_product(other_relation) ⇒ Object
- #complement(other_relation) ⇒ Object
- #count ⇒ Object
- #each(&block) ⇒ Object
- #eql?(other) ⇒ Boolean
- #group(column_names, new_column_name) ⇒ Object
- #hash ⇒ Object
-
#initialize(*value) ⇒ Relation
constructor
A new instance of Relation.
- #intersect(other_relation) ⇒ Object
- #join(other_relation, &block) ⇒ Object
- #length ⇒ Object
- #natrual_join(other_relation) ⇒ Object
- #project(*args) ⇒ Object
- #project_all_but(*args) ⇒ Object
- #proper_subset_of?(other_relation) ⇒ Boolean
- #proper_superset_of?(other_relation) ⇒ Boolean
- #rename(from, to) ⇒ Object
- #select(&block) ⇒ Object
- #size ⇒ Object
- #subset_of?(other_relation) ⇒ Boolean
- #summarize(column_names, &block) ⇒ Object
- #superset_of?(other_relation) ⇒ Boolean
- #ungroup(column_name) ⇒ Object
- #union(other_relation) ⇒ Object
Constructor Details
#initialize(*value) ⇒ Relation
Returns a new instance of Relation.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/values/relation.rb', line 73 def initialize *value value = value[0] if value.is_a? Tuple @heading = value.heading @body = ImmutableSet.new value elsif value.is_a? Heading @heading = value @body = ImmutableSet.new elsif value.is_a? Relation @heading = value.heading @body = value.body elsif value.is_a? Hash @heading = Heading.new value @body = ImmutableSet.new elsif value.nil? # oo... so you want an empty relation ? @heading = Heading.new @body = ImmutableSet.new else raise "Only accept Tuple,Heading,Relation or Hash types" end end |
Instance Attribute Details
#body ⇒ Object (readonly)
Returns the value of attribute body.
71 72 73 |
# File 'lib/values/relation.rb', line 71 def body @body end |
#heading ⇒ Object (readonly)
Returns the value of attribute heading.
71 72 73 |
# File 'lib/values/relation.rb', line 71 def heading @heading end |
Instance Method Details
#==(other) ⇒ Object
432 433 434 435 436 437 438 439 440 |
# File 'lib/values/relation.rb', line 432 def == other if other.equal?(self) true elsif !self.class.equal?(other.class) false else self.get_body.eql?(other.get_body) end end |
#add(tuple) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/values/relation.rb', line 96 def add tuple if tuple.is_a? Tuple if tuple.heading == @heading Relation.new(@heading).set_body(@body.add tuple) else throw 'its not of the same heading!'+", #{tuple.heading.inspect} != #{@heading.inspect}" end elsif tuple.is_a?(Array) && tuple.first.is_a?(Tuple) # Check that all tuples are valid tuple.each do |t| if t.heading != @heading throw 'its not of the same heading!'+", #{t.heading.inspect} != #{@heading.inspect}" end end Relation.new(@heading).set_body(@body.add tuple) else throw "Only tuples are supported" end end |
#cartesian_product(other_relation) ⇒ Object
281 282 283 284 285 |
# File 'lib/values/relation.rb', line 281 def cartesian_product other_relation self.join other_relation do |tuple| true end end |
#complement(other_relation) ⇒ Object
154 155 156 157 158 159 160 161 162 163 |
# File 'lib/values/relation.rb', line 154 def complement other_relation if self.heading == other_relation.heading new_body = self.get_body.complement other_relation.get_body new_relation = Relation.new self.heading new_relation.set_body new_body return new_relation else throw "Not of the same heading" end end |
#count ⇒ Object
240 241 242 |
# File 'lib/values/relation.rb', line 240 def count @body.size end |
#each(&block) ⇒ Object
252 253 254 255 256 |
# File 'lib/values/relation.rb', line 252 def each &block @body.each do |value| block.call value end end |
#eql?(other) ⇒ Boolean
428 429 430 |
# File 'lib/values/relation.rb', line 428 def eql? other self == other end |
#group(column_names, new_column_name) ⇒ Object
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/values/relation.rb', line 373 def group column_names,new_column_name # create the headings new_heading = Heading.new new_inner_heading = self.heading column_names.each do |column_name| throw "there is no #{column_name} in [#{self.heading.names.join(',')}]" if self.heading[column_name].nil? new_heading = new_heading.add self.heading[column_name] end column_names.each do |column_name| new_inner_heading = new_inner_heading.remove column_name end new_heading = new_heading.add(:name => new_column_name, :type => new_inner_heading) # split the data temp_data = {} self.each do |tuple| new_tuple = Tuple.new new_inner_tuple = Tuple.new new_heading.each do |attribute| new_tuple = new_tuple.add(attribute => tuple[attribute]) unless attribute.name.to_s == new_column_name.to_s end new_inner_heading.each do |attribute| new_inner_tuple = new_inner_tuple.add(attribute => tuple[attribute]) end temp_data[new_tuple] ||= [] temp_data[new_tuple].push new_inner_tuple end # create the new realation new_relation = Relation.new new_heading temp_data.each do |tuple,array_of_tuples| inner_relation = Relation.new new_inner_heading array_of_tuples.each do |inner_tuple| inner_relation = inner_relation.add(inner_tuple) end tuple = tuple.add(new_column_name => inner_relation) new_relation = new_relation.add(tuple) end new_relation end |
#hash ⇒ Object
442 443 444 |
# File 'lib/values/relation.rb', line 442 def hash self.get_body.hash end |
#intersect(other_relation) ⇒ Object
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/values/relation.rb', line 143 def intersect other_relation if self.heading == other_relation.heading new_body = self.get_body.intersect other_relation.get_body new_relation = Relation.new self.heading new_relation.set_body new_body return new_relation else throw "Not of the same heading" end end |
#join(other_relation, &block) ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/values/relation.rb', line 269 def join other_relation,&block new_relation = Relation.new(self.heading.add(other_relation.heading)) self.each do |tuple| other_relation.each do |tuple2| tuple3 = tuple.add(tuple2) new_relation = new_relation.add(tuple3) if block.call(tuple3) end end new_relation end |
#length ⇒ Object
248 249 250 |
# File 'lib/values/relation.rb', line 248 def length self.count end |
#natrual_join(other_relation) ⇒ 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 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'lib/values/relation.rb', line 287 def natrual_join other_relation the_same = [] self.heading.each do |attribute| other_relation.heading.each do |attribute2| if attribute == attribute2 the_same.push attribute end end end old_and_new_name = {} the_same.each do |value| other_relation = other_relation.rename(value.name,value.name+"_2") old_and_new_name[value.name] = value.name+"_2" end to_return = self.join(other_relation) do |tuple| r = true old_and_new_name.each do |name,name2| unless tuple[name] == tuple[name2] r = false end end r end to_return = to_return.project_all_but *(old_and_new_name.values) to_return end |
#project(*args) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/values/relation.rb', line 167 def project *args new_heading = Heading.new args.each do |symbol| if self.heading[symbol].nil? throw "no attribute with the name #{symbol}" end new_heading = new_heading.add(self.heading[symbol]) end if new_heading.count == 0 return Relation.new new_heading end new_relation = Relation.new new_heading @body.each do |tuple| new_tuple = Tuple.new args.each do |symbol| new_tuple = new_tuple.add(symbol => tuple[symbol]) end new_relation = new_relation.add new_tuple end return new_relation end |
#project_all_but(*args) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/values/relation.rb', line 199 def project_all_but *args new_heading = Heading.new self.heading args.each do |symbol| if self.heading[symbol].nil? throw "no attribute with the name #{symbol}" end new_heading = new_heading.remove symbol end if new_heading.count == 0 return Relation.new new_heading end new_relation = Relation.new new_heading @body.each do |tuple| new_tuple = Tuple.new new_heading.each do |attribute| new_tuple = new_tuple.add(attribute => tuple[attribute.name]) end new_relation = new_relation.add new_tuple end return new_relation end |
#proper_subset_of?(other_relation) ⇒ Boolean
120 121 122 |
# File 'lib/values/relation.rb', line 120 def proper_subset_of? other_relation @body.proper_subset_of? other_relation.get_body end |
#proper_superset_of?(other_relation) ⇒ Boolean
128 129 130 |
# File 'lib/values/relation.rb', line 128 def proper_superset_of? other_relation @body.proper_superset_of? other_relation.get_body end |
#rename(from, to) ⇒ Object
229 230 231 232 233 234 235 236 |
# File 'lib/values/relation.rb', line 229 def rename from,to new_relation = Relation.new self.heading.rename(from,to) self.each do |tuple| new_relation = new_relation.add tuple.rename(from,to) end new_relation end |
#select(&block) ⇒ Object
259 260 261 262 263 264 265 266 |
# File 'lib/values/relation.rb', line 259 def select &block new_relation = Relation.new self.heading self.each do |tuple| new_relation = new_relation.add(tuple) if block.call(tuple) end new_relation end |
#size ⇒ Object
244 245 246 |
# File 'lib/values/relation.rb', line 244 def size self.count end |
#subset_of?(other_relation) ⇒ Boolean
116 117 118 |
# File 'lib/values/relation.rb', line 116 def subset_of? other_relation @body.subset? other_relation.get_body end |
#summarize(column_names, &block) ⇒ Object
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/values/relation.rb', line 325 def summarize column_names, &block column_names = [column_names] unless column_names.is_a? Array new_tuples = [] self.group(column_names,"temp_12345").each do |tuple| new_tuples.push(block.call(tuple.remove("temp_12345"),tuple['temp_12345'])) end to_return = Relation.new new_tuples.first.heading new_tuples.each do |tuple| to_return = to_return.add tuple end to_return end |
#superset_of?(other_relation) ⇒ Boolean
124 125 126 |
# File 'lib/values/relation.rb', line 124 def superset_of? other_relation @body.superset_of? other_relation.get_body end |
#ungroup(column_name) ⇒ Object
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/values/relation.rb', line 345 def ungroup column_name new_tuples = [] self.each do |tuple| inner_relation = tuple[column_name] tuple = tuple.remove column_name inner_relation.each do |inner_tuple| temp = tuple inner_tuple.each do |attribute,value| temp = temp.add({attribute => value}) new_tuples.push(temp) end end end new_heading = self.heading.remove column_name self.heading[column_name].type.each do |attribute| new_heading = new_heading.add attribute end to_return = Relation.new new_heading new_tuples.each do |tuple| to_return = to_return.add tuple end to_return end |
#union(other_relation) ⇒ Object
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/values/relation.rb', line 132 def union other_relation if self.heading == other_relation.heading new_body = self.get_body.union(other_relation.get_body) new_relation = Relation.new self.heading new_relation.set_body new_body return new_relation else throw "Not of the same heading" end end |