@@ -114,6 +114,66 @@ typedef enum {
114114 DTYPE_FIXED_SIZE_LIST = 9 ,
115115} vx_dtype_variant ;
116116
117+ /**
118+ * Equalities, inequalities, and boolean operations over possibly null values.
119+ * For most operations, if either side is null, the result is null.
120+ * VX_OPERATOR_KLEENE_AND, VX_OPERATOR_KLEENE_OR obey Kleene (three-valued)
121+ * logic
122+ */
123+ typedef enum {
124+ /**
125+ * Expressions are equal.
126+ */
127+ VX_OPERATOR_EQ = 0 ,
128+ /**
129+ * Expressions are not equal.
130+ */
131+ VX_OPERATOR_NOT_EQ = 1 ,
132+ /**
133+ * Expression is greater than another
134+ */
135+ VX_OPERATOR_GT = 2 ,
136+ /**
137+ * Expression is greater or equal to another
138+ */
139+ VX_OPERATOR_GTE = 3 ,
140+ /**
141+ * Expression is less than another
142+ */
143+ VX_OPERATOR_LT = 4 ,
144+ /**
145+ * Expression is less or equal to another
146+ */
147+ VX_OPERATOR_LTE = 5 ,
148+ /**
149+ * Boolean AND /\.
150+ */
151+ VX_OPERATOR_KLEENE_AND = 6 ,
152+ /**
153+ * Boolean OR \/.
154+ */
155+ VX_OPERATOR_KLEENE_OR = 7 ,
156+ /**
157+ * The sum of the arguments.
158+ * Errors at runtime if the sum would overflow or underflow.
159+ */
160+ VX_OPERATOR_ADD = 8 ,
161+ /**
162+ * The difference between the arguments.
163+ * Errors at runtime if the sum would overflow or underflow.
164+ * The result is null at any index where either input is null.
165+ */
166+ VX_OPERATOR_SUB = 9 ,
167+ /**
168+ * Multiple two numbers
169+ */
170+ VX_OPERATOR_MUL = 10 ,
171+ /**
172+ * Divide the left side by the right side
173+ */
174+ VX_OPERATOR_DIV = 11 ,
175+ } vx_operator ;
176+
117177/**
118178 * Log levels for the Vortex library.
119179 */
@@ -297,6 +357,22 @@ typedef struct vx_dtype vx_dtype;
297357 */
298358typedef struct vx_error vx_error ;
299359
360+ /**
361+ * A node in a Vortex expression tree.
362+ *
363+ * Expressions represent scalar computations that can be performed on
364+ * data. Each expression consists of an encoding (vtable), heap-allocated
365+ * metadata, and child expressions.
366+ *
367+ * Unless stated explicitly, all expressions returned are owned and must
368+ * be freed by the caller.
369+ * Unless stated explicitly, if an operation on const vx_expression* is
370+ * passed NULL, NULL is returned.
371+ * Operations on expressions don't take ownership of input values, and so
372+ * input values must be freed by the caller.
373+ */
374+ typedef struct vx_expression vx_expression ;
375+
300376/**
301377 * A handle to a Vortex file encapsulating the footer and logic for instantiating a reader.
302378 */
@@ -478,6 +554,11 @@ const vx_string *vx_array_get_utf8(const vx_array *array, uint32_t index);
478554 */
479555const vx_binary * vx_array_get_binary (const vx_array * array , uint32_t index );
480556
557+ /**
558+ * Apply the expression to the array, producing a new array in constant time
559+ */
560+ const vx_array * vx_array_apply (const vx_array * array , const vx_expression * expression , vx_error * * error );
561+
481562/**
482563 * Free an owned [`vx_array_iterator`] object.
483564 */
@@ -677,6 +758,100 @@ void vx_error_free(vx_error *ptr);
677758 */
678759const vx_string * vx_error_get_message (const vx_error * error );
679760
761+ /**
762+ * Clone a borrowed [`vx_expression`], returning an owned [`vx_expression`].
763+ *
764+ *
765+ * Must be released with [`vx_expression_free`].
766+ */
767+ const vx_expression * vx_expression_clone (const vx_expression * ptr );
768+
769+ /**
770+ * Free an owned [`vx_expression`] object.
771+ */
772+ void vx_expression_free (const vx_expression * ptr );
773+
774+ /**
775+ * Create a root expression
776+ */
777+ const vx_expression * vx_expression_root (void );
778+
779+ /**
780+ * Create an expression that accesses a field from the root array.
781+ *
782+ * Equivalent to get_item(name, root()).
783+ */
784+ const vx_expression * vx_expression_column (const char * name );
785+
786+ /**
787+ * Create an expression that selects (includes) specific fields from a child
788+ * expression. Child expression must have a DTYPE_STRUCT dtype.
789+ *
790+ * Example:
791+ *
792+ * const vx_expression* root = vx_expression_root();
793+ * const char* names[] = {"name", "age"};
794+ * const vx_expression* select = vx_expression_select(names, 2, root);
795+ * vx_expression_free(select);
796+ * vx_expression_free(root);
797+ *
798+ */
799+ const vx_expression * vx_expression_select (const char * const * names , size_t len , const vx_expression * child );
800+
801+ /**
802+ * Create an AND expression for multiple child expressions.
803+ * If there are no input expressions, returns NULL.
804+ */
805+ const vx_expression * vx_expression_and (const vx_expression * const * expressions , size_t len );
806+
807+ /**
808+ * Create an OR disjunction expression for multiple child expressions.
809+ * If there are no input expressions, returns NULL.
810+ */
811+ const vx_expression * vx_expression_or (const vx_expression * const * expressions , size_t len );
812+
813+ /**
814+ * Create a binary expression for two expressions of form lhs OP rhs.
815+ * If either input is NULL, returns NULL.
816+ *
817+ * Example:
818+ *
819+ * const vx_expression* age = vx_expression_column("age");
820+ * const vx_expression* height = vx_expression_column("height");
821+ * const vx_expression* sum = vx_expression_binary(VX_OPERATOR_SUM, age, height);
822+ * vx_expression_free(sum);
823+ * vx_expression_free(height);
824+ * vx_expression_free(age);
825+ *
826+ */
827+ const vx_expression *
828+ vx_expression_binary (vx_operator operator_ , const vx_expression * lhs , const vx_expression * rhs );
829+
830+ const vx_expression * vx_expression_eq (const vx_expression * lhs , const vx_expression * rhs );
831+
832+ const vx_expression * vx_expression_not_eq (const vx_expression * lhs , const vx_expression * rhs );
833+
834+ const vx_expression * vx_expression_lt (const vx_expression * lhs , const vx_expression * rhs );
835+
836+ const vx_expression * vx_expression_lt_eq (const vx_expression * lhs , const vx_expression * rhs );
837+
838+ const vx_expression * vx_expression_gt (const vx_expression * lhs , const vx_expression * rhs );
839+
840+ const vx_expression * vx_expression_gt_eq (const vx_expression * lhs , const vx_expression * rhs );
841+
842+ const vx_expression * vx_expression_not (const vx_expression * child );
843+
844+ /**
845+ * Create an expression that checks for null values.
846+ *
847+ * Return a boolean array indicating which positions contain null values.
848+ */
849+ const vx_expression * vx_expression_is_null (const vx_expression * child );
850+
851+ const vx_expression * vx_expression_get_item (const vx_expression * child , const char * item );
852+
853+ const vx_expression * vx_expression_list_contains (const vx_expression * list , const vx_expression * value );
854+
680855/**
681856 * Clone a borrowed [`vx_file`], returning an owned [`vx_file`].
682857 *
0 commit comments