arcadedb 0.3.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/arcade/base.rb CHANGED
@@ -5,7 +5,7 @@ module Arcade
5
5
  # schema schema.strict # -- throws an error if specified keys are missing
6
6
  transform_keys{ |x| x[0] == '@' ? x[1..-1].to_sym : x.to_sym }
7
7
  # Types::Rid --> only accept #000:000, raises an Error, if rid is not present
8
- attribute :rid, Types::Rid
8
+ attribute :rid?, Types::Rid
9
9
  # maybe there are edges ## removed in favour of instance methods
10
10
  # attribute :in?, Types::Nominal::Any
11
11
  # attribute :out?, Types::Nominal::Any
@@ -27,6 +27,16 @@ module Arcade
27
27
  self.name.snake_case
28
28
  end
29
29
 
30
+ def begin_transaction
31
+ db.begin_transaction
32
+ end
33
+ def commit
34
+ db.commit
35
+ end
36
+ def rollback
37
+ db.rollback
38
+ end
39
+
30
40
  def create_type
31
41
  the_class = nil # declare as local var
32
42
  parent_present = ->(cl){ db.hierarchy.flatten.include? cl }
@@ -41,12 +51,7 @@ module Arcade
41
51
  if the_class.respond_to?(:demodulize)
42
52
  if [ 'Document','Vertex', 'Edge'].include?(the_class.demodulize)
43
53
  if the_class == superclass # no inheritance
44
- ## we have to use demodulize as the_class actually is Arcade::Vertex, ...
45
- unless parent_present[ to_s.snake_case ]
46
54
  db.create_type the_class.demodulize, to_s.snake_case
47
- else
48
- db.logger.warn "Type #{ to_s.snake_case } is present, process skipped"
49
- end
50
55
  else
51
56
  if superclass.is_a? Class # maybe its a module.
52
57
  extended = superclass.to_s.snake_case
@@ -72,10 +77,10 @@ module Arcade
72
77
  the_command = command[0 .. -2] # remove '\n'
73
78
  next if the_command == ''
74
79
  # db.logger.info "Custom Setup:: #{the_command}"
75
- db.execute { the_command }
80
+ db.transmit { the_command }
76
81
  end unless custom_setup.nil?
77
82
 
78
- rescue Arcade::RollbackError => e
83
+ rescue RollbackError => e
79
84
  db.logger.warn e
80
85
  rescue RuntimeError => e
81
86
  db.logger.warn e
@@ -123,9 +128,11 @@ module Arcade
123
128
  # (not supported (jet): [RETURN <expression>] [FROM <query>] )
124
129
 
125
130
  def insert **attributes
126
- db.insert type: database_name, **attributes
131
+ db.insert type: database_name, session_id: attributes.delete(:session_id), **attributes
127
132
  end
128
133
 
134
+ alias create insert
135
+
129
136
  ## ----------------------------------------- create ---------------------------------- ##
130
137
  #
131
138
  # Adds a record to the database
@@ -133,21 +140,21 @@ module Arcade
133
140
  # returns the model dataset
134
141
  # ( depreciated )
135
142
 
136
- def create **attributes
137
- Api.begin_transaction db.database
138
- attributes.merge!( created: DateTime.now ) if timestamps
139
- record = insert **attributes
140
- Api.commit db.database
141
- record
142
- rescue QueryError => e
143
- db.logger.error "Dataset NOT created"
144
- db.logger.error "Provided Attributes: #{ attributes.inspect }"
145
- # Api.rollback db.database ---> raises "transactgion not begun"
146
- rescue Dry::Struct::Error => e
147
- Api.rollback db.database
148
- db.logger.error "#{ rid } :: Validation failed, record deleted."
149
- db.logger.error e.message
150
- end
143
+ # def create **attributes
144
+ # s = Api.begin_transaction db.database
145
+ # attributes.merge!( created: DateTime.now ) if timestamps
146
+ # record = insert **attributes
147
+ # Api.commit db.database, s
148
+ # record
149
+ # rescue HTTPX::HTTPError => e
150
+ # db.logger.error "Dataset NOT created"
151
+ # db.logger.error "Provided Attributes: #{ attributes.inspect }"
152
+ # Api.rollback db.database # ---> raises "transactgion not begun"
153
+ # rescue Dry::Struct::Error => e
154
+ # Api.rollback db.database
155
+ # db.logger.error "#{ rid } :: Validation failed, record deleted."
156
+ # db.logger.error e.message
157
+ # end
151
158
 
