activerecord 4.2.0 → 5.2.8.1
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 +640 -928
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -11
- data/examples/performance.rb +32 -31
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +264 -247
- data/lib/active_record/association_relation.rb +24 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +87 -41
- data/lib/active_record/associations/association_scope.rb +106 -132
- data/lib/active_record/associations/belongs_to_association.rb +55 -36
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +29 -38
- data/lib/active_record/associations/builder/belongs_to.rb +77 -30
- data/lib/active_record/associations/builder/collection_association.rb +14 -23
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
- data/lib/active_record/associations/builder/has_many.rb +6 -4
- data/lib/active_record/associations/builder/has_one.rb +13 -6
- data/lib/active_record/associations/builder/singular_association.rb +15 -11
- data/lib/active_record/associations/collection_association.rb +145 -266
- data/lib/active_record/associations/collection_proxy.rb +242 -138
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +35 -75
- data/lib/active_record/associations/has_many_through_association.rb +51 -69
- data/lib/active_record/associations/has_one_association.rb +39 -24
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -154
- data/lib/active_record/associations/preloader/association.rb +85 -116
- data/lib/active_record/associations/preloader/through_association.rb +85 -74
- data/lib/active_record/associations/preloader.rb +83 -93
- data/lib/active_record/associations/singular_association.rb +27 -40
- data/lib/active_record/associations/through_association.rb +48 -23
- data/lib/active_record/associations.rb +1732 -1596
- data/lib/active_record/attribute_assignment.rb +58 -182
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -5
- data/lib/active_record/attribute_methods/dirty.rb +94 -125
- data/lib/active_record/attribute_methods/primary_key.rb +86 -71
- data/lib/active_record/attribute_methods/query.rb +4 -2
- data/lib/active_record/attribute_methods/read.rb +45 -63
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
- data/lib/active_record/attribute_methods/write.rb +31 -46
- data/lib/active_record/attribute_methods.rb +170 -117
- data/lib/active_record/attributes.rb +201 -74
- data/lib/active_record/autosave_association.rb +118 -45
- data/lib/active_record/base.rb +60 -48
- data/lib/active_record/callbacks.rb +97 -57
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +37 -13
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
- data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
- data/lib/active_record/connection_adapters/column.rb +50 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -195
- data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- 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 +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +466 -280
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +439 -330
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -324
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +40 -27
- data/lib/active_record/core.rb +205 -202
- data/lib/active_record/counter_cache.rb +80 -37
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +136 -90
- data/lib/active_record/errors.rb +180 -52
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixtures.rb +193 -135
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +148 -112
- data/lib/active_record/integration.rb +70 -28
- data/lib/active_record/internal_metadata.rb +45 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +92 -98
- data/lib/active_record/locking/pessimistic.rb +15 -3
- data/lib/active_record/log_subscriber.rb +95 -33
- data/lib/active_record/migration/command_recorder.rb +133 -90
- data/lib/active_record/migration/compatibility.rb +217 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +594 -267
- data/lib/active_record/model_schema.rb +292 -111
- data/lib/active_record/nested_attributes.rb +266 -214
- data/lib/active_record/no_touching.rb +8 -2
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +350 -119
- data/lib/active_record/query_cache.rb +13 -24
- data/lib/active_record/querying.rb +19 -17
- data/lib/active_record/railtie.rb +117 -35
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +9 -3
- data/lib/active_record/railties/databases.rake +160 -174
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +447 -288
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +204 -55
- data/lib/active_record/relation/calculations.rb +259 -244
- data/lib/active_record/relation/delegation.rb +67 -60
- data/lib/active_record/relation/finder_methods.rb +290 -253
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +91 -68
- data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +118 -92
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +446 -389
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -16
- data/lib/active_record/relation/where_clause.rb +186 -0
- data/lib/active_record/relation/where_clause_factory.rb +34 -0
- data/lib/active_record/relation.rb +287 -339
- data/lib/active_record/result.rb +54 -36
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +155 -124
- data/lib/active_record/schema.rb +30 -24
- data/lib/active_record/schema_dumper.rb +91 -87
- data/lib/active_record/schema_migration.rb +19 -19
- data/lib/active_record/scoping/default.rb +102 -84
- data/lib/active_record/scoping/named.rb +81 -32
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +45 -35
- data/lib/active_record/store.rb +42 -36
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +82 -0
- data/lib/active_record/tasks/database_tasks.rb +136 -95
- data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +64 -0
- data/lib/active_record/transactions.rb +208 -123
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +136 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +30 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type.rb +79 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +41 -32
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -21
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -6
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
- data/lib/rails/generators/active_record/migration.rb +18 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +77 -53
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -149
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
@@ -6,72 +6,90 @@ module ActiveRecord
|
|
6
6
|
module OID # :nodoc:
|
7
7
|
class Range < Type::Value # :nodoc:
|
8
8
|
attr_reader :subtype, :type
|
9
|
+
delegate :user_input_in_time_zone, to: :subtype
|
9
10
|
|
10
|
-
def initialize(subtype, type)
|
11
|
+
def initialize(subtype, type = :range)
|
11
12
|
@subtype = subtype
|
12
13
|
@type = type
|
13
14
|
end
|
14
15
|
|
15
16
|
def type_cast_for_schema(value)
|
16
|
-
value.inspect.gsub(
|
17
|
+
value.inspect.gsub("Infinity", "::Float::INFINITY")
|
17
18
|
end
|
18
19
|
|
19
20
|
def cast_value(value)
|
20
|
-
return if value ==
|
21
|
-
return value
|
21
|
+
return if value == "empty"
|
22
|
+
return value unless value.is_a?(::String)
|
22
23
|
|
23
24
|
extracted = extract_bounds(value)
|
24
25
|
from = type_cast_single extracted[:from]
|
25
26
|
to = type_cast_single extracted[:to]
|
26
27
|
|
27
28
|
if !infinity?(from) && extracted[:exclude_start]
|
28
|
-
|
29
|
-
from = from.succ
|
30
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
31
|
-
Excluding the beginning of a Range is only partialy supported
|
32
|
-
through `#succ`. This is not reliable and will be removed in
|
33
|
-
the future.
|
34
|
-
MSG
|
35
|
-
else
|
36
|
-
raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
|
37
|
-
end
|
29
|
+
raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
|
38
30
|
end
|
39
31
|
::Range.new(from, to, extracted[:exclude_end])
|
40
32
|
end
|
41
33
|
|
42
|
-
def
|
34
|
+
def serialize(value)
|
43
35
|
if value.is_a?(::Range)
|
44
36
|
from = type_cast_single_for_database(value.begin)
|
45
37
|
to = type_cast_single_for_database(value.end)
|
46
|
-
|
38
|
+
::Range.new(from, to, value.exclude_end?)
|
47
39
|
else
|
48
40
|
super
|
49
41
|
end
|
50
42
|
end
|
51
43
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
def ==(other)
|
45
|
+
other.is_a?(Range) &&
|
46
|
+
other.subtype == subtype &&
|
47
|
+
other.type == type
|
56
48
|
end
|
57
49
|
|
58
|
-
def
|
59
|
-
|
50
|
+
def map(value) # :nodoc:
|
51
|
+
new_begin = yield(value.begin)
|
52
|
+
new_end = yield(value.end)
|
53
|
+
::Range.new(new_begin, new_end, value.exclude_end?)
|
60
54
|
end
|
61
55
|
|
62
|
-
def
|
63
|
-
|
64
|
-
{
|
65
|
-
from: (value[1] == ',' || from == '-infinity') ? @subtype.infinity(negative: true) : from,
|
66
|
-
to: (value[-2] == ',' || to == 'infinity') ? @subtype.infinity : to,
|
67
|
-
exclude_start: (value[0] == '('),
|
68
|
-
exclude_end: (value[-1] == ')')
|
69
|
-
}
|
56
|
+
def force_equality?(value)
|
57
|
+
value.is_a?(::Range)
|
70
58
|
end
|
71
59
|
|
72
|
-
|
73
|
-
|
74
|
-
|
60
|
+
private
|
61
|
+
|
62
|
+
def type_cast_single(value)
|
63
|
+
infinity?(value) ? value : @subtype.deserialize(value)
|
64
|
+
end
|
65
|
+
|
66
|
+
def type_cast_single_for_database(value)
|
67
|
+
infinity?(value) ? value : @subtype.serialize(value)
|
68
|
+
end
|
69
|
+
|
70
|
+
def extract_bounds(value)
|
71
|
+
from, to = value[1..-2].split(",")
|
72
|
+
{
|
73
|
+
from: (value[1] == "," || from == "-infinity") ? infinity(negative: true) : from,
|
74
|
+
to: (value[-2] == "," || to == "infinity") ? infinity : to,
|
75
|
+
exclude_start: (value[0] == "("),
|
76
|
+
exclude_end: (value[-1] == ")")
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def infinity(negative: false)
|
81
|
+
if subtype.respond_to?(:infinity)
|
82
|
+
subtype.infinity(negative: negative)
|
83
|
+
elsif negative
|
84
|
+
-::Float::INFINITY
|
85
|
+
else
|
86
|
+
::Float::INFINITY
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def infinity?(value)
|
91
|
+
value.respond_to?(:infinite?) && value.infinite?
|
92
|
+
end
|
75
93
|
end
|
76
94
|
end
|
77
95
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -5,8 +7,9 @@ module ActiveRecord
|
|
5
7
|
class SpecializedString < Type::String # :nodoc:
|
6
8
|
attr_reader :type
|
7
9
|
|
8
|
-
def initialize(type)
|
10
|
+
def initialize(type, **options)
|
9
11
|
@type = type
|
12
|
+
super(options)
|
10
13
|
end
|
11
14
|
end
|
12
15
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -13,13 +15,13 @@ module ActiveRecord
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def run(records)
|
16
|
-
nodes = records.reject { |row| @store.key? row[
|
17
|
-
mapped, nodes = nodes.partition { |row| @store.key? row[
|
18
|
-
ranges, nodes = nodes.partition { |row| row[
|
19
|
-
enums, nodes = nodes.partition { |row| row[
|
20
|
-
domains, nodes = nodes.partition { |row| row[
|
21
|
-
arrays, nodes = nodes.partition { |row| row[
|
22
|
-
composites, nodes = nodes.partition { |row| row[
|
18
|
+
nodes = records.reject { |row| @store.key? row["oid"].to_i }
|
19
|
+
mapped, nodes = nodes.partition { |row| @store.key? row["typname"] }
|
20
|
+
ranges, nodes = nodes.partition { |row| row["typtype"] == "r".freeze }
|
21
|
+
enums, nodes = nodes.partition { |row| row["typtype"] == "e".freeze }
|
22
|
+
domains, nodes = nodes.partition { |row| row["typtype"] == "d".freeze }
|
23
|
+
arrays, nodes = nodes.partition { |row| row["typinput"] == "array_in".freeze }
|
24
|
+
composites, nodes = nodes.partition { |row| row["typelem"].to_i != 0 }
|
23
25
|
|
24
26
|
mapped.each { |row| register_mapped_type(row) }
|
25
27
|
enums.each { |row| register_enum_type(row) }
|
@@ -29,67 +31,79 @@ module ActiveRecord
|
|
29
31
|
composites.each { |row| register_composite_type(row) }
|
30
32
|
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
def query_conditions_for_initial_load
|
35
|
+
known_type_names = @store.keys.map { |n| "'#{n}'" }
|
36
|
+
known_type_types = %w('r' 'e' 'd')
|
37
|
+
<<-SQL % [known_type_names.join(", "), known_type_types.join(", ")]
|
38
|
+
WHERE
|
39
|
+
t.typname IN (%s)
|
40
|
+
OR t.typtype IN (%s)
|
41
|
+
OR t.typinput = 'array_in(cstring,oid,integer)'::regprocedure
|
42
|
+
OR t.typelem != 0
|
43
|
+
SQL
|
35
44
|
end
|
36
45
|
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
private
|
47
|
+
def register_mapped_type(row)
|
48
|
+
alias_type row["oid"], row["typname"]
|
49
|
+
end
|
40
50
|
|
41
|
-
|
42
|
-
|
43
|
-
OID::Array.new(subtype, row['typdelim'])
|
51
|
+
def register_enum_type(row)
|
52
|
+
register row["oid"], OID::Enum.new
|
44
53
|
end
|
45
|
-
end
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
def register_array_type(row)
|
56
|
+
register_with_subtype(row["oid"], row["typelem"].to_i) do |subtype|
|
57
|
+
OID::Array.new(subtype, row["typdelim"])
|
58
|
+
end
|
50
59
|
end
|
51
|
-
end
|
52
60
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
61
|
+
def register_range_type(row)
|
62
|
+
register_with_subtype(row["oid"], row["rngsubtype"].to_i) do |subtype|
|
63
|
+
OID::Range.new(subtype, row["typname"].to_sym)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def register_domain_type(row)
|
68
|
+
if base_type = @store.lookup(row["typbasetype"].to_i)
|
69
|
+
register row["oid"], base_type
|
70
|
+
else
|
71
|
+
warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
|
72
|
+
end
|
58
73
|
end
|
59
|
-
end
|
60
74
|
|
61
|
-
|
62
|
-
|
63
|
-
|
75
|
+
def register_composite_type(row)
|
76
|
+
if subtype = @store.lookup(row["typelem"].to_i)
|
77
|
+
register row["oid"], OID::Vector.new(row["typdelim"], subtype)
|
78
|
+
end
|
64
79
|
end
|
65
|
-
end
|
66
80
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
81
|
+
def register(oid, oid_type = nil, &block)
|
82
|
+
oid = assert_valid_registration(oid, oid_type || block)
|
83
|
+
if block_given?
|
84
|
+
@store.register_type(oid, &block)
|
85
|
+
else
|
86
|
+
@store.register_type(oid, oid_type)
|
87
|
+
end
|
73
88
|
end
|
74
|
-
end
|
75
89
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
90
|
+
def alias_type(oid, target)
|
91
|
+
oid = assert_valid_registration(oid, target)
|
92
|
+
@store.alias_type(oid, target)
|
93
|
+
end
|
80
94
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
95
|
+
def register_with_subtype(oid, target_oid)
|
96
|
+
if @store.key?(target_oid)
|
97
|
+
register(oid) do |_, *args|
|
98
|
+
yield @store.lookup(target_oid, *args)
|
99
|
+
end
|
85
100
|
end
|
86
101
|
end
|
87
|
-
end
|
88
102
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
103
|
+
def assert_valid_registration(oid, oid_type)
|
104
|
+
raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
|
105
|
+
oid.to_i
|
106
|
+
end
|
93
107
|
end
|
94
108
|
end
|
95
109
|
end
|
@@ -1,17 +1,19 @@
|
|
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 Uuid < Type::Value # :nodoc:
|
6
|
-
ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}
|
8
|
+
ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
|
7
9
|
|
8
|
-
alias_method :
|
10
|
+
alias_method :serialize, :deserialize
|
9
11
|
|
10
12
|
def type
|
11
13
|
:uuid
|
12
14
|
end
|
13
15
|
|
14
|
-
def
|
16
|
+
def cast(value)
|
15
17
|
value.to_s[ACCEPTABLE_UUID, 0]
|
16
18
|
end
|
17
19
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -16,7 +18,7 @@ module ActiveRecord
|
|
16
18
|
# FIXME: this should probably split on +delim+ and use +subtype+
|
17
19
|
# to cast the values. Unfortunately, the current Rails behavior
|
18
20
|
# is to just return the string.
|
19
|
-
def
|
21
|
+
def cast(value)
|
20
22
|
value
|
21
23
|
end
|
22
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -7,7 +9,7 @@ module ActiveRecord
|
|
7
9
|
:xml
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
12
|
+
def serialize(value)
|
11
13
|
return unless value
|
12
14
|
Data.new(super)
|
13
15
|
end
|
@@ -1,30 +1,28 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require 'active_record/connection_adapters/postgresql/oid/vector'
|
25
|
-
require 'active_record/connection_adapters/postgresql/oid/xml'
|
3
|
+
require "active_record/connection_adapters/postgresql/oid/array"
|
4
|
+
require "active_record/connection_adapters/postgresql/oid/bit"
|
5
|
+
require "active_record/connection_adapters/postgresql/oid/bit_varying"
|
6
|
+
require "active_record/connection_adapters/postgresql/oid/bytea"
|
7
|
+
require "active_record/connection_adapters/postgresql/oid/cidr"
|
8
|
+
require "active_record/connection_adapters/postgresql/oid/date"
|
9
|
+
require "active_record/connection_adapters/postgresql/oid/date_time"
|
10
|
+
require "active_record/connection_adapters/postgresql/oid/decimal"
|
11
|
+
require "active_record/connection_adapters/postgresql/oid/enum"
|
12
|
+
require "active_record/connection_adapters/postgresql/oid/hstore"
|
13
|
+
require "active_record/connection_adapters/postgresql/oid/inet"
|
14
|
+
require "active_record/connection_adapters/postgresql/oid/jsonb"
|
15
|
+
require "active_record/connection_adapters/postgresql/oid/money"
|
16
|
+
require "active_record/connection_adapters/postgresql/oid/oid"
|
17
|
+
require "active_record/connection_adapters/postgresql/oid/point"
|
18
|
+
require "active_record/connection_adapters/postgresql/oid/legacy_point"
|
19
|
+
require "active_record/connection_adapters/postgresql/oid/range"
|
20
|
+
require "active_record/connection_adapters/postgresql/oid/specialized_string"
|
21
|
+
require "active_record/connection_adapters/postgresql/oid/uuid"
|
22
|
+
require "active_record/connection_adapters/postgresql/oid/vector"
|
23
|
+
require "active_record/connection_adapters/postgresql/oid/xml"
|
26
24
|
|
27
|
-
require
|
25
|
+
require "active_record/connection_adapters/postgresql/oid/type_map_initializer"
|
28
26
|
|
29
27
|
module ActiveRecord
|
30
28
|
module ConnectionAdapters
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
@@ -27,8 +29,13 @@ module ActiveRecord
|
|
27
29
|
# - schema_name."table.name"
|
28
30
|
# - "schema.name".table_name
|
29
31
|
# - "schema.name"."table.name"
|
30
|
-
def quote_table_name(name)
|
31
|
-
Utils.extract_schema_qualified_name(name.to_s).quoted
|
32
|
+
def quote_table_name(name) # :nodoc:
|
33
|
+
@quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
34
|
+
end
|
35
|
+
|
36
|
+
# Quotes schema names for use in SQL queries.
|
37
|
+
def quote_schema_name(name)
|
38
|
+
PG::Connection.quote_ident(name)
|
32
39
|
end
|
33
40
|
|
34
41
|
def quote_table_name_for_assignment(table, attr)
|
@@ -36,72 +43,125 @@ module ActiveRecord
|
|
36
43
|
end
|
37
44
|
|
38
45
|
# Quotes column names for use in SQL queries.
|
39
|
-
def quote_column_name(name)
|
40
|
-
|
46
|
+
def quote_column_name(name) # :nodoc:
|
47
|
+
@quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
|
41
48
|
end
|
42
49
|
|
43
|
-
# Quote date/time values for use in SQL input.
|
44
|
-
# if the value is a Time responding to usec.
|
50
|
+
# Quote date/time values for use in SQL input.
|
45
51
|
def quoted_date(value) #:nodoc:
|
46
|
-
result = super
|
47
|
-
if value.acts_like?(:time) && value.respond_to?(:usec)
|
48
|
-
result = "#{result}.#{sprintf("%06d", value.usec)}"
|
49
|
-
end
|
50
|
-
|
51
52
|
if value.year <= 0
|
52
53
|
bce_year = format("%04d", -value.year + 1)
|
53
|
-
|
54
|
+
super.sub(/^-?\d+/, bce_year) + " BC"
|
55
|
+
else
|
56
|
+
super
|
54
57
|
end
|
55
|
-
result
|
56
58
|
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
def quoted_binary(value) # :nodoc:
|
61
|
+
"'#{escape_bytea(value.to_s)}'"
|
62
|
+
end
|
63
|
+
|
64
|
+
def quote_default_expression(value, column) # :nodoc:
|
65
|
+
if value.is_a?(Proc)
|
66
|
+
value.call
|
67
|
+
elsif column.type == :uuid && value.is_a?(String) && /\(\)/.match?(value)
|
68
|
+
value # Does not quote function default values for UUID columns
|
69
|
+
elsif column.respond_to?(:array?)
|
70
|
+
value = type_cast_from_column(column, value)
|
71
|
+
quote(value)
|
62
72
|
else
|
63
|
-
|
73
|
+
super
|
64
74
|
end
|
65
75
|
end
|
66
76
|
|
77
|
+
def lookup_cast_type_from_column(column) # :nodoc:
|
78
|
+
type_map.lookup(column.oid, column.fmod, column.sql_type)
|
79
|
+
end
|
80
|
+
|
67
81
|
private
|
82
|
+
def lookup_cast_type(sql_type)
|
83
|
+
super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
|
84
|
+
end
|
68
85
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
86
|
+
def _quote(value)
|
87
|
+
case value
|
88
|
+
when OID::Xml::Data
|
89
|
+
"xml '#{quote_string(value.to_s)}'"
|
90
|
+
when OID::Bit::Data
|
91
|
+
if value.binary?
|
92
|
+
"B'#{value}'"
|
93
|
+
elsif value.hex?
|
94
|
+
"X'#{value}'"
|
95
|
+
end
|
96
|
+
when Float
|
97
|
+
if value.infinite? || value.nan?
|
98
|
+
"'#{value}'"
|
99
|
+
else
|
100
|
+
super
|
101
|
+
end
|
102
|
+
when OID::Array::Data
|
103
|
+
_quote(encode_array(value))
|
104
|
+
when Range
|
105
|
+
_quote(encode_range(value))
|
106
|
+
else
|
107
|
+
super
|
80
108
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
109
|
+
end
|
110
|
+
|
111
|
+
def _type_cast(value)
|
112
|
+
case value
|
113
|
+
when Type::Binary::Data
|
114
|
+
# Return a bind param hash with format as binary.
|
115
|
+
# See https://deveiate.org/code/pg/PG/Connection.html#method-i-exec_prepared-doc
|
116
|
+
# for more information
|
117
|
+
{ value: value.to_s, format: 1 }
|
118
|
+
when OID::Xml::Data, OID::Bit::Data
|
119
|
+
value.to_s
|
120
|
+
when OID::Array::Data
|
121
|
+
encode_array(value)
|
122
|
+
when Range
|
123
|
+
encode_range(value)
|
84
124
|
else
|
85
125
|
super
|
86
126
|
end
|
87
|
-
else
|
88
|
-
super
|
89
127
|
end
|
90
|
-
end
|
91
128
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
129
|
+
def encode_array(array_data)
|
130
|
+
encoder = array_data.encoder
|
131
|
+
values = type_cast_array(array_data.values)
|
132
|
+
|
133
|
+
result = encoder.encode(values)
|
134
|
+
if encoding = determine_encoding_of_strings_in_array(values)
|
135
|
+
result.force_encoding(encoding)
|
136
|
+
end
|
137
|
+
result
|
138
|
+
end
|
139
|
+
|
140
|
+
def encode_range(range)
|
141
|
+
"[#{type_cast_range_value(range.first)},#{type_cast_range_value(range.last)}#{range.exclude_end? ? ')' : ']'}"
|
142
|
+
end
|
143
|
+
|
144
|
+
def determine_encoding_of_strings_in_array(value)
|
145
|
+
case value
|
146
|
+
when ::Array then determine_encoding_of_strings_in_array(value.first)
|
147
|
+
when ::String then value.encoding
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def type_cast_array(values)
|
152
|
+
case values
|
153
|
+
when ::Array then values.map { |item| type_cast_array(item) }
|
154
|
+
else _type_cast(values)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def type_cast_range_value(value)
|
159
|
+
infinity?(value) ? "" : type_cast(value)
|
160
|
+
end
|
161
|
+
|
162
|
+
def infinity?(value)
|
163
|
+
value.respond_to?(:infinite?) && value.infinite?
|
103
164
|
end
|
104
|
-
end
|
105
165
|
end
|
106
166
|
end
|
107
167
|
end
|
@@ -1,27 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQL
|
4
6
|
module ReferentialIntegrity # :nodoc:
|
5
|
-
def supports_disable_referential_integrity? # :nodoc:
|
6
|
-
true
|
7
|
-
end
|
8
|
-
|
9
7
|
def disable_referential_integrity # :nodoc:
|
10
|
-
|
11
|
-
|
8
|
+
original_exception = nil
|
9
|
+
|
10
|
+
begin
|
11
|
+
transaction(requires_new: true) do
|
12
12
|
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
|
13
|
-
rescue
|
14
|
-
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER USER" }.join(";"))
|
15
13
|
end
|
14
|
+
rescue ActiveRecord::ActiveRecordError => e
|
15
|
+
original_exception = e
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
yield
|
20
|
+
rescue ActiveRecord::InvalidForeignKey => e
|
21
|
+
warn <<-WARNING
|
22
|
+
WARNING: Rails was not able to disable referential integrity.
|
23
|
+
|
24
|
+
This is most likely caused due to missing permissions.
|
25
|
+
Rails needs superuser privileges to disable referential integrity.
|
26
|
+
|
27
|
+
cause: #{original_exception.try(:message)}
|
28
|
+
|
29
|
+
WARNING
|
30
|
+
raise e
|
16
31
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
begin
|
32
|
+
|
33
|
+
begin
|
34
|
+
transaction(requires_new: true) do
|
21
35
|
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
|
22
|
-
rescue
|
23
|
-
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER USER" }.join(";"))
|
24
36
|
end
|
37
|
+
rescue ActiveRecord::ActiveRecordError
|
25
38
|
end
|
26
39
|
end
|
27
40
|
end
|