@@ -1,8 +1,10 @@
1 1 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Graph storage backends for PlanOpticon knowledge graphs."""
2 2 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
3 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import json
3 4 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import logging
5 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import sqlite3
4 6 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
from abc import ABC, abstractmethod
5 7 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
from pathlib import Path
6 8 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
from typing import Any, Dict, List, Optional, Union
7 9 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
8 10 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
logger = logging.getLogger(__name__)
@@ -110,11 +112,11 @@
110 112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
If edge_label is None, checks for any relationship type.
111 113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""
112 114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
...
113 115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
114 116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def raw_query(self, query_string: str) -> Any:
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- """Execute a raw query against the backend (e.g. Cypher for FalkorDB).
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Execute a raw query against the backend (e.g. SQL for SQLite).
116 118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
117 119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Not supported by all backends — raises NotImplementedError by default.
118 120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""
119 121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
raise NotImplementedError(f"{type(self).__name__} does not support raw queries")
120 122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@@ -255,323 +257,265 @@
255 257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if edge_label is None or rel.get("type") == edge_label:
256 258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return True
257 259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return False
258 260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
259 261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- class FalkorDBStore(GraphStore):
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- """FalkorDB Lite-backed graph store. Requires falkordblite package."""
262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ class SQLiteStore(GraphStore):
263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """SQLite-backed graph store. Uses Python's built-in sqlite3 module."""
264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ _SCHEMA = """
266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE TABLE IF NOT EXISTS entities (
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ name TEXT NOT NULL,
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ name_lower TEXT NOT NULL UNIQUE,
269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type TEXT NOT NULL DEFAULT 'concept',
270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ descriptions TEXT NOT NULL DEFAULT '[]',
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source TEXT,
272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ properties TEXT NOT NULL DEFAULT '{}'
273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE TABLE IF NOT EXISTS occurrences (
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entity_name_lower TEXT NOT NULL,
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source TEXT NOT NULL,
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ timestamp REAL,
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ text TEXT,
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ FOREIGN KEY (entity_name_lower) REFERENCES entities(name_lower)
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE TABLE IF NOT EXISTS relationships (
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source TEXT NOT NULL,
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ target TEXT NOT NULL,
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type TEXT NOT NULL DEFAULT 'related_to',
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ content_source TEXT,
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ timestamp REAL,
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ properties TEXT NOT NULL DEFAULT '{}'
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE INDEX IF NOT EXISTS idx_entities_name_lower ON entities(name_lower);
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE INDEX IF NOT EXISTS idx_occurrences_entity ON occurrences(entity_name_lower);
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE INDEX IF NOT EXISTS idx_relationships_source ON relationships(source);
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CREATE INDEX IF NOT EXISTS idx_relationships_target ON relationships(target);
294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
262 295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
263 296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def __init__(self, db_path: Union[str, Path]) -> None:
264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Patch redis 7.x compat: UnixDomainSocketConnection missing 'port'
265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- import redis.connection
266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not hasattr(redis.connection.UnixDomainSocketConnection, "port"):
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- redis.connection.UnixDomainSocketConnection.port = 0
269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from redislite import FalkorDB
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
272 297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self._db_path = str(db_path)
273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._db = FalkorDB(self._db_path)
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph = self._db.select_graph("knowledge")
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._ensure_indexes()
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- def _ensure_indexes(self) -> None:
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for query in [
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE INDEX FOR (e:Entity) ON (e.name_lower)",
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE INDEX FOR (e:Entity) ON (e.type)",
281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE INDEX FOR (e:Entity) ON (e.dag_id)",
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ]:
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- try:
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(query)
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- except Exception:
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- pass # index already exists
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn = sqlite3.connect(self._db_path)
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute("PRAGMA journal_mode=WAL")
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute("PRAGMA foreign_keys=ON")
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.executescript(self._SCHEMA)
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.commit()
287 303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
288 304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def merge_entity(
289 305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self,
290 306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
name: str,
291 307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
entity_type: str,
292 308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
descriptions: List[str],
293 309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
source: Optional[str] = None,
294 310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
) -> None:
295 311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
name_lower = name.lower()
296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Check if entity exists
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower}) RETURN e.descriptions",
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={"name_lower": name_lower},
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if result.result_set:
304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Entity exists — merge descriptions
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- existing_descs = result.result_set[0][0] or []
306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- merged = list(set(existing_descs + descriptions))
307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower}) SET e.descriptions = $descs",
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={"name_lower": name_lower, "descs": merged},
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute(
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT descriptions FROM entities WHERE name_lower = ?",
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (name_lower,),
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if row:
318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ existing = json.loads(row[0])
319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ merged = list(set(existing + descriptions))
320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute(
321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "UPDATE entities SET descriptions = ? WHERE name_lower = ?",
322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (json.dumps(merged), name_lower),
310 323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
)
311 324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
else:
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Create new entity
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE (e:Entity {"
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "name: $name, name_lower: $name_lower, type: $type, "
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "descriptions: $descs, source: $source"
317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "})",
318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={
319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "name": name,
320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "name_lower": name_lower,
321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "type": entity_type,
322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "descs": descriptions,
323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "source": source,
324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- },
325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute(
326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "INSERT INTO entities (name, name_lower, type, descriptions, source) "
327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "VALUES (?, ?, ?, ?, ?)",
328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (name, name_lower, entity_type, json.dumps(descriptions), source),
329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.commit()
326 331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
327 332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def add_occurrence(
328 333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self,
329 334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
entity_name: str,
330 335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
source: str,
331 336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
timestamp: Optional[float] = None,
332 337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
text: Optional[str] = None,
333 338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
) -> None:
334 339 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
name_lower = entity_name.lower()
335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(
336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower}) "
337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE (o:Occurrence {source: $source, timestamp: $timestamp, text: $text}) "
338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE (e)-[:OCCURRED_IN]->(o)",
339 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={
340 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "name_lower": name_lower,
341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "source": source,
342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "timestamp": timestamp,
343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "text": text,
344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- },
345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
340 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ exists = self._conn.execute(
341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT 1 FROM entities WHERE name_lower = ?", (name_lower,)
342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not exists:
344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute(
346 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "INSERT INTO occurrences (entity_name_lower, source, timestamp, text) "
347 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "VALUES (?, ?, ?, ?)",
348 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (name_lower, source, timestamp, text),
349 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
350 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.commit()
346 351 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
347 352 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def add_relationship(
348 353 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self,
349 354 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
source: str,
350 355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
target: str,
351 356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
rel_type: str,
352 357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
content_source: Optional[str] = None,
353 358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
timestamp: Optional[float] = None,
354 359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
) -> None:
355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(
356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (a:Entity {name_lower: $src_lower}) "
357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (b:Entity {name_lower: $tgt_lower}) "
358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "CREATE (a)-[:RELATED_TO {"
359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "rel_type: $rel_type, content_source: $content_source, timestamp: $timestamp"
360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "}]->(b)",
361 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={
362 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "src_lower": source.lower(),
363 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "tgt_lower": target.lower(),
364 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "rel_type": rel_type,
365 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "content_source": content_source,
366 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "timestamp": timestamp,
367 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- },
368 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute(
361 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "INSERT INTO relationships (source, target, type, content_source, timestamp) "
362 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "VALUES (?, ?, ?, ?, ?)",
363 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (source, target, rel_type, content_source, timestamp),
364 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
365 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.commit()
369 366 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
370 367 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def get_entity(self, name: str) -> Optional[Dict[str, Any]]:
371 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(
372 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower}) "
373 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "RETURN e.name, e.type, e.descriptions, e.source",
374 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={"name_lower": name.lower()},
375 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
376 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not result.result_set:
368 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute(
369 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT name, type, descriptions, source FROM entities WHERE name_lower = ?",
370 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (name.lower(),),
371 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
372 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not row:
377 373 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return None
378 374 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
379 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- row = result.result_set[0]
380 375 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
entity_name = row[0]
381 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
382 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Fetch occurrences
383 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- occ_result = self._graph.query(
384 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower})-[:OCCURRED_IN]->(o:Occurrence) "
385 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "RETURN o.source, o.timestamp, o.text",
386 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={"name_lower": name.lower()},
387 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
388 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- occurrences = [
389 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- {"source": o[0], "timestamp": o[1], "text": o[2]} for o in occ_result.result_set
390 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ]
376 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ occ_rows = self._conn.execute(
377 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT source, timestamp, text FROM occurrences WHERE entity_name_lower = ?",
378 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (name.lower(),),
379 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchall()
380 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ occurrences = [{"source": o[0], "timestamp": o[1], "text": o[2]} for o in occ_rows]
391 381 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
392 382 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return {
393 383 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"id": entity_name,
394 384 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"name": entity_name,
395 385 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"type": row[1] or "concept",
396 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "descriptions": row[2] or [],
386 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "descriptions": json.loads(row[2]) if row[2] else [],
397 387 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"occurrences": occurrences,
398 388 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"source": row[3],
399 389 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
400 390 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
401 391 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def get_all_entities(self) -> List[Dict[str, Any]]:
402 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(
403 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity) RETURN e.name, e.name_lower, e.type, e.descriptions, e.source"
404 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
392 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rows = self._conn.execute(
393 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT name, name_lower, type, descriptions, source FROM entities"
394 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchall()
405 395 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
entities = []
406 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for row in result.result_set:
396 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for row in rows:
407 397 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
name_lower = row[1]
408 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Fetch occurrences for this entity
409 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- occ_result = self._graph.query(
410 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower})-[:OCCURRED_IN]->(o:Occurrence) "
411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "RETURN o.source, o.timestamp, o.text",
412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={"name_lower": name_lower},
413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- occurrences = [
415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- {"source": o[0], "timestamp": o[1], "text": o[2]} for o in occ_result.result_set
416 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ]
398 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ occ_rows = self._conn.execute(
399 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT source, timestamp, text FROM occurrences WHERE entity_name_lower = ?",
400 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (name_lower,),
401 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchall()
402 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ occurrences = [{"source": o[0], "timestamp": o[1], "text": o[2]} for o in occ_rows]
417 403 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
entities.append(
418 404 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
{
419 405 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"id": row[0],
420 406 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"name": row[0],
421 407 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"type": row[2] or "concept",
422 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "descriptions": row[3] or [],
408 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "descriptions": json.loads(row[3]) if row[3] else [],
423 409 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"occurrences": occurrences,
424 410 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"source": row[4],
425 411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
426 412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
)
427 413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return entities
428 414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
429 415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def get_all_relationships(self) -> List[Dict[str, Any]]:
430 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(
431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (a:Entity)-[r:RELATED_TO]->(b:Entity) "
432 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "RETURN a.name, b.name, r.rel_type, r.content_source, r.timestamp"
433 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
416 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rows = self._conn.execute(
417 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT source, target, type, content_source, timestamp FROM relationships"
418 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchall()
434 419 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return [
435 420 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
{
436 421 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"source": row[0],
437 422 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"target": row[1],
438 423 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"type": row[2] or "related_to",
439 424 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"content_source": row[3],
440 425 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"timestamp": row[4],
441 426 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
442 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for row in result.result_set
427 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for row in rows
443 428 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
]
444 429 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
445 430 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def get_entity_count(self) -> int:
446 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query("MATCH (e:Entity) RETURN count(e)")
447 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return result.result_set[0][0] if result.result_set else 0
431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute("SELECT COUNT(*) FROM entities").fetchone()
432 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return row[0] if row else 0
448 433 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
449 434 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def get_relationship_count(self) -> int:
450 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query("MATCH ()-[r]->() RETURN count(r)")
451 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- count = result.result_set[0][0] if result.result_set else 0
452 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Subtract occurrence edges which are internal bookkeeping
453 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- occ_result = self._graph.query("MATCH ()-[r:OCCURRED_IN]->() RETURN count(r)")
454 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- occ_count = occ_result.result_set[0][0] if occ_result.result_set else 0
455 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return count - occ_count
435 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute("SELECT COUNT(*) FROM relationships").fetchone()
436 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return row[0] if row else 0
456 437 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
457 438 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def has_entity(self, name: str) -> bool:
458 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(
459 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (e:Entity {name_lower: $name_lower}) RETURN count(e)",
460 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params={"name_lower": name.lower()},
461 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
462 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return result.result_set[0][0] > 0 if result.result_set else False
439 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute(
440 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT 1 FROM entities WHERE name_lower = ?", (name.lower(),)
441 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
442 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return row is not None
463 443 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
464 444 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def raw_query(self, query_string: str) -> Any:
465 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- """Execute a raw Cypher query and return the result set."""
466 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(query_string)
467 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return result.result_set
445 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Execute a raw SQL query and return all rows."""
446 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cursor = self._conn.execute(query_string)
447 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return cursor.fetchall()
468 448 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
469 449 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def add_typed_relationship(
470 450 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self,
471 451 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
source: str,
472 452 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
target: str,
473 453 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
edge_label: str,
474 454 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
properties: Optional[Dict[str, Any]] = None,
475 455 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
) -> None:
476 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- props = properties or {}
477 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Build property string for Cypher SET clause
478 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- prop_assignments = []
479 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params: Dict[str, Any] = {
480 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "src_lower": source.lower(),
481 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "tgt_lower": target.lower(),
482 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
483 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for i, (k, v) in enumerate(props.items()):
484 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- param_name = f"prop_{i}"
485 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- prop_assignments.append(f"r.{k} = ${param_name}")
486 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params[param_name] = v
487 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
488 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- set_clause = ""
489 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if prop_assignments:
490 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- set_clause = " SET " + ", ".join(prop_assignments)
491 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
492 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # FalkorDB requires static relationship types in CREATE, so we use
493 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # a parameterized approach with specific known labels
494 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- query = (
495 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"MATCH (a:Entity {{name_lower: $src_lower}}) "
496 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"MATCH (b:Entity {{name_lower: $tgt_lower}}) "
497 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"CREATE (a)-[r:{edge_label}]->(b)"
498 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"{set_clause}"
499 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
500 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(query, params=params)
456 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute(
457 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "INSERT INTO relationships (source, target, type, properties) VALUES (?, ?, ?, ?)",
458 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (source, target, edge_label, json.dumps(properties or {})),
459 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
460 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.commit()
501 461 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
502 462 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def set_entity_properties(
503 463 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self,
504 464 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
name: str,
505 465 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
properties: Dict[str, Any],
506 466 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
) -> bool:
507 467 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
name_lower = name.lower()
508 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Check entity exists
509 468 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if not self.has_entity(name):
510 469 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return False
511 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
512 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params: Dict[str, Any] = {"name_lower": name_lower}
513 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- set_parts = []
514 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for i, (k, v) in enumerate(properties.items()):
515 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- param_name = f"prop_{i}"
516 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- set_parts.append(f"e.{k} = ${param_name}")
517 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params[param_name] = v
518 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
519 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not set_parts:
470 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not properties:
520 471 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return True
521 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
522 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- query = f"MATCH (e:Entity {{name_lower: $name_lower}}) SET {', '.join(set_parts)}"
523 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph.query(query, params=params)
472 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute(
473 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT properties FROM entities WHERE name_lower = ?", (name_lower,)
474 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
475 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ existing = json.loads(row[0]) if row and row[0] else {}
476 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ existing.update(properties)
477 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.execute(
478 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "UPDATE entities SET properties = ? WHERE name_lower = ?",
479 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (json.dumps(existing), name_lower),
480 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
481 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.commit()
524 482 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return True
525 483 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
526 484 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def has_relationship(
527 485 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
self,
528 486 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
source: str,
529 487 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
target: str,
530 488 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
edge_label: Optional[str] = None,
531 489 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
) -> bool:
532 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- params = {
533 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "src_lower": source.lower(),
534 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "tgt_lower": target.lower(),
535 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
536 490 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if edge_label:
537 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- query = (
538 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"MATCH (a:Entity {{name_lower: $src_lower}})"
539 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"-[:{edge_label}]->"
540 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"(b:Entity {{name_lower: $tgt_lower}}) "
541 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"RETURN count(*)"
542 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
491 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute(
492 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT 1 FROM relationships "
493 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHERE LOWER(source) = ? AND LOWER(target) = ? AND type = ?",
494 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (source.lower(), target.lower(), edge_label),
495 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
543 496 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
else:
544 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- query = (
545 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "MATCH (a:Entity {name_lower: $src_lower})"
546 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "-[]->"
547 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "(b:Entity {name_lower: $tgt_lower}) "
548 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "RETURN count(*)"
549 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
550 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- result = self._graph.query(query, params=params)
551 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return result.result_set[0][0] > 0 if result.result_set else False
497 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ row = self._conn.execute(
498 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT 1 FROM relationships WHERE LOWER(source) = ? AND LOWER(target) = ?",
499 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (source.lower(), target.lower()),
500 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ).fetchone()
501 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return row is not None
552 502 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
553 503 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def close(self) -> None:
554 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- """Release references. FalkorDB Lite handles persistence automatically."""
555 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._graph = None
556 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- self._db = None
504 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Close the SQLite connection."""
505 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if self._conn:
506 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn.close()
507 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ self._conn = None
557 508 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
558 509 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
559 510 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def create_store(db_path: Optional[Union[str, Path]] = None) -> GraphStore:
560 511 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Create the best available graph store.
561 512 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
562 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- If db_path is provided and falkordblite is installed, uses FalkorDBStore.
563 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- Otherwise falls back to InMemoryStore.
513 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ If db_path is provided, uses SQLiteStore for persistent storage.
514 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Otherwise returns an InMemoryStore.
564 515 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""
565 516 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if db_path is not None:
566 517 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
try:
567 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return FalkorDBStore(db_path)
568 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- except ImportError:
569 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logger.info(
570 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "falkordblite not installed, falling back to in-memory store. "
571 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "Install with: pip install planopticon[graph]"
572 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
518 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return SQLiteStore(db_path)
573 519 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
except Exception as e:
574 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logger.warning(
575 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- f"Failed to initialize FalkorDB at {db_path}: {e}. Using in-memory store."
576 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
520 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logger.warning(f"Failed to initialize SQLite at {db_path}: {e}. Using in-memory store.")
577 521 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return InMemoryStore()
578 522 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!