activerecord 4.0.4 → 4.1.16

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1632 -1797
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/examples/performance.rb +30 -18
  6. data/examples/simple.rb +4 -4
  7. data/lib/active_record/aggregations.rb +2 -1
  8. data/lib/active_record/association_relation.rb +4 -0
  9. data/lib/active_record/associations/alias_tracker.rb +49 -29
  10. data/lib/active_record/associations/association.rb +9 -17
  11. data/lib/active_record/associations/association_scope.rb +59 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +34 -25
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +6 -1
  14. data/lib/active_record/associations/builder/association.rb +84 -54
  15. data/lib/active_record/associations/builder/belongs_to.rb +90 -58
  16. data/lib/active_record/associations/builder/collection_association.rb +47 -45
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +119 -25
  18. data/lib/active_record/associations/builder/has_many.rb +3 -3
  19. data/lib/active_record/associations/builder/has_one.rb +5 -7
  20. data/lib/active_record/associations/builder/singular_association.rb +6 -7
  21. data/lib/active_record/associations/collection_association.rb +121 -111
  22. data/lib/active_record/associations/collection_proxy.rb +73 -18
  23. data/lib/active_record/associations/has_many_association.rb +14 -11
  24. data/lib/active_record/associations/has_many_through_association.rb +33 -6
  25. data/lib/active_record/associations/has_one_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency/join_association.rb +46 -104
  27. data/lib/active_record/associations/join_dependency/join_base.rb +6 -8
  28. data/lib/active_record/associations/join_dependency/join_part.rb +18 -37
  29. data/lib/active_record/associations/join_dependency.rb +208 -168
  30. data/lib/active_record/associations/preloader/association.rb +69 -27
  31. data/lib/active_record/associations/preloader/collection_association.rb +2 -2
  32. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  33. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  34. data/lib/active_record/associations/preloader/through_association.rb +58 -26
  35. data/lib/active_record/associations/preloader.rb +63 -49
  36. data/lib/active_record/associations/singular_association.rb +6 -5
  37. data/lib/active_record/associations/through_association.rb +30 -9
  38. data/lib/active_record/associations.rb +116 -42
  39. data/lib/active_record/attribute_assignment.rb +6 -3
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -1
  41. data/lib/active_record/attribute_methods/dirty.rb +35 -26
  42. data/lib/active_record/attribute_methods/primary_key.rb +8 -1
  43. data/lib/active_record/attribute_methods/read.rb +56 -29
  44. data/lib/active_record/attribute_methods/serialization.rb +44 -12
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +13 -1
  46. data/lib/active_record/attribute_methods/write.rb +59 -26
  47. data/lib/active_record/attribute_methods.rb +82 -43
  48. data/lib/active_record/autosave_association.rb +209 -194
  49. data/lib/active_record/base.rb +6 -2
  50. data/lib/active_record/callbacks.rb +2 -2
  51. data/lib/active_record/coders/json.rb +13 -0
  52. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +5 -10
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +14 -24
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -13
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +6 -3
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +90 -0
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +9 -8
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +45 -70
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -0
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -96
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +74 -66
  63. data/lib/active_record/connection_adapters/column.rb +1 -35
  64. data/lib/active_record/connection_adapters/connection_specification.rb +231 -43
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -5
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +24 -17
  67. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +22 -15
  68. data/lib/active_record/connection_adapters/postgresql/cast.rb +12 -4
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -44
  70. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -14
  71. data/lib/active_record/connection_adapters/postgresql/quoting.rb +37 -12
  72. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +20 -11
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +98 -52
  74. data/lib/active_record/connection_adapters/schema_cache.rb +8 -29
  75. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -60
  76. data/lib/active_record/connection_handling.rb +39 -5
  77. data/lib/active_record/core.rb +38 -54
  78. data/lib/active_record/counter_cache.rb +9 -10
  79. data/lib/active_record/dynamic_matchers.rb +6 -2
  80. data/lib/active_record/enum.rb +199 -0
  81. data/lib/active_record/errors.rb +22 -5
  82. data/lib/active_record/fixture_set/file.rb +2 -1
  83. data/lib/active_record/fixtures.rb +173 -76
  84. data/lib/active_record/gem_version.rb +15 -0
  85. data/lib/active_record/inheritance.rb +23 -9
  86. data/lib/active_record/integration.rb +54 -1
  87. data/lib/active_record/locking/optimistic.rb +7 -2
  88. data/lib/active_record/locking/pessimistic.rb +1 -1
  89. data/lib/active_record/log_subscriber.rb +6 -13
  90. data/lib/active_record/migration/command_recorder.rb +8 -2
  91. data/lib/active_record/migration.rb +91 -56
  92. data/lib/active_record/model_schema.rb +7 -14
  93. data/lib/active_record/nested_attributes.rb +25 -13
  94. data/lib/active_record/no_touching.rb +52 -0
  95. data/lib/active_record/null_relation.rb +26 -6
  96. data/lib/active_record/persistence.rb +23 -29
  97. data/lib/active_record/querying.rb +15 -12
  98. data/lib/active_record/railtie.rb +12 -61
  99. data/lib/active_record/railties/databases.rake +37 -56
  100. data/lib/active_record/readonly_attributes.rb +0 -6
  101. data/lib/active_record/reflection.rb +230 -79
  102. data/lib/active_record/relation/batches.rb +74 -24
  103. data/lib/active_record/relation/calculations.rb +52 -48
  104. data/lib/active_record/relation/delegation.rb +54 -39
  105. data/lib/active_record/relation/finder_methods.rb +210 -67
  106. data/lib/active_record/relation/merger.rb +15 -12
  107. data/lib/active_record/relation/predicate_builder/array_handler.rb +29 -0
  108. data/lib/active_record/relation/predicate_builder/relation_handler.rb +17 -0
  109. data/lib/active_record/relation/predicate_builder.rb +81 -40
  110. data/lib/active_record/relation/query_methods.rb +185 -108
  111. data/lib/active_record/relation/spawn_methods.rb +8 -5
  112. data/lib/active_record/relation.rb +79 -84
  113. data/lib/active_record/result.rb +45 -6
  114. data/lib/active_record/runtime_registry.rb +5 -0
  115. data/lib/active_record/sanitization.rb +4 -4
  116. data/lib/active_record/schema_dumper.rb +18 -6
  117. data/lib/active_record/schema_migration.rb +31 -18
  118. data/lib/active_record/scoping/default.rb +5 -18
  119. data/lib/active_record/scoping/named.rb +14 -29
  120. data/lib/active_record/scoping.rb +5 -0
  121. data/lib/active_record/store.rb +67 -18
  122. data/lib/active_record/tasks/database_tasks.rb +66 -26
  123. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -10
  124. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  125. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  126. data/lib/active_record/timestamp.rb +6 -6
  127. data/lib/active_record/transactions.rb +10 -12
  128. data/lib/active_record/validations/presence.rb +1 -1
  129. data/lib/active_record/validations/uniqueness.rb +19 -9
  130. data/lib/active_record/version.rb +4 -7
  131. data/lib/active_record.rb +5 -7
  132. data/lib/rails/generators/active_record/migration/migration_generator.rb +4 -0
  133. data/lib/rails/generators/active_record/migration.rb +18 -0
  134. data/lib/rails/generators/active_record/model/model_generator.rb +4 -0
  135. data/lib/rails/generators/active_record.rb +2 -8
  136. metadata +18 -30
  137. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -65
  138. data/lib/active_record/associations/join_helper.rb +0 -45
  139. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +0 -56
  141. data/lib/active_record/tasks/oracle_database_tasks.rb +0 -45
  142. data/lib/active_record/tasks/sqlserver_database_tasks.rb +0 -48
  143. data/lib/active_record/test_case.rb +0 -96
