activerecord 3.1.12 → 3.2.22.1

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +804 -338
  3. data/README.rdoc +3 -3
  4. data/examples/performance.rb +20 -1
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/associations/alias_tracker.rb +3 -6
  7. data/lib/active_record/associations/association.rb +13 -45
  8. data/lib/active_record/associations/association_scope.rb +3 -15
  9. data/lib/active_record/associations/belongs_to_association.rb +1 -1
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +2 -1
  11. data/lib/active_record/associations/builder/association.rb +6 -4
  12. data/lib/active_record/associations/builder/belongs_to.rb +7 -4
  13. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  14. data/lib/active_record/associations/builder/has_many.rb +4 -4
  15. data/lib/active_record/associations/builder/has_one.rb +5 -6
  16. data/lib/active_record/associations/builder/singular_association.rb +3 -16
  17. data/lib/active_record/associations/collection_association.rb +65 -32
  18. data/lib/active_record/associations/collection_proxy.rb +8 -41
  19. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +1 -0
  20. data/lib/active_record/associations/has_many_association.rb +11 -7
  21. data/lib/active_record/associations/has_many_through_association.rb +19 -9
  22. data/lib/active_record/associations/has_one_association.rb +23 -13
  23. data/lib/active_record/associations/join_dependency/join_association.rb +6 -1
  24. data/lib/active_record/associations/join_dependency.rb +3 -3
  25. data/lib/active_record/associations/preloader/through_association.rb +3 -3
  26. data/lib/active_record/associations/preloader.rb +14 -10
  27. data/lib/active_record/associations/through_association.rb +8 -4
  28. data/lib/active_record/associations.rb +92 -76
  29. data/lib/active_record/attribute_assignment.rb +221 -0
  30. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  31. data/lib/active_record/attribute_methods/dirty.rb +21 -11
  32. data/lib/active_record/attribute_methods/primary_key.rb +62 -25
  33. data/lib/active_record/attribute_methods/read.rb +73 -83
  34. data/lib/active_record/attribute_methods/serialization.rb +120 -0
  35. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
  36. data/lib/active_record/attribute_methods/write.rb +32 -6
  37. data/lib/active_record/attribute_methods.rb +231 -30
  38. data/lib/active_record/autosave_association.rb +44 -26
  39. data/lib/active_record/base.rb +227 -1708
  40. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +150 -148
  41. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +85 -29
  42. data/lib/active_record/connection_adapters/abstract/database_statements.rb +7 -34
  43. data/lib/active_record/connection_adapters/abstract/query_cache.rb +10 -2
  44. data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -4
  45. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +39 -28
  46. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +48 -19
  47. data/lib/active_record/connection_adapters/abstract_adapter.rb +77 -42
  48. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
  49. data/lib/active_record/connection_adapters/column.rb +37 -11
  50. data/lib/active_record/connection_adapters/mysql2_adapter.rb +133 -581
  51. data/lib/active_record/connection_adapters/mysql_adapter.rb +136 -693
  52. data/lib/active_record/connection_adapters/postgresql_adapter.rb +209 -97
  53. data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
  54. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
  55. data/lib/active_record/connection_adapters/sqlite_adapter.rb +62 -35
  56. data/lib/active_record/counter_cache.rb +9 -4
  57. data/lib/active_record/dynamic_finder_match.rb +12 -0
  58. data/lib/active_record/dynamic_matchers.rb +84 -0
  59. data/lib/active_record/errors.rb +11 -1
  60. data/lib/active_record/explain.rb +86 -0
  61. data/lib/active_record/explain_subscriber.rb +25 -0
  62. data/lib/active_record/fixtures/file.rb +65 -0
  63. data/lib/active_record/fixtures.rb +57 -86
  64. data/lib/active_record/identity_map.rb +3 -4
  65. data/lib/active_record/inheritance.rb +174 -0
  66. data/lib/active_record/integration.rb +60 -0
  67. data/lib/active_record/locking/optimistic.rb +33 -26
  68. data/lib/active_record/locking/pessimistic.rb +23 -1
  69. data/lib/active_record/log_subscriber.rb +8 -4
  70. data/lib/active_record/migration/command_recorder.rb +8 -8
  71. data/lib/active_record/migration.rb +68 -35
  72. data/lib/active_record/model_schema.rb +368 -0
  73. data/lib/active_record/nested_attributes.rb +60 -24
  74. data/lib/active_record/persistence.rb +57 -11
  75. data/lib/active_record/query_cache.rb +6 -6
  76. data/lib/active_record/querying.rb +58 -0
  77. data/lib/active_record/railtie.rb +37 -29
  78. data/lib/active_record/railties/controller_runtime.rb +3 -1
  79. data/lib/active_record/railties/databases.rake +213 -117
  80. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  81. data/lib/active_record/readonly_attributes.rb +26 -0
  82. data/lib/active_record/reflection.rb +7 -15
  83. data/lib/active_record/relation/batches.rb +7 -4
  84. data/lib/active_record/relation/calculations.rb +55 -16
  85. data/lib/active_record/relation/delegation.rb +49 -0
  86. data/lib/active_record/relation/finder_methods.rb +16 -11
  87. data/lib/active_record/relation/predicate_builder.rb +8 -6
  88. data/lib/active_record/relation/query_methods.rb +75 -9
  89. data/lib/active_record/relation/spawn_methods.rb +48 -7
  90. data/lib/active_record/relation.rb +78 -32
  91. data/lib/active_record/result.rb +10 -4
  92. data/lib/active_record/sanitization.rb +194 -0
  93. data/lib/active_record/schema_dumper.rb +12 -5
  94. data/lib/active_record/scoping/default.rb +142 -0
  95. data/lib/active_record/scoping/named.rb +200 -0
  96. data/lib/active_record/scoping.rb +152 -0
  97. data/lib/active_record/serialization.rb +1 -43
  98. data/lib/active_record/serializers/xml_serializer.rb +4 -45
  99. data/lib/active_record/session_store.rb +18 -16
  100. data/lib/active_record/store.rb +52 -0
  101. data/lib/active_record/test_case.rb +11 -7
  102. data/lib/active_record/timestamp.rb +17 -3
  103. data/lib/active_record/transactions.rb +27 -6
  104. data/lib/active_record/translation.rb +22 -0
  105. data/lib/active_record/validations/associated.rb +5 -4
  106. data/lib/active_record/validations/uniqueness.rb +8 -8
  107. data/lib/active_record/validations.rb +1 -1
  108. data/lib/active_record/version.rb +3 -3
  109. data/lib/active_record.rb +38 -3
  110. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  111. data/lib/rails/generators/active_record/migration/templates/migration.rb +12 -3
  112. data/lib/rails/generators/active_record/model/model_generator.rb +9 -1
  113. data/lib/rails/generators/active_record/model/templates/migration.rb +3 -5
  114. data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
  115. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
  116. metadata +49 -28
  117. data/lib/active_record/named_scope.rb +0 -200