152
159
  def count **args
153
160
  command = "count(*)"
@@ -222,12 +229,11 @@ module Arcade
222
229
  # Finds the first matching record providing the parameters of a `where` query
223
230
  # Strategie.find symbol: 'Still'
224
231
  # is equivalent to
225
- # Strategie.all.find{|y| y.symbol == 'Still'
226
- # }
232
+ # Strategie.all.find{|y| y.symbol == 'Still' }
227
233
  def find **args
228
- f= where(**args).first
229
- f= where( "#{ args.keys.first } like #{ args.values.first.to_or }" ).first if f.nil? || f.empty?
230
- f
234
+ where(**args).first
235
+ # f= where( "#{ args.keys.first } like #{ args.values.first.to_or }" ).first if f.nil? || f.empty?
236
+ # f
231
237
  end
232
238
  # update returns a list of updated records
233
239
  #
@@ -278,14 +284,14 @@ module Arcade
278
284
  end
279
285
  result= query( **( { kind: :upsert }.merge statement ) ).execute do | answer|
280
286
  z= answer[:"$current"] &.allocate_model(false) # do not autoload modelfiles
281
- raise Arcade::LoadError "Upsert failed" unless z.is_a? Arcade::Base
287
+ raise LoadError "Upsert failed" unless z.is_a? Base
282
288
  z # return record
283
289
  end
284
290
  end
285
291
 
286
292
 
287
293
  def query **args
288
- Arcade::Query.new( **{ from: self }.merge(args) )
294
+ Query.new( **{ from: self }.merge(args) )
289
295
  end
290
296
 
291
297
  # immutable support
@@ -332,7 +338,7 @@ module Arcade
332
338
  end
333
339
 
334
340
  def query **args
335
- Arcade::Query.new( **{ from: rid }.merge(args) )
341
+ Query.new( **{ from: rid }.merge(args) )
336
342
  end
337
343
 
338
344
  # to JSON controlls the serialisation of Arcade::Base Objects for the HTTP-JSON API
@@ -364,7 +370,7 @@ module Arcade
364
370
 
365
371
  "<#{ self.class.to_s.snake_case }" + rid? ? "[#{ rid }]: " : " " + invariant_attributes.map do |attr, value|
366
372
  v= case value
367
- when Arcade::Base
373
+ when Base
368
374
  "< #{ self.class.to_s.snake_case }: #{ value.rid } >"
369
375
  when Array
370
376
  value.map{|x| x.to_s}
@@ -373,59 +379,85 @@ module Arcade
373
379
  end
374
380
  "%s : %s" % [ attr, v] unless v.nil?
375
381
  end.compact.sort.join(', ') + ">".gsub('"' , ' ')
382
+
383
+ rescue TypeError => e
384
+ attributes
376
385
  end
377
386
 
378
- alias to_s to_human
387
+
388
+ # configure irb-output to to_human for all Arcade::Base-Objects
389
+ #
390
+ def inspect
391
+ to_human
392
+ end
393
+
394
+
395
+ def html_attributes
396
+ invariant_attributes
397
+ end
398
+
399
+ def in_and_out_attributes
400
+ _modul, _class = self.class.to_s.split "::"
401
+ the_class = _modul == 'Arcade' ? _class : self.class.to_s
402
+ the_attributes = { :"CLASS" => the_class, :"IN" => self.in.count, :"OUT" => self.out.count, :"RID" => rid }
403
+ end
379
404
 
380
405
  def to_html # iruby
406
+ in_and_out = ->(r) { "[#{r}] : {#{self.in.count}->}{->#{self.out.count }}" }
407
+ the_rid = rid? && rid != "0:0" ? in_and_out[rid] : ""
381
408
  _modul, _class = self.class.to_s.split "::"
382
409
  the_class = _modul == 'Arcade' ? _class : self.class.to_s
