activerecord 5.2.8.1 → 6.1.7.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1347 -624
- 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 +16 -7
- 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 +107 -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 +73 -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 +225 -121
- 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 +341 -99
- 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 +4 -4
- 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 +113 -74
- 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 +478 -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 +94 -10
- 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 +291 -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 +118 -32
- 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
|