pub struct Engine { /* private fields */ }Implementations§
Source§impl Engine
impl Engine
pub fn execute_plan( &mut self, plan: &PlanNode, ) -> Result<QueryResult, QueryError>
Source§impl Engine
impl Engine
pub fn prepare(&mut self, query: &str) -> Result<PreparedQuery, QueryError>
Sourcepub fn execute_prepared(
&mut self,
prep: &PreparedQuery,
literals: &[Literal],
) -> Result<QueryResult, QueryError>
pub fn execute_prepared( &mut self, prep: &PreparedQuery, literals: &[Literal], ) -> Result<QueryResult, QueryError>
Execute a PreparedQuery with the given literal values.
The literals are substituted into a clone of the template plan in
the same deterministic walk order that crate::canonicalize
produces (filter predicate first, then projection, then assignment
RHS, and so on). Substitution errors here mean the caller passed
the wrong number of literals for this query shape.
Sourcepub fn execute_prepared_take(
&mut self,
prep: &PreparedQuery,
literals: &mut [Literal],
) -> Result<QueryResult, QueryError>
pub fn execute_prepared_take( &mut self, prep: &PreparedQuery, literals: &mut [Literal], ) -> Result<QueryResult, QueryError>
Mission C Phase 13: moving variant of Engine::execute_prepared
for the insert fast path. Takes literals by mutable reference
so that each Literal::String can be consumed via mem::take
instead of cloned into a Value::Str. On insert_batch_1k that
removes three per-row heap allocations (name, status, email),
bringing the workload over the line vs SQLite’s amortized
prepare+execute loop.
The caller’s Literal::String entries are replaced with empty
strings on successful inserts — the literals slice is not
left in a valid-for-reuse state except for Int/Float/Bool
values. Non-insert templates fall through to the standard
substitute-and-execute path.
Source§impl Engine
impl Engine
Sourcepub fn new(data_dir: &Path) -> Result<Self>
pub fn new(data_dir: &Path) -> Result<Self>
Open or create a PowDB engine rooted at data_dir.
If the directory already contains a catalog, it is reopened. Otherwise a fresh empty database is created.
§Examples
use powdb_query::executor::Engine;
let dir = tempfile::tempdir().unwrap();
let engine = Engine::new(dir.path()).unwrap();
// Engine is ready — the directory now contains a catalog.Sourcepub fn new_with_wal_archive<F>(data_dir: &Path, archive: F) -> Result<Self>
pub fn new_with_wal_archive<F>(data_dir: &Path, archive: F) -> Result<Self>
Open or create an engine that archives WAL records before any recovery, rollback, or drop checkpoint truncates them. This keeps the query crate independent of replication metadata while giving sync-aware callers one lifecycle boundary for retained-history preservation.
Sourcepub fn with_memory_limit(data_dir: &Path, limit_bytes: usize) -> Result<Self>
pub fn with_memory_limit(data_dir: &Path, limit_bytes: usize) -> Result<Self>
Open or create an engine with an explicit per-query memory limit
(bytes). Used by the server to apply POWDB_QUERY_MEMORY_LIMIT, and by
tests that need a tiny limit to exercise the budget guard.
Sourcepub fn with_memory_limit_and_wal_archive<F>(
data_dir: &Path,
limit_bytes: usize,
archive: F,
) -> Result<Self>
pub fn with_memory_limit_and_wal_archive<F>( data_dir: &Path, limit_bytes: usize, archive: F, ) -> Result<Self>
Open or create an archive-aware engine with an explicit per-query memory limit.
Sourcepub fn query_memory_limit(&self) -> usize
pub fn query_memory_limit(&self) -> usize
Current per-query memory limit in bytes.
Sourcepub fn set_query_memory_limit(&mut self, limit_bytes: usize)
pub fn set_query_memory_limit(&mut self, limit_bytes: usize)
Override the per-query memory limit in bytes (builder-style).
Sourcepub fn nested_loop_pair_limit(&self) -> usize
pub fn nested_loop_pair_limit(&self) -> usize
Current fallback nested-loop join candidate-pair cap.
Sourcepub fn set_nested_loop_pair_limit(&mut self, limit: usize)
pub fn set_nested_loop_pair_limit(&mut self, limit: usize)
Override the fallback nested-loop join candidate-pair cap. Used by the
server to apply POWDB_MAX_NESTED_LOOP_PAIRS, and by tests that need a
tiny cap to exercise the guard on a small join. A zero limit is clamped
to 1 so a valid single-pair join is never rejected outright.
Sourcepub fn set_wal_sync_mode(&mut self, mode: WalSyncMode)
pub fn set_wal_sync_mode(&mut self, mode: WalSyncMode)
Set the WAL durability mode (see WalSyncMode). Full (the default)
fsyncs every commit; Normal moves the fsync to a background flusher
with a bounded crash-loss window; Off is bench-only (no durability).
Wired from the server’s POWDB_SYNC_MODE / --sync-mode config.
Sourcepub fn run_with_deferred_durability<T>(
&mut self,
f: impl FnOnce(&mut Engine) -> T,
) -> (T, Option<WalDurabilityTicket>)
pub fn run_with_deferred_durability<T>( &mut self, f: impl FnOnce(&mut Engine) -> T, ) -> (T, Option<WalDurabilityTicket>)
Run f with commit durability deferred — the WAL group-commit entry
point for callers that serialize writers behind an exclusive lock.
Inside f, Full-mode commit points register the WAL generation they
need durable instead of fsyncing inline. The returned ticket (if any)
must be waited on before the statement’s result is acknowledged; the
caller should release its exclusive engine lock first, so other
committers can append while the fsync runs. That overlap is what lets
one fsync cover many commits. A lone committer’s wait performs the
fsync immediately — group commit never introduces a delay.
Normal/Off sync modes return no ticket; their durability
contracts are unchanged. If f panics the engine must not be reused
(the deferral flag may still be set); lock poisoning enforces this
for callers that share the engine behind a lock.
Sourcepub fn wal_fsync_count(&self) -> u64
pub fn wal_fsync_count(&self) -> u64
Number of fsyncs issued against the WAL (test/metrics hook).
Sourcepub fn rollback_transaction_with_wal_archive<F>(
&mut self,
archive: F,
) -> Result<QueryResult, QueryError>
pub fn rollback_transaction_with_wal_archive<F>( &mut self, archive: F, ) -> Result<QueryResult, QueryError>
Roll back the active explicit transaction while archiving any committed
pre-transaction WAL records that recovery must replay and truncate.
This is the sync-aware counterpart to the ordinary rollback statement;
callers provide the archive hook so the query crate stays independent of
replication metadata.
pub fn rollback_transaction_preserving_wal_archive( &mut self, ) -> Result<QueryResult, QueryError>
Sourcepub fn execute_with_dialect(
&mut self,
dialect: QueryDialect,
input: &str,
) -> Result<QueryResult, QueryError>
pub fn execute_with_dialect( &mut self, dialect: QueryDialect, input: &str, ) -> Result<QueryResult, QueryError>
Dispatch to the requested query frontend.
Sourcepub fn execute_readonly_with_dialect(
&self,
dialect: QueryDialect,
input: &str,
) -> Result<QueryResult, QueryError>
pub fn execute_readonly_with_dialect( &self, dialect: QueryDialect, input: &str, ) -> Result<QueryResult, QueryError>
Read-only variant of Engine::execute_with_dialect.
Sourcepub fn execute_powql(&mut self, input: &str) -> Result<QueryResult, QueryError>
pub fn execute_powql(&mut self, input: &str) -> Result<QueryResult, QueryError>
Parse + plan + execute a PowQL query.
§Examples
use powdb_query::executor::Engine;
use powdb_query::result::QueryResult;
let dir = tempfile::tempdir().unwrap();
let mut engine = Engine::new(dir.path()).unwrap();
// Create a table and insert a row.
engine.execute_powql("type User { required name: str, age: int }").unwrap();
engine.execute_powql(r#"insert User { name := "Alice", age := 30 }"#).unwrap();
// Query rows back.
let result = engine.execute_powql("User").unwrap();
assert_eq!(result.row_count(), 1);Mission D6 — tracing collapse: the previous implementation ran 4
Instant::now() + 3 elapsed().as_micros() calls + formatted an
info! span on every query, even when tracing was disabled. On a
sub-microsecond point_lookup_indexed call that overhead was
100-200ns — 20%+ of the whole query. We now measure time only when
INFO is actually enabled via tracing::enabled!, and we moved the
noisy debug!(?plan) line behind the same gate so the Debug
formatter can’t run unconditionally either.
Mission D9 — plan cache: on the hot path we canonicalise the query text (lex + FNV-1a hash with literal values stripped), check the cache, and on a hit substitute the new literals into a clone of the cached plan. This skips re-lexing, re-parsing, and re-planning — around 3μs per call on bench workloads. On a miss we plan as before and insert the plan under its canonical hash.
Sourcepub fn execute_sql(&mut self, input: &str) -> Result<QueryResult, QueryError>
pub fn execute_sql(&mut self, input: &str) -> Result<QueryResult, QueryError>
Parse + plan + execute a SQL query through the SQL frontend.
SQL is lowered to the existing PowDB AST and to canonical PowQL text. The canonical PowQL text is used as the plan-cache key, so equivalent SQL and PowQL spellings share cached plans.
Sourcepub fn execute_sql_readonly(
&self,
input: &str,
) -> Result<QueryResult, QueryError>
pub fn execute_sql_readonly( &self, input: &str, ) -> Result<QueryResult, QueryError>
Read-only variant of Engine::execute_sql.
Sourcepub fn execute_powql_with_params(
&mut self,
input: &str,
params: &[ParamValue],
) -> Result<QueryResult, QueryError>
pub fn execute_powql_with_params( &mut self, input: &str, params: &[ParamValue], ) -> Result<QueryResult, QueryError>
Execute PowQL with $N placeholders bound to positional params.
Task 4: parameters are substituted as literal tokens before
parsing (see crate::parser::parse_with_params), so untrusted
input can never change the query’s shape. This path deliberately
bypasses the plan cache — template caching is a follow-up — and
otherwise mirrors the non-cached tail of Engine::execute_powql.
Sourcepub fn execute_powql_readonly_with_params(
&self,
input: &str,
params: &[ParamValue],
) -> Result<QueryResult, QueryError>
pub fn execute_powql_readonly_with_params( &self, input: &str, params: &[ParamValue], ) -> Result<QueryResult, QueryError>
Read-only variant of Engine::execute_powql_with_params.
Mirrors Engine::execute_powql_readonly: parses with bound
params, rejects any write statement with
QueryError::ReadonlyNeedsWrite so the caller can escalate to the
write lock, then executes under a shared borrow. No plan-cache
interaction.
Sourcepub fn execute_powql_with_cancel(
&mut self,
input: &str,
cancel: Arc<ExecCancel>,
) -> Result<QueryResult, QueryError>
pub fn execute_powql_with_cancel( &mut self, input: &str, cancel: Arc<ExecCancel>, ) -> Result<QueryResult, QueryError>
Cancellation-aware variant of Engine::execute_powql. Installs
cancel as the current thread’s cancellation token for the duration of
the statement, so cancellable read and mutation-target discovery loops
poll it. Mutation application checks once before its first write, then
finishes without polling because the engine has no statement savepoint
with which to undo a written prefix. The base methods also honor an
already installed token; a caller with no token (embedded/direct use)
never cancels.
Sourcepub fn execute_sql_with_cancel(
&mut self,
input: &str,
cancel: Arc<ExecCancel>,
) -> Result<QueryResult, QueryError>
pub fn execute_sql_with_cancel( &mut self, input: &str, cancel: Arc<ExecCancel>, ) -> Result<QueryResult, QueryError>
Cancellation-aware variant of Engine::execute_sql.
Sourcepub fn execute_powql_readonly_with_cancel(
&self,
input: &str,
cancel: Arc<ExecCancel>,
) -> Result<QueryResult, QueryError>
pub fn execute_powql_readonly_with_cancel( &self, input: &str, cancel: Arc<ExecCancel>, ) -> Result<QueryResult, QueryError>
Cancellation-aware variant of Engine::execute_powql_readonly.
Sourcepub fn execute_sql_readonly_with_cancel(
&self,
input: &str,
cancel: Arc<ExecCancel>,
) -> Result<QueryResult, QueryError>
pub fn execute_sql_readonly_with_cancel( &self, input: &str, cancel: Arc<ExecCancel>, ) -> Result<QueryResult, QueryError>
Cancellation-aware variant of Engine::execute_sql_readonly.
Sourcepub fn execute_powql_with_params_and_cancel(
&mut self,
input: &str,
params: &[ParamValue],
cancel: Arc<ExecCancel>,
) -> Result<QueryResult, QueryError>
pub fn execute_powql_with_params_and_cancel( &mut self, input: &str, params: &[ParamValue], cancel: Arc<ExecCancel>, ) -> Result<QueryResult, QueryError>
Cancellation-aware variant of Engine::execute_powql_with_params.
Sourcepub fn execute_powql_readonly_with_params_and_cancel(
&self,
input: &str,
params: &[ParamValue],
cancel: Arc<ExecCancel>,
) -> Result<QueryResult, QueryError>
pub fn execute_powql_readonly_with_params_and_cancel( &self, input: &str, params: &[ParamValue], cancel: Arc<ExecCancel>, ) -> Result<QueryResult, QueryError>
Cancellation-aware variant of Engine::execute_powql_readonly_with_params.
Sourcepub fn plan_cache_stats(&self) -> (u64, u64, usize)
pub fn plan_cache_stats(&self) -> (u64, u64, usize)
Plan cache stats — useful for benches and debugging.
Sourcepub fn execute_powql_readonly(
&self,
input: &str,
) -> Result<QueryResult, QueryError>
pub fn execute_powql_readonly( &self, input: &str, ) -> Result<QueryResult, QueryError>
Mission infra-1: read-only entry point.
Parses + plans + executes a PowQL query using only a shared borrow
on the engine. Rejects any statement that would mutate state
(Insert/Update/Delete/CreateTable/AlterTable/DropTable/CreateView/
RefreshView/DropView) by returning READONLY_NEEDS_WRITE so the
caller can escalate to the write lock.
Also returns READONLY_NEEDS_WRITE if a materialized view in the
query is dirty — refreshing one requires &mut self, so the caller
must retake the write lock for the first refresh.
This method is the concurrent-read fast path behind
Arc<RwLock<Engine>>: multiple threads can call it simultaneously
under a shared .read() lock and each will scan independently.