active-orient 0.79 → 0.80

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.
@@ -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