@@ -56,7 +56,7 @@ module ActiveRecord
56
56
  end
57
57
 
58
58
  def select_all(arel, name = nil, binds = [])
59
- if @query_cache_enabled
59
+ if @query_cache_enabled && !locked?(arel)
60
60
  sql = to_sql(arel, binds)
61
61
  cache_sql(sql, binds) { super(sql, name, binds) }
62
62
  else
@@ -69,7 +69,7 @@ module ActiveRecord
69
69
  result =
70
70
  if @query_cache[sql].key?(binds)
71
71
  ActiveSupport::Notifications.instrument("sql.active_record",
72
- :sql => sql, :name => "CACHE", :connection_id => object_id)
72
+ :sql => sql, :binds => binds, :name => "CACHE", :connection_id => object_id)
73
73
  @query_cache[sql][binds]
74
74
  else
75
75
  @query_cache[sql][binds] = yield
@@ -77,6 +77,14 @@ module ActiveRecord
77
77
 
78
78
  result.collect { |row| row.dup }
79
79
  end
80
+
81
+ def locked?(arel)
82
+ if arel.respond_to?(:locked)
83
+ arel.locked
84
+ else
85
+ false
86
+ end
87
+ end
80
88
  end
81
89
  end
82
90
  end
@@ -102,10 +102,13 @@ module ActiveRecord
102
102
  def quoted_date(value)
