fix(raft): graph apply + reject non-default DB writes
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled

- applyReplicatedPut/Delete keep in-memory graphs in sync with node/edge
  table rows (idempotent edges via addEdgeWithIdIfAbsent).
- When Raft is enabled, DML is refused on any database other than
  'default' (the only DB the state machine is wired to).
- Docs updated (en/bg); unit test for graph apply.
This commit is contained in:
2026-07-30 21:19:01 +03:00
parent 0d51497f57
commit 50f827f8cf
6 changed files with 128 additions and 6 deletions
+10 -3
View File
@@ -254,15 +254,22 @@ proc executeQuery(db: LSMTree, ctx: ExecutionContext, query: string, params: seq
# C3b: writes go through the Raft log — only the leader may accept them.
# Inspect every statement so "SELECT 1; INSERT ..." cannot bypass the gate.
# Raft state machine is wired only to the default database (v1).
if raftNode != nil:
var hasWrite = false
for stmt in astNode.stmts:
if isWrite(stmt):
hasWrite = true
break
if hasWrite and raftNode.state != rsLeader:
let who = if raftNode.leaderId.len > 0: raftNode.leaderId else: "none elected"
return (false, QueryResult(), "not leader; leader is '" & who & "'")
if hasWrite:
let dbName = if ctx.currentDatabase.len > 0: ctx.currentDatabase else: "default"
if dbName != "default":
return (false, QueryResult(),
"raft writes only supported on the 'default' database; current is '" &
dbName & "'")
if raftNode.state != rsLeader:
let who = if raftNode.leaderId.len > 0: raftNode.leaderId else: "none elected"
return (false, QueryResult(), "not leader; leader is '" & who & "'")
let res = executor.executeQuery(ctx, astNode, params)
if res.success: