activerecord 4.0.0.beta1 → 4.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +573 -30
- data/README.rdoc +3 -3
- data/lib/active_record.rb +8 -2
- data/lib/active_record/associations.rb +16 -9
- data/lib/active_record/associations/association.rb +8 -6
- data/lib/active_record/associations/association_scope.rb +2 -1
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/belongs_to.rb +37 -5
- data/lib/active_record/associations/collection_association.rb +38 -14
- data/lib/active_record/associations/collection_proxy.rb +18 -15
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +3 -3
- data/lib/active_record/associations/has_many_association.rb +4 -3
- data/lib/active_record/associations/has_many_through_association.rb +1 -1
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +29 -8
- data/lib/active_record/associations/join_dependency/join_association.rb +26 -6
- data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_part.rb +6 -6
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
- data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +5 -5
- data/lib/active_record/attribute_methods.rb +20 -5
- data/lib/active_record/attribute_methods/dirty.rb +5 -1
- data/lib/active_record/attribute_methods/primary_key.rb +1 -1
- data/lib/active_record/attribute_methods/serialization.rb +9 -2
- data/lib/active_record/autosave_association.rb +19 -5
- data/lib/active_record/base.rb +3 -3
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +8 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +3 -9
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +2 -8
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +60 -61
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -153
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -1
- data/lib/active_record/connection_adapters/abstract_adapter.rb +92 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -29
- data/lib/active_record/connection_adapters/column.rb +4 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -3
- data/lib/active_record/connection_adapters/mysql_adapter.rb +5 -5
- data/lib/active_record/connection_adapters/postgresql/cast.rb +22 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -9
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +53 -24
- data/lib/active_record/connection_adapters/schema_cache.rb +35 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +13 -5
- data/lib/active_record/connection_handling.rb +7 -7
- data/lib/active_record/core.rb +43 -8
- data/lib/active_record/counter_cache.rb +2 -1
- data/lib/active_record/errors.rb +11 -10
- data/lib/active_record/explain.rb +9 -7
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +3 -2
- data/lib/active_record/fixture_set/file.rb +1 -2
- data/lib/active_record/fixtures.rb +13 -7
- data/lib/active_record/inheritance.rb +12 -4
- data/lib/active_record/integration.rb +3 -3
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/log_subscriber.rb +2 -2
- data/lib/active_record/migration.rb +69 -21
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/nested_attributes.rb +98 -46
- data/lib/active_record/persistence.rb +3 -3
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +18 -4
- data/lib/active_record/railties/console_sandbox.rb +3 -2
- data/lib/active_record/railties/controller_runtime.rb +2 -1
- data/lib/active_record/railties/databases.rake +38 -80
- data/lib/active_record/reflection.rb +36 -3
- data/lib/active_record/relation.rb +18 -8
- data/lib/active_record/relation/calculations.rb +10 -5
- data/lib/active_record/relation/delegation.rb +3 -5
- data/lib/active_record/relation/finder_methods.rb +27 -14
- data/lib/active_record/relation/merger.rb +30 -2
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_methods.rb +113 -16
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/schema_migration.rb +8 -5
- data/lib/active_record/scoping.rb +56 -2
- data/lib/active_record/scoping/default.rb +12 -11
- data/lib/active_record/scoping/named.rb +7 -3
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/tasks/database_tasks.rb +55 -10
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -2
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/timestamp.rb +6 -0
- data/lib/active_record/transactions.rb +7 -3
- data/lib/active_record/validations.rb +1 -2
- data/lib/active_record/validations/uniqueness.rb +7 -3
- data/lib/active_record/version.rb +7 -6
- data/lib/rails/generators/active_record/migration/migration_generator.rb +9 -2
- data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +4 -1
- metadata +17 -12
- data/examples/associations.png +0 -0
@@ -78,7 +78,7 @@ module ActiveRecord
|
|
78
78
|
@joinable = options.fetch(:joinable, true)
|
79
79
|
end
|
80
80
|
|
81
|
-
# This state is
|
81
|
+
# This state is necessary so that we correctly handle stuff that might
|
82
82
|
# happen in a commit/rollback. But it's kinda distasteful. Maybe we can
|
83
83
|
# find a better way to structure it in the future.
|
84
84
|
def finishing?
|
@@ -18,6 +18,7 @@ module ActiveRecord
|
|
18
18
|
autoload :ColumnDefinition
|
19
19
|
autoload :TableDefinition
|
20
20
|
autoload :Table
|
21
|
+
autoload :AlterTable
|
21
22
|
end
|
22
23
|
|
23
24
|
autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
|
@@ -100,6 +101,79 @@ module ActiveRecord
|
|
100
101
|
@visitor = nil
|
101
102
|
end
|
102
103
|
|
104
|
+
def valid_type?(type)
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
class SchemaCreation
|
109
|
+
def initialize(conn)
|
110
|
+
@conn = conn
|
111
|
+
@cache = {}
|
112
|
+
end
|
113
|
+
|
114
|
+
def accept(o)
|
115
|
+
m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
|
116
|
+
send m, o
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def visit_AlterTable(o)
|
122
|
+
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
123
|
+
sql << o.adds.map { |col| visit_AddColumn col }.join(' ')
|
124
|
+
end
|
125
|
+
|
126
|
+
def visit_AddColumn(o)
|
127
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
128
|
+
sql = "ADD #{quote_column_name(o.name)} #{sql_type}"
|
129
|
+
add_column_options!(sql, column_options(o))
|
130
|
+
end
|
131
|
+
|
132
|
+
def visit_ColumnDefinition(o)
|
133
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
134
|
+
column_sql = "#{quote_column_name(o.name)} #{sql_type}"
|
135
|
+
add_column_options!(column_sql, column_options(o)) unless o.primary_key?
|
136
|
+
column_sql
|
137
|
+
end
|
138
|
+
|
139
|
+
def visit_TableDefinition(o)
|
140
|
+
create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
|
141
|
+
create_sql << "#{quote_table_name(o.name)} ("
|
142
|
+
create_sql << o.columns.map { |c| accept c }.join(', ')
|
143
|
+
create_sql << ") #{o.options}"
|
144
|
+
create_sql
|
145
|
+
end
|
146
|
+
|
147
|
+
def column_options(o)
|
148
|
+
column_options = {}
|
149
|
+
column_options[:null] = o.null unless o.null.nil?
|
150
|
+
column_options[:default] = o.default unless o.default.nil?
|
151
|
+
column_options[:column] = o
|
152
|
+
column_options
|
153
|
+
end
|
154
|
+
|
155
|
+
def quote_column_name(name)
|
156
|
+
@conn.quote_column_name name
|
157
|
+
end
|
158
|
+
|
159
|
+
def quote_table_name(name)
|
160
|
+
@conn.quote_table_name name
|
161
|
+
end
|
162
|
+
|
163
|
+
def type_to_sql(type, limit, precision, scale)
|
164
|
+
@conn.type_to_sql type.to_sym, limit, precision, scale
|
165
|
+
end
|
166
|
+
|
167
|
+
def add_column_options!(column_sql, column_options)
|
168
|
+
@conn.add_column_options! column_sql, column_options
|
169
|
+
column_sql
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def schema_creation
|
174
|
+
SchemaCreation.new self
|
175
|
+
end
|
176
|
+
|
103
177
|
def lease
|
104
178
|
synchronize do
|
105
179
|
unless in_use
|
@@ -118,6 +192,17 @@ module ActiveRecord
|
|
118
192
|
@in_use = false
|
119
193
|
end
|
120
194
|
|
195
|
+
def unprepared_visitor
|
196
|
+
self.class::BindSubstitution.new self
|
197
|
+
end
|
198
|
+
|
199
|
+
def unprepared_statement
|
200
|
+
old, @visitor = @visitor, unprepared_visitor
|
201
|
+
yield
|
202
|
+
ensure
|
203
|
+
@visitor = old
|
204
|
+
end
|
205
|
+
|
121
206
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
122
207
|
# can always use downcase if needed.
|
123
208
|
def adapter_name
|
@@ -201,6 +286,12 @@ module ActiveRecord
|
|
201
286
|
[]
|
202
287
|
end
|
203
288
|
|
289
|
+
# A list of index algorithms, to be filled by adapters that support them.
|
290
|
+
# MySQL and PostgreSQL have support for them right now.
|
291
|
+
def index_algorithms
|
292
|
+
{}
|
293
|
+
end
|
294
|
+
|
204
295
|
# QUOTING ==================================================
|
205
296
|
|
206
297
|
# Returns a bind substitution value given a +column+ and list of current
|
@@ -342,7 +433,7 @@ module ActiveRecord
|
|
342
433
|
|
343
434
|
def translate_exception(exception, message)
|
344
435
|
# override in derived class
|
345
|
-
ActiveRecord::StatementInvalid.new(message)
|
436
|
+
ActiveRecord::StatementInvalid.new(message, exception)
|
346
437
|
end
|
347
438
|
end
|
348
439
|
end
|
@@ -3,13 +3,34 @@ require 'arel/visitors/bind_visitor'
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
class AbstractMysqlAdapter < AbstractAdapter
|
6
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation
|
7
|
+
private
|
8
|
+
|
9
|
+
def visit_AddColumn(o)
|
10
|
+
add_column_position!(super, o)
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_column_position!(sql, column)
|
14
|
+
if column.first
|
15
|
+
sql << " FIRST"
|
16
|
+
elsif column.after
|
17
|
+
sql << " AFTER #{quote_column_name(column.after)}"
|
18
|
+
end
|
19
|
+
sql
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def schema_creation
|
24
|
+
SchemaCreation.new self
|
25
|
+
end
|
26
|
+
|
6
27
|
class Column < ConnectionAdapters::Column # :nodoc:
|
7
|
-
attr_reader :collation, :strict
|
28
|
+
attr_reader :collation, :strict, :extra
|
8
29
|
|
9
|
-
def initialize(name, default, sql_type = nil, null = true, collation = nil, strict = false)
|
30
|
+
def initialize(name, default, sql_type = nil, null = true, collation = nil, strict = false, extra = "")
|
10
31
|
@strict = strict
|
11
32
|
@collation = collation
|
12
|
-
|
33
|
+
@extra = extra
|
13
34
|
super(name, default, sql_type, null)
|
14
35
|
end
|
15
36
|
|
@@ -61,6 +82,8 @@ module ActiveRecord
|
|
61
82
|
|
62
83
|
def extract_limit(sql_type)
|
63
84
|
case sql_type
|
85
|
+
when /^enum\((.+)\)/i
|
86
|
+
$1.split(',').map{|enum| enum.strip.length - 2}.max
|
64
87
|
when /blob|text/i
|
65
88
|
case sql_type
|
66
89
|
when /tiny/i
|
@@ -77,8 +100,6 @@ module ActiveRecord
|
|
77
100
|
when /^mediumint/i; 3
|
78
101
|
when /^smallint/i; 2
|
79
102
|
when /^tinyint/i; 1
|
80
|
-
when /^enum\((.+)\)/i
|
81
|
-
$1.split(',').map{|enum| enum.strip.length - 2}.max
|
82
103
|
else
|
83
104
|
super
|
84
105
|
end
|
@@ -130,6 +151,9 @@ module ActiveRecord
|
|
130
151
|
:boolean => { :name => "tinyint", :limit => 1 }
|
131
152
|
}
|
132
153
|
|
154
|
+
INDEX_TYPES = [:fulltext, :spatial]
|
155
|
+
INDEX_USINGS = [:btree, :hash]
|
156
|
+
|
133
157
|
class BindSubstitution < Arel::Visitors::MySQL # :nodoc:
|
134
158
|
include Arel::Visitors::BindVisitor
|
135
159
|
end
|
@@ -143,7 +167,7 @@ module ActiveRecord
|
|
143
167
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
144
168
|
@visitor = Arel::Visitors::MySQL.new self
|
145
169
|
else
|
146
|
-
@visitor =
|
170
|
+
@visitor = unprepared_visitor
|
147
171
|
end
|
148
172
|
end
|
149
173
|
|
@@ -187,6 +211,10 @@ module ActiveRecord
|
|
187
211
|
NATIVE_DATABASE_TYPES
|
188
212
|
end
|
189
213
|
|
214
|
+
def index_algorithms
|
215
|
+
{ default: 'ALGORITHM = DEFAULT', copy: 'ALGORITHM = COPY', inplace: 'ALGORITHM = INPLACE' }
|
216
|
+
end
|
217
|
+
|
190
218
|
# HELPER METHODS ===========================================
|
191
219
|
|
192
220
|
# The two drivers have slightly different ways of yielding hashes of results, so
|
@@ -196,8 +224,8 @@ module ActiveRecord
|
|
196
224
|
end
|
197
225
|
|
198
226
|
# Overridden by the adapters to instantiate their specific Column type.
|
199
|
-
def new_column(field, default, type, null, collation) # :nodoc:
|
200
|
-
Column.new(field, default, type, null, collation)
|
227
|
+
def new_column(field, default, type, null, collation, extra = "") # :nodoc:
|
228
|
+
Column.new(field, default, type, null, collation, extra)
|
201
229
|
end
|
202
230
|
|
203
231
|
# Must return the Mysql error number from the exception, if the exception has an
|
@@ -212,6 +240,8 @@ module ActiveRecord
|
|
212
240
|
if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
|
213
241
|
s = column.class.string_to_binary(value).unpack("H*")[0]
|
214
242
|
"x'#{s}'"
|
243
|
+
elsif value.kind_of?(BigDecimal)
|
244
|
+
value.to_s("F")
|
215
245
|
else
|
216
246
|
super
|
217
247
|
end
|
@@ -257,7 +287,7 @@ module ActiveRecord
|
|
257
287
|
end
|
258
288
|
rescue ActiveRecord::StatementInvalid => exception
|
259
289
|
if exception.message.split(":").first =~ /Packets out of order/
|
260
|
-
raise ActiveRecord::StatementInvalid
|
290
|
+
raise ActiveRecord::StatementInvalid.new("'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings.", exception.original_exception)
|
261
291
|
else
|
262
292
|
raise
|
263
293
|
end
|
@@ -330,20 +360,6 @@ module ActiveRecord
|
|
330
360
|
|
331
361
|
# SCHEMA STATEMENTS ========================================
|
332
362
|
|
333
|
-
def structure_dump #:nodoc:
|
334
|
-
if supports_views?
|
335
|
-
sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
|
336
|
-
else
|
337
|
-
sql = "SHOW TABLES"
|
338
|
-
end
|
339
|
-
|
340
|
-
select_all(sql, 'SCHEMA').map { |table|
|
341
|
-
table.delete('Table_type')
|
342
|
-
sql = "SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}"
|
343
|
-
exec_query(sql, 'SCHEMA').first['Create Table'] + ";\n\n"
|
344
|
-
}.join
|
345
|
-
end
|
346
|
-
|
347
363
|
# Drops the database specified on the +name+ attribute
|
348
364
|
# and creates it again using the provided +options+.
|
349
365
|
def recreate_database(name, options = {})
|
@@ -422,7 +438,11 @@ module ActiveRecord
|
|
422
438
|
if current_index != row[:Key_name]
|
423
439
|
next if row[:Key_name] == 'PRIMARY' # skip the primary key
|
424
440
|
current_index = row[:Key_name]
|
425
|
-
|
441
|
+
|
442
|
+
mysql_index_type = row[:Index_type].downcase.to_sym
|
443
|
+
index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
|
444
|
+
index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
|
445
|
+
indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [], nil, nil, index_type, index_using)
|
426
446
|
end
|
427
447
|
|
428
448
|
indexes.last.columns << row[:Column_name]
|
@@ -438,7 +458,7 @@ module ActiveRecord
|
|
438
458
|
sql = "SHOW FULL FIELDS FROM #{quote_table_name(table_name)}"
|
439
459
|
execute_and_free(sql, 'SCHEMA') do |result|
|
440
460
|
each_hash(result).map do |field|
|
441
|
-
new_column(field[:Field], field[:Default], field[:Type], field[:Null] == "YES", field[:Collation])
|
461
|
+
new_column(field[:Field], field[:Default], field[:Type], field[:Null] == "YES", field[:Collation], field[:Extra])
|
442
462
|
end
|
443
463
|
end
|
444
464
|
end
|
@@ -471,10 +491,6 @@ module ActiveRecord
|
|
471
491
|
rename_table_indexes(table_name, new_name)
|
472
492
|
end
|
473
493
|
|
474
|
-
def add_column(table_name, column_name, type, options = {})
|
475
|
-
execute("ALTER TABLE #{quote_table_name(table_name)} #{add_column_sql(table_name, column_name, type, options)}")
|
476
|
-
end
|
477
|
-
|
478
494
|
def change_column_default(table_name, column_name, default)
|
479
495
|
column = column_for(table_name, column_name)
|
480
496
|
change_column table_name, column_name, column.sql_type, :default => default
|
@@ -499,6 +515,11 @@ module ActiveRecord
|
|
499
515
|
rename_column_indexes(table_name, column_name, new_column_name)
|
500
516
|
end
|
501
517
|
|
518
|
+
def add_index(table_name, column_name, options = {}) #:nodoc:
|
519
|
+
index_name, index_type, index_columns, index_options, index_algorithm, index_using = add_index_options(table_name, column_name, options)
|
520
|
+
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options} #{index_algorithm}"
|
521
|
+
end
|
522
|
+
|
502
523
|
# Maps logical Rails types to MySQL-specific data types.
|
503
524
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
504
525
|
case type.to_s
|
@@ -584,6 +605,10 @@ module ActiveRecord
|
|
584
605
|
self.class.type_cast_config_to_boolean(@config.fetch(:strict, true))
|
585
606
|
end
|
586
607
|
|
608
|
+
def valid_type?(type)
|
609
|
+
!native_database_types[type].nil?
|
610
|
+
end
|
611
|
+
|
587
612
|
protected
|
588
613
|
|
589
614
|
# MySQL is too stupid to create a temporary table for use subquery, so we have
|
@@ -663,6 +688,7 @@ module ActiveRecord
|
|
663
688
|
if column = columns(table_name).find { |c| c.name == column_name.to_s }
|
664
689
|
options[:default] = column.default
|
665
690
|
options[:null] = column.null
|
691
|
+
options[:auto_increment] = (column.extra == "auto_increment")
|
666
692
|
else
|
667
693
|
raise ActiveRecordError, "No such column: #{table_name}.#{column_name}"
|
668
694
|
end
|
@@ -161,7 +161,7 @@ module ActiveRecord
|
|
161
161
|
|
162
162
|
def value_to_date(value)
|
163
163
|
if value.is_a?(String)
|
164
|
-
return nil if value.
|
164
|
+
return nil if value.empty?
|
165
165
|
fast_string_to_date(value) || fallback_string_to_date(value)
|
166
166
|
elsif value.respond_to?(:to_date)
|
167
167
|
value.to_date
|
@@ -172,14 +172,14 @@ module ActiveRecord
|
|
172
172
|
|
173
173
|
def string_to_time(string)
|
174
174
|
return string unless string.is_a?(String)
|
175
|
-
return nil if string.
|
175
|
+
return nil if string.empty?
|
176
176
|
|
177
177
|
fast_string_to_time(string) || fallback_string_to_time(string)
|
178
178
|
end
|
179
179
|
|
180
180
|
def string_to_dummy_time(string)
|
181
181
|
return string unless string.is_a?(String)
|
182
|
-
return nil if string.
|
182
|
+
return nil if string.empty?
|
183
183
|
|
184
184
|
dummy_time_string = "2000-01-01 #{string}"
|
185
185
|
|
@@ -192,7 +192,7 @@ module ActiveRecord
|
|
192
192
|
|
193
193
|
# convert something to a boolean
|
194
194
|
def value_to_boolean(value)
|
195
|
-
if value.is_a?(String) && value.
|
195
|
+
if value.is_a?(String) && value.empty?
|
196
196
|
nil
|
197
197
|
else
|
198
198
|
TRUE_VALUES.include?(value)
|
@@ -38,7 +38,7 @@ module ActiveRecord
|
|
38
38
|
private
|
39
39
|
def resolve_string_connection(spec) # :nodoc:
|
40
40
|
hash = configurations.fetch(spec) do |k|
|
41
|
-
|
41
|
+
connection_url_to_hash(k)
|
42
42
|
end
|
43
43
|
|
44
44
|
raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
|
@@ -65,7 +65,7 @@ module ActiveRecord
|
|
65
65
|
ConnectionSpecification.new(spec, adapter_method)
|
66
66
|
end
|
67
67
|
|
68
|
-
def
|
68
|
+
def connection_url_to_hash(url) # :nodoc:
|
69
69
|
config = URI.parse url
|
70
70
|
adapter = config.scheme
|
71
71
|
adapter = "postgresql" if adapter == "postgres"
|
@@ -4,7 +4,7 @@ gem 'mysql2', '~> 0.3.10'
|
|
4
4
|
require 'mysql2'
|
5
5
|
|
6
6
|
module ActiveRecord
|
7
|
-
module ConnectionHandling
|
7
|
+
module ConnectionHandling # :nodoc:
|
8
8
|
# Establishes a connection to the database that's used by all Active Record objects.
|
9
9
|
def mysql2_connection(config)
|
10
10
|
config = config.symbolize_keys
|
@@ -38,6 +38,15 @@ module ActiveRecord
|
|
38
38
|
configure_connection
|
39
39
|
end
|
40
40
|
|
41
|
+
MAX_INDEX_LENGTH_FOR_UTF8MB4 = 191
|
42
|
+
def initialize_schema_migrations_table
|
43
|
+
if @config[:encoding] == 'utf8mb4'
|
44
|
+
ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_UTF8MB4)
|
45
|
+
else
|
46
|
+
ActiveRecord::SchemaMigration.create_table
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
41
50
|
def supports_explain?
|
42
51
|
true
|
43
52
|
end
|
@@ -54,8 +63,8 @@ module ActiveRecord
|
|
54
63
|
end
|
55
64
|
end
|
56
65
|
|
57
|
-
def new_column(field, default, type, null, collation) # :nodoc:
|
58
|
-
Column.new(field, default, type, null, collation, strict_mode
|
66
|
+
def new_column(field, default, type, null, collation, extra = "") # :nodoc:
|
67
|
+
Column.new(field, default, type, null, collation, strict_mode?, extra)
|
59
68
|
end
|
60
69
|
|
61
70
|
def error_number(exception)
|
@@ -16,9 +16,9 @@ class Mysql
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module ActiveRecord
|
19
|
-
module ConnectionHandling
|
19
|
+
module ConnectionHandling # :nodoc:
|
20
20
|
# Establishes a connection to the database that's used by all Active Record objects.
|
21
|
-
def mysql_connection(config)
|
21
|
+
def mysql_connection(config)
|
22
22
|
config = config.symbolize_keys
|
23
23
|
host = config[:host]
|
24
24
|
port = config[:port]
|
@@ -150,8 +150,8 @@ module ActiveRecord
|
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
-
def new_column(field, default, type, null, collation) # :nodoc:
|
154
|
-
Column.new(field, default, type, null, collation, strict_mode
|
153
|
+
def new_column(field, default, type, null, collation, extra = "") # :nodoc:
|
154
|
+
Column.new(field, default, type, null, collation, strict_mode?, extra)
|
155
155
|
end
|
156
156
|
|
157
157
|
def error_number(exception) # :nodoc:
|
@@ -383,7 +383,7 @@ module ActiveRecord
|
|
383
383
|
|
384
384
|
TYPES = {}
|
385
385
|
|
386
|
-
# Register an MySQL +type_id+ with a
|
386
|
+
# Register an MySQL +type_id+ with a typecasting object in
|
387
387
|
# +type+.
|
388
388
|
def self.register_type(type_id, type)
|
389
389
|
TYPES[type_id] = type
|