383
- IRuby.display IRuby.html "<b style=\"color: #50953DFF\"><#{ the_class}</b>"
384
- + rid? ? "[#{ rid }]: " : " " + invariant_attributes.map do |attr, value|
385
- v= case value
386
- when Arcade::Base
387
- "< #{ self.class.to_s.snake_case }: #{ value.rid } >"
388
- when Array
389
- value.map{|x| x.to_s}
390
- else
391
- value.from_db
392
- end
393
- "%s : %s" % [ attr, v] unless v.nil?
394
- end.compact.sort.join(', ') + ">".gsub('"' , ' ')
410
+ # the_attribute = ->(v) do
411
+ # case v
412
+ # when Base
413
+ # "< #{ self.class.to_s.snake_case }: #{ v.rid } >"
414
+ # when Array
415
+ # v.map{|x| x.to_s}
416
+ # else
417
+ # v.to_s
418
+ # end
419
+ # end
420
+ # last_part = invariant_attributes.map do |attr, value|
421
+ # [ attr, the_attribute[value] ].join(": ")
422
+ # end.join(', ')
423
+
424
+ # IRuby.display( [IRuby.html("<span style=\"color: #50953DFF\"><b>#{the_class}</b><#{ the_class }</b>#{the_rid}</span><br/> ") , IRuby.table(html_attributes) ] )
425
+ IRuby.display IRuby.html("<span style=\"color: #50953DFF\"><b>#{the_class}</b><#{ the_class }</b>#{the_rid}</span>< #{ html_attributes.map{|_,v| v }.join(', ') } >")
395
426
  end
396
427
 
428
+
397
429
  def update **args
398
- Arcade::Query.new( from: rid , kind: :update, set: args).execute
430
+ Query.new( from: rid , kind: :update, set: args).execute
399
431
  refresh
400
432
  end
401
433
 
402
434
  # inserts or updates a embedded document
403
435
  def insert_document name, obj
404
- value = if obj.is_a? Arcade::Document
436
+ value = if obj.is_a? Document
405
437
  obj.to_json
406
438
  else
407
439
  obj.to_or
408
440
  end
409
441
  # if send( name ).nil? || send( name ).empty?
410
- db.execute { "update #{ rid } set #{ name } = #{ value }" }.first[:count]
442
+ db.transmit { "update #{ rid } set #{ name } = #{ value }" }.first[:count]
411
443
  # end
412
444
  end
413
445
 
414
446
  # updates a single property in an embedded document
415
447
  def update_embedded embedded, embedded_property, value
416
- db.execute{ " update #{rid} set `#{embedded}`.`#{embedded_property}` = #{value.to_or}" }
448
+ db.transmit { " update #{rid} set `#{embedded}`.`#{embedded_property}` = #{value.to_or}" }
417
449
  end
418
450
 
419
451
  def update_list list, value
420
- value = if value.is_a? Arcade::Document
452
+ value = if value.is_a? Document
421
453
  value.to_json
422
454
  else
423
455
  value.to_or
424
456
  end
425
457
  if send( list ).nil? || send( list ).empty?
426
- db.execute { "update #{ rid } set #{ list } = [#{ value }]" }
458
+ db.transmit { "update #{ rid } set #{ list } = [#{ value }]" }
427
459
  else
428
- db.execute { "update #{ rid } set #{ list } += #{ value }" }
460
+ db.transmit { "update #{ rid } set #{ list } += #{ value }" }
429
461
  end
430
462
  refresh
431
463
  end
@@ -433,14 +465,14 @@ module Arcade
433
465
  # updates a map property , actually adds the key-value pair to the property
434
466
  def update_map m, key, value
435
467
  if send( m ).nil?
436
- db.execute { "update #{ rid } set #{ m } = MAP ( #{ key.to_s.to_or } , #{ value.to_or } ) " }
468
+ db.transmit { "update #{ rid } set #{ m } = MAP ( #{ key.to_s.to_or } , #{ value.to_or } ) " }
437
469
  else
438
- db.execute { "update #{ rid } set #{ m }.`#{ key.to_s }` = #{ value.to_or }" }
470
+ db.transmit { "update #{ rid } set #{ m }.`#{ key.to_s }` = #{ value.to_or }" }
439
471
  end
440
472
  refresh
441
473
  end
442
474
  def delete
