|
| 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 |
0 commit comments