Skip to content

Commit b0a3b2f

Browse files
committed
allow for explicit tokio runtime definitions
add async tests both multithreaded and coroutine based Signed-off-by: Yuval Lifshitz <ylifshit@ibm.com>
1 parent 21038d5 commit b0a3b2f

22 files changed

Lines changed: 806 additions & 320 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ jobs:
3535
wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
3636
sudo apt-get install -y ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
3737
sudo apt-get update
38-
sudo apt-get install -y libarrow-dev
38+
sudo apt-get install -y libarrow-dev libboost-coroutine-dev libboost-context-dev
3939
4040
- name: Install dependencies (macOS)
4141
if: matrix.os == 'macos-latest'
4242
run: |
43-
brew install apache-arrow protobuf
43+
brew install apache-arrow protobuf boost
4444
4545
- uses: msys2/setup-msys2@v2
4646
if: matrix.os == 'windows-latest'
4747
with:
4848
msystem: ucrt64
4949
path-type: inherit
50-
install: mingw-w64-ucrt-x86_64-arrow mingw-w64-ucrt-x86_64-protobuf
50+
install: mingw-w64-ucrt-x86_64-arrow mingw-w64-ucrt-x86_64-protobuf mingw-w64-ucrt-x86_64-boost
5151

5252
- name: Configure CMake
5353
if: matrix.os != 'windows-latest'
@@ -163,7 +163,7 @@ jobs:
163163
cmake .. -G Ninja \
164164
-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/toolchain.cmake \
165165
-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/arrow-install \
166-
-DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release
166+
-DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release
167167
168168
- name: Build
169169
run: ninja -C build

.github/workflows/coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
3030
sudo apt-get install -y ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
3131
sudo apt-get update
32-
sudo apt-get install -y libarrow-dev
32+
sudo apt-get install -y libarrow-dev libboost-coroutine-dev libboost-context-dev
3333
3434
- name: Configure CMake
3535
run: |

CMakeLists.txt

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,57 @@ if(BUILD_TESTS)
351351
)
352352
list(APPEND TEST_TARGETS lancedb_index_tests)
353353

354+
# Add test executable for async table tests (runs without valgrind)
355+
add_executable(lancedb_table_async_tests
356+
tests/test_main.cpp
357+
tests/test_common.cpp
358+
tests/test_table_async.cpp
359+
)
360+
target_link_libraries(lancedb_table_async_tests
361+
PRIVATE
362+
lancedb
363+
Catch2::Catch2
364+
Threads::Threads
365+
${ARROW_LIBRARIES}
366+
)
367+
target_include_directories(lancedb_table_async_tests
368+
PRIVATE ${ARROW_INCLUDE_DIRS}
369+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
370+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests
371+
)
372+
target_compile_options(lancedb_table_async_tests PRIVATE ${ARROW_CFLAGS_OTHER})
373+
set_target_properties(lancedb_table_async_tests PROPERTIES
374+
BUILD_RPATH ${RUST_TARGET_DIR}
375+
)
376+
list(APPEND TEST_TARGETS lancedb_table_async_tests)
377+
378+
# Add test executable for coroutine table tests (runs with valgrind)
379+
find_package(Boost REQUIRED COMPONENTS coroutine context)
380+
add_executable(lancedb_table_coro_tests
381+
tests/test_main.cpp
382+
tests/test_common.cpp
383+
tests/test_table_coro.cpp
384+
)
385+
target_link_libraries(lancedb_table_coro_tests
386+
PRIVATE
387+
lancedb
388+
Catch2::Catch2
389+
Threads::Threads
390+
${ARROW_LIBRARIES}
391+
Boost::coroutine
392+
Boost::context
393+
)
394+
target_include_directories(lancedb_table_coro_tests
395+
PRIVATE ${ARROW_INCLUDE_DIRS}
396+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
397+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests
398+
)
399+
target_compile_options(lancedb_table_coro_tests PRIVATE ${ARROW_CFLAGS_OTHER})
400+
set_target_properties(lancedb_table_coro_tests PROPERTIES
401+
BUILD_RPATH ${RUST_TARGET_DIR}
402+
)
403+
list(APPEND TEST_TARGETS lancedb_table_coro_tests)
404+
354405
# Add test executable for vector tests (runs without valgrind)
355406
add_executable(lancedb_vector_index_tests
356407
tests/test_main.cpp
@@ -503,13 +554,41 @@ if(BUILD_TESTS)
503554
--suppressions=${CMAKE_CURRENT_SOURCE_DIR}/valgrind.supp
504555
$<TARGET_FILE:lancedb_query_tests>
505556
)
557+
# Run async table tests with valgrind
558+
add_test(NAME lancedb_table_async_tests
559+
COMMAND ${TEST_ENV_PREFIX} ${VALGRIND_EXECUTABLE}
560+
--tool=memcheck
561+
--leak-check=full
562+
--show-leak-kinds=definite
563+
--errors-for-leak-kinds=definite
564+
--track-origins=yes
565+
--error-exitcode=1
566+
--log-file=${CMAKE_BINARY_DIR}/valgrind_table_async.txt
567+
--suppressions=${CMAKE_CURRENT_SOURCE_DIR}/valgrind.supp
568+
$<TARGET_FILE:lancedb_table_async_tests>
569+
)
570+
# Run coroutine table tests with valgrind
571+
add_test(NAME lancedb_table_coro_tests
572+
COMMAND ${TEST_ENV_PREFIX} ${VALGRIND_EXECUTABLE}
573+
--tool=memcheck
574+
--leak-check=full
575+
--show-leak-kinds=definite
576+
--errors-for-leak-kinds=definite
577+
--track-origins=yes
578+
--error-exitcode=1
579+
--log-file=${CMAKE_BINARY_DIR}/valgrind_table_coro.txt
580+
--suppressions=${CMAKE_CURRENT_SOURCE_DIR}/valgrind.supp
581+
$<TARGET_FILE:lancedb_table_coro_tests>
582+
)
506583
else()
507584
message(WARNING "Valgrind not found, running tests without memory checking")
508585
add_test(NAME lancedb_connection_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_connection_tests>)
509586
add_test(NAME lancedb_table_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_table_tests>)
510587
add_test(NAME lancedb_table_meta_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_table_meta_tests>)
511588
add_test(NAME lancedb_index_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_index_tests>)
512589
add_test(NAME lancedb_query_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_query_tests>)
590+
add_test(NAME lancedb_table_async_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_table_async_tests>)
591+
add_test(NAME lancedb_table_coro_tests COMMAND ${TEST_ENV_PREFIX} $<TARGET_FILE:lancedb_table_coro_tests>)
513592
endif()
514593

