active-orient 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +8 -3
  4. data/Guardfile +12 -4
  5. data/README.md +221 -201
  6. data/VERSION +1 -1
  7. data/active-orient.gemspec +3 -2
  8. data/bin/active-orient-console +35 -0
  9. data/config/boot.rb +84 -16
  10. data/config/config.yml +10 -0
  11. data/config/connect.yml +6 -2
  12. data/create_project +19 -0
  13. data/examples/books.rb +86 -39
  14. data/examples/createTime.rb +91 -0
  15. data/examples/streets.rb +85 -84
  16. data/examples/test_commands.rb +92 -0
  17. data/examples/test_commands_2.rb +54 -0
  18. data/examples/test_commands_3.rb +48 -0
  19. data/examples/test_commands_4.rb +28 -0
  20. data/examples/time_graph/Gemfile +21 -0
  21. data/examples/time_graph/Guardfile +26 -0
  22. data/examples/time_graph/README.md +129 -0
  23. data/examples/time_graph/bin/active-orient-console +35 -0
  24. data/examples/time_graph/config/boot.rb +119 -0
  25. data/examples/time_graph/config/config.yml +8 -0
  26. data/examples/time_graph/config/connect.yml +17 -0
  27. data/examples/time_graph/config/init_db.rb +59 -0
  28. data/examples/time_graph/createTime.rb +51 -0
  29. data/examples/time_graph/lib/createTime.rb +82 -0
  30. data/examples/time_graph/model/day_of.rb +3 -0
  31. data/examples/time_graph/model/e.rb +6 -0
  32. data/examples/time_graph/model/edge.rb +53 -0
  33. data/examples/time_graph/model/monat.rb +19 -0
  34. data/examples/time_graph/model/stunde.rb +16 -0
  35. data/examples/time_graph/model/tag.rb +29 -0
  36. data/examples/time_graph/model/time_base.rb +6 -0
  37. data/examples/time_graph/model/time_of.rb +4 -0
  38. data/examples/time_graph/model/v.rb +3 -0
  39. data/examples/time_graph/model/vertex.rb +32 -0
  40. data/examples/time_graph/spec/lib/create_time_spec.rb +50 -0
  41. data/examples/time_graph/spec/rest_helper.rb +37 -0
  42. data/examples/time_graph/spec/spec_helper.rb +46 -0
  43. data/lib/active-orient.rb +56 -6
  44. data/lib/base.rb +149 -147
  45. data/lib/base_properties.rb +40 -41
  46. data/lib/class_utils.rb +301 -0
  47. data/lib/database_utils.rb +97 -0
  48. data/lib/init.rb +35 -0
  49. data/lib/java-api.rb +437 -0
  50. data/lib/jdbc.rb +211 -0
  51. data/lib/model/edge.rb +53 -0
  52. data/lib/model/model.rb +77 -0
  53. data/lib/model/the_class.rb +480 -0
  54. data/lib/model/the_record.rb +310 -0
  55. data/lib/model/vertex.rb +32 -0
  56. data/lib/orient.rb +113 -50
  57. data/lib/orientdb_private.rb +48 -0
  58. data/lib/other.rb +280 -0
  59. data/lib/query.rb +71 -73
  60. data/lib/rest/change.rb +124 -0
  61. data/lib/rest/create.rb +474 -0
  62. data/lib/rest/delete.rb +133 -0
  63. data/lib/rest/operations.rb +150 -0
  64. data/lib/rest/read.rb +150 -0
  65. data/lib/rest/rest.rb +111 -0
  66. data/lib/rest_disabled.rb +24 -0
  67. data/lib/support.rb +387 -296
  68. data/old_lib_functions/two_general_class.rb +139 -0
  69. data/usecase.md +49 -36
  70. data/usecase_oo.md +59 -0
  71. metadata +73 -9
  72. data/lib/model.rb +0 -461
  73. data/lib/rest.rb +0 -1036
  74. data/test.rb +0 -4