103
103
  if value.acts_like?(:time)
104
104
  zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
105
- value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
106
- else
107
- value
108
- end.to_s(:db)
105
+
106
+ if value.respond_to?(zone_conversion_method)
107
+ value = value.send(zone_conversion_method)
108
+ end
109
+ end
110
+
111
+ value.to_s(:db)
109
112
  end
110
113
  end
111
114
  end
@@ -6,7 +6,7 @@ require 'bigdecimal/util'
6
6
 
7
7
  module ActiveRecord
8
8
  module ConnectionAdapters #:nodoc:
9
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths) #:nodoc:
9
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders) #:nodoc:
10
10
  end
11
11
 
12
12
  # Abstract representation of a column definition. Instances of this type
@@ -42,8 +42,8 @@ module ActiveRecord
42
42
  # Represents the schema of an SQL table in an abstract way. This class
43
43
  # provides methods for manipulating the schema representation.
44
44
  #
45
- # Inside migration files, the +t+ object in +create_table+ and
46
- # +change_table+ is actually of this type:
45
+ # Inside migration files, the +t+ object in +create_table+
46
+ # is actually of this type:
47
47
  #
48
48
  # class SomeMigration < ActiveRecord::Migration
49
49
  # def up
@@ -66,6 +66,7 @@ module ActiveRecord
66
66
 
67
67
  def initialize(base)
68
68
  @columns = []
69
+ @columns_hash = {}
69
70
  @base = base
70
71
  end
71
72
 
@@ -86,7 +87,7 @@ module ActiveRecord
86
87
 
87
88
  # Returns a ColumnDefinition for the column with name +name+.
88
89
  def [](name)
89
- @columns.find {|column| column.name.to_s == name.to_s}
90
+ @columns_hash[name.to_s]
90
91
  end
91
92
 
92
93
  # Instantiates a new column for the table.
@@ -224,35 +225,38 @@ module ActiveRecord
224
225
  # t.references :taggable, :polymorphic => { :default => 'Photo' }
225
226
  # end
226
227
  def column(name, type, options = {})
227
- column = self[name] || ColumnDefinition.new(@base, name, type)
228
- if options[:limit]
229
- column.limit = options[:limit]
230
- elsif native[type.to_sym].is_a?(Hash)
231
- column.limit = native[type.to_sym][:limit]
228
+ name = name.to_s
229
+ type = type.to_sym
230
+
231
+ column = self[name] || new_column_definition(@base, name, type)
232
+
233
+ limit = options.fetch(:limit) do
234
+ native[type][:limit] if native[type].is_a?(Hash)
232
235
  end
236
+
237
+ column.limit = limit
233
238
  column.precision = options[:precision]
234
- column.scale = options[:scale]
235
- column.default = options[:default]
236
- column.null = options[:null]
237
- @columns << column unless @columns.include? column
239
+ column.scale = options[:scale]
240
+ column.default = options[:default]
241
+ column.null = options[:null]
238
242
  self
239
243
  end
240
244
 
241
245
  %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
242
246
  class_eval <<-EOV, __FILE__, __LINE__ + 1
