active-orient 0.4 → 0.5

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