diff --git a/src/binding/c/c_api.cc b/src/binding/c/c_api.cc index a81cc38..bc226f8 100644 --- a/src/binding/c/c_api.cc +++ b/src/binding/c/c_api.cc @@ -6122,6 +6122,34 @@ zvec_error_code_t zvec_sub_query_set_vamana_params( return ZVEC_OK; } +zvec_error_code_t zvec_sub_query_set_fts_params( + zvec_sub_query_t *query, zvec_fts_query_params_t *fts_params) { + if (!query || !fts_params) { + SET_LAST_ERROR(ZVEC_ERROR_INVALID_ARGUMENT, + "Sub-query or FTS params pointer is null"); + return ZVEC_ERROR_INVALID_ARGUMENT; + } + auto *ptr = reinterpret_cast(query); + auto *params_ptr = reinterpret_cast(fts_params); + ptr->target_.query_params_.reset(params_ptr); + return ZVEC_OK; +} + +zvec_error_code_t zvec_sub_query_set_fts(zvec_sub_query_t *query, + const zvec_fts_t *fts) { + if (!query) { + SET_LAST_ERROR(ZVEC_ERROR_INVALID_ARGUMENT, "Sub-query pointer is null"); + return ZVEC_ERROR_INVALID_ARGUMENT; + } + auto *ptr = reinterpret_cast(query); + if (!fts) { + ptr->target_.clause_ = zvec::VectorClause{}; + } else { + ptr->target_.clause_ = *reinterpret_cast(fts); + } + return ZVEC_OK; +} + // ============================================================================= // Index Interface Implementation // ============================================================================= diff --git a/src/include/zvec/c_api.h b/src/include/zvec/c_api.h index d02335c..29b9bd9 100644 --- a/src/include/zvec/c_api.h +++ b/src/include/zvec/c_api.h @@ -2359,6 +2359,24 @@ ZVEC_EXPORT zvec_error_code_t ZVEC_CALL zvec_sub_query_set_flat_params( ZVEC_EXPORT zvec_error_code_t ZVEC_CALL zvec_sub_query_set_vamana_params( zvec_sub_query_t *query, zvec_vamana_query_params_t *vamana_params); +/** + * @brief Set FTS query parameters on a sub-query (takes ownership) + * @param query Sub-query pointer + * @param fts_params FTS query parameters pointer + * @return zvec_error_code_t Error code + */ +ZVEC_EXPORT zvec_error_code_t ZVEC_CALL zvec_sub_query_set_fts_params( + zvec_sub_query_t *query, zvec_fts_query_params_t *fts_params); + +/** + * @brief Set FTS clause on a sub-query (copies the FTS clause) + * @param query Sub-query pointer + * @param fts FTS clause pointer, or NULL to clear + * @return zvec_error_code_t Error code + */ +ZVEC_EXPORT zvec_error_code_t ZVEC_CALL +zvec_sub_query_set_fts(zvec_sub_query_t *query, const zvec_fts_t *fts); + // ============================================================================= // Collection Options and Statistics (Opaque Pointer Pattern) // ============================================================================= diff --git a/tests/c/c_api_test.c b/tests/c/c_api_test.c index 8670ff8..45964b7 100644 --- a/tests/c/c_api_test.c +++ b/tests/c/c_api_test.c @@ -4307,6 +4307,45 @@ void test_fts_wiring_on_vector_query(void) { TEST_END(); } +void test_fts_wiring_on_sub_query(void) { + TEST_START(); + + zvec_fts_t *fts = zvec_fts_create(); + TEST_ASSERT(fts != NULL); + + zvec_error_code_t err = + zvec_fts_set_query_string(fts, "+hello -world \"phrase\""); + TEST_ASSERT(err == ZVEC_OK); + err = zvec_fts_set_match_string(fts, "machine learning"); + TEST_ASSERT(err == ZVEC_OK); + + zvec_sub_query_t *sq = zvec_sub_query_create(); + TEST_ASSERT(sq != NULL); + + // Set FTS clause. + err = zvec_sub_query_set_fts(sq, fts); + TEST_ASSERT(err == ZVEC_OK); + + // Clearing. + err = zvec_sub_query_set_fts(sq, NULL); + TEST_ASSERT(err == ZVEC_OK); + + // Attach FtsQueryParams (transfers ownership). + zvec_fts_query_params_t *fts_params = zvec_query_params_fts_create("AND"); + TEST_ASSERT(fts_params != NULL); + err = zvec_sub_query_set_fts_params(sq, fts_params); + TEST_ASSERT(err == ZVEC_OK); + + // NULL argument checks. + TEST_ASSERT(zvec_sub_query_set_fts(NULL, fts) == ZVEC_ERROR_INVALID_ARGUMENT); + TEST_ASSERT(zvec_sub_query_set_fts_params(NULL, NULL) == + ZVEC_ERROR_INVALID_ARGUMENT); + + zvec_sub_query_destroy(sq); + zvec_fts_destroy(fts); + TEST_END(); +} + void test_fts_end_to_end(void) { TEST_START(); @@ -5964,6 +6003,7 @@ int main(void) { test_fts_index_params_functions(); test_fts_query_params_functions(); test_fts_wiring_on_vector_query(); + test_fts_wiring_on_sub_query(); test_fts_end_to_end(); test_multi_vector_query_with_rrf_reranker();