515594
# Run vector index tests WITHOUT valgrind (too slow under valgrind)

examples/full.cpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ int main() {
101101
std::cerr << "failed to create connection builder" << std::endl;
102102
return 1;
103103
}
104-
LanceDBConnection* db = lancedb_connect_builder_execute(builder);
104+
LanceDBConnection* db = lancedb_connect_builder_execute(builder, nullptr);
105105
if (!db) {
106106
std::cerr << "failed to connect to database" << std::endl;
107107
return 1;
@@ -135,7 +135,7 @@ int main() {
135135
LanceDBTable* table = nullptr;
136136
if (const LanceDBError result = lancedb_table_create(db, table_name.c_str(),
137137
reinterpret_cast<FFI_ArrowSchema*>(&c_schema),
138-
nullptr, &table, nullptr); result != LANCEDB_SUCCESS) {
138+
nullptr, &table, nullptr, nullptr); result != LANCEDB_SUCCESS) {
139139
std::cerr << "error creating table: " << table_name << ", error: " << lancedb_error_to_message(result) << std::endl;
140140
lancedb_connection_free(db);
141141
if (c_schema.release) {
@@ -149,7 +149,7 @@ int main() {
149149
// try to create a table that already exists
150150
if (const LanceDBError result = lancedb_table_create(db, "my_table",
151151
reinterpret_cast<FFI_ArrowSchema*>(&c_schema),
152-
nullptr, &table, &error_message); result != LANCEDB_SUCCESS) {
152+
nullptr, &table, nullptr, &error_message); result != LANCEDB_SUCCESS) {
153153
std::cout << "failed to create table that already exists (expected), error: '" <<
154154
lancedb_error_to_message(result) <<
155155
"' message: " << std::endl << error_message << std::endl;
@@ -162,7 +162,7 @@ int main() {
162162
// try to create a table with invalid name
163163
if (const LanceDBError result = lancedb_table_create(db, "invalid table name",
164164
reinterpret_cast<FFI_ArrowSchema*>(&c_schema),
165-
nullptr, &table, &error_message); result != LANCEDB_SUCCESS) {
165+
nullptr, &table, nullptr, &error_message); result != LANCEDB_SUCCESS) {
166166
std::cout << "failed to create table with invalid name (expected), error: '" <<
167167
lancedb_error_to_message(result) <<
168168
"' message: " << std::endl << error_message << std::endl;
@@ -179,7 +179,7 @@ int main() {
179179
// try to create a table with invalid input (null schema)
180180
if (const LanceDBError result = lancedb_table_create(db, "invalid_table",
181181
nullptr,
182-
nullptr, &table, &error_message); result != LANCEDB_SUCCESS) {
182+
nullptr, &table, nullptr, &error_message); result != LANCEDB_SUCCESS) {
183183
std::cout << "failed to create table with null schema (expected), error: '" <<
184184
lancedb_error_to_message(result) <<
185185
"' message: " << std::endl << error_message << std::endl;
@@ -190,7 +190,7 @@ int main() {
190190
}
191191

192192
// open the table to work with it
193-
LanceDBTable* tbl = lancedb_connection_open_table(db, table_name.c_str());
193+
LanceDBTable* tbl = lancedb_connection_open_table(db, table_name.c_str(), nullptr);
194194
if (!tbl) {
195195
std::cerr << "failed to open table: " << table_name << std::endl;
196196
lancedb_connection_free(db);
@@ -204,7 +204,7 @@ int main() {
204204
.force_update_statistics = 0 // don't force update statistics
205205
};
206206
if (const LanceDBError result = lancedb_table_create_scalar_index(
207-
tbl, key_columns, 1, LANCEDB_INDEX_BTREE, &scalar_config, nullptr); result != LANCEDB_SUCCESS) {
207+
tbl, key_columns, 1, LANCEDB_INDEX_BTREE, &scalar_config, nullptr, nullptr); result != LANCEDB_SUCCESS) {
208208
std::cerr << "failed to create scalar index on 'key' column, error: '" <<
209209
lancedb_error_to_message(result) << "'" << std::endl;
210210
} else {
@@ -214,7 +214,7 @@ int main() {
214214
// try to create the same index again without replace flag
215215
scalar_config.replace = 0;
216216
if (const LanceDBError result = lancedb_table_create_scalar_index(
217-
tbl, key_columns, 1, LANCEDB_INDEX_BTREE, &scalar_config, &error_message); result != LANCEDB_SUCCESS) {
217+
tbl, key_columns, 1, LANCEDB_INDEX_BTREE, &scalar_config, nullptr, &error_message); result != LANCEDB_SUCCESS) {
218218
std::cout << "failed to create scalar index on 'key' column (expected), error: '" <<
219219
lancedb_error_to_message(result) <<
220220
"' message: " << std::endl << error_message << std::endl;
@@ -266,7 +266,7 @@ int main() {
266266
reinterpret_cast<FFI_ArrowSchema*>(&c_schema),
267267
&batch_reader, nullptr); error == LANCEDB_SUCCESS) {
268268
// add data to table
269-
if (const LanceDBError result = lancedb_table_add(tbl, batch_reader, nullptr); result != LANCEDB_SUCCESS) {
269+
if (const LanceDBError result = lancedb_table_add(tbl, batch_reader, nullptr, nullptr); result != LANCEDB_SUCCESS) {
270270
std::cerr << "failed to write record batch to table, error: " << lancedb_error_to_message(result) << std::endl;
271271
} else {
272272
std::cout << "wrote " << num_rows << " rows to table" << std::endl;
@@ -295,7 +295,7 @@ int main() {
295295
.replace = 1 // replace existing index
296296
};
297297
if (const LanceDBError result = lancedb_table_create_vector_index(
298-
tbl, data_columns, 1, LANCEDB_INDEX_IVF_FLAT, &vector_config, nullptr); result != LANCEDB_SUCCESS) {
298+
tbl, data_columns, 1, LANCEDB_INDEX_IVF_FLAT, &vector_config, nullptr, nullptr); result != LANCEDB_SUCCESS) {
299299
std::cerr << "failed to create vector index on 'data' column, error: " << lancedb_error_to_message(result) << std::endl;
300300
} else {
301301
std::cout << "created vector index on 'data' column" << std::endl;
@@ -309,7 +309,7 @@ int main() {
309309
};
310310
for (size_t i = 0; i < 3; i++) {
311311
if (const LanceDBError result = lancedb_table_create_scalar_index(
312-
tbl, &tag_columns[i], 1, LANCEDB_INDEX_BITMAP, &bitmap_config, nullptr); result != LANCEDB_SUCCESS) {
312+
tbl, &tag_columns[i], 1, LANCEDB_INDEX_BITMAP, &bitmap_config, nullptr, nullptr); result != LANCEDB_SUCCESS) {
313313
std::cerr << "failed to create bitmap index on '" << tag_columns[i] << "' column, error: " << lancedb_error_to_message(result) << std::endl;
314314
} else {
315315
std::cout << "created bitmap index on '" << tag_columns[i] << "' column" << std::endl;
@@ -336,7 +336,7 @@ int main() {
336336
"data",
337337
reinterpret_cast<FFI_ArrowArray***>(&c_arrays_ptr),
338338
reinterpret_cast<FFI_ArrowSchema**>(&c_schema_ptr),
339-
&count_out, nullptr); result != LANCEDB_SUCCESS) {
339+
&count_out, nullptr, nullptr); result != LANCEDB_SUCCESS) {
340340
std::cerr << "error querying nearest to vector, error: " << lancedb_error_to_message(result) << std::endl;
341341
} else {
342342
std::cout << "query returned " << count_out << " results" << std::endl;
@@ -375,7 +375,7 @@ int main() {
375375
} else {
376376
std::cout << "set query distance type to: L2" << std::endl;
377377
// execute the query
378-
if (LanceDBQueryResult* query_result = lancedb_vector_query_execute(query); query_result) {
378+
if (LanceDBQueryResult* query_result = lancedb_vector_query_execute(query, nullptr); query_result) {
379379
std::cout << "executed query" << std::endl;
380380
// get the result as arrow arrays
381381
struct ArrowArray** c_arrays_ptr;
@@ -386,6 +386,7 @@ int main() {
386386
reinterpret_cast<FFI_ArrowArray***>(&c_arrays_ptr),
387387
reinterpret_cast<FFI_ArrowSchema**>(&c_schema_ptr),
388388
&count_out,
389+
nullptr,
389390
nullptr); result != LANCEDB_SUCCESS) {
390391
std::cerr << "error converting query result to arrow, error: " << lancedb_error_to_message(result) << std::endl;
391392
lancedb_query_result_free(query_result);
@@ -410,19 +411,19 @@ int main() {
410411
// list all tables in the database and loop through them
411412
char** table_names;
412413
size_t name_count;
413-
if (const LanceDBError result = lancedb_connection_table_names(db, &table_names, &name_count, nullptr); result != LANCEDB_SUCCESS) {
414+
if (const LanceDBError result = lancedb_connection_table_names(db, &table_names, &name_count, nullptr, nullptr); result != LANCEDB_SUCCESS) {
414415
std::cerr << "error listing table names, error: " << lancedb_error_to_message(result) << std::endl;
415416
} else {
416417
std::cout << name_count << " tables found" << std::endl;
417418
for (size_t i = 0; i < name_count; i++) {
418-
if (LanceDBTable* tbl = lancedb_connection_open_table(db, table_names[i]); tbl) {
419+
if (LanceDBTable* tbl = lancedb_connection_open_table(db, table_names[i], nullptr); tbl) {
419420

420421
// get the schema of the table
421422
struct ArrowSchema* c_schema_ptr;
422423
if (const LanceDBError result = lancedb_table_arrow_schema(
423424
tbl,
424425
reinterpret_cast<FFI_ArrowSchema**>(&c_schema_ptr),
425-
nullptr); result == LANCEDB_SUCCESS) {
426+
nullptr, nullptr); result == LANCEDB_SUCCESS) {
426427
if (auto schema = arrow::ImportSchema(c_schema_ptr); schema.ok()) {
427428
std::cout << "table: " << table_names[i] << ", schema:" << std::endl;
428429
std::cout << (*schema)->ToString() << std::endl;
@@ -437,14 +438,14 @@ int main() {
437438
// list all indices of the table
438439
char** indices;
439440
size_t indices_count;
440-
if (const LanceDBError result = lancedb_table_list_indices(tbl, &indices, &indices_count, nullptr); result != LANCEDB_SUCCESS) {
441+
if (const LanceDBError result = lancedb_table_list_indices(tbl, &indices, &indices_count, nullptr, nullptr); result != LANCEDB_SUCCESS) {
441442
std::cerr << "failed to list indices, error: " << lancedb_error_to_message(result) << std::endl;
442443
} else {
443444
std::cout << "found " << indices_count << " indices:" << std::endl;
444445
for (size_t i = 0; i < indices_count; i++) {
445446
std::cout << " - " << indices[i] << std::endl;
446447
// delete the index
447-
if (const LanceDBError result = lancedb_table_drop_index(tbl, indices[i], nullptr); result != LANCEDB_SUCCESS) {
448+
if (const LanceDBError result = lancedb_table_drop_index(tbl, indices[i], nullptr, nullptr); result != LANCEDB_SUCCESS) {
448449
std::cerr << " error dropping index: " << indices[i] << ", error: " << lancedb_error_to_message(result) << std::endl;
449450
} else {
450451
std::cout << " dropped index: " << indices[i] << std::endl;
@@ -454,27 +455,27 @@ int main() {
454455
}
455456

456457
// optimize the table after index deletion
457-
if (const LanceDBError result = lancedb_table_optimize(tbl, LANCEDB_OPTIMIZE_ALL, nullptr); result != LANCEDB_SUCCESS) {
458+
if (const LanceDBError result = lancedb_table_optimize(tbl, LANCEDB_OPTIMIZE_ALL, nullptr, nullptr); result != LANCEDB_SUCCESS) {
458459
std::cerr << "error optimizing table: " << table_names[i] << ", error: " << lancedb_error_to_message(result) << std::endl;
459460
} else {
460461
std::cout << "optimized table: " << table_names[i] << std::endl;
461462
}
462463

463464
// number of rows in the table
464-
auto row_count = lancedb_table_count_rows(tbl);
465+
auto row_count = lancedb_table_count_rows(tbl, nullptr);
465466
std::cout << "table: " << table_names[i] << " has: " << row_count << " rows" << std::endl;
466467

467468
// delete some rows
468469
const auto delete_predicates = {"key = \"key_10\"", "key = \"key_20\"", "key = \"key_30\"", "key = \"kaboom\""};
469470
for (const auto& predicate : delete_predicates) {
470-
if (const LanceDBError result = lancedb_table_delete(tbl, predicate, nullptr); result != LANCEDB_SUCCESS) {
471+
if (const LanceDBError result = lancedb_table_delete(tbl, predicate, nullptr, nullptr); result != LANCEDB_SUCCESS) {
471472
std::cerr << "error deleting row with predicate: " << predicate << ", error: " << lancedb_error_to_message(result) << std::endl;
472473
} else {
473474
std::cout << "deleted row with predicate: " << predicate << std::endl;
474475
}
475476
}
476477
// check number of rows in the table after deletion
477-
row_count = lancedb_table_count_rows(tbl);
478+
row_count = lancedb_table_count_rows(tbl, nullptr);
478479
std::cout << "after deletion table: " << table_names[i] << " has: " << row_count << " rows" << std::endl;
479480

480481
// perform table upsert with 3 new rows and 3 updated rows
@@ -535,6 +536,7 @@ int main() {
535536
on_columns.data(),
536537
1,
537538
&config,
539+
nullptr,
538540
&error_message); result != LANCEDB_SUCCESS) {
539541
std::cerr << "failed to upsert record batch to table, error: " << lancedb_error_to_message(result) << ", message: " << error_message << std::endl;
540542
lancedb_free_string(error_message);
@@ -554,11 +556,11 @@ int main() {
554556
}
555557

556558
// check number of rows in the table after upsert
557-
row_count = lancedb_table_count_rows(tbl);
559+
row_count = lancedb_table_count_rows(tbl, nullptr);
558560
std::cout << "after upsert table: " << table_names[i] << " has: " << row_count << " rows" << std::endl;
559561

560562
// drop the table
561-
if (LanceDBError result = lancedb_connection_drop_table(db, table_names[i], nullptr, nullptr); result != LANCEDB_SUCCESS) {
563+
if (LanceDBError result = lancedb_connection_drop_table(db, table_names[i], nullptr, nullptr, nullptr); result != LANCEDB_SUCCESS) {
562564
std::cerr << "error dropping table: " << table_names[i] << ", error: " << lancedb_error_to_message(result) << std::endl;
563565
} else {
564566
std::cout << "dropped table: " << table_names[i] << std::endl;
@@ -571,7 +573,7 @@ int main() {
571573
}
572574

573575
lancedb_free_table_names(table_names, name_count);
574-
if (const LanceDBError result = lancedb_connection_drop_all_tables(db, nullptr, nullptr); result != LANCEDB_SUCCESS) {
576+
if (const LanceDBError result = lancedb_connection_drop_all_tables(db, nullptr, nullptr, nullptr); result != LANCEDB_SUCCESS) {
575577
std::cerr << "error dropping all tables, error: " << lancedb_error_to_message(result) << std::endl;
576578
} else {
577579
std::cout << "dropped all tables" << std::endl;

0 commit comments

Comments
 (0)