Skip to content

Commit eb8f233

Browse files
committed
Merge remote-tracking branch 'origin/dev' into experimental/sql-view
2 parents d8d39ed + 671ecc7 commit eb8f233

10 files changed

Lines changed: 99 additions & 13 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ jobs:
9191
# ===================
9292
linux:
9393
runs-on: ${{ matrix.os }}
94+
continue-on-error: ${{ matrix.experimental || false }}
9495
strategy:
9596
fail-fast: false
9697
matrix:
@@ -111,6 +112,24 @@ jobs:
111112
install_compiler: true
112113
compiler_package: g++-10
113114

115+
- name: "clang-14, C++23 (early)"
116+
os: ubuntu-22.04
117+
cc: clang-14
118+
cxx: clang++-14
119+
cxx_standard: "-DSQLITE_ORM_ENABLE_CXX_23=ON"
120+
install_compiler: true
121+
compiler_package: clang-14
122+
experimental: true
123+
124+
- name: "gcc-11, C++23 (early)"
125+
os: ubuntu-22.04
126+
cc: gcc-11
127+
cxx: g++-11
128+
cxx_standard: "-DSQLITE_ORM_ENABLE_CXX_23=ON"
129+
install_compiler: true
130+
compiler_package: g++-11
131+
experimental: true
132+
114133
- name: "gcc-16, C++26"
115134
os: ubuntu-24.04
116135
cc: gcc-16

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ cmake-build-debug/
99
build/
1010
build-xcode/
1111
build-code-edit/
12+
build-local/
1213
*.sqlite
13-
*.db
14+
*.db

dev/functional/config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
#define SQLITE_ORM_CPP20_RANGES_SUPPORTED
5656
#endif
5757

58+
#if __cpp_lib_ranges >= 202110L && !defined(SQLITE_ORM_BROKEN_CPP20_VIEWS)
59+
#define SQLITE_ORM_CPP20_VIEWS_SUPPORTED
60+
#endif
61+
5862
#if __cpp_lib_generator >= 202207L
5963
#define SQLITE_ORM_CPP23_GENERATOR_SUPPORTED
6064
#endif

dev/functional/cxx_compiler_quirks.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,7 @@
7272
#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && (defined(__clang__) && (__clang_major__ == 10))
7373
#define SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS
7474
#endif
75+
76+
#if defined(__clang__) && (__clang_major__ <= 15)
77+
#define SQLITE_ORM_BROKEN_CPP20_VIEWS
78+
#endif

