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
Class Method Summary collapse
-
.index(database, type, name, *properties) ⇒ Object
—————————— index ————————————————- #.
-
.property(database, type, **args) ⇒ Object
—————————— property ————————————————- # Adds properties to the type.
Instance Method Summary collapse
-
#connect(environment = :development) ⇒ Object
environments: production devel test.
-
#connection ⇒ Object
Postgres is not implemented connects to the database and initialises @connection.
-
#create(type, **params) ⇒ Object
———— create ———– 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
-
#drop_type(type) ⇒ Object
———— drop type ———– delete any record prior to the attempt to drop a type.
-
#execute(&block) ⇒ Object
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 ⇒ Object
-
#initialize(environment = :development) ⇒ Database
constructor
A new instance of Database.
- #insert(**params) ⇒ Object
-
#query(query_object) ⇒ Object
returns an array of results.
-
#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 ) @connection = connect environment 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 self.class.namespace Object.const_get( Config.namespace ) end |
Class Method Details
.index(database, type, name, *properties) ⇒ Object
—————————— index ————————————————- #
222 223 224 225 226 227 228 |
# File 'lib/arcade/database.rb', line 222 def self.index database, type, name , *properties properties = properties.map( &:to_s ) unique_requested = "unique" if properties.delete("unique") unique_requested = "notunique" if properties.delete("notunique" ) automatic = true if properties << name if properties.empty? end |
.property(database, type, **args) ⇒ Object
—————————— property ————————————————- # Adds properties to the type
call via
Api.property <database>, <type>, name1: a_format , name2: a_format
Format is one of
Boolean, Integer, Short, Long, Float, Double, String
Datetime, Binary, Byte, Decimal, Link
Embedded, EmbeddedList, EmbeddedMap
In case of an Error, anything is rolled back and nil is returned
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/arcade/database.rb', line 200 def self.property database, type, **args begin_transaction database success = args.map do | name, format | r= execute(database) {" create property #{type.to_s}.#{name.to_s} #{format.to_s} " } &.first if r.nil? false else r.keys == [ :propertyName, :typeName, :operation ] && r[:operation] == 'create property' end end.uniq if success == [true] commit database true else rollback database end end |
Instance Method Details
#connect(environment = :development) ⇒ Object
environments: production devel test
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/arcade/database.rb', line 344 def connect environment=:development # environments: production devel test if [:production, :development, :test].include? environment # connect through the ruby postgres driver # c= PG::Connection.new dbname: Config.database[environment], # user: Config.username[environment], # password: Config.password[environment], # host: Config.pg[:host], # port: Config.pg[:port] # end rescue PG::ConnectionBad => e if e.to_s =~ /Credentials/ logger.error "NOT CONNECTED ! Either Database is not present or credentials (#{ Config.username[environment]} / #{Config.password[environment]}) are wrong" nil else raise end end |
#connection ⇒ Object
Postgres is not implemented connects to the database and initialises @connection
340 341 342 |
# File 'lib/arcade/database.rb', line 340 def connection @connection end |
#create(type, **params) ⇒ Object
———— create ———– 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"
142 143 144 145 |
# File 'lib/arcade/database.rb', line 142 def create type, **params # uses API Api.create_document database, type, **params end |
#create_edge(edge_class, from:, to:, **attributes) ⇒ Object
returns an array of rid’s (same logic as create)
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
# File 'lib/arcade/database.rb', line 290 def create_edge edge_class, from:, to:, **attributes content = attributes.empty? ? "" : "CONTENT #{attributes.to_json}" cr = ->( f, t ) do begin edges = Api.execute( database, "create edge #{edge_class} from #{f.rid} to #{t.rid} #{content}").allocate_model(false) rescue HTTPX::HTTPError => e # if e.status == 503 # puts e.status # puts e.message # puts e.message.class # end raise unless e. =~ /Found duplicate key/ puts "#"+e..split("#").last[0..-3] end #else # logger.error "Could not create Edge #{edge_class} from #{f} to #{t}" ## logger.error edges.to_s #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`
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/arcade/database.rb', line 99 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 db= Api.execute database, &exe types( true ) # update cached schema db rescue HTTPX::HTTPError => e # puts "ERROR: #{e.message.to_s}" if e.status == 500 && e..to_s =~ /already exists/ Arcade::Database.logger.warn "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
230 231 232 233 |
# File 'lib/arcade/database.rb', line 230 def delete rid r = Api.execute( database ){ "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 nit implemented.
129 130 131 |
# File 'lib/arcade/database.rb', line 129 def drop_type type Api.execute database, "drop type #{type} if exists" end |
#execute(&block) ⇒ Object
execute a command which modifies the database
The operation is performed via Transaction/Commit If an Error occurs, its rolled back
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/arcade/database.rb', line 240 def execute &block s = Api.begin_transaction database # begin response = Api.execute database, nil, s, &block # rescue HTTPX::HTTPError => e # raise e.message # puts e.methods # puts e.status # puts e.response # puts e.message # puts e.exception # puts e.cause # end # puts response.inspect # debugging r= if response.is_a? Hash _allocate_model res # elsif response.is_a? Array # remove empty results # response.delete_if{|y| y.empty?} # response.map do | res | # if res.key? :"@rid" # allocate_model res # else # res # end # end else response end if Api.commit( database, s) == 204 r # return associated array of Arcade::Base-objects else [] end rescue Dry::Struct::Error, HTTPX::HTTPError, Arcade::QueryError => e Api.rollback database, s logger.error "Execution FAILED --> Status #{e.status}" # logger.error "Execution FAILED --> #{e.exception.message}" [] # 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”]>
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/arcade/database.rb', line 176 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}" ).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'
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/arcade/database.rb', line 65 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 ⇒ Object
54 55 56 |
# File 'lib/arcade/database.rb', line 54 def indexes DB.types.find{|x| x.key? :indexes }[:indexes] end |
#insert(**params) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/arcade/database.rb', line 147 def insert **params content_params = params.except( :type, :bucket, :index, :from, :return ) target_params = params.slice( :type, :bucket, :index ) if target_params.empty? logger.error "Could not insert: target mising (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 Api.execute( database, "INSERT INTO #{target} #{content} ") &.first.allocate_model(false) end end |
#query(query_object) ⇒ Object
returns an array of results
detects database-records and allocates them as model-objects
285 286 287 |
# File 'lib/arcade/database.rb', line 285 def query query_object Api.query database, query_object.to_s 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 52 |
# 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{ |x| x.transform_keys &:to_sym } # symbolize keys .map{ |y| y.delete_if{|_,b,| b.empty? } } # eliminate empty entries end $types ## upom 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 |