activerecord 5.1.0 → 5.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +410 -530
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +4 -2
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +20 -21
- data/lib/active_record/associations/association_scope.rb +49 -49
- data/lib/active_record/associations/belongs_to_association.rb +12 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +10 -6
- 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 +50 -41
- data/lib/active_record/associations/collection_proxy.rb +22 -39
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +12 -18
- data/lib/active_record/associations/has_one_association.rb +5 -1
- data/lib/active_record/associations/has_one_through_association.rb +8 -7
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/join_dependency.rb +27 -44
- 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/preloader.rb +17 -37
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +68 -76
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +24 -214
- 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 +8 -2
- 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/attribute_methods.rb +48 -12
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +8 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -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 +14 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
- 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 +58 -3
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
- 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 +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
- 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/array.rb +2 -0
- 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_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 +4 -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/oid.rb +2 -1
- 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 +14 -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 +269 -126
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
- 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 +18 -0
- 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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
- 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 +39 -60
- data/lib/active_record/counter_cache.rb +3 -2
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +17 -13
- data/lib/active_record/errors.rb +42 -3
- 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 +9 -9
- 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 +8 -6
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +74 -22
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +181 -137
- data/lib/active_record/model_schema.rb +73 -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 +153 -18
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +61 -3
- 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 +47 -37
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +131 -204
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/calculations.rb +58 -20
- data/lib/active_record/relation/delegation.rb +10 -29
- data/lib/active_record/relation/finder_methods.rb +74 -85
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +51 -20
- 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 +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +53 -78
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +101 -95
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -1
- 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/relation.rb +99 -202
- 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/default.rb +10 -7
- data/lib/active_record/scoping/named.rb +38 -12
- data/lib/active_record/scoping.rb +12 -10
- 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 +37 -25
- 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 +5 -5
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- 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 +2 -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.rb +4 -1
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.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 +35 -5
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/version.rb +2 -0
- data/lib/active_record.rb +11 -4
- 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/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/migration.rb +2 -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
- data/lib/rails/generators/active_record.rb +3 -1
- metadata +25 -37
- 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/user_provided_default.rb +0 -30
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute_mutation_tracker.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/attribute_set.rb +0 -113
- 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,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,19 +50,16 @@ 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
|
-
sql = to_sql(arel, binds)
|
64
|
-
if without_prepared_statement?(binds)
|
65
|
-
execute_and_free(sql, name) { |result| yield result }
|
66
|
-
else
|
67
|
-
exec_stmt_and_free(sql, name, binds, cache_stmt: true) { |_, result| yield result }
|
68
|
-
end
|
61
|
+
def discard_remaining_results
|
62
|
+
@connection.next_result while @connection.more_results?
|
69
63
|
end
|
70
64
|
|
71
65
|
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
@@ -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(?:\(\))?\z/i.match?(field[:Default])
|
84
|
+
default, default_function = nil, "CURRENT_TIMESTAMP"
|
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]
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record/connection_adapters/abstract_mysql_adapter"
|
2
4
|
require "active_record/connection_adapters/mysql/database_statements"
|
3
5
|
|
4
|
-
gem "mysql2", "
|
6
|
+
gem "mysql2", "~> 0.4.4"
|
5
7
|
require "mysql2"
|
6
|
-
raise "mysql2 0.4.3 is not supported. Please upgrade to 0.4.4+" if Mysql2::VERSION == "0.4.3"
|
7
8
|
|
8
9
|
module ActiveRecord
|
9
10
|
module ConnectionHandling # :nodoc:
|
@@ -103,6 +104,11 @@ module ActiveRecord
|
|
103
104
|
@connection.close
|
104
105
|
end
|
105
106
|
|
107
|
+
def discard! # :nodoc:
|
108
|
+
@connection.automatic_close = false
|
109
|
+
@connection = nil
|
110
|
+
end
|
111
|
+
|
106
112
|
private
|
107
113
|
|
108
114
|
def connect
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
# PostgreSQL-specific extensions to column definitions in a table.
|
@@ -5,11 +7,38 @@ module ActiveRecord
|
|
5
7
|
delegate :array, :oid, :fmod, to: :sql_type_metadata
|
6
8
|
alias :array? :array
|
7
9
|
|
10
|
+
def initialize(*, max_identifier_length: 63, **)
|
11
|
+
super
|
12
|
+
@max_identifier_length = max_identifier_length
|
13
|
+
end
|
14
|
+
|
8
15
|
def serial?
|
9
16
|
return unless default_function
|
10
17
|
|
11
|
-
%r{\Anextval\('"
|
18
|
+
if %r{\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z} =~ default_function
|
19
|
+
sequence_name_from_parts(table_name, name, suffix) == sequence_name
|
20
|
+
end
|
12
21
|
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
attr_reader :max_identifier_length
|
25
|
+
|
26
|
+
private
|
27
|
+
def sequence_name_from_parts(table_name, column_name, suffix)
|
28
|
+
over_length = [table_name, column_name, suffix].map(&:length).sum + 2 - max_identifier_length
|
29
|
+
|
30
|
+
if over_length > 0
|
31
|
+
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
|
32
|
+
over_length -= column_name.length - column_name_length
|
33
|
+
column_name = column_name[0, column_name_length - [over_length, 0].min]
|
34
|
+
end
|
35
|
+
|
36
|
+
if over_length > 0
|
37
|
+
table_name = table_name[0, table_name.length - over_length]
|
38
|
+
end
|
39
|
+
|
40
|
+
"#{table_name}_#{column_name}_#{suffix}"
|
41
|
+
end
|
13
42
|
end
|
14
43
|
end
|
15
44
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -7,30 +9,6 @@ module ActiveRecord
|
|
7
9
|
PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", binds))
|
8
10
|
end
|
9
11
|
|
10
|
-
def select_value(arel, name = nil, binds = []) # :nodoc:
|
11
|
-
select_result(arel, name, binds) do |result|
|
12
|
-
result.getvalue(0, 0) if result.ntuples > 0 && result.nfields > 0
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def select_values(arel, name = nil, binds = []) # :nodoc:
|
17
|
-
select_result(arel, name, binds) do |result|
|
18
|
-
if result.nfields > 0
|
19
|
-
result.column_values(0)
|
20
|
-
else
|
21
|
-
[]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Executes a SELECT query and returns an array of rows. Each row is an
|
27
|
-
# array of field values.
|
28
|
-
def select_rows(arel, name = nil, binds = []) # :nodoc:
|
29
|
-
select_result(arel, name, binds) do |result|
|
30
|
-
result.values
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
12
|
# The internal PostgreSQL identifier of the money data type.
|
35
13
|
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|
36
14
|
# The internal PostgreSQL identifier of the BYTEA data type.
|
@@ -171,18 +149,14 @@ module ActiveRecord
|
|
171
149
|
end
|
172
150
|
|
173
151
|
private
|
152
|
+
# Returns the current ID of a table's sequence.
|
153
|
+
def last_insert_id_result(sequence_name)
|
154
|
+
exec_query("SELECT currval(#{quote(sequence_name)})", "SQL")
|
155
|
+
end
|
174
156
|
|
175
157
|
def suppress_composite_primary_key(pk)
|
176
158
|
pk unless pk.is_a?(Array)
|
177
159
|
end
|
178
|
-
|
179
|
-
def select_result(arel, name, binds)
|
180
|
-
arel, binds = binds_from_relation(arel, binds)
|
181
|
-
sql = to_sql(arel, binds)
|
182
|
-
execute_and_clear(sql, name, binds) do |result|
|
183
|
-
yield result
|
184
|
-
end
|
185
|
-
end
|
186
160
|
end
|
187
161
|
end
|
188
162
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
4
6
|
module OID # :nodoc:
|
5
7
|
class Decimal < Type::Decimal # :nodoc:
|
6
8
|
def infinity(options = {})
|
7
|
-
BigDecimal
|
9
|
+
BigDecimal("Infinity") * (options[:negative] ? -1 : 1)
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,21 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
4
6
|
module OID # :nodoc:
|
5
|
-
class Jsonb < Json # :nodoc:
|
7
|
+
class Jsonb < Type::Json # :nodoc:
|
6
8
|
def type
|
7
9
|
:jsonb
|
8
10
|
end
|
9
|
-
|
10
|
-
def changed_in_place?(raw_old_value, new_value)
|
11
|
-
# Postgres does not preserve insignificant whitespaces when
|
12
|
-
# round-tripping jsonb columns. This causes some false positives for
|
13
|
-
# the comparison here. Therefore, we need to parse and re-dump the
|
14
|
-
# raw value here to ensure the insignificant whitespaces are
|
15
|
-
# consistent with our encoder's output.
|
16
|
-
raw_old_value = serialize(deserialize(raw_old_value))
|
17
|
-
super(raw_old_value, new_value)
|
18
|
-
end
|
19
11
|
end
|
20
12
|
end
|
21
13
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -22,7 +24,7 @@ module ActiveRecord
|
|
22
24
|
# (3) -$2.55
|
23
25
|
# (4) ($2.55)
|
24
26
|
|
25
|
-
value.sub
|
27
|
+
value = value.sub(/^\((.+)\)$/, '-\1') # (4)
|
26
28
|
case value
|
27
29
|
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
28
30
|
value.gsub!(/[^-\d.]/, "")
|