33#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
44#include < concepts>
55#endif
6- #include < type_traits> // std::remove_cvref, std::is_convertible, std::is_same, std::is_member_pointer
6+ #include < type_traits> // std::enable_if, std:: remove_cvref, std::is_convertible, std::is_same, std::is_member_pointer
77#include < string> // std::string
88#include < utility> // std::move
99#include < tuple> // std::tuple, std::get, std::tuple_size
@@ -28,9 +28,9 @@ namespace sqlite_orm {
2828#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
2929 template <class T >
3030 struct as_optional_t {
31- using value_type = T;
31+ using expression_type = T;
3232
33- value_type value ;
33+ expression_type expression ;
3434 };
3535#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
3636
@@ -45,11 +45,11 @@ namespace sqlite_orm {
4545 */
4646 template <class T >
4747 struct distinct_t : distinct_string {
48- using value_type = T;
48+ using expression_type = T;
4949
50- value_type value ;
50+ expression_type expression ;
5151
52- distinct_t (value_type value_ ) : value (std::move(value_ )) {}
52+ distinct_t (expression_type expression ) : expression (std::move(expression )) {}
5353 };
5454
5555 struct all_string {
@@ -63,17 +63,29 @@ namespace sqlite_orm {
6363 */
6464 template <class T >
6565 struct all_t : all_string {
66- T value ;
66+ using expression_type = T ;
6767
68- all_t (T value_) : value(std::move(value_)) {}
68+ expression_type expression;
69+
70+ all_t (expression_type expression) : expression(std::move(expression)) {}
6971 };
7072
73+ /* *
74+ * Whether a type represents a keyword for a result set modifier (as part of a simple select expression).
75+ */
76+ template <class T >
77+ SQLITE_ORM_INLINE_VAR constexpr bool is_rowset_deduplicator_v =
78+ polyfill::disjunction<polyfill::is_specialization_of<T, distinct_t >,
79+ polyfill::is_specialization_of<T, all_t >>::value;
80+
81+ template <class T >
82+ struct is_rowset_deduplicator : polyfill::bool_constant<is_rowset_deduplicator_v<T>> {};
83+
7184 template <class ... Args>
7285 struct columns_t {
7386 using columns_type = std::tuple<Args...>;
7487
7588 columns_type columns;
76- bool distinct = false ;
7789
7890 static constexpr int count = std::tuple_size<columns_type>::value;
7991
@@ -98,7 +110,6 @@ namespace sqlite_orm {
98110 using columns_type = std::tuple<Args...>;
99111
100112 columns_type columns;
101- bool distinct = false ;
102113
103114 static constexpr int count = std::tuple_size<columns_type>::value;
104115
@@ -323,24 +334,6 @@ namespace sqlite_orm {
323334 };
324335#endif
325336
326- /* *
327- * Generic way to get DISTINCT value from any type.
328- */
329- template <class T >
330- bool get_distinct (const T&) {
331- return false ;
332- }
333-
334- template <class ... Args>
335- bool get_distinct (const columns_t <Args...>& cols) {
336- return cols.distinct ;
337- }
338-
339- template <class T , class ... Args>
340- bool get_distinct (const struct_t <T, Args...>& cols) {
341- return cols.distinct ;
342- }
343-
344337 template <class T >
345338 struct asterisk_t {
346339 using type = T;
@@ -417,6 +410,19 @@ namespace sqlite_orm {
417410 }
418411 };
419412
413+ template <class T , std::enable_if_t <!is_rowset_deduplicator_v<T>, bool > = true >
414+ const T& access_column_expression (const T& expression) {
415+ return expression;
416+ }
417+
418+ /*
419+ * Access a column expression prefixed by a result set deduplicator (as part of a simple select expression, i.e. distinct, all)
420+ */
421+ template <class D , std::enable_if_t <is_rowset_deduplicator_v<D>, bool > = true >
422+ const typename D::expression_type& access_column_expression (const D& modifier) {
423+ return modifier.expression ;
424+ }
425+
420426 template <class T >
421427 constexpr void validate_conditions () {
422428 static_assert (count_tuple<T, is_where>::value <= 1 , " a single query cannot contain > 1 WHERE blocks" );
@@ -433,6 +439,7 @@ namespace sqlite_orm {
433439 return {std::move (value)};
434440 }
435441#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
442+
436443 template <class T >
437444 internal::then_t <T> then (T t) {
438445 return {std::move (t)};
@@ -458,18 +465,12 @@ namespace sqlite_orm {
458465 return {std::move (t)};
459466 }
460467
461- template <class ... Args>
462- internal::columns_t <Args...> distinct (internal::columns_t <Args...> cols) {
463- cols.distinct = true ;
464- return cols;
465- }
466-
467468 /*
468469 * Combine multiple columns in a tuple.
469470 */
470471 template <class ... Args>
471472 constexpr internal::columns_t <Args...> columns (Args... args) {
472- return {std::make_tuple<Args...>(std:: forward<Args>(args)...) };
473+ return {{ std::forward<Args>(args)...} };
473474 }
474475
475476 /*
@@ -478,7 +479,7 @@ namespace sqlite_orm {
478479 */
479480 template <class T , class ... Args>
480481 constexpr internal::struct_t <T, Args...> struct_ (Args... args) {
481- return {std::make_tuple<Args...>(std:: forward<Args>(args)...) };
482+ return {{ std::forward<Args>(args)...} };
482483 }
483484
484485 /* *
@@ -539,7 +540,7 @@ namespace sqlite_orm {
539540 * Example:
540541 * 1_ctealias().as<materialized()>(select(1));
541542 */
542- inline consteval internal::materialized_t materialized () {
543+ consteval internal::materialized_t materialized () {
543544 return {};
544545 }
545546
@@ -549,7 +550,7 @@ namespace sqlite_orm {
549550 * Example:
550551 * 1_ctealias().as<not_materialized()>(select(1));
551552 */
552- inline consteval internal::not_materialized_t not_materialized () {
553+ consteval internal::not_materialized_t not_materialized () {
553554 return {};
554555 }
555556#endif
0 commit comments