243
- def #{column_type}(*args) # def string(*args)
244
- options = args.extract_options! # options = args.extract_options!
245
- column_names = args # column_names = args
246
- #
247
- column_names.each { |name| column(name, '#{column_type}', options) } # column_names.each { |name| column(name, 'string', options) }
248
- end # end
247
+ def #{column_type}(*args) # def string(*args)
248
+ options = args.extract_options! # options = args.extract_options!
249
+ column_names = args # column_names = args
250
+ type = :'#{column_type}' # type = :string
251
+ column_names.each { |name| column(name, type, options) } # column_names.each { |name| column(name, type, options) }
252
+ end # end
249
253
  EOV
250
254
  end
251
255
 
252
256
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
253
257
  # <tt>:updated_at</tt> to the table.
254
258
  def timestamps(*args)
255
- options = args.extract_options!
259
+ options = { :null => false }.merge(args.extract_options!)
256
260
  column(:created_at, :datetime, options)
257
261
  column(:updated_at, :datetime, options)
258
262
  end
@@ -275,9 +279,16 @@ module ActiveRecord
275
279
  end
276
280
 
277
281
  private
278
- def native
279
- @base.native_database_types
280
- end
282
+ def new_column_definition(base, name, type)
283
+ definition = ColumnDefinition.new base, name, type
284
+ @columns << definition
285
+ @columns_hash[name] = definition
286
+ definition
287
+ end
288
+
289
+ def native
290
+ @base.native_database_types
291
+ end
281
292
  end
282
293
 
283
294
  # Represents an SQL table in an abstract way for updating a table.
@@ -380,7 +391,7 @@ module ActiveRecord
380
391
  # t.remove(:qualification)
381
392
  # t.remove(:qualification, :experience)
382
393
  def remove(*column_names)
383
- @base.remove_column(@table_name, column_names)
394
+ @base.remove_column(@table_name, *column_names)
384
395
  end
385
396
 
386
397
  # Removes the given index from the table.
@@ -453,13 +464,13 @@ module ActiveRecord
453
464
  def #{column_type}(*args) # def string(*args)
454
465
  options = args.extract_options! # options = args.extract_options!
455
466
  column_names = args # column_names = args
456
- #
467
+ type = :'#{column_type}' # type = :string
457
468
  column_names.each do |name| # column_names.each do |name|
458
- column = ColumnDefinition.new(@base, name, '#{column_type}') # column = ColumnDefinition.new(@base, name, 'string')
469
+ column = ColumnDefinition.new(@base, name.to_s, type) # column = ColumnDefinition.new(@base, name, type)
459
470
  if options[:limit] # if options[:limit]
460
471
  column.limit = options[:limit] # column.limit = options[:limit]
461
- elsif native['#{column_type}'.to_sym].is_a?(Hash) # elsif native['string'.to_sym].is_a?(Hash)
462
- column.limit = native['#{column_type}'.to_sym][:limit] # column.limit = native['string'.to_sym][:limit]
472
+ elsif native[type].is_a?(Hash) # elsif native[type].is_a?(Hash)
473
+ column.limit = native[type][:limit] # column.limit = native[type][:limit]
463
474
  end # end
464
475
  column.precision = options[:precision] # column.precision = options[:precision]
465
476
  column.scale = options[:scale] # column.scale = options[:scale]
@@ -1,10 +1,11 @@
1
1
  require 'active_support/core_ext/array/wrap'
2
+ require 'active_support/deprecation/reporting'
2
3
 
3
4
  module ActiveRecord
4
5
  module ConnectionAdapters # :nodoc:
5
6
  module SchemaStatements
6
7
  # Returns a Hash of mappings from the abstract data types to the native
7
- # database types. See TableDefinition#column for details on the recognized
8
+ # database types. See TableDefinition#column for details on the recognized
8
9
  # abstract data types.
9
10
  def native_database_types
10
11
  {}
@@ -15,8 +16,6 @@ module ActiveRecord
15
16
  table_name[0...table_alias_length].gsub(/\./, '_')
16
17
  end
17
18
 
18
- # def tables(name = nil) end
19
-
20
19
  # Checks to see if the table +table_name+ exists on the database.
21
20
  #
22
21
  # === Example
