Created
October 30, 2009 17:53
-
-
Save jwreagor/222582 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby -Ku | |
# encoding: utf-8 | |
require 'rubygems' | |
require 'dm-core' | |
require 'pp' | |
module DataMapper | |
class Collection | |
def union(other) | |
assert_no_loaded_entries(:union) | |
new_collection(query.union(other.query)) | |
end | |
alias | union | |
alias + union | |
def intersection(other) | |
assert_no_loaded_entries(:intersection) | |
new_collection(query.intersection(other.query)) | |
end | |
alias & intersection | |
def difference(other) | |
assert_no_loaded_entries(:difference) | |
new_collection(query.difference(other.query)) | |
end | |
alias - difference | |
private | |
def assert_no_loaded_entries(method) | |
unless loaded_entries.empty? | |
raise ArgumentError, "#{self.class}##{method} cannot be called on a loaded collection" | |
end | |
end | |
end | |
class Query | |
attr_accessor :conditions | |
def union(other) | |
assert_same_options(other) | |
query = dup | |
query.conditions = query.conditions.union(other.conditions) | |
query | |
end | |
alias | union | |
alias + union | |
def intersection(other) | |
assert_same_options(other) | |
query = dup | |
query.conditions = query.conditions.intersection(other.conditions) | |
query | |
end | |
alias & intersection | |
def difference(other) | |
assert_same_options(other) | |
query = dup | |
query.conditions = query.conditions.difference(other.conditions) | |
query | |
end | |
alias - difference | |
private | |
def assert_same_options(other) | |
# TODO: assert all the ivars, aside from @conditions, are identical | |
end | |
module Conditions | |
class AbstractOperation | |
def union(other) | |
Operation.new(:or, dup, other.dup) | |
end | |
alias | union | |
alias + union | |
def intersection(other) | |
Operation.new(:and, dup, other.dup) | |
end | |
alias & intersection | |
def difference(other) | |
Operation.new(:and, dup, Operation.new(:not, other.dup)) | |
end | |
alias - difference | |
end | |
end | |
end | |
end | |
DataMapper::Logger.new($stdout, :debug) | |
DataMapper.setup(:default, 'sqlite3:memory:') | |
class Customer | |
include DataMapper::Resource | |
property :id, Serial | |
property :name, String | |
property :age, Integer | |
has n, :orders | |
end | |
class Order | |
include DataMapper::Resource | |
property :id, Serial | |
property :reference_code, String | |
belongs_to :customer | |
end | |
DataMapper.auto_migrate! | |
customer1 = Customer.create(:name => 'Dan Kubb', :age => 34) | |
customer2 = Customer.create(:name => 'Alex Kubb', :age => 2) | |
customer1.orders.create(:reference_code => 'TEST123') | |
customer2.orders.create(:reference_code => 'TEST321') | |
puts '-' * 80, 'Union:' | |
pp Customer.all(:name => 'Dan Kubb') | Customer.all(:name => 'Alex Kubb') | |
pp Customer.all(:name => 'Dan Kubb') + Customer.all(:name => 'Alex Kubb') | |
puts '-' * 80, 'Intersection:' | |
pp Customer.all(:name => 'Dan Kubb') & Customer.all(:name => 'Alex Kubb') | |
puts '-' * 80, 'Difference:' | |
pp Customer.all(:name => 'Dan Kubb') - Customer.all(:name => 'Alex Kubb') | |
__END__ | |
~ (0.000258) SELECT sqlite_version(*) | |
~ (0.002850) DROP TABLE IF EXISTS "customers" | |
~ (0.001784) DROP TABLE IF EXISTS "orders" | |
~ (0.000038) PRAGMA table_info("customers") | |
~ (0.001835) CREATE TABLE "customers" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "name" VARCHAR(50), "age" INTEGER) | |
~ (0.000021) PRAGMA table_info("orders") | |
~ (0.002111) CREATE TABLE "orders" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "reference_code" VARCHAR(50), "customer_id" INTEGER NOT NULL) | |
~ (0.002192) CREATE INDEX "index_orders_customer" ON "orders" ("customer_id") | |
~ (0.001891) INSERT INTO "customers" ("name", "age") VALUES ('Dan Kubb', 34) | |
~ (0.004047) INSERT INTO "customers" ("name", "age") VALUES ('Alex Kubb', 2) | |
~ (0.003897) INSERT INTO "orders" ("reference_code", "customer_id") VALUES ('TEST123', 1) | |
~ (0.002357) INSERT INTO "orders" ("reference_code", "customer_id") VALUES ('TEST321', 2) | |
-------------------------------------------------------------------------------- | |
Union: | |
~ (0.000104) SELECT "id", "name", "age" FROM "customers" WHERE ("name" = 'Dan Kubb' OR "name" = 'Alex Kubb') ORDER BY "id" | |
[#<Customer @id=1 @name="Dan Kubb" @age=34>, #<Customer @id=2 @name="Alex Kubb" @age=2>] | |
~ (0.000096) SELECT "id", "name", "age" FROM "customers" WHERE ("name" = 'Dan Kubb' OR "name" = 'Alex Kubb') ORDER BY "id" | |
[#<Customer @id=1 @name="Dan Kubb" @age=34>, #<Customer @id=2 @name="Alex Kubb" @age=2>] | |
-------------------------------------------------------------------------------- | |
Intersection: | |
~ (0.000051) SELECT "id", "name", "age" FROM "customers" WHERE ("name" = 'Dan Kubb' AND "name" = 'Alex Kubb') ORDER BY "id" | |
[] | |
-------------------------------------------------------------------------------- | |
Difference: | |
~ (0.000153) SELECT "id", "name", "age" FROM "customers" WHERE ("name" = 'Dan Kubb' AND "name" <> 'Alex Kubb') ORDER BY "id" | |
[#<Customer @id=1 @name="Dan Kubb" @age=34>] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment