aboutsummaryrefslogtreecommitdiffstats
path: root/lib/arel/engines/sql/formatters.rb
blob: 2597beba9529f91dcb7b71d9ae19a8e5fa3b48e1 (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
module Arel
  module Sql
    class Formatter
      attr_reader :environment, :christener

      def initialize(environment)
        @environment = environment
        @christener  = environment.christener
      end

      def name_for thing
        @christener.name_for thing
      end

      def engine
        @environment.engine
      end

      def quote_column_name name
        engine.connection.quote_column_name name
      end

      def quote_table_name name
        engine.connection.quote_column_name name
      end

      def quote value, column = nil
        engine.connection.quote value, column
      end
    end

    class SelectClause < Formatter
      def attribute(attribute)
        "#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}" +
        (attribute.alias ? " AS #{quote(attribute.alias.to_s)}" : "")
      end

      def expression(expression)
        if expression.function_sql == "DISTINCT"
          "#{expression.function_sql} #{expression.attribute.to_sql(self)}" +
          (expression.alias ? " AS #{quote_column_name(expression.alias)}" : '')
        else
          "#{expression.function_sql}(#{expression.attribute.to_sql(self)})" +
          (expression.alias ? " AS #{quote_column_name(expression.alias)}" : " AS #{expression.function_sql.to_s.downcase}_id")
        end
      end

      def select(select_sql, table)
        "(#{select_sql}) AS #{quote_table_name(name_for(table))}"
      end

      def value(value)
        value
      end
    end

    class PassThrough < Formatter
      def value(value)
        value
      end
    end

    class WhereClause < PassThrough
    end

    class OrderClause < PassThrough
      def ordering(ordering)
        "#{quote_table_name(name_for(ordering.attribute.original_relation))}.#{quote_column_name(ordering.attribute.name)} #{ordering.direction_sql}"
      end
    end

    class GroupClause < PassThrough
      def attribute(attribute)
        "#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}"
      end
    end

    class HavingClause < PassThrough
      def attribute(attribute)
        attribute
      end
    end

    class WhereCondition < Formatter
      def attribute(attribute)
        "#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}"
      end

      def expression(expression)
        "#{expression.function_sql}(#{expression.attribute.to_sql(self)})"
      end

      def value(value)
        value.to_sql(self)
      end

      def scalar(value, column = nil)
        quote(value, column)
      end

      def select(select_sql, table)
        "(#{select_sql})"
      end
    end

    class SelectStatement < Formatter
      def select(select_sql, table)
        select_sql
      end
    end

    class TableReference < Formatter
      def select(select_sql, table)
        "(#{select_sql}) #{quote_table_name(name_for(table))}"
      end

      def table(table)
        if table.name =~ /\s/
          table.name
        else
          quote_table_name(table.name) +
            (table.name != name_for(table) ? " #{quote_table_name(name_for(table))}" : '')
        end
      end
    end

    class Attribute < WhereCondition
      def scalar(scalar)
        quote(scalar, environment.column)
      end

      def range(left, right)
        "#{scalar(left)} AND #{scalar(right)}"
      end
    end

    class Value < WhereCondition
    end
  end
end