square-arel 2.0.9.20110222133018

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.
Files changed (125) hide show
  1. data/.autotest +26 -0
  2. data/History.txt +105 -0
  3. data/MIT-LICENSE.txt +20 -0
  4. data/Manifest.txt +124 -0
  5. data/README.markdown +94 -0
  6. data/Rakefile +20 -0
  7. data/lib/arel.rb +39 -0
  8. data/lib/arel/attributes.rb +20 -0
  9. data/lib/arel/attributes/attribute.rb +18 -0
  10. data/lib/arel/compatibility/wheres.rb +33 -0
  11. data/lib/arel/crud.rb +37 -0
  12. data/lib/arel/delete_manager.rb +18 -0
  13. data/lib/arel/deprecated.rb +4 -0
  14. data/lib/arel/expression.rb +4 -0
  15. data/lib/arel/expressions.rb +23 -0
  16. data/lib/arel/insert_manager.rb +34 -0
  17. data/lib/arel/nodes.rb +53 -0
  18. data/lib/arel/nodes/and.rb +6 -0
  19. data/lib/arel/nodes/as.rb +6 -0
  20. data/lib/arel/nodes/assignment.rb +6 -0
  21. data/lib/arel/nodes/avg.rb +6 -0
  22. data/lib/arel/nodes/between.rb +6 -0
  23. data/lib/arel/nodes/binary.rb +12 -0
  24. data/lib/arel/nodes/count.rb +13 -0
  25. data/lib/arel/nodes/delete_statement.rb +19 -0
  26. data/lib/arel/nodes/does_not_match.rb +6 -0
  27. data/lib/arel/nodes/equality.rb +9 -0
  28. data/lib/arel/nodes/except.rb +7 -0
  29. data/lib/arel/nodes/exists.rb +7 -0
  30. data/lib/arel/nodes/function.rb +18 -0
  31. data/lib/arel/nodes/greater_than.rb +6 -0
  32. data/lib/arel/nodes/greater_than_or_equal.rb +6 -0
  33. data/lib/arel/nodes/group.rb +6 -0
  34. data/lib/arel/nodes/grouping.rb +6 -0
  35. data/lib/arel/nodes/having.rb +6 -0
  36. data/lib/arel/nodes/in.rb +6 -0
  37. data/lib/arel/nodes/inner_join.rb +6 -0
  38. data/lib/arel/nodes/insert_statement.rb +19 -0
  39. data/lib/arel/nodes/intersect.rb +7 -0
  40. data/lib/arel/nodes/join.rb +13 -0
  41. data/lib/arel/nodes/less_than.rb +6 -0
  42. data/lib/arel/nodes/less_than_or_equal.rb +6 -0
  43. data/lib/arel/nodes/limit.rb +7 -0
  44. data/lib/arel/nodes/lock.rb +6 -0
  45. data/lib/arel/nodes/matches.rb +6 -0
  46. data/lib/arel/nodes/max.rb +6 -0
  47. data/lib/arel/nodes/min.rb +6 -0
  48. data/lib/arel/nodes/node.rb +44 -0
  49. data/lib/arel/nodes/not.rb +6 -0
  50. data/lib/arel/nodes/not_equal.rb +6 -0
  51. data/lib/arel/nodes/not_in.rb +6 -0
  52. data/lib/arel/nodes/offset.rb +7 -0
  53. data/lib/arel/nodes/on.rb +6 -0
  54. data/lib/arel/nodes/or.rb +6 -0
  55. data/lib/arel/nodes/ordering.rb +20 -0
  56. data/lib/arel/nodes/outer_join.rb +6 -0
  57. data/lib/arel/nodes/select_core.rb +26 -0
  58. data/lib/arel/nodes/select_statement.rb +22 -0
  59. data/lib/arel/nodes/sql_literal.rb +8 -0
  60. data/lib/arel/nodes/string_join.rb +11 -0
  61. data/lib/arel/nodes/sum.rb +6 -0
  62. data/lib/arel/nodes/table_alias.rb +13 -0
  63. data/lib/arel/nodes/top.rb +6 -0
  64. data/lib/arel/nodes/unary.rb +11 -0
  65. data/lib/arel/nodes/union.rb +7 -0
  66. data/lib/arel/nodes/union_all.rb +7 -0
  67. data/lib/arel/nodes/unqualified_column.rb +16 -0
  68. data/lib/arel/nodes/update_statement.rb +21 -0
  69. data/lib/arel/nodes/values.rb +14 -0
  70. data/lib/arel/predications.rb +183 -0
  71. data/lib/arel/relation.rb +6 -0
  72. data/lib/arel/select_manager.rb +237 -0
  73. data/lib/arel/sql/engine.rb +10 -0
  74. data/lib/arel/sql_literal.rb +4 -0
  75. data/lib/arel/table.rb +134 -0
  76. data/lib/arel/tree_manager.rb +36 -0
  77. data/lib/arel/update_manager.rb +49 -0
  78. data/lib/arel/visitors.rb +38 -0
  79. data/lib/arel/visitors/depth_first.rb +154 -0
  80. data/lib/arel/visitors/dot.rb +230 -0
  81. data/lib/arel/visitors/join_sql.rb +40 -0
  82. data/lib/arel/visitors/mssql.rb +16 -0
  83. data/lib/arel/visitors/mysql.rb +34 -0
  84. data/lib/arel/visitors/oracle.rb +116 -0
  85. data/lib/arel/visitors/order_clauses.rb +11 -0
  86. data/lib/arel/visitors/postgresql.rb +58 -0
  87. data/lib/arel/visitors/sqlite.rb +11 -0
  88. data/lib/arel/visitors/to_sql.rb +331 -0
  89. data/lib/arel/visitors/visitor.rb +27 -0
  90. data/lib/arel/visitors/where_sql.rb +9 -0
  91. data/square-arel.gemspec +36 -0
  92. data/test/attributes/test_attribute.rb +664 -0
  93. data/test/helper.rb +13 -0
  94. data/test/nodes/test_as.rb +16 -0
  95. data/test/nodes/test_count.rb +18 -0
  96. data/test/nodes/test_delete_statement.rb +14 -0
  97. data/test/nodes/test_equality.rb +74 -0
  98. data/test/nodes/test_insert_statement.rb +18 -0
  99. data/test/nodes/test_node.rb +33 -0
  100. data/test/nodes/test_not.rb +20 -0
  101. data/test/nodes/test_or.rb +22 -0
  102. data/test/nodes/test_select_core.rb +22 -0
  103. data/test/nodes/test_select_statement.rb +13 -0
  104. data/test/nodes/test_sql_literal.rb +52 -0
  105. data/test/nodes/test_sum.rb +12 -0
  106. data/test/nodes/test_update_statement.rb +18 -0
  107. data/test/support/fake_record.rb +91 -0
  108. data/test/test_activerecord_compat.rb +18 -0
  109. data/test/test_attributes.rb +46 -0
  110. data/test/test_crud.rb +69 -0
  111. data/test/test_delete_manager.rb +42 -0
  112. data/test/test_insert_manager.rb +125 -0
  113. data/test/test_select_manager.rb +659 -0
  114. data/test/test_table.rb +193 -0
  115. data/test/test_update_manager.rb +86 -0
  116. data/test/visitors/test_depth_first.rb +212 -0
  117. data/test/visitors/test_dot.rb +29 -0
  118. data/test/visitors/test_join_sql.rb +35 -0
  119. data/test/visitors/test_mssql.rb +18 -0
  120. data/test/visitors/test_mysql.rb +45 -0
  121. data/test/visitors/test_oracle.rb +147 -0
  122. data/test/visitors/test_postgres.rb +36 -0
  123. data/test/visitors/test_sqlite.rb +18 -0
  124. data/test/visitors/test_to_sql.rb +255 -0
  125. metadata +261 -0
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ require 'fileutils'
4
+ require 'arel'
5
+
6
+ require 'support/fake_record'
7
+ Arel::Table.engine = Arel::Sql::Engine.new(FakeRecord::Base.new)
8
+
9
+ class Object
10
+ def must_be_like other
11
+ self.gsub(/\s+/, ' ').strip.must_equal other.gsub(/\s+/, ' ').strip
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'As' do
6
+ describe '#as' do
7
+ it 'makes an AS node' do
8
+ attr = Table.new(:users)[:id]
9
+ as = attr.as(Arel.sql('foo'))
10
+ assert_equal attr, as.left
11
+ assert_equal 'foo', as.right
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::Count do
4
+ describe 'backwards compatibility' do
5
+ it 'must be an expression' do
6
+ Arel::Nodes::Count.new('foo').must_be_kind_of Arel::Expression
7
+ end
8
+ end
9
+
10
+ describe "as" do
11
+ it 'should alias the count' do
12
+ table = Arel::Table.new :users
13
+ table[:id].count.as('foo').to_sql.must_be_like %{
14
+ COUNT("users"."id") AS foo
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::DeleteStatement do
4
+ describe "#clone" do
5
+ it "clones wheres" do
6
+ statement = Arel::Nodes::DeleteStatement.new
7
+ statement.wheres = %w[a b c]
8
+
9
+ dolly = statement.clone
10
+ dolly.wheres.must_equal statement.wheres
11
+ dolly.wheres.wont_be_same_as statement.wheres
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,74 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'equality' do
6
+ # FIXME: backwards compat
7
+ describe 'backwards compat' do
8
+ describe 'operator' do
9
+ it 'returns :==' do
10
+ attr = Table.new(:users)[:id]
11
+ left = attr.eq(10)
12
+ left.operator.must_equal :==
13
+ end
14
+ end
15
+
16
+ describe 'operand1' do
17
+ it "should equal left" do
18
+ attr = Table.new(:users)[:id]
19
+ left = attr.eq(10)
20
+ left.left.must_equal left.operand1
21
+ end
22
+ end
23
+
24
+ describe 'operand2' do
25
+ it "should equal right" do
26
+ attr = Table.new(:users)[:id]
27
+ left = attr.eq(10)
28
+ left.right.must_equal left.operand2
29
+ end
30
+ end
31
+
32
+ describe 'to_sql' do
33
+ it 'takes an engine' do
34
+ engine = FakeRecord::Base.new
35
+ engine.connection.extend Module.new {
36
+ attr_accessor :quote_count
37
+ def quote(*args) @quote_count += 1; super; end
38
+ def quote_column_name(*args) @quote_count += 1; super; end
39
+ def quote_table_name(*args) @quote_count += 1; super; end
40
+ }
41
+ engine.connection.quote_count = 0
42
+
43
+ attr = Table.new(:users)[:id]
44
+ test = attr.eq(10)
45
+ test.to_sql engine
46
+ engine.connection.quote_count.must_equal 2
47
+ end
48
+ end
49
+ end
50
+
51
+ describe 'or' do
52
+ it 'makes an OR node' do
53
+ attr = Table.new(:users)[:id]
54
+ left = attr.eq(10)
55
+ right = attr.eq(11)
56
+ node = left.or right
57
+ node.expr.left.must_equal left
58
+ node.expr.right.must_equal right
59
+ end
60
+ end
61
+
62
+ describe 'and' do
63
+ it 'makes and AND node' do
64
+ attr = Table.new(:users)[:id]
65
+ left = attr.eq(10)
66
+ right = attr.eq(11)
67
+ node = left.and right
68
+ node.left.must_equal left
69
+ node.right.must_equal right
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::InsertStatement do
4
+ describe "#clone" do
5
+ it "clones columns and values" do
6
+ statement = Arel::Nodes::InsertStatement.new
7
+ statement.columns = %w[a b c]
8
+ statement.values = %w[x y z]
9
+
10
+ dolly = statement.clone
11
+ dolly.columns.must_equal statement.columns
12
+ dolly.values.must_equal statement.values
13
+
14
+ dolly.columns.wont_be_same_as statement.columns
15
+ dolly.values.wont_be_same_as statement.values
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ class TestNode < MiniTest::Unit::TestCase
5
+ def test_all_nodes_are_nodes
6
+ Nodes.constants.map { |k|
7
+ Nodes.const_get(k)
8
+ }.grep(Class).each do |klass|
9
+ next if Nodes::SqlLiteral == klass
10
+ assert klass.ancestors.include?(Nodes::Node), klass.name
11
+ end
12
+ end
13
+
14
+ def test_each
15
+ list = []
16
+ node = Nodes::Node.new
17
+ node.each { |n| list << n }
18
+ assert_equal [node], list
19
+ end
20
+
21
+ def test_generator
22
+ list = []
23
+ node = Nodes::Node.new
24
+ node.each.each { |n| list << n }
25
+ assert_equal [node], list
26
+ end
27
+
28
+ def test_enumerable
29
+ node = Nodes::Node.new
30
+ assert_kind_of Enumerable, node
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'not' do
6
+ describe '#not' do
7
+ it 'makes a NOT node' do
8
+ attr = Table.new(:users)[:id]
9
+ left = attr.eq(10)
10
+ right = attr.eq(11)
11
+ node = left.or right
12
+ node.expr.left.must_equal left
13
+ node.expr.right.must_equal right
14
+
15
+ node.or(right).not
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'or' do
6
+ describe '#or' do
7
+ it 'makes an OR node' do
8
+ attr = Table.new(:users)[:id]
9
+ left = attr.eq(10)
10
+ right = attr.eq(11)
11
+ node = left.or right
12
+ node.expr.left.must_equal left
13
+ node.expr.right.must_equal right
14
+
15
+ oror = node.or(right)
16
+ oror.expr.left.must_equal node
17
+ oror.expr.right.must_equal right
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::SelectCore do
4
+ describe "#clone" do
5
+ it "clones froms, projections and wheres" do
6
+ core = Arel::Nodes::SelectCore.new
7
+ core.froms = %w[a b c]
8
+ core.projections = %w[d e f]
9
+ core.wheres = %w[g h i]
10
+
11
+ dolly = core.clone
12
+
13
+ dolly.froms.must_equal core.froms
14
+ dolly.projections.must_equal core.projections
15
+ dolly.wheres.must_equal core.wheres
16
+
17
+ dolly.froms.wont_be_same_as core.froms
18
+ dolly.projections.wont_be_same_as core.projections
19
+ dolly.wheres.wont_be_same_as core.wheres
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::SelectStatement do
4
+ describe "#clone" do
5
+ it "clones cores" do
6
+ statement = Arel::Nodes::SelectStatement.new %w[a b c]
7
+
8
+ dolly = statement.clone
9
+ dolly.cores.must_equal statement.cores
10
+ dolly.cores.wont_be_same_as statement.cores
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'sql literal' do
6
+ describe 'sql' do
7
+ it 'makes a sql literal node' do
8
+ sql = Arel.sql 'foo'
9
+ sql.must_be_kind_of Arel::Nodes::SqlLiteral
10
+ end
11
+ end
12
+
13
+ describe 'count' do
14
+ it 'makes a count node' do
15
+ node = SqlLiteral.new('*').count
16
+ viz = Visitors::ToSql.new Table.engine
17
+ viz.accept(node).must_be_like %{ COUNT(*) }
18
+ end
19
+
20
+ it 'makes a distinct node' do
21
+ node = SqlLiteral.new('*').count true
22
+ viz = Visitors::ToSql.new Table.engine
23
+ viz.accept(node).must_be_like %{ COUNT(DISTINCT *) }
24
+ end
25
+ end
26
+
27
+ describe 'equality' do
28
+ it 'makes an equality node' do
29
+ node = SqlLiteral.new('foo').eq(1)
30
+ viz = Visitors::ToSql.new Table.engine
31
+ viz.accept(node).must_be_like %{ foo = 1 }
32
+ end
33
+ end
34
+
35
+ describe 'grouped "or" equality' do
36
+ it 'makes a grouping node with an or node' do
37
+ node = SqlLiteral.new('foo').eq_any([1,2])
38
+ viz = Visitors::ToSql.new Table.engine
39
+ viz.accept(node).must_be_like %{ (foo = 1 OR foo = 2) }
40
+ end
41
+ end
42
+
43
+ describe 'grouped "and" equality' do
44
+ it 'makes a grouping node with an or node' do
45
+ node = SqlLiteral.new('foo').eq_all([1,2])
46
+ viz = Visitors::ToSql.new Table.engine
47
+ viz.accept(node).must_be_like %{ (foo = 1 AND foo = 2) }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,12 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::Sum do
4
+ describe "as" do
5
+ it 'should alias the sum' do
6
+ table = Arel::Table.new :users
7
+ table[:id].sum.as('foo').to_sql.must_be_like %{
8
+ SUM("users"."id") AS foo
9
+ }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ describe Arel::Nodes::UpdateStatement do
4
+ describe "#clone" do
5
+ it "clones wheres and values" do
6
+ statement = Arel::Nodes::UpdateStatement.new
7
+ statement.wheres = %w[a b c]
8
+ statement.values = %w[x y z]
9
+
10
+ dolly = statement.clone
11
+ dolly.wheres.must_equal statement.wheres
12
+ dolly.wheres.wont_be_same_as statement.wheres
13
+
14
+ dolly.values.must_equal statement.values
15
+ dolly.values.wont_be_same_as statement.values
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,91 @@
1
+ module FakeRecord
2
+ class Column < Struct.new(:name, :type)
3
+ end
4
+
5
+ class Connection
6
+ attr_reader :tables
7
+
8
+ def initialize
9
+ @tables = %w{ users photos developers }
10
+ @columns = {
11
+ 'users' => [
12
+ Column.new('id', :integer),
13
+ Column.new('name', :string),
14
+ Column.new('bool', :boolean),
15
+ Column.new('created_at', :date),
16
+ ]
17
+ }
18
+ @primary_keys = {
19
+ 'users' => 'id'
20
+ }
21
+ end
22
+
23
+ def primary_key name
24
+ @primary_keys[name.to_s]
25
+ end
26
+
27
+ def table_exists? name
28
+ @tables.include? name.to_s
29
+ end
30
+
31
+ def columns name, message = nil
32
+ @columns[name.to_s]
33
+ end
34
+
35
+ def quote_table_name name
36
+ "\"#{name.to_s}\""
37
+ end
38
+
39
+ def quote_column_name name
40
+ "\"#{name.to_s}\""
41
+ end
42
+
43
+ def quote thing, column = nil
44
+ if column && column.type == :integer
45
+ return 'NULL' if thing.nil?
46
+ return thing.to_i
47
+ end
48
+
49
+ case thing
50
+ when true
51
+ "'t'"
52
+ when false
53
+ "'f'"
54
+ when nil
55
+ 'NULL'
56
+ when Numeric
57
+ thing
58
+ else
59
+ "'#{thing}'"
60
+ end
61
+ end
62
+ end
63
+
64
+ class ConnectionPool
65
+ class Spec < Struct.new(:config)
66
+ end
67
+
68
+ attr_reader :spec, :connection
69
+
70
+ def initialize
71
+ @spec = Spec.new(:adapter => 'america')
72
+ @connection = Connection.new
73
+ end
74
+
75
+ def with_connection
76
+ yield connection
77
+ end
78
+ end
79
+
80
+ class Base
81
+ attr_accessor :connection_pool
82
+
83
+ def initialize
84
+ @connection_pool = ConnectionPool.new
85
+ end
86
+
87
+ def connection
88
+ connection_pool.connection
89
+ end
90
+ end
91
+ end