@@ -18,25 +18,16 @@ module ActiveRecord
18
18
  end
19
19
  end
20
20
 
21
- # Returns an array of record hashes with the column names as keys and
22
- # column values as values.
21
+ # Returns an ActiveRecord::Result instance.
23
22
  def select_all(arel, name = nil, binds = [])
24
- if arel.is_a?(Relation)
25
- relation = arel
26
- arel = relation.arel
27
- if !binds || binds.empty?
28
- binds = relation.bind_values
29
- end
30
- end
31
-
23
+ arel, binds = binds_from_relation arel, binds
32
24
  select(to_sql(arel, binds), name, binds)
33
25
  end
34
26
 
35
27
  # Returns a record hash with the column names as keys and column values
36
28
  # as values.
37
29
  def select_one(arel, name = nil, binds = [])
38
- result = select_all(arel, name, binds)
39
- result.first if result
30
+ select_all(arel, name, binds).first
40
31
  end
41
32
 
42
33
  # Returns a single value from a record
@@ -49,10 +40,7 @@ module ActiveRecord
49
40
  # Returns an array of the values of the first column in a select:
50
41
  # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
51
42
  def select_values(arel, name = nil)
52
- binds = []
53
- if arel.is_a?(Relation)
54
- arel, binds = arel.arel, arel.bind_values
55
- end
43
+ arel, binds = binds_from_relation arel, []
56
44
  select_rows(to_sql(arel, binds), name, binds).map(&:first)