443
- response = db.execute { "delete from #{ rid }" }
475
+ response = db.transmit { "delete from #{ rid }" }
444
476
  true if response == [{ count: 1 }]
445
477
  end
446
478
  def == arg
@@ -3,11 +3,11 @@ module Arcade
3
3
  extend Dry::Configurable
4
4
  # central place to initialize constants
5
5
  #
6
- # ProjectRoot has to be a Pathname-Object
6
+ # ProjectRoot should to be a Pathname-Object and has to be defined before `arcadedb` is required
7
7
  #
8
8
  #puts "expand: #{File.expand_path(__dir__)}"
9
- unless Arcade.const_defined?( :ProjectRoot )
10
- Arcade::ProjectRoot = if defined?( Rails.env )
9
+ unless Object.const_defined?( :ProjectRoot )
10
+ ::ProjectRoot = if defined?( Rails.env )
11
11
  Rails.root
12
12
  else
13
13
  STDERR.puts "Using default (arcadedb gem) database credentials and settings"
@@ -15,10 +15,9 @@ module Arcade
15
15
  Pathname.new( File.expand_path( "../../", __FILE__ ))
16
16
  end
17
17
  else
18
- STDERR.puts "Using provided database credentials and settings fron #{Arcade::ProjectRoot}"
18
+ STDERR.puts "Using provided database credentials and settings from #{::ProjectRoot}"
19
19
  end
20
20
 
21
-
22
21
  # initialised a hash { environment => property }
23
22
  setting :username, default: :user, reader: true,
24
23
  constructor: ->(v) { yml(:environment).map{|x,y| [x , y[v.to_s]] }.to_h }
@@ -48,17 +47,19 @@ module Arcade
48
47
  setting :namespace, default: :namespace, reader: true , constructor: ->(v) { yml(v) }
49
48
  setting :secret, reader: true, default: 12, constructor: ->(v) { seed(v) }
50
49
  private
51
- # if a config dir exists, use it
50
+ # if a config dir exists, use it.
51
+ # Standard: ProjectRoot/config.yml
52
52
  def self.config_file
53
- if @cd.nil?
54
- ( cd = ProjectRoot + 'arcade.yml' ).exist? ||
55
- ( cd = ProjectRoot + 'config' + 'arcade.yml' ).exist? ||
56
- ( cd = ProjectRoot + "config.yml" )
57
- @cd = cd
58
- else
59
- @cd
53
+
54
+ configdir = -> do
55
+ pr = ::ProjectRoot.is_a?(Pathname)? ::ProjectRoot : Pathname.new( ::ProjectRoot )
56
+ ( cd = pr + 'arcade.yml' ).exist? || ( cd = pr + 'config' + 'arcade.yml' ).exist? || ( cd = pr + 'config.yml' )
57
+ cd
60
58
  end
59
+
60
+ @cd ||= configdir[]
61
61
  end
62
+
62
63
  def self.yml key=nil
63
64
  y= YAML::load_file( config_file )
64
65
  key.nil? ? y : y[key]
@@ -17,12 +17,12 @@ module Arcade
17
17
  defines :environment
18
18
 
19
19
  def initialize environment=:development
20
- self.class.configure_logger( Config.logger )
21
- @connection = connect environment
20
+ self.class.configure_logger( Config.logger )
22
21
  if self.class.environment.nil? # class attribute is set on the first call
23
22
  # further instances of Database share the same environment
24
23
  self.class.environment environment
25
24
  end
25
+ @session_id = nil # declare session_id
26
26
  self.class.namespace Object.const_get( Config.namespace )
27
27
  end
28
28
 
@@ -39,20 +39,19 @@ module Arcade
39
39
  #
40
40
  def types refresh=false
41
41
  # uses API
42
- if $types.nil? || refresh
43
- $types = Api.query(database, "select from schema:types" )
44
- .map{ |x| x.transform_keys &:to_sym } # symbolize keys
45
- .map{ |y| y.delete_if{|_,b,| b.empty? } } # eliminate empty entries
42
+ if @types.nil? || refresh
43
+ @types = Api.query(database, "select from schema:types" )
44
+ .map{ |y| y.delete_if{|_,b,| b.blank? } } # eliminate empty entries
46
45
  end
