index/db/commands: fold duplicated index logic into single definitions

Cleanup pass over the secondary-index feature.

add_doc is now the one entry-commit path. create_index and
build_all_indexes each hand-rolled build -> check_unique -> reserve ->
insert, and had already drifted on whether multikey is set before or
after the unique check; add_doc gained an enforce_unique flag so the
rebuild path keeps its tolerate-and-warn behavior. reserve_for and
insert_entries are now the only way the engine touches Index.entries.

One definition each for: prefix comparison and the prefix binary
searches (prefix_order + std.sort), the cartesian-product odometer
(advance_choice), the spec pair list (write_spec builds on spec_pairs,
so the log format and the listIndexes reply share one schema), the _id
clause parser (plan_id reuses analyze_clause), key-pattern direction
(index.descending, which desc_dir already disagreed with on non-numeric
values), option truthiness (query.truthy), the E11000 message, and
index-removal-by-name (Collection.find_index/remove_index). Key-pattern
matching moved out of the dispatcher into index.find_by_key_pattern.

Dead or redundant: ParallelArraysError, the unread `dropped` counter,
insert_entries' discarded gpa, a third pass computing multikey, the
has_id/is_id_index flag pair, Plan.key_len (always lookup_keys[0].len,
now a method), first_match_consumed (now stages = stages[1..]).

Cheaper hot paths: remove_id compacts in one pass instead of an
orderedRemove per hit; Plan.search skips the sort/dedupe when neither
multikey nor multiple lookup keys can produce a repeat; the _id fast
path reuses one scratch key buffer (bson.write_serialized_value); the
plan loop uses the bound collection instead of re-resolving it through
two hash lookups per candidate.

Behavior is unchanged except that dropping plan_id's fixed 16-clause
buffer enables the _id fast path on filters that previously exceeded it.
This commit is contained in:
2026-08-02 13:40:42 +03:00
parent 0d264c6c57
commit 7482042f34
5 changed files with 260 additions and 334 deletions

View File

@@ -604,7 +604,7 @@ pub fn project(arena: std.mem.Allocator, doc: *const bson.Document, proj: *const
for (proj.pairs) |p| {
if (std.mem.eql(u8, p.key, "_id")) continue;
non_id_count += 1;
const flag = projection_flag(p.value);
const flag = truthy(p.value);
inclusion = if (inclusion == null) flag else inclusion;
}
@@ -614,7 +614,7 @@ pub fn project(arena: std.mem.Allocator, doc: *const bson.Document, proj: *const
// Inclusion list: _id unless excluded, plus listed paths.
var include_id = true;
if (bson.get_pair(proj.pairs, "_id")) |idv| {
include_id = projection_flag(idv);
include_id = truthy(idv);
}
if (include_id) {
if (bson.get_pair(doc.pairs, "_id")) |idv| {
@@ -623,7 +623,7 @@ pub fn project(arena: std.mem.Allocator, doc: *const bson.Document, proj: *const
}
for (proj.pairs) |p| {
if (std.mem.eql(u8, p.key, "_id")) continue;
if (!projection_flag(p.value)) continue;
if (!truthy(p.value)) continue;
try project_path(arena, doc.pairs, p.key, out);
}
} else {
@@ -631,7 +631,7 @@ pub fn project(arena: std.mem.Allocator, doc: *const bson.Document, proj: *const
for (doc.pairs) |p| {
if (std.mem.eql(u8, p.key, "_id")) {
var excluded = false;
if (bson.get_pair(proj.pairs, "_id")) |idv| excluded = !projection_flag(idv);
if (bson.get_pair(proj.pairs, "_id")) |idv| excluded = !truthy(idv);
if (excluded) continue;
}
if (is_excluded(proj, p.key)) continue;
@@ -673,7 +673,9 @@ fn has_deeper_exclusion(proj: *const bson.Document, key: []const u8) bool {
return false;
}
fn projection_flag(v: bson.Value) bool {
/// MongoDB's truthiness for an option/flag value (projection flags, index
/// spec options).
pub fn truthy(v: bson.Value) bool {
return switch (v) {
.bool => |b| b,
.int32 => |i| i != 0,