Skip to content

Commit ca580cf

Browse files
authored
Merge pull request #1457 from fnc12/feature/rtree-vtab
Support for R*Tree virtual tables
2 parents 36a07f7 + 2f724b4 commit ca580cf

File tree

14 files changed

+674
-31
lines changed

14 files changed

+674
-31
lines changed

appveyor.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ for:
113113
C:\Tools\vcpkg\bootstrap-vcpkg.bat -disableMetrics
114114
C:\Tools\vcpkg\vcpkg integrate install
115115
set VCPKG_DEFAULT_TRIPLET=%platform%-windows
116-
vcpkg install sqlite3[core,dbstat,math,json1,fts5,soundex]
116+
vcpkg install sqlite3[core,dbstat,math,json1,fts5,rtree,soundex]
117117
rem The Visual Studio 2017 build worker image comes with CMake 3.16 only, and sqlite_orm will build the Catch2 dependency from source
118118
if not "%appveyor_build_worker_image%"=="Visual Studio 2017" (vcpkg install catch2)
119119
before_build:
@@ -146,7 +146,7 @@ for:
146146
popd
147147
$HOME/vcpkg/bootstrap-vcpkg.sh -disableMetrics
148148
$HOME/vcpkg/vcpkg integrate install --overlay-triplets=vcpkg/triplets
149-
vcpkg install sqlite3[core,dbstat,math,json1,fts5,soundex] catch2 --overlay-triplets=vcpkg/triplets
149+
vcpkg install sqlite3[core,dbstat,math,json1,fts5,rtree,soundex] catch2 --overlay-triplets=vcpkg/triplets
150150
before_build:
151151
- |-
152152
mkdir compile
@@ -173,7 +173,7 @@ for:
173173
git clone --depth 1 --branch 2025.08.27 https://github.com/microsoft/vcpkg.git $HOME/vcpkg
174174
$HOME/vcpkg/bootstrap-vcpkg.sh -disableMetrics
175175
$HOME/vcpkg/vcpkg integrate install --overlay-triplets=vcpkg/triplets
176-
vcpkg install sqlite3[core,dbstat,math,json1,fts5,soundex] catch2 --overlay-triplets=vcpkg/triplets
176+
vcpkg install sqlite3[core,dbstat,math,json1,fts5,rtree,soundex] catch2 --overlay-triplets=vcpkg/triplets
177177
before_build:
178178
- |-
179179
mkdir compile

dev/constraints.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ namespace sqlite_orm {
167167
using mapped_type = T;
168168
};
169169

