rayforce-sys 1.4.0

Raw FFI bindings to the RayforceDB v2 core (librayforce)
Documentation
/*
 *   Copyright (c) 2025-2026 Anton Kundenko <singaraiona@gmail.com>
 *   All rights reserved.

 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:

 *   The above copyright notice and this permission notice shall be included in all
 *   copies or substantial portions of the Software.

 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *   SOFTWARE.
 */

#ifndef RAY_OPS_FUSED_PRED_H
#define RAY_OPS_FUSED_PRED_H

#include "store/colrange.h"
#include "store/enccol.h"   /* ray_enc_vview_t */
#include "rayforce.h"
#include "ops/internal.h"
#include "ops/glob.h"
#include "table/domain.h"

#define FP_PRED_MAX_CHILDREN 8

typedef enum {
    FP_EQ = 0,
    FP_NE = 1,
    FP_LT = 2,
    FP_LE = 3,
    FP_GT = 4,
    FP_GE = 5,
    FP_LIKE = 6,
    FP_IN = 7,
} fp_op_t;

/* fold values: when the predicate constant is provably outside the
 * column's representable range, we don't run the per-row compare at
 * all — the result is mathematically all-true or all-false.  Without
 * this fold, casting the constant down to the storage width silently
 * truncates (e.g. `u8_col == 300` becoming `u8_col == 44`). */
typedef enum {
    FP_FOLD_NONE  = 0,
    FP_FOLD_FALSE = 1,
    FP_FOLD_TRUE  = 2,
} fp_fold_t;

typedef struct {
    fp_op_t      op;
    int8_t       col_type;
    uint8_t      col_attrs;
    uint8_t      col_esz;
    uint8_t      fold;        /* fp_fold_t — set when cval is out-of-range */
    const void*  col_base;
    ray_t*       col_obj;
    int64_t      col_len;
    int64_t      cval;
    ray_t*       literal; /* borrowed from the predicate graph */
    uint8_t      typed_compare;
    double       fval;
    bool         constant_null;
    bool         float_compare;
    int          cval_in_dict;
    int64_t      cvals[16];
    uint8_t      n_cvals;
    const char*  pat_str;
    size_t       pat_len;
    ray_glob_compiled_t pat_compiled;
    ray_t*       aux_hdr;
    uint8_t*      like_lut;
    uint32_t     like_lut_count;
    ray_t**      like_sym_strings;
    /* FILE-domain column, pinned at compile: entries of the file prefix
     * read straight from the mapping (see ray_sym_domain_raw_pin). */
    ray_sym_domain_raw_t like_raw;
    uint8_t      like_raw_ok;
    /* pattern vs "": the answer for a null text cell and for a cell id the
     * LUT does not cover (the same rule as the bare like kernel). */
    uint8_t      like_empty_match;
    struct ray_sym_domain_s* like_dom;
    /* The bound source (borrowed from the graph).  enc: a generation-2
     * single-file column without a published materialization, or an
     * idict child (materialized or not); col_base
     * and col_obj are NULL at compile and a view is bound per morsel
     * (fp_eval_pred_rs).  col_pool: STR, the base of the pooled ray_str_t
     * offsets col_base's descriptors point into. */
    ray_col_src_t* src;
    bool         enc;
    const char*  col_pool;
    /* P6b: a STR == / != child over a generation-2 column's persisted DICT:
     * col_type RAY_I32, cval its code; fp_bind_view reads the codes by range
     * (never a zone decision: DICT codes are membership values) */
    struct ray_enccol_s* idict;
} fp_cmp_t;

typedef struct {
    fp_cmp_t children[FP_PRED_MAX_CHILDREN];
    uint8_t  n_children;
} fp_pred_t;

/* Evaluate a single comparison over rows [start, end), writing 0/1 into
 * bits[0..end-start). */
void fp_eval_cmp(const fp_cmp_t* p, int64_t start, int64_t end, uint8_t* bits);

/* Evaluate the full (possibly ANDed) predicate; AND of children into bits[].
 * No child may be encoded (fp_eval_pred_rs reads those). */
void fp_eval_pred(const fp_pred_t* p, int64_t start, int64_t end, uint8_t* bits);

/* Per-task range-read scratch, one per child, and one vector view for the
 * encoded leaves (about 21 KB: the task holds it on its stack).  Allocate
 * it per task, free it inside the same task (a scratch holds its column
 * until freed). */
typedef struct {
    ray_col_scratch_t sc[FP_PRED_MAX_CHILDREN];
    ray_enc_vview_t   vb;
} fp_scratch_t;
void   fp_scratch_init(fp_scratch_t* s);
void   fp_scratch_free(fp_scratch_t* s);
/* fp_eval_pred over [start, end) (end - start <= RAY_MORSEL_ELEMS) with
 * range reads for encoded children.  NULL or an owned error. */
ray_t* fp_eval_pred_rs(const fp_pred_t* p, int64_t start, int64_t end,
                       uint8_t* bits, fp_scratch_t* s);

/* Walk an OP_AND tree of leaf comparisons and populate fp_pred_t.
 * Returns 0 on success; -1 with *err NULL when a leaf is not supported
 * (a decline: the caller takes the unfused path) or the fan-in exceeds
 * FP_PRED_MAX_CHILDREN; -1 with an owned *err when binding or the plain
 * request failed (OOM, a corrupt column): the caller returns that error.
 * Call fp_pred_cleanup before releasing the graph (like_dom is borrowed
 * from a bound source). */
int fp_compile_pred(ray_graph_t* g, ray_op_t* pred_op, ray_t* tbl,
                    fp_pred_t* out, ray_t** err);

void fp_pred_cleanup(fp_pred_t* p);

#endif /* RAY_OPS_FUSED_PRED_H */