activerecord 5.1.0 → 5.2.3
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 +596 -450
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +77 -85
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +49 -35
- data/lib/active_record/associations/association_scope.rb +55 -55
- data/lib/active_record/associations/belongs_to_association.rb +30 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +66 -53
- data/lib/active_record/associations/collection_proxy.rb +30 -73
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +13 -2
- data/lib/active_record/associations/has_many_through_association.rb +37 -19
- data/lib/active_record/associations/has_one_association.rb +14 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +52 -96
- data/lib/active_record/associations/join_dependency/join_association.rb +22 -75
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +53 -92
- data/lib/active_record/associations/preloader/through_association.rb +72 -73
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +27 -12
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +33 -216
- data/lib/active_record/attribute_methods/primary_key.rb +10 -13
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +22 -19
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +15 -13
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +120 -39
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +192 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -25
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +65 -7
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -87
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +86 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +126 -189
- data/lib/active_record/connection_adapters/column.rb +4 -2
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -15
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +258 -129
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -87
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +90 -96
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +41 -61
- data/lib/active_record/counter_cache.rb +20 -15
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +60 -15
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +30 -42
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +81 -29
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +74 -58
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +199 -54
- data/lib/active_record/query_cache.rb +8 -10
- data/lib/active_record/querying.rb +5 -3
- data/lib/active_record/railtie.rb +62 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +48 -38
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +137 -207
- data/lib/active_record/relation.rb +132 -207
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +66 -25
- data/lib/active_record/relation/delegation.rb +45 -29
- data/lib/active_record/relation/finder_methods.rb +76 -85
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +135 -103
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +12 -10
- data/lib/active_record/scoping/default.rb +10 -7
- data/lib/active_record/scoping/named.rb +40 -12
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +38 -26
- data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +32 -27
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +6 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +24 -36
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -113
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -124
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# :stopdoc:
|
3
5
|
module ConnectionAdapters
|
@@ -9,11 +11,11 @@ module ActiveRecord
|
|
9
11
|
|
10
12
|
# Instantiates a new column in the table.
|
11
13
|
#
|
12
|
-
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id
|
14
|
+
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id bigint</tt>.
|
13
15
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
14
16
|
# +sql_type_metadata+ is various information about the type of the column
|
15
17
|
# +null+ determines if this column allows +NULL+ values.
|
16
|
-
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
|
18
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil, **)
|
17
19
|
@name = name.freeze
|
18
20
|
@table_name = table_name
|
19
21
|
@sql_type_metadata = sql_type_metadata
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "uri"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -181,13 +183,25 @@ module ActiveRecord
|
|
181
183
|
|
182
184
|
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
183
185
|
|
186
|
+
# Require the adapter itself and give useful feedback about
|
187
|
+
# 1. Missing adapter gems and
|
188
|
+
# 2. Adapter gems' missing dependencies.
|
184
189
|
path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
185
190
|
begin
|
186
191
|
require path_to_adapter
|
187
|
-
rescue Gem::LoadError => e
|
188
|
-
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)."
|
189
192
|
rescue LoadError => e
|
190
|
-
|
193
|
+
# We couldn't require the adapter itself. Raise an exception that
|
194
|
+
# points out config typos and missing gems.
|
195
|
+
if e.path == path_to_adapter
|
196
|
+
# We can assume that a non-builtin adapter was specified, so it's
|
197
|
+
# either misspelled or missing from Gemfile.
|
198
|
+
raise LoadError, "Could not load the '#{spec[:adapter]}' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
|
199
|
+
|
200
|
+
# Bubbled up from the adapter require. Prefix the exception message
|
201
|
+
# with some guidance about how to address it and reraise.
|
202
|
+
else
|
203
|
+
raise LoadError, "Error loading the '#{spec[:adapter]}' Active Record adapter. Missing a gem it depends on? #{e.message}", e.backtrace
|
204
|
+
end
|
191
205
|
end
|
192
206
|
|
193
207
|
adapter_method = "#{spec[:adapter]}_connection"
|
@@ -1,15 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module DetermineIfPreparableVisitor
|
4
|
-
|
6
|
+
attr_accessor :preparable
|
5
7
|
|
6
8
|
def accept(*)
|
7
9
|
@preparable = true
|
8
10
|
super
|
9
11
|
end
|
10
12
|
|
11
|
-
def visit_Arel_Nodes_In(
|
13
|
+
def visit_Arel_Nodes_In(o, collector)
|
12
14
|
@preparable = false
|
15
|
+
|
16
|
+
if Array === o.right && !o.right.empty?
|
17
|
+
o.right.delete_if do |bind|
|
18
|
+
if Arel::Nodes::BindParam === bind && Relation::QueryAttribute === bind.value
|
19
|
+
!bind.value.boundable?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
13
24
|
super
|
14
25
|
end
|
15
26
|
|
@@ -1,25 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module MySQL
|
4
6
|
module DatabaseStatements
|
5
7
|
# Returns an ActiveRecord::Result instance.
|
6
|
-
def select_all(
|
8
|
+
def select_all(*) # :nodoc:
|
7
9
|
result = if ExplainRegistry.collect? && prepared_statements
|
8
10
|
unprepared_statement { super }
|
9
11
|
else
|
10
12
|
super
|
11
13
|
end
|
12
|
-
|
14
|
+
discard_remaining_results
|
13
15
|
result
|
14
16
|
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
def select_rows(arel, name = nil, binds = []) # :nodoc:
|
19
|
-
select_result(arel, name, binds) do |result|
|
20
|
-
@connection.next_result while @connection.more_results?
|
21
|
-
result.to_a
|
22
|
-
end
|
18
|
+
def query(sql, name = nil) # :nodoc:
|
19
|
+
execute(sql, name).to_a
|
23
20
|
end
|
24
21
|
|
25
22
|
# Executes the SQL statement in the context of this connection.
|
@@ -53,18 +50,51 @@ module ActiveRecord
|
|
53
50
|
alias :exec_update :exec_delete
|
54
51
|
|
55
52
|
private
|
53
|
+
def default_insert_value(column)
|
54
|
+
Arel.sql("DEFAULT") unless column.auto_increment?
|
55
|
+
end
|
56
56
|
|
57
57
|
def last_inserted_id(result)
|
58
58
|
@connection.last_id
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
def discard_remaining_results
|
62
|
+
@connection.next_result while @connection.more_results?
|
63
|
+
end
|
64
|
+
|
65
|
+
def supports_set_server_option?
|
66
|
+
@connection.respond_to?(:set_server_option)
|
67
|
+
end
|
68
|
+
|
69
|
+
def multi_statements_enabled?(flags)
|
70
|
+
if flags.is_a?(Array)
|
71
|
+
flags.include?("MULTI_STATEMENTS")
|
66
72
|
else
|
67
|
-
|
73
|
+
(flags & Mysql2::Client::MULTI_STATEMENTS) != 0
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def with_multi_statements
|
78
|
+
previous_flags = @config[:flags]
|
79
|
+
|
80
|
+
unless multi_statements_enabled?(previous_flags)
|
81
|
+
if supports_set_server_option?
|
82
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
83
|
+
else
|
84
|
+
@config[:flags] = Mysql2::Client::MULTI_STATEMENTS
|
85
|
+
reconnect!
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
yield
|
90
|
+
ensure
|
91
|
+
unless multi_statements_enabled?(previous_flags)
|
92
|
+
if supports_set_server_option?
|
93
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
94
|
+
else
|
95
|
+
@config[:flags] = previous_flags
|
96
|
+
reconnect!
|
97
|
+
end
|
68
98
|
end
|
69
99
|
end
|
70
100
|
|
@@ -1,9 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module MySQL
|
4
6
|
module Quoting # :nodoc:
|
5
|
-
QUOTED_TRUE, QUOTED_FALSE = "1".freeze, "0".freeze
|
6
|
-
|
7
7
|
def quote_column_name(name)
|
8
8
|
@quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`".freeze
|
9
9
|
end
|
@@ -12,18 +12,10 @@ module ActiveRecord
|
|
12
12
|
@quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
|
13
13
|
end
|
14
14
|
|
15
|
-
def quoted_true
|
16
|
-
QUOTED_TRUE
|
17
|
-
end
|
18
|
-
|
19
15
|
def unquoted_true
|
20
16
|
1
|
21
17
|
end
|
22
18
|
|
23
|
-
def quoted_false
|
24
|
-
QUOTED_FALSE
|
25
|
-
end
|
26
|
-
|
27
19
|
def unquoted_false
|
28
20
|
0
|
29
21
|
end
|
@@ -39,6 +31,13 @@ module ActiveRecord
|
|
39
31
|
def quoted_binary(value)
|
40
32
|
"x'#{value.hex}'"
|
41
33
|
end
|
34
|
+
|
35
|
+
def _type_cast(value)
|
36
|
+
case value
|
37
|
+
when Date, Time then value
|
38
|
+
else super
|
39
|
+
end
|
40
|
+
end
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module MySQL
|
@@ -16,7 +18,7 @@ module ActiveRecord
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def visit_ChangeColumnDefinition(o)
|
19
|
-
change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
21
|
+
change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}".dup
|
20
22
|
add_column_position!(change_column_sql, column_options(o.column))
|
21
23
|
end
|
22
24
|
|
@@ -28,7 +30,7 @@ module ActiveRecord
|
|
28
30
|
# By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
|
29
31
|
# and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
|
30
32
|
# column to contain NULL, explicitly declare it with the NULL attribute.
|
31
|
-
# See
|
33
|
+
# See https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html
|
32
34
|
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
|
33
35
|
sql << " NULL" unless options[:null] == false || options_include_default?(options)
|
34
36
|
end
|
@@ -63,7 +65,7 @@ module ActiveRecord
|
|
63
65
|
|
64
66
|
def index_in_create(table_name, column_name, options)
|
65
67
|
index_name, index_type, index_columns, _, _, index_using, comment = @conn.add_index_options(table_name, column_name, options)
|
66
|
-
add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})", comment)
|
68
|
+
add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})".dup, comment)
|
67
69
|
end
|
68
70
|
end
|
69
71
|
end
|
@@ -1,12 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module MySQL
|
4
6
|
module ColumnMethods
|
5
|
-
def primary_key(name, type = :primary_key, **options)
|
6
|
-
options[:auto_increment] = true if [:integer, :bigint].include?(type) && !options.key?(:default)
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
7
|
def blob(*args, **options)
|
11
8
|
args.each { |name| column(name, :blob, options) }
|
12
9
|
end
|
@@ -35,10 +32,6 @@ module ActiveRecord
|
|
35
32
|
args.each { |name| column(name, :longtext, options) }
|
36
33
|
end
|
37
34
|
|
38
|
-
def json(*args, **options)
|
39
|
-
args.each { |name| column(name, :json, options) }
|
40
|
-
end
|
41
|
-
|
42
35
|
def unsigned_integer(*args, **options)
|
43
36
|
args.each { |name| column(name, :unsigned_integer, options) }
|
44
37
|
end
|
@@ -66,7 +59,6 @@ module ActiveRecord
|
|
66
59
|
when :primary_key
|
67
60
|
type = :integer
|
68
61
|
options[:limit] ||= 8
|
69
|
-
options[:auto_increment] = true
|
70
62
|
options[:primary_key] = true
|
71
63
|
when /\Aunsigned_(?<type>.+)\z/
|
72
64
|
type = $~[:type].to_sym
|
@@ -80,6 +72,11 @@ module ActiveRecord
|
|
80
72
|
def aliased_types(name, fallback)
|
81
73
|
fallback
|
82
74
|
end
|
75
|
+
|
76
|
+
def integer_like_primary_key_type(type, options)
|
77
|
+
options[:auto_increment] = true
|
78
|
+
type
|
79
|
+
end
|
83
80
|
end
|
84
81
|
|
85
82
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
@@ -1,25 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module MySQL
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
spec[:as] = extract_expression_for_virtual_column(column)
|
11
|
-
spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
|
12
|
-
spec = { type: schema_type(column).inspect }.merge!(spec)
|
13
|
-
end
|
6
|
+
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
7
|
+
private
|
8
|
+
def prepare_column_options(column)
|
9
|
+
spec = super
|
10
|
+
spec[:unsigned] = "true" if column.unsigned?
|
11
|
+
spec[:auto_increment] = "true" if column.auto_increment?
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
if @connection.supports_virtual_columns? && column.virtual?
|
14
|
+
spec[:as] = extract_expression_for_virtual_column(column)
|
15
|
+
spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
|
16
|
+
spec = { type: schema_type(column).inspect }.merge!(spec)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
end
|
19
|
+
spec
|
20
|
+
end
|
21
21
|
|
22
|
-
|
22
|
+
def column_spec_for_primary_key(column)
|
23
|
+
spec = super
|
24
|
+
spec.delete(:auto_increment) if column.type == :integer && column.auto_increment?
|
25
|
+
spec
|
26
|
+
end
|
23
27
|
|
24
28
|
def default_primary_key?(column)
|
25
29
|
super && column.auto_increment? && !column.unsigned?
|
@@ -47,24 +51,27 @@ module ActiveRecord
|
|
47
51
|
def schema_collation(column)
|
48
52
|
if column.collation && table_name = column.table_name
|
49
53
|
@table_collation_cache ||= {}
|
50
|
-
@table_collation_cache[table_name] ||=
|
54
|
+
@table_collation_cache[table_name] ||=
|
55
|
+
@connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
|
51
56
|
column.collation.inspect if column.collation != @table_collation_cache[table_name]
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
60
|
def extract_expression_for_virtual_column(column)
|
56
|
-
if mariadb?
|
57
|
-
create_table_info = create_table_info
|
58
|
-
|
61
|
+
if @connection.mariadb? && @connection.version < "10.2.5"
|
62
|
+
create_table_info = @connection.send(:create_table_info, column.table_name)
|
63
|
+
column_name = @connection.quote_column_name(column.name)
|
64
|
+
if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
|
59
65
|
$~[:expression].inspect
|
60
66
|
end
|
61
67
|
else
|
62
|
-
scope = quoted_scope
|
68
|
+
scope = @connection.send(:quoted_scope, column.table_name)
|
69
|
+
column_name = @connection.quote(column.name)
|
63
70
|
sql = "SELECT generation_expression FROM information_schema.columns" \
|
64
71
|
" WHERE table_schema = #{scope[:schema]}" \
|
65
72
|
" AND table_name = #{scope[:name]}" \
|
66
|
-
" AND column_name = #{
|
67
|
-
|
73
|
+
" AND column_name = #{column_name}"
|
74
|
+
@connection.query_value(sql, "SCHEMA").inspect
|
68
75
|
end
|
69
76
|
end
|
70
77
|
end
|
@@ -1,7 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module MySQL
|
4
6
|
module SchemaStatements # :nodoc:
|
7
|
+
# Returns an array of indexes for the given table.
|
8
|
+
def indexes(table_name)
|
9
|
+
indexes = []
|
10
|
+
current_index = nil
|
11
|
+
execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
|
12
|
+
each_hash(result) do |row|
|
13
|
+
if current_index != row[:Key_name]
|
14
|
+
next if row[:Key_name] == "PRIMARY" # skip the primary key
|
15
|
+
current_index = row[:Key_name]
|
16
|
+
|
17
|
+
mysql_index_type = row[:Index_type].downcase.to_sym
|
18
|
+
case mysql_index_type
|
19
|
+
when :fulltext, :spatial
|
20
|
+
index_type = mysql_index_type
|
21
|
+
when :btree, :hash
|
22
|
+
index_using = mysql_index_type
|
23
|
+
end
|
24
|
+
|
25
|
+
indexes << [
|
26
|
+
row[:Table],
|
27
|
+
row[:Key_name],
|
28
|
+
row[:Non_unique].to_i == 0,
|
29
|
+
[],
|
30
|
+
lengths: {},
|
31
|
+
orders: {},
|
32
|
+
type: index_type,
|
33
|
+
using: index_using,
|
34
|
+
comment: row[:Index_comment].presence
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
indexes.last[-2] << row[:Column_name]
|
39
|
+
indexes.last[-1][:lengths].merge!(row[:Column_name] => row[:Sub_part].to_i) if row[:Sub_part]
|
40
|
+
indexes.last[-1][:orders].merge!(row[:Column_name] => :desc) if row[:Collation] == "D"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
indexes.map { |index| IndexDefinition.new(*index) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def remove_column(table_name, column_name, type = nil, options = {})
|
48
|
+
if foreign_key_exists?(table_name, column: column_name)
|
49
|
+
remove_foreign_key(table_name, column: column_name)
|
50
|
+
end
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
5
54
|
def internal_string_options_for_primary_key
|
6
55
|
super.tap do |options|
|
7
56
|
if CHARSETS_OF_4BYTES_MAXLEN.include?(charset) && (mariadb? || version < "8.0.0")
|
@@ -10,13 +59,69 @@ module ActiveRecord
|
|
10
59
|
end
|
11
60
|
end
|
12
61
|
|
62
|
+
def update_table_definition(table_name, base)
|
63
|
+
MySQL::Table.new(table_name, base)
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_schema_dumper(options)
|
67
|
+
MySQL::SchemaDumper.create(self, options)
|
68
|
+
end
|
69
|
+
|
13
70
|
private
|
14
71
|
CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
|
15
72
|
|
73
|
+
def schema_creation
|
74
|
+
MySQL::SchemaCreation.new(self)
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_table_definition(*args)
|
78
|
+
MySQL::TableDefinition.new(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def new_column_from_field(table_name, field)
|
82
|
+
type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
|
83
|
+
if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(field[:Default])
|
84
|
+
default, default_function = nil, field[:Default]
|
85
|
+
else
|
86
|
+
default, default_function = field[:Default], nil
|
87
|
+
end
|
88
|
+
|
89
|
+
MySQL::Column.new(
|
90
|
+
field[:Field],
|
91
|
+
default,
|
92
|
+
type_metadata,
|
93
|
+
field[:Null] == "YES",
|
94
|
+
table_name,
|
95
|
+
default_function,
|
96
|
+
field[:Collation],
|
97
|
+
comment: field[:Comment].presence
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
def fetch_type_metadata(sql_type, extra = "")
|
102
|
+
MySQL::TypeMetadata.new(super(sql_type), extra: extra)
|
103
|
+
end
|
104
|
+
|
105
|
+
def extract_foreign_key_action(specifier)
|
106
|
+
super unless specifier == "RESTRICT"
|
107
|
+
end
|
108
|
+
|
109
|
+
def add_index_length(quoted_columns, **options)
|
110
|
+
lengths = options_for_index_columns(options[:length])
|
111
|
+
quoted_columns.each do |name, column|
|
112
|
+
column << "(#{lengths[name]})" if lengths[name].present?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_options_for_index_columns(quoted_columns, **options)
|
117
|
+
quoted_columns = add_index_length(quoted_columns, options)
|
118
|
+
super
|
119
|
+
end
|
120
|
+
|
16
121
|
def data_source_sql(name = nil, type: nil)
|
17
122
|
scope = quoted_scope(name, type: type)
|
18
123
|
|
19
|
-
sql = "SELECT table_name FROM information_schema.tables"
|
124
|
+
sql = "SELECT table_name FROM information_schema.tables".dup
|
20
125
|
sql << " WHERE table_schema = #{scope[:schema]}"
|
21
126
|
sql << " AND table_name = #{scope[:name]}" if scope[:name]
|
22
127
|
sql << " AND table_type = #{scope[:type]}" if scope[:type]
|