47
- $types
48
- ## upom startup, this is the first access to the database-server
46
+ @types
47
+ ## upon startup, this is the first access to the database-server
49
48
  rescue NoMethodError => e
50
49
  logger.fatal "Could not read Database Types. \n Is the database running?"
51
50
  Kernel.exit
52
51
  end
53
52
 
54
- def indexes
55
- DB.types.find{|x| x.key? :indexes }[:indexes]
53
+ def indexes refresh=false
54
+ types(refresh).find_all{|x| x.key? :indexes }.map{|y| y[:indexes]}.flatten
56
55
  end
57
56
 
58
57
  # ------------ hierarchy -------------
@@ -108,23 +107,56 @@ module Arcade
108
107
  "create edge type #{type} "
109
108
  end.concat( args.map{|x,y| "#{x} #{y} "}.join)
110
109
  end
111
- db= Api.execute database, &exe
110
+ dbe= Api.execute database, &exe
112
111
  types( true ) # update cached schema
113
- db
114
-
115
- rescue Arcade::QueryError
116
- Arcade::Database.logger.warn "Database type #{type} already present"
112
+ dbe
113
+
114
+ rescue Arcade::QueryError => e
115
+ if e.message =~/Type\s+.+\salready\s+exists/
116
+ Arcade::Database.logger.debug "Database type #{type} already present"
117
+ else
118
+ raise
119
+ end
117
120
  end
118
121
 
119
122
  alias create_class create_type
120
123
 
121
124
  # ------------ drop type -----------
122
125
  # delete any record prior to the attempt to drop a type.
123
- # The `unsafe` option is nit implemented.
126
+ # The `unsafe` option is not implemented.
124
127
  def drop_type type
125
128
  Api.execute database, "drop type #{type} if exists"
126
129
  end
127
130
 
131
+ # ------------------------------ transaction ----------------------------------------------------- #
132
+ # Encapsulates simple transactions
133
+ #
134
+ # nested transactions are not supported.
135
+ # * use the low-leve api.begin_tranaction for that purpose
136
+ # * reuses an existing transaction
137
+ #
138
+ def begin_transaction
139
+ @session_id ||= Api.begin_transaction database
140
+ end
141
+ # ------------------------------ commit ----------------------------------------------------- #
142
+ def commit
143
+ r = Api.commit( database, session_id: session)
144
+ @session_id = nil
145
+ true if r == 204
146
+ end
147
+
148
+ # ------------------------------ rollback ----------------------------------------------------- #
149
+ #
150
+ def rollback
151
+ r = Api.rollback( database, session_id: session)
152
+ @session_id = nil
153
+ true if r == 500
154
+ rescue HTTPX::HTTPError => e
155
+ raise
156
+ end
157
+
158
+
159
+
128
160
  # ------------ create -----------
129
161
  # returns an rid of the successfully created vertex or document
130
162
  #
@@ -136,21 +168,34 @@ module Arcade
136
168
  #
137
169
  def create type, **params
138
170
  # uses API
139
- Api.create_document database, type, **params
171
+ Api.create_document database, type, session_id: session, **params
140
172
  end
141
173
 
174
+ # ------------------------------ insert ------------------------------------------------------ #
175
+ #
176
+ # translates the given parameters to
177
+ # INSERT INTO [TYPE:]<type>|BUCKET:<bucket>|INDEX:<index>
178
+ # [(<field>[,]*) VALUES (<expression>[,]*)[,]*]|
179
+ # [CONTENT {<JSON>}|[{<JSON>}[,]*]]
180
+ #
181
+ # :from and :return are not supported
182
+ #
183
+ # If a transaction is active, the insert is executed in that context.
184
+ # Nested transactions are not supported
142
185
  def insert **params
143
186
 
144
- content_params = params.except( :type, :bucket, :index, :from, :return )
187
+ content_params = params.except( :type, :bucket, :index, :from, :return, :session_id )
145
188
  target_params = params.slice( :type, :bucket, :index )
189
+ # session_id = params[:session_id] # extraxt session_id --> future-use?
146
190
  if target_params.empty?
147
- logger.error "Could not insert: target mising (type:, bucket:, index:)"
191
+ raise "Could not insert: target missing (type:, bucket:, index:)"
148
192
  elsif content_params.empty?