@@ -0,0 +1,124 @@
1
+ module RestChange
2
+
3
+ ############### DATABASE ####################
4
+
5
+ # Changes the working-database to {name}
6
+
7
+ def change_database name
8
+ @classes = []
9
+ @database = name
10
+ ActiveOrient.database = name
11
+ end
12
+
13
+ ############# OBJECTS #################
14
+
15
+ =begin
16
+ Convient update of the dataset by calling sql-patch
17
+
18
+ The argument record can be specified as ActiveOrient::Model-instance or as rid-string( #0:0 )
19
+
20
+ called from ModelRecord#update
21
+
22
+ if the update was successful, the updated ActiveOrient::Model-record is returned.
23
+ =end
24
+
25
+ def update record, attributes , version=0 # :nodoc:
26
+ r = if record.is_a?(String) && record.rid?
27
+ ActiveOrient::Model.autoload record
28
+ else
29
+ record
30
+ end
31
+ return(false) unless r.is_a?(ActiveOrient::Model)
32
+ version = r.version if version.zero?
33
+ result = patch_record(r.rid) do
34
+ attributes.merge({'@version' => version, '@class' => r.class.ref_name })
35
+ end
36
+ # returns a new instance of ActiveOrient::Model and updates any reference on rid
37
+ # if the patch is not successfull no string is returned and thus no record is fetched
38
+ # puts JSON.parse(result) if result.is_a?(String)
39
+ ActiveOrient::Model.orientdb_class(name: r.class.ref_name, superclass: :find_ME ).new(JSON.parse(result)) if result.is_a?(String)
40
+ end
41
+
42
+
43
+ =begin
44
+ Example:
45
+ ORD.update_documents classname, set: {:symbol => 'TWR'}, where: {con_id: 340}
46
+
47
+ Replaces the symbol to TWR in each record where the con_id is 340
48
+
49
+ Both set and where take multiple attributes
50
+
51
+ Returns the JSON-Response.
52
+ =end
53
+
54
+ def update_records o_class, set:, where: {}
55
+ url = "UPDATE #{classname(o_class)} SET #{generate_sql_list(set)} #{compose_where(where)}"
56
+ response = @res[URI.encode("/command/#{ActiveOrient.database}/sql/" << url)].post ''
57
+ end
58
+ alias update_documents update_records
59
+
60
+ # Lazy Updating of the given Record.
61
+
62
+ def patch_record rid # :nodoc: (used by Model#update )
63
+ logger.progname = 'RestChange#PatchRecord'
64
+ content = yield
65
+ if content.is_a? Hash
66
+ begin
67
+ @res["/document/#{ActiveOrient.database}/#{rid}"].patch content.to_orient.to_json
68
+ rescue Exception => e
69
+ logger.error{e.message}
70
+ end
71
+ else
72
+ logger.error{"FAILED: The Block must provide an Hash with properties to be updated"}
73
+ end
74
+ end
75
+ alias patch_document patch_record
76
+
77
+
78
+ #### EXPERIMENTAL ##########
79
+
80
+ =begin
81
+ Used to add restriction or other properties to the Property of a Class.
82
+ See http://orientdb.com/docs/2.1/SQL-Alter-Property.html
83
+ =end
84
+
85
+ def alter_property o_class, property:, attribute: "DEFAULT", alteration: # :nodoc: because untested
86
+ logger.progname = 'RestChange#AlterProperty'
87
+ begin
88
+ attribute.to_s! unless attribute.is_a? String
89
+ attribute.capitalize_first_letter
90
+ case attribute
91
+ when "LINKEDCLASS", "LINKEDTYPE", "NAME", "REGEX", "TYPE", "REGEX", "COLLATE", "CUSTOM"
92
+ unless alteration.is_a? String
93
+ logger.error{"#{alteration} should be a String."}
94
+ return 0
95
+ end
96
+ when "MIN", "MAX"
97
+ unless alteration.is_a? Integer
98
+ logger.error{"#{alteration} should be an Integer."}
99
+ return 0
100
+ end
101
+ when "MANDATORY", "NOTNULL", "READONLY"
102
+ unless alteration.is_a? TrueClass or alteration.is_a? FalseClass
103
+ logger.error{"#{alteration} should be an Integer."}
104
+ return 0
105
+ end
106
+ when "DEFAULT"
107
+ else
108
+ logger.error{"Wrong attribute."}
109
+ return 0
110
+ end
111
+
112
+ name_class = classname(o_class)
113
+ execute name_class, transaction: false do # To execute commands
114
+ [{ type: "cmd",
115
+ language: 'sql',
116
+ command: "ALTER PROPERTY #{name_class}.#{property} #{attribute} #{alteration}"}]
117
+ end
118
+ rescue Exception => e
119
+ logger.error{e.message}
120
+ end
121
+ end
122
+
123
+
124
+ end
@@ -0,0 +1,474 @@
1
+ module RestCreate
2
+
3
+ ######### DATABASE ##########
4
+
5
+ =begin
6
+ Creates a database with the given name and switches to this database as working-database. Types are either 'plocal' or 'memory'
7
+
8
+ Returns the name of the working-database
9
+ =end
10
+
11
+ def create_database type: 'plocal', database: nil
12
+ logger.progname = 'RestCreate#CreateDatabase'
13
+ old_d = ActiveOrient.database
14
+ ActiveOrient.database_classes = []
15
+ ActiveOrient.database = database if database.present?
16
+ begin
17
+ response = @res["database/#{ActiveOrient.database}/#{type}"].post ""
18
+ if response.code == 200
19
+ logger.info{"Database #{ActiveOrient.database} successfully created and stored as working database"}
20
+ else
21
+ ActiveOrient.database = old_d
22
+ logger.error{"Database #{name} was NOT created. Working Database is still #{ActiveOrient.database}"}
23
+ end
24
+ rescue RestClient::InternalServerError => e
25
+ ActiveOrient.database = old_d
26
+ logger.error{"Database #{name} was NOT created. Working Database is still #{ActiveOrient.database}"}
27
+ end
28
+ ActiveOrient.database
29
+ end
30
+
31
+ ######### CLASS ##########
32
+ =begin
33
+ Creates classes and class-hierarchies in OrientDB and in Ruby.
34
+ Takes a String, Array or Hash as argument and returns a (nested) Array of
35
+ successfull allocated Ruby-Classes.
36
+ If a block is provided, this is used to allocate the class to this superclass.
37
+
38
+ Examples
39
+
40
+ create_class "a_single_class"
41
+ create_class :a_single_class
42
+ create_class( :a_single_class ){ :a_super_class }
43
+ create_class( :a_single_class ){ superclass: :a_super_class, abstract: true }
44
+ create_class( ["c",:l,:A,:SS] ){ :V } --> vertices
45
+ create_class( ["c",:l,:A,:SS] ){ superclass: :V, abstract: true } --> abstract vertices
46
+ create_class( { V: [ :A, :B, C: [:c1,:c3,:c2] ], E: [:has_content, :becomes_hot ]} )
47
+ =end
48
+
49
+
50
+ =begin
51
+ General method to create database classes
52
+
53
+ Accepts
54
+ * a string or symbol
55
+
56
+ creates a single class and returns the ActiveOrient::Model-Class
57
+ * an arrray of strings or symbols
58
+
59
+ creates alltogether and returns an array of created ActiveOrient::Model-Classes
60
+ * a (nested) Hash
61
+
62
+ then creates a hierarchy of database-classes and returns them as hash
63
+
64
+ takes an optional block to specify a superclass. This class MUST exist.
65
+
66
+
67
+ eg.
68
+ create_classes( :test ){ :V }
69
+
70
+ creates a vertex-class, returns just Test ( < ActiveOrient::Model)
71
+
72
+ a,b,c = create_classes( :test1, :test2, test3 ) { :V }
73
+
74
+ creates three vertex-classes and assigns them to var's a,b, and c
75
+
76
+ create_classes( test: [:test1, :test2, test3] ) { :V }
77
+
78
+ creates a vertex-class Test and three clild-classes
79
+
80
+ create_classes( :V => :test)
81
+
82
+ creates a vertex-class, too, returns the Hash
83
+
84
+ #todo
85
+ #check if a similar classname already exists --> Contract == contract == conTract
86
+ #and assign to this existing one.
87
+ =end
88
+ def create_classes *classes, &b
89
+ returt if classes.empty?
90
+
91
+ classes = classes.pop if classes.size == 1
92
+ consts = allocate_classes_in_ruby( classes , &b )
93
+ all_classes = consts.is_a?( Array) ? consts.flatten : [consts]
94
+ dc = database_classes(requery: true)
95
+ selected_classes = all_classes.map do | this_class |
96
+ this_class unless dc.include?( this_class.ref_name ) rescue nil
97
+ end.compact.uniq
98
+
99
+ command= selected_classes.map do | database_class |
100
+ ## improper initialized ActiveOrient::Model-classes lack a ref_name class-variable
101
+ if database_class.ref_name.blank?
102
+ logger.error{ "Improper initialized ActiveOrient::Model #{database_class}" }
103
+ raise ArgumentError
104
+ end
105
+ database_class.require_model_file
106
+ c = if database_class.superclass == ActiveOrient::Model || database_class.superclass.ref_name.blank?
107
+ "CREATE CLASS #{database_class.ref_name}"
108
+ else
109
+ "CREATE CLASS #{database_class.ref_name} EXTENDS #{database_class.superclass.ref_name}"
110
+ end
111
+ c << " ABSTRACT" if database_class.abstract
112
+ { type: "cmd", language: 'sql', command: c } # return value 4 command
113
+ end
114
+ # execute anything as batch, don't roll back in case of an error
115
+
116
+ execute transaction: false, tolerated_error_code: /already exists in current database/ do
117
+ command
118
+ end
119
+ # update the internal class hierarchy
120
+ database_classes requery: true
121
+ # return all allocated classes, no matter whether they had to be created in the DB or not.
122
+ # keep the format of the input-parameter
123
+ #consts.shift if block_given? && consts.is_a?( Array) # remove the first element
124
+ # remove traces of superclass-allocations
125
+ if classes.is_a? Hash
126
+ consts = Hash[ consts ]
127
+ consts.each_key{ |x| consts[x].delete_if{|y| y == x} if consts[x].is_a? Array }
128
+ end
129
+ consts
130
+
131
+ rescue ArgumentError => e
132
+ logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
133
+ end
134
+
135
+
136
+ # create_general_class singleclass, behaviour: behaviour, extended_class: extended_class, properties: properties
137
+
138
+ # when Hash
139
+ # classes.keys.each do |superclass|
140
+ # create_general_class superclass, behaviour: "SUPERCLASS", extended_class: nil, properties: nil
141
+ # create_general_class classes[superclass], behaviour: "EXTENDEDCLASS", extended_class: superclass, properties: properties
142
+ # end
143
+ #
144
+ # else
145
+ # name_class = classes.to_s.capitalize_first_letter
146
+ # unless @classes.downcase.include?(name_class.downcase)
147
+ #
148
+ # if behaviour == "NORMALCLASS"
149
+ # command = "CREATE CLASS #{name_class}"
150
+ # elsif behaviour == "SUPERCLASS"
151
+ # command = "CREATE CLASS #{name_class} ABSTRACT"
152
+ # elsif behaviour == "EXTENDEDCLASS"
153
+ # name_superclass = extended_class.to_s
154
+ # command = "CREATE CLASS #{name_class} EXTENDS #{name_superclass}"
155
+ # end
156
+ #
157
+ # #print "\n #{command} \n"
158
+ #
159
+ # execute transaction: false do
160
+ # [{ type: "cmd",
161
+ # language: "sql",
162
+ # command: command}]
163
+ # end
164
+ #
165
+ # @classes << name_class
166
+ #
167
+ # # Add properties
168
+ # unless properties.nil?
169
+ # create_properties name_class, properties
170
+ # end
171
+ # end
172
+ #
173
+ # consts << ActiveOrient::Model.orientdb_class(name: name_class)
174
+ # end
175
+
176
+ # return consts
177
+ #
178
+ # rescue RestClient::InternalServerError => e
179
+ # logger.progname = 'RestCreate#CreateGeneralClass'
180
+ # response = JSON.parse(e.response)['errors'].pop
181
+ # logger.error{"#{response['content'].split(':').last }"}
182
+ # nil
183
+ # end
184
+ #end
185
+
186
+
187
+ ############## OBJECT #############
188
+
189
+
190
+
191
+ =begin
192
+ Creates a Record (NOT edge) in the Database and returns this as ActiveOrient::Model-Instance
193
+ Creates a Record with the attributes provided in the attributes-hash e.g.
194
+ create_record @classname, attributes: {con_id: 343, symbol: 'EWTZ'}
195
+
196
+ untested: for hybrid and schema-less documents the following syntax is supported
197
+ create_document Account, attributes: {date: 1350426789, amount: 100.34, "@fieldTypes" => "date = t, amount = c"}
198
+
199
+ The supported special types are:
200
+ 'f' for float
201
+ 'c' for decimal
202
+ 'l' for long
203
+ 'd' for double
204
+ 'b' for byte and binary
205
+ 'a' for date
206
+ 't' for datetime
207
+ 's' for short
208
+ 'e' for Set, because arrays and List are serialized as arrays like [3,4,5]
209
+ 'x' for links
210
+ 'n' for linksets
211
+ 'z' for linklist
212
+ 'm' for linkmap
213
+ 'g' for linkbag
214
+ =end
215
+
216
+ def create_record o_class, attributes: {} # :nodoc: # use Model#create instead
217
+ logger.progname = 'RestCreate#CreateRecord'
218
+ attributes = yield if attributes.empty? && block_given?
219
+ # @class must not quoted! Quote only attributes(strings)
220
+ post_argument = {'@class' => classname(o_class)}.merge(attributes.to_orient)
221
+ begin
222
+ response = @res["/document/#{ActiveOrient.database}"].post post_argument.to_json
223
+ data = JSON.parse(response.body)
224
+ if o_class.is_a?(Class) && o_class.new.is_a?(ActiveOrient::Model)
225
+ o_class.new data
226
+ else
227
+ ActiveOrient::Model.orientdb_class(name: data['@class'], superclass: :find_ME).new data
228
+ end
229
+ rescue RestClient::InternalServerError => e
230
+ response = JSON.parse(e.response)['errors'].pop
231
+ logger.error{response['content'].split(':')[1..-1].join(':')}
232
+ logger.error{"No Object allocated"}
233
+ nil # return_value
234
+ end
235
+ end
236
+ alias create_document create_record
237
+
238
+ =begin
239
+ Used to create multiple records at once
240
+ For example:
241
+ $r.create_multiple_records "Month", ["date", "value"], [["June", 6], ["July", 7], ["August", 8]]
242
+ It is equivalent to this three functios:
243
+ $r.create_record "Month", attributes: {date: "June", value: 6}
244
+ $r.create_record "Month", attributes: {date: "July", value: 7}
245
+ $r.create_record "Month", attributes: {date: "August", value: 8}
246
+
247
+ The function $r.create_multiple_records "Month", ["date", "value"], [["June", 6], ["July", 7], ["August", 8]] will return an array with three element of class "Active::Model::Month".
248
+ =end
249
+
250
+ def create_multiple_records o_class, values, new_records # :nodoc: # untested
251
+ command = "INSERT INTO #{o_class} ("
252
+ values.each do |val|
253
+ command += "#{val},"
254
+ end
255
+ command[-1] = ")"
256
+ command += " VALUES "
257
+ new_records.each do |new_record|
258
+ command += "("
259
+ new_record.each do |record_value|
260
+ case record_value
261
+ when String
262
+ command += "\'#{record_value}\',"
263
+ when Integer
264
+ command += "#{record_value},"
265
+ when ActiveOrient::Model
266
+ command += "##{record_value.rid},"
267
+ when Array
268
+ if record_value[0].is_a? ActiveOrient::Model
269
+ command += "["
270
+ record_value.rid.each do |rid|
271
+ command += "##{rid},"
272
+ end
273
+ command[-1] = "]"
274
+ command += ","
275
+ else
276
+ command += "null,"
277
+ end
278
+ else
279
+ command += "null,"
280
+ end
281
+ end
282
+ command[-1] = ")"
283
+ command += ","
284
+ end
285
+ command[-1] = ""
286
+ execute transaction: false do # To execute commands
287
+ [{ type: "cmd",
288
+ language: 'sql',
289
+ command: command}]
290
+ end
291
+ end
292
+ # UPDATE <class>|CLUSTER:<cluster>|<recordID>
293
+ # [SET|INCREMENT|ADD|REMOVE|PUT <field-name> = <field-value>[,]*]|[CONTENT|MERGE <JSON>]
294
+ # [UPSERT]
295
+ # [RETURN <returning> [<returning-expression>]]
296
+ # [WHERE <conditions>]
297
+ # [LOCK default|record]
298
+ # [LIMIT <max-records>] [TIMEOUT <timeout>]
299
+
300
+ =begin
301
+ update or insert one record is implemented as upsert.
302
+ The where-condition is merged into the set-attributes if its a hash.
303
+ Otherwise it's taken unmodified.
304
+
305
+ The method returns the included or the updated dataset
306
+
307
+ ## to do
308
+ # yield works for updated and for inserted datasets
309
+ # upsert ( ) do | what, record |
310
+ # if what == :insert
311
+ # do stuff with insert
312
+ # if what == :update
313
+ # do stuff with update
314
+ # end
315
+ =end
316
+ def upsert o_class, set: {}, where: {} # :nodoc: use Model#Upsert instead
317
+ logger.progname = 'RestCreate#Upsert'
318
+ if where.blank?
319
+ new_record = create_record(o_class, attributes: set)
320
+ yield new_record if block_given? # in case if insert execute optional block
321
+ new_record # return_value
322
+ else
323
+ specify_return_value = block_given? ? "" : "return after @this"
324
+ set.merge! where if where.is_a?( Hash ) # copy where attributes to set
325
+ command = "Update #{classname(o_class)} set #{generate_sql_list( set ){','}} upsert #{specify_return_value} #{compose_where where}"
326
+
327
+
328
+ # puts "COMMAND: #{command} "
329
+ result = execute tolerated_error_code: /found duplicated key/, raw: true do # To execute commands
330
+ [ { type: "cmd", language: 'sql', command: command}]
331
+ end
332
+ result =result.pop if result.is_a? Array
333
+ # puts "RESULT: #{result.inspect}, #{result.class}"
334
+ if result.has_key?('@class')
335
+ if o_class.is_a?(Class) && o_class.new.is_a?(ActiveOrient::Model)
336
+ o_class.new result
337
+ else
338
+ AddctiveOrient::Model.orientdb_class(name: data['@class'], superclass: :find_ME).new data
339
+ end
340
+ elsif result.has_key?('value')
341
+ the_record= get_records(from: o_class, where: where, limit: 1).pop
342
+ ## process Code if a new dataset is inserted
343
+ if result['value'].to_i == 1
344
+ yield the_record if block_given?
345
+ logger.info{ "Dataset updated" }
346
+ elsif result['value'].to_i == 0
347
+ logger.info{ "Dataset inserted"}
348
+ end
349
+ the_record # return_value
350
+
351
+ else
352
+ logger.error{ "Unexpected result form Query \n #{command} \n Result: #{result}" }
353
+ raise ArgumentError
354
+ end
355
+
356
+ end
357
+ end
358
+ ############### PROPERTIES #############
359
+
360
+ =begin
361
+ Creates properties and optional an associated index as defined in the provided block
362
+ create_properties(classname or class, properties as hash){index}
363
+
364
+ The default-case
365
+ create_properties(:my_high_sophisticated_database_class,
366
+ con_id: {type: :integer},
367
+ details: {type: :link, linked_class: 'Contracts'}) do
368
+ contract_idx: :notunique
369
+ end
370
+
371
+ A composite index
372
+ create_properties(:my_high_sophisticated_database_class,
373
+ con_id: {type: :integer},
374
+ symbol: {type: :string}) do
375
+ {name: 'indexname',
376
+ on: [:con_id, :details] # default: all specified properties
377
+ type: :notunique # default: :unique
378
+ }
379
+ end
380
+ =end
381
+
382
+ def create_properties o_class, all_properties, &b
383
+ logger.progname = 'RestCreate#CreateProperties'
384
+ all_properties_in_a_hash = HashWithIndifferentAccess.new
385
+ all_properties.each{|field, args| all_properties_in_a_hash.merge! translate_property_hash(field, args)}
386
+ count=0
387
+ begin
388
+ if all_properties_in_a_hash.is_a?(Hash)
389
+ response = @res["/property/#{ActiveOrient.database}/#{classname(o_class)}"].post all_properties_in_a_hash.to_json
390
+ # response.body.to_i returns response.code, only to_f.to_i returns the correrect value
391
+ count= response.body.to_f.to_i if response.code == 201
392
+ end
393
+ rescue RestClient::InternalServerError => e
394
+ logger.progname = 'RestCreate#CreateProperties'
395
+ response = JSON.parse(e.response)['errors'].pop
396
+ error_message = response['content'].split(':').last
397
+ logger.error{"Properties in #{classname(o_class)} were NOT created"}
398
+ logger.error{"The Error was: #{response['content'].split(':').last}"}
399
+ nil
400
+ end
401
+ ### index
402
+ if block_given?# && count == all_properties_in_a_hash.size
403
+ index = yield
404
+ if index.is_a?(Hash)
405
+ puts "index_class: #{o_class}"
406
+ puts "index: "+index.inspect
407
+ if index.size == 1
408
+ create_index o_class, name: index.keys.first, on: all_properties_in_a_hash.keys, type: index.values.first
409
+ else
410
+ index_hash = HashWithIndifferentAccess.new(type: :unique, on: all_properties_in_a_hash.keys).merge index
411
+ create_index o_class, name: index_hash[:name], on: index_hash[:on], type: index_hash[:type]
412
+ end
413
+ end
414
+ end
415
+ count # return_value
416
+ end
417
+
418
+ =begin
419
+ Create a single property on class-level.
420
+ Supported types: https://orientdb.com/docs/last/SQL-Create-Property.html
421
+ If index is to be specified, it's defined in the optional block
422
+ create_property(class, field){:unique | :notunique} --> creates an automatic-Index on the given field
423
+ create_property(class, field){{»name« => :unique | :notunique | :full_text}} --> creates a manual index
424
+ =end
425
+
426
+ def create_property o_class, field, index: nil, **args, &b
427
+ logger.progname = 'RestCreate#CreateProperty'
428
+ args= { type: :integer} if args.blank? # the default case
429
+ c = create_properties o_class, {field => args}
430
+ if index.nil? && block_given?
431
+ index = yield
432
+ end
433
+ if index.present?
434
+ if index.is_a?(String) || index.is_a?(Symbol)
435
+ create_index o_class, name: field, type: index
436
+ elsif index.is_a? Hash
437
+ bez = index.keys.first
438
+ create_index o_class, name: bez, type: index[bez], on: [field]
439
+ end
440
+ end
441
+ end
442
+
443
+ ################# INDEX ###################
444
+
445
+ # Used to create an index
446
+
447
+ def create_index o_class, name:, on: :automatic, type: :unique
448
+ logger.progname = 'RestCreate#CreateIndex'
449
+ begin
450
+ c = classname o_class
451
+ puts "CREATE INDEX: class: #{c.inspect}"
452
+ execute transaction: false do
453
+ command = if on == :automatic
454
+ "CREATE INDEX #{c}.#{name} #{type.to_s.upcase}"
455
+ elsif on.is_a? Array
456
+ "CREATE INDEX #{name} ON #{c}(#{on.join(', ')}) #{type.to_s.upcase}"
457
+ else
458
+ "CREATE INDEX #{name} ON #{c}(#{on.to_s}) #{type.to_s.upcase}"
459
+ #nil
460
+ end
461
+ #puts "command: #{command}"
462
+ {type: "cmd", language: 'sql', command: command} if command.present?
463
+ end
464
+ logger.info{"Index on #{c} based on #{name} created."}
465
+ rescue RestClient::InternalServerError => e
466
+ response = JSON.parse(e.response)['errors'].pop
467
+ error_message = response['content'].split(':').last
468
+ logger.error{"Index not created."}
469
+ logger.error{"Error-code #{response['code']} --> #{response['content'].split(':').last }"}
470
+ nil
471
+ end
472
+ end
473
+
474
+ end