aws_advanced_ruby_driver_wrapper 1.0.0

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.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +23 -0
  3. data/LICENSE +175 -0
  4. data/NOTICE +1 -0
  5. data/README.md +168 -0
  6. data/THIRD-PARTY-LICENSES +473 -0
  7. data/aws_advanced_ruby_driver_wrapper.gemspec +73 -0
  8. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +73 -0
  9. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +95 -0
  10. data/lib/aws_advanced_ruby_driver_wrapper/custom_configuration.rb +58 -0
  11. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_mysql_dialect.rb +103 -0
  12. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_pg_dialect.rb +124 -0
  13. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/dialect_codes.rb +38 -0
  14. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_mysql_dialect.rb +91 -0
  15. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_pg_dialect.rb +92 -0
  16. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_mysql_dialect.rb +95 -0
  17. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_pg_dialect.rb +86 -0
  18. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/mysql_dialect.rb +98 -0
  19. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/pg_dialect.rb +95 -0
  20. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_mysql_dialect.rb +88 -0
  21. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_pg_dialect.rb +86 -0
  22. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/unknown_dialect.rb +72 -0
  23. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/utils/dialect_utils.rb +71 -0
  24. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +154 -0
  25. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +55 -0
  26. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +165 -0
  27. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +201 -0
  28. data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +62 -0
  29. data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +80 -0
  30. data/lib/aws_advanced_ruby_driver_wrapper/errors/pg_error_handler.rb +126 -0
  31. data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +59 -0
  32. data/lib/aws_advanced_ruby_driver_wrapper/host/connection_string_host_list_provider.rb +95 -0
  33. data/lib/aws_advanced_ruby_driver_wrapper/host/global_aurora_host_list_provider.rb +65 -0
  34. data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability.rb +24 -0
  35. data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability_strategy.rb +27 -0
  36. data/lib/aws_advanced_ruby_driver_wrapper/host/host_info.rb +137 -0
  37. data/lib/aws_advanced_ruby_driver_wrapper/host/host_role.rb +25 -0
  38. data/lib/aws_advanced_ruby_driver_wrapper/host/random_host_selector.rb +40 -0
  39. data/lib/aws_advanced_ruby_driver_wrapper/host/rds_host_list_provider.rb +206 -0
  40. data/lib/aws_advanced_ruby_driver_wrapper/logging.rb +110 -0
  41. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +709 -0
  42. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/global_cluster_topology_monitor.rb +72 -0
  43. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +99 -0
  44. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +57 -0
  45. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_state.rb +25 -0
  46. data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +429 -0
  47. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +205 -0
  48. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +132 -0
  49. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/iam_host_tracker.rb +84 -0
  50. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interim_status.rb +92 -0
  51. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interval_rate.rb +27 -0
  52. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase.rb +69 -0
  53. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_event_log.rb +85 -0
  54. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_time_info.rb +25 -0
  55. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/role.rb +38 -0
  56. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +83 -0
  57. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/reject_connect_routing.rb +40 -0
  58. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +136 -0
  59. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +53 -0
  60. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +52 -0
  61. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +83 -0
  62. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status.rb +68 -0
  63. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +244 -0
  64. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_info.rb +30 -0
  65. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +564 -0
  66. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +414 -0
  67. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_state.rb +98 -0
  68. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_timer.rb +46 -0
  69. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +266 -0
  70. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +158 -0
  71. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/info.rb +111 -0
  72. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/member_list_type.rb +31 -0
  73. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/role.rb +45 -0
  74. data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +108 -0
  75. data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_mode.rb +43 -0
  76. data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +467 -0
  77. data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_mode.rb +68 -0
  78. data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +403 -0
  79. data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +159 -0
  80. data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +485 -0
  81. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/audit_logger.rb +157 -0
  82. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_cipher.rb +159 -0
  83. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_encryption_config.rb +61 -0
  84. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/connection_source.rb +91 -0
  85. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/data_key_cache.rb +220 -0
  86. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_algorithm.rb +75 -0
  87. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_config.rb +146 -0
  88. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_service.rb +391 -0
  89. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/error_context.rb +198 -0
  90. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/errors.rb +259 -0
  91. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +435 -0
  92. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +378 -0
  93. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_metadata.rb +86 -0
  94. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +890 -0
  95. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_utility.rb +281 -0
  96. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/metadata_manager.rb +332 -0
  97. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sanitizer.rb +147 -0
  98. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_name.rb +70 -0
  99. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_validator.rb +211 -0
  100. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql_runner.rb +147 -0
  101. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/type_marker.rb +109 -0
  102. data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +358 -0
  103. data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +659 -0
  104. data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +409 -0
  105. data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +122 -0
  106. data/lib/aws_advanced_ruby_driver_wrapper/services/connection_service.rb +143 -0
  107. data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +267 -0
  108. data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +199 -0
  109. data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +186 -0
  110. data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_call_context.rb +63 -0
  111. data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +273 -0
  112. data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +30 -0
  113. data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +78 -0
  114. data/lib/aws_advanced_ruby_driver_wrapper/services/session_state_service.rb +56 -0
  115. data/lib/aws_advanced_ruby_driver_wrapper/utils/accessible_regions.rb +52 -0
  116. data/lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb +25 -0
  117. data/lib/aws_advanced_ruby_driver_wrapper/utils/aurora_topology_utils.rb +99 -0
  118. data/lib/aws_advanced_ruby_driver_wrapper/utils/aws_credentials_utils.rb +62 -0
  119. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +91 -0
  120. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +368 -0
  121. data/lib/aws_advanced_ruby_driver_wrapper/utils/conversion_utils.rb +51 -0
  122. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +119 -0
  123. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/data_access_event.rb +26 -0
  124. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/monitor_reset_event.rb +26 -0
  125. data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +185 -0
  126. data/lib/aws_advanced_ruby_driver_wrapper/utils/host_list_utils.rb +27 -0
  127. data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +112 -0
  128. data/lib/aws_advanced_ruby_driver_wrapper/utils/multi_az_topology_utils.rb +117 -0
  129. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +99 -0
  130. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +641 -0
  131. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +502 -0
  132. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +63 -0
  133. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_type.rb +35 -0
  134. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint.rb +27 -0
  135. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint_parser.rb +50 -0
  136. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +139 -0
  137. data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_url_type.rb +71 -0
  138. data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_utils.rb +575 -0
  139. data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +153 -0
  140. data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_encoding.rb +56 -0
  141. data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_method_analyzer.rb +195 -0
  142. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/cache_entry.rb +56 -0
  143. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/expiration_cache.rb +108 -0
  144. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/sliding_expiration_cache.rb +137 -0
  145. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +172 -0
  146. data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +127 -0
  147. data/lib/aws_advanced_ruby_driver_wrapper/version.rb +19 -0
  148. data/lib/aws_advanced_ruby_driver_wrapper/wrapper_property.rb +64 -0
  149. data/lib/aws_advanced_ruby_driver_wrapper.rb +116 -0
  150. metadata +227 -0
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'mysql_dialect'
18
+ require_relative 'utils/dialect_utils'
19
+
20
+ module AwsAdvancedRubyDriverWrapper
21
+ module DbDialects
22
+ class MultiAzClusterMysqlDialect < MysqlDialect
23
+ REPORT_HOST_EXISTS_QUERY = <<~SQL
24
+ SHOW VARIABLES LIKE 'report_host'
25
+ SQL
26
+
27
+ TOPOLOGY_TABLE_EXISTS_QUERY = <<~SQL
28
+ SELECT 1 AS tmp FROM information_schema.tables WHERE
29
+ table_schema = 'mysql' AND table_name = 'rds_topology'
30
+ SQL
31
+
32
+ TOPOLOGY_QUERY = <<~SQL
33
+ SELECT id AS instance_id, endpoint AS endpoint FROM mysql.rds_topology
34
+ SQL
35
+
36
+ INSTANCE_IDENTITY_QUERY = <<~SQL
37
+ SELECT id AS instance_id,
38
+ SUBSTRING_INDEX(endpoint, '.', 1) AS instance_name
39
+ FROM mysql.rds_topology
40
+ WHERE id = @@server_id
41
+ SQL
42
+
43
+ WRITER_ID_QUERY = <<~SQL
44
+ SHOW REPLICA STATUS
45
+ SQL
46
+
47
+ WRITER_ID_QUERY_COLUMN_NAME = 'Source_Server_Id'
48
+
49
+ def dialect?(connection)
50
+ return false unless
51
+ check_existence_queries(@driver_dialect, connection, TOPOLOGY_TABLE_EXISTS_QUERY, TOPOLOGY_QUERY)
52
+
53
+ begin
54
+ result = @driver_dialect.execute(connection, REPORT_HOST_EXISTS_QUERY)
55
+ return false if result.none?
56
+
57
+ row = result.first
58
+ report_host = row.values[1]
59
+ report_host.is_a?(String) && !report_host.empty?
60
+ rescue StandardError
61
+ false
62
+ end
63
+ end
64
+
65
+ def dialect_update_candidates
66
+ []
67
+ end
68
+
69
+ def topology_query
70
+ TOPOLOGY_QUERY
71
+ end
72
+
73
+ def instance_identity(connection)
74
+ query_instance_identity(@driver_dialect, connection, INSTANCE_IDENTITY_QUERY)
75
+ end
76
+
77
+ def writer_id_query
78
+ WRITER_ID_QUERY
79
+ end
80
+
81
+ def writer_id_column_name
82
+ WRITER_ID_QUERY_COLUMN_NAME
83
+ end
84
+
85
+ # @param service_container [Services::ServiceContainer]
86
+ # @return [Host::RdsHostListProvider] the host list provider
87
+ def create_host_list_provider(service_container)
88
+ require_relative '../utils/multi_az_topology_utils'
89
+ require_relative '../host/rds_host_list_provider'
90
+ topology_utils = Utils::MultiAzTopologyUtils.new(dialect: self)
91
+ Host::RdsHostListProvider.new(service_container:, topology_utils:)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'pg_dialect'
18
+ require_relative 'utils/dialect_utils'
19
+
20
+ module AwsAdvancedRubyDriverWrapper
21
+ module DbDialects
22
+ class MultiAzClusterPgDialect < PgDialect
23
+ IS_RDS_CLUSTER_QUERY = <<~SQL
24
+ SELECT multi_az_db_cluster_source_dbi_resource_id FROM rds_tools.multi_az_db_cluster_source_dbi_resource_id()
25
+ SQL
26
+
27
+ TOPOLOGY_QUERY = <<~SQL.freeze
28
+ SELECT id AS instance_id, endpoint AS endpoint FROM rds_tools.show_topology('aws_advanced_ruby_driver_wrapper-#{AwsAdvancedRubyDriverWrapper::VERSION}')
29
+ SQL
30
+
31
+ INSTANCE_IDENTITY_QUERY = <<~SQL
32
+ SELECT id AS instance_id,
33
+ SUBSTRING(endpoint FROM 0 FOR POSITION('.' IN endpoint)) AS instance_name
34
+ FROM rds_tools.show_topology()
35
+ WHERE id OPERATOR(pg_catalog.=) rds_tools.dbi_resource_id()
36
+ SQL
37
+
38
+ WRITER_ID_QUERY = <<~SQL
39
+ SELECT multi_az_db_cluster_source_dbi_resource_id FROM rds_tools.multi_az_db_cluster_source_dbi_resource_id()
40
+ WHERE multi_az_db_cluster_source_dbi_resource_id OPERATOR(pg_catalog.!=)
41
+ (SELECT dbi_resource_id FROM rds_tools.dbi_resource_id())
42
+ SQL
43
+
44
+ WRITER_ID_QUERY_COLUMN_NAME = 'multi_az_db_cluster_source_dbi_resource_id'
45
+
46
+ def dialect?(connection)
47
+ result = @driver_dialect.execute(connection, IS_RDS_CLUSTER_QUERY)
48
+ return false unless result.any?
49
+
50
+ row = result.first
51
+ !row['multi_az_db_cluster_source_dbi_resource_id'].nil?
52
+ rescue StandardError
53
+ false
54
+ end
55
+
56
+ def dialect_update_candidates
57
+ []
58
+ end
59
+
60
+ def topology_query
61
+ TOPOLOGY_QUERY
62
+ end
63
+
64
+ def instance_identity(connection)
65
+ query_instance_identity(@driver_dialect, connection, INSTANCE_IDENTITY_QUERY)
66
+ end
67
+
68
+ def writer_id_query
69
+ WRITER_ID_QUERY
70
+ end
71
+
72
+ def writer_id_column_name
73
+ WRITER_ID_QUERY_COLUMN_NAME
74
+ end
75
+
76
+ # @param service_container [Services::ServiceContainer]
77
+ # @return [Host::RdsHostListProvider] the host list provider
78
+ def create_host_list_provider(service_container)
79
+ require_relative '../utils/multi_az_topology_utils'
80
+ require_relative '../host/rds_host_list_provider'
81
+ topology_utils = Utils::MultiAzTopologyUtils.new(dialect: self)
82
+ Host::RdsHostListProvider.new(service_container:, topology_utils:)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'dialect_codes'
18
+ require_relative 'utils/dialect_utils'
19
+
20
+ module AwsAdvancedRubyDriverWrapper
21
+ module DbDialects
22
+ class MysqlDialect
23
+ include AwsAdvancedRubyDriverWrapper::DbDialects::DialectUtils
24
+
25
+ VERSION_QUERY = <<~SQL
26
+ SHOW VARIABLES LIKE 'version_comment'
27
+ SQL
28
+
29
+ INSTANCE_IDENTITY_QUERY = <<~SQL
30
+ SELECT @@hostname AS instance_id, CONCAT(@@hostname, ':', @@port) AS instance_name
31
+ SQL
32
+
33
+ IS_READER_QUERY = <<~SQL
34
+ SELECT @@read_only
35
+ SQL
36
+
37
+ DIALECT_UPDATE_CANDIDATES = [
38
+ AwsAdvancedRubyDriverWrapper::DialectCodes::GLOBAL_AURORA_MYSQL,
39
+ AwsAdvancedRubyDriverWrapper::DialectCodes::AURORA_MYSQL,
40
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MULTI_AZ_MYSQL_CLUSTER,
41
+ AwsAdvancedRubyDriverWrapper::DialectCodes::RDS_MYSQL
42
+ ].freeze
43
+
44
+ def initialize(driver_dialect)
45
+ @driver_dialect = driver_dialect
46
+ end
47
+
48
+ def execute(connection, sql)
49
+ @driver_dialect.execute(connection, sql)
50
+ end
51
+
52
+ def execute_with_params(connection, sql, params)
53
+ @driver_dialect.execute_with_params(connection, sql, params)
54
+ end
55
+
56
+ def dialect?(connection)
57
+ result = @driver_dialect.execute(connection, VERSION_QUERY)
58
+ result.any? do |row|
59
+ row.values[1]&.downcase&.include?('mysql')
60
+ end
61
+ rescue StandardError
62
+ false
63
+ end
64
+
65
+ def default_port
66
+ @default_port ||= 3306
67
+ end
68
+
69
+ # @return [Boolean] whether this dialect represents an Aurora Global Database.
70
+ # Overridden to true by the global dialects.
71
+ def global?
72
+ false
73
+ end
74
+
75
+ def dialect_update_candidates
76
+ DIALECT_UPDATE_CANDIDATES
77
+ end
78
+
79
+ def exception_handler(driver_dialect)
80
+ AwsAdvancedRubyDriverWrapper::Errors::MysqlErrorHandler.new(driver_dialect)
81
+ end
82
+
83
+ def host_role(connection)
84
+ query_host_role(@driver_dialect, connection, self.class::IS_READER_QUERY)
85
+ end
86
+
87
+ def instance_identity(connection)
88
+ query_instance_identity(@driver_dialect, connection, INSTANCE_IDENTITY_QUERY)
89
+ end
90
+
91
+ # @param service_container [Services::ServiceContainer]
92
+ # @return [Host::ConnectionStringHostListProvider] the host list provider
93
+ def create_host_list_provider(service_container)
94
+ Host::ConnectionStringHostListProvider.new(service_container:)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'dialect_codes'
18
+ require_relative 'utils/dialect_utils'
19
+ require_relative '../host/connection_string_host_list_provider'
20
+
21
+ module AwsAdvancedRubyDriverWrapper
22
+ module DbDialects
23
+ class PgDialect
24
+ include AwsAdvancedRubyDriverWrapper::DbDialects::DialectUtils
25
+
26
+ PG_PROC_EXISTS_QUERY = <<~SQL
27
+ SELECT 1 FROM pg_catalog.pg_proc LIMIT 1
28
+ SQL
29
+
30
+ INSTANCE_IDENTITY_QUERY = <<~SQL
31
+ SELECT pg_catalog.inet_server_addr() AS instance_id,
32
+ pg_catalog.CONCAT(pg_catalog.inet_server_addr(), ':', pg_catalog.inet_server_port()) AS instance_name
33
+ SQL
34
+
35
+ IS_READER_QUERY = <<~SQL
36
+ SELECT pg_catalog.pg_is_in_recovery()
37
+ SQL
38
+
39
+ DIALECT_UPDATE_CANDIDATES = [
40
+ AwsAdvancedRubyDriverWrapper::DialectCodes::GLOBAL_AURORA_PG,
41
+ AwsAdvancedRubyDriverWrapper::DialectCodes::AURORA_PG,
42
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MULTI_AZ_PG_CLUSTER,
43
+ AwsAdvancedRubyDriverWrapper::DialectCodes::RDS_PG
44
+ ].freeze
45
+
46
+ def initialize(driver_dialect)
47
+ @driver_dialect = driver_dialect
48
+ end
49
+
50
+ def execute(connection, sql)
51
+ @driver_dialect.execute(connection, sql)
52
+ end
53
+
54
+ def execute_with_params(connection, sql, params)
55
+ @driver_dialect.execute_with_params(connection, sql, params)
56
+ end
57
+
58
+ def dialect?(connection)
59
+ check_existence_queries(@driver_dialect, connection, PG_PROC_EXISTS_QUERY)
60
+ end
61
+
62
+ def default_port
63
+ @default_port ||= 5432
64
+ end
65
+
66
+ # @return [Boolean] whether this dialect represents an Aurora Global Database.
67
+ # Overridden to true by the global dialects.
68
+ def global?
69
+ false
70
+ end
71
+
72
+ def dialect_update_candidates
73
+ DIALECT_UPDATE_CANDIDATES
74
+ end
75
+
76
+ def exception_handler(driver_dialect)
77
+ AwsAdvancedRubyDriverWrapper::Errors::PgErrorHandler.new(driver_dialect)
78
+ end
79
+
80
+ def host_role(connection)
81
+ query_host_role(@driver_dialect, connection, IS_READER_QUERY)
82
+ end
83
+
84
+ def instance_identity(connection)
85
+ query_instance_identity(@driver_dialect, connection, INSTANCE_IDENTITY_QUERY)
86
+ end
87
+
88
+ # @param service_container [Services::ServiceContainer]
89
+ # @return [Host::ConnectionStringHostListProvider] the host list provider
90
+ def create_host_list_provider(service_container)
91
+ Host::ConnectionStringHostListProvider.new(service_container:)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'mysql_dialect'
18
+ require_relative 'utils/dialect_utils'
19
+
20
+ module AwsAdvancedRubyDriverWrapper
21
+ module DbDialects
22
+ class RdsMysqlDialect < MysqlDialect
23
+ REPORT_HOST_EXISTS_QUERY = <<~SQL
24
+ SHOW VARIABLES LIKE 'report_host'
25
+ SQL
26
+
27
+ TOPOLOGY_TABLE_EXISTS_QUERY = <<~SQL
28
+ SELECT 1 AS tmp FROM information_schema.tables WHERE
29
+ table_schema = 'mysql' AND table_name = 'rds_topology'
30
+ SQL
31
+
32
+ INSTANCE_IDENTITY_QUERY = <<~SQL
33
+ SELECT id AS instance_id,
34
+ SUBSTRING_INDEX(endpoint, '.', 1) AS instance_name
35
+ FROM mysql.rds_topology
36
+ WHERE id = @@server_id
37
+ SQL
38
+
39
+ BG_STATUS_QUERY = <<~SQL
40
+ SELECT * FROM mysql.rds_topology
41
+ SQL
42
+
43
+ DIALECT_UPDATE_CANDIDATES = [
44
+ AwsAdvancedRubyDriverWrapper::DialectCodes::GLOBAL_AURORA_MYSQL,
45
+ AwsAdvancedRubyDriverWrapper::DialectCodes::AURORA_MYSQL,
46
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MULTI_AZ_MYSQL_CLUSTER
47
+ ].freeze
48
+
49
+ def dialect?(connection)
50
+ return false if super
51
+
52
+ begin
53
+ result = @driver_dialect.execute(connection, VERSION_QUERY)
54
+ return false unless result.any?
55
+
56
+ row = result.first
57
+ column_value = row.values[1]
58
+ return false unless 'Source distribution'.casecmp?(column_value)
59
+
60
+ result = @driver_dialect.execute(connection, REPORT_HOST_EXISTS_QUERY)
61
+ return false unless result.any?
62
+
63
+ row = result.first
64
+ report_host = row.values[1]
65
+ report_host.nil? || report_host.empty?
66
+ rescue StandardError
67
+ false
68
+ end
69
+ end
70
+
71
+ def dialect_update_candidates
72
+ DIALECT_UPDATE_CANDIDATES
73
+ end
74
+
75
+ def blue_green_status_available?(connection)
76
+ check_existence_queries(@driver_dialect, connection, TOPOLOGY_TABLE_EXISTS_QUERY)
77
+ end
78
+
79
+ def instance_identity(connection)
80
+ query_instance_identity(@driver_dialect, connection, INSTANCE_IDENTITY_QUERY)
81
+ end
82
+
83
+ def blue_green_status_query
84
+ BG_STATUS_QUERY
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'pg_dialect'
18
+ require_relative 'utils/dialect_utils'
19
+
20
+ module AwsAdvancedRubyDriverWrapper
21
+ module DbDialects
22
+ class RdsPgDialect < PgDialect
23
+ EXTENSIONS_EXIST_SQL = <<~SQL
24
+ SELECT (setting OPERATOR(pg_catalog.~~) '%rds_tools%') AS rds_tools,
25
+ (setting OPERATOR(pg_catalog.~~) '%aurora_stat_utils%') AS aurora_stat_utils
26
+ FROM pg_catalog.pg_settings
27
+ WHERE name OPERATOR(pg_catalog.=) 'rds.extensions'
28
+ SQL
29
+
30
+ TOPOLOGY_TABLE_EXISTS_QUERY = <<~SQL
31
+ SELECT 'rds_tools.show_topology'::pg_catalog.regproc
32
+ SQL
33
+
34
+ INSTANCE_IDENTITY_QUERY = <<~SQL
35
+ SELECT id AS instance_id,
36
+ SUBSTRING(endpoint FROM 0 FOR POSITION('.' IN endpoint)) AS instance_name
37
+ FROM rds_tools.show_topology()
38
+ WHERE id OPERATOR(pg_catalog.=) rds_tools.dbi_resource_id()
39
+ SQL
40
+
41
+ BG_STATUS_QUERY = <<~SQL.freeze
42
+ SELECT * FROM rds_tools.show_topology('aws_advanced_ruby_driver_wrapper-#{AwsAdvancedRubyDriverWrapper::VERSION}')
43
+ SQL
44
+
45
+ DIALECT_UPDATE_CANDIDATES = [
46
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MULTI_AZ_PG_CLUSTER,
47
+ AwsAdvancedRubyDriverWrapper::DialectCodes::GLOBAL_AURORA_PG,
48
+ AwsAdvancedRubyDriverWrapper::DialectCodes::AURORA_PG
49
+ ].freeze
50
+
51
+ def dialect?(connection)
52
+ return false unless super
53
+
54
+ begin
55
+ result = @driver_dialect.execute(connection, EXTENSIONS_EXIST_SQL)
56
+ result.each do |row|
57
+ rds_tools_enabled = row['rds_tools'] == 't'
58
+ aurora_utils_enabled = row['aurora_stat_utils'] == 't'
59
+
60
+ return true if rds_tools_enabled && !aurora_utils_enabled
61
+ end
62
+ rescue StandardError
63
+ return false
64
+ end
65
+
66
+ false
67
+ end
68
+
69
+ def dialect_update_candidates
70
+ DIALECT_UPDATE_CANDIDATES
71
+ end
72
+
73
+ def blue_green_status_available?(connection)
74
+ check_existence_queries(@driver_dialect, connection, TOPOLOGY_TABLE_EXISTS_QUERY)
75
+ end
76
+
77
+ def instance_identity(connection)
78
+ query_instance_identity(@driver_dialect, connection, INSTANCE_IDENTITY_QUERY)
79
+ end
80
+
81
+ def blue_green_status_query
82
+ BG_STATUS_QUERY
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'dialect_codes'
18
+
19
+ module AwsAdvancedRubyDriverWrapper
20
+ module DbDialects
21
+ class UnknownDialect
22
+ DIALECT_UPDATE_CANDIDATES = [
23
+ AwsAdvancedRubyDriverWrapper::DialectCodes::GLOBAL_AURORA_PG,
24
+ AwsAdvancedRubyDriverWrapper::DialectCodes::GLOBAL_AURORA_MYSQL,
25
+ AwsAdvancedRubyDriverWrapper::DialectCodes::AURORA_PG,
26
+ AwsAdvancedRubyDriverWrapper::DialectCodes::AURORA_MYSQL,
27
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MULTI_AZ_PG_CLUSTER,
28
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MULTI_AZ_MYSQL_CLUSTER,
29
+ AwsAdvancedRubyDriverWrapper::DialectCodes::RDS_PG,
30
+ AwsAdvancedRubyDriverWrapper::DialectCodes::RDS_MYSQL,
31
+ AwsAdvancedRubyDriverWrapper::DialectCodes::PG,
32
+ AwsAdvancedRubyDriverWrapper::DialectCodes::MYSQL
33
+ ].freeze
34
+
35
+ def initialize(_driver_dialect = nil); end
36
+
37
+ def default_port
38
+ @default_port ||= -1
39
+ end
40
+
41
+ def host_role(connection)
42
+ raise NotImplementedError, 'Unable to gather host role, connected to unknown DB type.'
43
+ end
44
+
45
+ def host_id(connection)
46
+ raise NotImplementedError, 'Unable to gather host id, connected to unknown DB type.'
47
+ end
48
+
49
+ def instance_identity(_connection)
50
+ nil
51
+ end
52
+
53
+ def dialect?(_connection)
54
+ false
55
+ end
56
+
57
+ def dialect_update_candidates
58
+ DIALECT_UPDATE_CANDIDATES
59
+ end
60
+
61
+ def execute(connection, sql)
62
+ raise NotImplementedError, 'Unable to execute query, connected to unknown DB type.'
63
+ end
64
+
65
+ # @param service_container [Services::ServiceContainer]
66
+ # @return [Host::ConnectionStringHostListProvider] the host list provider
67
+ def create_host_list_provider(service_container)
68
+ Host::ConnectionStringHostListProvider.new(service_container:)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.module DialectUtils
16
+ #
17
+ require_relative '../../host/host_role'
18
+
19
+ module AwsAdvancedRubyDriverWrapper
20
+ module DbDialects
21
+ module DialectUtils
22
+ # Returns the instance identity for the given connection.
23
+ #
24
+ # @param driver_dialect [Object] the driver dialect used to execute queries
25
+ # @param connection [Object] the connection to analyze
26
+ # @param host_id_query [String] the SQL query to retrieve the instance identity
27
+ # @return [Array(String, String), nil] the instance_id and instance_name, or nil if they cannot be determined
28
+ def query_instance_identity(driver_dialect, connection, host_id_query)
29
+ result = driver_dialect.execute(connection, host_id_query)
30
+ return nil if result.nil? || result.none?
31
+
32
+ row = result.first
33
+ values = row.values
34
+ [values[0], values[1]]
35
+ rescue StandardError
36
+ nil
37
+ end
38
+
39
+ # Determines the role of the host behind the given connection.
40
+ #
41
+ # @param driver_dialect [Object] the driver dialect used to execute queries
42
+ # @param connection [Object] the connection to analyze
43
+ # @param reader_check_query [String] the SQL query to check if the host is a reader
44
+ # @return [HostRole] :writer or :reader
45
+ def query_host_role(driver_dialect, connection, reader_check_query)
46
+ result = driver_dialect.execute(connection, reader_check_query)
47
+ row = result.first
48
+ value = row.is_a?(Hash) ? row.values.first : row
49
+ %w[t 1].include?(value.to_s) ? Host::HostRole::READER : Host::HostRole::WRITER
50
+ end
51
+
52
+ # Checks that all given queries return non-empty results.
53
+ #
54
+ # @param driver_dialect [Object] the driver dialect used to execute queries
55
+ # @param connection [Object] the connection to execute queries against
56
+ # @param queries [Array<String>] one or more SQL queries to verify
57
+ # @return [Boolean] true if all queries return results, false otherwise
58
+ def check_existence_queries(driver_dialect, connection, *queries)
59
+ return false unless driver_dialect.respond_to?(:execute)
60
+
61
+ queries.each do |existence_query|
62
+ result = driver_dialect.execute(connection, existence_query)
63
+ return false if result.nil? || result.none?
64
+ end
65
+ true
66
+ rescue StandardError
67
+ false
68
+ end
69
+ end
70
+ end
71
+ end