activecypher 0.14.0 → 0.14.1
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfba386d94660c96cf6078ac0a7d370d2dd5670e9316a3de2ee917f409f227ab
|
|
4
|
+
data.tar.gz: e2e70d29dc99279b51f810363d50749e470556481e80c8c8276fc80ba612b7d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1fbe83583d2cdb4a7ea898e8ce5876cfd6907af332ffd7b77643473026ac5fd0d3714bcf037876d2c8ebd8722594a9e5635ae0b3c816c4a98ed9f49dad99e523
|
|
7
|
+
data.tar.gz: bc13b5392ce91d0247bd4166310e8967676763b9d11f3156206f7a8e3b004f3158b5341dfbadfec82677fc887ef6aedfc8fe51081ea722d847cce60eb155f1d0
|
|
@@ -88,10 +88,18 @@ module ActiveCypher
|
|
|
88
88
|
run_response = connection.read_message
|
|
89
89
|
unless run_response.is_a?(Bolt::Messaging::Success)
|
|
90
90
|
# Read any remaining messages to clear connection state
|
|
91
|
-
|
|
91
|
+
begin
|
|
92
|
+
connection.read_message
|
|
93
|
+
rescue StandardError
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
92
96
|
# Send RESET to clear connection state
|
|
93
97
|
connection.write_message(Bolt::Messaging::Reset.new)
|
|
94
|
-
|
|
98
|
+
begin
|
|
99
|
+
connection.read_message
|
|
100
|
+
rescue StandardError
|
|
101
|
+
nil
|
|
102
|
+
end
|
|
95
103
|
raise QueryError, "DDL failed for: #{cypher.inspect}\nError: #{run_response.fields.first}"
|
|
96
104
|
end
|
|
97
105
|
|
|
@@ -100,22 +108,71 @@ module ActiveCypher
|
|
|
100
108
|
end
|
|
101
109
|
end
|
|
102
110
|
|
|
103
|
-
# Override run to execute queries
|
|
104
|
-
# Memgraph auto
|
|
111
|
+
# Override run to execute queries using auto-commit mode.
|
|
112
|
+
# Memgraph auto-commits each query, so we send RUN + PULL directly
|
|
113
|
+
# without BEGIN/COMMIT wrapper. This avoids transaction state issues.
|
|
105
114
|
def run(cypher, params = {}, context: 'Query', db: nil, access_mode: :write)
|
|
106
115
|
connect
|
|
107
116
|
logger.debug { "[#{context}] #{cypher} #{params.inspect}" }
|
|
108
117
|
|
|
109
118
|
instrument_query(cypher, params, context: context, metadata: { db: db, access_mode: access_mode }) do
|
|
110
|
-
|
|
119
|
+
run_auto_commit(cypher, prepare_params(params))
|
|
120
|
+
end
|
|
121
|
+
end
|
|
111
122
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
123
|
+
# Execute a query in auto-commit mode (no explicit transaction).
|
|
124
|
+
# Sends RUN + PULL directly to the connection.
|
|
125
|
+
#
|
|
126
|
+
# @param cypher [String] The Cypher query
|
|
127
|
+
# @param params [Hash] Query parameters
|
|
128
|
+
# @return [Array<Hash>] The result rows
|
|
129
|
+
def run_auto_commit(cypher, params = {})
|
|
130
|
+
Sync do
|
|
131
|
+
# Send RUN message
|
|
132
|
+
run_meta = {}
|
|
133
|
+
connection.write_message(Bolt::Messaging::Run.new(cypher, params, run_meta))
|
|
116
134
|
|
|
117
|
-
|
|
118
|
-
|
|
135
|
+
# Read RUN response
|
|
136
|
+
run_response = connection.read_message
|
|
137
|
+
|
|
138
|
+
case run_response
|
|
139
|
+
when Bolt::Messaging::Success
|
|
140
|
+
# Send PULL to get results
|
|
141
|
+
connection.write_message(Bolt::Messaging::Pull.new({ n: -1 }))
|
|
142
|
+
|
|
143
|
+
# Collect records
|
|
144
|
+
rows = []
|
|
145
|
+
fields = run_response.metadata['fields'] || []
|
|
146
|
+
|
|
147
|
+
loop do
|
|
148
|
+
msg = connection.read_message
|
|
149
|
+
case msg
|
|
150
|
+
when Bolt::Messaging::Record
|
|
151
|
+
# Convert record values to hash with field names
|
|
152
|
+
row = fields.zip(msg.values).to_h
|
|
153
|
+
rows << row
|
|
154
|
+
when Bolt::Messaging::Success
|
|
155
|
+
# End of results
|
|
156
|
+
break
|
|
157
|
+
when Bolt::Messaging::Failure
|
|
158
|
+
code = msg.metadata['code']
|
|
159
|
+
message = msg.metadata['message']
|
|
160
|
+
connection.reset!
|
|
161
|
+
raise QueryError, "Query failed: #{code} - #{message}"
|
|
162
|
+
else
|
|
163
|
+
raise ProtocolError, "Unexpected response during PULL: #{msg.class}"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
rows
|
|
168
|
+
when Bolt::Messaging::Failure
|
|
169
|
+
code = run_response.metadata['code']
|
|
170
|
+
message = run_response.metadata['message']
|
|
171
|
+
connection.reset!
|
|
172
|
+
raise QueryError, "Query failed: #{code} - #{message}"
|
|
173
|
+
else
|
|
174
|
+
raise ProtocolError, "Unexpected response to RUN: #{run_response.class}"
|
|
175
|
+
end
|
|
119
176
|
end
|
|
120
177
|
end
|
|
121
178
|
|
|
@@ -59,26 +59,26 @@ module ActiveCypher
|
|
|
59
59
|
# --------------------------------------------------------------
|
|
60
60
|
# Connection fallback
|
|
61
61
|
# --------------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end
|
|
62
|
+
# Relationship classes usually share the same Bolt pool as the
|
|
63
|
+
# node they originate from; delegate there unless the relationship
|
|
64
|
+
# class was given its own pool explicitly.
|
|
65
|
+
#
|
|
66
|
+
# WorksAtRelationship.connection # -> PersonNode.connection
|
|
67
|
+
#
|
|
68
|
+
def self.connection
|
|
69
|
+
# If this is a concrete relationship class with from_class defined,
|
|
70
|
+
# prefer delegating to that node's connection (so role/shard routing is respected).
|
|
71
|
+
if !abstract_class? && (fc = from_class_name)
|
|
72
|
+
klass = fc.constantize
|
|
73
|
+
role = ActiveCypher::RuntimeRegistry.current_role
|
|
74
|
+
shard = ActiveCypher::RuntimeRegistry.current_shard
|
|
75
|
+
|
|
76
|
+
return klass.connected_to(role: role, shard: shard) do
|
|
77
|
+
klass.connection
|
|
79
78
|
end
|
|
79
|
+
end
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
# Otherwise, fall back to node_base_class if present (even if abstract)
|
|
82
82
|
if (klass = node_base_class)
|
|
83
83
|
return klass.connection
|
|
84
84
|
end
|
|
@@ -313,12 +313,10 @@ module ActiveCypher
|
|
|
313
313
|
end
|
|
314
314
|
rescue ActiveCypher::RecordNotSaved, RuntimeError => e
|
|
315
315
|
# Only catch specific validation errors, let other errors propagate
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
raise
|
|
321
|
-
end
|
|
316
|
+
raise unless e.message.include?('must be persisted') || e.message.include?('creation returned no id')
|
|
317
|
+
|
|
318
|
+
log_error "Failed to save #{self.class}: #{e.message}"
|
|
319
|
+
false
|
|
322
320
|
end
|
|
323
321
|
|
|
324
322
|
# Bang version of save - raises exception if save fails
|