Functions: predicates & queries
Predicates (11)
Section titled “Predicates (11)”Ten constructors return an OWNED corvid_pred* (NULL + CORVID_E_ARGUMENT
on bad input); the combinators consume their children. Rust counterparts
are the corvid::field(path) fluent builders. Paths are dotted and traverse
nested maps; an empty path resolves nothing.
corvid_pred* corvid_pred_exists(const char *path, size_t path_len);True when the path resolves. Counterpart: field(path).exists().
corvid_pred* corvid_pred_compare(const char *path, size_t path_len, corvid_cmp op, const corvid_value *value);Compare against a constant (CLONED). Counterpart: field(path).eq/ne/....
Semantics: missing path ⇒ false; unordered kinds under ordered ops ⇒ false;
Int/Float compare numerically across kinds (exact to 2^53); NaN compares
false against everything except NE.
corvid_pred* corvid_pred_in(const char *path, size_t path_len, const corvid_value *const *values, size_t count);corvid_pred* corvid_pred_between(const char *path, size_t path_len, const corvid_value *low, const corvid_value *high);corvid_pred* corvid_pred_starts_with(const char *path, size_t path_len, const char *prefix, size_t prefix_len);corvid_pred* corvid_pred_contains(const char *path, size_t path_len, const char *substr, size_t substr_len);is_in (each element CLONED; empty list matches nothing), inclusive
between, and the two text predicates (false on non-text values and missing
paths).
corvid_pred* corvid_pred_geo_within(const char *path, size_t path_len, double lat, double lon, double radius_km);Path holds a point within radius_km (inclusive, haversine). Counterpart:
field(path).within_km(...).
corvid_pred* corvid_pred_and(corvid_pred *a, corvid_pred *b);corvid_pred* corvid_pred_or(corvid_pred *a, corvid_pred *b);corvid_pred* corvid_pred_not(corvid_pred *a);void corvid_pred_free(corvid_pred *p);Combinators consume their argument(s) and return a new root — after a
combine, the children belong to the tree. corvid_pred_free frees a
never-consumed root only: predicates handed to and/or/not,
corvid_query_filter, or corvid_delete_where are consumed and must not be
freed (double free = UB).
Query builder & rows (15)
Section titled “Query builder & rows (15)”A query is built on a corvid_query* (single-threaded) and executed by
corvid_query_run or any aggregate, either of which consumes it
(mirroring the Rust builder taking self).
corvid_query* corvid_query_new(corvid_coll *coll); /* Collection::query() */
corvid_status corvid_query_filter(corvid_query *q, corvid_pred *pred);Add a filter — CONSUMES pred. Multiple calls AND together.
corvid_status corvid_query_vector(corvid_query *q, const char *field, size_t field_len, const float *query, size_t dim, size_t k, corvid_metric metric);corvid_status corvid_query_text(corvid_query *q, const char *field, size_t field_len, const char *s, size_t s_len, size_t k);Add a vector source (query CLONED) / a BM25 text source.
corvid_status corvid_query_fuse_rrf(corvid_query *q, float k); /* default 60 */corvid_status corvid_query_rerank_mmr(corvid_query *q, float lambda); /* [0,1] */The setters always succeed; the engine validates at execution (a
non-positive/NaN k or out-of-range lambda fails run/aggregates with
CORVID_E_ARGUMENT).
corvid_status corvid_query_approx(corvid_query *q);corvid_status corvid_query_limit(corvid_query *q, size_t n);corvid_status corvid_query_offset(corvid_query *q, size_t n);corvid_status corvid_query_order_by(corvid_query *q, const char *field, size_t field_len, int descending);corvid_status corvid_query_select(corvid_query *q, const char *const *fields, const size_t *field_lens, size_t count);limit 0 yields empty; offset applies after ordering, before limit. The
ordering contract is the engine’s class rule (comparable → incomparable →
missing, ties by key; descending reverses within-class order only — see
ordering). select projects result documents
(missing fields absent; non-map documents pass through; ranking sees the
full document).
corvid_rows* corvid_query_run(corvid_query *q);Execute — CONSUMES q. Returns a rows cursor even for an empty result
(distinguish failure by CORVID_ERR); NULL + error on failure. One MVCC
snapshot covers the query; ranking parameters validate here.
void corvid_query_free(corvid_query *q);For builders abandoned without running — NOT after run/aggregates.
int corvid_rows_next(corvid_rows *rows, const uint8_t **key_out, size_t *key_len_out, const corvid_value **doc_out, float *score_out);void corvid_rows_free(corvid_rows *rows);Advance: 1 and fill out-params, 0 at exhaustion (never errors — the result
is materialized). The key and document are BORROWED from the cursor:
valid only until the next corvid_rows_next or corvid_rows_free —
using or freeing them after is UB; corvid_value_clone copies what you keep.
score is the fused RRF score (0.0 for pure filter/order queries and
corvid_page rows).
Next: aggregations & mutations.