activerecord 3.1.12 → 3.2.0.rc1
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.
- data/CHANGELOG.md +6263 -103
- data/README.rdoc +2 -2
- data/examples/performance.rb +55 -31
- data/lib/active_record.rb +28 -2
- data/lib/active_record/aggregations.rb +2 -2
- data/lib/active_record/associations.rb +82 -69
- data/lib/active_record/associations/association.rb +2 -37
- 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/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods.rb +212 -32
- 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 +69 -80
- data/lib/active_record/attribute_methods/serialization.rb +89 -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/autosave_association.rb +23 -8
- data/lib/active_record/base.rb +223 -1712
- 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 +7 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +36 -25
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -13
- 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/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 +1 -1
- 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.rb +31 -76
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/identity_map.rb +1 -7
- data/lib/active_record/inheritance.rb +167 -0
- data/lib/active_record/integration.rb +49 -0
- data/lib/active_record/locking/optimistic.rb +19 -11
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +3 -3
- data/lib/active_record/migration.rb +38 -29
- data/lib/active_record/migration/command_recorder.rb +7 -7
- data/lib/active_record/model_schema.rb +362 -0
- data/lib/active_record/nested_attributes.rb +3 -2
- data/lib/active_record/persistence.rb +51 -1
- 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 +133 -77
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +7 -15
- data/lib/active_record/relation.rb +78 -35
- 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 +5 -4
- data/lib/active_record/relation/predicate_builder.rb +13 -16
- data/lib/active_record/relation/query_methods.rb +59 -4
- 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.rb +152 -0
- data/lib/active_record/scoping/default.rb +140 -0
- data/lib/active_record/scoping/named.rb +202 -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 +11 -11
- 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.rb +1 -1
- data/lib/active_record/validations/associated.rb +5 -4
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +3 -3
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
- metadata +48 -38
- checksums.yaml +0 -7
- data/lib/active_record/named_scope.rb +0 -200
@@ -1,14 +1,10 @@
|
|
1
|
-
require 'active_support/core_ext/module/deprecation'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module ConnectionAdapters # :nodoc:
|
5
3
|
module DatabaseStatements
|
6
4
|
# Converts an arel AST to SQL
|
7
|
-
def to_sql(arel
|
5
|
+
def to_sql(arel)
|
8
6
|
if arel.respond_to?(:ast)
|
9
|
-
visitor.accept(arel.ast)
|
10
|
-
quote(*binds.shift.reverse)
|
11
|
-
end
|
7
|
+
visitor.accept(arel.ast)
|
12
8
|
else
|
13
9
|
arel
|
14
10
|
end
|
@@ -17,7 +13,7 @@ module ActiveRecord
|
|
17
13
|
# Returns an array of record hashes with the column names as keys and
|
18
14
|
# column values as values.
|
19
15
|
def select_all(arel, name = nil, binds = [])
|
20
|
-
select(to_sql(arel
|
16
|
+
select(to_sql(arel), name, binds)
|
21
17
|
end
|
22
18
|
|
23
19
|
# Returns a record hash with the column names as keys and column values
|
@@ -37,7 +33,7 @@ module ActiveRecord
|
|
37
33
|
# Returns an array of the values of the first column in a select:
|
38
34
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
39
35
|
def select_values(arel, name = nil)
|
40
|
-
result = select_rows(to_sql(arel
|
36
|
+
result = select_rows(to_sql(arel), name)
|
41
37
|
result.map { |v| v[0] }
|
42
38
|
end
|
43
39
|
|
@@ -53,7 +49,7 @@ module ActiveRecord
|
|
53
49
|
undef_method :execute
|
54
50
|
|
55
51
|
# Executes +sql+ statement in the context of this connection using
|
56
|
-
# +binds+ as the bind substitutes.
|
52
|
+
# +binds+ as the bind substitutes. +name+ is logged along with
|
57
53
|
# the executed +sql+ statement.
|
58
54
|
def exec_query(sql, name = 'SQL', binds = [])
|
59
55
|
end
|
@@ -88,19 +84,19 @@ module ActiveRecord
|
|
88
84
|
# If the next id was calculated in advance (as in Oracle), it should be
|
89
85
|
# passed in as +id_value+.
|
90
86
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
91
|
-
sql, binds = sql_for_insert(to_sql(arel
|
87
|
+
sql, binds = sql_for_insert(to_sql(arel), pk, id_value, sequence_name, binds)
|
92
88
|
value = exec_insert(sql, name, binds)
|
93
89
|
id_value || last_inserted_id(value)
|
94
90
|
end
|
95
91
|
|
96
92
|
# Executes the update statement and returns the number of rows affected.
|
97
93
|
def update(arel, name = nil, binds = [])
|
98
|
-
exec_update(to_sql(arel
|
94
|
+
exec_update(to_sql(arel), name, binds)
|
99
95
|
end
|
100
96
|
|
101
97
|
# Executes the delete statement and returns the number of rows affected.
|
102
98
|
def delete(arel, name = nil, binds = [])
|
103
|
-
exec_delete(to_sql(arel
|
99
|
+
exec_delete(to_sql(arel), name, binds)
|
104
100
|
end
|
105
101
|
|
106
102
|
# Checks whether there is currently no transaction active. This is done
|
@@ -256,38 +252,13 @@ module ActiveRecord
|
|
256
252
|
# done if the transaction block raises an exception or returns false.
|
257
253
|
def rollback_db_transaction() end
|
258
254
|
|
259
|
-
# Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
|
260
|
-
# fragment that has the same semantics as LIMIT and OFFSET.
|
261
|
-
#
|
262
|
-
# +options+ must be a Hash which contains a +:limit+ option
|
263
|
-
# and an +:offset+ option.
|
264
|
-
#
|
265
|
-
# This method *modifies* the +sql+ parameter.
|
266
|
-
#
|
267
|
-
# This method is deprecated!! Stop using it!
|
268
|
-
#
|
269
|
-
# ===== Examples
|
270
|
-
# add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
|
271
|
-
# generates
|
272
|
-
# SELECT * FROM suppliers LIMIT 10 OFFSET 50
|
273
|
-
def add_limit_offset!(sql, options)
|
274
|
-
if limit = options[:limit]
|
275
|
-
sql << " LIMIT #{sanitize_limit(limit)}"
|
276
|
-
end
|
277
|
-
if offset = options[:offset]
|
278
|
-
sql << " OFFSET #{offset.to_i}"
|
279
|
-
end
|
280
|
-
sql
|
281
|
-
end
|
282
|
-
deprecate :add_limit_offset!
|
283
|
-
|
284
255
|
def default_sequence_name(table, column)
|
285
256
|
nil
|
286
257
|
end
|
287
258
|
|
288
259
|
# Set the sequence to the max value of the table's column.
|
289
260
|
def reset_sequence!(table, column, sequence = nil)
|
290
|
-
# Do nothing by default.
|
261
|
+
# Do nothing by default. Implement for PostgreSQL, Oracle, ...
|
291
262
|
end
|
292
263
|
|
293
264
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
@@ -319,10 +290,10 @@ module ActiveRecord
|
|
319
290
|
# Sanitizes the given LIMIT parameter in order to prevent SQL injection.
|
320
291
|
#
|
321
292
|
# The +limit+ may be anything that can evaluate to a string via #to_s. It
|
322
|
-
# should look like an integer, or a comma-delimited list of integers, or
|
293
|
+
# should look like an integer, or a comma-delimited list of integers, or
|
323
294
|
# an Arel SQL literal.
|
324
295
|
#
|
325
|
-
# Returns Integer and Arel::Nodes::SqlLiteral limits as is.
|
296
|
+
# Returns Integer and Arel::Nodes::SqlLiteral limits as is.
|
326
297
|
# Returns the sanitized limit parameter, either as an integer, or as a
|
327
298
|
# string which contains a comma-delimited list of integers.
|
328
299
|
def sanitize_limit(limit)
|
@@ -370,7 +341,7 @@ module ActiveRecord
|
|
370
341
|
|
371
342
|
# Send a rollback message to all records after they have been rolled back. If rollback
|
372
343
|
# is false, only rollback records since the last save point.
|
373
|
-
def rollback_transaction_records(rollback)
|
344
|
+
def rollback_transaction_records(rollback)
|
374
345
|
if rollback
|
375
346
|
records = @_current_transaction_records.flatten
|
376
347
|
@_current_transaction_records.clear
|
@@ -390,7 +361,7 @@ module ActiveRecord
|
|
390
361
|
end
|
391
362
|
|
392
363
|
# Send a commit message to all records after they have been committed.
|
393
|
-
def commit_transaction_records
|
364
|
+
def commit_transaction_records
|
394
365
|
records = @_current_transaction_records.flatten
|
395
366
|
@_current_transaction_records.clear
|
396
367
|
unless records.blank?
|
@@ -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
|
@@ -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,7 +298,7 @@ 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
304
|
# The index will be named after the table and the first column name,
|
@@ -339,6 +338,14 @@ module ActiveRecord
|
|
339
338
|
# CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
|
340
339
|
#
|
341
340
|
# Note: SQLite doesn't support index length
|
341
|
+
#
|
342
|
+
# ====== Creating an index with a sort order (desc or asc, asc is the default)
|
343
|
+
# add_index(:accounts, [:branch_id, :party_id, :surname], :order => {:branch_id => :desc, :part_id => :asc})
|
344
|
+
# generates
|
345
|
+
# CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
|
346
|
+
#
|
347
|
+
# Note: mysql doesn't yet support index order (it accepts the syntax but ignores it)
|
348
|
+
#
|
342
349
|
def add_index(table_name, column_name, options = {})
|
343
350
|
index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
|
344
351
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})"
|
@@ -405,7 +412,7 @@ module ActiveRecord
|
|
405
412
|
|
406
413
|
def dump_schema_information #:nodoc:
|
407
414
|
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
|
408
|
-
migrated = select_values("SELECT version FROM #{sm_table}")
|
415
|
+
migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
|
409
416
|
migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n")
|
410
417
|
end
|
411
418
|
|
@@ -426,6 +433,7 @@ module ActiveRecord
|
|
426
433
|
si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
|
427
434
|
|
428
435
|
if table_exists?(si_table)
|
436
|
+
ActiveRecord::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table"
|
429
437
|
|
430
438
|
old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
|
431
439
|
assume_migrated_upto_version(old_version)
|
@@ -507,8 +515,8 @@ module ActiveRecord
|
|
507
515
|
# ===== Examples
|
508
516
|
# add_timestamps(:suppliers)
|
509
517
|
def add_timestamps(table_name)
|
510
|
-
add_column table_name, :created_at, :datetime
|
511
|
-
add_column table_name, :updated_at, :datetime
|
518
|
+
add_column table_name, :created_at, :datetime, :null => false
|
519
|
+
add_column table_name, :updated_at, :datetime, :null => false
|
512
520
|
end
|
513
521
|
|
514
522
|
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
@@ -520,9 +528,29 @@ module ActiveRecord
|
|
520
528
|
end
|
521
529
|
|
522
530
|
protected
|
531
|
+
def add_index_sort_order(option_strings, column_names, options = {})
|
532
|
+
if options.is_a?(Hash) && order = options[:order]
|
533
|
+
case order
|
534
|
+
when Hash
|
535
|
+
column_names.each {|name| option_strings[name] += " #{order[name].to_s.upcase}" if order.has_key?(name)}
|
536
|
+
when String
|
537
|
+
column_names.each {|name| option_strings[name] += " #{order.upcase}"}
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
return option_strings
|
542
|
+
end
|
543
|
+
|
523
544
|
# Overridden by the mysql adapter for supporting index lengths
|
524
545
|
def quoted_columns_for_index(column_names, options = {})
|
525
|
-
column_names.map {|name|
|
546
|
+
option_strings = Hash[column_names.map {|name| [name, '']}]
|
547
|
+
|
548
|
+
# add index sort order if supported
|
549
|
+
if supports_index_sort_order?
|
550
|
+
option_strings = add_index_sort_order(option_strings, column_names, options)
|
551
|
+
end
|
552
|
+
|
553
|
+
column_names.map {|name| quote_column_name(name) + option_strings[name]}
|
526
554
|
end
|
527
555
|
|
528
556
|
def options_include_default?(options)
|
@@ -564,7 +592,7 @@ module ActiveRecord
|
|
564
592
|
def columns_for_remove(table_name, *column_names)
|
565
593
|
column_names = column_names.flatten
|
566
594
|
|
567
|
-
raise ArgumentError.new("You must specify at least one column name.
|
595
|
+
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.blank?
|
568
596
|
column_names.map {|column_name| quote_column_name(column_name) }
|
569
597
|
end
|
570
598
|
|
@@ -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 = [])
|