arel 6.0.0.beta2 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|