57
45
  end
58
46
 
@@ -314,10 +302,6 @@ module ActiveRecord
314
302
  "DEFAULT VALUES"
315
303
  end
316
304
 
317
- def case_sensitive_equality_operator
318
- "="
319
- end
320
-
321
305
  def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
322
306
  "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
323
307
  end
@@ -334,7 +318,7 @@ module ActiveRecord
334
318
  def sanitize_limit(limit)
335
319
  if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
336
320
  limit
337
- elsif limit.to_s =~ /,/
321
+ elsif limit.to_s.include?(',')
338
322
  Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
339
323
  else
340
324
  Integer(limit)
@@ -359,15 +343,14 @@ module ActiveRecord
359
343
 
360
344
  protected
361
345
 
362
- # Return a subquery for the given key using the join information.
346
+ # Returns a subquery for the given key using the join information.
363
347
  def subquery_for(key, select)
364
348
  subselect = select.clone
365
349
  subselect.projections = [key]
366
350
  subselect
367
351
  end
368
352
 
369
- # Returns an array of record hashes with the column names as keys and
370
- # column values as values.
353
+ # Returns an ActiveRecord::Result instance.
371
354
  def select(sql, name = nil, binds = [])
372
355
  end
373
356
  undef_method :select
@@ -396,6 +379,13 @@ module ActiveRecord
396
379
  row = result.rows.first
397
380
  row && row.first
398
381
  end
382
+
383
+ def binds_from_relation(relation, binds)
384
+ if relation.is_a?(Relation) && binds.blank?
385
+ relation, binds = relation.arel, relation.bind_values
386
+ end
387
+ [relation, binds]
388
+ end
399
389
  end
400
390
  end
401
391
  end
@@ -9,10 +9,10 @@ module ActiveRecord
9
9
  def dirties_query_cache(base, *method_names)
10
10
  method_names.each do |method_name|
11
11
  base.class_eval <<-end_code, __FILE__, __LINE__ + 1
12
- def #{method_name}(*) # def update_with_query_dirty(*)
13
- clear_query_cache if @query_cache_enabled # clear_query_cache if @query_cache_enabled
14
- super # super
15
- end # end
12
+ def #{method_name}(*)
13
+ clear_query_cache if @query_cache_enabled
14
+ super
15
+ end
16
16
  end_code
17
17
  end
18
18
  end
@@ -20,13 +20,19 @@ module ActiveRecord
20
20
 
21
21
  attr_reader :query_cache, :query_cache_enabled
22
22
 
23
+ def initialize(*)
24
+ super
25
+ @query_cache = Hash.new { |h,sql| h[sql] = {} }
26
+ @query_cache_enabled = false
27
+ end
28
+
23
29
  # Enable the query cache within the block.
