activerecord 4.2.11.3 → 5.0.0.beta1
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 +5 -5
- data/CHANGELOG.md +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +16 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -5,42 +5,32 @@ module ActiveRecord
|
|
5
5
|
module ConnectionAdapters
|
6
6
|
# An abstract definition of a column in a table.
|
7
7
|
class Column
|
8
|
-
|
9
|
-
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set
|
8
|
+
attr_reader :name, :null, :sql_type_metadata, :default, :default_function, :collation
|
10
9
|
|
11
|
-
|
12
|
-
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
13
|
-
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
|
14
|
-
end
|
15
|
-
|
16
|
-
attr_reader :name, :cast_type, :null, :sql_type, :default, :default_function
|
17
|
-
|
18
|
-
delegate :type, :precision, :scale, :limit, :klass, :accessor,
|
19
|
-
:text?, :number?, :binary?, :changed?,
|
20
|
-
:type_cast_from_user, :type_cast_from_database, :type_cast_for_database,
|
21
|
-
:type_cast_for_schema,
|
22
|
-
to: :cast_type
|
10
|
+
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
23
11
|
|
24
12
|
# Instantiates a new column in the table.
|
25
13
|
#
|
26
|
-
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int
|
14
|
+
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int</tt>.
|
27
15
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
28
|
-
# +
|
29
|
-
# +sql_type+ is used to extract the column's length, if necessary. For example +60+ in
|
30
|
-
# <tt>company_name varchar(60)</tt>.
|
31
|
-
# It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
|
16
|
+
# +sql_type_metadata+ is various information about the type of the column
|
32
17
|
# +null+ determines if this column allows +NULL+ values.
|
33
|
-
def initialize(name, default,
|
34
|
-
@name
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@
|
18
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation = nil)
|
19
|
+
@name = name.freeze
|
20
|
+
@sql_type_metadata = sql_type_metadata
|
21
|
+
@null = null
|
22
|
+
@default = default
|
23
|
+
@default_function = default_function
|
24
|
+
@collation = collation
|
25
|
+
@table_name = nil
|
40
26
|
end
|
41
27
|
|
42
28
|
def has_default?
|
43
|
-
!default.nil?
|
29
|
+
!default.nil? || default_function
|
30
|
+
end
|
31
|
+
|
32
|
+
def bigint?
|
33
|
+
/bigint/ === sql_type
|
44
34
|
end
|
45
35
|
|
46
36
|
# Returns the human name of the column name.
|
@@ -51,19 +41,9 @@ module ActiveRecord
|
|
51
41
|
Base.human_attribute_name(@name)
|
52
42
|
end
|
53
43
|
|
54
|
-
def with_type(type)
|
55
|
-
dup.tap do |clone|
|
56
|
-
clone.instance_variable_set('@cast_type', type)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
44
|
def ==(other)
|
61
|
-
other.
|
62
|
-
|
63
|
-
other.cast_type == cast_type &&
|
64
|
-
other.sql_type == sql_type &&
|
65
|
-
other.null == null &&
|
66
|
-
other.default_function == default_function
|
45
|
+
other.is_a?(Column) &&
|
46
|
+
attributes_for_hash == other.attributes_for_hash
|
67
47
|
end
|
68
48
|
alias :eql? :==
|
69
49
|
|
@@ -71,10 +51,16 @@ module ActiveRecord
|
|
71
51
|
attributes_for_hash.hash
|
72
52
|
end
|
73
53
|
|
74
|
-
|
54
|
+
protected
|
75
55
|
|
76
56
|
def attributes_for_hash
|
77
|
-
[self.class, name, default,
|
57
|
+
[self.class, name, default, sql_type_metadata, null, default_function, collation]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class NullColumn < Column
|
62
|
+
def initialize(name)
|
63
|
+
super(name, nil)
|
78
64
|
end
|
79
65
|
end
|
80
66
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'uri'
|
2
|
-
require 'active_support/core_ext/string/filters'
|
3
2
|
|
4
3
|
module ActiveRecord
|
5
4
|
module ConnectionAdapters
|
@@ -176,7 +175,7 @@ module ActiveRecord
|
|
176
175
|
rescue Gem::LoadError => e
|
177
176
|
raise Gem::LoadError, "Specified '#{spec[:adapter]}' for database adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord)."
|
178
177
|
rescue LoadError => e
|
179
|
-
raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than '
|
178
|
+
raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
|
180
179
|
end
|
181
180
|
|
182
181
|
adapter_method = "#{spec[:adapter]}_connection"
|
@@ -210,30 +209,12 @@ module ActiveRecord
|
|
210
209
|
when Symbol
|
211
210
|
resolve_symbol_connection spec
|
212
211
|
when String
|
213
|
-
|
212
|
+
resolve_url_connection spec
|
214
213
|
when Hash
|
215
214
|
resolve_hash_connection spec
|
216
215
|
end
|
217
216
|
end
|
218
217
|
|
219
|
-
def resolve_string_connection(spec)
|
220
|
-
# Rails has historically accepted a string to mean either
|
221
|
-
# an environment key or a URL spec, so we have deprecated
|
222
|
-
# this ambiguous behaviour and in the future this function
|
223
|
-
# can be removed in favor of resolve_url_connection.
|
224
|
-
if configurations.key?(spec) || spec !~ /:/
|
225
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
226
|
-
Passing a string to ActiveRecord::Base.establish_connection for a
|
227
|
-
configuration lookup is deprecated, please pass a symbol
|
228
|
-
(#{spec.to_sym.inspect}) instead.
|
229
|
-
MSG
|
230
|
-
|
231
|
-
resolve_symbol_connection(spec)
|
232
|
-
else
|
233
|
-
resolve_url_connection(spec)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
218
|
# Takes the environment such as +:production+ or +:development+.
|
238
219
|
# This requires that the @configurations was initialized with a key that
|
239
220
|
# matches.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module DetermineIfPreparableVisitor
|
4
|
+
attr_reader :preparable
|
5
|
+
|
6
|
+
def accept(*)
|
7
|
+
@preparable = true
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_Arel_Nodes_In(*)
|
12
|
+
@preparable = false
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit_Arel_Nodes_SqlLiteral(*)
|
17
|
+
@preparable = false
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation
|
5
|
+
private
|
6
|
+
|
7
|
+
def visit_DropForeignKey(name)
|
8
|
+
"DROP FOREIGN KEY #{name}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_ColumnDefinition(o)
|
12
|
+
o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.unsigned)
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit_AddColumnDefinition(o)
|
17
|
+
add_column_position!(super, column_options(o.column))
|
18
|
+
end
|
19
|
+
|
20
|
+
def visit_ChangeColumnDefinition(o)
|
21
|
+
change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
22
|
+
add_column_position!(change_column_sql, column_options(o.column))
|
23
|
+
end
|
24
|
+
|
25
|
+
def column_options(o)
|
26
|
+
column_options = super
|
27
|
+
column_options[:charset] = o.charset
|
28
|
+
column_options
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_column_options!(sql, options)
|
32
|
+
if options[:charset]
|
33
|
+
sql << " CHARACTER SET #{options[:charset]}"
|
34
|
+
end
|
35
|
+
if options[:collation]
|
36
|
+
sql << " COLLATE #{options[:collation]}"
|
37
|
+
end
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_column_position!(sql, options)
|
42
|
+
if options[:first]
|
43
|
+
sql << " FIRST"
|
44
|
+
elsif options[:after]
|
45
|
+
sql << " AFTER #{quote_column_name(options[:after])}"
|
46
|
+
end
|
47
|
+
sql
|
48
|
+
end
|
49
|
+
|
50
|
+
def index_in_create(table_name, column_name, options)
|
51
|
+
index_name, index_type, index_columns, _, _, index_using = @conn.add_index_options(table_name, column_name, options)
|
52
|
+
"#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns}) "
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
module ColumnMethods
|
5
|
+
def primary_key(name, type = :primary_key, **options)
|
6
|
+
options[:auto_increment] = true if type == :bigint && !options.key?(:default)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def blob(*args, **options)
|
11
|
+
args.each { |name| column(name, :blob, options) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def json(*args, **options)
|
15
|
+
args.each { |name| column(name, :json, options) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def unsigned_integer(*args, **options)
|
19
|
+
args.each { |name| column(name, :unsigned_integer, options) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def unsigned_bigint(*args, **options)
|
23
|
+
args.each { |name| column(name, :unsigned_bigint, options) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def unsigned_float(*args, **options)
|
27
|
+
args.each { |name| column(name, :unsigned_float, options) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def unsigned_decimal(*args, **options)
|
31
|
+
args.each { |name| column(name, :unsigned_decimal, options) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
36
|
+
attr_accessor :charset, :unsigned
|
37
|
+
end
|
38
|
+
|
39
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
40
|
+
include ColumnMethods
|
41
|
+
|
42
|
+
def new_column_definition(name, type, options) # :nodoc:
|
43
|
+
column = super
|
44
|
+
case column.type
|
45
|
+
when :primary_key
|
46
|
+
column.type = :integer
|
47
|
+
column.auto_increment = true
|
48
|
+
when /\Aunsigned_(?<type>.+)\z/
|
49
|
+
column.type = $~[:type].to_sym
|
50
|
+
column.unsigned = true
|
51
|
+
end
|
52
|
+
column.unsigned ||= options[:unsigned]
|
53
|
+
column.charset = options[:charset]
|
54
|
+
column
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def create_column_definition(name, type)
|
60
|
+
MySQL::ColumnDefinition.new(name, type)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
65
|
+
include ColumnMethods
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
module ColumnDumper
|
5
|
+
def column_spec_for_primary_key(column)
|
6
|
+
spec = {}
|
7
|
+
if column.bigint?
|
8
|
+
spec[:id] = ':bigint'
|
9
|
+
spec[:default] = schema_default(column) || 'nil' unless column.auto_increment?
|
10
|
+
spec[:unsigned] = 'true' if column.unsigned?
|
11
|
+
elsif column.auto_increment?
|
12
|
+
spec[:unsigned] = 'true' if column.unsigned?
|
13
|
+
return if spec.empty?
|
14
|
+
else
|
15
|
+
spec[:id] = column.type.inspect
|
16
|
+
spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) })
|
17
|
+
end
|
18
|
+
spec
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare_column_options(column)
|
22
|
+
spec = super
|
23
|
+
spec[:unsigned] = 'true' if column.unsigned?
|
24
|
+
spec
|
25
|
+
end
|
26
|
+
|
27
|
+
def migration_keys
|
28
|
+
super + [:unsigned]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def schema_type(column)
|
34
|
+
if column.sql_type == 'tinyblob'
|
35
|
+
'blob'
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def schema_limit(column)
|
42
|
+
super unless column.type == :boolean
|
43
|
+
end
|
44
|
+
|
45
|
+
def schema_precision(column)
|
46
|
+
super unless /time/ === column.sql_type && column.precision == 0
|
47
|
+
end
|
48
|
+
|
49
|
+
def schema_collation(column)
|
50
|
+
if column.collation && table_name = column.instance_variable_get(:@table_name)
|
51
|
+
@table_collation_cache ||= {}
|
52
|
+
@table_collation_cache[table_name] ||= select_one("SHOW TABLE STATUS LIKE '#{table_name}'")["Collation"]
|
53
|
+
column.collation.inspect if column.collation != @table_collation_cache[table_name]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
2
2
|
|
3
|
-
gem 'mysql2', '>= 0.3.
|
3
|
+
gem 'mysql2', '>= 0.3.18', '< 0.5'
|
4
4
|
require 'mysql2'
|
5
5
|
|
6
6
|
module ActiveRecord
|
@@ -10,17 +10,16 @@ module ActiveRecord
|
|
10
10
|
config = config.symbolize_keys
|
11
11
|
|
12
12
|
config[:username] = 'root' if config[:username].nil?
|
13
|
-
|
13
|
+
config[:flags] ||= 0
|
14
14
|
if Mysql2::Client.const_defined? :FOUND_ROWS
|
15
|
-
config[:flags]
|
15
|
+
config[:flags] |= Mysql2::Client::FOUND_ROWS
|
16
16
|
end
|
17
17
|
|
18
18
|
client = Mysql2::Client.new(config)
|
19
|
-
|
20
|
-
ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
|
19
|
+
ConnectionAdapters::Mysql2Adapter.new(client, logger, nil, config)
|
21
20
|
rescue Mysql2::Error => error
|
22
21
|
if error.message.include?("Unknown database")
|
23
|
-
raise ActiveRecord::NoDatabaseError
|
22
|
+
raise ActiveRecord::NoDatabaseError
|
24
23
|
else
|
25
24
|
raise
|
26
25
|
end
|
@@ -37,17 +36,8 @@ module ActiveRecord
|
|
37
36
|
configure_connection
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
if charset == 'utf8mb4'
|
43
|
-
ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_UTF8MB4)
|
44
|
-
else
|
45
|
-
ActiveRecord::SchemaMigration.create_table
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def supports_explain?
|
50
|
-
true
|
39
|
+
def supports_json?
|
40
|
+
version >= '5.7.8'
|
51
41
|
end
|
52
42
|
|
53
43
|
# HELPER METHODS ===========================================
|
@@ -79,6 +69,7 @@ module ActiveRecord
|
|
79
69
|
#++
|
80
70
|
|
81
71
|
def active?
|
72
|
+
return false unless @connection
|
82
73
|
@connection.ping
|
83
74
|
end
|
84
75
|
|
@@ -93,87 +84,16 @@ module ActiveRecord
|
|
93
84
|
# Otherwise, this method does nothing.
|
94
85
|
def disconnect!
|
95
86
|
super
|
96
|
-
@connection.
|
87
|
+
unless @connection.nil?
|
88
|
+
@connection.close
|
89
|
+
@connection = nil
|
90
|
+
end
|
97
91
|
end
|
98
92
|
|
99
93
|
#--
|
100
94
|
# DATABASE STATEMENTS ======================================
|
101
95
|
#++
|
102
96
|
|
103
|
-
def explain(arel, binds = [])
|
104
|
-
sql = "EXPLAIN #{to_sql(arel, binds.dup)}"
|
105
|
-
start = Time.now
|
106
|
-
result = exec_query(sql, 'EXPLAIN', binds)
|
107
|
-
elapsed = Time.now - start
|
108
|
-
|
109
|
-
ExplainPrettyPrinter.new.pp(result, elapsed)
|
110
|
-
end
|
111
|
-
|
112
|
-
class ExplainPrettyPrinter # :nodoc:
|
113
|
-
# Pretty prints the result of a EXPLAIN in a way that resembles the output of the
|
114
|
-
# MySQL shell:
|
115
|
-
#
|
116
|
-
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
117
|
-
# | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
118
|
-
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
119
|
-
# | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
|
120
|
-
# | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
|
121
|
-
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
122
|
-
# 2 rows in set (0.00 sec)
|
123
|
-
#
|
124
|
-
# This is an exercise in Ruby hyperrealism :).
|
125
|
-
def pp(result, elapsed)
|
126
|
-
widths = compute_column_widths(result)
|
127
|
-
separator = build_separator(widths)
|
128
|
-
|
129
|
-
pp = []
|
130
|
-
|
131
|
-
pp << separator
|
132
|
-
pp << build_cells(result.columns, widths)
|
133
|
-
pp << separator
|
134
|
-
|
135
|
-
result.rows.each do |row|
|
136
|
-
pp << build_cells(row, widths)
|
137
|
-
end
|
138
|
-
|
139
|
-
pp << separator
|
140
|
-
pp << build_footer(result.rows.length, elapsed)
|
141
|
-
|
142
|
-
pp.join("\n") + "\n"
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
|
147
|
-
def compute_column_widths(result)
|
148
|
-
[].tap do |widths|
|
149
|
-
result.columns.each_with_index do |column, i|
|
150
|
-
cells_in_column = [column] + result.rows.map {|r| r[i].nil? ? 'NULL' : r[i].to_s}
|
151
|
-
widths << cells_in_column.map(&:length).max
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def build_separator(widths)
|
157
|
-
padding = 1
|
158
|
-
'+' + widths.map {|w| '-' * (w + (padding*2))}.join('+') + '+'
|
159
|
-
end
|
160
|
-
|
161
|
-
def build_cells(items, widths)
|
162
|
-
cells = []
|
163
|
-
items.each_with_index do |item, i|
|
164
|
-
item = 'NULL' if item.nil?
|
165
|
-
justifier = item.is_a?(Numeric) ? 'rjust' : 'ljust'
|
166
|
-
cells << item.to_s.send(justifier, widths[i])
|
167
|
-
end
|
168
|
-
'| ' + cells.join(' | ') + ' |'
|
169
|
-
end
|
170
|
-
|
171
|
-
def build_footer(nrows, elapsed)
|
172
|
-
rows_label = nrows == 1 ? 'row' : 'rows'
|
173
|
-
"#{nrows} #{rows_label} in set (%.2f sec)" % elapsed
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
97
|
# FIXME: re-enable the following once a "better" query_cache solution is in core
|
178
98
|
#
|
179
99
|
# The overrides below perform much better than the originals in AbstractAdapter
|
@@ -205,20 +125,25 @@ module ActiveRecord
|
|
205
125
|
# Returns an array of arrays containing the field values.
|
206
126
|
# Order is the same as that returned by +columns+.
|
207
127
|
def select_rows(sql, name = nil, binds = [])
|
208
|
-
execute(sql, name)
|
128
|
+
result = execute(sql, name)
|
129
|
+
@connection.next_result while @connection.more_results?
|
130
|
+
result.to_a
|
209
131
|
end
|
210
132
|
|
211
133
|
# Executes the SQL statement in the context of this connection.
|
212
134
|
def execute(sql, name = nil)
|
213
|
-
|
214
|
-
|
215
|
-
|
135
|
+
if @connection
|
136
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
137
|
+
# made since we established the connection
|
138
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
139
|
+
end
|
216
140
|
|
217
141
|
super
|
218
142
|
end
|
219
143
|
|
220
|
-
def exec_query(sql, name = 'SQL', binds = [])
|
144
|
+
def exec_query(sql, name = 'SQL', binds = [], prepare: false)
|
221
145
|
result = execute(sql, name)
|
146
|
+
@connection.next_result while @connection.more_results?
|
222
147
|
ActiveRecord::Result.new(result.fields, result.to_a)
|
223
148
|
end
|
224
149
|
|
@@ -259,10 +184,6 @@ module ActiveRecord
|
|
259
184
|
def full_version
|
260
185
|
@full_version ||= @connection.server_info[:version]
|
261
186
|
end
|
262
|
-
|
263
|
-
def set_field_encoding field_name
|
264
|
-
field_name
|
265
|
-
end
|
266
187
|
end
|
267
188
|
end
|
268
189
|
end
|