public
Description: Extras for DataMapper, including bridges to DataObjects::Migrations and Merb::DataMapper
Homepage: http://datamapper.org
Clone URL: git://github.com/sam/dm-more.git
dm-more / dm-aggregates / lib / dm-aggregates / adapters / data_objects_adapter.rb
100644 86 lines (69 sloc) 2.449 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
module DataMapper
  module Adapters
    class DataObjectsAdapter
      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
 
      private
 
      def count(property, value)
        value.to_i
      end
 
      def min(property, value)
        property.typecast(value)
      end
 
      def max(property, value)
        property.typecast(value)
      end
 
      def avg(property, value)
        property.type == Integer ? value.to_f : property.typecast(value)
      end
 
      def sum(property, value)
        property.typecast(value)
      end
 
      module SQL
        private
 
        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 == :all
            '*'
          else
            property_to_column_name(repository, property, qualify)
          end
 
          function_name = case aggregate_function
            when :count then 'COUNT'
            when :min then 'MIN'
            when :max then 'MAX'
            when :avg then 'AVG'
            when :sum then 'SUM'
            else raise "Invalid aggregate function: #{aggregate_function.inspect}"
          end
 
          "#{function_name}(#{column_name})"
        end
      end # module SQL
 
      include SQL
    end # class DataObjectsAdapter
  end # module Adapters
end # module DataMapper