24
30
  def cache
25
31
  old, @query_cache_enabled = @query_cache_enabled, true
26
32
  yield
27
33
  ensure
28
- clear_query_cache
29
34
  @query_cache_enabled = old
35
+ clear_query_cache unless @query_cache_enabled
30
36
  end
31
37
 
32
38
  def enable_query_cache!
@@ -57,6 +63,7 @@ module ActiveRecord
57
63
 
58
64
  def select_all(arel, name = nil, binds = [])
59
65
  if @query_cache_enabled && !locked?(arel)
66
+ arel, binds = binds_from_relation arel, binds
60
67
  sql = to_sql(arel, binds)
61
68
  cache_sql(sql, binds) { super(sql, name, binds) }
62
69
  else
@@ -75,14 +82,7 @@ module ActiveRecord
75
82
  else
76
83
  @query_cache[sql][binds] = yield
77
84
  end
78
-
79
- # FIXME: we should guarantee that all cached items are Result
80
- # objects. Then we can avoid this conditional
81
- if ActiveRecord::Result === result
82
- result.dup
83
- else
84
- result.collect { |row| row.dup }
85
- end
85
+ result.dup
86
86
  end
87
87
 
88
88
  # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
@@ -15,7 +15,6 @@ module ActiveRecord
15
15
  return "'#{quote_string(value)}'" unless column
16
16
 
17
17
  case column.type
18
- when :binary then "'#{quote_string(column.string_to_binary(value))}'"
19
18
  when :integer then value.to_i.to_s
20
19
  when :float then value.to_f.to_s
21
20
  else
@@ -31,7 +30,12 @@ module ActiveRecord
31
30
  # BigDecimals need to be put in a non-normalized form and quoted.
32
31
  when nil then "NULL"
33
32
  when BigDecimal then value.to_s('F')
34
- when Numeric, ActiveSupport::Duration then value.to_s
33
+ when Numeric, ActiveSupport::Duration
34
+ if column.try(:type) == :string
35
+ quote(value.to_s, column)
36
+ else
37
+ value.to_s
38
+ end
35
39
  when Date, Time then "'#{quoted_date(value)}'"
36
40
  when Symbol then "'#{quote_string(value.to_s)}'"
37
41
  when Class then "'#{value.to_s}'"
@@ -54,7 +58,6 @@ module ActiveRecord
54
58
  return value unless column
55
59
 
56
60
  case column.type
57
- when :binary then value
58
61
  when :integer then value.to_i
59
62
  when :float then value.to_f
60
63
  else
@@ -0,0 +1,21 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Savepoints #:nodoc:
4
+ def supports_savepoints?
5
+ true
6
+ end
7
+
8
+ def create_savepoint(name = current_savepoint_name)
9
+ execute("SAVEPOINT #{name}")
10
+ end
11
+
12
+ def rollback_to_savepoint(name = current_savepoint_name)
13
+ execute("ROLLBACK TO SAVEPOINT #{name}")
14
+ end
15
+
16
+ def release_savepoint(name = current_savepoint_name)
17
+ execute("RELEASE SAVEPOINT #{name}")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,90 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class AbstractAdapter
4
+ class SchemaCreation # :nodoc:
5
+ def initialize(conn)
6
+ @conn = conn
7
+ @cache = {}
8
+ end
9
+
10
+ def accept(o)
11
+ m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
12
+ send m, o
13
+ end
14
+
15
+ def visit_AddColumn(o)
16
+ sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
17
+ sql = "ADD #{quote_column_name(o.name)} #{sql_type}"
18
+ add_column_options!(sql, column_options(o))
19
+ end
20
+
21
+ private
22
+
23
+ def visit_AlterTable(o)
24
+ sql = "ALTER TABLE #{quote_table_name(o.name)} "
25
+ sql << o.adds.map { |col| visit_AddColumn col }.join(' ')
26
+ end
27
+
28
+ def visit_ColumnDefinition(o)
29
+ sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
30
+ column_sql = "#{quote_column_name(o.name)} #{sql_type}"
31
+ add_column_options!(column_sql, column_options(o)) unless o.primary_key?
32
+ column_sql
33
+ end
34
+
35
+ def visit_TableDefinition(o)
36
+ create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
37
+ create_sql << "#{quote_table_name(o.name)} "
38
+ create_sql << "(#{o.columns.map { |c| accept c }.join(', ')}) " unless o.as
39
+ create_sql << "#{o.options}"
40
+ create_sql << " AS #{@conn.to_sql(o.as)}" if o.as
41
+ create_sql
42
+ end
43
+
44
+ def column_options(o)
45
+ column_options = {}
46
+ column_options[:null] = o.null unless o.null.nil?
47
+ column_options[:default] = o.default unless o.default.nil?
48
+ column_options[:column] = o
49
+ column_options[:first] = o.first
50
+ column_options[:after] = o.after
51
+ column_options
52
+ end
53
+
54
+ def quote_column_name(name)
55
+ @conn.quote_column_name name
56
+ end
57
+
58
+ def quote_table_name(name)
59
+ @conn.quote_table_name name
60
+ end
61
+
62
+ def type_to_sql(type, limit, precision, scale)
63
+ @conn.type_to_sql type.to_sym, limit, precision, scale
64
+ end
65
+
66
+ def add_column_options!(sql, options)
67
+ sql << " DEFAULT #{quote_value(options[:default], options[:column])}" if options_include_default?(options)
68
+ # must explicitly check for :null to allow change_column to work on migrations
69
+ if options[:null] == false
70
+ sql << " NOT NULL"
71
+ end
72
+ if options[:auto_increment] == true
73
+ sql << " AUTO_INCREMENT"
74
+ end
75
+ sql
76
+ end
77
+
78
+ def quote_value(value, column)
79
+ column.sql_type ||= type_to_sql(column.type, column.limit, column.precision, column.scale)
80
+
81
+ @conn.quote(value, column)
82
+ end
83
+
84
+ def options_include_default?(options)
85
+ options.include?(:default) && !(options[:null] == false && options[:default].nil?)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -15,16 +15,16 @@ module ActiveRecord
15
15
  # are typically created by methods in TableDefinition, and added to the
16
16
  # +columns+ attribute of said TableDefinition object, in order to be used
17
17
  # for generating a number of table creation or table changing SQL statements.
18
- class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key) #:nodoc:
19
- def string_to_binary(value)
20
- value
21
- end
18
+ class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type) #:nodoc:
22
19
 
23
20
  def primary_key?
24
21
  primary_key || type.to_sym == :primary_key
25
22
  end
26
23
  end
27
24
 
25
+ class ChangeColumnDefinition < Struct.new(:column, :type, :options) #:nodoc:
26
+ end
27
+
28
28
  # Represents the schema of an SQL table in an abstract way. This class
29
29
  # provides methods for manipulating the schema representation.
30
30
  #
@@ -49,14 +49,15 @@ module ActiveRecord
49
49
  # An array of ColumnDefinition objects, representing the column changes
50
50
  # that have been defined.
51
51
  attr_accessor :indexes
52
- attr_reader :name, :temporary, :options
52
+ attr_reader :name, :temporary, :options, :as
53
53
 
54
- def initialize(types, name, temporary, options)
54
+ def initialize(types, name, temporary, options, as = nil)
55
55
  @columns_hash = {}
56
56
  @indexes = {}
57
57
  @native = types
58
58
  @temporary = temporary
59
59
  @options = options
60
+ @as = as
60
61
  @name = name
61
62
  end
62
63
 
@@ -393,8 +394,8 @@ module ActiveRecord
393
394
  # Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
394
395
  #
395
396
  # t.timestamps
396
- def timestamps
397
- @base.add_timestamps(@table_name)
397
+ def timestamps(options = {})
398
+ @base.add_timestamps(@table_name, options)
398
399
  end
399
400
 
400
401
  # Changes the column's definition according to the new options.
