activerecord 7.0.8.6 → 7.2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +631 -1939
- data/MIT-LICENSE +1 -1
- data/README.rdoc +29 -29
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +26 -14
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +17 -7
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +10 -10
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +354 -485
- data/lib/active_record/attribute_assignment.rb +0 -4
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +148 -33
- data/lib/active_record/attributes.rb +64 -50
- data/lib/active_record/autosave_association.rb +69 -37
- data/lib/active_record/base.rb +9 -5
- data/lib/active_record/callbacks.rb +11 -25
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +323 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +217 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +307 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +278 -125
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +370 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +367 -201
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +124 -1
- data/lib/active_record/connection_handling.rb +96 -104
- data/lib/active_record/core.rb +251 -176
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +39 -10
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +45 -21
- data/lib/active_record/encryption/encrypted_attribute_type.rb +47 -12
- data/lib/active_record/encryption/encryptor.rb +18 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +3 -0
- data/lib/active_record/enum.rb +129 -28
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +234 -117
- data/lib/active_record/model_schema.rb +90 -102
- data/lib/active_record/nested_attributes.rb +48 -11
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +92 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +33 -8
- data/lib/active_record/railtie.rb +129 -85
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +145 -154
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +267 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +250 -93
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +28 -16
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +576 -107
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +580 -90
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +63 -14
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +3 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +27 -6
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +190 -118
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +106 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +61 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +56 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Trilogy
|
6
|
+
module DatabaseStatements
|
7
|
+
def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false) # :nodoc:
|
8
|
+
sql = transform_query(sql)
|
9
|
+
check_if_write_query(sql)
|
10
|
+
mark_transaction_written_if_write(sql)
|
11
|
+
|
12
|
+
result = raw_execute(sql, name, async: async, allow_retry: allow_retry)
|
13
|
+
ActiveRecord::Result.new(result.fields, result.to_a)
|
14
|
+
end
|
15
|
+
|
16
|
+
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil, returning: nil) # :nodoc:
|
17
|
+
sql = transform_query(sql)
|
18
|
+
check_if_write_query(sql)
|
19
|
+
mark_transaction_written_if_write(sql)
|
20
|
+
|
21
|
+
sql, _binds = sql_for_insert(sql, pk, binds, returning)
|
22
|
+
raw_execute(sql, name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def exec_delete(sql, name = nil, binds = []) # :nodoc:
|
26
|
+
sql = transform_query(sql)
|
27
|
+
check_if_write_query(sql)
|
28
|
+
mark_transaction_written_if_write(sql)
|
29
|
+
|
30
|
+
result = raw_execute(to_sql(sql, binds), name)
|
31
|
+
result.affected_rows
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :exec_update :exec_delete # :nodoc:
|
35
|
+
|
36
|
+
private
|
37
|
+
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
|
38
|
+
log(sql, name, async: async) do |notification_payload|
|
39
|
+
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
40
|
+
sync_timezone_changes(conn)
|
41
|
+
result = conn.query(sql)
|
42
|
+
while conn.more_results_exist?
|
43
|
+
conn.next_result
|
44
|
+
end
|
45
|
+
verified!
|
46
|
+
handle_warnings(sql)
|
47
|
+
notification_payload[:row_count] = result.count
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def last_inserted_id(result)
|
54
|
+
if supports_insert_returning?
|
55
|
+
super
|
56
|
+
else
|
57
|
+
result.last_insert_id
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def sync_timezone_changes(conn)
|
62
|
+
# Sync any changes since connection last established.
|
63
|
+
if default_timezone == :local
|
64
|
+
conn.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
|
65
|
+
else
|
66
|
+
conn.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def execute_batch(statements, name = nil)
|
71
|
+
statements = statements.map { |sql| transform_query(sql) }
|
72
|
+
combine_multi_statements(statements).each do |statement|
|
73
|
+
with_raw_connection do |conn|
|
74
|
+
raw_execute(statement, name)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def multi_statements_enabled?
|
80
|
+
!!@config[:multi_statement]
|
81
|
+
end
|
82
|
+
|
83
|
+
def with_multi_statements
|
84
|
+
if multi_statements_enabled?
|
85
|
+
return yield
|
86
|
+
end
|
87
|
+
|
88
|
+
with_raw_connection do |conn|
|
89
|
+
conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_ON)
|
90
|
+
|
91
|
+
yield
|
92
|
+
ensure
|
93
|
+
conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_OFF) if active?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/connection_adapters/abstract_mysql_adapter"
|
4
|
+
|
5
|
+
gem "trilogy", "~> 2.7"
|
6
|
+
require "trilogy"
|
7
|
+
|
8
|
+
require "active_record/connection_adapters/trilogy/database_statements"
|
9
|
+
|
10
|
+
module ActiveRecord
|
11
|
+
module ConnectionAdapters
|
12
|
+
class TrilogyAdapter < AbstractMysqlAdapter
|
13
|
+
ER_BAD_DB_ERROR = 1049
|
14
|
+
ER_DBACCESS_DENIED_ERROR = 1044
|
15
|
+
ER_ACCESS_DENIED_ERROR = 1045
|
16
|
+
|
17
|
+
ADAPTER_NAME = "Trilogy"
|
18
|
+
|
19
|
+
include Trilogy::DatabaseStatements
|
20
|
+
|
21
|
+
SSL_MODES = {
|
22
|
+
SSL_MODE_DISABLED: ::Trilogy::SSL_DISABLED,
|
23
|
+
SSL_MODE_PREFERRED: ::Trilogy::SSL_PREFERRED_NOVERIFY,
|
24
|
+
SSL_MODE_REQUIRED: ::Trilogy::SSL_REQUIRED_NOVERIFY,
|
25
|
+
SSL_MODE_VERIFY_CA: ::Trilogy::SSL_VERIFY_CA,
|
26
|
+
SSL_MODE_VERIFY_IDENTITY: ::Trilogy::SSL_VERIFY_IDENTITY
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def new_client(config)
|
31
|
+
config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
|
32
|
+
::Trilogy.new(config)
|
33
|
+
rescue ::Trilogy::Error => error
|
34
|
+
raise translate_connect_error(config, error)
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_ssl_mode(mode)
|
38
|
+
return mode if mode.is_a? Integer
|
39
|
+
|
40
|
+
m = mode.to_s.upcase
|
41
|
+
m = "SSL_MODE_#{m}" unless m.start_with? "SSL_MODE_"
|
42
|
+
|
43
|
+
SSL_MODES.fetch(m.to_sym, mode)
|
44
|
+
end
|
45
|
+
|
46
|
+
def translate_connect_error(config, error)
|
47
|
+
case error.error_code
|
48
|
+
when ER_DBACCESS_DENIED_ERROR, ER_BAD_DB_ERROR
|
49
|
+
ActiveRecord::NoDatabaseError.db_error(config[:database])
|
50
|
+
when ER_ACCESS_DENIED_ERROR
|
51
|
+
ActiveRecord::DatabaseConnectionError.username_error(config[:username])
|
52
|
+
else
|
53
|
+
if error.message.include?("TRILOGY_DNS_ERROR")
|
54
|
+
ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
|
55
|
+
else
|
56
|
+
ActiveRecord::ConnectionNotEstablished.new(error.message)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def initialize_type_map(m)
|
63
|
+
super
|
64
|
+
|
65
|
+
m.register_type(%r(char)i) do |sql_type|
|
66
|
+
limit = extract_limit(sql_type)
|
67
|
+
Type.lookup(:string, adapter: :trilogy, limit: limit)
|
68
|
+
end
|
69
|
+
|
70
|
+
m.register_type %r(^enum)i, Type.lookup(:string, adapter: :trilogy)
|
71
|
+
m.register_type %r(^set)i, Type.lookup(:string, adapter: :trilogy)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(config, *)
|
76
|
+
config = config.dup
|
77
|
+
|
78
|
+
# Trilogy ignores `socket` if `host is set. We want the opposite to allow
|
79
|
+
# configuring UNIX domain sockets via `DATABASE_URL`.
|
80
|
+
config.delete(:host) if config[:socket]
|
81
|
+
|
82
|
+
# Set FOUND_ROWS capability on the connection so UPDATE queries returns number of rows
|
83
|
+
# matched rather than number of rows updated.
|
84
|
+
config[:found_rows] = true
|
85
|
+
|
86
|
+
if config[:prepared_statements]
|
87
|
+
raise ArgumentError, "Trilogy currently doesn't support prepared statements. Remove `prepared_statements: true` from your database configuration."
|
88
|
+
end
|
89
|
+
|
90
|
+
super
|
91
|
+
end
|
92
|
+
|
93
|
+
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
|
94
|
+
|
95
|
+
def supports_json?
|
96
|
+
!mariadb? && database_version >= "5.7.8"
|
97
|
+
end
|
98
|
+
|
99
|
+
def supports_comments?
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def supports_comments_in_create?
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
def supports_savepoints?
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
def savepoint_errors_invalidate_transactions?
|
112
|
+
true
|
113
|
+
end
|
114
|
+
|
115
|
+
def supports_lazy_transactions?
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
def connected?
|
120
|
+
!(@raw_connection.nil? || @raw_connection.closed?)
|
121
|
+
end
|
122
|
+
|
123
|
+
def active?
|
124
|
+
connected? && @lock.synchronize { @raw_connection&.ping } || false
|
125
|
+
rescue ::Trilogy::Error
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
129
|
+
alias reset! reconnect!
|
130
|
+
|
131
|
+
def disconnect!
|
132
|
+
@lock.synchronize do
|
133
|
+
super
|
134
|
+
@raw_connection&.close
|
135
|
+
@raw_connection = nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def discard!
|
140
|
+
@lock.synchronize do
|
141
|
+
super
|
142
|
+
@raw_connection&.discard!
|
143
|
+
@raw_connection = nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
def text_type?(type)
|
149
|
+
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
|
150
|
+
end
|
151
|
+
|
152
|
+
def each_hash(result)
|
153
|
+
return to_enum(:each_hash, result) unless block_given?
|
154
|
+
|
155
|
+
keys = result.fields.map(&:to_sym)
|
156
|
+
result.rows.each do |row|
|
157
|
+
hash = {}
|
158
|
+
idx = 0
|
159
|
+
row.each do |value|
|
160
|
+
hash[keys[idx]] = value
|
161
|
+
idx += 1
|
162
|
+
end
|
163
|
+
yield hash
|
164
|
+
end
|
165
|
+
|
166
|
+
nil
|
167
|
+
end
|
168
|
+
|
169
|
+
def error_number(exception)
|
170
|
+
exception.error_code if exception.respond_to?(:error_code)
|
171
|
+
end
|
172
|
+
|
173
|
+
def connect
|
174
|
+
@raw_connection = self.class.new_client(@config)
|
175
|
+
rescue ConnectionNotEstablished => ex
|
176
|
+
raise ex.set_pool(@pool)
|
177
|
+
end
|
178
|
+
|
179
|
+
def reconnect
|
180
|
+
@raw_connection&.close
|
181
|
+
@raw_connection = nil
|
182
|
+
connect
|
183
|
+
end
|
184
|
+
|
185
|
+
def full_version
|
186
|
+
database_version.full_version_string
|
187
|
+
end
|
188
|
+
|
189
|
+
def get_full_version
|
190
|
+
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
|
191
|
+
conn.server_info[:version]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def translate_exception(exception, message:, sql:, binds:)
|
196
|
+
if exception.is_a?(::Trilogy::TimeoutError) && !exception.error_code
|
197
|
+
return ActiveRecord::AdapterTimeout.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
198
|
+
end
|
199
|
+
|
200
|
+
case exception
|
201
|
+
when ::Trilogy::ConnectionClosed, ::Trilogy::EOFError
|
202
|
+
return ConnectionFailed.new(message, connection_pool: @pool)
|
203
|
+
when ::Trilogy::Error
|
204
|
+
if exception.is_a?(SystemCallError) || exception.message.include?("TRILOGY_INVALID_SEQUENCE_ID")
|
205
|
+
return ConnectionFailed.new(message, connection_pool: @pool)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
super
|
210
|
+
end
|
211
|
+
|
212
|
+
def default_prepared_statements
|
213
|
+
false
|
214
|
+
end
|
215
|
+
|
216
|
+
ActiveRecord::Type.register(:immutable_string, adapter: :trilogy) do |_, **args|
|
217
|
+
Type::ImmutableString.new(true: "1", false: "0", **args)
|
218
|
+
end
|
219
|
+
|
220
|
+
ActiveRecord::Type.register(:string, adapter: :trilogy) do |_, **args|
|
221
|
+
Type::String.new(true: "1", false: "0", **args)
|
222
|
+
end
|
223
|
+
|
224
|
+
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :trilogy)
|
225
|
+
end
|
226
|
+
|
227
|
+
ActiveSupport.run_load_hooks(:active_record_trilogyadapter, TrilogyAdapter)
|
228
|
+
end
|
229
|
+
end
|
@@ -1,9 +1,130 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/string/filters"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
extend ActiveSupport::Autoload
|
6
8
|
|
9
|
+
@adapters = {}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Registers a custom database adapter.
|
13
|
+
#
|
14
|
+
# Can also be used to define aliases.
|
15
|
+
#
|
16
|
+
# == Example
|
17
|
+
#
|
18
|
+
# ActiveRecord::ConnectionAdapters.register("megadb", "MegaDB::ActiveRecordAdapter", "mega_db/active_record_adapter")
|
19
|
+
#
|
20
|
+
# ActiveRecord::ConnectionAdapters.register("mysql", "ActiveRecord::ConnectionAdapters::TrilogyAdapter", "active_record/connection_adapters/trilogy_adapter")
|
21
|
+
#
|
22
|
+
def register(name, class_name, path = class_name.underscore)
|
23
|
+
@adapters[name.to_s] = [class_name, path]
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve(adapter_name) # :nodoc:
|
27
|
+
# Require the adapter itself and give useful feedback about
|
28
|
+
# 1. Missing adapter gems.
|
29
|
+
# 2. Incorrectly registered adapters.
|
30
|
+
# 3. Adapter gems' missing dependencies.
|
31
|
+
class_name, path_to_adapter = @adapters[adapter_name.to_s]
|
32
|
+
|
33
|
+
unless class_name
|
34
|
+
# To provide better error messages for adapters expecting the pre-7.2 adapter registration API, we attempt
|
35
|
+
# to load the adapter file from the old location which was required by convention, and then raise an error
|
36
|
+
# describing how to upgrade the adapter to the new API.
|
37
|
+
legacy_adapter_path = "active_record/connection_adapters/#{adapter_name}_adapter"
|
38
|
+
legacy_adapter_connection_method_name = "#{adapter_name}_connection".to_sym
|
39
|
+
|
40
|
+
begin
|
41
|
+
require legacy_adapter_path
|
42
|
+
# If we reach here it means we found the found a file that may be the legacy adapter and should raise.
|
43
|
+
if ActiveRecord::ConnectionHandling.method_defined?(legacy_adapter_connection_method_name)
|
44
|
+
# If we find the connection method then we care certain it is a legacy adapter.
|
45
|
+
deprecation_message = <<~MSG.squish
|
46
|
+
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
47
|
+
Rails 7.2 has changed the way Active Record database adapters are loaded. The adapter needs to be
|
48
|
+
updated to register itself rather than being loaded by convention.
|
49
|
+
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
50
|
+
be modified.
|
51
|
+
See:
|
52
|
+
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
53
|
+
MSG
|
54
|
+
|
55
|
+
exception_message = <<~MSG.squish
|
56
|
+
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
57
|
+
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
58
|
+
be modified.
|
59
|
+
MSG
|
60
|
+
else
|
61
|
+
# If we do not find the connection method we are much less certain it is a legacy adapter. Even though the
|
62
|
+
# file exists in the location defined by convenntion, it does not necessarily mean that file is supposed
|
63
|
+
# to define the adapter the legacy way. So raise an error that explains both possibilities.
|
64
|
+
deprecation_message = <<~MSG.squish
|
65
|
+
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
66
|
+
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
67
|
+
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
68
|
+
adapter gem to your Gemfile if it's not in the list of available adapters.
|
69
|
+
Rails 7.2 has changed the way Active Record database adapters are loaded. Ensure that the adapter in
|
70
|
+
the Gemfile is at the latest version. If it is up to date, the adapter may need to be modified.
|
71
|
+
See:
|
72
|
+
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
73
|
+
MSG
|
74
|
+
|
75
|
+
exception_message = <<~MSG.squish
|
76
|
+
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
77
|
+
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
78
|
+
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
79
|
+
adapter gem to your Gemfile and that it is at its latest version. If it is up to date, the adapter may
|
80
|
+
need to be modified.
|
81
|
+
MSG
|
82
|
+
end
|
83
|
+
|
84
|
+
ActiveRecord.deprecator.warn(deprecation_message)
|
85
|
+
raise AdapterNotFound, exception_message
|
86
|
+
rescue LoadError => error
|
87
|
+
# The adapter was not found in the legacy location so fall through to the error handling for a missing adapter.
|
88
|
+
end
|
89
|
+
|
90
|
+
raise AdapterNotFound, <<~MSG.squish
|
91
|
+
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
92
|
+
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
93
|
+
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
94
|
+
adapter gem to your Gemfile if it's not in the list of available adapters.
|
95
|
+
MSG
|
96
|
+
end
|
97
|
+
|
98
|
+
unless Object.const_defined?(class_name)
|
99
|
+
begin
|
100
|
+
require path_to_adapter
|
101
|
+
rescue LoadError => error
|
102
|
+
# We couldn't require the adapter itself.
|
103
|
+
if error.path == path_to_adapter
|
104
|
+
# We can assume here that a non-builtin adapter was specified and the path
|
105
|
+
# registered by the adapter gem is incorrect.
|
106
|
+
raise LoadError, "Error loading the '#{adapter_name}' Active Record adapter. Ensure that the path registered by the adapter gem is correct. #{error.message}", error.backtrace
|
107
|
+
else
|
108
|
+
# Bubbled up from the adapter require. Prefix the exception message
|
109
|
+
# with some guidance about how to address it and reraise.
|
110
|
+
raise LoadError, "Error loading the '#{adapter_name}' Active Record adapter. Missing a gem it depends on? #{error.message}", error.backtrace
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
begin
|
116
|
+
Object.const_get(class_name)
|
117
|
+
rescue NameError => error
|
118
|
+
raise AdapterNotFound, "Could not load the #{class_name} Active Record adapter (#{error.message})."
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
register "sqlite3", "ActiveRecord::ConnectionAdapters::SQLite3Adapter", "active_record/connection_adapters/sqlite3_adapter"
|
124
|
+
register "mysql2", "ActiveRecord::ConnectionAdapters::Mysql2Adapter", "active_record/connection_adapters/mysql2_adapter"
|
125
|
+
register "trilogy", "ActiveRecord::ConnectionAdapters::TrilogyAdapter", "active_record/connection_adapters/trilogy_adapter"
|
126
|
+
register "postgresql", "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter", "active_record/connection_adapters/postgresql_adapter"
|
127
|
+
|
7
128
|
eager_autoload do
|
8
129
|
autoload :AbstractAdapter
|
9
130
|
end
|
@@ -11,14 +132,16 @@ module ActiveRecord
|
|
11
132
|
autoload :Column
|
12
133
|
autoload :PoolConfig
|
13
134
|
autoload :PoolManager
|
14
|
-
autoload :LegacyPoolManager
|
15
135
|
autoload :SchemaCache
|
136
|
+
autoload :BoundSchemaReflection, "active_record/connection_adapters/schema_cache"
|
137
|
+
autoload :SchemaReflection, "active_record/connection_adapters/schema_cache"
|
16
138
|
autoload :Deduplicable
|
17
139
|
|
18
140
|
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
19
141
|
autoload :IndexDefinition
|
20
142
|
autoload :ColumnDefinition
|
21
143
|
autoload :ChangeColumnDefinition
|
144
|
+
autoload :ChangeColumnDefaultDefinition
|
22
145
|
autoload :ForeignKeyDefinition
|
23
146
|
autoload :CheckConstraintDefinition
|
24
147
|
autoload :TableDefinition
|