orientdb_client 0.0.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 +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/Rakefile +30 -0
- data/lib/orientdb_client.rb +378 -0
- data/lib/orientdb_client/class_configurator.rb +10 -0
- data/lib/orientdb_client/errors.rb +35 -0
- data/lib/orientdb_client/http_adapters.rb +25 -0
- data/lib/orientdb_client/http_adapters/curb_adapter.rb +35 -0
- data/lib/orientdb_client/http_adapters/typhoeus_adapter.rb +53 -0
- data/lib/orientdb_client/test.rb +9 -0
- data/lib/orientdb_client/version.rb +3 -0
- data/orientdb_client.gemspec +31 -0
- data/spec/curb_adapter_spec.rb +8 -0
- data/spec/orientdb_client_spec.rb +703 -0
- data/spec/spec_helper.rb +111 -0
- data/spec/support/shared_examples_for_http_adapter.rb +67 -0
- data/spec/typhoeus_adapter_spec.rb +8 -0
- metadata +196 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aeff7a5103216c207de656f5dd0addb641d2265a
|
4
|
+
data.tar.gz: 54538b3766d81b1f42d244909b302a9789d71a67
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b7338004884c5dac72cbee3816ab4e1865c1a30f4389270f081e62a055f0d951b35845e8cdebfabfa6d18fcbf9ebd13b543e2c158043ac2335854db142eb63b7
|
7
|
+
data.tar.gz: bd0fd3eebb9028e72e9de1857eeff9e4c73b826153f291b39746f97acd73bd9dff60838910def0381478549480b77eec31da3817b2b01a5b43bf9c2f68e8b919
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Luke Rodgers
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# OrientdbClient
|
2
|
+
|
3
|
+
Ruby client for Orientdb. Probably not quite ready for production yet.
|
4
|
+
Inspired by https://github.com/veny/orientdb4r
|
5
|
+
|
6
|
+
Goals:
|
7
|
+
|
8
|
+
* speed (as much as possible with ruby)
|
9
|
+
* fine-grained handling of Orientdb errors, via rich set of ruby exceptions
|
10
|
+
|
11
|
+
Tested on:
|
12
|
+
* 2.1.5
|
13
|
+
* 2.0.6 - specs may fail due to Orientdb bug with deleting database (https://github.com/orientechnologies/orientdb/issues/3746)
|
14
|
+
* 2.0.4
|
15
|
+
* 2.0.2
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
gem 'orientdb_client'
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
$ gem install orientdb_client
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
# basic usage
|
35
|
+
my_client = OrientdbClient.client
|
36
|
+
# connect to default Orientdb database
|
37
|
+
my_client.connect(username: 'root', password: 'YOURPASSWORD', db: 'GratefulDeadConcerts')
|
38
|
+
my_client.query('select * from V')
|
39
|
+
|
40
|
+
# create database
|
41
|
+
my_client.create_database('new_db', 'plocal', 'graph')
|
42
|
+
|
43
|
+
# use a different logger
|
44
|
+
class MyLogger
|
45
|
+
def info(message)
|
46
|
+
puts "my message: #{message}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
Orientdb::logger = MyLogger.new
|
50
|
+
|
51
|
+
# use a different HttpAdapter
|
52
|
+
require 'orientdb_client'
|
53
|
+
require 'orientdb_client/http_adapters/curb_adapter'
|
54
|
+
client = OrientdbClient.cient(adapter: 'CurbAdapter')
|
55
|
+
```
|
56
|
+
|
57
|
+
## HTTP Adapters
|
58
|
+
|
59
|
+
OrientdbClient currently supports Typhoeus and Curb HTTP adapters.
|
60
|
+
|
61
|
+
Benchmarks:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
#tc is typhoeus client, cc is curb client
|
65
|
+
|
66
|
+
require 'benchmark'
|
67
|
+
Benchmark.bmbm do |x|
|
68
|
+
x.report('typhoeus') { 100.times { tc.query('select * from V') } }
|
69
|
+
x.report('curb') { 100.times { cc.query('select * from V') } }
|
70
|
+
end
|
71
|
+
Rehearsal --------------------------------------------
|
72
|
+
typhoeus 0.100000 0.010000 0.110000 ( 0.392666)
|
73
|
+
curb 0.060000 0.000000 0.060000 ( 0.347496)
|
74
|
+
----------------------------------- total: 0.170000sec
|
75
|
+
|
76
|
+
user system total real
|
77
|
+
typhoeus 0.100000 0.010000 0.110000 ( 0.387320)
|
78
|
+
curb 0.060000 0.010000 0.070000 ( 0.331764)
|
79
|
+
```
|
80
|
+
|
81
|
+
## Development
|
82
|
+
|
83
|
+
Launch pry session with the gem: `rake console`, in pry use `reload!` to reload all gem files.
|
84
|
+
|
85
|
+
Run tests: `rake db:test:create` (consult `test.rb` for information on customizing auth credentials via env variables).
|
86
|
+
|
87
|
+
Turn on/off rudimentary debug mode with `client.debug = true/false`.
|
88
|
+
|
89
|
+
## Contributing
|
90
|
+
|
91
|
+
1. Fork it ( https://github.com/[my-github-username]/orientdb_client/fork )
|
92
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
93
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
94
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
95
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'orientdb_client'
|
3
|
+
require 'orientdb_client/test'
|
4
|
+
|
5
|
+
task :console do
|
6
|
+
require 'pry'
|
7
|
+
require 'orientdb_client'
|
8
|
+
|
9
|
+
def reload!
|
10
|
+
files = $LOADED_FEATURES.select { |feat| feat =~ /\/orientdb_client\// }
|
11
|
+
files.each { |file| load file }
|
12
|
+
end
|
13
|
+
|
14
|
+
ARGV.clear
|
15
|
+
Pry.start
|
16
|
+
end
|
17
|
+
|
18
|
+
namespace :db do
|
19
|
+
namespace :test do
|
20
|
+
task :create do
|
21
|
+
client = OrientdbClient.client
|
22
|
+
db = OrientdbClient::Test::DatabaseName
|
23
|
+
username = OrientdbClient::Test::Username
|
24
|
+
password = OrientdbClient::Test::Password
|
25
|
+
if !client.database_exists?(db)
|
26
|
+
client.create_database(db, 'plocal', 'graph', username: username, password: password)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,378 @@
|
|
1
|
+
require "orientdb_client/version"
|
2
|
+
require "orientdb_client/errors"
|
3
|
+
require "orientdb_client/http_adapters"
|
4
|
+
require "orientdb_client/http_adapters/typhoeus_adapter"
|
5
|
+
require "orientdb_client/class_configurator"
|
6
|
+
|
7
|
+
require 'oj'
|
8
|
+
require 'cgi'
|
9
|
+
require 'logger'
|
10
|
+
require 'rainbow'
|
11
|
+
|
12
|
+
module OrientdbClient
|
13
|
+
class << self
|
14
|
+
def client(options = {})
|
15
|
+
Client.new(options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
DATABASE_TYPES = ['document', 'graph']
|
20
|
+
|
21
|
+
class Client
|
22
|
+
attr_reader :http_client
|
23
|
+
attr_accessor :logger
|
24
|
+
|
25
|
+
def initialize(options)
|
26
|
+
options = {
|
27
|
+
host: 'localhost',
|
28
|
+
port: '2480'
|
29
|
+
}.merge(options)
|
30
|
+
@host = options[:host]
|
31
|
+
@port = options[:port]
|
32
|
+
adapter_klass = if options[:adapter]
|
33
|
+
HttpAdapters.const_get(options[:adapter])
|
34
|
+
else
|
35
|
+
HttpAdapters::TyphoeusAdapter
|
36
|
+
end
|
37
|
+
@http_client = adapter_klass.new
|
38
|
+
@node = Node.new(host: @host, port: @port, http_client: @http_client, client: self)
|
39
|
+
@connected = false
|
40
|
+
@logger = Logger.new(STDOUT)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def connect(username:, password:, db:)
|
45
|
+
raise ClientError.new('Already connected') if connected?
|
46
|
+
@username = username
|
47
|
+
@password = password
|
48
|
+
@db = db
|
49
|
+
@http_client.username = @username
|
50
|
+
@http_client.password = @password
|
51
|
+
@node.connect(@db)
|
52
|
+
end
|
53
|
+
|
54
|
+
def disconnect
|
55
|
+
raise ClientError.new('Not connected') unless connected?
|
56
|
+
@username = nil
|
57
|
+
@password = nil
|
58
|
+
@db = nil
|
59
|
+
@http_client.reset_credentials
|
60
|
+
@node.disconnect
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_database(name, storage, type, options = {})
|
64
|
+
raise ArgumentError, "Invalid database type: #{type}" unless DATABASE_TYPES.include?(type)
|
65
|
+
@node.create_database(name, storage, type, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def delete_database(name, options = {})
|
69
|
+
@node.delete_database(name, options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_class(name, options = {})
|
73
|
+
response = @node.create_class(name, options)
|
74
|
+
if block_given?
|
75
|
+
yield ClassConfigurator.new(name, @node)
|
76
|
+
end
|
77
|
+
response
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_property(class_name, property_name, type, options = {})
|
81
|
+
@node.create_property(class_name, property_name, type, options)
|
82
|
+
end
|
83
|
+
|
84
|
+
def alter_property(class_name, property_name, field, value)
|
85
|
+
@node.alter_property(class_name, property_name, field, value)
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_class(name)
|
89
|
+
@node.get_class(name)
|
90
|
+
end
|
91
|
+
|
92
|
+
def has_class?(name)
|
93
|
+
@node.has_class?(name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def drop_class(name)
|
97
|
+
@node.drop_class(name)
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_database(name, options = {})
|
101
|
+
@node.get_database(name, options)
|
102
|
+
end
|
103
|
+
|
104
|
+
def database_exists?(name)
|
105
|
+
list_databases.include?(name)
|
106
|
+
end
|
107
|
+
|
108
|
+
def list_databases
|
109
|
+
@node.list_databases
|
110
|
+
end
|
111
|
+
|
112
|
+
def query(sql, options = {})
|
113
|
+
@node.query(sql, options)
|
114
|
+
end
|
115
|
+
|
116
|
+
def query_unparsed(sql, options = {})
|
117
|
+
@node.query_unparsed(sql, options)
|
118
|
+
end
|
119
|
+
|
120
|
+
def command(sql)
|
121
|
+
@node.command(sql)
|
122
|
+
end
|
123
|
+
|
124
|
+
def connected?
|
125
|
+
@node.connected?
|
126
|
+
end
|
127
|
+
|
128
|
+
def database
|
129
|
+
@node.database
|
130
|
+
end
|
131
|
+
|
132
|
+
def debug=(val)
|
133
|
+
@node.debug = val
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class Node
|
138
|
+
|
139
|
+
attr_reader :database
|
140
|
+
attr_writer :debug
|
141
|
+
|
142
|
+
def initialize(host:, port:, http_client: http_client, client: client)
|
143
|
+
@host = host
|
144
|
+
@port = port
|
145
|
+
@http_client = http_client
|
146
|
+
@client = client
|
147
|
+
@connected = false
|
148
|
+
@database = nil
|
149
|
+
@debug = false
|
150
|
+
end
|
151
|
+
|
152
|
+
def connect(database)
|
153
|
+
request(:get, "connect/#{database}")
|
154
|
+
@connected = true
|
155
|
+
@database = database
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
159
|
+
def disconnect
|
160
|
+
request(:get, 'disconnect') rescue UnauthorizedError
|
161
|
+
@connected = false
|
162
|
+
true
|
163
|
+
end
|
164
|
+
|
165
|
+
def create_database(name, storage, type, options)
|
166
|
+
r = request(:post, "database/#{name}/#{storage}/#{type}", options)
|
167
|
+
parse_response(r)
|
168
|
+
end
|
169
|
+
|
170
|
+
def delete_database(name, options)
|
171
|
+
r = request(:delete, "database/#{name}", options)
|
172
|
+
parse_response(r)
|
173
|
+
end
|
174
|
+
|
175
|
+
def get_database(name, options)
|
176
|
+
r = request(:get, "database/#{name}", options)
|
177
|
+
r = parse_response(r)
|
178
|
+
rescue UnauthorizedError => e
|
179
|
+
# Attempt to get not-found db, when connected, will return 401 error.
|
180
|
+
if connected?
|
181
|
+
raise NotFoundError.new("Database #{name} not found, or you are not authorized to access it.", 401)
|
182
|
+
else
|
183
|
+
raise e
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def list_databases
|
188
|
+
r = request(:get, 'listDatabases')
|
189
|
+
parse_response(r)['databases']
|
190
|
+
end
|
191
|
+
|
192
|
+
def create_class(name, options)
|
193
|
+
sql = "CREATE CLASS #{name}"
|
194
|
+
sql << " EXTENDS #{options[:extends]}" if options.key?(:extends)
|
195
|
+
sql << " CLUSTER #{options[:cluster]}" if options.key?(:cluster)
|
196
|
+
sql << ' ABSTRACT' if options.key?(:abstract)
|
197
|
+
command(sql)
|
198
|
+
end
|
199
|
+
|
200
|
+
def drop_class(name)
|
201
|
+
command("DROP CLASS #{name}")
|
202
|
+
end
|
203
|
+
|
204
|
+
def create_property(class_name, property_name, type, options)
|
205
|
+
command("CREATE PROPERTY #{class_name}.#{property_name} #{type}")
|
206
|
+
options.each do |k, v|
|
207
|
+
alter_property(class_name, property_name, k, v)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def alter_property(class_name, property_name, field, value)
|
212
|
+
command("ALTER PROPERTY #{class_name}.#{property_name} #{field} #{value}")
|
213
|
+
end
|
214
|
+
|
215
|
+
def query(sql, options)
|
216
|
+
parse_response(query_unparsed(sql, options))['result']
|
217
|
+
end
|
218
|
+
|
219
|
+
def query_unparsed(sql, options)
|
220
|
+
limit = limit_string(options)
|
221
|
+
request(:get, "query/#{@database}/sql/#{CGI::escape(sql)}#{limit}")
|
222
|
+
rescue NegativeArraySizeException
|
223
|
+
raise NotFoundError
|
224
|
+
end
|
225
|
+
|
226
|
+
def command(sql)
|
227
|
+
r = request(:post, "command/#{@database}/sql/#{CGI::escape(sql)}")
|
228
|
+
parse_response(r)
|
229
|
+
end
|
230
|
+
|
231
|
+
def get_class(name)
|
232
|
+
r = request(:get, "class/#{@database}/#{name}")
|
233
|
+
parse_response(r)
|
234
|
+
rescue IllegalArgumentException
|
235
|
+
raise NotFoundError
|
236
|
+
end
|
237
|
+
|
238
|
+
def has_class?(name)
|
239
|
+
if get_class(name)
|
240
|
+
return true
|
241
|
+
end
|
242
|
+
rescue NotFoundError
|
243
|
+
return false
|
244
|
+
end
|
245
|
+
|
246
|
+
def connected?
|
247
|
+
@connected == true
|
248
|
+
end
|
249
|
+
|
250
|
+
private
|
251
|
+
|
252
|
+
def request(method, path, options = {})
|
253
|
+
url = build_url(path)
|
254
|
+
t1 = Time.now
|
255
|
+
response = @http_client.request(method, url, options)
|
256
|
+
time = Time.now - t1
|
257
|
+
r = handle_response(response)
|
258
|
+
info("request (#{time}), #{response.response_code}: #{method} #{url}")
|
259
|
+
r
|
260
|
+
end
|
261
|
+
|
262
|
+
def build_url(path)
|
263
|
+
"http://#{@host}:#{@port}/#{path}"
|
264
|
+
end
|
265
|
+
|
266
|
+
def handle_response(response)
|
267
|
+
return response if @debug
|
268
|
+
case response.response_code
|
269
|
+
when 0
|
270
|
+
raise ConnectionError.new("No server at #{@host}:#{@port}", 0, nil)
|
271
|
+
when 200, 201, 204
|
272
|
+
return response
|
273
|
+
when 401
|
274
|
+
raise UnauthorizedError.new('Unauthorized', response.response_code, response.body)
|
275
|
+
when 404
|
276
|
+
raise NotFoundError.new('Not found', response.response_code, response.body)
|
277
|
+
when 409
|
278
|
+
translate_error(response)
|
279
|
+
when 500
|
280
|
+
translate_error(response)
|
281
|
+
else
|
282
|
+
raise ServerError.new("Unexpected HTTP status code: #{response.response_code}", response.response_code, response.body)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def parse_response(response)
|
287
|
+
return nil if response.body.empty?
|
288
|
+
@debug ? response : Oj.load(response.body)
|
289
|
+
end
|
290
|
+
|
291
|
+
def limit_string(options)
|
292
|
+
options[:limit] ? "/#{options[:limit]}" : ''
|
293
|
+
end
|
294
|
+
|
295
|
+
def translate_error(response)
|
296
|
+
odb_error_class, odb_error_message = if response.content_type.start_with?('application/json')
|
297
|
+
extract_odb_error_from_json(response)
|
298
|
+
else
|
299
|
+
extract_odb_error_from_text(response)
|
300
|
+
end
|
301
|
+
code = response.response_code
|
302
|
+
body = response.body
|
303
|
+
case odb_error_class
|
304
|
+
when /OCommandSQLParsingException/
|
305
|
+
raise ClientError.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
306
|
+
when /OQueryParsingException/
|
307
|
+
raise ClientError.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
308
|
+
when /OCommandExecutorNotFoundException/
|
309
|
+
raise ClientError.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
310
|
+
when /IllegalArgumentException/
|
311
|
+
raise IllegalArgumentException.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
312
|
+
when /OConfigurationException/
|
313
|
+
raise ClientError.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
314
|
+
when /OCommandExecutionException/
|
315
|
+
raise CommandExecutionException.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
316
|
+
when /OSchemaException/
|
317
|
+
raise ClientError.new("#{odb_error_class}: #{odb_error_message}", code, body)
|
318
|
+
when /OConcurrentModification/
|
319
|
+
raise MVCCError.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
320
|
+
when /IllegalStateException/
|
321
|
+
raise ServerError.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
322
|
+
when /ORecordDuplicate/
|
323
|
+
raise DuplicateRecordError.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
324
|
+
when /OTransactionException/
|
325
|
+
if odb_error_message.match(/ORecordDuplicate/)
|
326
|
+
raise DistributedDuplicateRecordError.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
327
|
+
elsif odb_error_message.match(/distributed/)
|
328
|
+
raise DistributedTransactionException.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
329
|
+
else
|
330
|
+
raise TransactionException.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
331
|
+
end
|
332
|
+
when /ODatabaseException/
|
333
|
+
if odb_error_message.match(/already exists/)
|
334
|
+
klass = ConflictError
|
335
|
+
else
|
336
|
+
klass = ServerError
|
337
|
+
end
|
338
|
+
raise klass.new("#{odb_error_class}: #{odb_error_message}", response.response_code, response.body)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
def extract_odb_error_from_json(response)
|
343
|
+
body = response.body
|
344
|
+
json = Oj.load(body)
|
345
|
+
# odb > 2.1 (?) errors are in JSON format
|
346
|
+
matches = json['errors'].first['content'].match(/\A([^:]+):\s?(.+)/m)
|
347
|
+
[matches[1], matches[2]]
|
348
|
+
rescue => e
|
349
|
+
if (response.body.match(/Database.*already exists/))
|
350
|
+
raise ConflictError.new(e.message, response.response_code, response.body)
|
351
|
+
elsif (response.body.match(/NegativeArraySizeException/))
|
352
|
+
raise NegativeArraySizeException.new(e.message, response.response_code, response.body)
|
353
|
+
else
|
354
|
+
raise OrientdbError.new("Could not parse Orientdb server error", response.response_code, response.body)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def extract_odb_error_from_text(response)
|
359
|
+
body = response.body
|
360
|
+
matches = body.match(/\A([^:]+):\s(.*)$/)
|
361
|
+
[matches[1], matches[2]]
|
362
|
+
rescue => e
|
363
|
+
if (response.body.match(/Database.*already exists/))
|
364
|
+
raise ConflictError.new(e.message, response.response_code, response.body)
|
365
|
+
elsif (response.body.match(/NegativeArraySizeException/))
|
366
|
+
raise NegativeArraySizeException.new(e.message, response.response_code, response.body)
|
367
|
+
else
|
368
|
+
raise OrientdbError.new("Could not parse Orientdb server error", response.response_code, response.body)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def info(message)
|
373
|
+
wrapped_message = "#{Rainbow('OrientdbClient:').yellow} #{message}"
|
374
|
+
@client.logger.info(wrapped_message)
|
375
|
+
end
|
376
|
+
|
377
|
+
end
|
378
|
+
end
|