arel-compat 0.4.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.
Files changed (164) hide show
  1. data/History.txt +25 -0
  2. data/README.markdown +182 -0
  3. data/lib/arel.rb +13 -0
  4. data/lib/arel/algebra.rb +10 -0
  5. data/lib/arel/algebra/attributes.rb +7 -0
  6. data/lib/arel/algebra/attributes/attribute.rb +270 -0
  7. data/lib/arel/algebra/attributes/boolean.rb +21 -0
  8. data/lib/arel/algebra/attributes/decimal.rb +9 -0
  9. data/lib/arel/algebra/attributes/float.rb +9 -0
  10. data/lib/arel/algebra/attributes/integer.rb +10 -0
  11. data/lib/arel/algebra/attributes/string.rb +10 -0
  12. data/lib/arel/algebra/attributes/time.rb +6 -0
  13. data/lib/arel/algebra/core_extensions.rb +4 -0
  14. data/lib/arel/algebra/core_extensions/class.rb +32 -0
  15. data/lib/arel/algebra/core_extensions/hash.rb +11 -0
  16. data/lib/arel/algebra/core_extensions/object.rb +30 -0
  17. data/lib/arel/algebra/core_extensions/symbol.rb +9 -0
  18. data/lib/arel/algebra/expression.rb +43 -0
  19. data/lib/arel/algebra/header.rb +67 -0
  20. data/lib/arel/algebra/ordering.rb +23 -0
  21. data/lib/arel/algebra/predicates.rb +190 -0
  22. data/lib/arel/algebra/relations.rb +17 -0
  23. data/lib/arel/algebra/relations/operations/alias.rb +7 -0
  24. data/lib/arel/algebra/relations/operations/from.rb +6 -0
  25. data/lib/arel/algebra/relations/operations/group.rb +12 -0
  26. data/lib/arel/algebra/relations/operations/having.rb +17 -0
  27. data/lib/arel/algebra/relations/operations/join.rb +69 -0
  28. data/lib/arel/algebra/relations/operations/lock.rb +12 -0
  29. data/lib/arel/algebra/relations/operations/order.rb +19 -0
  30. data/lib/arel/algebra/relations/operations/project.rb +20 -0
  31. data/lib/arel/algebra/relations/operations/skip.rb +7 -0
  32. data/lib/arel/algebra/relations/operations/take.rb +11 -0
  33. data/lib/arel/algebra/relations/operations/where.rb +17 -0
  34. data/lib/arel/algebra/relations/relation.rb +136 -0
  35. data/lib/arel/algebra/relations/row.rb +26 -0
  36. data/lib/arel/algebra/relations/utilities/compound.rb +54 -0
  37. data/lib/arel/algebra/relations/utilities/externalization.rb +24 -0
  38. data/lib/arel/algebra/relations/utilities/nil.rb +7 -0
  39. data/lib/arel/algebra/relations/writes.rb +36 -0
  40. data/lib/arel/algebra/value.rb +14 -0
  41. data/lib/arel/engines.rb +2 -0
  42. data/lib/arel/engines/memory.rb +4 -0
  43. data/lib/arel/engines/memory/engine.rb +16 -0
  44. data/lib/arel/engines/memory/predicates.rb +99 -0
  45. data/lib/arel/engines/memory/primitives.rb +27 -0
  46. data/lib/arel/engines/memory/relations.rb +5 -0
  47. data/lib/arel/engines/memory/relations/array.rb +35 -0
  48. data/lib/arel/engines/memory/relations/compound.rb +9 -0
  49. data/lib/arel/engines/memory/relations/operations.rb +67 -0
  50. data/lib/arel/engines/memory/relations/writes.rb +7 -0
  51. data/lib/arel/engines/sql.rb +8 -0
  52. data/lib/arel/engines/sql/attributes.rb +40 -0
  53. data/lib/arel/engines/sql/christener.rb +14 -0
  54. data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +48 -0
  55. data/lib/arel/engines/sql/compilers/mysql_compiler.rb +11 -0
  56. data/lib/arel/engines/sql/compilers/oracle_compiler.rb +95 -0
  57. data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +42 -0
  58. data/lib/arel/engines/sql/compilers/sqlite_compiler.rb +9 -0
  59. data/lib/arel/engines/sql/core_extensions.rb +4 -0
  60. data/lib/arel/engines/sql/core_extensions/array.rb +24 -0
  61. data/lib/arel/engines/sql/core_extensions/nil_class.rb +15 -0
  62. data/lib/arel/engines/sql/core_extensions/object.rb +19 -0
  63. data/lib/arel/engines/sql/core_extensions/range.rb +19 -0
  64. data/lib/arel/engines/sql/engine.rb +55 -0
  65. data/lib/arel/engines/sql/formatters.rb +122 -0
  66. data/lib/arel/engines/sql/predicates.rb +103 -0
  67. data/lib/arel/engines/sql/primitives.rb +97 -0
  68. data/lib/arel/engines/sql/relations.rb +10 -0
  69. data/lib/arel/engines/sql/relations/compiler.rb +118 -0
  70. data/lib/arel/engines/sql/relations/operations/alias.rb +5 -0
  71. data/lib/arel/engines/sql/relations/operations/join.rb +33 -0
  72. data/lib/arel/engines/sql/relations/relation.rb +65 -0
  73. data/lib/arel/engines/sql/relations/table.rb +88 -0
  74. data/lib/arel/engines/sql/relations/utilities/compound.rb +10 -0
  75. data/lib/arel/engines/sql/relations/utilities/externalization.rb +14 -0
  76. data/lib/arel/engines/sql/relations/utilities/nil.rb +6 -0
  77. data/lib/arel/engines/sql/relations/utilities/recursion.rb +13 -0
  78. data/lib/arel/engines/sql/relations/writes.rb +19 -0
  79. data/lib/arel/session.rb +51 -0
  80. data/lib/arel/version.rb +3 -0
  81. data/spec/algebra/unit/predicates/binary_spec.rb +35 -0
  82. data/spec/algebra/unit/predicates/equality_spec.rb +29 -0
  83. data/spec/algebra/unit/predicates/in_spec.rb +12 -0
  84. data/spec/algebra/unit/primitives/attribute_spec.rb +181 -0
  85. data/spec/algebra/unit/primitives/expression_spec.rb +45 -0
  86. data/spec/algebra/unit/primitives/value_spec.rb +15 -0
  87. data/spec/algebra/unit/relations/alias_spec.rb +16 -0
  88. data/spec/algebra/unit/relations/delete_spec.rb +9 -0
  89. data/spec/algebra/unit/relations/group_spec.rb +10 -0
  90. data/spec/algebra/unit/relations/insert_spec.rb +9 -0
  91. data/spec/algebra/unit/relations/join_spec.rb +25 -0
  92. data/spec/algebra/unit/relations/order_spec.rb +21 -0
  93. data/spec/algebra/unit/relations/project_spec.rb +34 -0
  94. data/spec/algebra/unit/relations/relation_spec.rb +187 -0
  95. data/spec/algebra/unit/relations/skip_spec.rb +10 -0
  96. data/spec/algebra/unit/relations/table_spec.rb +38 -0
  97. data/spec/algebra/unit/relations/take_spec.rb +10 -0
  98. data/spec/algebra/unit/relations/update_spec.rb +9 -0
  99. data/spec/algebra/unit/relations/where_spec.rb +19 -0
  100. data/spec/algebra/unit/session/session_spec.rb +84 -0
  101. data/spec/attributes/boolean_spec.rb +57 -0
  102. data/spec/attributes/float_spec.rb +119 -0
  103. data/spec/attributes/header_spec.rb +42 -0
  104. data/spec/attributes/integer_spec.rb +119 -0
  105. data/spec/attributes/string_spec.rb +43 -0
  106. data/spec/attributes/time_spec.rb +24 -0
  107. data/spec/engines/memory/integration/joins/cross_engine_spec.rb +51 -0
  108. data/spec/engines/memory/unit/relations/array_spec.rb +32 -0
  109. data/spec/engines/memory/unit/relations/insert_spec.rb +28 -0
  110. data/spec/engines/memory/unit/relations/join_spec.rb +31 -0
  111. data/spec/engines/memory/unit/relations/order_spec.rb +27 -0
  112. data/spec/engines/memory/unit/relations/project_spec.rb +27 -0
  113. data/spec/engines/memory/unit/relations/skip_spec.rb +26 -0
  114. data/spec/engines/memory/unit/relations/take_spec.rb +26 -0
  115. data/spec/engines/memory/unit/relations/where_spec.rb +39 -0
  116. data/spec/engines/sql/integration/joins/with_adjacency_spec.rb +258 -0
  117. data/spec/engines/sql/integration/joins/with_aggregations_spec.rb +221 -0
  118. data/spec/engines/sql/integration/joins/with_compounds_spec.rb +137 -0
  119. data/spec/engines/sql/unit/engine_spec.rb +45 -0
  120. data/spec/engines/sql/unit/predicates/binary_spec.rb +140 -0
  121. data/spec/engines/sql/unit/predicates/equality_spec.rb +75 -0
  122. data/spec/engines/sql/unit/predicates/in_spec.rb +179 -0
  123. data/spec/engines/sql/unit/predicates/noteq_spec.rb +75 -0
  124. data/spec/engines/sql/unit/predicates/predicates_spec.rb +79 -0
  125. data/spec/engines/sql/unit/primitives/attribute_spec.rb +36 -0
  126. data/spec/engines/sql/unit/primitives/expression_spec.rb +28 -0
  127. data/spec/engines/sql/unit/primitives/literal_spec.rb +43 -0
  128. data/spec/engines/sql/unit/primitives/value_spec.rb +29 -0
  129. data/spec/engines/sql/unit/relations/alias_spec.rb +53 -0
  130. data/spec/engines/sql/unit/relations/delete_spec.rb +83 -0
  131. data/spec/engines/sql/unit/relations/from_spec.rb +64 -0
  132. data/spec/engines/sql/unit/relations/group_spec.rb +72 -0
  133. data/spec/engines/sql/unit/relations/having_spec.rb +78 -0
  134. data/spec/engines/sql/unit/relations/insert_spec.rb +143 -0
  135. data/spec/engines/sql/unit/relations/join_spec.rb +180 -0
  136. data/spec/engines/sql/unit/relations/lock_spec.rb +86 -0
  137. data/spec/engines/sql/unit/relations/order_spec.rb +161 -0
  138. data/spec/engines/sql/unit/relations/project_spec.rb +143 -0
  139. data/spec/engines/sql/unit/relations/skip_spec.rb +41 -0
  140. data/spec/engines/sql/unit/relations/table_spec.rb +129 -0
  141. data/spec/engines/sql/unit/relations/take_spec.rb +49 -0
  142. data/spec/engines/sql/unit/relations/update_spec.rb +203 -0
  143. data/spec/engines/sql/unit/relations/where_spec.rb +72 -0
  144. data/spec/relations/join_spec.rb +42 -0
  145. data/spec/relations/relation_spec.rb +31 -0
  146. data/spec/shared/relation_spec.rb +255 -0
  147. data/spec/spec_helper.rb +36 -0
  148. data/spec/support/check.rb +6 -0
  149. data/spec/support/connections/mysql_connection.rb +14 -0
  150. data/spec/support/connections/oracle_connection.rb +17 -0
  151. data/spec/support/connections/postgresql_connection.rb +13 -0
  152. data/spec/support/connections/sqlite3_connection.rb +24 -0
  153. data/spec/support/guards.rb +28 -0
  154. data/spec/support/matchers.rb +4 -0
  155. data/spec/support/matchers/be_like.rb +24 -0
  156. data/spec/support/matchers/disambiguate_attributes.rb +28 -0
  157. data/spec/support/matchers/hash_the_same_as.rb +26 -0
  158. data/spec/support/matchers/have_rows.rb +18 -0
  159. data/spec/support/model.rb +62 -0
  160. data/spec/support/schemas/mysql_schema.rb +26 -0
  161. data/spec/support/schemas/oracle_schema.rb +20 -0
  162. data/spec/support/schemas/postgresql_schema.rb +26 -0
  163. data/spec/support/schemas/sqlite3_schema.rb +26 -0
  164. metadata +258 -0
