Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/sam/dm-more
Browse files Browse the repository at this point in the history
  • Loading branch information
Darrick Wiebe committed Jul 16, 2008
2 parents 2a066e6 + 8a08462 commit 780f0aa
Show file tree
Hide file tree
Showing 16 changed files with 405 additions and 225 deletions.
2 changes: 1 addition & 1 deletion adapters/dm-couchdb-adapter/README
Expand Up @@ -24,4 +24,4 @@ class User
view :by_name, "function(doc) { if (doc.type == 'user') map(doc.name, doc) }"
end

You could then call User.by_name to get a listing of users ordered by name, or pass a key to try and find a specific user by their name, ie User.by_name(:key => 'username').
You could then call User.by_name to get a listing of users ordered by name, or pass a key to try and find a specific user by their name, ie User.by_name(:key => 'username').
26 changes: 21 additions & 5 deletions adapters/dm-couchdb-adapter/lib/couchdb_adapter.rb
Expand Up @@ -50,7 +50,14 @@ def escaped_db_name
def create(resources)
created = 0
resources.each do |resource|
result = http_post("/#{self.escaped_db_name}", resource.to_json(true))
key = resource.class.key(self.name).map do |property|
resource.instance_variable_get(property.instance_variable_name)
end
if key.compact.empty?
result = http_post("/#{self.escaped_db_name}", resource.to_json(true))
else
result = http_put("/#{self.escaped_db_name}/#{key}", resource.to_json(true))
end
if result["ok"]
key = resource.class.key(self.name)
if key.size == 1
Expand Down Expand Up @@ -207,7 +214,7 @@ def ad_hoc_request(query)
request.body =
%Q({"map":
"function(doc) {
if (doc.type == '#{query.model.name.downcase}' && #{conditions.join(" && ")}) {
if (doc.type == '#{query.model.name.downcase}' && #{conditions.join(" && ")}) {
emit(#{key}, doc);
}
}"
Expand All @@ -225,13 +232,22 @@ def view_request(query)
"#{query_string(query)}"
request = Net::HTTP::Get.new(uri)
end

def query_string(query)
query_string = []
query_string << "key=%22#{query.key}%22" if query.key
if query.view_options
query_string +=
query.view_options.map do |key, value|
if [:endkey, :key, :startkey].include? key
URI.escape(%Q(#{key}=#{value.to_json}))
else
URI.escape("#{key}=#{value}")
end
end
end
query_string << "count=#{query.limit}" if query.limit
query_string << "descending=#{query.add_reversed?}" if query.add_reversed?
query_string << "skip=#{query.offset}" if query.offset
query_string << "skip=#{query.offset}" if query.offset != 0
query_string.empty? ? nil : "?#{query_string.join('&')}"
end

Expand Down
16 changes: 6 additions & 10 deletions adapters/dm-couchdb-adapter/lib/couchdb_views.rb
@@ -1,6 +1,6 @@
module DataMapper
class Query
attr_accessor :view, :key
attr_accessor :view, :view_options
end
end

Expand All @@ -18,18 +18,14 @@ def initialize(model, name)
def create_getter
@model.class_eval <<-EOS, __FILE__, __LINE__
def self.#{@name}(*args)
if args.size == 1 && args.last.is_a?(String)
options = {}
key = args.shift
elsif args.empty?
options = {}
key = nil
options = {}
if args.size == 1 && !args.is_a?(Hash)
options[:key] = args.shift
else
options = args.pop
key = options.delete(:key)
end
query = Query.new(repository, self, options)
query.key = key
query = Query.new(repository, self)
query.view_options = options
query.view = '#{@name}'
if options.is_a?(Hash) && options.has_key?(:repository)
repository(options.delete(:repository)).read_many(query)
Expand Down
17 changes: 17 additions & 0 deletions adapters/dm-couchdb-adapter/spec/couchdb_adapter_spec.rb
Expand Up @@ -73,6 +73,15 @@ class Company
company.id.should_not == nil
end

it "should create a record with a specified id" do
pending("No CouchDB connection.") if @no_connection
user_with_id = new_user
user_with_id.id = 'user_id'
user_with_id.save.should == true
User.get!('user_id').should == user_with_id
user_with_id.destroy
end

it "should get a record" do
pending("No CouchDB connection.") if @no_connection
created_user = new_user
Expand Down Expand Up @@ -188,6 +197,14 @@ class Company
User.by_age.first.should == User.all(:order => [:age]).first
end

it "should be able to call stored views with keys" do
pending("No CouchDB connection.") if @no_connection
User.by_name("Aaron").first == User.all(:name => "Aaron").first
User.by_age(30).first == User.all(:age => 30).first
User.by_name("Aaron").first == User.by_name(:key => "Aaron").first
User.by_age(30).first == User.by_age(:key => 30).first
end

def create_procedures
DataMapper.auto_migrate!
end
Expand Down
2 changes: 1 addition & 1 deletion adapters/dm-couchdb-adapter/spec/couchdb_view_spec.rb
Expand Up @@ -37,4 +37,4 @@ def self.default_repository_name
Zoo.view :open
Zoo.should respond_to(:open)
end
end
end
3 changes: 2 additions & 1 deletion dm-aggregates/lib/dm-aggregates.rb
Expand Up @@ -5,8 +5,9 @@

dir = Pathname(__FILE__).dirname.expand_path / 'dm-aggregates'

require dir / 'functions'
require dir / 'aggregate_functions'
require dir / 'model'
require dir / 'repository'
require dir / 'collection'
require dir / 'adapters' / 'data_objects_adapter'
require dir / 'support' / 'symbol'
75 changes: 44 additions & 31 deletions dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb
@@ -1,53 +1,66 @@
module DataMapper
module Adapters
class DataObjectsAdapter
def count(property, query)
query(aggregate_read_statement(:count, property, query), *query.bind_values).first
def aggregate(query)
with_reader(read_statement(query), query.bind_values) do |reader|
results = []

while(reader.next!) do
row = query.fields.zip(reader.values).map do |field,value|
if field.respond_to?(:operator)
send(field.operator, field.target, value)
else
field.typecast(value)
end
end

results << (query.fields.size > 1 ? row : row[0])
end

results
end
end

def min(property, query)
min = query(aggregate_read_statement(:min, property, query), *query.bind_values).first
property.typecast(min)
private

def count(property, value)
value.to_i
end

def min(property, value)
property.typecast(value)
end

def max(property, query)
max = query(aggregate_read_statement(:max, property, query), *query.bind_values).first
property.typecast(max)
def max(property, value)
property.typecast(value)
end

def avg(property, query)
avg = query(aggregate_read_statement(:avg, property, query), *query.bind_values).first
property.type == Integer ? avg.to_f : property.typecast(avg)
def avg(property, value)
property.type == Integer ? value.to_f : property.typecast(value)
end

def sum(property, query)
sum = query(aggregate_read_statement(:sum, property, query), *query.bind_values).first
property.typecast(sum)
def sum(property, value)
property.typecast(value)
end

module SQL
private

def aggregate_read_statement(aggregate_function, property, query)
statement = "SELECT #{aggregate_field_statement(query.repository, aggregate_function, property, query.links.any?)}"
statement << " FROM #{quote_table_name(query.model.storage_name(query.repository.name))}"
statement << links_statement(query) if query.links.any?
statement << " WHERE #{conditions_statement(query)}" if query.conditions.any?

# TODO: when GROUP BY support added, uncomment this, and (by default) have
# it sort on the non-aggregate fields being SELECTed
#statement << " ORDER BY #{order_statement(query)}" if query.order.any?

statement << " LIMIT #{quote_column_value(query.limit)}" if query.limit
statement << " OFFSET #{quote_column_value(query.offset)}" if query.offset && query.offset > 0
statement
rescue => e
DataMapper.logger.error("QUERY INVALID: #{query.inspect} (#{e})")
raise e
alias original_property_to_column_name property_to_column_name

def property_to_column_name(repository, property, qualify)
case property
when Query::Operator
aggregate_field_statement(repository, property.operator, property.target, qualify)
when Property
original_property_to_column_name(repository, property, qualify)
else
raise ArgumentError, "+property+ must be a DataMapper::Query::Operator or a DataMapper::Property, but was a #{property.class} (#{property.inspect})"
end
end

def aggregate_field_statement(repository, aggregate_function, property, qualify)
column_name = if aggregate_function == :count && property.nil?
column_name = if aggregate_function == :count && property == :all
'*'
else
property_to_column_name(repository, property, qualify)
Expand Down

0 comments on commit 780f0aa

Please sign in to comment.