dev/statement_serializer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1818,7 +1818,7 @@ namespace sqlite_orm::internal {
18181818
const Ctx&) SQLITE_ORM_OR_CONST_CALLOP {
18191819
std::stringstream ss;
18201820
ss << "SET ";
1821-
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
1821+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
18221822
ss << streaming_serialized(statement | std::views::transform(&dynamic_set_entry::serialized_value));
18231823
#else
18241824
int index = 0;

include/sqlite_orm/sqlite_orm.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ using std::nullptr_t;
221221
#define SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS
222222
#endif
223223

224+
#if defined(__clang__) && (__clang_major__ <= 15)
225+
#define SQLITE_ORM_BROKEN_CPP20_VIEWS
226+
#endif
227+
224228
// #include "platform_definitions.h"
225229

226230
#if defined(_WIN32)
@@ -313,6 +317,10 @@ using std::nullptr_t;
313317
#define SQLITE_ORM_CPP20_RANGES_SUPPORTED
314318
#endif
315319

320+
#if __cpp_lib_ranges >= 202110L && !defined(SQLITE_ORM_BROKEN_CPP20_VIEWS)
321+
#define SQLITE_ORM_CPP20_VIEWS_SUPPORTED
322+
#endif
323+
316324
#if __cpp_lib_generator >= 202207L
317325
#define SQLITE_ORM_CPP23_GENERATOR_SUPPORTED
318326
#endif
@@ -23853,7 +23861,7 @@ namespace sqlite_orm::internal {
2385323861
const Ctx&) SQLITE_ORM_OR_CONST_CALLOP {
2385423862
std::stringstream ss;
2385523863
ss << "SET ";
23856-
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
23864+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
2385723865
ss << streaming_serialized(statement | std::views::transform(&dynamic_set_entry::serialized_value));
2385823866
#else
2385923867
int index = 0;

tests/iterate.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ TEST_CASE("Iterate select statement") {
7676
};
7777
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
7878
constexpr orm_table_reference auto test_table = c<Test>();
79+
#endif
80+
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
7981
constexpr orm_table_alias auto test_alias = "t"_alias.for_<Test>();
8082
#endif
8183

@@ -91,26 +93,32 @@ TEST_CASE("Iterate select statement") {
9193
db.replace(expected);
9294
std::vector<Test> expected_vec{expected};
9395

96+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
9497
SECTION("range-based for") {
9598
for (Test&& obj: db.iterate(select(object<Test>()))) {
9699
REQUIRE(obj == expected);
97100
}
98101
}
102+
#endif
99103

100104
#ifdef SQLITE_ORM_STL_HAS_DEFAULT_SENTINEL
105+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
101106
SECTION("borrowed iterator") {
102107
std::input_iterator auto begin = db.iterate(select(object<Test>())).begin();
103108
REQUIRE(*begin == expected);
104109
REQUIRE(++begin == std::default_sentinel);
105110
}
106111
#endif
112+
#endif
107113

108114
#if __cpp_lib_containers_ranges >= 202202L
115+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
109116
SECTION("from range") {
110117
std::ranges::view auto view = db.iterate(select(object<Test>()));
111118
REQUIRE(std::vector<Test>{std::from_range, view} == expected_vec);
112119
}
113120
#endif
121+
#endif
114122

115123
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
116124
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
@@ -128,14 +136,18 @@ TEST_CASE("Iterate select statement") {
128136
auto view = db.yield<Test>();
129137
REQUIRE(std::vector<Test>{std::from_range, view} == expected_vec);
130138
}
139+
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
131140
SECTION("object generator, table reference") {
132141
auto view = db.yield<test_table>();
133142
REQUIRE(std::vector<Test>{std::from_range, view} == expected_vec);
134143
}
144+
#endif
145+
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
135146
SECTION("object generator, alias") {
136147
auto view = db.yield<test_alias>();
137148
REQUIRE(std::vector<Test>{std::from_range, view} == expected_vec);
138149
}
150+
#endif
139151
SECTION("select generator") {
140152
auto view = db.yield(select(object<Test>()));
141153
REQUIRE(std::vector<Test>{std::from_range, view} == expected_vec);

tests/static_tests/function_static_tests.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ concept storage_aggregate_callable = requires(S& storage) {
2424
{ storage.template create_aggregate_function<f>() };
2525
{ storage.template delete_aggregate_function<f>() };
2626
};
27+
28+
constexpr auto clamp_int_ptr = &std::clamp<int>;
2729
#endif
2830

2931
TEST_CASE("function static") {
@@ -343,16 +345,20 @@ TEST_CASE("function static") {
343345
}
344346
#endif
345347
SECTION("freestanding function") {
346-
constexpr auto quotedScalar = "f"_scalar.quote(std::clamp<int>);
347-
using quoted_type = decltype("f"_scalar.quote(std::clamp<int>));
348+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
349+
SKIP("GCC < 12 cannot use this function pointer as NTTP in this test.");
350+
#else
351+
constexpr auto quotedScalar = "f"_scalar.quote(clamp_int_ptr);
352+
using quoted_type = decltype("f"_scalar.quote(clamp_int_ptr));
353+
using expected_callable_type = std::remove_cv_t<decltype(clamp_int_ptr)>;
348354

349355
STATIC_REQUIRE(quotedScalar._nme[0] == 'f' && quotedScalar._nme[1] == '\0');
350356
STATIC_REQUIRE(std::is_same_v<decltype(quotedScalar),
351-
const quoted_scalar_function<decltype(&std::clamp<int>),
357+
const quoted_scalar_function<expected_callable_type,
352358
const int&(const int&, const int&, const int&),
353359
2>>);
354360

355-
STATIC_REQUIRE(std::is_same_v<quoted_type::callable_type, decltype(&std::clamp<int>)>);
361+
STATIC_REQUIRE(std::is_same_v<quoted_type::callable_type, expected_callable_type>);
356362
STATIC_REQUIRE(std::is_same_v<quoted_type::udf_type, const int&(const int&, const int&, const int&)>);
357363

358364
STATIC_REQUIRE(std::is_same_v<callable_arguments<quoted_type::udf_type>::return_type, int>);
@@ -368,18 +374,25 @@ TEST_CASE("function static") {
368374

369375
using storage_type = decltype(make_storage(""));
370376
STATIC_REQUIRE(storage_scalar_callable<storage_type, quotedScalar>);
377+
#endif
371378
}
372379
SECTION("template function") {
373-
constexpr auto quotedScalar = "f"_scalar.quote<const int&(const int&, const int&, const int&)>(std::clamp);
374-
using quoted_type = decltype("f"_scalar.quote<const int&(const int&, const int&, const int&)>(std::clamp));
380+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
381+
SKIP("GCC < 12 cannot use this function pointer as NTTP in this test.");
382+
#else
383+
constexpr auto quotedScalar =
384+
"f"_scalar.quote<const int&(const int&, const int&, const int&)>(clamp_int_ptr);
385+
using quoted_type =
386+
decltype("f"_scalar.quote<const int&(const int&, const int&, const int&)>(clamp_int_ptr));
387+
using expected_callable_type = std::remove_cv_t<decltype(clamp_int_ptr)>;
375388

376389
STATIC_REQUIRE(quotedScalar._nme[0] == 'f' && quotedScalar._nme[1] == '\0');
377390
STATIC_REQUIRE(std::is_same_v<decltype(quotedScalar),
378-
const quoted_scalar_function<decltype(&std::clamp<int>),
391+
const quoted_scalar_function<expected_callable_type,
379392
const int&(const int&, const int&, const int&),
380393
2>>);
381394

382-
STATIC_REQUIRE(std::is_same_v<quoted_type::callable_type, decltype(&std::clamp<int>)>);
395+
STATIC_REQUIRE(std::is_same_v<quoted_type::callable_type, expected_callable_type>);
383396
STATIC_REQUIRE(std::is_same_v<quoted_type::udf_type, const int&(const int&, const int&, const int&)>);
384397

385398
STATIC_REQUIRE(std::is_same_v<callable_arguments<quoted_type::udf_type>::return_type, int>);
@@ -395,6 +408,7 @@ TEST_CASE("function static") {
395408

396409
using storage_type = decltype(make_storage(""));
397410
STATIC_REQUIRE(storage_scalar_callable<storage_type, quotedScalar>);
411+
#endif
398412
}
399413
SECTION("lambda") {
400414
constexpr auto lambda = [](unsigned long errcode) {

tests/static_tests/iterator_t.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,10 @@ concept storage_yield_result_set = requires(S& storage_type, Select select) {
126126

127127
namespace {
128128
struct Object {};
129-
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
129+
#if defined(SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED) && defined(SQLITE_ORM_WITH_CPP20_ALIASES)
130130
constexpr orm_table_alias auto object_alias = "o"_alias.for_<Object>();
131+
#endif
132+
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
131133
constexpr orm_table_reference auto object_table = c<Object>();
132134
#endif
133135
}
@@ -177,9 +179,15 @@ TEST_CASE("can view and iterate mapped") {
177179

178180
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
179181
STATIC_REQUIRE(storage_iterate_mapped<storage_type, Object>);
182+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
180183
STATIC_REQUIRE(storage_iterate_mapped_ref<storage_type, object_table, Object>);
184+
#endif
185+
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
186+
#ifdef SQLITE_ORM_CPP20_VIEWS_SUPPORTED
181187
STATIC_REQUIRE(storage_iterate_mapped_ref<storage_type, object_alias, Object>);
182188
#endif
189+
#endif
190+
#endif
183191

184192
#ifdef SQLITE_ORM_CPP23_GENERATOR_SUPPORTED
185193
STATIC_REQUIRE(storage_yield_mapped<storage_type, Object, Object>);
@@ -188,7 +196,7 @@ TEST_CASE("can view and iterate mapped") {
188196
#endif
189197
}
190198

191-
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
199+
#if defined(SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED) && defined(SQLITE_ORM_CPP20_VIEWS_SUPPORTED)
192200
TEST_CASE("can view and iterate result set") {
193201
struct Object {};
194202
using empty_storage_type = decltype(make_storage(""));

tests/user_defined_functions.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@ TEST_CASE("generalized scalar udf") {
569569
storage.sync_schema();
570570

571571
SECTION("freestanding function") {
572+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
573+
SKIP("GCC < 12 cannot use this function as NTTP in quoted scalar tests.");
574+
#else
572575
constexpr auto err_fatal_error_f = "ERR_FATAL_ERROR"_scalar.quote(ERR_FATAL_ERROR);
573576
storage.create_scalar_function<err_fatal_error_f>();
574577
{
@@ -577,6 +580,7 @@ TEST_CASE("generalized scalar udf") {
577580
REQUIRE(rows == expected);
578581
}
579582
storage.delete_scalar_function<err_fatal_error_f>();
583+
#endif
580584
}
581585
SECTION("stateless lambda") {
582586
constexpr auto is_fatal_error_f = "is_fatal_error"_scalar.quote([](unsigned long errcode) {
@@ -659,6 +663,9 @@ TEST_CASE("generalized scalar udf") {
659663
}
660664
#endif
661665
SECTION("specialized template function") {
666+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
667+
SKIP("GCC < 12 cannot use std::clamp specialization as NTTP.");
668+
#else
662669
constexpr auto clamp_int_f = "clamp_int"_scalar.quote(std::clamp<int>);
663670
storage.create_scalar_function<clamp_int_f>();
664671
{
@@ -667,8 +674,12 @@ TEST_CASE("generalized scalar udf") {
667674
REQUIRE(rows == expected);
668675
}
669676
storage.delete_scalar_function<clamp_int_f>();
677+
#endif
670678
}
671679
SECTION("overloaded template function") {
680+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
681+
SKIP("GCC < 12 cannot use std::clamp overload as NTTP.");
682+
#else
672683
constexpr auto clamp_int_f =
673684
"clamp_int"_scalar.quote<const int&(const int&, const int&, const int&)>(std::clamp);
674685
storage.create_scalar_function<clamp_int_f>();
@@ -678,6 +689,7 @@ TEST_CASE("generalized scalar udf") {
678689
REQUIRE(rows == expected);
679690
}
680691
storage.delete_scalar_function<clamp_int_f>();
692+
#endif
681693
}
682694
SECTION("non-copyable function object") {
683695
// note: unlike msvc, gcc+clang require a constant template parameter to be copyable (and probably rightly so);
@@ -703,6 +715,9 @@ TEST_CASE("generalized scalar udf") {
703715
storage.delete_scalar_function<offset0_f>();
704716
}
705717
SECTION("escaped function identifier") {
718+
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
719+
SKIP("GCC < 12 cannot use std::clamp specialization as NTTP.");
720+
#else
706721
constexpr auto clamp_f = R"("clamp int")"_scalar.quote(std::clamp<int>);
707722
storage.create_scalar_function<clamp_f>();
708723
{
@@ -711,6 +726,7 @@ TEST_CASE("generalized scalar udf") {
711726
REQUIRE(rows == expected);
712727
}
713728
storage.delete_scalar_function<clamp_f>();
729+
#endif
714730
}
715731
}
716732
#endif

0 commit comments

Comments
 (0)