active-orient 0.79 → 0.80

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,7 +12,10 @@ module RestDelete
12
12
  old_ds = ActiveOrient.database
13
13
  change_database database
14
14
  begin
15
- response = @res["/database/#{ActiveOrient.database}"].delete
15
+ response = nil
16
+ ActiveOrient.db_pool.checkout do | conn |
17
+ response = conn["/database/#{ActiveOrient.database}"].delete
18
+ end
16
19
  if database == old_ds
17
20
  change_database 'temp'
18
21
  logger.info{"Working database deleted, switched to temp"}
@@ -30,77 +33,93 @@ module RestDelete
30
33
  ######### CLASS ##########
31
34
 
32
35
  =begin
33
- Deletes the specified class and returns true on success
34
- todo: remove all instances of the class
35
- =end
36
+ Deletes the specified class and returns true on success
36
37
 
37
- def delete_class o_class
38
- cl = classname(o_class)
39
- return if cl.nil?
40
- logger.progname = 'RestDelete#DeleteClass'
38
+ The class-entries in ActiveOrient.database_classes and ORD.database_classes are removed.
39
+
40
+ The Ruby-Class itself is untouched.
41
+ However, any furter operation leads to an Error.
41
42
 
42
- begin
43
- ## to do: if cl contains special characters, enclose with backticks
44
- response = @res["/class/#{ActiveOrient.database}/#{cl}"].delete
45
- if response.code == 204
46
- logger.info{"Class #{cl} deleted."}
47
- ActiveOrient.database_classes.delete(cl)
48
- end
49
- rescue RestClient::InternalServerError => e
50
- sentence= JSON.parse( e.response)['errors'].last['content']
51
- if ActiveOrient.database_classes.has_key? cl
52
- logger.error{"Class #{cl} still present."}
53
- logger.error{ sentence }
54
- false
55
- else
56
- logger.error{e.inspect}
57
- true
58
- end
59
- rescue Exception => e
60
- logger.error{e.message}
61
- logger.error{e.inspect}
62
- end
63
- end
43
+ todo: remove all instances of the class
44
+ =end
45
+
46
+ def delete_class o_class
47
+ cl = classname(o_class).to_s
48
+ return if cl.nil?
49
+ logger.progname = 'RestDelete#DeleteClass'
50
+
51
+ begin
52
+ ## to do: if cl contains special characters, enclose with backticks
53
+ response = nil
54
+ ActiveOrient.db_pool.checkout do | conn |
55
+ response = conn["/class/#{ActiveOrient.database}/#{cl}"].delete
56
+ end
57
+ if response.code == 204
58
+ logger.info{"Class #{cl} deleted."}
59
+
60
+ ActiveOrient.database_classes.delete(cl)
61
+ end
62
+ rescue RestClient::InternalServerError => e
63
+ sentence= JSON.parse( e.response)['errors'].last['content']
64
+ if ActiveOrient.database_classes.has_key? cl
65
+ logger.error{"Class #{cl} still present."}
66
+ logger.error{ sentence }
67
+ false
68
+ else
69
+ logger.error{e.inspect}
70
+ true
71
+ end
72
+ rescue Exception => e
73
+ logger.error{e.message}
74
+ logger.error{e.inspect}
75
+ end
76
+ end
64
77
 
65
78
  ############## RECORD #############
66
79
 
67
80
  =begin
