activecypher 0.7.3 → 0.8.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/lib/active_cypher/connection_adapters/memgraph_adapter.rb +10 -1
- data/lib/active_cypher/connection_adapters/neo4j_adapter.rb +1 -1
- data/lib/active_cypher/connection_adapters/persistence_methods.rb +31 -14
- data/lib/active_cypher/relation.rb +1 -1
- data/lib/active_cypher/version.rb +1 -1
- data/lib/activecypher.rb +3 -1
- data/lib/cyrel/ast/call_node.rb +39 -0
- data/lib/cyrel/ast/clause_adapter.rb +38 -0
- data/lib/cyrel/ast/clause_node.rb +10 -0
- data/lib/cyrel/ast/compiler.rb +609 -0
- data/lib/cyrel/ast/create_node.rb +21 -0
- data/lib/cyrel/ast/delete_node.rb +22 -0
- data/lib/cyrel/ast/expression_node.rb +10 -0
- data/lib/cyrel/ast/foreach_node.rb +23 -0
- data/lib/cyrel/ast/limit_node.rb +21 -0
- data/lib/cyrel/ast/literal_node.rb +39 -0
- data/lib/cyrel/ast/load_csv_node.rb +24 -0
- data/lib/cyrel/ast/match_node.rb +23 -0
- data/lib/cyrel/ast/merge_node.rb +23 -0
- data/lib/cyrel/ast/node.rb +36 -0
- data/lib/cyrel/ast/optimized_nodes.rb +117 -0
- data/lib/cyrel/ast/order_by_node.rb +21 -0
- data/lib/cyrel/ast/pattern_node.rb +10 -0
- data/lib/cyrel/ast/query_integrated_compiler.rb +27 -0
- data/lib/cyrel/ast/remove_node.rb +21 -0
- data/lib/cyrel/ast/return_node.rb +21 -0
- data/lib/cyrel/ast/set_node.rb +20 -0
- data/lib/cyrel/ast/simple_cache.rb +50 -0
- data/lib/cyrel/ast/skip_node.rb +19 -0
- data/lib/cyrel/ast/union_node.rb +22 -0
- data/lib/cyrel/ast/unwind_node.rb +20 -0
- data/lib/cyrel/ast/where_node.rb +20 -0
- data/lib/cyrel/ast/with_node.rb +23 -0
- data/lib/cyrel/clause/unwind.rb +71 -0
- data/lib/cyrel/expression/literal.rb +9 -2
- data/lib/cyrel/expression/property_access.rb +1 -1
- data/lib/cyrel/pattern/node.rb +11 -1
- data/lib/cyrel/pattern/relationship.rb +21 -13
- data/lib/cyrel/query.rb +405 -91
- data/lib/cyrel.rb +132 -2
- metadata +29 -1
data/lib/cyrel.rb
CHANGED
@@ -3,6 +3,18 @@
|
|
3
3
|
module Cyrel
|
4
4
|
module_function
|
5
5
|
|
6
|
+
# Cyrel DSL helper: creates a new query.
|
7
|
+
# Example: Cyrel.query.match(pattern)
|
8
|
+
def query
|
9
|
+
Query.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# Cyrel DSL helper: alias for node creation.
|
13
|
+
# Example: Cyrel.n(:person, :Person, name: 'Alice')
|
14
|
+
def n(alias_name = nil, *labels, **properties)
|
15
|
+
Pattern::Node.new(alias_name, labels: labels, properties: properties)
|
16
|
+
end
|
17
|
+
|
6
18
|
# Cyrel DSL helper: creates a CALL clause for a procedure.
|
7
19
|
# Example: Cyrel.call('db.labels')
|
8
20
|
def call(procedure)
|
@@ -16,11 +28,123 @@ module Cyrel
|
|
16
28
|
end
|
17
29
|
|
18
30
|
# Cyrel DSL helper: creates a node pattern.
|
19
|
-
# Example: Cyrel.node(:n,
|
20
|
-
def node(alias_name, labels
|
31
|
+
# Example: Cyrel.node(:n, :Person, name: 'Alice')
|
32
|
+
def node(alias_name = nil, *labels, **properties)
|
21
33
|
Pattern::Node.new(alias_name, labels: labels, properties: properties)
|
22
34
|
end
|
23
35
|
|
36
|
+
# Cyrel DSL helper: creates a relationship pattern.
|
37
|
+
# Example: Cyrel.rel(:r, :KNOWS, since: 2020)
|
38
|
+
def rel(alias_name = nil, *types, **properties)
|
39
|
+
length = properties.delete(:length)
|
40
|
+
Pattern::Relationship.new(alias_name: alias_name, types: types, properties: properties, length: length)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Cyrel DSL helper: creates a path pattern with a DSL block.
|
44
|
+
# Example: Cyrel.path { node(:a) > rel(:r) > node(:b) }
|
45
|
+
def path(&)
|
46
|
+
builder = PathBuilder.new
|
47
|
+
builder.instance_eval(&)
|
48
|
+
Pattern::Path.new(builder.elements)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Path builder DSL for constructing path patterns
|
52
|
+
class PathBuilder
|
53
|
+
attr_reader :elements
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
@elements = []
|
57
|
+
@pending_direction = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def node(alias_name = nil, *labels, **properties)
|
61
|
+
# If there's a pending direction, we need to add a relationship first
|
62
|
+
if @pending_direction && @elements.any? && @elements.last.is_a?(Cyrel::Pattern::Node)
|
63
|
+
@elements << Cyrel::Pattern::Relationship.new(types: [], direction: @pending_direction)
|
64
|
+
@pending_direction = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
n = Cyrel::Pattern::Node.new(alias_name, labels: labels, properties: properties)
|
68
|
+
@elements << n
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def rel(alias_name = nil, *types, **properties)
|
73
|
+
length = properties.delete(:length)
|
74
|
+
|
75
|
+
# Check if we need to replace the last element (an anonymous relationship)
|
76
|
+
if @elements.last.is_a?(Cyrel::Pattern::Relationship) && @elements.last.types.empty?
|
77
|
+
# Replace the anonymous relationship with specified one, keeping direction
|
78
|
+
direction = @elements.last.direction
|
79
|
+
@elements.pop
|
80
|
+
else
|
81
|
+
direction = @pending_direction || :both
|
82
|
+
end
|
83
|
+
|
84
|
+
r = Cyrel::Pattern::Relationship.new(alias_name: alias_name, types: types, properties: properties, length: length, direction: direction)
|
85
|
+
@elements << r
|
86
|
+
@pending_direction = nil
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def >(_other)
|
91
|
+
# When called like: node(:a) > rel(:r) > node(:b)
|
92
|
+
# The rel(:r) is evaluated first, then > is called
|
93
|
+
# So we need to modify the last relationship that was just added
|
94
|
+
if @elements.last.is_a?(Cyrel::Pattern::Relationship)
|
95
|
+
# Replace the last relationship with one that has the correct direction
|
96
|
+
last_rel = @elements.pop
|
97
|
+
new_rel = Cyrel::Pattern::Relationship.new(
|
98
|
+
alias_name: last_rel.alias_name,
|
99
|
+
types: last_rel.types,
|
100
|
+
properties: last_rel.properties,
|
101
|
+
length: last_rel.length,
|
102
|
+
direction: :outgoing
|
103
|
+
)
|
104
|
+
@elements << new_rel
|
105
|
+
else
|
106
|
+
@pending_direction = :outgoing
|
107
|
+
end
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def <(_other)
|
112
|
+
# Same logic as > but for incoming direction
|
113
|
+
if @elements.last.is_a?(Cyrel::Pattern::Relationship)
|
114
|
+
last_rel = @elements.pop
|
115
|
+
new_rel = Cyrel::Pattern::Relationship.new(
|
116
|
+
alias_name: last_rel.alias_name,
|
117
|
+
types: last_rel.types,
|
118
|
+
properties: last_rel.properties,
|
119
|
+
length: last_rel.length,
|
120
|
+
direction: :incoming
|
121
|
+
)
|
122
|
+
@elements << new_rel
|
123
|
+
else
|
124
|
+
@pending_direction = :incoming
|
125
|
+
end
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def -(_other)
|
130
|
+
# Same logic as > but for bidirectional
|
131
|
+
if @elements.last.is_a?(Cyrel::Pattern::Relationship)
|
132
|
+
last_rel = @elements.pop
|
133
|
+
new_rel = Cyrel::Pattern::Relationship.new(
|
134
|
+
alias_name: last_rel.alias_name,
|
135
|
+
types: last_rel.types,
|
136
|
+
properties: last_rel.properties,
|
137
|
+
length: last_rel.length,
|
138
|
+
direction: :both
|
139
|
+
)
|
140
|
+
@elements << new_rel
|
141
|
+
else
|
142
|
+
@pending_direction = :both
|
143
|
+
end
|
144
|
+
self
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
24
148
|
# Cyrel DSL helper: starts a CREATE query.
|
25
149
|
# Example: Cyrel.create(pattern)
|
26
150
|
def create(pattern)
|
@@ -44,6 +168,12 @@ module Cyrel
|
|
44
168
|
# Example: Cyrel.node_id(:n)
|
45
169
|
def node_id(...) = Functions.node_id(...)
|
46
170
|
|
171
|
+
# Cyrel DSL helper: creates a function call expression.
|
172
|
+
# Example: Cyrel.function(:count, :*)
|
173
|
+
def function(name, *args)
|
174
|
+
Expression::FunctionCall.new(name, args)
|
175
|
+
end
|
176
|
+
|
47
177
|
# Cyrel DSL helper: Cypher count() aggregation.
|
48
178
|
# Example: Cyrel.count(:n)
|
49
179
|
def count(...) = Functions.count(...)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activecypher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
@@ -171,6 +171,33 @@ files:
|
|
171
171
|
- lib/active_cypher/version.rb
|
172
172
|
- lib/activecypher.rb
|
173
173
|
- lib/cyrel.rb
|
174
|
+
- lib/cyrel/ast/call_node.rb
|
175
|
+
- lib/cyrel/ast/clause_adapter.rb
|
176
|
+
- lib/cyrel/ast/clause_node.rb
|
177
|
+
- lib/cyrel/ast/compiler.rb
|
178
|
+
- lib/cyrel/ast/create_node.rb
|
179
|
+
- lib/cyrel/ast/delete_node.rb
|
180
|
+
- lib/cyrel/ast/expression_node.rb
|
181
|
+
- lib/cyrel/ast/foreach_node.rb
|
182
|
+
- lib/cyrel/ast/limit_node.rb
|
183
|
+
- lib/cyrel/ast/literal_node.rb
|
184
|
+
- lib/cyrel/ast/load_csv_node.rb
|
185
|
+
- lib/cyrel/ast/match_node.rb
|
186
|
+
- lib/cyrel/ast/merge_node.rb
|
187
|
+
- lib/cyrel/ast/node.rb
|
188
|
+
- lib/cyrel/ast/optimized_nodes.rb
|
189
|
+
- lib/cyrel/ast/order_by_node.rb
|
190
|
+
- lib/cyrel/ast/pattern_node.rb
|
191
|
+
- lib/cyrel/ast/query_integrated_compiler.rb
|
192
|
+
- lib/cyrel/ast/remove_node.rb
|
193
|
+
- lib/cyrel/ast/return_node.rb
|
194
|
+
- lib/cyrel/ast/set_node.rb
|
195
|
+
- lib/cyrel/ast/simple_cache.rb
|
196
|
+
- lib/cyrel/ast/skip_node.rb
|
197
|
+
- lib/cyrel/ast/union_node.rb
|
198
|
+
- lib/cyrel/ast/unwind_node.rb
|
199
|
+
- lib/cyrel/ast/where_node.rb
|
200
|
+
- lib/cyrel/ast/with_node.rb
|
174
201
|
- lib/cyrel/call_procedure.rb
|
175
202
|
- lib/cyrel/clause.rb
|
176
203
|
- lib/cyrel/clause/call.rb
|
@@ -185,6 +212,7 @@ files:
|
|
185
212
|
- lib/cyrel/clause/return.rb
|
186
213
|
- lib/cyrel/clause/set.rb
|
187
214
|
- lib/cyrel/clause/skip.rb
|
215
|
+
- lib/cyrel/clause/unwind.rb
|
188
216
|
- lib/cyrel/clause/where.rb
|
189
217
|
- lib/cyrel/clause/with.rb
|
190
218
|
- lib/cyrel/direction.rb
|