From 67245c4b015b82117d4e365c2bebcdc44e7451ad Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Fri, 10 May 2024 20:59:35 +0100 Subject: [PATCH] Fix VoxelStreamSQLite wasn't loading anything with key cache enabled --- doc/source/changelog.md | 3 ++ streams/sqlite/voxel_stream_sqlite.cpp | 9 ++-- tests/tests.cpp | 2 + tests/voxel/test_stream_sqlite.cpp | 64 ++++++++++++++++++++++++++ tests/voxel/test_stream_sqlite.h | 10 ++++ 5 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 tests/voxel/test_stream_sqlite.cpp create mode 100644 tests/voxel/test_stream_sqlite.h diff --git a/doc/source/changelog.md b/doc/source/changelog.md index 0a6f9702a..00f7fb025 100644 --- a/doc/source/changelog.md +++ b/doc/source/changelog.md @@ -13,6 +13,9 @@ Semver is not yet in place, so each version can have breaking changes, although - Added project setting `voxel/ownership_checks` to turn off sanity checks done by certain virtual functions that pass an object (such as `_generate_block`). Relevant for C#, where the garbage collection model prevents such checks from working properly. - `VoxelViewer`: added `view_distance_vertical_ratio` to use different vertical view distance proportionally to the horizontal distance +- Fixes + - `VoxelStreamSQLite`: fixed `set_key_cache_enabled(true)` caused nothing to load + 1.2 - 20/04/2024 - branch `1.2` - tag `v1.2.0` ------------------------------------------------ diff --git a/streams/sqlite/voxel_stream_sqlite.cpp b/streams/sqlite/voxel_stream_sqlite.cpp index 5f52699ec..3b057a7d4 100644 --- a/streams/sqlite/voxel_stream_sqlite.cpp +++ b/streams/sqlite/voxel_stream_sqlite.cpp @@ -734,6 +734,11 @@ void VoxelStreamSQLite::save_voxel_block(VoxelStream::VoxelQueryData &q) { void VoxelStreamSQLite::load_voxel_blocks(Span p_blocks) { ZN_PROFILE_SCOPE(); + // Getting connection first to allow the key cache to load if enabled. + // This should be quick after the first call because the connection is cached. + VoxelStreamSQLiteInternal *con = get_connection(); + ERR_FAIL_COND(con == nullptr); + // Check the cache first StdVector blocks_to_load; for (unsigned int i = 0; i < p_blocks.size(); ++i) { @@ -757,12 +762,10 @@ void VoxelStreamSQLite::load_voxel_blocks(Span p_bl if (blocks_to_load.size() == 0) { // Everything was cached, no need to query the database + recycle_connection(con); return; } - VoxelStreamSQLiteInternal *con = get_connection(); - ERR_FAIL_COND(con == nullptr); - // TODO We should handle busy return codes ERR_FAIL_COND(con->begin_transaction() == false); diff --git a/tests/tests.cpp b/tests/tests.cpp index 895fed3e6..6b01a13cf 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -20,6 +20,7 @@ #include "voxel/test_octree.h" #include "voxel/test_region_file.h" #include "voxel/test_storage_funcs.h" +#include "voxel/test_stream_sqlite.h" #include "voxel/test_voxel_buffer.h" #include "voxel/test_voxel_data_map.h" #include "voxel/test_voxel_graph.h" @@ -118,6 +119,7 @@ void run_voxel_tests() { VOXEL_TEST(test_spatial_lock_spam); VOXEL_TEST(test_spatial_lock_dependent_map_chunks); VOXEL_TEST(test_discord_soakil_copypaste); + VOXEL_TEST(test_voxel_stream_sqlite_basic); print_line("------------ Voxel tests end -------------"); } diff --git a/tests/voxel/test_stream_sqlite.cpp b/tests/voxel/test_stream_sqlite.cpp new file mode 100644 index 000000000..4504dafa7 --- /dev/null +++ b/tests/voxel/test_stream_sqlite.cpp @@ -0,0 +1,64 @@ +#include "test_stream_sqlite.h" +#include "../../streams/sqlite/voxel_stream_sqlite.h" +#include "../testing.h" + +namespace zylann::voxel::tests { + +namespace { +void test_voxel_stream_sqlite_basic(bool with_key_cache) { + zylann::testing::TestDirectory test_dir; + ZN_TEST_ASSERT(test_dir.is_valid()); + + const String database_path = test_dir.get_path().path_join("database.sqlite"); + + VoxelBuffer vb1(VoxelBuffer::ALLOCATOR_DEFAULT); + vb1.create(Vector3i(16, 16, 16)); + vb1.fill_area(1, Vector3i(5, 5, 5), Vector3i(10, 11, 12), 0); + const Vector3i vb1_pos(1, 2, -3); + + { + Ref stream; + stream.instantiate(); + stream->set_key_cache_enabled(with_key_cache); + stream->set_database_path(database_path); + // Save block + { + VoxelStreamSQLite::VoxelQueryData q{ vb1, vb1_pos, 0, VoxelStream::RESULT_ERROR }; + stream->save_voxel_block(q); + // Result is not set currently for saves... + // ZN_TEST_ASSERT(q.result == VoxelStream::RESULT_BLOCK_FOUND); + } + // Load it back (caching might take effect) + { + VoxelBuffer loaded_vb1(VoxelBuffer::ALLOCATOR_DEFAULT); + VoxelStreamSQLite::VoxelQueryData q{ loaded_vb1, vb1_pos, 0, VoxelStream::RESULT_ERROR }; + stream->load_voxel_block(q); + ZN_TEST_ASSERT(q.result == VoxelStream::RESULT_BLOCK_FOUND); + ZN_TEST_ASSERT(loaded_vb1.equals(vb1)); + } + // Flush before the stream object is destroyed + stream->flush(); + } + { + // Create new stream object and reopen the database (avoids caching effects). + Ref stream; + stream.instantiate(); + stream->set_key_cache_enabled(with_key_cache); + stream->set_database_path(database_path); + { + VoxelBuffer loaded_vb1(VoxelBuffer::ALLOCATOR_DEFAULT); + VoxelStreamSQLite::VoxelQueryData q{ loaded_vb1, vb1_pos, 0, VoxelStream::RESULT_ERROR }; + stream->load_voxel_block(q); + ZN_TEST_ASSERT(q.result == VoxelStream::RESULT_BLOCK_FOUND); + ZN_TEST_ASSERT(loaded_vb1.equals(vb1)); + } + } +} +} // namespace + +void test_voxel_stream_sqlite_basic() { + test_voxel_stream_sqlite_basic(false); + test_voxel_stream_sqlite_basic(true); +} + +} // namespace zylann::voxel::tests \ No newline at end of file diff --git a/tests/voxel/test_stream_sqlite.h b/tests/voxel/test_stream_sqlite.h new file mode 100644 index 000000000..53824b6aa --- /dev/null +++ b/tests/voxel/test_stream_sqlite.h @@ -0,0 +1,10 @@ +#ifndef VOXEL_TESTS_STREAM_SQLITE_H +#define VOXEL_TESTS_STREAM_SQLITE_H + +namespace zylann::voxel::tests { + +void test_voxel_stream_sqlite_basic(); + +} // namespace zylann::voxel::tests + +#endif // VOXEL_TESTS_STREAM_SQLITE_H