149
193
  logger.error "Nothing to Insert"
150
194
  else
151
195
  content = "CONTENT #{ content_params.to_json }"
152
196
  target = target_params.map{|y,z| y==:type ? z : "#{y.to_s} #{ z } "}.join
153
- Api.execute( database, "INSERT INTO #{target} #{content} ") &.first.allocate_model(false)
197
+ result = Api.execute( database, session_id: session ){ "INSERT INTO #{target} #{content} "}
198
+ result &.first.allocate_model(false)
154
199
  end
155
200
  end
156
201
 
@@ -173,89 +218,61 @@ module Arcade
173
218
  rid = rid.join(':')
174
219
  rid = rid[1..-1] if rid[0]=="#"
175
220
  if rid.rid?
176
- Api.query( database, "select from #{rid}" ).first &.allocate_model(autocomplete)
221
+ Api.query( database, "select from #{rid}", session_id: session ).first &.allocate_model(autocomplete)
177
222
  else
178
223
  raise Arcade::QueryError "Get requires a rid input", caller
179
224
  end
180
225
  end
181
226
 
182
- # ------------------------------ property ------------------------------------------------- #
183
- # Adds properties to the type
227
+ # ------------------------------ get ------------------------------------------------------ #
184
228
  #
185
- # call via
186
- # Api.property <database>, <type>, name1: a_format , name2: a_format
229
+ # Delete the specified rid
187
230
  #
188
- # Format is one of
189
- # Boolean, Integer, Short, Long, Float, Double, String
190
- # Datetime, Binary, Byte, Decimal, Link
191
- # Embedded, EmbeddedList, EmbeddedMap
231
+ def delete rid
232
+ r = Api.execute( database, session_id: session ){ "delete from #{rid}" }
233
+ success = r == [{ :count => 1 }]
234
+ end
235
+
236
+ # ------------------------------ transmit ------------------------------------------------------ #
237
+ # transmits a command which potentially modifies the database
192
238
  #
193
- # In case of an Error, anything is rolled back and nil is returned
239
+ # Uses the given session_id for transaction-based operations
194
240
  #
195
- def self.property database, type, **args
196
-
197
- begin_transaction database
198
- success = args.map do | name, format |
199
- r= execute(database) {" create property #{type.to_s}.#{name.to_s} #{format.to_s} " } &.first
200
- if r.nil?
201
- false
202
- else
203
- r.keys == [ :propertyName, :typeName, :operation ] && r[:operation] == 'create property'
204
- end
205
- end.uniq
206
- if success == [true]
207
- commit database
208
- true
241
+ # Otherwise just performs the operation
242
+
243
+ def transmit &block
244
+ response = Api.execute database, session_id: session, &block
245
+ if response.is_a? Hash
246
+ _allocate_model res
209
247
  else
210
- rollback database
248
+ response
211
249
  end
212
-
213
-
214
- end
215
-
216
- # ------------------------------ index ------------------------------------------------- #
217
- def self.index database, type, name , *properties
218
- properties = properties.map( &:to_s )
219
- unique_requested = "unique" if properties.delete("unique")
220
- unique_requested = "notunique" if properties.delete("notunique" )
221
- automatic = true if
222
- properties << name if properties.empty?
223
250
  end
224
-
225
- def delete rid
226
- r = Api.execute( database ){ "delete from #{rid}" }
227
- success = r == [{ :count => 1 }]
228
- end
229
-
251
+ # ------------------------------ execute ------------------------------------------------------ #
230
252
  # execute a command which modifies the database
231
253
  #
232
254
  # The operation is performed via Transaction/Commit
233
255
  # If an Error occurs, its rolled back
234
256
  #
257
+ # If a transaction is already active, a nested transation is initiated
258
+ #
235
259
  def execute &block
236
- Api.begin_transaction database
237
- response = Api.execute database, &block
238
- # puts response.inspect # debugging
260
+ # initiate a new transaction
261
+ s= Api.begin_transaction database
262
+ response = Api.execute database, session_id: s, &block
239
263
  r= if response.is_a? Hash
