Merge pull request #884 from shafdev/fix/kg-missing-lock

fix: add missing self._lock to query_relationship, timeline, and stats in KnowledgeGraph
This commit is contained in:
Igor Lins e Silva
2026-04-14 16:47:24 -03:00
committed by GitHub
+52 -49
View File
@@ -260,7 +260,6 @@ class KnowledgeGraph:
def query_relationship(self, predicate: str, as_of: str = None): def query_relationship(self, predicate: str, as_of: str = None):
"""Get all triples with a given relationship type.""" """Get all triples with a given relationship type."""
pred = predicate.lower().replace(" ", "_") pred = predicate.lower().replace(" ", "_")
conn = self._conn()
query = """ query = """
SELECT t.*, s.name as sub_name, o.name as obj_name SELECT t.*, s.name as sub_name, o.name as obj_name
FROM triples t FROM triples t
@@ -274,45 +273,48 @@ class KnowledgeGraph:
params.extend([as_of, as_of]) params.extend([as_of, as_of])
results = [] results = []
for row in conn.execute(query, params).fetchall(): with self._lock:
results.append( conn = self._conn()
{ for row in conn.execute(query, params).fetchall():
"subject": row["sub_name"], results.append(
"predicate": pred, {
"object": row["obj_name"], "subject": row["sub_name"],
"valid_from": row["valid_from"], "predicate": pred,
"valid_to": row["valid_to"], "object": row["obj_name"],
"current": row["valid_to"] is None, "valid_from": row["valid_from"],
} "valid_to": row["valid_to"],
) "current": row["valid_to"] is None,
}
)
return results return results
def timeline(self, entity_name: str = None): def timeline(self, entity_name: str = None):
"""Get all facts in chronological order, optionally filtered by entity.""" """Get all facts in chronological order, optionally filtered by entity."""
conn = self._conn() with self._lock:
if entity_name: conn = self._conn()
eid = self._entity_id(entity_name) if entity_name:
rows = conn.execute( eid = self._entity_id(entity_name)
""" rows = conn.execute(
SELECT t.*, s.name as sub_name, o.name as obj_name """
FROM triples t SELECT t.*, s.name as sub_name, o.name as obj_name
JOIN entities s ON t.subject = s.id FROM triples t
JOIN entities o ON t.object = o.id JOIN entities s ON t.subject = s.id
WHERE (t.subject = ? OR t.object = ?) JOIN entities o ON t.object = o.id
ORDER BY t.valid_from ASC NULLS LAST WHERE (t.subject = ? OR t.object = ?)
LIMIT 100 ORDER BY t.valid_from ASC NULLS LAST
""", LIMIT 100
(eid, eid), """,
).fetchall() (eid, eid),
else: ).fetchall()
rows = conn.execute(""" else:
SELECT t.*, s.name as sub_name, o.name as obj_name rows = conn.execute("""
FROM triples t SELECT t.*, s.name as sub_name, o.name as obj_name
JOIN entities s ON t.subject = s.id FROM triples t
JOIN entities o ON t.object = o.id JOIN entities s ON t.subject = s.id
ORDER BY t.valid_from ASC NULLS LAST JOIN entities o ON t.object = o.id
LIMIT 100 ORDER BY t.valid_from ASC NULLS LAST
""").fetchall() LIMIT 100
""").fetchall()
return [ return [
{ {
@@ -329,19 +331,20 @@ class KnowledgeGraph:
# ── Stats ───────────────────────────────────────────────────────────── # ── Stats ─────────────────────────────────────────────────────────────
def stats(self): def stats(self):
conn = self._conn() with self._lock:
entities = conn.execute("SELECT COUNT(*) as cnt FROM entities").fetchone()["cnt"] conn = self._conn()
triples = conn.execute("SELECT COUNT(*) as cnt FROM triples").fetchone()["cnt"] entities = conn.execute("SELECT COUNT(*) as cnt FROM entities").fetchone()["cnt"]
current = conn.execute( triples = conn.execute("SELECT COUNT(*) as cnt FROM triples").fetchone()["cnt"]
"SELECT COUNT(*) as cnt FROM triples WHERE valid_to IS NULL" current = conn.execute(
).fetchone()["cnt"] "SELECT COUNT(*) as cnt FROM triples WHERE valid_to IS NULL"
expired = triples - current ).fetchone()["cnt"]
predicates = [ expired = triples - current
r["predicate"] predicates = [
for r in conn.execute( r["predicate"]
"SELECT DISTINCT predicate FROM triples ORDER BY predicate" for r in conn.execute(
).fetchall() "SELECT DISTINCT predicate FROM triples ORDER BY predicate"
] ).fetchall()
]
return { return {
"entities": entities, "entities": entities,
"triples": triples, "triples": triples,