68
81
  Deletes a single Record when providing a single rid-link (#00:00) or a record
82
+
69
83
  Deletes multible Records when providing a list of rid-links or a record
70
- Todo: implement delete_edges after querying the database in one statement
84
+
85
+ Todo: implement delete_edges after querying the database in one statement
71
86
 
72
87
  Example:
73
- record = Vertex.create_document attributes: { something: 'something' }
74
- Vertex.delete_record record
88
+ V.create_class :test
89
+ record = Test.new something: 'something'
90
+ V.db.delete_record record
75
91
 
76
- records= (1..100).map{|x| Vertex.create_document attributes: { something: x } }
77
- Vertex.delete_record *records
92
+ records= (1..100).map{|x| Test.create something: x }
93
+ V.db.delete_record *records
78
94
 
79
95
  delete_records provides the removal of datasets after quering the database.
80
96
  =end
81
97
 
82
- def delete_record *rid
98
+ def delete_record *o
83
99
  logger.progname = "ActiveOrient::RestDelete#DeleteRecord"
84
- ridvec= rid.map( &:to_orient).flatten
85
- unless ridvec.empty?
86
- ridvec.map do |rid|
87
- begin
88
- ActiveOrient::Base.remove_rid( ActiveOrient::Base.get_rid(rid) )
89
- @res["/document/#{ActiveOrient.database}/#{rid[1..-1]}"].delete
90
- rescue RestClient::InternalServerError => e
91
- logger.error{"Record #{rid} NOT deleted"}
92
- rescue RestClient::ResourceNotFound
93
- logger.error{"Record #{rid} does not exist in the database"}
94
- else
95
- logger.info{"Record #{rid} deleted"}
96
- end
97
- end
98
- else
99
- logger.info{"No record deleted."}
100
- return nil
101
- end
102
- end
103
- alias delete_document delete_record
100
+ #o.map( &:to_orient ).map do |r|
101
+ o.orient_flatten.map do |r|
102
+ rr = r.to_human
103
+ begin
104
+ ActiveOrient::Base.remove_rid r
105
+ # rest_resource["/document/#{ActiveOrient.database}/#{r[1..-1].to_or}"].delete
106
+ ActiveOrient.db_pool.checkout do | conn |
107
+ conn["/document/#{ActiveOrient.database}/#{r.rid}"].delete
108
+ end
109
+
110
+ rescue RestClient::InternalServerError => e
111
+ logger.error{"Record #{rr} NOT deleted"}
112
+ rescue RestClient::ResourceNotFound
113
+ logger.error{"Record #{rr} does not exist in the database"}
114
+ rescue RestClient::BadRequest => e
115
+ logger.error{"tried to delete #{rr}, but something went wrong"}
116
+ raise
117
+ else
118
+ logger.info{"Record #{rr} deleted"}
119
+ end
120
+ end
121
+ end
122
+ alias delete_document delete_record
104
123
 
105
124
  =begin
106
125
  Deletes records. They are defined by a query. All records which match the attributes are deleted.
@@ -109,12 +128,7 @@ module RestDelete
109
128
 
110
129
  def delete_records o_class, where: {}
111
130
  logger.progname = 'RestDelete#DeleteRecords'
112
- records_to_delete = get_records(from: o_class, where: where)
113
- if records_to_delete.empty?
114
- logger.info{"No record found"}
115
- else
116
- delete_record records_to_delete
117
- end
131
+ get_records(from: o_class, where: where).each{|y| delete_record y}
118
132
  end
119
133
  alias delete_documents delete_records
120
134
 
@@ -123,8 +137,10 @@ module RestDelete
123
137
  def delete_property o_class, field
124
138
  logger.progname = 'RestDelete#DeleteProperty'
125
139
  begin
126
- response = @res["/property/#{ActiveOrient.database}/#{classname(o_class)}/#{field}"].delete
127
- true if response.code == 204
140
+ response = ActiveOrient.db_pool.checkout do | conn |
141
+ r = conn["/property/#{ActiveOrient.database}/#{classname(o_class)}/#{field}"].delete
142
+ true if r.code == 204
143
+ end
128
144
  rescue RestClient::InternalServerError => e
129
145
  logger.error{"Property #{field} in class #{classname(o_class)} NOT deleted" }
130
146
  false
@@ -7,7 +7,8 @@ module RestOperations
7
7
  # puts "uri:#{function_uri { args.join('/') } }"
8
8
  begin
9
9
  term = args.join('/')
10
- @res["/function/#{@database}/#{term}"].post ''
10
+ rest_resource = Thread.current['resource'] || get_resource
11
+ rest_resource["/function/#{@database}/#{term}"].post ''
11
12
  rescue RestClient::InternalServerError => e
12
13
  puts JSON.parse(e.http_body)
13
14
  end
@@ -19,7 +20,7 @@ module RestOperations
19
20
  def count **args
20
21
  logger.progname = 'RestOperations#CountRecords'
21
22
  query = OrientSupport::OrientQuery.new args
22
- query.projection << 'COUNT(*)'
23
+ query.projection 'COUNT(*)'
23
24
  result = get_records raw: true, query: query
24
25
  result.first["COUNT(*)"] rescue 0 # return_value
25
26
  end
@@ -98,56 +99,82 @@ Multible statements are transmitted at once if the Block provides an Array of st
98
99
 
99
100
  =end
100
101
 
101
- def read_transaction
102
- @transaction
103
- end
104
- def execute transaction: false, tolerated_error_code: nil, process_error: true, raw: nil
102
+ def read_transaction
103
+ @transaction
104
+ end
105
+
106
+ def manage_transaction kind, command
105
107
  @transaction = [] unless @transaction.is_a?(Array)
106
- if block_given?
107
- command = yield
108
- command.is_a?(Array) ? command.each{|c| @transaction << c} : @transaction << command
109
- else
110
- logger.error { "No Block provided to execute" }
111
- return nil
112
- end
113
108
 
114
- # puts "transaction #{@transaction.inspect}"
115
- unless transaction == :prepare
109
+ # in any case: add statement to array
110
+ command.is_a?(Array) ? command.each{|c| @transaction << c} : @transaction << command
111
+
112
+ # if kind is prepare, we a done.
113
+ # now, combine anything
114
+ unless kind == :prepare
116
115
  commands = @transaction.map{|y| y if y.is_a? String }.compact
117
116
  @transaction.delete_if{|y| y if y.is_a?(String)}
118
117
  #puts "tn #{commands.inspect}"
119
- return nil if commands.empty?
120
- if commands.size >1
121
- @transaction << { type: 'script', language: 'sql', script: commands }
122
- elsif transaction == false
123
- @transaction = commands.first
124
- else
125
- transaction = true
126
- @transaction << { type: 'cmd', language: 'sql', command: commands.first }
127
- end
128
- _execute transaction, tolerated_error_code, process_error, raw
118
+ @transaction << { type: 'script', language: 'sql', script: commands } unless commands.empty?
119
+ # elsif transaction == false
120
+ # @transaction = commands.first
121
+ # else
122
+ # transaction = true
123
+ # @transaction << { type: 'cmd', language: 'sql', command: commands.first }
124
+
125
+ # transaction is true only for multible statements
126
+ # batch[:transaction] = transaction & batch[:operations].size >1
127
+ # logger.info{ @transaction.map{|y|y[:command]}.join(";\n ") }
128
+ # logger.info{ @transaction.map{|y|y[:script]}.join(";\n ") }
129
+ # batch= { transaction: transaction, operations: @transaction }
130
+ # puts "batch: #{batch.inspect}"
131
+
132
+ # @res["/batch/#{ActiveOrient.database}"].post batch.to_json
133
+ end
134
+ end
135
+
136
+ # execute the command
137
+ #
138
+ # thread-safe ( transaction = false)
139
+ #
140
+ #
141
+ def execute transaction: nil,
142
+ command: nil,
143
+ tolerated_error_code: nil,
144
+ process_error: true,
145
+ raw: nil
146
+
147
+ if block_given?
148
+ command = yield
149
+ end
150
+ unless command.present?
151
+ logger.error { "No Command provided to execute" }
152
+ return nil
153
+ end
154
+ if ( transaction.present? || command.is_a?(Array) )
155
+ logger.error "calling manage_transaction NOT IMPLEMENTED YET!"
156
+ manage_transaction transaction, command
157
+ end
158
+
159
+ logger.info command.to_s
160
+ _execute( tolerated_error_code, process_error, raw) do
161
+
162
+ ActiveOrient.db_pool.checkout do | conn |
163
+ conn["/command/#{ActiveOrient.database}/sql"].post command.to_s #.to_json
164
+ end
129
165
  end
166
+
167
+ # rest_resource.delete #if resource.present?
168
+
130
169
  end
131
170
 
132
171
 
133
- def _execute transaction, tolerated_error_code, process_error, raw
172
+ def _execute tolerated_error_code, process_error, raw
134
173
 
135
174
  logger.progname= "Execute"
175
+
136
176
  begin
137
- response = if @transaction.is_a?(Array)
138
- @transaction.compact!
139
- return nil if @transaction.empty?
140
- # transaction is true only for multible statements
141
- # batch[:transaction] = transaction & batch[:operations].size >1
142
- logger.info{ @transaction.map{|y|y[:command]}.join(";\n ") }
143
- logger.info{ @transaction.map{|y|y[:script]}.join(";\n ") }
144
- batch= { transaction: transaction, operations: @transaction }
145
- puts "batch: #{batch.inspect}"
146
- @res["/batch/#{ActiveOrient.database}"].post batch.to_json
147
- else
148
- logger.info{ @transaction }
149
- @res["/command/#{ActiveOrient.database}/sql"].post @transaction #.to_json
150
- end
177
+ response = yield
151
178
  rescue RestClient::BadRequest => f
152
179
  # extract the misspelled query in logfile and abort
153
180
  sentence= JSON.parse( f.response)['errors'].last['content']
@@ -155,8 +182,13 @@ end
155
182
  puts "Query not recognized"
156
183
  puts sentence
157
184
  raise
185
+ rescue RestClient::Conflict => e # (409)
186
+ # most probably the server is busy. we wait for a second print an Error-Message and retry
187
+ sleep(1)
188
+ logger.error{ e.inspect }
189
+ logger.error{ "RestClient::Error(409): Server is signaling a conflict ... retrying" }
190
+ retry
158
191
  rescue RestClient::InternalServerError => e
159
- @transaction = []
160
192
  sentence= JSON.parse( e.response)['errors'].last['content']
161
193
  if tolerated_error_code.present? && e.response =~ tolerated_error_code
162
194
  logger.debug('RestOperations#Execute'){ "tolerated_error::#{e.message}"}
@@ -164,8 +196,6 @@ end
164
196
  nil # return value
165
197
  else
166
198
  if process_error
167
- # puts batch.to_json
168
- # logger.error{e.response}
169
199
  logger.error{sentence}
170
200
  #logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
171
201
  # logger.error{e.message.to_s}
@@ -177,35 +207,16 @@ end
177
207
  sleep(2)
178
208
  retry
179
209
  else # code to execute if no exception is raised
180
- @transaction = []
181
210
  if response.code == 200
182
- if response.body['result'].present?
183
- result=JSON.parse(response.body)['result']
184
- return result if raw.present?
185
- result.map do |x|
186
- if x.is_a? Hash
187
- y = x.transform_keys{|y| y.delete('@').split('=').first.underscore.to_sym}
188
- if y[:type] == 'd' #0.present? # == 'd' # x.has_key?("@type") &&
189
- if y.has_key?(:class)
190
- the_object = ActiveOrient::Model.orientdb_class( name: y[:class] ).new x
191
- ActiveOrient::Base.store_rid( the_object ) # update cache
192
- else # create a dummy class and fill with attributes from result-set
193
- ActiveOrient::Model.orientdb_class(name: 'query' ).new x
194
- end
195
- else
196
- # return the result or the corresponding dataset
197
- r= y.map{ | _,v | v.is_a?(String) && v.rid? ? ActiveOrient::Model.get( v ): v }
198
- y.size ==1 ? r.first : r # return raw instead of array if only one value is present
199
- end
200
- end
201
- end.compact # return_value
211
+ result=JSON.parse(response.body)['result']
212
+ if raw.present?
213
+ result
202
214
  else
203
- response.body
204
- end
215
+ result.from_orient
216
+ end # raw present?
205
217
  else
206
- nil
218
+ logger.error { "code : #{response.code}" }
207
219
  end
208
220
  end
209
221
  end
210
-
211
222
  end
@@ -7,7 +7,10 @@ module RestRead
7
7
  # ORD.get_databases
8
8
  # => ["temp", "GratefulDeadConcerts", (...)]
9
9
  def get_databases
10
- JSON.parse(@res["/listDatabases"].get.body)['databases']
10
+
11
+ ActiveOrient.db_pool.checkout do | conn |
12
+ JSON.parse(conn["/listDatabases"].get.body)['databases']
13
+ end
11
14
  end
12
15
 
13
16
  =begin
@@ -20,18 +23,20 @@ Returns an Array with (unmodified) Class-attribute-hash-Elements
20
23
  (...) ]
21
24
  =end
22
25
  def get_classes *attributes
23
- begin
24
- response = @res["/database/#{ActiveOrient.database}"].get
25
- if response.code == 200
26
- classes = JSON.parse(response.body)['classes']
27
- unless attributes.empty?
28
- classes.map{|y| y.select{|v,_| attributes.include?(v)}}
29
- else
30
- classes
31
- end
32
- else
33
- []
34
- end
26
+ begin
27
+ response = ActiveOrient.db_pool.checkout do | conn |
28
+ conn["/database/#{ActiveOrient.database}"].get
29
+ end
30
+ if response.code == 200
31
+ classes = JSON.parse(response.body)['classes']
32
+ unless attributes.empty?
33
+ classes.map{|y| y.select{|v,_| attributes.include?(v)}}
34
+ else
35
+ classes
36
+ end
37
+ else
38
+ []
39
+ end
35
40
  rescue Exception => e
36
41
  logger.progname = 'RestRead#GetClasses'
37
42
  logger.error{e.message}
@@ -48,11 +53,13 @@ Returns an Array with (unmodified) Class-attribute-hash-Elements
48
53
  # => {"name"=>"a", "superClass"=>"V", "superClasses"=>["V"], "alias"=>nil, "abstract"=>false, "strictmode"=>false, "clusters"=>[65, 66, 67, 68], "defaultCluster"=>65, "clusterSelection"=>"round-robin", "records"=>3}
49
54
  #
50
55
  def get_class_properties o_class
51
- JSON.parse(@res["/class/#{ActiveOrient.database}/#{classname(o_class)}"].get)
52
- rescue => e
53
- logger.error e.message
54
- nil
55
- end
56
+ ActiveOrient.db_pool.checkout do | conn |
57
+ JSON.parse(conn["/class/#{ActiveOrient.database}/#{classname(o_class)}"].get)
58
+ end
59
+ rescue => e
60
+ logger.error e.message
61
+ nil
62
+ end
56
63
 
57
64
 
58
65
  def print_class_properties o_class
@@ -86,7 +93,10 @@ The rid-cache is not used or updated
86
93
  begin
87
94
  logger.progname = 'RestRead#GetRecord'
88
95
  if rid.rid?
89
- response = @res["/document/#{ActiveOrient.database}/#{rid.to_orient[1..-1]}"].get
96
+
97
+ response = ActiveOrient.db_pool.checkout do | conn |
98
+ conn["/document/#{ActiveOrient.database}/#{rid.to_orient[1..-1]}"].get
99
+ end
90
100
  raw_data = JSON.parse(response.body)
91
101
  # ActiveOrient::Model.use_or_allocate( raw_data['@rid'] ) do
92
102
  the_object= ActiveOrient::Model.orientdb_class(name: raw_data['@class']).new raw_data