240
- _allocate_model res
241
- # elsif response.is_a? Array
242
- # remove empty results
243
- # response.delete_if{|y| y.empty?}
244
- # response.map do | res |
245
- # if res.key? :"@rid"
246
- # allocate_model res
247
- # else
248
- # res
249
- # end
250
- # end
264
+ _allocate_model response
251
265
  else
252
266
  response
253
267
  end
254
- Api.commit database
255
- r # return associated array of Arcade::Base-objects
268
+ if Api.commit( database, session_id: s) == 204
269
+ r # return associated array of Arcade::Base-objects
270
+ else
271
+ []
272
+ end
256
273
  rescue Dry::Struct::Error, Arcade::QueryError => e
257
- Api.rollback database
258
- logger.error "Execution FAILED --> #{e.exception}"
274
+ Api.rollback database, session_id: s, log: false
275
+ logger.info "Execution FAILED --> Status #{e.status}"
259
276
  [] # return empty result
260
277
  end
261
278
 
@@ -264,7 +281,7 @@ module Arcade
264
281
  # detects database-records and allocates them as model-objects
265
282
  #
266
283
  def query query_object
267
- Api.query database, query_object.to_s
284
+ Api.query database, query_object.to_s, session_id: session
268
285
  end
269
286
 
270
287
  # returns an array of rid's (same logic as create)
@@ -272,11 +289,13 @@ module Arcade
272
289
 
273
290
  content = attributes.empty? ? "" : "CONTENT #{attributes.to_json}"
274
291
  cr = ->( f, t ) do
275
- edges = Api.execute( database, "create edge #{edge_class} from #{f.rid} to #{t.rid} #{content}").allocate_model(false)
276
- #else
277
- # logger.error "Could not create Edge #{edge_class} from #{f} to #{t}"
278
- ## logger.error edges.to_s
279
- #end
292
+ begin
293
+ cmd = -> (){ "create edge #{edge_class} from #{f.rid} to #{t.rid} #{content}" }
294
+ edges = transmit( &cmd ).allocate_model(false)
295
+ rescue Arcade::QueryError => e
296
+ raise unless e.message =~ /Found duplicate key/
297
+ puts "#"+e.detail.split("#").last[0..-3]
298
+ end
280
299
  end
281
300
  from = [from] unless from.is_a? Array
282
301
  to = [to] unless to.is_a? Array
@@ -287,52 +306,12 @@ module Arcade
287
306
 
288
307
  end
289
308
 
290
-
291
- # query all: select @rid, * from {database}
292
-
293
- # not used
294
- # def get_schema
295
- # query( "select from schema:types" ).map do |a|
296
- # puts "a: #{a}"
297
- # class_name = a["name"]
298
- # inherent_class = a["parentTypes"].empty? ? [Object,nil] : a["parentTypes"].map(&:camelcase_and_namespace)
299
- # namespace, type_name = a["type"].camelcase_and_namespace
300
- # namespace= Arcade if namespace.nil?
301
- # klass= Dry::Core::ClassBuilder.new( name: type_name,
302
- # parent: nil,
303
- # namespace: namespace).call
304
- # end
305
- # rescue NameError
306
- # logger.error "Dataset type #{e} not defined."
307
- # raise
308
- # end
309
- # Postgres is not implemented
310
- # connects to the database and initialises @connection
311
- def connection
312
- @connection
309
+ def session
310
+ @session_id
313
311
  end
314
312
 
315
- def connect environment=:development # environments: production devel test
316
- if [:production, :development, :test].include? environment
317
-
318
- # connect through the ruby postgres driver
319
- # c= PG::Connection.new dbname: Config.database[environment],
320
- # user: Config.username[environment],
321
- # password: Config.password[environment],
322
- # host: Config.pg[:host],
323
- # port: Config.pg[:port]
324
- #
325
- end
326
- rescue PG::ConnectionBad => e
327
- if e.to_s =~ /Credentials/
328
- logger.error "NOT CONNECTED ! Either Database is not present or credentials (#{ Config.username[environment]} / #{Config.password[environment]}) are wrong"
329
- nil
330
- else
331
- raise
332
- end
333
- end # def
334
-
335
-
336
-
313
+ def session?
314
+ !session.nil?
315
+ end
337
316
  end # class
338
317
  end # module