Skip to content

Commit 7af6a31

Browse files
authored
fix: c api ut crash on window platform (alibaba#298)
* fix c api ut * remove c query_by_group
1 parent dc8d1a5 commit 7af6a31

3 files changed

Lines changed: 27 additions & 183 deletions

File tree

src/binding/c/c_api.cc

Lines changed: 3 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,9 @@ void zvec_string_array_add(ZVecStringArray *array, size_t idx,
984984
void zvec_string_array_destroy(ZVecStringArray *array) {
985985
if (!array) return;
986986
for (size_t i = 0; i < array->count; i++) {
987-
free((void *)array->strings[i].data);
987+
if (array->strings[i].data) {
988+
free((void *)array->strings[i].data);
989+
}
988990
}
989991
free(array->strings);
990992
free(array);
@@ -5928,77 +5930,6 @@ ZVecErrorCode convert_document_results(
59285930
return ZVEC_OK;
59295931
}
59305932

5931-
// Helper function to convert grouped document results to C API format
5932-
ZVecErrorCode convert_grouped_document_results(
5933-
const std::vector<zvec::GroupResult> &group_results, ZVecDoc ***results,
5934-
ZVecString ***group_by_values, size_t *result_count) {
5935-
// Calculate total document count across all groups
5936-
size_t total_docs = 0;
5937-
for (const auto &group_result : group_results) {
5938-
total_docs += group_result.docs_.size();
5939-
}
5940-
5941-
// Allocate memory for document pointers and group by values
5942-
*result_count = total_docs;
5943-
*results =
5944-
static_cast<ZVecDoc **>(malloc(*result_count * sizeof(ZVecDoc *)));
5945-
*group_by_values = static_cast<ZVecString **>(
5946-
malloc(group_results.size() * sizeof(ZVecString *)));
5947-
5948-
if (!*results) {
5949-
set_last_error("Failed to allocate memory for query results");
5950-
return ZVEC_ERROR_INTERNAL_ERROR;
5951-
}
5952-
5953-
// Convert C++ grouped results to C API format
5954-
size_t doc_index = 0;
5955-
for (const auto &group_result : group_results) {
5956-
for (const auto &internal_doc : group_result.docs_) {
5957-
if (doc_index >= *result_count) {
5958-
break;
5959-
}
5960-
5961-
// Create new document wrapper
5962-
ZVecDoc *c_doc = zvec_doc_create();
5963-
if (!c_doc) {
5964-
// Clean up previously allocated documents
5965-
for (size_t j = 0; j < doc_index; ++j) {
5966-
zvec_doc_destroy((*results)[j]);
5967-
}
5968-
free(*results);
5969-
*results = nullptr;
5970-
*result_count = 0;
5971-
set_last_error("Failed to create document wrapper");
5972-
return ZVEC_ERROR_INTERNAL_ERROR;
5973-
}
5974-
5975-
// Copy the C++ document to our wrapper
5976-
auto *doc_ptr = reinterpret_cast<zvec::Doc *>(c_doc);
5977-
*doc_ptr = internal_doc; // Copy assignment
5978-
5979-
ZVecString *c_group_value =
5980-
zvec_string_create(group_result.group_by_value_.c_str());
5981-
if (!c_group_value) {
5982-
for (size_t j = 0; j < doc_index; ++j) {
5983-
zvec_doc_destroy((*results)[j]);
5984-
zvec_free_string((*group_by_values)[doc_index]);
5985-
}
5986-
free(*results);
5987-
*results = nullptr;
5988-
*result_count = 0;
5989-
set_last_error("Failed to create string wrapper");
5990-
return ZVEC_ERROR_INTERNAL_ERROR;
5991-
}
5992-
5993-
(*group_by_values)[doc_index] = c_group_value;
5994-
(*results)[doc_index] = c_doc;
5995-
++doc_index;
5996-
}
5997-
}
5998-
5999-
return ZVEC_OK;
6000-
}
6001-
60025933
// Helper function to convert fetched document results to C API format
60035934
static void normalize_nullable_fields_for_fetch(
60045935
const zvec::CollectionSchema &schema, zvec::DocPtrMap &doc_map) {
@@ -6122,44 +6053,6 @@ ZVecErrorCode zvec_collection_query(const ZVecCollection *collection,
61226053
return error_code;)
61236054
}
61246055

6125-
ZVecErrorCode zvec_collection_query_by_group(
6126-
const ZVecCollection *collection, const ZVecGroupByVectorQuery *query,
6127-
ZVecDoc ***results, ZVecString ***group_by_values, size_t *result_count) {
6128-
if (!collection || !query || !results || !group_by_values ||
6129-
!result_count) {
6130-
set_last_error(
6131-
"Invalid arguments: collection, query, results, group_by_values and "
6132-
"result_count cannot "
6133-
"be null");
6134-
return ZVEC_ERROR_INVALID_ARGUMENT;
6135-
}
6136-
6137-
ZVEC_TRY_RETURN_ERROR(
6138-
"Exception occurred",
6139-
auto coll_ptr =
6140-
reinterpret_cast<const std::shared_ptr<zvec::Collection> *>(
6141-
collection);
6142-
6143-
// Cast ZVecGroupByVectorQuery* to zvec::GroupByVectorQuery* directly
6144-
auto *internal_query =
6145-
reinterpret_cast<const zvec::GroupByVectorQuery *>(query);
6146-
6147-
auto result = (*coll_ptr)->GroupByQuery(*internal_query);
6148-
ZVecErrorCode error_code = handle_expected_result(result);
6149-
6150-
if (error_code == ZVEC_OK) {
6151-
const auto &group_results = result.value();
6152-
error_code = convert_grouped_document_results(
6153-
group_results, results, group_by_values, result_count);
6154-
} else {
6155-
*results = nullptr;
6156-
*group_by_values = nullptr;
6157-
*result_count = 0;
6158-
}
6159-
6160-
return error_code;)
6161-
}
6162-
61636056
ZVecErrorCode zvec_collection_fetch(ZVecCollection *collection,
61646057
const char *const *pks, size_t pk_count,
61656058
ZVecDoc ***results, size_t *doc_count) {

src/include/zvec/c_api.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,21 +2636,6 @@ ZVEC_EXPORT ZVecErrorCode ZVEC_CALL zvec_collection_query(
26362636
const ZVecCollection *collection, const ZVecVectorQuery *query,
26372637
ZVecDoc ***results, size_t *result_count);
26382638

2639-
/**
2640-
* @brief Grouped vector similarity search
2641-
* @param collection Collection handle
2642-
* @param query Grouped query parameters pointer
2643-
* @param[out] results Returned document array (needs to be freed by calling
2644-
* zvec_docs_free)
2645-
* @param[out] group_by_values Returned group by field values array (needs to be
2646-
* freed by calling zvec_string_array_destroy)
2647-
* @param[out] result_count Number of returned results
2648-
* @return ZVecErrorCode Error code
2649-
*/
2650-
ZVEC_EXPORT ZVecErrorCode ZVEC_CALL zvec_collection_query_by_group(
2651-
const ZVecCollection *collection, const ZVecGroupByVectorQuery *query,
2652-
ZVecDoc ***results, ZVecString ***group_by_values, size_t *result_count);
2653-
26542639
/**
26552640
* @brief Fetch documents by primary keys
26562641
* @param collection Collection handle

tests/c/c_api_test.c

Lines changed: 24 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,7 +2621,7 @@ void test_doc_get_field_value_copy(void) {
26212621
TEST_ASSERT(((int32_t *)array_int32_result)[0] == 100);
26222622
TEST_ASSERT(((int32_t *)array_int32_result)[1] == 200);
26232623
TEST_ASSERT(((int32_t *)array_int32_result)[2] == 300);
2624-
free(array_int32_result);
2624+
zvec_free(array_int32_result);
26252625

26262626
// ARRAY_INT64 type
26272627
int64_t array_int64_data[] = {-9223372036854775807LL, 0,
@@ -2642,7 +2642,7 @@ void test_doc_get_field_value_copy(void) {
26422642
TEST_ASSERT(((int64_t *)array_int64_result)[0] == -9223372036854775807LL);
26432643
TEST_ASSERT(((int64_t *)array_int64_result)[1] == 0);
26442644
TEST_ASSERT(((int64_t *)array_int64_result)[2] == 9223372036854775807LL);
2645-
free(array_int64_result);
2645+
zvec_free(array_int64_result);
26462646

26472647
// ARRAY_UINT32 type
26482648
uint32_t array_uint32_data[] = {0U, 1000000U, 4000000000U};
@@ -2662,7 +2662,7 @@ void test_doc_get_field_value_copy(void) {
26622662
TEST_ASSERT(((uint32_t *)array_uint32_result)[0] == 0U);
26632663
TEST_ASSERT(((uint32_t *)array_uint32_result)[1] == 1000000U);
26642664
TEST_ASSERT(((uint32_t *)array_uint32_result)[2] == 4000000000U);
2665-
free(array_uint32_result);
2665+
zvec_free(array_uint32_result);
26662666

26672667
// ARRAY_UINT64 type
26682668
uint64_t array_uint64_data[] = {0ULL, 1000000000000ULL,
@@ -2683,7 +2683,7 @@ void test_doc_get_field_value_copy(void) {
26832683
TEST_ASSERT(((uint64_t *)array_uint64_result)[0] == 0ULL);
26842684
TEST_ASSERT(((uint64_t *)array_uint64_result)[1] == 1000000000000ULL);
26852685
TEST_ASSERT(((uint64_t *)array_uint64_result)[2] == 18000000000000000000ULL);
2686-
free(array_uint64_result);
2686+
zvec_free(array_uint64_result);
26872687

26882688
// ARRAY_FLOAT type
26892689
float array_float_data[] = {1.5f, 2.5f, 3.5f};
@@ -2703,7 +2703,7 @@ void test_doc_get_field_value_copy(void) {
27032703
TEST_ASSERT(((float *)array_float_result)[0] == 1.5f);
27042704
TEST_ASSERT(((float *)array_float_result)[1] == 2.5f);
27052705
TEST_ASSERT(((float *)array_float_result)[2] == 3.5f);
2706-
free(array_float_result);
2706+
zvec_free(array_float_result);
27072707

27082708
// ARRAY_DOUBLE type
27092709
double array_double_data[] = {1.111111, 2.222222, 3.333333};
@@ -2723,10 +2723,10 @@ void test_doc_get_field_value_copy(void) {
27232723
TEST_ASSERT(fabs(((double *)array_double_result)[0] - 1.111111) < 1e-10);
27242724
TEST_ASSERT(fabs(((double *)array_double_result)[1] - 2.222222) < 1e-10);
27252725
TEST_ASSERT(fabs(((double *)array_double_result)[2] - 3.333333) < 1e-10);
2726-
free(array_double_result);
2726+
zvec_free(array_double_result);
27272727

27282728

2729-
free(binary_field.value.string_value.data);
2729+
zvec_free(binary_field.value.string_value.data);
27302730
zvec_doc_destroy(doc);
27312731

27322732
TEST_END();
@@ -3142,8 +3142,8 @@ void test_doc_get_field_value_pointer(void) {
31423142
TEST_ASSERT(fabs(((const double *)array_double_ptr)[1] - 2.222222) < 1e-10);
31433143
TEST_ASSERT(fabs(((const double *)array_double_ptr)[2] - 3.333333) < 1e-10);
31443144

3145-
free(string_field.value.string_value.data);
3146-
free(binary_field.value.string_value.data);
3145+
zvec_free(string_field.value.string_value.data);
3146+
zvec_free(binary_field.value.string_value.data);
31473147
zvec_doc_destroy(doc);
31483148

31493149
TEST_END();
@@ -3217,7 +3217,7 @@ void test_doc_field_operations(void) {
32173217
TEST_ASSERT(found_key_fields == true);
32183218

32193219
zvec_free_str_array(field_names, name_count);
3220-
free(string_field.value.string_value.data);
3220+
zvec_free(string_field.value.string_value.data);
32213221
zvec_doc_destroy(doc);
32223222

32233223
TEST_END();
@@ -3350,21 +3350,21 @@ void test_index_params(void) {
33503350
ZVecIndexParams *hnsw_params = zvec_test_create_default_hnsw_params();
33513351
TEST_ASSERT(hnsw_params != NULL);
33523352
if (hnsw_params) {
3353-
free(hnsw_params);
3353+
zvec_free(hnsw_params);
33543354
}
33553355

33563356
// Test Flat parameter creation
33573357
ZVecIndexParams *flat_params = zvec_test_create_default_flat_params();
33583358
TEST_ASSERT(flat_params != NULL);
33593359
if (flat_params) {
3360-
free(flat_params);
3360+
zvec_free(flat_params);
33613361
}
33623362

33633363
// Test scalar index parameter creation
33643364
ZVecIndexParams *invert_params = zvec_test_create_default_invert_params(true);
33653365
TEST_ASSERT(invert_params != NULL);
33663366
if (invert_params) {
3367-
free(invert_params);
3367+
zvec_free(invert_params);
33683368
}
33693369

33703370
TEST_END();
@@ -4681,40 +4681,6 @@ void test_collection_query_functions(void) {
46814681
TEST_ASSERT(found_count == 2);
46824682
zvec_docs_free(results, found_count);
46834683

4684-
// Test zvec_collection_query_by_group
4685-
ZVecGroupByVectorQuery *group_query = zvec_group_by_vector_query_create();
4686-
TEST_ASSERT(group_query != NULL);
4687-
zvec_group_by_vector_query_set_field_name(group_query, "vec");
4688-
float query_vec[4] = {0.5f, 0.5f, 0.0f, 0.0f};
4689-
zvec_group_by_vector_query_set_query_vector(group_query, query_vec,
4690-
sizeof(query_vec));
4691-
zvec_group_by_vector_query_set_group_by_field_name(group_query, "name");
4692-
zvec_group_by_vector_query_set_group_count(group_query, 2);
4693-
zvec_group_by_vector_query_set_group_topk(group_query, 1);
4694-
zvec_group_by_vector_query_set_include_vector(group_query, false);
4695-
4696-
const char *output_fields[] = {"name"};
4697-
zvec_group_by_vector_query_set_output_fields(group_query, output_fields, 1);
4698-
4699-
ZVecDoc **group_results = NULL;
4700-
ZVecString **group_values = NULL;
4701-
size_t group_result_count = 0;
4702-
err =
4703-
zvec_collection_query_by_group(collection, group_query, &group_results,
4704-
&group_values, &group_result_count);
4705-
TEST_ASSERT(err == ZVEC_OK);
4706-
if (group_results) {
4707-
zvec_docs_free(group_results, group_result_count);
4708-
}
4709-
if (group_values) {
4710-
for (size_t i = 0; i < group_result_count; i++) {
4711-
zvec_free_string(group_values[i]);
4712-
}
4713-
free(group_values);
4714-
}
4715-
4716-
zvec_group_by_vector_query_destroy(group_query);
4717-
47184684
// Test zvec_collection_get_options
47194685
ZVecCollectionOptions *options = NULL;
47204686
err = zvec_collection_get_options(collection, &options);
@@ -4750,7 +4716,7 @@ void test_doc_advanced_functions(void) {
47504716
const char *pk_copy = zvec_doc_get_pk_copy(doc);
47514717
TEST_ASSERT(pk_copy != NULL);
47524718
TEST_ASSERT(strcmp(pk_copy, "test_pk_copy") == 0);
4753-
free((void *)pk_copy);
4719+
zvec_free((void *)pk_copy);
47544720

47554721
// Test zvec_doc_is_empty
47564722
ZVecDoc *empty_doc = zvec_doc_create();
@@ -4803,7 +4769,7 @@ void test_doc_advanced_functions(void) {
48034769
ZVecErrorCode err = zvec_doc_validate(val_doc, schema, false, &error_msg);
48044770
TEST_ASSERT(err == ZVEC_OK);
48054771
if (error_msg) {
4806-
free(error_msg);
4772+
zvec_free(error_msg);
48074773
}
48084774

48094775
zvec_doc_destroy(val_doc);
@@ -4823,7 +4789,7 @@ void test_doc_advanced_functions(void) {
48234789
TEST_ASSERT(err == ZVEC_OK);
48244790
TEST_ASSERT(detail_str != NULL);
48254791
// printf(" Document detail: %s\n", detail_str);
4826-
free(detail_str);
4792+
zvec_free(detail_str);
48274793

48284794
zvec_doc_destroy(detail_doc);
48294795

@@ -4967,7 +4933,7 @@ void test_collection_open_close(void) {
49674933
zvec_get_last_error(&error_msg);
49684934
printf(" Insert error: %s (err=%d, success=%zu)\n",
49694935
error_msg ? error_msg : "unknown", err, success_count);
4970-
if (error_msg) free(error_msg);
4936+
if (error_msg) zvec_free(error_msg);
49714937
}
49724938
TEST_ASSERT(err == ZVEC_OK);
49734939
TEST_ASSERT(success_count == 1);
@@ -4985,7 +4951,7 @@ void test_collection_open_close(void) {
49854951
zvec_get_last_error(&error_msg);
49864952
printf(" Open error: %s (err=%d)\n", error_msg ? error_msg : "unknown",
49874953
err);
4988-
if (error_msg) free(error_msg);
4954+
if (error_msg) zvec_free(error_msg);
49894955
}
49904956
TEST_ASSERT(err == ZVEC_OK);
49914957
TEST_ASSERT(reopened_collection != NULL);
@@ -5008,19 +4974,19 @@ void test_collection_open_close(void) {
50084974
zvec_get_last_error(&error_msg);
50094975
printf(" Query error: %s (err=%d, count=%zu)\n",
50104976
error_msg ? error_msg : "unknown", err, result_count);
5011-
if (error_msg) free(error_msg);
4977+
if (error_msg) zvec_free(error_msg);
50124978
}
50134979
TEST_ASSERT(err == ZVEC_OK);
50144980
TEST_ASSERT(result_count >= 1);
50154981
if (result_count > 0) {
50164982
const char *pk = zvec_doc_get_pk_copy(results[0]);
50174983
TEST_ASSERT(pk != NULL);
50184984
TEST_ASSERT(strcmp(pk, "doc1") == 0);
5019-
free((void *)pk);
4985+
zvec_free((void *)pk);
50204986
for (size_t i = 0; i < result_count; i++) {
50214987
zvec_doc_destroy(results[i]);
50224988
}
5023-
free(results);
4989+
zvec_free(results);
50244990
}
50254991
zvec_vector_query_destroy(query);
50264992
}
@@ -5334,7 +5300,7 @@ void test_collection_schema_getters(void) {
53345300
printf("%s ", field_names[i]);
53355301
}
53365302
printf("\n");
5337-
free(field_names);
5303+
zvec_free(field_names);
53385304

53395305
// Test get_forward_fields
53405306
ZVecFieldSchema **forward_fields = NULL;
@@ -5346,7 +5312,7 @@ void test_collection_schema_getters(void) {
53465312
TEST_ASSERT(forward_count == 2); // field1 and field2 are scalars
53475313
// Note: forward_fields contains pointers to fields owned by schema,
53485314
// do not destroy them individually - just free the array
5349-
free(forward_fields);
5315+
zvec_free(forward_fields);
53505316

53515317
// Test get_vector_fields
53525318
ZVecFieldSchema **vector_fields = NULL;
@@ -5358,7 +5324,7 @@ void test_collection_schema_getters(void) {
53585324
TEST_ASSERT(vector_count == 1); // Only field3 is vector
53595325
// Note: vector_fields contains pointers to fields owned by schema,
53605326
// do not destroy them individually - just free the array
5361-
free(vector_fields);
5327+
zvec_free(vector_fields);
53625328

53635329
// Test NULL pointer handling
53645330
TEST_ASSERT(zvec_collection_schema_has_field(NULL, "field") == false);

0 commit comments

Comments
 (0)