arcadedb 0.4 → 0.5.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +2 -36
- data/README.md +105 -30
- data/arcade.yml +4 -4
- data/bin/console +16 -16
- data/iruby/.ipynb_checkpoints/01-start-and-end-of-datarows-checkpoint.ipynb +258 -0
- data/iruby/01-start-and-end-of-datarows.ipynb +203 -0
- data/iruby/db-console.rb +73 -0
- data/lib/arcade/api/operations.rb +26 -65
- data/lib/arcade/api/primitives.rb +57 -29
- data/lib/arcade/base.rb +72 -39
- data/lib/{config.rb → arcade/config.rb} +5 -6
- data/lib/arcade/database.rb +104 -154
- data/lib/arcade/errors.rb +8 -0
- data/lib/arcade/match.rb +162 -0
- data/lib/{query.rb → arcade/query.rb} +34 -18
- data/lib/{support → arcade/support}/conversions.rb +1 -0
- data/lib/{support → arcade/support}/model.rb +20 -15
- data/lib/arcade/version.rb +1 -1
- data/lib/arcade.rb +11 -11
- data/lib/model/document.rb +22 -0
- data/lib/model/edge.rb +12 -0
- data/lib/model/vertex.rb +67 -48
- metadata +15 -12
- data/lib/match.rb +0 -216
- /data/lib/{init.rb → arcade/init.rb} +0 -0
- /data/lib/{support → arcade/support}/class.rb +0 -0
- /data/lib/{support → arcade/support}/object.rb +0 -0
- /data/lib/{support → arcade/support}/sql.rb +0 -0
- /data/lib/{support → arcade/support}/string.rb +0 -0
@@ -23,34 +23,38 @@ module Arcade
|
|
23
23
|
if response.is_a? Hash
|
24
24
|
# save rid to a safe place
|
25
25
|
temp_rid = response.delete :"@rid"
|
26
|
-
type
|
27
|
-
cat
|
26
|
+
type = response.delete :"@type"
|
27
|
+
cat = response.delete :"@cat"
|
28
28
|
|
29
29
|
return response if type.nil?
|
30
30
|
temp_rid = "#0:0" if temp_rid.nil?
|
31
31
|
type = "d" if type.nil?
|
32
32
|
# extract type infos and convert to database-name
|
33
|
-
|
34
|
-
|
33
|
+
namespace, type_name = type.camelcase_and_namespace
|
34
|
+
namespace = self.namespace if namespace.nil?
|
35
35
|
# autoconvert rid's in attributes to model-records (exclude edges!)
|
36
36
|
if auto && !(cat.to_s =='e')
|
37
37
|
response.transform_values! do |x|
|
38
38
|
case x
|
39
39
|
when String
|
40
|
-
x.rid? ? x.load_rid : x
|
40
|
+
x.rid? ? x.load_rid : x # follow links
|
41
41
|
when Array
|
42
|
+
a =[]
|
42
43
|
x.map do| y |
|
43
|
-
|
44
|
-
y.
|
45
|
-
|
46
|
-
y.
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
# Thread.new do ## thread or fiber decrease the performance significantly.
|
45
|
+
if y.is_a?(Hash) && y.include?(:@type) # if embedded documents are present, load them
|
46
|
+
y.allocate_model(false)
|
47
|
+
elsif y.rid? # if links are present, load the object
|
48
|
+
y.load_rid(false) # do not autoload further records, prevents from recursive locking
|
49
|
+
else
|
50
|
+
y
|
51
|
+
end
|
52
|
+
# end
|
50
53
|
end
|
51
54
|
when Hash
|
52
55
|
if x.include?(:@type)
|
53
|
-
x.allocate_model(false)
|
56
|
+
#x.allocate_model(false)
|
57
|
+
_allocate_model(x,false)
|
54
58
|
else
|
55
59
|
x.transform_values!{|z| z.rid? ? z.load_rid(false) : z }
|
56
60
|
end
|
@@ -60,7 +64,7 @@ module Arcade
|
|
60
64
|
end
|
61
65
|
end
|
62
66
|
# choose the appropriate class
|
63
|
-
klass= Dry::Core::ClassBuilder.new( name: type_name, parent:
|
67
|
+
klass= Dry::Core::ClassBuilder.new( name: type_name, parent: nil, namespace: namespace ).call
|
64
68
|
#
|
65
69
|
begin
|
66
70
|
# create a new object of that class with the appropriate attributes
|
@@ -74,10 +78,11 @@ module Arcade
|
|
74
78
|
elsif response.is_a? Array
|
75
79
|
puts "Allocate_model..detected array"
|
76
80
|
## recursive behavior, just in case
|
77
|
-
response.map{ | y | _allocate_model y }
|
81
|
+
response.map{ | y | _allocate_model y, auto }
|
78
82
|
elsif response.rid?
|
79
83
|
# Autoload rid's
|
80
84
|
response.load_rid
|
85
|
+
# auto ? response.load_rid : response
|
81
86
|
else
|
82
87
|
response
|
83
88
|
end
|
data/lib/arcade/version.rb
CHANGED
data/lib/arcade.rb
CHANGED
@@ -16,21 +16,21 @@ require 'yaml'
|
|
16
16
|
require 'securerandom'
|
17
17
|
require 'httpx'
|
18
18
|
require 'arcade/errors'
|
19
|
-
require_relative '../lib/support/object'
|
20
|
-
require_relative '../lib/support/string'
|
21
|
-
require_relative '../lib/support/class'
|
22
|
-
require_relative '../lib/support/sql'
|
23
|
-
require_relative '../lib/support/model'
|
24
|
-
require_relative '../lib/arcade/
|
25
|
-
require_relative '../lib/config'
|
26
|
-
require_relative '../lib/support/conversions'
|
19
|
+
require_relative '../lib/arcade/support/object'
|
20
|
+
require_relative '../lib/arcade/support/string'
|
21
|
+
require_relative '../lib/arcade/support/class'
|
22
|
+
require_relative '../lib/arcade/support/sql'
|
23
|
+
require_relative '../lib/arcade/support/model'
|
24
|
+
require_relative '../lib/arcade/support/conversions'
|
27
25
|
require_relative '../lib/arcade/api/primitives'
|
28
26
|
require_relative '../lib/arcade/api/operations'
|
29
27
|
require_relative '../lib/arcade/base'
|
28
|
+
require_relative '../lib/arcade/logging'
|
29
|
+
require_relative '../lib/arcade/config'
|
30
30
|
require_relative '../lib/arcade/database'
|
31
|
-
require_relative '../lib/
|
31
|
+
require_relative '../lib/arcade/match'
|
32
|
+
require_relative '../lib/arcade/query'
|
33
|
+
require_relative '../lib/arcade/init'
|
32
34
|
require_relative "../lib/models"
|
33
|
-
require_relative '../lib/query'
|
34
|
-
require_relative '../lib/match'
|
35
35
|
require_relative '../lib/railtie' if defined? Rails::Railtie
|
36
36
|
|
data/lib/model/document.rb
CHANGED
@@ -6,5 +6,27 @@ module Arcade
|
|
6
6
|
# def accepted_methods
|
7
7
|
#
|
8
8
|
# end
|
9
|
+
def self.create **attributes
|
10
|
+
Api.create_document db.database, database_name, session_id: db.session, **attributes
|
11
|
+
end
|
12
|
+
|
13
|
+
=begin
|
14
|
+
Document.delete fires a "delete vertex" command to the database.
|
15
|
+
To remove all records use »all: true« as argument
|
16
|
+
|
17
|
+
The "where" parameter is optional
|
18
|
+
=end
|
19
|
+
def self.delete where: {} , **args
|
20
|
+
if args[:all] == true
|
21
|
+
where = {}
|
22
|
+
else
|
23
|
+
where.merge!(args) if where.is_a?(Hash)
|
24
|
+
return 0 if where.empty?
|
25
|
+
end
|
26
|
+
# query returns [{count => n }]
|
27
|
+
# puts "delete from #{database_name} #{compose_where(where)}"
|
28
|
+
db.transmit { "delete from `#{database_name}` #{compose_where(where)}" } &.first[:count] rescue 0
|
29
|
+
end
|
30
|
+
|
9
31
|
end
|
10
32
|
end
|
data/lib/model/edge.rb
CHANGED
@@ -13,6 +13,18 @@ module Arcade
|
|
13
13
|
#
|
14
14
|
def self.create from:, to:, **attr
|
15
15
|
db.create_edge database_name, from: from, to: to, **attr
|
16
|
+
rescue Arcade::QueryError => e
|
17
|
+
if e.message =~ /Duplicated key\s+.+\sfound on index/
|
18
|
+
if e.args.keys.first == :exceptionArgs
|
19
|
+
# return the previously assigned edge
|
20
|
+
e.args[:exceptionArgs].split('|').last.load_rid
|
21
|
+
else
|
22
|
+
raise
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
|
16
28
|
end
|
17
29
|
|
18
30
|
def delete
|
data/lib/model/vertex.rb
CHANGED
@@ -13,45 +13,46 @@ module Arcade
|
|
13
13
|
end
|
14
14
|
## ----------------------------------------- Class Methods------------------------------------ ##
|
15
15
|
# #
|
16
|
+
|
16
17
|
=begin
|
17
|
-
|
18
|
+
Creates a Vertex-Instance.
|
19
|
+
Similar to `Vertex#insert`.
|
18
20
|
|
19
|
-
|
21
|
+
Difference is the presence of a `created` property, a timestamp set to the time and date of creation.
|
22
|
+
=end
|
23
|
+
|
24
|
+
def self.create timestamp: true, **args
|
25
|
+
#t= timestamp ? ", created = Date(#{DateTime.now.to_i}) " : ""
|
26
|
+
t= timestamp ? ", created = sysdate() " : ""
|
27
|
+
# db.transmit { "create VERTEX #{database_name} set #{args.map{|x,y| [x,y.to_or].join("=")}.join(', ')+t}" } &.first.allocate_model(false)
|
28
|
+
Api.create_document db.database, database_name, session_id: db.session, **args
|
29
|
+
end
|
20
30
|
|
21
|
-
To remove a specific rid, use rid: "#nn:mmm" as argument
|
22
31
|
|
23
|
-
|
32
|
+
=begin
|
33
|
+
Vertex.delete fires a "delete vertex" command to the database.
|
34
|
+
To remove all records use »all: true« as argument
|
35
|
+
To remove a specific rid, use rid: "#nn:mmm" as argument
|
24
36
|
|
25
|
-
|
37
|
+
The "where" parameter is optional
|
26
38
|
|
39
|
+
Example:
|
40
|
+
ExtraNode.delete where: { item: 67 } == ExtraNode.delete item: 67
|
27
41
|
=end
|
28
42
|
def self.delete where: {} , **args
|
29
43
|
if args[:all] == true
|
30
44
|
where = {}
|
31
45
|
elsif args[:rid].present?
|
32
|
-
return db.
|
46
|
+
return db.transmit { "delete from #{args[:rid]}" }.first["count"]
|
33
47
|
else
|
34
48
|
where.merge!(args) if where.is_a?(Hash)
|
35
49
|
return 0 if where.empty?
|
36
50
|
end
|
37
51
|
# query returns [{count => n }]
|
38
|
-
|
52
|
+
# puts "delete from #{database_name} #{compose_where(where)}"
|
53
|
+
db.transmit { "delete from `#{database_name}` #{compose_where(where)}" } &.first[:count] rescue 0
|
39
54
|
end
|
40
55
|
|
41
|
-
=begin
|
42
|
-
Creates a Vertex-Instance.
|
43
|
-
Similar to `Vertex#insert`.
|
44
|
-
|
45
|
-
Difference is the presence of a `created` property, a timestamp set to the time and date of creation.
|
46
|
-
=end
|
47
|
-
|
48
|
-
def self.create timestamp: true, **args
|
49
|
-
#t= timestamp ? ", created = Date(#{DateTime.now.to_i}) " : ""
|
50
|
-
t= timestamp ? ", created = sysdate() " : ""
|
51
|
-
db.execute { "create VERTEX #{database_name} set #{args.map{|x,y| [x,y.to_or].join("=")}.join(', ')+t}" } &.first.allocate_model(false)
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
56
|
## get adjacent nodes based on a query on the actual model
|
56
57
|
|
57
58
|
|
@@ -71,22 +72,41 @@ module Arcade
|
|
71
72
|
def expand
|
72
73
|
self
|
73
74
|
end
|
74
|
-
#
|
75
|
-
|
75
|
+
# --------------------------------- Nodes ----------------------------------------------- #
|
76
|
+
# fetches adjacet nodes
|
77
|
+
# supported
|
78
|
+
# nodes in_or_out = :in, :out, :both, :inE, :outE
|
79
|
+
# depth = fetch the n'th node through travese
|
80
|
+
# via: = Arcade Database Type (the ruby class)
|
81
|
+
# where: = a condition
|
82
|
+
# inE, outE --> matches attributes on the edge
|
83
|
+
# in, out, both -> matches attributes on the adjacent vertex
|
84
|
+
# Example Strategie.first nodes where: {size: 10}
|
85
|
+
# "select both()[ size = 10 ] from #113:8 "
|
86
|
+
#
|
76
87
|
def nodes in_or_out=:both, depth= 1, via: nil , execute: true, **args
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
88
|
+
if depth <= 1
|
89
|
+
s= query.nodes in_or_out, via: via, **args
|
90
|
+
execute ? s.query &.select_result : s
|
91
|
+
else
|
92
|
+
travese in_or_out, depth: depth, start_at: depth-1, via: via, execute: execute, where: args[:where]
|
93
|
+
end
|
84
94
|
end
|
85
95
|
|
86
96
|
# Supports where: { where condition for edges }
|
87
|
-
def edges in_or_out = :both, depth= 1, via: nil , execute: true
|
88
|
-
|
89
|
-
|
97
|
+
def edges in_or_out = :both, depth= 1, via: nil , execute: true
|
98
|
+
|
99
|
+
v = in_or_out.to_s.delete_suffix 'E'
|
100
|
+
e = v + 'E'
|
101
|
+
edge_name = via.nil? ? "" : resolve_edge_name( via )
|
102
|
+
argument = "#{e}(#{edge_name})"
|
103
|
+
q= if depth > 1
|
104
|
+
repeated_argument = Array.new(depth -1 , "#{v}(#{edge_name})").join(".")
|
105
|
+
query.projection repeated_argument + "." + argument
|
106
|
+
else
|
107
|
+
query.projection argument
|
108
|
+
end
|
109
|
+
execute ? q.execute &.allocate_model : q
|
90
110
|
end
|
91
111
|
|
92
112
|
|
@@ -120,17 +140,17 @@ module Arcade
|
|
120
140
|
|
121
141
|
# get via-type-edges through in
|
122
142
|
def inE count=1, via:nil
|
123
|
-
|
143
|
+
edges :in, count, via: via
|
124
144
|
end
|
125
145
|
#
|
126
146
|
# get via-type-edges through out
|
127
147
|
def outE count=1, via:nil
|
128
|
-
|
148
|
+
edges :out, count, via: via
|
129
149
|
end
|
130
150
|
|
131
151
|
# get all via-type-edges
|
132
152
|
def bothE count=1, via:nil
|
133
|
-
|
153
|
+
edges :both, count, via: via
|
134
154
|
end
|
135
155
|
|
136
156
|
|
@@ -158,34 +178,33 @@ module Arcade
|
|
158
178
|
the_query.where where if where.present?
|
159
179
|
the_query.while "$depth < #{depth} " unless depth <=0
|
160
180
|
outer_query = Query.new from: the_query, where: "$depth >= #{start_at}"
|
161
|
-
|
162
|
-
outer_query.execute.allocate_model
|
163
|
-
else
|
164
|
-
# the_query.from self # complete the query by assigning self
|
165
|
-
the_query # returns the Query -traverse object
|
166
|
-
end
|
181
|
+
execute ? outer_query.execute.allocate_model : the_query # return only the traverse part
|
167
182
|
end
|
168
183
|
|
169
184
|
=begin
|
170
185
|
Assigns another Vertex via an EdgeClass. If specified, puts attributes on the edge.
|
171
186
|
|
187
|
+
`Vertex.assign via: Edge to: Vertex`
|
188
|
+
|
172
189
|
Returns the reloaded assigned vertex
|
173
190
|
|
174
191
|
Wrapper for
|
175
|
-
Edge.create
|
192
|
+
Edge.create from: self, to: a_vertex, some: attributes. on: the, edge: type }
|
176
193
|
|
177
194
|
returns the assigned vertex, thus enabling to chain vertices through
|
178
195
|
|
179
|
-
Vertex.assign() via: E ,
|
196
|
+
Vertex.assign() via: E , to: VertexClass.create()).assign( via: E, ... )
|
180
197
|
or
|
181
198
|
(1..100).each{|n| vertex = vertex.assign(via: E2, vertex: V2.create(item: n))}
|
182
199
|
=end
|
183
200
|
|
184
|
-
def assign vertex: , via: , **attributes
|
201
|
+
def assign vertex: nil , via: Arcade::Edge , **attributes
|
202
|
+
vertex = attributes[:to] if attributes.has_key? :to
|
203
|
+
raise "vertex not provided" if vertex.nil?
|
185
204
|
|
186
205
|
via.create from: self, to: vertex, **attributes
|
187
206
|
|
188
|
-
db.get vertex.rid
|
207
|
+
db.get vertex.rid unless vertex.is_a? Array # return the assigned vertex
|
189
208
|
rescue IndexError => e
|
190
209
|
db.logger.error "Edge not created, already present."
|
191
210
|
vertex # return the vertex (for chaining)
|
@@ -205,12 +224,12 @@ Format: < Classname: Edges, Attributes >
|
|
205
224
|
=end
|
206
225
|
def to_human
|
207
226
|
|
208
|
-
in_and_out =
|
227
|
+
in_and_out = "{#{inE.count}->}{->#{outE.count }}, "
|
209
228
|
|
210
229
|
#Default presentation of Arcade::Base::Model-Objects
|
211
230
|
|
212
231
|
"<#{self.class.to_s.snake_case}[#{rid}]:" +
|
213
|
-
in_and_out
|
232
|
+
in_and_out +
|
214
233
|
invariant_attributes.map do |attr, value|
|
215
234
|
v= case value
|
216
235
|
when Class
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arcadedb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hartmut Bischoff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -144,17 +144,27 @@ files:
|
|
144
144
|
- examples/relation_1__1.rb
|
145
145
|
- examples/relation_1__n.rb
|
146
146
|
- examples/relation_n_n.rb
|
147
|
+
- iruby/.ipynb_checkpoints/01-start-and-end-of-datarows-checkpoint.ipynb
|
148
|
+
- iruby/01-start-and-end-of-datarows.ipynb
|
149
|
+
- iruby/db-console.rb
|
147
150
|
- lib/arcade.rb
|
148
151
|
- lib/arcade/api/operations.rb
|
149
152
|
- lib/arcade/api/primitives.rb
|
150
153
|
- lib/arcade/base.rb
|
154
|
+
- lib/arcade/config.rb
|
151
155
|
- lib/arcade/database.rb
|
152
156
|
- lib/arcade/errors.rb
|
157
|
+
- lib/arcade/init.rb
|
153
158
|
- lib/arcade/logging.rb
|
159
|
+
- lib/arcade/match.rb
|
160
|
+
- lib/arcade/query.rb
|
161
|
+
- lib/arcade/support/class.rb
|
162
|
+
- lib/arcade/support/conversions.rb
|
163
|
+
- lib/arcade/support/model.rb
|
164
|
+
- lib/arcade/support/object.rb
|
165
|
+
- lib/arcade/support/sql.rb
|
166
|
+
- lib/arcade/support/string.rb
|
154
167
|
- lib/arcade/version.rb
|
155
|
-
- lib/config.rb
|
156
|
-
- lib/init.rb
|
157
|
-
- lib/match.rb
|
158
168
|
- lib/model/basicdocument.rb
|
159
169
|
- lib/model/basicedge.rb
|
160
170
|
- lib/model/basicvertex.rb
|
@@ -162,13 +172,6 @@ files:
|
|
162
172
|
- lib/model/edge.rb
|
163
173
|
- lib/model/vertex.rb
|
164
174
|
- lib/models.rb
|
165
|
-
- lib/query.rb
|
166
|
-
- lib/support/class.rb
|
167
|
-
- lib/support/conversions.rb
|
168
|
-
- lib/support/model.rb
|
169
|
-
- lib/support/object.rb
|
170
|
-
- lib/support/sql.rb
|
171
|
-
- lib/support/string.rb
|
172
175
|
- rails.md
|
173
176
|
- rails/arcade.rb
|
174
177
|
- rails/config.yml
|
data/lib/match.rb
DELETED
@@ -1,216 +0,0 @@
|
|
1
|
-
#require 'active_support/inflector'
|
2
|
-
|
3
|
-
module Arcade
|
4
|
-
######################## MatchConnection ###############################
|
5
|
-
|
6
|
-
MatchAttributes = Struct.new(:edge, :direction, :as, :count, :where, :while, :max_depth , :depth_alias, :path_alias, :optional )
|
7
|
-
|
8
|
-
# where and while can be composed incremental
|
9
|
-
# direction, as, connect and edge cannot be changed after initialisation
|
10
|
-
class MatchConnection
|
11
|
-
include Support::Sql
|
12
|
-
|
13
|
-
def initialize edge= nil, direction: :both, as: nil, count: 1, **args
|
14
|
-
|
15
|
-
the_edge = edge.is_a?( Class ) ? edge.ref_name : edge.to_s unless edge.nil? || edge == E
|
16
|
-
@q = MatchAttributes.new the_edge , # class
|
17
|
-
direction, # may be :both, :in, :out
|
18
|
-
as, # a string
|
19
|
-
count, # a number
|
20
|
-
args[:where],
|
21
|
-
args[:while],
|
22
|
-
args[:max_depth],
|
23
|
-
args[:depth_alias], # not implemented
|
24
|
-
args[:path_alias], # not implemented
|
25
|
-
args[:optional] # not implemented
|
26
|
-
end
|
27
|
-
|
28
|
-
def direction= dir
|
29
|
-
@q[:direction] = dir
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
def direction
|
34
|
-
fillup = @q[:edge].present? ? @q[:edge] : ''
|
35
|
-
case @q[:direction]
|
36
|
-
when :both
|
37
|
-
".both(#{fillup})"
|
38
|
-
when :in
|
39
|
-
".in(#{fillup})"
|
40
|
-
when :out
|
41
|
-
".out(#{fillup})"
|
42
|
-
when :both_vertex, :bothV
|
43
|
-
".bothV()"
|
44
|
-
when :out_vertex, :outV
|
45
|
-
".outV()"
|
46
|
-
when :in_vertex, :inV
|
47
|
-
".inV()"
|
48
|
-
when :both_edge, :bothE
|
49
|
-
".bothE(#{fillup})"
|
50
|
-
when :out_edge, :outE
|
51
|
-
".outE(#{fillup})"
|
52
|
-
when :in_edge, :outE
|
53
|
-
".inE(#{fillup})"
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
def count c=nil
|
59
|
-
if c
|
60
|
-
@q[:count] = c
|
61
|
-
else
|
62
|
-
@q[:count]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def max_depth d=nil
|
67
|
-
if d.nil?
|
68
|
-
@q[:max_depth].present? ? "maxDepth: #{@q[:max_depth] }" : nil
|
69
|
-
else
|
70
|
-
@q[:max_depth] = d
|
71
|
-
end
|
72
|
-
end
|
73
|
-
def edge
|
74
|
-
@q[:edge]
|
75
|
-
end
|
76
|
-
|
77
|
-
def compose
|
78
|
-
where_statement =( where.nil? || where.size <5 ) ? nil : "where: ( #{ generate_sql_list( @q[:where] ) })"
|
79
|
-
while_statement =( while_s.nil? || while_s.size <5) ? nil : "while: ( #{ generate_sql_list( @q[:while] )})"
|
80
|
-
|
81
|
-
ministatement = "{"+ [ as, where_statement, while_statement, max_depth].compact.join(', ') + "}"
|
82
|
-
ministatement = "" if ministatement=="{}"
|
83
|
-
|
84
|
-
(1 .. count).map{|x| direction }.join("") + ministatement
|
85
|
-
|
86
|
-
end
|
87
|
-
alias :to_s :compose
|
88
|
-
|
89
|
-
end # class
|
90
|
-
|
91
|
-
|
92
|
-
######################## MatchStatement ################################
|
93
|
-
|
94
|
-
MatchSAttributes = Struct.new(:match_class, :as, :where )
|
95
|
-
class MatchStatement
|
96
|
-
include Support
|
97
|
-
def initialize match_class, as: 0, **args
|
98
|
-
reduce_class = ->(c){ c.is_a?(Class) ? c.ref_name : c.to_s }
|
99
|
-
|
100
|
-
@q = MatchSAttributes.new( reduce_class[match_class], # class
|
101
|
-
as.respond_to?(:zero?) && as.zero? ? reduce_class[match_class].pluralize : as ,
|
102
|
-
args[ :where ])
|
103
|
-
|
104
|
-
@query_stack = [ self ]
|
105
|
-
end
|
106
|
-
|
107
|
-
def match_alias
|
108
|
-
"as: #{@q[:as]}"
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
# used for the first compose-statement of a compose-query
|
114
|
-
def compose_simple
|
115
|
-
where_statement = where.is_a?(String) && where.size <3 ? nil : "where: ( #{ generate_sql_list( @q[:where] ) })"
|
116
|
-
'{'+ [ "class: #{@q[:match_class]}", as , where_statement].compact.join(', ') + '}'
|
117
|
-
end
|
118
|
-
|
119
|
-
|
120
|
-
def << connection
|
121
|
-
@query_stack << connection
|
122
|
-
self # return MatchStatement
|
123
|
-
end
|
124
|
-
#
|
125
|
-
def compile &b
|
126
|
-
"match " + @query_stack.map( &:to_s ).join + return_statement( &b )
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
# executes the standard-case.
|
131
|
-
# returns
|
132
|
-
# * as: :hash : an array of hashes
|
133
|
-
# * as: :array : an array of hash-values
|
134
|
-
# * as :flatten: a simple array of hash-values
|
135
|
-
#
|
136
|
-
# The optional block is used to customize the output.
|
137
|
-
# All previously defiend »as«-Statements are provided though the control variable.
|
138
|
-
#
|
139
|
-
# Background
|
140
|
-
# A match query "Match {class aaa, as: 'aa'} return aa "
|
141
|
-
#
|
142
|
-
# returns [ aa: { result of the query, a Vertex or a value-item }, aa: {}...}, ...] ]
|
143
|
-
# (The standard case)
|
144
|
-
#
|
145
|
-
# A match query "Match {class aaa, as: 'aa'} return aa.name "
|
146
|
-
# returns [ aa.name: { name }, aa.name: { name }., ...] ]
|
147
|
-
#
|
148
|
-
# Now, execute( as: :flatten){ "aa.name" } returns
|
149
|
-
# [name1, name2 ,. ...]
|
150
|
-
#
|
151
|
-
#
|
152
|
-
# Return statements (examples from https://orientdb.org/docs/3.0.x/sql/SQL-Match.html)
|
153
|
-
# "person.name as name, friendship.since as since, friend.name as friend"
|
154
|
-
#
|
155
|
-
# " person.name + \" is a friend of \" + friend.name as friends"
|
156
|
-
#
|
157
|
-
# "$matches"
|
158
|
-
# "$elements"
|
159
|
-
# "$paths"
|
160
|
-
# "$pathElements"
|
161
|
-
#
|
162
|
-
#
|
163
|
-
def execute as: :hash, &b
|
164
|
-
r = V.db.execute{ compile &b }
|
165
|
-
case as
|
166
|
-
when :hash
|
167
|
-
r
|
168
|
-
when :array
|
169
|
-
r.map{|y| y.values}
|
170
|
-
when :flatten
|
171
|
-
r.map{|y| y.values}.orient_flatten
|
172
|
-
else
|
173
|
-
raise ArgumentError, "Specify parameter «as:» with :hash, :array, :flatten"
|
174
|
-
end
|
175
|
-
end
|
176
|
-
# def compose
|
177
|
-
#
|
178
|
-
# '{'+ [ "class: #{@q[:match_class]}",
|
179
|
-
# "as: #{@as}" , where, while_s,
|
180
|
-
# @maxdepth >0 ? "maxdepth: #{maxdepth}": nil ].compact.join(', ')+'}'
|
181
|
-
# end
|
182
|
-
|
183
|
-
alias :to_s :compose_simple
|
184
|
-
|
185
|
-
|
186
|
-
## return_statement
|
187
|
-
#
|
188
|
-
# summarizes defined as-statements ready to be included as last parameter
|
189
|
-
# in the match-statement-stack
|
190
|
-
#
|
191
|
-
# They can be modified through a block.
|
192
|
-
#
|
193
|
-
# i.e
|
194
|
-
#
|
195
|
-
# t= TestQuery.match( where: {a: 9, b: 's'}, as: nil ) << E.connect("<-", as: :test)
|
196
|
-
# t.return_statement{|y| "#{y.last}.name"}
|
197
|
-
#
|
198
|
-
# =>> " return test.name"
|
199
|
-
#
|
200
|
-
#return_statement is always called through compile
|
201
|
-
#
|
202
|
-
# t.compile{|y| "#{y.last}.name"}
|
203
|
-
|
204
|
-
private
|
205
|
-
def return_statement
|
206
|
-
resolve_as = ->{ @query_stack.map{|s| s.as.split(':').last unless s.as.nil? }.compact }
|
207
|
-
" return " + statement = if block_given?
|
208
|
-
a= yield resolve_as[]
|
209
|
-
a.is_a?(Array) ? a.join(', ') : a
|
210
|
-
else
|
211
|
-
resolve_as[].join(', ')
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end # class
|
215
|
-
|
216
|
-
end # module
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|