activerecord 6.0.0 → 6.1.4
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 +1178 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_record/aggregations.rb +5 -6
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +55 -29
- data/lib/active_record/associations/association_scope.rb +19 -15
- data/lib/active_record/associations/belongs_to_association.rb +23 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +25 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +77 -42
- data/lib/active_record/associations/preloader/association.rb +51 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/preloader.rb +13 -8
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +120 -13
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +33 -9
- data/lib/active_record/autosave_association.rb +63 -44
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
- data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
- data/lib/active_record/connection_adapters/abstract_adapter.rb +76 -79
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
- data/lib/active_record/connection_adapters/schema_cache.rb +106 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +219 -81
- data/lib/active_record/core.rb +268 -71
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -41
- data/lib/active_record/database_configurations.rb +124 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +80 -38
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +58 -12
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +43 -10
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +16 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +33 -18
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +28 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +71 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +115 -85
- data/lib/active_record/model_schema.rb +120 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +280 -99
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +106 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +55 -17
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +59 -40
- data/lib/active_record/relation/query_methods.rb +344 -181
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -62
- data/lib/active_record/relation.rb +116 -82
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +1 -4
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +3 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -36
- data/lib/active_record/tasks/database_tasks.rb +140 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +79 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +26 -73
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +15 -12
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +27 -24
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -9,65 +9,21 @@ module ActiveRecord
|
|
9
9
|
PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", binds))
|
10
10
|
end
|
11
11
|
|
12
|
-
# The internal PostgreSQL identifier of the money data type.
|
13
|
-
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|
14
|
-
# The internal PostgreSQL identifier of the BYTEA data type.
|
15
|
-
BYTEA_COLUMN_TYPE_OID = 17 #:nodoc:
|
16
|
-
|
17
|
-
# create a 2D array representing the result set
|
18
|
-
def result_as_array(res) #:nodoc:
|
19
|
-
# check if we have any binary column and if they need escaping
|
20
|
-
ftypes = Array.new(res.nfields) do |i|
|
21
|
-
[i, res.ftype(i)]
|
22
|
-
end
|
23
|
-
|
24
|
-
rows = res.values
|
25
|
-
return rows unless ftypes.any? { |_, x|
|
26
|
-
x == BYTEA_COLUMN_TYPE_OID || x == MONEY_COLUMN_TYPE_OID
|
27
|
-
}
|
28
|
-
|
29
|
-
typehash = ftypes.group_by { |_, type| type }
|
30
|
-
binaries = typehash[BYTEA_COLUMN_TYPE_OID] || []
|
31
|
-
monies = typehash[MONEY_COLUMN_TYPE_OID] || []
|
32
|
-
|
33
|
-
rows.each do |row|
|
34
|
-
# unescape string passed BYTEA field (OID == 17)
|
35
|
-
binaries.each do |index, _|
|
36
|
-
row[index] = unescape_bytea(row[index])
|
37
|
-
end
|
38
|
-
|
39
|
-
# If this is a money type column and there are any currency symbols,
|
40
|
-
# then strip them off. Indeed it would be prettier to do this in
|
41
|
-
# PostgreSQLColumn.string_to_decimal but would break form input
|
42
|
-
# fields that call value_before_type_cast.
|
43
|
-
monies.each do |index, _|
|
44
|
-
data = row[index]
|
45
|
-
# Because money output is formatted according to the locale, there are two
|
46
|
-
# cases to consider (note the decimal separators):
|
47
|
-
# (1) $12,345,678.12
|
48
|
-
# (2) $12.345.678,12
|
49
|
-
case data
|
50
|
-
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
51
|
-
data.gsub!(/[^-\d.]/, "")
|
52
|
-
when /^-?\D+[\d.]+,\d{2}$/ # (2)
|
53
|
-
data.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
12
|
# Queries the database and returns the results in an Array-like object
|
60
13
|
def query(sql, name = nil) #:nodoc:
|
61
14
|
materialize_transactions
|
15
|
+
mark_transaction_written_if_write(sql)
|
62
16
|
|
63
17
|
log(sql, name) do
|
64
18
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
65
|
-
|
19
|
+
@connection.async_exec(sql).map_types!(@type_map_for_results).values
|
66
20
|
end
|
67
21
|
end
|
68
22
|
end
|
69
23
|
|
70
|
-
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
24
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
25
|
+
:close, :declare, :fetch, :move, :set, :show
|
26
|
+
) # :nodoc:
|
71
27
|
private_constant :READ_QUERY
|
72
28
|
|
73
29
|
def write_query?(sql) # :nodoc:
|
@@ -84,6 +40,7 @@ module ActiveRecord
|
|
84
40
|
end
|
85
41
|
|
86
42
|
materialize_transactions
|
43
|
+
mark_transaction_written_if_write(sql)
|
87
44
|
|
88
45
|
log(sql, name) do
|
89
46
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
@@ -99,9 +56,13 @@ module ActiveRecord
|
|
99
56
|
fields.each_with_index do |fname, i|
|
100
57
|
ftype = result.ftype i
|
101
58
|
fmod = result.fmod i
|
102
|
-
|
59
|
+
case type = get_oid_type(ftype, fmod, fname)
|
60
|
+
when Type::Integer, Type::Float, OID::Decimal, Type::String, Type::DateTime, Type::Boolean
|
61
|
+
# skip if a column has already been type casted by pg decoders
|
62
|
+
else types[fname] = type
|
63
|
+
end
|
103
64
|
end
|
104
|
-
|
65
|
+
build_result(columns: fields, rows: result.values, column_types: types)
|
105
66
|
end
|
106
67
|
end
|
107
68
|
|
@@ -145,7 +106,7 @@ module ActiveRecord
|
|
145
106
|
|
146
107
|
# Begins a transaction.
|
147
108
|
def begin_db_transaction
|
148
|
-
execute
|
109
|
+
execute("BEGIN", "TRANSACTION")
|
149
110
|
end
|
150
111
|
|
151
112
|
def begin_isolated_db_transaction(isolation)
|
@@ -155,17 +116,21 @@ module ActiveRecord
|
|
155
116
|
|
156
117
|
# Commits a transaction.
|
157
118
|
def commit_db_transaction
|
158
|
-
execute
|
119
|
+
execute("COMMIT", "TRANSACTION")
|
159
120
|
end
|
160
121
|
|
161
122
|
# Aborts a transaction.
|
162
123
|
def exec_rollback_db_transaction
|
163
|
-
execute
|
124
|
+
execute("ROLLBACK", "TRANSACTION")
|
164
125
|
end
|
165
126
|
|
166
127
|
private
|
167
|
-
def
|
168
|
-
|
128
|
+
def execute_batch(statements, name = nil)
|
129
|
+
execute(combine_multi_statements(statements))
|
130
|
+
end
|
131
|
+
|
132
|
+
def build_truncate_statements(table_names)
|
133
|
+
["TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"]
|
169
134
|
end
|
170
135
|
|
171
136
|
# Returns the current ID of a table's sequence.
|
@@ -12,19 +12,17 @@ module ActiveRecord
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def type_cast_for_schema(value)
|
15
|
-
subnet_mask = value.instance_variable_get(:@mask_addr)
|
16
|
-
|
17
15
|
# If the subnet mask is equal to /32, don't output it
|
18
|
-
if
|
16
|
+
if value.prefix == 32
|
19
17
|
"\"#{value}\""
|
20
18
|
else
|
21
|
-
"\"#{value}/#{
|
19
|
+
"\"#{value}/#{value.prefix}\""
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
23
|
def serialize(value)
|
26
24
|
if IPAddr === value
|
27
|
-
"#{value}/#{value.
|
25
|
+
"#{value}/#{value.prefix}"
|
28
26
|
else
|
29
27
|
value
|
30
28
|
end
|
@@ -10,8 +10,8 @@ module ActiveRecord
|
|
10
10
|
when "infinity" then ::Float::INFINITY
|
11
11
|
when "-infinity" then -::Float::INFINITY
|
12
12
|
when / BC$/
|
13
|
-
|
14
|
-
super(value.
|
13
|
+
value = value.sub(/^\d+/) { |year| format("%04d", -year.to_i + 1) }
|
14
|
+
super(value.delete_suffix!(" BC"))
|
15
15
|
else
|
16
16
|
super
|
17
17
|
end
|
@@ -10,12 +10,20 @@ module ActiveRecord
|
|
10
10
|
when "infinity" then ::Float::INFINITY
|
11
11
|
when "-infinity" then -::Float::INFINITY
|
12
12
|
when / BC$/
|
13
|
-
|
14
|
-
super(value.
|
13
|
+
value = value.sub(/^\d+/) { |year| format("%04d", -year.to_i + 1) }
|
14
|
+
super(value.delete_suffix!(" BC"))
|
15
15
|
else
|
16
16
|
super
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def type_cast_for_schema(value)
|
21
|
+
case value
|
22
|
+
when ::Float::INFINITY then "::Float::INFINITY"
|
23
|
+
when -::Float::INFINITY then "-::Float::INFINITY"
|
24
|
+
else super
|
25
|
+
end
|
26
|
+
end
|
19
27
|
end
|
20
28
|
end
|
21
29
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/duration"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module ConnectionAdapters
|
7
|
+
module PostgreSQL
|
8
|
+
module OID # :nodoc:
|
9
|
+
class Interval < Type::Value # :nodoc:
|
10
|
+
def type
|
11
|
+
:interval
|
12
|
+
end
|
13
|
+
|
14
|
+
def cast_value(value)
|
15
|
+
case value
|
16
|
+
when ::ActiveSupport::Duration
|
17
|
+
value
|
18
|
+
when ::String
|
19
|
+
begin
|
20
|
+
::ActiveSupport::Duration.parse(value)
|
21
|
+
rescue ::ActiveSupport::Duration::ISO8601Parser::ParsingError
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize(value)
|
30
|
+
case value
|
31
|
+
when ::ActiveSupport::Duration
|
32
|
+
value.iso8601(precision: self.precision)
|
33
|
+
when ::Numeric
|
34
|
+
# Sometimes operations on Times returns just float number of seconds so we need to handle that.
|
35
|
+
# Example: Time.current - (Time.current + 1.hour) # => -3600.000001776 (Float)
|
36
|
+
value.seconds.iso8601(precision: self.precision)
|
37
|
+
else
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def type_cast_for_schema(value)
|
43
|
+
serialize(value).inspect
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
def cast(value)
|
15
15
|
case value
|
16
16
|
when ::String
|
17
|
-
if value
|
17
|
+
if value.start_with?("(") && value.end_with?(")")
|
18
18
|
value = value[1...-1]
|
19
19
|
end
|
20
20
|
cast(value.split(","))
|
@@ -34,9 +34,8 @@ module ActiveRecord
|
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
37
|
-
|
38
37
|
def number_for_point(number)
|
39
|
-
number.to_s.
|
38
|
+
number.to_s.delete_suffix(".0")
|
40
39
|
end
|
41
40
|
end
|
42
41
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module PostgreSQL
|
6
|
+
module OID # :nodoc:
|
7
|
+
class Macaddr < Type::String # :nodoc:
|
8
|
+
def type
|
9
|
+
:macaddr
|
10
|
+
end
|
11
|
+
|
12
|
+
def changed?(old_value, new_value, _new_value_before_type_cast)
|
13
|
+
old_value.class != new_value.class ||
|
14
|
+
new_value && old_value.casecmp(new_value) != 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def changed_in_place?(raw_old_value, new_value)
|
18
|
+
raw_old_value.class != new_value.class ||
|
19
|
+
new_value && raw_old_value.casecmp(new_value) != 0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -26,9 +26,9 @@ module ActiveRecord
|
|
26
26
|
|
27
27
|
value = value.sub(/^\((.+)\)$/, '-\1') # (4)
|
28
28
|
case value
|
29
|
-
when /^-?\D
|
29
|
+
when /^-?\D*+[\d,]+\.\d{2}$/ # (1)
|
30
30
|
value.gsub!(/[^-\d.]/, "")
|
31
|
-
when /^-?\D
|
31
|
+
when /^-?\D*+[\d.]+,\d{2}$/ # (2)
|
32
32
|
value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
|
33
33
|
end
|
34
34
|
|
@@ -18,7 +18,7 @@ module ActiveRecord
|
|
18
18
|
when ::String
|
19
19
|
return if value.blank?
|
20
20
|
|
21
|
-
if value
|
21
|
+
if value.start_with?("(") && value.end_with?(")")
|
22
22
|
value = value[1...-1]
|
23
23
|
end
|
24
24
|
x, y = value.split(",")
|
@@ -50,9 +50,8 @@ module ActiveRecord
|
|
50
50
|
end
|
51
51
|
|
52
52
|
private
|
53
|
-
|
54
53
|
def number_for_point(number)
|
55
|
-
number.to_s.
|
54
|
+
number.to_s.delete_suffix(".0")
|
56
55
|
end
|
57
56
|
|
58
57
|
def build_point(x, y)
|
@@ -58,7 +58,6 @@ module ActiveRecord
|
|
58
58
|
end
|
59
59
|
|
60
60
|
private
|
61
|
-
|
62
61
|
def type_cast_single(value)
|
63
62
|
infinity?(value) ? value : @subtype.deserialize(value)
|
64
63
|
end
|
@@ -68,15 +67,34 @@ module ActiveRecord
|
|
68
67
|
end
|
69
68
|
|
70
69
|
def extract_bounds(value)
|
71
|
-
from, to = value[1..-2].split(",")
|
70
|
+
from, to = value[1..-2].split(",", 2)
|
72
71
|
{
|
73
|
-
from: (
|
74
|
-
to: (
|
75
|
-
exclude_start: (
|
76
|
-
exclude_end: (
|
72
|
+
from: (from == "" || from == "-infinity") ? infinity(negative: true) : unquote(from),
|
73
|
+
to: (to == "" || to == "infinity") ? infinity : unquote(to),
|
74
|
+
exclude_start: value.start_with?("("),
|
75
|
+
exclude_end: value.end_with?(")")
|
77
76
|
}
|
78
77
|
end
|
79
78
|
|
79
|
+
# When formatting the bound values of range types, PostgreSQL quotes
|
80
|
+
# the bound value using double-quotes in certain conditions. Within
|
81
|
+
# a double-quoted string, literal " and \ characters are themselves
|
82
|
+
# escaped. In input, PostgreSQL accepts multiple escape styles for "
|
83
|
+
# (either \" or "") but in output always uses "".
|
84
|
+
# See:
|
85
|
+
# * https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO
|
86
|
+
# * https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-IO-SYNTAX
|
87
|
+
def unquote(value)
|
88
|
+
if value.start_with?('"') && value.end_with?('"')
|
89
|
+
unquoted_value = value[1..-2]
|
90
|
+
unquoted_value.gsub!('""', '"')
|
91
|
+
unquoted_value.gsub!('\\\\', '\\')
|
92
|
+
unquoted_value
|
93
|
+
else
|
94
|
+
value
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
80
98
|
def infinity(negative: false)
|
81
99
|
if subtype.respond_to?(:infinity)
|
82
100
|
subtype.infinity(negative: negative)
|
@@ -7,14 +7,23 @@ module ActiveRecord
|
|
7
7
|
class Uuid < Type::Value # :nodoc:
|
8
8
|
ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
|
9
9
|
|
10
|
-
|
10
|
+
alias :serialize :deserialize
|
11
11
|
|
12
12
|
def type
|
13
13
|
:uuid
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
def changed?(old_value, new_value, _new_value_before_type_cast)
|
17
|
+
old_value.class != new_value.class ||
|
18
|
+
new_value && old_value.casecmp(new_value) != 0
|
19
|
+
end
|
17
20
|
|
21
|
+
def changed_in_place?(raw_old_value, new_value)
|
22
|
+
raw_old_value.class != new_value.class ||
|
23
|
+
new_value && raw_old_value.casecmp(new_value) != 0
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
18
27
|
def cast_value(value)
|
19
28
|
casted = value.to_s
|
20
29
|
casted if casted.match?(ACCEPTABLE_UUID)
|
@@ -11,7 +11,9 @@ require "active_record/connection_adapters/postgresql/oid/decimal"
|
|
11
11
|
require "active_record/connection_adapters/postgresql/oid/enum"
|
12
12
|
require "active_record/connection_adapters/postgresql/oid/hstore"
|
13
13
|
require "active_record/connection_adapters/postgresql/oid/inet"
|
14
|
+
require "active_record/connection_adapters/postgresql/oid/interval"
|
14
15
|
require "active_record/connection_adapters/postgresql/oid/jsonb"
|
16
|
+
require "active_record/connection_adapters/postgresql/oid/macaddr"
|
15
17
|
require "active_record/connection_adapters/postgresql/oid/money"
|
16
18
|
require "active_record/connection_adapters/postgresql/oid/oid"
|
17
19
|
require "active_record/connection_adapters/postgresql/oid/point"
|
@@ -18,7 +18,7 @@ module ActiveRecord
|
|
18
18
|
|
19
19
|
# Quotes strings for use in SQL input.
|
20
20
|
def quote_string(s) #:nodoc:
|
21
|
-
|
21
|
+
PG::Connection.escape(s)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Checks the following cases:
|
@@ -67,8 +67,8 @@ module ActiveRecord
|
|
67
67
|
elsif column.type == :uuid && value.is_a?(String) && /\(\)/.match?(value)
|
68
68
|
value # Does not quote function default values for UUID columns
|
69
69
|
elsif column.respond_to?(:array?)
|
70
|
-
|
71
|
-
quote(value)
|
70
|
+
type = lookup_cast_type_from_column(column)
|
71
|
+
quote(type.serialize(value))
|
72
72
|
else
|
73
73
|
super
|
74
74
|
end
|
@@ -93,7 +93,7 @@ module ActiveRecord
|
|
93
93
|
# "table_name"."column_name"::type_name | function(one or no argument)::type_name
|
94
94
|
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
|
95
95
|
)
|
96
|
-
(?:\s+AS
|
96
|
+
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
97
97
|
)
|
98
98
|
(?:\s*,\s*\g<1>)*
|
99
99
|
\z
|
@@ -24,9 +24,9 @@ WARNING: Rails was not able to disable referential integrity.
|
|
24
24
|
This is most likely caused due to missing permissions.
|
25
25
|
Rails needs superuser privileges to disable referential integrity.
|
26
26
|
|
27
|
-
cause: #{original_exception
|
27
|
+
cause: #{original_exception&.message}
|
28
28
|
|
29
|
-
|
29
|
+
WARNING
|
30
30
|
raise e
|
31
31
|
end
|
32
32
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module PostgreSQL
|
6
|
-
class SchemaCreation <
|
6
|
+
class SchemaCreation < SchemaCreation # :nodoc:
|
7
7
|
private
|
8
8
|
def visit_AlterTable(o)
|
9
9
|
super << o.constraint_validations.map { |fk| visit_ValidateConstraint fk }.join(" ")
|
@@ -13,13 +13,17 @@ module ActiveRecord
|
|
13
13
|
super.dup.tap { |sql| sql << " NOT VALID" unless o.validate? }
|
14
14
|
end
|
15
15
|
|
16
|
+
def visit_CheckConstraintDefinition(o)
|
17
|
+
super.dup.tap { |sql| sql << " NOT VALID" unless o.validate? }
|
18
|
+
end
|
19
|
+
|
16
20
|
def visit_ValidateConstraint(name)
|
17
21
|
"VALIDATE CONSTRAINT #{quote_column_name(name)}"
|
18
22
|
end
|
19
23
|
|
20
24
|
def visit_ChangeColumnDefinition(o)
|
21
25
|
column = o.column
|
22
|
-
column.sql_type = type_to_sql(column.type, column.options)
|
26
|
+
column.sql_type = type_to_sql(column.type, **column.options)
|
23
27
|
quoted_column_name = quote_column_name(o.name)
|
24
28
|
|
25
29
|
change_column_sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}"
|
@@ -33,7 +37,7 @@ module ActiveRecord
|
|
33
37
|
if options[:using]
|
34
38
|
change_column_sql << " USING #{options[:using]}"
|
35
39
|
elsif options[:cast_as]
|
36
|
-
cast_as_type = type_to_sql(options[:cast_as], options)
|
40
|
+
cast_as_type = type_to_sql(options[:cast_as], **options)
|
37
41
|
change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
38
42
|
end
|
39
43
|
|