@@ -78,7 +77,7 @@ module ActiveRecord
78
77
  # Creates a new table with the name +table_name+. +table_name+ may either
79
78
  # be a String or a Symbol.
80
79
  #
81
- # There are two ways to work with +create_table+. You can use the block
80
+ # There are two ways to work with +create_table+. You can use the block
82
81
  # form or the regular form, like this:
83
82
  #
84
83
  # === Block form
@@ -113,7 +112,7 @@ module ActiveRecord
113
112
  # Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
114
113
  #
115
114
  # Also note that this just sets the primary key in the table. You additionally
116
- # need to configure the primary key in the model via the +set_primary_key+ macro.
115
+ # need to configure the primary key in the model via +self.primary_key=+.
117
116
  # Models do NOT auto-detect the primary key from their table definition.
118
117
  #
119
118
  # [<tt>:options</tt>]
@@ -270,7 +269,15 @@ module ActiveRecord
270
269
  # remove_column(:suppliers, :qualification)
271
270
  # remove_columns(:suppliers, :qualification, :experience)
272
271
  def remove_column(table_name, *column_names)
273
- columns_for_remove(table_name, *column_names).each {|column_name| execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{column_name}" }
272
+ if column_names.flatten!
273
+ message = 'Passing array to remove_columns is deprecated, please use ' +
274
+ 'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
275
+ ActiveSupport::Deprecation.warn message, caller
276
+ end
277
+
278
+ columns_for_remove(table_name, *column_names).each do |column_name|
279
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{column_name}"
280
+ end
274
281
  end
275
282
  alias :remove_columns :remove_column
276
283
 
@@ -299,18 +306,11 @@ module ActiveRecord
299
306
  raise NotImplementedError, "rename_column is not implemented"
300
307
  end
301
308
 
302
- # Adds a new index to the table. +column_name+ can be a single Symbol, or
309
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
303
310
  # an Array of Symbols.
304
311
  #
305
- # The index will be named after the table and the first column name,
306
- # unless you pass <tt>:name</tt> as an option.
307
- #
308
- # When creating an index on multiple columns, the first column is used as a name
309
- # for the index. For example, when you specify an index on two columns
310
- # [<tt>:first</tt>, <tt>:last</tt>], the DBMS creates an index for both columns as well as an
311
- # index for the first column <tt>:first</tt>. Using just the first name for this index
312
- # makes sense, because you will never have to create a singular index with this
313
- # name.
312
+ # The index will be named after the table and the column name(s), unless
313
+ # you pass <tt>:name</tt> as an option.
314
314
  #
315
315
  # ===== Examples
316
316
  #
@@ -339,6 +339,14 @@ module ActiveRecord
339
339
  # CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
340
340
  #
341
341
  # Note: SQLite doesn't support index length
342
+ #
343
+ # ====== Creating an index with a sort order (desc or asc, asc is the default)
344
+ # add_index(:accounts, [:branch_id, :party_id, :surname], :order => {:branch_id => :desc, :part_id => :asc})
345
+ # generates
346
+ # CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
347
+ #
348
+ # Note: mysql doesn't yet support index order (it accepts the syntax but ignores it)
349
+ #
342
350
  def add_index(table_name, column_name, options = {})
343
351
  index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
344
352
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})"
@@ -405,7 +413,7 @@ module ActiveRecord
405
413
 
406
414
  def dump_schema_information #:nodoc:
407
415
  sm_table = ActiveRecord::Migrator.schema_migrations_table_name
408
- migrated = select_values("SELECT version FROM #{sm_table}")
416
+ migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
409
417
  migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n")
410
418
  end
411
419
 
@@ -426,6 +434,7 @@ module ActiveRecord
426
434
  si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
427
435
 
428
436
  if table_exists?(si_table)
437
+ ActiveSupport::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table"
429
438
 
430
439
  old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
431
440
  assume_migrated_upto_version(old_version)
@@ -520,9 +529,29 @@ module ActiveRecord
520
529
  end
