aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/arel/visitors/mysql_test.rb
blob: 05dccd126e8a2b15d2cda8db2a18499eaba83759 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# frozen_string_literal: true

require_relative "../helper"

module Arel
  module Visitors
    class MysqlTest < Arel::Spec
      before do
        @visitor = MySQL.new Table.engine.connection
      end

      def compile(node)
        @visitor.accept(node, Collectors::SQLString.new).value
      end

      ###
      # :'(
      # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
      it "defaults limit to 18446744073709551615" do
        stmt = Nodes::SelectStatement.new
        stmt.offset = Nodes::Offset.new(1)
        sql = compile(stmt)
        sql.must_be_like "SELECT FROM DUAL LIMIT 18446744073709551615 OFFSET 1"
      end

      it "should escape LIMIT" do
        sc = Arel::Nodes::UpdateStatement.new
        sc.relation = Table.new(:users)
        sc.limit = Nodes::Limit.new(Nodes.build_quoted("omg"))
        assert_equal("UPDATE \"users\" LIMIT 'omg'", compile(sc))
      end

      it "uses DUAL for empty from" do
        stmt = Nodes::SelectStatement.new
        sql = compile(stmt)
        sql.must_be_like "SELECT FROM DUAL"
      end

      describe "locking" do
        it "defaults to FOR UPDATE when locking" do
          node = Nodes::Lock.new(Arel.sql("FOR UPDATE"))
          compile(node).must_be_like "FOR UPDATE"
        end

        it "allows a custom string to be used as a lock" do
          node = Nodes::Lock.new(Arel.sql("LOCK IN SHARE MODE"))
          compile(node).must_be_like "LOCK IN SHARE MODE"
        end
      end

      describe "concat" do
        it "concats columns" do
          @table = Table.new(:users)
          query = @table[:name].concat(@table[:name])
          compile(query).must_be_like %{
            CONCAT("users"."name", "users"."name")
          }
        end

        it "concats a string" do
          @table = Table.new(:users)
          query = @table[:name].concat(Nodes.build_quoted("abc"))
          compile(query).must_be_like %{
            CONCAT("users"."name", 'abc')
          }
        end
      end

      describe "Nodes::IsNotDistinctFrom" do
        it "should construct a valid generic SQL statement" do
          test = Table.new(:users)[:name].is_not_distinct_from "Aaron Patterson"
          compile(test).must_be_like %{
            "users"."name" <=> 'Aaron Patterson'
          }
        end

        it "should handle column names on both sides" do
          test = Table.new(:users)[:first_name].is_not_distinct_from Table.new(:users)[:last_name]
          compile(test).must_be_like %{
            "users"."first_name" <=> "users"."last_name"
          }
        end

        it "should handle nil" do
          @table = Table.new(:users)
          val = Nodes.build_quoted(nil, @table[:active])
          sql = compile Nodes::IsNotDistinctFrom.new(@table[:name], val)
          sql.must_be_like %{ "users"."name" <=> NULL }
        end
      end

      describe "Nodes::IsDistinctFrom" do
        it "should handle column names on both sides" do
          test = Table.new(:users)[:first_name].is_distinct_from Table.new(:users)[:last_name]
          compile(test).must_be_like %{
            NOT "users"."first_name" <=> "users"."last_name"
          }
        end

        it "should handle nil" do
          @table = Table.new(:users)
          val = Nodes.build_quoted(nil, @table[:active])
          sql = compile Nodes::IsDistinctFrom.new(@table[:name], val)
          sql.must_be_like %{ NOT "users"."name" <=> NULL }
        end
      end

      describe "Nodes::Regexp" do
        before do
          @table = Table.new(:users)
          @attr = @table[:id]
        end

        it "should know how to visit" do
          node = @table[:name].matches_regexp("foo.*")
          node.must_be_kind_of Nodes::Regexp
          compile(node).must_be_like %{
            "users"."name" REGEXP 'foo.*'
          }
        end

        it "can handle subqueries" do
          subquery = @table.project(:id).where(@table[:name].matches_regexp("foo.*"))
          node = @attr.in subquery
          compile(node).must_be_like %{
            "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" REGEXP 'foo.*')
          }
        end
      end

      describe "Nodes::NotRegexp" do
        before do
          @table = Table.new(:users)
          @attr = @table[:id]
        end

        it "should know how to visit" do
          node = @table[:name].does_not_match_regexp("foo.*")
          node.must_be_kind_of Nodes::NotRegexp
          compile(node).must_be_like %{
            "users"."name" NOT REGEXP 'foo.*'
          }
        end

        it "can handle subqueries" do
          subquery = @table.project(:id).where(@table[:name].does_not_match_regexp("foo.*"))
          node = @attr.in subquery
          compile(node).must_be_like %{
            "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" NOT REGEXP 'foo.*')
          }
        end
      end
    end
  end
end