activerecord 5.2.8.1 → 6.1.6.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 +4 -4
- data/CHANGELOG.md +1255 -596
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +9 -8
- 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 +100 -41
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +55 -48
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +44 -34
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +69 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- 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 +88 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- 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 +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- 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 +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- 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 +293 -33
- data/lib/active_record/core.rb +333 -98
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- 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 +3 -4
- data/lib/active_record/enum.rb +108 -36
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- 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 +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +28 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +145 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +116 -59
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +411 -80
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +476 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +115 -62
- data/lib/active_record/relation.rb +379 -115
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- 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 +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- 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 +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- 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 +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -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/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -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 +15 -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 +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -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 +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -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 +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -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_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +116 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -22,8 +22,8 @@ module ActiveRecord
|
|
22
22
|
def create_database(name, options = {})
|
23
23
|
options = { encoding: "utf8" }.merge!(options.symbolize_keys)
|
24
24
|
|
25
|
-
option_string = options.
|
26
|
-
memo
|
25
|
+
option_string = options.each_with_object(+"") do |(key, value), memo|
|
26
|
+
memo << case key
|
27
27
|
when :owner
|
28
28
|
" OWNER = \"#{value}\""
|
29
29
|
when :template
|
@@ -54,7 +54,8 @@ module ActiveRecord
|
|
54
54
|
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
|
55
55
|
end
|
56
56
|
|
57
|
-
def drop_table(table_name, options
|
57
|
+
def drop_table(table_name, **options) # :nodoc:
|
58
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
58
59
|
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
|
59
60
|
end
|
60
61
|
|
@@ -68,13 +69,13 @@ module ActiveRecord
|
|
68
69
|
table = quoted_scope(table_name)
|
69
70
|
index = quoted_scope(index_name)
|
70
71
|
|
71
|
-
query_value(
|
72
|
+
query_value(<<~SQL, "SCHEMA").to_i > 0
|
72
73
|
SELECT COUNT(*)
|
73
74
|
FROM pg_class t
|
74
75
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
75
76
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
76
77
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
77
|
-
WHERE i.relkind
|
78
|
+
WHERE i.relkind IN ('i', 'I')
|
78
79
|
AND i.relname = #{index[:name]}
|
79
80
|
AND t.relname = #{table[:name]}
|
80
81
|
AND n.nspname = #{index[:schema]}
|
@@ -85,14 +86,14 @@ module ActiveRecord
|
|
85
86
|
def indexes(table_name) # :nodoc:
|
86
87
|
scope = quoted_scope(table_name)
|
87
88
|
|
88
|
-
result = query(
|
89
|
+
result = query(<<~SQL, "SCHEMA")
|
89
90
|
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
|
90
91
|
pg_catalog.obj_description(i.oid, 'pg_class') AS comment
|
91
92
|
FROM pg_class t
|
92
93
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
93
94
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
94
95
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
95
|
-
WHERE i.relkind
|
96
|
+
WHERE i.relkind IN ('i', 'I')
|
96
97
|
AND d.indisprimary = 'f'
|
97
98
|
AND t.relname = #{scope[:name]}
|
98
99
|
AND n.nspname = #{scope[:schema]}
|
@@ -115,7 +116,7 @@ module ActiveRecord
|
|
115
116
|
if indkey.include?(0)
|
116
117
|
columns = expressions
|
117
118
|
else
|
118
|
-
columns = Hash[query(
|
119
|
+
columns = Hash[query(<<~SQL, "SCHEMA")].values_at(*indkey).compact
|
119
120
|
SELECT a.attnum, a.attname
|
120
121
|
FROM pg_attribute a
|
121
122
|
WHERE a.attrelid = #{oid}
|
@@ -158,7 +159,7 @@ module ActiveRecord
|
|
158
159
|
def table_comment(table_name) # :nodoc:
|
159
160
|
scope = quoted_scope(table_name, type: "BASE TABLE")
|
160
161
|
if scope[:name]
|
161
|
-
query_value(
|
162
|
+
query_value(<<~SQL, "SCHEMA")
|
162
163
|
SELECT pg_catalog.obj_description(c.oid, 'pg_class')
|
163
164
|
FROM pg_catalog.pg_class c
|
164
165
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
@@ -196,7 +197,7 @@ module ActiveRecord
|
|
196
197
|
|
197
198
|
# Returns an array of schema names.
|
198
199
|
def schema_names
|
199
|
-
query_values(
|
200
|
+
query_values(<<~SQL, "SCHEMA")
|
200
201
|
SELECT nspname
|
201
202
|
FROM pg_namespace
|
202
203
|
WHERE nspname !~ '^pg_.*'
|
@@ -211,7 +212,7 @@ module ActiveRecord
|
|
211
212
|
end
|
212
213
|
|
213
214
|
# Drops the schema for the given schema name.
|
214
|
-
def drop_schema(schema_name, options
|
215
|
+
def drop_schema(schema_name, **options)
|
215
216
|
execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{quote_schema_name(schema_name)} CASCADE"
|
216
217
|
end
|
217
218
|
|
@@ -287,7 +288,7 @@ module ActiveRecord
|
|
287
288
|
quoted_sequence = quote_table_name(sequence)
|
288
289
|
max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
|
289
290
|
if max_pk.nil?
|
290
|
-
if
|
291
|
+
if database_version >= 100000
|
291
292
|
minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
|
292
293
|
else
|
293
294
|
minvalue = query_value("SELECT min_value FROM #{quoted_sequence}", "SCHEMA")
|
@@ -302,7 +303,7 @@ module ActiveRecord
|
|
302
303
|
def pk_and_sequence_for(table) #:nodoc:
|
303
304
|
# First try looking for a sequence with a dependency on the
|
304
305
|
# given table's primary key.
|
305
|
-
result = query(
|
306
|
+
result = query(<<~SQL, "SCHEMA")[0]
|
306
307
|
SELECT attr.attname, nsp.nspname, seq.relname
|
307
308
|
FROM pg_class seq,
|
308
309
|
pg_attribute attr,
|
@@ -319,10 +320,10 @@ module ActiveRecord
|
|
319
320
|
AND cons.contype = 'p'
|
320
321
|
AND dep.classid = 'pg_class'::regclass
|
321
322
|
AND dep.refobjid = #{quote(quote_table_name(table))}::regclass
|
322
|
-
|
323
|
+
SQL
|
323
324
|
|
324
325
|
if result.nil? || result.empty?
|
325
|
-
result = query(
|
326
|
+
result = query(<<~SQL, "SCHEMA")[0]
|
326
327
|
SELECT attr.attname, nsp.nspname,
|
327
328
|
CASE
|
328
329
|
WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL
|
@@ -339,7 +340,7 @@ module ActiveRecord
|
|
339
340
|
WHERE t.oid = #{quote(quote_table_name(table))}::regclass
|
340
341
|
AND cons.contype = 'p'
|
341
342
|
AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate'
|
342
|
-
|
343
|
+
SQL
|
343
344
|
end
|
344
345
|
|
345
346
|
pk = result.shift
|
@@ -353,7 +354,7 @@ module ActiveRecord
|
|
353
354
|
end
|
354
355
|
|
355
356
|
def primary_keys(table_name) # :nodoc:
|
356
|
-
query_values(
|
357
|
+
query_values(<<~SQL, "SCHEMA")
|
357
358
|
SELECT a.attname
|
358
359
|
FROM (
|
359
360
|
SELECT indrelid, indkey, generate_subscripts(indkey, 1) idx
|
@@ -368,31 +369,6 @@ module ActiveRecord
|
|
368
369
|
SQL
|
369
370
|
end
|
370
371
|
|
371
|
-
def bulk_change_table(table_name, operations)
|
372
|
-
sql_fragments = []
|
373
|
-
non_combinable_operations = []
|
374
|
-
|
375
|
-
operations.each do |command, args|
|
376
|
-
table, arguments = args.shift, args
|
377
|
-
method = :"#{command}_for_alter"
|
378
|
-
|
379
|
-
if respond_to?(method, true)
|
380
|
-
sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
|
381
|
-
sql_fragments << sqls
|
382
|
-
non_combinable_operations.concat(procs)
|
383
|
-
else
|
384
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
385
|
-
non_combinable_operations.each(&:call)
|
386
|
-
sql_fragments = []
|
387
|
-
non_combinable_operations = []
|
388
|
-
send(command, table, *arguments)
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
393
|
-
non_combinable_operations.each(&:call)
|
394
|
-
end
|
395
|
-
|
396
372
|
# Renames a table.
|
397
373
|
# Also renames a table's primary key sequence if the sequence name exists and
|
398
374
|
# matches the Active Record default.
|
@@ -401,6 +377,8 @@ module ActiveRecord
|
|
401
377
|
# rename_table('octopuses', 'octopi')
|
402
378
|
def rename_table(table_name, new_name)
|
403
379
|
clear_cache!
|
380
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
381
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
404
382
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
405
383
|
pk, seq = pk_and_sequence_for(new_name)
|
406
384
|
if pk
|
@@ -415,15 +393,15 @@ module ActiveRecord
|
|
415
393
|
rename_table_indexes(table_name, new_name)
|
416
394
|
end
|
417
395
|
|
418
|
-
def add_column(table_name, column_name, type, options
|
396
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
419
397
|
clear_cache!
|
420
398
|
super
|
421
399
|
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
422
400
|
end
|
423
401
|
|
424
|
-
def change_column(table_name, column_name, type, options
|
402
|
+
def change_column(table_name, column_name, type, **options) #:nodoc:
|
425
403
|
clear_cache!
|
426
|
-
sqls, procs = Array(change_column_for_alter(table_name, column_name, type, options)).partition { |v| v.is_a?(String) }
|
404
|
+
sqls, procs = Array(change_column_for_alter(table_name, column_name, type, **options)).partition { |v| v.is_a?(String) }
|
427
405
|
execute "ALTER TABLE #{quote_table_name(table_name)} #{sqls.join(", ")}"
|
428
406
|
procs.each(&:call)
|
429
407
|
end
|
@@ -443,35 +421,40 @@ module ActiveRecord
|
|
443
421
|
end
|
444
422
|
|
445
423
|
# Adds comment for given table column or drops it if +comment+ is a +nil+
|
446
|
-
def change_column_comment(table_name, column_name,
|
424
|
+
def change_column_comment(table_name, column_name, comment_or_changes) # :nodoc:
|
447
425
|
clear_cache!
|
426
|
+
comment = extract_new_comment_value(comment_or_changes)
|
448
427
|
execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} IS #{quote(comment)}"
|
449
428
|
end
|
450
429
|
|
451
430
|
# Adds comment for given table or drops it if +comment+ is a +nil+
|
452
|
-
def change_table_comment(table_name,
|
431
|
+
def change_table_comment(table_name, comment_or_changes) # :nodoc:
|
453
432
|
clear_cache!
|
433
|
+
comment = extract_new_comment_value(comment_or_changes)
|
454
434
|
execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS #{quote(comment)}"
|
455
435
|
end
|
456
436
|
|
457
437
|
# Renames a column in a table.
|
458
438
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
459
439
|
clear_cache!
|
460
|
-
execute
|
440
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}")
|
461
441
|
rename_column_indexes(table_name, column_name, new_column_name)
|
462
442
|
end
|
463
443
|
|
464
|
-
def add_index(table_name, column_name, options
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
444
|
+
def add_index(table_name, column_name, **options) #:nodoc:
|
445
|
+
index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
|
446
|
+
|
447
|
+
create_index = CreateIndexDefinition.new(index, algorithm, if_not_exists)
|
448
|
+
result = execute schema_creation.accept(create_index)
|
449
|
+
|
450
|
+
execute "COMMENT ON INDEX #{quote_column_name(index.name)} IS #{quote(index.comment)}" if index.comment
|
451
|
+
result
|
469
452
|
end
|
470
453
|
|
471
|
-
def remove_index(table_name,
|
454
|
+
def remove_index(table_name, column_name = nil, **options) # :nodoc:
|
472
455
|
table = Utils.extract_schema_qualified_name(table_name.to_s)
|
473
456
|
|
474
|
-
if options.
|
457
|
+
if options.key?(:name)
|
475
458
|
provided_index = Utils.extract_schema_qualified_name(options[:name].to_s)
|
476
459
|
|
477
460
|
options[:name] = provided_index.identifier
|
@@ -482,14 +465,11 @@ module ActiveRecord
|
|
482
465
|
end
|
483
466
|
end
|
484
467
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
end
|
491
|
-
end
|
492
|
-
execute "DROP INDEX #{algorithm} #{quote_table_name(index_to_remove)}"
|
468
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
469
|
+
|
470
|
+
index_to_remove = PostgreSQL::Name.new(table.schema, index_name_for_remove(table.to_s, column_name, options))
|
471
|
+
|
472
|
+
execute "DROP INDEX #{index_algorithm(options[:algorithm])} #{quote_table_name(index_to_remove)}"
|
493
473
|
end
|
494
474
|
|
495
475
|
# Renames an index of a table. Raises error if length of new
|
@@ -502,7 +482,7 @@ module ActiveRecord
|
|
502
482
|
|
503
483
|
def foreign_keys(table_name)
|
504
484
|
scope = quoted_scope(table_name)
|
505
|
-
fk_info = exec_query(
|
485
|
+
fk_info = exec_query(<<~SQL, "SCHEMA")
|
506
486
|
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid
|
507
487
|
FROM pg_constraint c
|
508
488
|
JOIN pg_class t1 ON c.conrelid = t1.oid
|
@@ -539,6 +519,28 @@ module ActiveRecord
|
|
539
519
|
query_values(data_source_sql(table_name, type: "FOREIGN TABLE"), "SCHEMA").any? if table_name.present?
|
540
520
|
end
|
541
521
|
|
522
|
+
def check_constraints(table_name) # :nodoc:
|
523
|
+
scope = quoted_scope(table_name)
|
524
|
+
|
525
|
+
check_info = exec_query(<<-SQL, "SCHEMA")
|
526
|
+
SELECT conname, pg_get_constraintdef(c.oid) AS constraintdef, c.convalidated AS valid
|
527
|
+
FROM pg_constraint c
|
528
|
+
JOIN pg_class t ON c.conrelid = t.oid
|
529
|
+
WHERE c.contype = 'c'
|
530
|
+
AND t.relname = #{scope[:name]}
|
531
|
+
SQL
|
532
|
+
|
533
|
+
check_info.map do |row|
|
534
|
+
options = {
|
535
|
+
name: row["conname"],
|
536
|
+
validate: row["valid"]
|
537
|
+
}
|
538
|
+
expression = row["constraintdef"][/CHECK \({2}(.+)\){2}/, 1]
|
539
|
+
|
540
|
+
CheckConstraintDefinition.new(table_name, expression, options)
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
542
544
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
543
545
|
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
|
544
546
|
sql = \
|
@@ -548,21 +550,21 @@ module ActiveRecord
|
|
548
550
|
# The hard limit is 1GB, because of a 32-bit size field, and TOAST.
|
549
551
|
case limit
|
550
552
|
when nil, 0..0x3fffffff; super(type)
|
551
|
-
else raise
|
553
|
+
else raise ArgumentError, "No binary type has byte size #{limit}. The limit on binary can be at most 1GB - 1byte."
|
552
554
|
end
|
553
555
|
when "text"
|
554
556
|
# PostgreSQL doesn't support limits on text columns.
|
555
557
|
# The hard limit is 1GB, according to section 8.3 in the manual.
|
556
558
|
case limit
|
557
559
|
when nil, 0..0x3fffffff; super(type)
|
558
|
-
else raise
|
560
|
+
else raise ArgumentError, "No text type has byte size #{limit}. The limit on text can be at most 1GB - 1byte."
|
559
561
|
end
|
560
562
|
when "integer"
|
561
563
|
case limit
|
562
564
|
when 1, 2; "smallint"
|
563
565
|
when nil, 3, 4; "integer"
|
564
566
|
when 5..8; "bigint"
|
565
|
-
else raise
|
567
|
+
else raise ArgumentError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead."
|
566
568
|
end
|
567
569
|
else
|
568
570
|
super
|
@@ -575,13 +577,13 @@ module ActiveRecord
|
|
575
577
|
# PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
|
576
578
|
# requires that the ORDER BY include the distinct column.
|
577
579
|
def columns_for_distinct(columns, orders) #:nodoc:
|
578
|
-
order_columns = orders.
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
580
|
+
order_columns = orders.compact_blank.map { |s|
|
581
|
+
# Convert Arel node to string
|
582
|
+
s = visitor.compile(s) unless s.is_a?(String)
|
583
|
+
# Remove any ASC/DESC modifiers
|
584
|
+
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
585
|
+
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
|
586
|
+
}.compact_blank.map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
585
587
|
|
586
588
|
(order_columns << super).join(", ")
|
587
589
|
end
|
@@ -600,8 +602,6 @@ module ActiveRecord
|
|
600
602
|
#
|
601
603
|
# validate_constraint :accounts, :constraint_name
|
602
604
|
def validate_constraint(table_name, constraint_name)
|
603
|
-
return unless supports_validate_constraints?
|
604
|
-
|
605
605
|
at = create_alter_table table_name
|
606
606
|
at.validate_constraint constraint_name
|
607
607
|
|
@@ -623,21 +623,30 @@ module ActiveRecord
|
|
623
623
|
# validate_foreign_key :accounts, name: :special_fk_name
|
624
624
|
#
|
625
625
|
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
|
626
|
-
def validate_foreign_key(from_table,
|
627
|
-
|
628
|
-
|
629
|
-
fk_name_to_validate = foreign_key_for!(from_table, options_or_to_table).name
|
626
|
+
def validate_foreign_key(from_table, to_table = nil, **options)
|
627
|
+
fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name
|
630
628
|
|
631
629
|
validate_constraint from_table, fk_name_to_validate
|
632
630
|
end
|
633
631
|
|
632
|
+
# Validates the given check constraint.
|
633
|
+
#
|
634
|
+
# validate_check_constraint :products, name: "price_check"
|
635
|
+
#
|
636
|
+
# The +options+ hash accepts the same keys as add_check_constraint[rdoc-ref:ConnectionAdapters::SchemaStatements#add_check_constraint].
|
637
|
+
def validate_check_constraint(table_name, **options)
|
638
|
+
chk_name_to_validate = check_constraint_for!(table_name, **options).name
|
639
|
+
|
640
|
+
validate_constraint table_name, chk_name_to_validate
|
641
|
+
end
|
642
|
+
|
634
643
|
private
|
635
644
|
def schema_creation
|
636
645
|
PostgreSQL::SchemaCreation.new(self)
|
637
646
|
end
|
638
647
|
|
639
|
-
def create_table_definition(
|
640
|
-
PostgreSQL::TableDefinition.new(
|
648
|
+
def create_table_definition(name, **options)
|
649
|
+
PostgreSQL::TableDefinition.new(self, name, **options)
|
641
650
|
end
|
642
651
|
|
643
652
|
def create_alter_table(name)
|
@@ -650,16 +659,19 @@ module ActiveRecord
|
|
650
659
|
default_value = extract_value_from_default(default)
|
651
660
|
default_function = extract_default_function(default_value, default)
|
652
661
|
|
653
|
-
|
662
|
+
if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
|
663
|
+
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
|
664
|
+
end
|
665
|
+
|
666
|
+
PostgreSQL::Column.new(
|
654
667
|
column_name,
|
655
668
|
default_value,
|
656
669
|
type_metadata,
|
657
670
|
!notnull,
|
658
|
-
table_name,
|
659
671
|
default_function,
|
660
|
-
collation,
|
672
|
+
collation: collation,
|
661
673
|
comment: comment.presence,
|
662
|
-
|
674
|
+
serial: serial
|
663
675
|
)
|
664
676
|
end
|
665
677
|
|
@@ -672,7 +684,23 @@ module ActiveRecord
|
|
672
684
|
precision: cast_type.precision,
|
673
685
|
scale: cast_type.scale,
|
674
686
|
)
|
675
|
-
|
687
|
+
PostgreSQL::TypeMetadata.new(simple_type, oid: oid, fmod: fmod)
|
688
|
+
end
|
689
|
+
|
690
|
+
def sequence_name_from_parts(table_name, column_name, suffix)
|
691
|
+
over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length
|
692
|
+
|
693
|
+
if over_length > 0
|
694
|
+
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
|
695
|
+
over_length -= column_name.length - column_name_length
|
696
|
+
column_name = column_name[0, column_name_length - [over_length, 0].min]
|
697
|
+
end
|
698
|
+
|
699
|
+
if over_length > 0
|
700
|
+
table_name = table_name[0, table_name.length - over_length]
|
701
|
+
end
|
702
|
+
|
703
|
+
"#{table_name}_#{column_name}_#{suffix}"
|
676
704
|
end
|
677
705
|
|
678
706
|
def extract_foreign_key_action(specifier)
|
@@ -683,14 +711,14 @@ module ActiveRecord
|
|
683
711
|
end
|
684
712
|
end
|
685
713
|
|
686
|
-
def add_column_for_alter(table_name, column_name, type, options
|
714
|
+
def add_column_for_alter(table_name, column_name, type, **options)
|
687
715
|
return super unless options.key?(:comment)
|
688
716
|
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
689
717
|
end
|
690
718
|
|
691
|
-
def change_column_for_alter(table_name, column_name, type, options
|
719
|
+
def change_column_for_alter(table_name, column_name, type, **options)
|
692
720
|
td = create_table_definition(table_name)
|
693
|
-
cd = td.new_column_definition(column_name, type, options)
|
721
|
+
cd = td.new_column_definition(column_name, type, **options)
|
694
722
|
sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
|
695
723
|
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
|
696
724
|
sqls
|
@@ -715,14 +743,6 @@ module ActiveRecord
|
|
715
743
|
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
716
744
|
end
|
717
745
|
|
718
|
-
def add_timestamps_for_alter(table_name, options = {})
|
719
|
-
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
720
|
-
end
|
721
|
-
|
722
|
-
def remove_timestamps_for_alter(table_name, options = {})
|
723
|
-
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
724
|
-
end
|
725
|
-
|
726
746
|
def add_index_opclass(quoted_columns, **options)
|
727
747
|
opclasses = options_for_index_columns(options[:opclass])
|
728
748
|
quoted_columns.each do |name, column|
|
@@ -731,7 +751,7 @@ module ActiveRecord
|
|
731
751
|
end
|
732
752
|
|
733
753
|
def add_options_for_index_columns(quoted_columns, **options)
|
734
|
-
quoted_columns = add_index_opclass(quoted_columns, options)
|
754
|
+
quoted_columns = add_index_opclass(quoted_columns, **options)
|
735
755
|
super
|
736
756
|
end
|
737
757
|
|
@@ -739,7 +759,7 @@ module ActiveRecord
|
|
739
759
|
scope = quoted_scope(name, type: type)
|
740
760
|
scope[:type] ||= "'r','v','m','p','f'" # (r)elation/table, (v)iew, (m)aterialized view, (p)artitioned table, (f)oreign table
|
741
761
|
|
742
|
-
sql = "SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
|
762
|
+
sql = +"SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
|
743
763
|
sql << " WHERE n.nspname = #{scope[:schema]}"
|
744
764
|
sql << " AND c.relname = #{scope[:name]}" if scope[:name]
|
745
765
|
sql << " AND c.relkind IN (#{scope[:type]})"
|
@@ -1,39 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
+
# :stopdoc:
|
4
5
|
module ConnectionAdapters
|
5
|
-
|
6
|
-
|
6
|
+
module PostgreSQL
|
7
|
+
class TypeMetadata < DelegateClass(SqlTypeMetadata)
|
8
|
+
undef to_yaml if method_defined?(:to_yaml)
|
7
9
|
|
8
|
-
|
10
|
+
include Deduplicable
|
9
11
|
|
10
|
-
|
11
|
-
super(type_metadata)
|
12
|
-
@type_metadata = type_metadata
|
13
|
-
@oid = oid
|
14
|
-
@fmod = fmod
|
15
|
-
@array = /\[\]$/.match?(type_metadata.sql_type)
|
16
|
-
end
|
17
|
-
|
18
|
-
def sql_type
|
19
|
-
super.gsub(/\[\]$/, "".freeze)
|
20
|
-
end
|
21
|
-
|
22
|
-
def ==(other)
|
23
|
-
other.is_a?(PostgreSQLTypeMetadata) &&
|
24
|
-
attributes_for_hash == other.attributes_for_hash
|
25
|
-
end
|
26
|
-
alias eql? ==
|
12
|
+
attr_reader :oid, :fmod
|
27
13
|
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
def initialize(type_metadata, oid: nil, fmod: nil)
|
15
|
+
super(type_metadata)
|
16
|
+
@oid = oid
|
17
|
+
@fmod = fmod
|
18
|
+
end
|
31
19
|
|
32
|
-
|
20
|
+
def ==(other)
|
21
|
+
other.is_a?(TypeMetadata) &&
|
22
|
+
__getobj__ == other.__getobj__ &&
|
23
|
+
oid == other.oid &&
|
24
|
+
fmod == other.fmod
|
25
|
+
end
|
26
|
+
alias eql? ==
|
33
27
|
|
34
|
-
def
|
35
|
-
|
28
|
+
def hash
|
29
|
+
TypeMetadata.hash ^
|
30
|
+
__getobj__.hash ^
|
31
|
+
oid.hash ^
|
32
|
+
fmod.hash
|
36
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def deduplicated
|
37
|
+
__setobj__(__getobj__.deduplicate)
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
37
41
|
end
|
42
|
+
PostgreSQLTypeMetadata = PostgreSQL::TypeMetadata
|
38
43
|
end
|
39
44
|
end
|