qql-core
Transport-free QQL frontend: lexer, parser, typed AST, validation,
inject_filter, and explain. No I/O, no Qdrant JSON.
Canonical grammar: language/v1/grammar.pest
→ qql-grammar-gen → checked-in grammar/ (do not edit by hand).
Proposition
Own the language surface for every SDK. Hosts and agents parse here, inject
policy here, then hand Stmt to qql-plan / runtime.
Statement surface
| Kind | Examples |
|---|---|
| Query | QUERY (nearest, hybrid, formula, recommend, RERANK, CROSS RERANK, …), CTEs |
| Retrieval | SCROLL, COUNT, FACET |
| DML | UPSERT, DELETE, payload/vector updates (DELETE PAYLOAD, …) |
| DDL | CREATE/ALTER/DROP COLLECTION, indexes, CREATE/DROP/SHOW SHARD KEY |
| Meta | SHOW COLLECTIONS / SHOW COLLECTION |
| Quotas | SHOW QUOTAS / SET QUOTA (…) (Qdrant ≥ 1.19; REST at execute time) |
Clause order (QUERY)
QUERY <expr> FROM <coll>
[USING HYBRID … | USING <vec> [AS DENSE|SPARSE|MULTI]]
[PREFETCH (…)] [WHERE …] [SHARD '…'] [PARAMS (…)]
[SCORE THRESHOLD n] [GROUP BY …] [WITH PAYLOAD|VECTOR …]
[LIMIT n] [OFFSET n]
SHARD KEY vs SHARD
| Form | Role |
|---|---|
CREATE SHARD KEY 'acme' ON COLLECTION c |
DDL — define custom partition |
… SHARD 'acme' |
DML — route this request |
… SHARD 101 |
DML — route to a numeric partition (never coerced to "101") |
Routing field after parse: stmt.set_shard_key(Some("acme".into()))
(same AST field; no inject_shard_key).
PARAMS (selected)
Body search params: hnsw_ef, exact, acorn, max_selectivity, quantization,
idf ('global' or WHERE <filter> for sparse IDF, Qdrant ≥ 1.19), …
Request-level (REST query string / gRPC fields): timeout, consistency.
Filters (selected, Qdrant ≥ 1.19)
WHERE title MATCH PREFIX 'Comp' -- keyword prefix (needs prefix=true index)
WHERE SLICE (4, 1) -- hash(id) % total == index; total≥1, index<total
Typed config enums
| Type | Values | Use |
|---|---|---|
MemoryPlacement |
cold / cached / pinned |
`WITH HNSW |
VectorDatatype |
float32 / float16 / uint8 / turbo4 |
dense WITH VECTOR (datatype = …); sparse rejects turbo4 |
CREATE COLLECTION docs (
dense VECTOR(384, COSINE)
WITH VECTOR (memory = 'cached', datatype = 'turbo4')
) WITH HNSW (memory = 'cold')
WITH PARAMS (payload_memory = 'cold');
WITH (prefix = true, memory = 'cached');
SHOW QUOTAS;
SET QUOTA (enabled = true, max_resident_memory_percent = 80) WAIT true;
API
use ;
use Parser;
let mut stmt = parse?;
// Isolation (recurses CTEs / prefetches). Fail-closed on DDL / SHOW /
// UPDATE VECTOR, and on UPSERT unless Eq on a non-id payload field.
// ComparisonOp::parse_inject_op is ASCII-case-insensitive (`EQ`, ` Gt `).
inject_filter?;
// Optional routing (custom sharding)
stmt.set_shard_key;
// Prefer authoring: ... SHARD 'org_99' LIMIT 5
| Feature | Role |
|---|---|
serde |
AST serialize |
json |
Value from/to JSON |
std |
std::error::Error |
Docs
Test