@@ -0,0 +1,97 @@
1
+ module Arel
2
+ class SqlLiteral < String
3
+ def relation
4
+ nil
5
+ end
6
+
7
+ def to_sql(formatter = nil)
8
+ self
9
+ end
10
+
11
+ include Attribute::Expressions
12
+ end
13
+
14
+ class Attribute
15
+ def column
16
+ original_relation.column_for(self)
17
+ end
18
+
19
+ def format(object)
20
+ object.to_sql(Sql::Attribute.new(self))
21
+ end
22
+
23
+ def to_sql(formatter = Sql::WhereCondition.new(relation))
24
+ formatter.attribute self
25
+ end
26
+ end
27
+
28
+ class Value
29
+ def inclusion_predicate_sql
30
+ value.inclusion_predicate_sql
31
+ end
32
+
33
+ def exclusion_predicate_sql
34
+ value.exclusion_predicate_sql
35
+ end
36
+
37
+ def equality_predicate_sql
38
+ value.equality_predicate_sql
39
+ end
40
+
41
+ def inequality_predicate_sql
42
+ value.inequality_predicate_sql
43
+ end
44
+
45
+ def to_sql(formatter = Sql::WhereCondition.new(relation))
46
+ formatter.value value
47
+ end
48
+
49
+ def format(object)
50
+ object.to_sql(Sql::Value.new(relation))
51
+ end
52
+ end
53
+
54
+ class Ordering
55
+ def to_sql(formatter = Sql::OrderClause.new(relation))
56
+ formatter.ordering self
57
+ end
58
+ end
59
+
60
+ class Ascending < Ordering
61
+ def direction_sql; 'ASC' end
62
+ end
63
+
64
+ class Descending < Ordering
65
+ def direction_sql; 'DESC' end
66
+ end
67
+
68
+ class Expression < Attribute
69
+ def to_sql(formatter = Sql::SelectClause.new(relation))
70
+ formatter.expression self
71
+ end
72
+ end
73
+
74
+ class Count < Expression
75
+ def function_sql; 'COUNT' end
76
+ end
77
+
78
+ class Distinct < Expression
79
+ def function_sql; 'DISTINCT' end
80
+ end
81
+
82
+ class Sum < Expression
83
+ def function_sql; 'SUM' end
84
+ end
85
+
86
+ class Maximum < Expression
87
+ def function_sql; 'MAX' end
88
+ end
89
+
90
+ class Minimum < Expression
91
+ def function_sql; 'MIN' end
92
+ end
93
+
94
+ class Average < Expression
95
+ def function_sql; 'AVG' end
96
+ end
97
+ end
@@ -0,0 +1,10 @@
1
+ require 'arel/engines/sql/relations/utilities/compound'
2
+ require 'arel/engines/sql/relations/utilities/recursion'
3
+ require 'arel/engines/sql/relations/utilities/externalization'
4
+ require 'arel/engines/sql/relations/utilities/nil'
5
+ require 'arel/engines/sql/relations/compiler'
6
+ require 'arel/engines/sql/relations/relation'
7
+ require 'arel/engines/sql/relations/table'
8
+ require 'arel/engines/sql/relations/operations/join'
9
+ require 'arel/engines/sql/relations/operations/alias'
10
+ require 'arel/engines/sql/relations/writes'
@@ -0,0 +1,118 @@
1
+ module Arel
2
+ module SqlCompiler
3
+ class GenericCompiler
4
+ attr_reader :relation
5
+
6
+ def initialize(relation)
7
+ @relation = relation
8
+ end
9
+
10
+ def select_sql
11
+ query = build_query \
12
+ "SELECT #{select_clauses.join(', ')}",
13
+ "FROM #{from_clauses}",
14
+ (joins(self) unless joins(self).blank? ),
15
+ ("WHERE #{where_clauses.join(' AND ')}" unless wheres.blank? ),
16
+ ("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
17
+ ("HAVING #{having_clauses.join(' AND ')}" unless havings.blank? ),
18
+ ("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? )
19
+ engine.add_limit_offset!(query,{ :limit => taken, :offset => skipped }) if taken || skipped
20
+ query << " #{locked}" unless locked.blank?
21
+ query
22
+ end
23
+
24
+ def delete_sql
25
+ build_query \
26
+ "DELETE",
27
+ "FROM #{table_sql}",
28
+ ("WHERE #{wheres.collect(&:to_sql).join(' AND ')}" unless wheres.blank? ),
29
+ (add_limit_on_delete(taken) unless taken.blank? )
30
+ end
31
+
32
+ def add_limit_on_delete(taken)
33
+ "LIMIT #{taken}"
34
+ end
35
+
36
+ def insert_sql(include_returning = true)
37
+ insertion_attributes_values_sql = if record.is_a?(Value)
38
+ record.value
39
+ else
40
+ attributes = record.keys.sort_by do |attribute|
41
+ attribute.name.to_s
42
+ end
43
+
44
+ first = attributes.collect do |key|
45
+ engine.quote_column_name(key.name)
46
+ end.join(', ')
47
+
48
+ second = attributes.collect do |key|
49
+ key.format(record[key])
50
+ end.join(', ')
51
+
52
+ build_query "(#{first})", "VALUES (#{second})"
53
+ end
54
+
55
+ build_query \
56
+ "INSERT",
57
+ "INTO #{table_sql}",
58
+ insertion_attributes_values_sql,
59
+ ("RETURNING #{engine.quote_column_name(primary_key)}" if include_returning && compiler.supports_insert_with_returning?)
60
+ end
61
+
62
+ def supports_insert_with_returning?
63
+ false
64
+ end
65
+
66
+ def update_sql
67
+ build_query \
68
+ "UPDATE #{table_sql} SET",
69
+ assignment_sql,
70
+ build_update_conditions_sql
71
+ end
72
+
73
+ protected
74
+ def method_missing(method, *args, &block)
75
+ relation.send(method, *args, &block)
76
+ end
77
+
78
+ def build_query(*parts)
79
+ parts.compact.join(" ")
80
+ end
81
+
82
+ def assignment_sql
83
+ if assignments.respond_to?(:collect)
84
+ attributes = assignments.keys.sort_by do |attribute|
85
+ attribute.name.to_s
86
+ end
87
+
88
+ attributes.map do |attribute|
89
+ value = assignments[attribute]
90
+ "#{engine.quote_column_name(attribute.name)} = #{attribute.format(value)}"
91
+ end.join(", ")
92
+ else
93
+ assignments.value
94
+ end
95
+ end
96
+
97
+ def build_update_conditions_sql
98
+ conditions = ""
99
+ conditions << " WHERE #{wheres.collect(&:to_sql).join(' AND ')}" unless wheres.blank?
100
+ conditions << " ORDER BY #{order_clauses.join(', ')}" unless orders.blank?
101
+
102
+ unless taken.blank?
103
+ conditions = limited_update_conditions(conditions, taken)
104
+ end
105
+
106
+ conditions
107
+ end
108
+
109
+ def limited_update_conditions(conditions, taken)
110
+ conditions << " LIMIT #{taken}"
111
+ quoted_primary_key = engine.quote_column_name(primary_key)
112
+ "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{engine.connection.quote_table_name table.name} #{conditions})"
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,5 @@
1
+ module Arel
2
+ class Alias < Compound
3
+ include Recursion::BaseCase
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ module Arel
2
+ class Join
3
+ def table_sql(formatter = Sql::TableReference.new(self))
4
+ relation1.externalize.table_sql(formatter)
5
+ end
6
+
7
+ def joins(environment, formatter = Sql::TableReference.new(environment))
8
+ @joins ||= begin
9
+ this_join = [
10
+ join_sql,
11
+ relation2.externalize.table_sql(formatter),
12
+ ("ON" unless predicates.blank?),
13
+ (ons + relation2.externalize.wheres).collect { |p| p.bind(environment.relation).to_sql(Sql::WhereClause.new(environment)) }.join(' AND ')
14
+ ].compact.join(" ")
15
+ [relation1.joins(environment), this_join, relation2.joins(environment)].compact.join(" ")
16
+ end
17
+ end
18
+ end
19
+
20
+ class InnerJoin < Join
21
+ def join_sql; "INNER JOIN" end
22
+ end
23
+
24
+ class OuterJoin < Join
25
+ def join_sql; "LEFT OUTER JOIN" end
26
+ end
27
+
28
+ class StringJoin < Join
29
+ def joins(environment, formatter = Sql::TableReference.new(environment))
30
+ [relation1.joins(environment), relation2].compact.join(" ")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ module Arel
2
+ module Relation
3
+ @@connection_tables_primary_keys = {}
4
+
5
+ def compiler
6
+ @compiler ||= begin
7
+ "Arel::SqlCompiler::#{engine.adapter_name}Compiler".constantize.new(self)
8
+ rescue
9
+ Arel::SqlCompiler::GenericCompiler.new(self)
10
+ end
11
+ end
12
+
13
+ def to_sql(formatter = Sql::SelectStatement.new(self))
14
+ formatter.select compiler.select_sql, self
15
+ end
16
+
17
+ def christener
18
+ @christener ||= Sql::Christener.new
19
+ end
20
+
21
+ def inclusion_predicate_sql
22
+ "IN"
23
+ end
24
+
25
+ def exclusion_predicate_sql
26
+ "NOT IN"
27
+ end
28
+
29
+ def primary_key
30
+ connection_id = engine.connection.object_id
31
+ if @@connection_tables_primary_keys[connection_id] && @@connection_tables_primary_keys[connection_id].has_key?(table.name)
32
+ @@connection_tables_primary_keys[connection_id][table.name]
33
+ else
34
+ @@connection_tables_primary_keys[connection_id] ||= {}
35
+ @@connection_tables_primary_keys[connection_id][table.name] = engine.connection.primary_key(table.name)
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def from_clauses
42
+ sources.blank? ? table_sql(Sql::TableReference.new(self)) : sources
43
+ end
44
+
45
+ def select_clauses
46
+ attributes.collect { |a| a.to_sql(Sql::SelectClause.new(self)) }
47
+ end
48
+
49
+ def where_clauses
50
+ wheres.collect { |w| w.to_sql(Sql::WhereClause.new(self)) }
51
+ end
52
+
53
+ def group_clauses
54
+ groupings.collect { |g| g.to_sql(Sql::GroupClause.new(self)) }
55
+ end
56
+
57
+ def having_clauses
58
+ havings.collect { |g| g.to_sql(Sql::HavingClause.new(self)) }
59
+ end
60
+
61
+ def order_clauses
62
+ orders.collect { |o| o.to_sql(Sql::OrderClause.new(self)) }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,88 @@
1
+ module Arel
2
+ class Table
3
+ include Relation, Recursion::BaseCase
4
+
5
+ cattr_accessor :engine, :tables
6
+ attr_reader :name, :engine, :table_alias, :options
7
+
8
+ def initialize(name, options = {})
9
+ @name = name.to_s
10
+ @table_exists = nil
11
+
12
+ if options.is_a?(Hash)
13
+ @options = options
14
+ @engine = options[:engine] || Table.engine
15
+ @table_alias = options[:as].to_s if options[:as].present? && options[:as].to_s != @name
16
+ else
17
+ @engine = options # Table.new('foo', engine)
18
+ end
19
+
20
+ if @engine.connection
21
+ begin
22
+ require "arel/engines/sql/compilers/#{@engine.adapter_name.downcase}_compiler"
23
+ @@tables ||= engine.tables
24
+ rescue LoadError
25
+ raise "#{@engine.adapter_name} is not supported by Arel."
26
+ end
27
+ end
28
+ end
29
+
30
+ def as(table_alias)
31
+ Table.new(name, options.merge(:as => table_alias))
32
+ end
33
+
34
+ def table_exists?
35
+ if @table_exists
36
+ true
37
+ else
38
+ @table_exists = @@tables.include?(name) || engine.table_exists?(name)
39
+ end
40
+ end
41
+
42
+ def attributes
43
+ return @attributes if defined?(@attributes)
44
+ if table_exists?
45
+ @attributes ||= begin
46
+ attrs = columns.collect do |column|
47
+ Sql::Attributes.for(column).new(column, self, column.name.to_sym)
48
+ end
49
+ Header.new(attrs)
50
+ end
51
+ else
52
+ Header.new
53
+ end
54
+ end
55
+
56
+ def eql?(other)
57
+ self == other
58
+ end
59
+
60
+ def hash
61
+ @hash ||= :name.hash
62
+ end
63
+
64
+ def column_for(attribute)
65
+ has_attribute?(attribute) and columns.detect { |c| c.name == attribute.name.to_s }
66
+ end
67
+
68
+ def columns
69
+ @columns ||= engine.columns(name, "#{name} Columns")
70
+ end
71
+
72
+ def reset
73
+ @columns = nil
74
+ @attributes = Header.new([])
75
+ end
76
+
77
+ def ==(other)
78
+ Table === other and
79
+ name == other.name and
80
+ table_alias == other.table_alias
81
+ end
82
+ end
83
+ end
84
+
85
+ def Table(name, engine = Arel::Table.engine)
86
+ Arel::Table.new(name, engine)
87
+ end
88
+
@@ -0,0 +1,10 @@
1
+ module Arel
2
+ class Compound
3
+ delegate :table, :table_sql, :to => :relation
4
+
5
+ def build_query(*parts)
6
+ parts.compact.join(" ")
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,14 @@
1
+ module Arel
2
+ class Externalization < Compound
3
+ include Recursion::BaseCase
4
+
5
+ def table_sql(formatter = Sql::TableReference.new(relation))
6
+ formatter.select relation.compiler.select_sql, self
7
+ end
8
+
9
+ # REMOVEME
10
+ def name
11
+ relation.name + '_external'
12
+ end
13
+ end
14
+ end