Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Update mapped tables

Use GraphEngine::mapped to read and write application tables with Cypher, Gremlin, and SPARQL. All languages use the same mapping catalog, DuckDB connection, and transaction owner.

Create mapped rows

Declare every writable property, including a property alias for keys supplied through Cypher. For example, add .property("id", "id") to the tutorial’s Person mapping:

graph.cypher(
    "CREATE (p:Person {id:4, name:'dave', age:29}) RETURN p.name"
).await?;

Mapped keys must be supplied explicitly. Scalar and ordered composite keys are supported; there is no automatic integer allocation or primary-key default generation. For Gremlin, T.id supplies the mapped key without requiring a property alias:

graph.gremlin("g.addV('Person').property(T.id,4).property('name','dave').property('age',29)").await?;

These are alternative ways to create the same row; do not execute both against the same existing key. Every composite-key component must be non-null. Identity remains qualified by the mapped label or relationship type.

Constant defaults on omitted mapped columns are visible during the statement. Volatile/function defaults on omitted mapped values are currently rejected. Unmapped source columns retain their database defaults and constraints. Unknown properties are not stored in supplemental columns or overflow tables.

Update and return values

let result = graph.cypher(
    "MATCH (p:Person) WHERE p.id=4 \
     SET p.age=p.age+1, p.name='David' RETURN p.name,p.age"
).await?;
println!("{} rows", result.returned.batch.num_rows());

Use cypher_with_params to bind values. SET p += {...} assigns properties; SET p = {...} clears omitted writable mapped properties to SQL NULL. Identity and endpoint columns remain protected. Primary keys are immutable. Scalar and composite keys use the same typed identity rules.

Relationships and deletion

Independent edge-row mappings need explicit edge IDs for writes. Their endpoint columns match node keys in declared order. An FK-backed relationship instead uses its child row’s key as the edge identity: creating a child and its required relationship becomes one complete row insertion. Deleting that relationship clears its nullable non-key FK components; it does not delete the child row. See FK-backed relationships.

MATCH (p:Person {id:4})
DETACH DELETE p

Node deletion checks mapped incident relationships. Database constraints still apply. Properties must have one write owner: the tutorial’s total belongs to Order, so update o.total, not an unmapped ORDERED.total edge property.

MATCH (:Person)-[:ORDERED]->(o:Order)
WHERE o.total > 100.0
SET o.total = o.total + 10.0
RETURN o.total

RDF updates

Add writable RdfMapping rules with complete physical keys, then call sparql_update(update, "default", None). RDF inserts and deletes translate to mapped row transitions; they do not populate a separate triple store. A scalar property replacement requires deleting the old RDF value and inserting the new one in the same request. See RDF updates.

Query-backed mappings, partition-layout logical sources, and collection-backed node/edge mappings are read-only. Updates must target writable physical rows. No write is redirected to managed storage when a mapping cannot represent it.

Transactions

begin, commit, and rollback on GraphEngine cover all three languages. Statements outside an explicit transaction commit atomically; a failed mapped execution within an explicit transaction requires rollback before further work. See mapped transactions.

Compatibility APIs

MappedGraphEngine::cypher_update and cypher_update_with_params remain for callers needing an affected-row count. They accept one property assignment over a mapped target, without RETURN, CREATE, DELETE, MERGE, or map replacement. They execute through the shared runtime, not a separate direct-SQL update engine. Use GraphEngine::cypher for multiple assignments and returned values.

The compatibility facade also retains execute_sql and executor_mut. GraphEngine owns its connection: perform relational setup before passing the connection to GraphEngine::mapped, or consume the engine with into_executor to recover it for subsequent SQL work.