@@ -40,7 +40,7 @@ module ActiveRecord
40
40
  # index_exists?(:suppliers, :company_id, unique: true)
41
41
  #
42
42
  # # Check an index with a custom name exists
43
- # index_exists?(:suppliers, :company_id, name: "idx_company_id"
43
+ # index_exists?(:suppliers, :company_id, name: "idx_company_id")
44
44
  #
45
45
  def index_exists?(table_name, column_name, options = {})
46
46
  column_names = Array(column_name)
@@ -131,6 +131,9 @@ module ActiveRecord
131
131
  # [<tt>:force</tt>]
132
132
  # Set to true to drop the table before creating it.
133
133
  # Defaults to false.
134
+ # [<tt>:as</tt>]
135
+ # SQL to use to generate the table. When this option is used, the block is
136
+ # ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
134
137
  #
135
138
  # ====== Add a backend specific option to the generated SQL (MySQL)
136
139
  #
@@ -169,19 +172,31 @@ module ActiveRecord
169
172
  # supplier_id int
170
173
  # )
171
174
  #
175
+ # ====== Create a temporary table based on a query
176
+ #
177
+ # create_table(:long_query, temporary: true,
178
+ # as: "SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id")
179
+ #
180
+ # generates:
181
+ #
182
+ # CREATE TEMPORARY TABLE long_query AS
183
+ # SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
184
+ #
172
185
  # See also TableDefinition#column for details on how to create columns.
173
186
  def create_table(table_name, options = {})
174
- td = create_table_definition table_name, options[:temporary], options[:options]
187
+ td = create_table_definition table_name, options[:temporary], options[:options], options[:as]
175
188
 
176
- unless options[:id] == false
177
- pk = options.fetch(:primary_key) {
178
- Base.get_primary_key table_name.to_s.singularize
179
- }
189
+ if !options[:as]
190
+ unless options[:id] == false
191
+ pk = options.fetch(:primary_key) {
192
+ Base.get_primary_key table_name.to_s.singularize
193
+ }
180
194
 
181
- td.primary_key pk, options.fetch(:id, :primary_key), options
182
- end
195
+ td.primary_key pk, options.fetch(:id, :primary_key), options
196
+ end
183
197
 
184
- yield td if block_given?
198
+ yield td if block_given?
199
+ end
185
200
 
186
201
  if options[:force] && table_exists?(table_name)
187
202
  drop_table(table_name, options)
@@ -558,8 +573,8 @@ module ActiveRecord
558
573
  # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
559
574
  old_index_def = indexes(table_name).detect { |i| i.name == old_name }
560
575
  return unless old_index_def
561
- remove_index(table_name, :name => old_name)
562
- add_index(table_name, old_index_def.columns, :name => new_name, :unique => old_index_def.unique)
576
+ add_index(table_name, old_index_def.columns, name: new_name, unique: old_index_def.unique)
577
+ remove_index(table_name, name: old_name)
563
578
  end
564
579
 
565
580
  def index_name(table_name, options) #:nodoc:
@@ -606,7 +621,7 @@ module ActiveRecord
606
621
  index_options = options.delete(:index)
607
622
  add_column(table_name, "#{ref_name}_id", :integer, options)
608
623
  add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
609
- add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
624
+ add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
610
625
  end
611
626
  alias :add_belongs_to :add_reference
612
627
 
@@ -694,26 +709,6 @@ module ActiveRecord
694
709
  end
695
710
  end
696
711
 
697
- def add_column_options!(sql, options) #:nodoc:
698
- sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
699
- # must explicitly check for :null to allow change_column to work on migrations
700
- if options[:null] == false
701
- sql << " NOT NULL"
702
- end
703
- if options[:auto_increment] == true
704
- sql << " AUTO_INCREMENT"
705
- end
706
- end
707
-
708
- # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
709
- #
710
- # distinct("posts.id", ["posts.created_at desc"])
711
- #
712
- def distinct(columns, order_by)
713
- ActiveSupport::Deprecation.warn("#distinct is deprecated and shall be removed from future releases.")
714
- "DISTINCT #{columns_for_distinct(columns, order_by)}"
715
- end
716
-
717
712
  # Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
