elasticsearch_record 1.0.2 → 1.1.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.
- checksums.yaml +4 -4
- data/.yardopts +4 -0
- data/Gemfile.lock +10 -14
- data/README.md +180 -27
- data/docs/CHANGELOG.md +36 -18
- data/docs/LICENSE.txt +1 -1
- data/elasticsearch_record.gemspec +42 -0
- data/lib/active_record/connection_adapters/elasticsearch/column.rb +20 -6
- data/lib/active_record/connection_adapters/elasticsearch/database_statements.rb +142 -125
- data/lib/active_record/connection_adapters/elasticsearch/quoting.rb +2 -23
- data/lib/active_record/connection_adapters/elasticsearch/schema_creation.rb +30 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb +103 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb +42 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +158 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb +32 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +132 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb +110 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +136 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +174 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +37 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +110 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +398 -174
- data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +232 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb +2 -0
- data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +32 -0
- data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +112 -19
- data/lib/arel/collectors/elasticsearch_query.rb +0 -1
- data/lib/arel/visitors/elasticsearch.rb +7 -579
- data/lib/arel/visitors/elasticsearch_base.rb +234 -0
- data/lib/arel/visitors/elasticsearch_query.rb +463 -0
- data/lib/arel/visitors/elasticsearch_schema.rb +124 -0
- data/lib/elasticsearch_record/core.rb +44 -10
- data/lib/elasticsearch_record/errors.rb +13 -0
- data/lib/elasticsearch_record/gem_version.rb +6 -2
- data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +27 -9
- data/lib/elasticsearch_record/model_schema.rb +5 -0
- data/lib/elasticsearch_record/persistence.rb +31 -26
- data/lib/elasticsearch_record/query.rb +56 -17
- data/lib/elasticsearch_record/querying.rb +17 -0
- data/lib/elasticsearch_record/relation/calculation_methods.rb +3 -0
- data/lib/elasticsearch_record/relation/core_methods.rb +57 -17
- data/lib/elasticsearch_record/relation/query_clause_tree.rb +38 -1
- data/lib/elasticsearch_record/relation/query_methods.rb +6 -0
- data/lib/elasticsearch_record/relation/result_methods.rb +15 -9
- data/lib/elasticsearch_record/result.rb +32 -5
- data/lib/elasticsearch_record/statement_cache.rb +2 -1
- data/lib/elasticsearch_record.rb +2 -2
- metadata +29 -11
- data/.ruby-version +0 -1
- data/lib/elasticsearch_record/schema_migration.rb +0 -30
@@ -0,0 +1,232 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Elasticsearch
|
6
|
+
# extend adapter with table-related statements
|
7
|
+
module TableStatements
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
# ORIGINAL methods untouched:
|
12
|
+
#
|
13
|
+
# SUPPORTED but not used:
|
14
|
+
#
|
15
|
+
# UNSUPPORTED methods that will be ignored:
|
16
|
+
# - native_database_types
|
17
|
+
# - table_options
|
18
|
+
# - table_comment
|
19
|
+
# - table_alias_for
|
20
|
+
#
|
21
|
+
# UNSUPPORTED methods that will fail:
|
22
|
+
# - create_join_table
|
23
|
+
# - drop_join_table
|
24
|
+
# - create_alter_table
|
25
|
+
# - change_column_default
|
26
|
+
# - change_column_null
|
27
|
+
# - rename_column
|
28
|
+
#
|
29
|
+
# UPCOMING future methods:
|
30
|
+
# - clone (option -> close, or read-only (#lock / unlock) )
|
31
|
+
# - refresh
|
32
|
+
# - rename_table
|
33
|
+
|
34
|
+
define_unsupported_method :rename_table
|
35
|
+
|
36
|
+
# Opens a closed index.
|
37
|
+
# @param [String] table_name
|
38
|
+
# @return [Boolean] acknowledged status
|
39
|
+
def open_table(table_name)
|
40
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
41
|
+
api(:indices, :open, { index: table_name }, 'OPEN TABLE').dig('acknowledged')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Opens closed indices.
|
45
|
+
# @param [Array] table_names
|
46
|
+
# @return [Array] acknowledged status for each provided table
|
47
|
+
def open_tables(*table_names)
|
48
|
+
table_names -= [schema_migration.table_name, InternalMetadata.table_name]
|
49
|
+
return if table_names.empty?
|
50
|
+
|
51
|
+
table_names.map { |table_name| open_table(table_name) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Closes an index.
|
55
|
+
# @param [String] table_name
|
56
|
+
# @return [Boolean] acknowledged status
|
57
|
+
def close_table(table_name)
|
58
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
59
|
+
api(:indices, :close, { index: table_name }, 'CLOSE TABLE').dig('acknowledged')
|
60
|
+
end
|
61
|
+
|
62
|
+
# Closes indices by provided names.
|
63
|
+
# @param [Array] table_names
|
64
|
+
# @return [Array] acknowledged status for each provided table
|
65
|
+
def close_tables(*table_names)
|
66
|
+
table_names -= [schema_migration.table_name, InternalMetadata.table_name]
|
67
|
+
return if table_names.empty?
|
68
|
+
|
69
|
+
table_names.map { |table_name| close_table(table_name) }
|
70
|
+
end
|
71
|
+
|
72
|
+
# truncates index by provided name.
|
73
|
+
# HINT: Elasticsearch does not have a +truncate+ concept:
|
74
|
+
# - so we have to store the current index' schema
|
75
|
+
# - drop the index
|
76
|
+
# - and create it again
|
77
|
+
# @param [String] table_name
|
78
|
+
# @return [Boolean] acknowledged status
|
79
|
+
def truncate_table(table_name)
|
80
|
+
# force: automatically drops an existing index
|
81
|
+
create_table(table_name, force: true, **table_schema(table_name))
|
82
|
+
end
|
83
|
+
|
84
|
+
alias :truncate :truncate_table
|
85
|
+
|
86
|
+
# truncate indices by provided names.
|
87
|
+
# @param [Array] table_names
|
88
|
+
# @return [Array] acknowledged status for each provided table
|
89
|
+
def truncate_tables(*table_names)
|
90
|
+
table_names -= [schema_migration.table_name, InternalMetadata.table_name]
|
91
|
+
return if table_names.empty?
|
92
|
+
|
93
|
+
table_names.map { |table_name| truncate_table(table_name) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# drops an index
|
97
|
+
# [<tt>:if_exists</tt>]
|
98
|
+
# Set to +true+ to only drop the table if it exists.
|
99
|
+
# Defaults to false.
|
100
|
+
# @param [String] table_name
|
101
|
+
# @param [Hash] options
|
102
|
+
# @return [Array] acknowledged status for provided table
|
103
|
+
def drop_table(table_name, **options)
|
104
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
105
|
+
api(:indices, :delete, { index: table_name, ignore: (options[:if_exists] ? 404 : nil) }, 'DROP TABLE').dig('acknowledged')
|
106
|
+
end
|
107
|
+
|
108
|
+
# creates a new table (index).
|
109
|
+
# [<tt>:force</tt>]
|
110
|
+
# Set to +true+ to drop an existing table
|
111
|
+
# Defaults to false.
|
112
|
+
# [<tt>:copy_from</tt>]
|
113
|
+
# Set to an existing index, to copy it's schema.
|
114
|
+
# [<tt>:if_not_exists</tt>]
|
115
|
+
# Set to +true+ to skip creation if table already exists.
|
116
|
+
# Defaults to false.
|
117
|
+
# @param [String] table_name
|
118
|
+
# @param [Boolean] force - force a drop on the existing table (default: false)
|
119
|
+
# @param [nil, String] copy_from - copy schema from existing table
|
120
|
+
# @param [Hash] options
|
121
|
+
# @return [Boolean] acknowledged status
|
122
|
+
def create_table(table_name, force: false, copy_from: nil, if_not_exists: false, **options)
|
123
|
+
return if if_not_exists && table_exists?(table_name)
|
124
|
+
|
125
|
+
# copy schema from existing table
|
126
|
+
options.merge!(table_schema(copy_from)) if copy_from
|
127
|
+
|
128
|
+
# create new definition
|
129
|
+
definition = create_table_definition(table_name, **extract_table_options!(options))
|
130
|
+
|
131
|
+
# yield optional block
|
132
|
+
if block_given?
|
133
|
+
definition.assign do |d|
|
134
|
+
yield d
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# force drop existing table
|
139
|
+
if force
|
140
|
+
drop_table(table_name, if_exists: true)
|
141
|
+
else
|
142
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
143
|
+
end
|
144
|
+
|
145
|
+
# execute definition query(ies)
|
146
|
+
definition.exec!
|
147
|
+
end
|
148
|
+
|
149
|
+
# A block for changing mappings, settings & aliases in +table+.
|
150
|
+
#
|
151
|
+
# # change_table() yields a ChangeTableDefinition instance
|
152
|
+
# change_table(:suppliers) do |t|
|
153
|
+
# t.mapping :name, :string
|
154
|
+
# # Other column alterations here
|
155
|
+
# end
|
156
|
+
def change_table(table_name, **options)
|
157
|
+
definition = update_table_definition(table_name, self, **options)
|
158
|
+
|
159
|
+
# yield optional block
|
160
|
+
if block_given?
|
161
|
+
definition.assign do |d|
|
162
|
+
yield d
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# execute definition query(ies)
|
167
|
+
definition.exec!
|
168
|
+
end
|
169
|
+
|
170
|
+
# -- mapping -------------------------------------------------------------------------------------------------
|
171
|
+
|
172
|
+
def add_mapping(table_name, name, type, **options, &block)
|
173
|
+
_exec_change_table_with(:add_mapping, table_name, name, type, **options, &block)
|
174
|
+
end
|
175
|
+
|
176
|
+
alias :add_column :add_mapping
|
177
|
+
|
178
|
+
def change_mapping(table_name, name, type, **options, &block)
|
179
|
+
_exec_change_table_with(:change_mapping, table_name, name, type, **options, &block)
|
180
|
+
end
|
181
|
+
|
182
|
+
alias :change_column :change_mapping
|
183
|
+
|
184
|
+
def change_mapping_meta(table_name, name, **options)
|
185
|
+
_exec_change_table_with(:change_mapping_meta, table_name, name, **options)
|
186
|
+
end
|
187
|
+
|
188
|
+
def change_mapping_attributes(table_name, name, **options,&block)
|
189
|
+
_exec_change_table_with(:change_mapping_attributes, table_name, name, **options, &block)
|
190
|
+
end
|
191
|
+
alias :change_mapping_attribute :change_mapping_attributes
|
192
|
+
|
193
|
+
# -- setting -------------------------------------------------------------------------------------------------
|
194
|
+
|
195
|
+
def add_setting(table_name, name, value, **options, &block)
|
196
|
+
_exec_change_table_with(:add_setting, table_name, name, value, **options, &block)
|
197
|
+
end
|
198
|
+
|
199
|
+
def change_setting(table_name, name, value, **options, &block)
|
200
|
+
_exec_change_table_with(:change_setting, table_name, name, value, **options, &block)
|
201
|
+
end
|
202
|
+
|
203
|
+
def delete_setting(table_name, name, **options, &block)
|
204
|
+
_exec_change_table_with(:delete_setting, table_name, name, **options, &block)
|
205
|
+
end
|
206
|
+
|
207
|
+
# -- alias ---------------------------------------------------------------------------------------------------
|
208
|
+
|
209
|
+
def add_alias(table_name, name, **options, &block)
|
210
|
+
_exec_change_table_with(:add_alias, table_name, name, **options, &block)
|
211
|
+
end
|
212
|
+
|
213
|
+
def change_alias(table_name, name, **options, &block)
|
214
|
+
_exec_change_table_with(:change_alias, table_name, name, **options, &block)
|
215
|
+
end
|
216
|
+
|
217
|
+
def delete_alias(table_name, name, **options, &block)
|
218
|
+
_exec_change_table_with(:delete_alias, table_name, name, **options, &block)
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def _exec_change_table_with(method, table_name, *args, **kwargs, &block)
|
224
|
+
change_table(table_name) do |t|
|
225
|
+
t.send(method, *args, **kwargs, &block)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Elasticsearch
|
6
|
+
|
7
|
+
class UnsupportedImplementationError < StandardError
|
8
|
+
def initialize(method_name)
|
9
|
+
super "Unsupported implementation of method: #{method_name}."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module UnsupportedImplementation
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
|
16
|
+
class_methods do
|
17
|
+
def define_unsupported_method(*method_names)
|
18
|
+
method_names.each do |method_name|
|
19
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
20
|
+
def #{method_name}(*args)
|
21
|
+
raise NotImplementedError, "'##{method_name}' is originally defined by 'ActiveRecord::ConnectionAdapters' but is not supported by Elasticsearch. Choose a different solution to prevent the execution of this method!"
|
22
|
+
end
|
23
|
+
RUBY
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private :define_unsupported_method
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -2,12 +2,17 @@
|
|
2
2
|
|
3
3
|
require 'active_record/connection_adapters'
|
4
4
|
|
5
|
-
|
5
|
+
require 'active_record/connection_adapters/elasticsearch/unsupported_implementation'
|
6
|
+
|
6
7
|
require 'active_record/connection_adapters/elasticsearch/column'
|
7
8
|
require 'active_record/connection_adapters/elasticsearch/database_statements'
|
8
9
|
require 'active_record/connection_adapters/elasticsearch/quoting'
|
10
|
+
require 'active_record/connection_adapters/elasticsearch/schema_creation'
|
11
|
+
require 'active_record/connection_adapters/elasticsearch/schema_definitions'
|
12
|
+
require 'active_record/connection_adapters/elasticsearch/schema_dumper'
|
9
13
|
require 'active_record/connection_adapters/elasticsearch/schema_statements'
|
10
14
|
require 'active_record/connection_adapters/elasticsearch/type'
|
15
|
+
require 'active_record/connection_adapters/elasticsearch/table_statements'
|
11
16
|
|
12
17
|
require 'arel/visitors/elasticsearch'
|
13
18
|
require 'arel/collectors/elasticsearch_query'
|
@@ -40,15 +45,17 @@ module ActiveRecord # :nodoc:
|
|
40
45
|
|
41
46
|
# defines the Elasticsearch 'base' structure, which is always included but cannot be resolved through mappings ...
|
42
47
|
BASE_STRUCTURE = [
|
43
|
-
{ 'name' => '_id', 'type' => '
|
44
|
-
{ 'name' => '_index', 'type' => '
|
45
|
-
{ 'name' => '_score', 'type' => 'float', '
|
46
|
-
{ 'name' => '_type', 'type' => '
|
48
|
+
{ 'name' => '_id', 'type' => 'keyword', 'virtual' => true, 'meta' => { 'primary_key' => 'true' } },
|
49
|
+
{ 'name' => '_index', 'type' => 'keyword', 'virtual' => true },
|
50
|
+
{ 'name' => '_score', 'type' => 'float', 'virtual' => true },
|
51
|
+
{ 'name' => '_type', 'type' => 'keyword', 'virtual' => true }
|
47
52
|
].freeze
|
48
53
|
|
54
|
+
include Elasticsearch::UnsupportedImplementation
|
49
55
|
include Elasticsearch::Quoting
|
50
|
-
include Elasticsearch::SchemaStatements
|
51
56
|
include Elasticsearch::DatabaseStatements
|
57
|
+
include Elasticsearch::SchemaStatements
|
58
|
+
include Elasticsearch::TableStatements
|
52
59
|
|
53
60
|
class << self
|
54
61
|
def base_structure_keys
|
@@ -58,8 +65,10 @@ module ActiveRecord # :nodoc:
|
|
58
65
|
def new_client(config)
|
59
66
|
# IMPORTANT: remove +adapter+ from config - otherwise we mess up with Faraday::AdapterRegistry
|
60
67
|
client = ::Elasticsearch::Client.new(config.except(:adapter))
|
61
|
-
client.ping
|
68
|
+
client.ping unless config[:ping] == false
|
62
69
|
client
|
70
|
+
rescue ::Elastic::Transport::Transport::Errors::Unauthorized
|
71
|
+
raise ActiveRecord::DatabaseConnectionError.username_error(config[:username])
|
63
72
|
rescue ::Elastic::Transport::Transport::ServerError => error
|
64
73
|
raise ::ActiveRecord::ConnectionNotEstablished, error.message
|
65
74
|
end
|
@@ -123,6 +132,18 @@ module ActiveRecord # :nodoc:
|
|
123
132
|
# reinitialize the constant with new types
|
124
133
|
TYPE_MAP = ActiveRecord::Type::HashLookupTypeMap.new.tap { |m| initialize_type_map(m) }
|
125
134
|
|
135
|
+
# define native types - which will be used for schema-dumping
|
136
|
+
NATIVE_DATABASE_TYPES = {
|
137
|
+
primary_key: { name: 'long' },
|
138
|
+
string: { name: 'keyword' },
|
139
|
+
blob: { name: 'binary' },
|
140
|
+
datetime: { name: 'date' },
|
141
|
+
bigint: { name: 'long' },
|
142
|
+
json: { name: 'object' }
|
143
|
+
}.merge(
|
144
|
+
TYPE_MAP.keys.map { |key| [key.to_sym, { name: key }] }.to_h
|
145
|
+
)
|
146
|
+
|
126
147
|
def initialize(*args)
|
127
148
|
super(*args)
|
128
149
|
|
@@ -131,20 +152,78 @@ module ActiveRecord # :nodoc:
|
|
131
152
|
@prepared_statements = false
|
132
153
|
end
|
133
154
|
|
134
|
-
|
155
|
+
# overwrite method to provide a Elasticsearch path
|
156
|
+
def migrations_paths
|
135
157
|
@config[:migrations_paths] || ['db/migrate_elasticsearch']
|
136
158
|
end
|
137
159
|
|
138
|
-
#
|
139
|
-
|
160
|
+
# Does this adapter support explain?
|
161
|
+
def supports_explain?
|
162
|
+
false
|
163
|
+
end
|
164
|
+
|
165
|
+
# Does this adapter support creating indexes in the same statement as
|
166
|
+
# creating the table?
|
167
|
+
def supports_indexes_in_create?
|
168
|
+
false
|
169
|
+
end
|
170
|
+
|
171
|
+
# Does this adapter support metadata comments on database objects (tables)?
|
172
|
+
# PLEASE NOTE: Elasticsearch does only support comments on mappings as 'meta' information.
|
173
|
+
# This method only relies to create comments on tables (indices) and is therefore not supported.
|
174
|
+
# see @ ActiveRecord::ConnectionAdapters::SchemaStatements#create_table
|
175
|
+
def supports_comments?
|
176
|
+
false
|
177
|
+
end
|
178
|
+
|
179
|
+
# Can comments for tables, columns, and indexes be specified in create/alter table statements?
|
180
|
+
# see @ ActiveRecord::ConnectionAdapters::ElasticsearchAdapter#supports_comments?
|
181
|
+
def supports_comments_in_create?
|
182
|
+
false
|
183
|
+
end
|
184
|
+
|
185
|
+
# disable metadata tables
|
140
186
|
def use_metadata_table? # :nodoc:
|
141
187
|
false
|
142
188
|
end
|
143
189
|
|
144
|
-
#
|
145
|
-
#
|
146
|
-
def
|
147
|
-
|
190
|
+
# returns a hash of 'ActiveRecord types' -> 'Elasticsearch types' (defined @ +NATIVE_DATABASE_TYPES+)
|
191
|
+
# @return [Hash]
|
192
|
+
def native_database_types # :nodoc:
|
193
|
+
NATIVE_DATABASE_TYPES
|
194
|
+
end
|
195
|
+
|
196
|
+
# calls the +elasticsearch-api+ endpoints by provided namespace and action.
|
197
|
+
# if a block was provided it'll yield the response.body and returns the blocks result.
|
198
|
+
# otherwise it will return the response itself...
|
199
|
+
# @param [Symbol] namespace - the API namespace (e.g. indices, nodes, sql, ...)
|
200
|
+
# @param [Symbol] action - the API action to call in tha namespace
|
201
|
+
# @param [Hash] arguments - action arguments
|
202
|
+
# @param [String (frozen)] name - the logging name
|
203
|
+
# @param [Boolean] async - send async (default: false) - currently not supported
|
204
|
+
# @return [Elasticsearch::API::Response, Object]
|
205
|
+
def api(namespace, action, arguments = {}, name = 'API', async: false)
|
206
|
+
raise ::StandardError, 'ASYNC api calls are not supported' if async
|
207
|
+
|
208
|
+
# resolve the API target
|
209
|
+
target = namespace == :core ? @connection : @connection.__send__(namespace)
|
210
|
+
|
211
|
+
log("#{namespace}.#{action}", arguments, name, async: async) do
|
212
|
+
response = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
213
|
+
target.__send__(action, arguments)
|
214
|
+
end
|
215
|
+
|
216
|
+
if response.is_a?(::Elasticsearch::API::Response)
|
217
|
+
# reverse information for the LogSubscriber - shows the 'query-time' in the logs
|
218
|
+
# this works, since we use a referenced hash ...
|
219
|
+
arguments[:_qt] = response['took']
|
220
|
+
|
221
|
+
# raise timeouts
|
222
|
+
raise(ActiveRecord::StatementTimeout, "Elasticsearch api request failed due a timeout") if response['timed_out']
|
223
|
+
end
|
224
|
+
|
225
|
+
response
|
226
|
+
end
|
148
227
|
end
|
149
228
|
|
150
229
|
private
|
@@ -156,7 +235,22 @@ module ActiveRecord # :nodoc:
|
|
156
235
|
# catch Elasticsearch Transport-errors to be treated as +StatementInvalid+ (the original message is still readable ...)
|
157
236
|
def translate_exception(exception, message:, sql:, binds:)
|
158
237
|
case exception
|
159
|
-
when Elastic::Transport::Transport::
|
238
|
+
when ::Elastic::Transport::Transport::Errors::ClientClosedRequest
|
239
|
+
::ActiveRecord::QueryCanceled.new(message, sql: sql, binds: binds)
|
240
|
+
when ::Elastic::Transport::Transport::Errors::RequestTimeout
|
241
|
+
::ActiveRecord::StatementTimeout.new(message, sql: sql, binds: binds)
|
242
|
+
when ::Elastic::Transport::Transport::Errors::Conflict
|
243
|
+
::ActiveRecord::RecordNotUnique.new(message, sql: sql, binds: binds)
|
244
|
+
when ::Elastic::Transport::Transport::Errors::BadRequest
|
245
|
+
if exception.message.match?(/resource_already_exists_exception/)
|
246
|
+
::ActiveRecord::DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
|
247
|
+
else
|
248
|
+
::ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
249
|
+
end
|
250
|
+
when ::Elastic::Transport::Transport::Errors::Unauthorized
|
251
|
+
::ActiveRecord::DatabaseConnectionError.username_error(@config[:username])
|
252
|
+
# must be last 'Elastic' error
|
253
|
+
when ::Elastic::Transport::Transport::ServerError
|
160
254
|
::ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
161
255
|
else
|
162
256
|
# just forward the exception ...
|
@@ -181,10 +275,10 @@ module ActiveRecord # :nodoc:
|
|
181
275
|
# returns a new collector for the Arel visitor.
|
182
276
|
# @return [Arel::Collectors::ElasticsearchQuery]
|
183
277
|
def collector
|
184
|
-
# IMPORTANT:
|
185
|
-
# we don't have to check for +prepared_statements+ here.
|
278
|
+
# IMPORTANT: prepared statements doesn't make sense for elasticsearch,
|
279
|
+
# so we don't have to check for +prepared_statements+ here.
|
186
280
|
# Also, bindings are (currently) not supported.
|
187
|
-
# So, we just need a query collector...
|
281
|
+
# So, we just need a single, simple query collector...
|
188
282
|
Arel::Collectors::ElasticsearchQuery.new
|
189
283
|
end
|
190
284
|
|
@@ -195,7 +289,6 @@ module ActiveRecord # :nodoc:
|
|
195
289
|
end
|
196
290
|
|
197
291
|
# Builds the result object.
|
198
|
-
#
|
199
292
|
# This is an internal hook to make possible connection adapters to build
|
200
293
|
# custom result objects with response-specific data.
|
201
294
|
# @return [ElasticsearchRecord::Result]
|