170+
#if SQLITE_VERSION_NUMBER >= 3024000
171+
/**
172+
* Auxiliary virtual table column
173+
*/
174+
struct auxiliary_t {};
175+
176+
template<class T>
177+
using is_auxiliary = std::is_same<T, auxiliary_t>;
178+
#else
179+
template<class T>
180+
using is_auxiliary = std::false_type;
181+
#endif
182+
170183
/**
171184
* DEFAULT constraint class.
172185
* T is a value type.
@@ -514,7 +527,8 @@ namespace sqlite_orm {
514527
check_if_is_template<check_t>,
515528
check_if_is_type<collate_constraint_t>,
516529
check_if<is_generated_always>,
517-
check_if_is_type<unindexed_t>>,
530+
check_if_is_type<unindexed_t>,
531+
check_if<is_auxiliary>>,
518532
T>;
519533
}
520534
}
@@ -632,6 +646,15 @@ SQLITE_ORM_EXPORT namespace sqlite_orm {
632646
return {};
633647
}
634648

649+
#if SQLITE_VERSION_NUMBER >= 3024000
650+
/**
651+
* Auxiliary virtual table column
652+
*/
653+
inline internal::auxiliary_t auxiliary() {
654+
return {};
655+
}
656+
#endif
657+
635658
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
636659
/**
637660
* content='table' table constraint builder function. Used in FTS virtual tables.

dev/schema/virtual_table.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ namespace sqlite_orm::internal {
8181
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
8282
static_assert(module_tag<M>, "Template parameter M must be a module tag");
8383
#endif
84+
using module_type = M;
8485
};
8586

8687
/**

dev/serializing_util.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,10 @@ namespace sqlite_orm {
429429
auto& context = std::get<3>(tpl);
430430

431431
using constraints_tuple = decltype(column.constraints);
432-
iterate_tuple(column.constraints, [&ss, &context](auto& constraint) {
432+
// always append explicit constraints even when omitting type affinity and implicit constraints
433+
using excluding_auxiliary_index_sequence =
434+
filter_tuple_sequence_t<constraints_tuple, check_if_not<is_auxiliary>::template fn>;
435+
iterate_tuple(column.constraints, excluding_auxiliary_index_sequence{}, [&ss, &context](auto& constraint) {
433436
ss << ' ' << serialize(constraint, context);
434437
});
435438
// add implicit null constraint

dev/statement_serializer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,11 @@ namespace sqlite_orm {
13461346
SQLITE_ORM_STATIC_CALLOP std::string operator()(const statement_type& column,
13471347
const Ctx& context) SQLITE_ORM_OR_CONST_CALLOP {
13481348
std::stringstream ss;
1349+
#if SQLITE_VERSION_NUMBER >= 3024000
1350+
if constexpr (statement_type::template is<is_auxiliary>()) {
1351+
ss << '+';
1352+
}
1353+
#endif
13491354
ss << streaming_identifier(column.name);
13501355
if (!context.omit_column_type) {
13511356
ss << " " << type_printer<field_type_t<column_field<G, S>>>().print();

dev/vtabs/fts5.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ namespace sqlite_orm::internal {
3636
SQLITE_ORM_EXPORT namespace sqlite_orm {
3737
/**
3838
* Factory function for a FTS5 virtual table definition.
39-
*
40-
* The mapped object type will be determined implicitly from the first column definition when calling `make_virtual_table()`.
4139
*/
4240
template<class... Cs>
4341
internal::virtual_table_definition<internal::fts5_module_tag, Cs...> using_fts5(Cs... definition) {

dev/vtabs/rtree.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#pragma once
2+
3+
#ifndef SQLITE_ORM_IMPORT_STD_MODULE
4+
#ifdef SQLITE_ENABLE_RTREE
5+
#include <type_traits> // std::is_same
6+
#include <tuple> // std::tuple_element, std::make_tuple
7+
#include <utility> // std::forward
8+
#include <cstdint> // std::int32_t
9+
#endif
10+
#endif
11+
12+
#include "../functional/cxx_type_traits_polyfill.h"
13+
#include "../functional/gsl.h"
14+
#include "../functional/mpl.h"
15+
#include "../schema/virtual_table.h"
16+
#include "../schema/column.h"
17+
18+
#ifdef SQLITE_ENABLE_RTREE
19+
namespace sqlite_orm::internal {
20+
template<class T>
21+
using is_rtree_table_element_or_constraint = mpl::invoke_t<mpl::disjunction<check_if<is_column>>, T>;
22+
23+
struct rtree_module_tag {
24+
// simplify conceptual/meta programming
25+
using module_type = rtree_module_tag;
26+
27+
static constexpr orm_gsl::czstring name() {
28+
return "rtree";
29+
}
30+
};
31+
32+
struct rtree_i32_module_tag {
33+
// simplify conceptual/meta programming
34+
using module_type = rtree_i32_module_tag;
35+
36+
static constexpr orm_gsl::czstring name() {
37+
return "rtree_i32";
38+
}
39+
};
40+
41+
template<class ExpectedValueType, class... Cs>
42+
constexpr void validate_rtree_definition() {
43+
using elements_type = std::tuple<Cs...>;
44+
using rtree_col_index_sequence = col_index_sequence_excluding<elements_type, is_auxiliary>;
45+
constexpr size_t nRTreeColumns = rtree_col_index_sequence::size();
46+
constexpr size_t nRTreeColumnsOfExpectedType =
47+
count_filtered_tuple<elements_type,
48+
check_if_is_type<ExpectedValueType>::template fn,
49+
rtree_col_index_sequence,
50+
field_type_t>::value;
51+
52+
static_assert(polyfill::conjunction_v<is_rtree_table_element_or_constraint<Cs>...>,
53+
"Incorrect table elements or constraints");
54+
static_assert(nRTreeColumns >= 3 && nRTreeColumns <= 11 && nRTreeColumns % 2 == 1,
55+
"An RTREE table must have between 1 and 5 dimensions consisting of min/max-value pair columns");
56+
static_assert(
57+
nRTreeColumnsOfExpectedType == nRTreeColumns - 1,
58+
R"(The min/max-value pair columns need to be 32-bit floating point values for RTREE virtual tables and 32-bit signed integers for RTREE_I32 virtual tables, as they are stored as such)");
59+
static_assert(std::is_same<typename std::tuple_element_t<0, elements_type>::field_type, int64>::value,
60+
"The type of the first column must be a 64-bit integer");
61+
}
62+
}
63+
64+
SQLITE_ORM_EXPORT namespace sqlite_orm {
65+
/**
66+
* Factory function for a RTREE virtual table definition.
67+
*/
68+
template<class... Cs>
69+
internal::virtual_table_definition<internal::rtree_module_tag, Cs...> using_rtree(Cs... definition) {
70+
internal::validate_rtree_definition<float, Cs...>();
71+
72+
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::make_tuple(std::forward<Cs>(definition)...)});
73+
}
74+
/**
75+
* Factory function for a RTREE_I32 virtual table definition.
76+
*/
77+
template<class... Cs>
78+
internal::virtual_table_definition<internal::rtree_i32_module_tag, Cs...> using_rtree_i32(Cs... definition) {
79+
internal::validate_rtree_definition<std::int32_t, Cs...>();
80+
81+
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::make_tuple(std::forward<Cs>(definition)...)});
82+
}
83+
}
84+
#endif

dev/vtabs/vtabs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
#include "dbstat.h"
44
#include "fts5.h"
5+
#include "rtree.h"

0 commit comments

Comments
 (0)