Qirava DMS docs
Reading: joins (nested-loop with index probing)
QQL supports inner joins with JOIN <table> ON <left> = <right>. Joins use a nested-loop strategy: for each left row, the engine probes the right table — using the right side's index on the join key when one exists (O(matches) per left row), otherwise scanning the right side — and re-checks the exact value. Matching right rows are merged into the left row with their fields prefixed by <table>.. Multiple right matches produce cartesian (one-to-many) result rows. This page covers the syntax, the probe strategy, and the merged-row field naming.
Join syntax#
JOIN <table> ON <left_field> = <right_field> joins the FROM table (left) to another table (right) on equality of two fields. The join is an inner join: only left rows with at least one matching right row survive. Multiple JOIN clauses are applied in order, each joining onto the running result. The join key uses a single =.
SELECT id FROM a JOIN b ON aid = bid WHERE id = 1Probe strategy (index or scan)#
For each left row, the engine reads the left join value and probes the right table. If the right table has an equality index on the right join field, it looks up candidate positions through that index (O(matches) per left row); otherwise it scans the right rows. Either way the join value is re-compared exactly (values_eq) before a match is accepted, so an index-superset never produces a wrong row.
for each LEFT row l:
lv = l[left_field]
if RIGHT has index on right_field: candidates = index.lookup(lv)
else: candidates = scan RIGHT
for each r in candidates where r[right_field] == lv:
emit merge(l, r) # right fields prefixed "<right_table>."Merged rows and table.-prefixed fields#
A matched right row's fields are appended to a clone of the left row, each renamed to <right_table>.<field> so left and right fields never collide. The left row keeps its original (unprefixed) field names, including its own _id.
Request
-- a: { k: 1, label: "x" } ; b: { k: 1, extra: "y" }
SELECT * FROM a JOIN b ON k = k WHERE k = 1Response
{
"error": null,
"data": [ {
"_id": 1, "k": 1, "label": "x",
"b._id": 1, "b.k": 1, "b.extra": "y"
} ],
"root": { "count": 1 }
}Cartesian matches and ordering#
- If a left row matches N right rows, it produces N result rows (one-to-many fan-out).
- A left row with zero right matches is dropped (inner-join semantics).
- WHERE on the left FROM table narrows the left rows BEFORE the join is performed (the join runs on the already-filtered candidate set).
- Joined queries use the materializing read path, so subsequent SORT/LIMIT/aggregate/RETURN apply to the merged result rows.