activerecord 3.1.11 → 3.2.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.
- data/CHANGELOG.md +6294 -97
- data/README.rdoc +2 -2
- data/examples/performance.rb +55 -31
- data/lib/active_record/aggregations.rb +2 -2
- data/lib/active_record/associations/association.rb +2 -42
- data/lib/active_record/associations/association_scope.rb +3 -30
- data/lib/active_record/associations/builder/association.rb +6 -4
- data/lib/active_record/associations/builder/belongs_to.rb +3 -3
- 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 +55 -28
- data/lib/active_record/associations/collection_proxy.rb +1 -35
- data/lib/active_record/associations/has_many_association.rb +5 -1
- data/lib/active_record/associations/has_many_through_association.rb +11 -8
- data/lib/active_record/associations/join_dependency.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/associations.rb +82 -69
- 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 +3 -3
- data/lib/active_record/attribute_methods/primary_key.rb +62 -25
- data/lib/active_record/attribute_methods/read.rb +72 -83
- data/lib/active_record/attribute_methods/serialization.rb +93 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -14
- data/lib/active_record/attribute_methods/write.rb +27 -5
- data/lib/active_record/attribute_methods.rb +209 -30
- data/lib/active_record/autosave_association.rb +23 -8
- data/lib/active_record/base.rb +217 -1709
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +98 -132
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +82 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +13 -42
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +9 -12
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +36 -25
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +78 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +653 -0
- data/lib/active_record/connection_adapters/column.rb +2 -2
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +138 -578
- data/lib/active_record/connection_adapters/mysql_adapter.rb +86 -658
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +144 -94
- data/lib/active_record/connection_adapters/schema_cache.rb +50 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +43 -22
- data/lib/active_record/counter_cache.rb +4 -3
- data/lib/active_record/dynamic_matchers.rb +79 -0
- data/lib/active_record/errors.rb +11 -1
- data/lib/active_record/explain.rb +83 -0
- data/lib/active_record/explain_subscriber.rb +21 -0
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/fixtures.rb +31 -76
- data/lib/active_record/identity_map.rb +4 -11
- data/lib/active_record/inheritance.rb +167 -0
- data/lib/active_record/integration.rb +49 -0
- data/lib/active_record/locking/optimistic.rb +30 -25
- data/lib/active_record/locking/pessimistic.rb +23 -1
- data/lib/active_record/log_subscriber.rb +3 -3
- data/lib/active_record/migration/command_recorder.rb +8 -8
- data/lib/active_record/migration.rb +47 -30
- data/lib/active_record/model_schema.rb +366 -0
- data/lib/active_record/nested_attributes.rb +3 -2
- data/lib/active_record/persistence.rb +51 -9
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +24 -28
- data/lib/active_record/railties/controller_runtime.rb +3 -1
- data/lib/active_record/railties/databases.rake +134 -77
- 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 +5 -2
- data/lib/active_record/relation/calculations.rb +27 -6
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +6 -5
- data/lib/active_record/relation/predicate_builder.rb +12 -19
- data/lib/active_record/relation/query_methods.rb +76 -10
- data/lib/active_record/relation/spawn_methods.rb +11 -2
- data/lib/active_record/relation.rb +77 -34
- data/lib/active_record/result.rb +1 -1
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema_dumper.rb +5 -2
- data/lib/active_record/scoping/default.rb +142 -0
- data/lib/active_record/scoping/named.rb +202 -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 +2 -44
- data/lib/active_record/session_store.rb +15 -15
- data/lib/active_record/store.rb +50 -0
- data/lib/active_record/test_case.rb +11 -7
- data/lib/active_record/timestamp.rb +16 -3
- data/lib/active_record/transactions.rb +5 -5
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +5 -4
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/version.rb +2 -2
- data/lib/active_record.rb +28 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +5 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +3 -5
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
- metadata +50 -40
- checksums.yaml +0 -7
- data/lib/active_record/named_scope.rb +0 -200
|
@@ -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
|
|
@@ -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.
|
|
@@ -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>]
|
|
@@ -161,7 +160,7 @@ module ActiveRecord
|
|
|
161
160
|
yield td if block_given?
|
|
162
161
|
|
|
163
162
|
if options[:force] && table_exists?(table_name)
|
|
164
|
-
drop_table(table_name
|
|
163
|
+
drop_table(table_name)
|
|
165
164
|
end
|
|
166
165
|
|
|
167
166
|
create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
|
|
@@ -253,7 +252,7 @@ module ActiveRecord
|
|
|
253
252
|
end
|
|
254
253
|
|
|
255
254
|
# Drops a table from the database.
|
|
256
|
-
def drop_table(table_name
|
|
255
|
+
def drop_table(table_name)
|
|
257
256
|
execute "DROP TABLE #{quote_table_name(table_name)}"
|
|
258
257
|
end
|
|
259
258
|
|
|
@@ -299,18 +298,11 @@ module ActiveRecord
|
|
|
299
298
|
raise NotImplementedError, "rename_column is not implemented"
|
|
300
299
|
end
|
|
301
300
|
|
|
302
|
-
# Adds a new index to the table.
|
|
301
|
+
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
|
303
302
|
# an Array of Symbols.
|
|
304
303
|
#
|
|
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.
|
|
304
|
+
# The index will be named after the table and the column name(s), unless
|
|
305
|
+
# you pass <tt>:name</tt> as an option.
|
|
314
306
|
#
|
|
315
307
|
# ===== Examples
|
|
316
308
|
#
|
|
@@ -339,6 +331,14 @@ module ActiveRecord
|
|
|
339
331
|
# CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
|
|
340
332
|
#
|
|
341
333
|
# Note: SQLite doesn't support index length
|
|
334
|
+
#
|
|
335
|
+
# ====== Creating an index with a sort order (desc or asc, asc is the default)
|
|
336
|
+
# add_index(:accounts, [:branch_id, :party_id, :surname], :order => {:branch_id => :desc, :part_id => :asc})
|
|
337
|
+
# generates
|
|
338
|
+
# CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
|
|
339
|
+
#
|
|
340
|
+
# Note: mysql doesn't yet support index order (it accepts the syntax but ignores it)
|
|
341
|
+
#
|
|
342
342
|
def add_index(table_name, column_name, options = {})
|
|
343
343
|
index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
|
|
344
344
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})"
|
|
@@ -405,7 +405,7 @@ module ActiveRecord
|
|
|
405
405
|
|
|
406
406
|
def dump_schema_information #:nodoc:
|
|
407
407
|
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
|
|
408
|
-
migrated = select_values("SELECT version FROM #{sm_table}")
|
|
408
|
+
migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
|
|
409
409
|
migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n")
|
|
410
410
|
end
|
|
411
411
|
|
|
@@ -426,6 +426,7 @@ module ActiveRecord
|
|
|
426
426
|
si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
|
|
427
427
|
|
|
428
428
|
if table_exists?(si_table)
|
|
429
|
+
ActiveRecord::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table"
|
|
429
430
|
|
|
430
431
|
old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
|
|
431
432
|
assume_migrated_upto_version(old_version)
|
|
@@ -507,8 +508,8 @@ module ActiveRecord
|
|
|
507
508
|
# ===== Examples
|
|
508
509
|
# add_timestamps(:suppliers)
|
|
509
510
|
def add_timestamps(table_name)
|
|
510
|
-
add_column table_name, :created_at, :datetime
|
|
511
|
-
add_column table_name, :updated_at, :datetime
|
|
511
|
+
add_column table_name, :created_at, :datetime, :null => false
|
|
512
|
+
add_column table_name, :updated_at, :datetime, :null => false
|
|
512
513
|
end
|
|
513
514
|
|
|
514
515
|
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
|
@@ -520,9 +521,29 @@ module ActiveRecord
|
|
|
520
521
|
end
|
|
521
522
|
|
|
522
523
|
protected
|
|
524
|
+
def add_index_sort_order(option_strings, column_names, options = {})
|
|
525
|
+
if options.is_a?(Hash) && order = options[:order]
|
|
526
|
+
case order
|
|
527
|
+
when Hash
|
|
528
|
+
column_names.each {|name| option_strings[name] += " #{order[name].to_s.upcase}" if order.has_key?(name)}
|
|
529
|
+
when String
|
|
530
|
+
column_names.each {|name| option_strings[name] += " #{order.upcase}"}
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
return option_strings
|
|
535
|
+
end
|
|
536
|
+
|
|
523
537
|
# Overridden by the mysql adapter for supporting index lengths
|
|
524
538
|
def quoted_columns_for_index(column_names, options = {})
|
|
525
|
-
column_names.map {|name|
|
|
539
|
+
option_strings = Hash[column_names.map {|name| [name, '']}]
|
|
540
|
+
|
|
541
|
+
# add index sort order if supported
|
|
542
|
+
if supports_index_sort_order?
|
|
543
|
+
option_strings = add_index_sort_order(option_strings, column_names, options)
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
column_names.map {|name| quote_column_name(name) + option_strings[name]}
|
|
526
547
|
end
|
|
527
548
|
|
|
528
549
|
def options_include_default?(options)
|
|
@@ -564,7 +585,7 @@ module ActiveRecord
|
|
|
564
585
|
def columns_for_remove(table_name, *column_names)
|
|
565
586
|
column_names = column_names.flatten
|
|
566
587
|
|
|
567
|
-
raise ArgumentError.new("You must specify at least one column name.
|
|
588
|
+
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.blank?
|
|
568
589
|
column_names.map {|column_name| quote_column_name(column_name) }
|
|
569
590
|
end
|
|
570
591
|
|
|
@@ -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 :
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
attr_accessor :visitor, :pool
|
|
57
|
+
attr_reader :schema_cache, :last_use, :in_use
|
|
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.
|
|
@@ -129,7 +158,7 @@ module ActiveRecord
|
|
|
129
158
|
# Returns a bind substitution value given a +column+ and list of current
|
|
130
159
|
# +binds+
|
|
131
160
|
def substitute_at(column, index)
|
|
132
|
-
Arel
|
|
161
|
+
Arel.sql '?'
|
|
133
162
|
end
|
|
134
163
|
|
|
135
164
|
# REFERENTIAL INTEGRITY ====================================
|
|
@@ -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 = [])
|