Class: Arcade::Database
- Inherits:
-
Object
- Object
- Arcade::Database
- Extended by:
- Dry::Core::ClassAttributes
- Includes:
- Logging, Support::Model
- Defined in:
- lib/arcade/database.rb
Overview
Implements the Database-Adapter
currently, only attributes of type String are supported
{Database-instance}.database points to the connected Aradedb-database
DB.hi
Instance Method Summary collapse
-
#begin_transaction ⇒ Object
—————————— transaction —————————————————– # Encapsulates simple transactions.
-
#commit ⇒ Object
—————————— commit —————————————————– #.
-
#create(type, **params) ⇒ Object
———— create ———– ## not supported anymore by the api returns an rid of the successfully created vertex or document.
-
#create_edge(edge_class, from:, to:, **attributes) ⇒ Object
returns an array of rid’s (same logic as create).
-
#create_type(kind, type, **args) ⇒ Object
(also: #create_class)
———— create type ———– returns an Array Example: > create_type :vertex, :my_vertex => [“operation”=>“create vertex type”].
- #database ⇒ Object
-
#delete(rid) ⇒ Object
—————————— delete —————————————————— #.
-
#drop_type(type) ⇒ Object
———— drop type ———– delete any record prior to the attempt to drop a type.
-
#execute(&block) ⇒ Object
—————————— execute —————————————————— # execute a command which modifies the database.
-
#get(*rid) ⇒ Object
—————————— get —————————————————— # Get fetches the record associated with the rid given as parameter.
-
#hierarchy(type: 'vertex') ⇒ Object
———— hierarchy ————- returns an Array of types.
- #indexes(refresh = false) ⇒ Object
-
#initialize(environment = :development) ⇒ Database
constructor
A new instance of Database.
-
#insert(**params) ⇒ Object
—————————— insert —————————————————— #.
-
#query(query_object) ⇒ Object
returns an array of results.
-
#rollback ⇒ Object
—————————— rollback —————————————————– #.
- #session ⇒ Object
- #session? ⇒ Boolean
-
#transmit(&block) ⇒ Object
—————————— transmit —————————————————— # transmits a command which potentially modifies the database.
-
#types(refresh = false) ⇒ Object
———— types ————…
Methods included from Support::Model
#_allocate_model, #resolve_edge_name
Methods included from Logging
Constructor Details
#initialize(environment = :development) ⇒ Database
Returns a new instance of Database.
19 20 21 22 23 24 25 26 27 |
# File 'lib/arcade/database.rb', line 19 def initialize environment=:development self.class.configure_logger( Config.logger ) if self.class.environment.nil? # class attribute is set on the first call # further instances of Database share the same environment self.class.environment environment end @session_id = nil # declare session_id self.class.namespace Object.const_get( Config.namespace ) end |
Instance Method Details
#begin_transaction ⇒ Object
—————————— transaction —————————————————– #
Encapsulates simple transactions
nested transactions are not supported.
* use the low-leve api.begin_tranaction for that purpose
* reuses an existing transaction
138 139 140 |
# File 'lib/arcade/database.rb', line 138 def begin_transaction @session_id ||= Api.begin_transaction database end |
#commit ⇒ Object
—————————— commit —————————————————– #
142 143 144 145 146 |
# File 'lib/arcade/database.rb', line 142 def commit r = Api.commit( database, session_id: session) @session_id = nil true if r == 204 end |
#create(type, **params) ⇒ Object
———— create ———– ## not supported anymore by the api returns an rid of the successfully created vertex or document
Parameter: name of the vertex or document type
Hash of attributes
Example: > DB.create :my_vertex, a: 14, name: "Hugo"
=> "#177:0"
169 170 171 172 |
# File 'lib/arcade/database.rb', line 169 def create type, **params # uses API Api.create_document database, type, session_id: session, **params end |
#create_edge(edge_class, from:, to:, **attributes) ⇒ Object
returns an array of rid’s (same logic as create)
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/arcade/database.rb', line 289 def create_edge edge_class, from:, to:, **attributes content = attributes.empty? ? "" : "CONTENT #{attributes.to_json}" cr = ->( f, t ) do begin cmd = -> (){ "create edge #{edge_class} from #{f.rid} to #{t.rid} #{content}" } edges = transmit( &cmd ).allocate_model(false) rescue Arcade::QueryError => e raise unless e. =~ /Found duplicate key/ puts "#"+e.detail.split("#").last[0..-3] end end from = [from] unless from.is_a? Array to = [to] unless to.is_a? Array from.map do | from_record | to.map { | to_record | cr[ from_record, to_record ] if to_record.rid? } if from_record.rid? end.flatten end |
#create_type(kind, type, **args) ⇒ Object Also known as: create_class
———— create type ———–
returns an Array
Example: > create_type :vertex, :my_vertex
=> [{"typeName"=>"my_vertex", "operation"=>"create vertex type"}]
takes additional arguments: extends: '<a supertype>' (for inheritance)
bucket: <a list of bucket-id's >
buckets: <how many bukets to assign>
additional arguments are just added to the command
its aliased as ‘create_class`
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/arcade/database.rb', line 98 def create_type kind, type, **args exe = -> do case kind.to_s.downcase when /^v/ "create vertex type #{type} " when /^d/ "create document type #{type} " when /^e/ "create edge type #{type} " end.concat( args.map{|x,y| "#{x} #{y} "}.join) end dbe= Api.execute database, &exe types( true ) # update cached schema dbe rescue Arcade::QueryError => e if e. =~/Type\s+.+\salready\s+exists/ Arcade::Database.logger.debug "Database type #{type} already present" else raise end end |
#database ⇒ Object
29 30 31 |
# File 'lib/arcade/database.rb', line 29 def database @database ||= Config.database[self.class.environment] end |
#delete(rid) ⇒ Object
—————————— delete —————————————————— #
Delete the specified rid
232 233 234 235 |
# File 'lib/arcade/database.rb', line 232 def delete rid r = Api.execute( database, session_id: session ){ "delete from #{rid}" } success = r == [{ :count => 1 }] end |
#drop_type(type) ⇒ Object
———— drop type ———–
delete any record prior to the attempt to drop a type.
The `unsafe` option is not implemented.
127 128 129 |
# File 'lib/arcade/database.rb', line 127 def drop_type type Api.execute database, "drop type #{type} if exists" end |
#execute(&block) ⇒ Object
—————————— execute —————————————————— # execute a command which modifies the database
The operation is performed via Transaction/Commit If an Error occurs, its rolled back
If a transaction is already active, a nested transation is initiated
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/arcade/database.rb', line 260 def execute &block # initiate a new transaction s= Api.begin_transaction database response = Api.execute database, session_id: s, &block r= if response.is_a? Hash _allocate_model response else response end if Api.commit( database, session_id: s) == 204 r # return associated array of Arcade::Base-objects else [] end rescue Dry::Struct::Error, Arcade::QueryError => e Api.rollback database, session_id: s, log: false logger.fatal "Execution FAILED --> Status #{e}" [] # return empty result end |
#get(*rid) ⇒ Object
—————————— get —————————————————— # Get fetches the record associated with the rid given as parameter.
The rid is accepted as
DB.get "#123:123", DB.get "123:123" or DB.get 123, 123
Links are autoloaded (can be suppressed by the optional Block (false))
puts DB.get( 19,0 ) <my_document: emb : [“<my_alist: name : record 1, number : 1>”, “<my_alist: name : record 2, number : 2>”]> puts DB.get( 19,0 ){ false } <my_document: emb : [“#33:0”, “#34:0”]>
217 218 219 220 221 222 223 224 225 226 |
# File 'lib/arcade/database.rb', line 217 def get *rid autocomplete = block_given? ? yield : true rid = rid.join(':') rid = rid[1..-1] if rid[0]=="#" if rid.rid? Api.query( database, "select from #{rid}", session_id: session ).first &.allocate_model(autocomplete) else raise Arcade::QueryError "Get requires a rid input", caller end end |
#hierarchy(type: 'vertex') ⇒ Object
———— hierarchy ————-
returns an Array of types
each entry is an Array
=> [["test"], ["test1", "test2"]] (using the example above)
Parameter: type -- one of 'vertex', 'document', 'edge'
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/arcade/database.rb', line 64 def hierarchy type: 'vertex' # uses API # gets all types depending on the parent-type pt = ->( s ) { types.find_all{ |x| x[:parentTypes] &.include?(s) }.map{ |v| v[:name] } } # takes an array of base-types. gets recursivly all childs child_types = -> (base_types) do base_types.map do | bt | if pt[ bt ].empty? [ bt ] else [bt, child_types[ pt[ bt ] ] ].flatten end end end # gets child-types for all base-types child_types[ types.find_all{ |x| !x[:parentTypes] && x[:type] == type.to_s }.map{ |v| v[:name] } ] end |
#indexes(refresh = false) ⇒ Object
53 54 55 |
# File 'lib/arcade/database.rb', line 53 def indexes refresh=false types(refresh).find_all{|x| x.key? :indexes }.map{|y| y[:indexes]}.flatten end |
#insert(**params) ⇒ Object
—————————— insert —————————————————— #
translates the given parameters to INSERT INTO [TYPE:]<type>|BUCKET:<bucket>|INDEX:<index>
[(<field>[,]*) VALUES (<expression>[,]*)[,]*]|
[CONTENT {<JSON>}|[{<JSON>}[,]*]]
:from and :return are not supported
If a transaction is active, the insert is executed in that context. Nested transactions are not supported
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/arcade/database.rb', line 185 def insert **params content_params = params.except( :type, :bucket, :index, :from, :return, :session_id ) target_params = params.slice( :type, :bucket, :index ) # session_id = params[:session_id] # extraxt session_id --> future-use? if target_params.empty? raise "Could not insert: target missing (type:, bucket:, index:)" elsif content_params.empty? logger.error "Nothing to Insert" else content = "CONTENT #{ content_params.to_json }" target = target_params.map{|y,z| y==:type ? z : "#{y.to_s} #{ z } "}.join result = Api.execute( database, session_id: session ){ "INSERT INTO #{target} #{content} "} result &.first.allocate_model(false) end end |
#query(query_object) ⇒ Object
returns an array of results
detects database-records and allocates them as model-objects
284 285 286 |
# File 'lib/arcade/database.rb', line 284 def query query_object Api.query database, query_object.to_s, session_id: session end |
#rollback ⇒ Object
—————————— rollback —————————————————– #
150 151 152 153 154 155 156 |
# File 'lib/arcade/database.rb', line 150 def rollback r = Api.rollback( database, session_id: session) @session_id = nil true if r == 500 rescue HTTPX::HTTPError => e raise end |
#session ⇒ Object
310 311 312 |
# File 'lib/arcade/database.rb', line 310 def session @session_id end |
#session? ⇒ Boolean
314 315 316 |
# File 'lib/arcade/database.rb', line 314 def session? !session.nil? end |
#transmit(&block) ⇒ Object
—————————— transmit —————————————————— # transmits a command which potentially modifies the database
Uses the given session_id for transaction-based operations
Otherwise just performs the operation
244 245 246 247 248 249 250 251 |
# File 'lib/arcade/database.rb', line 244 def transmit &block response = Api.execute database, session_id: session, &block if response.is_a? Hash _allocate_model res else response end end |
#types(refresh = false) ⇒ Object
———— types ————… returns an Array of type-attributes [:type=>“document”, :type=>“vertex”, :type=>“vertex”, href=""test1"">parentTypes=>, :name=>“test2”, :type=>“vertex”]
40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/arcade/database.rb', line 40 def types refresh=false # uses API if @types.nil? || refresh @types = Api.query(database, "select from schema:types" ) .map{ |y| y.delete_if{|_,b,| b.blank? } } # eliminate empty entries end @types ## upon startup, this is the first access to the database-server rescue NoMethodError => e logger.fatal "Could not read Database Types. \n Is the database running?" Kernel.exit end |