Skip to content

Commit 91c036d

Browse files
committed
Corrected distinct/all result set modifiers
* `distinct(struct<>())` was missing. * Corrected streaming of DISTINCT/ALL; they must not parenthesize expressions following those result set modifiers. * Created unit tests for distinct/all.
1 parent b8fe04d commit 91c036d

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed

dev/select_constraints.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ namespace sqlite_orm {
469469
*/
470470
template<class... Args>
471471
constexpr internal::columns_t<Args...> columns(Args... args) {
472-
return {std::make_tuple<Args...>(std::forward<Args>(args)...)};
472+
return {{std::forward<Args>(args)...}};
473473
}
474474

475475
/*
@@ -478,7 +478,13 @@ namespace sqlite_orm {
478478
*/
479479
template<class T, class... Args>
480480
constexpr internal::struct_t<T, Args...> struct_(Args... args) {
481-
return {std::make_tuple<Args...>(std::forward<Args>(args)...)};
481+
return {{std::forward<Args>(args)...}};
482+
}
483+
484+
template<class T, class... Args>
485+
internal::struct_t<T, Args...> distinct(internal::struct_t<T, Args...> cols) {
486+
cols.distinct = true;
487+
return cols;
482488
}
483489

484490
/**

dev/statement_serializer.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,13 @@ namespace sqlite_orm {
554554

555555
template<class Ctx>
556556
std::string operator()(const statement_type& c, const Ctx& context) const {
557+
// DISTINCT has no parentheses
558+
auto subCtx = context;
559+
subCtx.use_parentheses = false;
560+
557561
std::stringstream ss;
558-
auto expr = serialize(c.value, context);
559-
ss << static_cast<std::string>(c) << "(" << expr << ")";
562+
auto expr = serialize(c.value, subCtx);
563+
ss << static_cast<std::string>(c) << " " << expr;
560564
return ss.str();
561565
}
562566
};
@@ -567,9 +571,13 @@ namespace sqlite_orm {
567571

568572
template<class Ctx>
569573
std::string operator()(const statement_type& c, const Ctx& context) const {
574+
// ALL has no parentheses
575+
auto subCtx = context;
576+
subCtx.use_parentheses = false;
577+
570578
std::stringstream ss;
571-
auto expr = serialize(c.value, context);
572-
ss << static_cast<std::string>(c) << "(" << expr << ")";
579+
auto expr = serialize(c.value, subCtx);
580+
ss << static_cast<std::string>(c) << " " << expr;
573581
return ss.str();
574582
}
575583
};
@@ -587,7 +595,7 @@ namespace sqlite_orm {
587595
}
588596
};
589597

590-
#if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
598+
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
591599
#if SQLITE_VERSION_NUMBER >= 3035003
592600
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
593601
template<>

tests/statement_serializer_tests/statements/select.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,42 @@ TEST_CASE("statement_serializer select_t") {
189189
stringValue = serialize(expression, context);
190190
expected = R"(SELECT "users".*, "users".* FROM "users")";
191191
}
192+
SECTION("distinct struct") {
193+
auto expression = select(distinct(struct_<User>(&User::name)));
194+
expression.highest_level = true;
195+
stringValue = serialize(expression, context);
196+
expected = R"(SELECT DISTINCT "users"."name" FROM "users")";
197+
}
198+
SECTION("all struct") {
199+
auto expression = select(all(struct_<User>(&User::name)));
200+
expression.highest_level = true;
201+
stringValue = serialize(expression, context);
202+
expected = R"(SELECT ALL "users"."name" FROM "users")";
203+
}
204+
SECTION("distinct") {
205+
auto expression = select(distinct(&User::name));
206+
expression.highest_level = true;
207+
stringValue = serialize(expression, context);
208+
expected = R"(SELECT DISTINCT "users"."name" FROM "users")";
209+
}
210+
SECTION("all") {
211+
auto expression = select(all(&User::name));
212+
expression.highest_level = true;
213+
stringValue = serialize(expression, context);
214+
expected = R"(SELECT ALL "users"."name" FROM "users")";
215+
}
216+
SECTION("distinct multi") {
217+
auto expression = select(distinct(columns(&User::id, &User::name)));
218+
expression.highest_level = true;
219+
stringValue = serialize(expression, context);
220+
expected = R"(SELECT DISTINCT "users"."id", "users"."name" FROM "users")";
221+
}
222+
SECTION("all multi") {
223+
auto expression = select(all(columns(&User::id, &User::name)));
224+
expression.highest_level = true;
225+
stringValue = serialize(expression, context);
226+
expected = R"(SELECT ALL "users"."id", "users"."name" FROM "users")";
227+
}
192228
// issue #1106
193229
SECTION("multi") {
194230
auto expression = columns(asterisk<User>(), asterisk<User>(true));

tests/static_tests/column_result_t.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ TEST_CASE("column_result_of_t") {
124124
runTest<db_objects_t, int64>(oid<User>());
125125
runTest<db_objects_t, int64>(_rowid_<User>());
126126
runTest<db_objects_t, tuple<int, std::string>>(columns(&User::id, &User::name));
127+
runTest<db_objects_t, tuple<int, std::string>>(distinct(columns(&User::id, &User::name)));
127128
runTest<db_objects_t, tuple<int, std::string>>(asterisk<User>());
128129
runTest<db_objects_t, tuple<int, std::string>>(asterisk<alias_a<User>>());
129130
runTest<db_objects_t, tuple<int, std::string, int, std::string>>(columns(asterisk<User>(), asterisk<User>()));
@@ -133,6 +134,7 @@ TEST_CASE("column_result_of_t") {
133134
runTest<db_objects_t, tuple<table_reference<User>, table_reference<User>>>(columns(object<User>(), object<User>()));
134135
runTest<db_objects_t, structure<User, tuple<int, std::string>>>(struct_<User>(&User::id, &User::name));
135136
runTest<db_objects_t, structure<User, tuple<int, std::string>>>(struct_<User>(asterisk<User>()));
137+
runTest<db_objects_t, structure<User, tuple<int, std::string>>>(distinct(struct_<User>(&User::id, &User::name)));
136138
runTest<db_objects_t, tuple<structure<User, tuple<int, std::string>>, structure<User, tuple<int, std::string>>>>(
137139
columns(struct_<User>(asterisk<User>()), struct_<User>(asterisk<User>())));
138140
runTest<db_objects_t, int>(union_all(select(1), select(2)));

0 commit comments

Comments
 (0)