521
530
 
522
531
  protected
532
+ def add_index_sort_order(option_strings, column_names, options = {})
533
+ if options.is_a?(Hash) && order = options[:order]
534
+ case order
535
+ when Hash
536
+ column_names.each {|name| option_strings[name] += " #{order[name].to_s.upcase}" if order.has_key?(name)}
537
+ when String
538
+ column_names.each {|name| option_strings[name] += " #{order.upcase}"}
539
+ end
540
+ end
541
+
542
+ return option_strings
543
+ end
544
+
523
545
  # Overridden by the mysql adapter for supporting index lengths
524
546
  def quoted_columns_for_index(column_names, options = {})
525
- column_names.map {|name| quote_column_name(name) }
547
+ option_strings = Hash[column_names.map {|name| [name, '']}]
548
+
549
+ # add index sort order if supported
550
+ if supports_index_sort_order?
551
+ option_strings = add_index_sort_order(option_strings, column_names, options)
552
+ end
553
+
554
+ column_names.map {|name| quote_column_name(name) + option_strings[name]}
526
555
  end
527
556
 
528
557
  def options_include_default?(options)
@@ -564,7 +593,7 @@ module ActiveRecord
564
593
  def columns_for_remove(table_name, *column_names)
565
594
  column_names = column_names.flatten
566
595
 
567
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.blank?
596
+ raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.blank?
568
597
  column_names.map {|column_name| quote_column_name(column_name) }
569
598
  end
570
599
 
@@ -3,21 +3,34 @@ require 'bigdecimal'
3
3
  require 'bigdecimal/util'
4
4
  require 'active_support/core_ext/benchmark'
5
5
  require 'active_support/deprecation'
6
-
7
- # TODO: Autoload these files
8
- require 'active_record/connection_adapters/column'
9
- require 'active_record/connection_adapters/abstract/schema_definitions'
10
- require 'active_record/connection_adapters/abstract/schema_statements'
11
- require 'active_record/connection_adapters/abstract/database_statements'
12
- require 'active_record/connection_adapters/abstract/quoting'
13
- require 'active_record/connection_adapters/abstract/connection_pool'
14
- require 'active_record/connection_adapters/abstract/connection_specification'
15
- require 'active_record/connection_adapters/abstract/query_cache'
16
- require 'active_record/connection_adapters/abstract/database_limits'
17
- require 'active_record/result'
6
+ require 'active_record/connection_adapters/schema_cache'
7
+ require 'monitor'
18
8
 
19
9
  module ActiveRecord
20
10
  module ConnectionAdapters # :nodoc:
11
+ extend ActiveSupport::Autoload
12
+
13
+ autoload :Column
14
+
15
+ autoload_under 'abstract' do
16
+ autoload :IndexDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
17
+ autoload :ColumnDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
18
+ autoload :TableDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
19
+ autoload :Table, 'active_record/connection_adapters/abstract/schema_definitions'
20
+
21
+ autoload :SchemaStatements
22
+ autoload :DatabaseStatements
23
+ autoload :DatabaseLimits
24
+ autoload :Quoting
25
+
26
+ autoload :ConnectionPool
27
+ autoload :ConnectionHandler, 'active_record/connection_adapters/abstract/connection_pool'
28
+ autoload :ConnectionManagement, 'active_record/connection_adapters/abstract/connection_pool'
29
+ autoload :ConnectionSpecification
30
+
31
+ autoload :QueryCache
32
+ end
33
+
21
34
  # Active Record supports multiple database systems. AbstractAdapter and
22
35
  # related classes form the abstraction layer which makes this possible.
23
36
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -36,39 +49,44 @@ module ActiveRecord
36
49
  include DatabaseLimits
37
50
  include QueryCache
38
51
  include ActiveSupport::Callbacks
52
+ include MonitorMixin
39
53
 
40
54
  define_callbacks :checkout, :checkin
41
55
 