@@ -107,6 +117,13 @@ The rid-cache is not used or updated
107
117
  logger.error { "RID: #{rid} ---> No Record present " }
108
118
  ActiveOrient::Model.remove_rid rid # remove rid from cache
109
119
  nil
120
+ rescue NoMethodError => e
121
+ logger.fatal { "---------------- Serious Trouble ----------------" }
122
+ logger.fatal { "GetRecord raw-data: #{raw_data}" }
123
+ logger.error { "GetRecord could not allocate Model-Instance" }
124
+ logger.error { "is a model file required but missing?" }
125
+ raise
126
+
110
127
  rescue Exception => e
111
128
  logger.error { "Something went wrong" }
112
129
  logger.error { "RID: #{rid} - #{e.message}" }
@@ -129,9 +146,11 @@ In this case cached data are used in favour and its not checked if the database
129
146
  query = OrientSupport::OrientQuery.new(args) if query.nil?
130
147
  begin
131
148
  logger.progname = 'RestRead#GetRecords'
132
- url = "/query/#{ActiveOrient.database}/sql/" + query.compose(destination: :rest) + "/#{query.get_limit}"
133
- response = @res[URI.encode(url)].get
134
- JSON.parse(response.body)['result'].map do |record|
149
+ response = ActiveOrient.db_pool.checkout do | conn |
150
+ url = "/query/#{ActiveOrient.database}/sql/" + query.compose(destination: :rest) + "/#{query.get_limit}"
151
+ conn[URI.encode(url)].get
152
+ end
153
+ JSON.parse(response.body)['result'].map do |record|
135
154
  if raw
136
155
  record
137
156
  # query returns an anonymus class: Use the provided Block or the Dummy-Model MyQuery
@@ -160,8 +179,7 @@ In this case cached data are used in favour and its not checked if the database
160
179
  logger.error{"Invalid URI detected"}
161
180
  logger.error query.to_s
162
181
  logger.info{"Trying batch processing"}
163
- sql_cmd = -> (command){{type: "cmd", language: "sql", command: command}}
164
- response = execute{[sql_cmd[query.to_s]]}
182
+ response = execute{ query.to_s}
165
183
  logger.info{"Success: to avoid this delay use ActiveOrient::Model#query_database instead"}
166
184
  response
167
185
  end