Python V1 · Deprecated
Runtime EDB
Runtime EDB in the Python V1 binding.The Python V1 runtime edb reference continues the Python V1 overview.
EDB: adding facts
The binding exports four type aliases that describe the public term boundary:
from maelys_datalog import Fact, InputTerm, RawFact, ResolvedTerm
# InputTerm = str | int | bool | Term
# ResolvedTerm = str | int | bool
# Fact = tuple[ResolvedTerm, ...]
# RawFact = tuple[Term, ...]ruleset.edb() returns a fresh, independent EDB object, and Edb.add_fact
accepts a Sequence[InputTerm]. EDB facts take Python values directly —
add_fact converts str, int, and bool for you. Use Term explicitly
only when you need to disambiguate (for example, forcing a small integer to be
treated as a pre-interned symbol ID rather than a fresh string to intern — see
Inserting by pre-interned symbol ID
below):
from maelys_datalog import Engine, Predicate, PRED_EDB, PRED_IDB, PRED_QUERY
# This example needs its own vocabulary: document_access above declares
# neither quota_exceeded nor has_flag.
with Engine() as engine:
engine.register_domain('typed_facts_docs', [
Predicate('owns', 2, PRED_EDB),
Predicate('quota_exceeded', 2, PRED_EDB),
Predicate('has_flag', 2, PRED_EDB),
Predicate('allow', 2, PRED_IDB | PRED_QUERY),
])
ruleset = engine.load_inline_ruleset(
'typed_facts_docs', 'typed.main',
'allow(User, Document) :- owns(User, Document).',
)
edb = ruleset.edb()
edb.add_fact('owns', ['alice', 'roadmap.pdf']) # str + str
edb.add_fact('quota_exceeded', ['alice', 1024]) # str + int
edb.add_fact('has_flag', ['alice', True]) # str + bool| Python value | Encoded as | Notes |
|---|---|---|
| str | TERM_SYMBOL | Interned via ruleset.intern_symbol() — idempotent, same string returns the same id. |
| int | TERM_INT | Full native int64_t range — no 32-bit split, unlike the WASM binding. |
| bool | TERM_BOOL | Checked before int — a bool is not treated as 0/1 integer. |
| Term.symbol_id(id) | TERM_SYMBOL | Insert by an already-interned id, skipping a redundant intern call. |
| Term.integer(v) | TERM_INT | Explicit form of the int case above. |
| Term.boolean(v) | TERM_BOOL | Explicit form of the bool case above. |
An add_fact call can fail in two very different ways, from two different
layers — a wrongly shaped call caught in Python, or a well-shaped call the
engine rejects. They raise different exception types, so it is worth keeping
them apart.
Inserting by pre-interned symbol ID
add_fact with a str value is ergonomic sugar: internally it calls
ruleset.intern_symbol(value) and wraps the result in Term.symbol_id(...)
for you, on every call. Use the ID path directly when the same symbol is
inserted many times (dense graphs, repeated nodes): intern once, reuse the
integer handle, and skip the redundant intern lookup on every fact.
from maelys_datalog import Term
alice = ruleset.intern_symbol('alice') # -> positive int handle
doc = ruleset.intern_symbol('roadmap.pdf')
edb = ruleset.edb()
edb.add_fact('owns', [Term.symbol_id(alice), Term.symbol_id(doc)])intern_symbol is idempotent — interning 'alice' twice returns the same
id — and is not scoped to one EDB session. The current
WASM binding accepts typed values instead of symbol IDs.
In this historical Python V1 API, it reads and writes the ruleset's own symbol table directly, so the
same handle stays valid across every Edb created from that Ruleset,
including ones created after the intern call.
Batch insertion
The current maelys_datalog.Edb has no add_facts() method.
add_fact() inserts one fact through the native shim on each call.
Performance comparisons with the WASM boundary require measurements;
neither binding removes the engine's capacity limits.
Read engine.limits.max_edb_facts and max_facts_per_pred from the
loaded library. The SMALL and LARGE builds allow at most 1,024 and 2,048
input facts respectively, with additional per-predicate and symbol limits.
The separate Python Next binding
supports add_fact() and add_facts() as Python-buffer operations, then
submits the entire buffer in one native solve call. That changes when native
validation errors surface; it does not add a batch method to this binding.