activerecord 5.2.4.4 → 6.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 +4 -4
- data/CHANGELOG.md +300 -725
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +2 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/arel.rb +44 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module DetermineIfPreparableVisitor
|
6
|
-
|
6
|
+
attr_reader :preparable
|
7
7
|
|
8
8
|
def accept(*)
|
9
9
|
@preparable = true
|
@@ -12,15 +12,11 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
def visit_Arel_Nodes_In(o, collector)
|
14
14
|
@preparable = false
|
15
|
+
super
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
if Arel::Nodes::BindParam === bind && Relation::QueryAttribute === bind.value
|
19
|
-
!bind.value.boundable?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
18
|
+
def visit_Arel_Nodes_NotIn(o, collector)
|
19
|
+
@preparable = false
|
24
20
|
super
|
25
21
|
end
|
26
22
|
|
@@ -19,8 +19,19 @@ module ActiveRecord
|
|
19
19
|
execute(sql, name).to_a
|
20
20
|
end
|
21
21
|
|
22
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback) # :nodoc:
|
23
|
+
private_constant :READ_QUERY
|
24
|
+
|
25
|
+
def write_query?(sql) # :nodoc:
|
26
|
+
!READ_QUERY.match?(sql)
|
27
|
+
end
|
28
|
+
|
22
29
|
# Executes the SQL statement in the context of this connection.
|
23
30
|
def execute(sql, name = nil)
|
31
|
+
if preventing_writes? && write_query?(sql)
|
32
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
33
|
+
end
|
34
|
+
|
24
35
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
25
36
|
# made since we established the connection
|
26
37
|
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
@@ -31,11 +42,19 @@ module ActiveRecord
|
|
31
42
|
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
32
43
|
if without_prepared_statement?(binds)
|
33
44
|
execute_and_free(sql, name) do |result|
|
34
|
-
|
45
|
+
if result
|
46
|
+
ActiveRecord::Result.new(result.fields, result.to_a)
|
47
|
+
else
|
48
|
+
ActiveRecord::Result.new([], [])
|
49
|
+
end
|
35
50
|
end
|
36
51
|
else
|
37
52
|
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
38
|
-
|
53
|
+
if result
|
54
|
+
ActiveRecord::Result.new(result.fields, result.to_a)
|
55
|
+
else
|
56
|
+
ActiveRecord::Result.new([], [])
|
57
|
+
end
|
39
58
|
end
|
40
59
|
end
|
41
60
|
end
|
@@ -59,7 +78,7 @@ module ActiveRecord
|
|
59
78
|
end
|
60
79
|
|
61
80
|
def discard_remaining_results
|
62
|
-
@connection.
|
81
|
+
@connection.abandon_results!
|
63
82
|
end
|
64
83
|
|
65
84
|
def supports_set_server_option?
|
@@ -99,6 +118,12 @@ module ActiveRecord
|
|
99
118
|
end
|
100
119
|
|
101
120
|
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
121
|
+
if preventing_writes? && write_query?(sql)
|
122
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
123
|
+
end
|
124
|
+
|
125
|
+
materialize_transactions
|
126
|
+
|
102
127
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
103
128
|
# made since we established the connection
|
104
129
|
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
@@ -107,10 +132,7 @@ module ActiveRecord
|
|
107
132
|
|
108
133
|
log(sql, name, binds, type_casted_binds) do
|
109
134
|
if cache_stmt
|
110
|
-
|
111
|
-
stmt: @connection.prepare(sql)
|
112
|
-
}
|
113
|
-
stmt = cache[:stmt]
|
135
|
+
stmt = @statements[sql] ||= @connection.prepare(sql)
|
114
136
|
else
|
115
137
|
stmt = @connection.prepare(sql)
|
116
138
|
end
|
@@ -4,8 +4,7 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module MySQL
|
6
6
|
class SchemaCreation < AbstractAdapter::SchemaCreation # :nodoc:
|
7
|
-
delegate :add_sql_comment!, :mariadb?, to: :@conn
|
8
|
-
private :add_sql_comment!, :mariadb?
|
7
|
+
delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true
|
9
8
|
|
10
9
|
private
|
11
10
|
|
@@ -18,7 +17,7 @@ module ActiveRecord
|
|
18
17
|
end
|
19
18
|
|
20
19
|
def visit_ChangeColumnDefinition(o)
|
21
|
-
change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
20
|
+
change_column_sql = +"CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
22
21
|
add_column_position!(change_column_sql, column_options(o.column))
|
23
22
|
end
|
24
23
|
|
@@ -65,7 +64,7 @@ module ActiveRecord
|
|
65
64
|
|
66
65
|
def index_in_create(table_name, column_name, options)
|
67
66
|
index_name, index_type, index_columns, _, _, index_using, comment = @conn.add_index_options(table_name, column_name, options)
|
68
|
-
add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})"
|
67
|
+
add_sql_comment!((+"#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})"), comment)
|
69
68
|
end
|
70
69
|
end
|
71
70
|
end
|
@@ -35,13 +35,39 @@ module ActiveRecord
|
|
35
35
|
]
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
if row[:Expression]
|
39
|
+
expression = row[:Expression]
|
40
|
+
expression = +"(#{expression})" unless expression.start_with?("(")
|
41
|
+
indexes.last[-2] << expression
|
42
|
+
indexes.last[-1][:expressions] ||= {}
|
43
|
+
indexes.last[-1][:expressions][expression] = expression
|
44
|
+
indexes.last[-1][:orders][expression] = :desc if row[:Collation] == "D"
|
45
|
+
else
|
46
|
+
indexes.last[-2] << row[:Column_name]
|
47
|
+
indexes.last[-1][:lengths][row[:Column_name]] = row[:Sub_part].to_i if row[:Sub_part]
|
48
|
+
indexes.last[-1][:orders][row[:Column_name]] = :desc if row[:Collation] == "D"
|
49
|
+
end
|
41
50
|
end
|
42
51
|
end
|
43
52
|
|
44
|
-
indexes.map
|
53
|
+
indexes.map do |index|
|
54
|
+
options = index.last
|
55
|
+
|
56
|
+
if expressions = options.delete(:expressions)
|
57
|
+
orders = options.delete(:orders)
|
58
|
+
lengths = options.delete(:lengths)
|
59
|
+
|
60
|
+
columns = index[-2].map { |name|
|
61
|
+
[ name.to_sym, expressions[name] || +quote_column_name(name) ]
|
62
|
+
}.to_h
|
63
|
+
|
64
|
+
index[-2] = add_options_for_index_columns(
|
65
|
+
columns, order: orders, length: lengths
|
66
|
+
).values.join(", ")
|
67
|
+
end
|
68
|
+
|
69
|
+
IndexDefinition.new(*index)
|
70
|
+
end
|
45
71
|
end
|
46
72
|
|
47
73
|
def remove_column(table_name, column_name, type = nil, options = {})
|
@@ -51,9 +77,13 @@ module ActiveRecord
|
|
51
77
|
super
|
52
78
|
end
|
53
79
|
|
80
|
+
def create_table(table_name, options: default_row_format, **)
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
54
84
|
def internal_string_options_for_primary_key
|
55
85
|
super.tap do |options|
|
56
|
-
if CHARSETS_OF_4BYTES_MAXLEN.include?(charset)
|
86
|
+
if !row_format_dynamic_by_default? && CHARSETS_OF_4BYTES_MAXLEN.include?(charset)
|
57
87
|
options[:collation] = collation.sub(/\A[^_]+/, "utf8")
|
58
88
|
end
|
59
89
|
end
|
@@ -70,6 +100,28 @@ module ActiveRecord
|
|
70
100
|
private
|
71
101
|
CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
|
72
102
|
|
103
|
+
def row_format_dynamic_by_default?
|
104
|
+
if mariadb?
|
105
|
+
version >= "10.2.2"
|
106
|
+
else
|
107
|
+
version >= "5.7.9"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def default_row_format
|
112
|
+
return if row_format_dynamic_by_default?
|
113
|
+
|
114
|
+
unless defined?(@default_row_format)
|
115
|
+
if query_value("SELECT @@innodb_file_per_table = 1 AND @@innodb_file_format = 'Barracuda'") == 1
|
116
|
+
@default_row_format = "ROW_FORMAT=DYNAMIC"
|
117
|
+
else
|
118
|
+
@default_row_format = nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
@default_row_format
|
123
|
+
end
|
124
|
+
|
73
125
|
def schema_creation
|
74
126
|
MySQL::SchemaCreation.new(self)
|
75
127
|
end
|
@@ -80,10 +132,13 @@ module ActiveRecord
|
|
80
132
|
|
81
133
|
def new_column_from_field(table_name, field)
|
82
134
|
type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
default, default_function =
|
135
|
+
default, default_function = field[:Default], nil
|
136
|
+
|
137
|
+
if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
|
138
|
+
default, default_function = nil, default
|
139
|
+
elsif type_metadata.extra == "DEFAULT_GENERATED"
|
140
|
+
default = +"(#{default})" unless default.start_with?("(")
|
141
|
+
default, default_function = nil, default
|
87
142
|
end
|
88
143
|
|
89
144
|
MySQL::Column.new(
|
@@ -121,7 +176,7 @@ module ActiveRecord
|
|
121
176
|
def data_source_sql(name = nil, type: nil)
|
122
177
|
scope = quoted_scope(name, type: type)
|
123
178
|
|
124
|
-
sql = "SELECT table_name FROM information_schema.tables"
|
179
|
+
sql = +"SELECT table_name FROM information_schema.tables"
|
125
180
|
sql << " WHERE table_schema = #{scope[:schema]}"
|
126
181
|
sql << " AND table_name = #{scope[:name]}" if scope[:name]
|
127
182
|
sql << " AND table_type = #{scope[:type]}" if scope[:type]
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_record/connection_adapters/abstract_mysql_adapter"
|
4
4
|
require "active_record/connection_adapters/mysql/database_statements"
|
5
5
|
|
6
|
-
gem "mysql2", ">= 0.4.4"
|
6
|
+
gem "mysql2", ">= 0.4.4"
|
7
7
|
require "mysql2"
|
8
8
|
|
9
9
|
module ActiveRecord
|
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
config[:flags] ||= 0
|
15
15
|
|
16
16
|
if config[:flags].kind_of? Array
|
17
|
-
config[:flags].push "FOUND_ROWS"
|
17
|
+
config[:flags].push "FOUND_ROWS"
|
18
18
|
else
|
19
19
|
config[:flags] |= Mysql2::Client::FOUND_ROWS
|
20
20
|
end
|
@@ -32,7 +32,7 @@ module ActiveRecord
|
|
32
32
|
|
33
33
|
module ConnectionAdapters
|
34
34
|
class Mysql2Adapter < AbstractMysqlAdapter
|
35
|
-
ADAPTER_NAME = "Mysql2"
|
35
|
+
ADAPTER_NAME = "Mysql2"
|
36
36
|
|
37
37
|
include MySQL::DatabaseStatements
|
38
38
|
|
@@ -58,6 +58,10 @@ module ActiveRecord
|
|
58
58
|
true
|
59
59
|
end
|
60
60
|
|
61
|
+
def supports_lazy_transactions?
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
61
65
|
# HELPER METHODS ===========================================
|
62
66
|
|
63
67
|
def each_hash(result) # :nodoc:
|
@@ -117,7 +121,7 @@ module ActiveRecord
|
|
117
121
|
end
|
118
122
|
|
119
123
|
def configure_connection
|
120
|
-
@connection.query_options
|
124
|
+
@connection.query_options[:as] = :array
|
121
125
|
super
|
122
126
|
end
|
123
127
|
|
@@ -20,10 +20,9 @@ module ActiveRecord
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
private
|
24
24
|
attr_reader :max_identifier_length
|
25
25
|
|
26
|
-
private
|
27
26
|
def sequence_name_from_parts(table_name, column_name, suffix)
|
28
27
|
over_length = [table_name, column_name, suffix].map(&:length).sum + 2 - max_identifier_length
|
29
28
|
|
@@ -58,6 +58,8 @@ module ActiveRecord
|
|
58
58
|
|
59
59
|
# Queries the database and returns the results in an Array-like object
|
60
60
|
def query(sql, name = nil) #:nodoc:
|
61
|
+
materialize_transactions
|
62
|
+
|
61
63
|
log(sql, name) do
|
62
64
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
63
65
|
result_as_array @connection.async_exec(sql)
|
@@ -65,11 +67,24 @@ module ActiveRecord
|
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
70
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback) # :nodoc:
|
71
|
+
private_constant :READ_QUERY
|
72
|
+
|
73
|
+
def write_query?(sql) # :nodoc:
|
74
|
+
!READ_QUERY.match?(sql)
|
75
|
+
end
|
76
|
+
|
68
77
|
# Executes an SQL statement, returning a PG::Result object on success
|
69
78
|
# or raising a PG::Error exception otherwise.
|
70
79
|
# Note: the PG::Result object is manually memory managed; if you don't
|
71
80
|
# need it specifically, you may want consider the <tt>exec_query</tt> wrapper.
|
72
81
|
def execute(sql, name = nil)
|
82
|
+
if preventing_writes? && write_query?(sql)
|
83
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
84
|
+
end
|
85
|
+
|
86
|
+
materialize_transactions
|
87
|
+
|
73
88
|
log(sql, name) do
|
74
89
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
75
90
|
@connection.async_exec(sql)
|
@@ -95,7 +110,7 @@ module ActiveRecord
|
|
95
110
|
end
|
96
111
|
alias :exec_update :exec_delete
|
97
112
|
|
98
|
-
def sql_for_insert(sql, pk,
|
113
|
+
def sql_for_insert(sql, pk, sequence_name, binds) # :nodoc:
|
99
114
|
if pk.nil?
|
100
115
|
# Extract the table from the insert sql. Yuck.
|
101
116
|
table_ref = extract_table_ref_from_insert_sql(sql)
|
@@ -43,10 +43,7 @@ module ActiveRecord
|
|
43
43
|
/\A[0-9A-F]*\Z/i.match?(value)
|
44
44
|
end
|
45
45
|
|
46
|
-
|
47
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
48
|
-
protected
|
49
|
-
|
46
|
+
private
|
50
47
|
attr_reader :value
|
51
48
|
end
|
52
49
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/array/extract"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
module PostgreSQL
|
@@ -16,12 +18,12 @@ module ActiveRecord
|
|
16
18
|
|
17
19
|
def run(records)
|
18
20
|
nodes = records.reject { |row| @store.key? row["oid"].to_i }
|
19
|
-
mapped
|
20
|
-
ranges
|
21
|
-
enums
|
22
|
-
domains
|
23
|
-
arrays
|
24
|
-
composites
|
21
|
+
mapped = nodes.extract! { |row| @store.key? row["typname"] }
|
22
|
+
ranges = nodes.extract! { |row| row["typtype"] == "r" }
|
23
|
+
enums = nodes.extract! { |row| row["typtype"] == "e" }
|
24
|
+
domains = nodes.extract! { |row| row["typtype"] == "d" }
|
25
|
+
arrays = nodes.extract! { |row| row["typinput"] == "array_in" }
|
26
|
+
composites = nodes.extract! { |row| row["typelem"].to_i != 0 }
|
25
27
|
|
26
28
|
mapped.each { |row| register_mapped_type(row) }
|
27
29
|
enums.each { |row| register_enum_type(row) }
|
@@ -34,7 +36,7 @@ module ActiveRecord
|
|
34
36
|
def query_conditions_for_initial_load
|
35
37
|
known_type_names = @store.keys.map { |n| "'#{n}'" }
|
36
38
|
known_type_types = %w('r' 'e' 'd')
|
37
|
-
|
39
|
+
<<~SQL % [known_type_names.join(", "), known_type_types.join(", ")]
|
38
40
|
WHERE
|
39
41
|
t.typname IN (%s)
|
40
42
|
OR t.typtype IN (%s)
|
@@ -93,11 +93,11 @@ module ActiveRecord
|
|
93
93
|
elsif value.hex?
|
94
94
|
"X'#{value}'"
|
95
95
|
end
|
96
|
-
when
|
97
|
-
if value.
|
98
|
-
"'#{value}'"
|
99
|
-
else
|
96
|
+
when Numeric
|
97
|
+
if value.finite?
|
100
98
|
super
|
99
|
+
else
|
100
|
+
"'#{value}'"
|
101
101
|
end
|
102
102
|
when OID::Array::Data
|
103
103
|
_quote(encode_array(value))
|