718
713
  # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax - they
719
714
  # require the order columns appear in the SELECT.
@@ -727,9 +722,9 @@ module ActiveRecord
727
722
  #
728
723
  # add_timestamps(:suppliers)
729
724
  #
730
- def add_timestamps(table_name)
731
- add_column table_name, :created_at, :datetime
732
- add_column table_name, :updated_at, :datetime
725
+ def add_timestamps(table_name, options = {})
726
+ add_column table_name, :created_at, :datetime, options
727
+ add_column table_name, :updated_at, :datetime, options
733
728
  end
734
729
 
735
730
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
@@ -779,37 +774,23 @@ module ActiveRecord
779
774
  column_names = Array(column_name)
780
775
  index_name = index_name(table_name, column: column_names)
781
776
 
782
- if Hash === options # legacy support, since this param was a string
783
- options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
784
-
785
- index_type = options[:unique] ? "UNIQUE" : ""
786
- index_type = options[:type].to_s if options.key?(:type)
787
- index_name = options[:name].to_s if options.key?(:name)
788
- max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
789
-
790
- if options.key?(:algorithm)
791
- algorithm = index_algorithms.fetch(options[:algorithm]) {
792
- raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}")
793
- }
794
- end
777
+ options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
795
778
 
796
- using = "USING #{options[:using]}" if options[:using].present?
779
+ index_type = options[:unique] ? "UNIQUE" : ""
780
+ index_type = options[:type].to_s if options.key?(:type)
781
+ index_name = options[:name].to_s if options.key?(:name)
782
+ max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
797
783
 
798
- if supports_partial_index?
799
- index_options = options[:where] ? " WHERE #{options[:where]}" : ""
800
- end
801
- else
802
- if options
803
- message = "Passing a string as third argument of `add_index` is deprecated and will" +
804
- " be removed in Rails 4.1." +
805
- " Use add_index(#{table_name.inspect}, #{column_name.inspect}, unique: true) instead"
784
+ if options.key?(:algorithm)
785
+ algorithm = index_algorithms.fetch(options[:algorithm]) {
786
+ raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}")
787
+ }
788
+ end
806
789
 
807
- ActiveSupport::Deprecation.warn message
808
- end
790
+ using = "USING #{options[:using]}" if options[:using].present?
809
791
 
810
- index_type = options
811
- max_index_length = allowed_index_name_length
812
- algorithm = using = nil
792
+ if supports_partial_index?
793
+ index_options = options[:where] ? " WHERE #{options[:where]}" : ""
813
794
  end
814
795
 
815
796
  if index_name.length > max_index_length
@@ -841,12 +822,6 @@ module ActiveRecord
841
822
  index_name
842
823
  end
843
824
 
844
- def columns_for_remove(table_name, *column_names)
845
- ActiveSupport::Deprecation.warn("columns_for_remove is deprecated and will be removed in the future")
846
- raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)") if column_names.blank?
847
- column_names.map {|column_name| quote_column_name(column_name) }
848
- end
849
-
850
825
  def rename_table_indexes(table_name, new_name)
851
826
  indexes(new_name).each do |index|
852
827
  generated_index_name = index_name(table_name, column: index.columns)
@@ -870,8 +845,8 @@ module ActiveRecord
870
845
  end
871
846
 
872
847
  private
873
- def create_table_definition(name, temporary, options)
874
- TableDefinition.new native_database_types, name, temporary, options
848
+ def create_table_definition(name, temporary, options, as = nil)
849
+ TableDefinition.new native_database_types, name, temporary, options, as
875
850
  end
876
851
 
877
852
  def create_alter_table(name)
@@ -201,6 +201,7 @@ module ActiveRecord
201
201
  @state.set_state(:committed)
202
202
  @state.parent = parent.state
203
203
  connection.release_savepoint
204
+ records.each { |r| parent.add_record(r) }
204
205
  end
205
206
  end
206
207
  end