arel 6.0.0.beta2 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +1 -1
- data/README.markdown +5 -5
- data/lib/arel.rb +1 -1
- data/lib/arel/collectors/sql_string.rb +7 -1
- data/lib/arel/expressions.rb +5 -4
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/nodes/bind_param.rb +6 -0
- data/lib/arel/nodes/sql_literal.rb +0 -3
- data/lib/arel/predications.rb +2 -2
- data/lib/arel/visitors/depth_first.rb +6 -0
- data/lib/arel/visitors/oracle.rb +4 -0
- data/lib/arel/visitors/postgresql.rb +4 -0
- data/lib/arel/visitors/reduce.rb +4 -4
- data/lib/arel/visitors/to_sql.rb +3 -2
- data/lib/arel/visitors/visitor.rb +15 -15
- metadata +26 -69
- data/.gitignore +0 -9
- data/.travis.yml +0 -18
- data/Gemfile +0 -5
- data/Rakefile +0 -15
- data/arel.gemspec +0 -24
- data/test/attributes/test_attribute.rb +0 -910
- data/test/collectors/test_bind_collector.rb +0 -70
- data/test/collectors/test_sql_string.rb +0 -38
- data/test/helper.rb +0 -22
- data/test/nodes/test_and.rb +0 -20
- data/test/nodes/test_as.rb +0 -34
- data/test/nodes/test_ascending.rb +0 -44
- data/test/nodes/test_bin.rb +0 -33
- data/test/nodes/test_binary.rb +0 -26
- data/test/nodes/test_count.rb +0 -33
- data/test/nodes/test_delete_statement.rb +0 -34
- data/test/nodes/test_descending.rb +0 -44
- data/test/nodes/test_distinct.rb +0 -20
- data/test/nodes/test_equality.rb +0 -84
- data/test/nodes/test_extract.rb +0 -41
- data/test/nodes/test_false.rb +0 -20
- data/test/nodes/test_grouping.rb +0 -25
- data/test/nodes/test_infix_operation.rb +0 -40
- data/test/nodes/test_insert_statement.rb +0 -42
- data/test/nodes/test_named_function.rb +0 -46
- data/test/nodes/test_node.rb +0 -39
- data/test/nodes/test_not.rb +0 -29
- data/test/nodes/test_or.rb +0 -34
- data/test/nodes/test_over.rb +0 -67
- data/test/nodes/test_select_core.rb +0 -69
- data/test/nodes/test_select_statement.rb +0 -49
- data/test/nodes/test_sql_literal.rb +0 -73
- data/test/nodes/test_sum.rb +0 -24
- data/test/nodes/test_table_alias.rb +0 -36
- data/test/nodes/test_true.rb +0 -21
- data/test/nodes/test_update_statement.rb +0 -58
- data/test/nodes/test_window.rb +0 -79
- data/test/support/fake_record.rb +0 -135
- data/test/test_attributes.rb +0 -66
- data/test/test_crud.rb +0 -63
- data/test/test_delete_manager.rb +0 -42
- data/test/test_factory_methods.rb +0 -44
- data/test/test_insert_manager.rb +0 -171
- data/test/test_select_manager.rb +0 -1181
- data/test/test_table.rb +0 -253
- data/test/test_update_manager.rb +0 -124
- data/test/visitors/test_bind_visitor.rb +0 -60
- data/test/visitors/test_depth_first.rb +0 -258
- data/test/visitors/test_dispatch_contamination.rb +0 -22
- data/test/visitors/test_dot.rb +0 -76
- data/test/visitors/test_ibm_db.rb +0 -33
- data/test/visitors/test_informix.rb +0 -58
- data/test/visitors/test_mssql.rb +0 -70
- data/test/visitors/test_mysql.rb +0 -60
- data/test/visitors/test_oracle.rb +0 -170
- data/test/visitors/test_postgres.rb +0 -122
- data/test/visitors/test_sqlite.rb +0 -23
- data/test/visitors/test_to_sql.rb +0 -598
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
describe 'avoiding contamination between visitor dispatch tables' do
|
6
|
-
before do
|
7
|
-
@connection = Table.engine.connection
|
8
|
-
@table = Table.new(:users)
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'dispatches properly after failing upwards' do
|
12
|
-
node = Nodes::Union.new(Nodes::True.new, Nodes::False.new)
|
13
|
-
assert_equal "( TRUE UNION FALSE )", node.to_sql
|
14
|
-
|
15
|
-
node.first # from Nodes::Node's Enumerable mixin
|
16
|
-
|
17
|
-
assert_equal "( TRUE UNION FALSE )", node.to_sql
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
data/test/visitors/test_dot.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
class TestDot < Minitest::Test
|
6
|
-
def setup
|
7
|
-
@visitor = Visitors::Dot.new
|
8
|
-
end
|
9
|
-
|
10
|
-
# functions
|
11
|
-
[
|
12
|
-
Nodes::Sum,
|
13
|
-
Nodes::Exists,
|
14
|
-
Nodes::Max,
|
15
|
-
Nodes::Min,
|
16
|
-
Nodes::Avg,
|
17
|
-
].each do |klass|
|
18
|
-
define_method("test_#{klass.name.gsub('::', '_')}") do
|
19
|
-
op = klass.new(:a, "z")
|
20
|
-
@visitor.accept op, Collectors::PlainString.new
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_named_function
|
25
|
-
func = Nodes::NamedFunction.new 'omg', 'omg'
|
26
|
-
@visitor.accept func, Collectors::PlainString.new
|
27
|
-
end
|
28
|
-
|
29
|
-
# unary ops
|
30
|
-
[
|
31
|
-
Arel::Nodes::Not,
|
32
|
-
Arel::Nodes::Group,
|
33
|
-
Arel::Nodes::On,
|
34
|
-
Arel::Nodes::Grouping,
|
35
|
-
Arel::Nodes::Offset,
|
36
|
-
Arel::Nodes::Ordering,
|
37
|
-
Arel::Nodes::Having,
|
38
|
-
Arel::Nodes::UnqualifiedColumn,
|
39
|
-
Arel::Nodes::Top,
|
40
|
-
Arel::Nodes::Limit,
|
41
|
-
].each do |klass|
|
42
|
-
define_method("test_#{klass.name.gsub('::', '_')}") do
|
43
|
-
op = klass.new(:a)
|
44
|
-
@visitor.accept op, Collectors::PlainString.new
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# binary ops
|
49
|
-
[
|
50
|
-
Arel::Nodes::Assignment,
|
51
|
-
Arel::Nodes::Between,
|
52
|
-
Arel::Nodes::DoesNotMatch,
|
53
|
-
Arel::Nodes::Equality,
|
54
|
-
Arel::Nodes::GreaterThan,
|
55
|
-
Arel::Nodes::GreaterThanOrEqual,
|
56
|
-
Arel::Nodes::In,
|
57
|
-
Arel::Nodes::LessThan,
|
58
|
-
Arel::Nodes::LessThanOrEqual,
|
59
|
-
Arel::Nodes::Matches,
|
60
|
-
Arel::Nodes::NotEqual,
|
61
|
-
Arel::Nodes::NotIn,
|
62
|
-
Arel::Nodes::Or,
|
63
|
-
Arel::Nodes::TableAlias,
|
64
|
-
Arel::Nodes::Values,
|
65
|
-
Arel::Nodes::As,
|
66
|
-
Arel::Nodes::DeleteStatement,
|
67
|
-
Arel::Nodes::JoinSource,
|
68
|
-
].each do |klass|
|
69
|
-
define_method("test_#{klass.name.gsub('::', '_')}") do
|
70
|
-
binary = klass.new(:a, :b)
|
71
|
-
@visitor.accept binary, Collectors::PlainString.new
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
describe 'the ibm_db visitor' do
|
6
|
-
before do
|
7
|
-
@visitor = IBM_DB.new Table.engine.connection
|
8
|
-
end
|
9
|
-
|
10
|
-
def compile node
|
11
|
-
@visitor.accept(node, Collectors::SQLString.new).value
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'uses FETCH FIRST n ROWS to limit results' do
|
15
|
-
stmt = Nodes::SelectStatement.new
|
16
|
-
stmt.limit = Nodes::Limit.new(1)
|
17
|
-
sql = compile(stmt)
|
18
|
-
sql.must_be_like "SELECT FETCH FIRST 1 ROWS ONLY"
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'uses FETCH FIRST n ROWS in updates with a limit' do
|
22
|
-
table = Table.new(:users)
|
23
|
-
stmt = Nodes::UpdateStatement.new
|
24
|
-
stmt.relation = table
|
25
|
-
stmt.limit = Nodes::Limit.new(Nodes.build_quoted(1))
|
26
|
-
stmt.key = table[:id]
|
27
|
-
sql = compile(stmt)
|
28
|
-
sql.must_be_like "UPDATE \"users\" WHERE \"users\".\"id\" IN (SELECT \"users\".\"id\" FROM \"users\" FETCH FIRST 1 ROWS ONLY)"
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
describe 'the informix visitor' do
|
6
|
-
before do
|
7
|
-
@visitor = Informix.new Table.engine.connection
|
8
|
-
end
|
9
|
-
|
10
|
-
def compile node
|
11
|
-
@visitor.accept(node, Collectors::SQLString.new).value
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'uses FIRST n to limit results' do
|
15
|
-
stmt = Nodes::SelectStatement.new
|
16
|
-
stmt.limit = Nodes::Limit.new(1)
|
17
|
-
sql = compile(stmt)
|
18
|
-
sql.must_be_like "SELECT FIRST 1"
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'uses FIRST n in updates with a limit' do
|
22
|
-
table = Table.new(:users)
|
23
|
-
stmt = Nodes::UpdateStatement.new
|
24
|
-
stmt.relation = table
|
25
|
-
stmt.limit = Nodes::Limit.new(Nodes.build_quoted(1))
|
26
|
-
stmt.key = table[:id]
|
27
|
-
sql = compile(stmt)
|
28
|
-
sql.must_be_like "UPDATE \"users\" WHERE \"users\".\"id\" IN (SELECT FIRST 1 \"users\".\"id\" FROM \"users\")"
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'uses SKIP n to jump results' do
|
32
|
-
stmt = Nodes::SelectStatement.new
|
33
|
-
stmt.offset = Nodes::Offset.new(10)
|
34
|
-
sql = compile(stmt)
|
35
|
-
sql.must_be_like "SELECT SKIP 10"
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'uses SKIP before FIRST' do
|
39
|
-
stmt = Nodes::SelectStatement.new
|
40
|
-
stmt.limit = Nodes::Limit.new(1)
|
41
|
-
stmt.offset = Nodes::Offset.new(1)
|
42
|
-
sql = compile(stmt)
|
43
|
-
sql.must_be_like "SELECT SKIP 1 FIRST 1"
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'uses INNER JOIN to perform joins' do
|
47
|
-
core = Nodes::SelectCore.new
|
48
|
-
table = Table.new(:posts)
|
49
|
-
core.source = Nodes::JoinSource.new(table, [table.create_join(Table.new(:comments))])
|
50
|
-
|
51
|
-
stmt = Nodes::SelectStatement.new([core])
|
52
|
-
sql = compile(stmt)
|
53
|
-
sql.must_be_like 'SELECT FROM "posts" INNER JOIN "comments"'
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/test/visitors/test_mssql.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
describe 'the mssql visitor' do
|
6
|
-
before do
|
7
|
-
@visitor = MSSQL.new Table.engine.connection
|
8
|
-
@table = Arel::Table.new "users"
|
9
|
-
end
|
10
|
-
|
11
|
-
def compile node
|
12
|
-
@visitor.accept(node, Collectors::SQLString.new).value
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should not modify query if no offset or limit' do
|
16
|
-
stmt = Nodes::SelectStatement.new
|
17
|
-
sql = compile(stmt)
|
18
|
-
sql.must_be_like "SELECT"
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'should go over table PK if no .order() or .group()' do
|
22
|
-
stmt = Nodes::SelectStatement.new
|
23
|
-
stmt.cores.first.from = @table
|
24
|
-
stmt.limit = Nodes::Limit.new(10)
|
25
|
-
sql = compile(stmt)
|
26
|
-
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY \"users\".\"id\") as _row_num FROM \"users\") as _t WHERE _row_num BETWEEN 1 AND 10"
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should go over query ORDER BY if .order()' do
|
30
|
-
stmt = Nodes::SelectStatement.new
|
31
|
-
stmt.limit = Nodes::Limit.new(10)
|
32
|
-
stmt.orders << Nodes::SqlLiteral.new('order_by')
|
33
|
-
sql = compile(stmt)
|
34
|
-
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY order_by) as _row_num) as _t WHERE _row_num BETWEEN 1 AND 10"
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'should go over query GROUP BY if no .order() and there is .group()' do
|
38
|
-
stmt = Nodes::SelectStatement.new
|
39
|
-
stmt.cores.first.groups << Nodes::SqlLiteral.new('group_by')
|
40
|
-
stmt.limit = Nodes::Limit.new(10)
|
41
|
-
sql = compile(stmt)
|
42
|
-
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY group_by) as _row_num GROUP BY group_by) as _t WHERE _row_num BETWEEN 1 AND 10"
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should use BETWEEN if both .limit() and .offset' do
|
46
|
-
stmt = Nodes::SelectStatement.new
|
47
|
-
stmt.limit = Nodes::Limit.new(10)
|
48
|
-
stmt.offset = Nodes::Offset.new(20)
|
49
|
-
sql = compile(stmt)
|
50
|
-
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY ) as _row_num) as _t WHERE _row_num BETWEEN 21 AND 30"
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should use >= if only .offset' do
|
54
|
-
stmt = Nodes::SelectStatement.new
|
55
|
-
stmt.offset = Nodes::Offset.new(20)
|
56
|
-
sql = compile(stmt)
|
57
|
-
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY ) as _row_num) as _t WHERE _row_num >= 21"
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'should generate subquery for .count' do
|
61
|
-
stmt = Nodes::SelectStatement.new
|
62
|
-
stmt.limit = Nodes::Limit.new(10)
|
63
|
-
stmt.cores.first.projections << Nodes::Count.new('*')
|
64
|
-
sql = compile(stmt)
|
65
|
-
sql.must_be_like "SELECT COUNT(1) as count_id FROM (SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY ) as _row_num) as _t WHERE _row_num BETWEEN 1 AND 10) AS subquery"
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
data/test/visitors/test_mysql.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
describe 'the mysql visitor' do
|
6
|
-
before do
|
7
|
-
@visitor = MySQL.new Table.engine.connection
|
8
|
-
end
|
9
|
-
|
10
|
-
def compile node
|
11
|
-
@visitor.accept(node, Collectors::SQLString.new).value
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'squashes parenthesis on multiple unions' do
|
15
|
-
subnode = Nodes::Union.new Arel.sql('left'), Arel.sql('right')
|
16
|
-
node = Nodes::Union.new subnode, Arel.sql('topright')
|
17
|
-
assert_equal 1, compile(node).scan('(').length
|
18
|
-
|
19
|
-
subnode = Nodes::Union.new Arel.sql('left'), Arel.sql('right')
|
20
|
-
node = Nodes::Union.new Arel.sql('topleft'), subnode
|
21
|
-
assert_equal 1, compile(node).scan('(').length
|
22
|
-
end
|
23
|
-
|
24
|
-
###
|
25
|
-
# :'(
|
26
|
-
# http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
|
27
|
-
it 'defaults limit to 18446744073709551615' do
|
28
|
-
stmt = Nodes::SelectStatement.new
|
29
|
-
stmt.offset = Nodes::Offset.new(1)
|
30
|
-
sql = compile(stmt)
|
31
|
-
sql.must_be_like "SELECT FROM DUAL LIMIT 18446744073709551615 OFFSET 1"
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should escape LIMIT" do
|
35
|
-
sc = Arel::Nodes::UpdateStatement.new
|
36
|
-
sc.relation = Table.new(:users)
|
37
|
-
sc.limit = Nodes::Limit.new(Nodes.build_quoted("omg"))
|
38
|
-
assert_equal("UPDATE \"users\" LIMIT 'omg'", compile(sc))
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'uses DUAL for empty from' do
|
42
|
-
stmt = Nodes::SelectStatement.new
|
43
|
-
sql = compile(stmt)
|
44
|
-
sql.must_be_like "SELECT FROM DUAL"
|
45
|
-
end
|
46
|
-
|
47
|
-
describe 'locking' do
|
48
|
-
it 'defaults to FOR UPDATE when locking' do
|
49
|
-
node = Nodes::Lock.new(Arel.sql('FOR UPDATE'))
|
50
|
-
compile(node).must_be_like "FOR UPDATE"
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'allows a custom string to be used as a lock' do
|
54
|
-
node = Nodes::Lock.new(Arel.sql('LOCK IN SHARE MODE'))
|
55
|
-
compile(node).must_be_like "LOCK IN SHARE MODE"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Arel
|
4
|
-
module Visitors
|
5
|
-
describe 'the oracle visitor' do
|
6
|
-
before do
|
7
|
-
@visitor = Oracle.new Table.engine.connection_pool
|
8
|
-
end
|
9
|
-
|
10
|
-
def compile node
|
11
|
-
@visitor.accept(node, Collectors::SQLString.new).value
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'modifies order when there is distinct and first value' do
|
15
|
-
# *sigh*
|
16
|
-
select = "DISTINCT foo.id, FIRST_VALUE(projects.name) OVER (foo) AS alias_0__"
|
17
|
-
stmt = Nodes::SelectStatement.new
|
18
|
-
stmt.cores.first.projections << Nodes::SqlLiteral.new(select)
|
19
|
-
stmt.orders << Nodes::SqlLiteral.new('foo')
|
20
|
-
sql = compile(stmt)
|
21
|
-
sql.must_be_like %{
|
22
|
-
SELECT #{select} ORDER BY alias_0__
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'is idempotent with crazy query' do
|
27
|
-
# *sigh*
|
28
|
-
select = "DISTINCT foo.id, FIRST_VALUE(projects.name) OVER (foo) AS alias_0__"
|
29
|
-
stmt = Nodes::SelectStatement.new
|
30
|
-
stmt.cores.first.projections << Nodes::SqlLiteral.new(select)
|
31
|
-
stmt.orders << Nodes::SqlLiteral.new('foo')
|
32
|
-
|
33
|
-
sql = compile(stmt)
|
34
|
-
sql2 = compile(stmt)
|
35
|
-
sql.must_equal sql2
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'splits orders with commas' do
|
39
|
-
# *sigh*
|
40
|
-
select = "DISTINCT foo.id, FIRST_VALUE(projects.name) OVER (foo) AS alias_0__"
|
41
|
-
stmt = Nodes::SelectStatement.new
|
42
|
-
stmt.cores.first.projections << Nodes::SqlLiteral.new(select)
|
43
|
-
stmt.orders << Nodes::SqlLiteral.new('foo, bar')
|
44
|
-
sql = compile(stmt)
|
45
|
-
sql.must_be_like %{
|
46
|
-
SELECT #{select} ORDER BY alias_0__, alias_1__
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'splits orders with commas and function calls' do
|
51
|
-
# *sigh*
|
52
|
-
select = "DISTINCT foo.id, FIRST_VALUE(projects.name) OVER (foo) AS alias_0__"
|
53
|
-
stmt = Nodes::SelectStatement.new
|
54
|
-
stmt.cores.first.projections << Nodes::SqlLiteral.new(select)
|
55
|
-
stmt.orders << Nodes::SqlLiteral.new('NVL(LOWER(bar, foo), foo) DESC, UPPER(baz)')
|
56
|
-
sql = compile(stmt)
|
57
|
-
sql.must_be_like %{
|
58
|
-
SELECT #{select} ORDER BY alias_0__ DESC, alias_1__
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
describe 'Nodes::SelectStatement' do
|
63
|
-
describe 'limit' do
|
64
|
-
it 'adds a rownum clause' do
|
65
|
-
stmt = Nodes::SelectStatement.new
|
66
|
-
stmt.limit = Nodes::Limit.new(10)
|
67
|
-
sql = compile stmt
|
68
|
-
sql.must_be_like %{ SELECT WHERE ROWNUM <= 10 }
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'is idempotent' do
|
72
|
-
stmt = Nodes::SelectStatement.new
|
73
|
-
stmt.orders << Nodes::SqlLiteral.new('foo')
|
74
|
-
stmt.limit = Nodes::Limit.new(10)
|
75
|
-
sql = compile stmt
|
76
|
-
sql2 = compile stmt
|
77
|
-
sql.must_equal sql2
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'creates a subquery when there is order_by' do
|
81
|
-
stmt = Nodes::SelectStatement.new
|
82
|
-
stmt.orders << Nodes::SqlLiteral.new('foo')
|
83
|
-
stmt.limit = Nodes::Limit.new(10)
|
84
|
-
sql = compile stmt
|
85
|
-
sql.must_be_like %{
|
86
|
-
SELECT * FROM (SELECT ORDER BY foo ) WHERE ROWNUM <= 10
|
87
|
-
}
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'creates a subquery when there is group by' do
|
91
|
-
stmt = Nodes::SelectStatement.new
|
92
|
-
stmt.cores.first.groups << Nodes::SqlLiteral.new('foo')
|
93
|
-
stmt.limit = Nodes::Limit.new(10)
|
94
|
-
sql = compile stmt
|
95
|
-
sql.must_be_like %{
|
96
|
-
SELECT * FROM (SELECT GROUP BY foo ) WHERE ROWNUM <= 10
|
97
|
-
}
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'creates a subquery when there is DISTINCT' do
|
101
|
-
stmt = Nodes::SelectStatement.new
|
102
|
-
stmt.cores.first.set_quantifier = Arel::Nodes::Distinct.new
|
103
|
-
stmt.cores.first.projections << Nodes::SqlLiteral.new('id')
|
104
|
-
stmt.limit = Arel::Nodes::Limit.new(10)
|
105
|
-
sql = compile stmt
|
106
|
-
sql.must_be_like %{
|
107
|
-
SELECT * FROM (SELECT DISTINCT id ) WHERE ROWNUM <= 10
|
108
|
-
}
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'creates a different subquery when there is an offset' do
|
112
|
-
stmt = Nodes::SelectStatement.new
|
113
|
-
stmt.limit = Nodes::Limit.new(Nodes.build_quoted(10))
|
114
|
-
stmt.offset = Nodes::Offset.new(10)
|
115
|
-
sql = compile stmt
|
116
|
-
sql.must_be_like %{
|
117
|
-
SELECT * FROM (
|
118
|
-
SELECT raw_sql_.*, rownum raw_rnum_
|
119
|
-
FROM (SELECT ) raw_sql_
|
120
|
-
WHERE rownum <= 20
|
121
|
-
)
|
122
|
-
WHERE raw_rnum_ > 10
|
123
|
-
}
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'is idempotent with different subquery' do
|
127
|
-
stmt = Nodes::SelectStatement.new
|
128
|
-
stmt.limit = Nodes::Limit.new(Nodes.build_quoted(10))
|
129
|
-
stmt.offset = Nodes::Offset.new(10)
|
130
|
-
sql = compile stmt
|
131
|
-
sql2 = compile stmt
|
132
|
-
sql.must_equal sql2
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
describe 'only offset' do
|
137
|
-
it 'creates a select from subquery with rownum condition' do
|
138
|
-
stmt = Nodes::SelectStatement.new
|
139
|
-
stmt.offset = Nodes::Offset.new(10)
|
140
|
-
sql = compile stmt
|
141
|
-
sql.must_be_like %{
|
142
|
-
SELECT * FROM (
|
143
|
-
SELECT raw_sql_.*, rownum raw_rnum_
|
144
|
-
FROM (SELECT) raw_sql_
|
145
|
-
)
|
146
|
-
WHERE raw_rnum_ > 10
|
147
|
-
}
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'modified except to be minus' do
|
154
|
-
left = Nodes::SqlLiteral.new("SELECT * FROM users WHERE age > 10")
|
155
|
-
right = Nodes::SqlLiteral.new("SELECT * FROM users WHERE age > 20")
|
156
|
-
sql = compile Nodes::Except.new(left, right)
|
157
|
-
sql.must_be_like %{
|
158
|
-
( SELECT * FROM users WHERE age > 10 MINUS SELECT * FROM users WHERE age > 20 )
|
159
|
-
}
|
160
|
-
end
|
161
|
-
|
162
|
-
describe 'locking' do
|
163
|
-
it 'defaults to FOR UPDATE when locking' do
|
164
|
-
node = Nodes::Lock.new(Arel.sql('FOR UPDATE'))
|
165
|
-
compile(node).must_be_like "FOR UPDATE"
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|