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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +804 -338
- data/README.rdoc +3 -3
- data/examples/performance.rb +20 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +3 -6
- data/lib/active_record/associations/association.rb +13 -45
- data/lib/active_record/associations/association_scope.rb +3 -15
- data/lib/active_record/associations/belongs_to_association.rb +1 -1
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +2 -1
- data/lib/active_record/associations/builder/association.rb +6 -4
- data/lib/active_record/associations/builder/belongs_to.rb +7 -4
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +5 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -16
- data/lib/active_record/associations/collection_association.rb +65 -32
- data/lib/active_record/associations/collection_proxy.rb +8 -41
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +1 -0
- data/lib/active_record/associations/has_many_association.rb +11 -7
- data/lib/active_record/associations/has_many_through_association.rb +19 -9
- data/lib/active_record/associations/has_one_association.rb +23 -13
- data/lib/active_record/associations/join_dependency/join_association.rb +6 -1
- data/lib/active_record/associations/join_dependency.rb +3 -3
- data/lib/active_record/associations/preloader/through_association.rb +3 -3
- data/lib/active_record/associations/preloader.rb +14 -10
- data/lib/active_record/associations/through_association.rb +8 -4
- data/lib/active_record/associations.rb +92 -76
- data/lib/active_record/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
- data/lib/active_record/attribute_methods/dirty.rb +21 -11
- data/lib/active_record/attribute_methods/primary_key.rb +62 -25
- data/lib/active_record/attribute_methods/read.rb +73 -83
- data/lib/active_record/attribute_methods/serialization.rb +120 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods/write.rb +32 -6
- data/lib/active_record/attribute_methods.rb +231 -30
- data/lib/active_record/autosave_association.rb +44 -26
- data/lib/active_record/base.rb +227 -1708
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +150 -148
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +85 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +7 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +10 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +39 -28
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +48 -19
- data/lib/active_record/connection_adapters/abstract_adapter.rb +77 -42
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
- data/lib/active_record/connection_adapters/column.rb +37 -11
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +133 -581
- data/lib/active_record/connection_adapters/mysql_adapter.rb +136 -693
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +209 -97
- data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +62 -35
- data/lib/active_record/counter_cache.rb +9 -4
- data/lib/active_record/dynamic_finder_match.rb +12 -0
- data/lib/active_record/dynamic_matchers.rb +84 -0
- data/lib/active_record/errors.rb +11 -1
- data/lib/active_record/explain.rb +86 -0
- data/lib/active_record/explain_subscriber.rb +25 -0
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/fixtures.rb +57 -86
- data/lib/active_record/identity_map.rb +3 -4
- data/lib/active_record/inheritance.rb +174 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locking/optimistic.rb +33 -26
- data/lib/active_record/locking/pessimistic.rb +23 -1
- data/lib/active_record/log_subscriber.rb +8 -4
- data/lib/active_record/migration/command_recorder.rb +8 -8
- data/lib/active_record/migration.rb +68 -35
- data/lib/active_record/model_schema.rb +368 -0
- data/lib/active_record/nested_attributes.rb +60 -24
- data/lib/active_record/persistence.rb +57 -11
- data/lib/active_record/query_cache.rb +6 -6
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +37 -29
- data/lib/active_record/railties/controller_runtime.rb +3 -1
- data/lib/active_record/railties/databases.rake +213 -117
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +7 -15
- data/lib/active_record/relation/batches.rb +7 -4
- data/lib/active_record/relation/calculations.rb +55 -16
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +16 -11
- data/lib/active_record/relation/predicate_builder.rb +8 -6
- data/lib/active_record/relation/query_methods.rb +75 -9
- data/lib/active_record/relation/spawn_methods.rb +48 -7
- data/lib/active_record/relation.rb +78 -32
- data/lib/active_record/result.rb +10 -4
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema_dumper.rb +12 -5
- data/lib/active_record/scoping/default.rb +142 -0
- data/lib/active_record/scoping/named.rb +200 -0
- data/lib/active_record/scoping.rb +152 -0
- data/lib/active_record/serialization.rb +1 -43
- data/lib/active_record/serializers/xml_serializer.rb +4 -45
- data/lib/active_record/session_store.rb +18 -16
- data/lib/active_record/store.rb +52 -0
- data/lib/active_record/test_case.rb +11 -7
- data/lib/active_record/timestamp.rb +17 -3
- data/lib/active_record/transactions.rb +27 -6
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +5 -4
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/version.rb +3 -3
- data/lib/active_record.rb +38 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb +12 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +3 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
- metadata +49 -28
- 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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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+
|
46
|
-
#
|
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
|
-
@
|
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
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
235
|
-
column.default
|
236
|
-
column.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)
|
244
|
-
options = args.extract_options!
|
245
|
-
column_names = args
|
246
|
-
|
247
|
-
column_names.each { |name| column(name,
|
248
|
-
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
|
-
|
279
|
-
|
280
|
-
|
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,
|
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[
|
462
|
-
column.limit = native[
|
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.
|
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+.
|
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
|
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
|
-
|
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.
|
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
|
306
|
-
#
|
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|
|
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.
|
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
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
-
@
|
50
|
-
@
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
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 = [])
|