42
- attr_accessor :visitor
43
- attr_reader :logger
44
-
45
- def initialize(connection, logger = nil) #:nodoc:
46
- @active = nil
47
- @connection, @logger = connection, logger
56
+ attr_accessor :visitor, :pool
57
+ attr_reader :schema_cache, :last_use, :in_use, :logger
58
+ alias :in_use? :in_use
59
+
60
+ def initialize(connection, logger = nil, pool = nil) #:nodoc:
61
+ super()
62
+
63
+ @active = nil
64
+ @connection = connection
65
+ @in_use = false
66
+ @instrumenter = ActiveSupport::Notifications.instrumenter
67
+ @last_use = false
68
+ @logger = logger
69
+ @open_transactions = 0
70
+ @pool = pool
71
+ @query_cache = Hash.new { |h,sql| h[sql] = {} }
48
72
  @query_cache_enabled = false
49
- @query_cache = Hash.new { |h,sql| h[sql] = {} }
50
- @instrumenter = ActiveSupport::Notifications.instrumenter
51
- @visitor = nil
52
- end
53
-
54
- # Returns a visitor instance for this adaptor, which conforms to the Arel::ToSql interface
55
- def self.visitor_for(pool) # :nodoc:
56
- adapter = pool.spec.config[:adapter]
57
-
58
- if Arel::Visitors::VISITORS[adapter]
59
- ActiveSupport::Deprecation.warn(
60
- "Arel::Visitors::VISITORS is deprecated and will be removed. Database adapters " \
61
- "should define a visitor_for method which returns the appropriate visitor for " \
62
- "the database. For example, MysqlAdapter.visitor_for(pool) returns " \
63
- "Arel::Visitors::MySQL.new(pool)."
64
- )
65
-
66
- Arel::Visitors::VISITORS[adapter].new(pool)
67
- else
68
- Arel::Visitors::ToSql.new(pool)
73
+ @schema_cache = SchemaCache.new self
74
+ @visitor = nil
75
+ end
76
+
77
+ def lease
78
+ synchronize do
79
+ unless in_use
80
+ @in_use = true
81
+ @last_use = Time.now
82
+ end
69
83
  end
70
84
  end
71
85
 
86
+ def expire
87
+ @in_use = false
88
+ end
89
+
72
90
  # Returns the human-readable name of the adapter. Use mixed case - one
73
91
  # can always use downcase if needed.
74
92
  def adapter_name
@@ -119,6 +137,17 @@ module ActiveRecord
119
137
  false
120
138
  end
121
139
 
140
+ # Does this adapter support index sort order?
141
+ def supports_index_sort_order?
142
+ false
143
+ end
144
+
145
+ # Does this adapter support explain? As of this writing sqlite3,
146
+ # mysql2, and postgresql are the only ones that do.
147
+ def supports_explain?
148
+ false
149
+ end
150
+
122
151
  # QUOTING ==================================================
123
152
 
124
153
  # Override to return the quoted table name. Defaults to column quoting.
@@ -200,12 +229,9 @@ module ActiveRecord
200
229
  @connection
201
230
  end
202
231
 
203
- def open_transactions
204
- @open_transactions ||= 0
205
- end
232
+ attr_reader :open_transactions
206
233
 
207
234
  def increment_open_transactions
208
- @open_transactions ||= 0
209
235
  @open_transactions += 1
210
236
  end
211
237
 
@@ -230,10 +256,19 @@ module ActiveRecord
230
256
  node
231
257
  end
232
258
 
259
+ def case_insensitive_comparison(table, attribute, column, value)
260
+ table[attribute].lower.eq(table.lower(value))
261
+ end
262
+
233
263
  def current_savepoint_name
234
264
  "active_record_#{open_transactions}"
235
265
  end
236
266
 
267
+ # Check the connection back in to the connection pool
268
+ def close
269
+ pool.checkin self
270
+ end
271
+
237
272
  protected
238
273
 
239
274
  def log(sql, name = "SQL", binds = [])