aboutsummaryrefslogtreecommitdiffstats
path: root/lib/arel/primitives/attribute.rb
blob: 280fc9f439015464ca3160c58acca8f82980d724 (plain) (blame)
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
module Arel
  class Attribute
    attr_reader :relation, :name, :alias, :ancestor
    delegate :engine, :to => :relation

    def initialize(relation, name, options = {})
      @relation, @name, @alias, @ancestor = relation, name, options[:alias], options[:ancestor]
    end
    
    def alias_or_name
      @alias || name
    end
    
    def aggregation?
      false
    end

    module Transformations
      def as(aliaz = nil)
        Attribute.new(relation, name, :alias => aliaz, :ancestor => self)
      end
    
      def bind(new_relation)
        relation == new_relation ? self : Attribute.new(new_relation, name, :alias => @alias, :ancestor => self)
      end

      def to_attribute
        self
      end
    end
    include Transformations
    
    def qualified_name
      "#{prefix}.#{name}"
    end
    
    def column
      relation.column_for(self)
    end

    def ==(other)
      self.class  == other.class     and
      relation    == other.relation  and
      name        == other.name      and
      @alias      == other.alias     and
      ancestor    == other.ancestor
    end
    
    module Congruence
      def self.included(klass)
        klass.hash_on :name
      end
      
      def history
        [self] + (ancestor ? [ancestor, ancestor.history].flatten : [])
      end
      
      def =~(other)
        !(history & other.history).empty?
      end
      
      def %(other)
        if other then (history - other.history) + (other.history - history)
        else history
        end
      end
    end
    include Congruence
    
    module Predications
      def eq(other)
        Equality.new(self, other)
      end

      def lt(other)
        LessThan.new(self, other)
      end

      def lteq(other)
        LessThanOrEqualTo.new(self, other)
      end

      def gt(other)
        GreaterThan.new(self, other)
      end

      def gteq(other)
        GreaterThanOrEqualTo.new(self, other)
      end

      def matches(regexp)
        Match.new(self, regexp)
      end
      
      def in(array)
        In.new(self, array)
      end
    end
    include Predications
    
    module Expressions
      def count
        Expression.new(self, "COUNT")
      end
      
      def sum
        Expression.new(self, "SUM")
      end
      
      def maximum
        Expression.new(self, "MAX")
      end
      
      def minimum
        Expression.new(self, "MIN")
      end
      
      def average
        Expression.new(self, "AVG")
      end
    end
    include Expressions

    def to_sql(formatter = Sql::WhereCondition.new(engine))
      formatter.attribute prefix, name, self.alias
    end
    
    def format(object)
      object.to_sql(formatter)
    end
    
    private
    def formatter
      Sql::Attribute.new(self)
    end
    
    def prefix
      relation.prefix_for(self)
    end
  end
end